11abf7346Smrg/* 21abf7346Smrg 31abf7346SmrgCopyright (c) 1987, 1988 X Consortium 41abf7346Smrg 51abf7346SmrgPermission is hereby granted, free of charge, to any person obtaining 61abf7346Smrga copy of this software and associated documentation files (the 71abf7346Smrg"Software"), to deal in the Software without restriction, including 81abf7346Smrgwithout limitation the rights to use, copy, modify, merge, publish, 91abf7346Smrgdistribute, sublicense, and/or sell copies of the Software, and to 101abf7346Smrgpermit persons to whom the Software is furnished to do so, subject to 111abf7346Smrgthe following conditions: 121abf7346Smrg 131abf7346SmrgThe above copyright notice and this permission notice shall be included 141abf7346Smrgin all copies or substantial portions of the Software. 151abf7346Smrg 161abf7346SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 171abf7346SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 181abf7346SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 191abf7346SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 201abf7346SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 211abf7346SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 221abf7346SmrgOTHER DEALINGS IN THE SOFTWARE. 231abf7346Smrg 241abf7346SmrgExcept as contained in this notice, the name of the X Consortium shall 251abf7346Smrgnot be used in advertising or otherwise to promote the sale, use or 261abf7346Smrgother dealings in this Software without prior written authorization 271abf7346Smrgfrom the X Consortium. 281abf7346Smrg 291abf7346Smrg*/ 301abf7346Smrg 311abf7346Smrg#include <stdio.h> 321abf7346Smrg#include <ctype.h> 331abf7346Smrg#include <X11/Xos.h> 341abf7346Smrg#include <stdlib.h> 35a5a2a776Smrg#include <limits.h> 361abf7346Smrg 371abf7346Smrg#include <X11/IntrinsicP.h> 386d36ef34Smrg#include <sys/stat.h> /* depends on IntrinsicP.h */ 391abf7346Smrg#include <X11/StringDefs.h> 401abf7346Smrg 411abf7346Smrg#include <X11/Xaw/Scrollbar.h> 421abf7346Smrg 431abf7346Smrg#include "ScrollByLP.h" 441abf7346Smrg 451abf7346Smrg/* Default Translation Table */ 461abf7346Smrg 476d36ef34Smrgstatic char defaultTranslations[] = 481abf7346Smrg "<Key>f: Page(Forward) \n\ 491abf7346Smrg <Key>b: Page(Back) \n\ 501abf7346Smrg <Key>1: Page(Line, 1) \n\ 511abf7346Smrg <Key>2: Page(Line, 2) \n\ 521abf7346Smrg <Key>3: Page(Line, 3) \n\ 531abf7346Smrg <Key>4: Page(Line, 4) \n\ 541abf7346Smrg <Key>\\ : Page(Forward)"; 551abf7346Smrg 561abf7346Smrg/**************************************************************** 571abf7346Smrg * 581abf7346Smrg * ScrollByLine Resources 591abf7346Smrg * 601abf7346Smrg ****************************************************************/ 611abf7346Smrg 621abf7346Smrg#define Offset(field) XtOffset(ScrollByLineWidget, scroll.field) 631abf7346Smrg#define CoreOffset(field) XtOffset(ScrollByLineWidget, core.field) 641abf7346Smrg 651abf7346Smrgstatic XtResource resources[] = { 661abf7346Smrg {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), 676d36ef34Smrg CoreOffset(width), XtRImmediate, (caddr_t) 500}, 681abf7346Smrg {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), 696d36ef34Smrg CoreOffset(height), XtRImmediate, (caddr_t) 700}, 701abf7346Smrg 711abf7346Smrg {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 726d36ef34Smrg Offset(foreground), XtRString, "XtDefaultForeground"}, 731abf7346Smrg {XtNforceVert, XtCBoolean, XtRBoolean, sizeof(Boolean), 746d36ef34Smrg Offset(force_vert), XtRImmediate, (caddr_t) FALSE}, 751abf7346Smrg {XtNindent, XtCIndent, XtRDimension, sizeof(Dimension), 766d36ef34Smrg Offset(indent), XtRImmediate, (caddr_t) 15}, 771abf7346Smrg {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean), 786d36ef34Smrg Offset(use_right), XtRImmediate, (caddr_t) FALSE}, 791abf7346Smrg {XtNmanualFontNormal, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 806d36ef34Smrg Offset(normal_font), XtRString, MANPAGE_NORMAL}, 811abf7346Smrg {XtNmanualFontBold, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 826d36ef34Smrg Offset(bold_font), XtRString, MANPAGE_BOLD}, 831abf7346Smrg {XtNmanualFontItalic, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 846d36ef34Smrg Offset(italic_font), XtRString, MANPAGE_ITALIC}, 851abf7346Smrg {XtNmanualFontSymbol, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 866d36ef34Smrg Offset(symbol_font), XtRString, MANPAGE_SYMBOL}, 871abf7346Smrg {XtNfile, XtCFile, XtRFile, sizeof(FILE *), 886d36ef34Smrg Offset(file), XtRImmediate, (caddr_t) NULL}, 891abf7346Smrg {XtNNumTotalLines, XtCNumTotalLines, XtRInt, sizeof(int), 906d36ef34Smrg Offset(lines), XtRImmediate, (caddr_t) 0}, 911abf7346Smrg {XtNNumVisibleLines, XtCNumVisibleLines, XtRInt, sizeof(int), 926d36ef34Smrg Offset(num_visible_lines), XtRImmediate, (caddr_t) 0}, 931abf7346Smrg}; 941abf7346Smrg 951abf7346Smrg#undef Offset 961abf7346Smrg#undef CoreOffset 971abf7346Smrg 981abf7346Smrg/**************************************************************** 991abf7346Smrg * 1001abf7346Smrg * Full class record constant 1011abf7346Smrg * 1021abf7346Smrg ****************************************************************/ 1031abf7346Smrg 1041abf7346Smrgstatic void CreateScrollbar(Widget w); 1051abf7346Smrgstatic Boolean ScrollVerticalText(Widget w, int new_line, Boolean force_redisp); 1061abf7346Smrgstatic void Layout(Widget w); 1071abf7346Smrgstatic void LoadFile(Widget w); 1081abf7346Smrgstatic void MoveAndClearText(Widget w, int old_y, int height, int new_y); 1091abf7346Smrgstatic void PaintText(Widget w, int y_loc, int height); 1101abf7346Smrgstatic void PrintText(Widget w, int start_line, int num_lines, int location); 1111abf7346Smrgstatic void SetThumbHeight(Widget w); 1121abf7346Smrgstatic void VerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr); 1136d36ef34Smrgstatic void VerticalScroll(Widget w, XtPointer client_data, 1146d36ef34Smrg XtPointer call_data); 1151abf7346Smrg 1161abf7346Smrg/* semi - public functions. */ 1171abf7346Smrg 1186d36ef34Smrgstatic void Realize(Widget w, Mask *valueMask, 1196d36ef34Smrg XSetWindowAttributes *attributes); 1206d36ef34Smrgstatic void Initialize(Widget req, Widget new, ArgList args, 1216d36ef34Smrg Cardinal *num_args); 1221abf7346Smrgstatic void Destroy(Widget w); 1231abf7346Smrgstatic void Redisplay(Widget w, XEvent *event, Region region); 1246d36ef34Smrgstatic void Page(Widget w, XEvent *event, String *params, Cardinal *num_params); 1251abf7346Smrgstatic Boolean SetValuesHook(Widget w, ArgList args, Cardinal *num_args); 1261abf7346Smrg 1271abf7346Smrgstatic XtActionsRec actions[] = { 1286d36ef34Smrg {"Page", Page}, 1291abf7346Smrg}; 1301abf7346Smrg 1311abf7346Smrg#define superclass (&simpleClassRec) 1321abf7346Smrg#define SuperClass simpleWidgetClass 1331abf7346Smrg 1341abf7346SmrgScrollByLineClassRec scrollByLineClassRec = { 1356d36ef34Smrg { 1361abf7346Smrg/* core_class fields */ 1376d36ef34Smrg /* superclass */ (WidgetClass) superclass, 1386d36ef34Smrg /* class_name */ "ScrollByLine", 1396d36ef34Smrg /* widget_size */ sizeof(ScrollByLineRec), 1406d36ef34Smrg /* class_initialize */ NULL, 1416d36ef34Smrg /* class_part_init */ NULL, 1426d36ef34Smrg /* class_inited */ FALSE, 1436d36ef34Smrg /* initialize */ Initialize, 1446d36ef34Smrg /* initialize_hook */ NULL, 1456d36ef34Smrg /* realize */ Realize, 1466d36ef34Smrg /* actions */ actions, 1476d36ef34Smrg /* num_actions */ XtNumber(actions), 1486d36ef34Smrg /* resources */ resources, 1496d36ef34Smrg /* num_resources */ XtNumber(resources), 1506d36ef34Smrg /* xrm_class */ NULLQUARK, 1516d36ef34Smrg /* compress_motion */ TRUE, 1526d36ef34Smrg /* compress_exposure */ FALSE, 1536d36ef34Smrg /* compress_enterleave */ TRUE, 1546d36ef34Smrg /* visible_interest */ FALSE, 1556d36ef34Smrg /* destroy */ Destroy, 1566d36ef34Smrg /* resize */ Layout, 1576d36ef34Smrg /* expose */ Redisplay, 1586d36ef34Smrg /* set_values */ NULL, 1596d36ef34Smrg /* set_values_hook */ SetValuesHook, 1606d36ef34Smrg /* set_values_almost */ XtInheritSetValuesAlmost, 1616d36ef34Smrg /* get_values_hook */ NULL, 1626d36ef34Smrg /* accept_focus */ NULL, 1636d36ef34Smrg /* version */ XtVersion, 1646d36ef34Smrg /* callback_private */ NULL, 1656d36ef34Smrg /* tm_table */ defaultTranslations, 1666d36ef34Smrg /* query_geometry */ XtInheritQueryGeometry, 1676d36ef34Smrg /* display_accelerator */ XtInheritDisplayAccelerator, 1686d36ef34Smrg /* extension */ NULL, 1696d36ef34Smrg }, 1706d36ef34Smrg { 1716d36ef34Smrg/* simple fields */ 1726d36ef34Smrg /* change_sensitive */ XtInheritChangeSensitive 1736d36ef34Smrg } 1741abf7346Smrg}; 1751abf7346Smrg 1766d36ef34SmrgWidgetClass scrollByLineWidgetClass = (WidgetClass) &scrollByLineClassRec; 1771abf7346Smrg 1781abf7346Smrg/**************************************************************** 1791abf7346Smrg * 1801abf7346Smrg * Private Routines 1811abf7346Smrg * 1821abf7346Smrg ****************************************************************/ 1831abf7346Smrg 1841abf7346Smrg/* Function Name: Layout 1851abf7346Smrg * Description: This function lays out the scroll widget. 1861abf7346Smrg * Arguments: w - the scroll widget. 1871abf7346Smrg * key - a boolean: if true then resize the widget to the child 1881abf7346Smrg * if false the resize children to fit widget. 1891abf7346Smrg * Returns: TRUE if successful. 1901abf7346Smrg */ 1911abf7346Smrg 1921abf7346Smrgstatic void 1931abf7346SmrgLayout(Widget w) 1946d36ef34Smrg{ 1956d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 1966d36ef34Smrg Dimension width, height; 1976d36ef34Smrg Widget bar; 1986d36ef34Smrg Position bar_bw; 1991abf7346Smrg 2006d36ef34Smrg CreateScrollbar(w); 2011abf7346Smrg 2026d36ef34Smrg/* 2031abf7346Smrg * For now always show the bar. 2041abf7346Smrg */ 2051abf7346Smrg 2066d36ef34Smrg bar = sblw->scroll.bar; 2076d36ef34Smrg height = sblw->core.height; 2086d36ef34Smrg width = sblw->core.width; 2096d36ef34Smrg bar_bw = bar->core.border_width; 2101abf7346Smrg 2116d36ef34Smrg /* Move child and v_bar to correct location. */ 2126d36ef34Smrg if (sblw->scroll.use_right) { 2136d36ef34Smrg XtMoveWidget(bar, width - (bar->core.width + bar_bw), -bar_bw); 2146d36ef34Smrg sblw->scroll.offset = 0; 2156d36ef34Smrg } 2166d36ef34Smrg else { 2176d36ef34Smrg XtMoveWidget(bar, -bar_bw, -bar_bw); 2186d36ef34Smrg sblw->scroll.offset = bar->core.width + bar_bw; 2196d36ef34Smrg } 2201abf7346Smrg 2216d36ef34Smrg /* resize the scrollbar to be the correct height or width. */ 2226d36ef34Smrg XtResizeWidget(bar, bar->core.width, height, bar->core.border_width); 2231abf7346Smrg 2246d36ef34Smrg SetThumbHeight(w); 2251abf7346Smrg 2266d36ef34Smrg sblw->scroll.num_visible_lines = height / sblw->scroll.font_height + 1; 2271abf7346Smrg} 2281abf7346Smrg 2291abf7346Smrg/* ARGSUSED */ 2306d36ef34Smrgstatic void 2316d36ef34SmrgGExpose(Widget w, XtPointer junk, XEvent * event, Boolean * cont) 2321abf7346Smrg{ 2331abf7346Smrg 2341abf7346Smrg/* 2351abf7346Smrg * Graphics exposure events are not currently sent to exposure proc. 2361abf7346Smrg */ 2371abf7346Smrg 2386d36ef34Smrg if (event->type == GraphicsExpose) 2396d36ef34Smrg Redisplay(w, event, NULL); 2401abf7346Smrg 2416d36ef34Smrg} /* ChildExpose */ 2421abf7346Smrg 2431abf7346Smrg/* 2441abf7346Smrg * Repaint the widget's child Window Widget. 2451abf7346Smrg */ 2461abf7346Smrg 2471abf7346Smrg/* ARGSUSED */ 2481abf7346Smrgstatic void 2496d36ef34SmrgRedisplay(Widget w, XEvent * event, Region region) 2501abf7346Smrg{ 2516d36ef34Smrg int top, height; /* the locations of the top and height 2526d36ef34Smrg of the region that needs to be repainted. */ 2536d36ef34Smrg 2541abf7346Smrg/* 2556d36ef34Smrg * This routine tells the client which sections of the window to 2561abf7346Smrg * repaint in his callback function which does the actual repainting. 2571abf7346Smrg */ 2581abf7346Smrg 2596d36ef34Smrg if (event->type == Expose) { 2606d36ef34Smrg top = event->xexpose.y; 2616d36ef34Smrg height = event->xexpose.height; 2626d36ef34Smrg } 2636d36ef34Smrg else { 2646d36ef34Smrg top = event->xgraphicsexpose.y; 2656d36ef34Smrg height = event->xgraphicsexpose.height; 2666d36ef34Smrg } 2676d36ef34Smrg 2686d36ef34Smrg PaintText(w, top, height); 2696d36ef34Smrg} /* redisplay (expose) */ 2701abf7346Smrg 2711abf7346Smrg/* Function Name: PaintText 2721abf7346Smrg * Description: paints the text at the give location for a given height. 2731abf7346Smrg * Arguments: w - the sbl widget. 2741abf7346Smrg * y_loc, height - location and size of area to paint. 2751abf7346Smrg * Returns: none 2761abf7346Smrg */ 2771abf7346Smrg 2781abf7346Smrgstatic void 2791abf7346SmrgPaintText(Widget w, int y_loc, int height) 2801abf7346Smrg{ 2816d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 2826d36ef34Smrg int start_line, location; 2836d36ef34Smrg 2846d36ef34Smrg start_line = y_loc / sblw->scroll.font_height + sblw->scroll.line_pointer; 2851abf7346Smrg 2866d36ef34Smrg if (start_line >= sblw->scroll.lines) 2876d36ef34Smrg return; 2881abf7346Smrg 2891abf7346Smrg/* 2906d36ef34Smrg * Only integer arithmetic makes this possible. 2911abf7346Smrg */ 2921abf7346Smrg 2936d36ef34Smrg location = y_loc / sblw->scroll.font_height * sblw->scroll.font_height; 2941abf7346Smrg 2956d36ef34Smrg PrintText(w, start_line, sblw->scroll.num_visible_lines, location); 2966d36ef34Smrg} 2971abf7346Smrg 2981abf7346Smrg/* Function Name: Page 2996d36ef34Smrg * Description: This function pages the widget, by the amount it receives 3001abf7346Smrg * from the translation Manager. 3011abf7346Smrg * Arguments: w - the ScrollByLineWidget. 3021abf7346Smrg * event - the event that caused this return. 3031abf7346Smrg * params - the parameters passed to it. 3041abf7346Smrg * num_params - the number of parameters. 3051abf7346Smrg * Returns: none. 3061abf7346Smrg */ 3071abf7346Smrg 3081abf7346Smrg/* ARGSUSED */ 3096d36ef34Smrgstatic void 3106d36ef34SmrgPage(Widget w, XEvent * event, String * params, Cardinal * num_params) 3111abf7346Smrg{ 3126d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3136d36ef34Smrg Widget bar = sblw->scroll.bar; 3141abf7346Smrg 3156d36ef34Smrg if (*num_params < 1) 3166d36ef34Smrg return; 3171abf7346Smrg/* 3181abf7346Smrg * If no scroll bar is visible then do not page, as the entire window is shown, 3196d36ef34Smrg * or scrolling has been turned off. 3201abf7346Smrg */ 3211abf7346Smrg 3226d36ef34Smrg if (bar == (Widget) NULL) 3236d36ef34Smrg return; 3246d36ef34Smrg 3256d36ef34Smrg switch (params[0][0]) { 3266d36ef34Smrg case 'f': 3276d36ef34Smrg case 'F': 3286d36ef34Smrg /* move one page forward */ 3296d36ef34Smrg VerticalScroll(bar, NULL, (XtPointer) ((long) bar->core.height)); 3306d36ef34Smrg break; 3316d36ef34Smrg case 'b': 3326d36ef34Smrg case 'B': 3336d36ef34Smrg /* move one page backward */ 3346d36ef34Smrg VerticalScroll(bar, NULL, (XtPointer) (-(long) bar->core.height)); 3356d36ef34Smrg break; 3366d36ef34Smrg case 'L': 3376d36ef34Smrg case 'l': 3386d36ef34Smrg /* move one line forward */ 3396d36ef34Smrg VerticalScroll(bar, NULL, 3406d36ef34Smrg (XtPointer) ((long) atoi(params[1]) * 3416d36ef34Smrg sblw->scroll.font_height)); 3426d36ef34Smrg break; 3436d36ef34Smrg default: 3446d36ef34Smrg return; 3456d36ef34Smrg } 3461abf7346Smrg} 3471abf7346Smrg 3481abf7346Smrg/* Function Name: CreateScrollbar 3491abf7346Smrg * Description: createst the scrollbar for us. 3501abf7346Smrg * Arguments: w - sblw widget. 3511abf7346Smrg * Returns: none. 3521abf7346Smrg */ 3531abf7346Smrg 3541abf7346Smrgstatic void 3551abf7346SmrgCreateScrollbar(Widget w) 3561abf7346Smrg{ 3576d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3586d36ef34Smrg Arg args[5]; 3596d36ef34Smrg Cardinal num_args = 0; 3606d36ef34Smrg 3616d36ef34Smrg if (sblw->scroll.bar != NULL) 3626d36ef34Smrg return; 3636d36ef34Smrg 3646d36ef34Smrg XtSetArg(args[num_args], XtNorientation, XtorientVertical); 3656d36ef34Smrg num_args++; 3666d36ef34Smrg 3676d36ef34Smrg sblw->scroll.bar = XtCreateWidget("scrollbar", scrollbarWidgetClass, w, 3686d36ef34Smrg args, num_args); 3696d36ef34Smrg XtAddCallback(sblw->scroll.bar, XtNscrollProc, VerticalScroll, NULL); 3706d36ef34Smrg XtAddCallback(sblw->scroll.bar, XtNjumpProc, VerticalJump, NULL); 3711abf7346Smrg} 3721abf7346Smrg 3731abf7346Smrg/* Function Name: ScrollVerticalText 3741abf7346Smrg * Description: This accomplished the actual movement of the text. 3751abf7346Smrg * Arguments: w - the ScrollByLine Widget. 3761abf7346Smrg * new_line - the new location for the line pointer 3776d36ef34Smrg * force_redisplay - should we force this window to get 3781abf7346Smrg * redisplayed? 3791abf7346Smrg * Returns: True if the thumb needs to be moved. 3801abf7346Smrg */ 3811abf7346Smrg 3821abf7346Smrgstatic Boolean 3836d36ef34SmrgScrollVerticalText(Widget w, int new_line, Boolean force_redisp) 3841abf7346Smrg{ 3856d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3866d36ef34Smrg int num_lines = sblw->scroll.num_visible_lines; 3876d36ef34Smrg int max_lines, old_line; 3886d36ef34Smrg Boolean move_thumb = FALSE; 3891abf7346Smrg 3901abf7346Smrg/* 3911abf7346Smrg * Do not let the window extend out of bounds. 3921abf7346Smrg */ 3931abf7346Smrg 3946d36ef34Smrg if (new_line < 0) { 3956d36ef34Smrg new_line = 0; 3966d36ef34Smrg move_thumb = TRUE; 3976d36ef34Smrg } 3986d36ef34Smrg else { 3996d36ef34Smrg max_lines = sblw->scroll.lines - 4006d36ef34Smrg (int) w->core.height / sblw->scroll.font_height; 4016d36ef34Smrg if (max_lines < 0) 4026d36ef34Smrg max_lines = 0; 4036d36ef34Smrg 4046d36ef34Smrg if (new_line > max_lines) { 4056d36ef34Smrg new_line = max_lines; 4066d36ef34Smrg move_thumb = TRUE; 4076d36ef34Smrg } 4081abf7346Smrg } 4091abf7346Smrg 4106d36ef34Smrg/* 4111abf7346Smrg * If forced to redisplay then do a full redisplay and return. 4121abf7346Smrg */ 4131abf7346Smrg 4146d36ef34Smrg old_line = sblw->scroll.line_pointer; 4156d36ef34Smrg sblw->scroll.line_pointer = new_line; /* Set current top of page. */ 4161abf7346Smrg 4176d36ef34Smrg if (force_redisp) 4186d36ef34Smrg MoveAndClearText(w, 0, /* cause a full redisplay */ 0, 0); 4191abf7346Smrg 4206d36ef34Smrg if (new_line == old_line) 4216d36ef34Smrg return (move_thumb); 4221abf7346Smrg 4231abf7346Smrg/* 4241abf7346Smrg * Scroll forward. 4251abf7346Smrg */ 4261abf7346Smrg 4276d36ef34Smrg else if (new_line < old_line) { 4286d36ef34Smrg int lines_to_scroll = old_line - new_line; 4296d36ef34Smrg MoveAndClearText(w, 0, num_lines - lines_to_scroll, lines_to_scroll); 4306d36ef34Smrg } 4311abf7346Smrg 4326d36ef34Smrg/* 4331abf7346Smrg * Scroll back. 4341abf7346Smrg */ 4351abf7346Smrg 4366d36ef34Smrg else { 4376d36ef34Smrg int lines_to_scroll = new_line - old_line; 4386d36ef34Smrg MoveAndClearText(w, lines_to_scroll, num_lines - lines_to_scroll, 0); 4396d36ef34Smrg } 4401abf7346Smrg 4416d36ef34Smrg return (move_thumb); 4421abf7346Smrg} 4431abf7346Smrg 4441abf7346Smrg/* Function Name: MoveAndClearText 4451abf7346Smrg * Description: Blits as much text as it can and clear the 4461abf7346Smrg * remaining area with generate exposures TRUE. 4471abf7346Smrg * Arguments: w - the sbl widget. 4481abf7346Smrg * old_y - the old y position. 4491abf7346Smrg * height - height of area to move. 4501abf7346Smrg * new_y - new y position. 4511abf7346Smrg * Returns: none 4521abf7346Smrg */ 4536d36ef34Smrg 4541abf7346Smrgstatic void 4551abf7346SmrgMoveAndClearText(Widget w, int old_y, int height, int new_y) 4561abf7346Smrg{ 4576d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 4586d36ef34Smrg int from_left = sblw->scroll.indent + sblw->scroll.offset - 1; 4596d36ef34Smrg int y_clear; 4601abf7346Smrg 4616d36ef34Smrg old_y *= sblw->scroll.font_height; 4626d36ef34Smrg new_y *= sblw->scroll.font_height; 4636d36ef34Smrg height *= sblw->scroll.font_height; 4641abf7346Smrg 4651abf7346Smrg/* 4661abf7346Smrg * If we are already at the right location then do nothing. 4671abf7346Smrg * (height == 0). 4681abf7346Smrg * 4691abf7346Smrg * If we have scrolled more than a screen height then just clear 4701abf7346Smrg * the window. 4711abf7346Smrg */ 4721abf7346Smrg 4736d36ef34Smrg if (height <= sblw->scroll.font_height) { /* avoid rounding errors. */ 4746d36ef34Smrg XClearArea(XtDisplay(w), XtWindow(w), from_left, 0, 4756d36ef34Smrg (unsigned int) 0, (unsigned int) 0, FALSE); 4766d36ef34Smrg PaintText(w, 0, (int) sblw->core.height); 4776d36ef34Smrg return; 4786d36ef34Smrg } 4796d36ef34Smrg 4806d36ef34Smrg if ((int) height + (int) old_y > (int) w->core.height) 4816d36ef34Smrg height = w->core.height - old_y; 4826d36ef34Smrg 4836d36ef34Smrg XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), sblw->scroll.move_gc, 4846d36ef34Smrg from_left, old_y, 4856d36ef34Smrg (unsigned int) w->core.width - from_left, (unsigned int) height, 4866d36ef34Smrg from_left, new_y); 4876d36ef34Smrg 4886d36ef34Smrg if (old_y > new_y) 4896d36ef34Smrg height -= sblw->scroll.font_height / 2; /* clear 1/2 font of extra space, 4906d36ef34Smrg to make sure we don't lose or 4916d36ef34Smrg gain descenders. */ 4926d36ef34Smrg else 4936d36ef34Smrg height -= sblw->scroll.font_height; /* clear 1 font of extra space, 4946d36ef34Smrg to make sure we don't overwrite 4956d36ef34Smrg with a last line in buffer. */ 4966d36ef34Smrg 4976d36ef34Smrg if (old_y > new_y) 4986d36ef34Smrg y_clear = height; 4996d36ef34Smrg else 5006d36ef34Smrg y_clear = 0; 5016d36ef34Smrg 5021abf7346Smrg/* 5031abf7346Smrg * We cannot use generate exposures, since that may allow another move and 5041abf7346Smrg * clear before the area get repainted, this would be bad. 5051abf7346Smrg */ 5061abf7346Smrg 5076d36ef34Smrg XClearArea(XtDisplay(w), XtWindow(w), from_left, y_clear, 5086d36ef34Smrg (unsigned int) 0, (unsigned int) (w->core.height - height), 5096d36ef34Smrg FALSE); 5106d36ef34Smrg PaintText(w, (int) y_clear, (int) (w->core.height - height)); 5111abf7346Smrg} 5121abf7346Smrg 5131abf7346Smrg/* Function Name: SetThumbHeight 5141abf7346Smrg * Description: Set the height of the thumb. 5151abf7346Smrg * Arguments: w - the sblw widget. 5161abf7346Smrg * Returns: none 5171abf7346Smrg */ 5181abf7346Smrg 5191abf7346Smrgstatic void 5201abf7346SmrgSetThumbHeight(Widget w) 5211abf7346Smrg{ 5226d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5236d36ef34Smrg float shown; 5241abf7346Smrg 5256d36ef34Smrg if (sblw->scroll.bar == NULL) 5266d36ef34Smrg return; 5271abf7346Smrg 5286d36ef34Smrg if (sblw->scroll.lines == 0) 5296d36ef34Smrg shown = 1.0; 5306d36ef34Smrg else 5316d36ef34Smrg shown = (float) w->core.height / (float) (sblw->scroll.lines * 5326d36ef34Smrg sblw->scroll.font_height); 5336d36ef34Smrg if (shown > 1.0) 5346d36ef34Smrg shown = 1.0; 5351abf7346Smrg 5366d36ef34Smrg XawScrollbarSetThumb(sblw->scroll.bar, (float) -1, shown); 5371abf7346Smrg} 5381abf7346Smrg 5391abf7346Smrg/* Function Name: SetThumb 5401abf7346Smrg * Description: Set the thumb location. 5411abf7346Smrg * Arguments: w - the sblw. 5421abf7346Smrg * Returns: none 5431abf7346Smrg */ 5441abf7346Smrg 5451abf7346Smrgstatic void 5461abf7346SmrgSetThumb(Widget w) 5471abf7346Smrg{ 5486d36ef34Smrg float location; 5496d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5501abf7346Smrg 5516d36ef34Smrg if ((sblw->scroll.lines == 0) || (sblw->scroll.bar == NULL)) 5526d36ef34Smrg return; 5531abf7346Smrg 5546d36ef34Smrg location = (float) sblw->scroll.line_pointer / (float) sblw->scroll.lines; 5556d36ef34Smrg XawScrollbarSetThumb(sblw->scroll.bar, location, (float) -1); 5561abf7346Smrg} 5571abf7346Smrg 5581abf7346Smrg/* Function Name: VerticalJump. 5591abf7346Smrg * Description: This function moves the test 5601abf7346Smrg * as the vertical scroll bar is moved. 5611abf7346Smrg * Arguments: w - the scrollbar widget. 5621abf7346Smrg * junk - not used. 5631abf7346Smrg * percent - the position of the scrollbar. 5641abf7346Smrg * Returns: none. 5651abf7346Smrg */ 5661abf7346Smrg 5671abf7346Smrg/* ARGSUSED */ 5681abf7346Smrgstatic void 5691abf7346SmrgVerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr) 5701abf7346Smrg{ 5716d36ef34Smrg float percent = *((float *) percent_ptr); 5726d36ef34Smrg int new_line; /* The new location for the line pointer. */ 5736d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 5741abf7346Smrg 5756d36ef34Smrg new_line = (int) ((float) sblw->scroll.lines * percent); 5766d36ef34Smrg if (ScrollVerticalText((Widget) sblw, new_line, FALSE)) 5776d36ef34Smrg SetThumb((Widget) sblw); 5781abf7346Smrg} 5791abf7346Smrg 5801abf7346Smrg/* Function Name: VerticalScroll 5816d36ef34Smrg * Description: This function moves the position of the interior window 5821abf7346Smrg * as the vertical scroll bar is moved. 5831abf7346Smrg * Arguments: w - the scrollbar widget. 5841abf7346Smrg * junk - not used. 5851abf7346Smrg * pos - the position of the cursor. 5861abf7346Smrg * Returns: none. 5871abf7346Smrg */ 5881abf7346Smrg 5891abf7346Smrg/* ARGSUSED */ 5901abf7346Smrgstatic void 5911abf7346SmrgVerticalScroll(Widget w, XtPointer client_data, XtPointer call_data) 5921abf7346Smrg{ 5936d36ef34Smrg int pos = (int) (long) call_data; 5946d36ef34Smrg int new_line; /* The new location for the line pointer. */ 5956d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 5961abf7346Smrg 5976d36ef34Smrg new_line = sblw->scroll.line_pointer + (pos / sblw->scroll.font_height); 5986d36ef34Smrg (void) ScrollVerticalText((Widget) sblw, new_line, FALSE); 5996d36ef34Smrg SetThumb((Widget) sblw); 6001abf7346Smrg} 6011abf7346Smrg 6021abf7346Smrg/* ARGSUSED */ 6036d36ef34Smrgstatic void 6046d36ef34SmrgInitialize(Widget req, Widget new, ArgList args, Cardinal * num_args) 6051abf7346Smrg{ 6066d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) new; 6076d36ef34Smrg unsigned long figWidth; 6086d36ef34Smrg Atom atomNum; 6091abf7346Smrg 6106d36ef34Smrg sblw->scroll.top_line = NULL; 6116d36ef34Smrg sblw->scroll.line_pointer = 0; 6126d36ef34Smrg LoadFile(new); 6136d36ef34Smrg sblw->scroll.bar = (Widget) NULL; 6141abf7346Smrg 6156d36ef34Smrg sblw->scroll.font_height = (sblw->scroll.normal_font->max_bounds.ascent + 6166d36ef34Smrg sblw->scroll.normal_font->max_bounds.descent); 6171abf7346Smrg 6186d36ef34Smrg atomNum = XInternAtom(XtDisplay(req), "FIGURE_WIDTH", False); 6191abf7346Smrg 6206d36ef34Smrg if (XGetFontProperty(sblw->scroll.normal_font, atomNum, &figWidth)) 6216d36ef34Smrg sblw->scroll.h_width = figWidth; 6226d36ef34Smrg else 6236d36ef34Smrg sblw->scroll.h_width = XTextWidth(sblw->scroll.normal_font, "$", 1); 6246d36ef34Smrg} /* Initialize. */ 6251abf7346Smrg 6261abf7346Smrg/* Function Name: CreateGCs 6276d36ef34Smrg * Description: Creates the graphics contexts that we need. 6281abf7346Smrg * Arguments: w - the sblw. 6291abf7346Smrg * Returns: none 6301abf7346Smrg */ 6311abf7346Smrg 6321abf7346Smrgstatic void 6331abf7346SmrgCreateGCs(Widget w) 6341abf7346Smrg{ 6356d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6366d36ef34Smrg 6376d36ef34Smrg XtGCMask mask; 6386d36ef34Smrg XGCValues values; 6391abf7346Smrg 6406d36ef34Smrg values.graphics_exposures = TRUE; 6416d36ef34Smrg sblw->scroll.move_gc = XtGetGC(w, GCGraphicsExposures, &values); 6421abf7346Smrg 6436d36ef34Smrg mask = GCForeground | GCFont; 6446d36ef34Smrg values.foreground = sblw->scroll.foreground; 6451abf7346Smrg 6466d36ef34Smrg values.font = sblw->scroll.normal_font->fid; 6476d36ef34Smrg sblw->scroll.normal_gc = XtGetGC(w, mask, &values); 6481abf7346Smrg 6496d36ef34Smrg values.font = sblw->scroll.italic_font->fid; 6506d36ef34Smrg sblw->scroll.italic_gc = XtGetGC(w, mask, &values); 6511abf7346Smrg 6526d36ef34Smrg values.font = sblw->scroll.bold_font->fid; 6536d36ef34Smrg sblw->scroll.bold_gc = XtGetGC(w, mask, &values); 6541abf7346Smrg 6556d36ef34Smrg values.font = sblw->scroll.symbol_font->fid; 6566d36ef34Smrg sblw->scroll.symbol_gc = XtGetGC(w, mask, &values); 6571abf7346Smrg} 6581abf7346Smrg 6591abf7346Smrg/* Function Name: DestroyGCs 6601abf7346Smrg * Description: removes all gcs for this widget. 6611abf7346Smrg * Arguments: w - the widget. 6621abf7346Smrg * Returns: none 6631abf7346Smrg */ 6641abf7346Smrg 6651abf7346Smrgstatic void 6661abf7346SmrgDestroyGCs(Widget w) 6671abf7346Smrg{ 6686d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6691abf7346Smrg 6706d36ef34Smrg XtReleaseGC(w, sblw->scroll.normal_gc); 6716d36ef34Smrg XtReleaseGC(w, sblw->scroll.bold_gc); 6726d36ef34Smrg XtReleaseGC(w, sblw->scroll.italic_gc); 6736d36ef34Smrg XtReleaseGC(w, sblw->scroll.move_gc); 6741abf7346Smrg} 6751abf7346Smrg 6761abf7346Smrgstatic void 6776d36ef34SmrgRealize(Widget w, Mask *valueMask, XSetWindowAttributes * attributes) 6781abf7346Smrg{ 6796d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6801abf7346Smrg 6816d36ef34Smrg CreateScrollbar(w); 6826d36ef34Smrg CreateGCs(w); 6836d36ef34Smrg Layout(w); 6846d36ef34Smrg (*SuperClass->core_class.realize) (w, valueMask, attributes); 6856d36ef34Smrg XtRealizeWidget(sblw->scroll.bar); /* realize scrollbar. */ 6866d36ef34Smrg XtMapWidget(sblw->scroll.bar); /* map scrollbar. */ 6871abf7346Smrg 6886d36ef34Smrg XtAddEventHandler(w, 0, TRUE, GExpose, NULL); /* Get Graphics Exposures */ 6896d36ef34Smrg} /* Realize */ 6901abf7346Smrg 6911abf7346Smrg/* Function Name: Destroy 6921abf7346Smrg * Description: Cleans up when we are killed. 6931abf7346Smrg * Arguments: w - the widget. 6941abf7346Smrg * Returns: none 6951abf7346Smrg */ 6961abf7346Smrg 6971abf7346Smrgstatic void 6981abf7346SmrgDestroy(Widget w) 6991abf7346Smrg{ 7006d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7011abf7346Smrg 7026d36ef34Smrg if (sblw->scroll.bar != NULL) 7036d36ef34Smrg XtDestroyWidget(sblw->scroll.bar); /* Destroy scrollbar. */ 704a5a2a776Smrg if (sblw->scroll.file != NULL) { 7056d36ef34Smrg fclose(sblw->scroll.file); 706a5a2a776Smrg sblw->scroll.file = NULL; 707a5a2a776Smrg } 708a5a2a776Smrg LoadFile(w); 7096d36ef34Smrg DestroyGCs(w); 7101abf7346Smrg} 7111abf7346Smrg 7121abf7346Smrg/* 7131abf7346Smrg * 7141abf7346Smrg * Set Values 7151abf7346Smrg * 7161abf7346Smrg */ 7171abf7346Smrg 7181abf7346Smrg/* ARGSUSED */ 7196d36ef34Smrgstatic Boolean 7206d36ef34SmrgSetValuesHook(Widget w, ArgList args, Cardinal * num_args) 7211abf7346Smrg{ 7226d36ef34Smrg Boolean ret = TRUE; 7236d36ef34Smrg Cardinal i; 7246d36ef34Smrg 7256d36ef34Smrg for (i = 0; i < *num_args; i++) { 7266d36ef34Smrg if (strcmp(XtNfile, args[i].name) == 0) { 7276d36ef34Smrg LoadFile(w); 7286d36ef34Smrg ret = TRUE; 7296d36ef34Smrg } 7301abf7346Smrg } 7311abf7346Smrg 7321abf7346Smrg/* 7336d36ef34Smrg * Changing anything else will have strange effects, I don't need it so 7341abf7346Smrg * I didn't code it. 7351abf7346Smrg */ 7361abf7346Smrg 7376d36ef34Smrg return (ret); 7381abf7346Smrg 7396d36ef34Smrg} /* Set Values */ 7401abf7346Smrg 7416d36ef34Smrg/* 7426d36ef34Smrg * A little design philosophy is probably wise to include at this point. 7431abf7346Smrg * 7441abf7346Smrg * One of the things that I has hoped to achieve with xman is to make the 7451abf7346Smrg * viewing of manpage not only easy for the nieve user, but also fast for 7461abf7346Smrg * the experienced user, I wanted to be able to use it too. To achieve this 7471abf7346Smrg * I end up sacrificing a bit of start up time for the manual data structure. 7486d36ef34Smrg * As well as, the overhead of reading the entire file before putting it up 7491abf7346Smrg * on the display. This is actually hardly even noticeable since most manual 7501abf7346Smrg * pages are shots, one to two pages - the notable exception is of course csh, 7516d36ef34Smrg * but then that should be broken up anyway. 7521abf7346Smrg * 7531abf7346Smrg * METHOD: 7541abf7346Smrg * 7551abf7346Smrg * I allocate a chunk of space that is the size of the file, plus a null for 7566d36ef34Smrg * debugging. Then copies the file into this chunk of memory. I then allocate 7571abf7346Smrg * an array of char*'s that are assigned to the beginning of each line. Yes, 7586d36ef34Smrg * this means that I have to read the file twice, and could probably be more 7591abf7346Smrg * clever about it, but once it is in memory the second read is damn fast. 7606d36ef34Smrg * There are a few obscurities here about guessing the number of lines and 7616d36ef34Smrg * reallocing if I guess wrong, but other than that it is pretty straight 7621abf7346Smrg * forward. 7631abf7346Smrg * 7641abf7346Smrg * Chris Peterson 7651abf7346Smrg * 1/27/88 7661abf7346Smrg */ 7671abf7346Smrg 7686d36ef34Smrg#define ADD_MORE_MEM 100 /* first guesses for allocations. */ 7691abf7346Smrg#define CHAR_PER_LINE 40 7701abf7346Smrg 7711abf7346Smrg/* Function Name: LoadFile 7721abf7346Smrg * Description: Loads the current file into the internal memory. 7731abf7346Smrg * Arguments: w - the sblw. 7741abf7346Smrg * Returns: none 7751abf7346Smrg */ 7761abf7346Smrg 7771abf7346Smrgstatic void 7781abf7346SmrgLoadFile(Widget w) 7791abf7346Smrg{ 7806d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7816d36ef34Smrg FILE *file = sblw->scroll.file; 7826d36ef34Smrg 7836d36ef34Smrg char *page; 7846d36ef34Smrg char **line_pointer, **top_line; /* pointers to beginnings of the 7856d36ef34Smrg lines of the file. */ 7866d36ef34Smrg int nlines; /* the current number of allocated lines. */ 7876d36ef34Smrg struct stat fileinfo; /* file information from fstat. */ 7886d36ef34Smrg 7896d36ef34Smrg if (sblw->scroll.top_line != NULL) { 7906d36ef34Smrg XtFree(*(sblw->scroll.top_line)); /* free characters. */ 7916d36ef34Smrg XtFree((char *) (sblw->scroll.top_line)); /* free lines. */ 7926d36ef34Smrg } 7936d36ef34Smrg sblw->scroll.top_line = NULL; 7941abf7346Smrg 7956d36ef34Smrg if (file == NULL) 7966d36ef34Smrg return; 7971abf7346Smrg 7981abf7346Smrg/* 7996d36ef34Smrg * Get file size and allocate a chunk of memory for the file to be 8001abf7346Smrg * copied into. 8011abf7346Smrg */ 8021abf7346Smrg 8036d36ef34Smrg if (fstat(fileno(file), &fileinfo)) 8046d36ef34Smrg XtAppError(XtWidgetToApplicationContext(w), 8056d36ef34Smrg "SBLW LoadFile: Failure in fstat."); 8061abf7346Smrg 807a5a2a776Smrg/* 808a5a2a776Smrg * The XtMalloc below is limited to a size of int by the libXt API. 809a5a2a776Smrg */ 810a5a2a776Smrg if (fileinfo.st_size >= INT_MAX) 811a5a2a776Smrg XtAppError(XtWidgetToApplicationContext(w), 812a5a2a776Smrg "SBLW LoadFile: File too large."); 813a5a2a776Smrg 8146d36ef34Smrg/* 8151abf7346Smrg * Allocate a space for a list of pointer to the beginning of each line. 8161abf7346Smrg */ 8171abf7346Smrg 8186d36ef34Smrg if ((nlines = fileinfo.st_size / CHAR_PER_LINE) == 0) 8196d36ef34Smrg return; 8201abf7346Smrg 8216d36ef34Smrg page = XtMalloc(fileinfo.st_size + 1); /* leave space for the NULL */ 8226d36ef34Smrg top_line = line_pointer = (char **) XtMalloc(nlines * sizeof(char *)); 8231abf7346Smrg 8241abf7346Smrg/* 8256d36ef34Smrg * Copy the file into memory. 8261abf7346Smrg */ 8271abf7346Smrg 8286d36ef34Smrg fseek(file, 0L, SEEK_SET); 8296d36ef34Smrg if (fread(page, sizeof(char), fileinfo.st_size, file) == 0) 8306d36ef34Smrg XtAppError(XtWidgetToApplicationContext(w), 8316d36ef34Smrg "SBLW LoadFile: Failure in fread."); 8321abf7346Smrg 8331abf7346Smrg/* put NULL at end of buffer. */ 8341abf7346Smrg 8356d36ef34Smrg *(page + fileinfo.st_size) = '\0'; 8361abf7346Smrg 8371abf7346Smrg/* 8386d36ef34Smrg * Go through the file setting a line pointer to the character after each 8391abf7346Smrg * new line. If we run out of line pointer space then realloc that space 8401abf7346Smrg * with space for more lines. 8411abf7346Smrg */ 8421abf7346Smrg 8436d36ef34Smrg *line_pointer++ = page; /* first line points to first char in buffer. */ 8446d36ef34Smrg while (*page != '\0') { 8456d36ef34Smrg 8466d36ef34Smrg if (*page == '\n') { 8476d36ef34Smrg *line_pointer++ = page + 1; 8486d36ef34Smrg 8496d36ef34Smrg if (line_pointer >= top_line + nlines) { 8506d36ef34Smrg top_line = (char **) XtRealloc((char *) top_line, (nlines + 8516d36ef34Smrg ADD_MORE_MEM) 8526d36ef34Smrg * sizeof(char *)); 8536d36ef34Smrg line_pointer = top_line + nlines; 8546d36ef34Smrg nlines += ADD_MORE_MEM; 8556d36ef34Smrg } 8566d36ef34Smrg } 8576d36ef34Smrg page++; 8581abf7346Smrg } 8596d36ef34Smrg 8601abf7346Smrg/* 8611abf7346Smrg * Realloc the line pointer space to take only the minimum amount of memory 8621abf7346Smrg */ 8631abf7346Smrg 8646d36ef34Smrg sblw->scroll.lines = nlines = line_pointer - top_line - 1; 8656d36ef34Smrg top_line = (char **) XtRealloc((char *) top_line, nlines * sizeof(char *)); 8661abf7346Smrg 8671abf7346Smrg/* 8681abf7346Smrg * Store the memory pointers 8691abf7346Smrg */ 8701abf7346Smrg 8716d36ef34Smrg sblw->scroll.top_line = top_line; 8726d36ef34Smrg sblw->scroll.line_pointer = 0; 8736d36ef34Smrg SetThumbHeight(w); 8746d36ef34Smrg SetThumb(w); 8751abf7346Smrg} 8761abf7346Smrg 8776d36ef34Smrg#define NLINES 66 /* This is the number of lines to wait until 8786d36ef34Smrg we boldify the line again, this allows 8796d36ef34Smrg me to bold the first line of each page. */ 8806d36ef34Smrg#define BACKSPACE 010 /* I doubt you would want to change this. */ 8811abf7346Smrg 8821abf7346Smrg#define NORMAL 0 8831abf7346Smrg#define BOLD 1 8841abf7346Smrg#define ITALIC 2 8851abf7346Smrg#define SYMBOL 3 8861abf7346Smrg#define WHICH(italic, bold) ((bold) ? BOLD : ((italic) ? ITALIC : NORMAL)) 8876d36ef34Smrg /* Choose BOLD over ITALICS. If neither */ 8886d36ef34Smrg /* is chosen, use NORMAL. */ 8891abf7346Smrg 8906d36ef34Smrgstatic int DumpText(Widget w, int x_loc, int y_loc, char *buf, int len, 8916d36ef34Smrg int format); 8921abf7346Smrgstatic Boolean Boldify(char *); 8931abf7346Smrg 8941abf7346Smrg/* Function Name: PrintText 8951abf7346Smrg * Description: This function actually prints the text. 8961abf7346Smrg * Arguments: w - the ScrollByLine widget. 8971abf7346Smrg * start_line - line to start printing, 8981abf7346Smrg * num_lines - the number of lines to print. 8991abf7346Smrg * location - the location to print the text. 9001abf7346Smrg * Returns: none. 9011abf7346Smrg */ 9021abf7346Smrg 9031abf7346Smrg/* ARGSUSED */ 9041abf7346Smrgstatic void 9051abf7346SmrgPrintText(Widget w, int start_line, int num_lines, int location) 9061abf7346Smrg{ 9076d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 9081abf7346Smrg 9096d36ef34Smrg register char *bufp, *c; /* Generic char pointers */ 9106d36ef34Smrg int current_line; /* the number of the current line */ 9116d36ef34Smrg char buf[BUFSIZ]; /* Misc. characters */ 9126d36ef34Smrg Boolean italicflag = FALSE; /* Print text in italics?? */ 9136d36ef34Smrg Boolean first = TRUE; /* First line of a manual page??? */ 9146d36ef34Smrg int x_loc, y_loc; /* x and y location of text. */ 9151abf7346Smrg 9161abf7346Smrg/* 9171abf7346Smrg * For table hack 9181abf7346Smrg * To get columns to line up reasonably in most cases, make the 9191abf7346Smrg * assumption that they were lined up using lots of spaces, where 9201abf7346Smrg * lots is greater than two. Use a space width of 70% of the 9211abf7346Smrg * widest character in the font. 9221abf7346Smrg */ 9236d36ef34Smrg int h_col, h_fix; 9246d36ef34Smrg char *h_c; 9251abf7346Smrg 9261abf7346Smrg/* 9271abf7346Smrg * Nothing loaded, take no action. 9281abf7346Smrg */ 9291abf7346Smrg 9306d36ef34Smrg if (sblw->scroll.top_line == NULL || num_lines == 0) 9316d36ef34Smrg return; 9321abf7346Smrg 9336d36ef34Smrg current_line = start_line; 9341abf7346Smrg 9351abf7346Smrg/* Set the first character to print at the first line. */ 9361abf7346Smrg 9376d36ef34Smrg c = *(sblw->scroll.top_line + start_line); 9381abf7346Smrg 9391abf7346Smrg/* 9401abf7346Smrg * Because XDrawString uses the bottom of the text as a position 9411abf7346Smrg * reference, add the height from the top of the font to the baseline 9421abf7346Smrg * to the ScollByLine position reference. 9431abf7346Smrg */ 9441abf7346Smrg 9456d36ef34Smrg y_loc = location + sblw->scroll.normal_font->max_bounds.ascent; 9461abf7346Smrg 9471abf7346Smrg/* 9481abf7346Smrg * Ok, here's the more than mildly heuristic man page formatter. 9491abf7346Smrg * We put chars into buf until either a font change or newline 9501abf7346Smrg * occurs (at which time we flush it to the screen.) 9511abf7346Smrg */ 9521abf7346Smrg 9536d36ef34Smrg bufp = buf; 9546d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 9556d36ef34Smrg h_col = 0; 9561abf7346Smrg 9571abf7346Smrg/* 9581abf7346Smrg * A fix: 9591abf7346Smrg * Assume that we are always starting to print on or before the 9601abf7346Smrg * first line of a page, and then prove it if we aren't. 9611abf7346Smrg */ 9626d36ef34Smrg for (h_fix = 1; h_fix <= (start_line % NLINES); h_fix++) 9636d36ef34Smrg if (**(sblw->scroll.top_line + start_line - h_fix) != '\n') { 9646d36ef34Smrg first = FALSE; 9656d36ef34Smrg break; 9666d36ef34Smrg } 9676d36ef34Smrg 9686d36ef34Smrg while (TRUE) { 9696d36ef34Smrg if (current_line % NLINES == 0) 9706d36ef34Smrg first = TRUE; 9716d36ef34Smrg 9726d36ef34Smrg/* 9731abf7346Smrg * Lets make sure that we do not run out of space in our buffer, making full 9741abf7346Smrg * use of it is not critical since no window will be wide enough to display 9751abf7346Smrg * nearly BUFSIZ characters. 9761abf7346Smrg */ 9771abf7346Smrg 9786d36ef34Smrg if ((bufp - buf) > (BUFSIZ - 10)) 9796d36ef34Smrg /* Toss everything until we find a <CR> or the end of the buffer. */ 9806d36ef34Smrg while ((*c != '\n') && (*c != '\0')) 9816d36ef34Smrg c++; 9826d36ef34Smrg 9836d36ef34Smrg switch (*c) { 9841abf7346Smrg 9856d36ef34Smrg case '\0': /* If we reach the end of the file then return */ 9866d36ef34Smrg DumpText(w, x_loc, y_loc, buf, bufp - buf, 9876d36ef34Smrg WHICH(italicflag, first)); 9886d36ef34Smrg return; 9891abf7346Smrg 9906d36ef34Smrg case '\n': 9916d36ef34Smrg if (bufp != buf) { 9926d36ef34Smrg Boolean bold; 9931abf7346Smrg 9946d36ef34Smrg *bufp = '\0'; /* for Boldify. */ 9956d36ef34Smrg bold = ((first) || ((x_loc == (sblw->scroll.offset + 9966d36ef34Smrg sblw->scroll.indent)) && 9976d36ef34Smrg Boldify(buf))); 9981abf7346Smrg 9996d36ef34Smrg (void) DumpText(w, x_loc, y_loc, buf, bufp - buf, 10006d36ef34Smrg WHICH(italicflag, bold)); 10011abf7346Smrg 10026d36ef34Smrg if (bold) 10036d36ef34Smrg first = FALSE; 10046d36ef34Smrg } 10051abf7346Smrg 10066d36ef34Smrg/* 10071abf7346Smrg * If we have painted the required number of lines then we should now return. 10081abf7346Smrg */ 10096d36ef34Smrg if (++current_line == start_line + num_lines) 10106d36ef34Smrg return; 10111abf7346Smrg 10126d36ef34Smrg bufp = buf; 10136d36ef34Smrg italicflag = FALSE; 10146d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10156d36ef34Smrg h_col = 0; 10166d36ef34Smrg y_loc += sblw->scroll.font_height; 10176d36ef34Smrg break; 10181abf7346Smrg 10191abf7346Smrg/* 10201abf7346Smrg * This tab handling code is not very clever it moves the cursor over 10216d36ef34Smrg * to the next boundary of eight (8) spaces, as calculated in width just 10221abf7346Smrg * before the printing loop started. 10231abf7346Smrg */ 10241abf7346Smrg 10256d36ef34Smrg case '\t': /* TAB */ 10266d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10276d36ef34Smrg WHICH(italicflag, first)); 10286d36ef34Smrg h_col += bufp - buf; 10296d36ef34Smrg bufp = buf; 10306d36ef34Smrg italicflag = FALSE; 10316d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10326d36ef34Smrg h_col = h_col + 8 - (h_col % 8); 10336d36ef34Smrg x_loc += sblw->scroll.h_width * h_col; 10346d36ef34Smrg break; 10356d36ef34Smrg 10366d36ef34Smrg case ' ': 10376d36ef34Smrg h_c = c + 1; 10386d36ef34Smrg while (*h_c == ' ') 10396d36ef34Smrg h_c++; 10406d36ef34Smrg 10416d36ef34Smrg if (h_c - c < 4) { 10426d36ef34Smrg *bufp++ = *c; 10436d36ef34Smrg break; 10446d36ef34Smrg } 10456d36ef34Smrg 10466d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10476d36ef34Smrg WHICH(italicflag, first)); 10486d36ef34Smrg h_col += bufp - buf; 10496d36ef34Smrg bufp = buf; 10506d36ef34Smrg italicflag = FALSE; 10516d36ef34Smrg 10526d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10536d36ef34Smrg h_col += (h_c - c); 10546d36ef34Smrg x_loc += sblw->scroll.h_width * h_col; 10556d36ef34Smrg c = h_c - 1; 10566d36ef34Smrg break; 10576d36ef34Smrg 10586d36ef34Smrg case '\033': /* ignore esc sequences for now */ 10596d36ef34Smrg c++; /* should always be esc-x */ 10606d36ef34Smrg break; 10616d36ef34Smrg 10626d36ef34Smrg/* 10636d36ef34Smrg * Overstrike code supplied by: cs.utexas.edu!ut-emx!clyde@rutgers.edu 10641abf7346Smrg * Since my manual pages do not have overstrike I couldn't test this. 10651abf7346Smrg */ 10661abf7346Smrg 10676d36ef34Smrg case BACKSPACE: /* Backspacing for nroff bolding */ 10686d36ef34Smrg if (c[-1] == c[1] && c[1] != BACKSPACE) { /* overstriking one char */ 10696d36ef34Smrg if (bufp > buf) { 10706d36ef34Smrg bufp--; /* Zap 1st instance of char to bolden */ 10716d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10726d36ef34Smrg WHICH(italicflag, FALSE)); 10736d36ef34Smrg h_col += bufp - buf; 10746d36ef34Smrg } 10756d36ef34Smrg bufp = buf; 10766d36ef34Smrg *bufp++ = c[1]; 10776d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, BOLD); 10786d36ef34Smrg h_col += bufp - buf; 10796d36ef34Smrg bufp = buf; 10806d36ef34Smrg first = FALSE; 10816d36ef34Smrg 10826d36ef34Smrg /* 10836d36ef34Smrg * Nroff bolding looks like: 10846d36ef34Smrg * C\bC\bC\bCN... 10856d36ef34Smrg * c points to ----^ ^ 10866d36ef34Smrg * it needs to point to --^ 10876d36ef34Smrg */ 10886d36ef34Smrg while (*c == BACKSPACE && c[-1] == c[1]) 10896d36ef34Smrg c += 2; 10906d36ef34Smrg c--; /* Back up to previous char */ 10916d36ef34Smrg } 10926d36ef34Smrg else { 10936d36ef34Smrg if ((c[-1] == 'o' && c[1] == '+') /* Nroff bullet */ 10946d36ef34Smrg ||(c[-1] == '+' && c[1] == 'o')) { /* Nroff bullet */ 10956d36ef34Smrg /* If we run into a bullet, print out */ 10966d36ef34Smrg /* everything that's accumulated to this */ 10976d36ef34Smrg /* point, then the bullet, then resume. */ 10986d36ef34Smrg if (bufp > buf) { 10996d36ef34Smrg bufp--; 11006d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 11016d36ef34Smrg WHICH(italicflag, FALSE)); 11026d36ef34Smrg h_col += bufp - buf; 11036d36ef34Smrg } 11046d36ef34Smrg bufp = buf; 11056d36ef34Smrg *bufp = (char) 183; 11066d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, 1, SYMBOL); 11076d36ef34Smrg h_col++; 11086d36ef34Smrg c++; 11096d36ef34Smrg } 11106d36ef34Smrg else { /* 'real' backspace - back up output ptr */ 11116d36ef34Smrg if (bufp > buf) 11126d36ef34Smrg bufp--; 11136d36ef34Smrg } 11146d36ef34Smrg } 11156d36ef34Smrg break; 11161abf7346Smrg 11171abf7346Smrg/* End of contributed overstrike code. */ 11181abf7346Smrg 11196d36ef34Smrg case '_': /* look for underlining [italicize] */ 11206d36ef34Smrg if (*(c + 1) == BACKSPACE) { 11216d36ef34Smrg if (!italicflag) { /* font change? */ 11226d36ef34Smrg if (bufp != buf) { 11236d36ef34Smrg x_loc = 11246d36ef34Smrg DumpText(w, x_loc, y_loc, buf, bufp - buf, NORMAL); 11256d36ef34Smrg h_col += bufp - buf; 11266d36ef34Smrg bufp = buf; 11276d36ef34Smrg } 11286d36ef34Smrg italicflag = TRUE; 11296d36ef34Smrg } 11306d36ef34Smrg c += 2; 11316d36ef34Smrg *bufp++ = *c; 11326d36ef34Smrg break; 11336d36ef34Smrg } 1134ae5a67adSmrg /* else fall through - to default, because this was a real underscore. */ 11356d36ef34Smrg 11366d36ef34Smrg default: 11376d36ef34Smrg if (italicflag) { /* font change? */ 11386d36ef34Smrg if (bufp != buf) { 11396d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 11406d36ef34Smrg WHICH(italicflag, FALSE)); 11416d36ef34Smrg h_col += bufp - buf; 11426d36ef34Smrg bufp = buf; 11436d36ef34Smrg } 11446d36ef34Smrg italicflag = FALSE; 11456d36ef34Smrg } 11466d36ef34Smrg *bufp++ = *c; 11476d36ef34Smrg break; 11486d36ef34Smrg } 11496d36ef34Smrg c++; 11501abf7346Smrg } 11511abf7346Smrg} 11521abf7346Smrg 11531abf7346Smrg/* Function Name: DumpText 11541abf7346Smrg * Description: Dumps text to the screen. 11551abf7346Smrg * Arguments: w - the widget. 11561abf7346Smrg * x_loc - to dump text at. 11571abf7346Smrg * y_loc - the y_location to draw_text. 11581abf7346Smrg * buf - buffer to dump. 11591abf7346Smrg * italic, bold, boolean that tells us which gc to use. 11601abf7346Smrg * Returns: x_location of the end of the text. 11611abf7346Smrg */ 11621abf7346Smrg 11631abf7346Smrgstatic int 11646d36ef34SmrgDumpText(Widget w, int x_loc, int y_loc, char *buf, int len, int format) 11651abf7346Smrg{ 11666d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 11676d36ef34Smrg GC gc; 11686d36ef34Smrg XFontStruct *font; 11696d36ef34Smrg 11706d36ef34Smrg switch (format) { 11716d36ef34Smrg 11726d36ef34Smrg case ITALIC: 11736d36ef34Smrg gc = sblw->scroll.italic_gc; 11746d36ef34Smrg font = sblw->scroll.italic_font; 11756d36ef34Smrg break; 11766d36ef34Smrg 11776d36ef34Smrg case BOLD: 11786d36ef34Smrg gc = sblw->scroll.bold_gc; 11796d36ef34Smrg font = sblw->scroll.bold_font; 11806d36ef34Smrg break; 11816d36ef34Smrg 11826d36ef34Smrg case SYMBOL: 11836d36ef34Smrg gc = sblw->scroll.symbol_gc; 11846d36ef34Smrg font = sblw->scroll.symbol_font; 11856d36ef34Smrg break; 11866d36ef34Smrg 11876d36ef34Smrg default: 11886d36ef34Smrg gc = sblw->scroll.normal_gc; 11896d36ef34Smrg font = sblw->scroll.normal_font; 11906d36ef34Smrg break; 11911abf7346Smrg } 11921abf7346Smrg 11936d36ef34Smrg XDrawString(XtDisplay(w), XtWindow(w), gc, x_loc, y_loc, buf, len); 11946d36ef34Smrg return (x_loc + XTextWidth(font, buf, len)); 11951abf7346Smrg} 11961abf7346Smrg 11971abf7346Smrg/* Function Name: Boldify 11981abf7346Smrg * Description: look for keyword. 11991abf7346Smrg * Arguments: sp - string pointer. 12001abf7346Smrg * Returns: 1 if keyword else 0. 12011abf7346Smrg */ 12021abf7346Smrg 12031abf7346Smrgstatic Boolean 12041abf7346SmrgBoldify(register char *sp) 12051abf7346Smrg{ 12066d36ef34Smrg register char *sp_pointer; 12076d36ef34Smrg int length, count; 12081abf7346Smrg 12096d36ef34Smrg/* 12101abf7346Smrg * If there are not lower case letters in the line the assume it is a 12111abf7346Smrg * keyword and boldify it in PrintManpage. 12121abf7346Smrg */ 12131abf7346Smrg 12146d36ef34Smrg length = strlen(sp); 12156d36ef34Smrg for (sp_pointer = sp, count = 0; count < length; sp_pointer++, count++) 12166d36ef34Smrg if (!isupper(*sp_pointer) && !isspace(*sp_pointer)) 12176d36ef34Smrg return (0); 12186d36ef34Smrg return (1); 12191abf7346Smrg} 12201abf7346Smrg 12211abf7346Smrg#undef superclass 12221abf7346Smrg#undef SuperClass 1223