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 #ifdef REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$XConsortium: GeoUtils.c /main/13 1996/08/15 17:11:25 pascale $"
26 #endif
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33
34 #ifndef X_NOT_STDC_ENV
35 #include <stdlib.h>
36 #endif
37 #include "XmI.h"
38 #include "GeoUtilsI.h"
39 #include "GMUtilsI.h"
40
41
42 /******** Static Function Declarations ********/
43
44 static XtGeometryResult QueryAnyPolicy(
45 XmGeoMatrix geoSpec,
46 XtWidgetGeometry *parentRequestRtn) ;
47 static XtGeometryResult QueryGrowPolicy(
48 XmGeoMatrix geoSpec,
49 XtWidgetGeometry *parentRequestRtn) ;
50 static XtGeometryResult QueryNonePolicy(
51 XmGeoMatrix geoSpec,
52 XtWidgetGeometry *parentRequestRtn) ;
53 static Dimension _XmGeoStretchVertical(
54 XmGeoMatrix geoSpec,
55 #if NeedWidePrototypes
56 int actualH,
57 int desiredH) ;
58 #else
59 Dimension actualH,
60 Dimension desiredH) ;
61 #endif /* NeedWidePrototypes */
62 static Dimension _XmGeoFillVertical(
63 XmGeoMatrix geoSpec,
64 #if NeedWidePrototypes
65 int actualH,
66 int desiredH) ;
67 #else
68 Dimension actualH,
69 Dimension desiredH) ;
70 #endif /* NeedWidePrototypes */
71 static void _XmGeoCalcFill(
72 #if NeedWidePrototypes
73 int fillSpace,
74 int margin,
75 #else
76 Dimension fillSpace,
77 Dimension margin,
78 #endif /* NeedWidePrototypes */
79 unsigned int numBoxes,
80 #if NeedWidePrototypes
81 int endSpec,
82 int betweenSpec,
83 #else
84 Dimension endSpec,
85 Dimension betweenSpec,
86 #endif /* NeedWidePrototypes */
87 Dimension *pEndSpace,
88 Dimension *pBetweenSpace) ;
89 static int boxWidthCompare(
90 XmConst void *boxPtr1,
91 XmConst void *boxPtr2) ;
92 static void FitBoxesAveraging(
93 XmKidGeometry rowPtr,
94 unsigned int numBoxes,
95 #if NeedWidePrototypes
96 int boxWidth,
97 #else
98 Dimension boxWidth,
99 #endif /* NeedWidePrototypes */
100 int amtOffset) ;
101 static void FitBoxesProportional(
102 XmKidGeometry rowPtr,
103 unsigned int numBoxes,
104 #if NeedWidePrototypes
105 int boxWidth,
106 #else
107 Dimension boxWidth,
108 #endif /* NeedWidePrototypes */
109 int amtOffset) ;
110 static void SegmentFill(
111 XmKidGeometry rowBoxes,
112 unsigned int numBoxes,
113 XmGeoRowLayout layoutPtr,
114 #if NeedWidePrototypes
115 int x,
116 int width,
117 int marginW,
118 int endX,
119 int maxX,
120 int endSpace,
121 int betweenSpace) ;
122 #else
123 Position x,
124 Dimension width,
125 Dimension marginW,
126 Position endX,
127 Position maxX,
128 Dimension endSpace,
129 Dimension betweenSpace) ;
130 #endif /* NeedWidePrototypes */
131 static Position _XmGeoLayoutWrap(
132 XmKidGeometry rowPtr,
133 XmGeoRowLayout layoutPtr,
134 #if NeedWidePrototypes
135 int x,
136 int y,
137 int endSpace,
138 int betweenSpace,
139 int maxX,
140 int width,
141 int marginW) ;
142 #else
143 Position x,
144 Position y,
145 Dimension endSpace,
146 Dimension betweenSpace,
147 Position maxX,
148 Dimension width,
149 Dimension marginW) ;
150 #endif /* NeedWidePrototypes */
151 static Position _XmGeoLayoutSimple(
152 XmKidGeometry rowPtr,
153 XmGeoRowLayout layoutPtr,
154 #if NeedWidePrototypes
155 int x,
156 int y,
157 int maxX,
158 int endSpace,
159 int betweenSpace) ;
160 #else
161 Position x,
162 Position y,
163 Position maxX,
164 Dimension endSpace,
165 Dimension betweenSpace) ;
166 #endif /* NeedWidePrototypes */
167 static Position _XmGeoArrangeList(
168 XmKidGeometry rowBoxes,
169 XmGeoRowLayout layoutPtr,
170 #if NeedWidePrototypes
171 int x,
172 int y,
173 int width,
174 int marginW,
175 int marginH) ;
176 #else
177 Position x,
178 Position y,
179 Dimension width,
180 Dimension marginW,
181 Dimension marginH) ;
182 #endif /* NeedWidePrototypes */
183
184 /******** End Static Function Declarations ********/
185
186 /****************************************************************/
187
188
189 #ifdef DEBUG_GEOUTILS
190
191 void PrintBox( char * hdr, XmKidGeometry box) ;
192 void PrintList( char * hdr, XmKidGeometry listPtr) ;
193 void PrintMatrix( char * hdr, XmGeoMatrix spec) ;
194
195 #endif /* DEBUG_GEOUTILS */
196
197
198 /****************************************************************/
199 XtGeometryResult
_XmHandleQueryGeometry(Widget widget,XtWidgetGeometry * intended,XtWidgetGeometry * desired,unsigned int resize_policy,XmGeoCreateProc createMatrix)200 _XmHandleQueryGeometry(
201 Widget widget,
202 XtWidgetGeometry *intended,
203 XtWidgetGeometry *desired,
204 #if NeedWidePrototypes
205 unsigned int resize_policy,
206 #else
207 unsigned char resize_policy,
208 #endif /* NeedWidePrototypes */
209 XmGeoCreateProc createMatrix)
210 {
211 Dimension width = 0 ;
212 Dimension height = 0 ;
213 XmGeoMatrix geoSpec ;
214
215 /* first determine what is the desired size, using the resize_policy. */
216 if (resize_policy == XmRESIZE_NONE) {
217 desired->width = XtWidth(widget) ;
218 desired->height = XtHeight(widget) ;
219 } else {
220 if (GMode( intended) & CWWidth) width = intended->width;
221 if (GMode( intended) & CWHeight) height = intended->height;
222
223 geoSpec = (*createMatrix)( widget, NULL, NULL) ;
224 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
225 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0,
226 &width, &height) ;
227 _XmGeoMatrixFree( geoSpec) ;
228 if ((resize_policy == XmRESIZE_GROW) &&
229 ((width < XtWidth(widget)) ||
230 (height < XtHeight(widget)))) {
231 desired->width = XtWidth(widget) ;
232 desired->height = XtHeight(widget) ;
233 } else {
234 desired->width = width ;
235 desired->height = height ;
236 }
237 }
238
239 /* deal with user initial size setting */
240 if (!XtIsRealized(widget)) {
241 if (XtWidth(widget) != 0) desired->width = XtWidth(widget) ;
242 if (XtHeight(widget) != 0) desired->height = XtHeight(widget) ;
243 }
244
245 return XmeReplyToQueryGeometry(widget, intended, desired) ;
246 }
247
248
249 /****************************************************************/
250 XtGeometryResult
_XmHandleGeometryManager(Widget wid,Widget instigator,XtWidgetGeometry * desired,XtWidgetGeometry * allowed,unsigned int policy,XmGeoMatrix * cachePtr,XmGeoCreateProc createMatrix)251 _XmHandleGeometryManager(
252 Widget wid,
253 Widget instigator,
254 XtWidgetGeometry *desired,
255 XtWidgetGeometry *allowed,
256 #if NeedWidePrototypes
257 unsigned int policy,
258 #else
259 unsigned char policy,
260 #endif /* NeedWidePrototypes */
261 XmGeoMatrix *cachePtr,
262 XmGeoCreateProc createMatrix)
263 {
264 XmGeoMatrix geoSpec ;
265 XtWidgetGeometry parentRequest ;
266 XtGeometryResult queryResult ;
267 XtGeometryResult result ;
268 /****************/
269
270 if( !cachePtr )
271 {
272 /* Almost replies are not entertained unless caching is supported.
273 */
274 allowed = NULL ;
275 }
276 else
277 { geoSpec = *cachePtr ;
278
279 if( geoSpec )
280 {
281 if( (geoSpec->composite == wid)
282 && (geoSpec->instigator == instigator)
283 && _XmGeometryEqual( instigator, geoSpec->in_layout, desired) )
284 {
285 /* This is a successive geometry request which matches the
286 * cached geometry record.
287 */
288 if( GMode( desired) & XtCWQueryOnly )
289 { return( XtGeometryYes) ;
290 }
291 else
292 { /* If we get here, we should have already verified that
293 * the current layout is acceptable to the parent, so
294 * we will ignore the result of the request.
295 */
296 if( geoSpec->parent_request.request_mode )
297 {
298 geoSpec->parent_request.request_mode &= ~XtCWQueryOnly ;
299
300 XtMakeGeometryRequest( wid, &geoSpec->parent_request,
301 NULL) ;
302 }
303 _XmGeoMatrixSet( geoSpec) ;
304
305 _XmGeoMatrixFree( geoSpec) ;
306 *cachePtr = NULL ;
307
308 return( XtGeometryYes) ;
309 }
310 }
311 else
312 { /* Cached geometry is different than current request, so clear
313 * existing cache record and allow request to be processed.
314 */
315 _XmGeoMatrixFree( geoSpec) ;
316 *cachePtr = NULL ;
317 }
318 }
319 }
320 /* Get box list and arrange boxes according to policy.
321 */
322 geoSpec = (*createMatrix)( wid, instigator, desired) ;
323
324 if( geoSpec->no_geo_request
325 && (*geoSpec->no_geo_request)( geoSpec) )
326 {
327 _XmGeoMatrixFree( geoSpec) ;
328 return( XtGeometryNo) ;
329 }
330
331 /* The following Query routines only respond with XtGeometryYes or
332 * XtGeometryNo. All requests made to the parent are strictly
333 * queries.
334 * A return value (from these routines!) of XtGeometryNo means that
335 * the composite widget would need to change size in order to
336 * entertain the child's request, and that the parent said "no"
337 * to the request. A XtGeometryNo leaves no alternatives to the
338 * child's geometry request.
339 * A return value of XtGeometryYes means that either the composite
340 * widget does not need to change size to entertain the child's
341 * request, or that negotiation with the parent yielded a viable
342 * geometry layout. If the composite widget does not need to
343 * change size, then request_mode field of the returned geometry
344 * structure will contain zero. Otherwise, the returned geometry
345 * structure will contain a request which is guaranteed to be
346 * accepted by a subsequent request to the parent.
347 * A return value of XtGeometryYes always loads the return geometry
348 * structure with valid data.
349 */
350 switch( policy )
351 {
352 case XmRESIZE_GROW:
353 { queryResult = QueryGrowPolicy( geoSpec, &parentRequest) ;
354 break;
355 }
356 case XmRESIZE_NONE:
357 { queryResult = QueryNonePolicy( geoSpec, &parentRequest) ;
358 break ;
359 }
360 case XmRESIZE_ANY:
361 default:
362 { queryResult = QueryAnyPolicy( geoSpec, &parentRequest) ;
363 break ;
364 }
365 }
366 result = XtGeometryNo ; /* Setup default response. */
367
368 /* If parent replies XtGeometryYes, then build appropriate reply for
369 * instigator. Otherwise, it is not reasonable to try to find a child
370 * size which would result in an acceptable overall size, so just say no.
371 */
372 if( queryResult == XtGeometryYes )
373 {
374 if( _XmGeoReplyYes( instigator, desired, geoSpec->in_layout) )
375 {
376 /* Reply Yes since desired geometry is same as the
377 * instigator geometry in this layout.
378 */
379 if( GMode( desired) & XtCWQueryOnly )
380 {
381 geoSpec->parent_request = parentRequest ;
382 result = XtGeometryYes ;
383 }
384 else
385 { /* Don't need almost reply and this is not a query, so do it!
386 */
387 if( parentRequest.request_mode )
388 {
389 /* The geometry request in parentRequest has already
390 * been tested by a query to the parent, so should
391 * always be honored.
392 */
393 parentRequest.request_mode &= ~XtCWQueryOnly ;
394
395 XtMakeGeometryRequest( wid, &parentRequest, NULL) ;
396 }
397 _XmGeoMatrixSet( geoSpec) ;
398
399 result = XtGeometryYes ;
400 }
401 }
402 else
403 { /* If allowed and not an exception then reply Almost, since
404 * desired geometry is different than geometry in this layout.
405 */
406 if( allowed
407 && ( !geoSpec->almost_except
408 || !(*(geoSpec->almost_except))(geoSpec)) )
409 {
410 geoSpec->parent_request = parentRequest ;
411 result = XtGeometryAlmost ;
412 }
413 }
414 }
415 switch( result )
416 {
417 case XtGeometryAlmost:
418 {
419 /* Cache "almost" replies. Variables cachePtr and allowed are
420 * guaranteed to be non-null since almost replies are prevented
421 * if either is null.
422 */
423 if(geoSpec->in_layout) {
424 *cachePtr = geoSpec ;
425 *allowed = *(geoSpec->in_layout) ;
426 } else /* For fixing OSF CR 5956 */ {
427 allowed = NULL ;
428 *cachePtr = NULL ;
429 result = XtGeometryNo ;
430 }
431 break ;
432 }
433 case XtGeometryYes:
434 {
435 /* This must be a query-only request, or the response would
436 * be XtGeometryYes. Cache this reply if caching is
437 * supported. Otherwise, drop through and free geoSpec.
438 */
439 if( cachePtr )
440 { *cachePtr = geoSpec ;
441 break ;
442 }
443 }
444 default:
445 { _XmGeoMatrixFree( geoSpec) ;
446 break ;
447 }
448 }
449 return( result) ;
450 }
451
452 /****************************************************************
453 * Handle geometry request for XmRESIZE_ANY resize policy.
454 * Accept request allowed by parent.
455 * Reject request to change both width and height if both
456 * are disallowed by parent, but return almost if one is
457 * allowed.
458 ****************/
459 static XtGeometryResult
QueryAnyPolicy(XmGeoMatrix geoSpec,XtWidgetGeometry * parentRequestRtn)460 QueryAnyPolicy(
461 XmGeoMatrix geoSpec,
462 XtWidgetGeometry *parentRequestRtn )
463 {
464 Widget wid ;
465 Dimension layoutW ;
466 Dimension layoutH ;
467 XtWidgetGeometry parentResponse ;
468 XtGeometryResult queryResult ;
469 Dimension almostW ;
470 Dimension almostH ;
471 /****************/
472
473 wid = geoSpec->composite ;
474
475 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
476
477 layoutW = 0 ;
478 layoutH = 0 ;
479 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &layoutW,
480 &layoutH) ;
481 /* Load request.
482 */
483 parentRequestRtn->request_mode = CWWidth | CWHeight ;
484 parentRequestRtn->width = layoutW ;
485 parentRequestRtn->height = layoutH ;
486
487 /* Query parent only if necessary.
488 */
489 if( (layoutW == XtWidth( wid))
490 && (layoutH == XtHeight( wid)) )
491 {
492 parentRequestRtn->request_mode = 0 ;
493 queryResult = XtGeometryYes ;
494 }
495 else
496 { parentRequestRtn->request_mode |= XtCWQueryOnly ;
497
498 queryResult = XtMakeGeometryRequest( wid, parentRequestRtn,
499 &parentResponse) ;
500 if( queryResult == XtGeometryAlmost )
501 {
502 if( (parentResponse.request_mode & (CWWidth | CWHeight))
503 != (CWWidth | CWHeight) )
504 { queryResult = XtGeometryNo ;
505 }
506 else
507 { /* The protocol guarantees an XtGeometryYes reply for
508 * for an immediately subsequent request which is
509 * identical to the XtGeometryAlmost reply.
510 */
511 *parentRequestRtn = parentResponse ;
512 queryResult = XtGeometryYes ;
513
514 almostW = parentResponse.width ;
515 almostH = parentResponse.height ;
516
517 if( (almostW != layoutW) || (almostH != layoutH) )
518 {
519 /* Response to geometry request was different than
520 * requested geometry in fields that we care about.
521 * So, try a new arrangement with the area being
522 * offered by the parent.
523 */
524 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
525 layoutW = almostW ;
526 layoutH = almostH ;
527 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0,
528 &layoutW, &layoutH) ;
529 if( (almostW != layoutW) || (almostH != layoutH) )
530 {
531 /* The children cannot be laid-out in the area offered
532 * by the parent, so parent result is No.
533 */
534 queryResult = XtGeometryNo ;
535 }
536 }
537 }
538 }
539 }
540 return( queryResult) ;
541 }
542
543 /****************************************************************
544 * Handle geometry request for XmRESIZE_GROW resize policy.
545 * Accept request which would increase or maintain current size.
546 * Reject request which would decrease both preferred width
547 * and preferred height, but return almost if only one
548 * would decrease.
549 ****************/
550 static XtGeometryResult
QueryGrowPolicy(XmGeoMatrix geoSpec,XtWidgetGeometry * parentRequestRtn)551 QueryGrowPolicy(
552 XmGeoMatrix geoSpec,
553 XtWidgetGeometry *parentRequestRtn )
554 {
555 Widget wid ;
556 Dimension layoutW ;
557 Dimension layoutH ;
558 XtWidgetGeometry parentResponse ;
559 XtGeometryResult queryResult ;
560 Dimension almostW ;
561 Dimension almostH ;
562 /****************/
563
564 wid = geoSpec->composite ;
565
566 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
567
568 if( geoSpec->instig_request.request_mode & CWWidth )
569 { layoutW = 0 ; /* Let the layout routine choose a width.*/
570 }
571 else
572 { layoutW = XtWidth( wid) ; /* All changes will be reflected in */
573 } /* vertical dimension. */
574 layoutH = XtHeight( wid) ; /* Layout routine will grow vert., if needed.*/
575
576 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &layoutW,
577 &layoutH) ;
578 if( layoutW < XtWidth( wid) )
579 {
580 /* Try again, this time passing the width to _XmGeoArrangeBoxes.
581 */
582 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
583
584 layoutW = XtWidth( wid) ;
585 layoutH = XtHeight( wid) ;
586 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &layoutW,
587 &layoutH) ;
588 }
589 /* Load request.
590 */
591 parentRequestRtn->request_mode = CWWidth | CWHeight ;
592 parentRequestRtn->width = layoutW ;
593 parentRequestRtn->height = layoutH ;
594
595 /* Query parent only if necessary.
596 */
597 if( (layoutW == XtWidth( wid))
598 && (layoutH == XtHeight( wid)) )
599 {
600 parentRequestRtn->request_mode = 0 ;
601 queryResult = XtGeometryYes ;
602 }
603 else
604 { parentRequestRtn->request_mode |= XtCWQueryOnly ;
605
606 queryResult = XtMakeGeometryRequest( wid, parentRequestRtn,
607 &parentResponse) ;
608 if( queryResult == XtGeometryAlmost )
609 {
610 if( (parentResponse.request_mode & (CWWidth | CWHeight))
611 != (CWWidth | CWHeight) )
612 { queryResult = XtGeometryNo ;
613 }
614 else
615 { /* The protocol guarantees an XtGeometryYes reply for
616 * for an immediately subsequent request which is
617 * identical to the XtGeometryAlmost reply.
618 */
619 *parentRequestRtn = parentResponse ;
620 queryResult = XtGeometryYes ;
621
622 almostW = parentResponse.width ;
623 almostH = parentResponse.height ;
624
625 if( (almostW < XtWidth( wid))
626 || (almostH < XtHeight( wid)) )
627 {
628 queryResult = XtGeometryNo ;
629 }
630 else
631 { if( (almostW != layoutW) || (almostH != layoutH) )
632 {
633 /* Response to geometry request was different than
634 * requested geometry in fields that we care about.
635 * So, try a new arrangement with the area being
636 * offered by the parent.
637 */
638 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
639 layoutW = almostW ;
640 layoutH = almostH ;
641 _XmGeoArrangeBoxes( geoSpec, (Position) 0,
642 (Position) 0, &layoutW, &layoutH) ;
643 if( (almostW != layoutW) || (almostH != layoutH) )
644 {
645 /* The children cannot be laid-out in the area
646 * offered by the parent, so parent result is No.
647 */
648 queryResult = XtGeometryNo ;
649 }
650 }
651 }
652 }
653 }
654 }
655 return( queryResult) ;
656 }
657 /****************************************************************
658 * Handle geometry request for XmRESIZE_NONE resize policy.
659 * Accept request which would not change preferred size and
660 * allowed by parent.
661 * Reject request which would change both preferred width
662 * and preferred height, but return almost if only one
663 * would change and parent allows the other.
664 ****************/
665 static XtGeometryResult
QueryNonePolicy(XmGeoMatrix geoSpec,XtWidgetGeometry * parentRequestRtn)666 QueryNonePolicy(
667 XmGeoMatrix geoSpec,
668 XtWidgetGeometry *parentRequestRtn )
669 {
670 Widget wid ;
671 Dimension layoutW ;
672 Dimension layoutH ;
673 /****************/
674
675 wid = geoSpec->composite ;
676
677 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
678
679 layoutW = XtWidth( wid) ;
680 layoutH = XtHeight( wid) ;
681 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0,
682 &layoutW, &layoutH) ;
683 parentRequestRtn->request_mode = 0 ;
684
685 if( (layoutW != XtWidth( wid)) || (layoutH != XtHeight( wid)) )
686 { return( XtGeometryNo) ;
687 }
688
689 return( XtGeometryYes) ;
690 }
691
692 /****************************************************************/
693 void
_XmHandleSizeUpdate(Widget wid,unsigned int policy,XmGeoCreateProc createMatrix)694 _XmHandleSizeUpdate(
695 Widget wid,
696 #if NeedWidePrototypes
697 unsigned int policy,
698 #else
699 unsigned char policy,
700 #endif /* NeedWidePrototypes */
701 XmGeoCreateProc createMatrix)
702 {
703 XmGeoMatrix geoSpec ;
704 Dimension w ;
705 Dimension h ;
706 Dimension r_w ;
707 Dimension r_h ;
708 XtGeometryResult parentResult = XtGeometryNo ;
709 /****************/
710
711 geoSpec = (*createMatrix)( wid, NULL, NULL) ;
712
713 _XmGeoMatrixGet( geoSpec, XmGET_PREFERRED_SIZE) ;
714
715 switch( policy )
716 {
717 case XmRESIZE_NONE:
718 {
719 w = XtWidth( wid) ;
720 h = XtHeight( wid) ;
721 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &w, &h) ;
722
723 break ;
724 }
725 case XmRESIZE_GROW:
726 {
727 w = 0 ;
728 h = XtHeight( wid) ;
729 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &w, &h) ;
730
731 if( w < XtWidth( wid) )
732 { w = XtWidth( wid) ;
733 h = XtHeight( wid) ;
734 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0,
735 &w, &h) ;
736 }
737 break ;
738 }
739 case XmRESIZE_ANY:
740 default:
741 {
742 w = 0 ;
743 h = 0 ;
744 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0, &w, &h) ;
745
746 break ;
747 }
748 }
749
750 if( ((w == XtWidth( wid)) && (h == XtHeight( wid))) )
751 { parentResult = XtGeometryYes ;
752 }
753 else
754 { if( policy != XmRESIZE_NONE )
755 {
756 parentResult = XtMakeResizeRequest( wid, w, h, &r_w, &r_h) ;
757
758 if( parentResult == XtGeometryAlmost )
759 {
760 if( (policy == XmRESIZE_GROW)
761 && ( (r_w < XtWidth( wid))
762 || (r_h < XtHeight( wid))) )
763 {
764 parentResult = XtGeometryNo ;
765 }
766 else
767 { w = r_w ;
768 h = r_h ;
769 _XmGeoArrangeBoxes( geoSpec, (Position) 0, (Position) 0,
770 &w, &h) ;
771 if( (w == r_w) && (h == r_h) )
772 { XtMakeResizeRequest( wid, w, h, NULL, NULL) ;
773 }
774 else
775 { parentResult = XtGeometryNo ;
776 }
777 }
778 }
779 }
780 }
781 if( parentResult != XtGeometryNo )
782 { _XmGeoMatrixSet( geoSpec) ;
783 }
784 _XmGeoMatrixFree( geoSpec) ;
785 return ;
786 }
787
788 /****************************************************************
789 * This routine allocates and initializes the data structure used
790 * to describe a matrix of geometry boxes. Supplemental initialization
791 * may be required for some of the fields of the data structure, if
792 * the user uses these fields in its supplied co-routines.
793 * Rows of the GeoMatrix are lists of kid boxes which are terminated with
794 * a NULL in the kid widget field of the box structure. This routine
795 * automatically allocates extra boxes to use to mark the end of each
796 * row list.
797 * This routine initializes all fields to NULL.
798 * The pointer returned by this routine should be freed by the user
799 * using the _XmGeoMatrixFree() routine.
800 ****************/
801 XmGeoMatrix
_XmGeoMatrixAlloc(unsigned int numRows,unsigned int numBoxes,unsigned int extSize)802 _XmGeoMatrixAlloc(
803 unsigned int numRows, /* Number of rows of widgets to layout.*/
804 unsigned int numBoxes, /* Total number of widgets of matrix.*/
805 unsigned int extSize ) /* Extension record size (bytes).*/
806 {
807 XmGeoMatrix geoSpecPtr ;
808 unsigned int matrixRecSize ;
809 unsigned int layoutRecSize ;
810 unsigned int kidGeoRecSize ;
811 unsigned int layoutSize ;
812 unsigned int boxesSize ;
813 unsigned int totalSize ;
814 /****************/
815
816 /* Get sizes of the various components of the GeoMatrix. Round up to
817 * prevent alignment problems.
818 */
819 matrixRecSize = sizeof( XmGeoMatrixRec) ;
820 if( matrixRecSize & 0x03 )
821 { matrixRecSize = (matrixRecSize + 4) & ~((unsigned int) 0x03) ;
822 }
823 layoutRecSize = sizeof( XmGeoRowLayoutRec) ;
824 if( layoutRecSize & 0x03 )
825 { layoutRecSize = (layoutRecSize + 4) & ~((unsigned int) 0x03) ;
826 }
827 kidGeoRecSize = sizeof( XmKidGeometryRec) ;
828 if( kidGeoRecSize & 0x03 )
829 { kidGeoRecSize = (kidGeoRecSize + 4) & ~((unsigned int) 0x03) ;
830 }
831 layoutSize = (numRows + 1) * layoutRecSize ;
832 /* Extra boxes are used to mark the end of each row.
833 */
834 boxesSize = (numBoxes + numRows) * kidGeoRecSize ;
835 totalSize = matrixRecSize + layoutSize + boxesSize + extSize ;
836
837 geoSpecPtr = (XmGeoMatrix) XtCalloc( 1, totalSize) ; /* Must be zeroed.*/
838
839 /* Set locations of arrays of row layout, box, and extension records.
840 */
841 geoSpecPtr->layouts = (XmGeoMajorLayout) (((char *) geoSpecPtr)
842 + matrixRecSize) ;
843 geoSpecPtr->boxes = (XmKidGeometry) (((char *) geoSpecPtr)
844 + matrixRecSize + layoutSize) ;
845 if( extSize )
846 { geoSpecPtr->extension = (XtPointer) (((char *) geoSpecPtr)
847 + matrixRecSize + layoutSize + boxesSize) ;
848 }
849 return( geoSpecPtr) ;
850 }
851 void
_XmGeoMatrixFree(XmGeoMatrix geo_spec)852 _XmGeoMatrixFree(
853 XmGeoMatrix geo_spec)
854 {
855 if( geo_spec->ext_destructor )
856 {
857 (*(geo_spec->ext_destructor))( geo_spec->extension) ;
858 }
859 XtFree( (char *) geo_spec) ;
860 }
861
862 /****************************************************************
863 * If the widget specified by the "kidWid" parameter is non-NULL and is managed,
864 * its value is copied into the appropriate field of the kid geometry
865 * structure provided by the "geo" parameter and TRUE is returned.
866 * Otherwise, nothing is done and FALSE is returned.
867 ****************/
868 Boolean
_XmGeoSetupKid(XmKidGeometry geo,Widget kidWid)869 _XmGeoSetupKid(
870 XmKidGeometry geo, /* Must be non-NULL.*/
871 Widget kidWid )
872 {
873 /****************/
874 if( !kidWid || !XtIsManaged( kidWid) )
875 { return( FALSE) ;
876 }
877 /* The widget ID will be used for subsequent "get" operation.
878 */
879 geo->kid = (Widget) kidWid;
880
881 /* Return TRUE so the user knows that the box record was filled with
882 * a widget ID and can then increment the box pointer for the next
883 * managed widget to be setup.
884 */
885 return( TRUE) ;
886 }
887
888 /****************************************************************
889 * This routine goes through the widget matrix and retrieves the appropriate
890 * values for the KidGeometry boxes. Field values of the boxes may be
891 * altered according to requirements specified in each row structure of
892 * the geoSpec.
893 * If the widget id within the matrix matches the instigator field of the
894 * geoSpec, then the value for the box is taken from the request field of
895 * the geoSpec or the widget itself as appropriate.
896 ****************/
897 void
_XmGeoMatrixGet(XmGeoMatrix geoSpec,int geoType)898 _XmGeoMatrixGet(
899 XmGeoMatrix geoSpec,
900 int geoType ) /* XmGET_PREFERRED_SIZE or */
901 {
902 register XmKidGeometry boxPtr ;
903 XmKidGeometry rowPtr ;
904 XmGeoRowLayout layoutPtr ;
905 XtWidgetGeometry * request ;
906 Widget instigator ;
907 /****************/
908
909 request = &geoSpec->instig_request ;
910 instigator = geoSpec->instigator ;
911 rowPtr = geoSpec->boxes ;
912 layoutPtr = &(geoSpec->layouts->row) ;
913
914 while( !(layoutPtr->end) )
915 {
916 boxPtr = rowPtr ;
917 while( boxPtr->kid )
918 {
919 _XmGeoLoadValues( boxPtr->kid, geoType, instigator, request,
920 &(boxPtr->box)) ;
921 if( boxPtr->kid == instigator )
922 { geoSpec->in_layout = &(boxPtr->box) ;
923 }
924 ++boxPtr ;
925 }
926 if( layoutPtr->fix_up )
927 {
928 (*(layoutPtr->fix_up))( geoSpec, geoType,
929 (XmGeoMajorLayout) layoutPtr, rowPtr) ;
930 }
931 rowPtr = boxPtr + 1 ; /* Skip over NULL box marking the end of row.*/
932 ++layoutPtr ; /* Go to next row layout record.*/
933 }
934 #ifdef DEBUG_GEOUTILS
935 PrintMatrix( "(get) ", geoSpec) ;
936 #endif
937 return ;
938 }
939
940 /****************************************************************
941 * The XtConfigureWidget routine is called on all widgets of the geoSpec
942 * matrix as needed (when the geometry values of the box have changed).
943 * If a widget ID matches that of the instigator field of the geoSpec,
944 * then that widget is not configured.
945 * Any layout "fixup" routines which are specified in the row structure
946 * of the geoSpec are called before and after the call
947 * to XmeConfigureObject, with appropriate parameter values.
948 ****************/
949 void
_XmGeoMatrixSet(XmGeoMatrix geoSpec)950 _XmGeoMatrixSet(
951 XmGeoMatrix geoSpec )
952 {
953 register XmKidGeometry rowPtr ;
954 register XmGeoRowLayout layoutPtr ;
955 Boolean fixUps = FALSE ;
956 /****************/
957
958 #ifdef DEBUG_GEOUTILS
959 PrintMatrix( "(set) ", geoSpec) ;
960 #endif
961
962 /* Give the user a chance to avoid setting the widgets to box values.
963 */
964 if( !geoSpec->set_except || !(*geoSpec->set_except)( geoSpec) )
965 {
966 /* Give the user a chance to modify box sizes before setting
967 * the widget to the values defined in the box record.
968 */
969 layoutPtr = &(geoSpec->layouts->row) ;
970 rowPtr = geoSpec->boxes ;
971 while( !(layoutPtr->end) )
972 {
973 if( layoutPtr->fix_up )
974 {
975 /* Call the user's routine which may modify boxes of this row.
976 */
977 (*(layoutPtr->fix_up))( geoSpec, XmGEO_PRE_SET,
978 (XmGeoMajorLayout) layoutPtr, rowPtr) ;
979 fixUps = TRUE ;
980 }
981 rowPtr += layoutPtr->box_count + 1 ; /* Skip to next row.*/
982 ++layoutPtr ;
983 }
984 /* Now set the widgets to the values in the boxes.
985 */
986 layoutPtr = &(geoSpec->layouts->row) ;
987 rowPtr = geoSpec->boxes ;
988 while( !(layoutPtr->end) )
989 {
990 _XmSetKidGeo( rowPtr, geoSpec->instigator) ;
991
992 rowPtr += layoutPtr->box_count + 1 ; /* Skip to next row.*/
993 ++layoutPtr ;
994 }
995 if( fixUps )
996 {
997 /* Now call the fix_up routines again, to give the user a chance to
998 * undo the chances to the boxes in order to keep consistency for
999 * subsequent layout operations.
1000 */
1001 layoutPtr = &(geoSpec->layouts->row) ;
1002 rowPtr = geoSpec->boxes ;
1003 while( !(layoutPtr->end) )
1004 {
1005 if( layoutPtr->fix_up )
1006 {
1007 (*(layoutPtr->fix_up))( geoSpec, XmGEO_POST_SET,
1008 (XmGeoMajorLayout) layoutPtr, rowPtr) ;
1009 }
1010 rowPtr += layoutPtr->box_count + 1 ; /* Skip to next row.*/
1011 ++layoutPtr ;
1012 }
1013 }
1014 }
1015 return ;
1016 }
1017
1018 /****************************************************************
1019 * This routine adjusts boxes according to policies regarding border size
1020 * and even-sized boxes. Box dimensions are altered appropriately if
1021 * even_width or even_height parameters are set. Borders are set if
1022 * uniform_border is TRUE.
1023 ****************/
1024 void
_XmGeoAdjustBoxes(XmGeoMatrix geoSpec)1025 _XmGeoAdjustBoxes(
1026 XmGeoMatrix geoSpec )
1027 {
1028 register XmKidGeometry rowPtr ;
1029 register XmKidGeometry boxPtr ;
1030 XmGeoRowLayout layoutPtr ;
1031 Dimension globalSetBorder ;
1032 Dimension globalBorder ;
1033 Dimension borderValue ;
1034 /****************/
1035
1036 globalSetBorder = geoSpec->uniform_border ;
1037 globalBorder = geoSpec->border ;
1038
1039 rowPtr = geoSpec->boxes ;
1040 layoutPtr = &(geoSpec->layouts->row) ;
1041
1042 while( !(layoutPtr->end) )
1043 {
1044 if( layoutPtr->even_width )
1045 { _XmGeoBoxesSameWidth( rowPtr, layoutPtr->even_width) ;
1046 }
1047 if( layoutPtr->even_height )
1048 { _XmGeoBoxesSameHeight( rowPtr, layoutPtr->even_height) ;
1049 }
1050 if( globalSetBorder || layoutPtr->uniform_border )
1051 { if( globalSetBorder )
1052 { borderValue = globalBorder ;
1053 }
1054 else
1055 { borderValue = layoutPtr->border ;
1056 }
1057 boxPtr = rowPtr ;
1058 while( boxPtr->kid )
1059 { boxPtr->box.border_width = borderValue ;
1060 ++boxPtr ;
1061 }
1062 }
1063 while( (rowPtr++)->kid ) /* Go to next row of boxes. */
1064 { /*EMPTY*/ }
1065 ++layoutPtr ; /* Go to next row layout record.*/
1066 }
1067 return ;
1068 }
1069
1070 /****************************************************************
1071 * This routine traverses the matrix and collects data regarding the
1072 * sizes of boxes, the minimum fill area expected, and various other
1073 * parameters which are used during the layout process.
1074 ****************/
1075 void
_XmGeoGetDimensions(XmGeoMatrix geoSpec)1076 _XmGeoGetDimensions(
1077 XmGeoMatrix geoSpec )
1078 {
1079 register XmKidGeometry rowPtr ;
1080 register XmKidGeometry boxPtr ;
1081 XmGeoRowLayout layoutPtr ;
1082 Dimension boxH ;
1083 Dimension rowH ;
1084 Dimension rowW ;
1085 Dimension matrixFillH ;
1086 Dimension matrixBoxesH ;
1087 Dimension matrixW ;
1088 Dimension endSpaceW ;
1089 unsigned int numBoxes ;
1090 Dimension marginW ;
1091 Dimension marginH ;
1092 /****************/
1093
1094 marginH = geoSpec->margin_h ;
1095 marginW = geoSpec->margin_w ;
1096 rowPtr = geoSpec->boxes ;
1097 layoutPtr = &(geoSpec->layouts->row) ;
1098 matrixW = 0 ;
1099 matrixBoxesH = 0 ;
1100 matrixFillH = layoutPtr->space_above ;
1101 if( matrixFillH < marginH )
1102 { matrixFillH = 0 ;
1103 }
1104 else
1105 { matrixFillH -= marginH ; /* This dimension does not include margins.*/
1106 }
1107 geoSpec->stretch_boxes = FALSE ;
1108 while( !(layoutPtr->end) )
1109 {
1110 /* Gather information about the height, width, and number of boxes
1111 * in the row.
1112 */
1113 rowW = 0 ;
1114 rowH = 0 ;
1115 numBoxes = 0 ;
1116 boxPtr = rowPtr ;
1117 while( boxPtr->kid )
1118 { rowW += boxPtr->box.width + (boxPtr->box.border_width << 1) ;
1119 boxH = boxPtr->box.height + (boxPtr->box.border_width << 1) ;
1120 ASSIGN_MAX( rowH, boxH) ; /* The tallest box is the row height.*/
1121 ++numBoxes ;
1122 ++boxPtr ;
1123 }
1124 /* Fill row layout record with info about row.
1125 */
1126 layoutPtr->max_box_height = rowH ;/* Tallest box in row, with border.*/
1127 layoutPtr->boxes_width = rowW ; /* Sum of box widths and borders.*/
1128 layoutPtr->box_count = numBoxes ;
1129
1130 /* Check for vertical stetch row.
1131 */
1132 if( layoutPtr->stretch_height )
1133 { if( layoutPtr->fit_mode != XmGEO_WRAP )
1134 { geoSpec->stretch_boxes = TRUE ;
1135 }
1136 else
1137 { layoutPtr->stretch_height = FALSE ;
1138 }
1139 }
1140 /* Compute row width to generate matrix width. Exclude margins.
1141 */
1142 if( layoutPtr->space_end > marginW )
1143 { endSpaceW = layoutPtr->space_end - marginW ;
1144 }
1145 else
1146 { endSpaceW = 0 ;
1147 }
1148 /* Fill width is the minimum spacing between (borders of) boxes plus
1149 * any extra space required at ends. Margins are not included.
1150 */
1151 layoutPtr->fill_width = (endSpaceW << 1)
1152 + ((numBoxes - 1) * layoutPtr->space_between) ;
1153 /* Maximum row width is the overall matrix width, less margins. Add
1154 * box width to fill width for total width this row.
1155 */
1156 rowW += layoutPtr->fill_width ;
1157 ASSIGN_MAX( matrixW, rowW) ;
1158 rowPtr = boxPtr + 1 ; /* Skip over NULL box marking the end of row.*/
1159 ++layoutPtr ; /* Go to next row layout record.*/
1160 /* Accumulate heights of each row.
1161 */
1162 matrixFillH += layoutPtr->space_above ;
1163 matrixBoxesH += rowH ;
1164 }
1165 /* The matrixFillH variable already has fill space included from the final
1166 * row layout record. This must be reduced by the amount of the margin,
1167 * or a smaller amount if the amount specified was less than the margin.
1168 */
1169 if( layoutPtr->space_above < marginH )
1170 { matrixFillH -= layoutPtr->space_above ;
1171 }
1172 else
1173 { matrixFillH -= marginH ;
1174 }
1175 geoSpec->max_major = matrixW ; /* Widest row, excluding margins. */
1176 geoSpec->boxes_minor = matrixBoxesH ; /* Sum of tallest box in each row.*/
1177 geoSpec->fill_minor = matrixFillH ; /* Sum of vertical fill spacing. */
1178 }
1179
1180 /****************************************************************
1181 * After the boxes have been layed-out according to the minimum vertical fill
1182 * requirements of the matrix, this routine stretches the layout to fill
1183 * any extra space required by the managing widget.
1184 * Returns new height after extra spacing is inserted.
1185 ****************/
1186 static Dimension
_XmGeoStretchVertical(XmGeoMatrix geoSpec,int actualH,int desiredH)1187 _XmGeoStretchVertical(
1188 XmGeoMatrix geoSpec,
1189 #if NeedWidePrototypes
1190 int actualH,
1191 int desiredH )
1192 #else
1193 Dimension actualH,
1194 Dimension desiredH )
1195 #endif /* NeedWidePrototypes */
1196 {
1197 register XmGeoRowLayout layoutPtr ;
1198 register XmKidGeometry rowPtr ;
1199 int fillOffset ;
1200 int stretchableSpace ;
1201 int deltaY ;
1202 int deltaH ;
1203 /****************/
1204
1205 layoutPtr = &(geoSpec->layouts->row) ;
1206 stretchableSpace = 0 ;
1207 fillOffset = ((int) desiredH) - ((int) actualH) ;
1208 if( fillOffset < 0 )
1209 { /* Must shrink stretchable boxes.
1210 */
1211 while( !layoutPtr->end )
1212 { if( layoutPtr->stretch_height
1213 && (layoutPtr->max_box_height > layoutPtr->min_height) )
1214 {
1215 stretchableSpace += layoutPtr->max_box_height
1216 - layoutPtr->min_height ;
1217 }
1218 ++layoutPtr ;
1219 }
1220 if( -fillOffset > stretchableSpace )
1221 { fillOffset = -stretchableSpace ;
1222 }
1223 }
1224 else
1225 { /* Must grow stretchable boxes.
1226 */
1227 while( !layoutPtr->end )
1228 { if( layoutPtr->stretch_height )
1229 { stretchableSpace += layoutPtr->max_box_height ;
1230 }
1231 ++layoutPtr ;
1232 }
1233 }
1234 if( !stretchableSpace )
1235 { /* No stretchable boxes, so return with current height.
1236 */
1237 return( actualH) ;
1238 }
1239 deltaY = 0 ;
1240 rowPtr = geoSpec->boxes ;
1241 layoutPtr = &(geoSpec->layouts->row) ;
1242 while( !layoutPtr->end )
1243 { if( layoutPtr->stretch_height )
1244 {
1245 if( fillOffset < 0 )
1246 { if( layoutPtr->max_box_height > layoutPtr->min_height )
1247 { deltaH = (((int) (layoutPtr->max_box_height
1248 - layoutPtr->min_height)) * fillOffset)
1249 / stretchableSpace ;
1250 }
1251 else
1252 { deltaH = 0 ;
1253 }
1254 /* deltaH is now <= 0.
1255 */
1256 while( rowPtr->kid )
1257 {
1258 int boxCorrection = layoutPtr->max_box_height
1259 - rowPtr->box.height ;
1260 if( boxCorrection > -deltaH )
1261 { boxCorrection = -deltaH ;
1262 }
1263 rowPtr->box.height += deltaH + boxCorrection ;
1264 rowPtr->box.y += deltaY - (boxCorrection >> 1) ;
1265 ++rowPtr ;
1266 }
1267 }
1268 else /* fillOffset >= 0 */
1269 {
1270 deltaH = (layoutPtr->max_box_height * fillOffset)
1271 / stretchableSpace ;
1272 while( rowPtr->kid )
1273 { rowPtr->box.height += deltaH ;
1274 rowPtr->box.y += deltaY ;
1275 ++rowPtr ;
1276 }
1277 }
1278 deltaY += deltaH ;
1279 }
1280 else
1281 { while( rowPtr->kid )
1282 { rowPtr->box.y += deltaY ;
1283 ++rowPtr ;
1284 }
1285 }
1286 ++rowPtr ;
1287 ++layoutPtr ;
1288 }
1289 return( actualH + deltaY) ; /* Return new height.*/
1290 }
1291
1292 /****************************************************************
1293 * After the boxes have been layed-out according to the minimum vertical fill
1294 * requirements of the matrix, this routine stretches the layout to fill
1295 * any extra space required by the managing widget.
1296 * Returns new height after extra spacing is inserted.
1297 ****************/
1298 static Dimension
_XmGeoFillVertical(XmGeoMatrix geoSpec,int actualH,int desiredH)1299 _XmGeoFillVertical(
1300 XmGeoMatrix geoSpec,
1301 #if NeedWidePrototypes
1302 int actualH,
1303 int desiredH )
1304 #else
1305 Dimension actualH,
1306 Dimension desiredH )
1307 #endif /* NeedWidePrototypes */
1308 {
1309 register XmGeoRowLayout layoutPtr ;
1310 register XmKidGeometry rowPtr ;
1311 unsigned long fillAmount ;
1312 unsigned long totalSpecSpace ;
1313 Dimension marginH ;
1314 Dimension firstSpecSpace ;
1315 Dimension lastSpecSpace ;
1316 Dimension currentFirstSpace ;
1317 Dimension currentLastSpace ;
1318 Dimension newFirstSpace ;
1319 Dimension newLastSpace ;
1320 int deltaY ;
1321 /****************/
1322
1323 /* Need to accumulate specified spacing factors, saving first and last
1324 * ends separately.
1325 */
1326 layoutPtr = &(geoSpec->layouts->row) ;
1327 totalSpecSpace = 0 ;
1328 firstSpecSpace = layoutPtr->space_above ;
1329 while( !(++layoutPtr)->end )
1330 { totalSpecSpace += layoutPtr->space_above ;
1331 }
1332 lastSpecSpace = layoutPtr->space_above ;
1333 totalSpecSpace += firstSpecSpace + lastSpecSpace ;
1334 if( !totalSpecSpace )
1335 { /* Zero spacing specified, so just return as is.
1336 */
1337 return( actualH) ;
1338 }
1339 /* Must reconstruct the actual spacing, which is the specified minimum.
1340 * Save current end spacing separately, since everything done here is
1341 * relative to the actual coordinates of the matrix and it will be
1342 * needed later.
1343 */
1344 marginH = geoSpec->margin_h ;
1345 currentFirstSpace = (firstSpecSpace < marginH) ? marginH : firstSpecSpace ;
1346 currentLastSpace = (lastSpecSpace < marginH) ? marginH : lastSpecSpace ;
1347
1348 /* Fill amount includes the current fill plus margins and extra
1349 * spacing.
1350 */
1351 fillAmount = (desiredH - actualH) + geoSpec->fill_minor
1352 + currentFirstSpace + currentLastSpace ;
1353 newFirstSpace = (Dimension) ((fillAmount * (unsigned long) firstSpecSpace)
1354 / totalSpecSpace) ;
1355 newLastSpace = (Dimension) ((fillAmount * (unsigned long) lastSpecSpace)
1356 / totalSpecSpace) ;
1357 if( newFirstSpace < marginH )
1358 { fillAmount -= marginH ;
1359 totalSpecSpace -= firstSpecSpace ;
1360 newFirstSpace = marginH ;
1361 }
1362 if( newLastSpace < marginH )
1363 { fillAmount -= marginH ;
1364 totalSpecSpace -= lastSpecSpace ;
1365 newLastSpace = marginH ;
1366 }
1367 /* Now traverse the matrix, offsetting all y-ccordinates according to
1368 * additional spacing. Wrapped lines receive no extra spacing between
1369 * them.
1370 */
1371 deltaY = newFirstSpace - currentFirstSpace ;
1372 rowPtr = geoSpec->boxes ;
1373 layoutPtr = &(geoSpec->layouts->row) ;
1374 for(;;)
1375 { while( rowPtr->kid )
1376 { rowPtr->box.y += deltaY ;
1377 ++rowPtr ;
1378 }
1379 ++rowPtr ;
1380 ++layoutPtr ;
1381 if( layoutPtr->end )
1382 { break ;
1383 }
1384 deltaY += (int) (((((unsigned long) layoutPtr->space_above)
1385 * fillAmount) / totalSpecSpace) - layoutPtr->space_above) ;
1386 }
1387 deltaY += newLastSpace - currentLastSpace ;
1388
1389 return( actualH + deltaY) ; /* Return new height.*/
1390 }
1391
1392 /****************************************************************
1393 * Calculates and returns appropriate fill factor from given layout
1394 * parameters. Also returns appropriate spacing for ends.
1395 * The fill factor returned is for use with all spacing between boxes, but
1396 * not the ends (use provided spacing).
1397 ****************/
1398 static void
_XmGeoCalcFill(int fillSpace,int margin,unsigned int numBoxes,int endSpec,int betweenSpec,Dimension * pEndSpace,Dimension * pBetweenSpace)1399 _XmGeoCalcFill(
1400 #if NeedWidePrototypes
1401 int fillSpace,
1402 int margin,
1403 #else
1404 Dimension fillSpace, /* Fill space, including margins.*/
1405 Dimension margin, /* Margin (included in fillSpace).*/
1406 #endif /* NeedWidePrototypes */
1407 unsigned int numBoxes,
1408 #if NeedWidePrototypes
1409 int endSpec,
1410 int betweenSpec,
1411 #else
1412 Dimension endSpec,
1413 Dimension betweenSpec,
1414 #endif /* NeedWidePrototypes */
1415 Dimension *pEndSpace, /* Receives end spacing.*/
1416 Dimension *pBetweenSpace ) /* Receives between spacing.*/
1417 {
1418 Dimension totalSpecSpace ;/* Sum of specified spacing.*/
1419 /****************/
1420
1421 if( !endSpec )
1422 { if( numBoxes == 1 )
1423 { endSpec = 1 ;
1424 }
1425 else
1426 { if( !betweenSpec )
1427 { betweenSpec = (Dimension) (numBoxes - 1) ;
1428 }
1429 }
1430 }
1431 totalSpecSpace = (betweenSpec * (numBoxes - 1)) + (endSpec << 1) ;
1432 *pEndSpace = (endSpec * fillSpace) / totalSpecSpace ;
1433
1434 if( *pEndSpace < margin )
1435 {
1436 if( (endSpec << 1) < totalSpecSpace )
1437 { totalSpecSpace -= endSpec << 1 ;
1438 }
1439 else
1440 { totalSpecSpace = 1 ;
1441 }
1442 if( (margin << 1) < fillSpace )
1443 { fillSpace -= margin << 1 ;
1444 }
1445 else
1446 { fillSpace = 0 ;
1447 }
1448 *pEndSpace = margin ;
1449 }
1450 *pBetweenSpace = (betweenSpec * fillSpace) / totalSpecSpace ;
1451 return ;
1452 }
1453
1454 /****************************************************************
1455 * The x, y, width, and height fields of the boxes in the geoSpec matrix
1456 * are modified with values appropriate for the layout parameters specified
1457 * by x, y, pW, and pH.
1458 * The overall width and height dimensions at the specified locations
1459 * of pW and pH must be initially set to their desired values, or zero
1460 * for the default layout.
1461 * The actual values of the width and height (after layout) are returned at
1462 * the locations pW and pH.
1463 ****************/
1464 void
_XmGeoArrangeBoxes(XmGeoMatrix geoSpec,int x,int y,Dimension * pW,Dimension * pH)1465 _XmGeoArrangeBoxes(
1466 XmGeoMatrix geoSpec, /* Array of box lists (rows).*/
1467 #if NeedWidePrototypes
1468 int x,
1469 int y,
1470 #else
1471 Position x, /* X coordinate of composite.*/
1472 Position y, /* Y coordinate of composite.*/
1473 #endif /* NeedWidePrototypes */
1474 Dimension *pW, /* Initial value is minimum width.*/
1475 Dimension *pH ) /* Initial value is minimum height.*/
1476 {
1477 Dimension marginW ; /* Margin between sides and boxes.*/
1478 Dimension marginH ; /* Margin between top/bot and boxes.*/
1479 XmKidGeometry rowPtr ;
1480 XmGeoRowLayout layoutPtr ;
1481 Dimension actualW ;
1482 Dimension actualH ;
1483 Dimension initY ;
1484 /****************/
1485
1486 if( geoSpec->arrange_boxes
1487 && (geoSpec->arrange_boxes != _XmGeoArrangeBoxes) )
1488 {
1489 (*(geoSpec->arrange_boxes))( geoSpec, x, y, pW, pH) ;
1490 return ;
1491 }
1492 /* Fix box dimensions according to even_height/width and uniform_border
1493 * specifications.
1494 */
1495 _XmGeoAdjustBoxes( geoSpec) ;
1496
1497 /* Compute layout dimensions.
1498 */
1499 _XmGeoGetDimensions( geoSpec) ;
1500
1501 /* Initialize global layout dimensions.
1502 */
1503 marginW = geoSpec->margin_w ;
1504 marginH = geoSpec->margin_h ;
1505 actualW = geoSpec->max_major + (marginW << 1) ;
1506
1507 /****** the value of this assignment is never used **********
1508 actualH = geoSpec->boxes_minor + geoSpec->fill_minor + (marginH << 1) ;
1509 *************************************************************/
1510
1511 /* Adjust layout dimensions to requested dimensions.
1512 */
1513 if( *pW )
1514 { actualW = *pW ;
1515 }
1516
1517 /******* the value assigned to actualH is never used *************
1518 if( *pH )
1519 { actualH = *pH ;
1520 }
1521 ******************************************************************/
1522
1523 /* Save initial Y coordinate for later computation of height.
1524 */
1525 initY = y ;
1526
1527 /* Layout horizontal position of each box in row, one row at a time.
1528 */
1529 layoutPtr = &(geoSpec->layouts->row) ;
1530 rowPtr = geoSpec->boxes ;
1531 /* Add first end spacing.
1532 */
1533 if( layoutPtr->space_above > marginH )
1534 { y += layoutPtr->space_above ;
1535 }
1536 else
1537 { y += marginH ;
1538 }
1539 while( !(layoutPtr->end) )
1540 {
1541 /* Arrange one row of boxes at a time.
1542 */
1543 y = _XmGeoArrangeList( rowPtr, layoutPtr, x, y, actualW,
1544 marginW, marginH) ;
1545 rowPtr += layoutPtr->box_count + 1 ; /* Skip to next row.*/
1546 ++layoutPtr ;
1547
1548 /* Add between-row spacing.
1549 */
1550 y += layoutPtr->space_above ;
1551 }
1552 if( layoutPtr->space_above < marginH )
1553 { /* Fill out to the minimum margin if previous spacing is less
1554 * than margin.
1555 */
1556 y += marginH - layoutPtr->space_above ;
1557 }
1558 actualH = y - initY ;
1559 if( *pH && (actualH != *pH) )
1560 { if( geoSpec->stretch_boxes )
1561 { /* Has stretchable boxes, so grow or shrink using stretch.
1562 */
1563 actualH = _XmGeoStretchVertical( geoSpec, actualH, *pH) ;
1564 }
1565 else
1566 { if( actualH < *pH )
1567 { /* Layout is smaller than specified height, so fill vertically.
1568 */
1569 actualH = _XmGeoFillVertical( geoSpec, actualH, *pH) ;
1570 }
1571 }
1572 }
1573 /* Set return values of actual width and height of matrix.
1574 */
1575 geoSpec->width = actualW ;
1576 if( *pW < actualW )
1577 { *pW = actualW ;
1578 }
1579 geoSpec->height = actualH ;
1580 if( *pH < actualH )
1581 { *pH = actualH ;
1582 }
1583 return ;
1584 }
1585
1586 /****************************************************************/
1587 static int
boxWidthCompare(XmConst void * boxPtr1,XmConst void * boxPtr2)1588 boxWidthCompare(
1589 XmConst void * boxPtr1,
1590 XmConst void * boxPtr2 )
1591 {
1592 /****************/
1593
1594 return( (*((XmKidGeometry *) boxPtr1))->box.width
1595 > (*((XmKidGeometry *) boxPtr2))->box.width) ;
1596 }
1597 /****************************************************************
1598 * This routine alters box sizes such that the composite width is reduced
1599 * by the offset amount specified. The boxWidth parameter is assumed to
1600 * contain the sum of the all box widths, including borders.
1601 * The algorithm used by this routine tends to average the width of all boxes.
1602 * In other words, to achieve the desired width reduction, the largest boxes
1603 * are reduced first, possibly until all boxes are the same width
1604 * (thereafter reducing all boxes evenly).
1605 ****************/
1606 static void
FitBoxesAveraging(XmKidGeometry rowPtr,unsigned int numBoxes,int boxWidth,int amtOffset)1607 FitBoxesAveraging(
1608 XmKidGeometry rowPtr,
1609 unsigned int numBoxes,
1610 #if NeedWidePrototypes
1611 int boxWidth,
1612 #else
1613 Dimension boxWidth,
1614 #endif /* NeedWidePrototypes */
1615 int amtOffset )
1616 {
1617 unsigned int Index ;
1618 XmKidGeometry * sortedBoxes ;
1619 /****************/
1620
1621 /* Get memory to use for sorting the list of boxes.
1622 */
1623 sortedBoxes = (XmKidGeometry *) XtMalloc( numBoxes
1624 * sizeof( XmKidGeometry)) ;
1625 /* Enter the boxes into the array and sort.
1626 */
1627 Index = 0 ;
1628 while( Index < numBoxes )
1629 { sortedBoxes[Index] = &rowPtr[Index] ;
1630 /* Need to remove the border_width component from boxWidth.
1631 */
1632 boxWidth -= (rowPtr[Index].box.border_width << 1) ;
1633 ++Index ;
1634 }
1635 qsort( (void *) sortedBoxes, (size_t) numBoxes, sizeof( XmKidGeometry),
1636 boxWidthCompare) ;
1637 /* Now sorted with smallest box first.
1638 */
1639 Index = 0 ;
1640 while( Index < numBoxes )
1641 {
1642 /* The right-hand side of the comparison represents the amount of
1643 * area that would be truncated if all boxes were the same width
1644 * as sortedBoxes[Index]. The loop will break when the Index
1645 * points to the smallest box in the list to be truncated.
1646 */
1647 if( amtOffset >= ((int) (boxWidth - ((sortedBoxes[Index]->box.width)
1648 * (numBoxes - Index)))) )
1649 { break ;
1650 }
1651 /* This keeps the above comparison simple.
1652 */
1653 boxWidth -= sortedBoxes[Index]->box.width ;
1654 ++Index ;
1655 }
1656 if( Index < numBoxes )
1657 {
1658 if( (int) boxWidth > amtOffset )
1659 {
1660 boxWidth = (boxWidth - amtOffset) / (numBoxes - Index) ;
1661
1662 if( !boxWidth )
1663 { boxWidth = 1 ;
1664 }
1665 }
1666 else
1667 { boxWidth = 1 ;
1668 }
1669 /* boxWidth is now the truncated width of the remaining boxes
1670 * in the sorted list. Set these boxes appropriately.
1671 */
1672 while( Index < numBoxes )
1673 { sortedBoxes[Index]->box.width = boxWidth ;
1674 ++Index ;
1675 }
1676 }
1677 XtFree( (char *) sortedBoxes) ;
1678
1679 return ;
1680 }
1681
1682 /****************************************************************
1683 * This routine alters the width of boxes in proportion to the width of each
1684 * box such that the total change is equal to amtOffset. If amtOffset is
1685 * greater than zero, the total width is reduced (a "fit"). Otherwise,
1686 * the total width is increased (a "fill").
1687 ****************/
1688 static void
FitBoxesProportional(XmKidGeometry rowPtr,unsigned int numBoxes,int boxWidth,int amtOffset)1689 FitBoxesProportional(
1690 XmKidGeometry rowPtr,
1691 unsigned int numBoxes,
1692 #if NeedWidePrototypes
1693 int boxWidth,
1694 #else
1695 Dimension boxWidth,
1696 #endif /* NeedWidePrototypes */
1697 int amtOffset )
1698 {
1699 int deltaX ;
1700 int deltaW ;
1701 /****************/
1702
1703
1704 if( boxWidth >= numBoxes )
1705 {
1706 deltaX = 0 ;
1707 while( rowPtr->kid )
1708 {
1709 deltaW = (amtOffset * (int)(rowPtr->box.width
1710 + (rowPtr->box.border_width << 1))) / ((int) boxWidth) ;
1711 if( deltaW < ((int) rowPtr->box.width) )
1712 { rowPtr->box.width -= deltaW ;
1713 }
1714 else
1715 { rowPtr->box.width = 1 ;
1716 }
1717 rowPtr->box.x += deltaX ;
1718 deltaX -= deltaW ;
1719 ++rowPtr ;
1720 }
1721 }
1722 else /* boxWidth < numBoxes */
1723 {
1724 if( (-amtOffset) > numBoxes )
1725 {
1726 boxWidth = (-amtOffset) / numBoxes ;
1727 }
1728 else
1729 { boxWidth = 1 ;
1730 }
1731 deltaX = 0 ;
1732 while( rowPtr->kid )
1733 {
1734 rowPtr->box.width = boxWidth ;
1735 rowPtr->box.x += deltaX ;
1736 deltaX += boxWidth ;
1737 ++rowPtr ;
1738 }
1739
1740 }
1741 return ;
1742 }
1743
1744 /****************************************************************/
1745 static void
SegmentFill(XmKidGeometry rowBoxes,unsigned int numBoxes,XmGeoRowLayout layoutPtr,int x,int width,int marginW,int endX,int maxX,int endSpace,int betweenSpace)1746 SegmentFill(
1747 XmKidGeometry rowBoxes,
1748 unsigned int numBoxes,
1749 XmGeoRowLayout layoutPtr,
1750 #if NeedWidePrototypes
1751 int x,
1752 int width,
1753 int marginW,
1754 int endX,
1755 int maxX,
1756 int endSpace,
1757 int betweenSpace )
1758 #else
1759 Position x,
1760 Dimension width,
1761 Dimension marginW,
1762 Position endX,
1763 Position maxX,
1764 Dimension endSpace,
1765 Dimension betweenSpace )
1766 #endif /* NeedWidePrototypes */
1767 {
1768 Widget holdEnd ;
1769 Dimension spacedWidth ;
1770 Dimension boxWidth ;
1771 Dimension sumW ;
1772 int amtOffset ;
1773 Dimension totalFill ;
1774 Position rowX ;
1775 XmKidGeometry rowPtr ;
1776 /****************/
1777
1778 holdEnd = rowBoxes[numBoxes].kid ;
1779 rowBoxes[numBoxes].kid = NULL ;
1780
1781 spacedWidth = (betweenSpace * (numBoxes - 1)) + (endSpace << 1) ;
1782 amtOffset = ((int) spacedWidth + (maxX - endX)) ;
1783 if( (amtOffset > 0) && (amtOffset < width) )
1784 { boxWidth = width - amtOffset ;
1785 }
1786 else
1787 { boxWidth = 1 ;
1788 }
1789 sumW = boxWidth + spacedWidth ;
1790
1791 amtOffset = ((int) sumW) - ((int) width) ;
1792 /* Setup the default spacing.
1793 */
1794 betweenSpace = layoutPtr->space_between ;
1795 endSpace = (layoutPtr->space_end < marginW)
1796 ? marginW : layoutPtr->space_end ;
1797 switch( layoutPtr->fill_mode )
1798 { case XmGEO_CENTER:
1799 {
1800 /* Compute new spacing values to result in a centered
1801 * layout when passed to the simple layout routine.
1802 */
1803 if( width > sumW )
1804 { totalFill = (spacedWidth + width) - sumW ;
1805 }
1806 else
1807 { totalFill = marginW << 1 ;
1808 }
1809 { /* This little exercise is needed for when NeedWidePrototypes
1810 * has value 1 which causes endSpace and betweenSpace to
1811 * become "int"s, and a pointer to an int cannot be passed
1812 * as an argument where a pointer to a dimension is required.
1813 */
1814 Dimension eSpace ;
1815 Dimension bSpace ;
1816 _XmGeoCalcFill( totalFill, marginW, numBoxes,
1817 layoutPtr->space_end, layoutPtr->space_between,
1818 &eSpace, &bSpace) ;
1819 endSpace = eSpace ;
1820 betweenSpace = bSpace ;
1821 }
1822 break ;
1823 }
1824 case XmGEO_PACK:
1825 { /* For a packed layout, just layout with extra space
1826 * at the end of the row.
1827 */
1828 break ;
1829 }
1830 case XmGEO_EXPAND:
1831 default:
1832 { /* FitBoxesProportional will fill if amtOffset < 0,
1833 * as it is here.
1834 */
1835 FitBoxesProportional( rowBoxes, numBoxes, boxWidth, amtOffset) ;
1836 break ;
1837 }
1838 }
1839 rowX = x + endSpace ;
1840 rowPtr = rowBoxes ;
1841 while( rowPtr->kid )
1842 {
1843 rowPtr->box.x = rowX ;
1844 rowX += rowPtr->box.width + (rowPtr->box.border_width << 1)
1845 + betweenSpace ;
1846 ++rowPtr ;
1847 }
1848 rowBoxes[numBoxes].kid = holdEnd ;
1849 return ;
1850 }
1851
1852 /****************************************************************
1853 * This routine lays out the row of boxes with the spacing specified in
1854 * the endSpace and betweenSpace parameters. If the width of a row
1855 * which contains more than one box causes the right edge of the
1856 * row to be greater than maxX, then the boxes will wrap to the next
1857 * line.
1858 * The Y coordinate of the space following the layout is returned.
1859 ****************/
1860 static Position
_XmGeoLayoutWrap(XmKidGeometry rowPtr,XmGeoRowLayout layoutPtr,int x,int y,int endSpace,int betweenSpace,int maxX,int width,int marginW)1861 _XmGeoLayoutWrap(
1862 XmKidGeometry rowPtr,
1863 XmGeoRowLayout layoutPtr,
1864 #if NeedWidePrototypes
1865 int x,
1866 int y,
1867 int endSpace,
1868 int betweenSpace,
1869 int maxX,
1870 int width,
1871 int marginW )
1872 #else
1873 Position x,
1874 Position y,
1875 Dimension endSpace,
1876 Dimension betweenSpace,
1877 Position maxX,
1878 Dimension width,
1879 Dimension marginW )
1880 #endif /* NeedWidePrototypes */
1881 {
1882 Position rowX ;
1883 Dimension rowH ;
1884 Position boxMaxX ;
1885 unsigned int numBoxes ;
1886 Dimension boxH ;
1887 int deltaW ;
1888 XmKidGeometry rowBegin ;
1889 register XmKidGeometry boxPtr ;
1890 Position endX ;
1891 /****************/
1892
1893 rowX = x + endSpace ;
1894 rowH = layoutPtr->max_box_height ;
1895 numBoxes = 0 ;
1896 rowBegin = rowPtr ;
1897 boxPtr = rowPtr ;
1898 while( boxPtr->kid )
1899 { boxMaxX = rowX + boxPtr->box.width + (boxPtr->box.border_width << 1) ;
1900
1901 if( (boxMaxX > maxX) && numBoxes )
1902 { /* Wrap the line. Also adjust preceding segment according to
1903 * fill policy.
1904 */
1905 endX = rowX - betweenSpace ;
1906 SegmentFill( rowBegin, numBoxes, layoutPtr, x, width,
1907 marginW, endX, maxX, endSpace, betweenSpace) ;
1908 numBoxes = 0 ;
1909 rowX = x + endSpace ;
1910 y += rowH ;
1911 rowBegin = boxPtr ;
1912 boxMaxX = rowX + boxPtr->box.width
1913 + (boxPtr->box.border_width << 1) ;
1914 }
1915 if( boxMaxX > maxX )
1916 { /* Since it wasn't wrapped, there must be only one box in this
1917 * segment. It is too wide, so simply truncate it.
1918 */
1919 deltaW = ((int) (endSpace + boxMaxX)) - ((int) (maxX + marginW)) ;
1920 if( (deltaW < ((int) boxPtr->box.width)) && (deltaW > 0) )
1921 { boxPtr->box.width -= deltaW ;
1922 }
1923 else
1924 { boxPtr->box.width = 1 ;
1925 }
1926 boxMaxX = rowX + boxPtr->box.width
1927 + (boxPtr->box.border_width << 1) ;
1928 }
1929 boxPtr->box.x = rowX ;
1930 boxPtr->box.y = y ;
1931 boxH = boxPtr->box.height + (boxPtr->box.border_width << 1) ;
1932 if( boxH != rowH )
1933 { /* If box height is not the same as the maximum box height
1934 * of the row, then adjust y to center the box in the row.
1935 */
1936 boxPtr->box.y += (((int) rowH - (int) boxH) >> 1) ;
1937 }
1938 rowX = boxMaxX + betweenSpace ;
1939 ++numBoxes ;
1940 ++boxPtr ;
1941 }
1942 endX = rowX - betweenSpace ;
1943 SegmentFill( rowBegin, numBoxes, layoutPtr, x, width,
1944 marginW, endX, maxX, endSpace, betweenSpace) ;
1945 if( layoutPtr->sticky_end )
1946 {
1947 boxPtr = &rowPtr[layoutPtr->box_count - 1] ;
1948 endX = maxX - (boxPtr->box.width + (boxPtr->box.border_width << 1)) ;
1949 if( endX > boxPtr->box.x )
1950 { boxPtr->box.x = endX ;
1951 }
1952 }
1953 return( y + rowH) ;
1954 }
1955 /****************************************************************
1956 * This routine does a simple layout of the boxes in the row. It assumes
1957 * that all boxes have been conditioned to fit appropriately with the
1958 * spacing specified by the endSpace and betweenSpace parameters.
1959 * The Y coordinate of the space following the layout is returned.
1960 ****************/
1961 static Position
_XmGeoLayoutSimple(XmKidGeometry rowPtr,XmGeoRowLayout layoutPtr,int x,int y,int maxX,int endSpace,int betweenSpace)1962 _XmGeoLayoutSimple(
1963 XmKidGeometry rowPtr,
1964 XmGeoRowLayout layoutPtr,
1965 #if NeedWidePrototypes
1966 int x,
1967 int y,
1968 int maxX,
1969 int endSpace,
1970 int betweenSpace )
1971 #else
1972 Position x,
1973 Position y,
1974 Position maxX,
1975 Dimension endSpace,
1976 Dimension betweenSpace )
1977 #endif /* NeedWidePrototypes */
1978 {
1979 Position rowX ;
1980 Position newX ;
1981 Dimension rowH ;
1982 Dimension boxH ;
1983 /****************/
1984
1985 rowH = layoutPtr->max_box_height ;
1986 rowX = x + endSpace ;
1987 while( rowPtr->kid )
1988 {
1989 rowPtr->box.x = rowX ;
1990 rowPtr->box.y = y ;
1991 boxH = rowPtr->box.height + (rowPtr->box.border_width << 1) ;
1992 if( boxH != rowH )
1993 { /* If box height is not the same as the maximum box height
1994 * of the row, then adjust y to center the box in the row.
1995 */
1996 rowPtr->box.y += ((rowH - boxH) >> 1) ;
1997 }
1998 rowX += rowPtr->box.width + (rowPtr->box.border_width << 1)
1999 + betweenSpace ;
2000 ++rowPtr ;
2001 }
2002 if( layoutPtr->sticky_end )
2003 {
2004 --rowPtr ;
2005 newX = maxX - (rowPtr->box.width + (rowPtr->box.border_width << 1)) ;
2006 if( newX > rowPtr->box.x )
2007 { rowPtr->box.x = newX ;
2008 }
2009 }
2010 return( y + rowH) ;
2011 }
2012
2013
2014 /****************************************************************
2015 * This routines lays out the boxes in this row according to the specified
2016 * paramaters and the policies specified in the layout record at layoutPtr.
2017 ****************/
2018 /*ARGSUSED*/
2019 static Position
_XmGeoArrangeList(XmKidGeometry rowBoxes,XmGeoRowLayout layoutPtr,int x,int y,int width,int marginW,int marginH)2020 _XmGeoArrangeList(
2021 XmKidGeometry rowBoxes,
2022 XmGeoRowLayout layoutPtr,
2023 #if NeedWidePrototypes
2024 int x,
2025 int y,
2026 int width,
2027 int marginW,
2028 int marginH ) /* unused */
2029 #else
2030 Position x,
2031 Position y,
2032 Dimension width,
2033 Dimension marginW,
2034 Dimension marginH ) /* unused */
2035 #endif /* NeedWidePrototypes */
2036 {
2037 Dimension sumW ;
2038 unsigned int numBoxes ;
2039 Dimension betweenBoxes ;
2040 Dimension endsOfBoxes ;
2041 int amtOffset ;
2042 Dimension boxWidth ;
2043 Position maxX ;
2044 Dimension totalFill ;
2045 /****************/
2046
2047 numBoxes = layoutPtr->box_count ;
2048 boxWidth = layoutPtr->boxes_width ;
2049 sumW = boxWidth + layoutPtr->fill_width + (marginW << 1) ;
2050 amtOffset = ((int) sumW) - ((int) width) ;
2051 /* Setup the default spacing.
2052 */
2053 betweenBoxes = layoutPtr->space_between ;
2054 endsOfBoxes = (layoutPtr->space_end < marginW)
2055 ? marginW : layoutPtr->space_end ;
2056 maxX = x + width - marginW ;
2057
2058 if( (sumW > width) && (layoutPtr->fit_mode == XmGEO_WRAP) )
2059 { /* Wrapping is required, so fill routines and other policy decisions
2060 * are not needed. Do the layout using the wrap routine and we're
2061 * done.
2062 */
2063 y = _XmGeoLayoutWrap( rowBoxes, layoutPtr, x, y, endsOfBoxes,
2064 betweenBoxes, maxX, width, marginW) ;
2065 }
2066 else
2067 { if( sumW > width )
2068 { switch( layoutPtr->fit_mode )
2069 { case XmGEO_AVERAGING:
2070 { FitBoxesAveraging( rowBoxes, numBoxes, boxWidth,
2071 amtOffset) ;
2072 break ;
2073 }
2074 case XmGEO_PROPORTIONAL:
2075 default:
2076 { FitBoxesProportional( rowBoxes, numBoxes, boxWidth,
2077 amtOffset) ;
2078 }
2079 }
2080 }
2081 else
2082 { if( sumW < width )
2083 { switch( layoutPtr->fill_mode )
2084 { case XmGEO_CENTER:
2085 {
2086 /* Compute new spacing values to result in a centered
2087 * layout when passed to the simple layout routine.
2088 */
2089 totalFill = (marginW << 1) + layoutPtr->fill_width
2090 + width - sumW ;
2091 _XmGeoCalcFill( totalFill, marginW, numBoxes,
2092 layoutPtr->space_end, layoutPtr->space_between,
2093 &endsOfBoxes, &betweenBoxes) ;
2094 break ;
2095 }
2096 case XmGEO_PACK:
2097 { /* For a packed layout, just layout with extra space
2098 * at the end of the row.
2099 */
2100 break ;
2101 }
2102 case XmGEO_EXPAND:
2103 default:
2104 { /* FitBoxesProportional will fill if amtOffset < 0,
2105 * as it is here.
2106 */
2107 FitBoxesProportional( rowBoxes, numBoxes, boxWidth,
2108 amtOffset) ;
2109 break ;
2110 }
2111 }
2112 }
2113 }
2114 y = _XmGeoLayoutSimple( rowBoxes, layoutPtr, x, y, maxX,
2115 endsOfBoxes, betweenBoxes) ;
2116 }
2117 return( y) ;
2118 }
2119
2120 /****************************************************************
2121 * Changes boxes in the kid geometry list to have desired width.
2122 * If width > 1, then use the specified width.
2123 * If width == 1, then use the width of the widest box.
2124 * If width == 0, then do not change the boxes but return the width of
2125 * the widest box.
2126 * Returns the value of the width actually used.
2127 ****************/
2128 Dimension
_XmGeoBoxesSameWidth(XmKidGeometry rowPtr,int width)2129 _XmGeoBoxesSameWidth(
2130 XmKidGeometry rowPtr,
2131 #if NeedWidePrototypes
2132 int width )
2133 #else
2134 Dimension width )
2135 #endif /* NeedWidePrototypes */
2136 {
2137 register XmKidGeometry boxPtr ;
2138 register Dimension useW ;
2139 /****************/
2140
2141 useW = width ; /* Setup default width of each box in row, as specified.*/
2142
2143 if( width <= 1 )
2144 {
2145 /* If user specified width parameter of zero or one, then find the
2146 * width of the widest box.
2147 */
2148 boxPtr = rowPtr ;
2149 while( boxPtr->kid )
2150 { ASSIGN_MAX( useW, boxPtr->box.width) ;
2151 ++boxPtr ;
2152 }
2153 }
2154 if( width )
2155 {
2156 /* If width parameter is non-zero, then set the boxes appropriately.
2157 */
2158 boxPtr = rowPtr ;
2159 while( boxPtr->kid )
2160 { boxPtr->box.width = useW ;
2161 ++boxPtr ;
2162 }
2163 }
2164 return( useW) ;
2165 }
2166 /****************************************************************
2167 * Changes boxes in the kid geometry list to have desired height.
2168 * If height > 1, then use the specified height.
2169 * If height == 1, then use the height of the tallest box.
2170 * If height == 0, then do not change the boxes but return the height of
2171 * the tallest box.
2172 * Returns the value of the height actually used.
2173 ****************/
2174 Dimension
_XmGeoBoxesSameHeight(XmKidGeometry rowPtr,int height)2175 _XmGeoBoxesSameHeight(
2176 XmKidGeometry rowPtr,
2177 #if NeedWidePrototypes
2178 int height )
2179 #else
2180 Dimension height )
2181 #endif /* NeedWidePrototypes */
2182 {
2183 register XmKidGeometry boxPtr ;
2184 register Dimension useH ;
2185 /****************/
2186
2187 useH = height ; /* Setup default height of each box in row, as specified.*/
2188
2189 if( height <= 1 )
2190 {
2191 /* If user specified height parameter of zero or one, then find the
2192 * height of the tallest box.
2193 */
2194 boxPtr = rowPtr ;
2195 while( boxPtr->kid )
2196 { ASSIGN_MAX( useH, boxPtr->box.height) ;
2197 ++boxPtr ;
2198 }
2199 }
2200 if( height )
2201 {
2202 /* If height parameter is non-zero, then set the boxes appropriately.
2203 */
2204 boxPtr = rowPtr ;
2205 while( boxPtr->kid )
2206 { boxPtr->box.height = useH ;
2207 ++boxPtr ;
2208 }
2209 }
2210 return( useH) ;
2211 }
2212
2213 /**************************************************************** ARGSUSED
2214 * This routine is a fixup routine which can be used for rows which consist
2215 * of a single separator widget. The effect of this routine is to have
2216 * the separator ignore the margin width.
2217 ****************/
2218 /*ARGSUSED*/
2219 void
_XmSeparatorFix(XmGeoMatrix geoSpec,int action,XmGeoMajorLayout layoutPtr,XmKidGeometry rowPtr)2220 _XmSeparatorFix(
2221 XmGeoMatrix geoSpec,
2222 int action,
2223 XmGeoMajorLayout layoutPtr, /* unused */
2224 XmKidGeometry rowPtr )
2225 {
2226 register Dimension marginW ;
2227 register Dimension twoMarginW ;
2228 /****************/
2229
2230 marginW = geoSpec->margin_w ;
2231 twoMarginW = (marginW << 1) ;
2232
2233 switch( action )
2234 {
2235 case XmGEO_PRE_SET:
2236 { rowPtr->box.x -= marginW ;
2237 rowPtr->box.width += twoMarginW ;
2238 break ;
2239 }
2240 default:
2241 { if( rowPtr->box.width > twoMarginW )
2242 {
2243 /* Avoid subtracting a margin from box width which would
2244 * result in underflow.
2245 */
2246 rowPtr->box.x += marginW ;
2247 rowPtr->box.width -= twoMarginW ;
2248 }
2249 if( action == XmGET_PREFERRED_SIZE )
2250 {
2251 /* Set width to some small value so it does not
2252 * effect total width of matrix.
2253 */
2254 rowPtr->box.width = 1 ;
2255 }
2256 break ;
2257 }
2258 }
2259 return ;
2260 }
2261
2262
2263 /**************************************************************** ARGSUSED
2264 * This routine is a fixup routine which can be used for rows which consist
2265 * of a single MenuBar RowColumn. The effect of this routine is to have
2266 * the RowColumn ignore the margin width and height.
2267 ****************/
2268 /*ARGSUSED*/
2269 void
_XmMenuBarFix(XmGeoMatrix geoSpec,int action,XmGeoMajorLayout layoutPtr,XmKidGeometry rowPtr)2270 _XmMenuBarFix(
2271 XmGeoMatrix geoSpec,
2272 int action,
2273 XmGeoMajorLayout layoutPtr, /* unused */
2274 XmKidGeometry rowPtr )
2275 {
2276 register Dimension marginW ;
2277 register Dimension marginH ;
2278 register Dimension twoMarginW ;
2279 /****************/
2280
2281 marginW = geoSpec->margin_w ;
2282 twoMarginW = (marginW << 1) ;
2283 marginH = geoSpec->margin_h ;
2284
2285 switch( action )
2286 {
2287 case XmGEO_PRE_SET:
2288 { rowPtr->box.x -= marginW ;
2289 rowPtr->box.width += twoMarginW ;
2290 rowPtr->box.y -= marginH ;
2291 break ;
2292 }
2293 default:
2294 { if( rowPtr->box.width > twoMarginW )
2295 {
2296 /* Avoid subtracting a margin from box width which would
2297 * result in underflow.
2298 */
2299 rowPtr->box.x += marginW ;
2300 rowPtr->box.width -= twoMarginW ;
2301 }
2302 if( action == XmGET_PREFERRED_SIZE )
2303 {
2304 /* Set width to some small value so it does not
2305 * effect total width of matrix.
2306 */
2307 rowPtr->box.width = 1 ;
2308 }
2309 break ;
2310 }
2311 }
2312 return ;
2313 }
2314
2315 /****************************************************************/
2316 void
_XmGeoLoadValues(Widget wid,int geoType,Widget instigator,XtWidgetGeometry * request,XtWidgetGeometry * geoResult)2317 _XmGeoLoadValues(
2318 Widget wid,
2319 int geoType,
2320 Widget instigator,
2321 XtWidgetGeometry *request,
2322 XtWidgetGeometry *geoResult )
2323 {
2324 XtWidgetGeometry reply ;
2325 XtWidgetGeometry * geoSource ;
2326 /****************/
2327
2328 if( wid == instigator )
2329 { /* If this widget is making the request, then use the request info.
2330 */
2331 geoSource = request ;
2332 }
2333 else
2334 { geoSource = &reply ;
2335
2336 switch( geoType )
2337 {
2338 case XmGET_PREFERRED_SIZE:
2339 { XtQueryGeometry( wid, NULL, &reply) ;
2340 break ;
2341 }
2342 case XmGET_ACTUAL_SIZE:
2343 default:
2344 { reply.request_mode = 0 ; /* Will cause geoSpec to be loaded.*/
2345 break ;
2346 }
2347 }
2348 }
2349 geoResult->x = IsX( geoSource) ? geoSource->x : XtX( wid) ;
2350 geoResult->y = IsY( geoSource) ? geoSource->y : XtY( wid) ;
2351 geoResult->width = IsWidth( geoSource) ? geoSource->width : XtWidth( wid) ;
2352 geoResult->height = IsHeight( geoSource)
2353 ? geoSource->height : XtHeight( wid) ;
2354 geoResult->border_width = IsBorder( geoSource)
2355 ? geoSource->border_width : XtBorderWidth( wid) ;
2356 geoResult->request_mode = CWX | CWY | CWWidth | CWHeight | CWBorderWidth ;
2357 return ;
2358 }
2359
2360 /****************************************************************
2361 * Get a count of the managed kids of a parent, it is assumed that all
2362 * gadgets are always managed
2363 ****************/
2364 int
_XmGeoCount_kids(register CompositeWidget c)2365 _XmGeoCount_kids(
2366 register CompositeWidget c )
2367 {
2368 register int i, n = 0 ;
2369 /****************/
2370
2371 for( i = 0 ; i < c->composite.num_children ; i++ )
2372 {
2373 if( c->composite.children[i]->core.managed )
2374 { n++ ;
2375 }
2376 }
2377 return( n) ;
2378 }
2379
2380 /**************************************************************** ARGSUSED
2381 * Assemble a kid box for each child widget and gadget, fill in data about
2382 * each widget and optionally set up uniform border widths.
2383 * Returns a list of records, last one has a 'kid' field of NULL. This memory
2384 * for this list should eventually be freed with a call to XtFree().
2385 ****************/
2386 /*ARGSUSED*/
2387 XmKidGeometry
_XmGetKidGeo(Widget wid,Widget instigator,XtWidgetGeometry * request,int uniform_border,int border,int uniform_width_margins,int uniform_height_margins,Widget help,int geo_type)2388 _XmGetKidGeo(
2389 Widget wid, /* Widget w/ children. */
2390 Widget instigator, /* May point to a child who */
2391 XtWidgetGeometry *request, /* is asking to change. */
2392 int uniform_border, /* T/F, enforce it. */
2393 #if NeedWidePrototypes
2394 int border,
2395 #else
2396 Dimension border, /* Value to use if enforcing.*/
2397 #endif /* NeedWidePrototypes */
2398 int uniform_width_margins, /* unused. T/F, enforce it. */
2399 int uniform_height_margins, /* unused. T/F, enforce it. */
2400 Widget help, /* May point to a help kid. */
2401 int geo_type ) /* Actual or preferred. */
2402 {
2403 CompositeWidget c = (CompositeWidget) wid ;
2404 XmKidGeometry geo ;
2405 Widget kidWid ;
2406 int i ;
2407 int j = 0 ;
2408 Boolean helpFound = FALSE ;
2409 /****************/
2410
2411 geo = (XmKidGeometry) XtMalloc(
2412 (_XmGeoCount_kids (c) + 1) * sizeof (XmKidGeometryRec)) ;
2413 /* load all managed kids */
2414 for( i = 0 ; i < c->composite.num_children ; i++ )
2415 {
2416 kidWid = c->composite.children[i] ;
2417 if( XtIsManaged( kidWid) )
2418 { if( kidWid == help )
2419 { /* Save to put help widget at the end of the widget list.*/
2420 helpFound = TRUE ;
2421 }
2422 else
2423 { geo[j].kid = kidWid ;
2424
2425 _XmGeoLoadValues( kidWid, geo_type, instigator, request,
2426 &(geo[j].box)) ;
2427 if( uniform_border ) /* if asked override border */
2428 { geo[j].box.border_width = border ;
2429 }
2430 j++ ;
2431 }
2432 }
2433 }
2434 if( helpFound ) /* put help guy into list */
2435 {
2436 geo[j].kid = help ;
2437
2438 _XmGeoLoadValues( help, geo_type, instigator, request, &(geo[j].box)) ;
2439
2440 if( uniform_border ) /* if asked override border */
2441 { geo[j].box.border_width = border ;
2442 }
2443 j++ ;
2444 }
2445 geo[j].kid = NULL ; /* signal end of list */
2446
2447 return( geo) ;
2448 }
2449
2450 /****************************************************************/
2451 void
_XmGeoClearRectObjAreas(RectObj r,XWindowChanges * old)2452 _XmGeoClearRectObjAreas(
2453 RectObj r,
2454 XWindowChanges *old )
2455 {
2456 Widget parent = XtParent( r) ;
2457 int bw2 ;
2458 /****************/
2459
2460 bw2 = old->border_width << 1;
2461 XClearArea( XtDisplay( parent), XtWindow( parent), old->x, old->y,
2462 old->width + bw2, old->height + bw2, TRUE) ;
2463
2464 bw2 = r->rectangle.border_width << 1;
2465 XClearArea( XtDisplay( parent), XtWindow( parent), (int) r->rectangle.x,
2466 (int) r->rectangle.y, (unsigned int) (r->rectangle.width + bw2),
2467 (unsigned int) (r->rectangle.height + bw2), TRUE) ;
2468 return ;
2469 }
2470
2471 /**************************************************************** ARGSUSED
2472 * Take the kid geometry array and change each kid to match them.
2473 * remember not to do the resize of the instigator.
2474 * The kid geometry "kg" is assumed to be fully specified.
2475 ****************/
2476 void
_XmSetKidGeo(XmKidGeometry kg,Widget instigator)2477 _XmSetKidGeo(
2478 XmKidGeometry kg,
2479 Widget instigator )
2480 {
2481 Widget w ;
2482 XtWidgetGeometry * b ;
2483 int i ;
2484 /****************/
2485
2486 for( i=0 ; kg[i].kid != NULL ; i++ ) {
2487 w = (Widget) kg[i].kid ;
2488 b = &(kg[i].box) ;
2489
2490 if( w != instigator ) {
2491 XmeConfigureObject( w, b->x, b->y,
2492 b->width, b->height, b->border_width) ;
2493 } else {
2494 XtX( w) = b->x ;
2495 XtY( w) = b->y ;
2496 XtWidth( w) = b->width ;
2497 XtHeight( w) = b->height ;
2498 XtBorderWidth( w) = b->border_width ;
2499 }
2500 }
2501 return ;
2502 }
2503
2504 /****************************************************************
2505 * Returns TRUE if all specified geometries of geoA are equal to either the
2506 * specified geometries of geoB or to the geometry of the widget, and
2507 * vice versa. The XtCWQueryOnly bit is ignored.
2508 ****************/
2509 Boolean
_XmGeometryEqual(Widget wid,XtWidgetGeometry * geoA,XtWidgetGeometry * geoB)2510 _XmGeometryEqual(
2511 Widget wid,
2512 XtWidgetGeometry *geoA,
2513 XtWidgetGeometry *geoB )
2514 {
2515 /****************/
2516 if(!geoA){ /* For fixing OSF CR 5956 */
2517 return(False);
2518 }
2519
2520 if( IsWidth( geoA) || IsWidth( geoB) )
2521 {
2522 if( IsWidth( geoA) && IsWidth( geoB) )
2523 { if( geoA->width != geoB->width )
2524 { return( FALSE) ;
2525 }
2526 }
2527 else
2528 { if( IsWidth( geoA) )
2529 { if( geoA->width != XtWidth( wid) )
2530 { return( FALSE) ;
2531 }
2532 }
2533 else
2534 { if( IsWidth( geoB) )
2535 { if( geoB->width != XtWidth( wid) )
2536 { return( FALSE) ;
2537 }
2538 }
2539 }
2540 }
2541 }
2542 if( IsHeight( geoA) || IsHeight( geoB) )
2543 {
2544 if( IsHeight( geoA) && IsHeight( geoB) )
2545 { if( geoA->height != geoB->height )
2546 { return( FALSE) ;
2547 }
2548 }
2549 else
2550 { if( IsHeight( geoA) )
2551 { if( geoA->height != XtHeight( wid) )
2552 { return( FALSE) ;
2553 }
2554 }
2555 else
2556 { if( IsHeight( geoB) )
2557 { if( geoB->height != XtHeight( wid) )
2558 { return( FALSE) ;
2559 }
2560 }
2561 }
2562 }
2563 }
2564 if( IsBorder( geoA) || IsBorder( geoB) )
2565 {
2566 if( IsBorder( geoA) && IsBorder( geoB) )
2567 { if( geoA->border_width != geoB->border_width )
2568 { return( FALSE) ;
2569 }
2570 }
2571 else
2572 { if( IsBorder( geoA) )
2573 { if( geoA->border_width != XtBorderWidth( wid) )
2574 { return( FALSE) ;
2575 }
2576 }
2577 else
2578 { if( IsBorder( geoB) )
2579 { if( geoB->border_width != XtBorderWidth( wid) )
2580 { return( FALSE) ;
2581 }
2582 }
2583 }
2584 }
2585 }
2586 if( IsX( geoA) || IsX( geoB) )
2587 {
2588 if( IsX( geoA) && IsX( geoB) )
2589 { if( geoA->x != geoB->x )
2590 { return( FALSE) ;
2591 }
2592 }
2593 else
2594 { if( IsX( geoA) )
2595 { if( geoA->x != XtX( wid) )
2596 { return( FALSE) ;
2597 }
2598 }
2599 else
2600 { if( IsX( geoB) )
2601 { if( geoB->x != XtX( wid) )
2602 { return( FALSE) ;
2603 }
2604 }
2605 }
2606 }
2607 }
2608 if( IsY( geoA) || IsY( geoB) )
2609 {
2610 if( IsY( geoA) && IsY( geoB) )
2611 { if( geoA->y != geoB->y )
2612 { return( FALSE) ;
2613 }
2614 }
2615 else
2616 { if( IsY( geoA) )
2617 { if( geoA->y != XtY( wid) )
2618 { return( FALSE) ;
2619 }
2620 }
2621 else
2622 { if( IsY( geoB) )
2623 { if( geoB->y != XtY( wid) )
2624 { return( FALSE) ;
2625 }
2626 }
2627 }
2628 }
2629 }
2630 return( TRUE) ;
2631 }
2632
2633 /****************************************************************
2634 * Returns TRUE if all specified geometries of "desired" correspond to
2635 * specified geometries of "response" and are equal to them.
2636 * The XtCWQueryOnly bit is ignored.
2637 ****************/
2638 /*ARGSUSED*/
2639 Boolean
_XmGeoReplyYes(Widget wid,XtWidgetGeometry * desired,XtWidgetGeometry * response)2640 _XmGeoReplyYes(
2641 Widget wid, /* unused */
2642 XtWidgetGeometry *desired,
2643 XtWidgetGeometry *response )
2644 {
2645 /****************/
2646 if(!response){ /* For fixing OSF CR 5956 */
2647 return(False);
2648 }
2649 if( IsWidth( desired) )
2650 {
2651 if( !IsWidth( response)
2652 || (desired->width != response->width) )
2653 {
2654 return( FALSE) ;
2655 }
2656 }
2657 if( IsHeight( desired) )
2658 {
2659 if( !IsHeight( response)
2660 || (desired->height != response->height) )
2661 {
2662 return( FALSE) ;
2663 }
2664 }
2665 if( IsBorder( desired) )
2666 {
2667 if( !IsBorder( response)
2668 || (desired->border_width != response->border_width) )
2669 {
2670 return( FALSE) ;
2671 }
2672 }
2673 if( IsX( desired) )
2674 {
2675 if( !IsX( response)
2676 || (desired->x != response->x) )
2677 {
2678 return( FALSE) ;
2679 }
2680 }
2681 if( IsY( desired) )
2682 {
2683 if( !IsY( response)
2684 || (desired->y != response->y) )
2685 {
2686 return( FALSE) ;
2687 }
2688 }
2689 return( TRUE) ;
2690 }
2691
2692 /****************************************************************
2693 * This routine calls the geometry manager and accept the almost
2694 ****************/
2695 XtGeometryResult
_XmMakeGeometryRequest(Widget w,XtWidgetGeometry * geom)2696 _XmMakeGeometryRequest(
2697 Widget w,
2698 XtWidgetGeometry *geom )
2699 {
2700 XtWidgetGeometry allowed ;
2701 XtGeometryResult answer ;
2702 /****************/
2703
2704 answer = XtMakeGeometryRequest( w, geom, &allowed) ;
2705
2706 /* On an almost, accept the returned value and make
2707 * a second request to get an XtGeometryYes returned.
2708 */
2709 if( answer == XtGeometryAlmost )
2710 {
2711 /* The Intrinsics protocol guarantees a Yes response
2712 * to a request with identical geometry to that which
2713 * was returned by a previous request returning almost.
2714 */
2715 *geom = allowed ;
2716 answer = XtMakeGeometryRequest( w, geom, &allowed) ;
2717 }
2718 return answer ;
2719 }
2720
2721
2722 /****************************************************************/
2723 #ifdef DEBUG_GEOUTILS
2724 /****************************************************************/
2725 void
PrintBox(char * hdr,XmKidGeometry box)2726 PrintBox(
2727 char * hdr,
2728 XmKidGeometry box)
2729 /****************
2730 *
2731 ****************/
2732 {
2733 /****************/
2734 printf( "%sw: %X, m: 0x%X, x: %d, y: %d, w: %d, h: %d, b: %d\n",
2735 hdr, box->kid, box->box.request_mode, box->box.x, box->box.y,
2736 box->box.width, box->box.height, box->box.border_width) ;
2737 return ;
2738 }
2739 /****************************************************************/
2740 void
PrintList(char * hdr,XmKidGeometry listPtr)2741 PrintList(
2742 char * hdr,
2743 XmKidGeometry listPtr)
2744 /****************
2745 *
2746 ****************/
2747 {
2748 int num ;
2749 char subhdr[256] ;
2750 /****************/
2751
2752 num = 0 ;
2753 while( listPtr->kid )
2754 { sprintf( subhdr, "%si: %d ", hdr, num) ;
2755 PrintBox( subhdr, listPtr) ;
2756 ++num ;
2757 ++listPtr ;
2758 }
2759 return ;
2760 }
2761
2762 /****************************************************************/
2763 void
PrintMatrix(char * hdr,XmGeoMatrix spec)2764 PrintMatrix(
2765 char * hdr,
2766 XmGeoMatrix spec)
2767 /****************
2768 *
2769 ****************/
2770 {
2771 int row ;
2772 int col ;
2773 XmKidGeometry boxPtr ;
2774 XmGeoRowLayout layoutPtr ;
2775 char subhdr[256] ;
2776 /****************/
2777 row = 1 ;
2778 boxPtr = spec->boxes ;
2779 layoutPtr = spec->layouts.row ;
2780 while( !(layoutPtr->end) )
2781 { col = 1 ;
2782 while( boxPtr->kid )
2783 { sprintf( subhdr, "%srow: %d, col: %d, ", hdr, row, col) ;
2784 PrintBox( subhdr, boxPtr) ;
2785 ++col ;
2786 ++boxPtr ;
2787 }
2788 ++row ;
2789 ++boxPtr ;
2790 ++layoutPtr ;
2791 }
2792 return ;
2793 }
2794 /****************************************************************/
2795 #endif /* DEBUG_GEOUTILS */
2796 /****************************************************************/
2797