ScrollByL.c revision ae5a67ad
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> 351abf7346Smrg 361abf7346Smrg#include <X11/IntrinsicP.h> 376d36ef34Smrg#include <sys/stat.h> /* depends on IntrinsicP.h */ 381abf7346Smrg#include <X11/StringDefs.h> 391abf7346Smrg 401abf7346Smrg#include <X11/Xaw/Scrollbar.h> 411abf7346Smrg 421abf7346Smrg#include "ScrollByLP.h" 431abf7346Smrg 441abf7346Smrg/* Default Translation Table */ 451abf7346Smrg 466d36ef34Smrgstatic char defaultTranslations[] = 471abf7346Smrg "<Key>f: Page(Forward) \n\ 481abf7346Smrg <Key>b: Page(Back) \n\ 491abf7346Smrg <Key>1: Page(Line, 1) \n\ 501abf7346Smrg <Key>2: Page(Line, 2) \n\ 511abf7346Smrg <Key>3: Page(Line, 3) \n\ 521abf7346Smrg <Key>4: Page(Line, 4) \n\ 531abf7346Smrg <Key>\\ : Page(Forward)"; 541abf7346Smrg 551abf7346Smrg/**************************************************************** 561abf7346Smrg * 571abf7346Smrg * ScrollByLine Resources 581abf7346Smrg * 591abf7346Smrg ****************************************************************/ 601abf7346Smrg 611abf7346Smrg#define Offset(field) XtOffset(ScrollByLineWidget, scroll.field) 621abf7346Smrg#define CoreOffset(field) XtOffset(ScrollByLineWidget, core.field) 631abf7346Smrg 641abf7346Smrgstatic XtResource resources[] = { 651abf7346Smrg {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), 666d36ef34Smrg CoreOffset(width), XtRImmediate, (caddr_t) 500}, 671abf7346Smrg {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), 686d36ef34Smrg CoreOffset(height), XtRImmediate, (caddr_t) 700}, 691abf7346Smrg 701abf7346Smrg {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 716d36ef34Smrg Offset(foreground), XtRString, "XtDefaultForeground"}, 721abf7346Smrg {XtNforceVert, XtCBoolean, XtRBoolean, sizeof(Boolean), 736d36ef34Smrg Offset(force_vert), XtRImmediate, (caddr_t) FALSE}, 741abf7346Smrg {XtNindent, XtCIndent, XtRDimension, sizeof(Dimension), 756d36ef34Smrg Offset(indent), XtRImmediate, (caddr_t) 15}, 761abf7346Smrg {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean), 776d36ef34Smrg Offset(use_right), XtRImmediate, (caddr_t) FALSE}, 781abf7346Smrg {XtNmanualFontNormal, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 796d36ef34Smrg Offset(normal_font), XtRString, MANPAGE_NORMAL}, 801abf7346Smrg {XtNmanualFontBold, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 816d36ef34Smrg Offset(bold_font), XtRString, MANPAGE_BOLD}, 821abf7346Smrg {XtNmanualFontItalic, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 836d36ef34Smrg Offset(italic_font), XtRString, MANPAGE_ITALIC}, 841abf7346Smrg {XtNmanualFontSymbol, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 856d36ef34Smrg Offset(symbol_font), XtRString, MANPAGE_SYMBOL}, 861abf7346Smrg {XtNfile, XtCFile, XtRFile, sizeof(FILE *), 876d36ef34Smrg Offset(file), XtRImmediate, (caddr_t) NULL}, 881abf7346Smrg {XtNNumTotalLines, XtCNumTotalLines, XtRInt, sizeof(int), 896d36ef34Smrg Offset(lines), XtRImmediate, (caddr_t) 0}, 901abf7346Smrg {XtNNumVisibleLines, XtCNumVisibleLines, XtRInt, sizeof(int), 916d36ef34Smrg Offset(num_visible_lines), XtRImmediate, (caddr_t) 0}, 921abf7346Smrg}; 931abf7346Smrg 941abf7346Smrg#undef Offset 951abf7346Smrg#undef CoreOffset 961abf7346Smrg 971abf7346Smrg/**************************************************************** 981abf7346Smrg * 991abf7346Smrg * Full class record constant 1001abf7346Smrg * 1011abf7346Smrg ****************************************************************/ 1021abf7346Smrg 1031abf7346Smrgstatic void CreateScrollbar(Widget w); 1041abf7346Smrgstatic Boolean ScrollVerticalText(Widget w, int new_line, Boolean force_redisp); 1051abf7346Smrgstatic void Layout(Widget w); 1061abf7346Smrgstatic void LoadFile(Widget w); 1071abf7346Smrgstatic void MoveAndClearText(Widget w, int old_y, int height, int new_y); 1081abf7346Smrgstatic void PaintText(Widget w, int y_loc, int height); 1091abf7346Smrgstatic void PrintText(Widget w, int start_line, int num_lines, int location); 1101abf7346Smrgstatic void SetThumbHeight(Widget w); 1111abf7346Smrgstatic void VerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr); 1126d36ef34Smrgstatic void VerticalScroll(Widget w, XtPointer client_data, 1136d36ef34Smrg XtPointer call_data); 1141abf7346Smrg 1151abf7346Smrg/* semi - public functions. */ 1161abf7346Smrg 1176d36ef34Smrgstatic void Realize(Widget w, Mask *valueMask, 1186d36ef34Smrg XSetWindowAttributes *attributes); 1196d36ef34Smrgstatic void Initialize(Widget req, Widget new, ArgList args, 1206d36ef34Smrg Cardinal *num_args); 1211abf7346Smrgstatic void Destroy(Widget w); 1221abf7346Smrgstatic void Redisplay(Widget w, XEvent *event, Region region); 1236d36ef34Smrgstatic void Page(Widget w, XEvent *event, String *params, Cardinal *num_params); 1241abf7346Smrgstatic Boolean SetValuesHook(Widget w, ArgList args, Cardinal *num_args); 1251abf7346Smrg 1261abf7346Smrgstatic XtActionsRec actions[] = { 1276d36ef34Smrg {"Page", Page}, 1281abf7346Smrg}; 1291abf7346Smrg 1301abf7346Smrg#define superclass (&simpleClassRec) 1311abf7346Smrg#define SuperClass simpleWidgetClass 1321abf7346Smrg 1331abf7346SmrgScrollByLineClassRec scrollByLineClassRec = { 1346d36ef34Smrg { 1351abf7346Smrg/* core_class fields */ 1366d36ef34Smrg /* superclass */ (WidgetClass) superclass, 1376d36ef34Smrg /* class_name */ "ScrollByLine", 1386d36ef34Smrg /* widget_size */ sizeof(ScrollByLineRec), 1396d36ef34Smrg /* class_initialize */ NULL, 1406d36ef34Smrg /* class_part_init */ NULL, 1416d36ef34Smrg /* class_inited */ FALSE, 1426d36ef34Smrg /* initialize */ Initialize, 1436d36ef34Smrg /* initialize_hook */ NULL, 1446d36ef34Smrg /* realize */ Realize, 1456d36ef34Smrg /* actions */ actions, 1466d36ef34Smrg /* num_actions */ XtNumber(actions), 1476d36ef34Smrg /* resources */ resources, 1486d36ef34Smrg /* num_resources */ XtNumber(resources), 1496d36ef34Smrg /* xrm_class */ NULLQUARK, 1506d36ef34Smrg /* compress_motion */ TRUE, 1516d36ef34Smrg /* compress_exposure */ FALSE, 1526d36ef34Smrg /* compress_enterleave */ TRUE, 1536d36ef34Smrg /* visible_interest */ FALSE, 1546d36ef34Smrg /* destroy */ Destroy, 1556d36ef34Smrg /* resize */ Layout, 1566d36ef34Smrg /* expose */ Redisplay, 1576d36ef34Smrg /* set_values */ NULL, 1586d36ef34Smrg /* set_values_hook */ SetValuesHook, 1596d36ef34Smrg /* set_values_almost */ XtInheritSetValuesAlmost, 1606d36ef34Smrg /* get_values_hook */ NULL, 1616d36ef34Smrg /* accept_focus */ NULL, 1626d36ef34Smrg /* version */ XtVersion, 1636d36ef34Smrg /* callback_private */ NULL, 1646d36ef34Smrg /* tm_table */ defaultTranslations, 1656d36ef34Smrg /* query_geometry */ XtInheritQueryGeometry, 1666d36ef34Smrg /* display_accelerator */ XtInheritDisplayAccelerator, 1676d36ef34Smrg /* extension */ NULL, 1686d36ef34Smrg }, 1696d36ef34Smrg { 1706d36ef34Smrg/* simple fields */ 1716d36ef34Smrg /* change_sensitive */ XtInheritChangeSensitive 1726d36ef34Smrg } 1731abf7346Smrg}; 1741abf7346Smrg 1756d36ef34SmrgWidgetClass scrollByLineWidgetClass = (WidgetClass) &scrollByLineClassRec; 1761abf7346Smrg 1771abf7346Smrg/**************************************************************** 1781abf7346Smrg * 1791abf7346Smrg * Private Routines 1801abf7346Smrg * 1811abf7346Smrg ****************************************************************/ 1821abf7346Smrg 1831abf7346Smrg/* Function Name: Layout 1841abf7346Smrg * Description: This function lays out the scroll widget. 1851abf7346Smrg * Arguments: w - the scroll widget. 1861abf7346Smrg * key - a boolean: if true then resize the widget to the child 1871abf7346Smrg * if false the resize children to fit widget. 1881abf7346Smrg * Returns: TRUE if successful. 1891abf7346Smrg */ 1901abf7346Smrg 1911abf7346Smrgstatic void 1921abf7346SmrgLayout(Widget w) 1936d36ef34Smrg{ 1946d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 1956d36ef34Smrg Dimension width, height; 1966d36ef34Smrg Widget bar; 1976d36ef34Smrg Position bar_bw; 1981abf7346Smrg 1996d36ef34Smrg CreateScrollbar(w); 2001abf7346Smrg 2016d36ef34Smrg/* 2021abf7346Smrg * For now always show the bar. 2031abf7346Smrg */ 2041abf7346Smrg 2056d36ef34Smrg bar = sblw->scroll.bar; 2066d36ef34Smrg height = sblw->core.height; 2076d36ef34Smrg width = sblw->core.width; 2086d36ef34Smrg bar_bw = bar->core.border_width; 2091abf7346Smrg 2106d36ef34Smrg /* Move child and v_bar to correct location. */ 2116d36ef34Smrg if (sblw->scroll.use_right) { 2126d36ef34Smrg XtMoveWidget(bar, width - (bar->core.width + bar_bw), -bar_bw); 2136d36ef34Smrg sblw->scroll.offset = 0; 2146d36ef34Smrg } 2156d36ef34Smrg else { 2166d36ef34Smrg XtMoveWidget(bar, -bar_bw, -bar_bw); 2176d36ef34Smrg sblw->scroll.offset = bar->core.width + bar_bw; 2186d36ef34Smrg } 2191abf7346Smrg 2206d36ef34Smrg /* resize the scrollbar to be the correct height or width. */ 2216d36ef34Smrg XtResizeWidget(bar, bar->core.width, height, bar->core.border_width); 2221abf7346Smrg 2236d36ef34Smrg SetThumbHeight(w); 2241abf7346Smrg 2256d36ef34Smrg sblw->scroll.num_visible_lines = height / sblw->scroll.font_height + 1; 2261abf7346Smrg} 2271abf7346Smrg 2281abf7346Smrg/* ARGSUSED */ 2296d36ef34Smrgstatic void 2306d36ef34SmrgGExpose(Widget w, XtPointer junk, XEvent * event, Boolean * cont) 2311abf7346Smrg{ 2321abf7346Smrg 2331abf7346Smrg/* 2341abf7346Smrg * Graphics exposure events are not currently sent to exposure proc. 2351abf7346Smrg */ 2361abf7346Smrg 2376d36ef34Smrg if (event->type == GraphicsExpose) 2386d36ef34Smrg Redisplay(w, event, NULL); 2391abf7346Smrg 2406d36ef34Smrg} /* ChildExpose */ 2411abf7346Smrg 2421abf7346Smrg/* 2431abf7346Smrg * Repaint the widget's child Window Widget. 2441abf7346Smrg */ 2451abf7346Smrg 2461abf7346Smrg/* ARGSUSED */ 2471abf7346Smrgstatic void 2486d36ef34SmrgRedisplay(Widget w, XEvent * event, Region region) 2491abf7346Smrg{ 2506d36ef34Smrg int top, height; /* the locations of the top and height 2516d36ef34Smrg of the region that needs to be repainted. */ 2526d36ef34Smrg 2531abf7346Smrg/* 2546d36ef34Smrg * This routine tells the client which sections of the window to 2551abf7346Smrg * repaint in his callback function which does the actual repainting. 2561abf7346Smrg */ 2571abf7346Smrg 2586d36ef34Smrg if (event->type == Expose) { 2596d36ef34Smrg top = event->xexpose.y; 2606d36ef34Smrg height = event->xexpose.height; 2616d36ef34Smrg } 2626d36ef34Smrg else { 2636d36ef34Smrg top = event->xgraphicsexpose.y; 2646d36ef34Smrg height = event->xgraphicsexpose.height; 2656d36ef34Smrg } 2666d36ef34Smrg 2676d36ef34Smrg PaintText(w, top, height); 2686d36ef34Smrg} /* redisplay (expose) */ 2691abf7346Smrg 2701abf7346Smrg/* Function Name: PaintText 2711abf7346Smrg * Description: paints the text at the give location for a given height. 2721abf7346Smrg * Arguments: w - the sbl widget. 2731abf7346Smrg * y_loc, height - location and size of area to paint. 2741abf7346Smrg * Returns: none 2751abf7346Smrg */ 2761abf7346Smrg 2771abf7346Smrgstatic void 2781abf7346SmrgPaintText(Widget w, int y_loc, int height) 2791abf7346Smrg{ 2806d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 2816d36ef34Smrg int start_line, location; 2826d36ef34Smrg 2836d36ef34Smrg start_line = y_loc / sblw->scroll.font_height + sblw->scroll.line_pointer; 2841abf7346Smrg 2856d36ef34Smrg if (start_line >= sblw->scroll.lines) 2866d36ef34Smrg return; 2871abf7346Smrg 2881abf7346Smrg/* 2896d36ef34Smrg * Only integer arithmetic makes this possible. 2901abf7346Smrg */ 2911abf7346Smrg 2926d36ef34Smrg location = y_loc / sblw->scroll.font_height * sblw->scroll.font_height; 2931abf7346Smrg 2946d36ef34Smrg PrintText(w, start_line, sblw->scroll.num_visible_lines, location); 2956d36ef34Smrg} 2961abf7346Smrg 2971abf7346Smrg/* Function Name: Page 2986d36ef34Smrg * Description: This function pages the widget, by the amount it receives 2991abf7346Smrg * from the translation Manager. 3001abf7346Smrg * Arguments: w - the ScrollByLineWidget. 3011abf7346Smrg * event - the event that caused this return. 3021abf7346Smrg * params - the parameters passed to it. 3031abf7346Smrg * num_params - the number of parameters. 3041abf7346Smrg * Returns: none. 3051abf7346Smrg */ 3061abf7346Smrg 3071abf7346Smrg/* ARGSUSED */ 3086d36ef34Smrgstatic void 3096d36ef34SmrgPage(Widget w, XEvent * event, String * params, Cardinal * num_params) 3101abf7346Smrg{ 3116d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3126d36ef34Smrg Widget bar = sblw->scroll.bar; 3131abf7346Smrg 3146d36ef34Smrg if (*num_params < 1) 3156d36ef34Smrg return; 3161abf7346Smrg/* 3171abf7346Smrg * If no scroll bar is visible then do not page, as the entire window is shown, 3186d36ef34Smrg * or scrolling has been turned off. 3191abf7346Smrg */ 3201abf7346Smrg 3216d36ef34Smrg if (bar == (Widget) NULL) 3226d36ef34Smrg return; 3236d36ef34Smrg 3246d36ef34Smrg switch (params[0][0]) { 3256d36ef34Smrg case 'f': 3266d36ef34Smrg case 'F': 3276d36ef34Smrg /* move one page forward */ 3286d36ef34Smrg VerticalScroll(bar, NULL, (XtPointer) ((long) bar->core.height)); 3296d36ef34Smrg break; 3306d36ef34Smrg case 'b': 3316d36ef34Smrg case 'B': 3326d36ef34Smrg /* move one page backward */ 3336d36ef34Smrg VerticalScroll(bar, NULL, (XtPointer) (-(long) bar->core.height)); 3346d36ef34Smrg break; 3356d36ef34Smrg case 'L': 3366d36ef34Smrg case 'l': 3376d36ef34Smrg /* move one line forward */ 3386d36ef34Smrg VerticalScroll(bar, NULL, 3396d36ef34Smrg (XtPointer) ((long) atoi(params[1]) * 3406d36ef34Smrg sblw->scroll.font_height)); 3416d36ef34Smrg break; 3426d36ef34Smrg default: 3436d36ef34Smrg return; 3446d36ef34Smrg } 3451abf7346Smrg} 3461abf7346Smrg 3471abf7346Smrg/* Function Name: CreateScrollbar 3481abf7346Smrg * Description: createst the scrollbar for us. 3491abf7346Smrg * Arguments: w - sblw widget. 3501abf7346Smrg * Returns: none. 3511abf7346Smrg */ 3521abf7346Smrg 3531abf7346Smrgstatic void 3541abf7346SmrgCreateScrollbar(Widget w) 3551abf7346Smrg{ 3566d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3576d36ef34Smrg Arg args[5]; 3586d36ef34Smrg Cardinal num_args = 0; 3596d36ef34Smrg 3606d36ef34Smrg if (sblw->scroll.bar != NULL) 3616d36ef34Smrg return; 3626d36ef34Smrg 3636d36ef34Smrg XtSetArg(args[num_args], XtNorientation, XtorientVertical); 3646d36ef34Smrg num_args++; 3656d36ef34Smrg 3666d36ef34Smrg sblw->scroll.bar = XtCreateWidget("scrollbar", scrollbarWidgetClass, w, 3676d36ef34Smrg args, num_args); 3686d36ef34Smrg XtAddCallback(sblw->scroll.bar, XtNscrollProc, VerticalScroll, NULL); 3696d36ef34Smrg XtAddCallback(sblw->scroll.bar, XtNjumpProc, VerticalJump, NULL); 3701abf7346Smrg} 3711abf7346Smrg 3721abf7346Smrg/* Function Name: ScrollVerticalText 3731abf7346Smrg * Description: This accomplished the actual movement of the text. 3741abf7346Smrg * Arguments: w - the ScrollByLine Widget. 3751abf7346Smrg * new_line - the new location for the line pointer 3766d36ef34Smrg * force_redisplay - should we force this window to get 3771abf7346Smrg * redisplayed? 3781abf7346Smrg * Returns: True if the thumb needs to be moved. 3791abf7346Smrg */ 3801abf7346Smrg 3811abf7346Smrgstatic Boolean 3826d36ef34SmrgScrollVerticalText(Widget w, int new_line, Boolean force_redisp) 3831abf7346Smrg{ 3846d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3856d36ef34Smrg int num_lines = sblw->scroll.num_visible_lines; 3866d36ef34Smrg int max_lines, old_line; 3876d36ef34Smrg Boolean move_thumb = FALSE; 3881abf7346Smrg 3891abf7346Smrg/* 3901abf7346Smrg * Do not let the window extend out of bounds. 3911abf7346Smrg */ 3921abf7346Smrg 3936d36ef34Smrg if (new_line < 0) { 3946d36ef34Smrg new_line = 0; 3956d36ef34Smrg move_thumb = TRUE; 3966d36ef34Smrg } 3976d36ef34Smrg else { 3986d36ef34Smrg max_lines = sblw->scroll.lines - 3996d36ef34Smrg (int) w->core.height / sblw->scroll.font_height; 4006d36ef34Smrg if (max_lines < 0) 4016d36ef34Smrg max_lines = 0; 4026d36ef34Smrg 4036d36ef34Smrg if (new_line > max_lines) { 4046d36ef34Smrg new_line = max_lines; 4056d36ef34Smrg move_thumb = TRUE; 4066d36ef34Smrg } 4071abf7346Smrg } 4081abf7346Smrg 4096d36ef34Smrg/* 4101abf7346Smrg * If forced to redisplay then do a full redisplay and return. 4111abf7346Smrg */ 4121abf7346Smrg 4136d36ef34Smrg old_line = sblw->scroll.line_pointer; 4146d36ef34Smrg sblw->scroll.line_pointer = new_line; /* Set current top of page. */ 4151abf7346Smrg 4166d36ef34Smrg if (force_redisp) 4176d36ef34Smrg MoveAndClearText(w, 0, /* cause a full redisplay */ 0, 0); 4181abf7346Smrg 4196d36ef34Smrg if (new_line == old_line) 4206d36ef34Smrg return (move_thumb); 4211abf7346Smrg 4221abf7346Smrg/* 4231abf7346Smrg * Scroll forward. 4241abf7346Smrg */ 4251abf7346Smrg 4266d36ef34Smrg else if (new_line < old_line) { 4276d36ef34Smrg int lines_to_scroll = old_line - new_line; 4286d36ef34Smrg MoveAndClearText(w, 0, num_lines - lines_to_scroll, lines_to_scroll); 4296d36ef34Smrg } 4301abf7346Smrg 4316d36ef34Smrg/* 4321abf7346Smrg * Scroll back. 4331abf7346Smrg */ 4341abf7346Smrg 4356d36ef34Smrg else { 4366d36ef34Smrg int lines_to_scroll = new_line - old_line; 4376d36ef34Smrg MoveAndClearText(w, lines_to_scroll, num_lines - lines_to_scroll, 0); 4386d36ef34Smrg } 4391abf7346Smrg 4406d36ef34Smrg return (move_thumb); 4411abf7346Smrg} 4421abf7346Smrg 4431abf7346Smrg/* Function Name: MoveAndClearText 4441abf7346Smrg * Description: Blits as much text as it can and clear the 4451abf7346Smrg * remaining area with generate exposures TRUE. 4461abf7346Smrg * Arguments: w - the sbl widget. 4471abf7346Smrg * old_y - the old y position. 4481abf7346Smrg * height - height of area to move. 4491abf7346Smrg * new_y - new y position. 4501abf7346Smrg * Returns: none 4511abf7346Smrg */ 4526d36ef34Smrg 4531abf7346Smrgstatic void 4541abf7346SmrgMoveAndClearText(Widget w, int old_y, int height, int new_y) 4551abf7346Smrg{ 4566d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 4576d36ef34Smrg int from_left = sblw->scroll.indent + sblw->scroll.offset - 1; 4586d36ef34Smrg int y_clear; 4591abf7346Smrg 4606d36ef34Smrg old_y *= sblw->scroll.font_height; 4616d36ef34Smrg new_y *= sblw->scroll.font_height; 4626d36ef34Smrg height *= sblw->scroll.font_height; 4631abf7346Smrg 4641abf7346Smrg/* 4651abf7346Smrg * If we are already at the right location then do nothing. 4661abf7346Smrg * (height == 0). 4671abf7346Smrg * 4681abf7346Smrg * If we have scrolled more than a screen height then just clear 4691abf7346Smrg * the window. 4701abf7346Smrg */ 4711abf7346Smrg 4726d36ef34Smrg if (height <= sblw->scroll.font_height) { /* avoid rounding errors. */ 4736d36ef34Smrg XClearArea(XtDisplay(w), XtWindow(w), from_left, 0, 4746d36ef34Smrg (unsigned int) 0, (unsigned int) 0, FALSE); 4756d36ef34Smrg PaintText(w, 0, (int) sblw->core.height); 4766d36ef34Smrg return; 4776d36ef34Smrg } 4786d36ef34Smrg 4796d36ef34Smrg if ((int) height + (int) old_y > (int) w->core.height) 4806d36ef34Smrg height = w->core.height - old_y; 4816d36ef34Smrg 4826d36ef34Smrg XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), sblw->scroll.move_gc, 4836d36ef34Smrg from_left, old_y, 4846d36ef34Smrg (unsigned int) w->core.width - from_left, (unsigned int) height, 4856d36ef34Smrg from_left, new_y); 4866d36ef34Smrg 4876d36ef34Smrg if (old_y > new_y) 4886d36ef34Smrg height -= sblw->scroll.font_height / 2; /* clear 1/2 font of extra space, 4896d36ef34Smrg to make sure we don't lose or 4906d36ef34Smrg gain descenders. */ 4916d36ef34Smrg else 4926d36ef34Smrg height -= sblw->scroll.font_height; /* clear 1 font of extra space, 4936d36ef34Smrg to make sure we don't overwrite 4946d36ef34Smrg with a last line in buffer. */ 4956d36ef34Smrg 4966d36ef34Smrg if (old_y > new_y) 4976d36ef34Smrg y_clear = height; 4986d36ef34Smrg else 4996d36ef34Smrg y_clear = 0; 5006d36ef34Smrg 5011abf7346Smrg/* 5021abf7346Smrg * We cannot use generate exposures, since that may allow another move and 5031abf7346Smrg * clear before the area get repainted, this would be bad. 5041abf7346Smrg */ 5051abf7346Smrg 5066d36ef34Smrg XClearArea(XtDisplay(w), XtWindow(w), from_left, y_clear, 5076d36ef34Smrg (unsigned int) 0, (unsigned int) (w->core.height - height), 5086d36ef34Smrg FALSE); 5096d36ef34Smrg PaintText(w, (int) y_clear, (int) (w->core.height - height)); 5101abf7346Smrg} 5111abf7346Smrg 5121abf7346Smrg/* Function Name: SetThumbHeight 5131abf7346Smrg * Description: Set the height of the thumb. 5141abf7346Smrg * Arguments: w - the sblw widget. 5151abf7346Smrg * Returns: none 5161abf7346Smrg */ 5171abf7346Smrg 5181abf7346Smrgstatic void 5191abf7346SmrgSetThumbHeight(Widget w) 5201abf7346Smrg{ 5216d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5226d36ef34Smrg float shown; 5231abf7346Smrg 5246d36ef34Smrg if (sblw->scroll.bar == NULL) 5256d36ef34Smrg return; 5261abf7346Smrg 5276d36ef34Smrg if (sblw->scroll.lines == 0) 5286d36ef34Smrg shown = 1.0; 5296d36ef34Smrg else 5306d36ef34Smrg shown = (float) w->core.height / (float) (sblw->scroll.lines * 5316d36ef34Smrg sblw->scroll.font_height); 5326d36ef34Smrg if (shown > 1.0) 5336d36ef34Smrg shown = 1.0; 5341abf7346Smrg 5356d36ef34Smrg XawScrollbarSetThumb(sblw->scroll.bar, (float) -1, shown); 5361abf7346Smrg} 5371abf7346Smrg 5381abf7346Smrg/* Function Name: SetThumb 5391abf7346Smrg * Description: Set the thumb location. 5401abf7346Smrg * Arguments: w - the sblw. 5411abf7346Smrg * Returns: none 5421abf7346Smrg */ 5431abf7346Smrg 5441abf7346Smrgstatic void 5451abf7346SmrgSetThumb(Widget w) 5461abf7346Smrg{ 5476d36ef34Smrg float location; 5486d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5491abf7346Smrg 5506d36ef34Smrg if ((sblw->scroll.lines == 0) || (sblw->scroll.bar == NULL)) 5516d36ef34Smrg return; 5521abf7346Smrg 5536d36ef34Smrg location = (float) sblw->scroll.line_pointer / (float) sblw->scroll.lines; 5546d36ef34Smrg XawScrollbarSetThumb(sblw->scroll.bar, location, (float) -1); 5551abf7346Smrg} 5561abf7346Smrg 5571abf7346Smrg/* Function Name: VerticalJump. 5581abf7346Smrg * Description: This function moves the test 5591abf7346Smrg * as the vertical scroll bar is moved. 5601abf7346Smrg * Arguments: w - the scrollbar widget. 5611abf7346Smrg * junk - not used. 5621abf7346Smrg * percent - the position of the scrollbar. 5631abf7346Smrg * Returns: none. 5641abf7346Smrg */ 5651abf7346Smrg 5661abf7346Smrg/* ARGSUSED */ 5671abf7346Smrgstatic void 5681abf7346SmrgVerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr) 5691abf7346Smrg{ 5706d36ef34Smrg float percent = *((float *) percent_ptr); 5716d36ef34Smrg int new_line; /* The new location for the line pointer. */ 5726d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 5731abf7346Smrg 5746d36ef34Smrg new_line = (int) ((float) sblw->scroll.lines * percent); 5756d36ef34Smrg if (ScrollVerticalText((Widget) sblw, new_line, FALSE)) 5766d36ef34Smrg SetThumb((Widget) sblw); 5771abf7346Smrg} 5781abf7346Smrg 5791abf7346Smrg/* Function Name: VerticalScroll 5806d36ef34Smrg * Description: This function moves the position of the interior window 5811abf7346Smrg * as the vertical scroll bar is moved. 5821abf7346Smrg * Arguments: w - the scrollbar widget. 5831abf7346Smrg * junk - not used. 5841abf7346Smrg * pos - the position of the cursor. 5851abf7346Smrg * Returns: none. 5861abf7346Smrg */ 5871abf7346Smrg 5881abf7346Smrg/* ARGSUSED */ 5891abf7346Smrgstatic void 5901abf7346SmrgVerticalScroll(Widget w, XtPointer client_data, XtPointer call_data) 5911abf7346Smrg{ 5926d36ef34Smrg int pos = (int) (long) call_data; 5936d36ef34Smrg int new_line; /* The new location for the line pointer. */ 5946d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 5951abf7346Smrg 5966d36ef34Smrg new_line = sblw->scroll.line_pointer + (pos / sblw->scroll.font_height); 5976d36ef34Smrg (void) ScrollVerticalText((Widget) sblw, new_line, FALSE); 5986d36ef34Smrg SetThumb((Widget) sblw); 5991abf7346Smrg} 6001abf7346Smrg 6011abf7346Smrg/* ARGSUSED */ 6026d36ef34Smrgstatic void 6036d36ef34SmrgInitialize(Widget req, Widget new, ArgList args, Cardinal * num_args) 6041abf7346Smrg{ 6056d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) new; 6066d36ef34Smrg unsigned long figWidth; 6076d36ef34Smrg Atom atomNum; 6081abf7346Smrg 6096d36ef34Smrg sblw->scroll.top_line = NULL; 6106d36ef34Smrg sblw->scroll.line_pointer = 0; 6116d36ef34Smrg LoadFile(new); 6126d36ef34Smrg sblw->scroll.bar = (Widget) NULL; 6131abf7346Smrg 6146d36ef34Smrg sblw->scroll.font_height = (sblw->scroll.normal_font->max_bounds.ascent + 6156d36ef34Smrg sblw->scroll.normal_font->max_bounds.descent); 6161abf7346Smrg 6176d36ef34Smrg atomNum = XInternAtom(XtDisplay(req), "FIGURE_WIDTH", False); 6181abf7346Smrg 6196d36ef34Smrg if (XGetFontProperty(sblw->scroll.normal_font, atomNum, &figWidth)) 6206d36ef34Smrg sblw->scroll.h_width = figWidth; 6216d36ef34Smrg else 6226d36ef34Smrg sblw->scroll.h_width = XTextWidth(sblw->scroll.normal_font, "$", 1); 6236d36ef34Smrg} /* Initialize. */ 6241abf7346Smrg 6251abf7346Smrg/* Function Name: CreateGCs 6266d36ef34Smrg * Description: Creates the graphics contexts that we need. 6271abf7346Smrg * Arguments: w - the sblw. 6281abf7346Smrg * Returns: none 6291abf7346Smrg */ 6301abf7346Smrg 6311abf7346Smrgstatic void 6321abf7346SmrgCreateGCs(Widget w) 6331abf7346Smrg{ 6346d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6356d36ef34Smrg 6366d36ef34Smrg XtGCMask mask; 6376d36ef34Smrg XGCValues values; 6381abf7346Smrg 6396d36ef34Smrg values.graphics_exposures = TRUE; 6406d36ef34Smrg sblw->scroll.move_gc = XtGetGC(w, GCGraphicsExposures, &values); 6411abf7346Smrg 6426d36ef34Smrg mask = GCForeground | GCFont; 6436d36ef34Smrg values.foreground = sblw->scroll.foreground; 6441abf7346Smrg 6456d36ef34Smrg values.font = sblw->scroll.normal_font->fid; 6466d36ef34Smrg sblw->scroll.normal_gc = XtGetGC(w, mask, &values); 6471abf7346Smrg 6486d36ef34Smrg values.font = sblw->scroll.italic_font->fid; 6496d36ef34Smrg sblw->scroll.italic_gc = XtGetGC(w, mask, &values); 6501abf7346Smrg 6516d36ef34Smrg values.font = sblw->scroll.bold_font->fid; 6526d36ef34Smrg sblw->scroll.bold_gc = XtGetGC(w, mask, &values); 6531abf7346Smrg 6546d36ef34Smrg values.font = sblw->scroll.symbol_font->fid; 6556d36ef34Smrg sblw->scroll.symbol_gc = XtGetGC(w, mask, &values); 6561abf7346Smrg} 6571abf7346Smrg 6581abf7346Smrg/* Function Name: DestroyGCs 6591abf7346Smrg * Description: removes all gcs for this widget. 6601abf7346Smrg * Arguments: w - the widget. 6611abf7346Smrg * Returns: none 6621abf7346Smrg */ 6631abf7346Smrg 6641abf7346Smrgstatic void 6651abf7346SmrgDestroyGCs(Widget w) 6661abf7346Smrg{ 6676d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6681abf7346Smrg 6696d36ef34Smrg XtReleaseGC(w, sblw->scroll.normal_gc); 6706d36ef34Smrg XtReleaseGC(w, sblw->scroll.bold_gc); 6716d36ef34Smrg XtReleaseGC(w, sblw->scroll.italic_gc); 6726d36ef34Smrg XtReleaseGC(w, sblw->scroll.move_gc); 6731abf7346Smrg} 6741abf7346Smrg 6751abf7346Smrgstatic void 6766d36ef34SmrgRealize(Widget w, Mask *valueMask, XSetWindowAttributes * attributes) 6771abf7346Smrg{ 6786d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6791abf7346Smrg 6806d36ef34Smrg CreateScrollbar(w); 6816d36ef34Smrg CreateGCs(w); 6826d36ef34Smrg Layout(w); 6836d36ef34Smrg (*SuperClass->core_class.realize) (w, valueMask, attributes); 6846d36ef34Smrg XtRealizeWidget(sblw->scroll.bar); /* realize scrollbar. */ 6856d36ef34Smrg XtMapWidget(sblw->scroll.bar); /* map scrollbar. */ 6861abf7346Smrg 6876d36ef34Smrg XtAddEventHandler(w, 0, TRUE, GExpose, NULL); /* Get Graphics Exposures */ 6886d36ef34Smrg} /* Realize */ 6891abf7346Smrg 6901abf7346Smrg/* Function Name: Destroy 6911abf7346Smrg * Description: Cleans up when we are killed. 6921abf7346Smrg * Arguments: w - the widget. 6931abf7346Smrg * Returns: none 6941abf7346Smrg */ 6951abf7346Smrg 6961abf7346Smrgstatic void 6971abf7346SmrgDestroy(Widget w) 6981abf7346Smrg{ 6996d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7001abf7346Smrg 7016d36ef34Smrg if (sblw->scroll.bar != NULL) 7026d36ef34Smrg XtDestroyWidget(sblw->scroll.bar); /* Destroy scrollbar. */ 7036d36ef34Smrg if (sblw->scroll.file != NULL) 7046d36ef34Smrg fclose(sblw->scroll.file); 7056d36ef34Smrg DestroyGCs(w); 7061abf7346Smrg} 7071abf7346Smrg 7081abf7346Smrg/* 7091abf7346Smrg * 7101abf7346Smrg * Set Values 7111abf7346Smrg * 7121abf7346Smrg */ 7131abf7346Smrg 7141abf7346Smrg/* ARGSUSED */ 7156d36ef34Smrgstatic Boolean 7166d36ef34SmrgSetValuesHook(Widget w, ArgList args, Cardinal * num_args) 7171abf7346Smrg{ 7186d36ef34Smrg Boolean ret = TRUE; 7196d36ef34Smrg Cardinal i; 7206d36ef34Smrg 7216d36ef34Smrg for (i = 0; i < *num_args; i++) { 7226d36ef34Smrg if (strcmp(XtNfile, args[i].name) == 0) { 7236d36ef34Smrg LoadFile(w); 7246d36ef34Smrg ret = TRUE; 7256d36ef34Smrg } 7261abf7346Smrg } 7271abf7346Smrg 7281abf7346Smrg/* 7296d36ef34Smrg * Changing anything else will have strange effects, I don't need it so 7301abf7346Smrg * I didn't code it. 7311abf7346Smrg */ 7321abf7346Smrg 7336d36ef34Smrg return (ret); 7341abf7346Smrg 7356d36ef34Smrg} /* Set Values */ 7361abf7346Smrg 7376d36ef34Smrg/* 7386d36ef34Smrg * A little design philosophy is probably wise to include at this point. 7391abf7346Smrg * 7401abf7346Smrg * One of the things that I has hoped to achieve with xman is to make the 7411abf7346Smrg * viewing of manpage not only easy for the nieve user, but also fast for 7421abf7346Smrg * the experienced user, I wanted to be able to use it too. To achieve this 7431abf7346Smrg * I end up sacrificing a bit of start up time for the manual data structure. 7446d36ef34Smrg * As well as, the overhead of reading the entire file before putting it up 7451abf7346Smrg * on the display. This is actually hardly even noticeable since most manual 7461abf7346Smrg * pages are shots, one to two pages - the notable exception is of course csh, 7476d36ef34Smrg * but then that should be broken up anyway. 7481abf7346Smrg * 7491abf7346Smrg * METHOD: 7501abf7346Smrg * 7511abf7346Smrg * I allocate a chunk of space that is the size of the file, plus a null for 7526d36ef34Smrg * debugging. Then copies the file into this chunk of memory. I then allocate 7531abf7346Smrg * an array of char*'s that are assigned to the beginning of each line. Yes, 7546d36ef34Smrg * this means that I have to read the file twice, and could probably be more 7551abf7346Smrg * clever about it, but once it is in memory the second read is damn fast. 7566d36ef34Smrg * There are a few obscurities here about guessing the number of lines and 7576d36ef34Smrg * reallocing if I guess wrong, but other than that it is pretty straight 7581abf7346Smrg * forward. 7591abf7346Smrg * 7601abf7346Smrg * Chris Peterson 7611abf7346Smrg * 1/27/88 7621abf7346Smrg */ 7631abf7346Smrg 7646d36ef34Smrg#define ADD_MORE_MEM 100 /* first guesses for allocations. */ 7651abf7346Smrg#define CHAR_PER_LINE 40 7661abf7346Smrg 7671abf7346Smrg/* Function Name: LoadFile 7681abf7346Smrg * Description: Loads the current file into the internal memory. 7691abf7346Smrg * Arguments: w - the sblw. 7701abf7346Smrg * Returns: none 7711abf7346Smrg */ 7721abf7346Smrg 7731abf7346Smrgstatic void 7741abf7346SmrgLoadFile(Widget w) 7751abf7346Smrg{ 7766d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7776d36ef34Smrg FILE *file = sblw->scroll.file; 7786d36ef34Smrg 7796d36ef34Smrg char *page; 7806d36ef34Smrg char **line_pointer, **top_line; /* pointers to beginnings of the 7816d36ef34Smrg lines of the file. */ 7826d36ef34Smrg int nlines; /* the current number of allocated lines. */ 7836d36ef34Smrg struct stat fileinfo; /* file information from fstat. */ 7846d36ef34Smrg 7856d36ef34Smrg if (sblw->scroll.top_line != NULL) { 7866d36ef34Smrg XtFree(*(sblw->scroll.top_line)); /* free characters. */ 7876d36ef34Smrg XtFree((char *) (sblw->scroll.top_line)); /* free lines. */ 7886d36ef34Smrg } 7896d36ef34Smrg sblw->scroll.top_line = NULL; 7901abf7346Smrg 7916d36ef34Smrg if (file == NULL) 7926d36ef34Smrg return; 7931abf7346Smrg 7941abf7346Smrg/* 7956d36ef34Smrg * Get file size and allocate a chunk of memory for the file to be 7961abf7346Smrg * copied into. 7971abf7346Smrg */ 7981abf7346Smrg 7996d36ef34Smrg if (fstat(fileno(file), &fileinfo)) 8006d36ef34Smrg XtAppError(XtWidgetToApplicationContext(w), 8016d36ef34Smrg "SBLW LoadFile: Failure in fstat."); 8021abf7346Smrg 8036d36ef34Smrg/* 8041abf7346Smrg * Allocate a space for a list of pointer to the beginning of each line. 8051abf7346Smrg */ 8061abf7346Smrg 8076d36ef34Smrg if ((nlines = fileinfo.st_size / CHAR_PER_LINE) == 0) 8086d36ef34Smrg return; 8091abf7346Smrg 8106d36ef34Smrg page = XtMalloc(fileinfo.st_size + 1); /* leave space for the NULL */ 8116d36ef34Smrg top_line = line_pointer = (char **) XtMalloc(nlines * sizeof(char *)); 8121abf7346Smrg 8131abf7346Smrg/* 8146d36ef34Smrg * Copy the file into memory. 8151abf7346Smrg */ 8161abf7346Smrg 8176d36ef34Smrg fseek(file, 0L, SEEK_SET); 8186d36ef34Smrg if (fread(page, sizeof(char), fileinfo.st_size, file) == 0) 8196d36ef34Smrg XtAppError(XtWidgetToApplicationContext(w), 8206d36ef34Smrg "SBLW LoadFile: Failure in fread."); 8211abf7346Smrg 8221abf7346Smrg/* put NULL at end of buffer. */ 8231abf7346Smrg 8246d36ef34Smrg *(page + fileinfo.st_size) = '\0'; 8251abf7346Smrg 8261abf7346Smrg/* 8276d36ef34Smrg * Go through the file setting a line pointer to the character after each 8281abf7346Smrg * new line. If we run out of line pointer space then realloc that space 8291abf7346Smrg * with space for more lines. 8301abf7346Smrg */ 8311abf7346Smrg 8326d36ef34Smrg *line_pointer++ = page; /* first line points to first char in buffer. */ 8336d36ef34Smrg while (*page != '\0') { 8346d36ef34Smrg 8356d36ef34Smrg if (*page == '\n') { 8366d36ef34Smrg *line_pointer++ = page + 1; 8376d36ef34Smrg 8386d36ef34Smrg if (line_pointer >= top_line + nlines) { 8396d36ef34Smrg top_line = (char **) XtRealloc((char *) top_line, (nlines + 8406d36ef34Smrg ADD_MORE_MEM) 8416d36ef34Smrg * sizeof(char *)); 8426d36ef34Smrg line_pointer = top_line + nlines; 8436d36ef34Smrg nlines += ADD_MORE_MEM; 8446d36ef34Smrg } 8456d36ef34Smrg } 8466d36ef34Smrg page++; 8471abf7346Smrg } 8486d36ef34Smrg 8491abf7346Smrg/* 8501abf7346Smrg * Realloc the line pointer space to take only the minimum amount of memory 8511abf7346Smrg */ 8521abf7346Smrg 8536d36ef34Smrg sblw->scroll.lines = nlines = line_pointer - top_line - 1; 8546d36ef34Smrg top_line = (char **) XtRealloc((char *) top_line, nlines * sizeof(char *)); 8551abf7346Smrg 8561abf7346Smrg/* 8571abf7346Smrg * Store the memory pointers 8581abf7346Smrg */ 8591abf7346Smrg 8606d36ef34Smrg sblw->scroll.top_line = top_line; 8616d36ef34Smrg sblw->scroll.line_pointer = 0; 8626d36ef34Smrg SetThumbHeight(w); 8636d36ef34Smrg SetThumb(w); 8641abf7346Smrg} 8651abf7346Smrg 8666d36ef34Smrg#define NLINES 66 /* This is the number of lines to wait until 8676d36ef34Smrg we boldify the line again, this allows 8686d36ef34Smrg me to bold the first line of each page. */ 8696d36ef34Smrg#define BACKSPACE 010 /* I doubt you would want to change this. */ 8701abf7346Smrg 8711abf7346Smrg#define NORMAL 0 8721abf7346Smrg#define BOLD 1 8731abf7346Smrg#define ITALIC 2 8741abf7346Smrg#define SYMBOL 3 8751abf7346Smrg#define WHICH(italic, bold) ((bold) ? BOLD : ((italic) ? ITALIC : NORMAL)) 8766d36ef34Smrg /* Choose BOLD over ITALICS. If neither */ 8776d36ef34Smrg /* is chosen, use NORMAL. */ 8781abf7346Smrg 8796d36ef34Smrgstatic int DumpText(Widget w, int x_loc, int y_loc, char *buf, int len, 8806d36ef34Smrg int format); 8811abf7346Smrgstatic Boolean Boldify(char *); 8821abf7346Smrg 8831abf7346Smrg/* Function Name: PrintText 8841abf7346Smrg * Description: This function actually prints the text. 8851abf7346Smrg * Arguments: w - the ScrollByLine widget. 8861abf7346Smrg * start_line - line to start printing, 8871abf7346Smrg * num_lines - the number of lines to print. 8881abf7346Smrg * location - the location to print the text. 8891abf7346Smrg * Returns: none. 8901abf7346Smrg */ 8911abf7346Smrg 8921abf7346Smrg/* ARGSUSED */ 8931abf7346Smrgstatic void 8941abf7346SmrgPrintText(Widget w, int start_line, int num_lines, int location) 8951abf7346Smrg{ 8966d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 8971abf7346Smrg 8986d36ef34Smrg register char *bufp, *c; /* Generic char pointers */ 8996d36ef34Smrg int current_line; /* the number of the current line */ 9006d36ef34Smrg char buf[BUFSIZ]; /* Misc. characters */ 9016d36ef34Smrg Boolean italicflag = FALSE; /* Print text in italics?? */ 9026d36ef34Smrg Boolean first = TRUE; /* First line of a manual page??? */ 9036d36ef34Smrg int x_loc, y_loc; /* x and y location of text. */ 9041abf7346Smrg 9051abf7346Smrg/* 9061abf7346Smrg * For table hack 9071abf7346Smrg * To get columns to line up reasonably in most cases, make the 9081abf7346Smrg * assumption that they were lined up using lots of spaces, where 9091abf7346Smrg * lots is greater than two. Use a space width of 70% of the 9101abf7346Smrg * widest character in the font. 9111abf7346Smrg */ 9126d36ef34Smrg int h_col, h_fix; 9136d36ef34Smrg char *h_c; 9141abf7346Smrg 9151abf7346Smrg/* 9161abf7346Smrg * Nothing loaded, take no action. 9171abf7346Smrg */ 9181abf7346Smrg 9196d36ef34Smrg if (sblw->scroll.top_line == NULL || num_lines == 0) 9206d36ef34Smrg return; 9211abf7346Smrg 9226d36ef34Smrg current_line = start_line; 9231abf7346Smrg 9241abf7346Smrg/* Set the first character to print at the first line. */ 9251abf7346Smrg 9266d36ef34Smrg c = *(sblw->scroll.top_line + start_line); 9271abf7346Smrg 9281abf7346Smrg/* 9291abf7346Smrg * Because XDrawString uses the bottom of the text as a position 9301abf7346Smrg * reference, add the height from the top of the font to the baseline 9311abf7346Smrg * to the ScollByLine position reference. 9321abf7346Smrg */ 9331abf7346Smrg 9346d36ef34Smrg y_loc = location + sblw->scroll.normal_font->max_bounds.ascent; 9351abf7346Smrg 9361abf7346Smrg/* 9371abf7346Smrg * Ok, here's the more than mildly heuristic man page formatter. 9381abf7346Smrg * We put chars into buf until either a font change or newline 9391abf7346Smrg * occurs (at which time we flush it to the screen.) 9401abf7346Smrg */ 9411abf7346Smrg 9426d36ef34Smrg bufp = buf; 9436d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 9446d36ef34Smrg h_col = 0; 9451abf7346Smrg 9461abf7346Smrg/* 9471abf7346Smrg * A fix: 9481abf7346Smrg * Assume that we are always starting to print on or before the 9491abf7346Smrg * first line of a page, and then prove it if we aren't. 9501abf7346Smrg */ 9516d36ef34Smrg for (h_fix = 1; h_fix <= (start_line % NLINES); h_fix++) 9526d36ef34Smrg if (**(sblw->scroll.top_line + start_line - h_fix) != '\n') { 9536d36ef34Smrg first = FALSE; 9546d36ef34Smrg break; 9556d36ef34Smrg } 9566d36ef34Smrg 9576d36ef34Smrg while (TRUE) { 9586d36ef34Smrg if (current_line % NLINES == 0) 9596d36ef34Smrg first = TRUE; 9606d36ef34Smrg 9616d36ef34Smrg/* 9621abf7346Smrg * Lets make sure that we do not run out of space in our buffer, making full 9631abf7346Smrg * use of it is not critical since no window will be wide enough to display 9641abf7346Smrg * nearly BUFSIZ characters. 9651abf7346Smrg */ 9661abf7346Smrg 9676d36ef34Smrg if ((bufp - buf) > (BUFSIZ - 10)) 9686d36ef34Smrg /* Toss everything until we find a <CR> or the end of the buffer. */ 9696d36ef34Smrg while ((*c != '\n') && (*c != '\0')) 9706d36ef34Smrg c++; 9716d36ef34Smrg 9726d36ef34Smrg switch (*c) { 9731abf7346Smrg 9746d36ef34Smrg case '\0': /* If we reach the end of the file then return */ 9756d36ef34Smrg DumpText(w, x_loc, y_loc, buf, bufp - buf, 9766d36ef34Smrg WHICH(italicflag, first)); 9776d36ef34Smrg return; 9781abf7346Smrg 9796d36ef34Smrg case '\n': 9806d36ef34Smrg if (bufp != buf) { 9816d36ef34Smrg Boolean bold; 9821abf7346Smrg 9836d36ef34Smrg *bufp = '\0'; /* for Boldify. */ 9846d36ef34Smrg bold = ((first) || ((x_loc == (sblw->scroll.offset + 9856d36ef34Smrg sblw->scroll.indent)) && 9866d36ef34Smrg Boldify(buf))); 9871abf7346Smrg 9886d36ef34Smrg (void) DumpText(w, x_loc, y_loc, buf, bufp - buf, 9896d36ef34Smrg WHICH(italicflag, bold)); 9901abf7346Smrg 9916d36ef34Smrg if (bold) 9926d36ef34Smrg first = FALSE; 9936d36ef34Smrg } 9941abf7346Smrg 9956d36ef34Smrg/* 9961abf7346Smrg * If we have painted the required number of lines then we should now return. 9971abf7346Smrg */ 9986d36ef34Smrg if (++current_line == start_line + num_lines) 9996d36ef34Smrg return; 10001abf7346Smrg 10016d36ef34Smrg bufp = buf; 10026d36ef34Smrg italicflag = FALSE; 10036d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10046d36ef34Smrg h_col = 0; 10056d36ef34Smrg y_loc += sblw->scroll.font_height; 10066d36ef34Smrg break; 10071abf7346Smrg 10081abf7346Smrg/* 10091abf7346Smrg * This tab handling code is not very clever it moves the cursor over 10106d36ef34Smrg * to the next boundary of eight (8) spaces, as calculated in width just 10111abf7346Smrg * before the printing loop started. 10121abf7346Smrg */ 10131abf7346Smrg 10146d36ef34Smrg case '\t': /* TAB */ 10156d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10166d36ef34Smrg WHICH(italicflag, first)); 10176d36ef34Smrg h_col += bufp - buf; 10186d36ef34Smrg bufp = buf; 10196d36ef34Smrg italicflag = FALSE; 10206d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10216d36ef34Smrg h_col = h_col + 8 - (h_col % 8); 10226d36ef34Smrg x_loc += sblw->scroll.h_width * h_col; 10236d36ef34Smrg break; 10246d36ef34Smrg 10256d36ef34Smrg case ' ': 10266d36ef34Smrg h_c = c + 1; 10276d36ef34Smrg while (*h_c == ' ') 10286d36ef34Smrg h_c++; 10296d36ef34Smrg 10306d36ef34Smrg if (h_c - c < 4) { 10316d36ef34Smrg *bufp++ = *c; 10326d36ef34Smrg break; 10336d36ef34Smrg } 10346d36ef34Smrg 10356d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10366d36ef34Smrg WHICH(italicflag, first)); 10376d36ef34Smrg h_col += bufp - buf; 10386d36ef34Smrg bufp = buf; 10396d36ef34Smrg italicflag = FALSE; 10406d36ef34Smrg 10416d36ef34Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10426d36ef34Smrg h_col += (h_c - c); 10436d36ef34Smrg x_loc += sblw->scroll.h_width * h_col; 10446d36ef34Smrg c = h_c - 1; 10456d36ef34Smrg break; 10466d36ef34Smrg 10476d36ef34Smrg case '\033': /* ignore esc sequences for now */ 10486d36ef34Smrg c++; /* should always be esc-x */ 10496d36ef34Smrg break; 10506d36ef34Smrg 10516d36ef34Smrg/* 10526d36ef34Smrg * Overstrike code supplied by: cs.utexas.edu!ut-emx!clyde@rutgers.edu 10531abf7346Smrg * Since my manual pages do not have overstrike I couldn't test this. 10541abf7346Smrg */ 10551abf7346Smrg 10566d36ef34Smrg case BACKSPACE: /* Backspacing for nroff bolding */ 10576d36ef34Smrg if (c[-1] == c[1] && c[1] != BACKSPACE) { /* overstriking one char */ 10586d36ef34Smrg if (bufp > buf) { 10596d36ef34Smrg bufp--; /* Zap 1st instance of char to bolden */ 10606d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10616d36ef34Smrg WHICH(italicflag, FALSE)); 10626d36ef34Smrg h_col += bufp - buf; 10636d36ef34Smrg } 10646d36ef34Smrg bufp = buf; 10656d36ef34Smrg *bufp++ = c[1]; 10666d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, BOLD); 10676d36ef34Smrg h_col += bufp - buf; 10686d36ef34Smrg bufp = buf; 10696d36ef34Smrg first = FALSE; 10706d36ef34Smrg 10716d36ef34Smrg /* 10726d36ef34Smrg * Nroff bolding looks like: 10736d36ef34Smrg * C\bC\bC\bCN... 10746d36ef34Smrg * c points to ----^ ^ 10756d36ef34Smrg * it needs to point to --^ 10766d36ef34Smrg */ 10776d36ef34Smrg while (*c == BACKSPACE && c[-1] == c[1]) 10786d36ef34Smrg c += 2; 10796d36ef34Smrg c--; /* Back up to previous char */ 10806d36ef34Smrg } 10816d36ef34Smrg else { 10826d36ef34Smrg if ((c[-1] == 'o' && c[1] == '+') /* Nroff bullet */ 10836d36ef34Smrg ||(c[-1] == '+' && c[1] == 'o')) { /* Nroff bullet */ 10846d36ef34Smrg /* If we run into a bullet, print out */ 10856d36ef34Smrg /* everything that's accumulated to this */ 10866d36ef34Smrg /* point, then the bullet, then resume. */ 10876d36ef34Smrg if (bufp > buf) { 10886d36ef34Smrg bufp--; 10896d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10906d36ef34Smrg WHICH(italicflag, FALSE)); 10916d36ef34Smrg h_col += bufp - buf; 10926d36ef34Smrg } 10936d36ef34Smrg bufp = buf; 10946d36ef34Smrg *bufp = (char) 183; 10956d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, 1, SYMBOL); 10966d36ef34Smrg h_col++; 10976d36ef34Smrg c++; 10986d36ef34Smrg } 10996d36ef34Smrg else { /* 'real' backspace - back up output ptr */ 11006d36ef34Smrg if (bufp > buf) 11016d36ef34Smrg bufp--; 11026d36ef34Smrg } 11036d36ef34Smrg } 11046d36ef34Smrg break; 11051abf7346Smrg 11061abf7346Smrg/* End of contributed overstrike code. */ 11071abf7346Smrg 11086d36ef34Smrg case '_': /* look for underlining [italicize] */ 11096d36ef34Smrg if (*(c + 1) == BACKSPACE) { 11106d36ef34Smrg if (!italicflag) { /* font change? */ 11116d36ef34Smrg if (bufp != buf) { 11126d36ef34Smrg x_loc = 11136d36ef34Smrg DumpText(w, x_loc, y_loc, buf, bufp - buf, NORMAL); 11146d36ef34Smrg h_col += bufp - buf; 11156d36ef34Smrg bufp = buf; 11166d36ef34Smrg } 11176d36ef34Smrg italicflag = TRUE; 11186d36ef34Smrg } 11196d36ef34Smrg c += 2; 11206d36ef34Smrg *bufp++ = *c; 11216d36ef34Smrg break; 11226d36ef34Smrg } 1123ae5a67adSmrg /* else fall through - to default, because this was a real underscore. */ 11246d36ef34Smrg 11256d36ef34Smrg default: 11266d36ef34Smrg if (italicflag) { /* font change? */ 11276d36ef34Smrg if (bufp != buf) { 11286d36ef34Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 11296d36ef34Smrg WHICH(italicflag, FALSE)); 11306d36ef34Smrg h_col += bufp - buf; 11316d36ef34Smrg bufp = buf; 11326d36ef34Smrg } 11336d36ef34Smrg italicflag = FALSE; 11346d36ef34Smrg } 11356d36ef34Smrg *bufp++ = *c; 11366d36ef34Smrg break; 11376d36ef34Smrg } 11386d36ef34Smrg c++; 11391abf7346Smrg } 11401abf7346Smrg} 11411abf7346Smrg 11421abf7346Smrg/* Function Name: DumpText 11431abf7346Smrg * Description: Dumps text to the screen. 11441abf7346Smrg * Arguments: w - the widget. 11451abf7346Smrg * x_loc - to dump text at. 11461abf7346Smrg * y_loc - the y_location to draw_text. 11471abf7346Smrg * buf - buffer to dump. 11481abf7346Smrg * italic, bold, boolean that tells us which gc to use. 11491abf7346Smrg * Returns: x_location of the end of the text. 11501abf7346Smrg */ 11511abf7346Smrg 11521abf7346Smrgstatic int 11536d36ef34SmrgDumpText(Widget w, int x_loc, int y_loc, char *buf, int len, int format) 11541abf7346Smrg{ 11556d36ef34Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 11566d36ef34Smrg GC gc; 11576d36ef34Smrg XFontStruct *font; 11586d36ef34Smrg 11596d36ef34Smrg switch (format) { 11606d36ef34Smrg 11616d36ef34Smrg case ITALIC: 11626d36ef34Smrg gc = sblw->scroll.italic_gc; 11636d36ef34Smrg font = sblw->scroll.italic_font; 11646d36ef34Smrg break; 11656d36ef34Smrg 11666d36ef34Smrg case BOLD: 11676d36ef34Smrg gc = sblw->scroll.bold_gc; 11686d36ef34Smrg font = sblw->scroll.bold_font; 11696d36ef34Smrg break; 11706d36ef34Smrg 11716d36ef34Smrg case SYMBOL: 11726d36ef34Smrg gc = sblw->scroll.symbol_gc; 11736d36ef34Smrg font = sblw->scroll.symbol_font; 11746d36ef34Smrg break; 11756d36ef34Smrg 11766d36ef34Smrg default: 11776d36ef34Smrg gc = sblw->scroll.normal_gc; 11786d36ef34Smrg font = sblw->scroll.normal_font; 11796d36ef34Smrg break; 11801abf7346Smrg } 11811abf7346Smrg 11826d36ef34Smrg XDrawString(XtDisplay(w), XtWindow(w), gc, x_loc, y_loc, buf, len); 11836d36ef34Smrg return (x_loc + XTextWidth(font, buf, len)); 11841abf7346Smrg} 11851abf7346Smrg 11861abf7346Smrg/* Function Name: Boldify 11871abf7346Smrg * Description: look for keyword. 11881abf7346Smrg * Arguments: sp - string pointer. 11891abf7346Smrg * Returns: 1 if keyword else 0. 11901abf7346Smrg */ 11911abf7346Smrg 11921abf7346Smrgstatic Boolean 11931abf7346SmrgBoldify(register char *sp) 11941abf7346Smrg{ 11956d36ef34Smrg register char *sp_pointer; 11966d36ef34Smrg int length, count; 11971abf7346Smrg 11986d36ef34Smrg/* 11991abf7346Smrg * If there are not lower case letters in the line the assume it is a 12001abf7346Smrg * keyword and boldify it in PrintManpage. 12011abf7346Smrg */ 12021abf7346Smrg 12036d36ef34Smrg length = strlen(sp); 12046d36ef34Smrg for (sp_pointer = sp, count = 0; count < length; sp_pointer++, count++) 12056d36ef34Smrg if (!isupper(*sp_pointer) && !isspace(*sp_pointer)) 12066d36ef34Smrg return (0); 12076d36ef34Smrg return (1); 12081abf7346Smrg} 12091abf7346Smrg 12101abf7346Smrg#undef superclass 12111abf7346Smrg#undef SuperClass 1212