1 | #ifndef lint |
---|
2 | static char rcsid[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/xmore/ScrollByLine.c,v 1.1 1988-05-24 14:04:40 kit Exp $"; |
---|
3 | #endif lint |
---|
4 | |
---|
5 | /* |
---|
6 | * ScrollByLine.c - This creates a widget the will text to |
---|
7 | * be scrolled vertically. |
---|
8 | * |
---|
9 | * Author: Chris Peterson |
---|
10 | * M. I. T. Project Athena. |
---|
11 | * Cambridge, Mass. |
---|
12 | * Date: 12/5/87 |
---|
13 | * |
---|
14 | */ |
---|
15 | |
---|
16 | /* |
---|
17 | * I wrote this widget before I knew what form did, and it shows, since |
---|
18 | * the "right" way to do this widget would be to subclass it to form, |
---|
19 | * and do it much more like the Viewport widget in the Athena widget set. |
---|
20 | * But this works and time is short, so here it is. |
---|
21 | * |
---|
22 | * Chris Peterson 1/30/88 |
---|
23 | */ |
---|
24 | |
---|
25 | /* |
---|
26 | * There is a horizontal scrollbar somewhat coded into this widget, the |
---|
27 | * layout function should be fine with the current horizontal code, (RIGHT!) |
---|
28 | * |
---|
29 | * But I didn't really sit down and figure out what horizontal scrolling meant |
---|
30 | * for this widget, as it displays the stuff by line. |
---|
31 | * |
---|
32 | * Any brilliant Ideas? |
---|
33 | */ |
---|
34 | |
---|
35 | #include <X11/IntrinsicP.h> |
---|
36 | #include "ScrollByLine.h" |
---|
37 | #include "ScrollByLineP.h" |
---|
38 | #include <X11/Scroll.h> |
---|
39 | #include <X11/Atoms.h> |
---|
40 | #include <X11/Misc.h> |
---|
41 | |
---|
42 | /* Default Translation Table */ |
---|
43 | |
---|
44 | static char defaultTranslations[] = |
---|
45 | "<Btn1Down>: Page(Forward) \n\ |
---|
46 | <Btn3Down>: Page(Back) \n\ |
---|
47 | <Key>f: Page(Forward) \n\ |
---|
48 | <Key>b: Page(Back) \n\ |
---|
49 | <Key>\\ : Page(Forward)"; |
---|
50 | |
---|
51 | |
---|
52 | /**************************************************************** |
---|
53 | * |
---|
54 | * ScrollByLine Resources |
---|
55 | * |
---|
56 | ****************************************************************/ |
---|
57 | |
---|
58 | static XtResource resources[] = { |
---|
59 | {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), |
---|
60 | XtOffset(ScrollByLineWidget, scroll_by_line.foreground), |
---|
61 | XtRString, "Black"}, |
---|
62 | {XtNinnerWidth, XtCWidth, XtRInt, sizeof(int), |
---|
63 | XtOffset(ScrollByLineWidget, scroll_by_line.inner_width), |
---|
64 | XtRString, "100"}, |
---|
65 | {XtNinnerHeight, XtCHeight, XtRInt, sizeof(int), |
---|
66 | XtOffset(ScrollByLineWidget, scroll_by_line.inner_height), |
---|
67 | XtRString, "100"}, |
---|
68 | {XtNforceBars, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
69 | XtOffset(ScrollByLineWidget, scroll_by_line.force_bars), |
---|
70 | XtRString, "FALSE"}, |
---|
71 | {XtNallowHoriz, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
72 | XtOffset(ScrollByLineWidget, scroll_by_line.allow_horiz), |
---|
73 | XtRString, "FALSE"}, |
---|
74 | {XtNallowVert, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
75 | XtOffset(ScrollByLineWidget, scroll_by_line.allow_vert), |
---|
76 | XtRString, "FALSE"}, |
---|
77 | {XtNuseBottom, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
78 | XtOffset(ScrollByLineWidget, scroll_by_line.use_bottom), |
---|
79 | XtRString, "FALSE"}, |
---|
80 | {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
81 | XtOffset(ScrollByLineWidget, scroll_by_line.use_right), |
---|
82 | XtRString, "FALSE"}, |
---|
83 | {XtNlines, XtCLine, XtRInt, sizeof(int), |
---|
84 | XtOffset(ScrollByLineWidget, scroll_by_line.lines), |
---|
85 | XtRString, "0"}, |
---|
86 | {XtNfontHeight, XtCHeight,XtRInt, sizeof(int), |
---|
87 | XtOffset(ScrollByLineWidget, scroll_by_line.font_height), |
---|
88 | XtRString, "0"}, |
---|
89 | {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t), |
---|
90 | XtOffset(ScrollByLineWidget, scroll_by_line.callbacks), |
---|
91 | XtRString, "NULL"}, |
---|
92 | {XtNformOnInner, XtCBoolean, XtRBoolean, sizeof(Boolean), |
---|
93 | XtOffset(ScrollByLineWidget, scroll_by_line.key), |
---|
94 | XtRString, "FALSE"}, |
---|
95 | }; |
---|
96 | |
---|
97 | /**************************************************************** |
---|
98 | * |
---|
99 | * Full class record constant |
---|
100 | * |
---|
101 | ****************************************************************/ |
---|
102 | |
---|
103 | static void HorizontalThumb(); |
---|
104 | static Boolean ScrollVerticalText(); |
---|
105 | static void VerticalThumb(); |
---|
106 | static void HorizontalScroll(); |
---|
107 | static void VerticalScroll(); |
---|
108 | static void Page(); |
---|
109 | static void InitializeHook(); |
---|
110 | static void Realize(); |
---|
111 | static void Resize(); |
---|
112 | static void ResetThumb(); |
---|
113 | static void Redisplay(); |
---|
114 | static void ChildExpose(); |
---|
115 | static Boolean SetValues(); |
---|
116 | static int MergeArglists(); |
---|
117 | static Boolean Layout(); |
---|
118 | static XtGeometryResult GeometryManager(); |
---|
119 | static void ChangeManaged(); |
---|
120 | static void ClassInitialize(); |
---|
121 | |
---|
122 | static XtActionsRec actions[] = { |
---|
123 | { "Page", Page}, |
---|
124 | { NULL, NULL}, |
---|
125 | }; |
---|
126 | |
---|
127 | ScrollByLineClassRec scrollByLineClassRec = { |
---|
128 | { |
---|
129 | /* core_class fields */ |
---|
130 | /* superclass */ (WidgetClass) &compositeClassRec, |
---|
131 | /* class_name */ "ScrollByLine", |
---|
132 | /* widget_size */ sizeof(ScrollByLineRec), |
---|
133 | /* class_initialize */ ClassInitialize, |
---|
134 | /* class_part_init */ NULL, |
---|
135 | /* class_inited */ FALSE, |
---|
136 | /* initialize */ NULL, |
---|
137 | /* initialize_hook */ InitializeHook, |
---|
138 | /* realize */ Realize, |
---|
139 | /* actions */ actions, |
---|
140 | /* num_actions */ XtNumber(actions), |
---|
141 | /* resources */ resources, |
---|
142 | /* num_resources */ XtNumber(resources), |
---|
143 | /* xrm_class */ NULLQUARK, |
---|
144 | /* compress_motion */ TRUE, |
---|
145 | /* compress_exposure */ FALSE, |
---|
146 | /* compress_enterleave*/ TRUE, |
---|
147 | /* visible_interest */ FALSE, |
---|
148 | /* destroy */ NULL, |
---|
149 | /* resize */ Resize, |
---|
150 | /* expose */ Redisplay, |
---|
151 | /* set_values */ SetValues, |
---|
152 | /* set_values_hook */ NULL, |
---|
153 | /* set_values_almost */ XtInheritSetValuesAlmost, |
---|
154 | /* get_values_hook */ NULL, |
---|
155 | /* accept_focus */ NULL, |
---|
156 | /* version */ XtVersion, |
---|
157 | /* callback_private */ NULL, |
---|
158 | /* tm_table */ defaultTranslations, |
---|
159 | },{ |
---|
160 | /* composite_class fields */ |
---|
161 | /* geometry_manager */ GeometryManager, |
---|
162 | /* change_managed */ ChangeManaged, |
---|
163 | /* insert_child */ NULL, /* Inherit from superclass */ |
---|
164 | /* delete_child */ NULL, /* Inherit from superclass */ |
---|
165 | /* move_focus_to_next */ NULL, |
---|
166 | /* move_focus_to_prev */ NULL |
---|
167 | },{ |
---|
168 | /* mumble */ 0 /* Make C compiler happy */ |
---|
169 | } |
---|
170 | }; |
---|
171 | |
---|
172 | WidgetClass scrollByLineWidgetClass = |
---|
173 | (WidgetClass) &scrollByLineClassRec; |
---|
174 | |
---|
175 | |
---|
176 | /**************************************************************** |
---|
177 | * |
---|
178 | * Private Routines |
---|
179 | * |
---|
180 | ****************************************************************/ |
---|
181 | |
---|
182 | /* Function Name: ClassInitialize |
---|
183 | * Description: Used to initialize this class of widgets. |
---|
184 | * Arguments: none. |
---|
185 | * Returns: none. |
---|
186 | */ |
---|
187 | |
---|
188 | static void ClassInitialize() |
---|
189 | { |
---|
190 | CompositeWidgetClass superclass; |
---|
191 | ScrollByLineWidgetClass myclass; |
---|
192 | |
---|
193 | myclass = (ScrollByLineWidgetClass) scrollByLineWidgetClass; |
---|
194 | superclass = (CompositeWidgetClass) myclass->core_class.superclass; |
---|
195 | |
---|
196 | /* Inherit insert_child and delete_child from Composite */ |
---|
197 | myclass->composite_class.insert_child = |
---|
198 | superclass->composite_class.insert_child; |
---|
199 | myclass->composite_class.delete_child = |
---|
200 | superclass->composite_class.delete_child; |
---|
201 | } |
---|
202 | |
---|
203 | /* Function Name: Layout |
---|
204 | * Description: This function lays out the scroll_by_line widget. |
---|
205 | * Arguments: w - the scroll_by_line widget. |
---|
206 | * Returns: TRUE if successful. |
---|
207 | */ |
---|
208 | |
---|
209 | static Boolean |
---|
210 | Layout(w,key) |
---|
211 | Widget w; |
---|
212 | int key; |
---|
213 | { |
---|
214 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; |
---|
215 | Dimension width,height; /* The size that the widget would like to be */ |
---|
216 | XtGeometryResult answer; /* the answer from the parent. */ |
---|
217 | Widget hbar,vbar,child; /* The three children of this |
---|
218 | scrolled widget. */ |
---|
219 | int vbar_x,vbar_y; /* The locations of the various elements. */ |
---|
220 | int hbar_x,hbar_y; |
---|
221 | int child_x,child_y; |
---|
222 | int c_width,c_height; |
---|
223 | Boolean make_bar; |
---|
224 | |
---|
225 | vbar = sblw->composite.children[0]; |
---|
226 | hbar = sblw->composite.children[1]; |
---|
227 | child = sblw->composite.children[2]; |
---|
228 | height = sblw->core.height; |
---|
229 | width = sblw->core.width; |
---|
230 | |
---|
231 | /* set the initial scroll bar positions. */ |
---|
232 | |
---|
233 | vbar_x = vbar_y = 0; |
---|
234 | hbar_x = hbar_y = 0; |
---|
235 | |
---|
236 | /* Should I allow the vertical scrollbar to be seen */ |
---|
237 | |
---|
238 | make_bar = FALSE; |
---|
239 | if ( (!key) && (sblw->scroll_by_line.lines * |
---|
240 | sblw->scroll_by_line.font_height > height) ) |
---|
241 | make_bar = TRUE; |
---|
242 | |
---|
243 | else if ( (key) && (sblw->scroll_by_line.lines * |
---|
244 | sblw->scroll_by_line.font_height > child->core.height) ) |
---|
245 | make_bar = TRUE; |
---|
246 | |
---|
247 | if (sblw->scroll_by_line.allow_vert && (sblw->scroll_by_line.force_bars || |
---|
248 | make_bar) ) { |
---|
249 | /* |
---|
250 | * Resize the outer window to fit the child, or visa versa. Also make scroll |
---|
251 | * bar become placed in the correct location. |
---|
252 | */ |
---|
253 | if (key) |
---|
254 | width = child->core.width + vbar->core.width + |
---|
255 | 2 * vbar->core.border_width; |
---|
256 | else |
---|
257 | c_width = width - vbar->core.width -2 * vbar->core.border_width; |
---|
258 | |
---|
259 | /* Put Scrollbar on right side if scrolled window? */ |
---|
260 | |
---|
261 | if (sblw->scroll_by_line.use_right) { |
---|
262 | vbar_x = width - vbar->core.width - 2 * vbar->core.border_width; |
---|
263 | child_x = 0; |
---|
264 | } |
---|
265 | else { |
---|
266 | child_x = vbar->core.width + 2 * vbar->core.border_width; |
---|
267 | vbar_x = 0; |
---|
268 | } |
---|
269 | } |
---|
270 | else { |
---|
271 | /* Make the scroll bar dissappear, note how scroll bar is always there, |
---|
272 | sometimes it is just that we cannot see them. */ |
---|
273 | vbar_x = - vbar->core.width - 10; |
---|
274 | child_x = 0; |
---|
275 | if (key) |
---|
276 | width = child->core.width; |
---|
277 | else |
---|
278 | c_width = width; |
---|
279 | } |
---|
280 | |
---|
281 | /* set the horizontal bar position. */ |
---|
282 | |
---|
283 | /* should we allow the horiz. scroll bar. */ |
---|
284 | |
---|
285 | if (sblw->scroll_by_line.allow_horiz && (child->core.width >= width || |
---|
286 | sblw->scroll_by_line.force_bars)) { |
---|
287 | if (key) |
---|
288 | height = child->core.height + hbar->core.height + |
---|
289 | 2 * hbar->core.border_width; |
---|
290 | else |
---|
291 | c_height = height - hbar->core.height - 2 * hbar->core.border_width; |
---|
292 | |
---|
293 | hbar_x = child_x; |
---|
294 | |
---|
295 | /* Should we put the scroll bar on the bottom?? */ |
---|
296 | |
---|
297 | if (sblw->scroll_by_line.use_bottom) { |
---|
298 | hbar_y = height - hbar->core.height - 2 * hbar->core.border_width; |
---|
299 | child_y = 0; |
---|
300 | } |
---|
301 | else { |
---|
302 | child_y = hbar->core.height + 2 * hbar->core.border_width; |
---|
303 | vbar_y = child_y; |
---|
304 | hbar_y = 0; |
---|
305 | } |
---|
306 | } |
---|
307 | else { |
---|
308 | /* make this scroll bar disappear. */ |
---|
309 | hbar_y = - hbar->core.height - 10; |
---|
310 | child_y = 0; |
---|
311 | if (key) |
---|
312 | height = child->core.height; |
---|
313 | else |
---|
314 | c_height = height; |
---|
315 | } |
---|
316 | |
---|
317 | /* if the windows are realized we have to move them. */ |
---|
318 | |
---|
319 | if (XtIsRealized( (Widget) sblw)) { |
---|
320 | XtMoveWidget(hbar,hbar_x,hbar_y); |
---|
321 | XtMoveWidget(vbar,vbar_x,vbar_y); |
---|
322 | XtMoveWidget(child,child_x,child_y); |
---|
323 | |
---|
324 | /* resize the children to be the correct height or width. */ |
---|
325 | |
---|
326 | XtResizeWidget(vbar,vbar->core.width,height - |
---|
327 | 2 * vbar->core.border_width - vbar_y, |
---|
328 | vbar->core.border_width); |
---|
329 | |
---|
330 | XtResizeWidget(hbar,width - hbar_x - |
---|
331 | 2 * hbar->core.border_width, |
---|
332 | hbar->core.height,hbar->core.border_width); |
---|
333 | |
---|
334 | if (!key) |
---|
335 | XtResizeWidget(child, (Cardinal) c_width, (Cardinal) c_height, |
---|
336 | child->core.border_width); |
---|
337 | |
---|
338 | } |
---|
339 | /* |
---|
340 | * If they are not realized we do not need to move them then just set their |
---|
341 | * core values, this saves a bit of time. |
---|
342 | */ |
---|
343 | else { |
---|
344 | hbar->core.x = hbar_x; |
---|
345 | hbar->core.y = hbar_y; |
---|
346 | vbar->core.x = vbar_x; |
---|
347 | vbar->core.y = vbar_y; |
---|
348 | child->core.x = child_x; |
---|
349 | child->core.y = child_y; |
---|
350 | |
---|
351 | /* resize the scrollbars to be the correct height or width. */ |
---|
352 | |
---|
353 | XtResizeWidget(vbar,vbar->core.width,height - |
---|
354 | 2 * vbar->core.border_width - vbar_y, |
---|
355 | vbar->core.border_width); |
---|
356 | |
---|
357 | XtResizeWidget(hbar,width - hbar_x - |
---|
358 | 2 * hbar->core.border_width, |
---|
359 | hbar->core.height,hbar->core.border_width); |
---|
360 | |
---|
361 | if (!key) { |
---|
362 | child->core.width = c_width; |
---|
363 | child->core.height = c_height; |
---|
364 | } |
---|
365 | } |
---|
366 | |
---|
367 | height = height; |
---|
368 | width = width; |
---|
369 | |
---|
370 | /* set the thumb size to be correct. */ |
---|
371 | |
---|
372 | ResetThumb( (Widget) sblw); |
---|
373 | |
---|
374 | answer = XtMakeResizeRequest( (Widget) sblw, width, height, &width, &height); |
---|
375 | |
---|
376 | switch(answer) { |
---|
377 | case XtGeometryYes: |
---|
378 | break; |
---|
379 | case XtGeometryNo: |
---|
380 | return(FALSE); |
---|
381 | case XtGeometryAlmost: |
---|
382 | (void) Layout( (Widget) sblw,FALSE); |
---|
383 | } |
---|
384 | return(TRUE); |
---|
385 | } |
---|
386 | |
---|
387 | /* Function Name: ResetThumb |
---|
388 | * Description: This function resets the thumb's shown percentage only. |
---|
389 | * Arguments: w - the ScrollByLineWidget. |
---|
390 | * Returns: none; |
---|
391 | */ |
---|
392 | |
---|
393 | static void |
---|
394 | ResetThumb(w) |
---|
395 | Widget w; |
---|
396 | { |
---|
397 | float shown; |
---|
398 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; |
---|
399 | Widget child,vbar,hbar; |
---|
400 | |
---|
401 | vbar = sblw->composite.children[0]; |
---|
402 | hbar = sblw->composite.children[1]; |
---|
403 | child = sblw->composite.children[2]; |
---|
404 | |
---|
405 | /* vertical */ |
---|
406 | |
---|
407 | shown = (float) child->core.height /(float) (sblw->scroll_by_line.lines * |
---|
408 | sblw->scroll_by_line.font_height); |
---|
409 | if (shown > 1.0) |
---|
410 | shown = 1.0; |
---|
411 | |
---|
412 | XtScrollBarSetThumb( vbar, (float) -1, shown ); |
---|
413 | |
---|
414 | /* horizontal */ |
---|
415 | |
---|
416 | shown = (float) child->core.width / (float) child->core.width; |
---|
417 | XtScrollBarSetThumb( hbar, (float) -1, shown ); |
---|
418 | } |
---|
419 | |
---|
420 | /* |
---|
421 | * |
---|
422 | * Geometry Manager - If the height of width is changed then try a new layout. |
---|
423 | * else dissallow the requwest. |
---|
424 | * |
---|
425 | */ |
---|
426 | |
---|
427 | /*ARGSUSED*/ |
---|
428 | static XtGeometryResult GeometryManager(w, request, reply) |
---|
429 | Widget w; |
---|
430 | XtWidgetGeometry *request; |
---|
431 | XtWidgetGeometry *reply; /* RETURN */ |
---|
432 | |
---|
433 | { |
---|
434 | ScrollByLineWidget sblw; |
---|
435 | |
---|
436 | sblw = (ScrollByLineWidget) w->core.parent; |
---|
437 | if ( request->width != 0 && request->height != 0 && |
---|
438 | (request->request_mode && (CWWidth || CWHeight)) ) { |
---|
439 | w->core.height = request->height; |
---|
440 | w->core.width = request->width; |
---|
441 | (void) Layout( (Widget) sblw,TRUE); |
---|
442 | return(XtGeometryYes); |
---|
443 | } |
---|
444 | return(XtGeometryNo); |
---|
445 | |
---|
446 | } /* Geometery Manager */ |
---|
447 | |
---|
448 | /* ARGSUSED */ |
---|
449 | static void ChildExpose(w,junk,event) |
---|
450 | Widget w; |
---|
451 | caddr_t junk; |
---|
452 | XEvent *event; |
---|
453 | { |
---|
454 | |
---|
455 | /* |
---|
456 | * since we are realy concerned with the expose events that happen |
---|
457 | * to the child, we have selected expose events on this window, and |
---|
458 | * then I call the redisplay routine. |
---|
459 | */ |
---|
460 | |
---|
461 | Redisplay(w->core.parent,event); |
---|
462 | } /* ChildExpose */ |
---|
463 | |
---|
464 | /* |
---|
465 | * Repaint the widget's child Window Widget. |
---|
466 | */ |
---|
467 | |
---|
468 | /* ARGSUSED */ |
---|
469 | static void Redisplay(w, event) |
---|
470 | Widget w; |
---|
471 | XEvent *event; |
---|
472 | { |
---|
473 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; |
---|
474 | |
---|
475 | int top,bottom; /* the locations of the top and |
---|
476 | bottom of the region that needs to be |
---|
477 | repainted. */ |
---|
478 | ScrollByLineStruct * sblw_struct; |
---|
479 | |
---|
480 | sblw_struct = (ScrollByLineStruct *) malloc(sizeof(ScrollByLineStruct)); |
---|
481 | |
---|
482 | /* |
---|
483 | * This routine tells the client which sections of the window to |
---|
484 | * repaint in his callback function which does the actual repainting. |
---|
485 | */ |
---|
486 | |
---|
487 | if (event->type == Expose) { |
---|
488 | top = event->xexpose.y; |
---|
489 | bottom = event->xexpose.height + top; |
---|
490 | } |
---|
491 | else { |
---|
492 | top = event->xgraphicsexpose.y; |
---|
493 | bottom = event->xgraphicsexpose.height + top; |
---|
494 | } |
---|
495 | |
---|
496 | sblw_struct->start_line = top / sblw->scroll_by_line.font_height + |
---|
497 | sblw->scroll_by_line.line_pointer; |
---|
498 | /* |
---|
499 | * If an expose event is called on a region that has no text assoicated |
---|
500 | * with it then do not redisplay. Only nescessary for very short file. |
---|
501 | */ |
---|
502 | if (sblw_struct->start_line > sblw->scroll_by_line.lines) |
---|
503 | return; |
---|
504 | sblw_struct->num_lines = (bottom - top) / |
---|
505 | sblw->scroll_by_line.font_height + 1; |
---|
506 | sblw_struct->location = top / sblw->scroll_by_line.font_height * |
---|
507 | sblw->scroll_by_line.font_height; |
---|
508 | |
---|
509 | XtCallCallbacks( (Widget) sblw, XtNcallback, (caddr_t) sblw_struct); |
---|
510 | |
---|
511 | free(sblw_struct); |
---|
512 | |
---|
513 | } /* redisplay (expose) */ |
---|
514 | |
---|
515 | static void |
---|
516 | Resize(w) |
---|
517 | Widget w; |
---|
518 | { |
---|
519 | |
---|
520 | (void) Layout(w,FALSE); |
---|
521 | |
---|
522 | } /* Resize */ |
---|
523 | |
---|
524 | static void ChangeManaged(w) |
---|
525 | Widget w; |
---|
526 | { |
---|
527 | /* note how we ignore bonus children, but since we control all children, |
---|
528 | there should never be a problem anyway. */ |
---|
529 | ScrollByLineWidget sblw = (ScrollByLineWidget) w;; |
---|
530 | |
---|
531 | if (sblw->composite.num_children == 3) { |
---|
532 | (void) Layout( w,sblw->scroll_by_line.key); |
---|
533 | } |
---|
534 | |
---|
535 | } /* Change Managed */ |
---|
536 | |
---|
537 | /* Function Name: Page |
---|
538 | * Description: This function pages the widget, by the amount it recieves |
---|
539 | * from the translation Manager. |
---|
540 | * Arguments: w - the ScrollByLineWidget. |
---|
541 | * event - the event that caused this return. |
---|
542 | * params - the parameters passed to it. |
---|
543 | * num_params - the number of parameters. |
---|
544 | * Returns: none. |
---|
545 | */ |
---|
546 | |
---|
547 | static void |
---|
548 | Page(w, event, params, num_params) |
---|
549 | Widget w; |
---|
550 | XEvent * event; |
---|
551 | String * params; |
---|
552 | Cardinal *num_params; |
---|
553 | { |
---|
554 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; |
---|
555 | Widget vbar = sblw->composite.children[0]; |
---|
556 | char direction; |
---|
557 | |
---|
558 | if (*num_params > 0) |
---|
559 | direction = *params[0]; |
---|
560 | else |
---|
561 | return; |
---|
562 | |
---|
563 | /* |
---|
564 | * If no scroll bar is visible then do not page, as the entire window is shown, |
---|
565 | * of scrolling has been turned off. |
---|
566 | */ |
---|
567 | |
---|
568 | if (vbar->core.x < 0) |
---|
569 | return; |
---|
570 | |
---|
571 | switch ( direction ) { |
---|
572 | case 'f': |
---|
573 | case 'F': |
---|
574 | /* move one page forward */ |
---|
575 | VerticalScroll(vbar,NULL, (int) vbar->core.height); |
---|
576 | break; |
---|
577 | case 'b': |
---|
578 | case 'B': |
---|
579 | /* move one page backward */ |
---|
580 | VerticalScroll(vbar,NULL, (int) - vbar->core.height); |
---|
581 | break; |
---|
582 | case 'L': |
---|
583 | case 'l': |
---|
584 | /* move one line forward */ |
---|
585 | VerticalScroll(vbar,NULL, (int) sblw->scroll_by_line.font_height); |
---|
586 | break; |
---|
587 | default: |
---|
588 | return; |
---|
589 | } |
---|
590 | } |
---|
591 | |
---|
592 | /* Function Name: ScrollVerticalText |
---|
593 | * Description: This accomplished the actual movement of the text. |
---|
594 | * Arguments: w - the ScrollByLine Widget. |
---|
595 | * new_line - the new location for the line pointer |
---|
596 | * force_redisplay - should we force this window to get |
---|
597 | * redisplayed? |
---|
598 | * Returns: True if the thumb needs to be moved. |
---|
599 | */ |
---|
600 | |
---|
601 | static Boolean |
---|
602 | ScrollVerticalText(w,new_line,force_redisp) |
---|
603 | Widget w; |
---|
604 | int new_line; |
---|
605 | Boolean force_redisp; |
---|
606 | { |
---|
607 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; |
---|
608 | int max_lines, /* The location of top of the last screen. */ |
---|
609 | num_lines, /* The number of lines in one screen of text */ |
---|
610 | y_pos, /* The location to start displaying text. */ |
---|
611 | num_lines_disp, /* The number of lines to display. */ |
---|
612 | start_line, /* The line to start displaying text. */ |
---|
613 | y_location, /* The y_location to for storing copy area. */ |
---|
614 | lines_to_move; /* The number of lines to copy. */ |
---|
615 | GC gc; |
---|
616 | Widget child,vbar; /* Widgets. */ |
---|
617 | ScrollByLineStruct * sblw_struct; |
---|
618 | Boolean move_thumb = FALSE; |
---|
619 | |
---|
620 | child = sblw->composite.children[2]; |
---|
621 | vbar = sblw->composite.children[0]; |
---|
622 | |
---|
623 | num_lines = child->core.height / sblw->scroll_by_line.font_height; |
---|
624 | |
---|
625 | gc = XCreateGC(XtDisplay( (Widget) sblw),XtWindow(child),NULL,0); |
---|
626 | XSetGraphicsExposures(XtDisplay( (Widget) sblw),gc,TRUE); |
---|
627 | |
---|
628 | /* do not let the window extend out of bounds */ |
---|
629 | |
---|
630 | if ( new_line < 0) { |
---|
631 | move_thumb = TRUE; |
---|
632 | new_line = 0; |
---|
633 | } |
---|
634 | else { |
---|
635 | max_lines = sblw->scroll_by_line.lines - |
---|
636 | child->core.height / sblw->scroll_by_line.font_height; |
---|
637 | |
---|
638 | if ( new_line > max_lines ) { |
---|
639 | new_line = max_lines; |
---|
640 | move_thumb = TRUE; |
---|
641 | } |
---|
642 | } |
---|
643 | |
---|
644 | if ( new_line == sblw->scroll_by_line.line_pointer && !force_redisp) |
---|
645 | /* No change in postion, and no action is nescessary */ |
---|
646 | return(move_thumb); |
---|
647 | else if ( new_line <= sblw->scroll_by_line.line_pointer) { /* scroll back. */ |
---|
648 | if ( sblw->scroll_by_line.line_pointer - new_line >= num_lines |
---|
649 | || force_redisp) { |
---|
650 | /* |
---|
651 | * We have moved so far that no text that is currently on the screen can |
---|
652 | * be saved thus there is no need to be clever just clear |
---|
653 | * the window and display a full screen of text. |
---|
654 | */ |
---|
655 | XClearWindow(XtDisplay(child),XtWindow(child)); |
---|
656 | y_pos = 0; |
---|
657 | start_line = new_line; |
---|
658 | num_lines_disp = num_lines; |
---|
659 | } |
---|
660 | else { |
---|
661 | /* |
---|
662 | * Move text that is to remain on the screen to its new location, and then |
---|
663 | * set up the proper callback values to display the rest of the text. |
---|
664 | */ |
---|
665 | lines_to_move = num_lines - sblw->scroll_by_line.line_pointer + new_line; |
---|
666 | y_location = sblw->scroll_by_line.line_pointer - new_line; |
---|
667 | XCopyArea(XtDisplay(vbar),XtWindow(child),XtWindow(child), |
---|
668 | gc,0,0,child->core.width, |
---|
669 | (lines_to_move + 1) * sblw->scroll_by_line.font_height, |
---|
670 | 0,y_location * sblw->scroll_by_line.font_height); |
---|
671 | XClearArea( XtDisplay(vbar),XtWindow(child),0,0,0, |
---|
672 | (num_lines - lines_to_move) |
---|
673 | * sblw->scroll_by_line.font_height, |
---|
674 | FALSE ); |
---|
675 | y_pos = 0; |
---|
676 | start_line = new_line; |
---|
677 | num_lines_disp = num_lines - lines_to_move; |
---|
678 | } |
---|
679 | } |
---|
680 | else { /* scrolling forward */ |
---|
681 | if ( new_line - sblw->scroll_by_line.line_pointer >= num_lines |
---|
682 | || force_redisp) { |
---|
683 | /* |
---|
684 | * We have moved so far that no text that is currently on the screen can |
---|
685 | * be saved thus there is no need to be clever just clear |
---|
686 | * the window and display a full screen of text. |
---|
687 | */ |
---|
688 | XClearWindow(XtDisplay(child),XtWindow(child)); |
---|
689 | y_pos = 0; |
---|
690 | start_line = new_line; |
---|
691 | num_lines_disp = num_lines; |
---|
692 | } |
---|
693 | else { |
---|
694 | /* |
---|
695 | * Move text that is to remain on the screen to its new location, and then |
---|
696 | * set up the proper callback values to display the rest of the text. |
---|
697 | */ |
---|
698 | lines_to_move = num_lines - new_line + sblw->scroll_by_line.line_pointer; |
---|
699 | y_location = new_line - sblw->scroll_by_line.line_pointer; |
---|
700 | XCopyArea(XtDisplay(vbar),XtWindow(child),XtWindow(child),gc,0, |
---|
701 | y_location * sblw->scroll_by_line.font_height, |
---|
702 | child->core.width, |
---|
703 | (lines_to_move)* sblw->scroll_by_line.font_height,0,0); |
---|
704 | |
---|
705 | lines_to_move--; /* make sure that we get the last, |
---|
706 | (possibly) partial line, fully painted. */ |
---|
707 | |
---|
708 | /* we add 10% of a font height here to the vertical position |
---|
709 | because some characters extend a little bit below the fontheight */ |
---|
710 | |
---|
711 | XClearArea(XtDisplay(vbar),XtWindow(child),0,lines_to_move * |
---|
712 | sblw->scroll_by_line.font_height + (int) |
---|
713 | (.1 * (float) sblw->scroll_by_line.font_height),0,0,FALSE); |
---|
714 | |
---|
715 | y_pos = lines_to_move * sblw->scroll_by_line.font_height; |
---|
716 | start_line = new_line + lines_to_move; |
---|
717 | num_lines_disp = num_lines - lines_to_move; |
---|
718 | } |
---|
719 | } |
---|
720 | |
---|
721 | sblw->scroll_by_line.line_pointer = new_line; |
---|
722 | |
---|
723 | /* |
---|
724 | * call the callbacks, this is the callback to the application to do the |
---|
725 | * actual painting of the text. |
---|
726 | */ |
---|
727 | |
---|
728 | sblw_struct = (ScrollByLineStruct *) malloc(sizeof(ScrollByLineStruct)); |
---|
729 | |
---|
730 | sblw_struct->location = y_pos; |
---|
731 | sblw_struct->start_line = start_line; |
---|
732 | sblw_struct->num_lines = num_lines_disp; |
---|
733 | |
---|
734 | XtCallCallbacks( (Widget) sblw,XtNcallback, (caddr_t) sblw_struct); |
---|
735 | |
---|
736 | /* Save that memory */ |
---|
737 | |
---|
738 | XFreeGC(XtDisplay( (Widget) sblw), gc); |
---|
739 | free(sblw_struct); |
---|
740 | |
---|
741 | return(move_thumb); |
---|
742 | } |
---|
743 | |
---|
744 | /* Function Name: VerticalThumb |
---|
745 | * Description: This function moves the postition of the interior window |
---|
746 | * as the vertical scroll bar is moved. |
---|
747 | * Arguments: w - the scrollbar widget. |
---|
748 | * junk - not used. |
---|
749 | * percent - the position of the scrollbar. |
---|
750 | * Returns: none. |
---|
751 | */ |
---|
752 | |
---|
753 | static void |
---|
754 | VerticalThumb(w,junk,percent) |
---|
755 | Widget w; |
---|
756 | caddr_t junk; |
---|
757 | float percent; |
---|
758 | { |
---|
759 | int new_line; /* The new location for the line pointer. */ |
---|
760 | float location; /* The location of the thumb. */ |
---|
761 | Widget vbar; |
---|
762 | |
---|
763 | ScrollByLineWidget sblw = (ScrollByLineWidget) w->core.parent; |
---|
764 | |
---|
765 | vbar = sblw->composite.children[0]; |
---|
766 | |
---|
767 | new_line = (int) ((float) sblw->scroll_by_line.lines * percent); |
---|
768 | |
---|
769 | if (ScrollVerticalText( (Widget) sblw, new_line, FALSE)) { |
---|
770 | /* reposition the thumb */ |
---|
771 | location = (float) sblw->scroll_by_line.line_pointer / |
---|
772 | (float) sblw->scroll_by_line.lines; |
---|
773 | XtScrollBarSetThumb( vbar, location , (float) -1 ); |
---|
774 | } |
---|
775 | |
---|
776 | } |
---|
777 | |
---|
778 | /* Function Name: VerticalScroll |
---|
779 | * Description: This function moves the postition of the interior window |
---|
780 | * as the vertical scroll bar is moved. |
---|
781 | * Arguments: w - the scrollbar widget. |
---|
782 | * junk - not used. |
---|
783 | * pos - the position of the cursor. |
---|
784 | * Returns: none. |
---|
785 | */ |
---|
786 | |
---|
787 | static void |
---|
788 | VerticalScroll(w,junk,pos) |
---|
789 | Widget w; |
---|
790 | caddr_t junk; |
---|
791 | int pos; |
---|
792 | { |
---|
793 | int new_line; /* The new location for the line pointer. */ |
---|
794 | float location; /* The new location of the thumb. */ |
---|
795 | Widget vbar; |
---|
796 | |
---|
797 | ScrollByLineWidget sblw = (ScrollByLineWidget) w->core.parent; |
---|
798 | |
---|
799 | vbar = sblw->composite.children[0]; |
---|
800 | |
---|
801 | new_line = sblw->scroll_by_line.line_pointer; |
---|
802 | new_line += (int) pos / sblw->scroll_by_line.font_height; |
---|
803 | |
---|
804 | (void) ScrollVerticalText( (Widget) sblw,new_line,FALSE); |
---|
805 | |
---|
806 | /* reposition the thumb */ |
---|
807 | |
---|
808 | location = (float) sblw->scroll_by_line.line_pointer / |
---|
809 | (float) sblw->scroll_by_line.lines; |
---|
810 | XtScrollBarSetThumb( vbar, location , (float) -1 ); |
---|
811 | |
---|
812 | |
---|
813 | } |
---|
814 | |
---|
815 | /* |
---|
816 | * I have not thought out the horizontal scrolling yet, I am not sure what |
---|
817 | * should be done here. This code is questionable. |
---|
818 | */ |
---|
819 | |
---|
820 | |
---|
821 | /* Function Name: HorizontalThumb |
---|
822 | * Description: This function moves the postition of the interior window |
---|
823 | * as the vertical scroll bar is moved. |
---|
824 | * Arguments: w - the scrollbar widget. |
---|
825 | * junk - not used. |
---|
826 | * percent - the position of the scrollbar. |
---|
827 | * Returns: none. |
---|
828 | */ |
---|
829 | |
---|
830 | static void |
---|
831 | HorizontalThumb(w,junk,percent) |
---|
832 | Widget w; |
---|
833 | caddr_t junk; |
---|
834 | float percent; |
---|
835 | { |
---|
836 | int x, y; |
---|
837 | Widget child,vbar; |
---|
838 | ScrollByLineWidget sblw = (ScrollByLineWidget) w->core.parent; |
---|
839 | |
---|
840 | /* reposition the client window (child[2]) */ |
---|
841 | |
---|
842 | vbar = sblw->composite.children[0]; |
---|
843 | child = sblw->composite.children[2]; |
---|
844 | |
---|
845 | x = (int) ( (0.0 - percent) * ((float) child->core.width)); |
---|
846 | y = child->core.y; |
---|
847 | |
---|
848 | /* |
---|
849 | * if there is a vertical scrollbar and it is on the left then |
---|
850 | * allow room for it . |
---|
851 | */ |
---|
852 | |
---|
853 | if (vbar->core.x == 0) |
---|
854 | x += vbar->core.width + 2 * vbar->core.border_width; |
---|
855 | |
---|
856 | XtMoveWidget(child,x,y); |
---|
857 | } |
---|
858 | |
---|
859 | /* Function Name: HorizontalScroll |
---|
860 | * Description: This function moves the postition of the interior window |
---|
861 | * as the horizontal scroll bar is moved. |
---|
862 | * Arguments: w - the scrollbar widget. |
---|
863 | * junk - not used. |
---|
864 | * pos - the position of the cursor. |
---|
865 | * Returns: none. |
---|
866 | */ |
---|
867 | |
---|
868 | static void |
---|
869 | HorizontalScroll(w,junk,pos) |
---|
870 | Widget w; |
---|
871 | caddr_t junk; |
---|
872 | int pos; |
---|
873 | { |
---|
874 | int x, y, min_x; |
---|
875 | float location; |
---|
876 | Widget child,vbar,hbar; |
---|
877 | ScrollByLineWidget sblw = (ScrollByLineWidget) w->core.parent; |
---|
878 | |
---|
879 | /* reposition the client window (child[2]) */ |
---|
880 | |
---|
881 | vbar = sblw->composite.children[0]; |
---|
882 | hbar = sblw->composite.children[1]; |
---|
883 | child = sblw->composite.children[2]; |
---|
884 | |
---|
885 | x = child->core.x - pos; |
---|
886 | y = child->core.y; |
---|
887 | |
---|
888 | /* |
---|
889 | * Keep us in bounds. |
---|
890 | */ |
---|
891 | |
---|
892 | if ( x > 0 ) x = 0; |
---|
893 | min_x = - (child->core.width - hbar->core.width - |
---|
894 | 2 * vbar->core.border_width); |
---|
895 | |
---|
896 | if (vbar->core.y > 0) /* vertical scrollbar is on right.*/ |
---|
897 | min_x -= vbar->core.width + 2 * vbar->core.border_width; |
---|
898 | |
---|
899 | if ( x < min_x ) x = min_x; |
---|
900 | |
---|
901 | /* reposition the thumb */ |
---|
902 | |
---|
903 | location = 0.0 - (float) y / (float) child->core.width; |
---|
904 | XtScrollBarSetThumb( hbar, location , (float) -1 ); |
---|
905 | |
---|
906 | /* |
---|
907 | * if there is a vertical scrollbar and it is on the left then |
---|
908 | * allow room for it . |
---|
909 | */ |
---|
910 | |
---|
911 | if (vbar->core.x == 0) |
---|
912 | y += vbar->core.width + 2 * vbar->core.border_width; |
---|
913 | |
---|
914 | XtMoveWidget(child,x,y); /* he's my child so I can move him. */ |
---|
915 | } |
---|
916 | |
---|
917 | static void InitializeHook(new, args, num_args) |
---|
918 | ScrollByLineWidget new; |
---|
919 | ArgList args; |
---|
920 | Cardinal *num_args; |
---|
921 | { |
---|
922 | ScrollByLineWidget sblw = (ScrollByLineWidget) new; |
---|
923 | Widget window; /* Window widget. */ |
---|
924 | Arg arglist[50]; /* Must be large enough for the |
---|
925 | arglist from the scrolled widget to |
---|
926 | be added to it. */ |
---|
927 | Cardinal scrollbar_num; /* the number of scrollbar args. */ |
---|
928 | Cardinal window_num; /* the number of window args. */ |
---|
929 | |
---|
930 | static XtCallbackRec scrollcallback[] = { /* The scroll callback function. */ |
---|
931 | { NULL, NULL }, |
---|
932 | { NULL, NULL }, |
---|
933 | }; |
---|
934 | static XtCallbackRec thumbcallback[] = { /* The thumb callback function. */ |
---|
935 | { NULL, NULL }, |
---|
936 | { NULL, NULL }, |
---|
937 | }; |
---|
938 | |
---|
939 | sblw->scroll_by_line.line_pointer = 0; /* initial point to line 0. */ |
---|
940 | |
---|
941 | if (sblw->core.height <= 0) |
---|
942 | sblw->core.height = DEFAULT_HEIGHT; |
---|
943 | if (sblw->core.width <= 0) |
---|
944 | sblw->core.width = DEFAULT_WIDTH; |
---|
945 | |
---|
946 | scrollbar_num = 0; |
---|
947 | XtSetArg(arglist[scrollbar_num], XtNheight, 10); /* changed in layout. */ |
---|
948 | scrollbar_num++; |
---|
949 | XtSetArg(arglist[scrollbar_num], XtNwidth, 16); |
---|
950 | scrollbar_num++; |
---|
951 | XtSetArg(arglist[scrollbar_num], XtNorientation, XtorientVertical); |
---|
952 | scrollbar_num++; |
---|
953 | thumbcallback[0].callback = VerticalThumb; |
---|
954 | scrollcallback[0].callback = VerticalScroll; |
---|
955 | XtSetArg(arglist[scrollbar_num], XtNthumbProc, thumbcallback); |
---|
956 | scrollbar_num++; |
---|
957 | XtSetArg(arglist[scrollbar_num], XtNscrollProc, scrollcallback); |
---|
958 | scrollbar_num++; |
---|
959 | |
---|
960 | /* |
---|
961 | * Merge the argument lists so but have the scrollbar arglist take |
---|
962 | * control when there is a discrepency this causes us to get the |
---|
963 | * correct height and width. |
---|
964 | */ |
---|
965 | |
---|
966 | scrollbar_num = MergeArglists(args, *num_args,arglist,scrollbar_num); |
---|
967 | |
---|
968 | XtCreateManagedWidget("Vertical Scroll Bar", |
---|
969 | scrollbarWidgetClass, (Widget) sblw,arglist,scrollbar_num); |
---|
970 | |
---|
971 | scrollbar_num = 0; |
---|
972 | XtSetArg(arglist[scrollbar_num], XtNwidth, 10); /* changed in layout. */ |
---|
973 | scrollbar_num++; |
---|
974 | XtSetArg(arglist[scrollbar_num], XtNheight, 16); |
---|
975 | scrollbar_num++; |
---|
976 | XtSetArg(arglist[scrollbar_num], XtNorientation, XtorientHorizontal); |
---|
977 | scrollbar_num++; |
---|
978 | thumbcallback[0].callback = HorizontalThumb; |
---|
979 | scrollcallback[0].callback = HorizontalScroll; |
---|
980 | XtSetArg(arglist[scrollbar_num], XtNthumbProc, thumbcallback); |
---|
981 | scrollbar_num++; |
---|
982 | XtSetArg(arglist[scrollbar_num], XtNscrollProc, scrollcallback); |
---|
983 | scrollbar_num++; |
---|
984 | |
---|
985 | /* |
---|
986 | * Merge the argument lists so but have the scrollbar arglist take |
---|
987 | * control when there is a discrepency this causes us to get the |
---|
988 | * correct height and width. |
---|
989 | */ |
---|
990 | |
---|
991 | scrollbar_num = MergeArglists(args, *num_args,arglist,scrollbar_num); |
---|
992 | |
---|
993 | XtCreateManagedWidget("Horizontal Scroll Bar", |
---|
994 | scrollbarWidgetClass, (Widget) sblw,arglist,scrollbar_num); |
---|
995 | |
---|
996 | window_num = 0; |
---|
997 | XtSetArg(arglist[window_num], XtNwidth, sblw->scroll_by_line.inner_width); |
---|
998 | window_num++; |
---|
999 | XtSetArg(arglist[window_num], XtNheight, sblw->scroll_by_line.inner_height); |
---|
1000 | window_num++; |
---|
1001 | XtSetArg(arglist[window_num], XtNborderWidth, 0); |
---|
1002 | window_num++; |
---|
1003 | |
---|
1004 | window = XtCreateWidget("Window with file",widgetClass,(Widget) sblw,arglist, |
---|
1005 | window_num); |
---|
1006 | XtManageChild(window); |
---|
1007 | |
---|
1008 | /* We want expose events for this window also. */ |
---|
1009 | |
---|
1010 | XtAddEventHandler(window, (Cardinal) ExposureMask, FALSE, ChildExpose, NULL); |
---|
1011 | |
---|
1012 | } /* InitializeHook */ |
---|
1013 | |
---|
1014 | static void Realize(w, valueMask, attributes) |
---|
1015 | register Widget w; |
---|
1016 | Mask *valueMask; |
---|
1017 | XSetWindowAttributes *attributes; |
---|
1018 | { |
---|
1019 | XtCreateWindow( w, (Cardinal) InputOutput, (Visual *)CopyFromParent, |
---|
1020 | *valueMask, attributes); |
---|
1021 | } /* Realize */ |
---|
1022 | |
---|
1023 | /* |
---|
1024 | * |
---|
1025 | * Set Values |
---|
1026 | * |
---|
1027 | */ |
---|
1028 | |
---|
1029 | static Boolean SetValues (current, request, new) |
---|
1030 | Widget current, request, new; |
---|
1031 | { |
---|
1032 | ScrollByLineWidget sblw_new, sblw_current; |
---|
1033 | Boolean ret = FALSE; |
---|
1034 | |
---|
1035 | sblw_current = (ScrollByLineWidget) current; |
---|
1036 | sblw_new = (ScrollByLineWidget) new; |
---|
1037 | |
---|
1038 | if (sblw_current->scroll_by_line.lines != sblw_new->scroll_by_line.lines) { |
---|
1039 | ResetThumb(new); |
---|
1040 | ret = TRUE; |
---|
1041 | } |
---|
1042 | if (sblw_current->scroll_by_line.font_height != |
---|
1043 | sblw_new->scroll_by_line.font_height) { |
---|
1044 | ResetThumb(new); |
---|
1045 | ret = TRUE; |
---|
1046 | } |
---|
1047 | return(ret); |
---|
1048 | |
---|
1049 | } /* Set Values */ |
---|
1050 | |
---|
1051 | /* Function Name: MergeArglists |
---|
1052 | * Description: This function merges two arglists. |
---|
1053 | * Arguments: from,num_from - the number and list of args for the source. |
---|
1054 | * to,num_to - the number and list of argument for the |
---|
1055 | * destination. |
---|
1056 | * Returns: new number of argument in to. |
---|
1057 | */ |
---|
1058 | |
---|
1059 | /* Note: This function will be very unhappy with you if 'to' is not |
---|
1060 | * large enough to contain 'from', you will end up with pointers |
---|
1061 | * in space. |
---|
1062 | */ |
---|
1063 | |
---|
1064 | static int |
---|
1065 | MergeArglists(from,num_from,to,num_to) |
---|
1066 | Arg from[],to[]; |
---|
1067 | Cardinal num_from,num_to; |
---|
1068 | { |
---|
1069 | int i,j; /* a counter. */ |
---|
1070 | |
---|
1071 | /* When there are two similar values ignore the from value. */ |
---|
1072 | |
---|
1073 | i = 0; |
---|
1074 | while ( i < num_from ) { |
---|
1075 | j = 0; |
---|
1076 | while ( j < num_to ) { |
---|
1077 | if ( !strcmp(from[i].name,to[j].name) ) { |
---|
1078 | /* if they are the same then goto next on the from list, |
---|
1079 | i.e. ignore this entry, do not add to to list. */ |
---|
1080 | i++; |
---|
1081 | if ( i > num_from) |
---|
1082 | j = num_to + 100; |
---|
1083 | else { |
---|
1084 | j = 0; |
---|
1085 | continue; |
---|
1086 | } |
---|
1087 | } |
---|
1088 | j++; |
---|
1089 | } |
---|
1090 | /* add to to list */ |
---|
1091 | if (j < num_to + 100) { |
---|
1092 | to[num_to].value = from[i].value; |
---|
1093 | to[num_to].name = from[i].name; |
---|
1094 | num_to++; |
---|
1095 | i++; |
---|
1096 | } |
---|
1097 | } |
---|
1098 | return(num_to); |
---|
1099 | } |
---|
1100 | |
---|
1101 | /* Public Routines. */ |
---|
1102 | |
---|
1103 | /* Function Name: XtScrollByLineWidget() |
---|
1104 | * Description: This function returns the window widget that the |
---|
1105 | * ScrollByLine widget uses to display its text. |
---|
1106 | * Arguments: w - the ScrollByLine Widget. |
---|
1107 | * Returns: the widget to display the text into. |
---|
1108 | */ |
---|
1109 | |
---|
1110 | extern Widget XtScrollByLineWidget(w) |
---|
1111 | Widget w; |
---|
1112 | { |
---|
1113 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; /* the sblw widget. */ |
---|
1114 | |
---|
1115 | return(sblw->composite.children[2]); |
---|
1116 | } |
---|
1117 | |
---|
1118 | /* Function Name: XtResetScrollByLine |
---|
1119 | * Description: This function resets the scroll by line widget. |
---|
1120 | * Arguments: w - the sblw widget. |
---|
1121 | * Returns: none. |
---|
1122 | */ |
---|
1123 | |
---|
1124 | extern void |
---|
1125 | XtResetScrollByLine(w) |
---|
1126 | Widget w; |
---|
1127 | { |
---|
1128 | float location; /* the location of the thumb. */ |
---|
1129 | ScrollByLineWidget sblw = (ScrollByLineWidget) w; /* the sblw widget. */ |
---|
1130 | Widget vbar; |
---|
1131 | |
---|
1132 | vbar = sblw->composite.children[0]; |
---|
1133 | |
---|
1134 | (void) ScrollVerticalText( w, 0, TRUE); |
---|
1135 | |
---|
1136 | /* reposition the thumb */ |
---|
1137 | |
---|
1138 | location = (float) sblw->scroll_by_line.line_pointer / |
---|
1139 | (float) sblw->scroll_by_line.lines; |
---|
1140 | XtScrollBarSetThumb( vbar, location , (float) -1 ); |
---|
1141 | |
---|
1142 | ResetThumb(w); |
---|
1143 | } |
---|