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  * HISTORY
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 
31 
32 #ifdef REV_INFO
33 #ifndef lint
34 static char *rcsid = "$XConsortium: RCLayout.c /main/6 1995/10/25 20:14:15 cde-sun $";
35 #endif
36 #endif
37 
38 #include <stdio.h>
39 #include <ctype.h>
40 #ifndef X_NOT_STDC_ENV
41 #include <stdlib.h>
42 #endif
43 #include <Xm/CascadeBGP.h>
44 #include <Xm/CascadeBP.h>
45 #include <Xm/GadgetP.h>
46 #include <Xm/LabelP.h>
47 #include <Xm/ManagerP.h>
48 #include <Xm/PrimitiveP.h>
49 #include <Xm/RowColumnP.h>
50 #include <Xm/TearOffBP.h>
51 #include <Xm/TearOffP.h>
52 #include <Xm/XmosP.h>		/* for bzero */
53 #include "LabelGI.h"
54 #include "GeoUtilsI.h"
55 #include "RCLayoutI.h"
56 #include "RowColumnI.h"
57 #include "XmI.h"
58 
59 #define RESOURCE_MIN_WIDTH	16 /* 'cuz it's the size of a hot spot... */
60 #define RESOURCE_MIN_HEIGHT	16
61 
62 
63 
64 static void CalcHelp(
65                         XmRowColumnWidget m,
66                         Dimension *m_width,
67                         Dimension *m_height,
68 #if NeedWidePrototypes
69                         int b,
70                         int max_x,
71                         int max_y,
72 #else
73                         Dimension b,
74                         Position max_x,
75                         Position max_y,
76 #endif /* NeedWidePrototypes */
77                         Position *x,
78                         Position *y,
79 #if NeedWidePrototypes
80                         int w,
81                         int h) ;
82 #else
83                         Dimension w,
84                         Dimension h) ;
85 #endif /* NeedWidePrototypes */
86 
87 static void GetMaxValues(
88                         XmRowColumnWidget m,
89                         Dimension *border,
90                         Dimension *w,
91                         Dimension *h,
92                         int *items_per,
93                         Dimension *baseline,
94                         Dimension *shadow,
95                         Dimension *highlight,
96                         Dimension *margin_top,
97                         Dimension *margin_height,
98                         Dimension *text_height) ;
99 
100 static void AdjustLast(
101                         XmRowColumnWidget m,
102                         int start_i,
103 #if NeedWidePrototypes
104                         int w,
105                         int h) ;
106 #else
107                         Dimension w,
108                         Dimension h) ;
109 #endif /* NeedWidePrototypes */
110 static void SetAsking(
111                         XmRowColumnWidget m,
112                         Dimension *m_width,
113                         Dimension *m_height,
114 #if NeedWidePrototypes
115                         int b,
116                         int max_x,
117                         int max_y,
118                         int x,
119                         int y,
120                         int w,
121                         int h) ;
122 #else
123                         Dimension b,
124                         Position max_x,
125                         Position max_y,
126                         Position x,
127                         Position y,
128                         Dimension w,
129                         Dimension h) ;
130 #endif /* NeedWidePrototypes */
131 static void FindLargestOption(
132                         XmRowColumnWidget submenu,
133                         Dimension *c_width,
134                         Dimension *c_height) ;
135 static void TopOrBottomAlignment(
136                         XmRowColumnWidget m,
137 #if NeedWidePrototypes
138                         int h,
139                         int shadow,
140                         int highlight,
141                         int baseline,
142                         int margin_top,
143                         int margin_height,
144                         int text_height,
145 #else
146                         Dimension h,
147                         Dimension shadow,
148                         Dimension highlight,
149                         Dimension baseline,
150                         Dimension margin_top,
151                         Dimension margin_height,
152                         Dimension text_height,
153 #endif /* NeedWidePrototypes */
154                         Dimension *new_height,
155                         int start_i,
156                         int end_i) ;
157 static void BaselineAlignment(
158                         XmRowColumnWidget m,
159 #if NeedWidePrototypes
160                         int h,
161                         int shadow,
162                         int highlight,
163                         int baseline,
164 #else
165                         Dimension h,
166                         Dimension shadow,
167                         Dimension highlight,
168                         Dimension baseline,
169 #endif /* NeedWidePrototypes */
170                         Dimension *new_height,
171                         int start_i,
172                         int end_i) ;
173 static void CenterAlignment(
174                         XmRowColumnWidget m,
175 #if NeedWidePrototypes
176                         int h,
177 #else
178                         Dimension h,
179 #endif /* NeedWidePrototypes */
180                         int start_i,
181                         int end_i) ;
182 static void ComputeTearOffHeight(
183 			XmRowColumnWidget m,
184 			Dimension *toc_b,
185                         Dimension *b,
186 	                Dimension *toc_height,
187                         int *start_i,
188                         int *child_i,
189 			int r);
190 static void LayoutColumn(
191                         XmRowColumnWidget m,
192                         Dimension *m_width,
193                         Dimension *m_height) ;
194 static void LayoutVerticalTight(
195                         XmRowColumnWidget m,
196                         Dimension *m_width,
197                         Dimension *m_height) ;
198 static void LayoutHorizontaltight(
199                         XmRowColumnWidget m,
200                         Dimension *m_width,
201                         Dimension *m_height) ;
202 static void LayoutNone(
203                         XmRowColumnWidget m,
204                         Dimension *m_width,
205                         Dimension *m_height) ;
206 static void LayoutOptionAndSize(
207                         register XmRowColumnWidget menu,
208                         Dimension *width,
209                         Dimension *height,
210                         Widget instigator,
211                         XtWidgetGeometry *request,
212 #if NeedWidePrototypes
213                         int calcMenuDimension) ;
214 #else
215                         Boolean calcMenuDimension) ;
216 #endif /* NeedWidePrototypes */
217 static void GetMenuKidMargins(
218 				 XmRowColumnWidget m,
219 				 Dimension *width,
220 				 Dimension *height,
221 				 Dimension *left,
222 				 Dimension *right,
223 				 Dimension *top,
224 				 Dimension *bottom );
225 
226 
227 
228 
229 /*************************************************************************
230  *
231  * This section is all the layout stuff, the whole thing has to operate
232  * in two different modes, one: a read-only mode which
233  * is nice for making decisions about the size of the row column vs. the size
234  * of the children.  two: a change everything mode which implements the
235  * change.
236  *
237  * further complicated by the xtoolkit restriction that a subwidget making
238  * a geo request (referred to as the 'instigator') of the row column may not
239  * have his resize proc called but all other widget children must.
240  *
241  * this is done by building a set of XtWidgetGeometry request blocks, one
242  * for each child (widget and gadget), which holds the changes we would like
243  * to make for this child.  If needed then another pass is made over the
244  * requests to actually implement the changes.
245  *************************************************************************/
246 
247 
248 /*
249  * Decide where to put the help child.  He better be the last one
250  * 'cuz we may trash the x, y's
251  */
252 static void
CalcHelp(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height,int b,int max_x,int max_y,Position * x,Position * y,int w,int h)253 CalcHelp(
254         XmRowColumnWidget m,
255         Dimension *m_width,     /* if 0 then caller's asking */
256         Dimension *m_height,    /* if 0 then caller's asking */
257 #if NeedWidePrototypes
258         int b,
259         int max_x,
260         int max_y,
261 #else
262         Dimension b,
263         Position max_x,
264         Position max_y,
265 #endif /* NeedWidePrototypes */
266         Position *x,
267         Position *y,
268 #if NeedWidePrototypes
269         int w,
270         int h )
271 #else
272         Dimension w,
273         Dimension h )
274 #endif /* NeedWidePrototypes */
275 {
276    register Dimension subtrahend;
277 
278    if (IsVertical (m))             /* glue to bottom edge of ... */
279    {
280       if (Asking (*m_height))
281       {
282 	 if (RC_NCol (m) == 1)       /* just use max_y */
283 	     *y = max_y;
284 	 else                /* go up from max_y */
285 	 {
286 	     subtrahend = RC_Spacing (m) + h + b;
287 	     *y = (max_y > (int)subtrahend) ? max_y - subtrahend : 0;
288 	 }
289       }
290       else
291       {
292 	  subtrahend = MGR_ShadowThickness(m) + RC_MarginH (m) + h + b;
293 	  *y = (*m_height > (int)subtrahend) ? *m_height - subtrahend : 0;
294       }
295    }
296    else                    /* glue to right edge of ... */
297    {
298       if (Asking (*m_width))
299       {
300 	 if (RC_NCol (m) == 1)
301 	     *x = max_x;
302 	 else
303 	 {
304 	     subtrahend = RC_Spacing (m) + w + b;
305 	     *x = (max_x > (int)subtrahend) ? max_x - subtrahend : 0;
306 	 }
307       }
308       else
309       {
310 	 subtrahend = MGR_ShadowThickness(m) + RC_MarginW (m) + w + b;
311 	 *x = (*m_width > (int)subtrahend) ? *m_width - subtrahend : 0;
312       }
313    }
314 }
315 
316 
317 /*
318  * count the widest & tallest entry dimensions
319  * and compute entries per row/column
320  */
321 static void
GetMaxValues(XmRowColumnWidget m,Dimension * border,Dimension * w,Dimension * h,int * items_per,Dimension * baseline,Dimension * shadow,Dimension * highlight,Dimension * margin_top,Dimension * margin_height,Dimension * text_height)322 GetMaxValues(
323         XmRowColumnWidget m,
324         Dimension *border,
325         Dimension *w,
326         Dimension *h,
327         int *items_per,
328         Dimension *baseline,
329         Dimension *shadow,
330         Dimension *highlight,
331         Dimension *margin_top,
332         Dimension *margin_height,
333         Dimension *text_height )
334 {
335     XtWidgetGeometry *b;
336     Widget k ;
337     int i, n ;
338 
339     *border = *w = *h = *baseline = *shadow = *highlight =
340 	*margin_top = *margin_height = *text_height = 0;
341 
342     /* skip the tearoff control */
343     for (i = (RC_TearOffControl(m) &&
344 	      XtIsManaged(RC_TearOffControl(m)))? 1 : 0, n = 0;
345 	 RC_Boxes (m) [i].kid != NULL;
346 	 i++, n++) {
347        b = &(RC_Boxes (m) [i].box);
348        k = RC_Boxes (m) [i].kid ;
349 
350        ASSIGN_MAX(*w, BWidth (b));
351        ASSIGN_MAX(*h, BHeight (b));
352 
353        if (XtIsWidget(k)) {
354 	   ASSIGN_MAX(*border, k->core.border_width);
355        } else if (XmIsGadget(k)) {
356 	   ASSIGN_MAX(*border, ((XmGadget)k)->rectangle.border_width);
357        }
358 
359        ASSIGN_MAX(*baseline, RC_Boxes (m) [i].baseline);
360 
361        if (XmIsGadget (k) || XmIsPrimitive (k) ) {
362          XmBaselineMargins textMargins;
363 	 _XmRC_SetOrGetTextMargins(k, XmBASELINE_GET, &textMargins);
364          ASSIGN_MAX(*shadow, textMargins.shadow);
365          ASSIGN_MAX(*highlight, textMargins.shadow);
366          ASSIGN_MAX(*margin_top, textMargins.margin_top);
367          ASSIGN_MAX(*margin_height, textMargins.margin_height);
368          ASSIGN_MAX(*text_height, textMargins.text_height);
369        }
370     }
371 
372     *items_per = n / RC_NCol (m);       /* calc column size */
373     if ((n % RC_NCol (m)) != 0) (*items_per)++;  /* some left overs */
374                                                  /* add another row/col */
375 }
376 
377 
378 /*
379  * Make sure that entries in the right most column/row extend all the
380  * way to the right/bottom edge of the row column widget.  This keeps
381  * 'dead space' in the row column widget to a minimum.  For single
382  * column widgets, the only column is the right most.
383  *
384  */
385 static void
AdjustLast(XmRowColumnWidget m,int start_i,int w,int h)386 AdjustLast(
387         XmRowColumnWidget m,
388         int start_i,
389 #if NeedWidePrototypes
390         int w,
391         int h )
392 #else
393         Dimension w,
394         Dimension h )
395 #endif /* NeedWidePrototypes */
396 {
397    XmRCKidGeometry kg = RC_Boxes (m);
398    XtWidgetGeometry *b;
399    register Dimension subtrahend;
400 
401    for ( ; kg [start_i].kid != NULL; start_i++)
402    {
403       b = &(kg[start_i].box);
404 
405       if (IsVertical (m))
406       {
407          subtrahend = MGR_ShadowThickness(m) + RC_MarginW (m) + BX (b)
408 	     + Double (BBorder (b));
409 
410 	 /* if w (rowcol width) is greater than subtrahend (the smallest
411 	  * width of the child, we'll guarantee at least a width of 1.
412 	  */
413 	 if (w > subtrahend)
414 	     BWidth (b) = w-subtrahend;
415       }
416       else
417       {
418          subtrahend =  MGR_ShadowThickness(m) + RC_MarginH (m) + BY (b)
419 	     + Double (BBorder (b));
420 
421          /* When adjusting the last line, text and label widgets or gadgets, */
422          /* use the extra height that is added differently. Text just adds  */
423          /* it on whereas label tries to center it in the extra space.      */
424          /* In order to make the baselines align again as a result of the   */
425          /* above behavior,  Text's margin top has to be adjusted. */
426 	 if (h > subtrahend)
427          {
428              Dimension m_top;
429 
430 	     /* Check for underflow */
431 	     /* The difference is what it grows in height */
432 	     m_top = ((h-subtrahend) > BHeight(b)) ?
433 		((h-subtrahend) - BHeight (b)) : 0 ;
434 
435 	     BHeight (b) = h-subtrahend;
436 
437 	     if (m_top && (XmIsText(kg [start_i].kid) ||
438 			   XmIsTextField(kg [start_i].kid) ||
439 			   XmIsCSText(kg [start_i].kid)))
440              {
441 	       kg [start_i].margin_top += m_top/2; /* Since labels center it */
442              }
443          }
444       }
445    }
446 }
447 
448 
449 /*
450  * decide exactly the dimensions of the row column widget we will return to
451  * an asking caller based on the accumulated layout information.
452  */
453 static void
SetAsking(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height,int b,int max_x,int max_y,int x,int y,int w,int h)454 SetAsking(
455         XmRowColumnWidget m,
456         Dimension *m_width,     /* if 0 then caller's asking */
457         Dimension *m_height,    /* if 0 then caller's asking */
458 #if NeedWidePrototypes
459         int b,
460         int max_x,
461         int max_y,
462         int x,
463         int y,
464         int w,
465         int h )
466 #else
467         Dimension b,
468         Position max_x,
469         Position max_y,
470         Position x,
471         Position y,
472         Dimension w,
473         Dimension h )
474 #endif /* NeedWidePrototypes */
475 {
476     long iheight;
477     long iwidth;
478 
479     if (IsVertical (m))             /* tell caller what he wants */
480     {
481         if (Asking (*m_width))
482             *m_width =   x + w + b      /* right edge of last child */
483                    + MGR_ShadowThickness(m)
484                    + RC_MarginW (m);    /* plus margin on right */
485 
486         if (Asking (*m_height))
487         {
488             ASSIGN_MAX (max_y, y);
489 
490             iheight = (long) max_y                /* last unused y */
491                 - (long) (RC_Spacing (m))         /* up by unused spacing */
492                 + (long) (MGR_ShadowThickness(m))
493                 + (long) (RC_MarginH (m)) ;       /* plus margin on bottom */
494 
495             if (iheight < 0)             /* this is a temporary fix */
496                 *m_height = 0;           /* to make sure we don't   */
497             else                         /* compute a negative height */
498                 *m_height = (Dimension) iheight; /*in an unsigned short   */
499         }
500     }
501     else
502     {
503         if (Asking (*m_width))
504         {
505             ASSIGN_MAX (max_x, x);
506 
507             iwidth = (long) max_x
508                 - (long) (RC_Spacing (m))
509                 + (long) (MGR_ShadowThickness(m))
510                 + (long) (RC_MarginW (m)) ;
511 
512             if (iwidth < 0)
513                 *m_width = 0;
514             else
515                 *m_width = (Dimension) iwidth ;
516         }
517 
518         if (Asking (*m_height))
519             *m_height = y + h + b
520                 + MGR_ShadowThickness(m)
521                 + RC_MarginH (m);
522     }
523 }
524 
525 
526 
527 
528 
529 static void
FindLargestOption(XmRowColumnWidget submenu,Dimension * c_width,Dimension * c_height)530 FindLargestOption(
531 	XmRowColumnWidget submenu,
532 	Dimension *c_width,
533 	Dimension *c_height )
534 {
535     int i;
536     Widget *child ;
537 
538     if (!submenu) return ;
539 
540     ForManagedChildren (submenu, i, child) {
541 	/* Is this recursivity wanted ? */
542 	if (XmIsCascadeButton(*child))	{
543 	    FindLargestOption((XmRowColumnWidget)
544 			      CB_Submenu(*child),
545 			      c_width, c_height);
546 	}
547 	else if (XmIsCascadeButtonGadget(*child))	       {
548 	    FindLargestOption((XmRowColumnWidget)
549 			      CBG_Submenu(*child),
550 			      c_width, c_height);
551 	}
552 	else {
553 	    /* The entire size of the largest menu
554 	     * item is used instead of only its TextRect.  This may
555 	     * result in large expanses of label white space when items
556 	     * utilize left and right margins, shadow, or accelerator
557 	     * text - but the glyph will be visible when the submenu is
558 	     * posted!
559 	     */
560 	    if (XmIsMenuShell(XtParent(submenu))) {
561 		ASSIGN_MAX(*c_width, XtWidth(*child));
562 		ASSIGN_MAX(*c_height, XtHeight(*child));
563 	    }
564 
565 	    /*
566 	     * must be a torn pane.  Don't rely on its dimensions
567 	     * since it may be stretched in the tear off so that
568 	     * the label string fits into the titlebar
569 	     */
570 	    else {
571 		XtWidgetGeometry preferred;
572 
573 		XtQueryGeometry (*child, NULL, &preferred);
574 		ASSIGN_MAX(*c_width, preferred.width);
575 		ASSIGN_MAX(*c_height, preferred.height);
576 
577 	    }
578 	}
579     }
580 }
581 
582 
583 
584 void
_XmRC_CheckAndSetOptionCascade(XmRowColumnWidget menu)585 _XmRC_CheckAndSetOptionCascade(
586       XmRowColumnWidget menu )
587 {
588    Dimension width = 0;
589    Dimension height = 0;
590    int i;
591    Widget cb;
592 
593    /*
594     * if its is a pulldown menu, travel up the cascades to verify the
595     * option menus cascade button is sized large enough.
596     */
597    if (IsPulldown(menu)) {
598        for (i=0; i < menu->row_column.postFromCount; i++) {
599 	   _XmRC_CheckAndSetOptionCascade((XmRowColumnWidget)
600 				XtParent(menu->row_column.postFromList[i]));
601        }
602    }
603 
604    if (!IsOption(menu)  || RC_FromResize(menu)) return ;
605 
606    if ((cb = XmOptionButtonGadget( (Widget) menu)) != NULL) {
607        if (RC_OptionSubMenu(menu)) {
608 	   FindLargestOption
609 	       ((XmRowColumnWidget)RC_OptionSubMenu(menu), &width, &height );
610 
611 	   if (LayoutIsRtoLG(cb))
612 	     width += Double(G_HighlightThickness(cb)) +
613 	       G_ShadowThickness(cb) + LabG_MarginLeft(cb) +
614 		 Double(MGR_ShadowThickness(RC_OptionSubMenu(menu))) - 2;
615 	   else
616 	     width += Double(G_HighlightThickness(cb)) +
617 	       G_ShadowThickness(cb) + LabG_MarginRight(cb) +
618 		 Double(MGR_ShadowThickness(RC_OptionSubMenu(menu))) - 2;
619 
620 	   height += Double(G_HighlightThickness(cb)) + LabG_MarginTop(cb)
621 	       + LabG_MarginBottom(cb);
622 
623 	   /* change cb if needed */
624 	   if ((width != XtWidth(cb)) || (height != XtHeight(cb))) {
625 
626 	       /* we have pixels, but the cascade unit type might not be
627 		  pixel, so save it and restore it after the setvalues */
628 	       unsigned char saved_unit_type =
629 		   ((XmGadget)cb)->gadget.unit_type ;
630 
631 	       ((XmGadget)cb)->gadget.unit_type = XmPIXELS;
632 	       XtVaSetValues (cb, XmNwidth, width, XmNheight, height, NULL);
633 	       ((XmGadget)cb)->gadget.unit_type = saved_unit_type;
634 	   }
635        }
636    }
637 }
638 
639 
640 /*ARGSUSED*/
641 static void
TopOrBottomAlignment(XmRowColumnWidget m,int h,int shadow,int highlight,int baseline,int margin_top,int margin_height,int text_height,Dimension * new_height,int start_i,int end_i)642 TopOrBottomAlignment(
643 	XmRowColumnWidget m,
644 #if NeedWidePrototypes
645 	int h,
646 	int shadow,
647 	int highlight,
648 	int baseline,		/* unused */
649 	int margin_top,
650 	int margin_height,
651 	int text_height,
652 #else
653         Dimension h,
654         Dimension shadow,
655         Dimension highlight,
656         Dimension baseline,	/* unused */
657         Dimension margin_top,
658         Dimension margin_height,
659         Dimension text_height,
660 #endif /* NeedWidePrototypes */
661 	Dimension *new_height,
662         int start_i,
663         int end_i)
664 {
665   XmRCKidGeometry kg = RC_Boxes (m);
666 
667   while (start_i < end_i)
668   {
669     if (XmIsGadget(kg [start_i].kid) || XmIsPrimitive(kg [start_i].kid))
670     {
671       XmBaselineMargins textMargins;
672 
673       _XmRC_SetOrGetTextMargins(kg[start_i].kid, XmBASELINE_GET, &textMargins);
674       kg[start_i].margin_top = textMargins.margin_top;
675       kg[start_i].margin_bottom = textMargins.margin_bottom;
676 
677       if (textMargins.shadow < shadow)
678       {
679          kg[start_i].margin_top += shadow - textMargins.shadow;
680          kg[start_i].box.height += shadow - textMargins.shadow;
681       }
682       if (textMargins.highlight < highlight)
683       {
684          kg[start_i].margin_top += highlight - textMargins.highlight;
685          kg[start_i].box.height += highlight - textMargins.highlight;
686       }
687       if (textMargins.margin_top < margin_top)
688       {
689          kg[start_i].margin_top += margin_top - textMargins.margin_top;
690          kg[start_i].box.height += margin_top - textMargins.margin_top;
691       }
692       if (textMargins.margin_height < margin_height)
693       {
694          kg[start_i].margin_top += margin_height - textMargins.margin_height;
695          kg[start_i].box.height += margin_height - textMargins.margin_height;
696       }
697       if (AlignmentBottom (m))
698        if (textMargins.text_height < text_height)
699        {
700          kg[start_i].margin_top += text_height - textMargins.text_height;
701          kg[start_i].box.height += text_height - textMargins.text_height;
702        }
703       if (kg[start_i].box.height < h)
704       {
705 	kg[start_i].margin_bottom += h - kg[start_i].box.height;
706         kg[start_i].box.height = h;
707       }
708     }
709     if (kg[start_i].box.height > h)
710       if (kg[start_i].box.height > *new_height)
711         *new_height = kg[start_i].box.height;
712     start_i++;
713   }
714 }
715 
716 /*ARGSUSED*/
717 static void
BaselineAlignment(XmRowColumnWidget m,int h,int shadow,int highlight,int baseline,Dimension * new_height,int start_i,int end_i)718 BaselineAlignment(
719 	XmRowColumnWidget m,
720 #if NeedWidePrototypes
721 	int h,
722 	int shadow,		/* unused */
723 	int highlight,		/* unused */
724 	int baseline,
725 #else
726         Dimension h,
727         Dimension shadow,	/* unused */
728         Dimension highlight,	/* unused */
729         Dimension baseline,
730 #endif /* NeedWidePrototypes */
731 	Dimension *new_height,
732         int start_i,
733         int end_i)
734 {
735    XmRCKidGeometry kg = RC_Boxes (m);
736    XmBaselineMargins textMargins;
737 
738    while (start_i < end_i)
739    {
740      if (XmIsPrimitive (kg [start_i].kid) || XmIsGadget (kg [start_i].kid))
741      {
742       unsigned char label_type;
743 
744       _XmRC_SetOrGetTextMargins(kg [start_i].kid, XmBASELINE_GET, &textMargins);
745       kg[start_i].margin_top = textMargins.margin_top;
746       kg[start_i].margin_bottom = textMargins.margin_bottom;
747       XtVaGetValues(kg [start_i].kid, XmNlabelType, &label_type, NULL);
748 
749       if (label_type == XmSTRING)
750       {
751         if (kg[start_i].baseline < baseline)
752         {
753           kg[start_i].margin_top += baseline - kg[start_i].baseline;
754           if (kg[start_i].box.height + (baseline - kg[start_i].baseline) > h)
755           {
756             if (kg[start_i].box.height + (baseline - kg[start_i].baseline) > *new_height)
757 	      *new_height = kg[start_i].box.height + (baseline - kg[start_i].baseline);
758 	    kg[start_i].box.height += baseline - kg[start_i].baseline;
759           }
760           else
761           {
762 	    kg[start_i].margin_bottom += h  - (kg[start_i].box.height +
763 					       (baseline - kg[start_i].baseline));
764 	    kg[start_i].box.height = h;
765           }
766         }
767         else
768         {
769 	  kg[start_i].margin_bottom += h  - (kg[start_i].box.height +
770 					     (baseline - kg[start_i].baseline));
771 	  kg[start_i].box.height = h;
772         }
773       }
774       else
775        kg[start_i].box.height = h;
776     }
777     else
778       kg[start_i].box.height = h;
779     start_i++;
780    }
781 }
782 
783 static void
CenterAlignment(XmRowColumnWidget m,int h,int start_i,int end_i)784 CenterAlignment(
785         XmRowColumnWidget m,
786 #if NeedWidePrototypes
787         int h,
788 #else
789         Dimension h,
790 #endif /* NeedWidePrototypes */
791         int start_i,
792         int end_i)
793 {
794 
795   XmRCKidGeometry kg = RC_Boxes (m);
796 
797   while(start_i < end_i)
798   {
799     if (XmIsGadget (kg [start_i].kid) || XmIsPrimitive (kg [start_i].kid))
800     {
801       XmBaselineMargins textMargins;
802 
803       _XmRC_SetOrGetTextMargins(kg [start_i].kid, XmBASELINE_GET, &textMargins);
804       kg[start_i].margin_top = textMargins.margin_top;
805       kg[start_i].margin_bottom = textMargins.margin_bottom;
806     }
807 
808     kg[start_i++].box.height = h;
809   }
810 }
811 
812 
813 static void
ComputeTearOffHeight(XmRowColumnWidget m,Dimension * toc_b,Dimension * b,Dimension * toc_height,int * start_i,int * child_i,int r)814 ComputeTearOffHeight(
815         XmRowColumnWidget m,
816         Dimension *toc_b,
817         Dimension *b,
818 	Dimension *toc_height,
819         int *start_i,
820         int *child_i,
821         int r)
822 
823 {
824     XmRCKidGeometry kg = RC_Boxes (m);
825 
826     *toc_b = *b = Double (RC_EntryBorder (m));
827 
828     if (RC_TearOffControl(m) && XtIsManaged(RC_TearOffControl(m))) {
829 	XmTearOffButtonWidget tw = (XmTearOffButtonWidget)RC_TearOffControl(m);
830 
831 	if (!RC_EntryBorder(m) && kg[0].kid && XtIsWidget(kg[0].kid))
832 	    *toc_b = Double(kg[0].kid->core.border_width);
833 
834 	*toc_height = 0;
835 
836 	/* Remember!  If toc exists, it has the  first kid geo */
837 	for (*start_i = 1;  kg[*start_i].kid != NULL; (*start_i)++)
838 	    ASSIGN_MAX(*toc_height, kg[*start_i].box.height);
839 
840 	*toc_height = *toc_height >> r;    /* r is 1 or 2 depending on the
841 					    orientation. 1 makes the tear off
842 					    half the highest, 2 makes 1/4 */
843 
844 	ASSIGN_MAX(*toc_height, 2 + *toc_b +  2*
845 	       ((XmPrimitiveWidget)kg[0].kid)->primitive.shadow_thickness);
846 
847 	/* Sync up the kid geo */
848 	/* Fix CR# 4778 */
849 	if (tw -> label.recompute_size == True)
850 	    kg[0].box.height = *toc_height;
851 	else
852 	    kg[0].box.height = *toc_height = XtHeight(tw);
853 	kg[0].box.width = XtWidth(m);
854 
855 	*start_i = *child_i = 1;
856     }
857     else
858 	*toc_height = *toc_b = *start_i = *child_i = 0;
859 }
860 
861 
862 
863 /*
864  * figure out where all the children of a column style widget go.  The
865  * border widths are already set.
866  *
867  * In columnar mode, all heights and widths are identical.  They are the
868  * size of the largest item.
869  *
870  * For vertical widgets the items are laid out in columns, going down the
871  * first column and then down the second.  For horizonatal, think of the
872  * columns as rows.
873  *
874  * By convention incoming row column size can be zero, indicating a request
875  * for preferred size, this means lay it out and record the needed size.
876  *
877  * NOTE: the layout is predicated on the help child being the last one since
878  * it messes up the x, y for a following child.
879  */
880 static void
LayoutColumn(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height)881 LayoutColumn(
882         XmRowColumnWidget m,
883         Dimension *m_width,     /* if 0 then caller's asking */
884         Dimension *m_height )   /* if 0 then caller's asking */
885 {
886     XmRCKidGeometry kg = RC_Boxes (m);
887     XtWidgetGeometry *bx;
888     Position x, y, max_x = 0, max_y = 0;
889     int items_per_column,
890         kid_i,
891         child_i,                    /* which child we are doing */
892         col_c   = 0,                /* items in col being done */
893         start_i = 0;                /* index of first item in col */
894     Dimension border, w, h, baseline, shadow, highlight,
895               margin_top, margin_height, text_height;
896     Dimension toc_height;
897     Dimension new_height= 0;
898     Dimension toc_b, b;
899 
900 
901     ComputeTearOffHeight(m, &toc_b, &b, &toc_height, &start_i, &child_i, 1);
902 
903     /* loc of first item */
904     x = MGR_ShadowThickness(m) + RC_MarginW (m);
905     y = MGR_ShadowThickness(m) + RC_MarginH (m) + toc_height + toc_b;
906 
907     GetMaxValues (m, &border, &w, &h, &items_per_column, &baseline,
908 	      &shadow, &highlight, &margin_top, &margin_height, &text_height);
909 
910     if (!RC_EntryBorder(m) && kg[child_i].kid && XtIsWidget(kg[child_i].kid))
911          b = Double(border);
912 
913     /* Loop through and find the new height, if any,  that the RowColumn */
914     /* children need to grow to as a result of adjusting the baselines.  */
915     /* The empty loop determine the number of kids                       */
916 
917     if (AlignmentBaselineTop(m) || AlignmentBaselineBottom(m))
918     {
919         kid_i = 0;
920         while (kg [kid_i].kid != NULL)
921 	  kid_i++;
922         BaselineAlignment(m, h, shadow, highlight, baseline,
923 			  &new_height, 0, kid_i);
924 
925     }
926     else if (AlignmentTop(m) || AlignmentBottom(m))
927     {
928         kid_i = 0;
929 	while (kg [kid_i].kid != NULL)
930 	  kid_i++;
931         TopOrBottomAlignment(m, h, shadow, highlight,
932 			     baseline, margin_top, margin_height,
933 			     text_height, &new_height, 0, kid_i);
934     }
935     else if (AlignmentCenter(m))
936     {
937         kid_i = 0;
938 	while (kg [kid_i].kid != NULL)
939 	  kid_i++;
940         CenterAlignment(m, h, start_i, kid_i);
941     }
942 
943     if (!new_height) new_height = h;
944 
945     for (; kg [child_i].kid != NULL; child_i++)
946     {
947         bx = &(kg[child_i].box);
948 
949         BWidth  (bx) = w;           /* all have same dimensions */
950 
951         if (AlignmentCenter(m))
952          BHeight(bx) = h;
953 
954         if (++col_c > items_per_column)     /* start a new column */
955         {
956 	   if (IsVertical (m))         /* calc loc of new column */
957 	   {
958 	      x += w + b + RC_Spacing (m);    /* to the right */
959 
960 	      /*back at top of menu */
961 	      y = MGR_ShadowThickness(m) + RC_MarginH (m) + toc_height + toc_b;
962 	   }
963 	   else                /* calc loc of new row */
964 	   {
965 	      /* back to left edge */
966 	      x = MGR_ShadowThickness(m) + RC_MarginW (m);
967 	      /* down a row */
968 	      y += new_height + b + RC_Spacing (m);
969 	   }
970 
971 	   col_c = 1;              /* already doing this one */
972 	   start_i = child_i;          /* record index */
973         }
974 
975         if (IsHelp (m, ((Widget) kg[child_i].kid)))
976             CalcHelp (m, m_width, m_height, b, max_x, max_y,
977 		       &x, &y, w, new_height);
978 
979         SetPosition (bx, x, y);         /* plunk him down */
980 
981         if (IsVertical (m))         /* get ready for next item */
982             y += new_height + b + RC_Spacing (m);
983         else
984             x += w + b + RC_Spacing (m);
985 
986         ASSIGN_MAX (max_y, y);
987 	ASSIGN_MAX (max_x, x); /* record for use later */
988      }
989 
990      if (new_height > h) {
991         for(kid_i = 0; kid_i < child_i; kid_i++) {
992           bx = &(kg[kid_i].box);
993           if (BHeight(bx) != new_height) {
994 	    kg[kid_i].margin_bottom += new_height - kg[kid_i].box.height;
995 	    BHeight(bx) = new_height;
996           }
997         }
998      }
999 
1000     SetAsking (m, m_width, m_height, b, max_x, max_y, x, y, w, new_height);
1001 
1002 
1003 /* Set toc width to the width of the pane */
1004 /* declare a macro and use it in the next 3 routines */
1005 #define SET_TEAR_OFF_BOX(toc_height) \
1006    if (toc_height)    {\
1007        kg[0].box.x = MGR_ShadowThickness(m) + RC_MarginW (m);\
1008        kg[0].box.y = MGR_ShadowThickness(m) + RC_MarginH (m);\
1009        kg[0].box.height = toc_height;\
1010        kg[0].box.width = *m_width - Double(MGR_ShadowThickness(m) + \
1011        RC_MarginW(m)) - toc_b; \
1012     }
1013 
1014     SET_TEAR_OFF_BOX(toc_height);
1015 
1016     if (RC_AdjLast(m))
1017         AdjustLast (m, start_i, *m_width, *m_height);
1018     if (LayoutIsRtoLM(m))
1019         for (child_i=0; kg [child_i].kid != NULL; child_i++)
1020         {
1021            bx = &(kg[child_i].box);
1022            /* Adjust x */
1023            BX (bx) = *m_width - BX (bx) - BWidth (bx) - b ;
1024         }
1025 }
1026 
1027 
1028 /*
1029  * do a vertical tight (non-column) layout.
1030  *
1031  * In a tight layout one dimension of the items is left alone and the other
1032  * is kept uniform.  In a vertical row column widgets, the widths of each child
1033  * are uniform for each column, the heights are never changed.  In a horiz
1034  * row column widget, the widths are never changed and the heights are kept
1035  * uniform for each row.
1036  *
1037  * It gets messy w.r.t. the help child because we don't know if there will
1038  * be room in the last column/row for it.  If there isn't room then a whole
1039  * new column/row has to be added.
1040  *
1041  * NOTE: the layout is predicated on the help child being the last one since
1042  * it messes up the x, y for a following child.
1043  */
1044 static void
LayoutVerticalTight(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height)1045 LayoutVerticalTight(
1046         XmRowColumnWidget m,
1047         Dimension *m_width,     /* if 0 then caller's asking */
1048         Dimension *m_height )   /* if 0 then caller's asking */
1049 {
1050     XmRCKidGeometry kg = RC_Boxes (m);
1051     XtWidgetGeometry *bx;
1052     Position x, y, max_y = 0;
1053     Dimension h = 0;
1054     Dimension w = 0;                /* widest item width in col */
1055     int child_i, start_i;
1056     Dimension toc_height;
1057     Dimension toc_b, b;
1058     Dimension border = 0;
1059 
1060     ComputeTearOffHeight(m, &toc_b, &b, &toc_height, &start_i, &child_i, 1);
1061 
1062     /* first item location */
1063     x = MGR_ShadowThickness(m) + RC_MarginW (m);
1064     y = MGR_ShadowThickness(m) + RC_MarginH (m) + toc_height + toc_b;
1065 
1066     for (; kg [child_i].kid != NULL; child_i++)
1067     {
1068        bx = &(kg[child_i].box);
1069        if (!RC_EntryBorder(m) && kg[child_i].kid &&
1070 	   XtIsWidget(kg[child_i].kid))
1071          b = Double(kg[child_i].kid->core.border_width);
1072 
1073        h = BHeight (bx) + b;           /* calc this item's height */
1074 
1075        if (((y + h) > *m_height) &&
1076 	   ( ! Asking (*m_height)) &&
1077 	   (child_i))
1078        {                   /* start new column */
1079 	  while (start_i < child_i)
1080 	      kg[start_i++].box.width = w;    /* set uniform width */
1081 
1082 	  x += w + Double(border)
1083 	      + MGR_ShadowThickness(m)
1084 		  + RC_MarginW (m);       /* go right and */
1085 
1086 	  y = MGR_ShadowThickness(m)
1087 	      + RC_MarginH (m) + toc_height + toc_b;  /* back to top of menu */
1088 
1089 	  w = BWidth (bx);            /* reset for new column */
1090 
1091           if (kg[child_i].kid && XtIsWidget(kg[child_i].kid))
1092             border = kg[child_i].kid->core.border_width;
1093           else
1094             border = ((XmGadget)kg[child_i].kid)->rectangle.border_width;
1095        }
1096 
1097        if (IsHelp (m, ((Widget) kg[child_i].kid)))
1098 	   CalcHelp (m, m_width, m_height, b, 0, max_y, &x, &y, w, h);
1099 
1100        SetPosition (bx, x, y);
1101 
1102        ASSIGN_MAX(w, BWidth (bx));
1103 
1104        if (kg[child_i].kid && XtIsWidget(kg[child_i].kid))
1105        {
1106          if (border < kg[child_i].kid->core.border_width)
1107            border = kg[child_i].kid->core.border_width;
1108        }
1109        else
1110        {
1111          if (border < ((XmGadget)kg[child_i].kid)->rectangle.border_width)
1112            border = ((XmGadget)kg[child_i].kid)->rectangle.border_width;
1113        }
1114 
1115        y += h + RC_Spacing (m);        /* loc of next item */
1116 
1117        ASSIGN_MAX(max_y, y);       /* record for use later */
1118     }
1119 
1120     SetAsking (m, m_width, m_height, Double(border), 0, max_y, x, y, w, h);
1121 
1122     /* Set toc width to the width of the pane */
1123     SET_TEAR_OFF_BOX(toc_height);
1124 
1125     if (RC_AdjLast(m))
1126         AdjustLast (m, start_i, *m_width, *m_height);
1127     else
1128 	while (start_i < child_i)
1129 	    kg[start_i++].box.width = w;    /* set uniform width */
1130     if (LayoutIsRtoLM(m))
1131         for (child_i=0; kg [child_i].kid != NULL; child_i++)
1132         {
1133            bx = &(kg[child_i].box);
1134            /* Adjust x */
1135            BX (bx) = *m_width - BX (bx) - BWidth (bx) - b ;
1136         }
1137 }
1138 
1139 
1140 static void
LayoutHorizontaltight(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height)1141 LayoutHorizontaltight(
1142         XmRowColumnWidget m,
1143         Dimension *m_width,     /* if 0 then caller's asking */
1144         Dimension *m_height )   /* if 0 then caller's asking */
1145 {
1146     XmRCKidGeometry kg = RC_Boxes (m);
1147     XtWidgetGeometry *bx;
1148     Position x, y, max_x = 0;
1149     Dimension w = 0;
1150     Dimension h = 0;                   /* tallest item height in row */
1151     Dimension new_height = 0;
1152     Dimension baseline = 0;
1153     Dimension shadow = 0;
1154     Dimension highlight = 0;
1155     Dimension margin_height = 0;
1156     Dimension margin_top = 0;
1157     Dimension text_height = 0;
1158     Dimension border = 0;
1159     int child_i, start_i;                /* index of first item in row */
1160     Dimension toc_height;
1161     Dimension toc_b, b;
1162 
1163     ComputeTearOffHeight(m, &toc_b, &b, &toc_height, &start_i, &child_i, 2);
1164 
1165     /* first item location */
1166     x = MGR_ShadowThickness(m) + RC_MarginW (m);
1167     y = MGR_ShadowThickness(m) + RC_MarginH (m) + toc_height + toc_b;
1168 
1169     for (; kg [child_i].kid != NULL; child_i++) {
1170 	bx = &(kg[child_i].box);
1171 	if (!RC_EntryBorder(m) && kg[child_i].kid &&
1172 	    XtIsWidget(kg[child_i].kid))
1173 	    b = Double(kg[child_i].kid->core.border_width);
1174 
1175 	w = BWidth (bx) + b;            /* item's width */
1176 
1177 	if (((x + w) > *m_width) &&
1178 	    ( ! Asking (*m_width)) &&
1179 	    (child_i)) {                   /* start a new row */
1180 
1181 	    if (AlignmentBaselineTop(m) || AlignmentBaselineBottom(m))
1182 		BaselineAlignment(m, h, shadow, highlight, baseline,
1183 				  &new_height, start_i, child_i);
1184 	    else if (AlignmentTop(m) || AlignmentBottom(m))
1185 		TopOrBottomAlignment(m, h, shadow, highlight,
1186 				     baseline, margin_top, margin_height,
1187 				     text_height, &new_height,
1188 				     start_i, child_i);
1189 	    else if (AlignmentCenter(m))
1190 		CenterAlignment(m, h, start_i, child_i);
1191 
1192 	    if (new_height > h) {
1193 		while (start_i < child_i) {
1194 		    if (kg[start_i].box.height != new_height) {
1195 		      kg[start_i].margin_bottom +=
1196 			new_height - kg[start_i].box.height;
1197 		      kg[start_i].box.height = new_height;
1198 		    }
1199 		    start_i++;
1200 		}
1201 		h = new_height;
1202 	    }
1203 
1204 	    start_i = child_i;
1205 
1206 	    x = MGR_ShadowThickness(m)
1207 		+ RC_MarginW (m);       /* left edge of menu */
1208 
1209 	    y += h + Double(border) + MGR_ShadowThickness(m)
1210 		+ RC_MarginH (m);       /* down to top of next row */
1211 
1212 	    h = BHeight (bx);           /* reset for this row */
1213 	    new_height = 0;
1214 	    baseline = kg[child_i].baseline;
1215 	    if (kg[child_i].kid && XtIsWidget (kg[child_i].kid))
1216 		border = kg[child_i].kid->core.border_width;
1217 	    else if (XmIsGadget (kg[child_i].kid))
1218 		border = ((XmGadget)kg[child_i].kid)->rectangle.border_width;
1219 
1220 	    if (XmIsGadget (kg[child_i].kid) ||
1221 		XmIsPrimitive (kg[child_i].kid)) {
1222 		XmBaselineMargins textMargins;
1223 
1224 		_XmRC_SetOrGetTextMargins(kg[child_i].kid, XmBASELINE_GET,
1225 					  &textMargins);
1226 		shadow = textMargins.shadow;
1227 		highlight = textMargins.highlight;
1228 		margin_top = textMargins.margin_top;
1229 		text_height = textMargins.text_height;
1230 		margin_height = textMargins.margin_height;
1231 	    }
1232 	}
1233 
1234 	if (IsHelp (m, ((Widget) kg[child_i].kid)))
1235 	    CalcHelp (m, m_width, m_height, b, max_x, 0, &x, &y, w, h);
1236 
1237 	SetPosition (bx, x, y);
1238 
1239 	if (XmIsGadget (kg[child_i].kid) || XmIsPrimitive (kg[child_i].kid))
1240 	  ASSIGN_MAX(baseline, kg[child_i].baseline);
1241 
1242 	ASSIGN_MAX(h, BHeight (bx));
1243 
1244 	if (kg[child_i].kid && XtIsWidget (kg[child_i].kid)) {
1245 	    ASSIGN_MAX(border, kg[child_i].kid->core.border_width);
1246 	} else if (XmIsGadget (kg[child_i].kid)) {
1247 	    ASSIGN_MAX(border,
1248 		      ((XmGadget)kg[child_i].kid)->rectangle.border_width);
1249 	}
1250 
1251 	if (XmIsGadget (kg[child_i].kid) || XmIsPrimitive (kg[child_i].kid))
1252 	    {
1253 		XmBaselineMargins textMargins;
1254 
1255 		_XmRC_SetOrGetTextMargins(kg[child_i].kid, XmBASELINE_GET,
1256 					  &textMargins);
1257 		ASSIGN_MAX(shadow, textMargins.shadow);
1258 		ASSIGN_MAX(highlight, textMargins.highlight);
1259 		ASSIGN_MAX(margin_top, textMargins.margin_top);
1260 		ASSIGN_MAX(text_height, textMargins.text_height);
1261 		ASSIGN_MAX(margin_height, textMargins.margin_height);
1262 	    }
1263 
1264 	x += w + RC_Spacing (m);        /* loc of next item */
1265 
1266 	ASSIGN_MAX (max_x, x);      /* record for use later */
1267     }
1268 
1269     /* Set toc width to the width of the pane */
1270     SET_TEAR_OFF_BOX(toc_height);
1271 
1272 
1273     if (AlignmentBaselineTop(m) || AlignmentBaselineBottom(m))
1274 	BaselineAlignment(m, h, shadow, highlight, baseline,
1275 			  &new_height, start_i, child_i);
1276     else if (AlignmentTop(m) || AlignmentBottom(m))
1277 	TopOrBottomAlignment(m, h, shadow, highlight,
1278 			     baseline, margin_top, margin_height,
1279 			     text_height, &new_height, start_i, child_i);
1280     else if (AlignmentCenter(m))
1281 	CenterAlignment(m, h, start_i, child_i);
1282 
1283     if (new_height > h){
1284 	while (start_i < child_i){
1285 		bx = &(kg[start_i].box);
1286 		if (BHeight(bx) != new_height) {
1287 		  kg[start_i].margin_bottom +=
1288 		    new_height - kg [start_i].box.height;
1289 		  BHeight(bx) = new_height;
1290 		}
1291 		start_i++;
1292 	    }
1293     }
1294 
1295     if (new_height > h)
1296 	SetAsking (m, m_width, m_height, Double(border),
1297 		    max_x, 0, x, y, w, new_height);
1298     else
1299 	SetAsking (m, m_width, m_height, Double(border),
1300 		    max_x, 0, x, y, w, h);
1301 
1302 #ifdef FIX_1521
1303     for (child_i = 0; kg[child_i].kid != NULL; child_i++)
1304     {
1305         bx = &(kg[child_i].box);
1306         ASSIGN_MIN(BWidth(bx), *m_width - Double(MGR_ShadowThickness(m))
1307             - Double(RC_MarginW(m)) - Double(BBorder(bx)));
1308         if (IsHelp(m, ((Widget) kg[child_i].kid)))
1309             ASSIGN_MAX(BX(&(kg[child_i].box)), MGR_ShadowThickness(m) + RC_MarginW(m));
1310     }
1311 #endif
1312     if (RC_AdjLast(m))
1313 	AdjustLast (m, start_i, *m_width, *m_height);
1314     else
1315 	while (start_i < child_i) {
1316 	    if (new_height > h) kg[start_i++].box.height = new_height;
1317 	    else kg[start_i++].box.height = h;   /* set uniform height */
1318 	}
1319     if (LayoutIsRtoLM(m))
1320         for (child_i=0; kg [child_i].kid != NULL; child_i++)
1321         {
1322            bx = &(kg[child_i].box);
1323            /* Adjust x */
1324            BX (bx) = *m_width - BX (bx) - BWidth (bx) - b ;
1325         }
1326 }
1327 
1328 
1329 
1330 /*
1331  * wrap a box around the entries, used with packing mode of none.
1332  *
1333  * we ignore negative positioning, ie. only worry about being wide enough
1334  * for the right edge of the rightmost entry (similarly for height)
1335  */
1336 static void
LayoutNone(XmRowColumnWidget m,Dimension * m_width,Dimension * m_height)1337 LayoutNone(
1338         XmRowColumnWidget m,
1339         Dimension *m_width,
1340         Dimension *m_height )
1341 {
1342     XtWidgetGeometry *b;
1343     XmRCKidGeometry kg = RC_Boxes (m);
1344     int i, dum;
1345     Dimension w, max_w = 0, max_h = 0;
1346     Dimension toc_height;
1347     Dimension toc_b, bw;
1348     short temp;
1349 
1350     ComputeTearOffHeight(m, &toc_b, &bw, &toc_height, &dum, &i, 2);
1351 
1352     for (; kg [i].kid != NULL; i++)
1353       {
1354         b = &(kg[i].box);
1355         if (!RC_EntryBorder(m) && kg[i].kid && XtIsWidget(kg[i].kid))
1356              bw = Double(kg[i].kid->core.border_width);
1357 
1358         if (Asking (*m_width))
1359         {
1360 	    /* be careful about negative positions */
1361             w = BWidth (b) + bw;
1362             temp = ((short)w) + BX (b);
1363             if (temp <= 0)
1364                 w = 1;
1365             else
1366                 w = (Dimension) temp;
1367 
1368             ASSIGN_MAX (max_w, w);
1369         }
1370 
1371         if (Asking (*m_height))
1372         {
1373             /* be careful about negative positions */
1374             w = BHeight (b) + Double (bw);
1375             temp = ((short)w) + BY (b);
1376             if (temp <= 0)
1377                 w = 1;
1378             else
1379                 w = (Dimension) temp;
1380 
1381             ASSIGN_MAX (max_h, w);
1382         }
1383     }
1384 
1385     /* Set toc width to the width of the pane */
1386     SET_TEAR_OFF_BOX(toc_height);
1387 
1388     if (Asking (*m_width)) *m_width  = max_w;
1389     if (Asking (*m_height)) *m_height = max_h;
1390 }
1391 
1392 
1393 /*
1394  * Routine used to determine the size of the option menu or to layout
1395  * the option menu given the current size.  The boolean calcMenuDimension
1396  * indicates whether the dimensions of the menu should be recalculated.
1397  * This is true when called from _XmRCThinkAboutSize and false when called
1398  * from AdaptToSize.
1399  *
1400  * This combines the two routines from Motif1.1: think_about_option_size
1401  * and option_layout.  Also new for Motif 1.2, the instigator is considered.
1402  * If the instigator is the label or the cascabebuttongadget, then the
1403  * dimensions are honored if they are large enough.
1404  */
1405 /* ARGSUSED */
1406 static void
LayoutOptionAndSize(register XmRowColumnWidget menu,Dimension * width,Dimension * height,Widget instigator,XtWidgetGeometry * request,int calcMenuDimension)1407 LayoutOptionAndSize (
1408         register XmRowColumnWidget menu,
1409         Dimension *width,
1410         Dimension *height,
1411         Widget instigator,
1412         XtWidgetGeometry *request,
1413 #if NeedWidePrototypes
1414         int calcMenuDimension )
1415 #else
1416         Boolean calcMenuDimension )
1417 #endif /* NeedWidePrototypes */
1418 {
1419    XtWidgetGeometry    *label_box = NULL, *button_box = NULL;
1420    Dimension c_width;
1421    Dimension c_height;
1422    register XmRowColumnWidget p = (XmRowColumnWidget) RC_OptionSubMenu(menu);
1423    XmCascadeButtonGadget cb =
1424       (XmCascadeButtonGadget)XmOptionButtonGadget( (Widget) menu);
1425 
1426    /*
1427     * if this is being destroyed, don't get new dimensions.  This routine
1428     * assumes that cb is valid.
1429     */
1430 
1431    if (menu->core.being_destroyed)
1432    {
1433        if (calcMenuDimension)
1434        {
1435            *width = XtWidth(menu);
1436            *height = XtHeight(menu);
1437        }
1438        return;
1439    }
1440 
1441    /* Find the interesting boxes */
1442 
1443    if (!XtIsManaged(XmOptionLabelGadget( (Widget) menu))) {
1444        button_box = &(RC_Boxes(menu)[0].box);
1445    } else {
1446        label_box = &(RC_Boxes(menu)[0].box);
1447        button_box = &(RC_Boxes(menu)[1].box);
1448    }
1449 
1450 
1451    if (p)
1452    {
1453       c_width = c_height = 0;
1454 
1455       FindLargestOption( p, &c_width, &c_height );
1456 
1457       if (LayoutIsRtoLG(cb))
1458 	c_width += Double(G_HighlightThickness(cb)) + G_ShadowThickness(cb) +
1459 	           LabG_MarginLeft(cb) + Double(MGR_ShadowThickness(p))  -
1460 		   /* magic value */ 2;
1461       else
1462 	c_width += Double(G_HighlightThickness(cb)) + G_ShadowThickness(cb) +
1463 	           LabG_MarginRight(cb) + Double(MGR_ShadowThickness(p))  -
1464 		   /* magic value */ 2;
1465       c_height += Double(G_HighlightThickness(cb)) + LabG_MarginTop(cb)
1466 		 + LabG_MarginBottom(cb);
1467 
1468       /* allow settings in cbg to be honored if greater than best size */
1469       if (instigator == (Widget) cb)
1470       {
1471 	  if ((request->request_mode & CWHeight) &&
1472 	      (request->height > c_height))
1473 	  {
1474 	      c_height = request->height;
1475 	  }
1476 	  if ((request->request_mode & CWWidth) &&
1477 	      (request->width > c_width))
1478 	  {
1479 	      c_width = request->width;
1480 	  }
1481       }
1482       BWidth(button_box) = c_width;
1483       BHeight(button_box) = c_height;
1484   }
1485    else
1486    {
1487       /* Option menu draws a toggle indicator with a childless submenu */
1488       c_width = BWidth(button_box);
1489       c_height = BHeight(button_box);
1490    }
1491 
1492    /* treat separate the case where the label is unmanaged */
1493    if (!XtIsManaged(XmOptionLabelGadget( (Widget) menu))) {
1494 
1495        if (!calcMenuDimension &&  c_height > XtHeight(menu))
1496 	   c_height = XtHeight(menu) - 2*RC_MarginH(menu);
1497 
1498        if (!calcMenuDimension && c_width > XtWidth (menu))
1499 	   c_width = XtWidth(menu) - 2*RC_MarginW(menu);
1500 
1501        BWidth(button_box) = c_width;
1502        BHeight(button_box) = c_height;
1503 
1504        BX(button_box) = RC_MarginW(menu);
1505        BY(button_box) = RC_MarginH(menu);
1506 
1507        if (calcMenuDimension)
1508 	   {
1509 	       *width = c_width + 2*RC_MarginW(menu);
1510 	       *height = c_height + 2*RC_MarginH(menu);
1511 	   }
1512        return ;
1513    }
1514 
1515    if (IsHorizontal(menu))
1516    {
1517       /*
1518        * Set the height to the highest of the two but if calcMenuDimension
1519        * is false, limit it to the size of the option menu
1520        */
1521 
1522       if (BHeight(label_box) > c_height)
1523 	  c_height = BHeight(label_box);
1524 
1525       if (!calcMenuDimension &&  c_height > XtHeight(menu))
1526 	  c_height = XtHeight(menu) - 2*RC_MarginH(menu);
1527 
1528       BHeight(label_box) = c_height;
1529       BHeight(button_box) = c_height;
1530 
1531       /* The label box is placed at... */
1532       /* The button is placed just next to the label */
1533       /* Reverse if RtoL */
1534 
1535       if (LayoutIsRtoLM(menu)) {
1536 	BX(button_box) = RC_MarginW(menu);
1537 	BX(label_box) = BX(button_box) + BWidth(button_box) + RC_Spacing(menu);
1538       } else {
1539 	BX(label_box) = RC_MarginW(menu);
1540 	BX(button_box) = BX(label_box) + BWidth(label_box) + RC_Spacing(menu);
1541       }
1542       BY(label_box) = RC_MarginH(menu);
1543       BY(button_box) = RC_MarginH(menu);
1544 
1545       if (calcMenuDimension)
1546       {
1547 	if (LayoutIsRtoLM(menu))
1548 	  *width = BX(label_box) + BWidth(label_box) + RC_MarginW(menu);
1549 	else
1550 	  *width = BX(button_box) + c_width + RC_MarginW(menu);
1551 	*height = c_height + 2*RC_MarginH(menu);
1552       }
1553    }
1554    else	/* is vertical menu */
1555    {
1556       /*
1557        * Set the height to the highest of the two but if calcMenuDimension
1558        * is false, limit it to the size of the option menu
1559        */
1560       if (BWidth(label_box) > c_width)
1561 	  c_width = BWidth(label_box);
1562 
1563       if (!calcMenuDimension && c_width > XtWidth (menu))
1564 	  c_width = XtWidth(menu) - 2*RC_MarginW(menu);
1565 
1566       BWidth(label_box) = c_width;
1567       BWidth(button_box) = c_width;
1568 
1569       /* The label box is placed at... */
1570       BX(label_box) = RC_MarginW(menu);
1571       BY(label_box) = RC_MarginH(menu);
1572 
1573       /* The button is placed just below the label */
1574       BX(button_box) = RC_MarginW(menu);
1575       BY(button_box) = BY(label_box) + BHeight(label_box) + RC_Spacing(menu);
1576 
1577       if (calcMenuDimension)
1578       {
1579 	  *width = c_width + 2*RC_MarginW(menu);
1580 	  *height = BY(button_box) + c_height + RC_MarginH(menu);
1581       }
1582    }
1583 }
1584 
1585 
1586 void
_XmRCThinkAboutSize(register XmRowColumnWidget m,Dimension * w,Dimension * h,Widget instigator,XtWidgetGeometry * request)1587 _XmRCThinkAboutSize(
1588         register XmRowColumnWidget m,
1589         Dimension *w,
1590         Dimension *h,
1591         Widget instigator,
1592         XtWidgetGeometry *request )
1593 {
1594     if (!RC_ResizeWidth(m))  *w = XtWidth  (m);
1595     if (!RC_ResizeHeight(m)) *h = XtHeight (m);
1596 
1597     if (IsOption(m))
1598 	LayoutOptionAndSize(m, w, h, instigator, request, TRUE);
1599     else if (PackNone (m))
1600         LayoutNone (m, w, h);
1601     else if (PackColumn (m))
1602 	LayoutColumn (m, w, h);
1603     else {
1604 	if (IsVertical (m))
1605 	    LayoutVerticalTight (m, w, h);
1606 	else
1607 	    LayoutHorizontaltight (m, w, h);
1608     }
1609 
1610     if (!RC_ResizeHeight(m) && !RC_ResizeWidth(m))
1611         return;
1612 
1613     ASSIGN_MAX(*w, RESOURCE_MIN_WIDTH);
1614     ASSIGN_MAX(*h, RESOURCE_MIN_HEIGHT);
1615 }
1616 
1617 
1618 
1619 void
_XmRCPreferredSize(XmRowColumnWidget m,Dimension * w,Dimension * h)1620 _XmRCPreferredSize(
1621         XmRowColumnWidget m,
1622         Dimension *w,
1623         Dimension *h )
1624 {
1625    Widget *q;
1626    int i;
1627    Dimension * baselines;
1628    int line_count;
1629    Dimension y;
1630 
1631    if ((!IsOption(m)) && ((PackColumn(m) && (IsVertical(m) ||
1632 					     IsHorizontal(m))) ||
1633 			  (PackTight(m) && IsHorizontal(m))))
1634    {
1635        if ((PackColumn(m) && (IsVertical(m) || IsHorizontal(m))) ||
1636          (PackTight(m) && IsHorizontal(m)))
1637      {
1638       if (*h == 0)
1639       {
1640        ForManagedChildren(m, i, q) /* reset Top and Bottom Margins that were */
1641        {                           /* set for vertical Alignment to work     */
1642           if (XmIsGadget(*q) || XmIsPrimitive(*q))
1643           {
1644             XmBaselineMargins textMargins;
1645 
1646             textMargins.margin_top = SavedMarginTop(*q);
1647             textMargins.margin_bottom = SavedMarginBottom(*q);
1648             _XmRC_SetOrGetTextMargins(*q, XmBASELINE_SET, &textMargins);
1649 
1650           }
1651        }
1652       }
1653      }
1654 
1655    /*
1656     * get array built for both widgets and gadgets layout is based only on
1657     * this array, adjust width margins &  adjust height margins
1658     */
1659      RC_Boxes(m)=
1660        (XmRCKidGeometry)_XmRCGetKidGeo( (Widget) m, NULL, NULL,
1661 				    RC_EntryBorder(m),
1662 				    RC_EntryBorder (m),
1663 				    (IsVertical (m) && RC_DoMarginAdjust (m)),
1664 				    (IsHorizontal (m) &&
1665 				     RC_DoMarginAdjust (m)),
1666 				    RC_HelpPb (m),
1667 				    RC_TearOffControl(m),
1668 				    XmGET_PREFERRED_SIZE);
1669      for (i = 0; RC_Boxes(m) [i].kid != NULL; i++)
1670      {
1671        Widget rc_kid;
1672        XmBaselineMargins textMargins;
1673        XRectangle displayRect;
1674        unsigned char label_type = XmSTRING;
1675        rc_kid = RC_Boxes(m) [i].kid;
1676 
1677        if (XmIsGadget (rc_kid) || XmIsPrimitive (rc_kid))
1678        {
1679 	 XtVaGetValues(rc_kid, XmNlabelType, &label_type, NULL);
1680 
1681 	 if (label_type == XmSTRING)
1682 	 {
1683 	   if (XmIsLabel(rc_kid) || XmIsLabelGadget(rc_kid)) {
1684 	     /* The baseline functions returns the baseline on the current size */
1685 	     /* Since we need the preferred baseline, we need to calculate the y   */
1686 	     /* coordinate on the preferred size and add this in to the baseline */
1687 	     /* returned, after subtracting the y coordinate of the current widget */
1688 	     _XmRC_SetOrGetTextMargins(rc_kid, XmBASELINE_GET, &textMargins);
1689 	     y = (  textMargins.highlight + textMargins.shadow
1690 		  + textMargins.margin_height + textMargins.margin_top
1691 		  + ((  RC_Boxes(m) [i].box.height
1692 		      - textMargins.margin_top
1693 		      - textMargins.margin_bottom
1694 		      - (2 * (  textMargins.margin_height
1695 			      + textMargins.shadow
1696 			      + textMargins.highlight))
1697 		      - textMargins.text_height) / 2));
1698 	     XmWidgetGetDisplayRect(rc_kid, &displayRect);
1699 	   }
1700 	   else {
1701 	     displayRect.y = y = 0;
1702 	   }
1703 
1704 	    if (AlignmentBaselineTop(m) || AlignmentBaselineBottom(m)) {
1705 	      if (XmWidgetGetBaselines(rc_kid, &baselines, &line_count)) {
1706 		if (AlignmentBaselineTop(m))
1707 		    RC_Boxes(m) [i].baseline = baselines[0] - displayRect.y + y;
1708 		else if (AlignmentBaselineBottom(m))
1709 		    RC_Boxes(m) [i].baseline = baselines[line_count - 1] -
1710 		                               displayRect.y + y;
1711 		XtFree((char *)baselines);
1712 	      }
1713 	      else
1714 	      {
1715 		RC_Boxes(m) [i].baseline = 0;
1716 	      }
1717 	    }
1718             RC_Boxes(m) [i].margin_top = 0;
1719             RC_Boxes(m) [i].margin_bottom = 0;
1720           }
1721           else
1722           {
1723             RC_Boxes(m) [i].baseline = 0;
1724             RC_Boxes(m) [i].margin_top = 0;
1725             RC_Boxes(m) [i].margin_bottom = 0;
1726           }
1727         }
1728       }
1729    }
1730    else
1731    {
1732      /*
1733       * get array built for both widgets and gadgets layout is based only on
1734       * this array, adjust width margins &  adjust height margins
1735       */
1736       RC_Boxes(m)=
1737        (XmRCKidGeometry)_XmRCGetKidGeo( (Widget) m, NULL, NULL,
1738 				    RC_EntryBorder(m),
1739 				    RC_EntryBorder (m),
1740 				    (IsVertical (m) && RC_DoMarginAdjust (m)),
1741 				    (IsHorizontal (m) &&
1742 				     RC_DoMarginAdjust (m)),
1743 				    RC_HelpPb (m),
1744 				    RC_TearOffControl(m),
1745 				    XmGET_PREFERRED_SIZE);
1746    }
1747 
1748    _XmRCThinkAboutSize (m, w, h, NULL, NULL);
1749 
1750    XtFree ((char *) RC_Boxes(m));
1751 }
1752 
1753 /*
1754  * Layout the row column widget to fit it's current size; ignore possible
1755  * non-fitting of the entries into a too small row column widget.
1756  *
1757  * Don't forget the instigator.
1758  */
1759 void
_XmRCAdaptToSize(XmRowColumnWidget m,Widget instigator,XtWidgetGeometry * request)1760 _XmRCAdaptToSize(
1761         XmRowColumnWidget m,
1762         Widget instigator,
1763         XtWidgetGeometry *request )
1764 {
1765    Dimension w = XtWidth (m);
1766    Dimension h = XtHeight (m);
1767    Dimension instigator_w = 0 ;
1768    Dimension instigator_h = 0;
1769    short i;
1770    Widget *q;
1771 
1772    if ((!IsOption(m)) && ((PackColumn(m) && (IsVertical(m) || IsHorizontal(m))) ||
1773        (PackTight(m) && IsHorizontal(m))))
1774    {
1775      ForManagedChildren(m, i, q)
1776      {
1777         if (XmIsGadget (*q) || XmIsPrimitive (*q))
1778         {
1779           XmBaselineMargins textMargins;
1780 
1781           textMargins.margin_top = SavedMarginTop(*q);
1782           textMargins.margin_bottom = SavedMarginBottom(*q);
1783           _XmRC_SetOrGetTextMargins(*q, XmBASELINE_SET, &textMargins);
1784         }
1785      }
1786    }
1787    /*
1788     * get array built for both widgets and gadgets,
1789     * layout is based only on this array,
1790     * adjust width margins and  adjust height margins
1791     */
1792    RC_Boxes(m) =
1793        (XmRCKidGeometry)_XmRCGetKidGeo( (Widget) m, instigator, request,
1794 				       RC_EntryBorder(m),
1795 				       RC_EntryBorder (m),
1796 				       (IsVertical (m) &&
1797 					RC_DoMarginAdjust (m)),
1798 				       (IsHorizontal (m) &&
1799 					RC_DoMarginAdjust (m)),
1800 				       RC_HelpPb (m),
1801 				       RC_TearOffControl(m),
1802 				       XmGET_PREFERRED_SIZE);
1803 
1804    if ((!IsOption(m)) && ((PackColumn(m) && (IsVertical(m) ||
1805 					     IsHorizontal(m))) ||
1806 			  (PackTight(m) && IsHorizontal(m))))
1807    {
1808      for (i = 0; RC_Boxes(m) [i].kid != NULL; i++)
1809      {
1810        if (XmIsGadget(RC_Boxes(m) [i].kid) || XmIsPrimitive(RC_Boxes(m) [i].kid))
1811        {
1812 	 unsigned char label_type = XmSTRING;
1813 	 RectObj ro = (RectObj) RC_Boxes(m) [i].kid;
1814 
1815 	 if (XtHeight (RC_Boxes(m) [i].kid) != RC_Boxes(m) [i].box.height)
1816          {
1817 	   XmeConfigureObject( (Widget) ro, ro->rectangle.x, ro->rectangle.y,
1818 			      ro->rectangle.width, RC_Boxes(m) [i].box.height,
1819 			      ro->rectangle.border_width);
1820 	 }
1821 
1822 	 XtVaGetValues(RC_Boxes(m) [i].kid, XmNlabelType, &label_type, NULL);
1823 
1824 	 if (label_type == XmSTRING &&
1825 	     (AlignmentBaselineTop(m) || AlignmentBaselineBottom(m)))
1826 	 {
1827 	   Dimension *baselines;
1828 	   int line_count;
1829 
1830 	   XmWidgetGetBaselines(RC_Boxes(m) [i].kid, &baselines, &line_count);
1831 	   if (AlignmentBaselineTop(m))
1832 	     RC_Boxes(m) [i].baseline = baselines[0];
1833 	   else if (AlignmentBaselineBottom(m))
1834 	     RC_Boxes(m) [i].baseline = baselines[line_count - 1];
1835 	   XtFree((char *)baselines);
1836 	 }
1837 	 else
1838 	   RC_Boxes(m) [i].baseline = 0;
1839 
1840        }
1841      }
1842    }
1843 
1844    if (IsOption(m))
1845        LayoutOptionAndSize (m, &w, &h, instigator, request, FALSE);
1846    else if (PackColumn (m))
1847        LayoutColumn (m, &w, &h);
1848    else if (!PackNone (m)) {
1849        if (IsVertical (m))
1850 	   LayoutVerticalTight (m, &w, &h);
1851        else
1852 	   LayoutHorizontaltight (m, &w, &h);
1853    }
1854 
1855    if ((!IsOption(m)) && ((PackColumn(m) && (IsVertical(m) || IsHorizontal(m))) ||
1856        (PackTight(m) && IsHorizontal(m))))
1857    {
1858      for (i = 0; RC_Boxes(m) [i].kid != NULL; i++)
1859      {
1860        if (XmIsGadget(RC_Boxes(m) [i].kid) || XmIsPrimitive(RC_Boxes(m) [i].kid))
1861        {
1862          XmBaselineMargins textMargins;
1863 
1864          textMargins.margin_top = RC_Boxes(m) [i].margin_top;
1865          textMargins.margin_bottom = RC_Boxes(m) [i].margin_bottom;
1866          _XmRC_SetOrGetTextMargins(RC_Boxes(m) [i].kid, XmBASELINE_SET, &textMargins);
1867 
1868        }
1869      }
1870    }
1871 
1872    if (instigator)
1873      {
1874        /* CR 5419: Save the original instigator dimensions */
1875        instigator_w = XtWidth(instigator);
1876        instigator_h = XtHeight(instigator);
1877      }
1878 
1879    _XmRCSetKidGeo ((XmRCKidGeometry)RC_Boxes(m), instigator);
1880 
1881    /*
1882    ** Hack alert!
1883    ** This is special code to enforce that the CBG in an option menu is
1884    ** kept correctly-sized when the items in this pulldown, associated with
1885    ** that cascade, change. There is no protocol for communicating this
1886    ** information nor any mechanism for adapting one; so we make the size
1887    ** request ourselves, here. The point is not that we are setting to the
1888    ** correct size so much as that the cascade's size is being adjusted after
1889    ** the menu size is fixed. calc_CBG_dims is probably being called an extra
1890    ** time to figure out the real size. This is not a frequent case.
1891     *
1892     * Do not call this routine below if this call was initiated by a geometry
1893     * request from an option menu's label or cascade button.  In that case,
1894     * the geometry has already been taken care of and must not be meddled
1895     * with or it will reset some values incorrectly.
1896     */
1897    if (!IsOption(m) || !instigator ||
1898        !((instigator == RC_Boxes(m)[0].kid) ||
1899 	 (instigator == RC_Boxes(m)[1].kid)))
1900    {
1901        _XmRC_CheckAndSetOptionCascade(m);
1902    }
1903 
1904 /* The old geometry management took care of resizing the instigator if
1905    XtGeometryYes was returned even if core.width and core.height had
1906    not changed. However this is not the case with the new geometry
1907    management. Therefore if margins have changed but not the core
1908    width and height label's resize needs to be called to calculate
1909    the x & y coordinates for the label text, with the new margins. */
1910 
1911    if ((instigator) &&
1912        (instigator_w == XtWidth(instigator)) &&
1913        (instigator_h == XtHeight(instigator)) &&
1914        (XmIsLabel(instigator) || XmIsLabelGadget(instigator)))
1915    {
1916      WidgetClass wc = XtClass(instigator);
1917      XtWidgetProc resize;
1918 
1919      _XmProcessLock();
1920      resize = wc->core_class.resize;
1921      _XmProcessUnlock();
1922      (*resize) ((Widget) instigator);
1923    }
1924    /* Patch submitted by Kevin B. Hendrix of Java-Linux project. */
1925    if (RC_Boxes(m))
1926    {
1927      XtFree ( (char *) RC_Boxes(m));
1928      RC_Boxes(m) = NULL;
1929    }
1930 }
1931 
1932 
1933 void
_XmRC_SetOrGetTextMargins(Widget wid,unsigned int op,XmBaselineMargins * textMargins)1934 _XmRC_SetOrGetTextMargins(
1935         Widget wid,
1936 #if NeedWidePrototypes
1937         unsigned int op,
1938 #else
1939         unsigned char op,
1940 #endif /* NeedWidePrototypes */
1941         XmBaselineMargins *textMargins )
1942 {
1943   WidgetClass wc = XtClass(wid);
1944 
1945   if (op == XmBASELINE_GET) {
1946     /* in case the class does not have this procedure */
1947     bzero((void *) textMargins, sizeof(XmBaselineMargins));
1948   }
1949 
1950   textMargins->get_or_set = op;
1951 
1952   if (XmIsGadget(wid))
1953     {
1954       XmGadgetClassExt     *wcePtr;
1955 
1956       wcePtr = _XmGetGadgetClassExtPtr(wc, NULLQUARK);
1957       if (*wcePtr && (*wcePtr)->version == XmGadgetClassExtVersion &&
1958 	  (*wcePtr)->widget_margins)
1959 	(*((*wcePtr)->widget_margins)) (wid, textMargins) ;
1960     }
1961   else if (XmIsPrimitive(wid))
1962     {
1963       XmPrimitiveClassExt  *wcePtr;
1964 
1965       wcePtr = _XmGetPrimitiveClassExtPtr(wc, NULLQUARK);
1966       if (*wcePtr && (*wcePtr)->widget_margins)
1967 	(*((*wcePtr)->widget_margins)) (wid, textMargins) ;
1968   }
1969 }
1970 
1971 
1972 /****************************************************************
1973  * Assemble a kid box for each child widget and gadget, fill in data about
1974  *   each widget and optionally set up uniform border widths.
1975  * Returns a list of records, last one has a 'kid' field of NULL.  This memory
1976  *   for this list should eventually be freed with a call to XtFree().
1977  ****************/
1978 /*ARGSUSED*/
1979 XmRCKidGeometry
_XmRCGetKidGeo(Widget wid,Widget instigator,XtWidgetGeometry * request,int uniform_border,int border,int uniform_width_margins,int uniform_height_margins,Widget help,Widget toc,int geo_type)1980 _XmRCGetKidGeo(
1981         Widget wid,                     /* Widget w/ children. */
1982         Widget instigator,              /* May point to a child who */
1983         XtWidgetGeometry *request,      /*   is asking to change. */
1984         int uniform_border,             /* T/F, enforce it. */
1985 #if NeedWidePrototypes
1986         int border,
1987 #else
1988         Dimension border,               /* Value to use if enforcing.*/
1989 #endif /* NeedWidePrototypes */
1990         int uniform_width_margins,      /* unused, T/F, enforce it. */
1991         int uniform_height_margins,     /* unused, T/F, enforce it. */
1992         Widget help,                    /* May point to a help kid. */
1993 	Widget toc,			/* May point to tear_off_control kid. */
1994         int geo_type )                  /* Actual or preferred. */
1995 {
1996     CompositeWidget	c = (CompositeWidget) wid ;
1997     XmRCKidGeometry	geo ;
1998     Widget		kidWid ;
1999     int			i ;
2000     int			j = 0 ;
2001     Boolean		helpFound = FALSE ;
2002     Boolean		tocFound;
2003 
2004     tocFound = (toc && XtIsManaged(toc)) & 0x1;
2005 
2006     geo = (XmRCKidGeometry) XtMalloc((_XmGeoCount_kids(c) + 1 + tocFound) *
2007        sizeof (XmRCKidGeometryRec));
2008 
2009     i = 0;
2010 
2011     if (tocFound)
2012     {
2013        geo[j].kid = toc ;
2014 
2015        _XmGeoLoadValues( toc, geo_type, instigator, request, &(geo[j].box));
2016 
2017        geo[j].margin_top = 0;
2018        geo[j].margin_bottom = 0;
2019        geo[j].baseline = 0;
2020 
2021 
2022        if (uniform_border)     /* if asked override border */
2023        {
2024 	  geo[j].box.border_width = border ;
2025        }
2026        j++ ;
2027     }
2028 
2029     /* load all managed kids */
2030     for( ; i < c->composite.num_children ; i++    )
2031     {
2032        kidWid = c->composite.children[i] ;
2033        if (XtIsManaged( kidWid))
2034        {
2035 	  if(    kidWid == help    )
2036           {  /* Save to put help widget at the end of the widget list.*/
2037              helpFound = TRUE ;
2038           }
2039           else
2040 	  {
2041 	     geo[j].kid = kidWid ;
2042 
2043 	     _XmGeoLoadValues( kidWid, geo_type, instigator, request,
2044 							       &(geo[j].box)) ;
2045              geo[j].margin_top = 0;
2046              geo[j].margin_bottom = 0;
2047              geo[j].baseline = 0;
2048 
2049 	     /* Fix for CR 5598 - If the child is a separator widget
2050 		or gadget, set the width in the geo box to 0.  This
2051 		will take the separator out of the width consideration. */
2052 	     /* Fix for 8131: only does that to Separators when packing
2053                if not none: this is the only time when it matters, plus
2054                pack_none does not correct the setting to 0 and the
2055                rowcolumn dies in protocol error later when trying to
2056                configure the separator to its 0 box.width or height */
2057 
2058 	     if ((XmIsSeparator(kidWid) || XmIsSeparatorGadget(kidWid)) &&
2059 		 (RC_Packing (c) != XmPACK_NONE)) {
2060 		 unsigned char orientation;
2061 		 Arg args[1];
2062 
2063 		 XtSetArg(args[0], XmNorientation, &orientation);
2064 		 XtGetValues(kidWid, args, 1);
2065 
2066 		 if (orientation == XmHORIZONTAL)
2067 		     geo[j].box.width = 0;
2068 		 else
2069 		     geo[j].box.height = 0;
2070              }
2071 	     /* End fix for CR 5598 and 8131 */
2072 
2073 
2074 	     if (uniform_border)     /* if asked override border */
2075 	     {
2076 		geo[j].box.border_width = border ;
2077 	     }
2078 	     j++ ;
2079 	  }
2080        }
2081     }
2082 
2083     if (helpFound)                 /* put help guy into list */
2084     {
2085         geo[j].kid = help ;
2086 
2087         _XmGeoLoadValues( help, geo_type, instigator, request, &(geo[j].box)) ;
2088 
2089         geo[j].margin_top = 0;
2090         geo[j].margin_bottom = 0;
2091         geo[j].baseline = 0;
2092 
2093 
2094         if (uniform_border)         /* if asked override border */
2095         {
2096 	   geo[j].box.border_width = border ;
2097 	}
2098         j++ ;
2099     }
2100     geo[j].kid = NULL ;                /* signal end of list */
2101 
2102     return( geo) ;
2103 }
2104 
2105 
2106 /**************************************************************** ARGSUSED
2107  * Take the kid geometry array and change each kid to match them.
2108  *   remember not to do the resize of the instigator.
2109  * The kid geometry "kg" is assumed to be fully specified.
2110  ****************/
2111 void
_XmRCSetKidGeo(XmRCKidGeometry kg,Widget instigator)2112 _XmRCSetKidGeo(
2113         XmRCKidGeometry kg,
2114         Widget instigator )
2115 {
2116     Widget          w ;
2117     XtWidgetGeometry * b ;
2118     int             i ;
2119 /****************/
2120 
2121     for(i=0 ; kg[i].kid != NULL ; i++) {
2122         w = (Widget) kg[i].kid ;
2123         b = &(kg[i].box) ;
2124 
2125 	if(    w != instigator    ) {
2126 	    XmeConfigureObject(w, b->x, b->y, b->width, b->height,
2127 			       b->border_width) ;
2128 	} else {
2129 	    XtX( w) = b->x ;
2130 	    XtY( w) = b->y ;
2131 	    XtWidth( w) = b->width ;
2132 	    XtHeight( w) = b->height ;
2133 	    XtBorderWidth( w) = b->border_width ;
2134 	}
2135     }
2136     return ;
2137 }
2138 
2139 
2140 
2141 
2142 static void
GetMenuKidMargins(XmRowColumnWidget m,Dimension * width,Dimension * height,Dimension * left,Dimension * right,Dimension * top,Dimension * bottom)2143 GetMenuKidMargins(
2144         XmRowColumnWidget m,
2145         Dimension *width,
2146         Dimension *height,
2147         Dimension *left,
2148         Dimension *right,
2149         Dimension *top,
2150         Dimension *bottom )
2151 {
2152    register int i;
2153    Widget *q;
2154 
2155    *width = *height = *left = *right = *top = *bottom = 0;
2156 
2157    ForManagedChildren(m, i, q) {
2158 	if (XmIsLabelGadget(*q)) {
2159 	    ASSIGN_MAX(*width, LabG_MarginWidth  (*q));
2160 	    ASSIGN_MAX(*height, LabG_MarginHeight (*q));
2161 	    ASSIGN_MAX(*left, LabG_MarginLeft   (*q));
2162 	    ASSIGN_MAX(*right, LabG_MarginRight  (*q));
2163 	} else if (XmIsLabel(*q)) {
2164 	    ASSIGN_MAX(*width, Lab_MarginWidth  (*q));
2165 	    ASSIGN_MAX(*height, Lab_MarginHeight (*q));
2166 	    ASSIGN_MAX(*left, Lab_MarginLeft   (*q));
2167 	    ASSIGN_MAX(*right, Lab_MarginRight  (*q));
2168 	}
2169     }
2170 
2171     ForManagedChildren (m, i, q)
2172     {
2173       if (XmIsLabel(*q) || XmIsLabelGadget(*q))
2174       {
2175        if (SavedMarginTop(*q) > *top)
2176            *top = SavedMarginTop(*q);
2177        if (SavedMarginBottom(*q) > *bottom)
2178            *bottom = SavedMarginBottom(*q);
2179       }
2180     }
2181 }
2182 
2183 
2184 /*
2185  * Toggle buttons have this thingy hanging off the left of the
2186  * widget, before the text.  This dimension is known as the MarginLeft.
2187  * Pulldown's have hot spots in the MarginRight, accelerators go in the
2188  * marginRight also.
2189  *
2190  * For generality's sake we should insure that all
2191  * of the current label subclass widgets in the menu have the
2192  * margins set to the same value.
2193  */
2194 void
_XmRCDoMarginAdjustment(XmRowColumnWidget m)2195 _XmRCDoMarginAdjustment(
2196         XmRowColumnWidget m )
2197 {
2198     register Widget *p;
2199     register int i;
2200     Dimension m_w, m_h, m_l, m_r, m_t, m_b;
2201     Dimension w, h;
2202 
2203     if ((!RC_DoMarginAdjust (m)) || (IsOption(m)))
2204     {
2205       ForManagedChildren (m, i, p)
2206       {
2207         if (XmIsGadget(*p) || XmIsPrimitive(*p))
2208         {
2209 
2210           XmBaselineMargins textMargins;
2211 
2212           _XmRC_SetOrGetTextMargins(*p, XmBASELINE_GET, &textMargins);
2213           SavedMarginTop(*p) = textMargins.margin_top;
2214           SavedMarginBottom(*p) = textMargins.margin_bottom;
2215 
2216         }
2217        }
2218        return;
2219     }
2220     /*
2221      * this should almost be part
2222      * of the layout process, except this requires a setvalue not a resize...
2223      */
2224 
2225     GetMenuKidMargins (m, &m_w, &m_h, &m_l, &m_r, &m_t, &m_b);
2226 
2227     ForManagedChildren (m, i, p)
2228     {
2229         if (XmIsLabelGadget(*p))
2230         {
2231             XmLabelGadget q;
2232 	    XmLabelGCacheObjPart localCache;
2233             /*
2234              * If in a popup or pulldown pane,
2235              * don't do labels; i.e. only do buttons.
2236              */
2237             if (((*p)->core.widget_class == xmLabelGadgetClass) &&
2238                 (IsPulldown(m) || IsPopup(m)))
2239                 continue;
2240 
2241             w = XtWidth  (*p);
2242             h = XtHeight (*p);
2243 
2244             q = (XmLabelGadget) (*p);
2245 
2246             if (IsVertical (m))
2247             {
2248 	       _XmQualifyLabelLocalCache(&localCache, q);
2249 
2250 	       /* change horiz margins to  be uniform */
2251 	       if (LabG_MarginLeft(q) != m_l)
2252 	       {
2253 		  w += m_l - LabG_MarginLeft(q);
2254 		  _XmAssignLabG_MarginLeft_r((&localCache), m_l);
2255 	       }
2256 
2257 	       if (LabG_MarginRight(q) != m_r)
2258 	       {
2259 		  w += m_r - LabG_MarginRight(q);
2260 		  _XmAssignLabG_MarginRight_r((&localCache), m_r);
2261 	       }
2262 
2263 	       if (LabG_MarginWidth(q) != m_w)
2264 	       {
2265 		  w += m_w - LabG_MarginWidth(q);
2266 		  _XmAssignLabG_MarginWidth_r((&localCache), m_w);
2267 	       }
2268        	       _XmReCacheLabG_r(&localCache, q);
2269 
2270 	       if (q->rectangle.width != w)
2271 	       {
2272 		  XmeConfigureObject( (Widget) q, q->rectangle.x,
2273                                         q->rectangle.y, w, q->rectangle.height,
2274                                                     q->rectangle.border_width);
2275 	       }
2276             }
2277 
2278             if (!IsVertical (m) || PackColumn(m))
2279             {
2280 	       _XmQualifyLabelLocalCache(&localCache, q);
2281 
2282 	       /* change vert margins */
2283 	       if (LabG_MarginTop(q) != m_t)
2284 	       {
2285 		  h += m_t - LabG_MarginTop(q);
2286 		  _XmAssignLabG_MarginTop_r((&localCache), m_t);
2287 	       }
2288 
2289 	       if (LabG_MarginBottom(q) != m_b)
2290 	       {
2291 		  h += m_b - LabG_MarginBottom(q);
2292 		  _XmAssignLabG_MarginBottom_r((&localCache), m_b);
2293 	       }
2294 
2295 	       if (LabG_MarginHeight(q) != m_h)
2296 	       {
2297 		  h += m_h - LabG_MarginHeight(q);
2298 		  _XmAssignLabG_MarginHeight_r((&localCache), m_h);
2299 	       }
2300 
2301 	       _XmReCacheLabG_r(&localCache, q);
2302 
2303 	       if (q->rectangle.height != h)
2304 	       {
2305 		  XmeConfigureObject( (Widget) q, q->rectangle.x,
2306                                          q->rectangle.y, q->rectangle.width, h,
2307                                                     q->rectangle.border_width);
2308 	       }
2309                SavedMarginTop(*p) = LabG_MarginTop (q);
2310                SavedMarginBottom(*p) = LabG_MarginBottom (q);
2311             }
2312 	 }
2313         else if (XmIsLabel(*p))
2314         {
2315             XmLabelWidget lw;
2316             /*
2317              * If in a popup or pulldown pane,
2318              * don't do labels; i.e. only do buttons.
2319              */
2320             if (((*p)->core.widget_class == xmLabelWidgetClass) &&
2321                 (IsPulldown(m) || IsPopup(m)))
2322                 continue;
2323 
2324             w = XtWidth  (*p);
2325             h = XtHeight (*p);
2326 
2327             lw = (XmLabelWidget) (*p);
2328 
2329             if (IsVertical (m)) /* change horiz margins to */
2330             {                   /* be uniform */
2331                ChangeMargin (Lab_MarginLeft  (lw), m_l, w);
2332                ChangeMargin (Lab_MarginRight (lw), m_r, w);
2333                ChangeMargin (Lab_MarginWidth (lw), m_w, w);
2334 
2335                if (XtWidth (lw) != w)
2336                {
2337                     XmeConfigureObject( (Widget) lw, lw->core.x, lw->core.y,
2338                                     w, lw->core.height, lw->core.border_width);
2339                }
2340             }
2341 
2342             if (!IsVertical (m) || PackColumn(m))      /* change vert margins */
2343             {
2344                 ChangeMargin (Lab_MarginTop (lw), m_t, h);
2345                 ChangeMargin (Lab_MarginBottom (lw), m_b, h);
2346                 ChangeMarginDouble (Lab_MarginHeight (lw), m_h, h);
2347 
2348                 if (XtHeight (lw) != h)
2349                 {
2350                     XmeConfigureObject( (Widget) lw, lw->core.x,lw->core.y,
2351                                      lw->core.width, h, lw->core.border_width);
2352                 }
2353                 SavedMarginTop(*p) = Lab_MarginTop (lw);
2354                 SavedMarginBottom(*p) = Lab_MarginBottom (lw);
2355             }
2356         }
2357     }
2358 }
2359