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 #ifndef OLDXAW
290 NULL,
291 #endif
292 },
293 };
294
295 WidgetClass formWidgetClass = (WidgetClass)&formClassRec;
296
297 /*
298 * Implementation
299 */
300 #ifndef OLDXAW
301 static void
XawFormRealize(Widget w,Mask * mask,XSetWindowAttributes * attr)302 XawFormRealize(Widget w, Mask *mask, XSetWindowAttributes *attr)
303 {
304 XawPixmap *pixmap;
305
306 (*formWidgetClass->core_class.superclass->core_class.realize)(w, mask, attr);
307
308 if (w->core.background_pixmap > XtUnspecifiedPixmap) {
309 pixmap = XawPixmapFromXPixmap(w->core.background_pixmap, XtScreen(w),
310 w->core.colormap, (int)w->core.depth);
311 if (pixmap && pixmap->mask)
312 XawReshapeWidget(w, pixmap);
313 }
314 }
315
316 static void
XawFormRedisplay(Widget w,XEvent * event,Region region)317 XawFormRedisplay(Widget w, XEvent *event, Region region)
318 {
319 FormWidget xaw = (FormWidget)w;
320
321 if (xaw->form.display_list)
322 XawRunDisplayList(w, xaw->form.display_list, event, region);
323 }
324 #endif
325
326 /*ARGSUSED*/
327 static void
_CvtStringToEdgeType(XrmValuePtr args _X_UNUSED,Cardinal * num_args _X_UNUSED,XrmValuePtr fromVal,XrmValuePtr toVal)328 _CvtStringToEdgeType(XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED,
329 XrmValuePtr fromVal, XrmValuePtr toVal)
330 {
331 static XtEdgeType edgeType;
332 XrmQuark q;
333 char name[12];
334
335 XmuNCopyISOLatin1Lowered(name, (char*)fromVal->addr, sizeof(name));
336 q = XrmStringToQuark(name);
337
338 if (q == QchainLeft)
339 edgeType = XtChainLeft;
340 else if (q == QchainRight)
341 edgeType = XtChainRight;
342 else if (q == QchainTop)
343 edgeType = XtChainTop;
344 else if (q == QchainBottom)
345 edgeType = XtChainBottom;
346 else if (q == Qrubber)
347 edgeType = XtRubber;
348 else {
349 XtStringConversionWarning(fromVal->addr, XtREdgeType);
350 toVal->size = 0;
351 toVal->addr = NULL;
352 return;
353 }
354
355 toVal->size = sizeof(XtEdgeType);
356 toVal->addr = (XPointer)&edgeType;
357 }
358
359 /*ARGSUSED*/
360 Boolean
CvtEdgeTypeToString(Display * dpy,XrmValuePtr args _X_UNUSED,Cardinal * num_args _X_UNUSED,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * data _X_UNUSED)361 CvtEdgeTypeToString(Display *dpy, XrmValuePtr args _X_UNUSED, Cardinal *num_args _X_UNUSED,
362 XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data _X_UNUSED)
363 {
364 static String buffer;
365 Cardinal size;
366
367 switch (*(XtEdgeType *)fromVal->addr) {
368 case XtChainLeft:
369 buffer = XtEchainLeft;
370 break;
371 case XtChainRight:
372 buffer = XtEchainRight;
373 break;
374 case XtChainTop:
375 buffer = XtEchainTop;
376 break;
377 case XtChainBottom:
378 buffer = XtEchainBottom;
379 break;
380 case XtRubber:
381 buffer = XtErubber;
382 break;
383 default:
384 XawTypeToStringWarning(dpy, XtREdgeType);
385 toVal->addr = NULL;
386 toVal->size = 0;
387 return (False);
388 }
389
390 size = (Cardinal)strlen(buffer) + 1;
391 if (toVal->addr != NULL) {
392 if (toVal->size < size) {
393 toVal->size = size;
394 return (False);
395 }
396 strcpy((char *)toVal->addr, buffer);
397 }
398 else
399 toVal->addr = (XPointer)buffer;
400 toVal->size = sizeof(String);
401
402 return (True);
403 }
404
405 static void
XawFormClassInitialize(void)406 XawFormClassInitialize(void)
407 {
408 static XtConvertArgRec parentCvtArgs[] = {
409 {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
410 sizeof(Widget)}
411 };
412
413 char name[12];
414
415 XawInitializeWidgetSet();
416 XmuNCopyISOLatin1Lowered(name, XtEchainLeft, sizeof(name));
417 QchainLeft = XrmStringToQuark(name);
418 XmuNCopyISOLatin1Lowered(name, XtEchainRight, sizeof(name));
419 QchainRight = XrmStringToQuark(name);
420 XmuNCopyISOLatin1Lowered(name, XtEchainTop, sizeof(name));
421 QchainTop = XrmStringToQuark(name);
422 XmuNCopyISOLatin1Lowered(name, XtEchainBottom, sizeof(name));
423 QchainBottom = XrmStringToQuark(name);
424 XmuNCopyISOLatin1Lowered(name, XtErubber, sizeof(name));
425 Qrubber = XrmStringToQuark(name);
426
427 XtAddConverter(XtRString, XtREdgeType, _CvtStringToEdgeType, NULL, 0);
428 XtSetTypeConverter(XtREdgeType, XtRString, CvtEdgeTypeToString,
429 NULL, 0, XtCacheNone, NULL);
430 XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
431 parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
432 NULL);
433 XtSetTypeConverter(XtRWidget, XtRString, XmuCvtWidgetToString,
434 NULL, 0, XtCacheNone, NULL);
435 }
436
437 static void
XawFormClassPartInitialize(WidgetClass cclass)438 XawFormClassPartInitialize(WidgetClass cclass)
439 {
440 FormWidgetClass c = (FormWidgetClass)cclass;
441 FormWidgetClass super = (FormWidgetClass)c->core_class.superclass;
442
443 if (c->form_class.layout == XtInheritLayout)
444 c->form_class.layout = super->form_class.layout;
445 }
446
447 /*ARGSUSED*/
448 static void
XawFormInitialize(Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)449 XawFormInitialize(Widget request _X_UNUSED, Widget cnew,
450 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
451 {
452 FormWidget fw = (FormWidget)cnew;
453
454 fw->form.old_width = fw->form.old_height = 0;
455 fw->form.no_refigure = False;
456 fw->form.needs_relayout = False;
457 fw->form.resize_in_layout = True;
458 fw->form.resize_is_no_op = False;
459 }
460
461 /*
462 * Function:
463 * ChangeFormGeometry
464 *
465 * Parameters:
466 * w - Form widget
467 * query_only - is only a query?
468 * width - new width and height
469 * height - ""
470 * ret_width - actual size the form is allowed to resize to (return)
471 * ret_height - ""
472 *
473 * Description:
474 * Ask the parent to change the form widget's geometry.
475 *
476 * Returns:
477 * True of children may always be resized
478 */
479 static Bool
ChangeFormGeometry(Widget w,Bool query_only,unsigned int width,unsigned int height,Dimension * ret_width,Dimension * ret_height)480 ChangeFormGeometry(Widget w, Bool query_only,
481 unsigned int width, unsigned int height,
482 Dimension *ret_width, Dimension *ret_height)
483 {
484 FormWidget fw = (FormWidget)w;
485 Boolean always_resize_children;
486 XtGeometryResult result;
487 XtWidgetGeometry request, return_request;
488
489 /*
490 * If we are already at the desired size then there is no need
491 * to ask our parent of we can change size
492 */
493 if (width == XtWidth(fw) && height == XtHeight(fw))
494 return (True);
495
496 request.width = (Dimension)width;
497 request.height = (Dimension)height;
498 request.request_mode = CWWidth | CWHeight;
499 if (query_only)
500 request.request_mode |= XtCWQueryOnly;
501
502 /*
503 * Do no invoke the resize rules if our size changes here
504 */
505 fw->form.resize_is_no_op = True;
506
507 result = XtMakeGeometryRequest(w, &request, &return_request);
508 if (result == XtGeometryAlmost) {
509 request = return_request;
510 (void)XtMakeGeometryRequest(w, &request, &return_request);
511 always_resize_children = False;
512 }
513 else
514 always_resize_children = result == XtGeometryYes;
515
516 fw->form.resize_is_no_op = False;
517
518 if (ret_width != NULL)
519 *ret_width = request.width;
520 if (ret_height != NULL)
521 *ret_height = request.height;
522
523 return (always_resize_children);
524 }
525
526 /*
527 * Function:
528 * Layout
529 *
530 * Parameters:
531 * fw - Form widget
532 * width - unused
533 * height - ""
534 * force_relayout - will force the children to be moved, even if some
535 * go past the edge of the form
536 *
537 * Description:
538 * Moves all the children around.
539 *
540 * Returns:
541 * True if the children are allowed to move from their
542 * current locations to the new ones.
543 */
544 /*ARGSUSED*/
545 static Boolean
Layout(FormWidget fw,unsigned int width _X_UNUSED,unsigned int height _X_UNUSED,Bool force_relayout)546 Layout(FormWidget fw, unsigned int width _X_UNUSED, unsigned int height _X_UNUSED,
547 Bool force_relayout)
548 {
549 int num_children = (int)fw->composite.num_children;
550 WidgetList children = fw->composite.children;
551 Widget *childP;
552 Dimension maxx, maxy;
553 Boolean ret_val;
554
555 for (childP = children; childP - children < num_children; childP++) {
556 FormConstraints form = (FormConstraints)(*childP)->core.constraints;
557 form->form.layout_state = LayoutPending;
558 }
559
560 maxx = maxy = 1;
561 for (childP = children; childP - children < num_children; childP++) {
562 if (XtIsManaged(*childP)) {
563 FormConstraints form;
564 Position x, y;
565
566 form = (FormConstraints)(*childP)->core.constraints;
567
568 LayoutChild(*childP);
569
570 x = (Position)(form->form.new_x + XtWidth(*childP)
571 + (XtBorderWidth(*childP) << 1));
572 if (x > (int)maxx)
573 maxx = (Dimension)x;
574
575 y = (Position)(form->form.new_y + XtHeight(*childP)
576 + (XtBorderWidth(*childP) << 1));
577 if (y > (int)maxy)
578 maxy = (Dimension)y;
579 }
580 }
581
582 fw->form.preferred_width = (maxx = (Dimension)(maxx + fw->form.default_spacing));
583 fw->form.preferred_height = (maxy = (Dimension)(maxy + fw->form.default_spacing));
584
585 if (fw->form.resize_in_layout) {
586 Boolean always_resize_children;
587
588 always_resize_children =
589 (Boolean)ChangeFormGeometry((Widget)fw, False, maxx, maxy, NULL, NULL);
590
591 #ifdef OLDXAW
592 fw->form.old_width = fw->core.width;
593 fw->form.old_height = fw->core.height;
594 #endif
595
596 if (force_relayout)
597 ret_val = True;
598 else
599 ret_val = always_resize_children ||
600 (XtWidth(fw) >= maxx && XtHeight(fw) >= maxy);
601
602 if (ret_val)
603 ResizeChildren((Widget)fw);
604 }
605 else
606 ret_val = False;
607
608 fw->form.needs_relayout = False;
609
610 return (ret_val);
611 }
612
613 /*
614 * Function:
615 * ResizeChildren
616 *
617 * Parameters:
618 * w - form widget
619 *
620 * Description:
621 * Resizes all children to new_x and new_y.
622 */
623 static void
ResizeChildren(Widget w)624 ResizeChildren(Widget w)
625 {
626 FormWidget fw = (FormWidget)w;
627 int num_children = (int)fw->composite.num_children;
628 WidgetList children = fw->composite.children;
629 Widget *childP;
630
631 for (childP = children; childP - children < num_children; childP++) {
632 FormConstraints form;
633 Position x, y;
634
635 if (!XtIsManaged(*childP))
636 continue;
637
638 form = (FormConstraints)(*childP)->core.constraints;
639
640 if (fw->form.old_width && fw->form.old_height) {
641 x = (Position)TransformCoord(form->form.new_x, fw->form.old_width,
642 XtWidth(fw), form->form.left);
643 y = (Position)TransformCoord(form->form.new_y, fw->form.old_height,
644 XtHeight(fw), form->form.top);
645 }
646 else {
647 x = form->form.new_x;
648 y = form->form.new_y;
649 }
650
651 if (fw->form.no_refigure) {
652 /*
653 * I am changing the widget wrapper w/o modifing the window. This is
654 * risky, but I can get away with it since I am the parent of this
655 * widget, and he must ask me for any geometry changes
656 *
657 * The window will be updated when no_refigure is set back to False
658 */
659 XtX(*childP) = x;
660 XtY(*childP) = y;
661 }
662 else
663 XtMoveWidget(*childP, x, y);
664 }
665 }
666
667 static void
LayoutChild(Widget w)668 LayoutChild(Widget w)
669 {
670 FormConstraints form = (FormConstraints)w->core.constraints;
671 Widget ref;
672
673 switch (form->form.layout_state) {
674 case LayoutPending:
675 form->form.layout_state = LayoutInProgress;
676 break;
677 case LayoutDone:
678 return;
679 case LayoutInProgress: {
680 String subs[2];
681 Cardinal num_subs = 2;
682 subs[0] = w->core.name;
683 subs[1] = w->core.parent->core.name;
684
685 XtAppWarningMsg(XtWidgetToApplicationContext(w),
686 "constraintLoop", "xawFormLayout", "XawToolkitError",
687 "constraint loop detected while laying out "
688 "child '%s' in FormWidget '%s'",
689 subs, &num_subs);
690 } return;
691 }
692
693 form->form.new_x = (Position)form->form.dx;
694 form->form.new_y = (Position)form->form.dy;
695 if ((ref = form->form.horiz_base) != NULL) {
696 FormConstraints ref_form = (FormConstraints)ref->core.constraints;
697
698 LayoutChild(ref);
699 form->form.new_x = (Position)(form->form.new_x
700 + (ref_form->form.new_x
701 + XtWidth(ref)
702 + (XtBorderWidth(ref) << 1)));
703 }
704 if ((ref = form->form.vert_base) != NULL) {
705 FormConstraints ref_form = (FormConstraints)ref->core.constraints;
706
707 LayoutChild(ref);
708 form->form.new_y = (Position)(form->form.new_y
709 + (ref_form->form.new_y
710 + XtHeight(ref)
711 + (XtBorderWidth(ref) << 1)));
712 }
713
714 form->form.layout_state = LayoutDone;
715 }
716
717 static int
TransformCoord(int loc,unsigned int old,unsigned int cnew,XtEdgeType type)718 TransformCoord(int loc, unsigned int old, unsigned int cnew, XtEdgeType type)
719 {
720 if (type == XtRubber) {
721 if ((int)old > 0)
722 loc = (int)(loc * ((double)cnew / (double)old));
723 }
724 else if (type == XtChainBottom || type == XtChainRight)
725 loc += (int)cnew - (int)old;
726
727 return (loc);
728 }
729
730 static void
XawFormResize(Widget w)731 XawFormResize(Widget w)
732 {
733 FormWidget fw = (FormWidget)w;
734 WidgetList children = fw->composite.children;
735 int num_children = (int)fw->composite.num_children;
736 Widget *childP;
737 int x, y;
738 int width, height;
739 Boolean unmap = XtIsRealized(w) && w->core.mapped_when_managed &&
740 XtIsManaged(w);
741
742 if (unmap)
743 XtUnmapWidget(w);
744
745 if (!fw->form.resize_is_no_op)
746 for (childP = children; childP - children < num_children; childP++) {
747 FormConstraints form = (FormConstraints)(*childP)->core.constraints;
748
749 if (!XtIsManaged(*childP))
750 continue;
751
752 #ifndef OLDXAW
753 x = TransformCoord(form->form.virtual_x, fw->form.old_width,
754 XtWidth(fw), form->form.left);
755 y = TransformCoord(form->form.virtual_y, fw->form.old_height,
756 XtHeight(fw), form->form.top);
757 width = TransformCoord(form->form.virtual_x +
758 form->form.virtual_width +
759 (XtBorderWidth(*childP) << 1),
760 fw->form.old_width, XtWidth(fw),
761 form->form.right) -
762 (x + (XtBorderWidth(*childP) << 1));
763 height = TransformCoord(form->form.virtual_y +
764 form->form.virtual_height +
765 (XtBorderWidth(*childP) << 1),
766 fw->form.old_height, XtHeight(fw),
767 form->form.bottom) -
768 (y + (XtBorderWidth(*childP) << 1));
769 #else
770 x = TransformCoord(XtX(*childP), fw->form.old_width,
771 XtWidth(fw), form->form.left);
772 y = TransformCoord(XtY(*childP), fw->form.old_height,
773 XtHeight(fw), form->form.top);
774 width = TransformCoord(XtX(*childP) + form->form.virtual_width +
775 (XtBorderWidth(*childP) << 1),
776 fw->form.old_width, XtWidth(fw),
777 form->form.right) -
778 (x + (XtBorderWidth(*childP) << 1));
779 height = TransformCoord(XtY(*childP) + form->form.virtual_height +
780 (XtBorderWidth(*childP) << 1),
781 fw->form.old_height, XtHeight(fw),
782 form->form.bottom) -
783 (y + (XtBorderWidth(*childP) << 1));
784 form->form.virtual_width = width;
785 form->form.virtual_height = height;
786 #endif
787
788 width = width < 1 ? 1 : width;
789 height = height < 1 ? 1 : height;
790
791 XtConfigureWidget(*childP,
792 (Position)x, (Position)y,
793 (Dimension)width, (Dimension)height,
794 XtBorderWidth(*childP));
795 }
796
797 if (unmap)
798 XtMapWidget(w);
799
800 #ifdef OLDXAW
801 fw->form.old_width = XtWidth(fw);
802 fw->form.old_height = XtHeight(fw);
803 #endif
804 }
805
806 /*ARGSUSED*/
807 static XtGeometryResult
XawFormGeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply _X_UNUSED)808 XawFormGeometryManager(Widget w, XtWidgetGeometry *request,
809 XtWidgetGeometry *reply _X_UNUSED)
810 {
811 Dimension old_width, old_height;
812 FormWidget fw = (FormWidget)XtParent(w);
813 FormConstraints form = (FormConstraints)w->core.constraints;
814 XtWidgetGeometry allowed;
815 XtGeometryResult ret_val;
816
817 if ((request->request_mode & (unsigned)~(XtCWQueryOnly | CWWidth | CWHeight))
818 || !form->form.allow_resize) {
819 /* If GeometryManager is invoked during a SetValues call on a child
820 * then it is necessary to compute a new layout if ConstraintSetValues
821 * allowed any constraint changes
822 */
823 if (fw->form.needs_relayout)
824 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
825 (fw, 0, 0, True);
826 return (XtGeometryNo);
827 }
828
829 if (request->request_mode & CWWidth)
830 allowed.width = request->width;
831 else
832 allowed.width = XtWidth(w);
833
834 if (request->request_mode & CWHeight)
835 allowed.height = request->height;
836 else
837 allowed.height = XtHeight(w);
838
839 if (allowed.width == XtWidth(w) && allowed.height == XtHeight(w)) {
840 /* If GeometryManager is invoked during a SetValues call on a child
841 * then it is necessary to compute a new layout if ConstraintSetValues
842 * allowed any constraint changes
843 */
844 if (fw->form.needs_relayout)
845 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
846 (fw, 0, 0, True);
847 return (XtGeometryNo);
848 }
849
850 /*
851 * Remember the old size, and then set the size to the requested size
852 */
853 old_width = XtWidth(w);
854 old_height = XtHeight(w);
855 XtWidth(w) = allowed.width;
856 XtHeight(w) = allowed.height;
857
858 if (request->request_mode & XtCWQueryOnly) {
859 Boolean always_resize_children;
860 Dimension ret_width, ret_height;
861
862 fw->form.resize_in_layout = False;
863
864 (*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
865 (fw, XtWidth(w), XtHeight(w), False);
866
867 /*
868 * Reset the size of this child back to what it used to be
869 */
870 XtWidth(w) = old_width;
871 XtHeight(w) = old_height;
872
873 fw->form.resize_in_layout = True;
874
875 always_resize_children = (Boolean)ChangeFormGeometry(w, True,
876 fw->form.preferred_width,
877 fw->form.preferred_height,
878 &ret_width, &ret_height);
879
880 if (always_resize_children
881 || (ret_width >= fw->form.preferred_width
882 && ret_height >= fw->form.preferred_height))
883 ret_val = XtGeometryYes;
884 else
885 ret_val = XtGeometryNo;
886 }
887 else {
888 if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout)
889 (fw, XtWidth(w), XtHeight(w), False)) {
890 Widget *childP;
891 int num_children = (int)fw->composite.num_children;
892 WidgetList children = fw->composite.children;
893
894 if (fw->form.no_refigure) {
895 /*
896 * I am changing the widget wrapper w/o modifing the window.
897 * This is risky, but I can get away with it since I am the
898 * parent of this widget, and he must ask me for any geometry
899 * changes
900 *
901 * The window will be updated when no_refigure is set back
902 * to False
903 */
904 form->form.deferred_resize = True;
905 ret_val = XtGeometryDone;
906 }
907 else
908 ret_val = XtGeometryYes;
909
910 /*
911 * Resets everything.
912 */
913 fw->form.old_width = XtWidth(fw);
914 fw->form.old_height = XtHeight(fw);
915 for (childP = children; childP - children < num_children; childP++) {
916 Widget nw = *childP;
917
918 if (XtIsManaged(nw)) {
919 FormConstraints nform = (FormConstraints)nw->core.constraints;
920
921 #ifndef OLDXAW
922 nform->form.virtual_x = XtX(nw);
923 nform->form.virtual_y = XtY(nw);
924 #endif
925 nform->form.virtual_width = (short)XtWidth(nw);
926 nform->form.virtual_height = (short)XtHeight(nw);
927 }
928 }
929 }
930 else {
931 XtWidth(w) = old_width;
932 XtHeight(w) = old_height;
933 ret_val = XtGeometryNo;
934 }
935 }
936
937 return (ret_val);
938 }
939
940 /*ARGSUSED*/
941 static Boolean
XawFormSetValues(Widget current _X_UNUSED,Widget request _X_UNUSED,Widget cnew _X_UNUSED,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)942 XawFormSetValues(Widget current _X_UNUSED, Widget request _X_UNUSED, Widget cnew _X_UNUSED,
943 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
944 {
945 #ifndef OLDXAW
946 FormWidget f_old = (FormWidget)current;
947 FormWidget f_new = (FormWidget)cnew;
948
949 if (f_old->core.background_pixmap != f_new->core.background_pixmap) {
950 XawPixmap *opix, *npix;
951
952 opix = XawPixmapFromXPixmap(f_old->core.background_pixmap, XtScreen(f_old),
953 f_old->core.colormap, (int)f_old->core.depth);
954 npix = XawPixmapFromXPixmap(f_new->core.background_pixmap, XtScreen(f_new),
955 f_new->core.colormap, (int)f_new->core.depth);
956 if ((npix && npix->mask) || (opix && opix->mask))
957 XawReshapeWidget(cnew, npix);
958 }
959 #endif /* OLDXAW */
960
961 return (False);
962 }
963
964 /* ARGSUSED */
965 static void
XawFormConstraintInitialize(Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)966 XawFormConstraintInitialize(Widget request _X_UNUSED, Widget cnew,
967 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
968 {
969 FormConstraints form = (FormConstraints)cnew->core.constraints;
970 FormWidget fw = (FormWidget)cnew->core.parent;
971
972 #ifndef OLDXAW
973 form->form.virtual_x = XtX(cnew);
974 form->form.virtual_y = XtY(cnew);
975 #endif
976 form->form.virtual_width = (short)XtWidth(cnew);
977 form->form.virtual_height = (short)XtHeight(cnew);
978
979 if (form->form.dx == default_value)
980 form->form.dx = fw->form.default_spacing;
981
982 if (form->form.dy == default_value)
983 form->form.dy = fw->form.default_spacing;
984
985 form->form.deferred_resize = False;
986 }
987
988 /*ARGSUSED*/
989 static Boolean
XawFormConstraintSetValues(Widget current,Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)990 XawFormConstraintSetValues(Widget current, Widget request _X_UNUSED, Widget cnew,
991 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
992 {
993 FormConstraints cfc = (FormConstraints)current->core.constraints;
994 FormConstraints nfc = (FormConstraints)cnew->core.constraints;
995
996 if (cfc->form.top != nfc->form.top || cfc->form.bottom != nfc->form.bottom
997 || cfc->form.left != nfc->form.left || cfc->form.right != nfc->form.right
998 || cfc->form.dx != nfc->form.dx || cfc->form.dy != nfc->form.dy
999 || cfc->form.horiz_base != nfc->form.horiz_base
1000 || cfc->form.vert_base != nfc->form.vert_base) {
1001 FormWidget fp = (FormWidget)XtParent(cnew);
1002
1003 /* If there are no subclass ConstraintSetValues procedures remaining
1004 * to be invoked, and if there is no geometry request about to be
1005 * made, then invoke the new layout now; else defer it
1006 */
1007 if (XtClass(XtParent(cnew)) == formWidgetClass
1008 && XtX(current) == XtX(cnew)
1009 && XtY(current) == XtY(cnew)
1010 && XtWidth(current) == XtWidth(cnew)
1011 && XtHeight(current) == XtHeight(cnew)
1012 && XtBorderWidth(current) == XtBorderWidth(cnew))
1013 Layout(fp, 0, 0, True);
1014 else
1015 fp->form.needs_relayout = True;
1016 }
1017
1018 return (False);
1019 }
1020
1021 static void
XawFormChangeManaged(Widget w)1022 XawFormChangeManaged(Widget w)
1023 {
1024 FormWidget fw = (FormWidget)w;
1025 FormConstraints form;
1026 WidgetList children, childP;
1027 int num_children = (int)fw->composite.num_children;
1028 Widget child;
1029
1030 (*((FormWidgetClass)w->core.widget_class)->form_class.layout)
1031 (fw, XtWidth(w), XtHeight(w), True);
1032
1033 fw->form.old_width = XtWidth(w);
1034 fw->form.old_height = XtHeight(w);
1035 for (children = childP = fw->composite.children;
1036 childP - children < num_children;
1037 childP++) {
1038 child = *childP;
1039 if (!XtIsManaged(child))
1040 continue;
1041 form = (FormConstraints)child->core.constraints;
1042 #ifndef OLDXAW
1043 form->form.virtual_x = XtX(child);
1044 form->form.virtual_y = XtY(child);
1045 #endif
1046 form->form.virtual_width = (short)XtWidth(child);
1047 form->form.virtual_height = (short)XtHeight(child);
1048 }
1049 }
1050
1051 static XtGeometryResult
XawFormQueryGeometry(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)1052 XawFormQueryGeometry(Widget widget, XtWidgetGeometry *request,
1053 XtWidgetGeometry *reply)
1054 {
1055 FormWidget w = (FormWidget)widget;
1056
1057 reply->width = w->form.preferred_width;
1058 reply->height = w->form.preferred_height;
1059 reply->request_mode = CWWidth | CWHeight;
1060
1061 if ((request->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight)
1062 && request->width == reply->width
1063 && request->height == reply->height)
1064 return (XtGeometryYes);
1065 else if (reply->width == XtWidth(w) && reply->height == XtHeight(w))
1066 return (XtGeometryNo);
1067
1068 return (XtGeometryAlmost);
1069 }
1070
1071 /*
1072 * Public routines
1073 */
1074 /*
1075 * Set or reset figuring (ignored if not realized)
1076 */
1077 void
XawFormDoLayout(Widget w,Bool force)1078 XawFormDoLayout(Widget w,
1079 #if NeedWidePrototypes
1080 Bool force
1081 #else
1082 Boolean force
1083 #endif
1084 )
1085 {
1086 Widget *childP;
1087 FormWidget fw = (FormWidget)w;
1088 int num_children = (int)fw->composite.num_children;
1089 WidgetList children = fw->composite.children;
1090
1091 if ((fw->form.no_refigure = !force) == True || !XtIsRealized(w))
1092 return;
1093
1094 for (childP = children; childP - children < num_children; childP++) {
1095 Widget nw = *childP;
1096
1097 if (XtIsManaged(nw)) {
1098 FormConstraints form = (FormConstraints)nw->core.constraints;
1099
1100 /*
1101 * Xt Configure widget is too smart, and optimizes out
1102 * my changes
1103 */
1104 XMoveResizeWindow(XtDisplay(nw), XtWindow(nw),
1105 XtX(nw), XtY(nw), XtWidth(nw), XtHeight(nw));
1106
1107 if (form)
1108 if (form->form.deferred_resize &&
1109 XtClass(nw)->core_class.resize != NULL) {
1110 (*(XtClass(nw)->core_class.resize))(nw);
1111 form->form.deferred_resize = False;
1112 }
1113 }
1114 }
1115 }
1116