1 /*
2  * Motif Tools Library, Version 3.1
3  * $Id: Layout.c,v 1.3 2001/07/07 01:38:33 grmcdorman Exp $
4  *
5  * Written by David Flanagan.
6  * Copyright (c) 1992-2001 by David Flanagan.
7  * All Rights Reserved.  See the file COPYRIGHT for details.
8  * This is open source software.  See the file LICENSE for details.
9  * There is no warranty for this software.  See NO_WARRANTY for details.
10  *
11  * $Log: Layout.c,v $
12  * Revision 1.3  2001/07/07 01:38:33  grmcdorman
13  * This change fixes redraw problems with Layout. Formerly,
14  * Layout would erase and redraw most of the layout (especially
15  * captions) on expose events. This caused noticable and
16  * ugly flickering.
17  *
18  * Revision 1.2  2001/04/15 15:29:36  grmcdorman
19  *   * XmtCallCallback has two new arguments types: XmtRCallbackUserData, which
20  *     is the XmNuserData value, and XmtRCallbackImmediate, which is a value
21  *     embedded in the list.
22  *
23  *   * Two new functions, XmtCreateQueryListChildren and XmtCreateQueryListChild,
24  *     are provided. They are like the XmtCreate* functions except that they
25  *     return a list of the widgets created (quark and pointer to the widget).
26  *
27  *   * Major enhancements to XmtInputField:
28  *     - The input field now has a cancel() action. This reverts the field's
29  *       value to that prior to the start of editing (i.e. the last commit).
30  *       No default translation is bound to this action, however.
31  *     - There is a callback for the cancel action (XmtNcancelCallback).
32  *     - The input field can be set to cancel, commit, or do nothing on focus
33  *       out. (Previously, it always did a commit). The default is commit.
34  *       (XmtNfocusOutAction)
35  *
36  *   * XmtLayout:
37  *     - It now has a losingFocusCallback (XmNloosingFocusCallback).
38  *     - It, and the layout widgets (XmtLayoutBox/XmtLayoutString), now
39  *       support background pixmaps.
40  *     - It now supports XmNresizePolicy.
41  *     - Strings in the layout parser are converted to XmStrings by
42  *       XtConvertAndStore, so any custom XmString conversion is used
43  *       (as, for example, the Xmt convert, which supports the @[]
44  *       embedded items)
45  *
46  *   * Other:
47  *     - Pixmaps are convered using XtConvertAndStore, again to allow
48  *       custom converters.
49  *
50  * Bug Fixes: (for Solaris 2.5.1/Motif 1.2/Sparc system)
51  *   * XmtInputField did not work properly if the widget had traversalOn
52  *     false.
53  *   * XmtLayout's child geometry manager was called by Xt when
54  *     a shell child was added to the layout; it did not handle
55  *     this case.
56  *   * XmtLayout had an XmtWarningMsg call with a missing argument (line 2029).
57  *   * Widgets automatically created by XmtLayout parsing have been given
58  *     non-blank names. [You may wish to tweak this by adding, for example,
59  *     a leading underscore.]
60  *   * Under some circumstances, XmtNameToWidget could be called during
61  *     widget creation, with 'w->core.num_popups' uninitialized. The
62  *     workaround applied is to ignore the popup list if the 'num_popups'
63  *     value is more than 50 or negative.
64  *
65  * Revision 1.1.1.1  2001/02/10 13:45:43  motiftools
66  * Initial import of Xmt310 to CVS
67  *
68  *
69  */
70 
71 #include <stdio.h>
72 #include <Xmt/XmtP.h>
73 #include <Xmt/LayoutP.h>
74 #include <Xmt/LayoutGP.h>
75 #include <Xmt/ConvertersP.h>
76 #include <Xmt/Pixmap.h>
77 #include <Xm/DialogS.h>
78 #if (XmVersion >= 1002)
79 #include <Xm/DrawP.h>  /* declaration of Motif drawing routines */
80 #endif
81 
82 #include <X11/IntrinsicP.h>
83 
84 #define offset(field) XtOffsetOf(XmtLayoutRec, field)
85 static XtResource resources[] = {
86 {XmtNlayout, XmtCLayout, XtRString, sizeof(String),
87      offset(layout.layout), XtRString, NULL},
88 #if XmVersion < 2000
89 {XmtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
90      offset(layout.font), XtRString, XtDefaultFont},
91 #else /* Motif 2.0 or later */
92 {XmtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
93      offset(layout.font), XtRImmediate, (XtPointer) NULL},
94 #endif
95 {XmtNfontList, XmCFontList, XmRFontList, sizeof(XmFontList),
96      offset(layout.font_list), XtRImmediate, (XtPointer) NULL},
97 #if XmVersion >= 2000
98 {XmtNrenderTable, XmCRenderTable, XmRRenderTable,
99      sizeof(XmRenderTable), offset(layout.render_table),
100      XtRImmediate, (XtPointer) NULL},
101 #endif
102 {XmtNdefaultSpacing, XmtCDefaultSpacing, XtRDimension, sizeof(Dimension),
103      offset(layout.default_spacing), XtRImmediate, (XtPointer) 10},
104 {XmtNorientation, XmCOrientation, XmROrientation,
105      sizeof(unsigned char), offset(layout.orientation),
106      XtRImmediate, (XtPointer) XmVERTICAL},
107 {XmtNdebugLayout, XmtCDebugLayout, XtRBoolean,
108      sizeof(Boolean), offset(layout.debug_layout),
109      XtRImmediate, (XtPointer)False},
110 {XmNlosingFocusCallback,XmCCallback,XmRCallback,
111      sizeof (XtCallbackList), offset(layout.losing_focus_callback),
112      XmRImmediate, (XtPointer) NULL},
113 /* override some BulletinBoard defaults */
114 {XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
115      sizeof(Dimension),
116      XtOffsetOf(struct _XmBulletinBoardRec, bulletin_board.margin_width),
117      XmRImmediate, (XtPointer)5},
118 {XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension,
119      sizeof(Dimension),
120      XtOffsetOf(struct _XmBulletinBoardRec, bulletin_board.margin_height),
121      XmRImmediate, (XtPointer)5},
122 };
123 #undef offset
124 
125 #define offset(field) XtOffsetOf(XmtLayoutConstraintsRec, layout.field)
126 static XtResource constraint_resources[] = {
127 {XmtNlayoutWidth, XmtCLayoutWidth, XtRDimension,
128      sizeof(Dimension), offset(width),
129      XtRImmediate, (XtPointer) 0},
130 {XmtNlayoutHeight, XmtCLayoutHeight, XtRDimension,
131      sizeof(Dimension), offset(height),
132      XtRImmediate, (XtPointer) 0},
133 {XmtNlayoutStretchability, XmtCLayoutStretchability, XtRDimension,
134      sizeof(Dimension), offset(stretchability),
135      XtRImmediate, (XtPointer) -1},  /* dynamic default */
136 {XmtNlayoutShrinkability, XmtCLayoutShrinkability, XtRDimension,
137      sizeof(Dimension), offset(shrinkability),
138      XtRImmediate, (XtPointer) -1},  /* dynamic default */
139 {XmtNlayoutCaption, XmtCLayoutCaption, XmRXmString,
140      sizeof(XmString), offset(caption),
141      XtRImmediate, NULL},
142 {XmtNlayoutIn, XmtCLayoutIn, XtRWidget,
143      sizeof(Object), offset(in),
144      XtRImmediate, (XtPointer) NULL},
145 {XmtNlayoutPosition, XmtCLayoutPosition, XtRPosition,
146      sizeof(Position), offset(position),
147      XtRImmediate, (XtPointer) -1},
148 {XmtNlayoutAfter, XmtCLayoutAfter, XtRWidget,
149      sizeof(Object), offset(after),
150      XtRImmediate, (XtPointer) NULL},
151 {XmtNlayoutBefore, XmtCLayoutBefore, XtRWidget,
152      sizeof(Object), offset(before),
153      XtRImmediate, (XtPointer) NULL},
154 {XmtNlayoutAllowResize, XmtCLayoutAllowResize, XtRBoolean,
155      sizeof(Boolean), offset(allow_resize),
156      XtRImmediate, (XtPointer)True},
157 {XmtNlayoutSensitive, XmtCLayoutSensitive, XtRBoolean,
158      sizeof(Boolean), offset(sensitive),
159      XtRImmediate, (XtPointer)True},
160 {XmtNlayoutJustification, XmtCLayoutJustification, XmtRXmtLayoutJustification,
161      sizeof(unsigned char), offset(justification),
162      XtRImmediate, (XtPointer)XmtLayoutFilled},
163 {XmtNlayoutMarginWidth, XmtCLayoutMarginWidth, XtRUnsignedChar,
164      sizeof(unsigned char), offset(margin_width),
165      XtRImmediate, (XtPointer)255},  /* special unset value */
166 {XmtNlayoutMarginHeight, XmtCLayoutMarginHeight, XtRUnsignedChar,
167      sizeof(unsigned char), offset(margin_height),
168      XtRImmediate, (XtPointer)255},  /* special unset value */
169 {XmtNlayoutFrameType, XmtCLayoutFrameType, XmtRXmtLayoutFrameType,
170      sizeof(unsigned char), offset(frame_type),
171      XtRImmediate, (XtPointer)XmtLayoutFrameNone},
172 {XmtNlayoutFrameLineType, XmtCLayoutFrameLineType, XmtRXmtLayoutFrameLineType,
173      sizeof(unsigned char), offset(frame_line_type),
174      XtRImmediate, (XtPointer)XmtLayoutFrameEtchedIn},
175 {XmtNlayoutFramePosition, XmtCLayoutFramePosition, XmtRXmtLayoutFramePosition,
176      sizeof(unsigned char), offset(frame_position),
177      XtRImmediate, (XtPointer)XmtLayoutFrameInside},
178 {XmtNlayoutFrameMargin, XmtCLayoutFrameMargin, XtRUnsignedChar,
179      sizeof(unsigned char), offset(frame_margin),
180      XtRImmediate, (XtPointer)2},
181 {XmtNlayoutFrameThickness, XmtCLayoutFrameThickness, XtRUnsignedChar,
182      sizeof(unsigned char), offset(frame_thickness),
183      XtRImmediate, (XtPointer)2},
184 {XmtNlayoutCaptionPosition, XmtCLayoutCaptionPosition, XmtRXmtLayoutEdge,
185      sizeof(unsigned char), offset(caption_position),
186      XtRImmediate, (XtPointer)XmtLayoutLeft},
187 {XmtNlayoutCaptionJustification, XmtCLayoutCaptionJustification,
188      XmtRXmtLayoutJustification,
189      sizeof(unsigned char), offset(caption_justification),
190      XtRImmediate, (XtPointer)XmtLayoutCentered},
191 {XmtNlayoutCaptionAlignment, XmtCLayoutCaptionAlignment, XmRAlignment,
192      sizeof(unsigned char), offset(caption_alignment),
193      XtRImmediate, (XtPointer)XmALIGNMENT_BEGINNING},
194 {XmtNlayoutCaptionMargin, XmtCLayoutCaptionMargin, XtRUnsignedChar,
195      sizeof(unsigned char), offset(caption_margin),
196      XtRImmediate, (XtPointer)2},
197 };
198 #undef offset
199 
200 #if NeedFunctionPrototypes
201 static void ClassInitialize(void);
202 static void Initialize(Widget, Widget, ArgList, Cardinal *);
203 static void Destroy(Widget);
204 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
205 static void Resize(Widget);
206 static void Realize(Widget, XtValueMask *, XSetWindowAttributes *);
207 static void Redisplay(Widget, XEvent *, Region);
208 static void ChangeManaged(Widget);
209 static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
210                                         XtWidgetGeometry *);
211 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
212                                       XtWidgetGeometry *);
213 static void InsertChild(Widget);
214 static void DeleteChild(Widget);
215 static void ConstraintInitialize(Widget, Widget, ArgList, Cardinal *);
216 static void ConstraintDestroy(Widget);
217 static Boolean ConstraintSetValues(Widget,Widget, Widget, ArgList, Cardinal *);
218 static void FocusMoved(Widget,XtPointer,XtPointer);
219 #else
220 static void ClassInitialize();
221 static void Initialize();
222 static void Destroy();
223 static Boolean SetValues();
224 static void Resize();
225 static void Realize();
226 static void Redisplay();
227 static void ChangeManaged();
228 static XtGeometryResult GeometryManager();
229 static XtGeometryResult QueryGeometry();
230 static void InsertChild();
231 static void DeleteChild();
232 static void ConstraintInitialize();
233 static void ConstraintDestroy();
234 static Boolean ConstraintSetValues();
235 static void FocusMoved();
236 #endif
237 
238 #define superclass (&xmBulletinBoardClassRec)
239 
240 externaldef(xmtlayoutclassrec) XmtLayoutClassRec xmtLayoutClassRec = {
241 {   /* core_class fields */
242     /* superclass         */    (WidgetClass) superclass,
243     /* class_name         */    "XmtLayout",
244     /* widget_size        */    sizeof(XmtLayoutRec),
245     /* class_initialize   */    ClassInitialize,
246     /* class_part_init    */    NULL,
247     /* class_inited       */    FALSE,
248     /* initialize         */    Initialize,
249     /* initialize_hook    */    NULL,
250     /* realize            */    Realize,
251     /* actions            */    NULL,
252     /* num_actions        */    0,
253     /* resources          */    resources,
254     /* num_resources      */    XtNumber(resources),
255     /* xrm_class          */    NULLQUARK,
256     /* compress_motion    */    TRUE,
257     /* compress_exposure  */    XtExposeCompressMaximal,
258     /* compress_enterleave*/    TRUE,
259     /* visible_interest   */    FALSE,
260     /* destroy            */    Destroy,
261     /* resize             */    Resize,
262     /* expose             */    Redisplay,
263     /* set_values         */    SetValues,
264     /* set_values_hook    */    NULL,
265     /* set_values_almost  */    XtInheritSetValuesAlmost,
266     /* get_values_hook    */    NULL,
267     /* accept_focus       */    NULL,
268     /* version            */    XtVersion,
269     /* callback_private   */    NULL,
270     /* tm_table           */    XtInheritTranslations,
271     /* query_geometry     */    QueryGeometry,
272     /* display_accelerator*/    XtInheritDisplayAccelerator,
273     /* extension          */    NULL
274   },
275   { /* composite_class fields */
276     /* geometry_manager   */    GeometryManager,
277     /* change_managed     */    ChangeManaged,
278     /* insert_child       */    InsertChild,
279     /* delete_child       */    DeleteChild,
280     /* extension          */    NULL
281   },
282   { /* constraint_class fields */
283     /* resource list 	  */    constraint_resources,
284     /* num resources	  */    XtNumber(constraint_resources),
285     /* constraint size    */    sizeof(XmtLayoutConstraintsRec),
286     /* init proc	  */    ConstraintInitialize,
287     /* destroy proc       */    ConstraintDestroy,
288     /* set values proc    */    ConstraintSetValues,
289     /* extension 	  */    NULL
290   },
291   { /* manager_class	  */
292     /* translations 	  */    XtInheritTranslations,
293     /* syn_resources	  */	NULL,
294     /* num_syn_resources  */	0,
295     /* syn_cont_resources */	NULL,
296     /* num_syn_cont_resources */0,
297     /* parent_process     */    XmInheritParentProcess,
298     /* extension	  */	NULL
299   },
300   { /* Bulletin Board     */
301     /* always_install_accelerators */ False,
302     /* geo_matrix_create  */	NULL,
303     /* focus_moved_proc   */	FocusMoved, /*XmInheritFocusMovedProc,*/
304     /* extension	  */    NULL
305   },
306   { /* XmtLayout          */
307     /* parser             */    NULL,
308     /* lookup_type_proc   */    NULL,
309     /* create_proc        */    NULL,
310     /* extension	  */    NULL
311   }
312 };
313 
314 externaldef(xmtlayoutwidgetclass)
315 WidgetClass xmtLayoutWidgetClass = (WidgetClass) &xmtLayoutClassRec;
316 
317 #if NeedFunctionPrototypes
ClassInitialize(void)318 static void ClassInitialize(void)
319 #else
320 static void ClassInitialize()
321 #endif
322 {
323     static String justification_names[] = {
324 	"Bottom", "Center", "Centered", "Filled", "Left", "Right", "Top"};
325     static int justification_values[] = {
326 	XmtLayoutFlushBottom, XmtLayoutCentered, XmtLayoutCentered,
327 	XmtLayoutFilled,XmtLayoutFlushLeft,
328 	XmtLayoutFlushRight, XmtLayoutFlushTop};
329     static String justification_prefixes[] = {"Xmt", "Layout", "Flush", NULL};
330 
331     static String edge_names[] = {
332 	"Bottom", "Left", "Right", "Top"};
333     static int edge_values[] = {
334         XmtLayoutBottom, XmtLayoutLeft, XmtLayoutRight, XmtLayoutTop
335     };
336     static String edge_prefixes[] = {"Xmt", "Layout", NULL};
337 
338     static String line_type_names[] = {
339         "Double", "DoubleLine", "Etched", "EtchedIn", "EtchedOut",
340         "Shadow", "ShadowIn", "ShadowOut", "Single", "SingleLine",
341     };
342     static int line_type_values[] = {
343         XmtLayoutFrameDoubleLine, XmtLayoutFrameDoubleLine,
344         XmtLayoutFrameEtchedIn, XmtLayoutFrameEtchedIn,
345         XmtLayoutFrameEtchedOut, XmtLayoutFrameShadowIn,
346         XmtLayoutFrameShadowIn, XmtLayoutFrameShadowOut,
347         XmtLayoutFrameSingleLine, XmtLayoutFrameSingleLine
348     };
349 
350     static String frame_type_names[] = {
351         "Bottom", "Box", "Left", "None", "Right", "Top" };
352     static int frame_type_values[] = {
353         XmtLayoutFrameBottom, XmtLayoutFrameBox, XmtLayoutFrameLeft,
354         XmtLayoutFrameNone, XmtLayoutFrameRight, XmtLayoutFrameTop
355     };
356     static String frame_type_prefixes[]  = {"Xmt", "Layout", "Frame", NULL};
357 
358     static String position_names[] = { "Inside", "Outside", "Through" };
359     static int position_values[] = {
360         XmtLayoutFrameInside, XmtLayoutFrameOutside, XmtLayoutFrameThrough };
361 
362     static String space_type_names[] = {
363         "CTabbed", "Even", "Interval", "LCR",
364 	"LREven", "LTabbed", "None", "RTabbed"
365     };
366     static int space_type_values[] = {
367         XmtLayoutSpaceCTabbed, XmtLayoutSpaceEven,
368 	XmtLayoutSpaceInterval, XmtLayoutSpaceLCR,
369         XmtLayoutSpaceLREven, XmtLayoutSpaceLTabbed,
370 	XmtLayoutSpaceNone, XmtLayoutSpaceRTabbed
371     };
372     static String space_type_prefixes[] = {"Xmt", "Layout", "Space", NULL};
373 
374 /* A bitmap we use for stippling captions */
375 #   define _xmt_gray50_width 32
376 #   define _xmt_gray50_height 2
377     static unsigned char _xmt_gray50_bits[] = {
378 	0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa};
379 
380     XmtRegisterEnumConverter(XmtRXmtLayoutJustification,
381 			     justification_names, justification_values,
382 			     XtNumber(justification_names),
383 			     justification_prefixes);
384 
385     XmtRegisterEnumConverter(XmtRXmtLayoutEdge,
386 			     edge_names, edge_values,
387 			     XtNumber(edge_names),
388 			     edge_prefixes);
389 
390     XmtRegisterEnumConverter(XmtRXmtLayoutFrameLineType,
391 			     line_type_names, line_type_values,
392 			     XtNumber(line_type_names),
393 			     frame_type_prefixes); /* really frame_type here */
394 
395     XmtRegisterEnumConverter(XmtRXmtLayoutFrameType,
396 			     frame_type_names, frame_type_values,
397 			     XtNumber(frame_type_names),
398 			     frame_type_prefixes);
399 
400     XmtRegisterEnumConverter(XmtRXmtLayoutFramePosition,
401 			     position_names, position_values,
402 			     XtNumber(position_names),
403 			     frame_type_prefixes); /* really */
404 
405     XmtRegisterEnumConverter(XmtRXmtLayoutSpaceType,
406 			     space_type_names, space_type_values,
407 			     XtNumber(space_type_names),
408 			     space_type_prefixes);
409 
410     XmtRegisterXbmData("_xmt_gray50", (char *)_xmt_gray50_bits, NULL,
411 		       _xmt_gray50_width, _xmt_gray50_height, 0, 0);
412 }
413 
414 #if XmVersion < 2000
415 #if NeedFunctionPrototypes
FontFromFontList(XmtLayoutWidget lw)416 static void FontFromFontList(XmtLayoutWidget lw)
417 #else
418 static void FontFromFontList(lw)
419 XmtLayoutWidget lw;
420 #endif
421 {
422     XmFontContext context;
423     XmStringCharSet charset;
424 
425     lw->layout.font_list = XmFontListCopy(lw->layout.font_list);
426     (void)XmFontListInitFontContext(&context, lw->layout.font_list);
427     (void)XmFontListGetNextFont(context, &charset, &lw->layout.font);
428     XmFontListFreeFontContext(context);
429     XtFree(charset);
430 }
431 #endif
432 
433 #if NeedFunctionPrototypes
GetGCs(XmtLayoutWidget lw)434 static void GetGCs(XmtLayoutWidget lw)
435 #else
436 static void GetGCs(lw)
437 XmtLayoutWidget lw;
438 #endif
439 {
440     XGCValues gcv;
441     XtGCMask mask;
442 
443     /*
444      * we set a font, even though we don't use it because XmStringDraw
445      * frobs the font field and will cause an X error if it is unset.
446      */
447     gcv.foreground = lw->manager.foreground;
448     gcv.background = lw->core.background_pixel;
449     gcv.font = lw->layout.font->fid;
450     gcv.line_width = 0;
451     gcv.graphics_exposures = False;
452     mask = GCForeground | GCBackground | GCFont | GCLineWidth |
453 	GCGraphicsExposures;
454    if ((lw->core.background_pixmap != None) &&
455        (lw->core.background_pixmap != XmUNSPECIFIED_PIXMAP))
456    {
457       mask |= GCFillStyle | GCTile;
458       gcv.fill_style = FillTiled;
459       gcv.tile = lw->core.background_pixmap;
460    }
461     lw->layout.gc = XtGetGC((Widget)lw, mask, &gcv);
462 
463     /*
464      * We could remember this bitmap and free it when the Layout is destroyed,
465      * but because of caching, this will rarely be worth the trouble.
466      */
467     gcv.fill_style = FillStippled;
468     gcv.stipple = XmtLookupBitmap((Widget)lw, "_xmt_gray50");
469     mask |= GCFillStyle | GCStipple;
470     mask &= ~GCTile;
471 
472     lw->layout.grey_gc = XtGetGC((Widget)lw, mask, &gcv);
473 }
474 
475 /* ARGSUSED */
476 #if NeedFunctionPrototypes
Initialize(Widget request,Widget init,ArgList args,Cardinal * num_args)477 static void Initialize(Widget request, Widget init,
478 		       ArgList args, Cardinal *num_args)
479 #else
480 static void Initialize(request, init, args, num_args)
481 Widget request;
482 Widget init;
483 ArgList args;
484 Cardinal *num_args;
485 #endif
486 {
487     XmtLayoutWidget lw = (XmtLayoutWidget) init;
488     Display *dpy = XtDisplay(init);
489     int scr = XScreenNumberOfScreen(XtScreen(init));
490     Arg arg;
491 
492 #if XmVersion < 2000
493     /*
494      * Copy the font list resource, and get its first font.
495      * Or, create a font list from the font.
496      */
497     if (lw->layout.font_list)
498 	FontFromFontList(lw);
499     else
500 	lw->layout.font_list = XmFontListCreate(lw->layout.font,
501 						XmSTRING_DEFAULT_CHARSET);
502 #else /* Motif 2.0 or later */
503     if (!lw->layout.render_table) {
504         if (!lw->layout.font_list) {
505             if (lw->layout.font) {
506                 Arg args[1];
507                 XmRendition rendition;
508 
509                 /*
510                  * If no renderTable or fontList was specified, but there is
511                  * a font, then create a renderTable.
512                  */
513                 XtSetArg(args[0], XmNfont, lw->layout.font);
514                 rendition = XmRenditionCreate(init, (XmStringTag)"default",
515                                               args, 1);
516                 lw->layout.render_table =
517 #if (XmVersion >= 2001)
518 		    XmRenderTableAddRenditions(NULL, &rendition, 1,
519 					       XmMERGE_REPLACE);
520 #else
521 		    XmRenderTableAddRenditions(NULL, &rendition, 1, XmREPLACE);
522 #endif
523             }
524             else {
525                 /*
526                  * Nothing was specified, so look up the default
527                  * renderTable.
528                  */
529                 lw->layout.render_table =
530 		    XmeGetDefaultRenderTable(init, XmLABEL_FONTLIST);
531 
532                 /* Make a copy of the renderTable. */
533                 lw->layout.render_table =
534                     XmRenderTableCopy(lw->layout.render_table, NULL, 0);
535             }
536         }
537         else {
538             /*
539              * There is a fontList, so copy it to the renderTable.
540              * NOTE: This code relies on the fact that there is no
541              *       disitinction between a fontList and a renderTable
542              *       in Motif 2.0.
543              */
544 	    lw->layout.render_table = XmFontListCopy(lw->layout.font_list);
545 	}
546     }
547     else {
548         /* Make a copy of the renderTable. */
549         lw->layout.render_table =
550 	    XmRenderTableCopy(lw->layout.render_table, NULL, 0);
551     }
552 
553     /*
554      * If no font was explicitly given, extract the default font from
555      * the renderTable.
556      */
557     if (!lw->layout.font)
558         XmeRenderTableGetDefaultFont(lw->layout.render_table,
559                                      &lw->layout.font);
560 #endif
561 
562     /* figure out resolution independence values */
563     lw->layout.pixpermm =(DisplayWidth(dpy,scr)/DisplayWidthMM(dpy,scr) +
564 			  DisplayHeight(dpy,scr)/DisplayHeightMM(dpy,scr)) / 2;
565     lw->layout.pixperem = XTextWidth(lw->layout.font, "M", 1);
566 
567 
568     /* get a GC for use by our gadget children */
569     GetGCs(lw);
570 
571     /* initialize misc. variables */
572     lw->layout.needs_layout = False;
573     lw->layout.layout_disabled = 0;
574 
575     lw->layout.in_parser = False;
576     lw->layout.geometry_okay = False;
577     lw->layout.widget_info = NULL;
578 
579     /*
580      * create the toplevel XmtLayoutBox gadget.
581      */
582     lw->layout.in_parser = True;
583     XtSetArg(arg, XmtNorientation, lw->layout.orientation);
584     /*
585      * got to initialize it to NULL first in order to detect
586      * this special case in ConstraintInitialize
587      */
588     lw->layout.toplevel = NULL;
589     lw->layout.toplevel = XmtCreateLayoutBox(init, "topbox", &arg, 1);
590     XtManageChild(lw->layout.toplevel);
591 
592     /*
593      * go parse the layout string, if any.
594      * We don't copy this string because we parse it once
595      * and never need it again.
596      */
597     if (lw->layout.layout) {
598 	if (xmtLayoutClassRec.layout_class.parser == NULL)
599 	    XmtWarningMsg("XmtLayout", "noParser",
600 			  "%s: no parser registered for layout string.\n\tSee XmtRegisterLayoutParser().",
601 			  XtName((Widget)lw));
602 	else
603 	    (*xmtLayoutClassRec.layout_class.parser)(lw, lw->layout.layout);
604     }
605     lw->layout.in_parser = False;
606 
607     /*
608      * go layout any children that were automatically created by
609      * parsing the layout string, but don't issue a resize request for
610      * the desired size.  If width and height are not set, we set them
611      * from the preferred size.
612      */
613     _XmtLayoutChildren(lw, True);
614     if (lw->core.width == 0)
615 	lw->core.width = LayoutConstraints(lw->layout.toplevel).pref_w +
616 	    2*lw->bulletin_board.margin_width;
617 
618     if (lw->core.height == 0)
619 	lw->core.height = LayoutConstraints(lw->layout.toplevel).pref_h +
620  	    2*lw->bulletin_board.margin_height;
621 }
622 
623 #if NeedFunctionPrototypes
Destroy(Widget w)624 static void Destroy(Widget w)
625 #else
626 static void Destroy(w)
627 Widget w;
628 #endif
629 {
630     XmtLayoutWidget lw = (XmtLayoutWidget) w;
631 
632 #if XmVersion < 2000
633     if (lw->layout.font_list) XmFontListFree(lw->layout.font_list);
634 #else /* Motif 2.0 or later */
635     if (lw->layout.render_table) XmRenderTableFree(lw->layout.render_table);
636 #endif
637 
638     XtReleaseGC(w, lw->layout.gc);
639     XtReleaseGC(w, lw->layout.grey_gc);
640 }
641 
642 #if NeedFunctionPrototypes
Realize(Widget w,XtValueMask * vm,XSetWindowAttributes * wa)643 static void Realize(Widget w, XtValueMask *vm, XSetWindowAttributes *wa)
644 #else
645 static void Realize(w, vm, wa)
646 Widget w;
647 XtValueMask *vm;
648 XSetWindowAttributes *wa;
649 #endif
650 {
651     XmtLayoutWidget lw = (XmtLayoutWidget)w;
652     Widget *children;
653     Cardinal num;
654     int i;
655 
656     /*
657      * Because Motif (1.1, at least) treats all RectObjs as XmGadgets,
658      * we've had to make LayoutGadgets a subclass of Object that just
659      * happen to have many of the same fields as RectObj.  There are
660      * a number of hacks here to support this--see the redefinition of
661      * XtIsManaged(), and XmtSetRectObj(), for example, in LayoutP.h
662      *
663      * This is another of those hacks--when the Layout is realized with
664      * only gadget children (as can happen with the XmtWorkingBox, e.g.)
665      * the Intrinsics decide that it has no managed children, and never
666      * invoke the ChangeManaged procedure.  We attempt to compensate for
667      * that here.
668      */
669     children = lw->composite.children;
670     num = lw->composite.num_children;
671     for(i=0; i < num; i++)
672 	if (XtIsManaged(children[i]) &&
673 	    (XtIsWidget(children[i]) || !XmtIsLayoutGadget(children[i])))
674 	    break;
675     if (i == num)
676 	ChangeManaged(w);
677 
678     /*
679      * And now envelop our superclass's realize method, so we
680      * actually get realized.
681      */
682     (*superclass->core_class.realize)(w, vm, wa);
683 }
684 
685 /* ARGSUSED */
686 #if NeedFunctionPrototypes
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)687 static Boolean SetValues(Widget current, Widget request, Widget set,
688 			 ArgList args, Cardinal *num_args)
689 #else
690 static Boolean SetValues(current, request, set, args, num_args)
691 Widget current;
692 Widget request;
693 Widget set;
694 ArgList args;
695 Cardinal *num_args;
696 #endif
697 {
698     XmtLayoutWidget cw = (XmtLayoutWidget) current;
699     XmtLayoutWidget nw = (XmtLayoutWidget) set;
700     Boolean got_new_gc = False;
701     Boolean relayout = False;
702     Boolean redisplay = False;
703 
704 #define Changed(field) (nw->layout.field != cw->layout.field)
705 
706     /* can't change XmtNlayout */
707     if (Changed(layout)) {
708 	XmtWarningMsg("XmtLayout", "setlayout",
709 		      "%s: the XmtNlayout resource may not be changed.",
710 		      XtName(set));
711 	nw->layout.layout = cw->layout.layout;
712     }
713 
714     /* can't change XmtNorientation */
715     if (Changed(orientation)) {
716 	XmtWarningMsg("XmtLayout", "setorient",
717 		      "%s: the XmtNorientation resource may not be changed.",
718 		      XtName(set));
719 	nw->layout.orientation = cw->layout.orientation;
720     }
721 
722 #if XmVersion < 2000
723     /*
724      * if fontlist or font changes, free old and figure out the other one.
725      */
726     if (Changed(font_list)) {
727 	XmFontListFree(cw->layout.font_list);
728 	FontFromFontList(nw);
729     }
730     else if (Changed(font)) {
731 	XmFontListFree(cw->layout.font_list);
732 	nw->layout.font_list = XmFontListCreate(nw->layout.font,
733 						XmSTRING_DEFAULT_CHARSET);
734     }
735 #else /* Motif 2.0 or later */
736     if (Changed(render_table) || !nw->layout.font) {
737         XmRenderTableFree(cw->layout.render_table);
738         if (nw->layout.render_table == NULL) {
739             nw->layout.render_table =
740                XmeGetDefaultRenderTable(set, XmLABEL_FONTLIST);
741         }
742         nw->layout.render_table =
743            XmRenderTableCopy(nw->layout.render_table, NULL, 0);
744 	/* unset the font, so it will be recomputed below */
745 	nw->layout.font = NULL;
746     }
747     else if (Changed(font_list)) {
748         XmRenderTableFree(cw->layout.render_table);
749         if (nw->layout.font_list == NULL) {
750             nw->layout.font_list =
751                XmeGetDefaultRenderTable(set, XmLABEL_FONTLIST);
752         }
753         nw->layout.render_table = XmFontListCopy(nw->layout.font_list);
754 	/* unset the font, so it will be recomputed below */
755 	nw->layout.font = NULL;
756     }
757     else if (Changed(font)) {
758         Arg args[1];
759         XmRendition rendition;
760 
761         XmRenderTableFree(cw->layout.render_table);
762 
763         XtSetArg(args[0], XmNfont, nw->layout.font);
764         rendition = XmRenditionCreate(set, (XmStringTag)"default",
765                                       args, 1);
766         nw->layout.render_table =
767 #if (XmVersion >= 2001)
768            XmRenderTableAddRenditions(NULL, &rendition, 1, XmMERGE_REPLACE);
769 #else
770            XmRenderTableAddRenditions(NULL, &rendition, 1, XmREPLACE);
771 #endif
772     }
773 
774     if (!nw->layout.font)
775         /* Extract the default font from the renderTable. */
776         XmeRenderTableGetDefaultFont(nw->layout.render_table,
777                                      &nw->layout.font);
778 #endif
779 
780     /*
781      * if the font list changed through either of the above cases,
782      * get a new GC, change resolution independence values,
783      * invoke the change_font method on all LayoutStringGadget children,
784      * and re-measure all caption strings.
785      */
786 #if XmVersion < 2000
787       if (Changed(font_list)) {
788 #else /* Motif 2.0 or later */
789     if (Changed(render_table)) {
790 #endif
791 	int i;
792 	Widget child;
793 	XmtLayoutConstraintsPart *c;
794 
795 	XtReleaseGC(set, cw->layout.gc);
796 	XtReleaseGC(set, cw->layout.grey_gc);
797 	GetGCs(nw);
798 	got_new_gc = True;
799 
800 	/*
801 	 * we can compute new resolution independence conversion values,
802 	 * but we cannot go update all the children that had their size
803 	 * based on the font...
804 	 */
805 	nw->layout.pixperem = XTextWidth(nw->layout.font, "M", 1);
806 
807 	/*
808 	 * tell any LayoutGadget children that care about the change.
809 	 * This is a hardcoded dependency which is a little gross.
810 	 * It means that we don't have to keep a bunch of copies of
811 	 * the same fontlist around, however.
812 	 */
813 	for(i=0; i < nw->composite.num_children; i++) {
814 	    child = nw->composite.children[i];
815 	    c = LayoutConstraintsRec(child);
816 	    if (!XtIsWidget(child) && !XmIsGadget(child)
817 		&& XtIsSubclass(child, xmtLayoutGadgetClass))
818 		_XmtCallChangeFontMethod(child);
819 	    if (c->caption) {
820 #if XmVersion < 2000
821 		XmStringExtent(nw->layout.font_list, c->caption,
822 			       &c->caption_width, &c->caption_height);
823 #else /* Motif 2.0 or later */
824 		XmStringExtent(nw->layout.render_table, c->caption,
825 			       &c->caption_width, &c->caption_height);
826 #endif
827 	    }
828 	}
829 
830 	relayout = True;
831     }
832 
833     if (Changed(debug_layout))
834 	relayout = True;
835 
836     /* if colors changed and we haven't already done so, get a new gc */
837     if (!got_new_gc &&
838 	((nw->core.background_pixel != cw->core.background_pixel) ||
839 	 (nw->manager.foreground != cw->manager.foreground))) {
840 	XtReleaseGC(set, cw->layout.gc);
841 	XtReleaseGC(set, cw->layout.grey_gc);
842 	GetGCs(nw);
843 	redisplay = True;
844     }
845 
846     /* if margin size changed, re-layout everything */
847     if ((nw->bulletin_board.margin_width != cw->bulletin_board.margin_width) ||
848 	(nw->bulletin_board.margin_height != cw->bulletin_board.margin_height))
849 	relayout = True;
850 
851     /* if sensitivity changed, redisplay everything to change captions */
852     if (nw->core.sensitive != cw->core.sensitive) redisplay = True;
853 
854     if (relayout)
855 	_XmtLayoutChildren(nw, True);
856 
857     return redisplay | relayout;
858 
859 #undef Changed
860 }
861 
862 #if NeedFunctionPrototypes
_XmtLayoutChildren(XmtLayoutWidget lw,XmtWideBoolean resize)863 void _XmtLayoutChildren(XmtLayoutWidget lw, XmtWideBoolean resize)
864 #else
865 void _XmtLayoutChildren(lw, resize)
866 XmtLayoutWidget lw;
867 int resize;
868 #endif
869 {
870     XtWidgetGeometry geometry;
871 
872     /* don't do anything if we've been told not to,
873      * but remember to later
874      */
875     if (lw->layout.layout_disabled > 0) {
876 	lw->layout.needs_layout = True;
877 	return;
878     }
879 
880     /*
881      * figure out how big we'd like to be.
882      * the gadget's query_geometry methods also do other necessary
883      * computation, so this must be called before the resize method...
884      */
885     XtQueryGeometry(lw->layout.toplevel, NULL, &geometry);
886 
887     /* XXX
888      * Under some circumstances, this query may return a width and height
889      * of 0.  If the margins are zero as well, the call to
890      * XtMakeResizeRequest() below will cause an X Error.  So we ensure
891      * that this never happens.  Note that it is probably a bug that is
892      * making the query return a 0,0 size, but it can't hurt to be safe here...
893      */
894     if (geometry.width == 0) geometry.width = 1;
895     if (geometry.height == 0) geometry.height = 1;
896 
897     /* remember this preferred size */
898     LayoutConstraints(lw->layout.toplevel).pref_w = geometry.width;
899     LayoutConstraints(lw->layout.toplevel).pref_h = geometry.height;
900 
901     /* add a margin all the way around */
902     geometry.width += 2*lw->bulletin_board.margin_width;
903     geometry.height += 2*lw->bulletin_board.margin_height;
904 
905     /* ask for size plus margins unless we're being called from Resize */
906     if (resize &&
907 	((geometry.width != lw->core.width) ||
908 	 (geometry.height != lw->core.height))) {
909 	XtGeometryResult result;
910 	Dimension compromisew, compromiseh;
911 	Dimension requestedw, requestedh;
912 
913 	requestedw = lw->core.width;
914 	requestedh = lw->core.height;
915 
916 	if (lw->bulletin_board.resize_policy == XmRESIZE_ANY) {
917 	    requestedw = geometry.width;
918 	    requestedh = geometry.height;
919 	} else if (lw->bulletin_board.resize_policy == XmRESIZE_GROW) {
920 	    if (requestedw < geometry.width) {
921 		requestedw = geometry.width;
922 	    }
923 	    if (requestedh < geometry.height) {
924 		requestedh = geometry.height;
925 	    }
926 	}
927 	result = XtMakeResizeRequest((Widget)lw,
928 				     requestedw, requestedh,
929 				     &compromisew, &compromiseh);
930 	if (result == XtGeometryAlmost)
931 	    XtMakeResizeRequest((Widget)lw,compromisew,compromiseh,NULL, NULL);
932     }
933 
934     /*
935      * Whether we got a new size or not, configure all the kids
936      * to the current size.
937      * If the size hasn't changed, this call is a no-op.
938      * This means that when we're called from changeManaged, often
939      * nothing is called, and the new widget doesn't get configured
940      * to appear in the right place.  To work around this, we explictly
941      * set the width on the toplevel box to something different.
942      */
943     lw->layout.toplevel->core.width = 0;
944     XtConfigureWidget(lw->layout.toplevel,
945 		      lw->bulletin_board.margin_width,
946 		      lw->bulletin_board.margin_height,
947 		      lw->core.width - 2*lw->bulletin_board.margin_width,
948 		      lw->core.height - 2*lw->bulletin_board.margin_height,
949 		      lw->layout.toplevel->core.border_width);
950 
951     lw->layout.needs_layout = False;
952 
953     /*
954      * When the Layout contains a lot of layout gadgets, this relayout
955      * process will cause a lot of XClearArea() expose events.  For
956      * complicated layouts, the Intrinsics may call the Expose() method
957      * before all the events have arrived and been put in the queue.
958      * Adding a call to XSync() here seems to help with this problem
959      * in some cases.
960      */
961     XSync(XtDisplay(lw), False);
962 }
963 
964 
965 #if NeedFunctionPrototypes
DrawFrame(XmtLayoutWidget lw,XmtLayoutFrameType type,XmtLayoutFrameLineType linetype,int thickness,int x,int y,int w,int h)966 static void DrawFrame(XmtLayoutWidget lw, XmtLayoutFrameType type,
967 		      XmtLayoutFrameLineType linetype,
968 		      int thickness, int x, int y, int w, int h)
969 #else
970 static void DrawFrame(lw, type, linetype, thickness, x, y, w, h)
971 XmtLayoutWidget lw;
972 XmtLayoutFrameType type;
973 XmtLayoutFrameLineType linetype;
974 int thickness;
975 int x;
976 int y;
977 int w;
978 int h;
979 #endif
980 {
981     Display *dpy = XtDisplay((Widget)lw);
982     Window win = XtWindow((Widget)lw);
983     Boolean horizontal = False;
984     GC topgc = lw->manager.top_shadow_GC;
985     GC botgc = lw->manager.bottom_shadow_GC;
986     GC tmpgc;  /* for swapping */
987     int halfthick = thickness/2;
988 
989     if (type == XmtLayoutFrameNone) return;
990 
991     if (type == XmtLayoutFrameTop || type == XmtLayoutFrameBottom)
992 	horizontal = True;
993 
994     if (thickness == 1) linetype = XmtLayoutFrameSingleLine;
995 
996     if (linetype == XmtLayoutFrameSingleLine) {
997 	XGCValues values;
998 
999 	if (thickness > 1) {
1000 	    values.line_width = thickness;
1001 	    XChangeGC(dpy, lw->layout.gc, GCLineWidth, &values);
1002 	}
1003 
1004         if ((lw->core.background_pixmap != None) &&
1005             (lw->core.background_pixmap != XmUNSPECIFIED_PIXMAP)) {
1006             XSetFillStyle(dpy, lw->layout.gc, FillSolid);
1007         }
1008 	if (type == XmtLayoutFrameBox)
1009 	    XDrawRectangle(dpy, win, lw->layout.gc,
1010 			   x+halfthick, y+halfthick,
1011 			   w-thickness, h-thickness);
1012 	else if (horizontal)
1013 	    XDrawLine(dpy, win, lw->layout.gc,
1014 		      x, y+halfthick, x+w, y+halfthick);
1015 	else
1016 	    XDrawLine(dpy, win, lw->layout.gc,
1017 		      x+halfthick, y, x+halfthick, y+h);
1018 
1019 	if (thickness > 1) {
1020 	    values.line_width = 0;
1021 	    XChangeGC(dpy, lw->layout.gc, GCLineWidth, &values);
1022 	}
1023     }
1024     else if (linetype == XmtLayoutFrameDoubleLine)
1025     {
1026 	if (type == XmtLayoutFrameBox) {
1027 	    XDrawRectangle(dpy, win, lw->layout.gc, x, y, w-1, h-1);
1028 	    XDrawRectangle(dpy, win, lw->layout.gc,
1029 			   x+thickness-1, y+thickness-1,
1030 			   w-2*(thickness-1)-1, h-2*(thickness-1)-1);
1031 	}
1032 	else if (horizontal) {
1033 	    XDrawLine(dpy, win, lw->layout.gc, x, y, x+w, y);
1034 	    XDrawLine(dpy, win, lw->layout.gc,
1035 		      x, y+thickness-1, x+w, y+thickness-1);
1036 	}
1037 	else {
1038 	    XDrawLine(dpy, win, lw->layout.gc, x, y, x, y+h);
1039 	    XDrawLine(dpy, win, lw->layout.gc,
1040 		      x+thickness-1, y, x+thickness-1, y+h);
1041 	}
1042     }
1043     else {
1044 	if (type == XmtLayoutFrameBox) {
1045 #if XmVersion >= 1002
1046 	    {
1047 		int xmtype;
1048 
1049 		switch(linetype) {
1050 		case XmtLayoutFrameShadowIn:
1051 		    xmtype = XmSHADOW_IN;
1052 		    break;
1053 		case XmtLayoutFrameShadowOut:
1054 		    xmtype = XmSHADOW_OUT;
1055 		    break;
1056 		default:
1057 		case XmtLayoutFrameEtchedIn:
1058 		    xmtype = XmSHADOW_ETCHED_IN;
1059 		    break;
1060 		case XmtLayoutFrameEtchedOut:
1061 		    xmtype = XmSHADOW_ETCHED_OUT;
1062 		    break;
1063 		}
1064 #if XmVersion >= 2000
1065 		XmeDrawShadows(dpy, win, topgc, botgc,
1066 			       x, y, w, h, thickness, xmtype);
1067 #else
1068 		_XmDrawShadows(dpy, win, topgc, botgc,
1069 			       x, y, w, h, thickness, xmtype);
1070 #endif
1071 	    }
1072 #else
1073 	    {
1074 		int roundthick = halfthick*2;
1075 
1076 		if (linetype == XmtLayoutFrameShadowIn ||
1077 		    linetype == XmtLayoutFrameEtchedIn) {
1078 		    tmpgc = botgc;
1079 		    botgc = topgc;
1080 		    topgc = tmpgc;
1081 		}
1082 
1083 		switch(linetype) {
1084 		case XmtLayoutFrameShadowOut:
1085 		case XmtLayoutFrameShadowIn:
1086 		    _XmDrawShadow(dpy, win, topgc, botgc, thickness,
1087 				  x, y, w, h);
1088 		    break;
1089 		case XmtLayoutFrameEtchedOut:
1090 		case XmtLayoutFrameEtchedIn:
1091 		    _XmDrawShadow(dpy, win, topgc, botgc, halfthick,
1092 				  x, y, w, h);
1093 		    _XmDrawShadow(dpy, win, botgc, topgc, halfthick,
1094 				  x+halfthick, y+halfthick,
1095 				  w-roundthick, h-roundthick);
1096 		    break;
1097 		default:
1098 		    break;
1099 		}
1100 	    }
1101 #endif
1102 	}
1103 	else {  /* draw an etched line in or out */
1104 	    if (linetype == XmtLayoutFrameShadowIn)
1105 		linetype = XmtLayoutFrameEtchedIn;
1106 	    if (linetype == XmtLayoutFrameShadowOut)
1107 		linetype = XmtLayoutFrameEtchedOut;
1108 	    if (linetype == XmtLayoutFrameEtchedIn) {
1109 		tmpgc = botgc;
1110 		botgc = topgc;
1111 		topgc = tmpgc;
1112 	    }
1113 	    if (horizontal) {
1114 		XFillRectangle(dpy, win, topgc, x, y, w, halfthick);
1115 		XFillRectangle(dpy, win, botgc,
1116 			       x, y+halfthick, w, thickness-halfthick);
1117 	    }
1118 	    else {
1119 		XFillRectangle(dpy, win, topgc, x, y, halfthick, h);
1120 		XFillRectangle(dpy, win, botgc,
1121 			       x+halfthick, y, thickness-halfthick, h);
1122 	    }
1123 	}
1124     }
1125 }
1126 
1127 
1128 #if NeedFunctionPrototypes
DrawFrameAndCaption(XmtLayoutWidget lw,Widget c,Region region,Boolean clear)1129 static void DrawFrameAndCaption(XmtLayoutWidget lw, Widget c, Region region, Boolean clear)
1130 #else
1131 static void DrawFrameAndCaption(lw, c, region, clear)
1132 XmtLayoutWidget lw;
1133 Widget c;
1134 Region region;
1135 Boolean clear;
1136 #endif
1137 {
1138     XmtLayoutConstraintsPart *cc;
1139     int x, y, w, h;      /* coordinates of widget */
1140     int fx, fy, fw, fh;  /* coordinates of outside of frame */
1141     int cx, cy, cw, ch;  /* coordinates of caption bounding box*/
1142     XmtLayoutFrameType frame_type;
1143     XmtLayoutFrameLineType frame_line_type;
1144     int frame_thickness;
1145     int frame_margin;
1146     XmtLayoutFramePosition frame_position;
1147     int frame_total;
1148     int caption_total_width, caption_total_height;
1149     Boolean frame_redrawn;
1150 
1151     /*
1152      * For the specified child widget:
1153      * compute the position of the frame and caption.  If the frame intersects
1154      * the region, redraw it.  If the caption intersects the region, or
1155      * if the frame intersects the caption and the frame was redrawn, then
1156      * redraw the caption
1157      */
1158 
1159     cc = LayoutConstraintsRec(c);
1160 
1161     /* get the frame args.  If debug_layout is set, force fixed values */
1162     frame_type = cc->frame_type;
1163     frame_line_type = cc->frame_line_type;
1164     frame_margin = cc->frame_margin;
1165     frame_thickness = cc->frame_thickness;
1166     frame_position = cc->frame_position;
1167     if (lw->layout.debug_layout) {
1168 	frame_type = XmtLayoutFrameBox;
1169 	frame_line_type = XmtLayoutFrameSingleLine;
1170 	frame_margin = 5;
1171 	frame_thickness = 1;
1172 	frame_position = XmtLayoutFrameOutside;
1173     }
1174 
1175     frame_total = frame_margin + frame_thickness;
1176     if (cc->caption) {
1177 	caption_total_width = cc->caption_width + cc->caption_margin;
1178 	caption_total_height = cc->caption_height + cc->caption_margin;
1179     }
1180 
1181     /* if no frame or caption, don't do anything */
1182     if (cc->caption == NULL && frame_type == XmtLayoutFrameNone)
1183 	return;
1184 
1185     /* widget coordinates */
1186     x = c->core.x; y = c->core.y; w = c->core.width; h = c->core.height;
1187 
1188     /* compute coordinates of outside of frame */
1189     if (frame_type != XmtLayoutFrameNone) {
1190 	fx = x - frame_total;
1191 	fy = y - frame_total;
1192 	fw = w + 2*frame_total;
1193 	fh = h + 2*frame_total;
1194 	if (cc->caption &&
1195 	    (frame_position == XmtLayoutFrameOutside)) {
1196 	    switch (cc->caption_position) {
1197 	    case XmtLayoutTop:
1198 		fy -= caption_total_height;
1199 		/* note no break statement */
1200 	    case XmtLayoutBottom:
1201 		fh += caption_total_height;
1202 		break;
1203 	    case XmtLayoutLeft:
1204 		fx -= caption_total_width;
1205 		/* note no break statement */
1206 	    case XmtLayoutRight:
1207 		fw += caption_total_width;
1208 		break;
1209 	    }
1210 	}
1211     }
1212 
1213     /* if the frame is just a line rather than a box, adjust coords */
1214     /* (x,y) will be top left of line, now, not outside of frame */
1215     switch(frame_type) {
1216     case XmtLayoutFrameBottom:
1217 	fy += fh - frame_thickness;
1218 	/* note: no break statement */
1219     case XmtLayoutFrameTop:
1220 	fx += frame_total;
1221 	fw -= 2*frame_total;
1222 	break;
1223     case XmtLayoutFrameRight:
1224 	fx += fw - frame_thickness;
1225 	/* note: no break */
1226     case XmtLayoutFrameLeft:
1227 	fy += frame_total;
1228 	fh -= 2*frame_total;
1229 	break;
1230     default: break;
1231     }
1232 
1233     /* compute coordinates of caption bounding box */
1234     if (cc->caption) {
1235 	/* width and height are given */
1236 	cw = cc->caption_width;
1237 	ch = cc->caption_height;
1238 
1239 	/* compute one dimension based on position */
1240 	switch (cc->caption_position) {
1241 	case XmtLayoutTop:
1242 	    cy = y - (cc->caption_margin + ch);
1243 	    break;
1244 	case XmtLayoutBottom:
1245 	    cy = y + h + cc->caption_margin;
1246 	    break;
1247 	case XmtLayoutLeft:
1248 	    cx = x - (cc->caption_margin + cw);
1249 	    break;
1250 	case XmtLayoutRight:
1251 	    cx = x + w + cc->caption_margin;
1252 	    break;
1253 	}
1254 
1255 	/* compute the other dimension based on justification */
1256 	if ((cc->caption_position == XmtLayoutTop) ||
1257 	    (cc->caption_position == XmtLayoutBottom)) {
1258 	    switch (cc->caption_justification) {
1259 	    case XmtLayoutFilled:
1260 	    case XmtLayoutFlushLeft:  cx = x; break;
1261 	    case XmtLayoutCentered:   cx = x + (w - cw)/2; break;
1262 	    case XmtLayoutFlushRight: cx = x + w - cw; break;
1263 	    }
1264 	}
1265 	else if ((cc->caption_position == XmtLayoutLeft) ||
1266 		 (cc->caption_position == XmtLayoutRight)) {
1267 	    switch (cc->caption_justification) {
1268 	    case XmtLayoutFilled:
1269 	    case XmtLayoutFlushLeft:  cy = y; break;
1270 	    case XmtLayoutCentered:   cy = y + (h - ch)/2; break;
1271 	    case XmtLayoutFlushRight: cy = y + h - ch; break;
1272 	    }
1273 	}
1274 
1275 	/* if there is a frame inside the caption, adjust position */
1276 	if ((frame_type != XmtLayoutFrameNone) &&
1277 	    (frame_position == XmtLayoutFrameInside)) {
1278 
1279 	    /* adjustments for full frames */
1280 	    if (frame_type == XmtLayoutFrameBox) {
1281 		switch (cc->caption_position) {
1282 		case XmtLayoutTop:     cy -= frame_total; break;
1283 		case XmtLayoutBottom:  cy += frame_total; break;
1284 		case XmtLayoutLeft:    cx -= frame_total; break;
1285 		case XmtLayoutRight:   cx += frame_total; break;
1286 		}
1287 
1288 		if ((cc->caption_position == XmtLayoutTop) ||
1289 		    (cc->caption_position == XmtLayoutBottom)) {
1290 		    switch (cc->caption_justification) {
1291 		    case XmtLayoutFilled:
1292 		    case XmtLayoutFlushLeft:  cx -= frame_total; break;
1293 		    case XmtLayoutCentered:   break;
1294 		    case XmtLayoutFlushRight: cx += frame_total; break;
1295 		    }
1296 		}
1297 		else if ((cc->caption_position == XmtLayoutLeft) ||
1298 			 (cc->caption_position == XmtLayoutRight)) {
1299 		    switch (cc->caption_justification) {
1300 		    case XmtLayoutFilled:
1301 		    case XmtLayoutFlushLeft:  cy -= frame_total; break;
1302 		    case XmtLayoutCentered:   break;
1303 		    case XmtLayoutFlushRight: cy += frame_total; break;
1304 		    }
1305 		}
1306 	    }
1307 	    else if (frame_type == XmtLayoutFrameLeft) {
1308 		if (cc->caption_position == XmtLayoutLeft)
1309 		    cx -= frame_total;
1310 	    }
1311 	    else if (frame_type == XmtLayoutFrameRight) {
1312 		if (cc->caption_position == XmtLayoutRight)
1313 		    cx += frame_total;
1314 	    }
1315 	    else if (frame_type == XmtLayoutFrameTop) {
1316 		if (cc->caption_position == XmtLayoutTop)
1317 		    cy -= frame_total;
1318 	    }
1319 	    else if (frame_type == XmtLayoutFrameBottom) {
1320 		if (cc->caption_position == XmtLayoutBottom)
1321 		    cy += frame_total;
1322 	    }
1323 	}
1324     }
1325 
1326     /* if there is a frame, and it is in the exposed region, redraw it */
1327     frame_redrawn = False;
1328     if ((frame_type != XmtLayoutFrameNone) &&
1329 	(!region || (XRectInRegion(region, fx, fy, fw, fh) != RectangleOut))) {
1330 	frame_redrawn = True;
1331 	DrawFrame(lw, frame_type, frame_line_type, frame_thickness,
1332 		  fx, fy, fw, fh);
1333     }
1334 
1335     /*
1336      * if there is a caption, and it is in the exposed region,
1337      * or if it intersects the frame and the frame was redrawn
1338      * then redraw it.
1339      */
1340     if (cc->caption &&
1341 	(!region ||
1342 	 (XRectInRegion(region, cx, cy, cw, ch) != RectangleOut) ||
1343 	 (frame_redrawn && (frame_position == XmtLayoutFrameThrough)))) {
1344 	/* X protocol ignores stippling with DrawImage functions,
1345 	 * so we simulate XmStringDrawImage by clearing first
1346          *
1347          * This is, of course, not needed if this is due to an Expose.
1348   	 */
1349         if (clear || (frame_redrawn && frame_position == XmtLayoutFrameThrough)) {
1350 
1351             XClearArea(XtDisplay((Widget)lw), XtWindow((Widget)lw),
1352                        cx, cy, cw, ch, False);
1353         }
1354     /* Lazy here: instead of having a separate GC for text,
1355        just change FillStyle if there is a background pixmap
1356        */
1357 	if (lw->core.background_pixmap != None &&
1358 	    lw->core.background_pixmap != XmUNSPECIFIED_PIXMAP)
1359 	{
1360 	    XSetFillStyle(XtDisplay((Widget)lw), lw->layout.gc, FillSolid);
1361 	}
1362 	XmStringDraw(XtDisplay((Widget)lw), XtWindow((Widget)lw),
1363 #if XmVersion < 2000
1364                      lw->layout.font_list,
1365 #else /* Motif 2.0 or later */
1366 		     lw->layout.render_table,
1367 #endif
1368                      cc->caption,
1369 		     (lw->core.ancestor_sensitive &&
1370 		      lw->core.sensitive &&
1371 		      cc->sensitive)
1372 		     ?lw->layout.gc
1373 		     :lw->layout.grey_gc,
1374 		     cx, cy, cw,
1375 		     cc->caption_alignment,
1376 		     XmSTRING_DIRECTION_L_TO_R, NULL);
1377 	if (lw->core.background_pixmap != None &&
1378 	    lw->core.background_pixmap != XmUNSPECIFIED_PIXMAP)
1379 	{
1380 	    XSetFillStyle(XtDisplay((Widget)lw), lw->layout.gc, FillTiled);
1381 	}
1382     }
1383 }
1384 
1385 
1386 #if NeedFunctionPrototypes
DrawFramesAndCaptions(XmtLayoutWidget lw,Region region)1387 static void DrawFramesAndCaptions(XmtLayoutWidget lw, Region region)
1388 #else
1389 static void DrawFramesAndCaptions(lw, region)
1390 XmtLayoutWidget lw;
1391 Region region;
1392 #endif
1393 {
1394     int i;
1395     Widget c;
1396 
1397     /*
1398      * For each child widget:
1399      * compute the position of the frame and caption.  If the frame intersects
1400      * the region, redraw it.  If the caption intersects the region, or
1401      * if the frame intersects the caption and the frame was redrawn, then
1402      * redraw the caption
1403      */
1404 
1405     ForEachChild(lw, c)
1406 	if (XtIsManaged(c))
1407 	    DrawFrameAndCaption(lw, c, region, False);
1408 }
1409 
1410 #if NeedFunctionPrototypes
Redisplay(Widget widget,XEvent * event,Region region)1411 static void Redisplay(Widget widget, XEvent *event, Region region)
1412 #else
1413 static void Redisplay(widget, event, region)
1414 Widget widget;
1415 XEvent *event;
1416 Region region;
1417 #endif
1418 {
1419     XmtLayoutWidget lw = (XmtLayoutWidget) widget;
1420 
1421     /* invoke the Redisplay method of the topmost XmtLayoutBox */
1422     _XmtRedisplayGadget(lw->layout.toplevel, event, region);
1423 
1424     /* redisplay any Xm Gadgets */
1425     _XmtRedisplayGadgets(widget, event, region);
1426 
1427     /* go draw all the XmtLayout frames and captions */
1428     DrawFramesAndCaptions(lw, region);
1429 }
1430 
1431 #if NeedFunctionPrototypes
Resize(Widget w)1432 static void Resize(Widget w)
1433 #else
1434 static void Resize(w)
1435 Widget w;
1436 #endif
1437 {
1438     if (XtIsRealized(w)) XClearWindow(XtDisplay(w), XtWindow(w));
1439     _XmtLayoutChildren((XmtLayoutWidget) w, False);
1440 }
1441 
1442 #if NeedFunctionPrototypes
ChangeManaged(Widget w)1443 static void ChangeManaged(Widget w)
1444 #else
1445 static void ChangeManaged(w)
1446 Widget w;
1447 #endif
1448 {
1449     _XmtLayoutChildren((XmtLayoutWidget) w, True);
1450 }
1451 
1452 
1453 
1454 
1455 /*
1456  * This GeometryManager() method is invoked in two distinct cases.
1457  * 1) When a child widget calls XtMakeGeometryRequest() to change something.
1458  *    In this case, we deny the request if XmtNlayoutAllowResize if False,
1459  *    or if the child is trying to change its position, rather than its size.
1460  *    Otherwise we grant the request.  When we grant this request, we call
1461  *    _XmtLayoutChildren() to configure the widget (and any of its siblings
1462  *    that change as a result, and return XtGeometryDone.  The algorithm in
1463  *    this case is modified from the Xaw Form widget.
1464  * 2) When the user sets a resource on a child that directly or indirectly
1465  *    changes a geometry field of the widget.  After a SetValues() request,
1466  *    the Intrinsics automatically call this method if any geometry fields
1467  *    have changed.  In this case, the ConstraintSetValues() method will
1468  *    always be called before this method is.  We have to handle this case
1469  *    specially because of the constraint resources.  If the XmtNlayoutIn
1470  *    constraint is set, for example, then the CSV method will call
1471  *    _XmtLayoutChildren() to rearrange things.  This means that the position
1472  *    of the child widget will change, and this change will be legal.  If
1473  *    we didn't have a special case, the change would be rejected.  Also,
1474  *    since _XmtLayoutChildren() has already been called, we know that we
1475  *    don't have to call it again here.  We do have to call XtConfigureWidget()
1476  *    however--when ConstraintSetValues() calls _XmtLayoutChildren(),
1477  *    the geometry fields of the widget are set at their new values, and so
1478  *    when _XmtLayoutChildren() tries to configure the widget to those
1479  *    new values (in the resize() method of LayoutBox.c), the Intrinsics
1480  *    will think that it doesn't have to do anything.
1481  *    Note the use of the geometry_okay flag for communication between
1482  *    the CSV method and this method.
1483  */
1484 /* ARGSUSED */
1485 #if NeedFunctionPrototypes
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)1486 static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
1487 					XtWidgetGeometry *reply)
1488 #else
1489 static XtGeometryResult GeometryManager(w, request, reply)
1490 Widget w;
1491 XtWidgetGeometry *request;
1492 XtWidgetGeometry *reply;
1493 #endif
1494 {
1495     XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(w);
1496     Position x,y;
1497     Dimension width, height, border_width;
1498 
1499     if (XtIsShell(w)) {
1500 	return(0);
1501     }
1502 
1503     /* this is case 2 described above */
1504     if (lw->layout.geometry_okay) {
1505 	XtConfigureWidget(w,
1506 	      (request->request_mode&CWX)?request->x:w->core.x,
1507 	      (request->request_mode&CWY)?request->y:w->core.y,
1508 	      (request->request_mode&CWWidth)?request->width:w->core.width,
1509 	      (request->request_mode&CWHeight)?request->height:w->core.height,
1510 	      (request->request_mode&CWBorderWidth)?request->border_width
1511 			  :w->core.border_width);
1512 
1513 	/* make sure we don't do this again without cause */
1514 	lw->layout.geometry_okay = False;
1515 
1516 	/*
1517 	 * Tell the Intrinsics we've done the update for it.  Note
1518 	 * that in this case, when the geometry_okay flag is set,
1519 	 * the Layout widget has already been re-laid out.  However,
1520 	 * this particular child may not have had its window
1521 	 * coordinates updated, as explained in a comment in
1522 	 * ConstraintSetValues().  Thus we do have to do the update here.
1523 	 */
1524 	return XtGeometryDone;
1525     }
1526 
1527     /* Otherwise, we handle case 1 described above */
1528     if (!LayoutConstraints(w).allow_resize) return XtGeometryNo;
1529 
1530     if (request->request_mode & ~(XtCWQueryOnly | CWWidth | CWHeight))
1531 	return XtGeometryNo;
1532 
1533     if (request->request_mode & CWWidth)
1534 	width = request->width;
1535     else
1536 	width = w->core.width;
1537 
1538     if (request->request_mode & CWHeight)
1539 	height = request->height;
1540     else
1541 	height = w->core.height;
1542 
1543     if (width == w->core.width && height == w->core.height)
1544 	return XtGeometryNo;
1545 
1546     if (!(request->request_mode & XtCWQueryOnly)) {
1547 	XtResizeWidget(w, width, height, w->core.border_width);
1548 	_XmtLayoutChildren((XmtLayoutWidget)XtParent(w), True);
1549 	return XtGeometryDone;
1550     }
1551     else
1552 	return XtGeometryYes;
1553 }
1554 
1555 /* stolen from Xaw Form widget.  Hope it works right */
1556 #if NeedFunctionPrototypes
QueryGeometry(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)1557 static XtGeometryResult QueryGeometry(Widget widget,
1558 				      XtWidgetGeometry *request,
1559 				      XtWidgetGeometry *reply)
1560 #else
1561 static XtGeometryResult QueryGeometry(widget, request, reply)
1562 Widget widget;
1563 XtWidgetGeometry *request;
1564 XtWidgetGeometry *reply;
1565 #endif
1566 {
1567     XmtLayoutWidget w = (XmtLayoutWidget)widget;
1568     int	wantedWidth;
1569     int wantedHeight;
1570 
1571     if (w->bulletin_board.resize_policy == XmRESIZE_NONE) {
1572 	wantedWidth = w->core.width;
1573 	wantedHeight = w->core.height;
1574     } else {
1575 	wantedWidth = LayoutConstraints(w->layout.toplevel).pref_w +
1576 	              2 * w->bulletin_board.margin_width;
1577 	wantedHeight = LayoutConstraints(w->layout.toplevel).pref_h +
1578 	              2 * w->bulletin_board.margin_height;
1579 	if (w->bulletin_board.resize_policy == XmRESIZE_GROW) {
1580 	    if (wantedWidth < w->core.width) {
1581 		wantedWidth = w->core.width;
1582 	    }
1583 	    if (wantedHeight < w->core.height) {
1584 		wantedHeight = w->core.height;
1585 	    }
1586 	} /* else resize_policy == XmRESIZE_ANY */
1587     }
1588     reply->width = wantedWidth;
1589     reply->height = wantedHeight;
1590     reply->request_mode = CWWidth | CWHeight;
1591     if (request->request_mode & (CWWidth | CWHeight) == (CWWidth | CWHeight)
1592 	&& request->width == reply->width
1593 	&& request->height == reply->height)
1594 	return XtGeometryYes;
1595     else if (reply->width == w->core.width && reply->height == w->core.height)
1596 	return XtGeometryNo;
1597     else
1598 	return XtGeometryAlmost;
1599 }
1600 
1601 #if NeedFunctionPrototypes
InsertChild(Widget w)1602 static void InsertChild(Widget w)
1603 #else
1604 static void InsertChild(w)
1605 Widget w;
1606 #endif
1607 {
1608     /*
1609      * This is another Motif workaround.
1610      * The BulletinBoard and Manager class InsertChild procedures ignore
1611      * non-rectobj children, and never insert them in the children array.
1612      * The workaround is to call the bulletin board method if this is a
1613      * RectObj, and call the composite method if this is a LayoutGadget,
1614      * and do nothing otherwise.  Same for DeleteChild.
1615      */
1616     if (XtIsRectObj(w))
1617 	(*xmBulletinBoardClassRec.composite_class.insert_child)(w);
1618     else if (XmtIsLayoutGadget(w))
1619 	(*compositeClassRec.composite_class.insert_child)(w);
1620 }
1621 
1622 
1623 #if NeedFunctionPrototypes
DeleteChild(Widget w)1624 static void DeleteChild(Widget w)
1625 #else
1626 static void DeleteChild(w)
1627 Widget w;
1628 #endif
1629 {
1630     /*
1631      * this is a hack.  See InsertChild()
1632      */
1633     if (XtIsRectObj(w))
1634 	(*xmBulletinBoardClassRec.composite_class.delete_child)(w);
1635     else if (XmtIsLayoutGadget(w))
1636 	(*compositeClassRec.composite_class.delete_child)(w);
1637 }
1638 
1639 
1640 #if NeedFunctionPrototypes
RepositionContents(Widget container)1641 static void RepositionContents(Widget container)
1642 #else
1643 static void RepositionContents(container)
1644 Widget container;
1645 #endif
1646 {
1647     Widget c;                     /* child */
1648     XmtLayoutConstraintsPart *cc; /* child constraints */
1649     int i;
1650 
1651     c = LayoutConstraints(container).first_child;
1652     i = 0;
1653     while(c) {
1654 	cc = LayoutConstraintsRec(c);
1655 	cc->position = i++;
1656 	c = cc->before;
1657     }
1658 }
1659 
1660 #if NeedFunctionPrototypes
PlaceObjectAfter(Widget w,Widget after)1661 static void PlaceObjectAfter(Widget w, Widget after)
1662 #else
1663 static void PlaceObjectAfter(w, after)
1664 Widget w;
1665 Widget after;
1666 #endif
1667 {
1668     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(w);
1669     XmtLayoutConstraintsPart *p = LayoutConstraintsRec(after);
1670     XmtLayoutConstraintsPart *n;
1671     Widget container = p->in ? p->in :
1672 	((XmtLayoutWidget)XtParent(w))->layout.toplevel;
1673 
1674     c->in = p->in;
1675     c->after = after;
1676     c->before = p->before;
1677     p->before = w;
1678     if (c->before != NULL) {
1679 	n = LayoutConstraintsRec(c->before);
1680 	n->after = w;
1681     }
1682     RepositionContents(container);
1683 }
1684 
1685 #if NeedFunctionPrototypes
PlaceObjectBefore(Widget w,Widget before)1686 static void PlaceObjectBefore(Widget w, Widget before)
1687 #else
1688 static void PlaceObjectBefore(w, before)
1689 Widget w;
1690 Widget before;
1691 #endif
1692 {
1693     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(w);
1694     XmtLayoutConstraintsPart *n = LayoutConstraintsRec(before);
1695     XmtLayoutConstraintsPart *p;
1696     Widget container = n->in ? n->in :
1697 	((XmtLayoutWidget)XtParent(w))->layout.toplevel;
1698 
1699     c->in = n->in;
1700     c->before = before;
1701     c->after = n->after;
1702     n->after = w;
1703 
1704     if (c->after == NULL)
1705 	LayoutConstraints(container).first_child = w;
1706     else {
1707 	p = LayoutConstraintsRec(c->after);
1708 	p->before = w;
1709     }
1710     RepositionContents(container);
1711 }
1712 
1713 #if NeedFunctionPrototypes
PlaceObjectIn(Widget w,Widget in,int pos)1714 static void PlaceObjectIn(Widget w, Widget in, int pos)
1715 #else
1716 static void PlaceObjectIn(w, in, pos)
1717 Widget w;
1718 Widget in;
1719 int pos;
1720 #endif
1721 {
1722     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(w);
1723     XmtLayoutConstraintsPart *cc;  /* container */
1724     Widget n, p;  /* next, previous */
1725     int j;
1726     Widget container = in ? in :
1727 	((XmtLayoutWidget)XtParent(w))->layout.toplevel;
1728 
1729     /*
1730      * if in is NULL, we leave the layoutIn constraint NULL as well,
1731      * instead of using the pointer to the actual internal container.
1732      * The value NULL is more meaningful to a programmer who might
1733      * query this resource.
1734      */
1735     c->in = in;
1736 
1737     /* now go find the position it belongs at */
1738     cc = LayoutConstraintsRec(container);
1739     for(p = NULL, n = cc->first_child, j = 0;
1740 	n && (j != pos);
1741 	p = n, n = LayoutConstraints(n).before, j++);
1742     c->position = j;  /* convert a -1 position to actual position */
1743     c->after = p;
1744     c->before = n;
1745     if (p)
1746 	LayoutConstraints(p).before = w;
1747     else
1748 	cc->first_child = w;
1749     if (n)
1750 	LayoutConstraints(n).after = w;
1751     RepositionContents(container);
1752 }
1753 
1754 /*
1755  * This procedure is called mostly from the SetValues method, and its
1756  * two arguments are the "current" and "set" arguments to that method.
1757  * We need to use the copy widget, because it has its doubly-linked
1758  * list intact, and we can extract the widget we need.  But we need
1759  * the actual widget as well, so that we can detect whether that
1760  * widget actually occurs on the list.
1761  */
1762 #if NeedFunctionPrototypes
UnlinkObject(Widget copy,Widget actual)1763 static void UnlinkObject(Widget copy, Widget actual)
1764 #else
1765 static void UnlinkObject(copy, actual)
1766 Widget copy, actual;
1767 #endif
1768 {
1769     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(copy);
1770     Widget container = c->in ? c->in :
1771 	((XmtLayoutWidget)XtParent(copy))->layout.toplevel;
1772 
1773     /*
1774      * Note that this procedure may sometimes be called more than once
1775      * on a particular child.  Thus the test in the else clause below
1776      * is necessary.  If the child has already been unlinked, then
1777      * this test will fail, and nothing will be done.
1778      */
1779     if (c->before)
1780 	LayoutConstraints(c->before).after = c->after;
1781     if (c->after)
1782 	LayoutConstraints(c->after).before = c->before;
1783     else if (LayoutConstraints(container).first_child == actual)
1784 	LayoutConstraints(container).first_child = c->before;
1785 
1786     RepositionContents(container);
1787     c->before = c->after = c->in = NULL;
1788 }
1789 
1790 #if NeedFunctionPrototypes
set_parsed_info(XmtLayoutWidget lw,Widget child)1791 static Boolean set_parsed_info(XmtLayoutWidget lw, Widget child)
1792 #else
1793 static Boolean set_parsed_info(lw, child)
1794 XmtLayoutWidget lw;
1795 Widget child;
1796 #endif
1797 {
1798     XmtLayoutInfo *info, *last;
1799     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(child);
1800     XmtLayoutConstraintsPart *mark;
1801 
1802     /* see if the child's name appears in the list */
1803     for(last = NULL, info = lw->layout.widget_info;
1804 	info; last = info, info = info->next)
1805 	if (info->name == child->core.xrm_name) break;
1806 
1807     /*
1808      * If no info was found, and if the child
1809      * is a scrolled window, and its name ends in "SW"
1810      * see if we have info for the grandchild's name without the SW.
1811      * This is a special case to make scrolled lists and scrolled texts
1812      * easier to use in a layout widget.
1813      */
1814     if (!info && XmIsScrolledWindow(child)) {
1815 	String name = XtName(child);
1816 	int len = strlen(name);
1817 	XrmQuark grandchild_name;
1818 
1819 	if ((name[len-2] == 'S') && (name[len-1] == 'W')) {
1820 	    name = XtNewString(name);
1821 	    name[len-2] = '\0';
1822 	    grandchild_name = XrmStringToQuark(name);
1823 	    XtFree(name);
1824 
1825 	    for(last = NULL, info = lw->layout.widget_info;
1826 		info; last = info, info = info->next)
1827 		if (info->name == grandchild_name) break;
1828 	}
1829     }
1830 
1831     /* if we found some info unlink it, otherwise quit */
1832     if (info) {
1833 	if (last) last->next = info->next;
1834 	else lw->layout.widget_info = info->next;
1835     }
1836     else return False;
1837 
1838     /* override any constraints with info from the layout string */
1839 
1840 #define Merge(field)\
1841     if (info->dummy_constraints.field) c->field = info->constraints.field
1842 
1843     Merge(width);
1844     Merge(height);
1845     Merge(stretchability);
1846     Merge(shrinkability);
1847     Merge(allow_resize);
1848     Merge(sensitive);
1849     Merge(justification);
1850     Merge(margin_width);
1851     Merge(margin_height);
1852     Merge(frame_type);
1853     Merge(frame_line_type);
1854     Merge(frame_position);
1855     Merge(frame_margin);
1856     Merge(frame_thickness);
1857     Merge(caption_position);
1858     Merge(caption_justification);
1859     Merge(caption_alignment);
1860     Merge(caption_margin);
1861     Merge(caption);
1862 
1863 #undef Merge
1864 
1865     /* this private flag is a special case */
1866     c->dont_copy_caption = info->constraints.dont_copy_caption;
1867     c->free_caption = info->constraints.free_caption;
1868 
1869     /*
1870      * Set after or before or in to the same value as
1871      * the marker widget we created in the parser.  We don't need to fully
1872      * attach this widget, just set a position resource so that
1873      * ConstraintInitialize can attach it in the right place.
1874      * Unlink and destroy the marker widget.
1875      */
1876     mark = LayoutConstraintsRec(info->constraints.after);
1877     c->in = mark->in;
1878     c->position = mark->position;
1879     /* destroy the marker object, and remove it from the list */
1880     XtDestroyWidget(info->constraints.after);
1881 
1882     XtFree((char *) info);
1883     return True;
1884 }
1885 
1886 
1887 /* ARGSUSED */
1888 #if NeedFunctionPrototypes
ConstraintInitialize(Widget request,Widget init,ArgList arglist,Cardinal * num_args)1889 static void ConstraintInitialize(Widget request, Widget init,
1890 				 ArgList arglist, Cardinal *num_args)
1891 #else
1892 static void ConstraintInitialize(request, init, arglist, num_args)
1893 Widget request;
1894 Widget init;
1895 ArgList arglist;
1896 Cardinal *num_args;
1897 #endif
1898 {
1899     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(init);
1900     XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(init);
1901 
1902     /*
1903      * we don't use constraints for non-rectobjs.  See comment
1904      * in ConstraintSetValues.
1905      */
1906     if (!XtIsWidget(init) &&
1907 	!XmIsGadget(init) &&
1908 	!XmtIsLayoutGadget(init))
1909 	return;
1910 
1911     /*
1912      * make a note if this is a widget or gadget.
1913      */
1914     if (XtIsWidget(init) || XmIsGadget(init))
1915 	c->type = XmtLayoutChild;
1916 
1917     c->dont_copy_caption = False;
1918 
1919     /*
1920      * go check if there is constraint info about this widget saved away.
1921      * If so, set it, overriding any resources already set.
1922      * Don't bother checking if this widget was created by the parser.
1923      */
1924     if (!lw->layout.in_parser) set_parsed_info(lw, init);
1925 
1926     /*
1927      * if stretchability and shrinkability are unset,
1928      * set the default depending on type
1929      */
1930     if (c->stretchability == (Dimension) -1) {
1931 	if ((c->type == XmtLayoutChild) ||
1932 	    (c->type == XmtLayoutSpace) ||
1933 	    (c->type == XmtLayoutRow) ||
1934 	    (c->type == XmtLayoutCol))
1935 	    c->stretchability = XmtLAYOUT_DEFAULT_STRETCHABILITY;
1936 	else
1937 	    c->stretchability = 0;
1938     }
1939     if (c->shrinkability == (Dimension) -1) {
1940 	if ((c->type == XmtLayoutChild) ||
1941 	    (c->type == XmtLayoutSpace) ||
1942 	    (c->type == XmtLayoutRow) ||
1943 	    (c->type == XmtLayoutCol))
1944 	    c->shrinkability = XmtLAYOUT_DEFAULT_SHRINKABILITY;
1945 	else
1946 	    c->shrinkability = 0;
1947     }
1948 
1949     /*
1950      * if margin width or margin height are unset, set default
1951      * depending on type.
1952      */
1953     if (c->margin_width == 255) {
1954 	if ((c->type == XmtLayoutRow) || (c->type == XmtLayoutCol))
1955 	    c->margin_width = 0;
1956 	else
1957 	    c->margin_width = lw->layout.default_spacing/2;
1958     }
1959     if (c->margin_height == 255) {
1960 	if ((c->type == XmtLayoutRow) || (c->type == XmtLayoutCol))
1961 	    c->margin_height = 0;
1962 	else
1963 	    c->margin_height = lw->layout.default_spacing/2;
1964     }
1965 
1966     /* if there is a caption, copy it and figure out how big it is */
1967     if (c->caption) {
1968 	if (!c->dont_copy_caption) {
1969 	    c->caption = XmStringCopy(c->caption);
1970 	    c->free_caption = 1;
1971         }
1972 #if XmVersion < 2000
1973 	XmStringExtent(lw->layout.font_list, c->caption,
1974 		       &c->caption_width, &c->caption_height);
1975 #else
1976 	XmStringExtent(lw->layout.render_table, c->caption,
1977 		       &c->caption_width, &c->caption_height);
1978 #endif
1979     }
1980 
1981     /*
1982      * Now figure out where this object will be laid out.
1983      * This can be specified in a number of ways:
1984      *   after,
1985      *   before, or
1986      *   in, optionally combined with position.
1987      * The fields are examined in the order listed, and the first one
1988      * specified is used.  Whichever fields are specified, all
1989      * except position are updated to reflect the actual layout.
1990      * If none are specified, then the widget is inserted in the toplevel
1991      * row or column.  position defaults to -1, which inserts
1992      * at the end of the row or column.
1993      * Note that if the toplevel box isn't created yet, then we must
1994      * be creating it now, and we shouldn't place it anywhere.
1995      */
1996     if (lw->layout.toplevel != 0) {
1997 	if (c->after)
1998 	    PlaceObjectAfter(init, c->after);
1999 	else if (c->before)
2000 	    PlaceObjectBefore(init, c->before);
2001 	else {
2002 	    PlaceObjectIn(init, c->in, c->position);
2003 	}
2004     }
2005 
2006     c->first_child = NULL;
2007 }
2008 
2009 
2010 #if NeedFunctionPrototypes
ConstraintDestroy(Widget w)2011 static void ConstraintDestroy(Widget w)
2012 #else
2013 static void ConstraintDestroy(w)
2014 Widget w;
2015 #endif
2016 {
2017     XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(w);
2018     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(w);
2019 
2020     if (!XtIsWidget(w) && !XmIsGadget(w) && !XmtIsLayoutGadget(w))
2021 	return;
2022 
2023     /* if there is a caption, free it */
2024     if (c->caption && c->free_caption)
2025 	XmStringFree(c->caption);
2026 
2027     /*
2028      * if the whole layout is being destroyed, don't
2029      * bother messing with the linked lists.  If this is a container,
2030      * we don't need to mess with the kids because they will be destroyed.
2031      */
2032     if (lw->core.being_destroyed)
2033 	return;
2034 
2035     /* unlink the item */
2036     UnlinkObject(w, w);
2037 }
2038 
2039 
2040 /* ARGSUSED */
2041 #if NeedFunctionPrototypes
ConstraintSetValues(Widget current,Widget request,Widget set,ArgList arglist,Cardinal * num_args)2042 static Boolean ConstraintSetValues(Widget current, Widget request, Widget set,
2043 				   ArgList arglist, Cardinal *num_args)
2044 #else
2045 static Boolean ConstraintSetValues(current, request, set, arglist, num_args)
2046 Widget current;
2047 Widget request;
2048 Widget set;
2049 ArgList arglist;
2050 Cardinal *num_args;
2051 #endif
2052 {
2053     XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(set);
2054     XmtLayoutConstraintsPart *c = LayoutConstraintsRec(current);
2055     XmtLayoutConstraintsPart *s = LayoutConstraintsRec(set);
2056     Boolean relayout = False;
2057     Boolean redisplay = False;
2058 
2059     /*
2060      * ** Another gross Motif hack.
2061      * Motif creates screwy non-rectobj cache objects for every Gadget.
2062      * These objects have NULL constraint fields but are passed to
2063      * this function anyway.  They are subclasses of xmExtObjectClass,
2064      * so we could test for them and rule them out.  But since none of
2065      * our constraints make sense for any non-rect object, we'll just
2066      * test that it is a subclass of RectObj.  We'll insert the same test
2067      * in the other constraint methods for efficiency
2068      */
2069 
2070     if (!XtIsWidget(set) && !XmIsGadget(set) && !XmtIsLayoutGadget(set))
2071 	return False;
2072 
2073 #define Changed(field) (s->field != c->field)
2074 
2075     if (Changed(justification) || Changed(margin_width) ||
2076 	Changed(margin_height) || Changed(frame_type) ||
2077 	Changed(frame_position) || Changed(frame_margin) ||
2078 	Changed(caption_position) || Changed(caption_margin) ||
2079 	Changed(width) || Changed(height) ||
2080 	Changed(stretchability) || Changed(shrinkability))
2081 	relayout = True;
2082 
2083     if (Changed(caption_justification)) redisplay = True;
2084 
2085     if (Changed(sensitive) || Changed(frame_line_type) ||
2086 	Changed(caption_alignment))
2087 	if (XtIsRealized((Widget)lw))
2088 	    DrawFrameAndCaption(lw, set, NULL, True);
2089 
2090     if (Changed(caption)) {
2091 	if (c->caption && c->free_caption) XmStringFree(c->caption);
2092 	if (s->caption) {
2093 	    s->caption = XmStringCopy(s->caption);
2094 	    s->free_caption = 1;
2095 #if XmVersion < 2000
2096 	    XmStringExtent(lw->layout.font_list, s->caption,
2097 			   &s->caption_width, &s->caption_height);
2098 #else
2099 	    XmStringExtent(lw->layout.render_table, s->caption,
2100 			   &s->caption_width, &s->caption_height);
2101 #endif
2102 	}
2103 	relayout = True;
2104     }
2105 
2106     if (set != ((XmtLayoutWidget)XtParent(set))->layout.toplevel) {
2107 	if (Changed(after)) {
2108 	    if (!s->after || (XtParent(s->after) != (Widget)lw)) {
2109 		XmtWarningMsg("XmtLayout", "badAfter",
2110 			      "XmtNlayoutAfter constraint of child `%s'\n\tmust be a sibling of the child.",
2111 			      XtName((Widget)set));
2112 		s->after = c->after;
2113 	    }
2114 	    else {
2115 		Widget after = s->after;
2116 		UnlinkObject(current, set);
2117 		PlaceObjectAfter(set, after);
2118 		relayout = True;
2119 	    }
2120 	}
2121 	else if (Changed(before)) {
2122 	    if (!s->before || (XtParent(s->before) != (Widget)lw)) {
2123 		XmtWarningMsg("XmtLayout", "badBefore",
2124 			      "XmtNlayoutBefore constraint of child `%s'\n\tmust be a sibling of the child.",
2125 			      XtName((Widget)set));
2126 		s->before = c->before;
2127 	    }
2128 	    else {
2129 		Widget before = s->before;
2130 		UnlinkObject(current, set);
2131 		PlaceObjectBefore(set, before);
2132 		relayout = True;
2133 	    }
2134 	}
2135 	else if (Changed(in) || Changed(position)) {
2136 	    if (Changed(in) && s->in &&
2137 		((XtParent(s->in) != (Widget)lw) ||
2138 		 (!XtIsSubclass(s->in, xmtLayoutBoxGadgetClass)))) {
2139 		XmtWarningMsg("XmtLayout", "badIn",
2140 			      "XmtNlayoutIn constraint of child `%s'\n\tmust be an XmtLayoutBox sibling of the child, or NULL.",
2141 			      XtName((Widget)set));
2142 		s->in = c->in;
2143 	    }
2144 	    else {
2145 		Widget in = s->in;
2146 		int position = s->position;
2147 		UnlinkObject(current, set);
2148 		PlaceObjectIn(set, in, position);
2149 		relayout = True;
2150 	    }
2151 	}
2152     }
2153 
2154     /*
2155      * It doesn't make sense to change the position of children of a layout
2156      * widget by setting XtNx or XtNy.  So, if these have been changed,
2157      * warn, and undo the changes.  Note that it is legal to set the
2158      * width or height of a child--if these fields have changed, the
2159      * Intrinsics will automatically call the GeometryManager field to
2160      * make the change, and the GeometryManager will do the relayout,
2161      * so we don't need to handle this case at all.
2162      */
2163     if ((set->core.x != current->core.x) || (set->core.y != current->core.y)) {
2164 	set->core.x = current->core.x;
2165 	set->core.y = current->core.y;
2166 	XmtWarningMsg("XmtLayout", "cantsetpos",
2167 		      "Widget %s: can't set XtNx or XtNy resources of a child of\n\tan XmtLayout widget.  Changes ignored.",
2168 		      XtName((Widget) set));
2169     }
2170 
2171 #undef Changed
2172 
2173     /*
2174      * If any of these changes require a relayout, do that now.
2175      *
2176      * If the changes or the relayout changed any of the widget's
2177      * geometry fields, then the Intrinsics will invoke the
2178      * GeometryManager() method to verify that those changes are okay.
2179      * But we've just called _XmtLayoutChildren() so we know that they're
2180      * okay.  So we set a flag to tell GeometryManager() to approve
2181      * the changes, even though they may include position changes
2182      * which are normally rejected.
2183      * Notice, however, that when we call _XmtLayoutChildren() here,
2184      * the core geometry fields are at their new values, and thus, when
2185      * the relayout procedure ends up calling XtConfigureWidget()
2186      * (actually XmtConfigureObject, in LayoutBox.c) on this child,
2187      * the Intrinsics may find that the new geometry matches the current
2188      * geometry, and thus will not update the actual window fields.
2189      * Therefore, we've got to be sure that the geometry manager
2190      * takes this into account.
2191      * See comment at GeometryManager() for more information.
2192      */
2193     if (relayout) {
2194 	_XmtLayoutChildren(lw, True);
2195 
2196 	if ((set->core.x != current->core.x) ||
2197 	    (set->core.y != current->core.y) ||
2198 	    (set->core.width != current->core.width) ||
2199 	    (set->core.height != current->core.height))
2200 	    lw->layout.geometry_okay = True;
2201     }
2202 
2203     /*
2204      * Returning True from this method will only redraw the child, not
2205      * the entire Layout widget, as happens when SetValues() returns True.
2206      * So if either relayout or redisplay is True, then we'll need to force
2207      * the redraw ourselves.  We do this by using XClearArea() to generate
2208      * an Expose event.  The relayout process may generate other Expose
2209      * events if gadgets are moved around, but these events will be combined
2210      * into a single call to the Layout Redisplay() method.  The reason that
2211      * it is important to do this is that the Layout provides captions and
2212      * frames for its children, and these have to be redrawn when the
2213      * children move or change size.  In particular, if only a widget child
2214      * is moved, then the relayout call won't generate any expose events,
2215      * and without the XClearArea() below, the captions and frames would
2216      * not be redrawn correctly.
2217      */
2218 
2219     if ((relayout || redisplay) && XtIsRealized((Widget)lw))
2220 	XClearArea(XtDisplay((Widget) lw), XtWindow((Widget) lw),
2221 		   lw->core.x, lw->core.y, lw->core.width, lw->core.height,
2222 		   True);
2223 
2224     return False;
2225 }
2226 
2227 
2228 /* ARGSUSED */
2229 #if NeedFunctionPrototypes
2230 void
FocusMoved(wid,client_data,data)2231 FocusMoved( wid, client_data, data )
2232         Widget wid ;
2233         XtPointer client_data ;
2234         XtPointer data ;
2235 #else
2236 void
2237 FocusMoved(
2238         Widget wid,
2239         XtPointer client_data,
2240         XtPointer data )
2241 #endif /* _NO_PROTO */
2242 {
2243     XmtLayoutWidget lw = (XmtLayoutWidget) client_data;
2244     XmAnyCallbackStruct	cb ;
2245     XmFocusMovedCallbackStruct * call_data
2246       = (XmFocusMovedCallbackStruct *) data ;
2247     Widget  testWidget;
2248     Boolean hadFocus, losingFocus;
2249     /*
2250      * Perform superclass focus processing.
2251      */
2252     (superclass->bulletin_board_class.focus_moved_proc)(wid, client_data, data);
2253     /*
2254      * Is focus processing still in effect?
2255      */
2256     if (!call_data->cont) {
2257         return;
2258     }
2259     /*
2260      * Does the old widget have us as an ancestor, but the current doesn't?
2261      */
2262     testWidget = call_data->old_focus;
2263     hadFocus = False;
2264     while (testWidget != NULL && !XtIsShell(testWidget)) {
2265         if (testWidget == (Widget) lw) {
2266             hadFocus = True;
2267             break;
2268         }
2269         testWidget = XtParent(testWidget);
2270     }
2271 
2272     if (hadFocus) {
2273         testWidget = call_data->new_focus;
2274 
2275         losingFocus = True;
2276         while (testWidget != NULL && !XtIsShell(testWidget)) {
2277             if (testWidget == (Widget) lw) {
2278                 losingFocus = False;
2279                 break;
2280             }
2281              testWidget = XtParent(testWidget);
2282         }
2283 
2284         if (losingFocus) {
2285             cb.reason = XmCR_LOSING_FOCUS ;
2286             cb.event = NULL ;
2287             XtCallCallbackList( (Widget) lw,
2288                                lw->layout.losing_focus_callback, &cb) ;
2289         }
2290     }
2291 }
2292 
2293 #if NeedFunctionPrototypes
XmtLayoutDisableLayout(Widget w)2294 void XmtLayoutDisableLayout(Widget w)
2295 #else
2296 void XmtLayoutDisableLayout(w)
2297 Widget w;
2298 #endif
2299 {
2300     XmtLayoutWidget lw = (XmtLayoutWidget) w;
2301 
2302     XmtAssertWidgetClass(w, xmtLayoutWidgetClass, "XmtLayoutDisable");
2303     lw->layout.layout_disabled++;
2304 }
2305 
2306 #if NeedFunctionPrototypes
XmtLayoutEnableLayout(Widget w)2307 void XmtLayoutEnableLayout(Widget w)
2308 #else
2309 void XmtLayoutEnableLayout(w)
2310 Widget w;
2311 #endif
2312 {
2313     XmtLayoutWidget lw = (XmtLayoutWidget) w;
2314 
2315     XmtAssertWidgetClass(w, xmtLayoutWidgetClass, "XmtEnableLayout");
2316     if (lw->layout.layout_disabled > 0) lw->layout.layout_disabled--;
2317     if (lw->layout.needs_layout) _XmtLayoutChildren(lw, True);
2318 }
2319 
2320 
2321 #if NeedFunctionPrototypes
XmtLayoutConvertSizeToPixels(Widget w,double size,XmtLayoutUnitType units)2322 int XmtLayoutConvertSizeToPixels(Widget w, double size,XmtLayoutUnitType units)
2323 #else
2324 int XmtLayoutConvertSizeToPixels(w, size, units)
2325 Widget w;
2326 double size;
2327 XmtLayoutUnitType units;
2328 #endif
2329 {
2330     XmtLayoutWidget lw = (XmtLayoutWidget) w;
2331 
2332     XmtAssertWidgetClass(w, xmtLayoutWidgetClass,
2333 			 "XmtLayoutConvertSizeToPixels");
2334 
2335     /* convert to pixels */
2336     /* note intentional missing break statements */
2337     switch(units) {
2338     case XmtLayoutPoints:
2339 	size /= 72;                  /* 1 point = 1/72 inch */
2340     case XmtLayoutInches:
2341 	size *= 25.4;                /* 1 inch = 25.4 mm */
2342     case XmtLayoutMillimeters:
2343 	size *= lw->layout.pixpermm; /* pixels per mm depends on screen res */
2344 	break;
2345     case XmtLayoutEns:
2346 	size /= 2;                   /* 1 en = 1/2 em */
2347     case XmtLayoutEms:
2348 	size *= lw->layout.pixperem; /* pixels per em depends on font size */
2349 	break;
2350     }
2351 
2352     /* round to the nearest pixel */
2353     return (int) size;
2354 }
2355 
2356 #if NeedFunctionPrototypes
XmtCreateLayout(Widget parent,String name,ArgList args,Cardinal n)2357 Widget XmtCreateLayout(Widget parent, String name,
2358 		       ArgList args, Cardinal n)
2359 #else
2360 Widget XmtCreateLayout(parent, name, args, n)
2361 Widget parent;
2362 String name;
2363 ArgList args;
2364 Cardinal n;
2365 #endif
2366 {
2367     return XtCreateWidget(name, xmtLayoutWidgetClass, parent, args, n);
2368 }
2369 
2370 #if NeedFunctionPrototypes
XmtCreateLayoutDialog(Widget parent,String name,ArgList al,Cardinal ac)2371 Widget XmtCreateLayoutDialog(Widget parent, String name,
2372 			     ArgList al, Cardinal ac)
2373 #else
2374 Widget XmtCreateLayoutDialog(parent, name, al, ac)
2375 Widget parent;
2376 String name;
2377 ArgList al;
2378 Cardinal ac;
2379 #endif
2380 {
2381     Widget shell, w;
2382     String shell_name;
2383 
2384     shell_name = XtMalloc(strlen(name) + 7);
2385     (void)sprintf(shell_name, "%s_shell", name);
2386 
2387     shell = XmCreateDialogShell(parent, shell_name, al, ac);
2388     XtFree(shell_name);
2389     XtVaSetValues(shell, XmNallowShellResize, True, NULL);
2390 
2391     w = XtCreateWidget(name, xmtLayoutWidgetClass, shell, al, ac);
2392     XtAddCallback(w, XtNdestroyCallback,
2393 		  (XtCallbackProc)_XmDestroyParentCallback, NULL);
2394     return w;
2395 }
2396 
2397 
2398