ScrollByL.c revision 1abf7346
11abf7346Smrg/* $XConsortium: ScrollByL.c,v 1.30 94/04/17 20:43:46 rws Exp $ */ 21abf7346Smrg/* 31abf7346Smrg 41abf7346SmrgCopyright (c) 1987, 1988 X Consortium 51abf7346Smrg 61abf7346SmrgPermission is hereby granted, free of charge, to any person obtaining 71abf7346Smrga copy of this software and associated documentation files (the 81abf7346Smrg"Software"), to deal in the Software without restriction, including 91abf7346Smrgwithout limitation the rights to use, copy, modify, merge, publish, 101abf7346Smrgdistribute, sublicense, and/or sell copies of the Software, and to 111abf7346Smrgpermit persons to whom the Software is furnished to do so, subject to 121abf7346Smrgthe following conditions: 131abf7346Smrg 141abf7346SmrgThe above copyright notice and this permission notice shall be included 151abf7346Smrgin all copies or substantial portions of the Software. 161abf7346Smrg 171abf7346SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 181abf7346SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 191abf7346SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 201abf7346SmrgIN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR 211abf7346SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 221abf7346SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 231abf7346SmrgOTHER DEALINGS IN THE SOFTWARE. 241abf7346Smrg 251abf7346SmrgExcept as contained in this notice, the name of the X Consortium shall 261abf7346Smrgnot be used in advertising or otherwise to promote the sale, use or 271abf7346Smrgother dealings in this Software without prior written authorization 281abf7346Smrgfrom the X Consortium. 291abf7346Smrg 301abf7346Smrg*/ 311abf7346Smrg/* $XFree86: xc/programs/xman/ScrollByL.c,v 1.6tsi Exp $ */ 321abf7346Smrg 331abf7346Smrg#if !defined(lint) && !defined(SABER) && 0 341abf7346Smrg static char rcs_version[] = "$Athena: ScrollByL.c,v 4.5 88/12/19 13:46:04 kit Exp $"; 351abf7346Smrg#endif 361abf7346Smrg 371abf7346Smrg#include <stdio.h> 381abf7346Smrg#include <ctype.h> 391abf7346Smrg#include <X11/Xos.h> 401abf7346Smrg#include <stdlib.h> 411abf7346Smrg 421abf7346Smrg#include <X11/IntrinsicP.h> 431abf7346Smrg#include <sys/stat.h> /* depends on IntrinsicP.h */ 441abf7346Smrg#include <X11/StringDefs.h> 451abf7346Smrg 461abf7346Smrg#include <X11/Xaw/Scrollbar.h> 471abf7346Smrg#include <X11/Xmu/Misc.h> 481abf7346Smrg 491abf7346Smrg#include "ScrollByLP.h" 501abf7346Smrg 511abf7346Smrg/* Default Translation Table */ 521abf7346Smrg 531abf7346Smrgstatic char defaultTranslations[] = 541abf7346Smrg "<Key>f: Page(Forward) \n\ 551abf7346Smrg <Key>b: Page(Back) \n\ 561abf7346Smrg <Key>1: Page(Line, 1) \n\ 571abf7346Smrg <Key>2: Page(Line, 2) \n\ 581abf7346Smrg <Key>3: Page(Line, 3) \n\ 591abf7346Smrg <Key>4: Page(Line, 4) \n\ 601abf7346Smrg <Key>\\ : Page(Forward)"; 611abf7346Smrg 621abf7346Smrg 631abf7346Smrg/**************************************************************** 641abf7346Smrg * 651abf7346Smrg * ScrollByLine Resources 661abf7346Smrg * 671abf7346Smrg ****************************************************************/ 681abf7346Smrg 691abf7346Smrg#define Offset(field) XtOffset(ScrollByLineWidget, scroll.field) 701abf7346Smrg#define CoreOffset(field) XtOffset(ScrollByLineWidget, core.field) 711abf7346Smrg 721abf7346Smrgstatic XtResource resources[] = { 731abf7346Smrg {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), 741abf7346Smrg CoreOffset(width), XtRImmediate, (caddr_t) 500}, 751abf7346Smrg {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), 761abf7346Smrg CoreOffset(height), XtRImmediate, (caddr_t) 700}, 771abf7346Smrg 781abf7346Smrg {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), 791abf7346Smrg Offset(foreground), XtRString, "XtDefaultForeground"}, 801abf7346Smrg {XtNforceVert, XtCBoolean, XtRBoolean, sizeof(Boolean), 811abf7346Smrg Offset(force_vert), XtRImmediate, (caddr_t) FALSE}, 821abf7346Smrg {XtNindent, XtCIndent, XtRDimension, sizeof(Dimension), 831abf7346Smrg Offset(indent), XtRImmediate, (caddr_t) 15}, 841abf7346Smrg {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean), 851abf7346Smrg Offset(use_right), XtRImmediate, (caddr_t) FALSE}, 861abf7346Smrg {XtNmanualFontNormal, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 871abf7346Smrg Offset(normal_font), XtRString, MANPAGE_NORMAL}, 881abf7346Smrg {XtNmanualFontBold, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 891abf7346Smrg Offset(bold_font), XtRString, MANPAGE_BOLD}, 901abf7346Smrg {XtNmanualFontItalic, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 911abf7346Smrg Offset(italic_font), XtRString, MANPAGE_ITALIC}, 921abf7346Smrg {XtNmanualFontSymbol, XtCFont, XtRFontStruct, sizeof(XFontStruct *), 931abf7346Smrg Offset(symbol_font), XtRString, MANPAGE_SYMBOL}, 941abf7346Smrg {XtNfile, XtCFile, XtRFile, sizeof(FILE *), 951abf7346Smrg Offset(file), XtRImmediate, (caddr_t) NULL}, 961abf7346Smrg {XtNNumTotalLines, XtCNumTotalLines, XtRInt, sizeof(int), 971abf7346Smrg Offset(lines), XtRImmediate, (caddr_t) 0}, 981abf7346Smrg {XtNNumVisibleLines, XtCNumVisibleLines, XtRInt, sizeof(int), 991abf7346Smrg Offset(num_visible_lines), XtRImmediate, (caddr_t) 0}, 1001abf7346Smrg}; 1011abf7346Smrg 1021abf7346Smrg#undef Offset 1031abf7346Smrg#undef CoreOffset 1041abf7346Smrg 1051abf7346Smrg/**************************************************************** 1061abf7346Smrg * 1071abf7346Smrg * Full class record constant 1081abf7346Smrg * 1091abf7346Smrg ****************************************************************/ 1101abf7346Smrg 1111abf7346Smrgstatic void CreateScrollbar(Widget w); 1121abf7346Smrgstatic Boolean ScrollVerticalText(Widget w, int new_line, Boolean force_redisp); 1131abf7346Smrgstatic void Layout(Widget w); 1141abf7346Smrgstatic void LoadFile(Widget w); 1151abf7346Smrgstatic void MoveAndClearText(Widget w, int old_y, int height, int new_y); 1161abf7346Smrgstatic void PaintText(Widget w, int y_loc, int height); 1171abf7346Smrgstatic void PrintText(Widget w, int start_line, int num_lines, int location); 1181abf7346Smrgstatic void SetThumbHeight(Widget w); 1191abf7346Smrgstatic void VerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr); 1201abf7346Smrgstatic void VerticalScroll(Widget w, XtPointer client_data, XtPointer call_data); 1211abf7346Smrg 1221abf7346Smrg/* semi - public functions. */ 1231abf7346Smrg 1241abf7346Smrgstatic void Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes); 1251abf7346Smrgstatic void Initialize(Widget req, Widget new, ArgList args, Cardinal *num_args); 1261abf7346Smrgstatic void Destroy(Widget w); 1271abf7346Smrgstatic void Redisplay(Widget w, XEvent *event, Region region); 1281abf7346Smrgstatic void Page(Widget w, XEvent * event, String * params, Cardinal *num_params); 1291abf7346Smrgstatic Boolean SetValuesHook(Widget w, ArgList args, Cardinal *num_args); 1301abf7346Smrg 1311abf7346Smrgstatic XtActionsRec actions[] = { 1321abf7346Smrg { "Page", Page}, 1331abf7346Smrg}; 1341abf7346Smrg 1351abf7346Smrg#define superclass (&simpleClassRec) 1361abf7346Smrg#define SuperClass simpleWidgetClass 1371abf7346Smrg 1381abf7346SmrgScrollByLineClassRec scrollByLineClassRec = { 1391abf7346Smrg { 1401abf7346Smrg/* core_class fields */ 1411abf7346Smrg /* superclass */ (WidgetClass) superclass, 1421abf7346Smrg /* class_name */ "ScrollByLine", 1431abf7346Smrg /* widget_size */ sizeof(ScrollByLineRec), 1441abf7346Smrg /* class_initialize */ NULL, 1451abf7346Smrg /* class_part_init */ NULL, 1461abf7346Smrg /* class_inited */ FALSE, 1471abf7346Smrg /* initialize */ Initialize, 1481abf7346Smrg /* initialize_hook */ NULL, 1491abf7346Smrg /* realize */ Realize, 1501abf7346Smrg /* actions */ actions, 1511abf7346Smrg /* num_actions */ XtNumber(actions), 1521abf7346Smrg /* resources */ resources, 1531abf7346Smrg /* num_resources */ XtNumber(resources), 1541abf7346Smrg /* xrm_class */ NULLQUARK, 1551abf7346Smrg /* compress_motion */ TRUE, 1561abf7346Smrg /* compress_exposure */ FALSE, 1571abf7346Smrg /* compress_enterleave*/ TRUE, 1581abf7346Smrg /* visible_interest */ FALSE, 1591abf7346Smrg /* destroy */ Destroy, 1601abf7346Smrg /* resize */ Layout, 1611abf7346Smrg /* expose */ Redisplay, 1621abf7346Smrg /* set_values */ NULL, 1631abf7346Smrg /* set_values_hook */ SetValuesHook, 1641abf7346Smrg /* set_values_almost */ XtInheritSetValuesAlmost, 1651abf7346Smrg /* get_values_hook */ NULL, 1661abf7346Smrg /* accept_focus */ NULL, 1671abf7346Smrg /* version */ XtVersion, 1681abf7346Smrg /* callback_private */ NULL, 1691abf7346Smrg /* tm_table */ defaultTranslations, 1701abf7346Smrg /* query_geometry */ XtInheritQueryGeometry, 1711abf7346Smrg /* display_accelerator*/ XtInheritDisplayAccelerator, 1721abf7346Smrg /* extension */ NULL, 1731abf7346Smrg }, 1741abf7346Smrg { /* simple fields */ 1751abf7346Smrg /* change_sensitive */ XtInheritChangeSensitive 1761abf7346Smrg } 1771abf7346Smrg}; 1781abf7346Smrg 1791abf7346SmrgWidgetClass scrollByLineWidgetClass = 1801abf7346Smrg (WidgetClass) &scrollByLineClassRec; 1811abf7346Smrg 1821abf7346Smrg 1831abf7346Smrg/**************************************************************** 1841abf7346Smrg * 1851abf7346Smrg * Private Routines 1861abf7346Smrg * 1871abf7346Smrg ****************************************************************/ 1881abf7346Smrg 1891abf7346Smrg/* Function Name: Layout 1901abf7346Smrg * Description: This function lays out the scroll widget. 1911abf7346Smrg * Arguments: w - the scroll widget. 1921abf7346Smrg * key - a boolean: if true then resize the widget to the child 1931abf7346Smrg * if false the resize children to fit widget. 1941abf7346Smrg * Returns: TRUE if successful. 1951abf7346Smrg */ 1961abf7346Smrg 1971abf7346Smrgstatic void 1981abf7346SmrgLayout(Widget w) 1991abf7346Smrg{ 2001abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 2011abf7346Smrg Dimension width, height; 2021abf7346Smrg Widget bar; 2031abf7346Smrg Position bar_bw; 2041abf7346Smrg 2051abf7346Smrg CreateScrollbar(w); 2061abf7346Smrg 2071abf7346Smrg/* 2081abf7346Smrg * For now always show the bar. 2091abf7346Smrg */ 2101abf7346Smrg 2111abf7346Smrg bar = sblw->scroll.bar; 2121abf7346Smrg height = sblw->core.height; 2131abf7346Smrg width = sblw->core.width; 2141abf7346Smrg bar_bw = bar->core.border_width; 2151abf7346Smrg 2161abf7346Smrg /* Move child and v_bar to correct location. */ 2171abf7346Smrg 2181abf7346Smrg if (sblw->scroll.use_right) { 2191abf7346Smrg XtMoveWidget(bar, width - (bar->core.width + bar_bw), - bar_bw); 2201abf7346Smrg sblw->scroll.offset = 0; 2211abf7346Smrg } 2221abf7346Smrg else { 2231abf7346Smrg XtMoveWidget(bar, - bar_bw, - bar_bw); 2241abf7346Smrg sblw->scroll.offset = bar->core.width + bar_bw; 2251abf7346Smrg } 2261abf7346Smrg 2271abf7346Smrg /* resize the scrollbar to be the correct height or width. */ 2281abf7346Smrg 2291abf7346Smrg XtResizeWidget(bar, bar->core.width, height, bar->core.border_width); 2301abf7346Smrg 2311abf7346Smrg SetThumbHeight(w); 2321abf7346Smrg 2331abf7346Smrg sblw->scroll.num_visible_lines = height / sblw->scroll.font_height + 1; 2341abf7346Smrg} 2351abf7346Smrg 2361abf7346Smrg/* ARGSUSED */ 2371abf7346Smrgstatic void 2381abf7346SmrgGExpose(Widget w, XtPointer junk, XEvent *event, Boolean *cont) 2391abf7346Smrg{ 2401abf7346Smrg 2411abf7346Smrg/* 2421abf7346Smrg * Graphics exposure events are not currently sent to exposure proc. 2431abf7346Smrg */ 2441abf7346Smrg 2451abf7346Smrg if (event->type == GraphicsExpose) 2461abf7346Smrg Redisplay(w, event, NULL); 2471abf7346Smrg 2481abf7346Smrg} /* ChildExpose */ 2491abf7346Smrg 2501abf7346Smrg/* 2511abf7346Smrg * Repaint the widget's child Window Widget. 2521abf7346Smrg */ 2531abf7346Smrg 2541abf7346Smrg/* ARGSUSED */ 2551abf7346Smrgstatic void 2561abf7346SmrgRedisplay(Widget w, XEvent *event, Region region) 2571abf7346Smrg{ 2581abf7346Smrg int top, height; /* the locations of the top and height 2591abf7346Smrg of the region that needs to be repainted. */ 2601abf7346Smrg 2611abf7346Smrg/* 2621abf7346Smrg * This routine tells the client which sections of the window to 2631abf7346Smrg * repaint in his callback function which does the actual repainting. 2641abf7346Smrg */ 2651abf7346Smrg 2661abf7346Smrg if (event->type == Expose) { 2671abf7346Smrg top = event->xexpose.y; 2681abf7346Smrg height = event->xexpose.height; 2691abf7346Smrg } 2701abf7346Smrg else { 2711abf7346Smrg top = event->xgraphicsexpose.y; 2721abf7346Smrg height = event->xgraphicsexpose.height; 2731abf7346Smrg } 2741abf7346Smrg 2751abf7346Smrg PaintText(w, top, height); 2761abf7346Smrg} /* redisplay (expose) */ 2771abf7346Smrg 2781abf7346Smrg/* Function Name: PaintText 2791abf7346Smrg * Description: paints the text at the give location for a given height. 2801abf7346Smrg * Arguments: w - the sbl widget. 2811abf7346Smrg * y_loc, height - location and size of area to paint. 2821abf7346Smrg * Returns: none 2831abf7346Smrg */ 2841abf7346Smrg 2851abf7346Smrgstatic void 2861abf7346SmrgPaintText(Widget w, int y_loc, int height) 2871abf7346Smrg{ 2881abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 2891abf7346Smrg int start_line, location; 2901abf7346Smrg 2911abf7346Smrg start_line = y_loc / sblw->scroll.font_height + sblw->scroll.line_pointer; 2921abf7346Smrg 2931abf7346Smrg if (start_line >= sblw->scroll.lines) 2941abf7346Smrg return; 2951abf7346Smrg 2961abf7346Smrg/* 2971abf7346Smrg * Only integer arithmetic makes this possible. 2981abf7346Smrg */ 2991abf7346Smrg 3001abf7346Smrg location = y_loc / sblw->scroll.font_height * sblw->scroll.font_height; 3011abf7346Smrg 3021abf7346Smrg PrintText(w, start_line, sblw->scroll.num_visible_lines, location); 3031abf7346Smrg} 3041abf7346Smrg 3051abf7346Smrg/* Function Name: Page 3061abf7346Smrg * Description: This function pages the widget, by the amount it recieves 3071abf7346Smrg * from the translation Manager. 3081abf7346Smrg * Arguments: w - the ScrollByLineWidget. 3091abf7346Smrg * event - the event that caused this return. 3101abf7346Smrg * params - the parameters passed to it. 3111abf7346Smrg * num_params - the number of parameters. 3121abf7346Smrg * Returns: none. 3131abf7346Smrg */ 3141abf7346Smrg 3151abf7346Smrg/* ARGSUSED */ 3161abf7346Smrgstatic void 3171abf7346SmrgPage(Widget w, XEvent * event, String * params, Cardinal *num_params) 3181abf7346Smrg{ 3191abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3201abf7346Smrg Widget bar = sblw->scroll.bar; 3211abf7346Smrg 3221abf7346Smrg if (*num_params < 1) 3231abf7346Smrg return; 3241abf7346Smrg/* 3251abf7346Smrg * If no scroll bar is visible then do not page, as the entire window is shown, 3261abf7346Smrg * of scrolling has been turned off. 3271abf7346Smrg */ 3281abf7346Smrg 3291abf7346Smrg if (bar == (Widget) NULL) 3301abf7346Smrg return; 3311abf7346Smrg 3321abf7346Smrg switch ( params[0][0] ) { 3331abf7346Smrg case 'f': 3341abf7346Smrg case 'F': 3351abf7346Smrg /* move one page forward */ 3361abf7346Smrg VerticalScroll(bar, NULL, (XtPointer)((long) bar->core.height)); 3371abf7346Smrg break; 3381abf7346Smrg case 'b': 3391abf7346Smrg case 'B': 3401abf7346Smrg /* move one page backward */ 3411abf7346Smrg VerticalScroll(bar, NULL, (XtPointer)(- (long) bar->core.height)); 3421abf7346Smrg break; 3431abf7346Smrg case 'L': 3441abf7346Smrg case 'l': 3451abf7346Smrg /* move one line forward */ 3461abf7346Smrg VerticalScroll(bar, NULL, 3471abf7346Smrg (XtPointer)((long) atoi(params[1]) * sblw->scroll.font_height)); 3481abf7346Smrg break; 3491abf7346Smrg default: 3501abf7346Smrg return; 3511abf7346Smrg } 3521abf7346Smrg} 3531abf7346Smrg 3541abf7346Smrg/* Function Name: CreateScrollbar 3551abf7346Smrg * Description: createst the scrollbar for us. 3561abf7346Smrg * Arguments: w - sblw widget. 3571abf7346Smrg * Returns: none. 3581abf7346Smrg */ 3591abf7346Smrg 3601abf7346Smrgstatic void 3611abf7346SmrgCreateScrollbar(Widget w) 3621abf7346Smrg{ 3631abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3641abf7346Smrg Arg args[5]; 3651abf7346Smrg Cardinal num_args = 0; 3661abf7346Smrg 3671abf7346Smrg if (sblw->scroll.bar != NULL) 3681abf7346Smrg return; 3691abf7346Smrg 3701abf7346Smrg XtSetArg(args[num_args], XtNorientation, XtorientVertical); num_args++; 3711abf7346Smrg 3721abf7346Smrg sblw->scroll.bar = XtCreateWidget("scrollbar", scrollbarWidgetClass, w, 3731abf7346Smrg args, num_args); 3741abf7346Smrg XtAddCallback(sblw->scroll.bar, XtNscrollProc, VerticalScroll, NULL); 3751abf7346Smrg XtAddCallback(sblw->scroll.bar, XtNjumpProc, VerticalJump, NULL); 3761abf7346Smrg} 3771abf7346Smrg 3781abf7346Smrg/* Function Name: ScrollVerticalText 3791abf7346Smrg * Description: This accomplished the actual movement of the text. 3801abf7346Smrg * Arguments: w - the ScrollByLine Widget. 3811abf7346Smrg * new_line - the new location for the line pointer 3821abf7346Smrg * force_redisplay - should we force this window to get 3831abf7346Smrg * redisplayed? 3841abf7346Smrg * Returns: True if the thumb needs to be moved. 3851abf7346Smrg */ 3861abf7346Smrg 3871abf7346Smrgstatic Boolean 3881abf7346SmrgScrollVerticalText( 3891abf7346SmrgWidget w, 3901abf7346Smrgint new_line, 3911abf7346SmrgBoolean force_redisp) 3921abf7346Smrg{ 3931abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 3941abf7346Smrg int num_lines = sblw->scroll.num_visible_lines; 3951abf7346Smrg int max_lines, old_line; 3961abf7346Smrg Boolean move_thumb = FALSE; 3971abf7346Smrg 3981abf7346Smrg/* 3991abf7346Smrg * Do not let the window extend out of bounds. 4001abf7346Smrg */ 4011abf7346Smrg 4021abf7346Smrg if ( new_line < 0) { 4031abf7346Smrg new_line = 0; 4041abf7346Smrg move_thumb = TRUE; 4051abf7346Smrg } 4061abf7346Smrg else { 4071abf7346Smrg max_lines = sblw->scroll.lines - (int)w->core.height / sblw->scroll.font_height; 4081abf7346Smrg AssignMax(max_lines, 0); 4091abf7346Smrg 4101abf7346Smrg if ( new_line > max_lines ) { 4111abf7346Smrg new_line = max_lines; 4121abf7346Smrg move_thumb = TRUE; 4131abf7346Smrg } 4141abf7346Smrg } 4151abf7346Smrg 4161abf7346Smrg/* 4171abf7346Smrg * If forced to redisplay then do a full redisplay and return. 4181abf7346Smrg */ 4191abf7346Smrg 4201abf7346Smrg old_line = sblw->scroll.line_pointer; 4211abf7346Smrg sblw->scroll.line_pointer = new_line; /* Set current top of page. */ 4221abf7346Smrg 4231abf7346Smrg if (force_redisp) 4241abf7346Smrg MoveAndClearText(w, 0, /* cause a full redisplay */ 0, 0); 4251abf7346Smrg 4261abf7346Smrg if (new_line == old_line) 4271abf7346Smrg return(move_thumb); 4281abf7346Smrg 4291abf7346Smrg/* 4301abf7346Smrg * Scroll forward. 4311abf7346Smrg */ 4321abf7346Smrg 4331abf7346Smrg else if (new_line < old_line) { 4341abf7346Smrg int lines_to_scroll = old_line - new_line; 4351abf7346Smrg MoveAndClearText(w, 0, num_lines - lines_to_scroll, lines_to_scroll); 4361abf7346Smrg } 4371abf7346Smrg 4381abf7346Smrg/* 4391abf7346Smrg * Scroll back. 4401abf7346Smrg */ 4411abf7346Smrg 4421abf7346Smrg else { 4431abf7346Smrg int lines_to_scroll = new_line - old_line; 4441abf7346Smrg MoveAndClearText(w, lines_to_scroll, num_lines - lines_to_scroll, 0); 4451abf7346Smrg } 4461abf7346Smrg 4471abf7346Smrg return(move_thumb); 4481abf7346Smrg} 4491abf7346Smrg 4501abf7346Smrg/* Function Name: MoveAndClearText 4511abf7346Smrg * Description: Blits as much text as it can and clear the 4521abf7346Smrg * remaining area with generate exposures TRUE. 4531abf7346Smrg * Arguments: w - the sbl widget. 4541abf7346Smrg * old_y - the old y position. 4551abf7346Smrg * height - height of area to move. 4561abf7346Smrg * new_y - new y position. 4571abf7346Smrg * Returns: none 4581abf7346Smrg */ 4591abf7346Smrg 4601abf7346Smrgstatic void 4611abf7346SmrgMoveAndClearText(Widget w, int old_y, int height, int new_y) 4621abf7346Smrg{ 4631abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 4641abf7346Smrg int from_left = sblw->scroll.indent + sblw->scroll.offset - 1; 4651abf7346Smrg int y_clear; 4661abf7346Smrg 4671abf7346Smrg old_y *= sblw->scroll.font_height; 4681abf7346Smrg new_y *= sblw->scroll.font_height; 4691abf7346Smrg height *= sblw->scroll.font_height; 4701abf7346Smrg 4711abf7346Smrg/* 4721abf7346Smrg * If we are already at the right location then do nothing. 4731abf7346Smrg * (height == 0). 4741abf7346Smrg * 4751abf7346Smrg * If we have scrolled more than a screen height then just clear 4761abf7346Smrg * the window. 4771abf7346Smrg */ 4781abf7346Smrg 4791abf7346Smrg if (height <= sblw->scroll.font_height) { /* avoid rounding errors. */ 4801abf7346Smrg XClearArea( XtDisplay(w), XtWindow(w), from_left, 0, 4811abf7346Smrg (unsigned int) 0, (unsigned int) 0, FALSE); 4821abf7346Smrg PaintText(w, 0, (int) sblw->core.height); 4831abf7346Smrg return; 4841abf7346Smrg } 4851abf7346Smrg 4861abf7346Smrg if ((int)height + (int)old_y > (int)w->core.height) 4871abf7346Smrg height = w->core.height - old_y; 4881abf7346Smrg 4891abf7346Smrg XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), sblw->scroll.move_gc, 4901abf7346Smrg from_left, old_y, 4911abf7346Smrg (unsigned int) w->core.width - from_left, (unsigned int) height, 4921abf7346Smrg from_left, new_y); 4931abf7346Smrg 4941abf7346Smrg if (old_y > new_y) 4951abf7346Smrg height -= sblw->scroll.font_height/2; /* clear 1/2 font of extra space, 4961abf7346Smrg to make sure we don't lose or 4971abf7346Smrg gain decenders. */ 4981abf7346Smrg else 4991abf7346Smrg height -= sblw->scroll.font_height; /* clear 1 font of extra space, 5001abf7346Smrg to make sure we don't overwrite 5011abf7346Smrg with a last line in buffer. */ 5021abf7346Smrg 5031abf7346Smrg if (old_y > new_y) 5041abf7346Smrg y_clear = height; 5051abf7346Smrg else 5061abf7346Smrg y_clear = 0; 5071abf7346Smrg 5081abf7346Smrg/* 5091abf7346Smrg * We cannot use generate exposures, since that may allow another move and 5101abf7346Smrg * clear before the area get repainted, this would be bad. 5111abf7346Smrg */ 5121abf7346Smrg 5131abf7346Smrg XClearArea( XtDisplay(w), XtWindow(w), from_left, y_clear, 5141abf7346Smrg (unsigned int) 0, (unsigned int) (w->core.height - height), 5151abf7346Smrg FALSE); 5161abf7346Smrg PaintText(w, (int) y_clear, (int) (w->core.height - height)); 5171abf7346Smrg} 5181abf7346Smrg 5191abf7346Smrg/* Function Name: SetThumbHeight 5201abf7346Smrg * Description: Set the height of the thumb. 5211abf7346Smrg * Arguments: w - the sblw widget. 5221abf7346Smrg * Returns: none 5231abf7346Smrg */ 5241abf7346Smrg 5251abf7346Smrgstatic void 5261abf7346SmrgSetThumbHeight(Widget w) 5271abf7346Smrg{ 5281abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5291abf7346Smrg float shown; 5301abf7346Smrg 5311abf7346Smrg if (sblw->scroll.bar == NULL) 5321abf7346Smrg return; 5331abf7346Smrg 5341abf7346Smrg if (sblw->scroll.lines == 0) 5351abf7346Smrg shown = 1.0; 5361abf7346Smrg else 5371abf7346Smrg shown = (float) w->core.height / (float) (sblw->scroll.lines * 5381abf7346Smrg sblw->scroll.font_height); 5391abf7346Smrg if (shown > 1.0) 5401abf7346Smrg shown = 1.0; 5411abf7346Smrg 5421abf7346Smrg XawScrollbarSetThumb( sblw->scroll.bar, (float) -1, shown ); 5431abf7346Smrg} 5441abf7346Smrg 5451abf7346Smrg/* Function Name: SetThumb 5461abf7346Smrg * Description: Set the thumb location. 5471abf7346Smrg * Arguments: w - the sblw. 5481abf7346Smrg * Returns: none 5491abf7346Smrg */ 5501abf7346Smrg 5511abf7346Smrgstatic void 5521abf7346SmrgSetThumb(Widget w) 5531abf7346Smrg{ 5541abf7346Smrg float location; 5551abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 5561abf7346Smrg 5571abf7346Smrg if ( (sblw->scroll.lines == 0) || (sblw->scroll.bar == NULL) ) 5581abf7346Smrg return; 5591abf7346Smrg 5601abf7346Smrg location = (float) sblw->scroll.line_pointer / (float) sblw->scroll.lines; 5611abf7346Smrg XawScrollbarSetThumb( sblw->scroll.bar, location , (float) -1 ); 5621abf7346Smrg} 5631abf7346Smrg 5641abf7346Smrg/* Function Name: VerticalJump. 5651abf7346Smrg * Description: This function moves the test 5661abf7346Smrg * as the vertical scroll bar is moved. 5671abf7346Smrg * Arguments: w - the scrollbar widget. 5681abf7346Smrg * junk - not used. 5691abf7346Smrg * percent - the position of the scrollbar. 5701abf7346Smrg * Returns: none. 5711abf7346Smrg */ 5721abf7346Smrg 5731abf7346Smrg/* ARGSUSED */ 5741abf7346Smrgstatic void 5751abf7346SmrgVerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr) 5761abf7346Smrg{ 5771abf7346Smrg float percent = *((float *) percent_ptr); 5781abf7346Smrg int new_line; /* The new location for the line pointer. */ 5791abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 5801abf7346Smrg 5811abf7346Smrg new_line = (int) ((float) sblw->scroll.lines * percent); 5821abf7346Smrg if (ScrollVerticalText( (Widget) sblw, new_line, FALSE)) 5831abf7346Smrg SetThumb((Widget) sblw); 5841abf7346Smrg} 5851abf7346Smrg 5861abf7346Smrg/* Function Name: VerticalScroll 5871abf7346Smrg * Description: This function moves the postition of the interior window 5881abf7346Smrg * as the vertical scroll bar is moved. 5891abf7346Smrg * Arguments: w - the scrollbar widget. 5901abf7346Smrg * junk - not used. 5911abf7346Smrg * pos - the position of the cursor. 5921abf7346Smrg * Returns: none. 5931abf7346Smrg */ 5941abf7346Smrg 5951abf7346Smrg/* ARGSUSED */ 5961abf7346Smrgstatic void 5971abf7346SmrgVerticalScroll(Widget w, XtPointer client_data, XtPointer call_data) 5981abf7346Smrg{ 5991abf7346Smrg int pos = (int)(long) call_data; 6001abf7346Smrg int new_line; /* The new location for the line pointer. */ 6011abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w); 6021abf7346Smrg 6031abf7346Smrg new_line = sblw->scroll.line_pointer + (pos / sblw->scroll.font_height); 6041abf7346Smrg (void) ScrollVerticalText( (Widget) sblw, new_line, FALSE); 6051abf7346Smrg SetThumb( (Widget) sblw); 6061abf7346Smrg} 6071abf7346Smrg 6081abf7346Smrg/* ARGSUSED */ 6091abf7346Smrgstatic void 6101abf7346SmrgInitialize(Widget req, Widget new, ArgList args, Cardinal *num_args) 6111abf7346Smrg{ 6121abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) new; 6131abf7346Smrg unsigned long figWidth; 6141abf7346Smrg Atom atomNum; 6151abf7346Smrg 6161abf7346Smrg sblw->scroll.top_line = NULL; 6171abf7346Smrg sblw->scroll.line_pointer = 0; 6181abf7346Smrg LoadFile(new); 6191abf7346Smrg sblw->scroll.bar = (Widget) NULL; 6201abf7346Smrg 6211abf7346Smrg sblw->scroll.font_height = (sblw->scroll.normal_font->max_bounds.ascent + 6221abf7346Smrg sblw->scroll.normal_font->max_bounds.descent); 6231abf7346Smrg 6241abf7346Smrg atomNum = XInternAtom(XtDisplay(req), "FIGURE_WIDTH", False); 6251abf7346Smrg 6261abf7346Smrg if (XGetFontProperty(sblw->scroll.normal_font, atomNum, &figWidth)) 6271abf7346Smrg sblw->scroll.h_width = figWidth; 6281abf7346Smrg else 6291abf7346Smrg sblw->scroll.h_width = XTextWidth(sblw->scroll.normal_font, "$", 1); 6301abf7346Smrg} /* Initialize. */ 6311abf7346Smrg 6321abf7346Smrg/* Function Name: CreateGCs 6331abf7346Smrg * Description: Creates the graphics contexts that we need. 6341abf7346Smrg * Arguments: w - the sblw. 6351abf7346Smrg * Returns: none 6361abf7346Smrg */ 6371abf7346Smrg 6381abf7346Smrgstatic void 6391abf7346SmrgCreateGCs(Widget w) 6401abf7346Smrg{ 6411abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6421abf7346Smrg 6431abf7346Smrg XtGCMask mask; 6441abf7346Smrg XGCValues values; 6451abf7346Smrg 6461abf7346Smrg values.graphics_exposures = TRUE; 6471abf7346Smrg sblw->scroll.move_gc = XtGetGC(w, GCGraphicsExposures, &values); 6481abf7346Smrg 6491abf7346Smrg mask = GCForeground | GCFont; 6501abf7346Smrg values.foreground = sblw->scroll.foreground; 6511abf7346Smrg 6521abf7346Smrg values.font = sblw->scroll.normal_font->fid; 6531abf7346Smrg sblw->scroll.normal_gc = XtGetGC(w, mask, &values); 6541abf7346Smrg 6551abf7346Smrg values.font = sblw->scroll.italic_font->fid; 6561abf7346Smrg sblw->scroll.italic_gc = XtGetGC(w, mask, &values); 6571abf7346Smrg 6581abf7346Smrg values.font = sblw->scroll.bold_font->fid; 6591abf7346Smrg sblw->scroll.bold_gc = XtGetGC(w, mask, &values); 6601abf7346Smrg 6611abf7346Smrg values.font = sblw->scroll.symbol_font->fid; 6621abf7346Smrg sblw->scroll.symbol_gc = XtGetGC(w, mask, &values); 6631abf7346Smrg} 6641abf7346Smrg 6651abf7346Smrg/* Function Name: DestroyGCs 6661abf7346Smrg * Description: removes all gcs for this widget. 6671abf7346Smrg * Arguments: w - the widget. 6681abf7346Smrg * Returns: none 6691abf7346Smrg */ 6701abf7346Smrg 6711abf7346Smrgstatic void 6721abf7346SmrgDestroyGCs(Widget w) 6731abf7346Smrg{ 6741abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6751abf7346Smrg 6761abf7346Smrg XtReleaseGC(w, sblw->scroll.normal_gc); 6771abf7346Smrg XtReleaseGC(w, sblw->scroll.bold_gc); 6781abf7346Smrg XtReleaseGC(w, sblw->scroll.italic_gc); 6791abf7346Smrg XtReleaseGC(w, sblw->scroll.move_gc); 6801abf7346Smrg} 6811abf7346Smrg 6821abf7346Smrgstatic void 6831abf7346SmrgRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) 6841abf7346Smrg{ 6851abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 6861abf7346Smrg 6871abf7346Smrg CreateScrollbar(w); 6881abf7346Smrg CreateGCs(w); 6891abf7346Smrg Layout(w); 6901abf7346Smrg (*SuperClass->core_class.realize) (w, valueMask, attributes); 6911abf7346Smrg XtRealizeWidget(sblw->scroll.bar); /* realize scrollbar. */ 6921abf7346Smrg XtMapWidget(sblw->scroll.bar); /* map scrollbar. */ 6931abf7346Smrg 6941abf7346Smrg XtAddEventHandler(w, 0, TRUE, GExpose, NULL); /* Get Graphics Exposures */ 6951abf7346Smrg} /* Realize */ 6961abf7346Smrg 6971abf7346Smrg/* Function Name: Destroy 6981abf7346Smrg * Description: Cleans up when we are killed. 6991abf7346Smrg * Arguments: w - the widget. 7001abf7346Smrg * Returns: none 7011abf7346Smrg */ 7021abf7346Smrg 7031abf7346Smrgstatic void 7041abf7346SmrgDestroy(Widget w) 7051abf7346Smrg{ 7061abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7071abf7346Smrg 7081abf7346Smrg if (sblw->scroll.bar != NULL) 7091abf7346Smrg XtDestroyWidget(sblw->scroll.bar); /* Destroy scrollbar. */ 7101abf7346Smrg if (sblw->scroll.file != NULL) 7111abf7346Smrg fclose(sblw->scroll.file); 7121abf7346Smrg DestroyGCs(w); 7131abf7346Smrg} 7141abf7346Smrg 7151abf7346Smrg/* 7161abf7346Smrg * 7171abf7346Smrg * Set Values 7181abf7346Smrg * 7191abf7346Smrg */ 7201abf7346Smrg 7211abf7346Smrg/* ARGSUSED */ 7221abf7346Smrgstatic Boolean 7231abf7346SmrgSetValuesHook(Widget w, ArgList args, Cardinal *num_args) 7241abf7346Smrg{ 7251abf7346Smrg Boolean ret = TRUE; 7261abf7346Smrg Cardinal i; 7271abf7346Smrg 7281abf7346Smrg for (i = 0; i < *num_args; i++) { 7291abf7346Smrg if (strcmp(XtNfile, args[i].name) == 0) { 7301abf7346Smrg LoadFile(w); 7311abf7346Smrg ret = TRUE; 7321abf7346Smrg } 7331abf7346Smrg } 7341abf7346Smrg 7351abf7346Smrg/* 7361abf7346Smrg * Changing anthing else will have strange effects, I don't need it so 7371abf7346Smrg * I didn't code it. 7381abf7346Smrg */ 7391abf7346Smrg 7401abf7346Smrg return(ret); 7411abf7346Smrg 7421abf7346Smrg} /* Set Values */ 7431abf7346Smrg 7441abf7346Smrg/* 7451abf7346Smrg * A little design philosophy is probabally wise to include at this point. 7461abf7346Smrg * 7471abf7346Smrg * One of the things that I has hoped to achieve with xman is to make the 7481abf7346Smrg * viewing of manpage not only easy for the nieve user, but also fast for 7491abf7346Smrg * the experienced user, I wanted to be able to use it too. To achieve this 7501abf7346Smrg * I end up sacrificing a bit of start up time for the manual data structure. 7511abf7346Smrg * As well as, the overhead of reading the entire file before putting it up 7521abf7346Smrg * on the display. This is actually hardly even noticeable since most manual 7531abf7346Smrg * pages are shots, one to two pages - the notable exception is of course csh, 7541abf7346Smrg * but then that should be broken up anyway. 7551abf7346Smrg * 7561abf7346Smrg * METHOD: 7571abf7346Smrg * 7581abf7346Smrg * I allocate a chunk of space that is the size of the file, plus a null for 7591abf7346Smrg * debugging. Then copiesthe file into this chunk of memory. I then allocate 7601abf7346Smrg * an array of char*'s that are assigned to the beginning of each line. Yes, 7611abf7346Smrg * this means that I have to read the file twice, and could probabally be more 7621abf7346Smrg * clever about it, but once it is in memory the second read is damn fast. 7631abf7346Smrg * There are a few obsucrities here about guessing the number of lines and 7641abf7346Smrg * reallocing if I guess wrong, but other than that it is pretty straight 7651abf7346Smrg * forward. 7661abf7346Smrg * 7671abf7346Smrg * Chris Peterson 7681abf7346Smrg * 1/27/88 7691abf7346Smrg */ 7701abf7346Smrg 7711abf7346Smrg#define ADD_MORE_MEM 100 /* first guesses for allocations. */ 7721abf7346Smrg#define CHAR_PER_LINE 40 7731abf7346Smrg 7741abf7346Smrg/* Function Name: LoadFile 7751abf7346Smrg * Description: Loads the current file into the internal memory. 7761abf7346Smrg * Arguments: w - the sblw. 7771abf7346Smrg * Returns: none 7781abf7346Smrg */ 7791abf7346Smrg 7801abf7346Smrgstatic void 7811abf7346SmrgLoadFile(Widget w) 7821abf7346Smrg{ 7831abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 7841abf7346Smrg FILE * file = sblw->scroll.file; 7851abf7346Smrg 7861abf7346Smrg char *page; 7871abf7346Smrg char **line_pointer,**top_line; /* pointers to beginnings of the 7881abf7346Smrg lines of the file. */ 7891abf7346Smrg int nlines; /* the current number of allocated lines. */ 7901abf7346Smrg struct stat fileinfo; /* file information from fstat. */ 7911abf7346Smrg 7921abf7346Smrg if ( sblw->scroll.top_line != NULL) { 7931abf7346Smrg XtFree(*(sblw->scroll.top_line)); /* free characters. */ 7941abf7346Smrg XtFree((char *)(sblw->scroll.top_line)); /* free lines. */ 7951abf7346Smrg } 7961abf7346Smrg sblw->scroll.top_line = NULL; 7971abf7346Smrg 7981abf7346Smrg if (file == NULL) 7991abf7346Smrg return; 8001abf7346Smrg 8011abf7346Smrg/* 8021abf7346Smrg * Get file size and allocate a chunk of memory for the file to be 8031abf7346Smrg * copied into. 8041abf7346Smrg */ 8051abf7346Smrg 8061abf7346Smrg if (fstat(fileno(file), &fileinfo)) 8071abf7346Smrg XtAppError(XtWidgetToApplicationContext(w), 8081abf7346Smrg "SBLW LoadFile: Failure in fstat."); 8091abf7346Smrg 8101abf7346Smrg/* 8111abf7346Smrg * Allocate a space for a list of pointer to the beginning of each line. 8121abf7346Smrg */ 8131abf7346Smrg 8141abf7346Smrg if ( (nlines = fileinfo.st_size/CHAR_PER_LINE) == 0) 8151abf7346Smrg return; 8161abf7346Smrg 8171abf7346Smrg page = XtMalloc(fileinfo.st_size + 1); /* leave space for the NULL */ 8181abf7346Smrg top_line = line_pointer = (char**) XtMalloc( nlines * sizeof(char *) ); 8191abf7346Smrg 8201abf7346Smrg/* 8211abf7346Smrg * Copy the file into memory. 8221abf7346Smrg */ 8231abf7346Smrg 8241abf7346Smrg fseek(file, 0L, SEEK_SET); 8251abf7346Smrg if (fread(page, sizeof(char), fileinfo.st_size, file) == 0) 8261abf7346Smrg XtAppError(XtWidgetToApplicationContext(w), 8271abf7346Smrg "SBLW LoadFile: Failure in fread."); 8281abf7346Smrg 8291abf7346Smrg 8301abf7346Smrg/* put NULL at end of buffer. */ 8311abf7346Smrg 8321abf7346Smrg *(page + fileinfo.st_size) = '\0'; 8331abf7346Smrg 8341abf7346Smrg/* 8351abf7346Smrg * Go through the file setting a line pointer to the character after each 8361abf7346Smrg * new line. If we run out of line pointer space then realloc that space 8371abf7346Smrg * with space for more lines. 8381abf7346Smrg */ 8391abf7346Smrg 8401abf7346Smrg *line_pointer++ = page; /* first line points to first char in buffer.*/ 8411abf7346Smrg while (*page != '\0') { 8421abf7346Smrg 8431abf7346Smrg if ( *page == '\n' ) { 8441abf7346Smrg *line_pointer++ = page + 1; 8451abf7346Smrg 8461abf7346Smrg if (line_pointer >= top_line + nlines) { 8471abf7346Smrg top_line = (char **) XtRealloc( (char *)top_line, (nlines + 8481abf7346Smrg ADD_MORE_MEM) * sizeof(char *) ); 8491abf7346Smrg line_pointer = top_line + nlines; 8501abf7346Smrg nlines += ADD_MORE_MEM; 8511abf7346Smrg } 8521abf7346Smrg } 8531abf7346Smrg page++; 8541abf7346Smrg } 8551abf7346Smrg 8561abf7346Smrg/* 8571abf7346Smrg * Realloc the line pointer space to take only the minimum amount of memory 8581abf7346Smrg */ 8591abf7346Smrg 8601abf7346Smrg sblw->scroll.lines = nlines = line_pointer - top_line - 1; 8611abf7346Smrg top_line = (char **) XtRealloc((char *)top_line, nlines * sizeof(char *)); 8621abf7346Smrg 8631abf7346Smrg/* 8641abf7346Smrg * Store the memory pointers 8651abf7346Smrg */ 8661abf7346Smrg 8671abf7346Smrg sblw->scroll.top_line = top_line; 8681abf7346Smrg sblw->scroll.line_pointer = 0; 8691abf7346Smrg SetThumbHeight(w); 8701abf7346Smrg SetThumb(w); 8711abf7346Smrg} 8721abf7346Smrg 8731abf7346Smrg#define NLINES 66 /* This is the number of lines to wait until 8741abf7346Smrg we boldify the line again, this allows 8751abf7346Smrg me to bold the first line of each page.*/ 8761abf7346Smrg#define BACKSPACE 010 /* I doubt you would want to change this. */ 8771abf7346Smrg 8781abf7346Smrg#define NORMAL 0 8791abf7346Smrg#define BOLD 1 8801abf7346Smrg#define ITALIC 2 8811abf7346Smrg#define SYMBOL 3 8821abf7346Smrg#define WHICH(italic, bold) ((bold) ? BOLD : ((italic) ? ITALIC : NORMAL)) 8831abf7346Smrg /* Choose BOLD over ITALICS. If neither */ 8841abf7346Smrg /* is chosen, use NORMAL. */ 8851abf7346Smrg 8861abf7346Smrgstatic int DumpText(Widget w, int x_loc, int y_loc, char * buf, int len, int format); 8871abf7346Smrgstatic Boolean Boldify(char *); 8881abf7346Smrg 8891abf7346Smrg/* Function Name: PrintText 8901abf7346Smrg * Description: This function actually prints the text. 8911abf7346Smrg * Arguments: w - the ScrollByLine widget. 8921abf7346Smrg * start_line - line to start printing, 8931abf7346Smrg * num_lines - the number of lines to print. 8941abf7346Smrg * location - the location to print the text. 8951abf7346Smrg * Returns: none. 8961abf7346Smrg */ 8971abf7346Smrg 8981abf7346Smrg/* ARGSUSED */ 8991abf7346Smrg 9001abf7346Smrgstatic void 9011abf7346SmrgPrintText(Widget w, int start_line, int num_lines, int location) 9021abf7346Smrg{ 9031abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 9041abf7346Smrg 9051abf7346Smrg register char *bufp, *c; /* Generic char pointers */ 9061abf7346Smrg int current_line; /* the number of the currrent line */ 9071abf7346Smrg char buf[BUFSIZ]; /* Misc. characters */ 9081abf7346Smrg Boolean italicflag = FALSE; /* Print text in italics?? */ 9091abf7346Smrg Boolean first = TRUE; /* First line of a manual page??? */ 9101abf7346Smrg int x_loc, y_loc; /* x and y location of text. */ 9111abf7346Smrg 9121abf7346Smrg/* 9131abf7346Smrg * For table hack 9141abf7346Smrg * To get columns to line up reasonably in most cases, make the 9151abf7346Smrg * assumption that they were lined up using lots of spaces, where 9161abf7346Smrg * lots is greater than two. Use a space width of 70% of the 9171abf7346Smrg * widest character in the font. 9181abf7346Smrg */ 9191abf7346Smrg int h_col, h_fix; 9201abf7346Smrg char * h_c; 9211abf7346Smrg 9221abf7346Smrg/* 9231abf7346Smrg * Nothing loaded, take no action. 9241abf7346Smrg */ 9251abf7346Smrg 9261abf7346Smrg if (sblw->scroll.top_line == NULL || num_lines == 0) 9271abf7346Smrg return; 9281abf7346Smrg 9291abf7346Smrg current_line = start_line; 9301abf7346Smrg 9311abf7346Smrg/* Set the first character to print at the first line. */ 9321abf7346Smrg 9331abf7346Smrg c = *(sblw->scroll.top_line + start_line); 9341abf7346Smrg 9351abf7346Smrg/* 9361abf7346Smrg * Because XDrawString uses the bottom of the text as a position 9371abf7346Smrg * reference, add the height from the top of the font to the baseline 9381abf7346Smrg * to the ScollByLine position reference. 9391abf7346Smrg */ 9401abf7346Smrg 9411abf7346Smrg y_loc = location + sblw->scroll.normal_font->max_bounds.ascent; 9421abf7346Smrg 9431abf7346Smrg/* 9441abf7346Smrg * Ok, here's the more than mildly heuristic man page formatter. 9451abf7346Smrg * We put chars into buf until either a font change or newline 9461abf7346Smrg * occurs (at which time we flush it to the screen.) 9471abf7346Smrg */ 9481abf7346Smrg 9491abf7346Smrg 9501abf7346Smrg bufp = buf; 9511abf7346Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 9521abf7346Smrg h_col = 0; 9531abf7346Smrg 9541abf7346Smrg/* 9551abf7346Smrg * A fix: 9561abf7346Smrg * Assume that we are always starting to print on or before the 9571abf7346Smrg * first line of a page, and then prove it if we aren't. 9581abf7346Smrg */ 9591abf7346Smrg for (h_fix = 1; h_fix <= (start_line % NLINES); h_fix++) 9601abf7346Smrg if (**(sblw->scroll.top_line + start_line - h_fix) != '\n') 9611abf7346Smrg { 9621abf7346Smrg first = FALSE; 9631abf7346Smrg break; 9641abf7346Smrg } 9651abf7346Smrg 9661abf7346Smrg while(TRUE) { 9671abf7346Smrg if (current_line % NLINES == 0) 9681abf7346Smrg first = TRUE; 9691abf7346Smrg 9701abf7346Smrg/* 9711abf7346Smrg * Lets make sure that we do not run out of space in our buffer, making full 9721abf7346Smrg * use of it is not critical since no window will be wide enough to display 9731abf7346Smrg * nearly BUFSIZ characters. 9741abf7346Smrg */ 9751abf7346Smrg 9761abf7346Smrg if ( (bufp - buf) > (BUFSIZ - 10) ) 9771abf7346Smrg /* Toss everything until we find a <CR> or the end of the buffer. */ 9781abf7346Smrg while ( (*c != '\n') && (*c != '\0') ) c++; 9791abf7346Smrg 9801abf7346Smrg switch(*c) { 9811abf7346Smrg 9821abf7346Smrg case '\0': /* If we reach the end of the file then return */ 9831abf7346Smrg DumpText(w, x_loc, y_loc, buf, bufp - buf, WHICH(italicflag, first)); 9841abf7346Smrg return; 9851abf7346Smrg 9861abf7346Smrg case '\n': 9871abf7346Smrg if (bufp != buf) { 9881abf7346Smrg Boolean bold; 9891abf7346Smrg *bufp = '\0'; /* for Boldify. */ 9901abf7346Smrg bold = ( (first) || ((x_loc == (sblw->scroll.offset + 9911abf7346Smrg sblw->scroll.indent)) && Boldify(buf)) ); 9921abf7346Smrg 9931abf7346Smrg (void) DumpText(w, x_loc, y_loc, buf, bufp - buf, 9941abf7346Smrg WHICH(italicflag, bold)); 9951abf7346Smrg 9961abf7346Smrg if (bold) 9971abf7346Smrg first = FALSE; 9981abf7346Smrg } 9991abf7346Smrg 10001abf7346Smrg/* 10011abf7346Smrg * If we have painted the required number of lines then we should now return. 10021abf7346Smrg */ 10031abf7346Smrg if (++current_line == start_line + num_lines ) 10041abf7346Smrg return; 10051abf7346Smrg 10061abf7346Smrg bufp = buf; 10071abf7346Smrg italicflag = FALSE; 10081abf7346Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10091abf7346Smrg h_col = 0; 10101abf7346Smrg y_loc += sblw->scroll.font_height; 10111abf7346Smrg break; 10121abf7346Smrg 10131abf7346Smrg/* 10141abf7346Smrg * This tab handling code is not very clever it moves the cursor over 10151abf7346Smrg * to the next boundry of eight (8) spaces, as calculated in width just 10161abf7346Smrg * before the printing loop started. 10171abf7346Smrg */ 10181abf7346Smrg 10191abf7346Smrg case '\t': /* TAB */ 10201abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10211abf7346Smrg WHICH(italicflag, first)); 10221abf7346Smrg h_col += bufp - buf; 10231abf7346Smrg bufp = buf; 10241abf7346Smrg italicflag = FALSE; 10251abf7346Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10261abf7346Smrg h_col = h_col + 8 - (h_col%8); 10271abf7346Smrg x_loc += sblw->scroll.h_width * h_col; 10281abf7346Smrg break; 10291abf7346Smrg 10301abf7346Smrg case ' ': 10311abf7346Smrg h_c = c + 1; 10321abf7346Smrg while (*h_c == ' ') h_c++; 10331abf7346Smrg 10341abf7346Smrg if (h_c - c < 4) 10351abf7346Smrg { 10361abf7346Smrg *bufp++ = *c; 10371abf7346Smrg break; 10381abf7346Smrg } 10391abf7346Smrg 10401abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10411abf7346Smrg WHICH(italicflag, first)); 10421abf7346Smrg h_col += bufp - buf; 10431abf7346Smrg bufp = buf; 10441abf7346Smrg italicflag = FALSE; 10451abf7346Smrg 10461abf7346Smrg x_loc = sblw->scroll.offset + sblw->scroll.indent; 10471abf7346Smrg h_col += (h_c - c); 10481abf7346Smrg x_loc += sblw->scroll.h_width * h_col; 10491abf7346Smrg c = h_c - 1; 10501abf7346Smrg break; 10511abf7346Smrg 10521abf7346Smrg case '\033': /* ignore esc sequences for now */ 10531abf7346Smrg c++; /* should always be esc-x */ 10541abf7346Smrg break; 10551abf7346Smrg 10561abf7346Smrg/* 10571abf7346Smrg * Overstrike code supplied by: cs.utexas.edu!ut-emx!clyde@rutgers.edu 10581abf7346Smrg * Since my manual pages do not have overstrike I couldn't test this. 10591abf7346Smrg */ 10601abf7346Smrg 10611abf7346Smrg case BACKSPACE: /* Backspacing for nroff bolding */ 10621abf7346Smrg if (c[-1] == c[1] && c[1] != BACKSPACE) { /* overstriking one char */ 10631abf7346Smrg if (bufp > buf) { 10641abf7346Smrg bufp--; /* Zap 1st instance of char to bolden */ 10651abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10661abf7346Smrg WHICH(italicflag, FALSE)); 10671abf7346Smrg h_col += bufp - buf; 10681abf7346Smrg } 10691abf7346Smrg bufp = buf; 10701abf7346Smrg *bufp++ = c[1]; 10711abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, BOLD); 10721abf7346Smrg h_col += bufp - buf; 10731abf7346Smrg bufp = buf; 10741abf7346Smrg first = FALSE; 10751abf7346Smrg 10761abf7346Smrg /* 10771abf7346Smrg * Nroff bolding looks like: 10781abf7346Smrg * C\bC\bC\bCN... 10791abf7346Smrg * c points to ----^ ^ 10801abf7346Smrg * it needs to point to --^ 10811abf7346Smrg */ 10821abf7346Smrg while (*c == BACKSPACE && c[-1] == c[1]) 10831abf7346Smrg c += 2; 10841abf7346Smrg c--; /* Back up to previous char */ 10851abf7346Smrg } 10861abf7346Smrg else { 10871abf7346Smrg if ((c[-1] == 'o' && c[1] == '+') /* Nroff bullet */ 10881abf7346Smrg || (c[-1] == '+' && c[1] == 'o')) { /* Nroff bullet */ 10891abf7346Smrg /* If we run into a bullet, print out */ 10901abf7346Smrg /* everything that's accumulated to this */ 10911abf7346Smrg /* point, then the bullet, then resume. */ 10921abf7346Smrg if (bufp>buf) { 10931abf7346Smrg bufp--; 10941abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 10951abf7346Smrg WHICH(italicflag, FALSE)); 10961abf7346Smrg h_col += bufp - buf; 10971abf7346Smrg } 10981abf7346Smrg bufp = buf; 10991abf7346Smrg *bufp = (char)183; 11001abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, 1, SYMBOL); 11011abf7346Smrg h_col++; 11021abf7346Smrg c++; 11031abf7346Smrg } 11041abf7346Smrg else { /* 'real' backspace - back up output ptr */ 11051abf7346Smrg if (bufp>buf) 11061abf7346Smrg bufp--; 11071abf7346Smrg } 11081abf7346Smrg } 11091abf7346Smrg break; 11101abf7346Smrg 11111abf7346Smrg/* End of contributed overstrike code. */ 11121abf7346Smrg 11131abf7346Smrg case '_': /* look for underlining [italicize] */ 11141abf7346Smrg if(*(c + 1) == BACKSPACE) { 11151abf7346Smrg if(!italicflag) { /* font change? */ 11161abf7346Smrg if (bufp != buf) { 11171abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, NORMAL); 11181abf7346Smrg h_col += bufp - buf; 11191abf7346Smrg bufp = buf; 11201abf7346Smrg } 11211abf7346Smrg italicflag = TRUE; 11221abf7346Smrg } 11231abf7346Smrg c += 2; 11241abf7346Smrg *bufp++ = *c; 11251abf7346Smrg break; 11261abf7346Smrg } 11271abf7346Smrg /* else fall through to default, because this was a real underscore. */ 11281abf7346Smrg 11291abf7346Smrg default: 11301abf7346Smrg if(italicflag) { /* font change? */ 11311abf7346Smrg if (bufp != buf) { 11321abf7346Smrg x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, 11331abf7346Smrg WHICH(italicflag, FALSE)); 11341abf7346Smrg h_col += bufp - buf; 11351abf7346Smrg bufp = buf; 11361abf7346Smrg } 11371abf7346Smrg italicflag = FALSE; 11381abf7346Smrg } 11391abf7346Smrg *bufp++ = *c; 11401abf7346Smrg break; 11411abf7346Smrg } 11421abf7346Smrg c++; 11431abf7346Smrg } 11441abf7346Smrg} 11451abf7346Smrg 11461abf7346Smrg/* Function Name: DumpText 11471abf7346Smrg * Description: Dumps text to the screen. 11481abf7346Smrg * Arguments: w - the widget. 11491abf7346Smrg * x_loc - to dump text at. 11501abf7346Smrg * y_loc - the y_location to draw_text. 11511abf7346Smrg * buf - buffer to dump. 11521abf7346Smrg * italic, bold, boolean that tells us which gc to use. 11531abf7346Smrg * Returns: x_location of the end of the text. 11541abf7346Smrg */ 11551abf7346Smrg 11561abf7346Smrgstatic int 11571abf7346SmrgDumpText(Widget w, int x_loc, int y_loc, char * buf, int len, int format) 11581abf7346Smrg{ 11591abf7346Smrg ScrollByLineWidget sblw = (ScrollByLineWidget) w; 11601abf7346Smrg GC gc; 11611abf7346Smrg XFontStruct * font; 11621abf7346Smrg 11631abf7346Smrg switch(format) { 11641abf7346Smrg 11651abf7346Smrg case ITALIC: 11661abf7346Smrg gc = sblw->scroll.italic_gc; 11671abf7346Smrg font = sblw->scroll.italic_font; 11681abf7346Smrg break; 11691abf7346Smrg 11701abf7346Smrg case BOLD: 11711abf7346Smrg gc = sblw->scroll.bold_gc; 11721abf7346Smrg font = sblw->scroll.bold_font; 11731abf7346Smrg break; 11741abf7346Smrg 11751abf7346Smrg case SYMBOL: 11761abf7346Smrg gc = sblw->scroll.symbol_gc; 11771abf7346Smrg font = sblw->scroll.symbol_font; 11781abf7346Smrg break; 11791abf7346Smrg 11801abf7346Smrg default: 11811abf7346Smrg gc = sblw->scroll.normal_gc; 11821abf7346Smrg font = sblw->scroll.normal_font; 11831abf7346Smrg break; 11841abf7346Smrg } 11851abf7346Smrg 11861abf7346Smrg XDrawString(XtDisplay(w), XtWindow(w), gc, x_loc, y_loc, buf, len); 11871abf7346Smrg return(x_loc + XTextWidth(font, buf, len)); 11881abf7346Smrg} 11891abf7346Smrg 11901abf7346Smrg/* Function Name: Boldify 11911abf7346Smrg * Description: look for keyword. 11921abf7346Smrg * Arguments: sp - string pointer. 11931abf7346Smrg * Returns: 1 if keyword else 0. 11941abf7346Smrg */ 11951abf7346Smrg 11961abf7346Smrgstatic Boolean 11971abf7346SmrgBoldify(register char *sp) 11981abf7346Smrg{ 11991abf7346Smrg register char *sp_pointer; 12001abf7346Smrg int length,count; 12011abf7346Smrg 12021abf7346Smrg/* 12031abf7346Smrg * If there are not lower case letters in the line the assume it is a 12041abf7346Smrg * keyword and boldify it in PrintManpage. 12051abf7346Smrg */ 12061abf7346Smrg 12071abf7346Smrg length = strlen(sp); 12081abf7346Smrg for (sp_pointer = sp, count = 0; count < length; sp_pointer++,count++) 12091abf7346Smrg if ( !isupper(*sp_pointer) && !isspace(*sp_pointer) ) 12101abf7346Smrg return(0); 12111abf7346Smrg return(1); 12121abf7346Smrg} 12131abf7346Smrg 12141abf7346Smrg#undef superclass 12151abf7346Smrg#undef SuperClass 1216