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