~ubuntu-branches/ubuntu/karmic/scilab/karmic

« back to all changes in this revision

Viewing changes to routines/X11/Xaw/Paned.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2002-03-21 16:57:43 UTC
  • Revision ID: james.westby@ubuntu.com-20020321165743-e9mv12c1tb1plztg
Tags: upstream-2.6
ImportĀ upstreamĀ versionĀ 2.6

Show diffs side-by-side

added added

removed removed

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