source: trunk/third/wcl/Xmp/TableLoc.c @ 8837

Revision 8837, 12.7 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r8836, which included commits to RCS files with non-trunk default branches.
Line 
1/*LINTLIBRARY*/
2/*
3 * SCCS_data:    %Z% %M%        %I% %E% %U%
4 */
5#include <X11/Xmp/COPY.h>
6#include <X11/IntrinsicP.h>
7
8#ifdef sun
9#include <X11/ObjectP.h>        /* why don't they just use X from mit!?! */
10#include <X11/RectObjP.h>
11#endif
12
13#include <X11/Xmp/TableP.h>
14
15/* TableLoc methods
16**==================**
17   An Table widget keeps its default_layout and real_layout as two TableLoc's,
18   which are pointers to the first element of a null terminated array of
19   TableLocRecs.
20
21   Each TableLocRec defines a Table widget child's location information (the
22   row, col, spans, and layout options like justification and sizing controls).
23   The default_layout describes where widgets may be placed if and when they
24   become managed.  The real_layout describes where managed children are
25   actually placed.
26
27   The default_layout differs slightly from the real_layout:  Initially, it
28   knows only the names of widgets (their quarks) as specified by the layout
29   resource.  As time goes on and widgets become managed or are placed, then
30   the default_layout may also learn the actual identities of widgets.  Note
31   that it is possible and sometimes very useful to have multiple children with
32   the same name, but different positions and/or options and/or sizes.  If a
33   table has multiple children of the same name, then there may be multiple
34   default_layout and real_layout locs with the same quark but different
35   widgets.
36
37   The default_layout is created from a string by the TableLocParse function
38   which is usually called via the converter.  It is changed due to positioning
39   and XtSetValues calls.  The real_layout is calculated by the table's layout
40   method, triggered by its ChangeManaged method and by the Positioning or
41   SetValues methods.
42*/
43
44/* Allocate, Grow, and Free Arrays of TableLocRec's
45**==================================================**
46*/
47XmpTableLoc XmpTableLocNew( n )
48    int n;
49{
50    return (XmpTableLoc)XtCalloc( n+1, sizeof(XmpTableLocRec) );
51}
52
53XmpTableLoc XmpTableLocGrow( loc )
54    XmpTableLoc loc;
55{
56    static XmpTableLocRec nullLoc;      /* all zeros, as if XtCalloc'd */
57
58    int len = XmpTableLocLen( loc );
59
60    /* XtRealloc leaves additional loc + terminating loc as garbage...
61    */
62    XmpTableLoc new = (XmpTableLoc)XtRealloc( (char*)loc,
63                                                (len+2)*sizeof(XmpTableLocRec) );
64
65    /* ... so initialize the additional and terminating loc to NULLs
66    */
67    new[len] = nullLoc;
68    new[len+1] = nullLoc;
69
70    /* Now new[TableLocLen(new)] is the additional location
71    */
72    return new;
73}
74
75XmpTableLoc XmpTableLocCopy( loc )
76    XmpTableLoc loc;
77{
78    int len = XmpTableLocLen( loc );
79    XmpTableLoc copy = XmpTableLocNew( len );
80    while (len--)
81        copy[len] = loc[len];
82    return copy;
83}
84
85void XmpTableLocFree( loc )
86    XmpTableLoc loc;
87{
88    XtFree( (char*)loc );
89}
90
91
92/* Parse Layout String
93**=====================**
94Parse a layout string, allocating and setting the values.  Return
95pointer to first element, or NULL if parse fails for any reason.
96The result is suitable for use in a call to XtSetValues().
97
98A layout is a list of location specifications separated by semi-colons.
99Each location specification has the form:
100
101        widget_name  column  row  col_span  row_span  opt_list
102
103where the meaning of each field is:
104
105        widget_name     Name of the widget as given to XtCreateWidget().
106        column          Integer >= 0 descibing column in array
107        row             Row >= 0 describing row in array
108        col_span        Integer >= 1 describing horizontal widget span
109        row_span        Integer >= 1 describing vertical widget span
110        opt_list        Series of characters each representing an option:
111                                l:  TBL_LEFT
112                                r:  TBL_RIGHT
113                                t:  TBL_TOP
114                                b:  TBL_BOTTOM
115                                w:  TBL_LK_WIDTH
116                                h:  TBL_LK_HEIGHT
117                                W:  TBL_SM_WIDTH
118                                H:  TBL_SM_HEIGHT
119
120The options are interpreted in the TableChildPosition() method.
121*/
122
123XmpTableLoc XmpTableLocParse( layout )
124    char* layout;
125{
126#ifndef CHILD_NAME_LEN
127#define CHILD_NAME_LEN 127
128#endif
129    char        buf[CHILD_NAME_LEN+1];
130    int         numLocs;
131    XmpTableLoc locs;           /* array XtCalloc'd and returned        */
132    XmpTableLoc loc;            /* current location being parsed        */
133    int         thisLoc;        /* index of current loc                 */
134    int         i;
135    char*       cp;
136
137    if ( layout == (char*)0 || *layout == '\0' )
138        return (XmpTableLoc)0;
139
140    /* Figure out how many location specification there are in the layout.
141    ** Each location specifier may be semi-colon SEPARATED, so we may
142    ** have one more than the number of semi-colons.  Space for null
143    ** termination is provided by TableLocNew().
144    */
145    for ( numLocs = 1, cp = layout ; *cp ; cp++ )
146        if (*cp == ';') numLocs++;
147
148    /* TableLocNew() provides additional NULL location so we do not
149    ** need logic to null terminate array.
150    */
151    locs = XmpTableLocNew( numLocs );
152
153    loc = locs;
154    thisLoc = 0;
155    cp = layout;
156
157#define EAT_WHITESPACE(cp) while (*cp && *cp <= ' ') cp++;
158
159    EAT_WHITESPACE(cp)
160
161    while ( *cp && ++thisLoc <= numLocs )
162    {
163        /* Parse a location specification from the layout string
164        */
165
166        for (i = 0 ; ' ' < *cp && i < CHILD_NAME_LEN ; i++, cp++ )
167            buf[i] = *cp;
168        buf[i] = '\0';
169
170        if ( i )
171            loc->w_quark = XrmStringToQuark(buf);       /* widget name */
172
173        EAT_WHITESPACE(cp)
174
175        while ('0' <= *cp && *cp <= '9')
176            loc->col = loc->col * 10 + *cp++ - '0';
177
178        EAT_WHITESPACE(cp)
179
180        while ('0' <= *cp && *cp <= '9')
181            loc->row = loc->row * 10 + *cp++ - '0';
182
183        EAT_WHITESPACE(cp)
184
185        while ('0' <= *cp && *cp <= '9')
186            loc->col_span = loc->col_span * 10 + *cp++ - '0';
187        if (loc->col_span == 0)
188            loc->col_span = 1;          /* default span */
189
190        EAT_WHITESPACE(cp)
191
192        while ('0' <= *cp && *cp <= '9')
193            loc->row_span = loc->row_span * 10 + *cp++ - '0';
194        if (loc->row_span == 0)
195            loc->row_span = 1;          /* default span */
196
197        EAT_WHITESPACE(cp)
198
199        i = 0;
200        while ( *cp && i < CHILD_NAME_LEN &&
201                *cp == 'l' || *cp == 'r' || *cp == 't' || *cp == 'b' ||
202                *cp == 'w' || *cp == 'h' || *cp == 'W' || *cp == 'H' )
203            buf[i++] = *cp++;
204        buf[i] = '\0';
205        if ( i )
206            loc->options = XmpTableOptsParse(buf);
207
208        while (*cp && *cp <= ' ' || *cp == ';' ) cp++;
209
210        loc++;
211    }
212
213    if (*cp )
214    {
215        /* Something went wrong.
216        */
217        XmpTableLocFree( locs );
218        locs = (XmpTableLoc)0;
219    }
220    return locs;
221}
222
223
224int XmpTableLocLen(loc)
225    XmpTableLoc loc;
226{
227    int i = 0;
228
229    for ( i = 0 ;  loc && loc->w_quark != NULLQUARK  ; loc++ )
230        i++;
231    return i;
232}
233
234/* Find things in TableLocs
235**==========================**
236   Linear search of TableLoc array looking for various parameters
237*/
238
239XmpTableLoc XmpTableLocFind( loc, w )
240    XmpTableLoc loc;            /* Table Locations to examine   */
241    Widget      w;              /* Widget to find               */
242{
243    if ( loc && w )
244    {
245        for ( ;  loc->w_quark != NULLQUARK  ; loc++ )
246        {
247            if ( loc->w_quark == w->core.xrm_name &&
248                 loc->w == w )
249                return loc;
250        }
251    }
252    return (XmpTableLoc)0;
253}
254
255XmpTableLoc XmpTableLocFindDefault( loc, w )
256    XmpTableLoc loc;            /* Table Locations to examine   */
257    Widget      w;              /* Widget to find               */
258{
259    if ( loc && w )
260    {
261        for ( ;  loc->w_quark != NULLQUARK  ; loc++ )
262        {
263            if ( loc->w_quark == w->core.xrm_name && loc->w == (Widget)0 )
264                return loc;
265        }
266    }
267    return (XmpTableLoc)0;
268}
269
270XmpTableLoc XmpTableLocFindAtPosition( loc, col, row )
271    XmpTableLoc loc;            /* Table Locations to examine   */
272    int         col, row;       /* position of widget to find   */
273{
274    if ( loc && (0 <= col) && (0 <= row) )
275    {
276        for ( ;  loc->w_quark != NULLQUARK  ; loc++ )
277        {
278            if ( loc->col == col && loc->row == row )
279                return loc;
280        }
281    }
282    return (XmpTableLoc)0;
283}
284
285
286/* Preferred size determination:
287**==============================**
288   This almost follows the Xt specification.  There are two distinctions:
289
290   First, if widgets are in any SameSize resource list, then that SameSize
291   is the preferred size.  This even overrides resize requests!
292
293   Second, Xt says:
294        "The changed_managed procedure may assume that the
295        child's current geometry is its preferred geometry."
296
297   This is usually wrong for Table:  take the case where we have 5
298   widgets, all of size 1.  Then 3 are unmanaged, and the layout causes
299   the two remaining to become size 2.5.  Then the same 3 are re-managed.
300   They will want to be 1 again, the existing ones still 2.5.  This causes
301   a total size of 8.  Table then squishes each down to make them fit,
302   resulting in the sizes of the re-managed widgets becoming much smaller
303   than the ones which were before.  Repeat several more times, and the
304   transient widgets become very small (size 1).
305*/
306
307int XmpTableLocPreferredWidth( loc, tw )
308    XmpTableLoc    loc;         /* preferred size of widget in this loc */
309    XmpTableWidget tw;          /* The widget containing this loc       */
310{
311    /* First take care of situations where SameSize resources apply
312    */
313    if ( loc->same_width && loc->same_border )
314    {
315        return loc->same_width + 2 * loc->same_border;
316    }
317    else if ( loc->same_width && tw->table.resize_child == loc->w )
318    {
319        return loc->same_width + 2 * tw->table.resize_border_width;
320    }
321    else if ( loc->same_width )
322    {
323        return loc->same_width + 2 * loc->w->core.border_width;
324    }
325    else if ( loc->same_border && tw->table.resize_child == loc->w )
326    {
327        return tw->table.resize_width + 2 * loc->same_border;
328    }
329    else if ( tw->table.resize_child == loc->w )
330    {
331        /* Xt says: "The change request passed to the geometry manager takes
332         * precedence over the preferred geometry [from XtQueryGeometry]"
333         */
334        return tw->table.resize_width + 2 * tw->table.resize_border_width;
335    }
336    else if ( loc->options & TBL_SM_WIDTH )
337    {
338        /* Do not change the size of this child from the size it
339         * was when it first became managed.
340         */
341        return loc->orig_width + 2 * loc->orig_border_width;
342    }
343    else if ( XtClass(loc->w)->core_class.query_geometry == NULL )
344    {
345        /* If the widget cannot figure its size out except at creation time
346         * (they can all at least do that), then we will use that originally
347         * determined size.  XtQueryGeometry returns the current size, which
348         * looks like the widget wants to stay at a changed size, which it
349         * usually does not: a label which has been shrunk seems to like
350         * clipping its image (wrong!), a separator which has been stretched
351         * seems to want to keep the interface wide (wrong!).
352         */
353        return loc->orig_width + 2 * loc->orig_border_width;
354    }
355    else
356    {
357        XtWidgetGeometry        child;
358        int                     width   = loc->w->core.width;
359        int                     border  = loc->w->core.border_width;
360
361        (void)XtQueryGeometry(loc->w, (XtWidgetGeometry*)0, &child);
362
363        if (child.request_mode & CWWidth)       width  = child.width;
364        if (child.request_mode & CWBorderWidth) border = child.border_width;
365
366        return width + 2*border;
367    }
368}
369
370int XmpTableLocPreferredHeight( loc, tw )
371    XmpTableLoc    loc;         /* preferred size of widget in this loc */
372    XmpTableWidget tw;          /* The widget containing this loc       */
373{
374    if ( loc->same_height && loc->same_border )
375    {
376        return loc->same_height + 2 * loc->same_border;
377    }
378    else if ( loc->same_height && tw->table.resize_child == loc->w )
379    {
380        return loc->same_height + 2 * tw->table.resize_border_width;
381    }
382    else if ( loc->same_height )
383    {
384        return loc->same_height + 2 * loc->w->core.border_width;
385    }
386    else if ( loc->same_border && tw->table.resize_child == loc->w )
387    {
388        return tw->table.resize_width + 2 * loc->same_border;
389    }
390    else if ( tw->table.resize_child == loc->w )
391    {
392        return tw->table.resize_height + 2 * tw->table.resize_border_width;
393    }
394    else if ( loc->options & TBL_SM_HEIGHT )
395    {
396        return loc->orig_height + 2 * loc->orig_border_width;
397    }
398    else if ( XtClass(loc->w)->core_class.query_geometry == NULL )
399    {
400        return loc->orig_height + 2 * loc->orig_border_width;
401    }
402    else
403    {
404        XtWidgetGeometry        child;
405        int                     height  = loc->w->core.height;
406        int                     border  = loc->w->core.border_width;
407
408        (void)XtQueryGeometry(loc->w, (XtWidgetGeometry*)0, &child);
409
410        if (child.request_mode & CWHeight)      height = child.height;
411        if (child.request_mode & CWBorderWidth) border = child.border_width;
412
413        return height + 2*border;
414    }
415}
416
417int XmpTableLocNumCols( loc )
418    XmpTableLoc loc;
419{
420    int cols;
421    for ( cols = 0  ;  loc && loc->w_quark != NULLQUARK  ; loc++ )
422        if ( cols < (loc->col + loc->col_span) )
423            cols = loc->col + loc->col_span;
424    return cols;
425}
426
427int XmpTableLocNumRows( loc )
428    XmpTableLoc loc;
429{
430    int rows;
431    for ( rows = 0  ;  loc && loc->w_quark != NULLQUARK  ;  loc++)
432        if ( rows < (loc->row + loc->row_span) )
433            rows = loc->row + loc->row_span;
434    return rows;
435}
436
437/* Used by qsort when the real_layout table is sorted by
438** span before doing distribution of space to rows or columns.
439*/
440int XmpTableLocCompareColSpan( loc1, loc2 )
441    XmpTableLoc loc1, loc2;
442{
443    if ( loc1->col_span == loc2->col_span )
444        return loc1->col - loc2->col;
445
446    return loc1->col_span - loc2->col_span;
447}
448
449int XmpTableLocCompareRowSpan( loc1, loc2 )
450    XmpTableLoc loc1, loc2;
451{
452    if ( loc1->row_span == loc2->row_span )
453        return loc1->row - loc2->row;
454
455    return loc1->row_span - loc2->row_span;
456}
Note: See TracBrowser for help on using the repository browser.