1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 /************************************************************
26  *       INCLUDE FILES
27  ************************************************************/
28 #include <Xm/Xm.h>
29 #include <stdio.h>
30 #include <Xm/ButtonBoxP.h>
31 #include <Xm/ExtP.h>
32 #include <Xm/TraitP.h>
33 #include <Xm/TakesDefT.h>
34 #include <Xm/VaSimpleP.h>
35 #include "XmI.h"
36 
37 /************************************************************
38  *       TYPEDEFS AND DEFINES
39  ************************************************************/
40 
41 #define SUPERCLASS ((ConstraintWidgetClass) &xmManagerClassRec)
42 
43 /************************************************************
44  *       MACROS
45  ************************************************************/
46 
47 #define IsHorizontal(x) (XmButtonBox_orientation((x)) == XmHORIZONTAL)
48 #define MarginH(x)	(XmButtonBox_margin_height((x)))
49 #define MarginW(x)	(XmButtonBox_margin_width((x)))
50 #define FillOption(x)	(XmButtonBox_fill_option((x)))
51 #define EqualSize(x)	(XmButtonBox_equal_size((x)))
52 
53 /************************************************************
54  *       EXTERNAL DECLARATIONS
55  ************************************************************/
56 
57 /************************************************************
58  *       STATIC FUNCTION DECLARATIONS
59  ************************************************************/
60 
61 static void 	Initialize(Widget, Widget, ArgList, Cardinal *);
62 static void	    ClassInitialize(void);
63 
64 static void     ClassPartInitialize(WidgetClass w_class) ;
65 
66 static void	    InsertChild(Widget);
67 static void     Resize(Widget), ChangeManaged(Widget);
68 static void 	ConstraintInitialize(Widget, Widget, ArgList, Cardinal *);
69 
70 static Boolean  SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
71 static Boolean  ConstraintSetValues(Widget, Widget,
72 				    Widget, ArgList, Cardinal *);
73 static Boolean CvtStringToFillOption(Display *, XrmValuePtr, Cardinal *,
74 				     XrmValuePtr, XrmValuePtr);
75 
76 static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
77 					XtWidgetGeometry *);
78 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
79 				      XtWidgetGeometry *);
80 
81 static XtGeometryResult TryNewLayout(Widget, Mask *, Boolean);
82 static Cardinal	       	CalcChildrenPrefSizes(XmButtonBoxWidget, Dimension *,
83 					      Dimension *, Dimension *);
84 static void		LayoutChildren(Widget, Widget);
85 static void	 	CalcChildSize(XmButtonBoxWidget, Widget, Dimension,
86 				      Dimension, Dimension, Cardinal,
87 				      Dimension *, Dimension *);
88 
89 static void ButtonBoxSetDefaultShadow(Widget button) ;
90 
91 
92 /************************************************************
93  *       STATIC DECLARATIONS
94  ************************************************************/
95 
96 static XtResource resources[] =
97 {
98   {
99     XmNequalSize, XmCEqualSize, XmRBoolean,
100     sizeof(Boolean), XtOffsetOf(XmButtonBoxRec, button_box.equal_size),
101     XmRImmediate, (XtPointer) False
102   },
103 
104   {
105     XmNfillOption, XmCFillOption, XmRXmFillOption,
106     sizeof(XmFillOption), XtOffsetOf(XmButtonBoxRec, button_box.fill_option),
107     XmRImmediate, (XtPointer) XmFillNone
108   },
109 
110   {
111     XmNmarginHeight, XmCMargin, XmRVerticalDimension,
112     sizeof(Dimension), XtOffsetOf(XmButtonBoxRec, button_box.margin_height),
113     XmRImmediate, (XtPointer) 0
114   },
115 
116   {
117     XmNmarginWidth, XmCMargin, XmRHorizontalDimension,
118     sizeof(Dimension), XtOffsetOf(XmButtonBoxRec, button_box.margin_width),
119     XmRImmediate, (XtPointer) 0
120   },
121 
122   {
123     XmNorientation, XmCOrientation, XmROrientation,
124     sizeof(unsigned char), XtOffsetOf(XmButtonBoxRec, button_box.orientation),
125     XmRImmediate, (XtPointer)XmHORIZONTAL
126   },
127 
128   {
129     XmNdefaultButton, XmCWidget, XmRWidget,
130     sizeof(Widget), XtOffsetOf(XmButtonBoxRec, button_box.default_button),
131     XmRImmediate, (XtPointer) NULL
132   }
133 };
134 
135 static XmSyntheticResource get_resources[] =
136 {
137   {
138     XmNmarginHeight, sizeof(Dimension),
139     XtOffsetOf(XmButtonBoxRec, button_box.margin_height),
140     XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels
141   },
142 
143   {
144     XmNmarginWidth, sizeof(Dimension),
145     XtOffsetOf(XmButtonBoxRec, button_box.margin_width),
146     XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels
147   }
148 };
149 
150 static XtResource constraints[] =
151 {
152    {
153       "pri.vate1", "Pri.vate1", XmRDimension, sizeof(Dimension),
154       XtOffsetOf(XmBBoxConstraintsRec, bbox.pref_width),
155       XmRImmediate, (XtPointer) 0
156    },
157    {
158       "pri.vate2", "Pri.vate2", XmRAttachment, sizeof(Dimension),
159       XtOffsetOf(XmBBoxConstraintsRec, bbox.pref_height),
160       XmRImmediate, (XtPointer) 0
161    }
162 };
163 
164 XmButtonBoxClassRec xmButtonBoxClassRec = {
165   {
166     /* core_class members      */
167     /* superclass         */	(WidgetClass)SUPERCLASS,
168     /* class_name         */	"XmButtonBox",
169     /* widget_size        */	sizeof(XmButtonBoxRec),
170     /* class_initialize   */	ClassInitialize,
171     /* class_part_init    */	ClassPartInitialize,
172     /* class_inited       */	False,
173     /* initialize         */	Initialize,
174     /* initialize_hook    */	NULL,
175     /* realize            */	XtInheritRealize,
176     /* actions            */	NULL,
177 
178 
179     /* num_actions        */	0,
180     /* resources          */	(XtResource*)resources,
181     /* num_resources      */	XtNumber(resources),
182     /* xrm_class          */	NULLQUARK,
183     /* compress_motion    */	True,
184     /* compress_exposure  */	True,
185     /* compress_enterleave*/	True,
186     /* visible_interest   */	False,
187     /* destroy            */	NULL,
188     /* resize             */	Resize,
189     /* expose             */	NULL,
190     /* set_values         */	SetValues,
191     /* set_values_hook    */	NULL,
192     /* set_values_almost  */	XtInheritSetValuesAlmost,
193     /* get_values_hook    */	NULL,
194     /* accept_focus       */	NULL,
195     /* version            */	XtVersion,
196     /* callback_private   */	NULL,
197     /* tm_table           */	XtInheritTranslations,
198     /* query_geometry     */	(XtGeometryHandler) QueryGeometry,
199     /* display_accelerator*/	NULL,
200     /* extension          */	NULL,
201   },
202   {
203     /* composite_class members */
204     /* geometry_manager   */	GeometryManager,
205     /* change_managed     */	ChangeManaged,
206     /* insert_child       */	InsertChild,
207     /* delete_child       */	XtInheritDeleteChild,
208     /* extension          */	NULL,
209   },
210   { /* constraint_class fields */
211     /* resource list      */    constraints,
212     /* num resources      */    XtNumber(constraints),
213     /* constraint size    */ 	sizeof(XmBBoxConstraintsRec),
214     /* init proc          */ 	ConstraintInitialize,
215     /* destroy proc       */ 	NULL,
216     /* set values proc    */ 	ConstraintSetValues,
217     /* extension          */ 	NULL,
218   },
219   { /* manager_class fields */
220     /* default translations */ 	XtInheritTranslations,
221     /* syn_resources        */ 	get_resources,
222     /* num_syn_resources    */ 	XtNumber(get_resources),
223     /* syn_cont_resources   */ 	NULL,
224     /* num_syn_cont_resources */ 0,
225     /* parent_process       */ 	XmInheritParentProcess,
226     /* extension            */ 	NULL,
227   },
228   {
229     /* Row class members */
230     /* extension            */	NULL,
231   }
232 };
233 
234 WidgetClass xmButtonBoxWidgetClass = (WidgetClass)&xmButtonBoxClassRec;
235 
236 /************************************************************
237  *       STATIC CODE
238  ************************************************************/
239 
240 /*      Function Name: ClassInitialize
241  *      Description:   Called to initialize information specific
242  *                     to this widget class.
243  *      Arguments:     none.
244  *      Returns:       none.
245  */
246 
247 /* ARGSUSED */
248 static void
ClassInitialize()249 ClassInitialize()
250 {
251     XmButtonBoxClassRec *wc = &xmButtonBoxClassRec;
252 
253     XtSetTypeConverter(XmRString, XmRXmFillOption,
254 		       (XtTypeConverter) CvtStringToFillOption,
255                        NULL, (Cardinal)0, XtCacheAll, (XtDestructor)NULL);
256 }
257 
258 
259 /****************************************************************/
260 static void
ClassPartInitialize(WidgetClass w_class)261 ClassPartInitialize(WidgetClass w_class )
262 {
263     XmButtonBoxWidgetClass bbClass
264         = (XmButtonBoxWidgetClass) w_class ;
265 
266 /* this seems to do nothing.... why is it here? -rh
267     XmButtonBoxWidgetClass bbSuper
268 	    = (XmButtonBoxWidgetClass) w_class->core_class.superclass ;
269 */
270     _XmFastSubclassInit (w_class, XmBUTTONBOX_BIT);
271 
272 
273     /* Install the specifyrendertable trait for all subclasses */
274     /*
275     XmeTraitSet((XtPointer)w_class, XmQTspecifyRenderTable,
276 		(XtPointer) &bulletinbSRT);
277     */
278     return ;
279 }
280 
281 
282 /****************************************************************/
283 
284 
285 /*	Function Name: Initialize
286  *	Description:   Called to initialize information specific
287  *                     to this widget.
288  *	Arguments:     req - what was originally requested.
289  *                     new - what will be created (our superclasses have
290  *                           already mucked with this)
291  *                     args, num_args - The arguments passed to
292  *                                      the creation call.
293  *	Returns:       none.
294  */
295 
296 /* ARGSUSED */
Initialize(Widget req,Widget set,ArgList args,Cardinal * num_args)297 static void Initialize(Widget req, Widget set,
298 		       ArgList args, Cardinal * num_args)
299 {
300     /*
301      * This is here just in case no children are added before the
302      * widget is realized.
303      */
304 
305     if (req->core.width == 0)
306 	set->core.width = 1;
307 
308     if (req->core.height == 0)
309 	set->core.height = 1;
310 }
311 
312 /*	Function Name: ConstraintInitialize
313  *	Description:   Called to initialize information specific
314  *                     to this child widget.
315  *	Arguments:     req - what was originally requested.
316  *                     set - what will be created (our superclassed have
317  *                           already mucked with this)
318  *                     args, num_args - The arguments passed to
319  *                                      the creation call.
320  *	Returns:       none.
321  */
322 
323 /* ARGSUSED */
324 static void
ConstraintInitialize(Widget request,Widget set,ArgList args,Cardinal * num_args)325 ConstraintInitialize(Widget request, Widget set, ArgList args, Cardinal *num_args)
326 {
327     XmButtonBoxC_pref_width(set) = XmButtonBoxC_pref_height(set) = 0;
328 }
329 
330 /*      Function Name: ConstraintSetValues
331  *      Description:   Called when child widget data needs to be modified on-
332  *                     the-fly.
333  *      Arguments:     current - the current (old) widget values.
334  *                     request - before superclassed have changed things.
335  *                     set - what will acutally be the new values.
336  *                     args, num_args - the arguments in the list.
337  *      Returns:       none
338  */
339 
340 /* ARGSUSED */
341 static Boolean
ConstraintSetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)342 ConstraintSetValues(Widget current, Widget request, Widget set,
343 		    ArgList args, Cardinal * num_args)
344 {
345     if ((XmButtonBoxC_pref_width(set) != set->core.width) ||
346 	(XmButtonBoxC_pref_height(set) != set->core.height))
347     {
348 	/*
349 	 * The desired height or width changed, this will
350 	 * tell the icon box to perform a new XtQueryGeom.
351 	 */
352 
353 	XmButtonBoxC_pref_width(set) = XmButtonBoxC_pref_height(set) = 0;
354     }
355 
356     return(False);
357 }
358 
359 /*
360  *	Function Name: Resize
361  *      Description:   Called when this widget has been resized.
362  *      Arguments:     w - Button Box Widget to resize.
363  *      Returns:       none.
364  */
365 
366 /*ARGSUSED */
367 static void
Resize(Widget w)368 Resize(Widget w)
369 {
370     LayoutChildren(w, NULL);
371 }
372 
373 /*      Function Name: QueryGeometry
374  *      Description:   Called when my parent wants to know my
375  *                     preferred size.
376  *      Arguments:     w - the widget to check.
377  *                     intended - parent imposed geometry.
378  *                     preferred - what I would like.
379  *      Returns:       status.
380  */
381 
382 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * preferred)383 QueryGeometry(Widget w, XtWidgetGeometry *request,
384               XtWidgetGeometry *preferred)
385 {
386     XmButtonBoxWidget 	bbox = (XmButtonBoxWidget)w;
387     Dimension		max_major, max_minor, child_major_total;
388 
389     /*
390      * Calculate our desired size.
391      */
392 
393     (void) CalcChildrenPrefSizes(bbox, &max_major,
394 				 &max_minor, &child_major_total);
395 
396     if (IsHorizontal(bbox)) {
397 	preferred->width = child_major_total + (2 * MarginW(bbox));
398 	preferred->height = max_minor + (2 * MarginH(bbox));
399     }
400     else
401     {
402 	preferred->width = max_minor + (2 * MarginW(bbox));
403 	preferred->height = child_major_total + (2 * MarginH(bbox));
404     }
405 
406     return(_XmHWQuery(w, request, preferred));
407 }
408 
409 /*      Function Name: GeometryManager
410  *      Description:   handles request from children for size changes.
411  *      Arguments:     child - the child to change.
412  *                     request - desired geometry of child.
413  *                     result - what will be allowed if almost.
414  *      Returns:       status.
415  */
416 
417 /* ARGSUSED */
418 static XtGeometryResult
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)419 GeometryManager(Widget w, XtWidgetGeometry *request,
420                 XtWidgetGeometry *reply)
421 {
422     XmButtonBoxWidget	bbox = (XmButtonBoxWidget)w->core.parent;
423     Mask             	mask = 0;
424     XtGeometryResult 	result;
425 
426     /*
427      * Say no to any change in position.
428      */
429 
430     if ( (request->request_mode & (CWX | CWY | CWBorderWidth)) &&
431 	 !(request->request_mode & (CWWidth | CWHeight)) )
432     {
433 	return (XtGeometryNo);
434     }
435 
436     if ( request->request_mode & (CWWidth | CWHeight) )
437     {
438 	Dimension		max_major, max_minor;
439 	Dimension		child_major, child_minor;
440 	Dimension	        child_width, child_height;
441 	Dimension		child_major_total;
442 
443 	Cardinal   		num_managed;
444 
445 	/*
446 	 * Save the old size, and set the corresponding
447 	 * widget fields to the requested sizes.
448 	 */
449 
450 	Dimension old_width       = XmButtonBoxC_pref_width(w);
451 	Dimension old_height      = XmButtonBoxC_pref_height(w);
452 
453 	if ( request->request_mode & CWWidth )
454 	    XmButtonBoxC_pref_width(w)  = request->width;
455 
456 	if ( request->request_mode & CWHeight )
457 	    XmButtonBoxC_pref_height(w) = request->height;
458 
459 	/*
460 	 * See if everything fits with the new size.
461 	 */
462 
463 	(void) TryNewLayout((Widget)bbox, &mask,
464 			    (request->request_mode & XtCWQueryOnly));
465 
466 	num_managed = CalcChildrenPrefSizes(bbox, &max_major,
467 					    &max_minor, &child_major_total);
468 
469 	CalcChildSize(bbox, w, max_major, max_minor,
470 		      child_major_total, num_managed, &child_major,
471 		      &child_minor);
472 
473 	if (IsHorizontal(bbox)) {
474 	    child_height = child_minor;
475 	    child_width = child_major;
476 	}
477 	else {
478 	    child_height = child_major;
479 	    child_width = child_minor;
480 	}
481 
482 	if ( (int)child_width >= (int)(2 * w->core.border_width) )
483 	    child_width -= (2 * w->core.border_width);
484 
485 	if ( (int)child_height >= (int)(2 * w->core.border_width) )
486 	    child_height -= (2 * w->core.border_width);
487 
488 	if (((child_width == XmButtonBoxC_pref_width(w)) ||
489 	     !(request->request_mode & CWWidth)) &&
490 	    ((child_height == XmButtonBoxC_pref_height(w)) ||
491 	     !(request->request_mode & CWHeight)))
492 	{
493 	    result = XtGeometryYes;
494 	}
495 	else if ((child_width != w->core.width) ||
496 		 (child_height != w->core.height))
497 	{
498 	    reply->request_mode = CWHeight | CWWidth;
499 	    reply->height = child_height;
500 	    reply->width = child_width;
501 	    result = XtGeometryAlmost;
502 	}
503 	else {
504 	    result = XtGeometryNo;
505 	}
506 
507 	if ((request->request_mode & XtCWQueryOnly) ||
508 	    (result != XtGeometryYes))
509 	{
510 	    XmButtonBoxC_pref_width(w) = old_width;
511 	    XmButtonBoxC_pref_height(w) = old_height;
512 	}
513 	else
514 	    LayoutChildren((Widget)bbox, w);
515 
516 	/*
517 	 * We didn't get what we wanted, our preferred
518 	 * size should be recomputed the next time we have
519 	 * a chance to ask it, given that we're rejecting
520 	 * its current geometry and that it may not agree
521 	 * with our Almost reply.
522 	 */
523 
524 	if (result != XtGeometryYes) {
525 	    if ( request->request_mode & CWWidth )
526 		XmButtonBoxC_pref_width(w) = 0;
527 
528 	    if ( request->request_mode & CWHeight )
529 		XmButtonBoxC_pref_height(w) = 0;
530 	}
531 
532 	return(result);
533     }
534 
535     /*
536      * Stacking request only.
537      */
538 
539     return (XtGeometryYes);
540 }
541 
542 
543 /*      Function Name: ChangeManaged
544  *      Description:   when a management change has occurred.
545  *      Arguments:     w - the ButtonBox widget.
546  *      Returns:       none.
547  */
548 
549 /* ARGSUSED */
550 static void
ChangeManaged(Widget w)551 ChangeManaged(Widget w)
552 {
553     Mask		mask = 0;
554     /* CR03420 mask should be set accordingly */
555     if (w->core.width == 1) mask |= CWWidth;
556     if (w->core.height == 1) mask |= CWHeight;
557     if (mask) (void)TryNewLayout(w, &mask, False);
558     LayoutChildren(w, NULL);
559 
560    /*
561     * for Motif navigation
562     */
563 
564    XmeNavigChangeManaged(w);
565 }
566 
567 
568 /*      Function Name: InsertChild
569  *      Description:   when a child widget is added.
570  *      Arguments:     w - the child widget
571  *      Returns:       none.
572  */
573 
574 /* ARGSUSED */
575 static void
InsertChild(register Widget child)576 InsertChild(register Widget child)
577 {
578 Boolean         is_button = False ;
579 XmButtonBoxWidget bb = (XmButtonBoxWidget) XtParent( child) ;
580     /*
581      * Check for non-widgets - ButtonBox doesn't support gadgets, for now ...
582      */
583 
584     if (_XmGadgetWarning(child))
585     {
586     	return;
587     }
588 
589     /*
590      * Insert the child widget in the composite children list with the
591      * superclass insert_child routine.
592      */
593 
594     /* (*SUPERCLASS->composite_class.insert_child)(w); */
595 
596     /* Another process may be updating the superclass's data */
597     /* (This was missed for some reason... - scorch)
598      * use composite class insert proc to do all the dirty work
599      */
600     {
601        XtWidgetProc insert_child;
602        _XmProcessLock();
603        insert_child = ((XmManagerWidgetClass)xmManagerWidgetClass)->
604 				composite_class.insert_child;
605        _XmProcessUnlock();
606        (*insert_child)(child);
607     }
608 
609     if(XmeTraitGet((XtPointer)XtClass(child), XmQTtakesDefault))
610     {
611         is_button = TRUE ;
612 
613         if( XmButtonBox_default_button( bb) )
614         {
615             /* Notify child that it has to be ready for default visual */
616             ButtonBoxSetDefaultShadow( child) ;
617         }
618     }
619 
620 }
621 
622 
623 /*      Function Name: SetValues
624  *      Description:   Called when some widget data needs to be modified on-
625  *                     the-fly.
626  *      Arguments:     current - the current (old) widget values.
627  *                     request - before superclassed have changed things.
628  *                     set - what will acutally be the new values.
629  *                     args, num_args - the arguments in the list.
630  *      Returns:       none
631  */
632 
633 /* ARGSUSED */
634 static Boolean
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)635 SetValues(Widget current, Widget request, Widget set,
636           ArgList args, Cardinal * num_args)
637 {
638     XmButtonBoxWidget b_old = (XmButtonBoxWidget) current;
639     XmButtonBoxWidget b_set = (XmButtonBoxWidget) set;
640     Boolean	      newLayout = False;
641     Mask mask = 0; /* CR03420 */
642     if ( XmButtonBox_equal_size(b_set) != XmButtonBox_equal_size(b_old) ||
643 	 XmButtonBox_fill_option(b_set) != XmButtonBox_fill_option(b_old) ||
644 	 XmButtonBox_margin_height(b_set) != XmButtonBox_margin_height(b_old) ||
645 	 XmButtonBox_margin_width(b_set) != XmButtonBox_margin_width(b_old) ||
646 	 XmButtonBox_orientation(b_set) != XmButtonBox_orientation(b_old) )
647     {
648 	newLayout = True;
649     }
650 
651     if (set->core.width == 0)
652     { /* CR03420 */
653       set->core.width = 1; /* setting to 1 to prevent zero width */
654       mask |= CWWidth;
655     }
656     if (set->core.height == 0)
657     { /* CR03420 */
658       set->core.height = 1; /* setting to 1 to prevent zero height */
659       mask |= CWHeight;
660     }
661     if (mask) TryNewLayout((Widget)b_set, &mask, False);
662     if ( newLayout == True ) LayoutChildren((Widget)b_set, NULL);
663 
664     return(False);
665 }
666 
667 /************************************************************
668  * Type Converters.
669  ************************************************************/
670 
671 /*      Function Name: CvtStringToFillOption
672  *      Description:   Converts a string to a FillOption
673  *      Arguments:     dpy - the X Display.
674  *                     args, num_args - *** NOT USED ***
675  *                     fromVal - contains the string to convert.
676  *                     toVal - contains the converted node state.
677  *      Returns:
678  */
679 
680 /* ARGSUSED */
681 static Boolean
CvtStringToFillOption(Display * dpy,XrmValuePtr args,Cardinal * num_args,XrmValuePtr fromVal,XrmValuePtr toVal)682 CvtStringToFillOption(Display * dpy, XrmValuePtr args, Cardinal *num_args,
683 		      XrmValuePtr fromVal, XrmValuePtr toVal)
684 {
685     static XmFillOption 	option;
686     char 			lowerName[BUFSIZ];
687 
688     XmCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr);
689 
690     if ( streq(lowerName, "none") || streq(lowerName,"fillnone") )
691         option = XmFillNone;
692     else if ( streq(lowerName, "major") || streq(lowerName, "fillmajor") )
693 	option = XmFillMajor;
694     else if ( streq(lowerName, "minor") || streq(lowerName, "fillminor") )
695 	option = XmFillMinor;
696     else if ( streq(lowerName, "all") || streq(lowerName, "fillall") )
697 	option = XmFillAll;
698     else
699     {
700 	XtDisplayStringConversionWarning(dpy, fromVal->addr, XmRXmFillOption);
701         return(False);          /* Conversion failed. */
702     }
703 
704     if ( toVal->addr == NULL )
705     {
706         toVal->size = sizeof(XmFillOption);
707         toVal->addr = (XtPointer)&option;
708         return(True);
709     }
710     else
711     {
712 	toVal->size = sizeof(XmFillOption);
713 	if ( toVal->size >= sizeof(XmFillOption) )
714 	{
715 	    XmFillOption *state = (XmFillOption *)toVal->addr;
716 
717 	    *state = option;
718 	    return(True);
719 	}
720 	else
721 	{
722 	    return(False);
723 	}
724     }
725 }
726 
727 /************************************************************
728  *      LOCAL CODE
729  ************************************************************/
730 
731 /*      Function Name: TryNewLayout
732  *      Description:   tries to do a layout within the current width
733  *                     and height.  If that fails, it tries to resize and
734  *                     do it within the geometry given in preferred_size.
735  *      Arguments:     parent - the ButtonBox
736  *		       mask - request mask
737  *		       queryOnly - should this only query
738  *      Returns:       status.
739  */
740 
741 /* ARGSUSED */
742 static XtGeometryResult
TryNewLayout(Widget parent,Mask * mask,Boolean queryOnly)743 TryNewLayout(Widget parent, Mask *mask,
744 	     Boolean queryOnly)
745 {
746     XmButtonBoxWidget 	bbox = (XmButtonBoxWidget)parent;
747     Dimension		new_width, new_height;
748     Dimension		max_major, max_minor, child_major_total;
749 
750     /*
751      * Get the bounding width and height of all children.
752      */
753 
754     (void) CalcChildrenPrefSizes(bbox, &max_major,
755 				 &max_minor, &child_major_total);
756 
757     if (IsHorizontal(bbox))
758     {
759 	new_width = child_major_total + 2 * MarginW(bbox);
760 	new_height = max_minor + 2 * MarginH(bbox);
761     }
762     else
763     {
764 	new_width = max_minor + 2 * MarginW(bbox);
765 	new_height = child_major_total + 2 * MarginH(bbox);
766     }
767 
768     /*
769      * Be sure that we are always at least one pixel high.
770      */
771 
772     if (new_width == 0)
773 	new_width = 1;
774     if (new_height == 0)
775 	new_height = 1;
776 
777     if ( new_width != parent->core.width || new_height != parent->core.height )
778     {
779 	XtWidgetGeometry	request, reply;
780 	XtGeometryResult	result;
781 
782 	request.width = new_width;
783 	request.height = new_height;
784 
785 	reply.width = 0;
786 	reply.height = 0;
787 
788 	request.request_mode = *mask; /* CR03420 */
789 	if ( queryOnly )
790 	{
791 	    request.request_mode |= XtCWQueryOnly;
792 	}
793 	result = XtMakeGeometryRequest(parent, &request, &reply);
794 
795 	if ( request.width == reply.width )
796 	{
797 	    *mask |= CWWidth;
798 	}
799 	if ( request.height == reply.height )
800 	{
801 	    *mask |= CWHeight;
802 	}
803 
804 	if ( result == XtGeometryAlmost && !queryOnly )
805 	{
806 	    result = XtMakeGeometryRequest(parent, &reply, &reply);
807 	}
808 
809 	return(result);
810     }
811 
812     *mask = CWWidth | CWHeight;
813     return(XtGeometryYes);
814 }
815 
816 
817 /*      Function Name: LayoutChildren
818  *      Description:   Lays out the "child" widgets in the ButtonBox widget.
819  *      Arguments:     w - the ButtonBox widget.
820  *                     special_child - Treat this child special, actually
821  *                                     set the new width and height instead
822  *                                     of calling the Xt routine.  This helps
823  *                                     the geom mgr implement XtGeometryYes
824  *                                     policy.
825  *      Returns:       none.
826  */
827 
828 /* ARGSUSED */
829 static void
LayoutChildren(Widget w,Widget special_child)830 LayoutChildren(Widget w, Widget special_child)
831 {
832     XmButtonBoxWidget 	bbox = (XmButtonBoxWidget)w;
833     Widget             *childp;
834 
835     Dimension		margin_major, margin_minor;
836     Dimension		max_major, max_minor;
837     Dimension		box_major, box_minor;
838     Dimension		child_major, child_minor;
839     Dimension	        child_width, child_height;
840     Dimension		child_major_total;
841 
842     Position		pos_minor;
843     Position   	        pos_x, pos_y;
844 
845     float  		pad = 0, pos_major;
846     Cardinal   		num_managed;
847 
848     child_major = 0;
849     child_minor = 0;
850 
851     if ( IsHorizontal(bbox) )
852     {
853 	margin_major = MarginW(bbox);
854 	margin_minor = MarginH(bbox);
855 	box_major = bbox->core.width;
856 	box_minor = bbox->core.height;
857     }
858     else
859     {
860 	margin_major = MarginH(bbox);
861 	margin_minor = MarginW(bbox);
862 	box_major = bbox->core.height;
863 	box_minor = bbox->core.width;
864     }
865     if ((int)box_major > (int)(2 * margin_major))
866 	box_major -= 2 * margin_major;
867     else
868 	box_major = 1;
869 
870     if ((int)box_minor > (int)(2 * margin_minor))
871 	box_minor -= 2 * margin_minor;
872     else
873 	box_minor = 1;
874 
875     num_managed = CalcChildrenPrefSizes(bbox, &max_major,
876 					&max_minor, &child_major_total);
877 
878     pad = 0.0;
879     pos_major = (float) margin_major;
880     if ((FillOption(bbox) == XmFillNone) || (FillOption(bbox) == XmFillMinor))
881     {
882 	if ( box_major >= child_major_total ) {
883 	    pad = ((float) box_major -
884 		   (float) child_major_total) / ((float) num_managed + 1.0);
885 	    pos_major += pad;
886 	}
887     }
888 
889     ForAllChildren(bbox, childp) {
890 	if ( !XtIsManaged(*childp) )
891 	    continue;
892 
893 	CalcChildSize(bbox, *childp, max_major, max_minor,
894 		      child_major_total, num_managed, &child_major,
895 		      &child_minor);
896 
897 	if ((FillOption(bbox) == XmFillNone) ||
898 	    (FillOption(bbox) == XmFillMajor))
899 	{
900 	    pos_minor = (((int)(box_minor - child_minor)) /2) + margin_minor;
901 	}
902 	else
903 	    pos_minor = margin_minor;
904 
905 	if ( IsHorizontal(bbox) ) {
906 	    child_width = child_major;
907 	    child_height = child_minor;
908 	    if (LayoutIsRtoLM(bbox))
909 		pos_x = box_major - (int) pos_major - child_width;
910 	    else
911 		pos_x = (int) pos_major;
912 	    pos_y = pos_minor;
913 	}
914 	else {
915 	    pos_x = pos_minor;
916 	    pos_y = (int) pos_major;
917 	    child_width = child_minor;
918 	    child_height = child_major;
919 	}
920 
921 	if ( (int)child_width >= (int)(2 * (*childp)->core.border_width) )
922 	    child_width -= (2 * (*childp)->core.border_width);
923 
924 	if ( (int)child_height >= (int)(2 * (*childp)->core.border_width) )
925 	    child_height -= (2 * (*childp)->core.border_width);
926 
927 	child_width = (child_width == 0) ? 1 : child_width;
928 	child_height = (child_height == 0) ? 1 : child_height;
929 
930 	if (*childp == special_child) {
931 	    special_child->core.x = pos_x;
932 	    special_child->core.y = pos_y;
933 	    special_child->core.width = child_width;
934 	    special_child->core.height = child_height;
935 	}
936 	else {
937 	    _XmConfigureWidget(*childp, pos_x, pos_y, child_width,
938 			       child_height, (*childp)->core.border_width);
939 	}
940 
941 	pos_major += (float) child_major + pad;
942     }
943 }
944 
945 /*      Function Name: CalcChildrenPrefSizes
946  *      Description:   Determines the total size in the major direction
947  *		       of all children of the ButtonBox, as well as the
948  *                     maximum value in both major and minor directions.
949  *      Arguments:     bbox - the ButtonBox parent.
950  *		       max_major - the maximum size of all the children
951  *				   in the major dimension.
952  *		       total - return location for the total size in the
953  *			       major direction.
954  *      Returns:       number of managed children.
955  */
956 
957 /* ARGSUSED */
958 static Cardinal
CalcChildrenPrefSizes(XmButtonBoxWidget bbox,Dimension * max_major,Dimension * max_minor,Dimension * total)959 CalcChildrenPrefSizes(XmButtonBoxWidget bbox, Dimension *max_major,
960 		      Dimension *max_minor, Dimension *total)
961 {
962     Cardinal		num_managed = 0;
963     Widget	       *childp;
964     XtWidgetGeometry	geo;
965     Dimension	       *maj_dim, *minor_dim;
966     Boolean		is_equal = EqualSize(bbox);
967 
968     if ( IsHorizontal(bbox) )
969     {
970 	maj_dim = &geo.width;
971 	minor_dim = &geo.height;
972     }
973     else
974     {
975 	maj_dim = &geo.height;
976 	minor_dim = &geo.width;
977     }
978 
979     *total = *max_major = *max_minor = 1;
980 
981     ForAllChildren(bbox, childp) {
982 
983 	if ( !XtIsManaged(*childp) )
984 	    continue;
985 
986 	num_managed++;
987 
988 	if ((XmButtonBoxC_pref_width(*childp) == 0) ||
989 	    (XmButtonBoxC_pref_height(*childp) == 0))
990 	{
991 	    XtQueryGeometry(*childp, NULL, &geo);
992 	}
993 	else
994 	    geo.border_width = (*childp)->core.border_width;
995 
996 	if (XmButtonBoxC_pref_width(*childp) == 0)
997 	    XmButtonBoxC_pref_width(*childp) = geo.width;
998 	else
999 	    geo.width = XmButtonBoxC_pref_width(*childp);
1000 
1001 	if (XmButtonBoxC_pref_height(*childp) == 0)
1002 	    XmButtonBoxC_pref_height(*childp) = geo.height;
1003 	else
1004 	    geo.height = XmButtonBoxC_pref_height(*childp);
1005 
1006 	ASSIGN_MAX(*max_major, *maj_dim + (2 * geo.border_width));
1007 	ASSIGN_MAX(*max_minor, *minor_dim + (2 * geo.border_width));
1008 
1009 	if (!is_equal)
1010 	    *total += (*maj_dim + (2 * geo.border_width));
1011     }
1012 
1013     if ( is_equal )
1014         *total = num_managed * (*max_major);
1015 
1016     return(num_managed);
1017 }
1018 
1019 /*      Function Name: CalcChildSize
1020  *      Description:   Determines the size of a child
1021  *      Arguments:     bbox - the ButtonBox parent.
1022  *		       w - the child of interest.
1023  *		       max_major - the largest size allowed in the
1024  *				   major direction.
1025  *		       max_minor - the largest size allowed in the
1026  *				   minor direction.
1027  *		       child_major_total - total size of all children in the
1028  *					   major direction.
1029  *		       num_managed - number of managed children.
1030  *		       child_major - return location for child's base
1031  *				     major size.
1032  *		       child_minor - return location for child's base
1033  *				     minor size.
1034  *      Returns:       none.
1035  */
1036 
1037 /* ARGSUSED */
1038 static void
CalcChildSize(XmButtonBoxWidget bbox,Widget w,Dimension max_major,Dimension max_minor,Dimension child_major_total,Cardinal num_managed,Dimension * child_major,Dimension * child_minor)1039 CalcChildSize(XmButtonBoxWidget bbox, Widget w, Dimension max_major,
1040 	      Dimension max_minor, Dimension child_major_total,
1041 	      Cardinal num_managed, Dimension *child_major,
1042 	      Dimension *child_minor)
1043 {
1044     XtWidgetGeometry	geo;
1045     Dimension		box_minor, box_major;
1046     Dimension		margin_major, margin_minor;
1047 
1048     if ((XmButtonBoxC_pref_width(w) == 0)||(XmButtonBoxC_pref_height(w) == 0))
1049 	XtQueryGeometry(w, NULL, &geo);
1050     else
1051 	geo.border_width = w->core.border_width;
1052 
1053     if (XmButtonBoxC_pref_width(w) != 0)
1054 	geo.width = XmButtonBoxC_pref_width(w);
1055 
1056     if (XmButtonBoxC_pref_height(w) != 0)
1057 	geo.height = XmButtonBoxC_pref_height(w);
1058 
1059     if ( IsHorizontal(bbox) )
1060     {
1061 	margin_major = MarginW(bbox);
1062 	margin_minor = MarginH(bbox);
1063 	box_major = bbox->core.width;
1064         box_minor = bbox->core.height;
1065         *child_major = geo.width;
1066         *child_minor = geo.height;
1067     }
1068     else
1069     {
1070 	margin_major = MarginH(bbox);
1071 	margin_minor = MarginW(bbox);
1072 	box_major = bbox->core.height;
1073         box_minor = bbox->core.width;
1074         *child_major = geo.height;
1075         *child_minor = geo.width;
1076     }
1077     *child_major += (2 * geo.border_width);
1078     *child_minor += (2 * geo.border_width);
1079 
1080     if ((int)box_major > (int)(2 * margin_major))
1081 	box_major -= (2 * margin_major);
1082     else
1083 	box_major = 1;
1084 
1085     if ((int)box_minor > (int)(2 * margin_minor))
1086 	box_minor -= (2 * margin_minor);
1087     else
1088 	box_minor = 1;
1089 
1090     if ( EqualSize(bbox) )
1091     {
1092         *child_major = max_major;
1093         *child_minor = max_minor;
1094     }
1095     if ( FillOption(bbox) == XmFillMajor || FillOption(bbox) == XmFillAll ||
1096 	 child_major_total > box_major )
1097     {
1098 	*child_major = (Dimension)
1099 	    (((float)*child_major/(float)child_major_total) * box_major);
1100     }
1101     if ( FillOption(bbox) == XmFillMinor || FillOption(bbox) == XmFillAll ||
1102 	 *child_minor > box_minor )
1103     {
1104 	*child_minor = box_minor;
1105     }
1106 }
1107 
1108 /************************************************************
1109  *
1110  *  Public functions
1111  *
1112  ************************************************************/
1113 
1114 /*	Function Name: XmCreateButtonBox
1115  *	Description: Creation Routine for UIL and ADA.
1116  *	Arguments: parent - the parent widget.
1117  *                 name - the name of the widget.
1118  *                 args, num_args - the number and list of args.
1119  *	Returns: The created widget.
1120  */
1121 
1122 Widget
XmCreateButtonBox(Widget parent,String name,ArgList args,Cardinal num_args)1123 XmCreateButtonBox(Widget parent, String name, ArgList args, Cardinal num_args)
1124 {
1125     return(XtCreateWidget(name,
1126 			  xmButtonBoxWidgetClass, parent, args, num_args));
1127 }
1128 
1129 Widget
XmVaCreateButtonBox(Widget parent,char * name,...)1130 XmVaCreateButtonBox(
1131         Widget parent,
1132         char *name,
1133         ...)
1134 {
1135     register Widget w;
1136     va_list var;
1137     int count;
1138 
1139     Va_start(var,name);
1140     count = XmeCountVaListSimple(var);
1141     va_end(var);
1142 
1143 
1144     Va_start(var, name);
1145     w = XmeVLCreateWidget(name,
1146                          xmButtonBoxWidgetClass,
1147                          parent, False,
1148                          var, count);
1149     va_end(var);
1150     return w;
1151 }
1152 
1153 Widget
XmVaCreateManagedButtonBox(Widget parent,char * name,...)1154 XmVaCreateManagedButtonBox(
1155         Widget parent,
1156         char *name,
1157         ...)
1158 {
1159     Widget w = NULL;
1160     va_list var;
1161     int count;
1162 
1163     Va_start(var, name);
1164     count = XmeCountVaListSimple(var);
1165     va_end(var);
1166 
1167     Va_start(var, name);
1168     w = XmeVLCreateWidget(name,
1169                          xmButtonBoxWidgetClass,
1170                          parent, True,
1171                          var, count);
1172     va_end(var);
1173     return w;
1174 }
1175 
1176 /****************************************************************/
1177 static void
ButtonBoxSetDefaultShadow(Widget button)1178 ButtonBoxSetDefaultShadow(Widget button)
1179 {
1180     XmTakesDefaultTrait trait_default ;
1181 
1182     trait_default = (XmTakesDefaultTrait) XmeTraitGet((XtPointer)
1183 						      XtClass(button),
1184 						      XmQTtakesDefault) ;
1185     if (trait_default)
1186 	trait_default->showAsDefault  (button, XmDEFAULT_READY);
1187 }
1188