upload tizen2.0 source
[framework/uifw/xorg/lib/libxaw.git] / src / Form.c
1 /***********************************************************
2
3 Copyright 1987, 1988, 1994, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                         All Rights Reserved
29
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
37
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
45
46 ******************************************************************/
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51 #include <X11/IntrinsicP.h>
52 #include <X11/StringDefs.h>
53 #include <X11/Xmu/CharSet.h>
54 #include <X11/Xmu/Converters.h>
55 #include <X11/Xaw/FormP.h>
56 #include <X11/Xaw/XawInit.h>
57 #include "Private.h"
58
59 /*
60  * Class Methods
61  */
62 static void XawFormChangeManaged(Widget);
63 static void XawFormClassInitialize(void);
64 static void XawFormClassPartInitialize(WidgetClass);
65 static void XawFormConstraintInitialize(Widget, Widget, ArgList, Cardinal*);
66 static Boolean XawFormConstraintSetValues(Widget, Widget, Widget,
67                                           ArgList, Cardinal*);
68 static XtGeometryResult XawFormGeometryManager(Widget, XtWidgetGeometry*,
69                                                XtWidgetGeometry*);
70 static void XawFormInitialize(Widget, Widget, ArgList, Cardinal*);
71 #ifndef OLDXAW
72 static void XawFormRealize(Widget, Mask*, XSetWindowAttributes*);
73 static void XawFormRedisplay(Widget, XEvent*, Region);
74 #endif
75 static XtGeometryResult XawFormQueryGeometry(Widget, XtWidgetGeometry*,
76                                              XtWidgetGeometry*);
77 static void XawFormResize(Widget);
78 static Boolean XawFormSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
79 static Boolean Layout(FormWidget, unsigned int, unsigned int, Bool);
80
81 /*
82  * Prototypes
83  */
84 static void _CvtStringToEdgeType(XrmValuePtr, Cardinal*,
85                                  XrmValuePtr, XrmValuePtr);
86 static Bool ChangeFormGeometry(Widget, Bool, unsigned int, unsigned int,
87                                Dimension*, Dimension*);
88 Boolean CvtEdgeTypeToString(Display*, XrmValuePtr, Cardinal*,
89                             XrmValuePtr, XrmValuePtr, XtPointer*);
90 static void LayoutChild(Widget);
91 static int TransformCoord(int, unsigned int, unsigned int, XtEdgeType);
92 static void ResizeChildren(Widget);
93
94 /*
95  * Initialization
96  */
97 #ifndef OLDXAW
98 static XtActionsRec actions[] = {
99   {"set-values", XawSetValuesAction},
100   {"get-values", XawGetValuesAction},
101   {"declare",    XawDeclareAction},
102   {"call-proc",  XawCallProcAction},
103 };
104 #endif
105
106 static XrmQuark QchainLeft, QchainRight, QchainTop, QchainBottom, Qrubber;
107
108 #define default_value   -99999
109 #define Offset(field) XtOffsetOf(FormRec, form.field)
110 static XtResource resources[] = {
111   {
112     XtNdefaultDistance,
113     XtCThickness,
114     XtRInt,
115     sizeof(int),
116     Offset(default_spacing),
117     XtRImmediate,
118     (XtPointer)4
119   },
120 #ifndef OLDXAW
121   {
122     XawNdisplayList,
123     XawCDisplayList,
124     XawRDisplayList,
125     sizeof(XawDisplayList*),
126     Offset(display_list),
127     XtRImmediate,
128     NULL
129   },
130 #endif
131 };
132 #undef Offset
133
134 #define defEdge         XtRubber
135
136 #define Offset(field) XtOffsetOf(FormConstraintsRec, form.field)
137 static XtResource formConstraintResources[] = {
138   {
139     XtNtop,
140     XtCEdge,
141     XtREdgeType,
142     sizeof(XtEdgeType),
143     Offset(top),
144     XtRImmediate,
145     (XtPointer)defEdge
146   },
147   {
148     XtNbottom,
149     XtCEdge,
150     XtREdgeType,
151     sizeof(XtEdgeType),
152     Offset(bottom),
153     XtRImmediate,
154     (XtPointer)defEdge
155   },
156   {
157     XtNleft,
158     XtCEdge,
159     XtREdgeType,
160     sizeof(XtEdgeType),
161     Offset(left),
162     XtRImmediate,
163     (XtPointer)defEdge
164   },
165   {
166     XtNright,
167     XtCEdge,
168     XtREdgeType,
169     sizeof(XtEdgeType),
170     Offset(right),
171     XtRImmediate,
172     (XtPointer)defEdge
173   },
174   {
175     XtNhorizDistance,
176     XtCThickness,
177     XtRInt,
178     sizeof(int),
179     Offset(dx),
180     XtRImmediate,
181     (XtPointer)default_value
182   },
183   {
184     XtNfromHoriz,
185     XtCWidget,
186     XtRWidget,
187     sizeof(Widget),
188     Offset(horiz_base),
189     XtRWidget,
190     NULL
191   },
192   {
193     XtNvertDistance,
194     XtCThickness,
195     XtRInt,
196     sizeof(int),
197     Offset(dy),
198     XtRImmediate,
199     (XtPointer)default_value
200   },
201   {
202     XtNfromVert,
203     XtCWidget,
204     XtRWidget,
205     sizeof(Widget),
206     Offset(vert_base),
207     XtRWidget,
208     NULL
209   },
210   {
211     XtNresizable,
212     XtCBoolean,
213     XtRBoolean,
214     sizeof(Boolean),
215     Offset(allow_resize),
216     XtRImmediate,
217     (XtPointer)False
218   },
219 };
220 #undef Offset
221
222 FormClassRec formClassRec = {
223   /* core */
224   {
225     (WidgetClass)&constraintClassRec,   /* superclass */
226     "Form",                             /* class_name */
227     sizeof(FormRec),                    /* widget_size */
228     XawFormClassInitialize,             /* class_initialize */
229     XawFormClassPartInitialize,         /* class_part_init */
230     False,                              /* class_inited */
231     XawFormInitialize,                  /* initialize */
232     NULL,                               /* initialize_hook */
233 #ifndef OLDXAW
234     XawFormRealize,                     /* realize */
235     actions,                            /* actions */
236     XtNumber(actions),                  /* num_actions */
237 #else
238     XtInheritRealize,                   /* realize */
239     NULL,                               /* actions */
240     0,                                  /* num_actions */
241 #endif
242     resources,                          /* resources */
243     XtNumber(resources),                /* num_resources */
244     NULLQUARK,                          /* xrm_class */
245     True,                               /* compress_motion */
246     True,                               /* compress_exposure */
247     True,                               /* compress_enterleave */
248     False,                              /* visible_interest */
249     NULL,                               /* destroy */
250     XawFormResize,                      /* resize */
251 #ifndef OLDXAW
252     XawFormRedisplay,                   /* expose */
253 #else
254     XtInheritExpose,                    /* expose */
255 #endif
256     XawFormSetValues,                   /* set_values */
257     NULL,                               /* set_values_hook */
258     XtInheritSetValuesAlmost,           /* set_values_almost */
259     NULL,                               /* get_values_hook */
260     NULL,                               /* accept_focus */
261     XtVersion,                          /* version */
262     NULL,                               /* callback_private */
263     NULL,                               /* tm_table */
264     XawFormQueryGeometry,               /* query_geometry */
265     XtInheritDisplayAccelerator,        /* display_accelerator */
266     NULL,                               /* extension */
267   },
268   /* composite */
269   {
270     XawFormGeometryManager,             /* geometry_manager */
271     XawFormChangeManaged,               /* change_managed */
272     XtInheritInsertChild,               /* insert_child */
273     XtInheritDeleteChild,               /* delete_child */
274     NULL,                               /* extension */
275   },
276   /* constraint */
277   {
278     formConstraintResources,            /* subresourses */
279     XtNumber(formConstraintResources),  /* subresource_count */
280     sizeof(FormConstraintsRec),         /* constraint_size */
281     XawFormConstraintInitialize,        /* initialize */
282     NULL,                               /* destroy */
283     XawFormConstraintSetValues,         /* set_values */
284     NULL,                               /* extension */
285   },
286   /* form */
287   {
288     Layout,                             /* layout */
289   },
290 };
291
292 WidgetClass formWidgetClass = (WidgetClass)&formClassRec;
293
294 /*
295  * Implementation
296  */
297 #ifndef OLDXAW
298 static void
299 XawFormRealize(Widget w, Mask *mask, XSetWindowAttributes *attr)
300 {
301     XawPixmap *pixmap;
302
303     (*formWidgetClass->core_class.superclass->core_class.realize)(w, mask, attr);
304
305     if (w->core.background_pixmap > XtUnspecifiedPixmap) {
306         pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
307                                       w->core.colormap, w->core.depth);
308         if (pixmap && pixmap->mask)
309             XawReshapeWidget(w, pixmap);
310     }
311 }
312
313 static void
314 XawFormRedisplay(Widget w, XEvent *event, Region region)
315 {
316     FormWidget xaw = (FormWidget)w;
317
318     if (xaw->form.display_list)
319         XawRunDisplayList(w, xaw->form.display_list, event, region);
320 }
321 #endif
322
323 /*ARGSUSED*/
324 static void
325 _CvtStringToEdgeType(XrmValuePtr args, Cardinal *num_args,
326                      XrmValuePtr fromVal, XrmValuePtr toVal)
327 {
328     static XtEdgeType edgeType;
329     XrmQuark q;
330     char name[12];
331
332     XmuNCopyISOLatin1Lowered(name, (char*)fromVal->addr, sizeof(name));
333     q = XrmStringToQuark(name);
334
335     if (q == QchainLeft)
336         edgeType = XtChainLeft;
337     else if (q == QchainRight)
338         edgeType = XtChainRight;
339     else if (q == QchainTop)
340         edgeType = XtChainTop;
341     else if (q == QchainBottom)
342         edgeType = XtChainBottom;
343     else if (q == Qrubber)
344         edgeType = XtRubber;
345     else {
346         XtStringConversionWarning(fromVal->addr, XtREdgeType);
347         toVal->size = 0;
348         toVal->addr = NULL;
349         return;
350     }
351
352     toVal->size = sizeof(XtEdgeType);
353     toVal->addr = (XPointer)&edgeType;
354 }
355
356 /*ARGSUSED*/
357 Boolean
358 CvtEdgeTypeToString(Display *dpy, XrmValuePtr args, Cardinal *num_args,
359                     XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data)
360 {
361     static String buffer;
362     Cardinal size;
363
364     switch (*(XtEdgeType *)fromVal->addr) {
365         case XtChainLeft:
366             buffer = XtEchainLeft;
367             break;
368         case XtChainRight:
369             buffer = XtEchainRight;
370             break;
371         case XtChainTop:
372             buffer = XtEchainTop;
373             break;
374         case XtChainBottom:
375             buffer = XtEchainBottom;
376             break;
377         case XtRubber:
378             buffer = XtErubber;
379             break;
380         default:
381             XawTypeToStringWarning(dpy, XtREdgeType);
382             toVal->addr = NULL;
383             toVal->size = 0;
384             return (False);
385     }
386
387     size = strlen(buffer) + 1;
388     if (toVal->addr != NULL) {
389         if (toVal->size < size) {
390             toVal->size = size;
391             return (False);
392         }
393         strcpy((char *)toVal->addr, buffer);
394     }
395     else
396         toVal->addr = (XPointer)buffer;
397     toVal->size = sizeof(String);
398
399     return (True);
400 }
401
402 static void
403 XawFormClassInitialize(void)
404 {
405     static XtConvertArgRec parentCvtArgs[] = {
406         {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
407          sizeof(Widget)}
408     };
409
410     char name[12];
411
412     XawInitializeWidgetSet();
413     XmuNCopyISOLatin1Lowered(name, XtEchainLeft, sizeof(name));
414     QchainLeft = XrmStringToQuark(name);
415     XmuNCopyISOLatin1Lowered(name, XtEchainRight, sizeof(name));
416     QchainRight = XrmStringToQuark(name);
417     XmuNCopyISOLatin1Lowered(name, XtEchainTop, sizeof(name));
418     QchainTop = XrmStringToQuark(name);
419     XmuNCopyISOLatin1Lowered(name, XtEchainBottom, sizeof(name));
420     QchainBottom = XrmStringToQuark(name);
421     XmuNCopyISOLatin1Lowered(name, XtErubber, sizeof(name));
422     Qrubber = XrmStringToQuark(name);
423
424     XtAddConverter(XtRString, XtREdgeType, _CvtStringToEdgeType, NULL, 0);
425     XtSetTypeConverter(XtREdgeType, XtRString, CvtEdgeTypeToString,
426                        NULL, 0, XtCacheNone, NULL);
427     XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
428                        parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
429                        NULL);
430     XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString,
431                        NULL, 0, XtCacheNone, NULL);
432 }
433
434 static void
435 XawFormClassPartInitialize(WidgetClass cclass)
436 {
437     FormWidgetClass c = (FormWidgetClass)cclass;
438     FormWidgetClass super = (FormWidgetClass)c->core_class.superclass;
439
440     if (c->form_class.layout == XtInheritLayout)
441         c->form_class.layout = super->form_class.layout;
442 }
443
444 /*ARGSUSED*/
445 static void
446 XawFormInitialize(Widget request, Widget cnew,
447                   ArgList args, Cardinal *num_args)
448 {
449     FormWidget fw = (FormWidget)cnew;
450
451     fw->form.old_width = fw->form.old_height = 0;
452     fw->form.no_refigure = False;
453     fw->form.needs_relayout = False;
454     fw->form.resize_in_layout = True;
455     fw->form.resize_is_no_op = False;
456 }
457
458 /*
459  * Function:
460  *      ChangeFormGeometry
461  *
462  * Parameters:
463  *      w          - Form widget
464  *      query_only - is only a query?
465  *      width      - new width and height
466  *      height     - ""
467  *      ret_width  - actual size the form is allowed to resize to (return)
468  *      ret_height - ""
469  *
470  * Description:
471  *      Ask the parent to change the form widget's geometry.
472  *
473  * Returns:
474  *      True of children may always be resized
475  */
476 static Bool
477 ChangeFormGeometry(Widget w, Bool query_only,
478                    unsigned int width, unsigned int height,
479                    Dimension *ret_width, Dimension *ret_height)
480 {
481     FormWidget fw = (FormWidget)w;
482     Boolean always_resize_children;
483     XtGeometryResult result;
484     XtWidgetGeometry request, return_request;
485
486     /*
487      * If we are already at the desired size then there is no need
488      * to ask our parent of we can change size
489      */
490     if (width == XtWidth(fw) && height == XtHeight(fw))
491         return (True);
492
493     request.width = width;
494     request.height = height;
495     request.request_mode = CWWidth | CWHeight;
496     if (query_only)
497         request.request_mode |= XtCWQueryOnly;
498
499     /*
500      * Do no invoke the resize rules if our size changes here
501      */
502     fw->form.resize_is_no_op = True;
503
504     result = XtMakeGeometryRequest(w, &request, &return_request);
505     if (result == XtGeometryAlmost) {
506         request = return_request;
507         (void)XtMakeGeometryRequest(w, &request, &return_request);
508         always_resize_children = False;
509     }
510     else
511         always_resize_children = result == XtGeometryYes;
512
513     fw->form.resize_is_no_op = False;
514
515     if (ret_width != NULL)
516         *ret_width = request.width;
517     if (ret_height != NULL)
518         *ret_height = request.height;
519
520     return (always_resize_children);
521 }
522
523 /*
524  * Function:
525  *      Layout
526  *
527  * Parameters:
528  *      fw             - Form widget
529  *      width          - unused
530  *      height         - ""
531  *      force_relayout - will force the children to be moved, even if some
532  *                       go past the edge of the form
533  *
534  * Description:
535  *      Moves all the children around.
536  *
537  * Returns:
538  *        True if the children are allowed to move from their
539  *        current locations to the new ones.
540  */
541 /*ARGSUSED*/
542 static Boolean
543 Layout(FormWidget fw, unsigned int width, unsigned int height,
544        Bool force_relayout)
545 {
546     int num_children = fw->composite.num_children;
547     WidgetList children = fw->composite.children;
548     Widget *childP;
549     Dimension maxx, maxy;
550     Boolean ret_val;
551
552     for (childP = children; childP - children < num_children; childP++) {
553         FormConstraints form = (FormConstraints)(*childP)->core.constraints;
554         form->form.layout_state = LayoutPending;
555     }
556
557     maxx = maxy = 1;
558     for (childP = children; childP - children < num_children; childP++) {
559         if (XtIsManaged(*childP)) {
560             FormConstraints form;
561             Position x, y;
562
563             form = (FormConstraints)(*childP)->core.constraints;
564
565             LayoutChild(*childP);
566
567             x = form->form.new_x + XtWidth(*childP)
568                 + (XtBorderWidth(*childP) << 1);
569             if (x > (int)maxx)
570                 maxx = x;
571
572             y = form->form.new_y + XtHeight(*childP)
573                 + (XtBorderWidth(*childP) << 1);
574             if (y > (int)maxy)
575                 maxy = y;
576         }
577     }
578
579     fw->form.preferred_width = (maxx += fw->form.default_spacing);
580     fw->form.preferred_height = (maxy += fw->form.default_spacing);
581
582     if (fw->form.resize_in_layout) {
583         Boolean always_resize_children;
584
585         always_resize_children =
586             ChangeFormGeometry((Widget)fw, False, maxx, maxy, NULL, NULL);
587
588 #ifdef OLDXAW
589         fw->form.old_width  = fw->core.width;
590         fw->form.old_height = fw->core.height;
591 #endif
592
593         if (force_relayout)
594             ret_val = True;
595         else
596             ret_val = always_resize_children ||
597                         (XtWidth(fw) >= maxx && XtHeight(fw) >= maxy);
598
599         if (ret_val)
600             ResizeChildren((Widget)fw);
601     }
602     else
603         ret_val = False;
604
605     fw->form.needs_relayout = False;
606
607     return (ret_val);
608 }
609
610 /*
611  * Function:
612  *      ResizeChildren
613  *
614  * Parameters:
615  *      w - form widget
616  *
617  * Description:
618  *      Resizes all children to new_x and new_y.
619  */
620 static void
621 ResizeChildren(Widget w)
622 {
623     FormWidget fw = (FormWidget)w;
624     int num_children = fw->composite.num_children;
625     WidgetList children = fw->composite.children;
626     Widget *childP;
627
628     for (childP = children; childP - children < num_children; childP++) {
629         FormConstraints form;
630         Position x, y;
631
632         if (!XtIsManaged(*childP))
633             continue;
634
635         form = (FormConstraints)(*childP)->core.constraints;
636
637         if (fw->form.old_width && fw->form.old_height) {
638             x = TransformCoord(form->form.new_x, fw->form.old_width,
639                                XtWidth(fw), form->form.left);
640             y = TransformCoord(form->form.new_y, fw->form.old_height,
641                                XtHeight(fw), form->form.top);
642         }
643         else {
644             x = form->form.new_x;
645             y = form->form.new_y;
646         }
647
648         if (fw->form.no_refigure) {
649            /*
650             * I am changing the widget wrapper w/o modifing the window.  This is
651             * risky, but I can get away with it since I am the parent of this
652             * widget, and he must ask me for any geometry changes
653             *
654             * The window will be updated when no_refigure is set back to False
655             */
656             XtX(*childP) = x;
657             XtY(*childP) = y;
658         }
659         else
660             XtMoveWidget(*childP, x, y);
661     }
662 }
663
664 static void
665 LayoutChild(Widget w)
666 {
667     FormConstraints form = (FormConstraints)w->core.constraints;
668     Widget ref;
669
670     switch (form->form.layout_state) {
671         case LayoutPending:
672             form->form.layout_state = LayoutInProgress;
673             break;
674         case LayoutDone:
675             return;
676         case LayoutInProgress: {
677             String subs[2];
678             Cardinal num_subs = 2;
679             subs[0] = w->core.name;
680             subs[1] = w->core.parent->core.name;
681
682             XtAppWarningMsg(XtWidgetToApplicationContext(w),
683                             "constraintLoop", "xawFormLayout", "XawToolkitError",
684                             "constraint loop detected while laying out "
685                             "child '%s' in FormWidget '%s'",
686                             subs, &num_subs);
687         }   return;
688     }
689
690     form->form.new_x = form->form.dx;
691     form->form.new_y = form->form.dy;
692     if ((ref = form->form.horiz_base) != NULL) {
693         FormConstraints ref_form = (FormConstraints)ref->core.constraints;
694
695         LayoutChild(ref);
696         form->form.new_x += ref_form->form.new_x + XtWidth(ref) +
697                             (XtBorderWidth(ref) << 1);
698     }
699     if ((ref = form->form.vert_base) != NULL) {
700         FormConstraints ref_form = (FormConstraints)ref->core.constraints;
701
702         LayoutChild(ref);
703         form->form.new_y += ref_form->form.new_y + XtHeight(ref) +
704                             (XtBorderWidth(ref) << 1);
705     }
706
707     form->form.layout_state = LayoutDone;
708 }
709
710 static int
711 TransformCoord(int loc, unsigned int old, unsigned int cnew, XtEdgeType type)
712 {
713     if (type == XtRubber) {
714         if ((int)old > 0)
715             loc = (int)(loc * ((double)cnew / (double)old));
716     }
717     else if (type == XtChainBottom || type == XtChainRight)
718         loc += (int)cnew - (int)old;
719
720     return (loc);
721 }
722
723 static void
724 XawFormResize(Widget w)
725 {
726     FormWidget fw = (FormWidget)w;
727     WidgetList children = fw->composite.children;
728     int num_children = fw->composite.num_children;
729     Widget *childP;
730     int x, y;
731     int width, height;
732     Boolean unmap = XtIsRealized(w) && w->core.mapped_when_managed &&
733                     XtIsManaged(w);
734
735     if (unmap)
736         XtUnmapWidget(w);
737
738     if (!fw->form.resize_is_no_op)
739         for (childP = children; childP - children < num_children; childP++) {
740             FormConstraints form = (FormConstraints)(*childP)->core.constraints;
741
742             if (!XtIsManaged(*childP))
743                 continue;
744
745 #ifndef OLDXAW
746             x = TransformCoord(form->form.virtual_x, fw->form.old_width,
747                               XtWidth(fw), form->form.left);
748             y = TransformCoord(form->form.virtual_y, fw->form.old_height,
749                                XtHeight(fw), form->form.top);
750             width = TransformCoord(form->form.virtual_x +
751                                    form->form.virtual_width +
752                                    (XtBorderWidth(*childP) << 1),
753                                    fw->form.old_width, XtWidth(fw),
754                                    form->form.right) -
755                                    (x + (XtBorderWidth(*childP) << 1));
756             height = TransformCoord(form->form.virtual_y +
757                                     form->form.virtual_height +
758                                     (XtBorderWidth(*childP) << 1),
759                                     fw->form.old_height, XtHeight(fw),
760                                     form->form.bottom) -
761                                     (y + (XtBorderWidth(*childP) << 1));
762 #else
763             x = TransformCoord(XtX(*childP), fw->form.old_width,
764                               XtWidth(fw), form->form.left);
765             y = TransformCoord(XtY(*childP), fw->form.old_height,
766                                XtHeight(fw), form->form.top);
767             width = TransformCoord(XtX(*childP) + form->form.virtual_width +
768                                    (XtBorderWidth(*childP) << 1),
769                                    fw->form.old_width, XtWidth(fw),
770                                    form->form.right) -
771                                    (x + (XtBorderWidth(*childP) << 1));
772             height = TransformCoord(XtY(*childP) + form->form.virtual_height +
773                                     (XtBorderWidth(*childP) << 1),
774                                     fw->form.old_height, XtHeight(fw),
775                                     form->form.bottom) -
776                                     (y + (XtBorderWidth(*childP) << 1));
777             form->form.virtual_width = width;
778             form->form.virtual_height = height;
779 #endif
780
781             width = width < 1 ? 1 : width;
782             height = height < 1 ? 1 : height;
783
784             XtConfigureWidget(*childP, x, y, width, height,
785                               XtBorderWidth(*childP));
786         }
787
788     if (unmap)
789         XtMapWidget(w);
790
791 #ifdef OLDXAW
792     fw->form.old_width = XtWidth(fw);
793     fw->form.old_height = XtHeight(fw);
794 #endif
795 }
796
797 /*ARGSUSED*/
798 static XtGeometryResult
799 XawFormGeometryManager(Widget w, XtWidgetGeometry *request,
800                        XtWidgetGeometry *reply)
801 {
802     Dimension old_width, old_height;
803     FormWidget fw = (FormWidget)XtParent(w);
804     FormConstraints form = (FormConstraints)w->core.constraints;
805     XtWidgetGeometry allowed;
806     XtGeometryResult ret_val;
807
808     if ((request->request_mode & (unsigned)~(XtCWQueryOnly | CWWidth | CWHeight))
809         || !form->form.allow_resize) {
810         /* If GeometryManager is invoked during a SetValues call on a child
811          * then it is necessary to compute a new layout if ConstraintSetValues
812          * allowed any constraint changes
813          */
814         if (fw->form.needs_relayout)
815             (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
816                 (fw, 0, 0, True);
817         return (XtGeometryNo);
818     }
819
820     if (request->request_mode & CWWidth)
821         allowed.width = request->width;
822     else
823         allowed.width = XtWidth(w);
824
825     if (request->request_mode & CWHeight)
826         allowed.height = request->height;
827     else
828         allowed.height = XtHeight(w);
829
830     if (allowed.width == XtWidth(w) && allowed.height == XtHeight(w)) {
831         /* If GeometryManager is invoked during a SetValues call on a child
832          * then it is necessary to compute a new layout if ConstraintSetValues
833          * allowed any constraint changes
834          */
835         if (fw->form.needs_relayout)
836             (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
837                 (fw, 0, 0, True);
838         return (XtGeometryNo);
839     }
840
841     /*
842      * Remember the old size, and then set the size to the requested size
843      */
844     old_width = XtWidth(w);
845     old_height = XtHeight(w);
846     XtWidth(w) = allowed.width;
847     XtHeight(w) = allowed.height;
848
849     if (request->request_mode & XtCWQueryOnly) {
850         Boolean always_resize_children;
851         Dimension ret_width, ret_height;
852
853         fw->form.resize_in_layout = False;
854
855         (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
856             (fw, XtWidth(w), XtHeight(w), False);
857
858         /*
859          * Reset the size of this child back to what it used to be
860          */
861         XtWidth(w) = old_width;
862         XtHeight(w) = old_height;
863
864         fw->form.resize_in_layout = True;
865
866         always_resize_children = ChangeFormGeometry(w, True,
867                                    fw->form.preferred_width,
868                                    fw->form.preferred_height,
869                                    &ret_width, &ret_height);
870
871         if (always_resize_children
872             || (ret_width >= fw->form.preferred_width
873                 && ret_height >= fw->form.preferred_height))
874             ret_val = XtGeometryYes;
875         else
876             ret_val = XtGeometryNo;
877     }
878     else {
879         if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
880                 (fw, XtWidth(w), XtHeight(w), False)) {
881             Widget *childP;
882             int num_children = fw->composite.num_children;
883             WidgetList children = fw->composite.children;
884
885             if (fw->form.no_refigure) {
886                 /*
887                  * I am changing the widget wrapper w/o modifing the window.
888                  * This is risky, but I can get away with it since I am the
889                  * parent of this widget, and he must ask me for any geometry
890                  * changes
891                  *
892                  * The window will be updated when no_refigure is set back
893                  * to False
894                  */
895                 form->form.deferred_resize = True;
896                 ret_val = XtGeometryDone;
897             }
898             else
899                 ret_val = XtGeometryYes;
900
901             /*
902              * Resets everything.
903              */
904             fw->form.old_width = XtWidth(fw);
905             fw->form.old_height = XtHeight(fw);
906             for (childP = children; childP - children < num_children; childP++) {
907                 Widget nw = *childP;
908
909                 if (XtIsManaged(nw)) {
910                     FormConstraints nform = (FormConstraints)nw->core.constraints;
911
912 #ifndef OLDXAW
913                     nform->form.virtual_x = XtX(nw);
914                     nform->form.virtual_y = XtY(nw);
915 #endif
916                     nform->form.virtual_width = XtWidth(nw);
917                     nform->form.virtual_height = XtHeight(nw);
918                 }
919             }
920         }
921         else {
922             XtWidth(w) = old_width;
923             XtHeight(w) = old_height;
924             ret_val = XtGeometryNo;
925         }
926     }
927
928     return (ret_val);
929 }
930
931 /*ARGSUSED*/
932 static Boolean
933 XawFormSetValues(Widget current, Widget request, Widget cnew,
934                  ArgList args, Cardinal *num_args)
935 {
936 #ifndef OLDXAW
937     FormWidget f_old = (FormWidget)current;
938     FormWidget f_new = (FormWidget)cnew;
939
940     if (f_old->core.background_pixmap != f_new->core.background_pixmap) {
941         XawPixmap *opix, *npix;
942
943         opix = XawPixmapFromXPixmap(f_old->core.background_pixmap, XtScreen(f_old),
944                                     f_old->core.colormap, f_old->core.depth);
945         npix = XawPixmapFromXPixmap(f_new->core.background_pixmap, XtScreen(f_new),
946                                     f_new->core.colormap, f_new->core.depth);
947         if ((npix && npix->mask) || (opix && opix->mask))
948             XawReshapeWidget(cnew, npix);
949     }
950 #endif /* OLDXAW */
951
952     return (False);
953 }
954
955 /* ARGSUSED */
956 static void
957 XawFormConstraintInitialize(Widget request, Widget cnew,
958                             ArgList args, Cardinal *num_args)
959 {
960     FormConstraints form = (FormConstraints)cnew->core.constraints;
961     FormWidget fw = (FormWidget)cnew->core.parent;
962
963 #ifndef OLDXAW
964     form->form.virtual_x = XtX(cnew);
965     form->form.virtual_y = XtY(cnew);
966 #endif
967     form->form.virtual_width = XtWidth(cnew);
968     form->form.virtual_height = XtHeight(cnew);
969
970     if (form->form.dx == default_value)
971         form->form.dx = fw->form.default_spacing;
972
973     if (form->form.dy == default_value)
974         form->form.dy = fw->form.default_spacing;
975
976     form->form.deferred_resize = False;
977 }
978
979 /*ARGSUSED*/
980 static Boolean
981 XawFormConstraintSetValues(Widget current, Widget request, Widget cnew,
982                            ArgList args, Cardinal *num_args)
983 {
984     FormConstraints cfc = (FormConstraints)current->core.constraints;
985     FormConstraints nfc = (FormConstraints)cnew->core.constraints;
986
987     if (cfc->form.top != nfc->form.top || cfc->form.bottom != nfc->form.bottom
988         || cfc->form.left != nfc->form.left || cfc->form.right != nfc->form.right
989         || cfc->form.dx != nfc->form.dx || cfc->form.dy != nfc->form.dy
990         || cfc->form.horiz_base != nfc->form.horiz_base
991         || cfc->form.vert_base != nfc->form.vert_base) {
992         FormWidget fp = (FormWidget)XtParent(cnew);
993
994         /* If there are no subclass ConstraintSetValues procedures remaining
995          * to be invoked, and if there is no geometry request about to be
996          * made, then invoke the new layout now; else defer it
997          */
998         if (XtClass(XtParent(cnew)) == formWidgetClass
999             && XtX(current) == XtX(cnew)
1000             && XtY(current) == XtY(cnew)
1001             && XtWidth(current) == XtWidth(cnew)
1002             && XtHeight(current) == XtHeight(cnew)
1003             && XtBorderWidth(current) == XtBorderWidth(cnew))
1004             Layout(fp, 0, 0, True);
1005         else
1006             fp->form.needs_relayout = True;
1007     }
1008
1009     return (False);
1010 }
1011
1012 static void
1013 XawFormChangeManaged(Widget w)
1014 {
1015     FormWidget fw = (FormWidget)w;
1016     FormConstraints form;
1017     WidgetList children, childP;
1018     int num_children = fw->composite.num_children;
1019     Widget child;
1020
1021     (*((FormWidgetClass)w->core.widget_class)->form_class.layout)
1022         (fw, XtWidth(w), XtHeight(w), True);
1023
1024     fw->form.old_width = XtWidth(w);
1025     fw->form.old_height = XtHeight(w);
1026     for (children = childP = fw->composite.children;
1027          childP - children < num_children;
1028          childP++) {
1029         child = *childP;
1030         if (!XtIsManaged(child))
1031             continue;
1032         form = (FormConstraints)child->core.constraints;
1033 #ifndef OLDXAW
1034         form->form.virtual_x = XtX(child);
1035         form->form.virtual_y = XtY(child);
1036 #endif
1037         form->form.virtual_width = XtWidth(child);
1038         form->form.virtual_height = XtHeight(child);
1039     }
1040 }
1041
1042 static XtGeometryResult
1043 XawFormQueryGeometry(Widget widget, XtWidgetGeometry *request,
1044                      XtWidgetGeometry *reply)
1045 {
1046     FormWidget w = (FormWidget)widget;
1047
1048     reply->width = w->form.preferred_width;
1049     reply->height = w->form.preferred_height;
1050     reply->request_mode = CWWidth | CWHeight;
1051
1052     if ((request->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)
1053         && request->width == reply->width
1054         && request->height == reply->height)
1055         return (XtGeometryYes);
1056     else if (reply->width == XtWidth(w) && reply->height == XtHeight(w))
1057         return (XtGeometryNo);
1058
1059     return (XtGeometryAlmost);
1060 }
1061
1062 /*
1063  * Public routines
1064  */
1065 /*
1066  * Set or reset figuring (ignored if not realized)
1067  */
1068 void
1069 XawFormDoLayout(Widget w,
1070 #if NeedWidePrototypes
1071                 Bool force
1072 #else
1073                 Boolean force
1074 #endif
1075 )
1076 {
1077     Widget *childP;
1078     FormWidget fw = (FormWidget)w;
1079     int num_children = fw->composite.num_children;
1080     WidgetList children = fw->composite.children;
1081
1082     if ((fw->form.no_refigure = !force) == True || !XtIsRealized(w))
1083         return;
1084
1085     for (childP = children; childP - children < num_children; childP++) {
1086         Widget nw = *childP;
1087
1088         if (XtIsManaged(nw)) {
1089             FormConstraints form = (FormConstraints)nw->core.constraints;
1090
1091             /*
1092              * Xt Configure widget is too smart, and optimizes out
1093              * my changes
1094              */
1095             XMoveResizeWindow(XtDisplay(nw), XtWindow(nw),
1096                               XtX(nw), XtY(nw), XtWidth(nw), XtHeight(nw));
1097
1098             if (form)
1099               if (form->form.deferred_resize &&
1100                 XtClass(nw)->core_class.resize != NULL) {
1101                 (*(XtClass(nw)->core_class.resize))(nw);
1102                 form->form.deferred_resize = False;
1103               }
1104         }
1105     }
1106 }