1 /***********************************************************
2 
3 Copyright 1987, 1988, 1994, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24 
25 
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
27 
28                         All Rights Reserved
29 
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
37 
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
45 
46 ******************************************************************/
47 
48 /*
49  * Updated and significantly modified from the Athena VPaned Widget.
50  *
51  * Date:    March 1, 1989
52  *
53  * By:      Chris D. Peterson
54  *          MIT X Consortium
55  *          kit@expo.lcs.mit.edu
56  */
57 
58 #ifdef HAVE_CONFIG_H
59 #include <config.h>
60 #endif
61 #include <X11/IntrinsicP.h>
62 #include <X11/cursorfont.h>
63 #include <X11/StringDefs.h>
64 #include <X11/Xmu/CharSet.h>
65 #include <X11/Xmu/Converters.h>
66 #include <X11/Xmu/Misc.h>
67 #include <X11/Xaw/Grip.h>
68 #include <X11/Xaw/PanedP.h>
69 #include <X11/Xaw/XawImP.h>
70 #include <X11/Xaw/XawInit.h>
71 #include "Private.h"
72 
73 typedef enum {
74   UpLeftPane = 'U',
75   LowRightPane = 'L',
76   ThisBorderOnly = 'T',
77   AnyPane = 'A'
78 } Direction;
79 
80 #define NO_INDEX -100
81 #define IS_GRIP  NULL
82 
83 #define PaneInfo(w)	((Pane)(w)->core.constraints)
84 #define HasGrip(w)	(PaneInfo(w)->grip != NULL)
85 #define IsPane(w)	((w)->core.widget_class != gripWidgetClass)
86 #define PaneIndex(w)	(PaneInfo(w)->position)
87 #define IsVert(w)	((w)->paned.orientation == XtorientVertical)
88 
89 #define ForAllPanes(pw, childP) \
90 for ((childP) = (pw)->composite.children;				\
91      (childP) < (pw)->composite.children + (pw)->paned.num_panes;	\
92      (childP)++)
93 
94 #define ForAllChildren(pw, childP) \
95 for ((childP) = (pw)->composite.children;				 \
96      (childP) < (pw)->composite.children + (pw)->composite.num_children; \
97      (childP)++)
98 
99 #define PaneSize(paned, vertical)			\
100      ((vertical) ? XtHeight(paned) : XtWidth(paned))
101 
102 #define GetRequestInfo(geo, vertical)			\
103      ((vertical) ? (geo)->height : (geo)->width)
104 
105 #define SatisfiesRule1(pane, shrink)			\
106      (((shrink) && ((pane)->size != (pane)->min))	\
107       || (!(shrink) && ((pane)->size != (pane)->max)))
108 
109 #define SatisfiesRule2(pane)					\
110      (!(pane)->skip_adjust || (pane)->paned_adjusted_me)
111 
112 #define SatisfiesRule3(pane, shrink)					\
113      ((pane)->paned_adjusted_me						\
114       && (((shrink) && ((int)(pane)->wp_size <= (pane)->size))		\
115 	  || (!(shrink) && ((int)(pane)->wp_size >= (pane)->size))))
116 
117 
118 /*
119  * Class Methods
120  */
121 static void XawPanedClassInitialize(void);
122 static void XawPanedChangeManaged(Widget);
123 static void XawPanedDeleteChild(Widget);
124 static void XawPanedDestroy(Widget);
125 static XtGeometryResult XawPanedGeometryManager(Widget, XtWidgetGeometry*,
126 						XtWidgetGeometry*);
127 static void XawPanedInitialize(Widget, Widget, ArgList, Cardinal*);
128 static void XawPanedInsertChild(Widget);
129 static Boolean XawPanedPaneSetValues(Widget, Widget, Widget,
130 				     ArgList, Cardinal*);
131 static void XawPanedRealize(Widget, Mask*, XSetWindowAttributes*);
132 static void XawPanedRedisplay(Widget, XEvent*, Region);
133 static void XawPanedResize(Widget);
134 static Boolean XawPanedSetValues(Widget, Widget, Widget, ArgList, Cardinal*);
135 
136 /*
137  * Prototypes
138  */
139 static void _DrawInternalBorders(PanedWidget, GC);
140 static void _DrawRect(PanedWidget, GC, int, int, unsigned int, unsigned int);
141 static void _DrawTrackLines(PanedWidget, Bool);
142 static void AdjustPanedSize(PanedWidget, unsigned int, XtGeometryResult*,
143 			    Dimension*, Dimension*);
144 static void ChangeAllGripCursors(PanedWidget);
145 static Pane ChoosePaneToResize(PanedWidget, int, Direction, Bool);
146 static void ClearPaneStack(PanedWidget);
147 static void CommitGripAdjustment(PanedWidget);
148 static void CreateGrip(Widget);
149 static int GetEventLocation(PanedWidget, XEvent*);
150 static void GetGCs(Widget);
151 static void GetPaneStack(PanedWidget, Bool, Pane*, int*);
152 static void HandleGrip(Widget, XtPointer, XtPointer);
153 static void LoopAndRefigureChildren(PanedWidget, int, Direction, int*);
154 static void ManageAndUnmanageGrips(PanedWidget);
155 static void MoveGripAdjustment(PanedWidget, Widget, Direction, int);
156 static Bool PopPaneStack(PanedWidget);
157 static void PushPaneStack(PanedWidget, Pane);
158 static void RefigureLocations(PanedWidget, int, Direction);
159 static void RefigureLocationsAndCommit(Widget);
160 static void ReleaseGCs(Widget);
161 static void ResortChildren(PanedWidget);
162 static void SetChildrenPrefSizes(PanedWidget, unsigned int);
163 static void StartGripAdjustment(PanedWidget, Widget, Direction);
164 
165 /*
166  * Initialization
167  */
168 static char defGripTranslations[] =
169 "<Btn1Down>:"		"GripAction(Start,UpLeftPane)\n"
170 "<Btn2Down>:"		"GripAction(Start,ThisBorderOnly)\n"
171 "<Btn3Down>:"		"GripAction(Start,LowRightPane)\n"
172 "<Btn1Motion>:"		"GripAction(Move,UpLeft)\n"
173 "<Btn2Motion>:"		"GripAction(Move,ThisBorder)\n"
174 "<Btn3Motion>:"		"GripAction(Move,LowRight)\n"
175 "Any<BtnUp>:"		"GripAction(Commit)\n"
176 ;
177 
178 #define offset(field) XtOffsetOf(PanedRec, paned.field)
179 static XtResource resources[] = {
180   {
181     XtNinternalBorderColor,
182     XtCBorderColor,
183     XtRPixel,
184     sizeof(Pixel),
185     offset(internal_bp),
186     XtRString,
187     (XtPointer)XtDefaultForeground
188   },
189   {
190     XtNinternalBorderWidth,
191     XtCBorderWidth,
192     XtRDimension,
193     sizeof(Dimension),
194     offset(internal_bw),
195     XtRImmediate,
196     (XtPointer)1
197   },
198   {
199     XtNgripIndent,
200     XtCGripIndent,
201     XtRPosition,
202     sizeof(Position),
203     offset(grip_indent),
204     XtRImmediate,
205     (XtPointer)10
206   },
207   {
208     XtNrefigureMode,
209     XtCBoolean,
210     XtRBoolean,
211     sizeof(Boolean),
212     offset(refiguremode),
213     XtRImmediate,
214     (XtPointer)True
215   },
216   {
217     XtNgripTranslations,
218     XtCTranslations,
219     XtRTranslationTable,
220     sizeof(XtTranslations),
221     offset(grip_translations),
222     XtRString,
223     (XtPointer)defGripTranslations
224   },
225   {
226     XtNorientation,
227     XtCOrientation,
228     XtROrientation,
229     sizeof(XtOrientation),
230     offset(orientation),
231     XtRImmediate,
232     (XtPointer)XtorientVertical
233   },
234   {
235     XtNcursor,
236     XtCCursor,
237     XtRCursor,
238     sizeof(Cursor),
239     offset(cursor),
240     XtRImmediate,
241     NULL
242   },
243   {
244     XtNgripCursor,
245     XtCCursor,
246     XtRCursor,
247     sizeof(Cursor),
248     offset(grip_cursor),
249     XtRImmediate,
250     NULL
251   },
252   {
253     XtNverticalGripCursor,
254     XtCCursor,
255     XtRCursor,
256     sizeof(Cursor),
257     offset(v_grip_cursor),
258     XtRString,
259     (XtPointer)"sb_v_double_arrow"
260   },
261   {
262     XtNhorizontalGripCursor,
263     XtCCursor,
264     XtRCursor,
265     sizeof(Cursor),
266     offset(h_grip_cursor),
267     XtRString,
268     (XtPointer)"sb_h_double_arrow"
269   },
270   {
271     XtNbetweenCursor,
272     XtCCursor,
273     XtRCursor,
274     sizeof(Cursor),
275     offset(adjust_this_cursor),
276     XtRString,
277     NULL
278   },
279   {
280     XtNverticalBetweenCursor,
281     XtCCursor,
282     XtRCursor,
283     sizeof(Cursor),
284     offset(v_adjust_this_cursor),
285     XtRString,
286     (XtPointer)"sb_left_arrow"
287   },
288   {
289     XtNhorizontalBetweenCursor,
290     XtCCursor,
291     XtRCursor,
292     sizeof(Cursor),
293     offset(h_adjust_this_cursor),
294     XtRString,
295     (XtPointer)"sb_up_arrow"
296   },
297   {
298     XtNupperCursor,
299     XtCCursor,
300     XtRCursor,
301     sizeof(Cursor),
302     offset(adjust_upper_cursor),
303     XtRString,
304     (XtPointer)"sb_up_arrow"
305   },
306   {
307     XtNlowerCursor,
308     XtCCursor,
309     XtRCursor,
310     sizeof(Cursor),
311     offset(adjust_lower_cursor),
312     XtRString,
313     (XtPointer)"sb_down_arrow"
314   },
315   {
316     XtNleftCursor,
317     XtCCursor,
318     XtRCursor,
319     sizeof(Cursor),
320     offset(adjust_left_cursor),
321     XtRString,
322     (XtPointer)"sb_left_arrow"
323   },
324   {
325     XtNrightCursor,
326     XtCCursor,
327     XtRCursor,
328     sizeof(Cursor),
329     offset(adjust_right_cursor),
330     XtRString,
331     (XtPointer)"sb_right_arrow"
332   },
333 };
334 #undef offset
335 
336 #define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field)
337 static XtResource subresources[] = {
338   {
339     XtNallowResize,
340     XtCBoolean,
341     XtRBoolean,
342     sizeof(Boolean),
343     offset(allow_resize),
344     XtRImmediate,
345     (XtPointer)False
346   },
347   {
348     XtNposition,
349     XtCPosition,
350     XtRInt,
351     sizeof(int),
352     offset(position),
353     XtRImmediate,
354     (XtPointer)0
355   },
356   {
357     XtNmin,
358     XtCMin,
359     XtRDimension,
360     sizeof(Dimension),
361     offset(min),
362     XtRImmediate,
363     (XtPointer)PANED_GRIP_SIZE
364   },
365   {
366     XtNmax,
367     XtCMax,
368     XtRDimension,
369     sizeof(Dimension),
370     offset(max),
371     XtRImmediate,
372     (XtPointer)~0
373   },
374   {
375     XtNpreferredPaneSize,
376     XtCPreferredPaneSize,
377     XtRDimension,
378     sizeof(Dimension),
379     offset(preferred_size),
380     XtRImmediate,
381     (XtPointer)PANED_ASK_CHILD
382   },
383   {
384     XtNresizeToPreferred,
385     XtCBoolean,
386     XtRBoolean,
387     sizeof(Boolean),
388     offset(resize_to_pref),
389     XtRImmediate,
390     (XtPointer)False
391   },
392   {
393     XtNskipAdjust,
394     XtCBoolean,
395     XtRBoolean,
396     sizeof(Boolean),
397     offset(skip_adjust),
398     XtRImmediate,
399     (XtPointer)False
400   },
401   {
402     XtNshowGrip,
403     XtCShowGrip,
404     XtRBoolean,
405     sizeof(Boolean),
406     offset(show_grip),
407     XtRImmediate,
408     (XtPointer)True
409   },
410 };
411 #undef offset
412 
413 #define SuperClass ((ConstraintWidgetClass)&constraintClassRec)
414 
415 PanedClassRec panedClassRec = {
416    /* core */
417    {
418     (WidgetClass)SuperClass,		/* superclass */
419     "Paned",				/* class name */
420     sizeof(PanedRec),			/* size */
421     XawPanedClassInitialize,		/* class_initialize */
422     NULL,				/* class_part init */
423     False,				/* class_inited */
424     XawPanedInitialize,			/* initialize */
425     NULL,				/* initialize_hook */
426     XawPanedRealize,			/* realize */
427     NULL,				/* actions */
428     0,					/* num_actions */
429     resources,				/* resources */
430     XtNumber(resources),		/* num_resources */
431     NULLQUARK,				/* xrm_class */
432     True,				/* compress_motion */
433     True,				/* compress_exposure */
434     True,				/* compress_enterleave */
435     False,				/* visible_interest */
436     XawPanedDestroy,			/* destroy */
437     XawPanedResize,			/* resize */
438     XawPanedRedisplay,			/* expose */
439     XawPanedSetValues,			/* set_values */
440     NULL,				/* set_values_hook */
441     XtInheritSetValuesAlmost,		/* set_values_almost */
442     NULL,				/* get_values_hook */
443     NULL,				/* accept_focus */
444     XtVersion,				/* version */
445     NULL,				/* callback_private */
446     NULL,				/* tm_table */
447     XtInheritQueryGeometry,		/* query_geometry */
448     XtInheritDisplayAccelerator,	/* display_accelerator */
449     NULL,				/* extension */
450   },
451   /* composite */
452   {
453     XawPanedGeometryManager,		/* geometry_manager */
454     XawPanedChangeManaged,		/* change_managed */
455     XawPanedInsertChild,		/* insert_child */
456     XawPanedDeleteChild,		/* delete_child */
457     NULL,				/* extension */
458   },
459   /* constraint */
460   {
461     subresources,			/* subresources */
462     XtNumber(subresources),		/* subresource_count */
463     sizeof(PanedConstraintsRec),	/* constraint_size */
464     NULL,				/* initialize */
465     NULL,				/* destroy */
466     XawPanedPaneSetValues,		/* set_values */
467     NULL,				/* extension */
468   },
469 };
470 
471 WidgetClass panedWidgetClass = (WidgetClass)&panedClassRec;
472 WidgetClass vPanedWidgetClass = (WidgetClass)&panedClassRec;
473 
474 /*
475  * Implementation
476  */
477 /* Function:
478  *	AdjustPanedSize
479  *
480  * Parameters:
481  *	pw	     - paned widget to adjust
482  *	off_size     - new off_size to use
483  *	result_ret   - result of query (return)
484  *	on_size_ret  - new on_size  (return)
485  *	off_size_ret - new off_size (return)
486  *
487  * Description:
488  *	Adjusts the size of the pane.
489  *
490  * Returns:
491  *	amount of change in size
492  */
493 static void
AdjustPanedSize(PanedWidget pw,unsigned int off_size,XtGeometryResult * result_ret,Dimension * on_size_ret,Dimension * off_size_ret)494 AdjustPanedSize(PanedWidget pw, unsigned int off_size,
495 		XtGeometryResult *result_ret,
496 		Dimension *on_size_ret, Dimension *off_size_ret)
497 {
498     Dimension old_size = PaneSize((Widget)pw, IsVert(pw));
499     Dimension newsize = 0;
500     Widget *childP;
501     XtWidgetGeometry request, reply;
502 
503     request.request_mode = CWWidth | CWHeight;
504 
505     ForAllPanes(pw, childP) {
506 	int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min);
507 
508 	AssignMin(size, (int)PaneInfo(*childP)->max);
509 	newsize = (newsize + (size + pw->paned.internal_bw));
510     }
511     newsize = (Dimension)(newsize - pw->paned.internal_bw);
512 
513     if (newsize < 1)
514 	newsize = 1;
515 
516     if (IsVert(pw)) {
517 	request.width = (Dimension)off_size;
518 	request.height = newsize;
519     }
520     else {
521 	request.width = newsize;
522 	request.height = (Dimension)off_size;
523     }
524 
525     if (result_ret != NULL) {
526 	request.request_mode |= XtCWQueryOnly;
527 
528 	*result_ret = XtMakeGeometryRequest((Widget)pw, &request, &reply);
529 	_XawImCallVendorShellExtResize((Widget)pw);
530 
531 	if (newsize == old_size || *result_ret == XtGeometryNo) {
532 	    *on_size_ret = old_size;
533 	    *off_size_ret = (Dimension)off_size;
534 	    return;
535 	}
536 	if (*result_ret != XtGeometryAlmost) {
537 	    *on_size_ret = GetRequestInfo(&request, IsVert(pw));
538 	    *off_size_ret = GetRequestInfo(&request, !IsVert(pw));
539 	    return;
540 	}
541 	*on_size_ret = GetRequestInfo(&reply, IsVert(pw));
542 	*off_size_ret = GetRequestInfo(&reply, !IsVert(pw));
543 	return;
544     }
545 
546     if (newsize == old_size)
547 	return;
548 
549     if (XtMakeGeometryRequest((Widget)pw, &request, &reply) == XtGeometryAlmost)
550 	XtMakeGeometryRequest((Widget)pw, &reply, &request);
551 }
552 
553 /*
554  * Function:
555  *	ChoosePaneToResize.
556  *
557  * Parameters:
558  *	pw	  - paned widget
559  *	paneindex - index of the current pane
560  *	dir	  - direction to search first
561  *	shrink	  - True if we need to shrink a pane, False otherwise
562  *
563  * Description:
564  *	  This function chooses a pane to resize.
565  *	  They are chosen using the following rules:
566  *
567  *		   1) size < max && size > min
568  *	2) skip adjust == False
569  *	3) widget not its prefered height
570  *	   && this change will bring it closer
571  *	   && The user has not resized this pane.
572  *
573  *		   If no widgets are found that fits all the rules then
574  *		      rule #3 is broken.
575  *		   If there are still no widgets found than
576  *		      rule #2 is broken.
577  *		   Rule #1 is never broken.
578  *		   If no widgets are found then NULL is returned.
579  *
580  * Returns:
581  *	pane to resize or NULL
582  */
583 static Pane
ChoosePaneToResize(PanedWidget pw,int paneindex,Direction dir,Bool shrink)584 ChoosePaneToResize(PanedWidget pw, int paneindex, Direction dir, Bool shrink)
585 {
586     Widget *childP;
587     int rules = 3;
588     Direction _dir = dir;
589     int _index = paneindex;
590 
591     if (paneindex == NO_INDEX || dir == AnyPane) {		/* Use defaults */
592 	_dir = LowRightPane;			/* Go up - really */
593 	_index = pw->paned.num_panes - 1;	/* Start the last pane, and work
594 						   backwards */
595     }
596     childP = pw->composite.children + _index;
597 
598     /*CONSTCOND*/
599     while(True) {
600 	Pane pane = PaneInfo(*childP);
601 
602 	if ((rules < 3 || SatisfiesRule3(pane, shrink))
603 	    && (rules < 2 || SatisfiesRule2(pane))
604 	    && SatisfiesRule1(pane, shrink)
605 	    && (paneindex != PaneIndex(*childP) || dir == AnyPane))
606 	    return (pane);
607 
608 	/*
609 	 * This is counter-intuitive, but if we are resizing the pane
610 	 * above the grip we want to choose a pane below the grip to lose,
611 	 * and visa-versa
612 	 */
613 	if (_dir == LowRightPane)
614 	    --childP;
615 	else
616 	    ++childP;
617 
618 	/*
619 	 * If we have come to and edge then reduce the rule set, and try again
620 	 * If we are reduced the rules to none, then return NULL
621 	 */
622 	if ((childP - pw->composite.children) < 0 ||
623 	    (childP - pw->composite.children) >= pw->paned.num_panes) {
624 	    if (--rules < 1)	/* less strict rules */
625 		return (NULL);
626 	    childP = pw->composite.children + _index;
627 	}
628     }
629 }
630 
631 /*
632  * Function:
633  *	LoopAndRefigureChildren
634  *
635  * Parameters:
636  *	pw	  - paned widget
637  *	paneindex - number of the pane border we are moving
638  *	dir	  - pane to move (either UpLeftPane or LowRightPane)
639  *	sizeused  - current amount of space used (used and returned)
640  *
641  * Description:
642  *	  If we are resizing either the UpleftPane or LowRight Pane loop
643  *	through all the children to see if any will allow us to resize them.
644  */
645 static void
LoopAndRefigureChildren(PanedWidget pw,int paneindex,Direction dir,int * sizeused)646 LoopAndRefigureChildren(PanedWidget pw, int paneindex, Direction dir,
647 			int *sizeused)
648 {
649     int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
650     Boolean shrink = (*sizeused > pane_size);
651 
652     if (dir == LowRightPane)
653 	paneindex++;
654 
655     /* While all panes do not fit properly */
656     while (*sizeused != pane_size) {
657 	/*
658 	 * Choose a pane to resize
659 	 * First look on the Pane Stack, and then go hunting for another one
660 	 * If we fail to find a pane to resize then give up
661 	 */
662 	Pane pane;
663 	int start_size;
664 	Dimension old;
665 	Boolean rule3_ok = False, from_stack = True;
666 
667 	GetPaneStack(pw, shrink, &pane, &start_size);
668 	if (pane == NULL) {
669 	    pane = ChoosePaneToResize(pw, paneindex, dir, shrink);
670 	    if (pane == NULL)
671 		return; /* no one to resize, give up */
672 
673 	    rule3_ok = SatisfiesRule3(pane, shrink);
674 	    from_stack = False;
675 	    PushPaneStack(pw, pane);
676 	}
677 
678 	/*
679 	 * Try to resize this pane so that all panes will fit, take min and max
680 	 * into account
681 	 */
682 	old = (Dimension) pane->size;
683 	pane->size += pane_size - *sizeused;
684 
685 	if (from_stack) {
686 	    if (shrink) {
687 		AssignMax(pane->size, start_size);
688 	    }	/* don't remove these braces */
689 	    else
690 		AssignMin(pane->size, start_size);
691 
692 	  if (pane->size == start_size)
693 	    (void)PopPaneStack(pw);
694 	}
695 	else if (rule3_ok) {
696 	    if (shrink) {
697 		AssignMax(pane->size, (int)pane->wp_size);
698 	    }	/* don't remove these braces */
699 	    else
700 		AssignMin(pane->size, (int)pane->wp_size);
701 	}
702 
703 	pane->paned_adjusted_me = pane->size != pane->wp_size;
704 	AssignMax(pane->size, (int)pane->min);
705 	AssignMin(pane->size, (int)pane->max);
706 	*sizeused += (pane->size - old);
707     }
708 }
709 
710 /*
711  * Function:
712  *	RefigureLocations
713  *
714  * Parameters:
715  *	pw	  - paned widget
716  *	paneindex - child to start refiguring at
717  *	dir	  - direction to move from child
718  *
719  * Description:
720  *	  Refigures all locations of children.
721  *      There are special arguments to paneindex and dir, they are:
722  *      paneindex - NO_INDEX.
723  *      dir   - AnyPane.
724  *
725  *      If either of these is true then all panes may be resized and
726  *      the choosing of panes procedes in reverse order starting with the
727  *      last child.
728  */
729 static void
RefigureLocations(PanedWidget pw,int paneindex,Direction dir)730 RefigureLocations(PanedWidget pw, int paneindex, Direction dir)
731 {
732     Widget *childP;
733     int pane_size = (int)PaneSize((Widget)pw, IsVert(pw));
734     int sizeused = 0;
735     Position loc = 0;
736 
737     if (pw->paned.num_panes == 0 || !pw->paned.refiguremode)
738 	return;
739 
740     /*
741      * Get an initial estimate of the size we will use
742      */
743     ForAllPanes(pw, childP) {
744 	Pane pane = PaneInfo(*childP);
745 
746 	AssignMax(pane->size, (int) pane->min);
747 	AssignMin(pane->size, (int) pane->max);
748 	sizeused += (int)pane->size + (int)pw->paned.internal_bw;
749     }
750     sizeused -= (int)pw->paned.internal_bw;
751 
752     if (dir != ThisBorderOnly && sizeused != pane_size)
753 	LoopAndRefigureChildren(pw, paneindex, dir, &sizeused);
754 
755     /*
756      * If we still are not the right size, then tell the pane that
757      * wanted to resize that it can't
758      */
759     if (paneindex != NO_INDEX && dir != AnyPane) {
760 	Pane pane = PaneInfo(*(pw->composite.children + paneindex));
761 	Dimension old = (Dimension)pane->size;
762 
763 	pane->size += pane_size - sizeused;
764 	AssignMax(pane->size, (int) pane->min);
765 	AssignMin(pane->size, (int) pane->max);
766 	sizeused += pane->size - old;
767     }
768 
769     /*
770      * It is possible that the panes will not fit inside the vpaned widget, but
771      * we have tried out best
772      *
773      * Assign each pane a location
774      */
775     ForAllPanes(pw, childP) {
776 	PaneInfo(*childP)->delta = loc;
777 	loc = (Position)(loc + (PaneInfo(*childP)->size + pw->paned.internal_bw));
778     }
779 }
780 
781 /*
782  * Function:
783  *	CommitNewLocations
784  *
785  * Parameters:
786  *	pw - paned widget
787  *
788  * Description:
789  *	Commits all of the previously figured locations.
790  */
791 static void
CommitNewLocations(PanedWidget pw)792 CommitNewLocations(PanedWidget pw)
793 {
794     Widget *childP;
795     XWindowChanges changes;
796 
797     changes.stack_mode = Above;
798 
799     ForAllPanes(pw, childP) {
800 	Pane pane = PaneInfo(*childP);
801 	Widget grip = pane->grip;	/* may be NULL */
802 
803 	if (IsVert(pw)) {
804 	    XtMoveWidget(*childP, (Position) 0, pane->delta);
805 	    XtResizeWidget(*childP, XtWidth(pw), (Dimension)pane->size, 0);
806 
807 	    if (HasGrip(*childP)) {	/* Move and Display the Grip */
808 		changes.x = XtWidth(pw) - pw->paned.grip_indent -
809 			    XtWidth(grip) - (XtBorderWidth(grip) << 1);
810 		changes.y = XtY(*childP) + XtHeight(*childP) -
811 			    (XtHeight(grip) >> 1) - XtBorderWidth(grip) +
812 			    (pw->paned.internal_bw >> 1);
813 	    }
814 	}
815 	else {
816 	    XtMoveWidget(*childP, pane->delta, 0);
817 	    XtResizeWidget(*childP, (Dimension)pane->size, (Dimension)XtHeight(pw), 0);
818 
819 	    if (HasGrip(*childP)) {		/* Move and Display the Grip */
820 		changes.x = XtX(*childP) + XtWidth(*childP) -
821 			    (XtWidth(grip) >> 1) - XtBorderWidth(grip) +
822 			    (pw->paned.internal_bw >> 1);
823 		changes.y = XtHeight(pw) - pw->paned.grip_indent -
824 			    XtHeight(grip) - (XtBorderWidth(grip) << 1);
825 	    }
826 	}
827 
828 	/*
829 	 * This should match XtMoveWidget, except that we're also insuring the
830 	 * grip is Raised in the same request
831 	 */
832 
833 	if (HasGrip(*childP)) {
834 	    XtX(grip) = (Position)changes.x;
835 	    XtY(grip) = (Position)changes.y;
836 
837 	    if (XtIsRealized(pane->grip))
838 		XConfigureWindow(XtDisplay(pane->grip), XtWindow(pane->grip),
839 				 CWX | CWY | CWStackMode, &changes);
840 	}
841     }
842     ClearPaneStack(pw);
843 }
844 
845 /*
846  * Function:
847  *	RefigureLocationsAndCommit
848  *
849  * Parameters:
850  *	pw - paned widget
851  *
852  * Description:
853  *	Refigures all locations in a paned widget and commits them immediately.
854  *
855  *      This function does nothing if any of the following are true.
856  *      o refiguremode is false.
857  *      o The widget is unrealized.
858  *      o There are no panes is the paned widget.
859  */
860 static void
RefigureLocationsAndCommit(Widget w)861 RefigureLocationsAndCommit(Widget w)
862 {
863     PanedWidget pw = (PanedWidget)w;
864 
865     if (pw->paned.refiguremode && XtIsRealized(w) && pw->paned.num_panes > 0) {
866 	RefigureLocations(pw, NO_INDEX, AnyPane);
867 	CommitNewLocations(pw);
868     }
869 }
870 
871 /*
872  * Function:
873  *	_DrawRect
874  *
875  * Parameters:
876  *	pw	 - paned widget
877  *	gc	 - gc to used for the draw
878  *	on_olc	 - location of upper left corner of rect
879  *	off_loc	 - ""
880  *	on_size	 - size of rectangle
881  *	off_size - ""
882  *
883  * Description:
884  *	Draws a rectangle in the proper orientation.
885  */
886 static void
_DrawRect(PanedWidget pw,GC gc,int on_loc,int off_loc,unsigned int on_size,unsigned int off_size)887 _DrawRect(PanedWidget pw, GC gc, int on_loc, int off_loc,
888 	  unsigned int on_size, unsigned int off_size)
889 {
890     if (IsVert(pw))
891 	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
892 		       off_loc, on_loc, off_size, on_size);
893     else
894 	XFillRectangle(XtDisplay((Widget)pw), XtWindow((Widget)pw), gc,
895 		       on_loc, off_loc, on_size, off_size);
896 }
897 
898 /*
899  * Function:
900  *	_DrawInternalBorders
901  *
902  * Parameters:
903  *	pw - paned widget
904  *	gc - GC to use to draw the borders
905  *
906  * Description:
907  *	Draws the internal borders into the paned widget.
908  */
909 static void
_DrawInternalBorders(PanedWidget pw,GC gc)910 _DrawInternalBorders(PanedWidget pw, GC gc)
911 {
912     Widget *childP;
913     int on_loc, off_loc;
914     unsigned int on_size, off_size;
915 
916     /*
917      * This is an optimization.  Do not paint the internal borders if
918      * they are the same color as the background
919      */
920     if (pw->core.background_pixel == pw->paned.internal_bp)
921 	return;
922 
923     off_loc = 0;
924     off_size = (unsigned int) PaneSize((Widget)pw, !IsVert(pw));
925     on_size = (unsigned int)pw->paned.internal_bw;
926 
927     ForAllPanes(pw, childP) {
928 	on_loc = IsVert(pw) ? XtY(*childP) : XtX(*childP);
929 	on_loc -= (int)on_size;
930 
931 	_DrawRect(pw, gc, on_loc, off_loc, on_size, off_size);
932     }
933 }
934 
935 #define DrawInternalBorders(pw)				\
936 	_DrawInternalBorders((pw), (pw)->paned.normgc)
937 #define EraseInternalBorders(pw)			\
938 	_DrawInternalBorders((pw), (pw)->paned.invgc)
939 /*
940  * Function Name:
941  *	_DrawTrackLines
942  *
943  * Parameters:
944  *	pw - Paned widget
945  *	erase - if True then just erase track lines, else draw them in
946  *
947  * Description:
948  *	Draws the lines that animate the pane borders when the grips are moved.
949  */
950 static void
_DrawTrackLines(PanedWidget pw,Bool erase)951 _DrawTrackLines(PanedWidget pw, Bool erase)
952 {
953     Widget *childP;
954     Pane pane;
955     int on_loc, off_loc;
956     unsigned int on_size, off_size;
957 
958     off_loc = 0;
959     off_size = PaneSize((Widget)pw, !IsVert(pw));
960 
961     ForAllPanes(pw, childP) {
962 	pane = PaneInfo(*childP);
963 	if (erase || pane->olddelta != pane->delta) {
964 	    on_size = pw->paned.internal_bw;
965 	    if (!erase) {
966 		on_loc = PaneInfo(*childP)->olddelta - (int) on_size;
967 		_DrawRect(pw, pw->paned.flipgc,
968 			  on_loc, off_loc, on_size, off_size);
969 	    }
970 
971 	    on_loc = PaneInfo(*childP)->delta - (int)on_size;
972 
973 	    _DrawRect(pw, pw->paned.flipgc,
974 		      on_loc, off_loc, on_size, off_size);
975 
976 	    pane->olddelta = pane->delta;
977 	}
978     }
979 }
980 
981 #define DrawTrackLines(pw)	_DrawTrackLines((pw), False);
982 #define EraseTrackLines(pw)	_DrawTrackLines((pw), True);
983 /*
984  * Function:
985  *	GetEventLocation
986  *
987  * Parameters:
988  *	pw    - the paned widget
989  *	event - pointer to an event
990  *
991  * Description:
992  *	Converts and event to an x and y location.
993  *
994  * Returns:
995  *	if this is a vertical pane then (y) else (x)
996  */
997 static int
GetEventLocation(PanedWidget pw,XEvent * event)998 GetEventLocation(PanedWidget pw, XEvent *event)
999 {
1000     int x, y;
1001 
1002     switch (event->xany.type) {
1003 	case ButtonPress:
1004 	case ButtonRelease:
1005 	    x = event->xbutton.x_root;
1006 	    y = event->xbutton.y_root;
1007 	    break;
1008 	case KeyPress:
1009 	case KeyRelease:
1010 	    x = event->xkey.x_root;
1011 	    y = event->xkey.y_root;
1012 	    break;
1013 	case MotionNotify:
1014 	    x = event->xmotion.x_root;
1015 	    y = event->xmotion.y_root;
1016 	    break;
1017 	default:
1018 	    x = pw->paned.start_loc;
1019 	    y = pw->paned.start_loc;
1020     }
1021 
1022     if (IsVert(pw))
1023 	return (y);
1024 
1025   return (x);
1026 }
1027 
1028 /*
1029  * Function:
1030  *	StartGripAdjustment
1031  *
1032  * Parameters:
1033  *	pw   - paned widget
1034  *	grip - grip widget selected
1035  *	dir  - direction that we are to be moving
1036  *
1037  * Description:
1038  *	Starts the grip adjustment procedure.
1039  */
1040 static void
StartGripAdjustment(PanedWidget pw,Widget grip,Direction dir)1041 StartGripAdjustment(PanedWidget pw, Widget grip, Direction dir)
1042 {
1043     Widget *childP;
1044     Cursor cursor;
1045 
1046     pw->paned.whichadd = pw->paned.whichsub = NULL;
1047 
1048     if (dir == ThisBorderOnly || dir == UpLeftPane)
1049 	pw->paned.whichadd = pw->composite.children[PaneIndex(grip)];
1050     if (dir == ThisBorderOnly || dir == LowRightPane)
1051 	pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1];
1052 
1053     /*
1054      * Change the cursor
1055      */
1056     if (XtIsRealized(grip)) {
1057 	if (IsVert(pw)) {
1058 	    if (dir == UpLeftPane)
1059 		cursor = pw->paned.adjust_upper_cursor;
1060 	    else if (dir == LowRightPane)
1061 		cursor = pw->paned.adjust_lower_cursor;
1062 	    else {
1063 		if (pw->paned.adjust_this_cursor == None)
1064 		    cursor = pw->paned.v_adjust_this_cursor;
1065 		else
1066 		    cursor = pw->paned.adjust_this_cursor;
1067 	    }
1068 	}
1069 	else {
1070 	    if (dir == UpLeftPane)
1071 		cursor = pw->paned.adjust_left_cursor;
1072 	    else if (dir == LowRightPane)
1073 		cursor = pw->paned.adjust_right_cursor;
1074 	    else {
1075 		if (pw->paned.adjust_this_cursor == None)
1076 		    cursor = pw->paned.h_adjust_this_cursor;
1077 		else
1078 		    cursor = pw->paned.adjust_this_cursor;
1079 	    }
1080 	}
1081 
1082 	XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
1083     }
1084 
1085     EraseInternalBorders(pw);
1086     ForAllPanes(pw, childP)
1087 	PaneInfo(*childP)->olddelta = -99;
1088 
1089     EraseTrackLines(pw);
1090 }
1091 
1092 /*
1093  * Function:
1094  *	MoveGripAdjustment
1095  *
1096  * Parameters:
1097  *	pw   - paned widget
1098  *	grip - grip that we are moving
1099  *	dir  - direction the pane we are interested is w.r.t the grip
1100  *	loc  - location of pointer in proper direction
1101  *
1102  * Description:
1103  *	This routine moves all panes around when a grip is moved.
1104  */
1105 static void
MoveGripAdjustment(PanedWidget pw,Widget grip,Direction dir,int loc)1106 MoveGripAdjustment(PanedWidget pw, Widget grip, Direction dir, int loc)
1107 {
1108     int diff, add_size = 0, sub_size = 0;
1109 
1110     diff = loc - pw->paned.start_loc;
1111 
1112     if (pw->paned.whichadd)
1113     add_size = PaneSize(pw->paned.whichadd, IsVert(pw)) + diff;
1114 
1115     if (pw->paned.whichsub)
1116     sub_size = PaneSize(pw->paned.whichsub, IsVert(pw)) - diff;
1117 
1118     /*
1119      * If moving this border only then do not allow either of the borders
1120      * to go beyond the min or max size allowed
1121      */
1122     if (dir == ThisBorderOnly) {
1123 	int old_add_size = add_size, old_sub_size;
1124 
1125 	AssignMax(add_size, (int)PaneInfo(pw->paned.whichadd)->min);
1126 	AssignMin(add_size, (int)PaneInfo(pw->paned.whichadd)->max);
1127 	if (add_size != old_add_size)
1128 	    sub_size += old_add_size - add_size;
1129 
1130 	old_sub_size = sub_size;
1131 	AssignMax(sub_size, (int)PaneInfo(pw->paned.whichsub)->min);
1132 	AssignMin(sub_size, (int)PaneInfo(pw->paned.whichsub)->max);
1133 	if (sub_size != old_sub_size)
1134 	    return;	/* Abort to current sizes */
1135     }
1136 
1137     if (add_size != 0)
1138 	PaneInfo(pw->paned.whichadd)->size = add_size;
1139     if (sub_size != 0)
1140 	PaneInfo(pw->paned.whichsub)->size = sub_size;
1141     RefigureLocations(pw, PaneIndex(grip), dir);
1142     DrawTrackLines(pw);
1143 }
1144 
1145 /*
1146  * Function:
1147  *	CommitGripAdjustment
1148  *
1149  * Parameters:
1150  *	pw - paned widget
1151  *
1152  * Description:
1153  *	Commits the grip adjustment.
1154  */
1155 static void
CommitGripAdjustment(PanedWidget pw)1156 CommitGripAdjustment(PanedWidget pw)
1157 {
1158     EraseTrackLines(pw);
1159     CommitNewLocations(pw);
1160     DrawInternalBorders(pw);
1161 
1162     /*
1163      * Since the user selected this size then use it as the preferred size
1164      */
1165     if (pw->paned.whichadd) {
1166 	Pane pane = PaneInfo(pw->paned.whichadd);
1167 
1168 	pane->wp_size = (Dimension)pane->size;
1169     }
1170     if (pw->paned.whichsub) {
1171 	Pane pane = PaneInfo(pw->paned.whichsub);
1172 
1173 	pane->wp_size = (Dimension)pane->size;
1174     }
1175 }
1176 
1177 /*
1178  * Function:
1179  *	HandleGrip
1180  *
1181  * Parameters:
1182  *	grip	  - grip widget that has been moved
1183  *	temp	  - (not used)
1184  *	call_data - data passed to us from the grip widget
1185  *
1186  * Description:
1187  *	Handles the grip manipulations.
1188  */
1189 /*ARGSUSED*/
1190 static void
HandleGrip(Widget grip,XtPointer temp _X_UNUSED,XtPointer callData)1191 HandleGrip(Widget grip, XtPointer temp _X_UNUSED, XtPointer callData)
1192 {
1193     XawGripCallData call_data = (XawGripCallData)callData;
1194     PanedWidget pw = (PanedWidget) XtParent(grip);
1195     int loc;
1196     char action_type[2], direction[2];
1197     Cursor cursor;
1198     Arg arglist[1];
1199 
1200     if (call_data->num_params)
1201 	XmuNCopyISOLatin1Uppered(action_type, call_data->params[0],
1202 				 sizeof(action_type));
1203 
1204     if (call_data->num_params == 0
1205 	|| (action_type[0] == 'C' && call_data->num_params != 1)
1206 	|| (action_type[0] != 'C' && call_data->num_params != 2))
1207 	XtAppError(XtWidgetToApplicationContext(grip),
1208 		   "Paned GripAction has been passed incorrect parameters.");
1209 
1210     loc = GetEventLocation(pw, (XEvent *)call_data->event);
1211 
1212     if (action_type[0] != 'C')
1213 	XmuNCopyISOLatin1Uppered(direction, call_data->params[1],
1214 				 sizeof(direction));
1215 
1216     switch (action_type[0]) {
1217 	case 'S':		/* Start adjustment */
1218 	    pw->paned.resize_children_to_pref = False;
1219 	    StartGripAdjustment(pw, grip, (Direction)direction[0]);
1220 	    pw->paned.start_loc = loc;
1221 	    break;
1222 	case 'M':
1223 	    MoveGripAdjustment(pw, grip, (Direction)direction[0], loc);
1224 	    break;
1225 	case 'C':
1226 	    XtSetArg(arglist[0], XtNcursor, &cursor);
1227 	    XtGetValues(grip, arglist, 1);
1228 	    XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor);
1229 	    CommitGripAdjustment(pw);
1230 	    break;
1231 	default:
1232 	    XtAppError(XtWidgetToApplicationContext(grip),
1233 		       "Paned GripAction(); 1st parameter invalid");
1234 	    break;
1235      }
1236 }
1237 
1238 /*
1239  * Function:
1240  *	ResortChildren
1241  *
1242  * Arguments:
1243  *	pw - paned widget
1244  *
1245  * Description:
1246  *	Resorts the children so that all managed children are first.
1247  */
1248 static void
ResortChildren(PanedWidget pw)1249 ResortChildren(PanedWidget pw)
1250 {
1251     Widget *unmanagedP, *childP;
1252 
1253     unmanagedP = NULL;
1254     ForAllChildren(pw, childP) {
1255 	if (!IsPane(*childP) || !XtIsManaged(*childP)) {
1256 	    /*
1257 	     * We only keep track of the first unmanaged pane
1258 	     */
1259 	    if (unmanagedP == NULL)
1260 		unmanagedP = childP;
1261 	}
1262 	else {			/* must be a managed pane */
1263 	    /*
1264 	     * If an earlier widget was not a managed pane, then swap
1265 	     */
1266 	    if (unmanagedP != NULL) {
1267 		Widget child = *unmanagedP;
1268 
1269 		*unmanagedP = *childP;
1270 		*childP = child;
1271 		childP = unmanagedP;  /* easiest to just back-track */
1272 		unmanagedP = NULL;    /* in case there is another managed */
1273 	   }
1274        }
1275    }
1276 }
1277 
1278 /*
1279  * Function:
1280  *	ManageAndUnmanageGrips
1281  *
1282  * Parameters:
1283  *	pw - paned widget
1284  *
1285  * Description:
1286  *	  This function manages and unmanages the grips so that
1287  *		   the managed state of each grip matches that of its pane.
1288  */
1289 static void
ManageAndUnmanageGrips(PanedWidget pw)1290 ManageAndUnmanageGrips(PanedWidget pw)
1291 {
1292     WidgetList managed_grips, unmanaged_grips;
1293     Widget *managedP, *unmanagedP, *childP;
1294     Cardinal alloc_size;
1295 
1296     alloc_size = (Cardinal)(sizeof(Widget) * (pw->composite.num_children >> 1));
1297     managedP = managed_grips = (WidgetList)XtMalloc(alloc_size);
1298     unmanagedP = unmanaged_grips = (WidgetList)XtMalloc(alloc_size);
1299 
1300     ForAllChildren(pw, childP)
1301 	if (IsPane(*childP) && HasGrip(*childP)) {
1302 	    if (XtIsManaged(*childP))
1303 		*managedP++ = PaneInfo(*childP)->grip;
1304 	    else
1305 		*unmanagedP++ = PaneInfo(*childP)->grip;
1306 	}
1307 
1308     if (managedP != managed_grips) {
1309 	*unmanagedP++ = *--managedP;   /* Last grip is never managed */
1310 	XtManageChildren(managed_grips, (Cardinal)(managedP - managed_grips));
1311     }
1312 
1313     if (unmanagedP != unmanaged_grips)
1314 	XtUnmanageChildren(unmanaged_grips, (Cardinal)(unmanagedP - unmanaged_grips));
1315 
1316     XtFree((char *)managed_grips);
1317     XtFree((char *)unmanaged_grips);
1318 }
1319 
1320 /*
1321  * Function:
1322  *	CreateGrip
1323  *
1324  * Parameters:
1325  *	child - child that wants a grip to be created for it
1326  *
1327  * Description:
1328  *	Creates a grip widget.
1329  */
1330 static void
CreateGrip(Widget child)1331 CreateGrip(Widget child)
1332 {
1333     PanedWidget pw = (PanedWidget)XtParent(child);
1334     Arg arglist[2];
1335     Cardinal num_args = 0;
1336     Cursor cursor;
1337 
1338     XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations);
1339     num_args++;
1340     if ((cursor = pw->paned.grip_cursor) == None) {
1341 	if (IsVert(pw))
1342 	    cursor = pw->paned.v_grip_cursor;
1343 	else
1344 	    cursor = pw->paned.h_grip_cursor;
1345     }
1346 
1347     XtSetArg(arglist[num_args], XtNcursor, cursor);
1348     num_args++;
1349     PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw,
1350 					   arglist, num_args);
1351 
1352     XtAddCallback(PaneInfo(child)->grip, XtNcallback,
1353 		  HandleGrip, (XtPointer)child);
1354 }
1355 
1356 /*
1357  * Function:
1358  *	GetGCs
1359  *
1360  * Parameters:
1361  *	w - paned widget
1362  */
1363 static void
GetGCs(Widget w)1364 GetGCs(Widget w)
1365 {
1366     PanedWidget pw = (PanedWidget)w;
1367     XtGCMask valuemask;
1368     XGCValues values;
1369 
1370     /*
1371      * Draw pane borders in internal border color
1372      */
1373     values.foreground = pw->paned.internal_bp;
1374     valuemask = GCForeground;
1375     pw->paned.normgc = XtGetGC(w, valuemask, &values);
1376 
1377     /*
1378      * Erase pane borders with background color
1379      */
1380     values.foreground = pw->core.background_pixel;
1381     valuemask = GCForeground;
1382     pw->paned.invgc = XtGetGC(w, valuemask, &values);
1383 
1384     /*
1385      * Draw Track lines (animate pane borders) in
1386      * internal border color ^ bg color
1387      */
1388     values.function = GXinvert;
1389     values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel;
1390     values.subwindow_mode = IncludeInferiors;
1391     valuemask = GCPlaneMask | GCFunction | GCSubwindowMode;
1392     pw->paned.flipgc = XtGetGC(w, valuemask, &values);
1393 }
1394 
1395 /*
1396  * Function:
1397  *	SetChildrenPrefSizes
1398  *
1399  * Parameters:
1400  *	pw - paned widget
1401  *
1402  * Description:
1403  *	Sets the preferred sizes of the children.
1404  */
1405 static void
SetChildrenPrefSizes(PanedWidget pw,unsigned int off_size)1406 SetChildrenPrefSizes(PanedWidget pw, unsigned int off_size)
1407 {
1408     Widget *childP;
1409     Boolean vert = IsVert(pw);
1410     XtWidgetGeometry request, reply;
1411 
1412     ForAllPanes(pw, childP)
1413 	if (pw->paned.resize_children_to_pref || PaneInfo(*childP)->size == 0 ||
1414 	    PaneInfo(*childP)->resize_to_pref) {
1415 	    if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD)
1416 		PaneInfo(*childP)->wp_size = PaneInfo(*childP)->preferred_size;
1417 	    else {
1418 		if(vert) {
1419 		    request.request_mode = CWWidth;
1420 		    request.width = (Dimension) off_size;
1421 		}
1422 		else {
1423 		    request.request_mode = CWHeight;
1424 		    request.height = (Dimension) off_size;
1425 		}
1426 
1427 		if ((XtQueryGeometry(*childP, &request, &reply)
1428 		     == XtGeometryAlmost)
1429 		    && (reply.request_mode = (vert ? CWHeight : CWWidth)))
1430 		    PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert);
1431 		else
1432 		    PaneInfo(*childP)->wp_size = PaneSize(*childP, vert);
1433 	    }
1434 
1435 	    PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size;
1436 	}
1437 }
1438 
1439 /*
1440  * Function:
1441  *	ChangeAllGripCursors
1442  *
1443  * Parameters:
1444  *	pw - paned widget
1445  *
1446  *	Description:
1447  *	Changes all the grip cursors.
1448  */
1449 static void
ChangeAllGripCursors(PanedWidget pw)1450 ChangeAllGripCursors(PanedWidget pw)
1451 {
1452     Widget *childP;
1453 
1454     ForAllPanes(pw, childP) {
1455 	Arg arglist[1];
1456 	Cursor cursor;
1457 
1458 	if ((cursor = pw->paned.grip_cursor) == None) {
1459 	    if (IsVert(pw))
1460 		cursor = pw->paned.v_grip_cursor;
1461 	    else
1462 		cursor = pw->paned.h_grip_cursor;
1463 	}
1464 
1465 	if (HasGrip(*childP)) {
1466 	    XtSetArg(arglist[0], XtNcursor, cursor);
1467 	    XtSetValues(PaneInfo(*childP)->grip, arglist, 1);
1468 	}
1469     }
1470 }
1471 
1472 /*
1473  * Function:
1474  *	PushPaneStack
1475  *
1476  * Parameters:
1477  *	pw   - paned widget
1478  *	pane - pane that we are pushing
1479  *
1480  * Description:
1481  *	Pushes a value onto the pane stack.
1482  */
1483 static void
PushPaneStack(PanedWidget pw,Pane pane)1484 PushPaneStack(PanedWidget pw, Pane pane)
1485 {
1486     PaneStack *stack = (PaneStack *)XtMalloc(sizeof(PaneStack));
1487 
1488     stack->next = pw->paned.stack;
1489     stack->pane = pane;
1490     stack->start_size = pane->size;
1491 
1492     pw->paned.stack = stack;
1493 }
1494 
1495 /*
1496  * Function:
1497  *	GetPaneStack
1498  *
1499  * Parameters:
1500  *	pw - paned widget
1501  *	shrink	   - True if we want to shrink this pane, False otherwise
1502  *	pane	   - pane that we are popping (return)
1503  *	start_size - size that this pane started at (return)
1504  *
1505  * Description:
1506  *	Gets the top value from the pane stack.
1507  */
1508 static void
GetPaneStack(PanedWidget pw,Bool shrink,Pane * pane,int * start_size)1509 GetPaneStack(PanedWidget pw, Bool shrink, Pane *pane, int *start_size)
1510 {
1511     if (pw->paned.stack == NULL) {
1512 	*pane = NULL;
1513 	return;
1514     }
1515 
1516     *pane = pw->paned.stack->pane;
1517     *start_size = pw->paned.stack->start_size;
1518 
1519     if (shrink != ((*pane)->size > *start_size))
1520 	*pane = NULL;
1521 }
1522 
1523 /*
1524  * Function:
1525  *	PopPaneStack
1526  *
1527  * Parameters:
1528  *	pw - paned widget
1529  *
1530  * Description:
1531  *	Pops the top item off the pane stack.
1532  *
1533  * Returns: True if this is not the last element on the stack
1534  */
1535 static Bool
PopPaneStack(PanedWidget pw)1536 PopPaneStack(PanedWidget pw)
1537 {
1538     PaneStack *stack = pw->paned.stack;
1539 
1540     if (stack == NULL)
1541 	return (False);
1542 
1543     pw->paned.stack = stack->next;
1544     XtFree((char *)stack);
1545 
1546     if (pw->paned.stack == NULL)
1547 	return (False);
1548 
1549     return (True);
1550 }
1551 
1552 /*
1553  * Function:
1554  *	ClearPaneStack
1555  *
1556  * Parameters:
1557  *	pw - paned widget
1558  *
1559  * Description:
1560  *	Removes all entries from the pane stack.
1561  */
1562 static void
ClearPaneStack(PanedWidget pw)1563 ClearPaneStack(PanedWidget pw)
1564 {
1565     while(PopPaneStack(pw))
1566 	;
1567 }
1568 
1569 static void
XawPanedClassInitialize(void)1570 XawPanedClassInitialize(void)
1571 {
1572     XawInitializeWidgetSet();
1573     XtAddConverter(XtRString, XtROrientation, XmuCvtStringToOrientation,
1574 		   NULL, 0);
1575     XtSetTypeConverter(XtROrientation, XtRString, XmuCvtOrientationToString,
1576 		       NULL, 0, XtCacheNone, NULL);
1577 }
1578 
1579 /* The Geometry Manager only allows changes after Realize if
1580  * allow_resize is True in the constraints record.
1581  *
1582  * For vertically paned widgets:
1583  *
1584  * It only allows height changes, but offers the requested height
1585  * as a compromise if both width and height changes were requested.
1586  *
1587  * For horizontal widgets the converse is true.
1588  * As all good Geometry Managers should, we will return No if the
1589  * request will have no effect; i.e. when the requestor is already
1590  * of the desired geometry.
1591  */
1592 static XtGeometryResult
XawPanedGeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)1593 XawPanedGeometryManager(Widget w, XtWidgetGeometry *request,
1594 			XtWidgetGeometry *reply)
1595 {
1596     PanedWidget pw = (PanedWidget)XtParent(w);
1597     XtGeometryMask mask = request->request_mode;
1598     Dimension old_size, old_wpsize, old_paned_size;
1599     Pane pane = PaneInfo(w);
1600     Boolean vert = IsVert(pw);
1601     Dimension on_size, off_size;
1602     XtGeometryResult result;
1603     Boolean almost = False;
1604 
1605     /*
1606      * If any of the following is true, disallow the geometry change
1607      *
1608      * o The paned widget is realized and allow_resize is false for the pane
1609      * o The child did not ask to change the on_size
1610      * o The request is not a width or height request
1611      * o The requested size is the same as the current size
1612      */
1613 
1614     if ((XtIsRealized((Widget)pw) && !pane->allow_resize)
1615 	|| !(mask & (vert ? CWHeight : CWWidth))
1616 	|| (mask & (XtGeometryMask)(~(CWWidth | CWHeight)))
1617 	|| GetRequestInfo(request, vert) ==  PaneSize(w, vert))
1618 	return (XtGeometryNo);
1619 
1620     old_paned_size = PaneSize((Widget)pw, vert);
1621     old_wpsize = pane->wp_size;
1622     old_size = (Dimension)pane->size;
1623 
1624     pane->wp_size = (Dimension)(pane->size = GetRequestInfo(request, vert));
1625 
1626     AdjustPanedSize(pw, PaneSize((Widget)pw, !vert), &result, &on_size,
1627 		    &off_size);
1628 
1629     /*
1630      * Fool the Refigure Locations proc to thinking that we are
1631      * a different on_size
1632      */
1633 
1634     if (result != XtGeometryNo) {
1635 	if (vert)
1636 	    XtHeight(pw) = on_size;
1637 	else
1638 	    XtWidth(pw) = on_size;
1639     }
1640 
1641     RefigureLocations(pw, PaneIndex(w), AnyPane);
1642 
1643     /*
1644      * Set up reply struct and reset core on_size
1645      */
1646     if (vert) {
1647 	XtHeight(pw) = old_paned_size;
1648 	reply->height = (Dimension) pane->size;
1649 	reply->width = off_size;
1650     }
1651     else {
1652 	XtWidth(pw) = old_paned_size;
1653 	reply->height = off_size;
1654 	reply->width = (Dimension) pane->size;
1655     }
1656 
1657     /*
1658      * IF either of the following is true
1659      *
1660      * o There was a "off_size" request and the new "off_size" is different
1661      *   from that requested
1662      * o There was no "off_size" request and the new "off_size" is different
1663      *
1664      * o The "on_size" we will allow is different from that requested
1665      *
1666      * THEN: set almost
1667      */
1668     if (!((vert ? CWWidth : CWHeight) & mask)) {
1669 	if (vert)
1670 	    request->width = XtWidth(w);
1671 	else
1672 	    request->height = XtHeight(w);
1673     }
1674 
1675     almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert);
1676     almost = (Boolean)(almost | (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert)));
1677 
1678     if ((mask & XtCWQueryOnly) || almost) {
1679 	pane->wp_size = old_wpsize;
1680 	pane->size = old_size;
1681 	RefigureLocations(pw, PaneIndex(w), AnyPane);
1682 	reply->request_mode = CWWidth | CWHeight;
1683 	if (almost)
1684 	    return (XtGeometryAlmost);
1685     }
1686     else {
1687 	AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), NULL, NULL, NULL);
1688 	CommitNewLocations(pw);		/* layout already refigured */
1689     }
1690 
1691     return (XtGeometryDone);
1692 }
1693 
1694 /*ARGSUSED*/
1695 static void
XawPanedInitialize(Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1696 XawPanedInitialize(Widget request _X_UNUSED, Widget cnew,
1697 		   ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
1698 {
1699     PanedWidget pw = (PanedWidget)cnew;
1700 
1701     GetGCs((Widget)pw);
1702 
1703     pw->paned.recursively_called = False;
1704     pw->paned.stack = NULL;
1705     pw->paned.resize_children_to_pref = True;
1706     pw->paned.num_panes = 0;
1707 }
1708 
1709 static void
XawPanedRealize(Widget w,Mask * valueMask,XSetWindowAttributes * attributes)1710 XawPanedRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
1711 {
1712     PanedWidget pw = (PanedWidget)w;
1713     Widget *childP;
1714 
1715     if ((attributes->cursor = pw->paned.cursor) != None)
1716 	*valueMask |= CWCursor;
1717 
1718     (*SuperClass->core_class.realize)(w, valueMask, attributes);
1719 
1720     /*
1721      * Before we commit the new locations we need to realize all the panes and
1722      * their grips
1723      */
1724     ForAllPanes(pw, childP) {
1725 	XtRealizeWidget(*childP);
1726 	if (HasGrip(*childP))
1727 	    XtRealizeWidget(PaneInfo(*childP)->grip);
1728     }
1729 
1730     RefigureLocationsAndCommit(w);
1731     pw->paned.resize_children_to_pref = False;
1732 }
1733 
1734 static void
XawPanedDestroy(Widget w)1735 XawPanedDestroy(Widget w)
1736 {
1737     ReleaseGCs(w);
1738 }
1739 
1740 static void
ReleaseGCs(Widget w)1741 ReleaseGCs(Widget w)
1742 {
1743     PanedWidget pw = (PanedWidget)w;
1744 
1745     XtReleaseGC(w, pw->paned.normgc);
1746     XtReleaseGC(w, pw->paned.invgc);
1747     XtReleaseGC(w, pw->paned.flipgc);
1748 }
1749 
1750 static void
XawPanedInsertChild(Widget w)1751 XawPanedInsertChild(Widget w)
1752 {
1753     Pane pane = PaneInfo(w);
1754 
1755     /* insert the child widget in the composite children list with the
1756        superclass insert_child routine
1757      */
1758     (*SuperClass->composite_class.insert_child)(w);
1759 
1760     if (!IsPane(w))
1761 	return;
1762 
1763     if (pane->show_grip == True) {
1764 	CreateGrip(w);
1765 	if (pane->min == PANED_GRIP_SIZE)
1766 	    pane->min = PaneSize(pane->grip, IsVert((PanedWidget)XtParent(w)));
1767     }
1768     else {
1769 	if (pane->min == PANED_GRIP_SIZE)
1770 	    pane->min = 1;
1771 	pane->grip = NULL;
1772     }
1773 
1774     pane->size = 0;
1775     pane->paned_adjusted_me = False;
1776 }
1777 
1778 static void
XawPanedDeleteChild(Widget w)1779 XawPanedDeleteChild(Widget w)
1780 {
1781     /* remove the subwidget info and destroy the grip */
1782     if (IsPane(w) && HasGrip(w))
1783 	XtDestroyWidget(PaneInfo(w)->grip);
1784 
1785     /* delete the child widget in the composite children list with the
1786        superclass delete_child routine
1787      */
1788     (*SuperClass->composite_class.delete_child)(w);
1789 }
1790 
1791 static void
XawPanedChangeManaged(Widget w)1792 XawPanedChangeManaged(Widget w)
1793 {
1794     PanedWidget pw = (PanedWidget)w;
1795     Boolean vert = IsVert(pw);
1796     Dimension size;
1797     Widget *childP;
1798 
1799     if (pw->paned.recursively_called++)
1800 	return;
1801 
1802     /*
1803      * If the size is zero then set it to the size of the widest or tallest pane
1804      */
1805 
1806     if ((size = PaneSize((Widget)pw, !vert)) == 0) {
1807 	size = 1;
1808 	ForAllChildren(pw, childP)
1809 	if (XtIsManaged(*childP) && (PaneSize(*childP, !vert) > size))
1810 	    size = PaneSize(*childP, !vert);
1811     }
1812 
1813     ManageAndUnmanageGrips(pw);
1814     pw->paned.recursively_called = False;
1815     ResortChildren(pw);
1816 
1817     pw->paned.num_panes = 0;
1818     ForAllChildren(pw, childP)
1819 	if (IsPane(*childP)) {
1820 	    if (XtIsManaged(*childP)) {
1821 		Pane pane = PaneInfo(*childP);
1822 
1823 		if (HasGrip(*childP))
1824 		    PaneInfo(pane->grip)->position = pw->paned.num_panes;
1825 		pane->position = pw->paned.num_panes; /* TEMPORY -CDP 3/89 */
1826 		pw->paned.num_panes++;
1827 	    }
1828 	    else
1829 		break;		 /* This list is already sorted */
1830 	}
1831 
1832     SetChildrenPrefSizes((PanedWidget) w, size);
1833 
1834     /*
1835      * ForAllPanes can now be used
1836      */
1837     if (PaneSize((Widget) pw, vert) == 0)
1838 	AdjustPanedSize(pw, size, NULL, NULL, NULL);
1839 
1840     if (XtIsRealized((Widget)pw))
1841 	RefigureLocationsAndCommit((Widget)pw);
1842 }
1843 
1844 static void
XawPanedResize(Widget w)1845 XawPanedResize(Widget w)
1846 {
1847     SetChildrenPrefSizes((PanedWidget)w,
1848 			 PaneSize(w, !IsVert((PanedWidget)w)));
1849     RefigureLocationsAndCommit(w);
1850 }
1851 
1852 /*ARGSUSED*/
1853 static void
XawPanedRedisplay(Widget w,XEvent * event _X_UNUSED,Region region _X_UNUSED)1854 XawPanedRedisplay(Widget w, XEvent *event _X_UNUSED, Region region _X_UNUSED)
1855 {
1856     DrawInternalBorders((PanedWidget)w);
1857 }
1858 
1859 /*ARGSUSED*/
1860 static Boolean
XawPanedSetValues(Widget old,Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1861 XawPanedSetValues(Widget old, Widget request _X_UNUSED, Widget cnew,
1862 		  ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
1863 {
1864     PanedWidget old_pw = (PanedWidget)old;
1865     PanedWidget new_pw = (PanedWidget)cnew;
1866     Boolean redisplay = False;
1867 
1868     if ((old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(cnew))
1869 	XDefineCursor(XtDisplay(cnew), XtWindow(cnew), new_pw->paned.cursor);
1870 
1871     if (old_pw->paned.internal_bp != new_pw->paned.internal_bp ||
1872 	old_pw->core.background_pixel != new_pw->core.background_pixel) {
1873 	ReleaseGCs(old);
1874 	GetGCs(cnew);
1875 	redisplay = True;
1876     }
1877 
1878     if (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor ||
1879 	old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor ||
1880 	old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor)
1881 	ChangeAllGripCursors(new_pw);
1882 
1883     if (IsVert(old_pw) != IsVert(new_pw)) {
1884 	/*
1885 	 * We are fooling the paned widget into thinking that is needs to
1886 	 * fully refigure everything, which is what we want
1887 	 */
1888 	if (IsVert(new_pw))
1889 	    XtWidth(new_pw) = 0;
1890 	else
1891 	    XtHeight(new_pw) = 0;
1892 
1893 	new_pw->paned.resize_children_to_pref = True;
1894 	XawPanedChangeManaged(cnew); /* Seems weird, but does the right thing */
1895 	new_pw->paned.resize_children_to_pref = False;
1896 	if (new_pw->paned.grip_cursor == None)
1897 	    ChangeAllGripCursors(new_pw);
1898 	return (True);
1899     }
1900 
1901     if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) {
1902 	AdjustPanedSize(new_pw, PaneSize(cnew, !IsVert(old_pw)),
1903 		        NULL, NULL, NULL);
1904 	RefigureLocationsAndCommit(cnew);
1905 	return (True);		/* We have done a full configuration, return */
1906     }
1907 
1908     if (old_pw->paned.grip_indent != new_pw->paned.grip_indent &&
1909 	XtIsRealized(cnew)) {
1910 	CommitNewLocations(new_pw);
1911 	redisplay = True;
1912     }
1913 
1914     return (redisplay);
1915 }
1916 
1917 /*ARGSUSED*/
1918 static Boolean
XawPanedPaneSetValues(Widget old,Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1919 XawPanedPaneSetValues(Widget old, Widget request _X_UNUSED, Widget cnew,
1920 		      ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
1921 {
1922     Pane old_pane = PaneInfo(old);
1923     Pane new_pane = PaneInfo(cnew);
1924     Boolean redisplay = False;
1925 
1926     /* Check for new min and max */
1927     if (old_pane->min != new_pane->min || old_pane->max != new_pane->max)
1928 	XawPanedSetMinMax(cnew, (int)new_pane->min, (int)new_pane->max);
1929 
1930     /* Check for change in XtNshowGrip */
1931     if (old_pane->show_grip != new_pane->show_grip) {
1932 	if (new_pane->show_grip == True) {
1933 	    CreateGrip(cnew);
1934 	    if (XtIsRealized(XtParent(cnew))) {
1935 		if (XtIsManaged(cnew))	/* if paned is unrealized this will
1936 					   happen automatically at realize time
1937 					 */
1938 		    XtManageChild(PaneInfo(cnew)->grip);	/* manage the grip */
1939 		XtRealizeWidget(PaneInfo(cnew)->grip); /* realize the grip */
1940 		CommitNewLocations((PanedWidget)XtParent(cnew));
1941 	    }
1942 	}
1943 	else if (HasGrip(old)) {
1944 	    XtDestroyWidget(old_pane->grip);
1945 	    new_pane->grip = NULL;
1946 	    redisplay = True;
1947 	}
1948     }
1949 
1950     return (redisplay);
1951 }
1952 
1953 /*
1954  * Public routines
1955  */
1956 /*
1957  * Function:
1958  *	XawPanedSetMinMax
1959  *
1960  * Parameters:
1961  *	widget - widget that is a child of the Paned widget
1962  *	min    - new min and max size for the pane
1963  *	max    - ""
1964  *
1965  * Description:
1966  *	Sets the min and max size for a pane.
1967  */
1968 void
XawPanedSetMinMax(Widget widget,int min,int max)1969 XawPanedSetMinMax(Widget widget, int min, int max)
1970 {
1971     Pane pane = PaneInfo(widget);
1972 
1973     pane->min = (Dimension) min;
1974     pane->max = (Dimension) max;
1975     RefigureLocationsAndCommit(widget->core.parent);
1976 }
1977 
1978 /*
1979  * Function:
1980  *	XawPanedGetMinMax
1981  *
1982  * Parameters:
1983  *	widget - widget that is a child of the Paned widget
1984  *	min    - current min and max size for the pane (return)
1985  *	max    - ""
1986  *
1987  * Description:
1988  *	Gets the min and max size for a pane.
1989  */
1990 void
XawPanedGetMinMax(Widget widget,int * min,int * max)1991 XawPanedGetMinMax(Widget widget, int *min, int *max)
1992 {
1993     Pane pane = PaneInfo(widget);
1994 
1995     *min = pane->min;
1996     *max = pane->max;
1997 }
1998 
1999 /*
2000  * Function:
2001  *	XawPanedSetRefigureMode
2002  *
2003  * Parameters:
2004  *	w    - paned widget
2005  *	mode - if False then inhibit refigure
2006  *
2007  * Description:
2008  *	Allows a flag to be set the will inhibit
2009  *		   the paned widgets relayout routine.
2010  */
2011 void
XawPanedSetRefigureMode(Widget w,int mode)2012 XawPanedSetRefigureMode(Widget w,
2013 #if NeedWidePrototypes
2014 	int mode
2015 #else
2016 	Boolean mode
2017 #endif
2018 )
2019 {
2020     ((PanedWidget)w)->paned.refiguremode = mode;
2021     RefigureLocationsAndCommit(w);
2022 }
2023 
2024 /*
2025  * Function:
2026  *	XawPanedGetNumSub
2027  *
2028  * Parameters:
2029  *	w - paned widget
2030  *
2031  * Description:
2032  *	Returns the number of panes in the paned widget.
2033  * Returns:
2034  *	the number of panes in the paned widget
2035  */
2036 int
XawPanedGetNumSub(Widget w)2037 XawPanedGetNumSub(Widget w)
2038 {
2039     return (((PanedWidget)w)->paned.num_panes);
2040 }
2041 
2042 /*
2043  * Function:
2044  *	XawPanedAllowResize
2045  *
2046  * Parameters:
2047  *	widget - child of the paned widget
2048  *
2049  * Description:
2050  *	  Allows a flag to be set that determines if the paned
2051  *	widget will allow geometry requests from this child.
2052  */
2053 void
XawPanedAllowResize(Widget widget,int allow_resize)2054 XawPanedAllowResize(Widget widget,
2055 #if NeedWidePrototypes
2056 	int allow_resize
2057 #else
2058 	Boolean allow_resize
2059 #endif
2060 )
2061 {
2062     PaneInfo(widget)->allow_resize = allow_resize;
2063 }
2064