1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * HISTORY
25  */
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 
31 #include <stdlib.h>
32 #include <Xm/AccTextT.h>
33 #include <Xm/ActivatableT.h>
34 #include <Xm/ArrowBG.h>
35 #include <Xm/CareVisualT.h>
36 #include <Xm/JoinSideT.h>
37 #include <Xm/NavigatorT.h>
38 #include <Xm/NotebookP.h>
39 #include <Xm/PushBGP.h>
40 #include <Xm/ScrollFrameT.h>
41 #include <Xm/SpinB.h>
42 #include <Xm/TextF.h>
43 #include <Xm/TraitP.h>
44 #include <Xm/TransltnsP.h>
45 #include <Xm/TravConT.h>
46 #include <Xm/UnhighlightT.h>
47 #include <Xm/VendorSEP.h>
48 #include <Xm/VaSimpleP.h>
49 #include "CareVisualTI.h"
50 #include "ColorI.h"
51 #include "GeoUtilsI.h"
52 #include "GMUtilsI.h"
53 #include "MessagesI.h"
54 #include "RegionI.h"
55 #include "RepTypeI.h"
56 #include "ScrollFramTI.h"
57 #include "XmI.h"
58 
59 #define MESSAGE0     _XmMMsgNotebook_0000
60 #define MESSAGE1     _XmMMsgMotif_0001
61 
62 
63 /* Under SunOS /usr/include/sys/sysmacros.h (included by types.h) */
64 /*	thoughtfully grabs part of our name space. */
65 #ifdef major
66 #undef major
67 #endif
68 
69 #ifdef minor
70 #undef minor
71 #endif
72 
73 
74 /*****************************************************************************
75  *                                                                           *
76  *                        constants & useful macros                          *
77  *                                                                           *
78  *****************************************************************************/
79 
80 
81 /* names of notebook internal children */
82 #define MAJOR_TAB_NEXT_NAME     "MajorTabScrollerNext"
83 #define MAJOR_TAB_PREV_NAME     "MajorTabScrollerPrevious"
84 #define MINOR_TAB_NEXT_NAME     "MinorTabScrollerNext"
85 #define MINOR_TAB_PREV_NAME     "MinorTabScrollerPrevious"
86 #define PAGE_SCROLLER_NAME      "PageScroller"
87 #define NB_TEXT_FIELD_NAME 	"NBTextField"
88 
89 /* status values for notebook.scroller_status */
90 #define DEFAULT_NONE    	0	/* default is not created yet */
91 #define DEFAULT_CREATE  	1	/* default being created */
92 #define DEFAULT_USED    	2	/* default is being used */
93 #define DEFAULT_GONE    	3	/* default is destroyed */
94 
95 /* Notebook position value */
96 #define LEFT                    0
97 #define RIGHT                   1
98 #define TOP                     2
99 #define BOTTOM                  4
100 
101 /* tab traversal value */
102 #define _HOME                   0
103 #define _END                    1
104 #define _NEXT                   2
105 #define _PREVIOUS               3
106 #define	_FIRST_VISIBLE		4	/* For KNextTab/KPrevTab, scrolling */
107 #define	_LAST_VISIBLE		5	/* For tab scrolling */
108 #define	_CURRENT_VISIBLE	6	/* For tab group traversal */
109 
110 /* status values for drawing minor tabs */
111 #define TAB_DRAW        0               /* tab is to be drawn */
112 #define TAB_DRAWING     1               /* tab is being drawn */
113 #define TAB_DRAWN       2               /* tab has been drawn */
114 
115 
116 /* XmNotebook default values */
117 #define FIRST_PAGE_NUMBER_DEFAULT	1
118 #define BACK_PAGE_NUMBER_DEFAULT	2
119 #define BACK_PAGE_SIZE_DEFAULT		8
120 #define BINDING_WIDTH_DEFAULT		25
121 #define MARGIN_WIDTH_DEFAULT		0
122 #define MARGIN_HEIGHT_DEFAULT		0
123 #define MAJOR_TAB_SPACING_DEFAULT	3
124 #define MINOR_TAB_SPACING_DEFAULT	3
125 #define TAB_SCROLLER_WIDTH_DEFAULT	20
126 #define TAB_SCROLLER_HEIGHT_DEFAULT	20
127 #define NOTEBOOK_MINIMUM_WIDTH		16
128 #define NOTEBOOK_MINIMUM_HEIGHT		16
129 #define MIN_DRAWABLE_SPIRAL_SIZE	6
130 
131 /* macros */
132 
133 #define NB_IS_CHILD_NONE(x) \
134         ((unsigned char)x == XmNONE)
135 #define NB_IS_CHILD_PAGE(x) \
136         ((unsigned char)x == XmPAGE)
137 #define NB_IS_CHILD_MAJOR(x) \
138         ((unsigned char)x == XmMAJOR_TAB)
139 #define NB_IS_CHILD_MINOR(x) \
140         ((unsigned char)x == XmMINOR_TAB)
141 #define NB_IS_CHILD_TAB(x) \
142         (((unsigned char)x == XmMAJOR_TAB) \
143         || ((unsigned char)x == XmMINOR_TAB))
144 #define NB_IS_CHILD_STATUS(x) \
145         ((unsigned char)x == XmSTATUS_AREA)
146 #define NB_IS_CHILD_PAGE_SCROLLER(x) \
147         ((unsigned char)x == XmPAGE_SCROLLER)
148 #define NB_IS_CHILD_MAJOR_SCROLLER(x) \
149         (((unsigned char)x == XmMAJOR_TAB_SCROLLER) \
150         || ((unsigned char)x == XmTAB_SCROLLER))
151 #define NB_IS_CHILD_MINOR_SCROLLER(x) \
152         (((unsigned char)x == XmMINOR_TAB_SCROLLER) \
153         || ((unsigned char)x == XmTAB_SCROLLER))
154 
155 
156 /* Layout defines */
157 #define NB_IS_VISIBLE(w) \
158       ((XtIsManaged(w) && \
159       ((w)->core.x > -(int)((w)->core.width + (w)->core.border_width * 2)) && \
160       ((w)->core.y > -(int)((w)->core.height + (w)->core.border_width * 2))))
161 
162 #define	NB_IS_HIDDEN(w) \
163     (((w)->core.x <= -(int)((w)->core.width + (w)->core.border_width * 2)) && \
164      ((w)->core.y <= -(int)((w)->core.height + (w)->core.border_width * 2)))
165 
166 #define NB_ENFORCE_SIGN(s,x) ((s) > 0 ? (x) : -(x))
167 
168 				/* Fixed placement of non-top minor tabs */
169 #define NB_MINOR_TAB_STEP(x) ((x) /2)
170 
171 				/* Max dimension of major tab area, i.e.,
172 				   max of tab and tab scroller dimension */
173 #define NB_MAJOR_MAX(n,x,y) (MAX((x), (y)))
174  /* MAX(0, (n)->notebook.shadow_thickness - (n)->notebook.back_page_size)) */
175 
176 				/* Max dimension of minor tab area, i.e.,
177 				   max of tab (minus fixed placement) and
178 				   tab scroller dimension */
179 #define NB_MINOR_MAX(n,x,y) \
180  (MAX((int)((x) - NB_MINOR_TAB_STEP((n)->notebook.back_page_size)),(int)(y)))
181  /* MAX(0, (n)->notebook.shadow_thickness - (n)->notebook.back_page_size)) */
182 
183 
184 /* Retrieve trait defines */
185 #define NB_SCROLL_FRAME(x) \
186     ((XmScrollFrameTrait)XmeTraitGet((XtPointer)XtClass((Widget)(x)), \
187     XmQTscrollFrame))
188 
189 #define NB_ACTIVATABLE(x) \
190     ((XmActivatableTrait)XmeTraitGet((XtPointer)XtClass((Widget)(x)), \
191     XmQTactivatable))
192 
193 #define NB_NAVIGATOR(x) \
194     ((XmNavigatorTrait)XmeTraitGet((XtPointer)XtClass((Widget)(x)), \
195     XmQTnavigator))
196 
197 #define NB_JOINSIDE(x) \
198     ((XmJoinSideTrait)XmeTraitGet((XtPointer)XtClass((Widget)(x)), \
199     XmQTjoinSide))
200 
201 
202 /* Is trait defines */
203 #define NB_IS_CHILD_ACTIVATABLE(x) \
204     (((XmeTraitGet((XtPointer)XtClass(x),XmQTactivatable)) != NULL) \
205     ? True : False)
206 
207 #define NB_IS_CHILD_NAVIGATOR(x) \
208     (((XmeTraitGet((XtPointer)XtClass(x),XmQTnavigator)) != NULL) \
209     ? True : False)
210 
211 #define NB_IS_CHILD_JOINSIDE(x) \
212     (((XmeTraitGet((XtPointer)XtClass(x),XmQTjoinSide)) != NULL) \
213     ? True : False)
214 
215 #define NB_IS_CHILD_ACCESSTEXTUAL(x) \
216     (((XmeTraitGet((XtPointer)XtClass(x),XmQTaccessTextual)) != NULL) \
217     ? True : False)
218 
219 
220 #define NotebookConstraint(w) \
221         (&((XmNotebookConstraintPtr) (w)->core.constraints)->notebook)
222 
223 
224 /* If the original dimension is negative, then offset the original
225    position by that negative amount and make it the new position. Also
226    make the new dimension be the positive original dimension. So for
227    instance, if the x value is 20 and the width is -10, then make the x
228    value be 10 and the width be positive 10. If the original dimension
229    is not negative, then just set the new values to be the same as the
230    old values. */
231 
232 #define ADJUST_NEGATIVE_DIMENSION(orig_pos, orig_dim, new_pos, new_dim) \
233         if (orig_dim < 0) \
234         { \
235 	    new_pos = orig_pos + orig_dim; \
236 	    new_dim = (Dimension) (orig_dim * -1) ; \
237 	} \
238         else \
239         { \
240 	    new_pos = orig_pos; \
241 	    new_dim = (Dimension) orig_dim; \
242 	}
243 
244 
245 #define manager_translations _XmNotebook_manager_translations
246 
247 
248 /*****************************************************************************
249  *                                                                           *
250  *                               global variables                            *
251  *                                                                           *
252  *****************************************************************************/
253 
254 
255 static XtAccelerators TabAcceleratorsParsed;
256 
257 
258 /*****************************************************************************
259  *                                                                           *
260  *                           Static function declarations                    *
261  *                                                                           *
262  *****************************************************************************/
263 
264 
265 
266 /* synthetic hook */
267 static void GetDefaultFrameBackground(
268                         Widget g,
269                         int offset,
270                         XrmValue *value) ;
271 static void GetDefaultBackPageBackground(
272                         Widget g,
273                         int offset,
274                         XrmValue *value) ;
275 static void GetDefaultBackPagePos(
276 			Widget w,
277 			int offset,
278 			XrmValue *value) ;
279 static void FromOrientationPixels(
280 			Widget w,
281                         int offset,
282 			XtArgVal *value) ;
283 static XmImportOperator ToOrientationPixels(
284 			Widget w,
285 			int offset,
286 			XtArgVal *value) ;
287 static void FromOrientationOppositePixels(
288 			Widget w,
289 			int offset,
290 			XtArgVal *value) ;
291 static XmImportOperator ToOrientationOppositePixels(
292 			Widget w,
293 			int offset,
294 			XtArgVal *value) ;
295 /* core class method */
296 static void ClassInitialize (
297 			void) ;
298 static void ClassPartInitialize(
299 			WidgetClass wc) ;
300 static void Initialize(
301 			Widget rw,
302 			Widget nw,
303 			ArgList args,
304 			Cardinal *num) ;
305 static void Destroy(
306 			Widget w) ;
307 static void Resize(
308 			Widget w) ;
309 static void Redisplay(
310 			Widget w,
311 			XEvent *e,
312 			Region region) ;
313 static Boolean SetValues(
314 			Widget ow,
315 			Widget rw,
316 			Widget nw,
317 			ArgList args,
318 			Cardinal *num) ;
319 static XtGeometryResult QueryGeometry(
320 			Widget w,
321 			XtWidgetGeometry *intended,
322 			XtWidgetGeometry *desired) ;
323 static XtGeometryResult GeometryManager(
324 			Widget instigator,
325 			XtWidgetGeometry *desired,
326 			XtWidgetGeometry *reply) ;
327 static void ChangeManaged(
328 			Widget w) ;
329 static void InsertChild(
330 			Widget child) ;
331 static void DeleteChild(
332 			Widget child) ;
333 static void ConstraintInitialize(
334 			Widget req,
335 			Widget new_w,
336 			ArgList args,
337 			Cardinal *num) ;
338 static void CreateTabScrollers(
339 			XmNotebookWidget nb) ;
340 static void SetVisualConfig(
341 			XmNotebookWidget nb) ;
342 static Boolean UpdateJoinSide(
343 			XmNotebookWidget nb,
344 			Widget child,
345 			unsigned char child_type,
346 			Dimension shadow_thickness) ;
347 static void UpdateJoinSideChildren(
348 			XmNotebookWidget nb,
349 			Dimension shadow_thickness) ;
350 static void SetPageScroller(
351 			XmNotebookWidget nb) ;
352 static void LayoutChildren(
353 			XmNotebookWidget nb,
354 			Widget instigator) ;
355 static void LayoutPages(
356 			XmNotebookWidget nb,
357 			Widget instigator) ;
358 static void LayoutMajorTabs(
359 			XmNotebookWidget nb,
360 			Widget instigator) ;
361 static void LayoutMinorTabs(
362 			XmNotebookWidget nb,
363 			Widget instigator) ;
364 static void ResetTopPointers(
365 			XmNotebookWidget nb,
366 			unsigned char reason,
367 			int scroll) ;
368 static void GetFrameGCs(
369 			XmNotebookWidget nb) ;
370 static void GetBackpageGCs(
371 			XmNotebookWidget nb) ;
372 static void DrawBinding(
373 			XmNotebookWidget nb,
374 			XExposeEvent *event,
375 			Region region) ;
376 static void MakeSpiralPixmap(
377 			XmNotebookWidget nb,
378 			Dimension width,
379 			Dimension height) ;
380 static void DrawPixmapBinding(
381 			XmNotebookWidget nb,
382 			Dimension x,
383 			Dimension y,
384 			Dimension width,
385 			Dimension height,
386                         Pixmap pixmap) ;
387 static void DrawFrameShadow(
388 			XmNotebookWidget nb,
389 			XExposeEvent *event,
390 			Region region) ;
391 static void DrawBackPages(
392 			XmNotebookWidget nb,
393 			XExposeEvent *event,
394 			Region region) ;
395 static Boolean NewPreferredGeometry(
396 			XmNotebookWidget nb,
397 			Widget instigator,
398 			XtWidgetGeometry *desired,
399 			XtWidgetGeometry *preferred) ;
400 static void AdjustGeometry(
401 			XmNotebookWidget nb,
402 			Widget instigator,
403                 	XtWidgetGeometry *desired) ;
404 static Boolean SetLastPageNumber (
405 			XmNotebookWidget nb,
406     			int last_page_number) ;
407 static Boolean AssignDefaultPageNumber(
408 			XmNotebookWidget nb) ;
409 static Boolean ConstraintSetValues(
410 			Widget old_w,
411 			Widget req,
412 			Widget new_w,
413 			ArgList args,
414 			Cardinal *num) ;
415 static void SetActiveChildren(
416 			XmNotebookWidget nb) ;
417 static void RepositionChild(
418 			XmNotebookWidget nb,
419 			Widget child) ;
420 static void SortChildren(
421 			XmNotebookWidget nb) ;
422 static int GetNextAvailPageNum(
423 			XmNotebookWidget nb,
424 			int last) ;
425 static Widget GetChildWidget(
426 			XmNotebookWidget nb,
427 			int page_number,
428 			unsigned char child_type) ;
429 static void GotoPage(
430 			XmNotebookWidget nb,
431 			int page_number,
432 			XEvent *event,
433 			int reason) ;
434 static void ShowChild(
435 			Widget child,
436 			Widget instigator,
437 			int x,
438 			int y,
439 			int width,
440 			int height) ;
441 static void HideChild(
442 			Widget child,
443 			Widget instigator) ;
444 static void HideShadowedTab(
445 			XmNotebookWidget nb,
446 			Widget child) ;
447 static void FlipTabs(
448 			Widget w,
449 			XtPointer data,
450 			XtPointer call_data) ;
451 static void TabPressed(
452 			Widget w,
453 			XtPointer data,
454 			XtPointer call_data) ;
455 static void TraverseTab(
456 			Widget w,
457 			XEvent *event,
458 			String *params,
459 			Cardinal *num_params) ;
460 static Widget GetNextTab(
461 			XmNotebookWidget nb,
462 			unsigned char child_type,
463 			int page_number,
464 			unsigned char direction) ;
465 static Boolean MaxIsRightUp(
466 			XmNotebookWidget nb,
467 			unsigned char child_type) ;
468 static void ScrollFrameInit(
469 			Widget w,
470 			XtCallbackProc moveCB,
471 			Widget scrollable) ;
472 static Boolean ScrollFrameGetInfo(
473 			Widget w,
474 			Cardinal *dimension,
475 			Widget **nav_list,
476 			Cardinal *num_nav_list) ;
477 static void AddNavigator(
478 			Widget w,
479 			Widget nav,
480 			Mask dimMask) ;
481 static void RemoveNavigator(
482 			Widget w,
483 			Widget nav) ;
484 static void PageMove(
485 			Widget w,
486 			XtPointer data,
487 			XtPointer call_data) ;
488 static Widget RedirectTraversal(
489 			Widget old_focus,
490 			Widget new_focus,
491 			unsigned int focus_policy,
492 			XmTraversalDirection direction,
493 			unsigned int pass) ;
494 static void UpdateNavigators(
495 			XmNotebookWidget nb) ;
496 static GC GetUnhighlightGC(
497 			Widget w,
498 			Widget child) ;
499 static unsigned char  GetDefaultBackPagePosAgain(
500 			Widget w);
501 
502 
503 /*****************************************************************************
504  *                                                                           *
505  *               		Action Records				     *
506  *                                                                           *
507  *****************************************************************************/
508 
509 
510 static XtActionsRec tab_actions_list[] =
511 {
512     {"TraverseTab",		TraverseTab},
513 };
514 
515 
516 /*****************************************************************************
517  *                                                                           *
518  *                		Resources                                    *
519  *                                                                           *
520  *****************************************************************************/
521 
522 
523 static XtResource resources[]  =
524 {
525     {
526 	XmNcurrentPageNumber,
527 	XmCCurrentPageNumber,
528 	XmRInt,
529 	sizeof(int),
530 	XtOffsetOf(XmNotebookRec, notebook.current_page_number),
531 	XmRImmediate,
532 	(XtPointer)XmUNSPECIFIED_PAGE_NUMBER
533     },
534     {
535 	XmNfirstPageNumber,
536 	XmCFirstPageNumber,
537 	XmRInt,
538 	sizeof(int),
539 	XtOffsetOf(XmNotebookRec, notebook.first_page_number),
540 	XmRImmediate,
541 	(XtPointer)FIRST_PAGE_NUMBER_DEFAULT,
542     },
543     {
544 	XmNlastPageNumber,
545 	XmCLastPageNumber,
546 	XmRInt,
547 	sizeof(int),
548 	XtOffsetOf(XmNotebookRec, notebook.last_page_number),
549 	XmRImmediate,
550 	(XtPointer)XmUNSPECIFIED_PAGE_NUMBER
551     },
552     {
553 	XmNorientation,
554 	XmCOrientation,
555         XmROrientation,
556         sizeof(unsigned char),
557         XtOffsetOf(XmNotebookRec, notebook.orientation),
558         XmRImmediate,
559         (XtPointer)XmHORIZONTAL
560     },
561     {
562 	XmNframeBackground,
563 	XmCFrameBackground,
564 	XmRPixel,
565 	sizeof(Pixel),
566 	XtOffsetOf(XmNotebookRec, notebook.frame_background),
567 	XmRCallProc,
568 	(XtPointer) GetDefaultFrameBackground
569     },
570     {
571 	XmNbackPagePlacement,
572         XmCBackPagePlacement,
573         XmRScrollBarPlacement,
574         sizeof(unsigned char),
575         XtOffsetOf(XmNotebookRec, notebook.back_page_pos),
576         XmRCallProc,
577         (XtPointer)GetDefaultBackPagePos
578     },
579     {
580 	XmNbackPageNumber,
581 	XmCBackPageNumber,
582 	XmRCardinal,
583 	sizeof(Cardinal),
584 	XtOffsetOf(XmNotebookRec, notebook.back_page_number),
585 	XmRImmediate,
586 	(XtPointer)BACK_PAGE_NUMBER_DEFAULT
587     },
588     {
589 	XmNbackPageSize,
590 	XmCBackPageSize,
591 	XmRHorizontalDimension,
592 	sizeof(Dimension),
593 	XtOffsetOf(XmNotebookRec, notebook.back_page_size),
594 	XmRImmediate,
595 	(XtPointer)BACK_PAGE_SIZE_DEFAULT
596     },
597     {
598 	XmNbackPageForeground,
599         XmCBackPageForeground,
600         XmRPixel,
601         sizeof(Pixel),
602         XtOffsetOf(XmNotebookRec, notebook.back_page_foreground),
603         XmRCallProc,
604         (XtPointer)_XmForegroundColorDefault
605     },
606     {
607 	XmNbackPageBackground,
608         XmCBackPageBackground,
609         XmRPixel,
610         sizeof(Pixel),
611         XtOffsetOf(XmNotebookRec, notebook.back_page_background),
612         XmRCallProc,
613         (XtPointer)GetDefaultBackPageBackground
614     },
615     {
616 	XmNbindingType,
617         XmCBindingType,
618         XmRBindingType,
619         sizeof(unsigned char),
620         XtOffsetOf(XmNotebookRec, notebook.binding_type),
621         XmRImmediate,
622         (XtPointer)XmSPIRAL
623     },
624     {
625 	XmNbindingPixmap,
626 	XmCBindingPixmap,
627         XmRDynamicPixmap,
628         sizeof(Pixmap),
629         XtOffsetOf(XmNotebookRec, notebook.binding_pixmap),
630         XmRImmediate,
631         (XtPointer)XmUNSPECIFIED_PIXMAP
632     },
633     {
634 	XmNbindingWidth,
635 	XmCBindingWidth,
636 	XmRHorizontalDimension,
637 	sizeof(Dimension),
638 	XtOffsetOf(XmNotebookRec, notebook.binding_width),
639 	XmRImmediate,
640 	(XtPointer)BINDING_WIDTH_DEFAULT
641     },
642     {
643 	XmNinnerMarginWidth,
644 	XmCInnerMarginWidth,
645 	XmRHorizontalDimension,
646 	sizeof(Dimension),
647 	XtOffsetOf(XmNotebookRec, notebook.margin_width),
648 	XmRImmediate,
649 	(XtPointer)MARGIN_WIDTH_DEFAULT
650     },
651     {
652 	XmNinnerMarginHeight,
653 	XmCInnerMarginHeight,
654 	XmRVerticalDimension,
655 	sizeof(Dimension),
656 	XtOffsetOf(XmNotebookRec, notebook.margin_height),
657 	XmRImmediate,
658 	(XtPointer)MARGIN_HEIGHT_DEFAULT
659     },
660     {
661 	XmNmajorTabSpacing,
662 	XmCMajorTabSpacing,
663 	XmRHorizontalDimension,
664 	sizeof(Dimension),
665 	XtOffsetOf(XmNotebookRec, notebook.major_spacing),
666 	XmRImmediate,
667 	(XtPointer)MAJOR_TAB_SPACING_DEFAULT
668     },
669     {
670 	XmNminorTabSpacing,
671 	XmCMinorTabSpacing,
672 	XmRHorizontalDimension,
673 	sizeof(Dimension),
674 	XtOffsetOf(XmNotebookRec, notebook.minor_spacing),
675 	XmRImmediate,
676 	(XtPointer)MINOR_TAB_SPACING_DEFAULT
677     },
678     {
679 	XmNframeShadowThickness,
680 	XmCShadowThickness,
681 	XmRHorizontalDimension,
682 	sizeof(Dimension),
683 	XtOffsetOf(XmNotebookRec, notebook.shadow_thickness),
684 	XmRCallProc,
685 	(XtPointer) _XmSetThickness
686     },
687     {
688 	XmNpageChangedCallback,
689         XmCCallback,
690         XmRCallback,
691         sizeof(XtCallbackList),
692         XtOffsetOf(XmNotebookRec, notebook.page_change_callback),
693         XmRPointer,
694         (XtPointer)NULL
695     }
696 };
697 
698 
699 static XtResource constraint_resources[] =
700 {
701     {
702 	XmNnotebookChildType,
703 	XmCNotebookChildType,
704         XmRNotebookChildType,
705 	sizeof(unsigned char),
706 	XtOffsetOf(XmNotebookConstraintRec, notebook.child_type),
707 	XmRImmediate,
708 	(XtPointer)XmNONE
709     },
710     {
711 	XmNpageNumber,
712 	XmCPageNumber,
713 	XmRInt,
714 	sizeof(int),
715 	XtOffsetOf(XmNotebookConstraintRec, notebook.page_number),
716 	XmRImmediate,
717 	(XtPointer)XmUNSPECIFIED_PAGE_NUMBER
718     },
719     {
720 	XmNresizable,
721 	XmCResizable,
722 	XmRBoolean,
723 	sizeof(Boolean),
724 	XtOffsetOf(XmNotebookConstraintRec, notebook.resizable),
725 	XmRImmediate,
726 	(XtPointer)True
727     }
728 };
729 
730 
731 static XmSyntheticResource syn_resources[] =
732 {
733     {
734         XmNbackPageSize,
735         sizeof(Dimension),
736         XtOffsetOf(XmNotebookRec, notebook.back_page_size),
737 	XmeFromHorizontalPixels,XmeToHorizontalPixels
738     },
739     {
740         XmNbindingWidth,
741         sizeof(Dimension),
742         XtOffsetOf(XmNotebookRec, notebook.binding_width),
743 	FromOrientationPixels,ToOrientationPixels
744     },
745     {
746         XmNinnerMarginWidth,
747         sizeof(Dimension),
748         XtOffsetOf(XmNotebookRec, notebook.margin_width),
749         XmeFromHorizontalPixels,XmeToHorizontalPixels
750     },
751     {
752         XmNinnerMarginHeight,
753         sizeof(Dimension),
754         XtOffsetOf(XmNotebookRec, notebook.margin_height),
755         XmeFromVerticalPixels,XmeToVerticalPixels
756     },
757     {
758         XmNmajorTabSpacing,
759         sizeof(Dimension),
760         XtOffsetOf(XmNotebookRec, notebook.major_spacing),
761 	FromOrientationOppositePixels,ToOrientationOppositePixels
762     },
763     {
764         XmNminorTabSpacing,
765         sizeof(Dimension),
766         XtOffsetOf(XmNotebookRec, notebook.minor_spacing),
767 	FromOrientationPixels,ToOrientationPixels
768     },
769     {
770         XmNframeShadowThickness,
771         sizeof(Dimension),
772         XtOffsetOf(XmNotebookRec, notebook.shadow_thickness),
773         XmeFromHorizontalPixels,XmeToHorizontalPixels
774     }
775 };
776 
777 
778 /*****************************************************************************
779  *                                                                           *
780  *                    Notebook class record definition  		     *
781  *                                                                           *
782  *****************************************************************************/
783 
784 
785 externaldef(xmnotebookclassrec) XmNotebookClassRec xmNotebookClassRec =
786 {
787     /* core class record */
788     {
789 	(WidgetClass)&xmManagerClassRec,    /* superclass */
790         "XmNotebook",              	    /* class_name */
791         sizeof(XmNotebookRec),		    /* widget_size */
792         ClassInitialize,                    /* class_initialize */
793         ClassPartInitialize,                /* class_part_initialize */
794         FALSE,                              /* class_inited */
795         Initialize,                         /* initialize */
796         NULL,                               /* initialize_hook */
797         XtInheritRealize,	    	    /* realize */
798         tab_actions_list,                   /* actions */
799         XtNumber(tab_actions_list),         /* num_actions */
800         resources,                          /* resources */
801         XtNumber(resources),                /* num_resources */
802         NULLQUARK,                          /* xrm_class */
803         TRUE,                               /* compress_motion */
804         XtExposeCompressMaximal, 	    /* compress_exposure */
805         TRUE,                               /* compress enterleave */
806         TRUE,                               /* visible_interest */
807         Destroy,                            /* destroy */
808         Resize,                             /* resize */
809         Redisplay,                          /* expose */
810         SetValues,                          /* set_values */
811         NULL,                               /* set_values_hook */
812         XtInheritSetValuesAlmost,           /* set_value_almost */
813         NULL,                               /* get_values_hook */
814         NULL,                               /* accept focus */
815         XtVersion,                          /* current version */
816         NULL,                               /* callback private */
817         XtInheritTranslations,              /* translation table */
818         QueryGeometry,                      /* query_geometry */
819         NULL,                               /* display_accelerator */
820         NULL				    /* extension */
821     },
822     /* Composite class record */
823     {
824         GeometryManager,		    /* childrens geometry_manager */
825         ChangeManaged,     		    /* change_managed */
826 	InsertChild,		    	    /* insert_child */
827         DeleteChild,			    /* delete_child */
828         NULL                    	    /* extension */
829     },
830     /* Constraint class record */
831     {
832 	constraint_resources,               /* constraint resource */
833 	XtNumber(constraint_resources),     /* number of constraints */
834 	sizeof(XmNotebookConstraintRec),    /* size of constraint */
835 	ConstraintInitialize,         	    /* initialization */
836 	NULL,                  		    /* destroy proc */
837 	ConstraintSetValues,          	    /* set_values proc */
838 	NULL                         	    /* extension */
839     },
840     /* Manager class record */
841     {
842         manager_translations,   	    /* translations */
843         syn_resources,         		    /* syn_resources */
844         XtNumber(syn_resources),	    /* num_syn_resources */
845 	NULL,			     	    /* get_cont_resources   */
846 	0, 				    /* num_get_cont_resources */
847         XmInheritParentProcess,  	    /* parent_process */
848         NULL                    	    /* extension */
849     },
850     /* Notebook class record */
851     {
852 	NULL				    /* unused */
853     }
854 };
855 
856 
857 externaldef(xmnotebookwidgetclass) WidgetClass xmNotebookWidgetClass =
858 	(WidgetClass) &xmNotebookClassRec;
859 
860 
861 /* Trait record for Notebook scrollFrame */
862 static XmConst XmScrollFrameTraitRec notebookSFT =
863 {
864     1,				/* version */
865     ScrollFrameInit,		/* initialize */
866     ScrollFrameGetInfo,		/* get trait info */
867     AddNavigator,		/* add navigator method */
868     RemoveNavigator,		/* remove navigator method */
869     NULL			/* update original geometry */
870 };
871 
872 
873 /* Trait record for Notebook traversalControl */
874 static XmConst XmTraversalControlTraitRec notebookTCT =
875 {
876   0,				/* version */
877   RedirectTraversal		/* redirect */
878 };
879 
880 
881 /* Trait record for Notebook specifyUnhighlight */
882 static XmConst XmSpecifyUnhighlightTraitRec notebookSUT =
883 {
884   0,				/* version */
885   GetUnhighlightGC		/* getUnhighlightGC */
886 };
887 
888 
889 
890 
891 /*****************************************************************************
892  *                                                                           *
893  *			    Core method functions			     *
894  *                                                                           *
895  *****************************************************************************/
896 
897 
898 /*- ClassInitialize ---------------------------------------------------------
899 
900 	This routine is invoked only once.
901 
902 -----------------------------------------------------------------------------*/
903 static void
ClassInitialize(void)904 ClassInitialize(void)
905 {
906     /* Parse the default accelerator table */
907     TabAcceleratorsParsed =
908                 XtParseAcceleratorTable( _XmNotebook_TabAccelerators );
909 }
910 
911 
912 /*- ClassPartInitialize -----------------------------------------------------
913 
914 	Set up the fast subclassing for the widget and install traits
915 
916 -----------------------------------------------------------------------------*/
917 static void
ClassPartInitialize(WidgetClass wc)918 ClassPartInitialize (
919     WidgetClass wc)
920 {
921     _XmFastSubclassInit(wc, XmNOTEBOOK_BIT);
922 
923     XmeTraitSet((XtPointer)wc,XmQTscrollFrame,(XtPointer)&notebookSFT);
924     XmeTraitSet((XtPointer)wc,XmQTtraversalControl,(XtPointer)&notebookTCT);
925     XmeTraitSet((XtPointer)wc,XmQTspecifyUnhighlight,(XtPointer)&notebookSUT);
926 
927 }
928 
929 
930 /*- Initialize --------------------------------------------------------------
931 
932 	Initialize method
933 
934 -----------------------------------------------------------------------------*/
935 
936 /*ARGSUSED*/
937 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num)938 Initialize (
939     Widget rw,			/* unused */
940     Widget nw,
941     ArgList args,		/* unused */
942     Cardinal *num)		/* unused */
943 {
944     XmNotebookWidget new_w = (XmNotebookWidget)nw;
945     XmScrollFrameTrait scroll_frameT;
946 
947     /* XmNaccelerators */
948     new_w->core.accelerators = TabAcceleratorsParsed;
949 
950     /* XmNorientation */
951     if (!XmRepTypeValidValue(XmRID_ORIENTATION,new_w->notebook.orientation,nw))
952 	new_w->notebook.orientation = XmHORIZONTAL;
953 
954     /* XmNbackPagePlacement */
955     if (!XmRepTypeValidValue(XmRID_SCROLL_BAR_PLACEMENT,
956 			new_w->notebook.back_page_pos, nw))
957 	new_w->notebook.back_page_pos = GetDefaultBackPagePosAgain(nw);
958 
959     /* XmNbindingType */
960     if (!XmRepTypeValidValue(XmRID_BINDING_TYPE,
961 			new_w->notebook.binding_type, nw))
962 	new_w->notebook.binding_type = XmSOLID;
963 
964     /* set tab and binding positions */
965     SetVisualConfig(new_w);
966 
967     /* page number resources */
968 
969     /* fix BUX 1183 in notebook widget, the real_back_page_number is used
970      * for division, however it is never set unless the back_page_number
971      * changed (in SetValues).
972      */
973     ASSIGN_MIN(new_w->notebook.real_back_page_number,
974                  (Dimension)(new_w->notebook.back_page_size /2));
975     ASSIGN_MAX(new_w->notebook.real_back_page_number, 1);
976 
977     if (new_w->notebook.current_page_number == XmUNSPECIFIED_PAGE_NUMBER)
978        new_w->notebook.current_page_number = new_w->notebook.first_page_number;
979     if (new_w->notebook.last_page_number == XmUNSPECIFIED_PAGE_NUMBER)
980     {
981        new_w->notebook.last_page_number = new_w->notebook.first_page_number;
982        new_w->notebook.dynamic_last_page_num = True;
983     }
984     else
985 	new_w->notebook.dynamic_last_page_num = False;
986     new_w->notebook.last_alloc_num = new_w->notebook.first_page_number;
987 
988     /* intialize variables for layouting tabs */
989     new_w->notebook.first_major = NULL;
990     new_w->notebook.old_top_major = NULL;
991     new_w->notebook.top_major = NULL;
992     new_w->notebook.last_major = NULL;
993     new_w->notebook.first_minor = NULL;
994     new_w->notebook.old_top_minor = NULL;
995     new_w->notebook.top_minor = NULL;
996     new_w->notebook.last_minor = NULL;
997     new_w->notebook.constraint_child = NULL;
998 
999    /* shadow thickness state for current page major and minor tab */
1000     new_w->notebook.major_shadow_thickness = (Dimension) 0;
1001     new_w->notebook.minor_shadow_thickness = (Dimension) 0;
1002     new_w->notebook.in_setshadow = False;
1003     new_w->notebook.major_shadow_child = NULL;
1004     new_w->notebook.minor_shadow_child = NULL;
1005 
1006     /* other misc. variables */
1007     new_w->notebook.which_tab = XmMAJOR_TAB;
1008     new_w->notebook.scroller_status = DEFAULT_NONE;
1009     new_w->notebook.need_scroller = XmNONE;
1010     new_w->notebook.scroller = NULL;
1011     new_w->notebook.scroller_child = NULL;
1012     new_w->notebook.in_callback = False;
1013     new_w->notebook.frame_gc = NULL;
1014     new_w->notebook.binding_gc = NULL;
1015     new_w->notebook.background_gc = NULL;
1016     new_w->notebook.foreground_gc = NULL;
1017     new_w->notebook.spiral_pixmap = XmUNSPECIFIED_PIXMAP;
1018 
1019 
1020     /* initialize the scroll_frame and change_managed flags */
1021     new_w->notebook.scroll_frame_data = NULL;
1022     new_w->notebook.first_change_managed = True;
1023 
1024     /* initialize the scrollFrame with move callback (subclass trait check) */
1025 
1026     if (((scroll_frameT=NB_SCROLL_FRAME(nw)) != NULL)
1027 	&& (scroll_frameT->init != NULL) )
1028 	scroll_frameT->init(nw, PageMove, nw);
1029 
1030     /* creating GCs */
1031     GetFrameGCs(new_w);
1032     GetBackpageGCs(new_w);
1033 
1034     /* create tab scrollers */
1035     CreateTabScrollers(new_w);
1036     SetPageScroller(new_w);
1037 
1038 }
1039 
1040 
1041 /*- Destroy -----------------------------------------------------------------
1042 
1043 	Destroy the widget and its children
1044 
1045 -----------------------------------------------------------------------------*/
1046 static void
Destroy(Widget w)1047 Destroy (
1048     Widget w)
1049 {
1050     XmNotebookWidget nb = (XmNotebookWidget)w;
1051 
1052     /* release all GCs */
1053     if (nb->notebook.frame_gc)
1054         XtReleaseGC(w, nb->notebook.frame_gc);
1055     if (nb->notebook.binding_gc)
1056         XtReleaseGC(w,nb->notebook.binding_gc);
1057     if (nb->notebook.foreground_gc)
1058         XtReleaseGC(w,nb->notebook.foreground_gc);
1059     if (nb->notebook.background_gc)
1060         XtReleaseGC(w,nb->notebook.background_gc);
1061 
1062     /* release spiral pixmap */
1063     if (nb->notebook.spiral_pixmap != XmUNSPECIFIED_PIXMAP
1064 	&& nb->notebook.spiral_pixmap != XmNONE)
1065         XFreePixmap(XtDisplay(w), nb->notebook.spiral_pixmap);
1066 
1067     /* release scroll frame data */
1068     if (nb->notebook.scroll_frame_data != NULL)
1069 	XtFree((char*)nb->notebook.scroll_frame_data);
1070 }
1071 
1072 
1073 /*- Resize -----------------------------------------------------------------
1074 
1075 	Resize the widget
1076 
1077 -----------------------------------------------------------------------------*/
1078 static void
Resize(Widget w)1079 Resize (
1080     Widget w)
1081 {
1082     XmNotebookWidget nb = (XmNotebookWidget)w;
1083 
1084     /* Adjust notebook children sizes based on notebook size */
1085     AdjustGeometry(nb, NULL, NULL);
1086 
1087     /* Layout children based on notebook sizes */
1088     LayoutChildren(nb, NULL);
1089 
1090     if (XtIsRealized(w))
1091 	XClearArea(XtDisplay(w),XtWindow(w),0,0,0,0,True);
1092 }
1093 
1094 
1095 /*- Redisplay ---------------------------------------------------------------
1096 
1097 	Method for expose event
1098 
1099 -----------------------------------------------------------------------------*/
1100 static void
Redisplay(Widget w,XEvent * e,Region region)1101 Redisplay (
1102     Widget w,
1103     XEvent *e,
1104     Region region)
1105 {
1106     XmNotebookWidget nb = (XmNotebookWidget)w;
1107     XExposeEvent *event = (XExposeEvent *)e;
1108     Widget child;			/* fix for CR8959, hack for CR9805 */
1109     int i;				/* fix for CR8959, hack for CR9805 */
1110     int total_major_tabs,total_minor_tabs;
1111     XmNotebookConstraint nc;
1112     total_major_tabs = 0;
1113     for (i = 0; i < nb->composite.num_children; i++)
1114         {
1115         child = nb->composite.children[i];
1116         nc = NotebookConstraint(child);
1117         if (NB_IS_CHILD_MAJOR(nc->child_type))
1118                 total_major_tabs++;
1119         }
1120     if (total_major_tabs > 0 )
1121     {
1122 	XtManageChild(nb->notebook.prev_major);
1123 	XtManageChild(nb->notebook.next_major);
1124     }
1125     else
1126     {
1127 	XtUnmanageChild(nb->notebook.prev_major);
1128 	XtUnmanageChild(nb->notebook.next_major);
1129     }
1130     total_minor_tabs = 0;
1131     for (i = 0; i < nb->composite.num_children; i++)
1132         {
1133         child = nb->composite.children[i];
1134         nc = NotebookConstraint(child);
1135         if (NB_IS_CHILD_MAJOR(nc->child_type))
1136                 total_minor_tabs++;
1137         }
1138     if (total_minor_tabs > 0 )
1139     {
1140 	XtManageChild(nb->notebook.prev_minor);
1141 	XtManageChild(nb->notebook.next_minor);
1142     }
1143     else
1144     {
1145 	XtUnmanageChild(nb->notebook.prev_minor);
1146 	XtUnmanageChild(nb->notebook.next_minor);
1147     }
1148     /* draw the background */
1149     DrawBackPages(nb, event, region);
1150     DrawBinding(nb, event, region);
1151     DrawFrameShadow(nb, event, region);
1152 
1153     /* display gadgets */
1154     XmeRedisplayGadgets(w,e,region);
1155 
1156     /* Work-around due to PushBG not updating border highlight
1157        -- to be removed when PushBG is fixed, see CR9805 */
1158     for (i=0; i < nb->composite.num_children; i++)
1159 	{
1160 	child = nb->composite.children[i];
1161 	if ( (NB_IS_CHILD_TAB(NotebookConstraint(child)->child_type))
1162 	  && (NotebookConstraint(child)->active)
1163 	  && (XmIsPushButtonGadget((child))))
1164 	    {
1165 	  (*(xmPushButtonGadgetClassRec.gadget_class.border_unhighlight))((child));
1166 	    }
1167 	}
1168 }
1169 
1170 
1171 /*- SetValues ---------------------------------------------------------------
1172 
1173         Set notebook widget resources
1174 
1175 -----------------------------------------------------------------------------*/
1176 /*ARGSUSED*/
1177 static Boolean
SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal * num)1178 SetValues (
1179     Widget ow,
1180     Widget rw,			/* unused */
1181     Widget nw,
1182     ArgList args,		/* unused */
1183     Cardinal *num)		/* unused */
1184 {
1185     XmNotebookWidget old = (XmNotebookWidget) ow;
1186     XmNotebookWidget new_w = (XmNotebookWidget) nw;
1187     Boolean redraw = False;
1188     Boolean updateJoin = False;
1189     Boolean updateVisual = False;
1190     Boolean relayout = False;
1191     Mask visualFlag = NoVisualChange;
1192 
1193     /* XmNorientation */
1194     if (new_w->notebook.orientation != old->notebook.orientation)
1195         {
1196         if (!XmRepTypeValidValue(XmRID_ORIENTATION,
1197 			new_w->notebook.orientation, nw))
1198            new_w->notebook.orientation = old->notebook.orientation;
1199         }
1200 
1201     /* XmNbackPagePlacement */
1202     if (new_w->notebook.back_page_pos != old->notebook.back_page_pos)
1203         {
1204 	if (!XmRepTypeValidValue(XmRID_SCROLL_BAR_PLACEMENT,
1205 			new_w->notebook.back_page_pos, nw))
1206             new_w->notebook.back_page_pos = old->notebook.back_page_pos;
1207         }
1208 
1209     /* XmNbindingType */
1210     if (new_w->notebook.binding_type != old->notebook.binding_type)
1211 	{
1212 	if (!XmRepTypeValidValue(XmRID_BINDING_TYPE,
1213 			new_w->notebook.binding_type, nw))
1214             new_w->notebook.binding_type = old->notebook.binding_type;
1215         }
1216 
1217     /* XmNcurrentPageNumber */
1218     /* current page must be in the page number range */
1219     ASSIGN_MAX(new_w->notebook.current_page_number,
1220 		new_w->notebook.first_page_number);
1221     ASSIGN_MIN(new_w->notebook.current_page_number,
1222 		new_w->notebook.last_page_number);
1223 
1224     /* XmNlastPageNumber */
1225     /* set static last page number, if the last page number is set */
1226     if (new_w->notebook.last_page_number != old->notebook.last_page_number)
1227 	new_w->notebook.dynamic_last_page_num = False;
1228 
1229     /* XmNfirstPageNumber */
1230     /* re-determine active children, if page number range has been changed */
1231     if (new_w->notebook.first_page_number != old->notebook.first_page_number
1232 	|| new_w->notebook.last_page_number != old->notebook.last_page_number)
1233 	{
1234 	/* Update navigators, unless GotoPage() will */
1235         if (new_w->notebook.current_page_number ==
1236 				old->notebook.current_page_number)
1237 	    UpdateNavigators(new_w);
1238 	SetActiveChildren(new_w);
1239 	}
1240 
1241     /* if XmNcurrentPageNumber is changed, go to the new page */
1242     if (new_w->notebook.current_page_number !=
1243 				old->notebook.current_page_number)
1244 	{
1245 	int page_number;
1246 
1247 	page_number = new_w->notebook.current_page_number;
1248 	new_w->notebook.current_page_number = old->notebook.current_page_number;
1249 	GotoPage(new_w, page_number, NULL, XmCR_NONE);
1250 	}
1251 
1252     /*
1253      * Notebook visuals
1254      */
1255 
1256     /* XmNorientation, XmNbackPagePlacement */
1257     if (new_w->notebook.orientation != old->notebook.orientation
1258 	|| new_w->notebook.back_page_pos != old->notebook.back_page_pos)
1259 	{
1260 	updateVisual = True;
1261 	updateJoin = True;
1262 	}
1263 
1264     /* XmNframeShadowThickness */
1265     if (new_w->notebook.shadow_thickness != old->notebook.shadow_thickness)
1266 	updateJoin = True;
1267 
1268     /* XmNbackPageNumber */
1269     if (new_w->notebook.back_page_number != old->notebook.back_page_number)
1270 	{
1271     	/* set the real back page number */
1272     	new_w->notebook.real_back_page_number =
1273 					new_w->notebook.back_page_number;
1274 	ASSIGN_MIN(new_w->notebook.real_back_page_number,
1275 		   (Dimension)(new_w->notebook.back_page_size /2));
1276 	ASSIGN_MAX(new_w->notebook.real_back_page_number, 1);
1277 	if (new_w->notebook.real_back_page_number !=
1278 					old->notebook.real_back_page_number)
1279 	    redraw = True;
1280 	}
1281 
1282     /* XmNframeBackground */
1283     if (new_w->notebook.frame_background != old->notebook.frame_background
1284 	|| new_w->manager.foreground != old->manager.foreground)
1285 	{
1286 	GetFrameGCs(new_w);
1287 	visualFlag |= (VisualHighlightColor|VisualHighlightPixmap);
1288 	}
1289 
1290     /* XmNbackPageBackground, XmNbackPageForeground */
1291     if (new_w->notebook.back_page_background !=
1292 				    old->notebook.back_page_background
1293 	|| new_w->notebook.back_page_foreground !=
1294 				    old->notebook.back_page_foreground)
1295 	GetBackpageGCs(new_w);
1296 
1297     /* Set new size, if necessary */
1298     if (XtIsRealized((Widget)new_w) &&
1299 	(new_w->notebook.orientation != old->notebook.orientation
1300 	|| new_w->notebook.back_page_pos != old->notebook.back_page_pos
1301 	|| new_w->notebook.back_page_size != old->notebook.back_page_size
1302 	|| new_w->notebook.binding_type != old->notebook.binding_type
1303 	|| new_w->notebook.binding_width != old->notebook.binding_width
1304 	|| new_w->notebook.first_page_number != old->notebook.first_page_number
1305         || new_w->notebook.last_page_number != old->notebook.last_page_number
1306 	|| new_w->notebook.margin_width != old->notebook.margin_width
1307 	|| new_w->notebook.margin_height != old->notebook.margin_height
1308 	|| new_w->notebook.major_spacing != old->notebook.major_spacing
1309 	|| new_w->notebook.minor_spacing != old->notebook.minor_spacing
1310 	|| new_w->notebook.shadow_thickness != old->notebook.shadow_thickness))
1311 	{
1312 	relayout = True;
1313 	redraw = True;
1314 	}
1315 
1316     /* if visual is changed, redraw */
1317     if (new_w->notebook.frame_background != old->notebook.frame_background
1318 	|| new_w->notebook.binding_pixmap != old->notebook.binding_pixmap
1319 	|| new_w->notebook.back_page_foreground !=
1320 				old->notebook.back_page_foreground
1321 	|| new_w->notebook.back_page_background !=
1322 				old->notebook.back_page_background)
1323 	{
1324 	redraw = True;
1325 	}
1326 
1327 
1328     if (updateVisual)
1329 	SetVisualConfig(new_w);
1330 
1331     if (updateJoin)
1332 	UpdateJoinSideChildren (new_w, (Dimension) 0);
1333 
1334     if (relayout)
1335 	{
1336 	Dimension save_width, save_height;
1337 	XtWidgetGeometry preferred_geo;
1338 
1339 	/* Store new w/h, restore old w/h, and adjust geometry to the old */
1340 	save_width = XtWidth(new_w);
1341 	save_height = XtHeight(new_w);
1342 	XtWidth(new_w) = XtWidth(old);
1343 	XtHeight(new_w) = XtHeight(old);
1344 
1345 	/* Adjust notebook's children type sizes to old size */
1346 	AdjustGeometry(new_w, NULL, NULL);
1347 
1348 	/* Layout Children based on old notebook sizes */
1349 	LayoutChildren(new_w, NULL);
1350 
1351 	/* Get preferred size unless app changed both width & height */
1352 	if ((XtWidth(old) == save_width) || (XtHeight(old) == save_height))
1353 	    NewPreferredGeometry(new_w, NULL, NULL, &preferred_geo);
1354 
1355 	/* App request for width takes precedence over NewPreferredGeometry */
1356 	if (XtWidth(old) != save_width)
1357 	    XtWidth(new_w) = save_width;
1358 	else
1359 	    XtWidth(new_w) = preferred_geo.width;
1360 
1361 	/* App request for height takes precedence over NewPreferredGeometry */
1362 	if (XtHeight(old) != save_height)
1363 	    XtHeight(new_w) = save_height;
1364 	else
1365 	    XtHeight(new_w) = preferred_geo.height;
1366 	}
1367 
1368     if (visualFlag)
1369 	redraw |= _XmNotifyChildrenVisual (ow, nw, visualFlag);
1370 
1371 
1372     return(redraw);
1373 }
1374 
1375 
1376 /*- QueryGeometry -----------------------------------------------------------
1377 
1378         Method for the composite widget's QueryGeometry
1379 
1380 	Returns:
1381 	    preferred size if realized, else user/application w/h values
1382 
1383 -----------------------------------------------------------------------------*/
1384 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * intended,XtWidgetGeometry * desired)1385 QueryGeometry (
1386     Widget w,
1387     XtWidgetGeometry *intended,
1388     XtWidgetGeometry *desired)
1389 {
1390 
1391     /* Get the preferred w/h based on children preferred sizes */
1392     NewPreferredGeometry((XmNotebookWidget)w, NULL, NULL, desired);
1393 
1394     /* Handle user initial size setting */
1395     if (!XtIsRealized(w))
1396 	{
1397 	if (XtWidth(w))
1398 	    desired->width = XtWidth(w);
1399 	if (XtHeight(w))
1400 	    desired->height = XtHeight(w);
1401 	}
1402 
1403     /* Return result, XmeReplyToQueryGeometry will set CWidth and CHeight */
1404     return(XmeReplyToQueryGeometry(w, intended, desired));
1405 }
1406 
1407 
1408 
1409 /*****************************************************************************
1410  *                                                                           *
1411  *                         Composite Class Methods                           *
1412  *                                                                           *
1413  *****************************************************************************/
1414 
1415 
1416 /*- GeometryManager ---------------------------------------------------------
1417 
1418         Method for the composite widget's GeometryManager
1419 
1420 -----------------------------------------------------------------------------*/
1421 
1422 /*ARGSUSED*/
1423 static XtGeometryResult
GeometryManager(Widget instigator,XtWidgetGeometry * desired,XtWidgetGeometry * reply)1424 GeometryManager (
1425     Widget instigator,
1426     XtWidgetGeometry *desired,
1427     XtWidgetGeometry *reply)	/* unused */
1428 {
1429     XmNotebookWidget nb = (XmNotebookWidget)XtParent(instigator);
1430     XmNotebookConstraint nc = NotebookConstraint(instigator);
1431     XtGeometryResult result = XtGeometryNo;
1432     XtWidgetGeometry myrequest, myallowed;
1433 
1434     /* handle changes during ConstraintSetValues layout */
1435     if ( (nb->notebook.constraint_child == instigator)
1436       && ((IsX(desired)) && (IsY(desired))))
1437 	{
1438 	nb->notebook.constraint_child = NULL;
1439 	XtX(instigator) = desired->x;
1440 	XtY(instigator) = desired->y;
1441         if (IsWidth(desired))
1442 	    XtWidth(instigator) = desired->width;
1443         if (IsHeight(desired))
1444 	    XtHeight(instigator) = desired->height;
1445 	return XtGeometryYes;
1446 	}
1447 
1448     /* only for resizing request */
1449     if ((nc->resizable || NB_IS_CHILD_TAB(nc->child_type))
1450         && (desired->request_mode & (CWWidth|CWHeight|CWBorderWidth))
1451 	&& !nb->notebook.in_setshadow)
1452 	{
1453 	/* Determine preferred geometry based on instigator preferrences */
1454 	NewPreferredGeometry(nb, instigator, desired, &myrequest);
1455 
1456 	/*
1457 	 * Prepare resize request (as needed) to the parent
1458 	 */
1459         myrequest.request_mode = 0;
1460 	if (IsQueryOnly(desired))
1461 	    myrequest.request_mode |= XtCWQueryOnly;
1462         if (IsWidth(desired) && XtWidth(nb) != myrequest.width)
1463             myrequest.request_mode |= CWWidth;
1464         if (IsHeight(desired) && XtHeight(nb) != myrequest.height)
1465             myrequest.request_mode |= CWHeight;
1466         if (IsBorder(desired) && XtBorderWidth(nb) != myrequest.border_width)
1467             myrequest.border_width |= CWBorderWidth;
1468 
1469         /* ask parent, only if notebook resize request is needed */
1470         if (myrequest.request_mode)
1471 	    {
1472 	    if (NB_IS_CHILD_TAB(nc->child_type))
1473 	      result = XtGeometryYes;
1474 	    else /* nc->resizable */
1475             {
1476 	    result = XtMakeGeometryRequest((Widget)nb, &myrequest, &myallowed);
1477 
1478 	    /* Parent unable to completely fulfill request */
1479 	    if (result == XtGeometryAlmost)
1480 	    result = XtGeometryNo;
1481 	    }
1482 	    }
1483 
1484 	/* Update the geometry, if necessary */
1485 	if (result == XtGeometryYes && !IsQueryOnly(desired))
1486 	    {
1487 	    /* Adjust notebook's children type sizes to new size */
1488 	    AdjustGeometry(nb, instigator, desired);
1489 
1490 	    /* Layout Children based on new notebook size */
1491 	    LayoutChildren(nb, instigator);
1492 
1493 	    if (XtIsRealized((Widget)nb))
1494 		XClearArea(XtDisplay((Widget)nb),XtWindow((Widget)nb),
1495 			0,0,0,0,True);
1496 	    }
1497 	}
1498     return result;
1499 }
1500 
1501 
1502 /*- ChangeManaged -----------------------------------------------------------
1503 
1504         Method for the composite widget's ChangeManaged
1505 
1506         Something changed in the set of managed children, so place
1507         the children and change the form widget size to reflect new size,
1508         if possible.
1509 
1510 -----------------------------------------------------------------------------*/
1511 static void
ChangeManaged(Widget w)1512 ChangeManaged (
1513     Widget w)
1514 {
1515     XmNotebookWidget nb = (XmNotebookWidget)w;
1516     XtWidgetGeometry preferred;
1517 
1518     /* ChangeManaged recursively called by SetPageScroller; return */
1519     if (nb->notebook.scroller_status == DEFAULT_CREATE)
1520 	return;
1521 
1522     /* if this is the first time through, set the page scroller */
1523     if (nb->notebook.scroller_status == DEFAULT_NONE)
1524 	{
1525 	SetPageScroller(nb);
1526 	UpdateNavigators(nb);
1527 	}
1528 
1529     /* assign default page number to those who don't have */
1530     AssignDefaultPageNumber(nb);
1531 
1532     /* invoke XmNpageChangedCallback for initial setting of current page */
1533     if (nb->notebook.first_change_managed
1534 	&& XtHasCallbacks(w, XmNpageChangedCallback) == XtCallbackHasSome)
1535 	{
1536 	XmNotebookCallbackStruct cbs;
1537 
1538 	cbs.reason           = XmCR_NONE;
1539 	cbs.event            = NULL;
1540 	cbs.page_number      = nb->notebook.current_page_number;
1541 	cbs.page_widget      = GetChildWidget(nb,
1542 				nb->notebook.current_page_number, XmPAGE);
1543 	cbs.prev_page_number = XmUNSPECIFIED_PAGE_NUMBER;
1544 	cbs.prev_page_widget = NULL;
1545 
1546 	/* Mark that the callback is being called and when it finishes */
1547 	nb->notebook.in_callback = True;
1548 	XtCallCallbackList(w, nb->notebook.page_change_callback, &cbs);
1549 	nb->notebook.in_callback = False;
1550 	}
1551 
1552     /* sort children by their page number and update their activity */
1553     SortChildren(nb);
1554 
1555     /*
1556      * Determine preferred notebook size based on new managed child
1557      */
1558 
1559     /* Check if current size is the preferred size */
1560     if (NewPreferredGeometry(nb, NULL, NULL, &preferred))
1561     {
1562 	/* Prepare parent geometry request */
1563 	preferred.request_mode = 0;
1564         if (XtIsRealized((Widget)nb) || XtWidth(nb) == 0)
1565             preferred.request_mode |= CWWidth;
1566         if (XtIsRealized((Widget)nb) || XtHeight(nb) == 0)
1567             preferred.request_mode |= CWHeight;
1568 
1569 	/* Make parent geometry request, if necessary */
1570 	if (preferred.request_mode)
1571 	    _XmMakeGeometryRequest((Widget)nb, &preferred);
1572 
1573 	/* Clear notebook area otherwise binder and backpage don't update. */
1574 	if (XtIsRealized((Widget)nb) && !nb->notebook.first_change_managed)
1575 	    XClearArea(XtDisplay(nb), XtWindow(nb), 0, 0, 0, 0, True);
1576     }
1577 
1578     /* Adjust notebook's children type sizes (based on notebook size) */
1579     AdjustGeometry(nb, NULL, NULL);
1580 
1581     /* Layout Children (based on notebook size) */
1582     LayoutChildren(nb, NULL);
1583 
1584     XmeNavigChangeManaged(w);
1585     nb->notebook.first_change_managed = False;
1586 }
1587 
1588 
1589 /*- InsertChild -------------------------------------------------------------
1590 
1591         Method for the composite widget's InsertChild
1592 
1593 -----------------------------------------------------------------------------*/
1594 static void
InsertChild(Widget child)1595 InsertChild (
1596     Widget child)
1597 {
1598     XmNotebookWidget nb = (XmNotebookWidget)XtParent(child);
1599     XmNotebookConstraint nc = NotebookConstraint(child);
1600     XmScrollFrameTrait scroll_frameT;
1601     XtWidgetProc insert_child;
1602 
1603     /* check if trying to insert an invalid object */
1604     if (!XtIsRectObj(child))
1605 	return;
1606 
1607     /* call manager's InsertChild method */
1608     _XmProcessLock();
1609     insert_child = ((XmManagerWidgetClass)xmManagerWidgetClass)
1610 			->composite_class.insert_child;
1611     _XmProcessUnlock();
1612     (*insert_child)(child);
1613 
1614     /* add some keyboard traversal stuff */
1615     switch (nc->child_type)
1616 	{
1617 	case XmPAGE_SCROLLER:
1618 	    /* First: take care of previous page scroller */
1619 
1620 	    /* default page scroller not yet made, so just put this one in */
1621 	    if (nb->notebook.scroller_status == DEFAULT_NONE)
1622 	       nb->notebook.scroller_status = DEFAULT_GONE;
1623 
1624 	    /* remove previously created default page scroller */
1625 	    else if (nb->notebook.scroller_status == DEFAULT_USED)
1626 		{
1627 		nb->notebook.scroller_status = DEFAULT_CREATE;
1628 
1629 		/* remove navigator, if page scroller is a navigator */
1630 		if (NB_IS_CHILD_NAVIGATOR(nb->notebook.scroller))
1631 		    {
1632 		    if ((scroll_frameT=NB_SCROLL_FRAME(nb)) != NULL
1633 			&& scroll_frameT->removeNavigator != NULL)
1634 			scroll_frameT->removeNavigator((Widget) nb,
1635 							nb->notebook.scroller);
1636 		    }
1637 		XtDestroyWidget(nb->notebook.scroller);
1638 
1639 		nb->notebook.scroller_status = DEFAULT_GONE;
1640 		}
1641 
1642 	    /* remove previously created non-default page scroller */
1643 	    else if (nb->notebook.scroller_status == DEFAULT_GONE
1644 		  && nb->notebook.scroller != NULL)
1645 		{
1646 		nb->notebook.scroller_status = DEFAULT_CREATE;
1647 
1648 		/* remove navigator, if page scroller is a navigator */
1649 		if (NB_IS_CHILD_NAVIGATOR(nb->notebook.scroller))
1650 		    {
1651 		    if ((scroll_frameT=NB_SCROLL_FRAME(nb)) != NULL
1652                         && scroll_frameT->removeNavigator != NULL)
1653 			scroll_frameT->removeNavigator((Widget)nb,
1654 							nb->notebook.scroller);
1655 		    }
1656 		XtUnmanageChild(nb->notebook.scroller);
1657 
1658 		nb->notebook.scroller_status = DEFAULT_GONE;
1659 		}
1660 
1661 	    /* Second: take care of this new page scroller */
1662 
1663 	    /* update scroller's translation table */
1664 	    nb->notebook.scroller = child;
1665 
1666 	    /* add navigator, if page scroller has navigator trait */
1667 	    if (NB_IS_CHILD_NAVIGATOR(nb->notebook.scroller))
1668 		{
1669 		if ((scroll_frameT = NB_SCROLL_FRAME(nb)) != NULL
1670 		    && scroll_frameT->addNavigator != NULL)
1671 			scroll_frameT->addNavigator((Widget)nb,
1672 						    child, NavigDimensionX);
1673 		}
1674 
1675 	    /* update navigators so this one get initial info */
1676             UpdateNavigators(nb);
1677 
1678 	    break;
1679 
1680 	case XmPAGE:
1681 	case XmSTATUS_AREA:
1682             XtVaSetValues(child, XmNnavigationType, XmTAB_GROUP, NULL);
1683 	    break;
1684 
1685 	case XmMAJOR_TAB:
1686 	case XmMINOR_TAB:
1687 	    /* Install activiation callback */
1688 	    {
1689 	    XmActivatableTrait activeT;
1690 
1691 	    if ((activeT=NB_ACTIVATABLE(child)) != NULL
1692 		&& activeT->changeCB != NULL)
1693 		activeT->changeCB(child, TabPressed,
1694 		    (XtPointer)(unsigned long)(NB_IS_CHILD_MAJOR(nc->child_type)
1695 		    ? XmCR_MAJOR_TAB : XmCR_MINOR_TAB), True);
1696 	    }
1697 
1698 	    /* Update JoinSide information */
1699 	    (void) UpdateJoinSide(nb, child, nc->child_type, (Dimension) 0);
1700 
1701 	    /* Install accelerators */
1702 	    if (!XmIsGadget(child))
1703                 XtInstallAccelerators(child, (Widget)nb);
1704 	    break;
1705 	}
1706 }
1707 
1708 
1709 /*- DeleteChild -------------------------------------------------------------
1710 
1711         Method for the composite widget's DeleteChild
1712 
1713 -----------------------------------------------------------------------------*/
1714 static void
DeleteChild(Widget child)1715 DeleteChild (
1716     Widget child)
1717 {
1718     XmNotebookWidget nb = (XmNotebookWidget)XtParent(child);
1719     XmNotebookConstraint nc = NotebookConstraint(child);
1720     XmScrollFrameTrait scroll_frameT;
1721     XtWidgetProc delete_child;
1722 
1723     /* clear child pointers in Notebook */
1724     switch (nc->child_type)
1725 	{
1726         case XmPAGE_SCROLLER:
1727 	    if (nb->notebook.scroller == child)
1728 		{
1729 		/* remove navigator */
1730 		if (NB_IS_CHILD_NAVIGATOR(nb->notebook.scroller))
1731 		    {
1732 		    if ((scroll_frameT=NB_SCROLL_FRAME(nb)) != NULL
1733 			&& scroll_frameT->removeNavigator != NULL)
1734 			scroll_frameT->removeNavigator((Widget)nb,
1735 						    nb->notebook.scroller);
1736 		    }
1737 		/* Mark that no page scroller is established */
1738 		nb->notebook.scroller = NULL;
1739 		nb->notebook.scroller_status = DEFAULT_GONE;
1740 		}
1741 	    break;
1742 	case XmMAJOR_TAB_SCROLLER:
1743 	    nb->notebook.next_major = NULL;
1744 	    nb->notebook.prev_major = NULL;
1745 	    break;
1746 	case XmMINOR_TAB_SCROLLER:
1747 	    nb->notebook.next_minor = NULL;
1748 	    nb->notebook.prev_minor = NULL;
1749 	    break;
1750 	}
1751 
1752     /* call manager's DeleteChild method */
1753     _XmProcessLock();
1754     delete_child = ((XmManagerWidgetClass)xmManagerWidgetClass)
1755 			->composite_class.delete_child;
1756     _XmProcessUnlock();
1757     (*delete_child)(child);
1758 }
1759 
1760 
1761 
1762 /*****************************************************************************
1763  *                                                                           *
1764  *                        Constraint Class Methods                           *
1765  *                                                                           *
1766  *****************************************************************************/
1767 
1768 
1769 /*- ConstraintInitialize ----------------------------------------------------
1770 
1771         Initialize method for Notebook's constraint class
1772 
1773 	A default page number will be provided when the widget is managed.
1774 
1775 -----------------------------------------------------------------------------*/
1776 
1777 /*ARGSUSED*/
1778 static void
ConstraintInitialize(Widget req,Widget new_w,ArgList args,Cardinal * num)1779 ConstraintInitialize (
1780     Widget req,			/* unused */
1781     Widget new_w,
1782     ArgList args,		/* unused */
1783     Cardinal *num)		/* unused */
1784 {
1785     XmNotebookConstraint nc = NotebookConstraint(new_w);
1786 
1787     /* check for invalid object */
1788     if (!XtIsRectObj(new_w))
1789         return;
1790 
1791     /* validate the child type */
1792     if (nc->child_type != XmMAJOR_TAB_SCROLLER
1793 	&& nc->child_type != XmMINOR_TAB_SCROLLER
1794 	&& !XmRepTypeValidValue(XmRID_NB_CHILD_TYPE, nc->child_type, new_w))
1795         nc->child_type = XmNONE;
1796 
1797     /* convert to internal */
1798      if (nc->child_type == XmNONE)
1799         {
1800 	if (NB_IS_CHILD_ACTIVATABLE(new_w))
1801 	    nc->child_type = XmMAJOR_TAB;
1802 	else if (NB_IS_CHILD_ACCESSTEXTUAL(new_w))
1803 	    nc->child_type = XmSTATUS_AREA;
1804 	else if (NB_IS_CHILD_NAVIGATOR(new_w))
1805 	    nc->child_type = XmPAGE_SCROLLER;
1806 	else
1807 	    nc->child_type = XmPAGE;
1808 	}
1809 }
1810 
1811 
1812 /*- ConstraintSetValues -----------------------------------------------------
1813 
1814         SetValue method for notebook's constraint class
1815 
1816 -----------------------------------------------------------------------------*/
1817 
1818 /*ARGSUSED*/
1819 static Boolean
ConstraintSetValues(Widget old_w,Widget req,Widget new_w,ArgList args,Cardinal * num)1820 ConstraintSetValues (
1821     Widget old_w,
1822     Widget req,			/* unused */
1823     Widget new_w,
1824     ArgList args,		/* unused */
1825     Cardinal *num)		/* unused */
1826 {
1827     XmNotebookWidget nb = (XmNotebookWidget)XtParent(new_w);
1828     XmNotebookConstraint old_nc = NotebookConstraint(old_w);
1829     XmNotebookConstraint new_nc = NotebookConstraint(new_w);
1830     Boolean redraw = False;
1831     Boolean need_reset = False;
1832 
1833     /* check for invalid object */
1834     if (!XtIsRectObj(new_w))
1835 	return False;
1836 
1837     /* XmNnotebookChildType is only CG, not Settable */
1838     if (new_nc->child_type != old_nc->child_type) {
1839 	new_nc->child_type = old_nc->child_type;
1840 	XmeWarning(new_w, MESSAGE0);
1841     }
1842 
1843     /* if the page number is changed, sort again */
1844     /* by just repositioning that child */
1845     if (new_nc->page_number != old_nc->page_number)
1846 	{
1847 	/* check for last page number change */
1848 	if (nb->notebook.dynamic_last_page_num)
1849 	    {
1850 	    if (new_nc->page_number > nb->notebook.last_page_number
1851 	    && XtIsManaged(new_w)
1852 	    && (NB_IS_CHILD_PAGE(new_nc->child_type)
1853 		|| NB_IS_CHILD_TAB(new_nc->child_type)
1854 		|| NB_IS_CHILD_STATUS(new_nc->child_type)))
1855 		need_reset = SetLastPageNumber(nb, new_nc->page_number);
1856 	    else if (old_nc->page_number == nb->notebook.last_page_number)
1857 		need_reset = AssignDefaultPageNumber(nb);
1858 	    }
1859 
1860 	/* re-sort and check child list */
1861 	RepositionChild(nb, new_w);
1862 	SetActiveChildren(nb);
1863 
1864 	/* check for changes that affect layout */
1865 	if (!nb->notebook.in_callback)
1866 	    {
1867 	    switch(new_nc->child_type)
1868 		{
1869 		case XmPAGE:
1870 		case XmSTATUS_AREA:
1871 		if (nb->notebook.current_page_number == old_nc->page_number
1872 		|| nb->notebook.current_page_number == new_nc->page_number)
1873 		    {
1874 		    if (need_reset)
1875 			ResetTopPointers(nb, XmNONE, 0);
1876 		    nb->notebook.constraint_child = new_w;
1877 		    LayoutPages(nb, NULL);
1878 		    redraw = True;
1879 		    }
1880 		    break;
1881 		case XmMAJOR_TAB:
1882 		    ResetTopPointers(nb, XmNONE, 0);
1883 		    nb->notebook.constraint_child = new_w;
1884 		    LayoutMajorTabs(nb, NULL);
1885 		    LayoutMinorTabs(nb, NULL);
1886 		    redraw = True;
1887 		    break;
1888 		case XmMINOR_TAB:
1889 		    ResetTopPointers(nb, XmNONE, 0);
1890 		    nb->notebook.constraint_child = new_w;
1891 		    LayoutMinorTabs(nb, NULL);
1892 		    redraw = True;
1893 		    break;
1894 		} /* switch */
1895 	    } /* if */
1896 	} /* if */
1897 
1898     return(redraw);
1899 }
1900 
1901 
1902 
1903 /*****************************************************************************
1904  *                                                                           *
1905  *			  Initializing & Resource Managing		     *
1906  *                                                                           *
1907  *****************************************************************************/
1908 
1909 
1910 /*- GetDefaultBackPagePos ---------------------------------------------------
1911 
1912 	Get the default back page position
1913 
1914 -----------------------------------------------------------------------------*/
1915 
1916 /*ARGSUSED*/
1917 static void
GetDefaultFrameBackground(Widget w,int offset,XrmValue * value)1918 GetDefaultFrameBackground(
1919     Widget w,
1920     int offset,			/* unused */
1921     XrmValue *value)
1922 {
1923   value->addr = (XtPointer) &w->core.background_pixel;
1924 }
1925 
1926 
1927 /*ARGSUSED*/
1928 static void
GetDefaultBackPageBackground(Widget w,int offset,XrmValue * value)1929 GetDefaultBackPageBackground(
1930     Widget w,
1931     int offset,			/* unused */
1932     XrmValue *value)
1933 {
1934   XmNotebookWidget nb = (XmNotebookWidget)w;
1935   static Pixel pixel;
1936 
1937   value->addr = (XtPointer) &pixel;
1938 
1939   XmGetColors(XtScreen(w), nb->core.colormap, nb->notebook.frame_background,
1940 	      NULL, NULL, NULL, &pixel);
1941 }
1942 
1943 
1944 /*ARGSUSED*/
1945 static void
GetDefaultBackPagePos(Widget w,int offset,XrmValue * value)1946 GetDefaultBackPagePos (
1947     Widget w,
1948     int offset,			/* unused */
1949     XrmValue *value)
1950 {
1951     static unsigned char back_page_pos;
1952     XmNotebookWidget nb = (XmNotebookWidget)w;
1953 
1954     /* initialize the notebook layout default */
1955     if (LayoutIsRtoLM(w))
1956 	{
1957 	if (nb->notebook.orientation == XmVERTICAL)
1958 	    /* RIGHT_TO_LEFT and VERTICAL */
1959 	    back_page_pos = XmBOTTOM_LEFT;
1960 	else
1961 	    /* RIGHT_TO_LEFT and HORIZONTAL */
1962 	    back_page_pos = XmBOTTOM_LEFT;
1963 	}
1964     else
1965 	{
1966 	 if (nb->notebook.orientation == XmVERTICAL)
1967 	    /* LEFT_TO_RIGHT and VERTICAL */
1968 	    back_page_pos = XmBOTTOM_RIGHT;
1969 	else
1970 	    /* LEFT_TO_RIGHT and HORIZONTAL */
1971 	    back_page_pos = XmBOTTOM_RIGHT;
1972 	}
1973     /*
1974      * This will have to change when BOTTOM_TO_TOP is supported for
1975      * XmNlayoutDirection.
1976      */
1977 
1978     value->addr = (XPointer) &back_page_pos;
1979 }
1980 
1981 /* Same logic as the GetDefaultBackPagePos default proc ... rewritten
1982  * without the static variable - for use from the Initialize proc .
1983  */
1984 static unsigned char
GetDefaultBackPagePosAgain(Widget w)1985 GetDefaultBackPagePosAgain (
1986     Widget w)
1987 {
1988     unsigned char back_page_pos;
1989     XmNotebookWidget nb = (XmNotebookWidget)w;
1990 
1991     if (LayoutIsRtoLM(w))
1992 	{
1993 	if (nb->notebook.orientation == XmVERTICAL)
1994 	    /* RIGHT_TO_LEFT and VERTICAL */
1995 	    back_page_pos = XmBOTTOM_LEFT;
1996 	else
1997 	    /* RIGHT_TO_LEFT and HORIZONTAL */
1998 	    back_page_pos = XmBOTTOM_LEFT;
1999 	}
2000     else
2001 	{
2002 	 if (nb->notebook.orientation == XmVERTICAL)
2003 	    /* LEFT_TO_RIGHT and VERTICAL */
2004 	    back_page_pos = XmBOTTOM_RIGHT;
2005 	else
2006 	    /* LEFT_TO_RIGHT and HORIZONTAL */
2007 	    back_page_pos = XmBOTTOM_RIGHT;
2008 	}
2009 
2010     return back_page_pos;
2011 }
2012 
2013 /*- FromOrientationPixels ---------------------------------------------------
2014 
2015         Determines orientation and calls appropriate converter.
2016 
2017 -----------------------------------------------------------------------------*/
2018 static void
FromOrientationPixels(Widget w,int offset,XtArgVal * value)2019 FromOrientationPixels (
2020     Widget w,
2021     int offset,
2022     XtArgVal *value)
2023 {
2024     XmNotebookWidget nb = (XmNotebookWidget)w;
2025 
2026     if ((int)(*value) < 0)
2027 	*value = 0;
2028     if (nb->notebook.orientation == XmHORIZONTAL)
2029 	XmeFromHorizontalPixels(w, offset, value);
2030     else
2031 	XmeFromVerticalPixels(w, offset, value);
2032 }
2033 
2034 
2035 /*- ToOrientationPixels ----------------------------------------------------
2036 
2037         Determines orientation and calls appropriate converter.
2038 
2039 -----------------------------------------------------------------------------*/
2040 static XmImportOperator
ToOrientationPixels(Widget w,int offset,XtArgVal * value)2041 ToOrientationPixels (
2042     Widget w,
2043     int offset,
2044     XtArgVal *value)
2045 {
2046     XmNotebookWidget nb = (XmNotebookWidget)w;
2047 
2048     if (nb->notebook.orientation == XmHORIZONTAL)
2049         return(XmeToHorizontalPixels(w, offset, value));
2050     else
2051         return(XmeToVerticalPixels(w, offset, value));
2052 }
2053 
2054 
2055 /*- FromOrientationOppositePixels -------------------------------------------
2056 
2057         Determines orientation and calls appropriate converter.
2058 
2059 -----------------------------------------------------------------------------*/
2060 static void
FromOrientationOppositePixels(Widget w,int offset,XtArgVal * value)2061 FromOrientationOppositePixels (
2062     Widget w,
2063     int offset,
2064     XtArgVal *value)
2065 {
2066     XmNotebookWidget nb = (XmNotebookWidget)w;
2067 
2068     if ((int)(*value) < 0)
2069         *value = 0;
2070     if (nb->notebook.orientation == XmHORIZONTAL)
2071 	XmeFromVerticalPixels(w, offset, value);
2072     else
2073         XmeFromHorizontalPixels(w, offset, value);
2074 }
2075 
2076 
2077 /*- ToOrientationOppositePixels --------------------------------------------
2078 
2079         Determines orientation and calls appropriate converter.
2080 
2081 -----------------------------------------------------------------------------*/
2082 static XmImportOperator
ToOrientationOppositePixels(Widget w,int offset,XtArgVal * value)2083 ToOrientationOppositePixels (
2084     Widget w,
2085     int offset,
2086     XtArgVal *value)
2087 {
2088     XmNotebookWidget nb = (XmNotebookWidget)w;
2089 
2090     if (nb->notebook.orientation == XmHORIZONTAL)
2091 	return(XmeToVerticalPixels(w, offset, value));
2092     else
2093         return(XmeToHorizontalPixels(w, offset, value));
2094 }
2095 
2096 
2097 /*- CreateTabScrollers -----------------------------------------------------
2098 
2099 	Create Notebook's tab scrollers
2100 
2101 -----------------------------------------------------------------------------*/
2102 static void
CreateTabScrollers(XmNotebookWidget nb)2103 CreateTabScrollers (
2104     XmNotebookWidget nb)
2105 {
2106     /* creating major tab scrollers */
2107     nb->notebook.next_major = XtVaCreateManagedWidget(MAJOR_TAB_NEXT_NAME,
2108                 xmArrowButtonGadgetClass, (Widget)nb,
2109                 XmNwidth, TAB_SCROLLER_WIDTH_DEFAULT,
2110                 XmNheight, TAB_SCROLLER_HEIGHT_DEFAULT,
2111                 XmNnotebookChildType, XmMAJOR_TAB_SCROLLER,
2112 		XmNtraversalOn, False,
2113                 NULL);
2114     ((XmActivatableTrait)XmeTraitGet((XtPointer)
2115 		XtClass((Widget)nb->notebook.next_major),XmQTactivatable))->
2116 		changeCB(nb->notebook.next_major,FlipTabs,NULL,True);
2117 
2118     nb->notebook.prev_major = XtVaCreateManagedWidget(MAJOR_TAB_PREV_NAME,
2119                 xmArrowButtonGadgetClass, (Widget)nb,
2120                 XmNwidth, TAB_SCROLLER_WIDTH_DEFAULT,
2121                 XmNheight, TAB_SCROLLER_HEIGHT_DEFAULT,
2122                 XmNnotebookChildType, XmMAJOR_TAB_SCROLLER,
2123 		XmNtraversalOn, False,
2124                 NULL);
2125     ((XmActivatableTrait)XmeTraitGet((XtPointer)
2126                 XtClass((Widget)nb->notebook.prev_major),XmQTactivatable))->
2127                 changeCB(nb->notebook.prev_major,FlipTabs,NULL,True);
2128 
2129     /* creating minor tab scrollers */
2130     nb->notebook.next_minor = XtVaCreateManagedWidget(MINOR_TAB_NEXT_NAME,
2131                 xmArrowButtonGadgetClass, (Widget)nb,
2132                 XmNwidth, TAB_SCROLLER_WIDTH_DEFAULT,
2133                 XmNheight, TAB_SCROLLER_HEIGHT_DEFAULT,
2134                 XmNnotebookChildType, XmMINOR_TAB_SCROLLER,
2135 		XmNtraversalOn, False,
2136                 NULL);
2137     ((XmActivatableTrait)XmeTraitGet((XtPointer)
2138                 XtClass((Widget)nb->notebook.next_minor),XmQTactivatable))->
2139                 changeCB(nb->notebook.next_minor,FlipTabs,NULL,True);
2140 
2141     nb->notebook.prev_minor = XtVaCreateManagedWidget(MINOR_TAB_PREV_NAME,
2142                 xmArrowButtonGadgetClass, (Widget)nb,
2143                 XmNwidth, TAB_SCROLLER_WIDTH_DEFAULT,
2144                 XmNheight, TAB_SCROLLER_HEIGHT_DEFAULT,
2145                 XmNnotebookChildType, XmMINOR_TAB_SCROLLER,
2146 		XmNtraversalOn, False,
2147                 NULL);
2148     ((XmActivatableTrait)XmeTraitGet((XtPointer)
2149                 XtClass((Widget)nb->notebook.prev_minor),XmQTactivatable))->
2150                 changeCB(nb->notebook.prev_minor,FlipTabs,NULL,True);
2151 }
2152 
2153 
2154 /*- SetVisualConfig ---------------------------------------------------------
2155 
2156         Sets Notebook visual configuration private variables.
2157 
2158 -----------------------------------------------------------------------------*/
2159 static void
SetVisualConfig(XmNotebookWidget nb)2160 SetVisualConfig (
2161     XmNotebookWidget nb)
2162 {
2163     /* set tab and binding position variables */
2164     if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
2165         nb->notebook.orientation == XmHORIZONTAL)
2166     {
2167         nb->notebook.major_pos = RIGHT;
2168         nb->notebook.minor_pos = BOTTOM;
2169         nb->notebook.binding_pos = LEFT;
2170     }
2171     else if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
2172         nb->notebook.orientation == XmVERTICAL)
2173     {
2174         nb->notebook.major_pos = BOTTOM;
2175         nb->notebook.minor_pos = RIGHT;
2176         nb->notebook.binding_pos = TOP;
2177     }
2178     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
2179         nb->notebook.orientation == XmHORIZONTAL)
2180     {
2181         nb->notebook.major_pos = LEFT;
2182         nb->notebook.minor_pos = BOTTOM;
2183         nb->notebook.binding_pos = RIGHT;
2184     }
2185     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
2186         nb->notebook.orientation == XmVERTICAL)
2187     {
2188         nb->notebook.major_pos = BOTTOM;
2189         nb->notebook.minor_pos = LEFT;
2190         nb->notebook.binding_pos = TOP;
2191     }
2192     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
2193         nb->notebook.orientation == XmHORIZONTAL)
2194     {
2195         nb->notebook.major_pos = RIGHT;
2196         nb->notebook.minor_pos = TOP;
2197         nb->notebook.binding_pos = LEFT;
2198     }
2199     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
2200         nb->notebook.orientation == XmVERTICAL)
2201     {
2202         nb->notebook.major_pos = TOP;
2203         nb->notebook.minor_pos = RIGHT;
2204         nb->notebook.binding_pos = BOTTOM;
2205     }
2206     else if (nb->notebook.back_page_pos == XmTOP_LEFT &&
2207         nb->notebook.orientation == XmHORIZONTAL)
2208     {
2209         nb->notebook.major_pos = LEFT;
2210         nb->notebook.minor_pos = TOP;
2211         nb->notebook.binding_pos = RIGHT;
2212     }
2213     else if (nb->notebook.back_page_pos == XmTOP_LEFT &&
2214         nb->notebook.orientation == XmVERTICAL)
2215     {
2216         nb->notebook.major_pos = TOP;
2217         nb->notebook.minor_pos = LEFT;
2218         nb->notebook.binding_pos = BOTTOM;
2219     }
2220 }
2221 
2222 
2223 /*- UpdateJoinSide ------------------------------------------------------------
2224 
2225         Update tab's JoinSide Trait to match current visual configuration.
2226 
2227 	Uses instance state:
2228 		major_pos
2229 		minor_pos
2230 	Returns
2231 	    True, if the child is major or minor tab and holds the
2232 	    JoinSide trait.  Otherwise, returns False.
2233 
2234 -----------------------------------------------------------------------------*/
2235 static Boolean
UpdateJoinSide(XmNotebookWidget nb,Widget child,unsigned char child_type,Dimension shadow_thickness)2236 UpdateJoinSide (
2237     XmNotebookWidget nb,
2238     Widget child,
2239     unsigned char child_type,
2240     Dimension shadow_thickness)
2241 {
2242     XmJoinSideTrait joinsideT;          /* child JoinSide trait */
2243     unsigned char side_of_book;         /* side of notebook tab is on */
2244     unsigned char side_to_join;         /* side to join */
2245 
2246    /* Determine side of nookbook tabs reside */
2247     if (NB_IS_CHILD_MAJOR(child_type))
2248 	side_of_book = nb->notebook.major_pos;
2249     else if (NB_IS_CHILD_MINOR(child_type))
2250 	side_of_book = nb->notebook.minor_pos;
2251     else
2252 	return(False);
2253 
2254    /* Update JoinSide trait infomation, unless trait not found */
2255     if ((joinsideT=NB_JOINSIDE(child)) != NULL
2256 	&& joinsideT->setValue != NULL)
2257 	{
2258        /* Convert notebook position to JoinSide position */
2259 	switch (side_of_book)
2260 	    {
2261 	    case RIGHT:
2262 		side_to_join = XmLEFT;
2263 		break;
2264 	    case BOTTOM:
2265 		side_to_join = XmTOP;
2266 		break;
2267 	    case LEFT:
2268 		side_to_join = XmRIGHT;
2269 		break;
2270 	    case TOP:
2271 	    default:
2272 		side_to_join = XmBOTTOM;
2273 		break;
2274 	    }
2275 	/* Invoke JoinSideSetValues */
2276 	joinsideT->setValue(child, side_to_join, shadow_thickness);
2277 	return(True);
2278 	}
2279 
2280     return(False);
2281 }
2282 
2283 
2284 /*- UpdateJoinSideChildren --------------------------------------------------
2285 
2286         Update JoinSide aware children of new shadow_thickness or JoinSide.
2287 
2288 -----------------------------------------------------------------------------*/
2289 static void
UpdateJoinSideChildren(XmNotebookWidget nb,Dimension shadow_thickness)2290 UpdateJoinSideChildren (
2291     XmNotebookWidget nb,
2292     Dimension shadow_thickness)
2293 {
2294     Widget cw;				/* child widget */
2295     unsigned char ct;			/* child constraint type */
2296     int i;
2297 
2298     for (i=0; i < nb->composite.num_children; i++)
2299 	{
2300 	cw = nb->composite.children[i];
2301         ct = NotebookConstraint(cw)->child_type;
2302 	if (NB_IS_CHILD_TAB(ct))
2303 	    (void) UpdateJoinSide(nb, cw, ct, shadow_thickness);
2304 	}
2305 }
2306 
2307 
2308 /*- SetPageScroller ---------------------------------------------------------
2309 
2310 	Set the visual configuration of the page scroller.
2311 
2312 	It creates the default page scroller if no page scroller
2313 	is created yet (consisting of a SpinBox with TextField child).
2314 
2315 -----------------------------------------------------------------------------*/
2316 static void
SetPageScroller(XmNotebookWidget nb)2317 SetPageScroller (
2318     XmNotebookWidget nb)
2319 {
2320 
2321     /* Only create default page scroller if none currently exists */
2322     if (nb->notebook.scroller_status != DEFAULT_NONE)
2323     	return;
2324 
2325     /* Mark that we are in the process of creating the default */
2326     nb->notebook.scroller_status = DEFAULT_CREATE;
2327 
2328     nb->notebook.scroller = XtVaCreateManagedWidget(PAGE_SCROLLER_NAME,
2329 		  xmSpinBoxWidgetClass, (Widget)nb,
2330 		  XmNarrowLayout, XmARROWS_SPLIT,
2331 		  XmNnotebookChildType, XmPAGE_SCROLLER,
2332 		  NULL);
2333 
2334     nb->notebook.scroller_child = XtVaCreateManagedWidget(NB_TEXT_FIELD_NAME,
2335 		  xmTextFieldWidgetClass, nb->notebook.scroller,
2336 		  XmNspinBoxChildType, XmNUMERIC,
2337 		  XmNcolumns, 6,
2338 		  XmNmarginHeight, 2,
2339 		  XmNcursorPositionVisible, False,
2340 		  XmNeditable, False,
2341 		  XmNtraversalOn, True,
2342 		  NULL);
2343 
2344     /* Mark that the default page scroller has been established */
2345     nb->notebook.scroller_status = DEFAULT_USED;
2346 }
2347 
2348 
2349 
2350 /*****************************************************************************
2351  *                                                                           *
2352  *			   Child Layout Functions			     *
2353  *                                                                           *
2354  *****************************************************************************/
2355 
2356 
2357 /*- LayoutChildren ----------------------------------------------------------
2358 
2359         Function to layout Notebook's children
2360 
2361 -----------------------------------------------------------------------------*/
2362 static void
LayoutChildren(XmNotebookWidget nb,Widget instigator)2363 LayoutChildren (
2364     XmNotebookWidget nb,
2365     Widget instigator)
2366 {
2367     /* reset top pointers of tabs */
2368     ResetTopPointers(nb, XmNONE, 0);
2369 
2370     /* layout children */
2371     LayoutPages(nb, instigator);
2372     LayoutMajorTabs(nb, instigator);
2373     LayoutMinorTabs(nb, instigator);
2374 }
2375 
2376 
2377 /*- LayoutPages -------------------------------------------------------------
2378 
2379 	Function to layout Page, Status, and Page Scroller.
2380 
2381 	Uses instance state:
2382 		current_page_number,
2383 		orientation, and
2384 		precalculated sizes of each child type.
2385 
2386         Called from:
2387 	    LayoutChildren(), when performing complete relayout
2388 	    ConstraintSetValues(), when child page number changes
2389 	    GotoPage(), when notebook.current_page_number changes
2390 
2391 -----------------------------------------------------------------------------*/
2392 static void
LayoutPages(XmNotebookWidget nb,Widget instigator)2393 LayoutPages (
2394     XmNotebookWidget nb,
2395     Widget instigator)
2396 {
2397     XmNotebookConstraint nc;
2398     Widget child;
2399     int i;
2400     Dimension x, y, x1, y1, x2;
2401 
2402     /* get the page's x, y position */
2403     x = nb->notebook.margin_width + nb->notebook.shadow_thickness + 1;
2404     y = nb->notebook.margin_height + nb->notebook.shadow_thickness + 1;
2405     if (nb->notebook.binding_pos == LEFT)
2406 	x += nb->notebook.real_binding_width;
2407     else if (nb->notebook.binding_pos == TOP)
2408 	y += nb->notebook.real_binding_width;
2409     if (nb->notebook.major_pos == LEFT)
2410 	x += NB_MAJOR_MAX(nb, nb->notebook.major_width,
2411 	    nb->notebook.major_scroller_width) + nb->notebook.back_page_size;
2412     else if (nb->notebook.major_pos == TOP)
2413 	y += NB_MAJOR_MAX(nb, nb->notebook.major_height,
2414 	    nb->notebook.major_scroller_height) + nb->notebook.back_page_size;
2415     if (nb->notebook.minor_pos == LEFT)
2416 	x += NB_MINOR_MAX(nb, nb->notebook.minor_width,
2417 	    nb->notebook.minor_scroller_width) + nb->notebook.back_page_size;
2418     else if (nb->notebook.minor_pos == TOP)
2419 	y += NB_MINOR_MAX(nb, nb->notebook.minor_height,
2420 	    nb->notebook.minor_scroller_height) + nb->notebook.back_page_size;
2421 
2422     /* get the status area and the page scroller's position */
2423     y1 = y + nb->notebook.page_height + nb->notebook.margin_height;
2424     if (nb->notebook.back_page_pos == XmTOP_RIGHT ||
2425 	nb->notebook.back_page_pos == XmBOTTOM_RIGHT)
2426     {
2427 	x1 = x;
2428 	x2 = x + nb->notebook.page_width - nb->notebook.scroller_width;
2429     }
2430     else
2431     {
2432         x1 = x + nb->notebook.page_width - nb->notebook.status_width;
2433 	x2 = x;
2434     }
2435 
2436     /* resize pages & status */
2437     for (i = 0; i < nb->composite.num_children; i++)
2438 	{
2439 	child = nb->composite.children[i];
2440 	nc = NotebookConstraint(child);
2441         if (   NB_IS_CHILD_PAGE(nc->child_type)
2442 	    || NB_IS_CHILD_STATUS(nc->child_type) )
2443 	    {
2444 	    if (nc->active &&
2445 		nc->page_number == nb->notebook.current_page_number)
2446 		{
2447 		if (NB_IS_CHILD_PAGE(nc->child_type))
2448 		    ShowChild(child, instigator, x, y,
2449 				nb->notebook.page_width,
2450 				nb->notebook.page_height);
2451 		else if (NB_IS_CHILD_STATUS(nc->child_type))
2452 		    ShowChild(child, instigator, x1, y1,
2453 				nb->notebook.status_width,
2454 				nb->notebook.status_height);
2455 		}
2456 	    else
2457 		{
2458 	        /* This is to get HideChild to function properly on
2459 		   widgets such as Form which fail to properly set
2460 		   default width/height to a non-zero value */
2461 		if (nb->notebook.first_change_managed
2462 		    && (!XtWidth(child) && !XtHeight(child)))
2463 		   {
2464 		   XtWidth(child) = 10;
2465 		   XtHeight(child) = 10;
2466 		   HideChild(child, instigator);
2467 		   XtWidth(child) = 0;
2468                    XtHeight(child) = 0;
2469 		   }
2470 		else
2471 		   HideChild(child, instigator);
2472 		}
2473 	    }
2474 	}
2475 
2476     /* Show the page scroller */
2477     if (nb->notebook.scroller != NULL)
2478     {
2479 	child = nb->notebook.scroller;
2480 	ShowChild(child, instigator, x2, y1,
2481 			nb->notebook.scroller_width,
2482 			nb->notebook.scroller_height);
2483     }
2484 }
2485 
2486 
2487 /*- LayoutMajorTabs ---------------------------------------------------------
2488 
2489         Function to layout major tabs
2490 
2491 -----------------------------------------------------------------------------*/
2492 static void
LayoutMajorTabs(XmNotebookWidget nb,Widget instigator)2493 LayoutMajorTabs (
2494     XmNotebookWidget nb,
2495     Widget instigator)
2496 {
2497     XmNotebookConstraint nc;		/* constraint pointer */
2498     Widget child;			/* a major tab widget */
2499     Widget join_child = NULL;		/* top major and joinSide tab */
2500     int x, y, tmpx, tmpy;		/* tab's geometry */
2501     int tab_count;			/* # of tabs shown */
2502     int margin_w, margin_h;		/* temporary margin value */
2503     int sx1, sy1, sx2, sy2;		/* tab scroller position */
2504     int fixed;				/* back page fixed position */
2505     int limit;				/* the last possible position */
2506     int delta, spacing;			/* major tab spacing */
2507     int first_major, top_major;		/* page# of first and top major tabs */
2508     unsigned char prev, next;		/* for tab scroller arrow direction */
2509     Boolean gray_prev, gray_next;	/* True if need to gray out scrollers */
2510     int i;
2511     unsigned char direction;
2512     int total_major_tabs, top_tab_count = 0, current_tab = 0;
2513     /*
2514      * Initialize
2515      */
2516     first_major = nb->notebook.first_major ?
2517 		NotebookConstraint(nb->notebook.first_major)->page_number :
2518 		nb->notebook.first_page_number - 1;
2519     top_major = nb->notebook.top_major ?
2520 		NotebookConstraint(nb->notebook.top_major)->page_number :
2521 		nb->notebook.first_page_number - 1;
2522     gray_prev = gray_next = True;
2523     sx1 = sy1 = sx2 = sy2 = 0;
2524 
2525     /*
2526      * Determine tab margin spacing and tab staggering
2527      */
2528     spacing = MAX(nb->notebook.major_spacing, nb->notebook.shadow_thickness);
2529     delta = nb->notebook.back_page_size / nb->notebook.real_back_page_number;
2530 
2531     /*
2532      * Determine tab positions
2533      */
2534     if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
2535         nb->notebook.orientation == XmHORIZONTAL)
2536 	{
2537         /* set starting position */
2538         x = nb->notebook.real_binding_width + nb->notebook.frame_width;
2539 	y = nb->notebook.back_page_size;
2540 	fixed = x + nb->notebook.back_page_size;
2541 	limit = nb->notebook.frame_height -
2542 		nb->notebook.major_height -
2543 		nb->notebook.shadow_thickness;
2544         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2545 	    {
2546 	    sx1 = sx2 = fixed;
2547             sy1 = y;
2548             sy2 = sy1 + nb->notebook.frame_height -
2549 		  nb->notebook.major_scroller_height;
2550 	    limit = nb->notebook.frame_height -
2551 		    MAX(0, (int)(nb->notebook.major_scroller_height -
2552 			   nb->notebook.back_page_size)) -
2553 		    nb->notebook.major_height -
2554 		    nb->notebook.shadow_thickness;
2555 	    y += nb->notebook.major_scroller_height + spacing;
2556 	    }
2557 	else
2558 	    y += nb->notebook.shadow_thickness;
2559 
2560         /* set arrow direction resource */
2561         prev = XmARROW_UP;
2562         next = XmARROW_DOWN;
2563 	}
2564     else if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
2565 	     nb->notebook.orientation == XmVERTICAL)
2566 	{
2567         /* set starting position */
2568         x = nb->notebook.back_page_size;
2569         y = nb->notebook.real_binding_width + nb->notebook.frame_height;
2570         fixed = y + nb->notebook.back_page_size;
2571         limit = nb->notebook.frame_width -
2572                 nb->notebook.major_width -
2573 		nb->notebook.shadow_thickness;
2574         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2575 	    {
2576             sy1 = sy2 = fixed;
2577             sx1 = x;
2578             sx2 = sx1 + nb->notebook.frame_width -
2579  		  nb->notebook.major_scroller_width;
2580             limit = nb->notebook.frame_width -
2581 		    MAX(0, (int)(nb->notebook.major_scroller_width -
2582 			   nb->notebook.back_page_size)) -
2583 		    nb->notebook.major_width -
2584 		    nb->notebook.shadow_thickness;
2585             x += nb->notebook.major_scroller_width + spacing;
2586 	    }
2587 	else
2588 	    x += nb->notebook.shadow_thickness;
2589 
2590         /* set arrow direction resource */
2591         prev = XmARROW_LEFT;
2592         next = XmARROW_RIGHT;
2593 	}
2594     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
2595 	     nb->notebook.orientation == XmHORIZONTAL)
2596 	{
2597         /* set starting position */
2598 	margin_w = NB_MAJOR_MAX(nb, nb->notebook.major_width,
2599 				nb->notebook.major_scroller_width) +1;
2600         x = margin_w + nb->notebook.back_page_size - nb->notebook.major_width;
2601         y = nb->notebook.back_page_size;
2602         fixed = x - nb->notebook.back_page_size;
2603         limit = nb->notebook.frame_height -
2604                 nb->notebook.major_height -
2605 		nb->notebook.shadow_thickness;
2606         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2607 	    {
2608             sx1 = sx2 = margin_w - nb->notebook.minor_scroller_width;
2609             sy1 = y;
2610             sy2 = y + nb->notebook.frame_height -
2611 		  nb->notebook.major_scroller_height;
2612             limit = nb->notebook.frame_height -
2613 		    MAX(0, (int)(nb->notebook.major_scroller_height -
2614 			   nb->notebook.back_page_size)) -
2615 		    nb->notebook.major_height -
2616 		    nb->notebook.shadow_thickness;
2617             y += nb->notebook.major_scroller_height + spacing;
2618 	    }
2619 	else
2620 	    y += nb->notebook.shadow_thickness;
2621 
2622         /* set arrow direction resource */
2623         prev = XmARROW_UP;
2624         next = XmARROW_DOWN;
2625 	}
2626     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
2627              nb->notebook.orientation == XmVERTICAL)
2628 	{
2629         /* set starting position */
2630 	margin_w = NB_MINOR_MAX(nb, nb->notebook.minor_width,
2631 		   	 	nb->notebook.minor_scroller_width);
2632         x = margin_w + nb->notebook.frame_width - nb->notebook.major_width;
2633         y = nb->notebook.real_binding_width + nb->notebook.frame_height;
2634         fixed = y + nb->notebook.back_page_size;
2635         limit = margin_w + nb->notebook.back_page_size +
2636 		nb->notebook.shadow_thickness;
2637         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2638 	    {
2639             sy1 = sy2 = fixed;
2640 	    sx1 = margin_w + nb->notebook.frame_width -
2641 		  nb->notebook.major_scroller_width;
2642 	    sx2 = margin_w;
2643             limit = margin_w +
2644 		    MAX(nb->notebook.back_page_size,
2645 		        nb->notebook.major_scroller_width) +
2646 		    nb->notebook.shadow_thickness;
2647             x -= nb->notebook.major_scroller_width + spacing;
2648 	    }
2649 	else
2650 	    x -= spacing;
2651 
2652 	/* set arrow direction resource */
2653 	prev = XmARROW_RIGHT;
2654 	next = XmARROW_LEFT;
2655 	}
2656     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
2657         nb->notebook.orientation == XmHORIZONTAL)
2658 	{
2659         /* set starting position */
2660 	margin_h = NB_MINOR_MAX(nb, nb->notebook.minor_height,
2661 				nb->notebook.minor_scroller_height);
2662         x = nb->notebook.real_binding_width + nb->notebook.frame_width;
2663         y = margin_h + nb->notebook.frame_height - nb->notebook.major_height;
2664         fixed = x + nb->notebook.back_page_size;
2665         limit = margin_h + nb->notebook.back_page_size +
2666 		nb->notebook.shadow_thickness;
2667         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2668 	    {
2669             sx1 = sx2 = fixed;
2670             sy1 = margin_h + nb->notebook.frame_height -
2671 		  nb->notebook.minor_scroller_height;
2672             sy2 = margin_h;
2673             limit = margin_h +
2674 		    MAX(nb->notebook.back_page_size,
2675 		        nb->notebook.major_scroller_height) +
2676 		    nb->notebook.shadow_thickness;
2677             y -= nb->notebook.major_scroller_height + spacing;
2678 	    }
2679 	else
2680 	    y -= spacing;
2681 
2682         /* set arrow direction resource */
2683         prev = XmARROW_DOWN;
2684         next = XmARROW_UP;
2685 	}
2686     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
2687              nb->notebook.orientation == XmVERTICAL)
2688 	{
2689         /* set starting position */
2690 	margin_h = NB_MAJOR_MAX(nb, nb->notebook.major_height,
2691 		nb->notebook.major_scroller_height) +1;
2692         x = nb->notebook.back_page_size;
2693         y = margin_h + nb->notebook.back_page_size - nb->notebook.major_height;
2694         fixed = margin_h - nb->notebook.major_height;
2695         limit = nb->notebook.frame_width -
2696 		nb->notebook.major_width -
2697 		nb->notebook.shadow_thickness;
2698         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2699 	    {
2700             sy1 = sy2 = margin_h - nb->notebook.major_scroller_height;
2701             sx1 = x;
2702             sx2 = nb->notebook.frame_width +
2703 		  nb->notebook.back_page_size -
2704 		  nb->notebook.major_scroller_width;
2705             limit = nb->notebook.frame_width -
2706 		    MAX(0, (int)(nb->notebook.major_scroller_width -
2707 			   nb->notebook.back_page_size)) -
2708 		    nb->notebook.major_width -
2709 		    nb->notebook.shadow_thickness;
2710             x += nb->notebook.major_scroller_width + spacing;
2711 	    }
2712 	else
2713 	    x += nb->notebook.shadow_thickness;
2714 
2715         /* set arrow direction resource */
2716         prev = XmARROW_LEFT;
2717         next = XmARROW_RIGHT;
2718 	}
2719     else if (nb->notebook.back_page_pos == XmTOP_LEFT &&
2720              nb->notebook.orientation == XmHORIZONTAL)
2721 	{
2722         /* set starting position */
2723         margin_w = NB_MAJOR_MAX(nb, nb->notebook.major_width,
2724 				nb->notebook.major_scroller_width) +1;
2725 	margin_h = NB_MINOR_MAX(nb, nb->notebook.minor_height,
2726 				nb->notebook.minor_scroller_height) +1;
2727         x = margin_w + nb->notebook.back_page_size - nb->notebook.major_width;
2728         y = margin_h + nb->notebook.frame_height - nb->notebook.major_height;
2729         fixed = x - nb->notebook.back_page_size;
2730         limit = margin_h +
2731 		nb->notebook.back_page_size +
2732 		nb->notebook.shadow_thickness;
2733         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2734 	    {
2735             sx1 = sx2 = margin_w - nb->notebook.minor_scroller_width;
2736             sy1 = margin_h + nb->notebook.frame_height -
2737 		nb->notebook.major_scroller_height;
2738             sy2 = margin_h;
2739             limit = margin_h +
2740 		    MAX(nb->notebook.back_page_size,
2741 		        nb->notebook.major_scroller_height) +
2742 		    nb->notebook.shadow_thickness;
2743             y -= nb->notebook.major_scroller_height + spacing;
2744 	    }
2745 	else
2746 	    y -= spacing;
2747 
2748         /* set arrow direction resource */
2749         prev = XmARROW_DOWN;
2750         next = XmARROW_UP;
2751 	}
2752     else
2753 	{
2754         /* set starting position */
2755         margin_w = NB_MINOR_MAX(nb, nb->notebook.minor_width,
2756 				nb->notebook.minor_scroller_width) +1;
2757 	margin_h = NB_MAJOR_MAX(nb, nb->notebook.major_height,
2758 				nb->notebook.major_scroller_height) +1;
2759         x = margin_w + nb->notebook.frame_width - nb->notebook.major_width;
2760         y = margin_h + nb->notebook.back_page_size - nb->notebook.major_height;
2761         fixed = y - nb->notebook.back_page_size;
2762         limit = margin_w + nb->notebook.back_page_size +
2763 		nb->notebook.shadow_thickness;
2764         if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
2765 	    {
2766 	    sy1 = sy2 = margin_h - nb->notebook.major_scroller_height;
2767 	    sx1 = margin_w + nb->notebook.frame_width -
2768 		nb->notebook.major_scroller_width;
2769             sx2 = margin_w;
2770             limit = margin_w +
2771 		    MAX(nb->notebook.back_page_size,
2772 		        nb->notebook.major_scroller_width) +
2773 		    nb->notebook.shadow_thickness;
2774             x -= nb->notebook.major_scroller_width + spacing;
2775 	    }
2776 	else
2777 	    x -= spacing;
2778 
2779         /* set arrow direction resource */
2780         prev = XmARROW_RIGHT;
2781         next = XmARROW_LEFT;
2782 	}
2783 
2784 
2785 
2786     /*
2787      * Deal with previous top and current top tab shadowing
2788      */
2789 
2790     /* Inform old top major to restore shadow_thickness */
2791     if (nb->notebook.old_top_major != NULL
2792 	&& nb->notebook.old_top_major != nb->notebook.top_major)
2793 	{
2794 	/* Protect against geometry requests during join changes */
2795 	nb->notebook.in_setshadow = True;
2796 
2797 	/* Inform join-aware tab else restore shadow thickness */
2798 	if (!UpdateJoinSide(nb, nb->notebook.old_top_major,
2799 			    XmMAJOR_TAB, (Dimension)0))
2800 	    {
2801 	    /* Hide the old top major shadow */
2802 	    HideShadowedTab(nb, nb->notebook.old_top_major);
2803 
2804 	    /* Restore child shadow thickness */
2805 	    XtVaSetValues(nb->notebook.old_top_major,
2806 		    XmNshadowThickness, nb->notebook.major_shadow_thickness,
2807 		    NULL);
2808 	    }
2809 
2810 	/* Release protection against geometry requests */
2811 	nb->notebook.in_setshadow = False;
2812 	}
2813 
2814 
2815     /* Store & set new top major's shadow */
2816     if (nb->notebook.top_major != NULL)
2817 	{
2818 	/* Hide the top major shadow, as it may be moving (shown or hidden) */
2819 	HideShadowedTab(nb, nb->notebook.top_major);
2820 
2821 	/* Protect against geometry requests during join changes */
2822 	nb->notebook.in_setshadow = True;
2823 
2824 	/* Set shadow thickness of new top tab */
2825 	if (!UpdateJoinSide(nb, nb->notebook.top_major,
2826 			XmMAJOR_TAB, nb->notebook.shadow_thickness))
2827 	    {
2828 	    /* Save shadow_thickness of top tab, unless we already have */
2829 	    if (nb->notebook.top_major != nb->notebook.major_shadow_child)
2830 		{
2831 		XtVaGetValues(nb->notebook.top_major,
2832 		    XmNshadowThickness, &(nb->notebook.major_shadow_thickness),
2833 		    NULL);
2834 		nb->notebook.major_shadow_child = nb->notebook.top_major;
2835 		}
2836 	    else
2837 	      {
2838 		/* CR 9903: The application may have set shadow_thickness. */
2839 		Dimension current = 0;
2840 		XtVaGetValues(nb->notebook.top_major,
2841 			      XmNshadowThickness, &current,
2842 			      NULL);
2843 		if (current != 0)
2844 		  nb->notebook.major_shadow_thickness = current;
2845 	      }
2846 
2847 	    /* Notebook will draw shadow for non-JoinSide trait tabs */
2848 	    XtVaSetValues(nb->notebook.top_major,
2849 		    XmNshadowThickness, 0,
2850 		    NULL);
2851 	    }
2852 	else
2853 	    join_child = nb->notebook.top_major;
2854 
2855 	/* Release protection against geometry requests */
2856 	nb->notebook.in_setshadow = False;
2857 	}
2858     else
2859 	/* There is no top tab so advance to the first back page line */
2860 	{
2861 	if (nb->notebook.major_pos == RIGHT)
2862 	    x += delta;
2863 	else if (nb->notebook.major_pos == LEFT)
2864 	    x -= delta;
2865 	else if (nb->notebook.major_pos == BOTTOM)
2866 	    y += delta;
2867 	else /* if (nb->notebook.major_pos == TOP) */
2868 	    y -= delta;
2869 	}
2870     /*
2871      * FIX for CDExc23791
2872      */
2873     total_major_tabs = 0;
2874     for (i = 0; i < nb->composite.num_children; i++)
2875         {
2876         child = nb->composite.children[i];
2877         nc = NotebookConstraint(child);
2878         if (NB_IS_CHILD_MAJOR(nc->child_type))
2879                 total_major_tabs++;
2880         if ( child == nb->notebook.top_major)
2881                 top_tab_count = total_major_tabs;
2882         }
2883     /*
2884      * Layout major tabs
2885      */
2886     tab_count = 0;
2887     for (i = 0; i < nb->composite.num_children; i++)
2888 	{
2889 	child = nb->composite.children[i];
2890 	nc = NotebookConstraint(child);
2891 
2892         if (NB_IS_CHILD_MAJOR(nc->child_type))
2893 	    {
2894 	    if (!nc->active)
2895 		HideChild(child, instigator);
2896 	    else if (nc->page_number < first_major)
2897 		{
2898 		HideChild(child, instigator);
2899 		gray_prev = False;
2900 		}
2901 	    else if ((nb->notebook.minor_pos == BOTTOM && y > limit)
2902 		     || (nb->notebook.minor_pos == TOP && y < limit)
2903 		     || (nb->notebook.minor_pos == RIGHT && x > limit)
2904 		     || (nb->notebook.minor_pos == LEFT && x < limit))
2905 		{
2906 		HideChild(child, instigator);
2907 		gray_next = False;
2908 		}
2909 	    else
2910 	     {
2911                /* Display the tab */
2912                if (  current_tab < top_tab_count - 1 )
2913                  {
2914                  /*
2915                   * FIX for CDExc23791
2916                   */
2917                  if (nb->notebook.orientation == XmHORIZONTAL)
2918                    {
2919                    if (nb->notebook.major_pos == RIGHT)
2920                      tmpx = x + ( total_major_tabs + 1 - top_tab_count + current_tab) * delta;
2921                    else
2922                      tmpx = x - ( total_major_tabs + 1 - top_tab_count + current_tab) * delta;
2923                    tmpy = y;
2924                    }
2925                   else
2926                   {
2927                     tmpx = x;
2928                     if (nb->notebook.major_pos == TOP)
2929                       tmpy = y - (total_major_tabs + 1 - top_tab_count + current_tab) * delta;
2930                     else
2931                       tmpy = y + (total_major_tabs + 1 - top_tab_count + current_tab) * delta;
2932                   }
2933                 }
2934               else
2935                 {
2936                 tmpx = x;
2937                 tmpy = y;
2938                 }
2939 
2940 		if (/*(nb->notebook.orientation == XmHORIZONTAL &&
2941 		    nc->page_number < top_major)
2942 		    ||*/ (nb->notebook.major_pos == RIGHT && tmpx > fixed)
2943 		    || (nb->notebook.major_pos == LEFT && tmpx < fixed))
2944 		    {
2945 		    tmpx = fixed;
2946 		    }
2947 		else if (/*(nb->notebook.orientation == XmVERTICAL &&
2948 		     nc->page_number < top_major)
2949 		    ||*/ (nb->notebook.major_pos == BOTTOM && tmpy > fixed)
2950 		    || (nb->notebook.major_pos == TOP && tmpy < fixed))
2951 		    {
2952 		    tmpy = fixed;
2953 		    }
2954 
2955 		/* move joinSide top tab over to align with frame */
2956 		if ((join_child && (join_child == child))
2957 		||  (nb->notebook.top_major
2958 			&& (nb->notebook.top_major == child)))
2959 		    {
2960 		    if (nb->notebook.major_pos == LEFT)
2961 			tmpx = tmpx + nb->notebook.shadow_thickness;
2962 		    else if (nb->notebook.major_pos == RIGHT)
2963 			tmpx = tmpx - nb->notebook.shadow_thickness;
2964 		    else if (nb->notebook.major_pos == TOP)
2965 			tmpy = tmpy + nb->notebook.shadow_thickness;
2966 		    else /* (nb->notebook.major_pos == BOTTOM) */
2967 			tmpy = tmpy - nb->notebook.shadow_thickness;
2968 		    }
2969 
2970 		/* Make tab visible */
2971 		ShowChild(child, instigator, tmpx, tmpy,
2972 			    nb->notebook.major_width,
2973 			    nb->notebook.major_height);
2974 		tab_count++;
2975                 /* Calculate the next position */
2976 		if (nb->notebook.minor_pos == BOTTOM)
2977                     y += nb->notebook.major_height + spacing;
2978 		else if (nb->notebook.minor_pos == TOP)
2979 		    y -= nb->notebook.major_height + spacing;
2980 		else if (nb->notebook.minor_pos == RIGHT)
2981                     x += nb->notebook.major_width + spacing;
2982 		else /* (nb->notebook.minor_pos == LEFT) */
2983 		    x -= nb->notebook.major_width + spacing;
2984 
2985 		}
2986 
2987             /* to the next back page line */
2988 	    if (nc->page_number >= top_major)
2989 		{
2990 		if (nb->notebook.major_pos == RIGHT)
2991                     x += delta;
2992 		else if (nb->notebook.major_pos == LEFT)
2993 		    x -= delta;
2994 		else if (nb->notebook.major_pos == BOTTOM)
2995 		    y += delta;
2996 		else
2997 		    y -= delta;
2998 		}
2999 		current_tab++;
3000 	} /* if */
3001     } /* for */
3002 
3003 
3004     /*
3005      * Display the tab scrolling tab, if neccessary
3006      */
3007     if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller) && tab_count)
3008 	{
3009 
3010 	/* set scroller's arrow directions */
3011 	XtVaGetValues(nb->notebook.prev_major,
3012 	     XmNarrowDirection, &direction, NULL);
3013 	if (direction != prev)
3014              XtVaSetValues(nb->notebook.prev_major,
3015                 XmNarrowDirection, prev, NULL);
3016 	XtVaGetValues(nb->notebook.next_major,
3017 	     XmNarrowDirection, &direction, NULL);
3018 	if (direction != next)
3019            XtVaSetValues(nb->notebook.next_major,
3020              XmNarrowDirection, next, NULL);
3021 
3022 	/* Gray out scrollers, if necessary */
3023 	if (gray_prev)
3024 	    XtSetSensitive(nb->notebook.prev_major, False);
3025 	else
3026 	    XtSetSensitive(nb->notebook.prev_major, True);
3027 
3028 	if (gray_next)
3029 	    XtSetSensitive(nb->notebook.next_major, False);
3030 	else
3031 	    XtSetSensitive(nb->notebook.next_major, True);
3032 
3033 	/* show the scrollers */
3034         ShowChild(nb->notebook.prev_major, instigator, sx1, sy1,
3035 			nb->notebook.major_scroller_width,
3036 			nb->notebook.major_scroller_height);
3037         ShowChild(nb->notebook.next_major, instigator, sx2, sy2,
3038 			nb->notebook.major_scroller_width,
3039 			nb->notebook.major_scroller_height);
3040 	}
3041     else
3042 	{
3043         HideChild(nb->notebook.prev_major, instigator);
3044         HideChild(nb->notebook.next_major, instigator);
3045 	}
3046 }
3047 
3048 
3049 /*- LayoutMinorTabs ---------------------------------------------------------
3050 
3051         Function to layout minor tabs
3052 
3053 -----------------------------------------------------------------------------*/
3054 static void
LayoutMinorTabs(XmNotebookWidget nb,Widget instigator)3055 LayoutMinorTabs (
3056     XmNotebookWidget nb,
3057     Widget instigator)
3058 {
3059     XmNotebookConstraint nc;		/* constraint pointer */
3060     Widget child;			/* a major tab widget */
3061     Widget join_child = NULL;		/* top minor and joinSide tab */
3062     int x, y, tmpx, tmpy;		/* tab's geometry */
3063     int tab_count;                      /* # of tabs shown */
3064     int backpage_h;			/* temporary backpage value */
3065     int margin_w, margin_h;		/* temporary margin value */
3066     int sx1, sy1, sx2, sy2;		/* tab scroller position */
3067     int fixed;				/* back page fixed position */
3068     int limit;				/* the last possible position */
3069     int spacing;			/* major tab spacing */
3070     int status;				/* minor tab drawing status */
3071     int top_major;			/* page# of the top major tab */
3072     int first_minor, top_minor;		/* page# of first and top minor tabs */
3073     unsigned char prev, next;		/* for tab scroller arrow direction */
3074     Boolean gray_prev, gray_next;	/* True if need to gray out scrollers */
3075     int i;
3076     unsigned char direction;
3077     int offset = 0;
3078     /*
3079      * Initialize
3080      */
3081     top_major = nb->notebook.top_major
3082 		? NotebookConstraint(nb->notebook.top_major)->page_number
3083 		: nb->notebook.first_page_number - 1;
3084     first_minor = nb->notebook.first_minor
3085 		? NotebookConstraint(nb->notebook.first_minor)->page_number
3086 		: nb->notebook.first_page_number - 1;
3087     top_minor = nb->notebook.top_minor
3088 		? NotebookConstraint(nb->notebook.top_minor)->page_number
3089 		: nb->notebook.first_page_number - 1;
3090     gray_prev = gray_next = True;
3091     sx1 = sy1 = sx2 = sy2 = 0;
3092 
3093     if ( nb->notebook.shadow_thickness == 0 )
3094        offset = 1;
3095 
3096     /*
3097      * Determine tap spacing
3098      */
3099     spacing = MAX(nb->notebook.minor_spacing, nb->notebook.shadow_thickness);
3100 
3101     /*
3102      * Determine tab positions
3103      */
3104     if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT
3105         && nb->notebook.orientation == XmHORIZONTAL)
3106 	{
3107         /* set starting position */
3108         x = MAX((nb->notebook.real_binding_width + 1 + offset),
3109 		nb->notebook.back_page_size);
3110 	y = nb->notebook.frame_height;
3111 	fixed = y + NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3112 	limit = nb->notebook.real_binding_width +
3113 		nb->notebook.frame_width -
3114 		nb->notebook.minor_width -
3115 		nb->notebook.shadow_thickness;
3116         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3117 	    {
3118 	    sy1 = sy2 = y + nb->notebook.back_page_size;
3119 	    sx1 = x;
3120 	    sx2 = nb->notebook.real_binding_width +
3121 		  nb->notebook.frame_width +
3122 		  nb->notebook.back_page_size -
3123 		  nb->notebook.minor_scroller_width;
3124 	    limit = nb->notebook.real_binding_width +
3125 		    nb->notebook.frame_width -
3126 		    nb->notebook.minor_width -
3127 		    nb->notebook.shadow_thickness -
3128 		    MAX(0, (int)(nb->notebook.minor_scroller_width -
3129 			   nb->notebook.back_page_size));
3130 	    x += nb->notebook.minor_scroller_width + spacing;
3131 	    }
3132 	else
3133 	    x += nb->notebook.shadow_thickness;
3134 
3135 	/* set arrow direction resource */
3136 	prev = XmARROW_LEFT;
3137 	next = XmARROW_RIGHT;
3138 	}
3139     else if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT
3140 	     && nb->notebook.orientation == XmVERTICAL)
3141 	{
3142         /* set starting position */
3143 	backpage_h = 1;
3144 	if (nb->notebook.back_page_size > nb->notebook.real_binding_width)
3145 	    backpage_h = nb->notebook.back_page_size -
3146 			 nb->notebook.real_binding_width;
3147         x = nb->notebook.frame_width;
3148         y = nb->notebook.real_binding_width + backpage_h + offset;
3149         fixed = x + NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3150         limit = nb->notebook.real_binding_width +
3151 		nb->notebook.frame_height -
3152 		nb->notebook.minor_height -
3153 		nb->notebook.shadow_thickness;
3154         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3155 	    {
3156             sx1 = sx2 = x + nb->notebook.back_page_size;
3157             sy1 = y;
3158             sy2 = nb->notebook.real_binding_width +
3159 		  nb->notebook.frame_height +
3160 		  nb->notebook.back_page_size -
3161 		  nb->notebook.minor_scroller_height;
3162             limit = nb->notebook.real_binding_width +
3163 		    nb->notebook.frame_height -
3164 		    MAX(0, (int)(nb->notebook.minor_scroller_height -
3165 			   nb->notebook.back_page_size)) -
3166 		    nb->notebook.minor_height -
3167 		    nb->notebook.shadow_thickness;
3168             y += nb->notebook.minor_scroller_height + spacing;
3169 	    }
3170 	else
3171 	    y += nb->notebook.shadow_thickness;
3172 
3173         /* set arrow direction resource */
3174         prev = XmARROW_UP;
3175         next = XmARROW_DOWN;
3176 	}
3177     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT
3178 	     && nb->notebook.orientation == XmHORIZONTAL)
3179 	{
3180         /* set starting position */
3181 	margin_w = NB_MAJOR_MAX(nb, nb->notebook.major_width,
3182 				nb->notebook.major_scroller_width);
3183         x = margin_w +
3184 	    nb->notebook.back_page_size +
3185 	    nb->notebook.frame_width -
3186 	    MAX(0, (int)(nb->notebook.back_page_size -
3187 		   nb->notebook.real_binding_width)) -
3188 	    nb->notebook.minor_width - offset;
3189         y = nb->notebook.frame_height;
3190         fixed = y + NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3191 	limit = margin_w +
3192 		nb->notebook.back_page_size +
3193 		nb->notebook.shadow_thickness;
3194         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3195 	    {
3196             sy1 = sy2 = y + nb->notebook.back_page_size;
3197             sx1 = margin_w + nb->notebook.back_page_size +
3198 	 	  nb->notebook.frame_width -
3199 		  MAX(0, (int)(nb->notebook.back_page_size -
3200 		         nb->notebook.real_binding_width)) -
3201 		  nb->notebook.minor_scroller_width;
3202             sx2 = margin_w;
3203             limit = margin_w +
3204 		    MAX(nb->notebook.minor_scroller_width,
3205 			nb->notebook.back_page_size) +
3206 		    nb->notebook.shadow_thickness;
3207             x -= nb->notebook.minor_scroller_width + spacing;
3208 	    }
3209 	else
3210 	    x -= nb->notebook.shadow_thickness;
3211 
3212         /* set arrow direction resource */
3213         prev = XmARROW_RIGHT;
3214         next = XmARROW_LEFT;
3215 	}
3216     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT
3217              && nb->notebook.orientation == XmVERTICAL)
3218 	{
3219         /* set starting position */
3220 	margin_w = NB_MINOR_MAX(nb, nb->notebook.minor_width,
3221 				nb->notebook.minor_scroller_width) +1;
3222 	x = margin_w + nb->notebook.back_page_size - nb->notebook.minor_width;
3223         y = MAX((nb->notebook.real_binding_width + 1 + offset),
3224 		nb->notebook.back_page_size);
3225 	fixed = margin_w +
3226 		NB_MINOR_TAB_STEP(nb->notebook.back_page_size) -
3227 		nb->notebook.minor_width;
3228         limit = nb->notebook.real_binding_width +
3229 		nb->notebook.frame_height -
3230 		nb->notebook.minor_height -
3231 		nb->notebook.shadow_thickness;
3232         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3233 	    {
3234             sx1 = sx2 = margin_w - nb->notebook.minor_scroller_width;
3235             sy1 = y;
3236             sy2 = nb->notebook.real_binding_width +
3237 		  nb->notebook.frame_height +
3238 		  nb->notebook.back_page_size -
3239 		  nb->notebook.minor_scroller_height;
3240             limit = nb->notebook.real_binding_width +
3241 		    nb->notebook.frame_height -
3242 		    MAX(0, (int)(nb->notebook.minor_scroller_height -
3243 			   nb->notebook.back_page_size)) -
3244 		    nb->notebook.minor_height -
3245 		    nb->notebook.shadow_thickness;
3246             y += nb->notebook.minor_scroller_height + spacing;
3247 	    }
3248 	else
3249 	    y += nb->notebook.shadow_thickness;
3250 
3251         /* set arrow direction resource */
3252         prev = XmARROW_UP;
3253         next = XmARROW_DOWN;
3254 	}
3255     else if (nb->notebook.back_page_pos == XmTOP_RIGHT
3256         && nb->notebook.orientation == XmHORIZONTAL)
3257 	{
3258         /* set starting position */
3259         margin_h = NB_MINOR_MAX(nb, nb->notebook.minor_height,
3260 				nb->notebook.minor_scroller_height) + 1;
3261         x = MAX((nb->notebook.real_binding_width + 1 + offset),
3262 		nb->notebook.back_page_size);
3263         y = margin_h + nb->notebook.back_page_size - nb->notebook.minor_height;
3264         fixed = margin_h + NB_MINOR_TAB_STEP(nb->notebook.back_page_size) -
3265 		nb->notebook.minor_height;
3266         limit = nb->notebook.real_binding_width +
3267 		nb->notebook.frame_width -
3268 		nb->notebook.minor_width -
3269 		nb->notebook.shadow_thickness;
3270         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3271 	    {
3272             sy1 = sy2 = margin_h - nb->notebook.minor_scroller_height;
3273             sx1 = x;
3274             sx2 = nb->notebook.real_binding_width +
3275 		  nb->notebook.frame_width +
3276 		  nb->notebook.back_page_size -
3277 		  nb->notebook.minor_scroller_width;
3278             limit = nb->notebook.real_binding_width +
3279 		    nb->notebook.frame_width -
3280 		    MAX(0, (int)(nb->notebook.minor_scroller_width -
3281 			   nb->notebook.back_page_size)) -
3282 		    nb->notebook.minor_width -
3283 		    nb->notebook.shadow_thickness;
3284 	    x += nb->notebook.minor_scroller_width + spacing;
3285 	    }
3286 	else
3287 	    x += nb->notebook.shadow_thickness;
3288 
3289 	/* set arrow direction resource */
3290 	prev = XmARROW_LEFT;
3291 	next = XmARROW_RIGHT;
3292 	}
3293     else if (nb->notebook.back_page_pos == XmTOP_RIGHT
3294              && nb->notebook.orientation == XmVERTICAL)
3295 	{
3296         /* set starting position */
3297 	backpage_h = 0;
3298 	if (nb->notebook.back_page_size > nb->notebook.real_binding_width)
3299 	    backpage_h = nb->notebook.back_page_size -
3300 			 nb->notebook.real_binding_width;
3301 	margin_h = NB_MAJOR_MAX(nb, nb->notebook.major_height,
3302 				nb->notebook.major_scroller_height);
3303         x = nb->notebook.frame_width;
3304         y = margin_h + nb->notebook.back_page_size +
3305 		nb->notebook.frame_height -
3306 		nb->notebook.minor_height - backpage_h - offset;
3307         fixed = x + NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3308         limit = margin_h + nb->notebook.back_page_size +
3309 		nb->notebook.shadow_thickness;
3310         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3311 	    {
3312             sx1 = sx2 = x + nb->notebook.back_page_size;
3313             sy1 = margin_h + nb->notebook.back_page_size +
3314 		  nb->notebook.frame_height -
3315 		  nb->notebook.minor_scroller_height - backpage_h;
3316             sy2 = margin_h;
3317             limit = margin_h +
3318 		    MAX(nb->notebook.back_page_size,
3319 		        nb->notebook.minor_scroller_height) +
3320 		    nb->notebook.shadow_thickness;
3321             y -= (nb->notebook.minor_scroller_height + spacing);
3322 	    }
3323 	else
3324 	    y -= nb->notebook.shadow_thickness;
3325 
3326         /* set arrow direction resource */
3327         prev = XmARROW_DOWN;
3328         next = XmARROW_UP;
3329 	}
3330     else if (nb->notebook.back_page_pos == XmTOP_LEFT
3331              && nb->notebook.orientation == XmHORIZONTAL)
3332 	{
3333         /* set starting position */
3334         margin_w = NB_MAJOR_MAX(nb, nb->notebook.major_width,
3335 				nb->notebook.major_scroller_width);
3336         margin_h = NB_MINOR_MAX(nb, nb->notebook.minor_height,
3337 				    nb->notebook.minor_scroller_height) +1;
3338         x = margin_w +
3339 	    nb->notebook.back_page_size +
3340 	    nb->notebook.frame_width -
3341 	    MAX(0, (int)(nb->notebook.back_page_size -
3342 		   nb->notebook.real_binding_width)) -
3343 	    nb->notebook.minor_width - offset;
3344         y = margin_h + nb->notebook.back_page_size - nb->notebook.minor_height;
3345         fixed = y - NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3346         limit = margin_w +
3347 		nb->notebook.back_page_size +
3348 		nb->notebook.shadow_thickness;
3349         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3350         {
3351             sy1 = sy2 = margin_h - nb->notebook.minor_scroller_height;
3352             sx1 = margin_w +
3353 		  nb->notebook.back_page_size +
3354 		  nb->notebook.frame_width -
3355 		  MAX(0, (int)(nb->notebook.back_page_size -
3356 		         nb->notebook.real_binding_width)) -
3357 		  nb->notebook.minor_scroller_width;
3358 	    sx2 = margin_w;
3359 	    limit = margin_w +
3360 		    MAX(nb->notebook.minor_scroller_width,
3361 			   nb->notebook.back_page_size) +
3362 		    nb->notebook.shadow_thickness;
3363             x -= nb->notebook.minor_scroller_width + spacing;
3364         }
3365 	else
3366 	    x -= nb->notebook.shadow_thickness;
3367 
3368         /* set arrow direction resource */
3369         prev = XmARROW_RIGHT;
3370         next = XmARROW_LEFT;
3371 	}
3372     else /* if (nb->notebook.back_page_pos == XmTOP_LEFT
3373 	    && nb->notebook.orientation == XmVERTICAL) */
3374 	{
3375         /* set starting position */
3376         margin_w = NB_MINOR_MAX(nb, nb->notebook.minor_width,
3377 				nb->notebook.minor_scroller_width) + 1;
3378         margin_h = NB_MAJOR_MAX(nb, nb->notebook.major_height,
3379 				nb->notebook.major_scroller_height);
3380         x = margin_w + nb->notebook.back_page_size - nb->notebook.minor_width;
3381         y = margin_h +
3382 	    nb->notebook.back_page_size +
3383 	    nb->notebook.frame_height -
3384 	    nb->notebook.minor_height -
3385 	    MAX(0, (int)(nb->notebook.back_page_size -
3386 		   nb->notebook.real_binding_width)) - offset;
3387         fixed = x - NB_MINOR_TAB_STEP(nb->notebook.back_page_size);
3388         limit = margin_h + nb->notebook.back_page_size +
3389 		nb->notebook.shadow_thickness;
3390         if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller))
3391 	    {
3392             sx1 = sx2 = margin_w - nb->notebook.minor_scroller_width;
3393             sy1 = margin_h +
3394 		  nb->notebook.back_page_size +
3395 		  nb->notebook.frame_height -
3396 		  MAX(0, (int)(nb->notebook.back_page_size -
3397 		         nb->notebook.real_binding_width)) -
3398 		  nb->notebook.minor_scroller_height;
3399             sy2 = margin_h;
3400             limit = margin_h +
3401 		    MAX(nb->notebook.back_page_size,
3402 		        nb->notebook.minor_scroller_height) +
3403 		    nb->notebook.shadow_thickness;
3404             y -= nb->notebook.minor_scroller_height + spacing;
3405 	    }
3406 	else
3407 	    y -= nb->notebook.shadow_thickness;
3408 
3409         /* set arrow direction resource */
3410         prev = XmARROW_DOWN;
3411         next = XmARROW_UP;
3412 	}
3413 
3414     /*
3415      * Deal with previous top and current top tab shadowing
3416      */
3417 
3418     /* Inform old top minor to restore shadow_thickness */
3419     if (nb->notebook.old_top_minor != NULL
3420 	&& nb->notebook.old_top_minor != nb->notebook.top_minor)
3421         {
3422         /* Protect against geometry requests during join changes */
3423         nb->notebook.in_setshadow = True;
3424 
3425         /* Inform join-aware tab else restore shadow thickness */
3426         if (!UpdateJoinSide(nb, nb->notebook.old_top_minor,
3427 				XmMINOR_TAB, (Dimension)0))
3428 	    {
3429 	    /* Hide the old top minor shadow */
3430 	    HideShadowedTab(nb, nb->notebook.old_top_minor);
3431 
3432 	    /* Restore the old top minor shadow thickness */
3433             XtVaSetValues(nb->notebook.old_top_minor,
3434                     XmNshadowThickness, nb->notebook.minor_shadow_thickness,
3435                     NULL);
3436 	    }
3437 
3438         /* Release protection against geometry requests */
3439         nb->notebook.in_setshadow = False;
3440         }
3441 
3442 
3443     /* Store & set new top minor's shadow */
3444     if (nb->notebook.top_minor != NULL)
3445         {
3446 	/* Hide the top minor shadow, as it may be moving (shown or hidden) */
3447 	HideShadowedTab(nb, nb->notebook.top_minor);
3448 
3449         /* Protect against geometry requests during join changes */
3450         nb->notebook.in_setshadow = True;
3451 
3452         /* Set shadow thickness of new top tab */
3453         if (!UpdateJoinSide(nb, nb->notebook.top_minor,
3454 				XmMINOR_TAB, nb->notebook.shadow_thickness))
3455             {
3456             /* Save shadow_thickness of top tab, unless we already have */
3457 	    if (nb->notebook.top_minor != nb->notebook.minor_shadow_child)
3458 		{
3459 		/* Save shadow_thickness of top tab, unless already saved */
3460 		XtVaGetValues(nb->notebook.top_minor,
3461                     XmNshadowThickness, &(nb->notebook.minor_shadow_thickness),
3462                     NULL);
3463 		nb->notebook.minor_shadow_child = nb->notebook.top_minor;
3464 		}
3465 	    else
3466 	      {
3467 		/* CR 9903: The application may have set shadow_thickness. */
3468 		Dimension current = 0;
3469 		XtVaGetValues(nb->notebook.top_minor,
3470 			      XmNshadowThickness, &current,
3471 			      NULL);
3472 		if (current != 0)
3473 		  nb->notebook.minor_shadow_thickness = current;
3474 	      }
3475 
3476             /* Notebook will draw shadow */
3477             XtVaSetValues(nb->notebook.top_minor,
3478                     XmNshadowThickness, 0,
3479                     NULL);
3480             }
3481 	else
3482 	    join_child = nb->notebook.top_minor;
3483 
3484         /* Release protection against geometry requests */
3485 	nb->notebook.in_setshadow = False;
3486         }
3487 
3488 
3489     /*
3490      * Layout major tabs
3491      */
3492     status = TAB_DRAW;
3493     tab_count = 0;
3494     for (i = 0; i < nb->composite.num_children; i++)
3495 	{
3496 	child = nb->composite.children[i];
3497 	nc = NotebookConstraint(child);
3498 
3499 	if (first_minor < nb->notebook.first_page_number
3500 	    || (nc->active
3501 		&& NB_IS_CHILD_MAJOR(nc->child_type)
3502 		&& (status == TAB_DRAWING || nc->page_number > first_minor)))
3503 	    status = TAB_DRAWN;
3504 
3505         if (NB_IS_CHILD_MINOR(nc->child_type))
3506 	    {
3507             if (!nc->active || status == TAB_DRAWN)
3508                 HideChild(child, instigator);
3509 
3510             else if (nc->page_number < first_minor)
3511 		{
3512 		if (nc->page_number >= top_major)
3513 		    gray_prev = False;
3514                 HideChild(child, instigator);
3515 		}
3516             else if ((nb->notebook.binding_pos == LEFT && x > limit)
3517 		    || (nb->notebook.binding_pos == RIGHT && x < limit)
3518 		    || (nb->notebook.binding_pos == TOP && y > limit)
3519 		    || (nb->notebook.binding_pos == BOTTOM && y < limit))
3520 		{
3521                 gray_next = False;
3522                 HideChild(child, instigator);
3523 		}
3524 	    else
3525 		{
3526                 /* Display the tab */
3527                 status = TAB_DRAWING;
3528 		tmpx = x;
3529 		tmpy = y;
3530                 if (nc->page_number != top_minor)
3531 		    {
3532 		    if (nb->notebook.orientation == XmHORIZONTAL)
3533 			tmpy = fixed;
3534 		    else
3535 			tmpx = fixed;
3536 		    }
3537 
3538 		/* move joinSide top tab over to align with frame */
3539 		if ((join_child && (join_child == child))
3540 		||  (nb->notebook.top_minor
3541 			&& (nb->notebook.top_minor == child)))
3542 		    {
3543 		    if (nb->notebook.minor_pos == LEFT)
3544 			tmpx = tmpx + nb->notebook.shadow_thickness;
3545 		    else if (nb->notebook.minor_pos == RIGHT)
3546 			tmpx = tmpx - nb->notebook.shadow_thickness;
3547 		    else if (nb->notebook.minor_pos == TOP)
3548 			tmpy = tmpy + nb->notebook.shadow_thickness;
3549 		    else if (nb->notebook.minor_pos == BOTTOM)
3550 			tmpy = tmpy - nb->notebook.shadow_thickness;
3551 		    }
3552 
3553 		/* Make tab visible */
3554 		ShowChild(child, instigator, tmpx, tmpy,
3555 			    nb->notebook.minor_width,
3556 			    nb->notebook.minor_height);
3557 		tab_count++;
3558 
3559                 /* Calculate the next position */
3560 		if (nb->notebook.binding_pos == LEFT)
3561 		    x += nb->notebook.minor_width + spacing;
3562 		else if (nb->notebook.binding_pos == RIGHT)
3563 		    x -= nb->notebook.minor_width + spacing;
3564 		else if (nb->notebook.binding_pos == TOP)
3565 		    y += nb->notebook.minor_height + spacing;
3566 		else
3567 		    y -= nb->notebook.minor_height + spacing;
3568 
3569 		}
3570 	    }
3571 	}
3572 
3573 
3574     /* display the tab scrolling tab if neccessary */
3575     if (NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller) && tab_count)
3576 	{
3577 
3578         /* set scroller's arrow directions */
3579         XtVaGetValues(nb->notebook.prev_minor,
3580                 XmNarrowDirection, &direction, NULL);
3581         if (direction != prev)
3582             XtVaSetValues(nb->notebook.prev_minor,
3583                 XmNarrowDirection, prev, NULL);
3584         XtVaGetValues(nb->notebook.next_minor,
3585                 XmNarrowDirection, &direction, NULL);
3586         if (direction != next)
3587             XtVaSetValues(nb->notebook.next_minor,
3588                 XmNarrowDirection, next, NULL);
3589 
3590         /* gray out scrollers if necessary */
3591         if (gray_prev)
3592             XtSetSensitive(nb->notebook.prev_minor, False);
3593         else
3594             XtSetSensitive(nb->notebook.prev_minor, True);
3595         if (gray_next)
3596             XtSetSensitive(nb->notebook.next_minor, False);
3597         else
3598             XtSetSensitive(nb->notebook.next_minor, True);
3599 
3600         /* show the scrollers */
3601         ShowChild(nb->notebook.prev_minor, instigator, sx1, sy1,
3602                         nb->notebook.minor_scroller_width,
3603                         nb->notebook.minor_scroller_height);
3604         ShowChild(nb->notebook.next_minor, instigator, sx2, sy2,
3605                         nb->notebook.minor_scroller_width,
3606                         nb->notebook.minor_scroller_height);
3607 	}
3608     else
3609 	{
3610         HideChild(nb->notebook.prev_minor, instigator);
3611         HideChild(nb->notebook.next_minor, instigator);
3612 	}
3613 }
3614 
3615 
3616 /*- ResetTopPointers --------------------------------------------------------
3617 
3618     Function to calculate and update needed information to perform
3619     layout for major and minor tabs, and the tab scroller.
3620 
3621     Uses instance state:
3622 	notebook.current_page_number
3623 
3624     Updates instance state:
3625 
3626 	notebook.first_major 	- page# of the first visible major tab
3627 	notebook.first_minor 	- page# of the first visible minor tab
3628 	notebook.top_major 	- page# of the currently active major tab
3629 	notebook.top_minor 	- page# of the currently active minor tab
3630 	notebook.need_scroller	- tab scroller necessary, where
3631 				  XmNONE indicates none,
3632 				  XmMAJOR_TAB_SCROLLER indicates major only,
3633 				  XmMINOR_TAB_SCROLLER indicates minor only,
3634 				  XmTAB_SCROLLER indicates both are needed.
3635 
3636     Called from:
3637 	LayoutChildren(), when performing layout
3638 	GotoPage(), when changing the top pages
3639 	FlipTabs(), when tab scrolling are activated
3640 	TraverseTab(), when tab traverse actions are activated
3641 
3642 
3643     Parameters:
3644 	IN reason 		- Why was this routine called?
3645 		where
3646 		XmNONE		= reset all information
3647 		XmPAGE 		= reset due to a page navigation (general)
3648 		XmPAGE_SCROLLER = reset due to navigating via the page scroller
3649 		XmMAJOR_TAB 	= reset due to activating a minor tab
3650 		XmMINOR_TAB 	= reset due to activating a major tab
3651 		XmMAJOR_TAB_SCROLLER = reset due to major scroller activation
3652 		XmMINOR_TAB_SCROLLER = reset due to minor scroller activation
3653 
3654 	IN scroll 		- What type of scrolling
3655 		where
3656 		_NEXT		= scroll to the next major/minor tab
3657 		_PREV		= scroll to the previous major/minor tab
3658 		_HOME		= scroll to the first major/minor tab
3659 		_END		= scroll to the last major/minor tab
3660 		(only used for reason == NB_IS_CHILD_MAJOR_SCROLLER or
3661 		NB_IS_CHILD_MINOR_SCROLLER)
3662 
3663 -----------------------------------------------------------------------------*/
3664 static void
ResetTopPointers(XmNotebookWidget nb,unsigned char reason,int scroll)3665 ResetTopPointers (
3666     XmNotebookWidget nb,
3667     unsigned char reason,
3668     int scroll)
3669 {
3670     XmNotebookConstraint nc;		/* constraint pointer */
3671     Widget child;			/* a tab widget */
3672     int i;				/* index */
3673     int spacing;			/* tab spacing */
3674     int half;
3675     int count;				/* temporary counting */
3676     Dimension frame_dim,
3677 	      tab_dim,
3678 	      scroller_dim; 		/* temporary w/h */
3679 
3680     /* major tab information */
3681     Widget start_major;		/* the very first major tab */
3682     Widget top_major;		/* the currently major tab */
3683     Widget next_major;		/* the next major tab of first_major */
3684     Widget prev_major;		/* the prev major tab of first_major */
3685     int first_major_page;	/* page# of the first visible major tab */
3686     int top_major_page;		/* page# of the current major tab */
3687     int top_major_idx;		/* top major tab's index in the child array */
3688     int num_major;		/* # of major tabs */
3689     int num_visible_major;	/* # of visible major tabs */
3690     int num_rest_major;		/* # of next major tabs of the current page */
3691     int num_next_major;		/* # of next major tabs of first_major */
3692     int num_prev_major;		/* # of prev major tabs of first_major */
3693 
3694     /* minor tab information */
3695     Widget start_minor;		/* the first minor tab in the current major */
3696     Widget top_minor;		/* the current minor tab */
3697     Widget next_minor;		/* the next minor tab of first_minor */
3698     Widget prev_minor;		/* the prev minor tab of first_minor */
3699     int first_minor_page;	/* page# of the first visible minor tab */
3700     int top_minor_page;		/* page# of the current minor tab */
3701     int top_minor_idx;		/* top minor tab's index in the child array */
3702     int start_minor_idx;	/* start minor tab's index in the child array */
3703     int end_minor_idx;		/* end minor tab's index in the child array */
3704     int num_minor;		/* # of minor tabs */
3705     int num_visible_minor;	/* # of visible minor tabs */
3706     int num_rest_minor;		/* # of next minor tabs of the current page */
3707     int num_next_minor;		/* # of next minor tabs of first_minor */
3708     int num_prev_minor;		/* # of prev minor tabs of first_minor */
3709 
3710 
3711     /*
3712      * Calculate general tab information, based on the current_page_number.
3713      */
3714 
3715     /* Major tab */
3716     first_major_page = nb->notebook.first_major
3717 		? NotebookConstraint(nb->notebook.first_major)->page_number
3718 		: nb->notebook.first_page_number - 1;
3719     top_major_page = nb->notebook.first_page_number - 1;
3720     top_major_idx = -1;
3721     start_major = top_major = next_major = prev_major = NULL;
3722     num_major = num_rest_major = num_next_major = num_prev_major = 0;
3723 
3724     for (i=0; i < nb->composite.num_children; i++)
3725 	{
3726 	child = nb->composite.children[i];
3727         nc = NotebookConstraint(child);
3728 	if (nc->active && NB_IS_CHILD_MAJOR(nc->child_type))
3729 	    {
3730 	    if (!start_major)
3731 		/* Mark the very first tab */
3732 		start_major = child;
3733 
3734 	    if (nc->page_number <= nb->notebook.current_page_number)
3735 		{
3736 		/* Mark the closest tab to the current page */
3737 		top_major = child;
3738 		top_major_page = nc->page_number;
3739 		top_major_idx = i;
3740 		}
3741 	    else
3742 		/* Count of tabs past the current page  */
3743 		num_rest_major++;
3744 
3745 	    if (nc->page_number < first_major_page)
3746 		{
3747 		/* Mark the closest previous tab to the first visible tab */
3748 		prev_major = child;
3749 		/* Count of tabs prior to the current page  */
3750 		num_prev_major++;
3751 		}
3752 	    else if (nc->page_number > first_major_page)
3753 		{
3754 		if (!num_next_major)
3755 		    /* Mark the closest next tab to the current page */
3756 		    next_major = child;
3757 		/* Count of tabs after the current page */
3758 		num_next_major++;
3759 		}
3760 
3761 	    /* Count of all tabs */
3762 	    num_major++;
3763 	    }
3764 	}
3765 
3766     /* Minor tab */
3767     first_minor_page = nb->notebook.first_minor
3768 		? NotebookConstraint(nb->notebook.first_minor)->page_number
3769 		: nb->notebook.first_page_number - 1;
3770     top_minor_page = nb->notebook.first_page_number - 1;
3771     top_minor_idx = -1;
3772     start_minor_idx = end_minor_idx = -1;
3773     start_minor = top_minor = next_minor = prev_minor = NULL;
3774     num_minor = num_rest_minor = num_next_minor = num_prev_minor = 0;
3775     for (i = 0; i < nb->composite.num_children; i++)
3776 	{
3777 	child = nb->composite.children[i];
3778         nc = NotebookConstraint(child);
3779 	if (nc->active)
3780 	    {
3781 	    /* Break out when next major tab section is reached */
3782             if (   nc->page_number > top_major_page
3783 		&& NB_IS_CHILD_MAJOR(nc->child_type) )
3784                 break;
3785 
3786 	    /* This minor tab is in the current major tab section */
3787             if (   nc->page_number >= top_major_page
3788 		&& NB_IS_CHILD_MINOR(nc->child_type) )
3789 		{
3790 		if (!num_minor)
3791 		    {
3792 		    /* Mark the first tab in this section */
3793 		    start_minor = child;
3794 		    start_minor_idx = i;
3795 		    }
3796 		if (nc->page_number <= nb->notebook.current_page_number)
3797 		    {
3798 		    /* Mark the closest tab to the current page */
3799 		    top_minor = child;
3800 		    top_minor_page = nc->page_number;
3801 		    top_minor_idx = i;
3802 		    }
3803 		else
3804 		    {
3805 		    /* Count of tabs past the current page */
3806 		    num_rest_minor++;
3807 		    }
3808 		if (nc->page_number < first_minor_page)
3809 		    {
3810 		    /* Mark the closest previous tab to the first visible tab */
3811 		    prev_minor = child;
3812 		    num_prev_minor++;
3813 		    }
3814 		else if (nc->page_number > first_minor_page)
3815 		    {
3816 		    if (!num_next_minor)
3817 			{
3818 			/* Mark the closest next tab to the current page */
3819 			next_minor = child;
3820 			}
3821 		    /* Count of tabs after the current page */
3822 		    num_next_minor++;
3823 		    }
3824 
3825 		end_minor_idx = i;
3826 		num_minor++;
3827 		}
3828 	    }
3829 	}
3830 
3831 
3832     /*
3833      * Find the number of possibly visible tabs (num_visible_xxx), and
3834      * find whether the tab scroller is needed (notebook.need_scroller)
3835      */
3836     nb->notebook.need_scroller = XmNONE;
3837 
3838     /* Major tab */
3839     if (nb->notebook.orientation == XmHORIZONTAL)
3840 	{
3841 	frame_dim 	= nb->notebook.frame_height;
3842 	tab_dim 	= MAX(nb->notebook.major_height, 1); /* Avoid div 0 */
3843 	scroller_dim 	= nb->notebook.major_scroller_height;
3844 	}
3845     else /* (nb->notebook.orientation == XmVERTICAL) */
3846 	{
3847 	frame_dim 	= nb->notebook.frame_width;
3848 	tab_dim 	= MAX(nb->notebook.major_width, 1); /* Avoid div 0 */
3849 	scroller_dim 	= nb->notebook.major_scroller_width;
3850 	}
3851     spacing = MAX(nb->notebook.major_spacing, nb->notebook.shadow_thickness);
3852     num_visible_major = (int)(frame_dim -
3853 			 nb->notebook.back_page_size -
3854 			 nb->notebook.shadow_thickness) /
3855 			 (int)(tab_dim + spacing);
3856     if (num_visible_major < num_major)
3857 	{
3858 	nb->notebook.need_scroller = XmMAJOR_TAB_SCROLLER;
3859 	num_visible_major = (int)(frame_dim -
3860 			     nb->notebook.back_page_size -
3861 			     scroller_dim -
3862 			     MAX(0, (int)(scroller_dim -
3863 				    nb->notebook.back_page_size)) -
3864 			     nb->notebook.shadow_thickness ) /
3865 			     (int)(tab_dim + spacing);
3866 	}
3867 
3868     /* Minor tab */
3869     if (nb->notebook.orientation == XmHORIZONTAL)
3870 	{
3871 	frame_dim 	= nb->notebook.frame_width;
3872 	tab_dim 	= MAX(nb->notebook.minor_width, 1); /* Avoid div 0 */
3873 	scroller_dim 	= nb->notebook.minor_scroller_width;
3874 	}
3875     else /* (nb->notebook.orientation == XmVERTICAL) */
3876 	{
3877 	frame_dim 	= nb->notebook.frame_height;
3878 	tab_dim 	= MAX(nb->notebook.minor_height, 1); /* Avoid div 0 */
3879 	scroller_dim 	= nb->notebook.minor_scroller_height;
3880 	}
3881     spacing = MAX(nb->notebook.minor_spacing, nb->notebook.shadow_thickness);
3882     num_visible_minor 	= (int)(frame_dim -
3883 			 MAX(0, (int)(nb->notebook.back_page_size -
3884 				nb->notebook.real_binding_width)) -
3885 			 nb->notebook.shadow_thickness) /
3886 			 (int)(tab_dim + spacing);
3887     if (num_visible_minor < num_minor)
3888 	{
3889 	if (NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller))
3890 	    nb->notebook.need_scroller = XmTAB_SCROLLER;
3891 	else
3892 	    nb->notebook.need_scroller = XmMINOR_TAB_SCROLLER;
3893 	num_visible_minor = (int)(frame_dim -
3894 			     MAX(0, (int)(nb->notebook.back_page_size -
3895 				    nb->notebook.real_binding_width)) -
3896 			     scroller_dim -
3897 			     MAX(0, (int)(scroller_dim -
3898 				 nb->notebook.back_page_size)) -
3899 			     nb->notebook.shadow_thickness) /
3900 				 (int)(tab_dim + spacing);
3901 	}
3902 
3903 
3904     /*
3905      * If tab scrolling, then determine first tab but leave top tab alone.
3906      */
3907 
3908     /* Major tab */
3909     if (NB_IS_CHILD_MAJOR_SCROLLER(reason))
3910     {
3911 	if (scroll == _NEXT)
3912 	    {
3913 	    /* If there is a next non-visible tab(s), move up one */
3914 	    if (num_next_major >= num_visible_major)
3915 		nb->notebook.first_major = next_major;
3916 	    }
3917 	else if (scroll == _PREVIOUS)
3918 	    {
3919 	    /* If there is a prev non-visible tab(s), move back one */
3920 	    if (num_prev_major > 0)
3921 		nb->notebook.first_major = prev_major;
3922 	    }
3923 	else if (scroll == _HOME)
3924 	    {
3925 	    /* If there is a starting tab, move to it */
3926 	    if (start_major)
3927 		nb->notebook.first_major = start_major;
3928 	    }
3929 	else if (scroll == _END)
3930 	    {
3931 	    /* Back up from the last tab "num_visible_major" tabs */
3932 	    for (count = num_visible_major,i = nb->composite.num_children -1;
3933 		i >= 0 && count > 0; i--)
3934 		{
3935 		child = nb->composite.children[i];
3936 		nc = NotebookConstraint(child);
3937 		if (nc->active && NB_IS_CHILD_MAJOR(nc->child_type))
3938 		    {
3939 			nb->notebook.first_major = child;
3940 			count--;
3941 		    }
3942 		}
3943 	    }
3944 	return;
3945     }
3946 
3947     /* Minor tab */
3948     if (NB_IS_CHILD_MINOR_SCROLLER(reason))
3949 	{
3950 	if (scroll == _NEXT)
3951 	    {
3952 	    if (num_next_minor >= num_visible_minor)
3953 		nb->notebook.first_minor = next_minor;
3954 	    }
3955 	else if (scroll == _PREVIOUS)
3956 	    {
3957 	    if (num_prev_minor > 0)
3958 		nb->notebook.first_minor = prev_minor;
3959 	    }
3960 	else if (scroll == _HOME)
3961 	    {
3962 		nb->notebook.first_minor = start_minor;
3963 	    }
3964 	else if (scroll == _END)
3965 	    {
3966 	    for (count = num_visible_minor,i = end_minor_idx;
3967 		i >= 0 && i >= start_minor_idx && count > 0; i--)
3968 		{
3969 		child = nb->composite.children[i];
3970 		nc = NotebookConstraint(child);
3971 		if (nc->active && NB_IS_CHILD_MINOR(nc->child_type))
3972 		    {
3973 			nb->notebook.first_minor = child;
3974 			count--;
3975 		    }
3976 		}
3977 	    }
3978 	    return;
3979 	}
3980 
3981 
3982     /*
3983      * If going to a new page, then determine if we need to scroll
3984      * the tabs to make the top major/minor tabs visible
3985      */
3986     if (NB_IS_CHILD_PAGE(reason)
3987 	|| NB_IS_CHILD_PAGE_SCROLLER(reason)
3988 	|| NB_IS_CHILD_MAJOR(reason)
3989 	|| NB_IS_CHILD_MINOR(reason))
3990 	{
3991 	if (top_major && (top_major != nb->notebook.top_major))
3992 	    {
3993 	    if (NB_IS_VISIBLE(top_major))
3994 		reason = XmMAJOR_TAB;
3995 	    }
3996 	else if (top_minor && (top_minor != nb->notebook.top_minor))
3997 	    {
3998 	    if (NB_IS_VISIBLE(top_minor))
3999 		reason = XmMINOR_TAB;
4000 	    }
4001 	}
4002 
4003     /*
4004      * Set new top major/minor tabs
4005      */
4006     nb->notebook.old_top_major = nb->notebook.top_major;
4007     nb->notebook.top_major = top_major;
4008 
4009     nb->notebook.old_top_minor = nb->notebook.top_minor;
4010     nb->notebook.top_minor = top_minor;
4011 
4012 
4013     /*
4014      * Determine new first tab for the new top tab.
4015      * If apparently activated by a minor tab, we don't need to do anything
4016      * because the top major and minor must be visible .
4017      * If apparently activated by a major tab, we don't need to do anything.
4018      */
4019 
4020     /* A page change NOT caused by a major tab activiation */
4021     if (!NB_IS_CHILD_MAJOR(reason) && !NB_IS_CHILD_MINOR(reason))
4022 	{
4023 	/* Set the first tab to the starting tab, if we do not need a page
4024 	   scroller or if the calculated top tab page number is less than
4025 	   the first page number */
4026         if (!NB_IS_CHILD_MAJOR_SCROLLER(nb->notebook.need_scroller)
4027 	    || (top_major_page <= nb->notebook.first_page_number))
4028 	    nb->notebook.first_major = start_major;
4029 
4030 	/* Set the first tab to the calculated top tab, if it is the
4031 	   only one that might be visible */
4032 	else if (num_visible_major <= 1)
4033 	    nb->notebook.first_major = top_major;
4034 
4035 	/* Set the first tab so that the top tab is near the center of the
4036 	   visible tabs */
4037 	else
4038 	    {
4039 	    half = num_visible_major /2;
4040 	    half += MAX(((num_visible_major - 1) /2) - num_rest_major, 0);
4041 	    nb->notebook.first_major = top_major;
4042 	    for (i = top_major_idx - 1; i >= 0 && half > 0; i--)
4043 		{
4044 		child = nb->composite.children[i];
4045         	nc = NotebookConstraint(child);
4046                 if (nc->active && NB_IS_CHILD_MAJOR(nc->child_type))
4047 		    {
4048 		    nb->notebook.first_major = child;
4049 		    half--;
4050 		    }
4051 		}
4052 	    }
4053 	}
4054 
4055     /* Minor tab */
4056     if (!(NB_IS_CHILD_MINOR(reason)))
4057 	{
4058 	/* Set the first tab to the starting tab in this tab section, if we
4059 	   do not need a page scroller or if the calculated top tab
4060 	   page number is less than the first page number */
4061         if (!NB_IS_CHILD_MINOR_SCROLLER(nb->notebook.need_scroller)
4062 	    || (top_minor_page <= nb->notebook.first_page_number))
4063 	    nb->notebook.first_minor = start_minor;
4064 
4065 	/* Set the first tab to the calculated top tab, if it is the
4066 	   only one that might be visible */
4067 	else if (num_visible_minor <= 1)
4068 	    nb->notebook.first_minor = top_minor;
4069 
4070 	/* Set the first tab so that the top tab is near the center of the
4071 	   visible tabs */
4072         else
4073 	    {
4074 	    half = num_visible_minor /2;
4075 	    half += MAX(((num_visible_minor - 1) /2) - num_rest_minor, 0);
4076 	    nb->notebook.first_minor = top_minor;
4077             for (i = top_minor_idx - 1; i >= 0 && half > 0; i--)
4078 		{
4079 		child = nb->composite.children[i];
4080                 nc = NotebookConstraint(child);
4081 	        if (nc->active)
4082 		    {
4083                     if (NB_IS_CHILD_MAJOR(nc->child_type))
4084 			break;
4085                     else if (NB_IS_CHILD_MINOR(nc->child_type))
4086 			{
4087 			nb->notebook.first_minor = child;
4088 			half--;
4089 			}
4090 		    }
4091 		}
4092 	    }
4093 	}
4094 }
4095 
4096 
4097 
4098 /*****************************************************************************
4099  *                                                                           *
4100  *			      Drawing Functions 			     *
4101  *                                                                           *
4102  *****************************************************************************/
4103 
4104 
4105 /*- GetFrameGCs -------------------------------------------------------------
4106 
4107         Get the GC's for drawing notebook frame and binding
4108 
4109 -----------------------------------------------------------------------------*/
4110 static void
GetFrameGCs(XmNotebookWidget nb)4111 GetFrameGCs (
4112     XmNotebookWidget nb)
4113 {
4114     XGCValues values;
4115     XtGCMask mask, dynamicMask;
4116 
4117     if (nb->notebook.frame_gc)
4118         XtReleaseGC((Widget)nb, nb->notebook.frame_gc);
4119     if (nb->notebook.binding_gc)
4120         XtReleaseGC((Widget)nb, nb->notebook.binding_gc);
4121 
4122     dynamicMask = GCForeground;
4123     mask = GCForeground | GCBackground | GCLineWidth;
4124     values.foreground = nb->manager.foreground;
4125     values.background = nb->notebook.frame_background;
4126     values.line_width = 1;
4127     nb->notebook.frame_gc = XtAllocateGC((Widget)nb, 0, mask, &values,
4128 					 dynamicMask, 0);
4129 
4130     mask = GCForeground | GCBackground;
4131     dynamicMask = (GCFillStyle | GCTile | GCStipple | GCTileStipXOrigin |
4132 		   GCTileStipYOrigin);
4133     values.foreground = nb->manager.foreground;
4134     values.background = nb->notebook.frame_background;
4135     nb->notebook.binding_gc = XtAllocateGC((Widget)nb, 0, mask, &values,
4136 					   dynamicMask, 0);
4137 }
4138 
4139 
4140 /*- GetBackpageGCs ---------------------------------------------------------
4141 
4142         Get the GC's for drawing notebook backpages. These two may be
4143 	shared with other widgets.
4144 
4145 -----------------------------------------------------------------------------*/
4146 static void
GetBackpageGCs(XmNotebookWidget nb)4147 GetBackpageGCs (
4148     XmNotebookWidget nb)
4149 {
4150     XGCValues values;
4151     XtGCMask mask, dynamicMask, unusedMask;
4152 
4153     if (nb->notebook.foreground_gc)
4154         XtReleaseGC((Widget)nb, nb->notebook.foreground_gc);
4155     if (nb->notebook.background_gc)
4156         XtReleaseGC((Widget)nb, nb->notebook.background_gc);
4157 
4158     /* Will often be the same as HighlightGC in List */
4159     mask = GCForeground;
4160     dynamicMask = (GCLineWidth | GCLineStyle |
4161 		   GCClipMask | GCClipXOrigin | GCClipYOrigin);
4162     unusedMask = GCBackground | GCDashList;
4163     values.foreground = nb->notebook.back_page_foreground;
4164     nb->notebook.foreground_gc = XtAllocateGC((Widget)nb, 0, mask, &values,
4165 					      dynamicMask, unusedMask);
4166 
4167     /* Will often be the same as InverseGC in List */
4168     mask |= GCGraphicsExposures;
4169     dynamicMask = GCClipMask | GCClipXOrigin | GCClipYOrigin;
4170     unusedMask = GCBackground | GCFont;
4171     values.foreground = nb->notebook.back_page_background;
4172     values.graphics_exposures = FALSE;
4173     nb->notebook.background_gc = XtAllocateGC((Widget)nb, 0, mask, &values,
4174 					      dynamicMask, unusedMask);
4175 
4176 }
4177 
4178 
4179 /*- MakeSpiralPixmap -------------------------------------------------------
4180 
4181     Makes a spiral binding pixmap.
4182 
4183     Uses instance state:
4184 	binding placement	(XmNorientation and XmNbackPagePlacement)
4185 
4186     Updates instance state:
4187 	spiral_pixmap
4188 
4189     Parameters:
4190 	IN width   		- binding area width
4191 	IN height  		- binding area height
4192 
4193 -----------------------------------------------------------------------------*/
4194 static void
MakeSpiralPixmap(XmNotebookWidget nb,Dimension width,Dimension height)4195 MakeSpiralPixmap (
4196     XmNotebookWidget nb,
4197     Dimension width,
4198     Dimension height)
4199 {
4200     int rx=0, ry=0, rw=0, rh=0;         /* rectangle values for binding surface */
4201     int sx=0, sy=0, sw=0, sh=0, sd=0;     /* spiral values */
4202     int a1=0, a2=0, a3=0, a4=0;           /* spiral angle values */
4203     int hx=0, hy=0, hd=0;                 /* hole values */
4204     int lx1=0, ly1=0, lx2=0, ly2=0;       /* line values for binding edge */
4205     int pw=0, ph=0;                       /* pixmap size */
4206     int gap=0;                            /* gap between spirals */
4207     int div;                              /* division of binding width */
4208     int i;
4209     Pixmap pixmap;
4210 
4211     /* check binding width for reasonable values */
4212     if (width < MIN_DRAWABLE_SPIRAL_SIZE || height < MIN_DRAWABLE_SPIRAL_SIZE)
4213         return;
4214 
4215     /*
4216      * Determine spiral component values
4217      */
4218     if (nb->notebook.binding_pos == LEFT)
4219         {
4220         div = width / 3;
4221         gap = div / 2;
4222 
4223         pw = width;
4224         ph = div + gap;
4225 
4226         sx = 0;
4227         sy = gap / 2;
4228         sw = div * 2;
4229         sh = div;
4230         sd = sh / 4;
4231 
4232         a1 =  270 - 20;
4233         a2 = -270;
4234         a3 =  90 - 20;
4235         a4 =  110;
4236 
4237         hx = sx + sw - sd;
4238         hy = sy + (sh / 2) - sd +1;
4239         hd = MIN(div, sd * 2);
4240 
4241         rx = div;
4242         ry = 0;
4243         rw = width - div;
4244         rh = ph;
4245 
4246         lx1 = div;
4247         ly1 = 0;
4248         lx2 = lx1;
4249         ly2 = ph;
4250         }
4251     else if (nb->notebook.binding_pos == RIGHT)
4252         {
4253         div = width / 3;
4254         gap = div / 2;
4255 
4256         pw = width;
4257         ph = div + gap;
4258 
4259         sx = div - 1;
4260         sy = gap / 2;
4261         sw = div * 2;
4262         sh = div;
4263         sd = sh / 4;
4264 
4265         a1 =  275;
4266         a2 =  270;
4267         a3 =  90 - 10;
4268         a4 =  100;
4269 
4270         hx = sx - (sd / 2);
4271         hy = sy + (sh / 2) - sd +1;
4272         hd = MIN(div, sd * 2);
4273 
4274         rx = 0;
4275         ry = 0;
4276         rw = pw - div;
4277         rh = ph;
4278 
4279         lx1 = pw - div;
4280         ly1 = 0;
4281         lx2 = lx1;
4282         ly2 = rh;
4283         }
4284     else if (nb->notebook.binding_pos == TOP)
4285         {
4286         div = height / 3;
4287         gap = div / 2;
4288 
4289         pw = div + gap;
4290         ph = height;
4291 
4292         sx = gap / 2;
4293         sy = 0;
4294         sw = div;
4295         sh = div * 2;
4296         sd = sw / 4;
4297 
4298         a1 =  0 + 15;
4299         a2 =  270;
4300         a3 =  90;
4301         a4 =  110;
4302 
4303         hx = sx + (sw / 2) - sd +1;
4304         hy = sh - sd;
4305         hd = MIN(div, sd * 2);
4306 
4307         rx = 0;
4308         ry = div;
4309         rw = pw;
4310         rh = height - div;
4311 
4312         lx1 = 0;
4313         ly1 = div;
4314         lx2 = pw;
4315         ly2 = ly1;
4316         }
4317     else if (nb->notebook.binding_pos == BOTTOM)
4318         {
4319         div = height / 3;
4320         gap = div / 2;
4321 
4322         pw = div + gap;
4323         ph = height;
4324 
4325         sx = gap / 2;
4326         sy = div -1;
4327         sw = div;
4328         sh = (div * 2);
4329         sd = sw / 4;
4330 
4331         a1 =  360 - 5;
4332         a2 =  -295;
4333         a3 =  90 + 8;
4334         a4 =  110;
4335 
4336         hx = sx + (sw / 2);
4337         hy = sy;
4338         hd = MIN(div, sd * 2);
4339 
4340         rx = 0;
4341         ry = 0;
4342         rw = pw;
4343         rh = ph - div;
4344 
4345         lx1 = 0;
4346         ly1 = ph - div;
4347         lx2 = pw;
4348         ly2 = ly1;
4349         }
4350 
4351     /*
4352      * Create spiral pixmap, if previous one exists destroy it
4353      */
4354     if (nb->notebook.spiral_pixmap != XmUNSPECIFIED_PIXMAP
4355     &&  nb->notebook.spiral_pixmap != XmNONE)
4356             XFreePixmap(XtDisplay(nb), nb->notebook.spiral_pixmap);
4357 
4358     pixmap = nb->notebook.spiral_pixmap =
4359         XCreatePixmap(XtDisplay(nb), XtWindow(nb), pw, ph, nb->core.depth);
4360 
4361     /*
4362      * Scribble in spiral pixmap
4363      */
4364     /* Fill pixmap with notebook background */
4365     XFillRectangle(XtDisplay(nb), pixmap, nb->manager.background_GC,
4366                 0, 0, pw, ph);
4367 
4368     /* draw binding surface */
4369     XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
4370                 nb->notebook.frame_background);
4371     XFillRectangle(XtDisplay(nb), pixmap, nb->notebook.frame_gc,
4372                 rx, ry, rw, rh);
4373 
4374     /* draw line along binding surface */
4375     XSetClipMask(XtDisplay(nb), nb->notebook.foreground_gc, None);
4376     XSetLineAttributes(XtDisplay(nb), nb->notebook.foreground_gc, 1,
4377                 LineSolid, CapRound, JoinMiter);
4378     XDrawLine(XtDisplay(nb), pixmap, nb->notebook.foreground_gc,
4379                 lx1, ly1, lx2, ly2);
4380 
4381     /* draw hole in binding surface with top/bottom shadows */
4382     XFillArc(XtDisplay(nb), pixmap, nb->manager.background_GC,
4383                 hx, hy, hd, hd, 0, 360 * 64);
4384     XDrawArc(XtDisplay(nb), pixmap, nb->manager.bottom_shadow_GC,
4385                 hx, hy, hd, hd, 225 * 64, -180 * 64);
4386     XDrawArc(XtDisplay(nb), pixmap, nb->manager.top_shadow_GC,
4387                 hx, hy, hd, hd,  45 * 64, -180 * 64);
4388 
4389     /* draw spiral with top/bottom shadows */
4390     XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
4391                 nb->manager.foreground);
4392     XSetLineAttributes(XtDisplay(nb), nb->notebook.frame_gc, 1,
4393                 LineSolid, CapRound, JoinMiter);
4394     for(i=1; i < sd; i++)
4395         XDrawArc(XtDisplay(nb), pixmap, nb->notebook.frame_gc,
4396                 sx +i, sy +i, sw -i, sh -i, a1 * 64, a2 * 64);
4397     XSetLineAttributes(XtDisplay(nb), nb->notebook.frame_gc, MAX(0,sd -2),
4398                 LineSolid, CapRound, JoinMiter);
4399     XDrawArc(XtDisplay(nb), pixmap, nb->notebook.frame_gc,
4400                 sx +(sd/2), sy +(sd/2), sw, sh, a3 * 64, a4 * 64);
4401     XDrawArc(XtDisplay(nb), pixmap, nb->manager.top_shadow_GC,
4402                 sx, sy, sw, sh, a1 * 64, a2 * 64);
4403     XDrawArc(XtDisplay(nb), pixmap, nb->manager.bottom_shadow_GC,
4404                 sx +sd, sy +sd, sw -sd, sh -sd, a1 * 64, a2 * 64);
4405 }
4406 
4407 
4408 
4409 
4410 /*- DrawBinding -------------------------------------------------------------
4411 
4412         Draw the Notebook binding
4413 
4414 -----------------------------------------------------------------------------*/
4415 
4416 /*ARGSUSED*/
4417 static void
DrawBinding(XmNotebookWidget nb,XExposeEvent * event,Region region)4418 DrawBinding (
4419     XmNotebookWidget nb,
4420     XExposeEvent *event,	/* unused */
4421     Region region)
4422 {
4423     Dimension x, y, width, height;
4424 
4425     /* check binding type resource and binding width */
4426     if (nb->notebook.binding_type == XmNONE
4427 	|| nb->notebook.real_binding_width <= 0)
4428 	return;
4429 
4430     /* get the binding area */
4431     x = y = 0;
4432     if (nb->notebook.major_pos == LEFT)
4433         x += NB_MAJOR_MAX(nb, nb->notebook.major_width,
4434 	    	nb->notebook.major_scroller_width) +
4435 		nb->notebook.back_page_size + nb->notebook.frame_width;
4436     else if (nb->notebook.major_pos == TOP)
4437         y += NB_MAJOR_MAX(nb, nb->notebook.major_height,
4438 		nb->notebook.major_scroller_height) +
4439 		nb->notebook.back_page_size + nb->notebook.frame_height;
4440     if (nb->notebook.minor_pos == LEFT)
4441         x += NB_MINOR_MAX(nb, nb->notebook.minor_width,
4442 		nb->notebook.minor_scroller_width) +
4443 		nb->notebook.back_page_size;
4444     else if (nb->notebook.minor_pos == TOP)
4445         y += NB_MINOR_MAX(nb, nb->notebook.minor_height,
4446 		nb->notebook.minor_scroller_height) +
4447 		nb->notebook.back_page_size;
4448     if (nb->notebook.orientation == XmHORIZONTAL)
4449 	{
4450 	width = nb->notebook.real_binding_width;
4451 	height = nb->notebook.frame_height - 1;
4452 	y += 1;
4453 	}
4454     else
4455 	{
4456 	width = nb->notebook.frame_width - 1;
4457 	height = nb->notebook.real_binding_width;
4458 	x += 1;
4459 	}
4460 
4461     /* draw the binding if applicable */
4462     if (XRectInRegion(region, x, y, width, height))
4463 	{
4464 	switch (nb->notebook.binding_type)
4465 	    {
4466 	    case XmSOLID:
4467 	        XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
4468 			       nb->manager.foreground);
4469 		XFillRectangle(XtDisplay(nb), XtWindow(nb),
4470 			       nb->notebook.frame_gc, x, y, width, height);
4471 	        break;
4472 	    case XmSPIRAL:
4473                 MakeSpiralPixmap (nb, width, height);
4474 	        DrawPixmapBinding(nb, x, y, width, height,
4475 				    nb->notebook.spiral_pixmap);
4476 	        break;
4477 	    case XmPIXMAP:
4478 	        DrawPixmapBinding(nb, x, y, width, height,
4479 				    nb->notebook.binding_pixmap);
4480 	        break;
4481 	    case XmPIXMAP_OVERLAP_ONLY:
4482 	        DrawPixmapBinding(nb, x, y, width, height,
4483 				    nb->notebook.binding_pixmap);
4484 	        break;
4485 	    } /* switch */
4486 	} /* if */
4487 }
4488 
4489 
4490 
4491 /*- DrawPixmapBinding -------------------------------------------------------
4492 
4493         Draw the pixmap binding
4494 
4495 -----------------------------------------------------------------------------*/
4496 static void
DrawPixmapBinding(XmNotebookWidget nb,Dimension x,Dimension y,Dimension width,Dimension height,Pixmap pixmap)4497 DrawPixmapBinding (
4498     XmNotebookWidget nb,
4499     Dimension x,
4500     Dimension y,
4501     Dimension width,
4502     Dimension height,
4503     Pixmap pixmap)
4504 {
4505     int depth;
4506     int x_origin, y_origin;
4507     XGCValues values;
4508     XtGCMask mask;
4509 
4510     /* no pixmap? don't draw */
4511     if (pixmap == XmUNSPECIFIED_PIXMAP || pixmap == XmNONE)
4512 	return;
4513 
4514     /* get Pixmap depth */
4515     XmeGetPixmapData(XtScreen(nb), pixmap,
4516 			NULL, &depth, NULL, NULL, NULL, NULL, NULL, NULL);
4517 
4518     /* creating the gc */
4519     if (depth == 1)
4520 	{
4521 	mask = GCFillStyle | GCStipple;
4522 	values.fill_style = FillStippled;
4523 	values.stipple = pixmap;
4524 	}
4525     else
4526 	{
4527 	mask = GCFillStyle | GCTile;
4528 	values.fill_style = FillTiled;
4529 	values.tile = pixmap;
4530 	}
4531     XChangeGC(XtDisplay(nb), nb->notebook.binding_gc, mask, &values);
4532 
4533     /*
4534      * set TSOrigin
4535      */
4536     if (nb->notebook.binding_pos == LEFT || nb->notebook.binding_pos == TOP)
4537         x_origin = x, y_origin = y;
4538     else if (nb->notebook.binding_pos == RIGHT)
4539         x_origin = x + width - 1, y_origin = y;
4540     else /* if (nb->notebook.binding_pos == BOTTOM) */
4541         x_origin = x, y_origin = y + height;
4542 
4543     XSetTSOrigin(XtDisplay(nb), nb->notebook.binding_gc, x_origin, y_origin);
4544 
4545     /* display the pixmap binding */
4546     XFillRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.binding_gc,
4547 		    x, y, width -1, height - 1);
4548 }
4549 
4550 
4551 /*- DrawFrameShadow ---------------------------------------------------------
4552 
4553         Draw the Notebook frame shadow
4554 
4555 -----------------------------------------------------------------------------*/
4556 
4557 /*ARGSUSED*/
4558 static void
DrawFrameShadow(XmNotebookWidget nb,XExposeEvent * event,Region region)4559 DrawFrameShadow (
4560     XmNotebookWidget nb,
4561     XExposeEvent *event,	/* unused */
4562     Region region)		/* unused */
4563 {
4564     Dimension x, y, width, height;
4565     Region shadow_region;
4566     XRectangle rect;
4567 
4568     /* get the page's x, y position */
4569     x = y = 1;
4570     if (nb->notebook.binding_pos == LEFT)
4571         x += nb->notebook.real_binding_width;
4572     else if (nb->notebook.binding_pos == TOP)
4573         y += nb->notebook.real_binding_width;
4574     if (nb->notebook.major_pos == LEFT)
4575         x += NB_MAJOR_MAX(nb, nb->notebook.major_width,
4576             nb->notebook.major_scroller_width) + nb->notebook.back_page_size;
4577     else if (nb->notebook.major_pos == TOP)
4578         y += NB_MAJOR_MAX(nb, nb->notebook.major_height,
4579             nb->notebook.major_scroller_height) + nb->notebook.back_page_size;
4580     if (nb->notebook.minor_pos == LEFT)
4581         x += NB_MINOR_MAX(nb, nb->notebook.minor_width,
4582             nb->notebook.minor_scroller_width) + nb->notebook.back_page_size;
4583     else if (nb->notebook.minor_pos == TOP)
4584         y += NB_MINOR_MAX(nb, nb->notebook.minor_height,
4585             nb->notebook.minor_scroller_height) + nb->notebook.back_page_size;
4586     width = nb->notebook.frame_width - 2;
4587     height = nb->notebook.frame_height - 2;
4588 
4589     XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
4590 		   nb->notebook.frame_background);
4591 
4592     /* draw the frame shadow */
4593     if (nb->notebook.shadow_thickness)
4594     {
4595 	/* draw the shadow */
4596 	/* creating the shadow region */
4597 	shadow_region = XCreateRegion();
4598 
4599 	/* adding the frame area to the shadow region */
4600 	rect.x = x;
4601 	rect.y = y;
4602 	rect.width = width;
4603 	rect.height = height;
4604 	XFillRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.frame_gc,
4605 			x, y, width + 1, height + 1);
4606 	XUnionRectWithRegion(&rect, shadow_region, shadow_region);
4607 
4608 	/* adding the top major tab area to the shadow region */
4609 	if (nb->notebook.top_major
4610 	    && NB_IS_VISIBLE(nb->notebook.top_major)
4611 	    && !NB_IS_CHILD_JOINSIDE(nb->notebook.top_major))
4612 	{
4613 	    rect.x = nb->notebook.top_major->core.x -
4614 		     nb->notebook.shadow_thickness;
4615 	    rect.y = nb->notebook.top_major->core.y -
4616 		     nb->notebook.shadow_thickness;
4617 	    rect.width = nb->notebook.top_major->core.width +
4618 		     nb->notebook.shadow_thickness * 2 - 1;
4619 	    rect.height = nb->notebook.top_major->core.height +
4620 		     nb->notebook.shadow_thickness * 2 - 1;
4621 	    /* ensure x/y of rect does not go negative */
4622 	    /* this can be removed when _XmRegionDrawShadow is fixed
4623 		to allow negative y values */
4624             if( rect.x < 0)
4625                 {
4626                 rect.width -= rect.x;
4627                 rect.x = 0;
4628                 }
4629             if( rect.y < 0)
4630                 {
4631                 rect.height -= rect.y;
4632                 rect.y = 0;
4633                 }
4634 
4635 	    XUnionRectWithRegion(&rect, shadow_region, shadow_region);
4636 	}
4637 
4638 	/* adding the top minor tab area to the shadow region */
4639 	if (nb->notebook.top_minor
4640 	    && NB_IS_VISIBLE(nb->notebook.top_minor)
4641 	    && !NB_IS_CHILD_JOINSIDE(nb->notebook.top_minor))
4642 	{
4643 	    rect.x = nb->notebook.top_minor->core.x -
4644 		     nb->notebook.shadow_thickness;
4645 	    rect.y = nb->notebook.top_minor->core.y -
4646 		     nb->notebook.shadow_thickness;
4647 	    rect.width = nb->notebook.top_minor->core.width +
4648 		     nb->notebook.shadow_thickness * 2 - 1;
4649 	    rect.height = nb->notebook.top_minor->core.height +
4650 		     nb->notebook.shadow_thickness * 2 - 1;
4651 	    /* ensure x/y of rect does not go negative */
4652 	    /* this can be removed when _XmRegionDrawShadow is fixed
4653 		to allow negative y values */
4654             if( rect.x < 0)
4655                 {
4656                 rect.width -= rect.x;
4657                 rect.x = 0;
4658                 }
4659             if( rect.y < 0)
4660                 {
4661                 rect.height -= rect.y;
4662                 rect.y = 0;
4663                 }
4664 	    XUnionRectWithRegion(&rect, shadow_region, shadow_region);
4665 	}
4666 
4667 	/* draw the shadow */
4668 	_XmRegionDrawShadow(XtDisplay(nb), XtWindow(nb),
4669 			    nb->manager.top_shadow_GC,
4670 			    nb->manager.bottom_shadow_GC,
4671 			    (XmRegion)shadow_region, nb->core.border_width,
4672 			    nb->notebook.shadow_thickness, XmSHADOW_OUT);
4673 	XDestroyRegion(shadow_region);
4674     }
4675     else
4676     {
4677 	XFillRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.frame_gc,
4678 			x, y, width, height);
4679 	XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
4680 		       nb->manager.foreground);
4681 	XDrawRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.frame_gc,
4682 			x, y, width, height);
4683 	if (nb->notebook.top_major
4684 	    && NB_IS_VISIBLE(nb->notebook.top_major)
4685 	    && !NB_IS_CHILD_JOINSIDE(nb->notebook.top_major))
4686 	{
4687 	    rect.x = nb->notebook.top_major->core.x - 1;
4688 	    rect.y = nb->notebook.top_major->core.y - 1;
4689 	    rect.width = nb->notebook.top_major->core.width + 1;
4690 	    rect.height = nb->notebook.top_major->core.height + 1;
4691 	    /* ensure x/y of rect does not go negative */
4692 	    /* this can be removed when _XmRegionDrawShadow is fixed
4693 		to allow negative y values */
4694             if( rect.x < 0)
4695                 {
4696                 rect.width -= rect.x;
4697                 rect.x = 0;
4698                 }
4699             if( rect.y < 0)
4700                 {
4701                 rect.height -= rect.y;
4702                 rect.y = 0;
4703                 }
4704 
4705 	XDrawRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.frame_gc,
4706 			rect.x, rect.y, rect.width, rect.height);
4707 	}
4708 
4709 	/* adding the top minor tab area to the shadow region */
4710 	if (nb->notebook.top_minor
4711 	    && NB_IS_VISIBLE(nb->notebook.top_minor)
4712 	    && !NB_IS_CHILD_JOINSIDE(nb->notebook.top_minor))
4713 	{
4714 	    rect.x = nb->notebook.top_minor->core.x - 1;
4715 	    rect.y = nb->notebook.top_minor->core.y - 1;
4716 	    rect.width = nb->notebook.top_minor->core.width + 1;
4717 	    rect.height = nb->notebook.top_minor->core.height + 1;
4718 	    /* ensure x/y of rect does not go negative */
4719 	    /* this can be removed when _XmRegionDrawShadow is fixed
4720 		to allow negative y values */
4721             if( rect.x < 0)
4722                 {
4723                 rect.width -= rect.x;
4724                 rect.x = 0;
4725                 }
4726             if( rect.y < 0)
4727                 {
4728                 rect.height -= rect.y;
4729                 rect.y = 0;
4730                 }
4731 	XDrawRectangle(XtDisplay(nb), XtWindow(nb), nb->notebook.frame_gc,
4732 			rect.x, rect.y, rect.width, rect.height);
4733 	}
4734     }
4735 
4736 }
4737 
4738 
4739 /*- DrawBackPages -----------------------------------------------------------
4740 
4741 	Draw Notebook back pages
4742 
4743 -----------------------------------------------------------------------------*/
4744 
4745 /*ARGSUSED*/
4746 static void
DrawBackPages(XmNotebookWidget nb,XExposeEvent * event,Region region)4747 DrawBackPages (
4748     XmNotebookWidget nb,
4749     XExposeEvent *event,	/* unused */
4750     Region region)
4751 {
4752     int delta, back;	/* backpage foreground & background deltas */
4753     int binding_width;	/* the real binding width */
4754     int dx, dy;		/* delta-x and delta-y */
4755     int mx, my;		/* maximum delta-x and delta-y */
4756     int x, y, limit;	/* temporary variables */
4757     XPoint p[5];	/* foreground line pattern */
4758     XPoint q[3];	/* background line pattern */
4759 
4760 
4761     /*
4762      * initialize
4763      */
4764     delta = nb->notebook.back_page_size / nb->notebook.real_back_page_number;
4765 
4766     /* draw backpages on the frame, which is not necessarily along the
4767        entire binding */
4768     if (nb->notebook.binding_type == XmPIXMAP)
4769 	binding_width = MAX(nb->notebook.real_binding_width,
4770 			nb->notebook.binding_width);
4771     else
4772 	binding_width = MIN(nb->notebook.real_binding_width,
4773 			nb->notebook.binding_width);
4774 
4775     /* find back page line pattern */
4776     if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
4777 	nb->notebook.orientation == XmHORIZONTAL)
4778     {
4779 	p[1].x = nb->notebook.real_binding_width - binding_width;
4780 	p[1].y = nb->notebook.frame_height;
4781 	p[2].x = binding_width + nb->notebook.frame_width;
4782 	p[2].y = 0;
4783 	p[3].x = 0;
4784 	p[3].y = - nb->notebook.frame_height;
4785 	p[4].x = - delta;
4786 	p[4].y = 0;
4787 	p[0].x = p[1].x;
4788 	p[0].y = p[1].y - delta;
4789 	x = 0;
4790 	y = delta;
4791 	dx = dy = delta;
4792 	mx = my = nb->notebook.back_page_size;
4793     }
4794     else if (nb->notebook.back_page_pos == XmBOTTOM_RIGHT &&
4795 	nb->notebook.orientation == XmVERTICAL)
4796     {
4797 	p[1].x = nb->notebook.frame_width;
4798 	p[1].y = nb->notebook.real_binding_width - binding_width;
4799 	p[2].x = 0;
4800 	p[2].y = binding_width + nb->notebook.frame_height;
4801 	p[3].x = - nb->notebook.frame_width;
4802 	p[3].y = 0;
4803 	p[4].x = 0;
4804 	p[4].y = - delta;
4805 	p[0].x = p[1].x - delta;
4806 	p[0].y = p[1].y;
4807 	x = delta;
4808 	y = 0;
4809 	dx = dy = delta;
4810 	mx = my = nb->notebook.back_page_size;
4811     }
4812     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
4813 	nb->notebook.orientation == XmHORIZONTAL)
4814     {
4815 	p[1].x = NB_MAJOR_MAX(nb, nb->notebook.major_width,
4816 		nb->notebook.major_scroller_width) +
4817 		nb->notebook.back_page_size + nb->notebook.frame_width +
4818 		binding_width - 1;
4819 	p[1].y = nb->notebook.frame_height;
4820 	p[2].x = - (nb->notebook.frame_width + binding_width);
4821 	p[2].y = 0;
4822 	p[3].x = 0;
4823 	p[3].y = - nb->notebook.frame_height;
4824 	p[4].x = delta;
4825 	p[4].y = 0;
4826 	p[0].x = p[1].x;
4827 	p[0].y = p[1].y - delta;
4828 	x = 0;
4829 	y = delta;
4830 	dx = - delta;
4831 	dy = delta;
4832 	mx = - nb->notebook.back_page_size;
4833 	my = nb->notebook.back_page_size;
4834     }
4835     else if (nb->notebook.back_page_pos == XmBOTTOM_LEFT &&
4836 	nb->notebook.orientation == XmVERTICAL)
4837     {
4838 	p[1].x = nb->notebook.back_page_size +
4839 		NB_MINOR_MAX(nb, nb->notebook.minor_width,
4840 		nb->notebook.minor_scroller_width) - 1;
4841 	p[1].y = nb->notebook.real_binding_width - binding_width;
4842 	p[2].x = 0;
4843 	p[2].y = binding_width + nb->notebook.frame_height;
4844 	p[3].x = nb->notebook.frame_width;
4845 	p[3].y = 0;
4846 	p[4].x = 0;
4847 	p[4].y = - delta;
4848 	p[0].x = p[1].x + delta;
4849 	p[0].y = p[1].y;
4850 	x = - delta;
4851 	y = 0;
4852 	dx = - delta;
4853 	dy = delta;
4854 	mx = - nb->notebook.back_page_size;
4855 	my = nb->notebook.back_page_size;
4856     }
4857     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
4858 	nb->notebook.orientation == XmHORIZONTAL)
4859     {
4860 	p[1].x = nb->notebook.real_binding_width - binding_width;
4861 	p[1].y = nb->notebook.back_page_size +
4862 		NB_MINOR_MAX(nb, nb->notebook.minor_height,
4863 		nb->notebook.minor_scroller_height) - 1;
4864 	p[2].x = binding_width + nb->notebook.frame_width;
4865 	p[2].y = 0;
4866 	p[3].x = 0;
4867 	p[3].y = nb->notebook.frame_height;
4868 	p[4].x = - delta;
4869 	p[4].y = 0;
4870 	p[0].x = p[1].x;
4871 	p[0].y = p[1].y + delta;
4872 	x = 0;
4873 	y = - delta;
4874 	dx = delta;
4875 	dy = - delta;
4876 	mx = nb->notebook.back_page_size;
4877 	my = - nb->notebook.back_page_size;
4878     }
4879     else if (nb->notebook.back_page_pos == XmTOP_RIGHT &&
4880 	nb->notebook.orientation == XmVERTICAL)
4881     {
4882 	p[1].x = nb->notebook.frame_width;
4883 	p[1].y = nb->notebook.back_page_size + nb->notebook.frame_height +
4884 		binding_width + NB_MAJOR_MAX(nb, nb->notebook.major_height,
4885 		nb->notebook.major_scroller_height) - 1;
4886 	p[2].x = 0;
4887 	p[2].y = - (binding_width + nb->notebook.frame_height);
4888 	p[3].x = - nb->notebook.frame_width;
4889 	p[3].y = 0;
4890 	p[4].x = 0;
4891 	p[4].y = delta;
4892 	p[0].x = p[1].x - delta;
4893 	p[0].y = p[1].y;
4894 	x = delta;
4895 	y = 0;
4896 	dx = delta;
4897 	dy = - delta;
4898 	mx = nb->notebook.back_page_size;
4899 	my = - nb->notebook.back_page_size;
4900     }
4901     else if (nb->notebook.back_page_pos == XmTOP_LEFT &&
4902 	nb->notebook.orientation == XmHORIZONTAL)
4903     {
4904 	p[1].x = nb->notebook.back_page_size + nb->notebook.frame_width +
4905 		binding_width + NB_MAJOR_MAX(nb, nb->notebook.major_width,
4906 		nb->notebook.major_scroller_width) - 1;
4907 	p[1].y = nb->notebook.back_page_size +
4908 		NB_MINOR_MAX(nb, nb->notebook.minor_height,
4909 		nb->notebook.minor_scroller_height) - 1;
4910 	p[2].x = - (binding_width + nb->notebook.frame_width);
4911 	p[2].y = 0;
4912 	p[3].x = 0;
4913 	p[3].y = nb->notebook.frame_height;
4914 	p[4].x = delta;
4915 	p[4].y = 0;
4916 	p[0].x = p[1].x;
4917 	p[0].y = p[1].y + delta;
4918 	x = 0;
4919 	y = - delta;
4920 	dx = - delta;
4921 	dy = - delta;
4922 	mx = - nb->notebook.back_page_size;
4923 	my = - nb->notebook.back_page_size;
4924     }
4925     else
4926     {
4927 	p[1].x = nb->notebook.back_page_size +
4928 		NB_MINOR_MAX(nb, nb->notebook.minor_width,
4929 		nb->notebook.minor_scroller_width) - 1;
4930 	p[1].y = nb->notebook.back_page_size + nb->notebook.frame_height +
4931 		binding_width + NB_MAJOR_MAX(nb, nb->notebook.major_height,
4932 		nb->notebook.major_scroller_height) -1;
4933 	p[2].x = 0;
4934 	p[2].y = - (binding_width + nb->notebook.frame_height);
4935 	p[3].x = nb->notebook.frame_width;
4936 	p[3].y = 0;
4937 	p[4].x = 0;
4938 	p[4].y = delta;
4939 	p[0].x = p[1].x + delta;
4940 	p[0].y = p[1].y;
4941 	x = - delta;
4942 	y = 0;
4943 	dx = - delta;
4944 	dy = - delta;
4945 	mx = - nb->notebook.back_page_size;
4946 	my = - nb->notebook.back_page_size;
4947     }
4948 
4949     /* set the clipping region if necessary */
4950     XSetRegion(XtDisplay(nb), nb->notebook.foreground_gc, region);
4951     XSetRegion(XtDisplay(nb), nb->notebook.background_gc, region);
4952     XSetClipOrigin(XtDisplay(nb), nb->notebook.foreground_gc, 0, 0);
4953     XSetClipOrigin(XtDisplay(nb), nb->notebook.background_gc, 0, 0);
4954 
4955     /* draw the first page outline */
4956     XSetLineAttributes(XtDisplay(nb), nb->notebook.foreground_gc, 1,
4957 			LineSolid, CapButt, JoinMiter);
4958     if (nb->notebook.binding_type == XmSPIRAL ||
4959 	nb->notebook.binding_type == XmPIXMAP ||
4960 	nb->notebook.binding_type == XmSOLID ||
4961 	nb->notebook.binding_type == XmNONE ||
4962 	nb->notebook.binding_type == XmPIXMAP_OVERLAP_ONLY)
4963     {
4964 	Dimension width, height;
4965 	Position x, y;
4966 
4967 	/* We can't pass a negative width or height to the draw call.
4968 	   Since it appears that draw functions later in the code need
4969 	   the p values set as above, let's check whether the height and
4970 	   width here are negative and adjust the draw coordinates
4971 	   as appropriate. */
4972 
4973 	if (nb->notebook.orientation == XmHORIZONTAL)
4974 	{
4975 	    ADJUST_NEGATIVE_DIMENSION(p[1].x, p[2].x, x, width);
4976 	    ADJUST_NEGATIVE_DIMENSION(p[1].y, p[3].y, y, height);
4977 	    XDrawRectangle(XtDisplay(nb), XtWindow(nb),
4978 			   nb->notebook.foreground_gc,
4979 			   x, y, width, height);
4980 	}
4981 	else
4982 	{
4983 	    ADJUST_NEGATIVE_DIMENSION(p[1].x, p[3].x, x, width);
4984 	    ADJUST_NEGATIVE_DIMENSION(p[1].y, p[2].y, y, height);
4985 	    XDrawRectangle(XtDisplay(nb), XtWindow(nb),
4986 			   nb->notebook.foreground_gc,
4987 			   x, y, width, height);
4988 	}
4989     }
4990 
4991     /* for XmSOLID, XmPIXMAP, and XmPIXMAP_OVERLAP_ONLY */
4992     if (nb->notebook.binding_type == XmSOLID ||
4993 	nb->notebook.binding_type == XmPIXMAP ||
4994 	nb->notebook.binding_type == XmPIXMAP_OVERLAP_ONLY)
4995     {
4996 	/* draw back page lines */
4997 	x = p[1].x;
4998 	y = p[1].y;
4999 	limit = nb->notebook.back_page_size;
5000 	while (limit > 0)
5001 	{
5002 	    /* draw backpage foreground */
5003 	    XDrawLines(XtDisplay(nb), XtWindow(nb), nb->notebook.foreground_gc,
5004 			&(p[1]), 4, CoordModePrevious);
5005 
5006 	    /* draw backpage background */
5007 	    if (delta >= 2 && limit > delta - 2)
5008 	    {
5009 		back = delta - 1;
5010 		q[0].x = p[1].x;
5011 		q[0].y = p[1].y;
5012 		q[1].x = p[2].x;
5013 		q[1].y = p[2].y;
5014 		q[2].x = p[3].x;
5015 		q[2].y = p[3].y;
5016 		q[0].x += NB_ENFORCE_SIGN(dx, 1);
5017 		q[0].y += NB_ENFORCE_SIGN(dy, 1);
5018 		if (q[2].x) q[2].x += dx;
5019 		if (q[2].y) q[2].y += dy;
5020 		while (back > 0)
5021 		{
5022 		    XDrawLines(XtDisplay(nb), XtWindow(nb),
5023 				nb->notebook.background_gc,
5024 				q, 3, CoordModePrevious);
5025 		    q[0].y += NB_ENFORCE_SIGN(dy, 1);
5026 		    q[0].x += NB_ENFORCE_SIGN(dx, 1);
5027 		    if (q[2].x) q[2].x -= NB_ENFORCE_SIGN(dx, 1);
5028 		    if (q[2].y) q[2].y -= NB_ENFORCE_SIGN(dy, 1);
5029 		    back--;
5030 		}
5031 	    }
5032 	    p[1].x += dx;
5033 	    p[1].y += dy;
5034 	    limit -= delta;
5035 	}
5036 
5037 	/* draw the last page line */
5038 	p[0].x = x;
5039 	p[0].y = y;
5040 	p[1].x = mx;
5041 	p[1].y = my;
5042 	XSetLineAttributes(XtDisplay(nb), nb->notebook.foreground_gc, 2,
5043 			LineSolid, CapButt, JoinMiter);
5044 	XDrawLines(XtDisplay(nb), XtWindow(nb), nb->notebook.foreground_gc,
5045 			p, 5, CoordModePrevious);
5046     }
5047 
5048     /* for XmNONE and XmSPIRAL */
5049     else
5050     {
5051 	/* draw back page lines */
5052 	p[1].x = x;
5053 	p[1].y = y;
5054 	x = p[0].x;
5055 	y = p[0].y;
5056 	limit = nb->notebook.back_page_size;
5057 	while (limit > 0)
5058 	{
5059 	    /* draw backpage foreground */
5060 	    XDrawLines(XtDisplay(nb), XtWindow(nb), nb->notebook.foreground_gc,
5061 			p, 5, CoordModePrevious);
5062 
5063 	    /* draw backpage background */
5064 	    if (delta >= 2 && limit > delta - 2)
5065 	    {
5066 		back = delta - 1;
5067 		q[0].x = p[0].x + p[1].x;
5068 		q[0].y = p[0].y + p[1].y;
5069 		q[1].x = p[2].x;
5070 		q[1].y = p[2].y;
5071 		q[2].x = p[3].x;
5072 		q[2].y = p[3].y;
5073 		q[0].x += NB_ENFORCE_SIGN(dx, 1);
5074 		q[0].y += NB_ENFORCE_SIGN(dy, 1);
5075 		if (q[1].x)
5076 		    {
5077 		    q[0].x += dx;
5078 		    q[1].x -= dx;
5079 		    }
5080 		if (q[1].y)
5081 		    {
5082 		    q[0].y += dy;
5083 		    q[1].y -= dy;
5084 		    }
5085 		if (q[2].x) q[2].x += dx;
5086 		if (q[2].y) q[2].y += dy;
5087 		while (back > 0)
5088 		{
5089 		    XDrawLines(XtDisplay(nb), XtWindow(nb),
5090 				nb->notebook.background_gc,
5091 				q, 3, CoordModePrevious);
5092 		    if (q[1].x)
5093 			{
5094 			q[0].y += NB_ENFORCE_SIGN(dy, 1);
5095 			q[1].x += NB_ENFORCE_SIGN(dx, 1);
5096 			}
5097 		    if (q[1].y)
5098 			{
5099 			q[0].x += NB_ENFORCE_SIGN(dx, 1);
5100 			q[1].y += NB_ENFORCE_SIGN(dy, 1);
5101 			}
5102 		    if (q[2].x) q[2].x -= NB_ENFORCE_SIGN(dx, 1);
5103 		    if (q[2].y) q[2].y -= NB_ENFORCE_SIGN(dy, 1);
5104 		    back--;
5105 		}
5106 	    }
5107 	    p[0].x += dx;
5108 	    p[0].y += dy;
5109 	    limit -= delta;
5110 	}
5111 
5112 	/* draw the last page line */
5113 	p[0].x = x + mx;
5114 	p[0].y = y + my;
5115 	XSetLineAttributes(XtDisplay(nb), nb->notebook.foreground_gc, 2,
5116 			LineSolid, CapButt, JoinMiter);
5117 	XDrawLines(XtDisplay(nb), XtWindow(nb), nb->notebook.foreground_gc,
5118 			p, 5, CoordModePrevious);
5119     }
5120 
5121 }
5122 
5123 
5124 
5125 /*****************************************************************************
5126  *                                                                           *
5127  *			      Geometry Functions			     *
5128  *                                                                           *
5129  *****************************************************************************/
5130 
5131 
5132 /*- CalcGeoInfo ------------------------------------------------------------
5133 
5134     Calculate Notebook's preferred geometry.
5135 
5136     Updates instance state:
5137 	page_width
5138 	page_height
5139 	status_width
5140 	status_height
5141 	major_width
5142 	major_height
5143 	minor_width
5144 	minor_height
5145 	scroller_width
5146 	scroller_height
5147 	major_scroller_width
5148 	major_scroller_height
5149 	minor_scroller_width
5150 	minor_scroller_height
5151 	frame_width
5152 	frame_height
5153 	real_binding_width
5154 	real_back_page_number,	if adjust is True
5155 
5156     Parameters:
5157 	IN instigator  		- child widget requesting geo request
5158 	IN desired     		- instigator's requested geometry
5159 	IN adjust		- flag to indicate whether instance geometry
5160 			    	  variables used for layout should be set.
5161 	OUT preferred_width,
5162 	OUT preferred_height	- notebook w/h based on children sizes
5163 
5164 -----------------------------------------------------------------------------*/
5165 static void
CalcGeoInfo(XmNotebookWidget nb,Widget instigator,XtWidgetGeometry * desired,Dimension * preferred_width,Dimension * preferred_height,Boolean adjust)5166 CalcGeoInfo (
5167     XmNotebookWidget nb,
5168     Widget instigator,
5169     XtWidgetGeometry *desired,
5170     Dimension *preferred_width,
5171     Dimension *preferred_height,
5172     Boolean adjust)
5173 {
5174     XmNotebookConstraint nc;
5175     Dimension width, height;
5176     Widget child;
5177     XtWidgetGeometry preferred;
5178     int i;
5179     unsigned int w, h;
5180     Dimension	page_width = 0,page_height = 0;
5181     Dimension	status_width = 0,status_height = 0;
5182     Dimension	major_width = 0,major_height = 0;
5183     Dimension	minor_width = 0,minor_height = 0;
5184     Dimension	scroller_width = 0,scroller_height = 0;
5185     Dimension	major_scroller_width = 0,major_scroller_height = 0;
5186     Dimension	minor_scroller_width = 0,minor_scroller_height = 0;
5187     Dimension	frame_width,frame_height;
5188     Dimension	real_binding_width,real_back_page_number;
5189 
5190     /* get width and height of children */
5191     for (i = 0; i < nb->composite.num_children; i++)
5192     {
5193 	/* ask preferred size */
5194 	child = nb->composite.children[i];
5195 
5196 	if (child == instigator)
5197 	    {
5198 	    width = IsWidth(desired)
5199 				? desired->width
5200 				: XtWidth(instigator);
5201 	    width += (IsBorder(desired)
5202 				? desired->border_width
5203 				: XtBorderWidth(instigator)) * 2;
5204 	    height = IsHeight(desired)
5205 				? desired->height
5206 				: XtHeight(instigator);
5207 	    height += (IsBorder(desired)
5208 				? desired->border_width
5209 				: XtBorderWidth(instigator)) * 2;
5210 	    }
5211 	else
5212 	    {
5213 	    XtQueryGeometry(child, NULL, &preferred);
5214 	    width = (preferred.request_mode & CWWidth)
5215 				? preferred.width
5216 				: XtWidth(child) + child->core.border_width*2;
5217 	    height = (preferred.request_mode & CWHeight)
5218 				? preferred.height
5219 				: XtHeight(child) + child->core.border_width*2;
5220 	    }
5221 
5222 	/* get the maximum */
5223 	if (XtIsManaged(child))
5224 	{
5225 	    nc = NotebookConstraint(child);
5226 	    switch (nc->child_type)
5227 	    {
5228 		case XmPAGE:
5229 		    ASSIGN_MAX(page_width, width);
5230 		    ASSIGN_MAX(page_height, height);
5231 		    break;
5232 		case XmSTATUS_AREA:
5233 		    ASSIGN_MAX(status_width, width);
5234 		    ASSIGN_MAX(status_height, height);
5235 		    break;
5236 		case XmMAJOR_TAB:
5237 		    ASSIGN_MAX(major_width, width);
5238 		    ASSIGN_MAX(major_height, height);
5239 		    break;
5240 		case XmMINOR_TAB:
5241 		    ASSIGN_MAX(minor_width, width);
5242 		    ASSIGN_MAX(minor_height, height);
5243 		    break;
5244 		case XmPAGE_SCROLLER:
5245 		    ASSIGN_MAX(scroller_width, width);
5246 		    ASSIGN_MAX(scroller_height, height);
5247 		    break;
5248 		case XmMAJOR_TAB_SCROLLER:
5249 		    ASSIGN_MAX(major_scroller_width, width);
5250 		    ASSIGN_MAX(major_scroller_height, height);
5251 		    break;
5252 		case XmMINOR_TAB_SCROLLER:
5253 		    ASSIGN_MAX(minor_scroller_width, width);
5254 		    ASSIGN_MAX(minor_scroller_height, height);
5255 		    break;
5256 	    }
5257 	}
5258     }
5259 
5260     /* adjust page's width */
5261     page_width = MAX((int)page_width, (int)(status_width + nb->notebook.margin_width +
5262 					scroller_width));
5263 
5264     /* set the real binding width */
5265     real_binding_width = nb->notebook.binding_width;
5266     switch (nb->notebook.binding_type)
5267     {
5268 	case XmNONE:
5269 	    real_binding_width = 0;
5270 	    break;
5271 	case XmSPIRAL:
5272 	    real_binding_width = ((int)(nb->notebook.binding_width * 3))/2;
5273 	    break;
5274 	case XmPIXMAP:
5275 	    if (nb->notebook.binding_pixmap != XmUNSPECIFIED_PIXMAP
5276 		&& nb->notebook.binding_pixmap != XmNONE)
5277 	    {
5278 		w = h = 0;
5279     	        XmeGetPixmapData(XtScreen(nb),nb->notebook.binding_pixmap,
5280            		             NULL,NULL,NULL,NULL,NULL,NULL,&w,&h);
5281 		if (nb->notebook.orientation == XmHORIZONTAL)
5282 		    {
5283 		    ASSIGN_MAX(real_binding_width, w);
5284 		    }
5285 		else
5286 		    {
5287 		    ASSIGN_MAX(real_binding_width, h);
5288 		    }
5289 	    }
5290 	    break;
5291 	/* Note: in case of XmPIXMAP_OVERLAP_ONLY binding_width is used
5292 	   so we don't care about the Pixmap size here */
5293     }
5294 
5295     /* Calculate the real back page number */
5296     real_back_page_number = nb->notebook.back_page_number;
5297     ASSIGN_MIN(real_back_page_number, (Dimension)(nb->notebook.back_page_size /2));
5298     ASSIGN_MAX(real_back_page_number, 1);
5299 
5300     /* Calculate status w/h based on page,margin,& scroller w/h */
5301     status_width = MAX(0,(int)
5302 		(page_width - nb->notebook.margin_width - scroller_width));
5303     status_height = scroller_height = MAX(status_height,scroller_height);
5304 
5305     /* Calculate the notebook frame size based on page size,shadows,& margins*/
5306     frame_width = page_width +
5307 		  (nb->notebook.shadow_thickness * 2) +
5308                   (nb->notebook.margin_width * 2) + 1;
5309     frame_height = page_height + status_height +
5310                   (nb->notebook.shadow_thickness * 2) +
5311                   (nb->notebook.margin_height * 3) + 1;
5312 
5313     /*
5314      * Return calculated notebook's preferred size
5315      */
5316     /* add frame and back pages area */
5317     *preferred_width = frame_width + nb->notebook.back_page_size;
5318     *preferred_height = frame_height + nb->notebook.back_page_size;
5319 
5320     /* add binding and tab area */
5321     if (nb->notebook.orientation == XmHORIZONTAL)
5322 	{
5323 	*preferred_width += real_binding_width +
5324 			NB_MAJOR_MAX(nb, major_width, major_scroller_width);
5325 	*preferred_height +=
5326 			NB_MINOR_MAX(nb, minor_height, minor_scroller_height);
5327 	}
5328     else
5329 	{
5330 	*preferred_width +=
5331 			NB_MINOR_MAX(nb, minor_width, minor_scroller_width);
5332 	*preferred_height += real_binding_width +
5333 			NB_MAJOR_MAX(nb, major_height, major_scroller_height);
5334 	}
5335 
5336 
5337     /*
5338      * Set notebook geometry, if adjusting
5339      */
5340     if (adjust)
5341     {
5342 	nb->notebook.page_width = page_width;
5343 	nb->notebook.page_height = page_height;
5344 	nb->notebook.status_width = status_width;
5345 	nb->notebook.status_height = status_height;
5346 	nb->notebook.major_width = major_width;
5347 	nb->notebook.major_height = major_height;
5348 	nb->notebook.minor_width = minor_width;
5349 	nb->notebook.minor_height = minor_height;
5350 	nb->notebook.scroller_width = scroller_width;
5351 	nb->notebook.scroller_height = scroller_height;
5352 	nb->notebook.major_scroller_width = major_scroller_width;
5353 	nb->notebook.major_scroller_height = major_scroller_height;
5354 	nb->notebook.minor_scroller_width = minor_scroller_width;
5355 	nb->notebook.minor_scroller_height = minor_scroller_height;
5356 	nb->notebook.frame_width = frame_width;
5357 	nb->notebook.frame_height = frame_height;
5358 	nb->notebook.real_binding_width = real_binding_width;
5359 	nb->notebook.real_back_page_number = real_back_page_number;
5360     }
5361 }
5362 
5363 
5364 /*- NewPreferredGeometry ----------------------------------------------------
5365 
5366     Get Notebook's preferred geometry
5367 
5368     Parameters:
5369 	IN instigator		- child widget requesting geo request
5370 	IN desired		- instigator's requested geometry
5371 	OUT preferred		- w/h based on child's preferred sizes
5372 
5373 -----------------------------------------------------------------------------*/
5374 static Boolean
NewPreferredGeometry(XmNotebookWidget nb,Widget instigator,XtWidgetGeometry * desired,XtWidgetGeometry * preferred)5375 NewPreferredGeometry (
5376     XmNotebookWidget nb,
5377     Widget instigator,
5378     XtWidgetGeometry *desired,
5379     XtWidgetGeometry *preferred)
5380 {
5381     Dimension preferred_width, preferred_height;
5382 
5383     /* calculate preferred geometry information */
5384     CalcGeoInfo(nb, instigator, desired,
5385 	    &preferred_width, &preferred_height, FALSE);
5386 
5387     preferred->width = preferred_width;
5388     preferred->height = preferred_height;
5389     preferred->request_mode = CWHeight | CWWidth;
5390 
5391     return(!((preferred->width == nb->core.width) &&
5392 	     (preferred->height == nb->core.height)));
5393 }
5394 
5395 
5396 /*- AdjustGeometry ----------------------------------------------------------
5397 
5398         Adjust notebook's children sizes based on the Notebook's width
5399 	and height.
5400 
5401 	The minimum width needed is determined by the following:
5402 	   1. page and status are minimized until they reach XmNbackPageWidth
5403 	   2. binding is minimized
5404 	   3. major tabs are minimized
5405 	   4. page scroller is minimized
5406 	   5. back pages and frame are clipped
5407 
5408 	The minimum height needed is determined by the following:
5409 	   1. page is minimized
5410 	   2. status and page scroller are minimized
5411 	   3. minor tabs are minimized
5412 	   4. back pages and frame are clipped
5413 
5414 -----------------------------------------------------------------------------*/
5415 static void
AdjustGeometry(XmNotebookWidget nb,Widget instigator,XtWidgetGeometry * desired)5416 AdjustGeometry (
5417     XmNotebookWidget nb,
5418     Widget instigator,
5419     XtWidgetGeometry *desired)
5420 {
5421     Dimension ideal_width,ideal_height;
5422 
5423     /* the value min is the minimum width/height that the Notebook can be
5424        after a component is reduced to its minimum */
5425     Dimension min;
5426 
5427     /* calculate preferred geometry information */
5428     CalcGeoInfo(nb, instigator, desired, &ideal_width, &ideal_height, TRUE);
5429 
5430     /* adjust children's width */
5431     /* Notebook's width is bigger than ideal width */
5432     if (nb->core.width > ideal_width)
5433 	nb->notebook.page_width += nb->core.width - ideal_width;
5434 
5435     /* Notebook's width is smaller than ideal width */
5436     else if (nb->core.width < ideal_width)
5437     {
5438 	/* minimize the page area */
5439 	min = ideal_width - nb->notebook.page_width +
5440 	      nb->notebook.scroller_width;
5441         if (nb->core.width >= min)
5442 	    nb->notebook.page_width = nb->core.width -
5443 			(min - nb->notebook.scroller_width);
5444 	else if (nb->core.width < min)
5445 	{
5446 	    nb->notebook.page_width = nb->notebook.scroller_width;
5447 	    if (nb->notebook.orientation == XmHORIZONTAL)
5448 	    {
5449 		/* minimize the binding area */
5450 		min -= nb->notebook.real_binding_width;
5451 		if (nb->core.width >= min)
5452 		    nb->notebook.real_binding_width = nb->core.width - min;
5453 		else
5454 		{
5455 		    /* minimize major tabs */
5456 		    nb->notebook.real_binding_width = 0;
5457 		    min -= nb->notebook.major_width;
5458 		    if (nb->core.width > min)
5459 			nb->notebook.major_width = nb->core.width - min;
5460 		    else
5461 			nb->notebook.major_width = 0;
5462 		}
5463 	    }
5464 	    else
5465 	    {
5466 		/* minimize minor tabs */
5467 		min -= nb->notebook.minor_width;
5468 		if (nb->core.width > min)
5469 		    nb->notebook.minor_width = nb->core.width - min;
5470 		else
5471 		    nb->notebook.minor_width = 0;
5472 	    }
5473 	}
5474     }
5475 
5476     /* adjust children's height */
5477     /* Notebook's height is bigger than ideal height */
5478     if (nb->core.height > ideal_height)
5479 	nb->notebook.page_height += nb->core.height - ideal_height;
5480 
5481     /* Notebook's height is smaller than ideal height */
5482     else if (nb->core.height < ideal_height)
5483     {
5484 	/* minimize the page area */
5485 	min = ideal_height - nb->notebook.page_height;
5486         if (nb->core.height >= min)
5487 	    nb->notebook.page_height = nb->core.height - min;
5488 	else if (nb->core.height < min)
5489 	{
5490 	    /* minimize the page scroller area */
5491 	    nb->notebook.page_height = 0;
5492 	    min -= nb->notebook.scroller_height;
5493 	    if (nb->core.height >= min)
5494 		nb->notebook.scroller_height = nb->notebook.status_height =
5495 			nb->core.height - min;
5496 	    else
5497 	    {
5498 		nb->notebook.scroller_height = nb->notebook.status_height = 0;
5499 		if (nb->notebook.orientation == XmVERTICAL)
5500 		{
5501 		    /* minimize the binding area */
5502 		    min -= nb->notebook.real_binding_width;
5503 		    if (nb->core.height >= min)
5504 			nb->notebook.real_binding_width = nb->core.height - min;
5505 		    else
5506 		    {
5507 			/* minimize major tabs */
5508 			nb->notebook.real_binding_width = 0;
5509 			min -= nb->notebook.major_height;
5510 			if (nb->core.height > min)
5511 			    nb->notebook.major_height = nb->core.height - min;
5512 			else
5513 			    nb->notebook.major_height = 0;
5514 		    }
5515 		}
5516 		else
5517 		{
5518 		    /* minimize minor tabs */
5519 		    min -= nb->notebook.minor_height;
5520 		    if (nb->core.height > min)
5521 			nb->notebook.minor_height = nb->core.height - min;
5522 		    else
5523 			nb->notebook.minor_height = 0;
5524 		}
5525 	    }
5526 	}
5527     }
5528 
5529     /* Calculate status w/h based on page,margin,& scroller w/h */
5530     nb->notebook.status_width = MAX(0,(int)(nb->notebook.page_width -
5531 	nb->notebook.margin_width - nb->notebook.scroller_width));
5532     nb->notebook.status_height = nb->notebook.scroller_height =
5533 	MAX(nb->notebook.status_height, nb->notebook.scroller_height);
5534 
5535     /* Calculate the notebook frame size based on page size,shadows,& margins*/
5536       nb->notebook.frame_width = nb->notebook.page_width +
5537                    (nb->notebook.shadow_thickness * 2) +
5538                    (nb->notebook.margin_width * 2) + 1;
5539       nb->notebook.frame_height = nb->notebook.page_height + nb->notebook.status_height +
5540                    (nb->notebook.shadow_thickness * 2) +
5541                    (nb->notebook.margin_height * 3) + 1;
5542 
5543 }
5544 
5545 
5546 
5547 /*****************************************************************************
5548  *                                                                           *
5549  *			   Child Managing Functions			     *
5550  *                                                                           *
5551  *****************************************************************************/
5552 
5553 
5554 /*- SetLastPageNumber ----------------------------------------------------
5555 
5556     Sets XmNlastPageNumber if no explicit last page number was set,
5557     and updates navigators.
5558 
5559     Uses instance state:
5560 	dynamic_last_page_num		,True, if no explicit setting
5561 
5562     Called from:
5563 	AssignDefaultPageNumber		,when children are managed
5564 	ConstraintSetValues		,when a child page # is changed
5565 
5566     Return:
5567 	True, if last_page_number changed. Otherwise, False.
5568 
5569 -----------------------------------------------------------------------------*/
5570 static Boolean
SetLastPageNumber(XmNotebookWidget nb,int last_page_number)5571 SetLastPageNumber (
5572     XmNotebookWidget nb,
5573     int last_page_number)
5574 {
5575     if (nb->notebook.dynamic_last_page_num
5576     && last_page_number > nb->notebook.last_page_number)
5577 	{
5578 	nb->notebook.last_page_number = last_page_number;
5579 	UpdateNavigators(nb);
5580 	return(True);
5581 	}
5582     return(False);
5583 }
5584 
5585 
5586 /*- AssignDefaultPageNumber -------------------------------------------------
5587 
5588         assign a default page number to those children who did not get
5589 	from the application.
5590 
5591 	When a page is managed without a page number, the Notebook provides
5592 	the page with the smallest unallocated page number that is greater
5593 	than or equal to the first page number and is greater than the last
5594 	allocated page number. When a tab or a status area is managed without
5595 	a page number, the widget gets the page number of the most recently
5596 	managed page that does not have the same type of child. If the page
5597 	does have the same type of child, however, the Notebook associates the
5598 	child with the next page whose page number is one greater than the
5599 	most recently managed one. The Notebook, then, assumes the new page
5600 	number is occupied. The next subsequent page without a page number
5601 	will not receive this number. The default page number that the Notebook
5602 	generates can exceed the last page number, which makes those page
5603 	inaccessable by the user.
5604 
5605 -----------------------------------------------------------------------------*/
5606 static Boolean
AssignDefaultPageNumber(XmNotebookWidget nb)5607 AssignDefaultPageNumber (
5608     XmNotebookWidget nb)
5609 {
5610     XmNotebookConstraint nc;
5611     Widget child;
5612     int i, last_page_number;
5613 
5614     /* initialize */
5615     last_page_number = nb->notebook.first_page_number;
5616 
5617     /* for all children */
5618     for (i = 0; i < nb->composite.num_children; i++)
5619 	{
5620 	child = nb->composite.children[i];
5621 	nc = NotebookConstraint(child);
5622 
5623 	/* for all managed children */
5624 	if (XtIsManaged(child))
5625 	    {
5626 	    /* assign a default page number */
5627 	    if (nc->page_number == XmUNSPECIFIED_PAGE_NUMBER)
5628 		{
5629 		if (NB_IS_CHILD_PAGE(nc->child_type))
5630 		    {
5631 		    nc->page_number = GetNextAvailPageNum(nb, i);
5632 		    nb->notebook.last_alloc_num = nc->page_number;
5633 		    }
5634 		else if (NB_IS_CHILD_MAJOR(nc->child_type) ||
5635 		         NB_IS_CHILD_MINOR(nc->child_type) ||
5636 		         NB_IS_CHILD_STATUS(nc->child_type))
5637 		    {
5638 		    if (GetChildWidget(nb, nb->notebook.last_alloc_num,
5639 					    nc->child_type))
5640 			{
5641 			nc->page_number = GetNextAvailPageNum(nb, i);
5642 			nb->notebook.last_alloc_num = nc->page_number;
5643 			}
5644 		    else
5645 			nc->page_number = nb->notebook.last_alloc_num;
5646 		    }
5647 		}
5648 	    else
5649 		nb->notebook.last_alloc_num = nc->page_number;
5650 
5651 	    /* update the last_page_number */
5652 	    if (NB_IS_CHILD_PAGE(nc->child_type)
5653 	    || NB_IS_CHILD_TAB(nc->child_type)
5654 	    || NB_IS_CHILD_STATUS(nc->child_type))
5655 		{
5656 		ASSIGN_MAX(last_page_number, nc->page_number);
5657 		}
5658 	    } /* if */
5659 	} /* for */
5660     return(SetLastPageNumber(nb, last_page_number));
5661 }
5662 
5663 
5664 /*- SetActiveChildren ------------------------------------------------------
5665 
5666     Determine which children should be active.
5667 
5668     Active children are all managed scrollers and managed pages, status
5669     areas, and tabs which are within the page number range and not
5670     duplicated or later matched ones if duplicated.
5671 
5672     Uses instance state:
5673 	first_page_number
5674 	last_page_number
5675 
5676     Updates child constraint "active" field
5677 	FALSE, if child is NOT managed or
5678 		  child page # less than notebook.first_page_number or
5679 		  child page # greater than notebook.last_page_number or
5680 		  child page # duplicated by a child of the same type
5681 	TRUE,  otherwise
5682 
5683 
5684 -----------------------------------------------------------------------------*/
5685 static void
SetActiveChildren(XmNotebookWidget nb)5686 SetActiveChildren (
5687     XmNotebookWidget nb)
5688 {
5689     Widget child;
5690     XmNotebookConstraint nc;
5691     XmNotebookConstraint last = NULL;		/* initial previous child */
5692     unsigned char type = XmNONE;		/* initial previous type */
5693     int num  = XmUNSPECIFIED_PAGE_NUMBER;	/* initial previous page */
5694     int i;
5695 
5696     for (i = 0; i < nb->composite.num_children; i++)
5697 	{
5698 	child = nb->composite.children[i];
5699 	nc = NotebookConstraint(child);
5700 	if (XtIsManaged(child)
5701 	    && nc->page_number >= nb->notebook.first_page_number
5702 	    && nc->page_number <= nb->notebook.last_page_number)
5703 	    {
5704 	    if (last)
5705 		last->active = !(nc->child_type == type
5706 				&& nc->page_number == num);
5707 	    last = nc;
5708 	    type = nc->child_type;
5709 	    num = nc->page_number;
5710 	    }
5711 	else /* NOT managed or NOT (1st page) <= (page #) <= (last page #) */
5712 	    {
5713 	    nc->active = False;
5714 	    }
5715 	}
5716     if (last)
5717 	last->active = True;
5718 }
5719 
5720 
5721 /*- CompareChildren ---------------------------------------------------------
5722 
5723         Compares children, used for qsort() in SortChildren.
5724 
5725 -----------------------------------------------------------------------------*/
5726 static int
CompareChildren(XmConst void * a,XmConst void * b)5727 CompareChildren (
5728     XmConst void *a,
5729     XmConst void *b)
5730 {
5731     XmNotebookConstraint ac = NotebookConstraint(*((Widget *)a));
5732     XmNotebookConstraint bc = NotebookConstraint(*((Widget *)b));
5733     int cmp;
5734 
5735     /* Compare page numbers */
5736     cmp = ac->page_number - bc->page_number;
5737 
5738     /* Compare child types, if page numbers are same */
5739     if (!cmp)
5740 	cmp = ac->child_type - bc->child_type;
5741 
5742     /* Compare position in the array, if child types are the same */
5743     if (!cmp)
5744 	cmp = (unsigned long)a - (unsigned long)b;
5745 
5746     return cmp;
5747 }
5748 
5749 
5750 /*- SortChildren ------------------------------------------------------------
5751 
5752         Sorts children by page number and type.
5753 
5754 	Assumptions:
5755 		Previously created children are already sorted,
5756 		and newly created children are at the end of the
5757 		composite.children list.
5758 
5759 -----------------------------------------------------------------------------*/
5760 static void
SortChildren(XmNotebookWidget nb)5761 SortChildren (
5762     XmNotebookWidget nb)
5763 {
5764 
5765 
5766     qsort(nb->composite.children, nb->composite.num_children,
5767             sizeof(Widget), CompareChildren);
5768 
5769     SetActiveChildren(nb);
5770 }
5771 
5772 
5773 /*- RepositionChild ---------------------------------------------------------
5774 
5775         Repositions a childs position in composite array using an
5776         insertion method.
5777 
5778 -----------------------------------------------------------------------------*/
5779 static void
RepositionChild(XmNotebookWidget nb,Widget child)5780 RepositionChild (
5781     XmNotebookWidget nb,
5782     Widget child)
5783 {
5784     XmNotebookConstraint rnc = NotebookConstraint(child);
5785     XmNotebookConstraint nc;            /* temp comparator value */
5786     Widget w;                           /* temp comparator value */
5787     int cmp;                            /* temp comparator value */
5788     int cur_pos = -1;                   /* position of changing child */
5789     int ins_pos = -1;                   /* position to insert child */
5790     int i;                              /* counter */
5791 
5792     /* nothing to do, if there is only one child in array */
5793     if (nb->composite.num_children == 1)
5794         return;
5795 
5796     for (i = 0; i < nb->composite.num_children; i++)
5797         {
5798         w = nb->composite.children[i];
5799         nc = NotebookConstraint(w);
5800         if (rnc == nc)
5801             cur_pos = i;
5802         else if (ins_pos < 0)
5803             {
5804             cmp = rnc->page_number - nc->page_number;
5805             if (!cmp) cmp = rnc->child_type - nc->child_type;
5806             if (!cmp) cmp = (unsigned long)child - (unsigned long)w;
5807             if (cmp < 0)
5808                 ins_pos = i; /* should be inserted before this element */
5809             }
5810         } /* for */
5811 
5812     /* error, unable to locate repositioning child in array??? */
5813     if (cur_pos < 0)
5814         return;
5815 
5816     /* found no one less than, move others down, and insert at last position */
5817     if (ins_pos < 0)
5818         {
5819         for (i = cur_pos; i < nb->composite.num_children -1; i++)
5820             nb->composite.children[i] = nb->composite.children[i+1];
5821         nb->composite.children[nb->composite.num_children -1] = child;
5822         }
5823     /* found new position above, move others down, and then insert */
5824     else if (cur_pos < ins_pos)
5825         {
5826         for (i = cur_pos; i < ins_pos -1; i++)
5827             nb->composite.children[i] = nb->composite.children[i+1];
5828         nb->composite.children[ins_pos -1] = child;
5829         }
5830     /* found new position below, move others up, and then insert */
5831     else if (cur_pos > ins_pos)
5832         {
5833         for (i = cur_pos; i > ins_pos; i--)
5834             nb->composite.children[i] = nb->composite.children[i-1];
5835         nb->composite.children[ins_pos] = child;
5836         }
5837 }
5838 
5839 
5840 /*- GetNextAvailPageNum -----------------------------------------------------
5841 
5842         Finds out the next available page number for allocating it to
5843 	a newly created page or other child.
5844 
5845 -----------------------------------------------------------------------------*/
5846 static int
GetNextAvailPageNum(XmNotebookWidget nb,int last)5847 GetNextAvailPageNum(
5848     XmNotebookWidget nb,
5849     int last)
5850 {
5851     XmNotebookConstraint nc;
5852     Widget child;
5853     int i, avail;
5854 
5855     avail = nb->notebook.last_alloc_num;
5856     for (i = 0; i < last; i++)
5857     {
5858 	child = nb->composite.children[i];
5859 	nc = NotebookConstraint(child);
5860 	if (XtIsManaged(child) && nc->page_number == avail)
5861 	    avail++;
5862     }
5863     return avail;
5864 }
5865 
5866 
5867 /*- GetChildWidget ---------------------------------------------------------
5868 
5869         Finds the later matched child widget of the specified type.
5870 	It returns NULL if not found.
5871 
5872 -----------------------------------------------------------------------------*/
5873 static Widget
GetChildWidget(XmNotebookWidget nb,int page_number,unsigned char child_type)5874 GetChildWidget(
5875     XmNotebookWidget nb,
5876     int page_number,
5877     unsigned char child_type)
5878 {
5879     XmNotebookConstraint nc;
5880     Widget child, this_w;
5881     int i;
5882 
5883     this_w = NULL;
5884     for (i = 0; i < nb->composite.num_children; i++)
5885     {
5886         child = nb->composite.children[i];
5887         nc = NotebookConstraint(child);
5888 	if (nc->page_number == page_number && nc->child_type == child_type)
5889 	    {
5890 	    this_w = child;
5891 	    }
5892 	else
5893 	    {
5894 	    /* Skip remaining array once last matching child is found */
5895 	    if (this_w)
5896 		break;
5897 	    }
5898     }
5899     return this_w;
5900 }
5901 
5902 
5903 /*- GotoPage ---------------------------------------------------------------
5904 
5905         Places the specified page on top.
5906 
5907 	If the specified page IS currently on top nothing is done.
5908 	Otherwise,
5909 	    - the XmNpageChangedCallback is called. During which
5910 	      notebook.in_callback is set to True. This is checked
5911 	      in XmNotebook:ConstraintSetValues() to avoid performing
5912 	      layout at that time.
5913 	    - navigators are updated
5914 	    - relayout is performed
5915 
5916 	Called from:
5917 		SetValues(), when notebook.current_page_number is set
5918 		TabPressed(), when tabs are activated
5919 		PageMove(), when ScrollFrame trait navigation is triggered
5920 
5921 -----------------------------------------------------------------------------*/
5922 static void
GotoPage(XmNotebookWidget nb,int page_number,XEvent * event,int reason)5923 GotoPage(
5924     XmNotebookWidget nb,
5925     int page_number,
5926     XEvent *event,
5927     int reason)
5928 {
5929     XmNotebookCallbackStruct call_value;
5930     Dimension save_width, save_height;
5931     Widget old_top_major, old_first_major;
5932     Widget old_top_minor, old_first_minor;
5933     int prev_page = nb->notebook.current_page_number;
5934 
5935 
5936     /* Don't bother when the page number is out of the page number
5937        range, or if it is same as the old page number */
5938     if (   page_number == nb->notebook.current_page_number
5939 	|| page_number < nb->notebook.first_page_number
5940 	|| page_number > nb->notebook.last_page_number)
5941 	return;
5942 
5943     /* Save the notebook's size before invoking the callback */
5944     save_width = XtWidth(nb);
5945     save_height = XtHeight(nb);
5946 
5947     /* Set the NEW current page number */
5948     nb->notebook.current_page_number = page_number;
5949 
5950     /* Invoke the XmNpageChangedCallback, if any exist */
5951     if ((XtHasCallbacks((Widget)nb, XmNpageChangedCallback)
5952 			    == XtCallbackHasSome))
5953 	{
5954 	call_value.reason 	    = reason;
5955 	call_value.event 	    = event;
5956 	call_value.page_number 	    = page_number;
5957 	call_value.page_widget 	    = GetChildWidget(nb, page_number, XmPAGE);
5958 	call_value.prev_page_number = prev_page;
5959 	call_value.prev_page_widget = GetChildWidget(nb, prev_page, XmPAGE);
5960 
5961 	/* Mark that the callback is being called and when it finishes */
5962 	nb->notebook.in_callback = True;
5963 	XtCallCallbackList((Widget)nb, nb->notebook.page_change_callback,
5964 			    &call_value);
5965 	nb->notebook.in_callback = False;
5966 	}
5967 
5968     /* Tell all navigators about our page change */
5969     UpdateNavigators(nb);
5970 
5971     /* If there is any visual change caused by the callback then
5972 	relayout and redisplay children */
5973     if (save_width != XtWidth(nb) || save_height != XtHeight(nb))
5974 	{
5975         LayoutChildren(nb, NULL);
5976 	if (XtIsRealized((Widget)nb))
5977             XClearArea(XtDisplay(nb),XtWindow(nb),0,0,0,0,True);
5978 	}
5979     /* Otherwise just relayout children */
5980     else
5981 	{
5982 	/* Save top tab pointers */
5983 	old_top_major = nb->notebook.top_major;
5984 	old_first_major = nb->notebook.first_major;
5985 	old_top_minor = nb->notebook.top_minor;
5986 	old_first_minor = nb->notebook.first_minor;
5987 
5988 	/* Reset tab pointers */
5989 	ResetTopPointers(nb, XmPAGE, 0);
5990 
5991 	/* Layout children */
5992 	LayoutPages(nb, NULL);
5993 
5994 	if (   old_top_major != nb->notebook.top_major
5995 	    || old_first_major != nb->notebook.first_major)
5996 	    LayoutMajorTabs(nb, NULL);
5997 
5998 	if (   old_top_minor != nb->notebook.top_minor
5999 	    || old_first_minor != nb->notebook.first_minor)
6000 	    LayoutMinorTabs(nb, NULL);
6001 	}
6002 
6003 
6004 }
6005 
6006 
6007 
6008 /*****************************************************************************
6009  *                                                                           *
6010  *                            utility functions                              *
6011  *                                                                           *
6012  *****************************************************************************/
6013 
6014 
6015 /*- ShowChild ---------------------------------------------------------------
6016 
6017         Change the dimensional aspects of a child, and display it.
6018 
6019 -----------------------------------------------------------------------------*/
6020 static void
ShowChild(Widget child,Widget instigator,int x,int y,int width,int height)6021 ShowChild (
6022     Widget child,
6023     Widget instigator,
6024     int x,
6025     int y,
6026     int width,
6027     int height)
6028 {
6029     int border_width;
6030 
6031     /* adjust width and height and calculate border_width */
6032     border_width = child->core.border_width;
6033     width -= border_width * 2;
6034     height -= border_width * 2;
6035     /* Since width and height can potentially be 0, need to check
6036        that they aren't negative after subtracting the border */
6037     if (width <= 0)
6038 	width = 1, border_width = 0;
6039     if (height <= 0)
6040 	height = 1, border_width = 0;
6041 
6042     /* Configure the object */
6043     if (child == instigator)
6044 	{
6045 	/* if this child is making a geometry request */
6046 	XtX(child) = x;
6047 	XtY(child) = y;
6048 	XtWidth(child) = width;
6049 	XtHeight(child) = height;
6050 	}
6051     else
6052 	{
6053 	/* otherwise, configure the child */
6054 	XmeConfigureObject(child,
6055 				(Position)x,
6056 				(Position)y,
6057 				(Dimension)width,
6058 				(Dimension)height,
6059 				(Dimension)border_width);
6060 	}
6061 }
6062 
6063 
6064 /*- HideChild ---------------------------------------------------------------
6065 
6066         Hide a child by placing it to invisible place.
6067 
6068 -----------------------------------------------------------------------------*/
6069 static void
HideChild(Widget child,Widget instigator)6070 HideChild (
6071     Widget child,
6072     Widget instigator)
6073 {
6074     int x = - (int)(child->core.width + child->core.border_width * 2);
6075     int y = - (int)(child->core.height + child->core.border_width * 2);
6076 
6077     /* if the child is already invisible, don't bother */
6078     if (!NB_IS_VISIBLE(child))
6079 	return;
6080 
6081     /* place the child to (x, y) */
6082     if (child == instigator)
6083 	{
6084 	/* if child is making a geometry request */
6085 	XtX(child) = (Position)x;
6086 	XtY(child) = (Position)y;
6087 	}
6088     else
6089 	{
6090 	/* otherwise, configure the child */
6091 	XmeConfigureObject(child,
6092 			(Position)x,
6093 			(Position)y,
6094 			child->core.width,
6095 			child->core.height,
6096 			child->core.border_width);
6097 	}
6098 }
6099 
6100 
6101 /*- HideShadowedTab ---------------------------------------------------------
6102 
6103         Clear tab child and its surrounding frame shadow
6104 
6105 -----------------------------------------------------------------------------*/
6106 static void
HideShadowedTab(XmNotebookWidget nb,Widget child)6107 HideShadowedTab (
6108     XmNotebookWidget nb,
6109     Widget child)
6110 {
6111     int x, y, width, height;
6112 
6113     if (XtIsRealized((Widget)nb) && child && NB_IS_VISIBLE(child))
6114     {
6115         x = child->core.x - nb->notebook.shadow_thickness;
6116         y = child->core.y - nb->notebook.shadow_thickness;
6117         width = child->core.width + nb->notebook.shadow_thickness * 2 + 1;
6118         height = child->core.height + nb->notebook.shadow_thickness * 2 + 1;
6119 	if ( nb->notebook.shadow_thickness )
6120           XClearArea(XtDisplay(nb), XtWindow(nb), x, y, width, height, True);
6121 	else
6122           XClearArea(XtDisplay(nb), XtWindow(nb), x - 1 , y - 1, width + 1, height + 1, True);
6123     }
6124 }
6125 
6126 
6127 
6128 /*****************************************************************************
6129  *                                                                           *
6130  *                             callback functions                            *
6131  *                                                                           *
6132  *****************************************************************************/
6133 
6134 
6135 /*- FlipTabs ----------------------------------------------------------------
6136 
6137         callback function for events for tab scrolling
6138 
6139 -----------------------------------------------------------------------------*/
6140 
6141 /*ARGSUSED*/
6142 static void
FlipTabs(Widget w,XtPointer data,XtPointer call_data)6143 FlipTabs (
6144     Widget w,
6145     XtPointer data,		/* unused */
6146     XtPointer call_data)	/* unused */
6147 {
6148     XmNotebookWidget nb = (XmNotebookWidget)XtParent(w);
6149     Widget old_first_major, old_first_minor;
6150     Widget cfw = XmGetFocusWidget((Widget)nb);
6151 
6152     /* save tab pointers */
6153     old_first_major = nb->notebook.first_major;
6154     old_first_minor = nb->notebook.first_minor;
6155 
6156     /* request to reset notebook.first_major */
6157     if (w == nb->notebook.next_major)
6158 	ResetTopPointers(nb, XmMAJOR_TAB_SCROLLER, _NEXT);
6159     else if (w == nb->notebook.prev_major)
6160 	ResetTopPointers(nb, XmMAJOR_TAB_SCROLLER, _PREVIOUS);
6161     else if (w == nb->notebook.next_minor)
6162 	ResetTopPointers(nb, XmMINOR_TAB_SCROLLER, _NEXT);
6163     else if (w == nb->notebook.prev_minor)
6164 	ResetTopPointers(nb, XmMINOR_TAB_SCROLLER, _PREVIOUS);
6165 
6166     /* redraw tabs if necessary */
6167     if (old_first_major != nb->notebook.first_major)
6168 	LayoutMajorTabs(nb, NULL);
6169     if (old_first_minor != nb->notebook.first_minor)
6170 	LayoutMinorTabs(nb, NULL);
6171 
6172     /*
6173      * If focus was a tab widget that is now hidden due to tab scrolling then
6174      * move focus to the next visible tab
6175      */
6176     if (cfw && XtParent(cfw) == (Widget)nb)
6177 	{
6178 	unsigned char ct = NotebookConstraint(cfw)->child_type;
6179 
6180 	if (NB_IS_HIDDEN(cfw) && NB_IS_CHILD_TAB(ct))
6181 	    {
6182 	    if ((w == nb->notebook.next_major) && NB_IS_CHILD_MAJOR(ct))
6183 		XmProcessTraversal(
6184 		    (Widget) GetNextTab(nb, XmMAJOR_TAB, 0, _FIRST_VISIBLE),
6185 		    XmTRAVERSE_CURRENT);
6186 	    else if (w == nb->notebook.prev_major && NB_IS_CHILD_MAJOR(ct))
6187 		XmProcessTraversal(
6188 		    (Widget) GetNextTab(nb, XmMAJOR_TAB, 0, _LAST_VISIBLE),
6189 		    XmTRAVERSE_CURRENT);
6190 	    else if (w == nb->notebook.next_minor && NB_IS_CHILD_MINOR(ct))
6191 		XmProcessTraversal(
6192 		    (Widget) GetNextTab(nb, XmMINOR_TAB, 0, _FIRST_VISIBLE),
6193 		    XmTRAVERSE_CURRENT);
6194 	    else if (w == nb->notebook.prev_minor && NB_IS_CHILD_MINOR(ct))
6195 		XmProcessTraversal(
6196 		    (Widget) GetNextTab(nb, XmMINOR_TAB, 0, _LAST_VISIBLE),
6197 		    XmTRAVERSE_CURRENT);
6198 	    }
6199 	}
6200 }
6201 
6202 
6203 /*- TabPressed --------------------------------------------------------------
6204 
6205         callback function for events for tab push-buttons.
6206 
6207 -----------------------------------------------------------------------------*/
6208 static void
TabPressed(Widget w,XtPointer data,XtPointer call_data)6209 TabPressed (
6210     Widget w,
6211     XtPointer data,
6212     XtPointer call_data)
6213 {
6214     XmNotebookWidget nb = (XmNotebookWidget)XtParent(w);
6215     XmNotebookConstraint nc = NotebookConstraint(w);
6216     XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)call_data;
6217     int reason = (unsigned long)data;
6218 
6219     /* move to the selected page */
6220     GotoPage(nb, nc->page_number, cbs->event, reason);
6221 }
6222 
6223 
6224 
6225 /*****************************************************************************
6226  *                                                                           *
6227  *                Keyboard Traversal Functions & Action Procs                *
6228  *                                                                           *
6229  *****************************************************************************/
6230 
6231 
6232 /*- TraverseTab -------------------------------------------------------------
6233 
6234         action for moving the focus on tabs
6235 
6236 -----------------------------------------------------------------------------*/
6237 
6238 /*ARGSUSED*/
6239 static void
TraverseTab(Widget w,XEvent * event,String * params,Cardinal * num_params)6240 TraverseTab (
6241     Widget w,
6242     XEvent *event,		/* unused */
6243     String *params,
6244     Cardinal *num_params)
6245 {
6246     XmNotebookWidget nb = (XmNotebookWidget)w;
6247     XmNotebookConstraint nc;
6248     Widget first, last, next, prev, child = NULL;
6249     int traverse_to;
6250 
6251     /* Check error conditions */
6252     if (nb && XmIsNotebook(nb))
6253         child = XmGetFocusWidget(w);
6254     else
6255         while (nb && !(XmIsNotebook(nb)))
6256            {
6257            child = (Widget)nb;
6258            nb = (XmNotebookWidget)XtParent(child);
6259            }
6260     if (!nb || !child)
6261         return;
6262 
6263     if (!num_params || (*num_params != 1) || !params)
6264 	{
6265         XmeWarning(w, MESSAGE1);
6266         return;
6267 	}
6268 
6269     /* Only valid for major or minor tabs */
6270     if (!(nc = NotebookConstraint(child))
6271 	|| !(NB_IS_CHILD_MAJOR(nc->child_type)
6272 	   || NB_IS_CHILD_MINOR(nc->child_type)))
6273         return;
6274 
6275     if (_XmConvertActionParamToRepTypeId((Widget) nb,
6276 				 XmRID_NOTEBOOK_TRAVERSE_TAB_ACTION_PARAMS,
6277 				 params[0], False, &traverse_to) == False)
6278 	traverse_to = _HOME;
6279 
6280 
6281     /*
6282      * Make the traversal
6283      */
6284     if (traverse_to == _HOME)
6285 	{
6286 	/* Major HOME traversal */
6287 	first = GetNextTab(nb,nc->child_type,nc->page_number,_HOME);
6288 	if ((first) && NB_IS_HIDDEN(first))
6289 	    {
6290 	    if (NB_IS_CHILD_MAJOR(nc->child_type))
6291 	    	{
6292 		ResetTopPointers(nb,XmMAJOR_TAB_SCROLLER,_HOME);
6293 	        LayoutMajorTabs(nb, NULL);
6294 	        }
6295 	    else
6296 	        {
6297 		ResetTopPointers(nb,XmMINOR_TAB_SCROLLER,_HOME);
6298 		LayoutMinorTabs(nb, NULL);
6299 		}
6300 	    }
6301 	if (first)
6302 	    XmProcessTraversal(first,XmTRAVERSE_CURRENT);
6303 	}
6304 
6305     else if (traverse_to == _END)
6306 	{
6307 	last = GetNextTab(nb,nc->child_type,nc->page_number,_END);
6308 	if ((last) && NB_IS_HIDDEN(last))
6309 	    {
6310 	    if (NB_IS_CHILD_MAJOR(nc->child_type))
6311 	    	{
6312 		ResetTopPointers(nb,XmMAJOR_TAB_SCROLLER,_END);
6313 	    	LayoutMajorTabs(nb, NULL);
6314 	    	}
6315 	    else
6316 	    	{
6317 		ResetTopPointers(nb,XmMINOR_TAB_SCROLLER,_END);
6318 	    	LayoutMinorTabs(nb, NULL);
6319 	    	}
6320 	    }
6321 	if (last)
6322 	    XmProcessTraversal(last,XmTRAVERSE_CURRENT);
6323 	}
6324 
6325     else if (traverse_to == _PREVIOUS)
6326 	{
6327 	prev = GetNextTab(nb,nc->child_type,nc->page_number,_PREVIOUS);
6328 	if ((prev) && NB_IS_HIDDEN(prev))
6329 	    {
6330 	    if (NB_IS_CHILD_MAJOR(nc->child_type))
6331 		FlipTabs(
6332 		    (MaxIsRightUp(nb,nc->child_type)) ?
6333 		    nb->notebook.prev_major : nb->notebook.next_major,
6334 		    NULL,NULL);
6335 	    else
6336 		FlipTabs(
6337 		    (MaxIsRightUp(nb,nc->child_type)) ?
6338 		    nb->notebook.prev_minor : nb->notebook.next_minor,
6339 		    NULL,NULL);
6340 	    }
6341 	if (prev)
6342 	    XmProcessTraversal(prev, XmTRAVERSE_CURRENT);
6343 	}
6344 
6345     else if (traverse_to == _NEXT)
6346 	{
6347 	next = GetNextTab(nb,nc->child_type,nc->page_number,_NEXT);
6348         if ((next) && NB_IS_HIDDEN(next))
6349             {
6350             if (NB_IS_CHILD_MAJOR(nc->child_type))
6351                 FlipTabs(
6352 		    (MaxIsRightUp(nb,nc->child_type)) ?
6353 		    nb->notebook.next_major : nb->notebook.prev_major,
6354                     NULL,NULL);
6355             else
6356                 FlipTabs(
6357                     (MaxIsRightUp(nb,nc->child_type)) ?
6358 		    nb->notebook.next_minor : nb->notebook.prev_minor,
6359                     NULL,NULL);
6360             }
6361 	if (next)
6362 	    XmProcessTraversal(next, XmTRAVERSE_CURRENT);
6363 	}
6364 }
6365 
6366 
6367 /*- RedirectTraversal -------------------------------------------------------
6368 
6369         redirect traversal control trait
6370 
6371 			Focus From      Focus To        Focus Request
6372 	NEXT_TAB_GROUP  <anything>      MINOR           _CURRENT_VISIBLE MAJOR
6373 			MAJOR           <anything>      _CURRENT_VISIBLE MINOR
6374 	PREV_TAB_GROUP <anything>       MAJOR           _CURRENT_VISIBLE MINOR
6375 			MINOR           <anything>      _CURRENT_VISIBLE MAJOR
6376 
6377 
6378 -----------------------------------------------------------------------------*/
6379 
6380 /*ARGSUSED*/
6381 static Widget
RedirectTraversal(Widget old_focus,Widget new_focus,unsigned int focus_policy,XmTraversalDirection direction,unsigned int pass)6382 RedirectTraversal(
6383     Widget 		old_focus,
6384     Widget	       	new_focus,
6385     unsigned int	focus_policy,
6386     XmTraversalDirection direction,
6387     unsigned int	pass) /* unused */
6388 {
6389     unsigned char to_type = XmMAJOR_TAB, from_type = XmMAJOR_TAB;
6390     Widget to_child, from_child;
6391     Widget to_parent, from_parent;
6392     Widget new_focus_widget;
6393 
6394     /* If we're in pointer focus mode there's nothing to be done. */
6395     if ((focus_policy != XmEXPLICIT)
6396      || ((direction != XmTRAVERSE_NEXT_TAB_GROUP) &&
6397 	 (direction != XmTRAVERSE_PREV_TAB_GROUP)))
6398     return new_focus;
6399 
6400     /* Determine nearest notebook parent for the target. */
6401     to_parent = NULL;
6402     if ((to_child=new_focus))
6403 	{
6404 	if ((to_parent=XtParent(to_child)) == NULL)
6405 	    return new_focus;
6406 	while (!XmIsNotebook(to_parent))
6407 	    {
6408 	    to_child = to_parent;
6409 	    if ((to_parent=XtParent(to_child)) == NULL)
6410 		break;
6411 	    }
6412 	}
6413 
6414     /* Determine target child type. */
6415     if (to_parent)
6416 	to_type = NotebookConstraint(to_child)->child_type;
6417 
6418     /* Determine nearest notebook parent for the source. */
6419     from_parent = NULL;
6420     if ((from_child=old_focus))
6421 	{
6422         if ((from_parent = XtParent(from_child)) == NULL)
6423 	    return new_focus;
6424 	while (!XmIsNotebook(from_parent))
6425 	    {
6426 	    from_child = from_parent;
6427 	    if ((from_parent=XtParent(from_child)) == NULL)
6428 		break;
6429 	    }
6430 	}
6431 
6432     /* Determine source child type. */
6433     if (from_parent)
6434 	from_type = NotebookConstraint(from_child)->child_type;
6435 
6436     /*
6437      * Determine if we need to force traversal between major and
6438      * minor tabs (traverse to nearest tab to the current page)
6439      *
6440      * Note: If TO is NULL, then it is assumed that there is only
6441      * one TAB GROUP i.e., the Major/Minor tabs TAB GROUP
6442      */
6443     new_focus_widget = NULL;
6444 
6445     if (direction == XmTRAVERSE_NEXT_TAB_GROUP)
6446 	{
6447 	/* If FROM Minor with a NULL TO then GOTO Major */
6448         if (to_child == NULL && (from_parent && (from_type == XmMINOR_TAB)))
6449 	    new_focus_widget = GetNextTab((XmNotebookWidget)from_parent,
6450 					    XmMAJOR_TAB,0,_CURRENT_VISIBLE);
6451 
6452 	/* If FROM Major with any TO then GOTO Minor */
6453 	else if (from_parent && (from_type == XmMAJOR_TAB))
6454 	    new_focus_widget = GetNextTab((XmNotebookWidget)from_parent,
6455 					    XmMINOR_TAB,0,_CURRENT_VISIBLE);
6456 
6457 	/* If *NOT* FROM Major and TO Minor then GOTO Major */
6458 	else if (to_parent && (to_type == XmMINOR_TAB))
6459 	    new_focus_widget = GetNextTab((XmNotebookWidget)to_parent,
6460 					    XmMAJOR_TAB,0,_CURRENT_VISIBLE);
6461 
6462 	/* If TO Major with any FROM then GOTO Major */
6463 	else if (to_parent && (to_type == XmMAJOR_TAB))
6464 	    new_focus_widget = GetNextTab((XmNotebookWidget)to_parent,
6465                                             XmMAJOR_TAB,0,_CURRENT_VISIBLE);
6466 	}
6467     else /* if (direction == XmTRAVERSE_PREV_TAB_GROUP) */
6468 	{
6469 	/* If FROM Major with a NULL TO then GOTO Minor */
6470         if (to_child == NULL && (from_parent && (from_type == XmMAJOR_TAB)))
6471 	    new_focus_widget = GetNextTab((XmNotebookWidget)from_parent,
6472 					    XmMINOR_TAB,0,_CURRENT_VISIBLE);
6473 
6474         /* If FROM Minor with any TO and then GOTO Major */
6475 	else if (from_parent && (from_type == XmMINOR_TAB))
6476 	    new_focus_widget = GetNextTab((XmNotebookWidget)from_parent,
6477 					    XmMAJOR_TAB,0,_CURRENT_VISIBLE);
6478 
6479 	/* If *NOT* FROM Minor with TO Major then GOTO Major */
6480 	else if (to_parent && (to_type == XmMAJOR_TAB))
6481 	    new_focus_widget = GetNextTab((XmNotebookWidget)to_parent,
6482 					    XmMINOR_TAB,0,_CURRENT_VISIBLE);
6483 
6484 	/* If to a Minor then traverse to a Minor nearest the current page */
6485         else if (to_parent && (to_type == XmMINOR_TAB))
6486 	    new_focus_widget = GetNextTab((XmNotebookWidget)to_parent,
6487                                             XmMINOR_TAB,0,_CURRENT_VISIBLE);
6488 	}
6489 
6490     if (new_focus_widget && XmIsTraversable(new_focus_widget))
6491 	return new_focus_widget;
6492 
6493     return new_focus;
6494 }
6495 
6496 /*- GetNextTab --------------------------------------------------------------
6497 
6498         Get next tab to set focus to.
6499 
6500 	In Parameters:
6501 		child_type	XmMAJOR_TAB or XmMINOR_TAB
6502 		page_number	page number of interest
6503 		direction	traversal direction
6504         returns
6505 		next major || minor tab (can be NULL)
6506 
6507 -----------------------------------------------------------------------------*/
6508 static Widget
GetNextTab(XmNotebookWidget nb,unsigned char child_type,int page_number,unsigned char direction)6509 GetNextTab (
6510     XmNotebookWidget nb,
6511     unsigned char child_type,
6512     int page_number,
6513     unsigned char direction)
6514 {
6515     XmNotebookConstraint nc;
6516     Widget child;
6517     int i;
6518     Widget target;
6519     unsigned char target_dir;
6520     unsigned char target_child_type;
6521     Boolean  target_found;
6522     int top_major_page;
6523 
6524     if (NB_IS_CHILD_MAJOR(child_type) || NB_IS_CHILD_MINOR(child_type))
6525 	target_child_type = child_type;
6526     else
6527 	return(NULL);	/* Bad parameter */
6528 
6529     if (MaxIsRightUp(nb,target_child_type))
6530 	target_dir = direction;
6531     else
6532 	switch(direction)
6533 	{
6534 	case _PREVIOUS:
6535 	    target_dir = _NEXT;
6536 	    break;
6537 	case _NEXT:
6538 	    target_dir = _PREVIOUS;
6539 	    break;
6540 	default:
6541 	    target_dir = direction;
6542 	}
6543 
6544     /*
6545      * Attempt to return top tab
6546      */
6547     if (target_dir == _CURRENT_VISIBLE)
6548 	{
6549 	if (NB_IS_CHILD_MAJOR(child_type))
6550 	    {
6551 	    if ( (nb->notebook.top_major != NULL)
6552 	      && (NB_IS_VISIBLE(nb->notebook.top_major)))
6553 		return nb->notebook.top_major;
6554 	    else
6555 		target_dir = _FIRST_VISIBLE;
6556 	    }
6557 	else if (NB_IS_CHILD_MINOR(child_type))
6558 	    {
6559 	    if (  (nb->notebook.top_minor != NULL)
6560 	       && (NB_IS_VISIBLE(nb->notebook.top_minor)))
6561 		return nb->notebook.top_minor;
6562 	    else
6563 		target_dir = _FIRST_VISIBLE;
6564 	    }
6565 	}
6566 
6567     i = 0;
6568     target = NULL;
6569     target_found = False;
6570     if (NB_IS_CHILD_MAJOR(target_child_type))
6571 	{
6572 	while((!target_found) && (i < nb->composite.num_children))
6573 	  {
6574 	  child = nb->composite.children[i];
6575 	  nc = NotebookConstraint(child);
6576 	  if ((nc->active) && (NB_IS_CHILD_MAJOR(nc->child_type)))
6577 	    switch (target_dir)
6578 	    {
6579 	    case _HOME:
6580 		target = child;
6581 		target_found = True;
6582 		break;
6583 	    case _FIRST_VISIBLE:
6584 		if (NB_IS_VISIBLE(child))
6585 		    {
6586 		    target = child;
6587 		    target_found = True;
6588 		    }
6589 		break;
6590 	    case _LAST_VISIBLE:
6591 		if (NB_IS_VISIBLE(child))
6592 		    {
6593 		    target = child;
6594 		    }
6595 		break;
6596 	    case _PREVIOUS:
6597 		if (nc->page_number < page_number)
6598 		    target = child;
6599 		else
6600 		    target_found = True;
6601 		break;
6602 	    case _NEXT:
6603 		if (nc->page_number > page_number)
6604 		    {
6605 		    target = child;
6606 		    target_found = True;
6607 		    }
6608 		break;
6609             case _END:
6610 		target = child;
6611 	    } /* switch */
6612 	    i++;
6613 	  }   /* while  */
6614 	}     /* if     */
6615     else /* NB_IS_CHILD_MINOR(target_child_type) */
6616 	{
6617         top_major_page = nb->notebook.top_major ?
6618                 NotebookConstraint(nb->notebook.top_major)->page_number :
6619                 nb->notebook.first_page_number - 1;
6620 
6621 	while((!target_found) && (i < nb->composite.num_children))
6622           {
6623           child = nb->composite.children[i];
6624           nc = NotebookConstraint(child);
6625 	  if (NB_IS_CHILD_MAJOR(nc->child_type)
6626 	  && (nc->page_number > top_major_page))
6627 	    target_found = True;
6628 	  else
6629 	    if ((nc->active)
6630 		&& (NB_IS_CHILD_MINOR(nc->child_type))
6631 		&& (nc->page_number >= top_major_page))
6632               switch (target_dir)
6633               {
6634 	      case _HOME:
6635 		target = child;
6636 		target_found = True;
6637 	    	break;
6638 	      case _FIRST_VISIBLE:
6639 		if (NB_IS_VISIBLE(child))
6640 		    {
6641 		    target = child;
6642 		    target_found = True;
6643 		    }
6644 		break;
6645 	      case _LAST_VISIBLE:
6646 		if (NB_IS_VISIBLE(child))
6647 		    {
6648 		    target = child;
6649 		    }
6650 		break;
6651 	      case _PREVIOUS:
6652 		if (nc->page_number < page_number)
6653 		    target = child;
6654 		else
6655 		    target_found = True;
6656 		break;
6657 	      case _NEXT:
6658 		if (nc->page_number > page_number)
6659 		    {
6660 		    target = child;
6661 		    target_found = True;
6662 		    }
6663 		break;
6664 	      case _END:
6665 		target = child;
6666 	      } /* switch */
6667 	    i++;
6668 	  }     /* while  */
6669 	}       /* else   */
6670     return(target);
6671 }
6672 
6673 
6674 /*- MaxIsRightUp ------------------------------------------------------------
6675 
6676         returns
6677                 True,
6678                     if "<Key>osfRight" and "<Key>osfDown" mean "next"
6679                     and "<Key>osfLeft" and "<Key>osfUp" mean "prev"
6680 
6681                 False,
6682                     if "<Key>osfLeft" and "<Key>osfUp" mean "next"
6683                     and "<Key>osfRight" and "<Key>osfDown" mean "prev"
6684 
6685 -----------------------------------------------------------------------------*/
6686 static Boolean
MaxIsRightUp(XmNotebookWidget nb,unsigned char child_type)6687 MaxIsRightUp (
6688     XmNotebookWidget nb,
6689     unsigned char child_type)
6690 {
6691     return( (
6692 		(NB_IS_CHILD_MAJOR(child_type))
6693 	    &&  (
6694 		    (nb->notebook.back_page_pos == XmBOTTOM_RIGHT)
6695 		||  (
6696 			(nb->notebook.back_page_pos == XmBOTTOM_LEFT)
6697 		    &&  (nb->notebook.orientation == XmHORIZONTAL))
6698 		||
6699 		    (
6700 			(nb->notebook.back_page_pos == XmTOP_RIGHT)
6701 		    &&  (nb->notebook.orientation == XmVERTICAL))))
6702 	||  (
6703 		(NB_IS_CHILD_MINOR(child_type))
6704 	    &&  (
6705 		    (nb->notebook.back_page_pos == XmBOTTOM_RIGHT)
6706 		||  (
6707 			(nb->notebook.back_page_pos == XmBOTTOM_LEFT)
6708 		    &&  (nb->notebook.orientation == XmVERTICAL))
6709 		||  (
6710 			(nb->notebook.back_page_pos == XmTOP_RIGHT)
6711 		    &&  (nb->notebook.orientation == XmHORIZONTAL)))));
6712 }
6713 
6714 
6715 
6716 /*****************************************************************************
6717  *                                                                           *
6718  *                          Trait Stuff			      		     *
6719  *                                                                           *
6720  *****************************************************************************/
6721 
6722 
6723 /*- ScrollFrameInit ---------------------------------------------------------
6724 
6725 	ScrollFrame init trait method
6726 
6727 -----------------------------------------------------------------------------*/
6728 static void
ScrollFrameInit(Widget w,XtCallbackProc moveCB,Widget scrollable)6729 ScrollFrameInit (
6730     Widget w,
6731     XtCallbackProc moveCB,
6732     Widget scrollable)
6733 {
6734     XmNotebookWidget nb = (XmNotebookWidget)w;
6735 
6736     if (nb->notebook.scroll_frame_data != NULL)
6737 	return;
6738 
6739     nb->notebook.scroll_frame_data = (XmScrollFrameData)
6740         XtMalloc(sizeof(XmScrollFrameDataRec));
6741 
6742     nb->notebook.scroll_frame_data->num_nav_list = 0 ;
6743     nb->notebook.scroll_frame_data->nav_list = NULL ;
6744     nb->notebook.scroll_frame_data->num_nav_slots = 0 ;
6745 
6746     nb->notebook.scroll_frame_data->move_cb = moveCB ;
6747     nb->notebook.scroll_frame_data->scrollable = scrollable ;
6748 }
6749 
6750 
6751 /*- ScrollFrameGetInfo ------------------------------------------------------
6752 
6753         ScrollFrame getInfo trait method
6754 	Notebook is a 1 dimensional frame.
6755 
6756 -----------------------------------------------------------------------------*/
6757 static Boolean
ScrollFrameGetInfo(Widget w,Cardinal * dimension,Widget ** nav_list,Cardinal * num_nav_list)6758 ScrollFrameGetInfo (
6759     Widget w,
6760     Cardinal *dimension,
6761     Widget **nav_list,
6762     Cardinal *num_nav_list)
6763 {
6764     XmNotebookWidget nb = (XmNotebookWidget)w;
6765 
6766     if (dimension) *dimension = 1;  /* one dimensional frame */
6767 
6768     if (nb->notebook.scroll_frame_data != NULL)
6769 	{
6770         if (nav_list)
6771 	    *nav_list = nb->notebook.scroll_frame_data->nav_list;
6772         if (num_nav_list)
6773             *num_nav_list = nb->notebook.scroll_frame_data->num_nav_list;
6774 	}
6775 
6776     return( nb->notebook.scroll_frame_data != NULL );
6777 }
6778 
6779 
6780 /*- AddNavigator ------------------------------------------------------------
6781 
6782         ScrollFrame addNavigator trait method
6783 
6784 -----------------------------------------------------------------------------*/
6785 static void
AddNavigator(Widget w,Widget nav,Mask dimMask)6786 AddNavigator (
6787     Widget w,
6788     Widget nav,
6789     Mask dimMask)
6790 {
6791     XmNotebookWidget nb = (XmNotebookWidget)w;
6792     if (nb->notebook.scroll_frame_data != NULL)
6793 	_XmSFAddNavigator(w, nav, dimMask, nb->notebook.scroll_frame_data);
6794 }
6795 
6796 
6797 /*- RemoveNavigator ---------------------------------------------------------
6798 
6799         ScrollFrame removeNavigator trait method
6800 
6801 -----------------------------------------------------------------------------*/
6802 static void
RemoveNavigator(Widget w,Widget nav)6803 RemoveNavigator (
6804     Widget w,
6805     Widget nav)
6806 {
6807     XmNotebookWidget nb = (XmNotebookWidget)w;
6808 
6809     if (nb->notebook.scroll_frame_data != NULL)
6810 	_XmSFRemoveNavigator(w, nav, nb->notebook.scroll_frame_data);
6811 }
6812 
6813 
6814 /*- PageMove ----------------------------------------------------------------
6815 
6816 	Callback for the value changes of navigators.
6817 
6818 -----------------------------------------------------------------------------*/
6819 
6820 /*ARGSUSED*/
6821 static void
PageMove(Widget w,XtPointer data,XtPointer call_data)6822 PageMove (
6823     Widget w,
6824     XtPointer data,
6825     XtPointer call_data)	/* unused */
6826 {
6827     /* w is a navigator widget */
6828     XmNotebookWidget nb = (XmNotebookWidget)data;
6829     XmNavigatorDataRec nav_data;
6830     XmNavigatorTrait navigatorT;
6831     int reason;
6832 
6833     /* Get the new navigator value using the trait getValue */
6834     nav_data.valueMask = NavValue;
6835 
6836     /* Check to ensure navigator is ok */
6837     if ((navigatorT=NB_NAVIGATOR(w)) == NULL || navigatorT->getValue == NULL)
6838 	return;
6839     navigatorT->getValue(w, &nav_data);
6840 
6841     /* Determine the callback reason */
6842     if (nav_data.value.x > nb->notebook.current_page_number)
6843         reason = XmCR_PAGE_SCROLLER_INCREMENT;
6844     else if (nav_data.value.x < nb->notebook.current_page_number)
6845         reason = XmCR_PAGE_SCROLLER_DECREMENT;
6846     else
6847         reason = XmCR_NONE;
6848 
6849     /* Look at the kind of navigator and make the appropriate move */
6850     if ((nav_data.dimMask & NavigDimensionX) && (reason != XmCR_NONE))
6851 	GotoPage(nb, nav_data.value.x, NULL, reason);
6852 
6853 }
6854 
6855 
6856 /*- UpdateNavigators --------------------------------------------------------
6857 
6858         Update navigators due to page change
6859 
6860 -----------------------------------------------------------------------------*/
6861 static void
UpdateNavigators(XmNotebookWidget nb)6862 UpdateNavigators (
6863     XmNotebookWidget nb)
6864 {
6865     XmNavigatorDataRec nav_data;
6866 
6867     /* update navigators */
6868     nav_data.value.x = nb->notebook.current_page_number;
6869     nav_data.minimum.x = nb->notebook.first_page_number;
6870     nav_data.maximum.x = nb->notebook.last_page_number + 1;
6871     nav_data.slider_size.x = 1;
6872     nav_data.increment.x = 1;
6873     nav_data.page_increment.x = 1;
6874     nav_data.dimMask = NavigDimensionX;
6875     nav_data.valueMask = NavValue | NavMinimum | NavMaximum |
6876 	NavSliderSize | NavIncrement | NavPageIncrement;
6877 
6878     _XmSFUpdateNavigatorsValue((Widget)nb, &nav_data, True);
6879 
6880     /* Control arrow sensitivity if using default page scroller */
6881     if (nb->notebook.scroller_status == DEFAULT_USED)
6882 	{
6883 	if ((nb->notebook.current_page_number ==nb->notebook.last_page_number)
6884 	&& (nb->notebook.current_page_number ==nb->notebook.first_page_number))
6885 	   XtVaSetValues(nb->notebook.scroller_child,XmNarrowSensitivity,
6886 		XmARROWS_INSENSITIVE, NULL);
6887 	else if (nb->notebook.current_page_number ==
6888 					    nb->notebook.last_page_number)
6889 	   XtVaSetValues(nb->notebook.scroller_child,XmNarrowSensitivity,
6890 		XmARROWS_DECREMENT_SENSITIVE, NULL);
6891 	else if (nb->notebook.current_page_number ==
6892 					    nb->notebook.first_page_number)
6893 	   XtVaSetValues(nb->notebook.scroller_child,XmNarrowSensitivity,
6894 		XmARROWS_INCREMENT_SENSITIVE, NULL);
6895 	else
6896 	   XtVaSetValues(nb->notebook.scroller_child,XmNarrowSensitivity,
6897 		XmARROWS_SENSITIVE, NULL);
6898 	}
6899 }
6900 
6901 
6902 /*- GetUnhighlightGC --------------------------------------------------------
6903 
6904         ScrollFrame removeNavigator trait method
6905 
6906 -----------------------------------------------------------------------------*/
6907 static GC
GetUnhighlightGC(Widget w,Widget child)6908 GetUnhighlightGC (
6909     Widget w,
6910     Widget child)
6911 {
6912     XmNotebookWidget nb = (XmNotebookWidget)w;
6913     XmNotebookConstraint nc;
6914     GC background_GC = NULL;
6915 
6916     if (child)
6917 	{
6918 	nc = NotebookConstraint(child);
6919 	switch (nc->child_type)
6920 	    {
6921 	    case XmMAJOR_TAB:
6922 		if (nb->notebook.top_major == child)
6923 		    {
6924 		    XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
6925 				    nb->notebook.frame_background);
6926 		    background_GC = nb->notebook.frame_gc;
6927 		    }
6928 		else
6929 		  background_GC = nb->manager.background_GC;
6930 		break;
6931 
6932 	    case XmMINOR_TAB:
6933 		if (nb->notebook.top_minor == child)
6934 		    {
6935 		    XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
6936 				    nb->notebook.frame_background);
6937 		    background_GC = nb->notebook.frame_gc;
6938 		    }
6939 		else
6940 		    background_GC = nb->manager.background_GC;
6941 		break;
6942 
6943 	    case XmPAGE:
6944 	    case XmPAGE_SCROLLER:
6945 	    case XmSTATUS_AREA:
6946 		XSetForeground(XtDisplay(nb), nb->notebook.frame_gc,
6947 			       nb->notebook.frame_background);
6948 		background_GC = nb->notebook.frame_gc;
6949 		break;
6950 
6951 	    case XmMAJOR_TAB_SCROLLER:
6952 	    case XmMINOR_TAB_SCROLLER:
6953 		background_GC = nb->manager.background_GC;
6954 		break;
6955 
6956 	    }
6957 	}
6958 
6959     return(background_GC);
6960 }
6961 
6962 
6963 
6964 /*****************************************************************************
6965  *                                                                           *
6966  *                               Public Functions                            *
6967  *                                                                           *
6968  *****************************************************************************/
6969 
6970 
6971 XmNotebookPageStatus
XmNotebookGetPageInfo(Widget notebook,int page_number,XmNotebookPageInfo * page_info)6972 XmNotebookGetPageInfo (
6973     Widget notebook,
6974     int page_number,
6975     XmNotebookPageInfo *page_info)
6976 {
6977     XmNotebookWidget nb = (XmNotebookWidget)notebook;
6978     XmNotebookConstraint nc;
6979     Widget child;
6980     Widget page, status, major_tab, minor_tab;
6981     XmNotebookPageStatus result;
6982     int i;
6983     _XmWidgetToAppContext(notebook);
6984 
6985     _XmAppLock(app);
6986 
6987     /* initialize */
6988     page = status = major_tab = minor_tab = NULL;
6989     result = XmPAGE_EMPTY;
6990 
6991     /* searching for the page */
6992     for (i = 0; i < nb->composite.num_children; i++)
6993     {
6994         child = nb->composite.children[i];
6995         nc = NotebookConstraint(child);
6996 
6997 	if (nc->page_number > page_number)
6998 	    break;
6999 	switch (nc->child_type)
7000 	    {
7001 		case XmPAGE:
7002 		    if (nc->page_number == page_number)
7003 		    {
7004 		        if (nc->active)
7005 			{
7006 			    page = child;
7007 			    if (result == XmPAGE_EMPTY)
7008 			        result = XmPAGE_FOUND;
7009 		        }
7010 			else
7011 			    result = XmPAGE_DUPLICATED;
7012 		    }
7013 		    break;
7014 		case XmSTATUS_AREA:
7015 		    if ((nc->active) && (nc->page_number == page_number))
7016 			status = child;
7017 		    break;
7018 		case XmMAJOR_TAB:
7019 		    if (nc->active)
7020 			major_tab = child;
7021 		    break;
7022 		case XmMINOR_TAB:
7023 		    if (nc->active)
7024 			minor_tab = child;
7025 		    break;
7026 	    }
7027     }
7028 
7029     /* see if the page number is invalid */
7030     if (page_number < nb->notebook.first_page_number ||
7031 	page_number > nb->notebook.last_page_number)
7032 	result = XmPAGE_INVALID;
7033 
7034     /* fill the XmNotebookPageInfo struct */
7035     page_info->page_number = page_number;
7036     page_info->page_widget = page;
7037     page_info->status_area_widget = status;
7038     page_info->major_tab_widget = major_tab;
7039     page_info->minor_tab_widget = minor_tab;
7040 
7041     _XmAppUnlock(app);
7042     return result;
7043 }
7044 
7045 
7046 Widget
XmCreateNotebook(Widget parent,String name,ArgList arglist,Cardinal argcount)7047 XmCreateNotebook(
7048         Widget          parent,
7049         String		name,
7050         ArgList         arglist,
7051         Cardinal        argcount)
7052 {
7053         /*
7054          * Create an instance of a notebook and return the widget id.
7055          */
7056    return(XtCreateWidget(name,xmNotebookWidgetClass,parent,arglist,argcount));
7057 }
7058 
7059 Widget
XmVaCreateNotebook(Widget parent,char * name,...)7060 XmVaCreateNotebook(
7061         Widget parent,
7062         char *name,
7063         ...)
7064 {
7065     register Widget w;
7066     va_list var;
7067     int count;
7068 
7069     Va_start(var,name);
7070     count = XmeCountVaListSimple(var);
7071     va_end(var);
7072 
7073 
7074     Va_start(var, name);
7075     w = XmeVLCreateWidget(name,
7076                          xmNotebookWidgetClass,
7077                          parent, False,
7078                          var, count);
7079     va_end(var);
7080     return w;
7081 }
7082 
7083 Widget
XmVaCreateManagedNotebook(Widget parent,char * name,...)7084 XmVaCreateManagedNotebook(
7085         Widget parent,
7086         char *name,
7087         ...)
7088 {
7089     Widget w = NULL;
7090     va_list var;
7091     int count;
7092 
7093     Va_start(var, name);
7094     count = XmeCountVaListSimple(var);
7095     va_end(var);
7096 
7097     Va_start(var, name);
7098     w = XmeVLCreateWidget(name,
7099                          xmNotebookWidgetClass,
7100                          parent, True,
7101                          var, count);
7102     va_end(var);
7103     return w;
7104 }
7105 
7106 /* End of Notebook.c */
7107 
7108