home *** CD-ROM | disk | FTP | other *** search
- /*
- * xman - X window system manual page display program.
- *
- * $XConsortium: ScrollByL.c,v 1.27 91/07/26 18:30:47 dave Exp $
- * $Header: ScrollByL.c,v 1.27 91/07/26 18:30:47 dave Exp $
- *
- * Copyright 1987, 1988 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of M.I.T. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. M.I.T. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * Author: Chris D. Peterson, MIT Project Athena
- * Created: December 5, 1987
- */
-
- #if ( !defined(lint) && !defined(SABER))
- static char rcs_version[] = "$Athena: ScrollByL.c,v 4.5 88/12/19 13:46:04 kit Exp $";
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
-
- #include <X11/IntrinsicP.h>
- #include <sys/stat.h> /* depends on IntrinsicP.h */
- #include <X11/StringDefs.h>
-
- #include <X11/Xaw/Scrollbar.h>
- #include <X11/Xmu/Misc.h>
-
- #include "ScrollByLP.h"
-
- /* Default Translation Table */
-
- static char defaultTranslations[] =
- "<Key>f: Page(Forward) \n\
- <Key>b: Page(Back) \n\
- <Key>1: Page(Line, 1) \n\
- <Key>2: Page(Line, 2) \n\
- <Key>3: Page(Line, 3) \n\
- <Key>4: Page(Line, 4) \n\
- <Key>\\ : Page(Forward)";
-
-
- /****************************************************************
- *
- * ScrollByLine Resources
- *
- ****************************************************************/
-
- #define Offset(field) XtOffset(ScrollByLineWidget, scroll.field)
- #define CoreOffset(field) XtOffset(ScrollByLineWidget, core.field)
-
- static XtResource resources[] = {
- {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
- CoreOffset(width), XtRImmediate, (caddr_t) 500},
- {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
- CoreOffset(height), XtRImmediate, (caddr_t) 700},
-
- {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
- Offset(foreground), XtRString, "XtDefaultForeground"},
- {XtNforceVert, XtCBoolean, XtRBoolean, sizeof(Boolean),
- Offset(force_vert), XtRImmediate, (caddr_t) FALSE},
- {XtNindent, XtCIndent, XtRDimension, sizeof(Dimension),
- Offset(indent), XtRImmediate, (caddr_t) 15},
- {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean),
- Offset(use_right), XtRImmediate, (caddr_t) FALSE},
- {XtNmanualFontNormal, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- Offset(normal_font), XtRString, MANPAGE_NORMAL},
- {XtNmanualFontBold, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- Offset(bold_font), XtRString, MANPAGE_BOLD},
- {XtNmanualFontItalic, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- Offset(italic_font), XtRString, MANPAGE_ITALIC},
- {XtNmanualFontSymbol, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
- Offset(symbol_font), XtRString, MANPAGE_SYMBOL},
- {XtNfile, XtCFile, XtRFile, sizeof(FILE *),
- Offset(file), XtRImmediate, (caddr_t) NULL},
- };
-
- #undef Offset
- #undef CoreOffset
-
- /****************************************************************
- *
- * Full class record constant
- *
- ****************************************************************/
-
- static Boolean ScrollVerticalText();
- static void MoveAndClearText(), LoadFile(), PrintText(), VerticalJump();
- static void VerticalScroll(), SetThumbHeight(), PaintText(), Layout();
-
- /* semi - public functions. */
-
- static void Realize(), Initialize(), Destroy(), Redisplay(), Page();
- static Boolean SetValuesHook();
-
- static XtActionsRec actions[] = {
- { "Page", Page},
- };
-
- #define superclass (&simpleClassRec)
-
- ScrollByLineClassRec scrollByLineClassRec = {
- {
- /* core_class fields */
- /* superclass */ (WidgetClass) superclass,
- /* class_name */ "ScrollByLine",
- /* widget_size */ sizeof(ScrollByLineRec),
- /* class_initialize */ NULL,
- /* class_part_init */ NULL,
- /* class_inited */ FALSE,
- /* initialize */ Initialize,
- /* initialize_hook */ NULL,
- /* realize */ Realize,
- /* actions */ actions,
- /* num_actions */ XtNumber(actions),
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ FALSE,
- /* compress_enterleave*/ TRUE,
- /* visible_interest */ FALSE,
- /* destroy */ Destroy,
- /* resize */ Layout,
- /* expose */ Redisplay,
- /* set_values */ NULL,
- /* set_values_hook */ SetValuesHook,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_private */ NULL,
- /* tm_table */ defaultTranslations,
- /* query_geometry */ XtInheritQueryGeometry,
- /* display_accelerator*/ XtInheritDisplayAccelerator,
- /* extension */ NULL,
- },
- { /* simple fields */
- /* change_sensitive */ XtInheritChangeSensitive
- }
- };
-
- WidgetClass scrollByLineWidgetClass =
- (WidgetClass) &scrollByLineClassRec;
-
-
- /****************************************************************
- *
- * Private Routines
- *
- ****************************************************************/
-
- /* Function Name: Layout
- * Description: This function lays out the scroll widget.
- * Arguments: w - the scroll widget.
- * key - a boolean: if true then resize the widget to the child
- * if false the resize children to fit widget.
- * Returns: TRUE if successful.
- */
-
- static void
- Layout(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- Dimension width, height;
- Widget bar;
- Position bar_bw;
-
- /*
- * For now always show the bar.
- */
-
- bar = sblw->scroll.bar;
- height = sblw->core.height;
- width = sblw->core.width;
- bar_bw = bar->core.border_width;
-
- /* Move child and v_bar to correct location. */
-
- if (sblw->scroll.use_right) {
- XtMoveWidget(bar, width - (bar->core.width + bar_bw), - bar_bw);
- sblw->scroll.offset = 0;
- }
- else {
- XtMoveWidget(bar, - bar_bw, - bar_bw);
- sblw->scroll.offset = bar->core.width + bar_bw;
- }
-
- /* resize the scrollbar to be the correct height or width. */
-
- XtResizeWidget(bar, bar->core.width, height, bar->core.border_width);
-
- SetThumbHeight(w);
- }
-
- /* ARGSUSED */
- static void
- GExpose(w,junk,event,cont)
- Widget w;
- XtPointer junk;
- XEvent *event;
- Boolean *cont;
- {
-
- /*
- * Graphics exposure events are not currently sent to exposure proc.
- */
-
- if (event->type == GraphicsExpose)
- Redisplay(w, event, NULL);
-
- } /* ChildExpose */
-
- /*
- * Repaint the widget's child Window Widget.
- */
-
- /* ARGSUSED */
- static void Redisplay(w, event, region)
- Widget w;
- XEvent *event;
- Region region;
- {
- int top, height; /* the locations of the top and height
- of the region that needs to be repainted. */
-
- /*
- * This routine tells the client which sections of the window to
- * repaint in his callback function which does the actual repainting.
- */
-
- if (event->type == Expose) {
- top = event->xexpose.y;
- height = event->xexpose.height;
- }
- else {
- top = event->xgraphicsexpose.y;
- height = event->xgraphicsexpose.height;
- }
-
- PaintText(w, top, height);
- } /* redisplay (expose) */
-
- /* Function Name: PaintText
- * Description: paints the text at the give location for a given height.
- * Arguments: w - the sbl widget.
- * y_loc, height - location and size of area to paint.
- * Returns: none
- */
-
- static void
- PaintText(w, y_loc, height)
- Widget w;
- int y_loc, height;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- int start_line, num_lines, location;
-
- start_line = y_loc / sblw->scroll.font_height + sblw->scroll.line_pointer;
-
- if (start_line >= sblw->scroll.lines)
- return;
-
- num_lines = height / sblw->scroll.font_height + 1;
-
- /*
- * Only integer arithmetic makes this possible.
- */
-
- location = y_loc / sblw->scroll.font_height * sblw->scroll.font_height;
-
- PrintText(w, start_line, num_lines, location);
- }
-
- /* Function Name: Page
- * Description: This function pages the widget, by the amount it recieves
- * from the translation Manager.
- * Arguments: w - the ScrollByLineWidget.
- * event - the event that caused this return.
- * params - the parameters passed to it.
- * num_params - the number of parameters.
- * Returns: none.
- */
-
- /* ARGSUSED */
- static void
- Page(w, event, params, num_params)
- Widget w;
- XEvent * event;
- String * params;
- Cardinal *num_params;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- Widget bar = sblw->scroll.bar;
-
- if (*num_params < 1)
- return;
- /*
- * If no scroll bar is visible then do not page, as the entire window is shown,
- * of scrolling has been turned off.
- */
-
- if (bar == (Widget) NULL)
- return;
-
- switch ( params[0][0] ) {
- case 'f':
- case 'F':
- /* move one page forward */
- VerticalScroll(bar, NULL, (int) bar->core.height);
- break;
- case 'b':
- case 'B':
- /* move one page backward */
- VerticalScroll(bar, NULL, - (int) bar->core.height);
- break;
- case 'L':
- case 'l':
- /* move one line forward */
- VerticalScroll(bar, NULL,
- (int) atoi(params[1]) * sblw->scroll.font_height);
- break;
- default:
- return;
- }
- }
-
- /* Function Name: CreateScrollbar
- * Description: createst the scrollbar for us.
- * Arguments: w - sblw widget.
- * Returns: none.
- */
-
- static void
- CreateScrollbar(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- Arg args[5];
- Cardinal num_args = 0;
-
- if (sblw->scroll.bar != NULL)
- return;
-
- XtSetArg(args[num_args], XtNorientation, XtorientVertical); num_args++;
-
- sblw->scroll.bar = XtCreateWidget("scrollbar", scrollbarWidgetClass, w,
- args, num_args);
- XtAddCallback(sblw->scroll.bar, XtNscrollProc, VerticalScroll, NULL);
- XtAddCallback(sblw->scroll.bar, XtNjumpProc, VerticalJump, NULL);
- }
-
- /* Function Name: ScrollVerticalText
- * Description: This accomplished the actual movement of the text.
- * Arguments: w - the ScrollByLine Widget.
- * new_line - the new location for the line pointer
- * force_redisplay - should we force this window to get
- * redisplayed?
- * Returns: True if the thumb needs to be moved.
- */
-
- static Boolean
- ScrollVerticalText(w, new_line, force_redisp)
- Widget w;
- int new_line;
- Boolean force_redisp;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- int num_lines = (int)w->core.height / sblw->scroll.font_height + 1;
- int max_lines, old_line;
- Boolean move_thumb = FALSE;
-
- /*
- * Do not let the window extend out of bounds.
- */
-
- if ( new_line < 0) {
- new_line = 0;
- move_thumb = TRUE;
- }
- else {
- max_lines = sblw->scroll.lines - (int)w->core.height / sblw->scroll.font_height;
- AssignMax(max_lines, 0);
-
- if ( new_line > max_lines ) {
- new_line = max_lines;
- move_thumb = TRUE;
- }
- }
-
- /*
- * If forced to redisplay then do a full redisplay and return.
- */
-
- old_line = sblw->scroll.line_pointer;
- sblw->scroll.line_pointer = new_line; /* Set current top of page. */
-
- if (force_redisp)
- MoveAndClearText(w, 0, /* cause a full redisplay */ 0, 0);
-
- if (new_line == old_line)
- return(move_thumb);
-
- /*
- * Scroll forward.
- */
-
- else if (new_line < old_line) {
- int lines_to_scroll = old_line - new_line;
- MoveAndClearText(w, 0, num_lines - lines_to_scroll, lines_to_scroll);
- }
-
- /*
- * Scroll back.
- */
-
- else {
- int lines_to_scroll = new_line - old_line;
- MoveAndClearText(w, lines_to_scroll, num_lines - lines_to_scroll, 0);
- }
-
- return(move_thumb);
- }
-
- /* Function Name: MoveAndClearText
- * Description: Blits as much text as it can and clear the
- * remaining area with generate exposures TRUE.
- * Arguments: w - the sbl widget.
- * old_y - the old y position.
- * height - height of area to move.
- * new_y - new y position.
- * Returns: none
- */
-
- static void
- MoveAndClearText(w, old_y, height, new_y)
- Widget w;
- int old_y, new_y, height;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- int from_left = sblw->scroll.indent + sblw->scroll.offset;
- int y_clear;
-
- old_y *= sblw->scroll.font_height;
- new_y *= sblw->scroll.font_height;
- height *= sblw->scroll.font_height;
-
- /*
- * If we are already at the right location then do nothing.
- * (height == 0).
- *
- * If we have scrolled more than a screen height then just clear
- * the window.
- */
-
- if (height <= sblw->scroll.font_height) { /* avoid rounding errors. */
- XClearArea( XtDisplay(w), XtWindow(w), from_left, 0,
- (unsigned int) 0, (unsigned int) 0, FALSE);
- PaintText(w, 0, (int) sblw->core.height);
- return;
- }
-
- if ((int)height + (int)old_y > (int)w->core.height)
- height = w->core.height - old_y;
-
- XCopyArea(XtDisplay(w), XtWindow(w), XtWindow(w), sblw->scroll.move_gc,
- from_left, old_y,
- (unsigned int) w->core.width - from_left, (unsigned int) height,
- from_left, new_y);
-
- height -= sblw->scroll.font_height/2; /* clear 1/2 font of extra space,
- to make sure we don't lose or
- gain decenders. */
- if (old_y > new_y)
- y_clear = height;
- else
- y_clear = 0;
-
- /*
- * We cannot use generate exposures, since that may allow another move and
- * clear before the area get repainted, this would be bad.
- */
-
- XClearArea( XtDisplay(w), XtWindow(w), from_left, y_clear,
- (unsigned int) 0, (unsigned int) (w->core.height - height),
- FALSE);
- PaintText(w, (int) y_clear, (int) (w->core.height - height));
- }
-
- /* Function Name: SetThumbHeight
- * Description: Set the height of the thumb.
- * Arguments: w - the sblw widget.
- * Returns: none
- */
-
- static void
- SetThumbHeight(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- float shown;
-
- if (sblw->scroll.bar == NULL)
- return;
-
- if (sblw->scroll.lines == 0)
- shown = 1.0;
- else
- shown = (float) w->core.height / (float) (sblw->scroll.lines *
- sblw->scroll.font_height);
- if (shown > 1.0)
- shown = 1.0;
-
- XawScrollbarSetThumb( sblw->scroll.bar, (float) -1, shown );
- }
-
- /* Function Name: SetThumb
- * Description: Set the thumb location.
- * Arguments: w - the sblw.
- * Returns: none
- */
-
- static void
- SetThumb(w)
- Widget w;
- {
- float location;
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- if ( (sblw->scroll.lines == 0) || (sblw->scroll.bar == NULL) )
- return;
-
- location = (float) sblw->scroll.line_pointer / (float) sblw->scroll.lines;
- XawScrollbarSetThumb( sblw->scroll.bar, location , (float) -1 );
- }
-
- /* Function Name: VerticalJump.
- * Description: This function moves the test
- * as the vertical scroll bar is moved.
- * Arguments: w - the scrollbar widget.
- * junk - not used.
- * percent - the position of the scrollbar.
- * Returns: none.
- */
-
- /* ARGSUSED */
- static void
- VerticalJump(w, junk, percent_ptr)
- Widget w;
- caddr_t junk;
- caddr_t percent_ptr;
- {
- float percent = *((float *) percent_ptr);
- int new_line; /* The new location for the line pointer. */
- ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w);
-
- new_line = (int) ((float) sblw->scroll.lines * percent);
- if (ScrollVerticalText( (Widget) sblw, new_line, FALSE))
- SetThumb((Widget) sblw);
- }
-
- /* Function Name: VerticalScroll
- * Description: This function moves the postition of the interior window
- * as the vertical scroll bar is moved.
- * Arguments: w - the scrollbar widget.
- * junk - not used.
- * pos - the position of the cursor.
- * Returns: none.
- */
-
- /* ARGSUSED */
- static void
- VerticalScroll(w,junk,pos)
- Widget w;
- caddr_t junk;
- int pos;
- {
- int new_line; /* The new location for the line pointer. */
- ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w);
-
- new_line = sblw->scroll.line_pointer + (pos / sblw->scroll.font_height);
- (void) ScrollVerticalText( (Widget) sblw, new_line, FALSE);
- SetThumb( (Widget) sblw);
- }
-
- int h_width; /* main font width */
-
- /* ARGSUSED */
- static void
- Initialize(req, new)
- Widget req, new;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) new;
- unsigned long figWidth;
- Atom atomNum;
-
- sblw->scroll.top_line = NULL;
- sblw->scroll.line_pointer = 0;
- LoadFile(new);
- sblw->scroll.bar = (Widget) NULL;
-
- sblw->scroll.font_height = (sblw->scroll.normal_font->max_bounds.ascent +
- sblw->scroll.normal_font->max_bounds.descent);
-
- atomNum = XInternAtom(XtDisplay(req), "FIGURE_WIDTH", False);
-
- if (XGetFontProperty(sblw->scroll.normal_font, atomNum, &figWidth))
- h_width = figWidth;
- else
- h_width = XTextWidth(sblw->scroll.normal_font, "$", 1);
-
-
-
- } /* Initialize. */
-
- /* Function Name: CreateGCs
- * Description: Creates the graphics contexts that we need.
- * Arguments: w - the sblw.
- * Returns: none
- */
-
- static void
- CreateGCs(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- XtGCMask mask;
- XGCValues values;
-
- values.graphics_exposures = TRUE;
- sblw->scroll.move_gc = XtGetGC(w, GCGraphicsExposures, &values);
-
- mask = GCForeground | GCFont;
- values.foreground = sblw->scroll.foreground;
-
- values.font = sblw->scroll.normal_font->fid;
- sblw->scroll.normal_gc = XtGetGC(w, mask, &values);
-
- values.font = sblw->scroll.italic_font->fid;
- sblw->scroll.italic_gc = XtGetGC(w, mask, &values);
-
- values.font = sblw->scroll.bold_font->fid;
- sblw->scroll.bold_gc = XtGetGC(w, mask, &values);
-
- values.font = sblw->scroll.symbol_font->fid;
- sblw->scroll.symbol_gc = XtGetGC(w, mask, &values);
- }
-
- /* Function Name: DestroyGCs
- * Description: removes all gcs for this widget.
- * Arguments: w - the widget.
- * Returns: none
- */
-
- static void
- DestroyGCs(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- XtReleaseGC(w, sblw->scroll.normal_gc);
- XtReleaseGC(w, sblw->scroll.bold_gc);
- XtReleaseGC(w, sblw->scroll.italic_gc);
- XtReleaseGC(w, sblw->scroll.move_gc);
- }
-
- static void
- Realize(w, valueMask, attributes)
- register Widget w;
- Mask *valueMask;
- XSetWindowAttributes *attributes;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- CreateScrollbar(w);
- CreateGCs(w);
- Layout(w);
- (*superclass->core_class.realize) (w, valueMask, attributes);
- XtRealizeWidget(sblw->scroll.bar); /* realize scrollbar. */
- XtMapWidget(sblw->scroll.bar); /* map scrollbar. */
-
- XtAddEventHandler(w, 0, TRUE, GExpose, NULL); /* Get Graphics Exposures */
- } /* Realize */
-
- /* Function Name: Destroy
- * Description: Cleans up when we are killed.
- * Arguments: w - the widget.
- * Returns: none
- */
-
- static void
- Destroy(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- if (sblw->scroll.bar != NULL)
- XtDestroyWidget(sblw->scroll.bar); /* Destroy scrollbar. */
- if (sblw->scroll.file != NULL)
- fclose(sblw->scroll.file);
- DestroyGCs(w);
- }
-
- /*
- *
- * Set Values
- *
- */
-
- /* ARGSUSED */
- static Boolean
- SetValuesHook( w, args, num_args)
- Widget w;
- ArgList args;
- Cardinal *num_args;
- {
- Boolean ret = TRUE;
- int i;
-
- for (i = 0; i < *num_args; i++) {
- if (strcmp(XtNfile, args[i].name) == 0) {
- LoadFile(w);
- ret = TRUE;
- }
- }
-
- /*
- * Changing anthing else will have strange effects, I don't need it so
- * I didn't code it.
- */
-
- return(ret);
-
- } /* Set Values */
-
- /*
- * A little design philosophy is probabally wise to include at this point.
- *
- * One of the things that I has hoped to achieve with xman is to make the
- * viewing of manpage not only easy for the nieve user, but also fast for
- * the experienced user, I wanted to be able to use it too. To achieve this
- * I end up sacrificing a bit of start up time for the manual data structure.
- * As well as, the overhead of reading the entire file before putting it up
- * on the display. This is actually hardly even noticeable since most manual
- * pages are shots, one to two pages - the notable exception is of course csh,
- * but then that should be broken up anyway.
- *
- * METHOD:
- *
- * I allocate a chunk of space that is the size of the file, plus a null for
- * debugging. Then copiesthe file into this chunk of memory. I then allocate
- * an array of char*'s that are assigned to the beginning of each line. Yes,
- * this means that I have to read the file twice, and could probabally be more
- * clever about it, but once it is in memory the second read is damn fast.
- * There are a few obsucrities here about guessing the number of lines and
- * reallocing if I guess wrong, but other than that it is pretty straight
- * forward.
- *
- * Chris Peterson
- * 1/27/88
- */
-
- #define ADD_MORE_MEM 100 /* first guesses for allocations. */
- #define CHAR_PER_LINE 40
-
- /* Function Name: LoadFile
- * Description: Loads the current file into the internal memory.
- * Arguments: w - the sblw.
- * Returns: none
- */
-
- static void
- LoadFile(w)
- Widget w;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- FILE * file = sblw->scroll.file;
-
- char *page;
- char **line_pointer,**top_line; /* pointers to beginnings of the
- lines of the file. */
- int nlines; /* the current number of allocated lines. */
- struct stat fileinfo; /* file information from fstat. */
-
- if ( sblw->scroll.top_line != NULL) {
- XtFree(*(sblw->scroll.top_line)); /* free characters. */
- XtFree((char *)(sblw->scroll.top_line)); /* free lines. */
- }
- sblw->scroll.top_line = NULL;
-
- if (file == NULL)
- return;
-
- /*
- * Get file size and allocate a chunk of memory for the file to be
- * copied into.
- */
-
- if (fstat(fileno(file), &fileinfo))
- XtAppError(XtWidgetToApplicationContext(w),
- "SBLW LoadFile: Failure in fstat.");
-
- /*
- * Allocate a space for a list of pointer to the beginning of each line.
- */
-
- if ( (nlines = fileinfo.st_size/CHAR_PER_LINE) == 0)
- return;
-
- page = XtMalloc(fileinfo.st_size + 1); /* leave space for the NULL */
- top_line = line_pointer = (char**) XtMalloc( nlines * sizeof(char *) );
-
- /*
- * Copy the file into memory.
- */
-
- if (fread(page, sizeof(char), fileinfo.st_size, file) == 0)
- XtAppError(XtWidgetToApplicationContext(w),
- "SBLW LoadFile: Failure in fread.");
-
-
- /* put NULL at end of buffer. */
-
- *(page + fileinfo.st_size) = '\0';
-
- /*
- * Go through the file setting a line pointer to the character after each
- * new line. If we run out of line pointer space then realloc that space
- * with space for more lines.
- */
-
- *line_pointer++ = page; /* first line points to first char in buffer.*/
- while (*page != '\0') {
-
- if ( *page == '\n' ) {
- *line_pointer++ = page + 1;
-
- if (line_pointer >= top_line + nlines) {
- top_line = (char **) XtRealloc( (char *)top_line, (nlines +
- ADD_MORE_MEM) * sizeof(char *) );
- line_pointer = top_line + nlines;
- nlines += ADD_MORE_MEM;
- }
- }
- page++;
- }
-
- /*
- * Realloc the line pointer space to take only the minimum amount of memory
- */
-
- sblw->scroll.lines = nlines = line_pointer - top_line - 1;
- top_line = (char **) XtRealloc((char *)top_line, nlines * sizeof(char *));
-
- /*
- * Store the memory pointers
- */
-
- sblw->scroll.top_line = top_line;
- sblw->scroll.line_pointer = 0;
- SetThumbHeight(w);
- SetThumb(w);
- }
-
- #define NLINES 66 /* This is the number of lines to wait until
- we boldify the line again, this allows
- me to bold the first line of each page.*/
- #define BACKSPACE 010 /* I doubt you would want to change this. */
-
- #define NORMAL 0
- #define BOLD 1
- #define ITALIC 2
- #define SYMBOL 3
- #define WHICH(italic, bold) ((bold) ? BOLD : ((italic) ? ITALIC : NORMAL))
- /* Choose BOLD over ITALICS. If neither */
- /* is chosen, use NORMAL. */
-
- static int DumpText();
- static Boolean Boldify();
-
- /* Function Name: PrintText
- * Description: This function actually prints the text.
- * Arguments: w - the ScrollByLine widget.
- * start_line - line to start printing,
- * num_lines - the number of lines to print.
- * location - the location to print the text.
- * Returns: none.
- */
-
- /* ARGSUSED */
-
- static void
- PrintText(w, start_line, num_lines, location)
- Widget w;
- int start_line, num_lines, location;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
-
- register char *bufp, *c; /* Generic char pointers */
- int current_line; /* the number of the currrent line */
- char buf[BUFSIZ]; /* Misc. characters */
- int width; /* Width of a tab stop. */
- Boolean italicflag = FALSE; /* Print text in italics?? */
- Boolean first = TRUE; /* First line of a manual page??? */
- int x_loc, y_loc; /* x and y location of text. */
-
- /*
- * For table hack
- * To get columns to line up reasonably in most cases, make the
- * assumption that they were lined up using lots of spaces, where
- * lots is greater than two. Use a space width of 70% of the
- * widest character in the font.
- */
- XFontStruct * h_font;
- int h_col, h_fix;
- char * h_c;
-
- h_font = sblw->scroll.normal_font;
-
- /*
- * Nothing loaded, take no action.
- */
-
- if (sblw->scroll.top_line == NULL || num_lines == 0)
- return;
-
- current_line = start_line;
-
- /* Set the first character to print at the first line. */
-
- c = *(sblw->scroll.top_line + start_line);
-
- /* Width of a tab stop. */
- width = 8 * h_width;
-
- /*
- * Because XDrawString uses the bottom of the text as a position
- * reference, add the height from the top of the font to the baseline
- * to the ScollByLine position reference.
- */
-
- y_loc = location + sblw->scroll.normal_font->max_bounds.ascent;
-
- /*
- * Ok, here's the more than mildly heuristic man page formatter.
- * We put chars into buf until either a font change or newline
- * occurs (at which time we flush it to the screen.)
- */
-
-
- bufp = buf;
- x_loc = sblw->scroll.offset + sblw->scroll.indent;
- h_col = 0;
-
- /*
- * A fix:
- * Assume that we are always starting to print on or before the
- * first line of a page, and then prove it if we aren't.
- */
- for (h_fix = 1; h_fix <= (start_line % NLINES); h_fix++)
- if (**(sblw->scroll.top_line + start_line - h_fix) != '\n')
- {
- first = FALSE;
- break;
- }
-
- while(TRUE) {
- if (current_line % NLINES == 0)
- first = TRUE;
-
- /*
- * Lets make sure that we do not run out of space in our buffer, making full
- * use of it is not critical since no window will be wide enough to display
- * nearly BUFSIZ characters.
- */
-
- if ( (bufp - buf) > (BUFSIZ - 10) )
- /* Toss everything until we find a <CR> or the end of the buffer. */
- while ( (*c != '\n') && (*c != '\0') ) c++;
-
- switch(*c) {
-
- case '\0': /* If we reach the end of the file then return */
- DumpText(w, x_loc, y_loc, buf, bufp - buf, WHICH(italicflag, first));
- return;
-
- case '\n':
- if (bufp != buf) {
- Boolean bold;
- *bufp = '\0'; /* for Boldify. */
- bold = ( (first) || ((x_loc == (sblw->scroll.offset +
- sblw->scroll.indent)) && Boldify(buf)) );
-
- (void) DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, bold));
-
- if (bold)
- first = FALSE;
- }
-
- /*
- * If we have painted the required number of lines then we should now return.
- */
- if (++current_line == start_line + num_lines )
- return;
-
- bufp = buf;
- italicflag = FALSE;
- x_loc = sblw->scroll.offset + sblw->scroll.indent;
- h_col = 0;
- y_loc += sblw->scroll.font_height;
- break;
-
- /*
- * This tab handling code is not very clever it moves the cursor over
- * to the next boundry of eight (8) spaces, as calculated in width just
- * before the printing loop started.
- */
-
- case '\t': /* TAB */
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, first));
- h_col += bufp - buf;
- bufp = buf;
- italicflag = FALSE;
- x_loc = sblw->scroll.offset + sblw->scroll.indent;
- h_col = h_col + 8 - (h_col%8);
- x_loc += h_width * h_col;
- break;
-
- case ' ':
- h_c = c + 1;
- while (*h_c == ' ') h_c++;
-
- if (h_c - c < 4)
- {
- *bufp++ = *c;
- break;
- }
-
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, first));
- h_col += bufp - buf;
- bufp = buf;
- italicflag = FALSE;
-
- x_loc = sblw->scroll.offset + sblw->scroll.indent;
- h_col += (h_c - c);
- x_loc += h_width * h_col;
- c = h_c - 1;
- break;
-
- case '\033': /* ignore esc sequences for now */
- c++; /* should always be esc-x */
- break;
-
- /*
- * Overstrike code supplied by: cs.utexas.edu!ut-emx!clyde@rutgers.edu
- * Since my manual pages do not have overstrike I couldn't test this.
- */
-
- case BACKSPACE: /* Backspacing for nroff bolding */
- if (c[-1] == c[1] && c[1] != BACKSPACE) { /* overstriking one char */
- bufp--; /* Zap 1st instance of char to bolden */
- if (bufp > buf) {
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, FALSE));
- h_col += bufp - buf;
- bufp = buf;
- }
- *bufp++ = c[1];
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, BOLD);
- h_col += bufp - buf;
- bufp = buf;
- first = FALSE;
-
- /*
- * Nroff bolding looks like:
- * C\bC\bC\bCN...
- * c points to ----^ ^
- * it needs to point to --^
- */
- while (*c == BACKSPACE && c[-1] == c[1])
- c += 2;
- c--; /* Back up to previous char */
- }
- else {
- if ((c[-1] == 'o' && c[1] == '+') /* Nroff bullet */
- || (c[-1] == '+' && c[1] == 'o')) { /* Nroff bullet */
- /* If we run into a bullet, print out */
- /* everything that's accumulated to this */
- /* point, then the bullet, then resume. */
- bufp--;
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, FALSE));
- h_col += bufp - buf;
- bufp = buf;
- *bufp = (char)183;
- x_loc = DumpText(w, x_loc, y_loc, buf, 1, SYMBOL);
- h_col++;
- c++;
- }
- else { /* 'real' backspace - back up output ptr */
- bufp--;
- }
- }
- break;
-
- /* End of contributed overstrike code. */
-
- case '_': /* look for underlining [italicize] */
- if(*(c + 1) == BACKSPACE) {
- if(!italicflag) { /* font change? */
- if (bufp != buf) {
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, NORMAL);
- h_col += bufp - buf;
- bufp = buf;
- }
- italicflag = TRUE;
- }
- c += 2;
- *bufp++ = *c;
- break;
- }
- /* else fall through to default, because this was a real underscore. */
-
- default:
- if(italicflag) { /* font change? */
- if (bufp != buf) {
- x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
- WHICH(italicflag, FALSE));
- h_col += bufp - buf;
- bufp = buf;
- }
- italicflag = FALSE;
- }
- *bufp++ = *c;
- break;
- }
- c++;
- }
- }
-
- /* Function Name: DumpText
- * Description: Dumps text to the screen.
- * Arguments: w - the widget.
- * x_loc - to dump text at.
- * y_loc - the y_location to draw_text.
- * buf - buffer to dump.
- * italic, bold, boolean that tells us which gc to use.
- * Returns: x_location of the end of the text.
- */
-
- static int
- DumpText(w, x_loc, y_loc, buf, len, format)
- Widget w;
- int x_loc, y_loc;
- char * buf;
- int len;
- int format;
- {
- ScrollByLineWidget sblw = (ScrollByLineWidget) w;
- GC gc;
- XFontStruct * font;
-
- switch(format) {
-
- case ITALIC:
- gc = sblw->scroll.italic_gc;
- font = sblw->scroll.italic_font;
- break;
-
- case BOLD:
- gc = sblw->scroll.bold_gc;
- font = sblw->scroll.bold_font;
- break;
-
- case SYMBOL:
- gc = sblw->scroll.symbol_gc;
- font = sblw->scroll.symbol_font;
- break;
-
- default:
- gc = sblw->scroll.normal_gc;
- font = sblw->scroll.normal_font;
- break;
- }
-
- XDrawString(XtDisplay(w), XtWindow(w), gc, x_loc, y_loc, buf, len);
- return(x_loc + XTextWidth(font, buf, len));
- }
-
- /* Function Name: Boldify
- * Description: look for keyword.
- * Arguments: sp - string pointer.
- * Returns: 1 if keyword else 0.
- */
-
- static Boolean
- Boldify(sp)
- register char *sp;
- {
- register char *sp_pointer;
- int length,count;
-
- /*
- * If there are not lower case letters in the line the assume it is a
- * keyword and boldify it in PrintManpage.
- */
-
- length = strlen(sp);
- for (sp_pointer = sp, count = 0; count < length; sp_pointer++,count++)
- if ( !isupper(*sp_pointer) && !isspace(*sp_pointer) )
- return(0);
- return(1);
- }
-
- #undef superclass
-