1 /*************************************<+>*************************************
2  *****************************************************************************
3  **
4  **   File:        Form.c
5  **
6  **   Project:     X Widgets
7  **
8  **   Description: Contains code for the X Widget's Form manager.
9  **
10  *****************************************************************************
11  **
12  **   Copyright (c) 1988 by Hewlett-Packard Company
13  **   Copyright (c) 1988 by the Massachusetts Institute of Technology
14  **
15  **   Permission to use, copy, modify, and distribute this software
16  **   and its documentation for any purpose and without fee is hereby
17  **   granted, provided that the above copyright notice appear in all
18  **   copies and that both that copyright notice and this permission
19  **   notice appear in supporting documentation, and that the names of
20  **   Hewlett-Packard or  M.I.T.  not be used in advertising or publicity
21  **   pertaining to distribution of the software without specific, written
22  **   prior permission.
23  **
24  *****************************************************************************
25  *************************************<+>*************************************/
26 
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <X11/Xlib.h>
32 #include <X11/IntrinsicP.h>
33 #include <X11/Intrinsic.h>
34 #include <Xw/Xw.h>
35 #include <Xw/XwP.h>
36 #include <Xw/Form.h>
37 #include <Xw/FormP.h>
38 #include <X11/StringDefs.h>
39 #include <X11/keysymdef.h>
40 
41 
42 /*  Constraint resource list for Form  */
43 
44 static XtResource constraintResources[] =
45 {
46    {
47       XtNxRefName, XtCXRefName, XtRString, sizeof(caddr_t),
48       XtOffset(XwFormConstraints, x_ref_name), XtRString, (caddr_t) NULL
49    },
50 
51    {
52       XtNxRefWidget, XtCXRefWidget, XtRPointer, sizeof(caddr_t),
53       XtOffset(XwFormConstraints, x_ref_widget), XtRPointer, NULL
54    },
55 
56    {
57       XtNxOffset, XtCXOffset, XtRInt, sizeof(int),
58       XtOffset(XwFormConstraints, x_offset), XtRString, "0"
59    },
60 
61    {
62       XtNxAddWidth, XtCXAddWidth, XtRBoolean, sizeof(Boolean),
63       XtOffset(XwFormConstraints, x_add_width), XtRString, "False"
64    },
65 
66    {
67       XtNxVaryOffset, XtCXVaryOffset, XtRBoolean, sizeof(Boolean),
68       XtOffset(XwFormConstraints, x_vary_offset), XtRString, "False"
69    },
70 
71    {
72       XtNxResizable, XtCXResizable, XtRBoolean, sizeof(Boolean),
73       XtOffset(XwFormConstraints, x_resizable), XtRString, "False"
74    },
75 
76    {
77       XtNxAttachRight, XtCXAttachRight, XtRBoolean, sizeof(Boolean),
78       XtOffset(XwFormConstraints, x_attach_right), XtRString, "False"
79    },
80 
81    {
82       XtNxAttachOffset, XtCXAttachOffset, XtRInt, sizeof(int),
83       XtOffset(XwFormConstraints, x_attach_offset), XtRString, "0"
84    },
85 
86    {
87       XtNyRefName, XtCYRefName, XtRString, sizeof(caddr_t),
88       XtOffset(XwFormConstraints, y_ref_name), XtRString, (caddr_t) NULL
89    },
90 
91    {
92       XtNyRefWidget, XtCYRefWidget, XtRPointer, sizeof(caddr_t),
93       XtOffset(XwFormConstraints, y_ref_widget), XtRPointer, NULL
94    },
95 
96    {
97       XtNyOffset, XtCYOffset, XtRInt, sizeof(int),
98       XtOffset(XwFormConstraints, y_offset), XtRString, "0"
99    },
100 
101    {
102       XtNyAddHeight, XtCYAddHeight, XtRBoolean, sizeof(Boolean),
103       XtOffset(XwFormConstraints, y_add_height), XtRString, "False"
104    },
105 
106    {
107       XtNyVaryOffset, XtCYVaryOffset, XtRBoolean, sizeof(Boolean),
108       XtOffset(XwFormConstraints, y_vary_offset), XtRString, "False"
109    },
110 
111    {
112       XtNyResizable, XtCYResizable, XtRBoolean, sizeof(Boolean),
113       XtOffset(XwFormConstraints, y_resizable), XtRString, "False"
114    },
115 
116    {
117       XtNyAttachBottom, XtCYAttachBottom, XtRBoolean, sizeof(Boolean),
118       XtOffset(XwFormConstraints, y_attach_bottom), XtRString, "False"
119    },
120 
121    {
122       XtNyAttachOffset, XtCYAttachOffset, XtRInt, sizeof(int),
123       XtOffset(XwFormConstraints, y_attach_offset), XtRString, "0"
124    }
125 };
126 
127 
128 
129 /*  Static routine definitions  */
130 
131 static void    Initialize();
132 static void    Realize();
133 static void    Resize();
134 static void    Destroy();
135 static Boolean SetValues();
136 
137 static void      ChangeManaged();
138 static XtGeometryResult GeometryManager();
139 
140 static void      ConstraintInitialize();
141 static void    ConstraintDestroy();
142 static Boolean ConstraintSetValues();
143 
144 static void        GetRefWidget();
145 static Widget      XwFindWidget();
146 static XwFormRef * XwGetFormRef();
147 static Widget      XwFindValidRef();
148 static XwFormRef * XwRefTreeSearch();
149 static XwFormRef * XwParentRefTreeSearch();
150 static void        XwMakeRefs();
151 static void        XwDestroyRefs();
152 static void        XwProcessRefs();
153 static void        XwAddRef();
154 static void        XwRemoveRef();
155 static void        XwFindDepthAndCount();
156 static void        XwInitProcessList();
157 static void        XwConstrainList();
158 static void        XwFreeConstraintList();
159 
160 
161 /*  Static global variable definitions  */
162 
163 static int depth, leaves, arrayIndex;
164 
165 
166 /*  The Form class record */
167 
168 XwFormClassRec XwformClassRec =
169 {
170    {
171       (WidgetClass) &XwmanagerClassRec, /* superclass	         */
172       "XwForm",                         /* class_name	         */
173       sizeof(XwFormRec),                /* widget_size	         */
174       NULL,                             /* class_initialize      */
175       NULL,                             /* class_part_initialize */
176       FALSE,                            /* class_inited          */
177       (XtInitProc) Initialize,          /* initialize	         */
178       NULL,                             /* initialize_hook       */
179       (XtRealizeProc) Realize,          /* realize	         */
180       NULL,	                        /* actions               */
181       0,                                /* num_actions	         */
182       NULL,                             /* resources	         */
183       0,                                /* num_resources         */
184       NULLQUARK,                        /* xrm_class	         */
185       TRUE,                             /* compress_motion       */
186       TRUE,                             /* compress_exposure     */
187       TRUE,                             /* compress_enterleave   */
188       FALSE,                            /* visible_interest      */
189       (XtWidgetProc) Destroy,           /* destroy               */
190       (XtWidgetProc) Resize,            /* resize                */
191       NULL,                             /* expose                */
192       (XtSetValuesFunc) SetValues,      /* set_values	         */
193       NULL,                             /* set_values_hook       */
194       XtInheritSetValuesAlmost,         /* set_values_almost     */
195       NULL,                             /* get_values_hook       */
196       NULL,                             /* accept_focus	         */
197       XtVersion,                        /* version               */
198       NULL,                             /* callback private      */
199       NULL,                             /* tm_table              */
200       NULL,                             /* query_geometry        */
201     /* display_accelerator	*/	XtInheritDisplayAccelerator,
202     /* extension		*/	NULL
203    },
204 
205    {                                         /*  composite class           */
206       (XtGeometryHandler) GeometryManager,   /*  geometry_manager          */
207       (XtWidgetProc) ChangeManaged,          /*  change_managed            */
208       XtInheritInsertChild,		     /* insert_child	           */
209       XtInheritDeleteChild,                  /*  delete_child (inherited)  */
210       NULL,
211    },
212 
213    {                                      /*  constraint class            */
214       constraintResources,		  /*  constraint resource set     */
215       XtNumber(constraintResources),      /*  num_resources               */
216       sizeof(XwFormConstraintRec),	  /*  size of the constraint data */
217       (XtInitProc) ConstraintInitialize,  /*  contraint initilize proc    */
218       (XtWidgetProc) ConstraintDestroy,   /*  contraint destroy proc      */
219       (XtSetValuesFunc) ConstraintSetValues,  /*  contraint set values proc */
220       NULL,
221    },
222 
223    {                           /*  manager class      */
224       (XwTraversalProc) XtInheritTraversalProc   /*  traversal handler  */
225    },
226 
227    {              /*  form class  */
228       0           /*  mumble      */
229    }
230 };
231 
232 
233 WidgetClass XwformWidgetClass = (WidgetClass) &XwformClassRec;
234 
235 
236 
237 
238 /************************************************************************
239  *
240  *  Initialize
241  *     The main widget instance initialization routine.
242  *
243  ************************************************************************/
244 
Initialize(request,new)245 static void Initialize (request, new)
246 XwFormWidget request, new;
247 
248 {
249    /*  Initialize the tree fields to NULL  */
250 
251    new -> form.width_tree =
252       XwGetFormRef (new, NULL, 0, False, False, True, False, 0, 0, 0);
253    new -> form.height_tree =
254       XwGetFormRef (new, NULL, 0, False, False, True, False, 0, 0, 0);
255 
256 
257    /*  Set up a geometry for the widget if it is currently 0.  */
258 
259    if (request -> core.width == 0)
260       new -> core.width += 200;
261    if (request -> core.height == 0)
262       new -> core.height += 200;
263 }
264 
265 
266 
267 
268 /************************************************************************
269  *
270  *  ConstraintInitialize
271  *     The main widget instance constraint initialization routine.
272  *
273  ************************************************************************/
274 
ConstraintInitialize(request,new)275 static void ConstraintInitialize (request, new)
276 Widget request, new;
277 
278 {
279    XwFormConstraintRec * constraintRec;
280 
281    constraintRec = (XwFormConstraintRec *) new -> core.constraints;
282 
283 
284    /*  Initialize the contraint widget sizes for later processing  */
285 
286    constraintRec -> set_x = 0;
287    constraintRec -> set_y = 0;
288    constraintRec -> set_width = 0;
289    constraintRec -> set_height = 0;
290 
291    constraintRec -> x = new -> core.x;
292    constraintRec -> y = new -> core.y;
293    constraintRec -> width = new -> core.width;
294    constraintRec -> height = new -> core.height;
295 
296    constraintRec -> managed = False;
297 
298 
299    /*  Get and save copies of the names of the reference widgets  */
300 
301    GetRefWidget (&constraintRec -> x_ref_widget,
302                  &constraintRec -> x_ref_name, new);
303    GetRefWidget (&constraintRec -> y_ref_widget,
304                  &constraintRec -> y_ref_name, new);
305 
306 }
307 
308 
309 
310 
311 /************************************************************************
312  *
313  *  GetRefWidget
314  *     Get and verify the reference widget given.
315  *
316  ************************************************************************/
317 
GetRefWidget(widget,name,new)318 static void GetRefWidget (widget, name, new)
319 Widget *  widget;
320 char   ** name;
321 Widget    new;
322 
323 {
324    if (*widget != NULL)
325    {
326       if (*name != NULL)
327       {
328          if (strcmp (*name, (char *) ((*widget) -> core.name)) != 0)
329          {
330             XtWarning
331                ("Form: The reference widget and widget name do not match.");
332             *name = (char *) (*widget) -> core.name;
333          }
334       }
335       else
336          *name = (char *) (*widget) -> core.name;
337 
338       if ((*widget) != new -> core.parent &&
339           (*widget) -> core.parent != new -> core.parent)
340       {
341          XtWarning ("Form: The reference widget is not a child of the form");
342          XtWarning ("      or the form widget.");
343          *name = new -> core.parent -> core.name;
344          *widget = new -> core.parent;
345       }
346    }
347 
348    else if (*name != NULL)
349    {
350       if ((*widget = XwFindWidget ((CompositeWidget)(new->core.parent), *name)) == NULL)
351       {
352 	 XtWarning ("Form: The reference widget was not found.");
353          *name = new -> core.parent -> core.name;
354          *widget = new -> core.parent;
355       }
356    }
357    else
358    {
359       *name = new -> core.parent -> core.name;
360       *widget = new -> core.parent;
361    }
362 
363    *name = strcpy (XtMalloc((unsigned) XwStrlen (*name) + 1), *name);
364 }
365 
366 
367 
368 
369 /************************************************************************
370  *
371  *  XwFindWidget
372  *
373  ************************************************************************/
374 
XwFindWidget(w,name)375 static Widget XwFindWidget (w, name)
376 CompositeWidget w;
377 char   * name;
378 
379 {
380    register int i;
381    register Widget * list;
382    int count;
383 
384    if (strcmp (name, w -> core.name) == 0)
385       return ((Widget) w);
386 
387    list = w -> composite.children;
388    count = w -> composite.num_children;
389 
390    for (i = 0; i < count; i++)
391    {
392       if (strcmp (name, (*list) -> core.name) == 0)
393          return (*list);
394       list++;
395    }
396    return (NULL);
397 }
398 
399 
400 
401 
402 /************************************************************************
403  *
404  *  Realize
405  *	Create the widget window and create the gc's.
406  *
407  ************************************************************************/
408 
Realize(fw,valueMask,attributes)409 static void Realize (fw, valueMask, attributes)
410 XwFormWidget           fw;
411 XtValueMask          * valueMask;
412 XSetWindowAttributes * attributes;
413 
414 {
415    Mask newValueMask = *valueMask;
416    XtCreateWindow ((Widget)fw, InputOutput, (Visual *) CopyFromParent,
417 		   newValueMask, attributes);
418    _XwRegisterName(fw);
419    XwProcessRefs (fw, False);
420 }
421 
422 
423 
424 
425 /************************************************************************
426  *
427  *  Resize
428  *
429  ************************************************************************/
430 
Resize(fw)431 static void Resize (fw)
432 XwFormWidget fw;
433 
434 {
435    if (XtIsRealized ((Widget)fw)) XwProcessRefs (fw, False);
436 }
437 
438 
439 
440 
441 
442 /************************************************************************
443  *
444  *  Destroy
445  *	Deallocate the head structures of the reference trees.
446  *	The rest of the tree has already been deallocated.
447  *
448  ************************************************************************/
449 
Destroy(fw)450 static void Destroy (fw)
451 XwFormWidget fw;
452 
453 {
454    XtFree ((char *)(fw -> form.width_tree));
455    XtFree ((char *)(fw -> form.height_tree));
456 }
457 
458 
459 
460 
461 /************************************************************************
462  *
463  *  ConstraintDestroy
464  *	Deallocate the allocated referenence names.
465  *
466  ************************************************************************/
467 
ConstraintDestroy(w)468 static void ConstraintDestroy (w)
469 XwFormWidget w;
470 
471 {
472    XwFormConstraintRec * constraint;
473 
474    constraint = (XwFormConstraintRec *) w -> core.constraints;
475 
476    if (constraint -> x_ref_name != NULL) XtFree (constraint -> x_ref_name);
477    if (constraint -> y_ref_name != NULL) XtFree (constraint -> y_ref_name);
478 }
479 
480 
481 
482 
483 
484 /************************************************************************
485  *
486  *  SetValues
487  *	Currently nothing needs to be done.  The XtSetValues call
488  *	handles geometry requests and form does not define any
489  *	new resources.
490  *
491  ************************************************************************/
492 
SetValues(current,request,new)493 static Boolean SetValues (current, request, new)
494 XwFormWidget current, request, new;
495 
496 {
497    return (False);
498 }
499 
500 
501 
502 
503 /************************************************************************
504  *
505  *  ConstraintSetValues
506  *	Process changes in the constraint set of a widget.
507  *
508  ************************************************************************/
509 
ConstraintSetValues(current,request,new)510 static Boolean ConstraintSetValues (current, request, new)
511 Widget current, request, new;
512 
513 {
514    XwFormConstraintRec * curConstraint;
515    XwFormConstraintRec * newConstraint;
516    XwFormConstraintRec * tempConstraint;
517 
518 
519    curConstraint = (XwFormConstraintRec *) current -> core.constraints;
520    newConstraint = (XwFormConstraintRec *) new -> core.constraints;
521 
522 
523    /*  Check the geometrys to see if new's contraint record  */
524    /*  saved geometry data needs to be updated.              */
525 
526    if (XtIsRealized (current))
527    {
528       if (new -> core.x != current -> core.x)
529          newConstraint -> set_x = new -> core.x;
530       if (new -> core.y != current -> core.y)
531          newConstraint -> set_y = new -> core.y;
532       if (new -> core.width != current -> core.width)
533          newConstraint -> set_width = new -> core.width;
534       if (new -> core.height != current -> core.height)
535          newConstraint -> set_height = new -> core.height;
536    }
537 
538 
539    /*  If the reference widget or name has changed, set the  */
540    /*  opposing member to NULL in order to get the proper    */
541    /*  referencing.  For names, the string space will be     */
542    /*  deallocated out of current later.                     */
543 
544    if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget)
545       newConstraint -> x_ref_name = NULL;
546    else if (newConstraint -> x_ref_name != curConstraint -> x_ref_name)
547       newConstraint -> x_ref_widget = NULL;
548 
549    if (newConstraint -> y_ref_widget != curConstraint -> y_ref_widget)
550       newConstraint -> y_ref_name = NULL;
551    else if (newConstraint -> y_ref_name != curConstraint -> y_ref_name)
552       newConstraint -> y_ref_widget = NULL;
553 
554 
555    /*  Get and save copies of the names of the reference widget names  */
556    /*  and get the reference widgets.                                  */
557 
558    GetRefWidget (&newConstraint -> x_ref_widget,
559                  &newConstraint -> x_ref_name, new);
560    GetRefWidget (&newConstraint -> y_ref_widget,
561                  &newConstraint -> y_ref_name, new);
562 
563 
564    /*  See if the reference widgets have changed.  If so, free the  */
565    /*  old allocated names and set them to the new names.           */
566 
567    if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget)
568    {
569       XtFree (curConstraint -> x_ref_name);
570       curConstraint -> x_ref_name = newConstraint -> x_ref_name;
571    }
572 
573    if (newConstraint -> y_ref_widget != curConstraint -> y_ref_widget)
574    {
575       XtFree (curConstraint -> y_ref_name);
576       curConstraint -> y_ref_name = newConstraint -> y_ref_name;
577    }
578 
579 
580    /*  See if any constraint data for the widget has changed.  */
581    /*  Is so, remove the old reference tree elements from the  */
582    /*  forms constraint processing trees and build and insert  */
583    /*  new reference tree elements.                            */
584    /*                                                          */
585    /*  Once this is finished, reprocess the constraint trees.  */
586 
587    if (newConstraint -> x_ref_widget != curConstraint -> x_ref_widget       ||
588        newConstraint -> y_ref_widget != curConstraint -> y_ref_widget       ||
589 
590        newConstraint -> x_offset != curConstraint -> x_offset               ||
591        newConstraint -> y_offset != curConstraint -> y_offset               ||
592 
593        newConstraint -> x_vary_offset != curConstraint -> x_vary_offset     ||
594        newConstraint -> y_vary_offset != curConstraint -> y_vary_offset     ||
595 
596        newConstraint -> x_resizable != curConstraint -> x_resizable         ||
597        newConstraint -> y_resizable != curConstraint -> y_resizable         ||
598 
599        newConstraint -> x_add_width != curConstraint -> x_add_width         ||
600        newConstraint -> y_add_height != curConstraint -> y_add_height       ||
601 
602        newConstraint -> x_attach_right != curConstraint -> x_attach_right   ||
603        newConstraint -> y_attach_bottom != curConstraint -> y_attach_bottom ||
604 
605        newConstraint -> x_attach_offset != curConstraint -> x_attach_offset ||
606        newConstraint -> y_attach_offset != curConstraint -> y_attach_offset)
607    {
608       if (XtIsRealized (current) && current -> core.managed)
609       {
610          XwDestroyRefs (current);
611 
612          tempConstraint = (XwFormConstraintRec *) current -> core.constraints;
613          current -> core.constraints = new -> core.constraints;
614          XwMakeRefs (current);
615          current -> core.constraints = (caddr_t) tempConstraint;
616       }
617 
618       if (XtIsRealized (current)) XwProcessRefs (new -> core.parent, True);
619    }
620 
621    return (False);
622 }
623 
624 
625 
626 
627 /************************************************************************
628  *
629  *  GeometryManager
630  *      Always accept the childs new size, set the childs constraint
631  *      record size to the new size and process the constraints.
632  *
633  ************************************************************************/
634 
GeometryManager(w,request,reply)635 static XtGeometryResult GeometryManager (w, request, reply)
636 Widget w;
637 XtWidgetGeometry * request;
638 XtWidgetGeometry * reply;
639 
640 {
641    XwFormWidget fw = (XwFormWidget) w -> core.parent;
642    XwFormConstraintRec * constraint;
643    XwFormRef * xRef;
644    XwFormRef * yRef;
645    int newBorder = w -> core.border_width;
646    Boolean moveFlag = False;
647    Boolean resizeFlag = False;
648 
649 
650    constraint = (XwFormConstraintRec *) w -> core.constraints;
651 
652    if (request -> request_mode & CWX)
653       constraint -> set_x = request -> x;
654 
655    if (request -> request_mode & CWY)
656       constraint -> set_y = request -> y;
657 
658    if (request -> request_mode & CWWidth)
659       constraint -> set_width = request -> width;
660 
661    if (request -> request_mode & CWHeight)
662       constraint -> set_height = request -> height;
663 
664    if (request -> request_mode & CWBorderWidth)
665       newBorder = request -> border_width;
666 
667 
668    /*  If the x or the width has changed, find the horizontal  */
669    /*  reference tree structure for this widget and update it  */
670 
671    xRef = yRef = NULL;
672    if  ((request->request_mode & CWWidth) || (request->request_mode & CWX))
673    {
674       if ((xRef = XwRefTreeSearch (w, fw -> form.width_tree)) != NULL)
675       {
676          if  (request->request_mode & CWX)
677             xRef -> set_loc = request -> x;
678          if  (request->request_mode & CWWidth)
679             xRef -> set_size = request -> width;
680       }
681    }
682 
683 
684    /*  If the y or the height has changed, find the vertical   */
685    /*  reference tree structure for this widget and update it  */
686 
687    if  ((request->request_mode & CWHeight) || (request->request_mode & CWY))
688    {
689       if ((yRef = XwRefTreeSearch (w, fw -> form.height_tree)) != NULL)
690       {
691          if  (request->request_mode & CWY)
692             yRef -> set_loc = request -> y;
693          if  (request->request_mode & CWHeight)
694             yRef -> set_size = request -> height;
695       }
696    }
697 
698 
699    /*  Process the constraints if either of the ref structs have changed */
700 
701    if (xRef != NULL || yRef != NULL)
702    {
703       if ((request->request_mode & CWX) || (request->request_mode & CWY))
704          moveFlag = True;
705       if ((request->request_mode & CWWidth) ||
706           (request->request_mode & CWHeight))
707          resizeFlag = True;
708 
709       if (moveFlag && resizeFlag)
710          XtConfigureWidget (w, constraint -> set_x, constraint -> set_y,
711                             constraint -> set_width, constraint -> set_height,
712                             newBorder);
713       else if (resizeFlag)
714          XtResizeWidget (w, constraint -> set_width, constraint -> set_height,
715                             newBorder);
716       else if (moveFlag)
717          XtMoveWidget (w, constraint -> set_x, constraint -> set_y);
718 
719 
720       XwProcessRefs (w -> core.parent, True);
721    }
722 
723 
724    /*  See if an almost condition should be returned  */
725 
726    if (((request->request_mode & CWX) && w->core.x != request->x) ||
727        ((request->request_mode & CWY) && w->core.y != request->y) ||
728        ((request->request_mode & CWWidth) &&
729          w->core.width != request->width) ||
730        ((request->request_mode & CWHeight) &&
731          w->core.height != request->height))
732    {
733       reply->request_mode = request->request_mode;
734 
735       if (request->request_mode & CWX) reply->x = w->core.x;
736       if (request->request_mode & CWY) reply->y = w->core.y;
737       if (request->request_mode & CWWidth) reply->width = w->core.width;
738       if (request->request_mode & CWHeight) reply->height = w->core.height;
739       if (request->request_mode & CWBorderWidth)
740          reply->border_width = request->border_width;
741       if (request->request_mode & CWSibling)
742          reply->sibling = request->sibling;
743       if (request->request_mode & CWStackMode)
744           reply->stack_mode = request->stack_mode;
745 
746       return (XtGeometryAlmost);
747    }
748 
749    return (XtGeometryDone);
750 }
751 
752 
753 
754 
755 /************************************************************************
756  *
757  *  ChangeManaged
758  *
759  ************************************************************************/
760 
ChangeManaged(fw)761 static void ChangeManaged (fw)
762 XwFormWidget fw;
763 
764 {
765    Widget child;
766    XwFormConstraintRec * constraint;
767    register int i;
768 
769 
770    /*  If the widget is being managed, build up the reference     */
771    /*  structures for it, adjust any references, and process the  */
772    /*  reference set.  If unmanaged, remove its reference.        */
773 
774    for (i = 0; i < fw -> composite.num_children; i++)
775    {
776       child = fw -> composite.children[i];
777       constraint = (XwFormConstraintRec *) child -> core.constraints;
778 
779       if (constraint -> set_width == 0)
780       {
781          constraint -> set_x = child -> core.x;
782          constraint -> set_y = child -> core.y;
783          constraint -> set_width = child -> core.width;
784          constraint -> set_height = child -> core.height;
785       }
786 
787       if (child -> core.managed != constraint -> managed)
788       {
789 	 if (child -> core.managed)
790          {
791             if (constraint->width_when_unmanaged != child->core.width)
792                constraint->set_width = child->core.width;
793             if (constraint->height_when_unmanaged != child->core.height)
794                constraint->set_height = child->core.height;
795             XwMakeRefs (child);
796          }
797          else
798          {
799             constraint -> width_when_unmanaged = child->core.width;
800             constraint -> height_when_unmanaged = child->core.height;
801             XwDestroyRefs (child);
802          }
803          constraint -> managed = child -> core.managed;
804       }
805    }
806 
807    XwProcessRefs (fw, True);
808 }
809 
810 
811 
812 
813 /************************************************************************
814  *
815  *  XwMakeRefs
816  *	Build up and insert into the forms reference trees the reference
817  *      structures needed for the widget w.
818  *
819  ************************************************************************/
820 
XwMakeRefs(w)821 static void XwMakeRefs (w)
822 Widget w;
823 
824 {
825    Widget xRefWidget;
826    Widget yRefWidget;
827    XwFormWidget formWidget;
828    XwFormConstraintRec * constraint;
829    XwFormRef * xRefParent;
830    XwFormRef * yRefParent;
831    XwFormRef * xRef;
832    XwFormRef * yRef;
833    XwFormRef * checkRef;
834    register int i;
835 
836 
837    formWidget = (XwFormWidget) w -> core.parent;
838    constraint = (XwFormConstraintRec *) w -> core.constraints;
839 
840 
841    /*  The "true" reference widget may be unmanaged, so  */
842    /*  we need to back up through the reference set      */
843    /*  perhaps all the way to Form.                      */
844 
845    xRefWidget = XwFindValidRef (constraint -> x_ref_widget, XwHORIZONTAL,
846                                 formWidget -> form.width_tree);
847    yRefWidget = XwFindValidRef (constraint -> y_ref_widget, XwVERTICAL,
848                                 formWidget -> form.height_tree);
849 
850 
851    /*  Search the referencing trees for the referencing widgets  */
852    /*  The constraint reference struct will be added as a child  */
853    /*  of this struct.                                           */
854 
855    if (xRefWidget != NULL)
856       xRefParent = XwRefTreeSearch (xRefWidget, formWidget -> form.width_tree);
857 
858    if (yRefWidget != NULL)
859       yRefParent = XwRefTreeSearch (yRefWidget, formWidget->form.height_tree);
860 
861 
862    /*  Allocate, initialize, and insert the reference structures  */
863 
864    if (xRefWidget != NULL)
865    {
866       xRef = XwGetFormRef (w, xRefWidget, constraint->x_offset,
867  		           constraint->x_add_width, constraint->x_vary_offset,
868 		           constraint->x_resizable, constraint->x_attach_right,
869 		           constraint->x_attach_offset,
870   			   constraint->set_x, constraint->set_width);
871       XwAddRef (xRefParent, xRef);
872    }
873 
874    if (yRefWidget != NULL)
875    {
876       yRef = XwGetFormRef(w, yRefWidget, constraint->y_offset,
877 		          constraint->y_add_height, constraint->y_vary_offset,
878 		          constraint->y_resizable, constraint->y_attach_bottom,
879 		          constraint->y_attach_offset,
880 			  constraint->set_y, constraint->set_height);
881       XwAddRef (yRefParent, yRef);
882    }
883 
884 
885    /*  Search through the parents reference set to get any child  */
886    /*  references which need to be made child references of the   */
887    /*  widget just added.                                         */
888 
889    for (i = 0; i < xRefParent -> ref_to_count; i++)
890    {
891       checkRef = xRefParent -> ref_to[i];
892       constraint = (XwFormConstraintRec *) checkRef->this->core.constraints;
893 
894       if (XwFindValidRef (constraint->x_ref_widget, XwHORIZONTAL,
895                           formWidget -> form.width_tree) != xRefWidget)
896       {
897  	 XwRemoveRef (xRefParent, checkRef);
898          checkRef -> ref = xRef -> this;
899 	 XwAddRef (xRef, checkRef);
900       }
901    }
902 
903    for (i = 0; i < yRefParent -> ref_to_count; i++)
904    {
905       checkRef = yRefParent -> ref_to[i];
906       constraint = (XwFormConstraintRec *) checkRef->this->core.constraints;
907 
908       if (XwFindValidRef (constraint->y_ref_widget, XwVERTICAL,
909                           formWidget -> form.height_tree) != yRefWidget)
910       {
911  	 XwRemoveRef (yRefParent, checkRef);
912          checkRef -> ref = yRef -> this;
913 	 XwAddRef (yRef, checkRef);
914       }
915    }
916 }
917 
918 
919 
920 
921 /************************************************************************
922  *
923  *  XwDestroyRefs
924  *	Remove and deallocate the reference structures for the widget w.
925  *
926  ************************************************************************/
927 
XwDestroyRefs(w)928 static void XwDestroyRefs (w)
929 Widget w;
930 
931 {
932    Widget xRefWidget;
933    Widget yRefWidget;
934    XwFormWidget formWidget;
935    XwFormConstraintRec * constraint;
936    XwFormRef * xRefParent;
937    XwFormRef * yRefParent;
938    XwFormRef * xRef;
939    XwFormRef * yRef;
940    XwFormRef * tempRef;
941    register int i;
942 
943 
944    formWidget = (XwFormWidget) w -> core.parent;
945    constraint = (XwFormConstraintRec *) w -> core.constraints;
946 
947 
948    /*  Search through the reference trees to see if the widget  */
949    /*  is within the tree.                                      */
950 
951    xRefWidget = w;
952    yRefWidget = w;
953 
954    xRefParent =
955       XwParentRefTreeSearch (xRefWidget, formWidget -> form.width_tree,
956                                          formWidget -> form.width_tree);
957    yRefParent =
958       XwParentRefTreeSearch (yRefWidget, formWidget -> form.height_tree,
959                                           formWidget -> form.height_tree);
960 
961 
962    /*  For both the width and height references, if the ref parent was  */
963    /*  not null, find the reference to be removed within the parents    */
964    /*  list, remove this reference.  Then, for any references attached  */
965    /*  to the one just removed, reparent them to the parent reference.  */
966 
967    if (xRefParent != NULL)
968    {
969       for (i = 0; i < xRefParent -> ref_to_count; i++)
970       {
971          if (xRefParent -> ref_to[i] -> this == xRefWidget)
972          {
973              xRef = xRefParent -> ref_to[i];
974 	     break;
975          }
976       }
977 
978       XwRemoveRef (xRefParent, xRefParent -> ref_to[i]);
979 
980       while (xRef -> ref_to_count)
981       {
982          tempRef = xRef -> ref_to[0];
983          tempRef -> ref = xRefParent -> this;
984 	 XwRemoveRef (xRef, tempRef);
985 	 XwAddRef (xRefParent, tempRef);
986       }
987 
988       XtFree ((char *)xRef);
989    }
990 
991    if (yRefParent != NULL)
992    {
993       for (i = 0; i < yRefParent -> ref_to_count; i++)
994       {
995          if (yRefParent -> ref_to[i] -> this == yRefWidget)
996          {
997             yRef = yRefParent -> ref_to[i];
998 	    break;
999 	 }
1000       }
1001 
1002       XwRemoveRef (yRefParent, yRef);
1003 
1004       while (yRef -> ref_to_count)
1005       {
1006          tempRef = yRef -> ref_to[0];
1007          tempRef -> ref = yRefParent -> this;
1008 	 XwRemoveRef (yRef, tempRef);
1009 	 XwAddRef (yRefParent, tempRef);
1010       }
1011 
1012       XtFree ((char *)yRef);
1013    }
1014 }
1015 
1016 
1017 
1018 
1019 /************************************************************************
1020  *
1021  *  XwGetFormRef
1022  *	Allocate and initialize a form constraint referencing structure.
1023  *
1024  ************************************************************************/
1025 
1026 static XwFormRef *
XwGetFormRef(this,ref,offset,add,vary,resizable,attach,attach_offset,loc,size)1027 XwGetFormRef (this, ref, offset, add, vary,
1028 	      resizable, attach, attach_offset, loc, size)
1029 Widget  this;
1030 Widget  ref;
1031 int     offset;
1032 Boolean add;
1033 Boolean vary;
1034 Boolean resizable;
1035 Boolean attach;
1036 int     attach_offset;
1037 
1038 {
1039    XwFormRef * formRef;
1040 
1041    formRef = (XwFormRef *) XtMalloc (sizeof (XwFormRef));
1042    formRef -> this = this;
1043    formRef -> ref = ref;
1044    formRef -> offset = offset;
1045    formRef -> add = add;
1046    formRef -> vary = vary;
1047    formRef -> resizable = resizable;
1048    formRef -> attach = attach;
1049    formRef -> attach_offset = attach_offset;
1050 
1051    formRef -> set_loc = loc;
1052    formRef -> set_size = size;
1053 
1054    formRef -> ref_to = NULL;
1055    formRef -> ref_to_count = 0;
1056 
1057    return (formRef);
1058 }
1059 
1060 
1061 
1062 
1063 /************************************************************************
1064  *
1065  *  XwFindValidRef
1066  *	Given an initial reference widget to be used as a constraint,
1067  *	find a valid (managed) reference widget.  This is done by
1068  *	backtracking through the widget references listed in the
1069  *	constraint records.  If no valid constraint is found, "form"
1070  *	is returned indicating that this reference should be stuck
1071  *	immediately under the form reference structure.
1072  *
1073  ************************************************************************/
1074 
XwFindValidRef(refWidget,refType,formRef)1075 static Widget XwFindValidRef (refWidget, refType, formRef)
1076 Widget refWidget;
1077 int    refType;
1078 XwFormRef * formRef;
1079 
1080 {
1081    XwFormConstraintRec * constraint;
1082 
1083    if (refWidget == NULL) return (NULL);
1084 
1085    while (1)
1086    {
1087       if (XwRefTreeSearch (refWidget, formRef) != NULL) return (refWidget);
1088 
1089       constraint = (XwFormConstraintRec *) refWidget -> core.constraints;
1090 
1091       if (refType == XwHORIZONTAL) refWidget = constraint -> x_ref_widget;
1092       else refWidget = constraint -> y_ref_widget;
1093 
1094       if (refWidget == NULL) return (refWidget -> core.parent);
1095    }
1096 }
1097 
1098 
1099 
1100 
1101 /************************************************************************
1102  *
1103  *  XwRefTreeSearch
1104  *	Search the reference tree until the widget listed is found.
1105  *
1106  ************************************************************************/
1107 
XwRefTreeSearch(w,formRef)1108 static XwFormRef * XwRefTreeSearch (w, formRef)
1109 Widget w;
1110 XwFormRef * formRef;
1111 
1112 {
1113    register int i;
1114    XwFormRef * tempRef;
1115 
1116    if (formRef == NULL) return (NULL);
1117    if (formRef -> this == w) return (formRef);
1118 
1119    for (i = 0; i < formRef -> ref_to_count; i++)
1120    {
1121       tempRef = XwRefTreeSearch (w, formRef -> ref_to[i]);
1122       if (tempRef != NULL) return (tempRef);
1123    }
1124 
1125    return (NULL);
1126 }
1127 
1128 
1129 
1130 
1131 /************************************************************************
1132  *
1133  *  XwParentRefTreeSearch
1134  *	Search the reference tree until the parent reference of the
1135  *      widget listed is found.
1136  *
1137  ************************************************************************/
1138 
XwParentRefTreeSearch(w,wFormRef,parentFormRef)1139 static XwFormRef * XwParentRefTreeSearch (w, wFormRef, parentFormRef)
1140 Widget w;
1141 XwFormRef * wFormRef;
1142 XwFormRef * parentFormRef;
1143 
1144 {
1145    register int i;
1146    XwFormRef * tempRef;
1147 
1148    if (parentFormRef == NULL) return (NULL);
1149    if (wFormRef -> this == w) return (parentFormRef);
1150 
1151    for (i = 0; i < wFormRef -> ref_to_count; i++)
1152    {
1153       tempRef =
1154          XwParentRefTreeSearch (w, wFormRef -> ref_to[i], wFormRef);
1155       if (tempRef != NULL) return (tempRef);
1156    }
1157 
1158    return (NULL);
1159 }
1160 
1161 
1162 
1163 
1164 /************************************************************************
1165  *
1166  *  XwAddRef
1167  *	Add a reference structure into a parent reference structure.
1168  *
1169  ************************************************************************/
1170 
XwAddRef(refParent,ref)1171 static void XwAddRef (refParent, ref)
1172 XwFormRef * refParent;
1173 XwFormRef * ref;
1174 
1175 {
1176    refParent -> ref_to =
1177       (XwFormRef **)
1178 	 XtRealloc ((char *) refParent -> ref_to,
1179                     sizeof (XwFormRef *) * (refParent -> ref_to_count + 1));
1180 
1181    refParent -> ref_to[refParent -> ref_to_count] = ref;
1182    refParent -> ref_to_count += 1;
1183 }
1184 
1185 
1186 
1187 
1188 /************************************************************************
1189  *
1190  *  XwRemoveRef
1191  *	Remove a reference structure from a parent reference structure.
1192  *
1193  ************************************************************************/
1194 
XwRemoveRef(refParent,ref)1195 static void XwRemoveRef (refParent, ref)
1196 XwFormRef * refParent;
1197 XwFormRef * ref;
1198 
1199 {
1200    register int i, j;
1201 
1202    for (i = 0; i < refParent -> ref_to_count; i++)
1203    {
1204       if (refParent -> ref_to[i] == ref)
1205       {
1206 	 for (j = i; j < refParent -> ref_to_count - 1; j++)
1207 	    refParent -> ref_to[j] = refParent -> ref_to[j + 1];
1208          break;
1209       }
1210    }
1211 
1212    if (refParent -> ref_to_count > 1)
1213    {
1214       refParent -> ref_to =
1215          (XwFormRef **)	 XtRealloc ((char *) refParent -> ref_to,
1216          sizeof (XwFormRef *) * (refParent -> ref_to_count - 1));
1217 
1218    }
1219    else
1220    {
1221       XtFree ((char *)(refParent -> ref_to));
1222       refParent -> ref_to = NULL;
1223    }
1224 
1225    refParent -> ref_to_count -= 1;
1226 }
1227 
1228 
1229 
1230 
1231 /************************************************************************
1232  *
1233  *  XwProcessRefs
1234  *	Traverse throught the form's reference trees, calculate new
1235  *      child sizes and locations based on the constraints and adjust
1236  *      the children as is calculated.  The resizable flag indicates
1237  *      whether the form can be resized or not.
1238  *
1239  ************************************************************************/
1240 
XwProcessRefs(fw,formResizable)1241 static void XwProcessRefs (fw, formResizable)
1242 XwFormWidget fw;
1243 Boolean      formResizable;
1244 
1245 {
1246    int formWidth, formHeight;
1247    register int i, j;
1248 
1249    int horDepth, horLeaves;
1250    int vertDepth, vertLeaves;
1251    XwFormProcess ** horProcessList;
1252    XwFormProcess ** vertProcessList;
1253 
1254    XtGeometryResult geometryReturn;
1255    Dimension replyW, replyH;
1256 
1257    XwFormConstraintRec * constraintRec;
1258    Widget child;
1259    Boolean moveFlag, resizeFlag;
1260 
1261 
1262    /*  Initialize the form width and height variables  */
1263 
1264    if (fw -> manager.layout == XwIGNORE) formResizable = False;
1265 
1266    if (formResizable) formWidth = formHeight = -1;
1267    else
1268    {
1269       formWidth = fw -> core.width;
1270       formHeight = fw -> core.height;
1271    }
1272 
1273 
1274    /*  Traverse the reference trees to find the depth and leaf node count  */
1275 
1276    leaves = 0;
1277    depth = 0;
1278    XwFindDepthAndCount (fw -> form.width_tree, 1);
1279    horDepth = depth;
1280    horLeaves = leaves;
1281 
1282    leaves = 0;
1283    depth = 0;
1284    XwFindDepthAndCount (fw -> form.height_tree, 1);
1285    vertDepth = depth;
1286    vertLeaves = leaves;
1287 
1288    if (horDepth == 0 && vertDepth == 0)
1289       return;
1290 
1291 
1292    /*  Allocate and initialize the constraint array processing structures  */
1293 
1294    horProcessList =
1295        (XwFormProcess **) XtMalloc (sizeof (XwFormProcess **) * horLeaves);
1296    for (i = 0; i < horLeaves; i++)
1297    {
1298       horProcessList[i] =
1299          (XwFormProcess *) XtMalloc (sizeof (XwFormProcess) * horDepth);
1300 
1301       for (j = 0; j < horDepth; j++)
1302          horProcessList[i][j].ref = NULL;
1303    }
1304 
1305 
1306    vertProcessList =
1307       (XwFormProcess **) XtMalloc (sizeof (XwFormProcess **) * vertLeaves);
1308    for (i = 0; i < vertLeaves; i++)
1309    {
1310       vertProcessList[i] =
1311          (XwFormProcess *) XtMalloc (sizeof (XwFormProcess) * vertDepth);
1312 
1313       for (j = 0; j < vertDepth; j++)
1314          vertProcessList[i][j].ref = NULL;
1315    }
1316 
1317 
1318    /*  Initialize the process array placing each node of the tree into    */
1319    /*  the array such that it is listed only once and its first children  */
1320    /*  listed directly next within the array.                             */
1321 
1322    arrayIndex = 0;
1323    XwInitProcessList (horProcessList, fw -> form.width_tree, 0);
1324    arrayIndex = 0;
1325    XwInitProcessList (vertProcessList, fw -> form.height_tree, 0);
1326 
1327 
1328    /*  Process each array such that each row of the arrays contain  */
1329    /*  their required sizes and locations to match the constraints  */
1330 
1331    XwConstrainList (horProcessList, horLeaves,
1332 		    horDepth, &formWidth, formResizable, XwHORIZONTAL);
1333    XwConstrainList (vertProcessList, vertLeaves,
1334 		    vertDepth, &formHeight, formResizable, XwVERTICAL);
1335 
1336 
1337    /*  If the form is resizable and the form width or height returned  */
1338    /*  is different from the current form width or height, then make   */
1339    /*  a geometry request to get the new form size.  If almost is      */
1340    /*  returned, use these sizes and reprocess the constrain lists     */
1341 
1342    if (formResizable &&
1343        (formWidth != fw -> core.width || formHeight != fw -> core.height))
1344    {
1345       geometryReturn =
1346 	 XtMakeResizeRequest((Widget)fw, formWidth, formHeight, &replyW, &replyH);
1347 
1348       if (geometryReturn == XtGeometryAlmost)
1349       {
1350          formWidth = replyW;
1351          formHeight = replyH;
1352 
1353 	 XtMakeResizeRequest((Widget)fw, formWidth, formHeight, NULL, NULL);
1354 
1355          XwConstrainList (horProcessList, horLeaves,
1356       		          horDepth, &formWidth, False, XwHORIZONTAL);
1357          XwConstrainList (vertProcessList, vertLeaves,
1358 		          vertDepth, &formHeight, False, XwVERTICAL);
1359       }
1360 
1361       else if (geometryReturn == XtGeometryNo)
1362       {
1363          formWidth = fw -> core.width;
1364          formHeight = fw -> core.height;
1365 
1366          XwConstrainList (horProcessList, horLeaves,
1367       		          horDepth, &formWidth, False, XwHORIZONTAL);
1368          XwConstrainList (vertProcessList, vertLeaves,
1369 		          vertDepth, &formHeight, False, XwVERTICAL);
1370       }
1371    }
1372 
1373 
1374    /*  Process the forms child list to compare the widget sizes and  */
1375    /*  locations with the widgets current values and if changed,     */
1376    /*  reposition, resize, or reconfigure the child.                 */
1377 
1378    for (i = 0; i < fw -> composite.num_children; i++)
1379    {
1380       child = (Widget) fw -> composite.children[i];
1381 
1382       if (child -> core.managed)
1383       {
1384 	 constraintRec = (XwFormConstraintRec *) child -> core.constraints;
1385 
1386          moveFlag = resizeFlag = False;
1387 
1388 	 if (constraintRec -> x != child -> core.x ||
1389 	     constraintRec -> y != child -> core.y)
1390 	    moveFlag = True;
1391 
1392 	 if (constraintRec -> width != child -> core.width ||
1393 	     constraintRec -> height != child -> core.height)
1394 	    resizeFlag = True;
1395 
1396          if (moveFlag && resizeFlag)
1397 	    XtConfigureWidget (child, constraintRec->x, constraintRec->y,
1398                                constraintRec->width, constraintRec->height,
1399                                child -> core.border_width);
1400          else if (moveFlag)
1401 	    XtMoveWidget (child, constraintRec->x, constraintRec->y);
1402          else if (resizeFlag)
1403 	    XtResizeWidget (child, constraintRec->width,
1404                             constraintRec->height, child->core.border_width);
1405       }
1406    }
1407 
1408    XwFreeConstraintList (horProcessList, horLeaves);
1409    XwFreeConstraintList (vertProcessList, vertLeaves);
1410 }
1411 
1412 
1413 
1414 
1415 /************************************************************************
1416  *
1417  *  XwFreeConstraintList
1418  *	Free an allocated constraint list.
1419  *
1420  ************************************************************************/
1421 
XwFreeConstraintList(processList,leaves)1422 static void XwFreeConstraintList (processList, leaves)
1423 XwFormProcess ** processList;
1424 int leaves;
1425 
1426 {
1427    register int i;
1428 
1429 
1430    /*  Free each array attached to the list then free the list  */
1431 
1432    for (i = 0; i < leaves; i++)
1433       XtFree ((char *)(processList[i]));
1434 
1435    XtFree ((char *)processList);
1436 }
1437 
1438 
1439 
1440 
1441 /************************************************************************
1442  *
1443  *  XwFindDepthAndCount
1444  *	Search a constraint reference tree and find the maximum depth
1445  *      of the tree and the number of leaves in the tree.
1446  *
1447  ************************************************************************/
1448 
XwFindDepthAndCount(node,nodeLevel)1449 static void XwFindDepthAndCount (node, nodeLevel)
1450 XwFormRef * node;
1451 int         nodeLevel;
1452 
1453 {
1454    register int i;
1455 
1456    if (node -> ref_to == NULL) leaves++;
1457    else
1458    {
1459       nodeLevel++;
1460       if (nodeLevel > depth) depth = nodeLevel;
1461       for (i = 0; i < node -> ref_to_count; i++)
1462 	 XwFindDepthAndCount (node -> ref_to[i], nodeLevel);
1463    }
1464 }
1465 
1466 
1467 
1468 
1469 /************************************************************************
1470  *
1471  *  XwInitProcessList
1472  *	Search a constraint reference tree and find place the ref node
1473  *      pointers into the list.
1474  *
1475  ************************************************************************/
1476 
XwInitProcessList(processList,node,nodeLevel)1477 static void XwInitProcessList (processList, node, nodeLevel)
1478 XwFormProcess ** processList;
1479 XwFormRef      * node;
1480 int              nodeLevel;
1481 
1482 {
1483    register int i;
1484 
1485    processList[arrayIndex][nodeLevel].ref = node;
1486 
1487    if (node -> ref_to == NULL)
1488    {
1489       processList[arrayIndex][nodeLevel].leaf = True;
1490       arrayIndex++;
1491    }
1492    else
1493    {
1494       processList[arrayIndex][nodeLevel].leaf = False;
1495       nodeLevel++;
1496       for (i = 0; i < node -> ref_to_count; i++)
1497 	 XwInitProcessList (processList, node -> ref_to[i], nodeLevel);
1498    }
1499 }
1500 
1501 
1502 
1503 /************************************************************************
1504  *
1505  *  XwConstrainList
1506  *	Process each array such that each row of the arrays contain
1507  *	their required sizes and locations to match the constraints
1508  *
1509  ************************************************************************/
1510 
XwConstrainList(processList,leaves,depth,formSize,varySize,orient)1511 static void XwConstrainList (processList, leaves, depth,
1512 			     formSize, varySize, orient)
1513 XwFormProcess ** processList;
1514 int              leaves;
1515 int              depth;
1516 int            * formSize;
1517 Boolean          varySize;
1518 int              orient;
1519 
1520 {
1521    register int i, j;
1522    register XwFormRef  * ref;
1523    XwFormConstraintRec * constraint;
1524    XwFormConstraintRec * parentConstraint;
1525    int heldSize;
1526    int sizeDif;
1527    int vary, resize;
1528    int varyCount, varyAmount;
1529    int resizeCount, resizeAmount;
1530    int constantSubtract;
1531    int addAmount, subtractAmount;
1532    int size, separation;
1533 
1534 
1535 
1536    heldSize = 0;
1537 
1538 
1539    for (i = 0; i < leaves; i++)		/* Process all array lines  */
1540    {
1541       processList[i][0].size = 0;
1542       processList[i][0].loc = 0;
1543 
1544 
1545       for (j = 1; j < depth; j++)	/* Process array line */
1546       {
1547          ref = processList[i][j].ref;
1548 
1549 	 if (ref != NULL)
1550 	 {
1551             processList[i][j].size = ref -> set_size;
1552 
1553             if (ref -> ref == ref -> this -> core.parent)
1554             {
1555 	       if (ref -> offset != 0)
1556                   processList[i][j].loc = ref -> offset;
1557 	       else
1558 		  processList[i][j].loc = ref -> set_loc;
1559             }
1560 	    else
1561 	    {
1562 	       processList[i][j].loc =
1563                   processList[i][j - 1].loc + ref->offset;
1564 	       if (ref -> add)
1565 		  processList[i][j].loc += processList[i][j - 1].size +
1566                   processList[i][j].ref -> this -> core.border_width * 2;
1567 	    }
1568 
1569 	 }
1570          else
1571 	 {
1572 	    processList[i][j].ref = processList[i - 1][j].ref;
1573 	    processList[i][j].loc = processList[i - 1][j].loc;
1574 	    processList[i][j].size = processList[i - 1][j].size;
1575 	    processList[i][j].leaf = processList[i - 1][j].leaf;
1576 	 }
1577 
1578          if (processList[i][j].leaf)
1579          {
1580             if (processList[i][0].size < processList[i][j].size +
1581                 processList[i][j].ref -> this -> core.border_width * 2 +
1582                 processList[i][j].loc + ref -> attach_offset)
1583             {
1584 	       processList[i][0].size = processList[i][j].size +
1585                   processList[i][j].ref -> this -> core.border_width * 2 +
1586                   processList[i][j].loc + ref -> attach_offset;
1587             }
1588 
1589             if (processList[i][j].leaf && processList[i][0].size > heldSize)
1590                heldSize = processList[i][0].size;
1591 
1592   	    break;
1593          }
1594       }
1595    }
1596 
1597 
1598    /*  Each array line has now been processed to optimal size.  Reprocess  */
1599    /*  each line to constrain it to formSize if not varySize or to         */
1600    /*  heldSize if varySize.                                               */
1601 
1602    if (varySize)
1603       *formSize = heldSize;
1604 
1605 
1606 
1607    for (i = 0; i < leaves; i++)
1608    {
1609 
1610       /*  For each array line if the 0th size (calculated form size needed  */
1611       /*  for this array line is less than the form size then increase the  */
1612       /*  seperations between widgets whose constaints allow it.            */
1613       /*  If can't do it by varying separation, but can do it by resizing,  */
1614       /*  then do that. 						    */
1615 
1616       if (processList[i][0].size < *formSize)
1617       {
1618 	 sizeDif = *formSize - processList[i][0].size;
1619 
1620          varyCount = 0;
1621 	 resizeCount = 0;
1622 	 for (j = 1; j < depth; j++)
1623 	 {
1624 	     /*  Can't vary the first spacing  */
1625 	     if (j > 1 && processList[i][j].ref -> vary) varyCount++;
1626 	     if (processList[i][j].ref -> resizable) resizeCount++;
1627 	     if (processList[i][j].leaf) break;
1628 	 }
1629 
1630          addAmount = 0;
1631 	 resizeAmount = 0;
1632          if (varyCount == 0)
1633 	 {
1634 	     varyAmount = 0;
1635 	     if (resizeCount != 0)
1636 	        resizeAmount = sizeDif / resizeCount;
1637 	 }
1638          else varyAmount = sizeDif / varyCount;
1639 
1640          j = 1;
1641 
1642          while (j < depth)
1643          {
1644             if (j > 1 && processList[i][j].ref -> vary)
1645 	       addAmount += varyAmount;
1646             processList[i][j].loc += addAmount;
1647 	    if (processList[i][j].ref -> resizable)
1648 	    {
1649 	       processList[i][j].size += resizeAmount;
1650 	       addAmount += resizeAmount;
1651 	    }
1652 
1653             if (processList[i][j].leaf) break;
1654 
1655             j++;
1656 	 }
1657 
1658          if (j > 1)
1659          {
1660             if (processList[i][j].ref -> vary   &&
1661                 processList[i][j].ref -> attach)
1662                processList[i][j].loc = *formSize - processList[i][j].size -
1663                                        processList[i][j].ref -> attach_offset;
1664             else if (processList[i][j].ref -> vary == False &&
1665                      processList[i][j].ref -> resizable     &&
1666                      processList[i][j].ref -> attach)
1667             {
1668                processList[i][j].size =
1669                   *formSize - processList[i][j].loc -
1670                   processList[i][j].ref -> this -> core.border_width * 2 -
1671                   processList[i][j].ref -> attach_offset;
1672             }
1673          }
1674          else
1675          {
1676             if (processList[i][j].ref -> vary == False &&
1677                 processList[i][j].ref -> resizable     &&
1678                 processList[i][j].ref -> attach)
1679             {
1680                processList[i][j].loc = processList[i][j].ref -> offset;
1681                processList[i][j].size =
1682                   *formSize - processList[i][j].loc -
1683                   processList[i][j].ref -> this -> core.border_width * 2 -
1684                   processList[i][j].ref -> attach_offset;
1685 
1686             }
1687             else if (processList[i][j].ref -> vary &&
1688                      processList[i][j].ref -> attach)
1689             {
1690                processList[i][j].loc =
1691                   *formSize - processList[i][j].size -
1692                   processList[i][j].ref -> this -> core.border_width * 2 -
1693                   processList[i][j].ref -> attach_offset;
1694             }
1695             else if (processList[i][j].ref -> vary &&
1696                      processList[i][j].ref -> attach == False)
1697             {
1698                processList[i][j].loc = processList[i][j].ref -> offset;
1699             }
1700          }
1701       }
1702 
1703 
1704       /*  If the form size has gotton smaller, process the vary constraints */
1705       /*  until the needed size is correct or all seperations are 1 pixel.  */
1706       /*  If separations go to 1, then process the resizable widgets        */
1707       /*  until the needed size is correct or the sizes have gone to 1      */
1708       /*  pixel.  If the size is still not correct punt, cannot find a      */
1709       /*  usable size so clip it.                                           */
1710 
1711       if (processList[i][0].size > *formSize)
1712       {
1713 	 sizeDif = processList[i][0].size - *formSize;
1714 
1715          varyAmount = 0;
1716          varyCount = 0;
1717 
1718          j = 0;
1719          do
1720          {
1721             j++;
1722 
1723             if (j > 1 && processList[i][j].ref -> vary &&
1724                 processList[i][j].ref -> offset)
1725             {
1726                varyAmount += processList[i][j].ref -> offset;
1727    	       varyCount++;
1728             }
1729   	 }
1730          while (processList[i][j].leaf == False);
1731 
1732 
1733 	 resizeAmount = 0;
1734 	 resizeCount = 0;
1735          for (j = 1; j < depth; j++)
1736          {
1737             if (processList[i][j].ref->resizable && processList[i][j].size > 1)
1738 	    {
1739                if (processList[i][j].leaf || processList[i][j+1].ref->add)
1740                {
1741                   resizeCount++;
1742                   resizeAmount += processList[i][j].size - 1;
1743                }
1744             }
1745             if (processList[i][j].leaf) break;
1746 	 }
1747 
1748 
1749          /*  Do we have enough varience to match the constraints?  */
1750 
1751          if (varyAmount + resizeAmount > sizeDif)
1752          {
1753 
1754             /*  first process out the vary amount  */
1755 
1756             if (varyCount)
1757             {
1758    	       do
1759                {
1760                   subtractAmount = 0;
1761 
1762                   for (j = 1; j < depth; j++)
1763                   {
1764                      if (j > 1 && processList[i][j].ref -> vary)
1765 		     {
1766                         vary =
1767                            processList[i][j].loc - processList[i][j - 1].loc;
1768 
1769                         if (processList[i][j].ref -> add)
1770 			   vary = vary - processList[i][j - 1].size - 1 -
1771                                   processList[i][j-1].ref->
1772                                   this->core.border_width * 2;
1773                      }
1774                      else vary = 0;
1775 
1776                      if (vary > 0) subtractAmount++;
1777 
1778                      if (subtractAmount)
1779                      {
1780                         processList[i][j].loc -= subtractAmount;
1781                         sizeDif--;
1782                      }
1783 
1784                      if (processList[i][j].leaf) break;
1785 		  }
1786                }
1787                while (subtractAmount != 0 && sizeDif > 0);
1788 	    }
1789 
1790 
1791             /*  now process resize constraints if further constraint */
1792 	    /*  processing is necessary.                             */
1793 
1794             if (sizeDif)
1795 	    {
1796                if (resizeAmount > sizeDif) resizeAmount = sizeDif;
1797 	       if (resizeCount) constantSubtract = resizeAmount / resizeCount;
1798 
1799    	       while (resizeAmount > 0)
1800                {
1801                   subtractAmount = 0;
1802 
1803                   for (j = 1; j < depth; j++)
1804                   {
1805                      if (processList[i][j].ref -> add)
1806                         processList[i][j].loc -= subtractAmount;
1807 
1808                      if (processList[i][j].ref -> resizable)
1809                      {
1810                         if (processList[i][j].leaf ||
1811                             processList[i][j + 1].ref -> add)
1812                            resize = processList[i][j].size - 1;
1813                         else
1814                            resize = 0;
1815 
1816                         if (resize > 1)
1817                         {
1818                            if (constantSubtract < resize)
1819 			      resize = constantSubtract;
1820                            subtractAmount += resize;
1821                            processList[i][j].size -= resize;
1822 			}
1823 		     }
1824 
1825                      if (processList[i][j].leaf) break;
1826 		  }
1827 
1828                   resizeAmount -= subtractAmount;
1829                   constantSubtract = 1;
1830 	       }
1831 	    }
1832 	 }
1833       }
1834    }
1835 
1836 
1837 
1838    /*  Now each array line is processed such that its line is properly  */
1839    /*  constrained to match the specified form size.  Since a single    */
1840    /*  widget reference structure can be referenced in multiple array   */
1841    /*  lines, the minumum constraint for each widget needs to be found. */
1842    /*  When found, the width and height will be placed into the widgets */
1843    /*  constraint structure.                                            */
1844 
1845    for (i = 1; i < depth; i++)
1846    {
1847       ref = NULL;
1848 
1849       for (j = 0; j < leaves + 1; j++)    /*  loop one to many - for exit  */
1850       {
1851 	 if (j == leaves || ref != processList[j][i].ref)
1852 	 {
1853             if (j == leaves || ref != NULL)
1854 	    {
1855                if (ref != NULL)
1856                {
1857                   constraint =
1858                      (XwFormConstraintRec *) ref -> this -> core.constraints;
1859                   parentConstraint =
1860                      (XwFormConstraintRec *) ref -> ref -> core.constraints;
1861 
1862                   if (orient == XwHORIZONTAL) constraint -> width = size;
1863                   else constraint -> height = size;
1864 
1865   	          if (i > 1)
1866                   {
1867 		     if (orient== XwHORIZONTAL)
1868    		        constraint -> x = parentConstraint -> x + separation;
1869                      else
1870 		        constraint -> y = parentConstraint -> y + separation;
1871 	          }
1872 	          else
1873 	          {
1874 		     if (orient == XwHORIZONTAL) constraint -> x = separation;
1875 		     else constraint -> y = separation;
1876 	          }
1877                }
1878 
1879                if (j == leaves) break;	/* exit out of the inner loop  */
1880 	    }
1881 
1882             ref = processList[j][i].ref;
1883             separation = 10000000;
1884             size = 10000000;
1885 	 }
1886 
1887          if (ref != NULL)
1888          {
1889             if (size > processList[j][i].size) size = processList[j][i].size;
1890 
1891             if (i > 1)
1892             {
1893                if (separation > processList[j][i].loc-processList[j][i-1].loc)
1894                   separation = processList[j][i].loc-processList[j][i-1].loc;
1895             }
1896             else
1897                if (separation > processList[j][i].loc)
1898 	           separation = processList[j][i].loc;
1899          }
1900       }
1901    }
1902 }
1903