Bug Summary

File:ScrollByL.c
Location:line 1015, column 13
Description:Value stored to 'x_loc' is never read

Annotated Source Code

1/*
2
3Copyright (c) 1987, 1988 X Consortium
4
5Permission is hereby granted, free of charge, to any person obtaining
6a copy of this software and associated documentation files (the
7"Software"), to deal in the Software without restriction, including
8without limitation the rights to use, copy, modify, merge, publish,
9distribute, sublicense, and/or sell copies of the Software, and to
10permit persons to whom the Software is furnished to do so, subject to
11the following conditions:
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of the X Consortium shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from the X Consortium.
28
29*/
30
31#include <stdio.h>
32#include <ctype.h>
33#include <X11/Xos.h>
34#include <stdlib.h>
35
36#include <X11/IntrinsicP.h>
37#include <sys/stat.h> /* depends on IntrinsicP.h */
38#include <X11/StringDefs.h>
39
40#include <X11/Xaw/Scrollbar.h>
41
42#include "ScrollByLP.h"
43
44/* Default Translation Table */
45
46static char defaultTranslations[] =
47 "<Key>f: Page(Forward) \n\
48 <Key>b: Page(Back) \n\
49 <Key>1: Page(Line, 1) \n\
50 <Key>2: Page(Line, 2) \n\
51 <Key>3: Page(Line, 3) \n\
52 <Key>4: Page(Line, 4) \n\
53 <Key>\\ : Page(Forward)";
54
55/****************************************************************
56 *
57 * ScrollByLine Resources
58 *
59 ****************************************************************/
60
61#define Offset(field) XtOffset(ScrollByLineWidget, scroll.field)((Cardinal) (((char *) (&(((ScrollByLineWidget)((void*)0)
)->scroll.field))) - ((char *) ((void*)0))))
62#define CoreOffset(field) XtOffset(ScrollByLineWidget, core.field)((Cardinal) (((char *) (&(((ScrollByLineWidget)((void*)0)
)->core.field))) - ((char *) ((void*)0))))
63
64static XtResource resources[] = {
65 {XtNwidth((char*)&XtStrings[872]), XtCWidth((char*)&XtStrings[1510]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension),
66 CoreOffset(width), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) 500},
67 {XtNheight((char*)&XtStrings[234]), XtCHeight((char*)&XtStrings[1051]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension),
68 CoreOffset(height), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) 700},
69
70 {XtNforeground((char*)&XtStrings[214]), XtCForeground((char*)&XtStrings[1022]), XtRPixel((char*)&XtStrings[1754]), sizeof(Pixel),
71 Offset(foreground), XtRString((char*)&XtStrings[1797]), "XtDefaultForeground"},
72 {XtNforceVert"forceVert", XtCBoolean((char*)&XtStrings[920]), XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean),
73 Offset(force_vert), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) FALSE0},
74 {XtNindent"indent", XtCIndent"Indent", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension),
75 Offset(indent), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) 15},
76 {XtNuseRight((char*)&XtStrings[850]), XtCBoolean((char*)&XtStrings[920]), XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean),
77 Offset(use_right), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) FALSE0},
78 {XtNmanualFontNormal"manualFontNormal", XtCFont((char*)&XtStrings[1017]), XtRFontStruct((char*)&XtStrings[1666]), sizeof(XFontStruct *),
79 Offset(normal_font), XtRString((char*)&XtStrings[1797]), MANPAGE_NORMAL"*-new century schoolbook-medium-r-normal--*-120-*"},
80 {XtNmanualFontBold"manualFontBold", XtCFont((char*)&XtStrings[1017]), XtRFontStruct((char*)&XtStrings[1666]), sizeof(XFontStruct *),
81 Offset(bold_font), XtRString((char*)&XtStrings[1797]), MANPAGE_BOLD"*-new century schoolbook-bold-r-normal--*-120-*"},
82 {XtNmanualFontItalic"manualFontItalic", XtCFont((char*)&XtStrings[1017]), XtRFontStruct((char*)&XtStrings[1666]), sizeof(XFontStruct *),
83 Offset(italic_font), XtRString((char*)&XtStrings[1797]), MANPAGE_ITALIC"*-new century schoolbook-bold-i-normal--*-120-*"},
84 {XtNmanualFontSymbol"manualFontSymbol", XtCFont((char*)&XtStrings[1017]), XtRFontStruct((char*)&XtStrings[1666]), sizeof(XFontStruct *),
85 Offset(symbol_font), XtRString((char*)&XtStrings[1797]), MANPAGE_SYMBOL"*-symbol-medium-r-normal--*-120-*"},
86 {XtNfile((char*)&XtStrings[194]), XtCFile((char*)&XtStrings[1012]), XtRFile((char*)&XtStrings[1650]), sizeof(FILE *),
87 Offset(file), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) NULL((void*)0)},
88 {XtNNumTotalLines"numTotalLines", XtCNumTotalLines"NumTotalLines", XtRInt((char*)&XtStrings[1718]), sizeof(int),
89 Offset(lines), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) 0},
90 {XtNNumVisibleLines"numVisibleLines", XtCNumVisibleLines"NumVisibleLines", XtRInt((char*)&XtStrings[1718]), sizeof(int),
91 Offset(num_visible_lines), XtRImmediate((char*)&XtStrings[1695]), (caddr_t) 0},
92};
93
94#undef Offset
95#undef CoreOffset
96
97/****************************************************************
98 *
99 * Full class record constant
100 *
101 ****************************************************************/
102
103static void CreateScrollbar(Widget w);
104static Boolean ScrollVerticalText(Widget w, int new_line, Boolean force_redisp);
105static void Layout(Widget w);
106static void LoadFile(Widget w);
107static void MoveAndClearText(Widget w, int old_y, int height, int new_y);
108static void PaintText(Widget w, int y_loc, int height);
109static void PrintText(Widget w, int start_line, int num_lines, int location);
110static void SetThumbHeight(Widget w);
111static void VerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr);
112static void VerticalScroll(Widget w, XtPointer client_data,
113 XtPointer call_data);
114
115/* semi - public functions. */
116
117static void Realize(Widget w, Mask *valueMask,
118 XSetWindowAttributes *attributes);
119static void Initialize(Widget req, Widget new, ArgList args,
120 Cardinal *num_args);
121static void Destroy(Widget w);
122static void Redisplay(Widget w, XEvent *event, Region region);
123static void Page(Widget w, XEvent *event, String *params, Cardinal *num_params);
124static Boolean SetValuesHook(Widget w, ArgList args, Cardinal *num_args);
125
126static XtActionsRec actions[] = {
127 {"Page", Page},
128};
129
130#define superclass (&simpleClassRec)
131#define SuperClass simpleWidgetClass
132
133ScrollByLineClassRec scrollByLineClassRec = {
134 {
135/* core_class fields */
136 /* superclass */ (WidgetClass) superclass,
137 /* class_name */ "ScrollByLine",
138 /* widget_size */ sizeof(ScrollByLineRec),
139 /* class_initialize */ NULL((void*)0),
140 /* class_part_init */ NULL((void*)0),
141 /* class_inited */ FALSE0,
142 /* initialize */ Initialize,
143 /* initialize_hook */ NULL((void*)0),
144 /* realize */ Realize,
145 /* actions */ actions,
146 /* num_actions */ XtNumber(actions)((Cardinal) (sizeof(actions) / sizeof(actions[0]))),
147 /* resources */ resources,
148 /* num_resources */ XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))),
149 /* xrm_class */ NULLQUARK((XrmQuark) 0),
150 /* compress_motion */ TRUE1,
151 /* compress_exposure */ FALSE0,
152 /* compress_enterleave */ TRUE1,
153 /* visible_interest */ FALSE0,
154 /* destroy */ Destroy,
155 /* resize */ Layout,
156 /* expose */ Redisplay,
157 /* set_values */ NULL((void*)0),
158 /* set_values_hook */ SetValuesHook,
159 /* set_values_almost */ XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit),
160 /* get_values_hook */ NULL((void*)0),
161 /* accept_focus */ NULL((void*)0),
162 /* version */ XtVersion(11 * 1000 + 6),
163 /* callback_private */ NULL((void*)0),
164 /* tm_table */ defaultTranslations,
165 /* query_geometry */ XtInheritQueryGeometry((XtGeometryHandler) _XtInherit),
166 /* display_accelerator */ XtInheritDisplayAccelerator((XtStringProc) _XtInherit),
167 /* extension */ NULL((void*)0),
168 },
169 {
170/* simple fields */
171 /* change_sensitive */ XtInheritChangeSensitive((int (*)(Widget))_XtInherit)
172 }
173};
174
175WidgetClass scrollByLineWidgetClass = (WidgetClass) &scrollByLineClassRec;
176
177/****************************************************************
178 *
179 * Private Routines
180 *
181 ****************************************************************/
182
183/* Function Name: Layout
184 * Description: This function lays out the scroll widget.
185 * Arguments: w - the scroll widget.
186 * key - a boolean: if true then resize the widget to the child
187 * if false the resize children to fit widget.
188 * Returns: TRUE if successful.
189 */
190
191static void
192Layout(Widget w)
193{
194 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
195 Dimension width, height;
196 Widget bar;
197 Position bar_bw;
198
199 CreateScrollbar(w);
200
201/*
202 * For now always show the bar.
203 */
204
205 bar = sblw->scroll.bar;
206 height = sblw->core.height;
207 width = sblw->core.width;
208 bar_bw = bar->core.border_width;
209
210 /* Move child and v_bar to correct location. */
211 if (sblw->scroll.use_right) {
212 XtMoveWidget(bar, width - (bar->core.width + bar_bw), -bar_bw);
213 sblw->scroll.offset = 0;
214 }
215 else {
216 XtMoveWidget(bar, -bar_bw, -bar_bw);
217 sblw->scroll.offset = bar->core.width + bar_bw;
218 }
219
220 /* resize the scrollbar to be the correct height or width. */
221 XtResizeWidget(bar, bar->core.width, height, bar->core.border_width);
222
223 SetThumbHeight(w);
224
225 sblw->scroll.num_visible_lines = height / sblw->scroll.font_height + 1;
226}
227
228/* ARGSUSED */
229static void
230GExpose(Widget w, XtPointer junk, XEvent * event, Boolean * cont)
231{
232
233/*
234 * Graphics exposure events are not currently sent to exposure proc.
235 */
236
237 if (event->type == GraphicsExpose13)
238 Redisplay(w, event, NULL((void*)0));
239
240} /* ChildExpose */
241
242/*
243 * Repaint the widget's child Window Widget.
244 */
245
246/* ARGSUSED */
247static void
248Redisplay(Widget w, XEvent * event, Region region)
249{
250 int top, height; /* the locations of the top and height
251 of the region that needs to be repainted. */
252
253/*
254 * This routine tells the client which sections of the window to
255 * repaint in his callback function which does the actual repainting.
256 */
257
258 if (event->type == Expose12) {
259 top = event->xexpose.y;
260 height = event->xexpose.height;
261 }
262 else {
263 top = event->xgraphicsexpose.y;
264 height = event->xgraphicsexpose.height;
265 }
266
267 PaintText(w, top, height);
268} /* redisplay (expose) */
269
270/* Function Name: PaintText
271 * Description: paints the text at the give location for a given height.
272 * Arguments: w - the sbl widget.
273 * y_loc, height - location and size of area to paint.
274 * Returns: none
275 */
276
277static void
278PaintText(Widget w, int y_loc, int height)
279{
280 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
281 int start_line, location;
282
283 start_line = y_loc / sblw->scroll.font_height + sblw->scroll.line_pointer;
284
285 if (start_line >= sblw->scroll.lines)
286 return;
287
288/*
289 * Only integer arithmetic makes this possible.
290 */
291
292 location = y_loc / sblw->scroll.font_height * sblw->scroll.font_height;
293
294 PrintText(w, start_line, sblw->scroll.num_visible_lines, location);
295}
296
297/* Function Name: Page
298 * Description: This function pages the widget, by the amount it receives
299 * from the translation Manager.
300 * Arguments: w - the ScrollByLineWidget.
301 * event - the event that caused this return.
302 * params - the parameters passed to it.
303 * num_params - the number of parameters.
304 * Returns: none.
305 */
306
307/* ARGSUSED */
308static void
309Page(Widget w, XEvent * event, String * params, Cardinal * num_params)
310{
311 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
312 Widget bar = sblw->scroll.bar;
313
314 if (*num_params < 1)
315 return;
316/*
317 * If no scroll bar is visible then do not page, as the entire window is shown,
318 * or scrolling has been turned off.
319 */
320
321 if (bar == (Widget) NULL((void*)0))
322 return;
323
324 switch (params[0][0]) {
325 case 'f':
326 case 'F':
327 /* move one page forward */
328 VerticalScroll(bar, NULL((void*)0), (XtPointer) ((long) bar->core.height));
329 break;
330 case 'b':
331 case 'B':
332 /* move one page backward */
333 VerticalScroll(bar, NULL((void*)0), (XtPointer) (-(long) bar->core.height));
334 break;
335 case 'L':
336 case 'l':
337 /* move one line forward */
338 VerticalScroll(bar, NULL((void*)0),
339 (XtPointer) ((long) atoi(params[1]) *
340 sblw->scroll.font_height));
341 break;
342 default:
343 return;
344 }
345}
346
347/* Function Name: CreateScrollbar
348 * Description: createst the scrollbar for us.
349 * Arguments: w - sblw widget.
350 * Returns: none.
351 */
352
353static void
354CreateScrollbar(Widget w)
355{
356 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
357 Arg args[5];
358 Cardinal num_args = 0;
359
360 if (sblw->scroll.bar != NULL((void*)0))
361 return;
362
363 XtSetArg(args[num_args], XtNorientation, XtorientVertical)((void)( (args[num_args]).name = (((char*)&XtStrings[505]
)), (args[num_args]).value = (XtArgVal)(XtorientVertical) ))
;
364 num_args++;
365
366 sblw->scroll.bar = XtCreateWidget("scrollbar", scrollbarWidgetClass, w,
367 args, num_args);
368 XtAddCallback(sblw->scroll.bar, XtNscrollProc((char*)&XtStrings[591]), VerticalScroll, NULL((void*)0));
369 XtAddCallback(sblw->scroll.bar, XtNjumpProc((char*)&XtStrings[370]), VerticalJump, NULL((void*)0));
370}
371
372/* Function Name: ScrollVerticalText
373 * Description: This accomplished the actual movement of the text.
374 * Arguments: w - the ScrollByLine Widget.
375 * new_line - the new location for the line pointer
376 * force_redisplay - should we force this window to get
377 * redisplayed?
378 * Returns: True if the thumb needs to be moved.
379 */
380
381static Boolean
382ScrollVerticalText(Widget w, int new_line, Boolean force_redisp)
383{
384 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
385 int num_lines = sblw->scroll.num_visible_lines;
386 int max_lines, old_line;
387 Boolean move_thumb = FALSE0;
388
389/*
390 * Do not let the window extend out of bounds.
391 */
392
393 if (new_line < 0) {
394 new_line = 0;
395 move_thumb = TRUE1;
396 }
397 else {
398 max_lines = sblw->scroll.lines -
399 (int) w->core.height / sblw->scroll.font_height;
400 if (max_lines < 0)
401 max_lines = 0;
402
403 if (new_line > max_lines) {
404 new_line = max_lines;
405 move_thumb = TRUE1;
406 }
407 }
408
409/*
410 * If forced to redisplay then do a full redisplay and return.
411 */
412
413 old_line = sblw->scroll.line_pointer;
414 sblw->scroll.line_pointer = new_line; /* Set current top of page. */
415
416 if (force_redisp)
417 MoveAndClearText(w, 0, /* cause a full redisplay */ 0, 0);
418
419 if (new_line == old_line)
420 return (move_thumb);
421
422/*
423 * Scroll forward.
424 */
425
426 else if (new_line < old_line) {
427 int lines_to_scroll = old_line - new_line;
428 MoveAndClearText(w, 0, num_lines - lines_to_scroll, lines_to_scroll);
429 }
430
431/*
432 * Scroll back.
433 */
434
435 else {
436 int lines_to_scroll = new_line - old_line;
437 MoveAndClearText(w, lines_to_scroll, num_lines - lines_to_scroll, 0);
438 }
439
440 return (move_thumb);
441}
442
443/* Function Name: MoveAndClearText
444 * Description: Blits as much text as it can and clear the
445 * remaining area with generate exposures TRUE.
446 * Arguments: w - the sbl widget.
447 * old_y - the old y position.
448 * height - height of area to move.
449 * new_y - new y position.
450 * Returns: none
451 */
452
453static void
454MoveAndClearText(Widget w, int old_y, int height, int new_y)
455{
456 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
457 int from_left = sblw->scroll.indent + sblw->scroll.offset - 1;
458 int y_clear;
459
460 old_y *= sblw->scroll.font_height;
461 new_y *= sblw->scroll.font_height;
462 height *= sblw->scroll.font_height;
463
464/*
465 * If we are already at the right location then do nothing.
466 * (height == 0).
467 *
468 * If we have scrolled more than a screen height then just clear
469 * the window.
470 */
471
472 if (height <= sblw->scroll.font_height) { /* avoid rounding errors. */
473 XClearArea(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), from_left, 0,
474 (unsigned int) 0, (unsigned int) 0, FALSE0);
475 PaintText(w, 0, (int) sblw->core.height);
476 return;
477 }
478
479 if ((int) height + (int) old_y > (int) w->core.height)
480 height = w->core.height - old_y;
481
482 XCopyArea(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), XtWindow(w)((w)->core.window), sblw->scroll.move_gc,
483 from_left, old_y,
484 (unsigned int) w->core.width - from_left, (unsigned int) height,
485 from_left, new_y);
486
487 if (old_y > new_y)
488 height -= sblw->scroll.font_height / 2; /* clear 1/2 font of extra space,
489 to make sure we don't lose or
490 gain descenders. */
491 else
492 height -= sblw->scroll.font_height; /* clear 1 font of extra space,
493 to make sure we don't overwrite
494 with a last line in buffer. */
495
496 if (old_y > new_y)
497 y_clear = height;
498 else
499 y_clear = 0;
500
501/*
502 * We cannot use generate exposures, since that may allow another move and
503 * clear before the area get repainted, this would be bad.
504 */
505
506 XClearArea(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), from_left, y_clear,
507 (unsigned int) 0, (unsigned int) (w->core.height - height),
508 FALSE0);
509 PaintText(w, (int) y_clear, (int) (w->core.height - height));
510}
511
512/* Function Name: SetThumbHeight
513 * Description: Set the height of the thumb.
514 * Arguments: w - the sblw widget.
515 * Returns: none
516 */
517
518static void
519SetThumbHeight(Widget w)
520{
521 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
522 float shown;
523
524 if (sblw->scroll.bar == NULL((void*)0))
525 return;
526
527 if (sblw->scroll.lines == 0)
528 shown = 1.0;
529 else
530 shown = (float) w->core.height / (float) (sblw->scroll.lines *
531 sblw->scroll.font_height);
532 if (shown > 1.0)
533 shown = 1.0;
534
535 XawScrollbarSetThumb(sblw->scroll.bar, (float) -1, shown);
536}
537
538/* Function Name: SetThumb
539 * Description: Set the thumb location.
540 * Arguments: w - the sblw.
541 * Returns: none
542 */
543
544static void
545SetThumb(Widget w)
546{
547 float location;
548 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
549
550 if ((sblw->scroll.lines == 0) || (sblw->scroll.bar == NULL((void*)0)))
551 return;
552
553 location = (float) sblw->scroll.line_pointer / (float) sblw->scroll.lines;
554 XawScrollbarSetThumb(sblw->scroll.bar, location, (float) -1);
555}
556
557/* Function Name: VerticalJump.
558 * Description: This function moves the test
559 * as the vertical scroll bar is moved.
560 * Arguments: w - the scrollbar widget.
561 * junk - not used.
562 * percent - the position of the scrollbar.
563 * Returns: none.
564 */
565
566/* ARGSUSED */
567static void
568VerticalJump(Widget w, XtPointer junk, XtPointer percent_ptr)
569{
570 float percent = *((float *) percent_ptr);
571 int new_line; /* The new location for the line pointer. */
572 ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w)((w)->core.parent);
573
574 new_line = (int) ((float) sblw->scroll.lines * percent);
575 if (ScrollVerticalText((Widget) sblw, new_line, FALSE0))
576 SetThumb((Widget) sblw);
577}
578
579/* Function Name: VerticalScroll
580 * Description: This function moves the position of the interior window
581 * as the vertical scroll bar is moved.
582 * Arguments: w - the scrollbar widget.
583 * junk - not used.
584 * pos - the position of the cursor.
585 * Returns: none.
586 */
587
588/* ARGSUSED */
589static void
590VerticalScroll(Widget w, XtPointer client_data, XtPointer call_data)
591{
592 int pos = (int) (long) call_data;
593 int new_line; /* The new location for the line pointer. */
594 ScrollByLineWidget sblw = (ScrollByLineWidget) XtParent(w)((w)->core.parent);
595
596 new_line = sblw->scroll.line_pointer + (pos / sblw->scroll.font_height);
597 (void) ScrollVerticalText((Widget) sblw, new_line, FALSE0);
598 SetThumb((Widget) sblw);
599}
600
601/* ARGSUSED */
602static void
603Initialize(Widget req, Widget new, ArgList args, Cardinal * num_args)
604{
605 ScrollByLineWidget sblw = (ScrollByLineWidget) new;
606 unsigned long figWidth;
607 Atom atomNum;
608
609 sblw->scroll.top_line = NULL((void*)0);
610 sblw->scroll.line_pointer = 0;
611 LoadFile(new);
612 sblw->scroll.bar = (Widget) NULL((void*)0);
613
614 sblw->scroll.font_height = (sblw->scroll.normal_font->max_bounds.ascent +
615 sblw->scroll.normal_font->max_bounds.descent);
616
617 atomNum = XInternAtom(XtDisplay(req)(((req)->core.screen)->display), "FIGURE_WIDTH", False0);
618
619 if (XGetFontProperty(sblw->scroll.normal_font, atomNum, &figWidth))
620 sblw->scroll.h_width = figWidth;
621 else
622 sblw->scroll.h_width = XTextWidth(sblw->scroll.normal_font, "$", 1);
623} /* Initialize. */
624
625/* Function Name: CreateGCs
626 * Description: Creates the graphics contexts that we need.
627 * Arguments: w - the sblw.
628 * Returns: none
629 */
630
631static void
632CreateGCs(Widget w)
633{
634 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
635
636 XtGCMask mask;
637 XGCValues values;
638
639 values.graphics_exposures = TRUE1;
640 sblw->scroll.move_gc = XtGetGC(w, GCGraphicsExposures(1L<<16), &values);
641
642 mask = GCForeground(1L<<2) | GCFont(1L<<14);
643 values.foreground = sblw->scroll.foreground;
644
645 values.font = sblw->scroll.normal_font->fid;
646 sblw->scroll.normal_gc = XtGetGC(w, mask, &values);
647
648 values.font = sblw->scroll.italic_font->fid;
649 sblw->scroll.italic_gc = XtGetGC(w, mask, &values);
650
651 values.font = sblw->scroll.bold_font->fid;
652 sblw->scroll.bold_gc = XtGetGC(w, mask, &values);
653
654 values.font = sblw->scroll.symbol_font->fid;
655 sblw->scroll.symbol_gc = XtGetGC(w, mask, &values);
656}
657
658/* Function Name: DestroyGCs
659 * Description: removes all gcs for this widget.
660 * Arguments: w - the widget.
661 * Returns: none
662 */
663
664static void
665DestroyGCs(Widget w)
666{
667 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
668
669 XtReleaseGC(w, sblw->scroll.normal_gc);
670 XtReleaseGC(w, sblw->scroll.bold_gc);
671 XtReleaseGC(w, sblw->scroll.italic_gc);
672 XtReleaseGC(w, sblw->scroll.move_gc);
673}
674
675static void
676Realize(Widget w, Mask *valueMask, XSetWindowAttributes * attributes)
677{
678 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
679
680 CreateScrollbar(w);
681 CreateGCs(w);
682 Layout(w);
683 (*SuperClass->core_class.realize) (w, valueMask, attributes);
684 XtRealizeWidget(sblw->scroll.bar); /* realize scrollbar. */
685 XtMapWidget(sblw->scroll.bar)XMapWindow((((sblw->scroll.bar)->core.screen)->display
), ((sblw->scroll.bar)->core.window))
; /* map scrollbar. */
686
687 XtAddEventHandler(w, 0, TRUE1, GExpose, NULL((void*)0)); /* Get Graphics Exposures */
688} /* Realize */
689
690/* Function Name: Destroy
691 * Description: Cleans up when we are killed.
692 * Arguments: w - the widget.
693 * Returns: none
694 */
695
696static void
697Destroy(Widget w)
698{
699 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
700
701 if (sblw->scroll.bar != NULL((void*)0))
702 XtDestroyWidget(sblw->scroll.bar); /* Destroy scrollbar. */
703 if (sblw->scroll.file != NULL((void*)0))
704 fclose(sblw->scroll.file);
705 DestroyGCs(w);
706}
707
708/*
709 *
710 * Set Values
711 *
712 */
713
714/* ARGSUSED */
715static Boolean
716SetValuesHook(Widget w, ArgList args, Cardinal * num_args)
717{
718 Boolean ret = TRUE1;
719 Cardinal i;
720
721 for (i = 0; i < *num_args; i++) {
722 if (strcmp(XtNfile((char*)&XtStrings[194]), args[i].name) == 0) {
723 LoadFile(w);
724 ret = TRUE1;
725 }
726 }
727
728/*
729 * Changing anything else will have strange effects, I don't need it so
730 * I didn't code it.
731 */
732
733 return (ret);
734
735} /* Set Values */
736
737/*
738 * A little design philosophy is probably wise to include at this point.
739 *
740 * One of the things that I has hoped to achieve with xman is to make the
741 * viewing of manpage not only easy for the nieve user, but also fast for
742 * the experienced user, I wanted to be able to use it too. To achieve this
743 * I end up sacrificing a bit of start up time for the manual data structure.
744 * As well as, the overhead of reading the entire file before putting it up
745 * on the display. This is actually hardly even noticeable since most manual
746 * pages are shots, one to two pages - the notable exception is of course csh,
747 * but then that should be broken up anyway.
748 *
749 * METHOD:
750 *
751 * I allocate a chunk of space that is the size of the file, plus a null for
752 * debugging. Then copies the file into this chunk of memory. I then allocate
753 * an array of char*'s that are assigned to the beginning of each line. Yes,
754 * this means that I have to read the file twice, and could probably be more
755 * clever about it, but once it is in memory the second read is damn fast.
756 * There are a few obscurities here about guessing the number of lines and
757 * reallocing if I guess wrong, but other than that it is pretty straight
758 * forward.
759 *
760 * Chris Peterson
761 * 1/27/88
762 */
763
764#define ADD_MORE_MEM100 100 /* first guesses for allocations. */
765#define CHAR_PER_LINE40 40
766
767/* Function Name: LoadFile
768 * Description: Loads the current file into the internal memory.
769 * Arguments: w - the sblw.
770 * Returns: none
771 */
772
773static void
774LoadFile(Widget w)
775{
776 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
777 FILE *file = sblw->scroll.file;
778
779 char *page;
780 char **line_pointer, **top_line; /* pointers to beginnings of the
781 lines of the file. */
782 int nlines; /* the current number of allocated lines. */
783 struct stat fileinfo; /* file information from fstat. */
784
785 if (sblw->scroll.top_line != NULL((void*)0)) {
786 XtFree(*(sblw->scroll.top_line)); /* free characters. */
787 XtFree((char *) (sblw->scroll.top_line)); /* free lines. */
788 }
789 sblw->scroll.top_line = NULL((void*)0);
790
791 if (file == NULL((void*)0))
792 return;
793
794/*
795 * Get file size and allocate a chunk of memory for the file to be
796 * copied into.
797 */
798
799 if (fstat(fileno(file), &fileinfo))
800 XtAppError(XtWidgetToApplicationContext(w),
801 "SBLW LoadFile: Failure in fstat.");
802
803/*
804 * Allocate a space for a list of pointer to the beginning of each line.
805 */
806
807 if ((nlines = fileinfo.st_size / CHAR_PER_LINE40) == 0)
808 return;
809
810 page = XtMalloc(fileinfo.st_size + 1); /* leave space for the NULL */
811 top_line = line_pointer = (char **) XtMalloc(nlines * sizeof(char *));
812
813/*
814 * Copy the file into memory.
815 */
816
817 fseek(file, 0L, SEEK_SET0);
818 if (fread(page, sizeof(char), fileinfo.st_size, file) == 0)
819 XtAppError(XtWidgetToApplicationContext(w),
820 "SBLW LoadFile: Failure in fread.");
821
822/* put NULL at end of buffer. */
823
824 *(page + fileinfo.st_size) = '\0';
825
826/*
827 * Go through the file setting a line pointer to the character after each
828 * new line. If we run out of line pointer space then realloc that space
829 * with space for more lines.
830 */
831
832 *line_pointer++ = page; /* first line points to first char in buffer. */
833 while (*page != '\0') {
834
835 if (*page == '\n') {
836 *line_pointer++ = page + 1;
837
838 if (line_pointer >= top_line + nlines) {
839 top_line = (char **) XtRealloc((char *) top_line, (nlines +
840 ADD_MORE_MEM100)
841 * sizeof(char *));
842 line_pointer = top_line + nlines;
843 nlines += ADD_MORE_MEM100;
844 }
845 }
846 page++;
847 }
848
849/*
850 * Realloc the line pointer space to take only the minimum amount of memory
851 */
852
853 sblw->scroll.lines = nlines = line_pointer - top_line - 1;
854 top_line = (char **) XtRealloc((char *) top_line, nlines * sizeof(char *));
855
856/*
857 * Store the memory pointers
858 */
859
860 sblw->scroll.top_line = top_line;
861 sblw->scroll.line_pointer = 0;
862 SetThumbHeight(w);
863 SetThumb(w);
864}
865
866#define NLINES66 66 /* This is the number of lines to wait until
867 we boldify the line again, this allows
868 me to bold the first line of each page. */
869#define BACKSPACE010 010 /* I doubt you would want to change this. */
870
871#define NORMAL0 0
872#define BOLD1 1
873#define ITALIC2 2
874#define SYMBOL3 3
875#define WHICH(italic, bold)((bold) ? 1 : ((italic) ? 2 : 0)) ((bold) ? BOLD1 : ((italic) ? ITALIC2 : NORMAL0))
876 /* Choose BOLD over ITALICS. If neither */
877 /* is chosen, use NORMAL. */
878
879static int DumpText(Widget w, int x_loc, int y_loc, char *buf, int len,
880 int format);
881static Boolean Boldify(char *);
882
883/* Function Name: PrintText
884 * Description: This function actually prints the text.
885 * Arguments: w - the ScrollByLine widget.
886 * start_line - line to start printing,
887 * num_lines - the number of lines to print.
888 * location - the location to print the text.
889 * Returns: none.
890 */
891
892/* ARGSUSED */
893static void
894PrintText(Widget w, int start_line, int num_lines, int location)
895{
896 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
897
898 register char *bufp, *c; /* Generic char pointers */
899 int current_line; /* the number of the current line */
900 char buf[BUFSIZ1024]; /* Misc. characters */
901 Boolean italicflag = FALSE0; /* Print text in italics?? */
902 Boolean first = TRUE1; /* First line of a manual page??? */
903 int x_loc, y_loc; /* x and y location of text. */
904
905/*
906 * For table hack
907 * To get columns to line up reasonably in most cases, make the
908 * assumption that they were lined up using lots of spaces, where
909 * lots is greater than two. Use a space width of 70% of the
910 * widest character in the font.
911 */
912 int h_col, h_fix;
913 char *h_c;
914
915/*
916 * Nothing loaded, take no action.
917 */
918
919 if (sblw->scroll.top_line == NULL((void*)0) || num_lines == 0)
920 return;
921
922 current_line = start_line;
923
924/* Set the first character to print at the first line. */
925
926 c = *(sblw->scroll.top_line + start_line);
927
928/*
929 * Because XDrawString uses the bottom of the text as a position
930 * reference, add the height from the top of the font to the baseline
931 * to the ScollByLine position reference.
932 */
933
934 y_loc = location + sblw->scroll.normal_font->max_bounds.ascent;
935
936/*
937 * Ok, here's the more than mildly heuristic man page formatter.
938 * We put chars into buf until either a font change or newline
939 * occurs (at which time we flush it to the screen.)
940 */
941
942 bufp = buf;
943 x_loc = sblw->scroll.offset + sblw->scroll.indent;
944 h_col = 0;
945
946/*
947 * A fix:
948 * Assume that we are always starting to print on or before the
949 * first line of a page, and then prove it if we aren't.
950 */
951 for (h_fix = 1; h_fix <= (start_line % NLINES66); h_fix++)
952 if (**(sblw->scroll.top_line + start_line - h_fix) != '\n') {
953 first = FALSE0;
954 break;
955 }
956
957 while (TRUE1) {
958 if (current_line % NLINES66 == 0)
959 first = TRUE1;
960
961/*
962 * Lets make sure that we do not run out of space in our buffer, making full
963 * use of it is not critical since no window will be wide enough to display
964 * nearly BUFSIZ characters.
965 */
966
967 if ((bufp - buf) > (BUFSIZ1024 - 10))
968 /* Toss everything until we find a <CR> or the end of the buffer. */
969 while ((*c != '\n') && (*c != '\0'))
970 c++;
971
972 switch (*c) {
973
974 case '\0': /* If we reach the end of the file then return */
975 DumpText(w, x_loc, y_loc, buf, bufp - buf,
976 WHICH(italicflag, first)((first) ? 1 : ((italicflag) ? 2 : 0)));
977 return;
978
979 case '\n':
980 if (bufp != buf) {
981 Boolean bold;
982
983 *bufp = '\0'; /* for Boldify. */
984 bold = ((first) || ((x_loc == (sblw->scroll.offset +
985 sblw->scroll.indent)) &&
986 Boldify(buf)));
987
988 (void) DumpText(w, x_loc, y_loc, buf, bufp - buf,
989 WHICH(italicflag, bold)((bold) ? 1 : ((italicflag) ? 2 : 0)));
990
991 if (bold)
992 first = FALSE0;
993 }
994
995/*
996 * If we have painted the required number of lines then we should now return.
997 */
998 if (++current_line == start_line + num_lines)
999 return;
1000
1001 bufp = buf;
1002 italicflag = FALSE0;
1003 x_loc = sblw->scroll.offset + sblw->scroll.indent;
1004 h_col = 0;
1005 y_loc += sblw->scroll.font_height;
1006 break;
1007
1008/*
1009 * This tab handling code is not very clever it moves the cursor over
1010 * to the next boundary of eight (8) spaces, as calculated in width just
1011 * before the printing loop started.
1012 */
1013
1014 case '\t': /* TAB */
1015 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
Value stored to 'x_loc' is never read
1016 WHICH(italicflag, first)((first) ? 1 : ((italicflag) ? 2 : 0)));
1017 h_col += bufp - buf;
1018 bufp = buf;
1019 italicflag = FALSE0;
1020 x_loc = sblw->scroll.offset + sblw->scroll.indent;
1021 h_col = h_col + 8 - (h_col % 8);
1022 x_loc += sblw->scroll.h_width * h_col;
1023 break;
1024
1025 case ' ':
1026 h_c = c + 1;
1027 while (*h_c == ' ')
1028 h_c++;
1029
1030 if (h_c - c < 4) {
1031 *bufp++ = *c;
1032 break;
1033 }
1034
1035 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
1036 WHICH(italicflag, first)((first) ? 1 : ((italicflag) ? 2 : 0)));
1037 h_col += bufp - buf;
1038 bufp = buf;
1039 italicflag = FALSE0;
1040
1041 x_loc = sblw->scroll.offset + sblw->scroll.indent;
1042 h_col += (h_c - c);
1043 x_loc += sblw->scroll.h_width * h_col;
1044 c = h_c - 1;
1045 break;
1046
1047 case '\033': /* ignore esc sequences for now */
1048 c++; /* should always be esc-x */
1049 break;
1050
1051/*
1052 * Overstrike code supplied by: cs.utexas.edu!ut-emx!clyde@rutgers.edu
1053 * Since my manual pages do not have overstrike I couldn't test this.
1054 */
1055
1056 case BACKSPACE010: /* Backspacing for nroff bolding */
1057 if (c[-1] == c[1] && c[1] != BACKSPACE010) { /* overstriking one char */
1058 if (bufp > buf) {
1059 bufp--; /* Zap 1st instance of char to bolden */
1060 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
1061 WHICH(italicflag, FALSE)((0) ? 1 : ((italicflag) ? 2 : 0)));
1062 h_col += bufp - buf;
1063 }
1064 bufp = buf;
1065 *bufp++ = c[1];
1066 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf, BOLD1);
1067 h_col += bufp - buf;
1068 bufp = buf;
1069 first = FALSE0;
1070
1071 /*
1072 * Nroff bolding looks like:
1073 * C\bC\bC\bCN...
1074 * c points to ----^ ^
1075 * it needs to point to --^
1076 */
1077 while (*c == BACKSPACE010 && c[-1] == c[1])
1078 c += 2;
1079 c--; /* Back up to previous char */
1080 }
1081 else {
1082 if ((c[-1] == 'o' && c[1] == '+') /* Nroff bullet */
1083 ||(c[-1] == '+' && c[1] == 'o')) { /* Nroff bullet */
1084 /* If we run into a bullet, print out */
1085 /* everything that's accumulated to this */
1086 /* point, then the bullet, then resume. */
1087 if (bufp > buf) {
1088 bufp--;
1089 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
1090 WHICH(italicflag, FALSE)((0) ? 1 : ((italicflag) ? 2 : 0)));
1091 h_col += bufp - buf;
1092 }
1093 bufp = buf;
1094 *bufp = (char) 183;
1095 x_loc = DumpText(w, x_loc, y_loc, buf, 1, SYMBOL3);
1096 h_col++;
1097 c++;
1098 }
1099 else { /* 'real' backspace - back up output ptr */
1100 if (bufp > buf)
1101 bufp--;
1102 }
1103 }
1104 break;
1105
1106/* End of contributed overstrike code. */
1107
1108 case '_': /* look for underlining [italicize] */
1109 if (*(c + 1) == BACKSPACE010) {
1110 if (!italicflag) { /* font change? */
1111 if (bufp != buf) {
1112 x_loc =
1113 DumpText(w, x_loc, y_loc, buf, bufp - buf, NORMAL0);
1114 h_col += bufp - buf;
1115 bufp = buf;
1116 }
1117 italicflag = TRUE1;
1118 }
1119 c += 2;
1120 *bufp++ = *c;
1121 break;
1122 }
1123 /* else fall through to default, because this was a real underscore. */
1124
1125 default:
1126 if (italicflag) { /* font change? */
1127 if (bufp != buf) {
1128 x_loc = DumpText(w, x_loc, y_loc, buf, bufp - buf,
1129 WHICH(italicflag, FALSE)((0) ? 1 : ((italicflag) ? 2 : 0)));
1130 h_col += bufp - buf;
1131 bufp = buf;
1132 }
1133 italicflag = FALSE0;
1134 }
1135 *bufp++ = *c;
1136 break;
1137 }
1138 c++;
1139 }
1140}
1141
1142/* Function Name: DumpText
1143 * Description: Dumps text to the screen.
1144 * Arguments: w - the widget.
1145 * x_loc - to dump text at.
1146 * y_loc - the y_location to draw_text.
1147 * buf - buffer to dump.
1148 * italic, bold, boolean that tells us which gc to use.
1149 * Returns: x_location of the end of the text.
1150 */
1151
1152static int
1153DumpText(Widget w, int x_loc, int y_loc, char *buf, int len, int format)
1154{
1155 ScrollByLineWidget sblw = (ScrollByLineWidget) w;
1156 GC gc;
1157 XFontStruct *font;
1158
1159 switch (format) {
1160
1161 case ITALIC2:
1162 gc = sblw->scroll.italic_gc;
1163 font = sblw->scroll.italic_font;
1164 break;
1165
1166 case BOLD1:
1167 gc = sblw->scroll.bold_gc;
1168 font = sblw->scroll.bold_font;
1169 break;
1170
1171 case SYMBOL3:
1172 gc = sblw->scroll.symbol_gc;
1173 font = sblw->scroll.symbol_font;
1174 break;
1175
1176 default:
1177 gc = sblw->scroll.normal_gc;
1178 font = sblw->scroll.normal_font;
1179 break;
1180 }
1181
1182 XDrawString(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), gc, x_loc, y_loc, buf, len);
1183 return (x_loc + XTextWidth(font, buf, len));
1184}
1185
1186/* Function Name: Boldify
1187 * Description: look for keyword.
1188 * Arguments: sp - string pointer.
1189 * Returns: 1 if keyword else 0.
1190 */
1191
1192static Boolean
1193Boldify(register char *sp)
1194{
1195 register char *sp_pointer;
1196 int length, count;
1197
1198/*
1199 * If there are not lower case letters in the line the assume it is a
1200 * keyword and boldify it in PrintManpage.
1201 */
1202
1203 length = strlen(sp);
1204 for (sp_pointer = sp, count = 0; count < length; sp_pointer++, count++)
1205 if (!isupper(*sp_pointer) && !isspace(*sp_pointer))
1206 return (0);
1207 return (1);
1208}
1209
1210#undef superclass
1211#undef SuperClass