1 /* $XConsortium: Form.c,v 1.52 94/04/17 20:12:06 kaleb Exp $ */
2
3 /***********************************************************
4
5 Copyright (c) 1987, 1988, 1994 X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27
28
29 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
30
31 All Rights Reserved
32
33 Permission to use, copy, modify, and distribute this software and its
34 documentation for any purpose and without fee is hereby granted,
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in
37 supporting documentation, and that the name of Digital not be
38 used in advertising or publicity pertaining to distribution of the
39 software without specific, written prior permission.
40
41 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
43 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
44 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
45 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 SOFTWARE.
48
49 ******************************************************************/
50
51 /* $XFree86: xc/lib/Xaw/Form.c,v 1.1.1.1.12.2 1998/05/16 09:05:19 dawes Exp $ */
52
53 #include <X11/IntrinsicP.h>
54 #include <X11/StringDefs.h>
55 #include <X11/Xmu/Converters.h>
56 #include <X11/Xmu/CharSet.h>
57 #include "XawInit.h"
58 #include "FormP.h"
59 #include "Misc.h"
60
61 /* Private Definitions */
62
63 static int default_value = -99999;
64
65 #define Offset(field) XtOffsetOf(FormRec, form.field)
66 static XtResource resources[] = {
67 {XtNdefaultDistance, XtCThickness, XtRInt, sizeof(int),
68 Offset(default_spacing), XtRImmediate, (XtPointer)4},
69 #ifdef XPM_TILE
70 {XtNbackgroundTile, XtCBackgroundTile, XtRTilePixmap, sizeof(Pixmap),
71 Offset(background_tile), XtRImmediate, (XtPointer)None}
72 #endif
73 };
74 #undef Offset
75
76 static XtEdgeType defEdge = XtRubber;
77
78 #define Offset(field) XtOffsetOf(FormConstraintsRec, form.field)
79 static XtResource formConstraintResources[] = {
80 {XtNtop, XtCEdge, XtREdgeType, sizeof(XtEdgeType),
81 Offset(top), XtREdgeType, (XtPointer)&defEdge},
82 {XtNbottom, XtCEdge, XtREdgeType, sizeof(XtEdgeType),
83 Offset(bottom), XtREdgeType, (XtPointer)&defEdge},
84 {XtNleft, XtCEdge, XtREdgeType, sizeof(XtEdgeType),
85 Offset(left), XtREdgeType, (XtPointer)&defEdge},
86 {XtNright, XtCEdge, XtREdgeType, sizeof(XtEdgeType),
87 Offset(right), XtREdgeType, (XtPointer)&defEdge},
88 {XtNhorizDistance, XtCThickness, XtRInt, sizeof(int),
89 Offset(dx), XtRInt, (XtPointer) &default_value},
90 {XtNfromHoriz, XtCWidget, XtRWidget, sizeof(Widget),
91 Offset(horiz_base), XtRWidget, (XtPointer)NULL},
92 {XtNvertDistance, XtCThickness, XtRInt, sizeof(int),
93 Offset(dy), XtRInt, (XtPointer) &default_value},
94 {XtNfromVert, XtCWidget, XtRWidget, sizeof(Widget),
95 Offset(vert_base), XtRWidget, (XtPointer)NULL},
96 {XtNresizable, XtCBoolean, XtRBoolean, sizeof(Boolean),
97 Offset(allow_resize), XtRImmediate, (XtPointer) FALSE},
98 };
99 #undef Offset
100
101 static void ClassInitialize(), ClassPartInitialize(), Initialize(), Resize();
102 static void ConstraintInitialize();
103 static Boolean SetValues(), ConstraintSetValues();
104 static XtGeometryResult GeometryManager(), PreferredGeometry();
105 static void ChangeManaged();
106 static Boolean Layout();
107 #ifdef XPM_TILE
108 static void Realize();
109 #endif
110 static void LayoutChild(), ResizeChildren();
111
112 FormClassRec formClassRec = {
113 { /* core_class fields */
114 /* superclass */ (WidgetClass) &constraintClassRec,
115 /* class_name */ "Form",
116 /* widget_size */ sizeof(FormRec),
117 /* class_initialize */ ClassInitialize,
118 /* class_part_init */ ClassPartInitialize,
119 /* class_inited */ FALSE,
120 /* initialize */ Initialize,
121 /* initialize_hook */ NULL,
122 #ifdef XPM_TILE
123 /* realize */ Realize,
124 #else
125 /* realize */ XtInheritRealize,
126 #endif
127 /* actions */ NULL,
128 /* num_actions */ 0,
129 /* resources */ resources,
130 /* num_resources */ XtNumber(resources),
131 /* xrm_class */ NULLQUARK,
132 /* compress_motion */ TRUE,
133 /* compress_exposure */ TRUE,
134 /* compress_enterleave*/ TRUE,
135 /* visible_interest */ FALSE,
136 /* destroy */ NULL,
137 /* resize */ Resize,
138 /* expose */ XtInheritExpose,
139 /* set_values */ SetValues,
140 /* set_values_hook */ NULL,
141 /* set_values_almost */ XtInheritSetValuesAlmost,
142 /* get_values_hook */ NULL,
143 /* accept_focus */ NULL,
144 /* version */ XtVersion,
145 /* callback_private */ NULL,
146 /* tm_table */ NULL,
147 /* query_geometry */ PreferredGeometry,
148 /* display_accelerator*/ XtInheritDisplayAccelerator,
149 /* extension */ NULL
150 },
151 { /* composite_class fields */
152 /* geometry_manager */ GeometryManager,
153 /* change_managed */ ChangeManaged,
154 /* insert_child */ XtInheritInsertChild,
155 /* delete_child */ XtInheritDeleteChild,
156 /* extension */ NULL
157 },
158 { /* constraint_class fields */
159 /* subresourses */ formConstraintResources,
160 /* subresource_count */ XtNumber(formConstraintResources),
161 /* constraint_size */ sizeof(FormConstraintsRec),
162 /* initialize */ ConstraintInitialize,
163 /* destroy */ NULL,
164 /* set_values */ ConstraintSetValues,
165 /* extension */ NULL
166 },
167 { /* form_class fields */
168 /* layout */ Layout
169 }
170 };
171
172 WidgetClass formWidgetClass = (WidgetClass)&formClassRec;
173
174 /****************************************************************
175 *
176 * Private Procedures
177 *
178 ****************************************************************/
179
180
181 static XrmQuark XtQChainLeft, XtQChainRight, XtQChainTop,
182 XtQChainBottom, XtQRubber;
183
184 /* ARGSUSED */
_CvtStringToEdgeType(args,num_args,fromVal,toVal)185 static void _CvtStringToEdgeType(args, num_args, fromVal, toVal)
186 XrmValuePtr args; /* unused */
187 Cardinal *num_args; /* unused */
188 XrmValuePtr fromVal;
189 XrmValuePtr toVal;
190 {
191 static XtEdgeType edgeType;
192 XrmQuark q;
193 char lowerName[40];
194
195 if (strlen ((char*) fromVal->addr) < sizeof lowerName) {
196 XmuCopyISOLatin1Lowered (lowerName, (char*)fromVal->addr);
197 q = XrmStringToQuark(lowerName);
198 if (q == XtQChainLeft) edgeType = XtChainLeft;
199 else if (q == XtQChainRight) edgeType = XtChainRight;
200 else if (q == XtQChainTop) edgeType = XtChainTop;
201 else if (q == XtQChainBottom) edgeType = XtChainBottom;
202 else if (q == XtQRubber) edgeType = XtRubber;
203 else {
204 toVal->size = 0;
205 toVal->addr = NULL;
206 return;
207 }
208 toVal->size = sizeof edgeType;
209 toVal->addr = (XPointer) &edgeType;
210 return;
211 }
212 toVal->addr = NULL;
213 toVal->size = 0;
214 }
215
ClassInitialize()216 static void ClassInitialize()
217 {
218 #ifdef XPM_TILE
219 static XtConvertArgRec convertArg[] = {
220 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
221 sizeof(Screen *)},
222 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
223 sizeof(Colormap)}
224 };
225 #endif
226 static XtConvertArgRec parentCvtArgs[] = {
227 {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
228 sizeof(Widget)}
229 };
230 XawInitializeWidgetSet();
231 XtQChainLeft = XrmPermStringToQuark("chainleft");
232 XtQChainRight = XrmPermStringToQuark("chainright");
233 XtQChainTop = XrmPermStringToQuark("chaintop");
234 XtQChainBottom = XrmPermStringToQuark("chainbottom");
235 XtQRubber = XrmPermStringToQuark("rubber");
236
237 XtAddConverter( XtRString, XtREdgeType, _CvtStringToEdgeType,
238 (XtConvertArgList)NULL, 0 );
239 XtSetTypeConverter (XtRString, XtRWidget, XmuNewCvtStringToWidget,
240 parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
241 (XtDestructor)NULL);
242 #ifdef XPM_TILE
243 XtSetTypeConverter(XtRString, XtRTilePixmap, neXtawcvtStringToTilePixmap,
244 convertArg, XtNumber(convertArg),
245 XtCacheByDisplay, (XtDestructor)NULL);
246 #endif
247 }
248
ClassPartInitialize(class)249 static void ClassPartInitialize(class)
250 WidgetClass class;
251 {
252 FormWidgetClass c = (FormWidgetClass)class;
253 FormWidgetClass super = (FormWidgetClass)
254 c->core_class.superclass;
255
256 if (c->form_class.layout == XtInheritLayout)
257 c->form_class.layout = super->form_class.layout;
258 }
259
260 /* ARGSUSED */
Initialize(request,new,args,num_args)261 static void Initialize(request, new, args, num_args)
262 Widget request, new;
263 ArgList args;
264 Cardinal *num_args;
265 {
266 FormWidget fw = (FormWidget)new;
267
268 fw->form.old_width = fw->core.width;
269 fw->form.old_height = fw->core.height;
270 fw->form.no_refigure = False;
271 fw->form.needs_relayout = False;
272 fw->form.resize_in_layout = True;
273 fw->form.resize_is_no_op = False;
274 }
275
276
277 #ifdef XPM_TILE
Realize(widget,value_mask,attributes)278 static void Realize(widget, value_mask, attributes)
279 Widget widget;
280 XtValueMask *value_mask;
281 XSetWindowAttributes *attributes;
282 {
283 FormWidget w = (FormWidget) widget;
284 (*((WidgetClass)&constraintClassRec)->core_class.realize)(widget,value_mask,attributes);
285 if (w->form.background_tile!=None) {
286 XSetWindowBackgroundPixmap(XtDisplay(widget), XtWindow(widget),
287 w->form.background_tile);
288 XClearWindow(XtDisplay(widget), XtWindow(widget));
289 }
290 }
291 #endif
292
293
294 /* Function Name: ChangeFormGeometry
295 * Description: Ask the parent to change the form widget's geometry.
296 * Arguments: w - the Form widget.
297 * query_only - TRUE if this is only a query.
298 * width, height - the new width and height.
299 * ret_width, ret_height - the actual size the form is allowed
300 * to resize to.
301 * Returns: TRUE of children may always be resized.
302 */
303
304 static Boolean
ChangeFormGeometry(w,query_only,width,height,ret_width,ret_height)305 ChangeFormGeometry(w, query_only, width, height, ret_width, ret_height)
306 Widget w;
307 Boolean query_only;
308 Dimension width, height;
309 Dimension *ret_width, *ret_height;
310 {
311 FormWidget fw = (FormWidget) w;
312 Boolean always_resize_children;
313 XtGeometryResult result;
314 XtWidgetGeometry request, return_request;
315
316 /*
317 * If we are already at the desired size then there is no need
318 * to ask our parent of we can change size.
319 */
320
321 if ( (width == fw->core.width) && (height == fw->core.height) )
322 return(TRUE);
323
324 request.width = width;
325 request.height = height;
326 request.request_mode = CWWidth | CWHeight;
327 if (query_only)
328 request.request_mode |= XtCWQueryOnly;
329
330 /*
331 * Do no invoke the resize rules if our size changes here.
332 */
333
334 fw->form.resize_is_no_op = TRUE;
335
336 result = XtMakeGeometryRequest(w, &request, &return_request);
337 if (result == XtGeometryAlmost) {
338 request = return_request;
339 (void) XtMakeGeometryRequest(w, &request, &return_request);
340 always_resize_children = FALSE;
341 }
342 else
343 always_resize_children = (result == XtGeometryYes);
344
345 fw->form.resize_is_no_op = FALSE;
346
347 if (ret_width != NULL)
348 *ret_width = request.width;
349 if (ret_height != NULL)
350 *ret_height = request.height;
351
352 return(always_resize_children);
353 }
354
355 /* Function Name: Layout
356 * Description: Moves all the children around.
357 * Arguments: fw - the Form widget.
358 * width, height - ** UNUSED **.
359 * force_relayout - will force the children to be
360 * moved, even if some go past the edge
361 * of the form.
362 * Returns: True if the children are allowed to move from their
363 * current locations to the new ones.
364 */
365
366 /* ARGSUSED */
Layout(fw,width,height,force_relayout)367 static Boolean Layout(fw, width, height, force_relayout)
368 FormWidget fw;
369 Dimension width, height;
370 Boolean force_relayout;
371 {
372 int num_children = fw->composite.num_children;
373 WidgetList children = fw->composite.children;
374 Widget *childP;
375 Dimension maxx, maxy;
376 Boolean ret_val;
377
378 for (childP = children; childP - children < num_children; childP++) {
379 FormConstraints form = (FormConstraints)(*childP)->core.constraints;
380 form->form.layout_state = LayoutPending;
381 }
382
383 maxx = maxy = 1;
384 for (childP = children; childP - children < num_children; childP++) {
385 if (XtIsManaged(*childP)) {
386 FormConstraints form;
387 Position x, y;
388
389 form = (FormConstraints)(*childP)->core.constraints;
390
391 LayoutChild(*childP);
392
393 x = form->form.new_x + (*childP)->core.width +
394 ((*childP)->core.border_width << 1);
395 if (x > (int)maxx)
396 maxx = x;
397
398 y = form->form.new_y + (*childP)->core.height +
399 ((*childP)->core.border_width << 1);
400 if (y > (int)maxy)
401 maxy = y;
402 }
403 }
404
405 fw->form.preferred_width = (maxx += fw->form.default_spacing);
406 fw->form.preferred_height = (maxy += fw->form.default_spacing);
407
408 if (fw->form.resize_in_layout) {
409 Boolean always_resize_children;
410
411 always_resize_children =
412 ChangeFormGeometry( (Widget) fw, FALSE, maxx, maxy,
413 (Dimension *)NULL, (Dimension *)NULL);
414
415 fw->form.old_width = fw->core.width;
416 fw->form.old_height = fw->core.height;
417
418 ret_val = (always_resize_children || ( (fw->core.width >= maxx) &&
419 (fw->core.height >= maxy)));
420
421 if (force_relayout)
422 ret_val = TRUE;
423
424 if (ret_val)
425 ResizeChildren((Widget) fw);
426 }
427 else
428 ret_val = False;
429
430 fw->form.needs_relayout = False;
431 return ret_val;
432 }
433
434 /* Function Name: ResizeChildren
435 * Description: Resizes all children to new_x and new_y.
436 * Arguments: w - the form widget.
437 * Returns: none.
438 */
439
ResizeChildren(w)440 static void ResizeChildren(w)
441 Widget w;
442 {
443 FormWidget fw = (FormWidget) w;
444 int num_children = fw->composite.num_children;
445 WidgetList children = fw->composite.children;
446 Widget *childP;
447
448 for (childP = children; childP - children < num_children; childP++) {
449 FormConstraints form;
450
451 if (!XtIsManaged(*childP))
452 continue;
453
454 form = (FormConstraints)(*childP)->core.constraints;
455 if (fw->form.no_refigure) {
456 /*
457 * I am changing the widget wrapper w/o modifing the window. This is
458 * risky, but I can get away with it since I am the parent of this
459 * widget, and he must ask me for any geometry changes.
460 *
461 * The window will be updated when no_refigure is set back to False.
462 */
463 (*childP)->core.x = form->form.new_x;
464 (*childP)->core.y = form->form.new_y;
465 }
466 else
467 XtMoveWidget(*childP, form->form.new_x, form->form.new_y);
468 }
469 }
470
471
LayoutChild(w)472 static void LayoutChild(w)
473 Widget w;
474 {
475 FormConstraints form = (FormConstraints)w->core.constraints;
476 Widget ref;
477
478 switch (form->form.layout_state) {
479
480 case LayoutPending:
481 form->form.layout_state = LayoutInProgress;
482 break;
483
484 case LayoutDone:
485 return;
486
487 case LayoutInProgress:
488 {
489 String subs[2];
490 Cardinal num_subs = 2;
491 subs[0] = w->core.name;
492 subs[1] = w->core.parent->core.name;
493 XtAppWarningMsg(XtWidgetToApplicationContext(w),
494 "constraintLoop","xawFormLayout","XawToolkitError",
495 "constraint loop detected while laying out child '%s' in FormWidget '%s'",
496 subs, &num_subs);
497 return;
498 }
499 }
500
501 form->form.new_x = form->form.dx;
502 form->form.new_y = form->form.dy;
503 if ((ref = form->form.horiz_base) != (Widget)NULL) {
504 FormConstraints ref_form = (FormConstraints) ref->core.constraints;
505
506 LayoutChild(ref);
507 form->form.new_x += (ref_form->form.new_x +
508 ref->core.width + (ref->core.border_width << 1));
509 }
510 if ((ref = form->form.vert_base) != (Widget)NULL) {
511 FormConstraints ref_form = (FormConstraints) ref->core.constraints;
512
513 LayoutChild(ref);
514 form->form.new_y += (ref_form->form.new_y +
515 ref->core.height + (ref->core.border_width << 1));
516 }
517
518 form->form.layout_state = LayoutDone;
519 }
520
521
TransformCoord(loc,old,new,type)522 static Position TransformCoord(loc, old, new, type)
523 Position loc;
524 Dimension old, new;
525 XtEdgeType type;
526 {
527 if (type == XtRubber) {
528 if ( ((int) old) > 0)
529 loc = (int)(loc * new) / (int)old;
530 }
531 else if (type == XtChainBottom || type == XtChainRight)
532 loc += (Position)new - (Position)old;
533
534 /* I don't see any problem with returning values less than zero. */
535
536 return (loc);
537 }
538
Resize(w)539 static void Resize(w)
540 Widget w;
541 {
542 FormWidget fw = (FormWidget)w;
543 WidgetList children = fw->composite.children;
544 int num_children = fw->composite.num_children;
545 Widget *childP;
546 Position x, y;
547 Dimension width, height;
548
549 if (!fw->form.resize_is_no_op)
550 for (childP = children; childP - children < num_children; childP++) {
551 FormConstraints form= (FormConstraints)(*childP)->core.constraints;
552 if (!XtIsManaged(*childP)) continue;
553 x = TransformCoord( (*childP)->core.x, fw->form.old_width,
554 fw->core.width, form->form.left );
555 y = TransformCoord( (*childP)->core.y, fw->form.old_height,
556 fw->core.height, form->form.top );
557
558 form->form.virtual_width =
559 TransformCoord((Position)((*childP)->core.x
560 + form->form.virtual_width
561 + 2 * (*childP)->core.border_width),
562 fw->form.old_width, fw->core.width,
563 form->form.right )
564 - (x + 2 * (*childP)->core.border_width);
565
566 form->form.virtual_height =
567 TransformCoord((Position)((*childP)->core.y
568 + form->form.virtual_height
569 + 2 * (*childP)->core.border_width),
570 fw->form.old_height, fw->core.height,
571 form->form.bottom )
572 - ( y + 2 * (*childP)->core.border_width);
573
574 width = (Dimension)
575 (form->form.virtual_width < 1) ? 1 : form->form.virtual_width;
576 height = (Dimension)
577 (form->form.virtual_height < 1) ? 1 : form->form.virtual_height;
578
579 XtConfigureWidget(*childP,x,y, (Dimension)width, (Dimension)height,
580 (*childP)->core.border_width );
581 }
582
583 fw->form.old_width = fw->core.width;
584 fw->form.old_height = fw->core.height;
585 }
586
587 /*
588 * I don't want to even think about what ``Almost'' would mean - Chris.
589 */
590
591 /* ARGSUSED */
GeometryManager(w,request,reply)592 static XtGeometryResult GeometryManager(w, request, reply)
593 Widget w;
594 XtWidgetGeometry *request;
595 XtWidgetGeometry *reply; /* RETURN */
596 {
597 Dimension old_width, old_height;
598 FormWidget fw = (FormWidget) XtParent(w);
599 FormConstraints form = (FormConstraints) w->core.constraints;
600 XtWidgetGeometry allowed;
601 XtGeometryResult ret_val;
602
603 if ((request->request_mode & ~(XtCWQueryOnly | CWWidth | CWHeight)) ||
604 !form->form.allow_resize) {
605
606 /* If GeometryManager is invoked during a SetValues call on a child
607 * then it is necessary to compute a new layout if ConstraintSetValues
608 * allowed any constraint changes. */
609
610 if (fw->form.needs_relayout)
611 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
612 (fw, 0, 0, True);
613 return(XtGeometryNo);
614 }
615
616 if (request->request_mode & CWWidth)
617 allowed.width = request->width;
618 else
619 allowed.width = w->core.width;
620
621 if (request->request_mode & CWHeight)
622 allowed.height = request->height;
623 else
624 allowed.height = w->core.height;
625
626 if (allowed.width == w->core.width && allowed.height == w->core.height) {
627
628 /* If GeometryManager is invoked during a SetValues call on a child
629 * then it is necessary to compute a new layout if ConstraintSetValues
630 * allowed any constraint changes. */
631
632 if (fw->form.needs_relayout)
633 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
634 (fw, 0, 0, True);
635 return(XtGeometryNo);
636 }
637
638 /*
639 * Remember the old size, and then set the size to the requested size.
640 */
641
642 old_width = w->core.width;
643 old_height = w->core.height;
644 w->core.width = allowed.width;
645 w->core.height = allowed.height;
646
647 if (request->request_mode & XtCWQueryOnly) {
648 Boolean always_resize_children;
649 Dimension ret_width, ret_height;
650
651 fw->form.resize_in_layout = FALSE;
652
653 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
654 ( fw, w->core.width, w->core.height,
655 FALSE );
656
657 /*
658 * Reset the size of this child back to what it used to be.
659 */
660
661 w->core.width = old_width;
662 w->core.height = old_height;
663
664 fw->form.resize_in_layout = TRUE;
665
666 always_resize_children = ChangeFormGeometry(w, TRUE,
667 fw->form.preferred_width,
668 fw->form.preferred_height,
669 &ret_width, &ret_height);
670
671 if (always_resize_children ||
672 ((ret_width >= fw->form.preferred_width) &&
673 (ret_height >= fw->form.preferred_height)))
674 {
675 ret_val = XtGeometryYes;
676 }
677 else
678 ret_val = XtGeometryNo;
679 }
680 else {
681 if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
682 ( fw, w->core.width, w->core.height,
683 FALSE))
684 {
685 form->form.virtual_width = w->core.width; /* reset virtual */
686 form->form.virtual_height = w->core.height; /* width and height. */
687 if (fw->form.no_refigure) {
688 /*
689 * I am changing the widget wrapper w/o modifing the window. This is
690 * risky, but I can get away with it since I am the parent of this
691 * widget, and he must ask me for any geometry changes.
692 *
693 * The window will be updated when no_refigure is set back to False.
694 */
695 form->form.deferred_resize = True;
696 ret_val = XtGeometryDone;
697 }
698 else
699 ret_val = XtGeometryYes;
700 }
701 else {
702 w->core.width = old_width;
703 w->core.height = old_height;
704 ret_val = XtGeometryNo;
705 }
706 }
707
708 return(ret_val);
709 }
710
711
712 /* ARGSUSED */
SetValues(current,request,new,args,num_args)713 static Boolean SetValues(current, request, new, args, num_args)
714 Widget current, request, new;
715 ArgList args;
716 Cardinal *num_args;
717 {
718 return( FALSE );
719 }
720
721
722 /* ARGSUSED */
ConstraintInitialize(request,new,args,num_args)723 static void ConstraintInitialize(request, new, args, num_args)
724 Widget request, new;
725 ArgList args;
726 Cardinal *num_args;
727 {
728 FormConstraints form = (FormConstraints)new->core.constraints;
729 FormWidget fw = (FormWidget)new->core.parent;
730
731 form->form.virtual_width = (int) new->core.width;
732 form->form.virtual_height = (int) new->core.height;
733
734 if (form->form.dx == default_value)
735 form->form.dx = fw->form.default_spacing;
736
737 if (form->form.dy == default_value)
738 form->form.dy = fw->form.default_spacing;
739
740 form->form.deferred_resize = False;
741 }
742
743 /*ARGSUSED*/
ConstraintSetValues(current,request,new,args,num_args)744 static Boolean ConstraintSetValues(current, request, new, args, num_args)
745 Widget current, request, new;
746 ArgList args;
747 Cardinal *num_args;
748 {
749 FormConstraints cfc = (FormConstraints) current->core.constraints;
750 FormConstraints nfc = (FormConstraints) new->core.constraints;
751
752 if (cfc->form.top != nfc->form.top ||
753 cfc->form.bottom != nfc->form.bottom ||
754 cfc->form.left != nfc->form.left ||
755 cfc->form.right != nfc->form.right ||
756 cfc->form.dx != nfc->form.dx ||
757 cfc->form.dy != nfc->form.dy ||
758 cfc->form.horiz_base != nfc->form.horiz_base ||
759 cfc->form.vert_base != nfc->form.vert_base) {
760
761 FormWidget fp = (FormWidget) XtParent(new);
762
763 /* If there are no subclass ConstraintSetValues procedures remaining
764 * to be invoked, and if there is no geometry request about to be
765 * made, then invoke the new layout now; else defer it. */
766
767 if (XtClass(XtParent(new)) == formWidgetClass &&
768 current->core.x == new->core.x &&
769 current->core.y == new->core.y &&
770 current->core.width == new->core.width &&
771 current->core.height == new->core.height &&
772 current->core.border_width == new->core.border_width)
773 Layout(fp, 0, 0, True);
774 else fp->form.needs_relayout = True;
775 }
776 return( FALSE );
777 }
778
ChangeManaged(w)779 static void ChangeManaged(w)
780 Widget w;
781 {
782 FormWidget fw = (FormWidget)w;
783 FormConstraints form;
784 WidgetList children, childP;
785 int num_children = fw->composite.num_children;
786 Widget child;
787
788 /*
789 * Reset virtual width and height for all children.
790 */
791
792 for (children = childP = fw->composite.children ;
793 childP - children < num_children; childP++) {
794 child = *childP;
795 if (XtIsManaged(child)) {
796 form = (FormConstraints)child->core.constraints;
797
798 /*
799 * If the size is one (1) then we must not change the virtual sizes, as
800 * they contain useful information. If someone actually wants a widget of
801 * width or height one (1) in a form widget he will lose, can't win them all.
802 *
803 * Chris D. Peterson 2/9/89.
804 */
805
806 if ( child->core.width != 1)
807 form->form.virtual_width = (int) child->core.width;
808 if ( child->core.height != 1)
809 form->form.virtual_height = (int) child->core.height;
810 }
811 }
812 (*((FormWidgetClass)w->core.widget_class)->form_class.layout)
813 ((FormWidget) w, w->core.width,
814 w->core.height, TRUE);
815 }
816
817
PreferredGeometry(widget,request,reply)818 static XtGeometryResult PreferredGeometry( widget, request, reply )
819 Widget widget;
820 XtWidgetGeometry *request, *reply;
821 {
822 FormWidget w = (FormWidget)widget;
823
824 reply->width = w->form.preferred_width;
825 reply->height = w->form.preferred_height;
826 reply->request_mode = CWWidth | CWHeight;
827 if ( (request->request_mode & (CWWidth | CWHeight)) ==
828 (CWWidth | CWHeight)
829 && request->width == reply->width
830 && request->height == reply->height)
831 return XtGeometryYes;
832 else if (reply->width == w->core.width && reply->height == w->core.height)
833 return XtGeometryNo;
834 else
835 return XtGeometryAlmost;
836 }
837
838
839 /**********************************************************************
840 *
841 * Public routines
842 *
843 **********************************************************************/
844
845 /*
846 * Set or reset figuring (ignored if not realized)
847 */
848
849 void
850 #if NeedFunctionPrototypes
XawFormDoLayout(Widget w,int doit)851 XawFormDoLayout(Widget w,
852 #if NeedWidePrototypes
853 int doit)
854 #else
855 Boolean doit)
856 #endif
857 #else
858 XawFormDoLayout(w, doit)
859 Widget w;
860 Boolean doit;
861 #endif
862 {
863 Widget *childP;
864 FormWidget fw = (FormWidget)w;
865 int num_children = fw->composite.num_children;
866 WidgetList children = fw->composite.children;
867
868 if ( ((fw->form.no_refigure = !doit) == TRUE) || !XtIsRealized(w) )
869 return;
870
871 for (childP = children; childP - children < num_children; childP++) {
872 Widget w = *childP;
873 if (XtIsManaged(w)) {
874 FormConstraints form = (FormConstraints)w->core.constraints;
875
876 /*
877 * Xt Configure widget is too smart, and optimizes out
878 * my changes.
879 */
880
881 XMoveResizeWindow(XtDisplay(w), XtWindow(w),
882 w->core.x, w->core.y,
883 w->core.width, w->core.height);
884
885 if (form->form.deferred_resize &&
886 XtClass(w)->core_class.resize != (XtWidgetProc) NULL) {
887 (*(XtClass(w)->core_class.resize))(w);
888 form->form.deferred_resize = False;
889 }
890 }
891 }
892 }
893