glslang: add 14.3.0
[oi-userland.git] / components / x11 / libXaw4 / src / Xaw3_1Viewport.c
blob7c7a5602a13a18c011932c2662d2d0f2940f81db
1 #ifndef lint
2 static char Xrcsid[] = "$XConsortium: Viewport.c,v 1.48 89/12/15 11:37:22 kit Exp $";
3 #endif /* lint */
6 /***********************************************************
7 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
8 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
10 All Rights Reserved
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital or MIT not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 SOFTWARE.
28 ******************************************************************/
30 #include <X11/IntrinsicP.h>
31 #include <X11/StringDefs.h>
33 #include <./Xaw3_1XawInit.h>
34 #include <X11/Xmu/Misc.h>
35 #include <./Xaw3_1Scrollbar.h>
36 #include <./Xaw3_1ViewportP.h>
38 static void ScrollUpDownProc(), ThumbProc();
39 static Boolean GetGeometry();
41 #define offset(field) XtOffset(ViewportWidget,viewport.field)
42 static XtResource resources[] = {
43 {XtNforceBars, XtCBoolean, XtRBoolean, sizeof(Boolean),
44 offset(forcebars), XtRImmediate, (caddr_t)False},
45 {XtNallowHoriz, XtCBoolean, XtRBoolean, sizeof(Boolean),
46 offset(allowhoriz), XtRImmediate, (caddr_t)False},
47 {XtNallowVert, XtCBoolean, XtRBoolean, sizeof(Boolean),
48 offset(allowvert), XtRImmediate, (caddr_t)False},
49 {XtNuseBottom, XtCBoolean, XtRBoolean, sizeof(Boolean),
50 offset(usebottom), XtRImmediate, (caddr_t)False},
51 {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean),
52 offset(useright), XtRImmediate, (caddr_t)False},
54 #undef offset
56 static void Initialize(), ConstraintInitialize(),
57 Realize(), Resize(), ChangeManaged();
58 static Boolean SetValues(), Layout();
59 static XtGeometryResult GeometryManager(), PreferredGeometry();
61 #define superclass (&formClassRec)
62 ViewportClassRec viewportClassRec = {
63 { /* core_class fields */
64 /* superclass */ (WidgetClass) superclass,
65 /* class_name */ "Viewport",
66 /* widget_size */ sizeof(ViewportRec),
67 /* class_initialize */ XawInitializeWidgetSet,
68 /* class_part_init */ NULL,
69 /* class_inited */ FALSE,
70 /* initialize */ Initialize,
71 /* initialize_hook */ NULL,
72 /* realize */ Realize,
73 /* actions */ NULL,
74 /* num_actions */ 0,
75 /* resources */ resources,
76 /* num_resources */ XtNumber(resources),
77 /* xrm_class */ NULLQUARK,
78 /* compress_motion */ TRUE,
79 /* compress_exposure */ TRUE,
80 /* compress_enterleave*/ TRUE,
81 /* visible_interest */ FALSE,
82 /* destroy */ NULL,
83 /* resize */ Resize,
84 /* expose */ XtInheritExpose,
85 /* set_values */ SetValues,
86 /* set_values_hook */ NULL,
87 /* set_values_almost */ XtInheritSetValuesAlmost,
88 /* get_values_hook */ NULL,
89 /* accept_focus */ NULL,
90 /* version */ XtVersion,
91 /* callback_private */ NULL,
92 /* tm_table */ NULL,
93 /* query_geometry */ PreferredGeometry,
94 /* display_accelerator*/ XtInheritDisplayAccelerator,
95 /* extension */ NULL
97 { /* composite_class fields */
98 /* geometry_manager */ GeometryManager,
99 /* change_managed */ ChangeManaged,
100 /* insert_child */ XtInheritInsertChild,
101 /* delete_child */ XtInheritDeleteChild,
102 /* extension */ NULL
104 { /* constraint_class fields */
105 /* subresourses */ NULL,
106 /* subresource_count */ 0,
107 /* constraint_size */ sizeof(ViewportConstraintsRec),
108 /* initialize */ ConstraintInitialize,
109 /* destroy */ NULL,
110 /* set_values */ NULL,
111 /* extension */ NULL
113 { /* form_class fields */
114 /* layout */ Layout
116 { /* viewport_class fields */
117 /* empty */ 0
122 WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec;
124 static Widget CreateScrollbar(w, horizontal)
125 ViewportWidget w;
126 Boolean horizontal;
128 Widget clip = w->viewport.clip;
129 ViewportConstraints constraints =
130 (ViewportConstraints)clip->core.constraints;
131 static Arg barArgs[] = {
132 {XtNorientation, NULL},
133 {XtNlength, NULL},
134 {XtNleft, NULL},
135 {XtNright, NULL},
136 {XtNtop, NULL},
137 {XtNbottom, NULL},
138 {XtNmappedWhenManaged, False},
140 Widget bar;
142 XtSetArg(barArgs[0], XtNorientation,
143 horizontal ? XtorientHorizontal : XtorientVertical );
144 XtSetArg(barArgs[1], XtNlength,
145 horizontal ? clip->core.width : clip->core.height);
146 XtSetArg(barArgs[2], XtNleft,
147 (!horizontal && w->viewport.useright) ? XtChainRight : XtChainLeft);
148 XtSetArg(barArgs[3], XtNright,
149 (!horizontal && !w->viewport.useright) ? XtChainLeft : XtChainRight);
150 XtSetArg(barArgs[4], XtNtop,
151 (horizontal && w->viewport.usebottom) ? XtChainBottom: XtChainTop);
152 XtSetArg(barArgs[5], XtNbottom,
153 (horizontal && !w->viewport.usebottom) ? XtChainTop: XtChainBottom);
155 bar = XtCreateWidget( (horizontal ? "horizontal" : "vertical"),
156 scrollbarWidgetClass, (Widget)w,
157 barArgs, XtNumber(barArgs) );
158 XtAddCallback( bar, XtNscrollProc, ScrollUpDownProc, (caddr_t)w );
159 XtAddCallback( bar, XtNjumpProc, ThumbProc, (caddr_t)w );
161 if (horizontal) {
162 w->viewport.horiz_bar = bar;
163 constraints->form.vert_base = bar;
165 else {
166 w->viewport.vert_bar = bar;
167 constraints->form.horiz_base = bar;
170 XtManageChild( bar );
172 return bar;
175 /* ARGSUSED */
176 static void Initialize(request, new)
177 Widget request, new;
179 ViewportWidget w = (ViewportWidget)new;
180 static Arg clip_args[5];
181 Cardinal num_args;
182 Widget h_bar, v_bar;
183 Dimension clip_height, clip_width;
185 w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels. */
189 * Initialize all widget pointers to NULL.
192 w->viewport.child = (Widget) NULL;
193 w->viewport.horiz_bar = w->viewport.vert_bar = (Widget)NULL;
196 * Create Clip Widget.
199 num_args = 0;
200 XtSetArg(clip_args[num_args], XtNborderWidth, 0); num_args++;
201 XtSetArg(clip_args[num_args], XtNleft, XtChainLeft); num_args++;
202 XtSetArg(clip_args[num_args], XtNright, XtChainRight); num_args++;
203 XtSetArg(clip_args[num_args], XtNtop, XtChainTop); num_args++;
204 XtSetArg(clip_args[num_args], XtNbottom, XtChainBottom); num_args++;
206 w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, new,
207 clip_args, num_args);
210 if (!w->viewport.forcebars)
211 return; /* If we are not forcing the bars then we are done. */
213 if (w->viewport.allowhoriz)
214 (void) CreateScrollbar(w, True);
215 if (w->viewport.allowvert)
216 (void) CreateScrollbar(w, False);
218 h_bar = w->viewport.horiz_bar;
219 v_bar = w->viewport.vert_bar;
222 * Set the clip widget to the correct height.
225 clip_width = w->core.width;
226 clip_height = w->core.height;
228 if ( (h_bar != NULL) &&
229 (w->core.width > h_bar->core.width + h_bar->core.border_width) )
230 clip_width -= h_bar->core.width + h_bar->core.border_width;
232 if ( (v_bar != NULL) &&
233 (w->core.height > v_bar->core.height + v_bar->core.border_width) )
234 clip_height -= v_bar->core.height + v_bar->core.border_width;
236 num_args = 0;
237 XtSetArg(clip_args[num_args], XtNwidth, clip_width); num_args++;
238 XtSetArg(clip_args[num_args], XtNheight, clip_height); num_args++;
239 XtSetValues(w->viewport.clip, clip_args, num_args);
242 /* ARGSUSED */
243 static void ConstraintInitialize(request, new)
244 Widget request, new;
246 ((ViewportConstraints)new->core.constraints)->viewport.reparented = False;
249 static void Realize(widget, value_mask, attributes)
250 Widget widget;
251 XtValueMask *value_mask;
252 XSetWindowAttributes *attributes;
254 ViewportWidget w = (ViewportWidget)widget;
255 register Widget child = w->viewport.child;
256 register Widget clip = w->viewport.clip;
258 *value_mask |= CWBitGravity;
259 attributes->bit_gravity = NorthWestGravity;
260 (*superclass->core_class.realize)(widget, value_mask, attributes);
262 (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */
264 if (child != (Widget)NULL) {
265 XtMoveWidget( child, (Position)0, (Position)0 );
266 XtRealizeWidget( clip );
267 XtRealizeWidget( child );
268 XReparentWindow( XtDisplay(w), XtWindow(child), XtWindow(clip),
269 (Position)0, (Position)0 );
270 XtMapWidget( child );
274 /* ARGSUSED */
275 static Boolean SetValues(current, request, new)
276 Widget current, request, new;
278 ViewportWidget w = (ViewportWidget)new;
279 ViewportWidget cw = (ViewportWidget)current;
281 if (w->viewport.forcebars != cw->viewport.forcebars) {
282 if (w->viewport.forcebars) {
283 if (w->viewport.allowhoriz && w->viewport.horiz_bar == (Widget)NULL)
284 (void) CreateScrollbar( w, True );
285 if (w->viewport.allowvert && w->viewport.vert_bar == (Widget)NULL)
286 (void) CreateScrollbar( w, False );
290 /* take care of bars, &tc. */
291 (*w->core.widget_class->core_class.resize)( new );
292 return False;
296 static void ChangeManaged(widget)
297 Widget widget;
299 ViewportWidget w = (ViewportWidget)widget;
300 register int num_children = w->composite.num_children;
301 register Widget child, *childP;
302 register int i;
304 child = (Widget)NULL;
305 for (childP=w->composite.children, i=0; i < num_children; childP++, i++) {
306 if (XtIsManaged(*childP)
307 && *childP != w->viewport.clip
308 && *childP != w->viewport.horiz_bar
309 && *childP != w->viewport.vert_bar)
311 child = *childP;
312 break;
316 if (child != w->viewport.child) {
317 w->viewport.child = child;
318 if (child != (Widget)NULL) {
319 XtResizeWidget( child, child->core.width,
320 child->core.height, (Dimension)0 );
321 if (XtIsRealized(widget)) {
322 ViewportConstraints constraints =
323 (ViewportConstraints)child->core.constraints;
324 if (!XtIsRealized(child)) {
325 Window window = XtWindow(w);
326 XtMoveWidget( child, (Position)0, (Position)0 );
327 #ifdef notdef
328 /* this is dirty, but it saves the following code: */
329 XtRealizeWidget( child );
330 XReparentWindow( XtDisplay(w), XtWindow(child),
331 XtWindow(w->viewport.clip),
332 (Position)0, (Position)0 );
333 if (child->core.mapped_when_managed)
334 XtMapWidget( child );
335 #else
336 w->core.window = XtWindow(w->viewport.clip);
337 XtRealizeWidget( child );
338 w->core.window = window;
339 #endif /* notdef */
340 constraints->viewport.reparented = True;
342 else if (!constraints->viewport.reparented) {
343 XReparentWindow( XtDisplay(w), XtWindow(child),
344 XtWindow(w->viewport.clip),
345 (Position)0, (Position)0 );
346 constraints->viewport.reparented = True;
347 if (child->core.mapped_when_managed)
348 XtMapWidget( child );
351 GetGeometry( widget, child->core.width, child->core.height );
352 (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout)
353 ( (FormWidget)w, w->core.width, w->core.height );
354 /* %%% do we need to hide this child from Form? */
358 #ifdef notdef
359 (*superclass->composite_class.change_managed)( widget );
360 #endif
364 static void SetBar(w, top, length, total)
365 Widget w;
366 Position top;
367 Dimension length, total;
369 XawScrollbarSetThumb(w, (float) top / total, (float) length / total );
372 static void RedrawThumbs(w)
373 ViewportWidget w;
375 register Widget child = w->viewport.child;
376 register Widget clip = w->viewport.clip;
378 if (w->viewport.horiz_bar != (Widget)NULL)
379 SetBar( w->viewport.horiz_bar, -(child->core.x),
380 clip->core.width, child->core.width );
382 if (w->viewport.vert_bar != (Widget)NULL)
383 SetBar( w->viewport.vert_bar, -(child->core.y),
384 clip->core.height, child->core.height );
389 static void MoveChild(w, x, y)
390 ViewportWidget w;
391 Position x, y;
393 register Widget child = w->viewport.child;
394 register Widget clip = w->viewport.clip;
396 /* make sure we never move past right/bottom borders */
397 if (-x + clip->core.width > child->core.width)
398 x = -(child->core.width - clip->core.width);
400 if (-y + clip->core.height > child->core.height)
401 y = -(child->core.height - clip->core.height);
403 /* make sure we never move past left/top borders */
404 if (x >= 0) x = 0;
405 if (y >= 0) y = 0;
407 XtMoveWidget(child, x, y);
409 RedrawThumbs(w);
412 static void ComputeWithForceBars(Widget, Boolean, XtWidgetGeometry *, int *, int *);
414 static void ComputeLayout(widget, query, destroy_scrollbars)
415 Widget widget; /* Viewport */
416 Boolean query; /* query child's preferred geom? */
417 Boolean destroy_scrollbars; /* destroy un-needed scrollbars? */
419 ViewportWidget w = (ViewportWidget)widget;
420 register Widget child = w->viewport.child;
421 register Widget clip = w->viewport.clip;
422 ViewportConstraints constraints
423 = (ViewportConstraints)clip->core.constraints;
424 Boolean needshoriz, needsvert;
425 int clip_width, clip_height;
426 XtWidgetGeometry intended;
428 if (child == (Widget) NULL) return;
430 clip_width = w->core.width;
431 clip_height = w->core.height;
432 intended.request_mode = CWBorderWidth;
433 intended.border_width = 0;
435 if (w->viewport.forcebars) {
436 needsvert = w->viewport.allowvert;
437 needshoriz = w->viewport.allowhoriz;
438 ComputeWithForceBars(widget, query, &intended,
439 &clip_width, &clip_height);
441 else {
442 Dimension prev_width, prev_height;
443 XtGeometryMask prev_mode;
444 XtWidgetGeometry preferred;
446 needshoriz = needsvert = False;
449 * intended.{width,height} caches the eventual child dimensions,
450 * but we don't set the mode bits until after we decide that the
451 * child's preferences are not acceptable.
454 if (!w->viewport.allowhoriz)
455 intended.request_mode |= CWWidth;
457 if (child->core.width < clip_width)
458 intended.width = clip_width;
459 else
460 intended.width = child->core.width;
462 if (child->core.height < clip_height)
463 intended.height = clip_height;
464 else
465 intended.height = child->core.height;
467 if (!w->viewport.allowvert)
468 intended.request_mode |= CWHeight;
470 if (!query) {
471 preferred.width = child->core.width;
472 preferred.height = child->core.height;
474 do { /* while intended != prev */
476 if (query) {
477 (void) XtQueryGeometry( child, &intended, &preferred );
478 if ( !(preferred.request_mode & CWWidth) )
479 preferred.width = intended.width;
480 if ( !(preferred.request_mode & CWHeight) )
481 preferred.height = intended.height;
483 prev_width = intended.width;
484 prev_height = intended.height;
485 prev_mode = intended.request_mode;
487 * note that having once decided to turn on either bar
488 * we'll not change our mind until we're next resized,
489 * thus avoiding potential oscillations.
491 #define CheckHoriz() \
492 if (w->viewport.allowhoriz && preferred.width > clip_width) { \
493 if (!needshoriz) { \
494 Widget bar; \
495 needshoriz = True; \
496 if ((bar = w->viewport.horiz_bar) == (Widget)NULL) \
497 bar = CreateScrollbar(w, True); \
498 clip_height -= bar->core.height + \
499 bar->core.border_width; \
500 if (clip_height < 1) clip_height = 1; \
502 intended.width = preferred.width; \
504 /*enddef*/
505 CheckHoriz();
506 if (w->viewport.allowvert && preferred.height > clip_height) {
507 if (!needsvert) {
508 Widget bar;
509 needsvert = True;
510 if ((bar = w->viewport.vert_bar) == (Widget)NULL)
511 bar = CreateScrollbar(w, False);
512 clip_width -= bar->core.width + bar->core.border_width;
513 if (clip_width < 1) clip_width = 1;
514 CheckHoriz();
516 intended.height = preferred.height;
518 if (!w->viewport.allowhoriz || preferred.width < clip_width) {
519 intended.width = clip_width;
520 intended.request_mode |= CWWidth;
522 if (!w->viewport.allowvert || preferred.height < clip_height) {
523 intended.height = clip_height;
524 intended.request_mode |= CWHeight;
526 } while (intended.request_mode != prev_mode
527 || (intended.request_mode & CWWidth
528 && intended.width != prev_width)
529 || (intended.request_mode & CWHeight
530 && intended.height != prev_height));
533 if (XtIsRealized(clip))
534 XRaiseWindow( XtDisplay(clip), XtWindow(clip) );
536 XtMoveWidget( clip,
537 needsvert ? (w->viewport.useright ? 0 :
538 w->viewport.vert_bar->core.width +
539 w->viewport.vert_bar->core.border_width) : 0,
540 needshoriz ? (w->viewport.usebottom ? 0 :
541 w->viewport.horiz_bar->core.height +
542 w->viewport.horiz_bar->core.border_width) : 0);
543 XtResizeWidget( clip, (Dimension)clip_width,
544 (Dimension)clip_height, (Dimension)0 );
546 if (w->viewport.horiz_bar != (Widget)NULL) {
547 register Widget bar = w->viewport.horiz_bar;
548 if (!needshoriz) {
549 constraints->form.vert_base = (Widget)NULL;
550 if (destroy_scrollbars) {
551 XtDestroyWidget( bar );
552 w->viewport.horiz_bar = (Widget)NULL;
555 else {
556 register int bw = bar->core.border_width;
557 XtResizeWidget( bar, clip_width, bar->core.height, bw );
558 XtMoveWidget( bar,
559 ((needsvert && !w->viewport.useright)
560 ? w->viewport.vert_bar->core.width
561 : -bw),
562 (w->viewport.usebottom
563 ? w->core.height - bar->core.height - bw
564 : -bw) );
565 XtSetMappedWhenManaged( bar, True );
569 if (w->viewport.vert_bar != (Widget)NULL) {
570 register Widget bar = w->viewport.vert_bar;
571 if (!needsvert) {
572 constraints->form.horiz_base = (Widget)NULL;
573 if (destroy_scrollbars) {
574 XtDestroyWidget( bar );
575 w->viewport.vert_bar = (Widget)NULL;
578 else {
579 register int bw = bar->core.border_width;
580 XtResizeWidget( bar, bar->core.width, clip_height, bw );
581 XtMoveWidget( bar,
582 (w->viewport.useright
583 ? w->core.width - bar->core.width - bw
584 : -bw),
585 ((needshoriz && !w->viewport.usebottom)
586 ? w->viewport.horiz_bar->core.height
587 : -bw) );
588 XtSetMappedWhenManaged( bar, True );
592 if (child != (Widget)NULL) {
593 XtResizeWidget( child, (Dimension)intended.width,
594 (Dimension)intended.height, (Dimension)0 );
595 MoveChild(w,
596 needshoriz ? child->core.x : 0,
597 needsvert ? child->core.y : 0);
601 /* Function Name: ComputeWithForceBars
602 * Description: Computes the layout give forcebars is set.
603 * Arguments: widget - the viewport widget.
604 * query - whether or not to query the child.
605 * intended - the cache of the childs height is
606 * stored here ( USED AND RETURNED ).
607 * clip_width, clip_height - size of clip window.
608 * (USED AND RETURNED ).
609 * Returns: none.
612 static void
613 ComputeWithForceBars(widget, query, intended, clip_width, clip_height)
614 Widget widget;
615 Boolean query;
616 XtWidgetGeometry * intended;
617 int *clip_width, *clip_height;
619 ViewportWidget w = (ViewportWidget)widget;
620 register Widget child = w->viewport.child;
621 XtWidgetGeometry preferred;
624 * If forcebars then needs = allows = has.
625 * Thus if needsvert is set it MUST have a scrollbar.
628 if (w->viewport.allowvert)
629 *clip_width -= w->viewport.vert_bar->core.width +
630 w->viewport.vert_bar->core.border_width;
632 if (w->viewport.allowhoriz)
633 *clip_height -= w->viewport.horiz_bar->core.height +
634 w->viewport.horiz_bar->core.border_width;
636 AssignMax( *clip_width, 1 );
637 AssignMax( *clip_height, 1 );
639 if (!w->viewport.allowvert) {
640 intended->height = *clip_height;
641 intended->request_mode = CWHeight;
643 if (!w->viewport.allowhoriz) {
644 intended->width = *clip_width;
645 intended->request_mode = CWWidth;
648 if ( query ) {
649 if ( (w->viewport.allowvert || w->viewport.allowhoriz) ) {
650 XtQueryGeometry( child, intended, &preferred );
652 if ( !(intended->request_mode & CWWidth) )
653 if ( preferred.request_mode & CWWidth )
654 intended->width = preferred.width;
655 else
656 intended->width = child->core.width;
658 if ( !(intended->request_mode & CWHeight) )
659 if ( preferred.request_mode & CWHeight )
660 intended->height = preferred.height;
661 else
662 intended->height = child->core.height;
665 else {
666 if (w->viewport.allowvert)
667 intended->height = child->core.height;
668 if (w->viewport.allowhoriz)
669 intended->width = child->core.width;
672 AssignMax(intended->width, *clip_width);
673 AssignMax(intended->height, *clip_height);
676 static void Resize(widget)
677 Widget widget;
679 ComputeLayout( widget, /*query=*/True, /*destroy=*/True );
683 /* ARGSUSED */
684 static Boolean Layout(w, width, height)
685 FormWidget w;
686 Dimension width, height;
688 ComputeLayout( (Widget)w, /*query=*/True, /*destroy=*/True );
689 w->form.preferred_width = w->core.width;
690 w->form.preferred_height = w->core.height;
691 return False;
695 static void ScrollUpDownProc(widget, closure, call_data)
696 Widget widget;
697 caddr_t closure;
698 caddr_t call_data;
700 ViewportWidget w = (ViewportWidget)closure;
701 register Widget child = w->viewport.child;
702 int pix = (int)call_data;
703 Position x, y;
705 if (child == NULL) return; /* no child to scroll. */
707 x = child->core.x - ((widget == w->viewport.horiz_bar) ? pix : 0);
708 y = child->core.y - ((widget == w->viewport.vert_bar) ? pix : 0);
709 MoveChild(w, x, y);
713 /* ARGSUSED */
714 static void ThumbProc(widget, closure, percent)
715 Widget widget;
716 caddr_t closure;
717 float *percent;
719 ViewportWidget w = (ViewportWidget)closure;
720 register Widget child = w->viewport.child;
721 Position x, y;
723 if (child == NULL) return; /* no child to scroll. */
725 if (widget == w->viewport.horiz_bar)
726 #ifdef macII /* bug in the macII A/UX 1.0 cc */
727 x = (int)(-*percent * child->core.width);
728 #else /* else not macII */
729 x = -(int)(*percent * child->core.width);
730 #endif /* macII */
731 else
732 x = child->core.x;
734 if (widget == w->viewport.vert_bar)
735 #ifdef macII /* bug in the macII A/UX 1.0 cc */
736 y = (int)(-*percent * child->core.height);
737 #else /* else not macII */
738 y = -(int)(*percent * child->core.height);
739 #endif /* macII */
740 else
741 y = child->core.y;
743 MoveChild(w, x, y);
747 static XtGeometryResult GeometryManager(child, request, reply)
748 Widget child;
749 XtWidgetGeometry *request, *reply;
751 ViewportWidget w = (ViewportWidget)child->core.parent;
752 Boolean rWidth = (Boolean)(request->request_mode & CWWidth);
753 Boolean rHeight = (Boolean)(request->request_mode & CWHeight);
754 XtWidgetGeometry allowed;
755 XtGeometryResult result;
756 Boolean reconfigured;
757 Dimension height_remaining;
759 if (child != w->viewport.child
760 || request->request_mode & ~(CWWidth | CWHeight | CWBorderWidth)
761 || ((request->request_mode & CWBorderWidth)
762 && request->border_width > 0))
763 return XtGeometryNo;
765 allowed = *request;
768 reconfigured = GetGeometry( (Widget)w,
769 (rWidth ? request->width : w->core.width),
770 (rHeight ? request->height : w->core.height)
773 height_remaining = w->core.height;
774 if (rWidth && w->core.width != request->width) {
775 if (w->viewport.allowhoriz && request->width > w->core.width) {
776 /* horizontal scrollbar will be needed so possibly reduce height */
777 Widget bar;
778 if ((bar = w->viewport.horiz_bar) == (Widget)NULL)
779 bar = CreateScrollbar( w, True );
780 height_remaining -= bar->core.height + bar->core.border_width;
781 reconfigured = True;
783 else {
784 allowed.width = w->core.width;
787 if (rHeight && height_remaining != request->height) {
788 if (w->viewport.allowvert && request->height > height_remaining) {
789 /* vertical scrollbar will be needed, so possibly reduce width */
790 if (!w->viewport.allowhoriz || request->width < w->core.width) {
791 Widget bar;
792 if ((bar = w->viewport.vert_bar) == (Widget)NULL)
793 bar = CreateScrollbar( w, False );
794 if (!rWidth) {
795 allowed.width = w->core.width;
796 allowed.request_mode |= CWWidth;
798 if (allowed.width > (bar->core.width + bar->core.border_width))
799 allowed.width -= bar->core.width + bar->core.border_width;
800 else
801 allowed.width = 1;
802 reconfigured = True;
805 else {
806 allowed.height = height_remaining;
810 if (allowed.width != request->width || allowed.height != request->height) {
811 *reply = allowed;
812 result = XtGeometryAlmost;
814 else {
815 if (rWidth) child->core.width = request->width;
816 if (rHeight) child->core.height = request->height;
817 result = XtGeometryYes;
820 if (reconfigured)
821 ComputeLayout( (Widget)w,
822 /*query=*/ False,
823 /*destroy=*/ (result == XtGeometryYes) ? True : False );
825 return result;
829 static Boolean GetGeometry(w, width, height)
830 Widget w;
831 Dimension width, height;
833 XtWidgetGeometry geometry;
834 XtGeometryResult result;
836 if (width == w->core.width && height == w->core.height)
837 return False;
839 geometry.request_mode = CWWidth | CWHeight;
840 geometry.width = width;
841 geometry.height = height;
843 if (XtIsRealized(w)) {
844 if (((ViewportWidget)w)->viewport.allowhoriz && width > w->core.width)
845 geometry.width = w->core.width;
846 if (((ViewportWidget)w)->viewport.allowvert && height > w->core.height)
847 geometry.height = w->core.height;
848 } else {
849 /* This is the Realize call; we'll inherit a w&h iff none currently */
850 if (w->core.width != 0) {
851 if (w->core.height != 0) return False;
852 geometry.width = w->core.width;
854 if (w->core.height != 0) geometry.height = w->core.height;
856 if ((result = XtMakeGeometryRequest(w, &geometry, &geometry))
857 == XtGeometryAlmost)
858 result = XtMakeGeometryRequest(w, &geometry, NULL);
860 return (result == XtGeometryYes);
863 static XtGeometryResult PreferredGeometry(w, constraints, reply)
864 Widget w;
865 XtWidgetGeometry *constraints, *reply;
867 if (((ViewportWidget)w)->viewport.child != NULL)
868 return XtQueryGeometry( ((ViewportWidget)w)->viewport.child,
869 constraints, reply );
870 else
871 return XtGeometryYes;