1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>.
17  *
18  * The Initial Developer of the Original Code is
19  * Netscape Communications Corporation.
20  * Portions created by the Initial Developer are Copyright (C) 1998
21  * the Initial Developer. All Rights Reserved.
22  *
23  * Contributor(s):
24  *
25  * Alternatively, the contents of this file may be used under the terms of
26  * either the GNU General Public License Version 2 or later (the "GPL"), or
27  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28  * in which case the provisions of the GPL or the LGPL are applicable instead
29  * of those above. If you wish to allow use of your version of this file only
30  * under the terms of either the GPL or the LGPL, and not to allow others to
31  * use your version of this file under the terms of the MPL, indicate your
32  * decision by deleting the provisions above and replace them with the notice
33  * and other provisions required by the GPL or the LGPL. If you do not delete
34  * the provisions above, a recipient may use your version of this file under
35  * the terms of any one of the MPL, the GPL or the LGPL.
36  *
37  * In addition, as a special exception to the GNU GPL, the copyright holders
38  * give permission to link the code of this program with the Motif and Open
39  * Motif libraries (or with modified versions of these that use the same
40  * license), and distribute linked combinations including the two. You
41  * must obey the GNU General Public License in all respects for all of
42  * the code used other than linking with Motif/Open Motif. If you modify
43  * this file, you may extend this exception to your version of the file,
44  * but you are not obligated to do so. If you do not wish to do so,
45  * delete this exception statement from your version.
46  *
47  * ***** END LICENSE BLOCK ***** */
48 
49 #include "FolderP.h"
50 #include <X11/StringDefs.h>
51 #include <Xm/DrawnB.h>
52 #include <Xm/Label.h>
53 #include <Xm/Form.h>
54 
55 #include <stdio.h>
56 #include <stdlib.h>
57 
58 #ifdef SUNOS4
59 int fprintf(FILE *, char *, ...);
60 #endif
61 
62 /* Create and Destroy */
63 static void ClassInitialize();
64 static void Initialize(Widget req, Widget newW,
65 	ArgList args, Cardinal *nargs);
66 static void Destroy(Widget w);
67 
68 /* Geometry, Drawing, Entry and Picking */
69 static void Realize(Widget w, XtValueMask *valueMask,
70 	XSetWindowAttributes *attr);
71 static void Redisplay(Widget w, XExposeEvent *event, Region region);
72 static void Layout(XmLFolderWidget f, int resizeIfNeeded);
73 static void LayoutTopBottom(XmLFolderWidget f, int resizeIfNeeded);
74 static void LayoutLeftRight(XmLFolderWidget f, int resizeIfNeeded);
75 static void Resize(Widget w);
76 static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
77 	XtWidgetGeometry *);
78 static void ChangeManaged(Widget w);
79 static void ConstraintInitialize(Widget, Widget w,
80 	ArgList args, Cardinal *nargs);
81 static void ConstraintDestroy(Widget w);
82 static void SetActiveTab(XmLFolderWidget f, Widget w, XEvent *event,
83 	Boolean notify);
84 static void DrawTabPixmap(XmLFolderWidget f, Widget tab, int active);
85 static void DrawManagerShadowLeftRight(XmLFolderWidget f, XRectangle *rect);
86 static void DrawManagerShadowTopBottom(XmLFolderWidget f, XRectangle *rect);
87 static void DrawTabHighlight(XmLFolderWidget f, Widget w);
88 static void SetTabPlacement(XmLFolderWidget f, Widget tab);
89 static void GetTabRect(XmLFolderWidget f, Widget tab, XRectangle *rect,
90 	int includeShadow);
91 static void DrawTabShadowArcTopBottom(XmLFolderWidget f, Widget w);
92 static void DrawTabShadowArcLeftRight(XmLFolderWidget f, Widget w);
93 static void DrawTabShadowLineTopBottom(XmLFolderWidget f, Widget w);
94 static void DrawTabShadowLineLeftRight(XmLFolderWidget f, Widget w);
95 static void DrawTabShadowNoneTopBottom(XmLFolderWidget f, Widget w);
96 static void DrawTabShadowNoneLeftRight(XmLFolderWidget f, Widget w);
97 static void SetGC(XmLFolderWidget f, int type);
98 
99 /* Getting and Setting Values */
100 static Boolean SetValues(Widget curW, Widget reqW, Widget newW,
101 	ArgList args, Cardinal *nargs);
102 static Boolean ConstraintSetValues(Widget curW, Widget, Widget newW,
103 	ArgList, Cardinal *);
104 static void CopyFontList(XmLFolderWidget f);
105 static Boolean CvtStringToCornerStyle(Display *dpy, XrmValuePtr args,
106 	Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
107 	XtPointer *data);
108 static Boolean CvtStringToFolderResizePolicy(Display *dpy, XrmValuePtr args,
109 	Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
110 	XtPointer *data);
111 static Boolean CvtStringToTabPlacement(Display *dpy, XrmValuePtr args,
112 	Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
113 	XtPointer *data);
114 
115 /* Utility */
116 static void GetCoreBackground(Widget w, int, XrmValue *value);
117 static void GetDefaultTabWidgetClass(Widget w, int, XrmValue *value);
118 static void GetManagerForeground(Widget w, int, XrmValue *value);
119 static Boolean ServerDrawsArcsLarge(Display *dpy, int debug);
120 
121 /* Actions, Callbacks and Handlers */
122 static void Activate(Widget w, XEvent *event, String *, Cardinal *);
123 static void PrimActivate(Widget w, XtPointer, XtPointer);
124 static void PrimFocusIn(Widget w, XEvent *event, String *, Cardinal *);
125 static void PrimFocusOut(Widget w, XEvent *event, String *, Cardinal *);
126 
127 static XtActionsRec actions[] =
128 	{
129 	{ "XmLFolderActivate",      Activate     },
130 	{ "XmLFolderPrimFocusIn",   PrimFocusIn  },
131 	{ "XmLFolderPrimFocusOut",  PrimFocusOut },
132 	};
133 
134 #define MAX_TAB_ROWS 64
135 
136 #define GC_SHADOWBOT  0
137 #define GC_SHADOWTOP  1
138 #define GC_BLANK      2
139 #define GC_UNSET      3
140 
141 /* Folder Translations */
142 
143 static char translations[] =
144 "<Btn1Down>: XmLFolderActivate()\n\
145 <EnterWindow>:   ManagerEnter()\n\
146 <LeaveWindow>:   ManagerLeave()\n\
147 <FocusOut>:      ManagerFocusOut()\n\
148 <FocusIn>:       ManagerFocusIn()";
149 
150 /* Primitive Child Translations */
151 
152 static char primTranslations[] =
153 "<FocusIn>: XmLFolderPrimFocusIn() PrimitiveFocusIn()\n\
154 <FocusOut>: XmLFolderPrimFocusOut() PrimitiveFocusOut()";
155 
156 static XtResource resources[] =
157 	{
158 		/* Folder Resources */
159 		{
160 		XmNtabWidgetClass, XmCTabWidgetClass,
161 		XmRWidgetClass, sizeof(WidgetClass),
162 		XtOffset(XmLFolderWidget, folder.tabWidgetClass),
163 		XmRCallProc, (XtPointer)GetDefaultTabWidgetClass,
164 		},
165 		{
166 		XmNactivateCallback, XmCCallback,
167 		XmRCallback, sizeof(XtCallbackList),
168 		XtOffset(XmLFolderWidget, folder.activateCallback),
169 		XmRImmediate, (XtPointer)0,
170 		},
171 		{
172 		XmNactiveTab, XmCActiveTab,
173 		XmRInt, sizeof(int),
174 		XtOffset(XmLFolderWidget, folder.activeTab),
175 		XmRImmediate, (XtPointer)-1,
176 		},
177 		{
178 		XmNautoSelect, XmCAutoSelect,
179 		XmRBoolean, sizeof(Boolean),
180 		XtOffset(XmLFolderWidget, folder.autoSelect),
181 		XmRImmediate, (XtPointer)True,
182 		},
183 		{
184 		XmNblankBackground, XmCBlankBackground,
185 		XmRPixel, sizeof(Pixel),
186 		XtOffset(XmLFolderWidget, folder.blankBg),
187 		XmRCallProc, (XtPointer)GetCoreBackground,
188 		},
189 		{
190 		XmNblankBackgroundPixmap, XmCBlankBackgroundPixmap,
191 		XmRManForegroundPixmap, sizeof(Pixmap),
192 		XtOffset(XmLFolderWidget, folder.blankPix),
193 		XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
194 		},
195 		{
196 		XmNcornerDimension, XmCCornerDimension,
197 		XmRDimension, sizeof(Dimension),
198 		XtOffset(XmLFolderWidget, folder.cornerDimension),
199 		XmRImmediate, (XtPointer)2,
200 		},
201 		{
202 		XmNcornerStyle, XmCCornerStyle,
203 		XmRCornerStyle, sizeof(unsigned char),
204 		XtOffset(XmLFolderWidget, folder.cornerStyle),
205 		XmRImmediate, (XtPointer)XmCORNER_ARC,
206 		},
207 		{
208 		XmNfontList, XmCFontList,
209 		XmRFontList, sizeof(XmFontList),
210 		XtOffset(XmLFolderWidget, folder.fontList),
211 		XmRImmediate, (XtPointer)0,
212 		},
213 		{
214 		XmNhighlightThickness, XmCHighlightThickness,
215 		XmRDimension, sizeof(Dimension),
216 		XtOffset(XmLFolderWidget, folder.highlightThickness),
217 		XmRImmediate, (XtPointer)2,
218 		},
219 		{
220 		XmNinactiveBackground, XmCInactiveBackground,
221 		XmRPixel, sizeof(Pixel),
222 		XtOffset(XmLFolderWidget, folder.inactiveBg),
223 		XmRCallProc, (XtPointer)GetCoreBackground,
224 		},
225 		{
226 		XmNinactiveForeground, XmCInactiveForeground,
227 		XmRPixel, sizeof(Pixel),
228 		XtOffset(XmLFolderWidget, folder.inactiveFg),
229 		XmRCallProc, (XtPointer)GetManagerForeground,
230 		},
231 		{
232 		XmNmarginHeight, XmCMarginHeight,
233 		XmRDimension, sizeof(Dimension),
234 		XtOffset(XmLFolderWidget, folder.marginHeight),
235 		XmRImmediate, (XtPointer)0,
236 		},
237 		{
238 		XmNmarginWidth, XmCMarginWidth,
239 		XmRDimension, sizeof(Dimension),
240 		XtOffset(XmLFolderWidget, folder.marginWidth),
241 		XmRImmediate, (XtPointer)0,
242 		},
243 		{
244 		XmNminTabWidth, XmCminTabWidth,
245 		XmRDimension, sizeof(Dimension),
246 		XtOffset(XmLFolderWidget, folder.minTabWidth),
247 		XmRImmediate, (XtPointer)0,
248 		},
249 		{
250 		XmNmaxTabWidth, XmCmaxTabWidth,
251 		XmRDimension, sizeof(Dimension),
252 		XtOffset(XmLFolderWidget, folder.maxTabWidth),
253 		XmRImmediate, (XtPointer)100,
254 		},
255 		{
256 		XmNpixmapMargin, XmCPixmapMargin,
257 		XmRDimension, sizeof(Dimension),
258 		XtOffset(XmLFolderWidget, folder.pixmapMargin),
259 		XmRImmediate, (XtPointer)2,
260 		},
261 		{
262 		XmNresizePolicy, XmCFolderResizePolicy,
263 		XmRFolderResizePolicy, sizeof(unsigned char),
264 		XtOffset(XmLFolderWidget, folder.resizePolicy),
265 		XmRImmediate, (XtPointer)XmRESIZE_STATIC,
266 		},
267 		{
268 		XmNrotateWhenLeftRight, XmCRotateWhenLeftRight,
269 		XmRBoolean, sizeof(Boolean),
270 		XtOffset(XmLFolderWidget, folder.allowRotate),
271 		XmRImmediate, (XtPointer)True,
272 		},
273 		{
274 		XmNspacing, XmCSpacing,
275 		XmRDimension, sizeof(Dimension),
276 		XtOffset(XmLFolderWidget, folder.spacing),
277 		XmRImmediate, (XtPointer)0,
278 		},
279 		{
280 		XmNtabBarHeight, XmCTabBarHeight,
281 		XmRDimension, sizeof(Dimension),
282 		XtOffset(XmLFolderWidget, folder.tabBarHeight),
283 		XmRImmediate, (XtPointer)0,
284 		},
285 		{
286 		XmNtabCount, XmCTabCount,
287 		XmRInt, sizeof(int),
288 		XtOffset(XmLFolderWidget, folder.tabCount),
289 		XmRImmediate, (XtPointer)0,
290 		},
291 		{
292 		XmNtabPlacement, XmCTabPlacement,
293 		XmRTabPlacement, sizeof(unsigned char),
294 		XtOffset(XmLFolderWidget, folder.tabPlacement),
295 		XmRImmediate, (XtPointer)XmFOLDER_TOP,
296 		},
297 		{
298 		XmNtabsPerRow, XmCTabsPerRow,
299 		XmRInt, sizeof(int),
300 		XtOffset(XmLFolderWidget, folder.tabsPerRow),
301 		XmRImmediate, (XtPointer)0,
302 		},
303 		{
304 		XmNtabWidgetList, XmCReadOnly,
305 		XmRPointer, sizeof(XtPointer),
306 		XtOffset(XmLFolderWidget, folder.tabs),
307 		XmRImmediate, (XtPointer)0,
308 		},
309 		{
310 		XmNtabTranslations, XmCTranslations,
311 		XmRTranslationTable, sizeof(XtTranslations),
312 		XtOffset(XmLFolderWidget, folder.primTrans),
313 		XmRString, (XtPointer)primTranslations,
314 		},
315 		{
316 		XmNdebugLevel, XmCDebugLevel,
317 		XmRInt, sizeof(int),
318 		XtOffset(XmLFolderWidget, folder.debugLevel),
319 		XmRImmediate, (XtPointer)0,
320 		},
321 		/* Overridden inherited resources */
322 		{
323 		XmNshadowThickness, XmCShadowThickness,
324 		XmRHorizontalDimension, sizeof(Dimension),
325 		XtOffset(XmLFolderWidget, manager.shadow_thickness),
326 		XmRImmediate, (XtPointer)2,
327 		},
328     };
329 
330 static XtResource constraint_resources[] =
331 	{
332 		/* Folder Constraint Resources */
333 		{
334 		XmNtabFreePixmaps, XmCTabFreePixmaps,
335 		XmRBoolean, sizeof(Boolean),
336 		XtOffset(XmLFolderConstraintPtr, folder.freePix),
337 		XmRImmediate, (XtPointer)False,
338 		},
339 		{
340 		XmNtabInactivePixmap, XmCTabInactivePixmap,
341 		XmRPrimForegroundPixmap, sizeof(Pixmap),
342 		XtOffset(XmLFolderConstraintPtr, folder.inactPix),
343 		XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
344 		},
345 		{
346 		XmNtabManagedName, XmCTabManagedName,
347 		XmRString, sizeof(char *),
348 		XtOffset(XmLFolderConstraintPtr, folder.managedName),
349 		XmRImmediate, (XtPointer)0,
350 		},
351 		{
352 		XmNtabManagedWidget, XmCTabManagedWidget,
353 		XmRWidget, sizeof(Widget),
354 		XtOffset(XmLFolderConstraintPtr, folder.managedW),
355 		XmRImmediate, (XtPointer)0,
356 		},
357 		{
358 		XmNtabPixmap, XmCTabPixmap,
359 		XmRPrimForegroundPixmap, sizeof(Pixmap),
360 		XtOffset(XmLFolderConstraintPtr, folder.pix),
361 		XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
362 		},
363 	};
364 
365 XmLFolderClassRec xmlFolderClassRec =
366 	{
367 		{ /* core_class */
368 		(WidgetClass)&xmManagerClassRec,          /* superclass         */
369 		"XmLFolder",                              /* class_name         */
370 		sizeof(XmLFolderRec),                     /* widget_size        */
371 		ClassInitialize,                          /* class_init         */
372 		0,                                        /* class_part_init    */
373 		FALSE,                                    /* class_inited       */
374 		(XtInitProc)Initialize,                   /* initialize         */
375 		0,                                        /* initialize_hook    */
376 		(XtRealizeProc)Realize,                   /* realize            */
377 		(XtActionList)actions,                    /* actions            */
378 		(Cardinal)XtNumber(actions),              /* num_actions        */
379 		(XtResource *)resources,				  /* resources          */
380 		XtNumber(resources),                      /* num_resources      */
381 		NULLQUARK,                                /* xrm_class          */
382 		TRUE,                                     /* compress_motion    */
383 		XtExposeCompressMultiple,                 /* compress_exposure  */
384 		TRUE,                                     /* compress_enterlv   */
385 		TRUE,                                     /* visible_interest   */
386 		(XtWidgetProc)Destroy,                    /* destroy            */
387 		(XtWidgetProc)Resize,                     /* resize             */
388 		(XtExposeProc)Redisplay,                  /* expose             */
389 		(XtSetValuesFunc)SetValues,               /* set_values         */
390 		0,                                        /* set_values_hook    */
391 		XtInheritSetValuesAlmost,                 /* set_values_almost  */
392 		0,                                        /* get_values_hook    */
393 		0,                                        /* accept_focus       */
394 		XtVersion,                                /* version            */
395 		0,                                        /* callback_private   */
396 		translations,                             /* tm_table           */
397 		0,                                        /* query_geometry     */
398 		0,                                        /* display_acceleratr */
399 		0,                                        /* extension          */
400 		},
401 		{ /* composite_class */
402 		(XtGeometryHandler)GeometryManager,       /* geometry_manager   */
403 		(XtWidgetProc)ChangeManaged,              /* change_managed     */
404 		XtInheritInsertChild,                     /* insert_child       */
405 		XtInheritDeleteChild,                     /* delete_child       */
406 		0,                                        /* extension          */
407 		},
408 		{ /* constraint_class */
409 		(XtResource *)constraint_resources,		  /* subresources       */
410 		XtNumber(constraint_resources),           /* subresource_count  */
411 		sizeof(XmLFolderConstraintRec),           /* constraint_size    */
412 		(XtInitProc)ConstraintInitialize,         /* initialize         */
413 		(XtWidgetProc)ConstraintDestroy,          /* destroy            */
414 		(XtSetValuesFunc)ConstraintSetValues,     /* set_values         */
415 		0,                                        /* extension          */
416 		},
417 		{ /* manager_class */
418 		XtInheritTranslations,                    /* translations       */
419 		0,                                        /* syn resources      */
420 		0,                                        /* num syn_resources  */
421 		0,                                        /* get_cont_resources */
422 		0,                                        /* num_get_cont_resrc */
423 		XmInheritParentProcess,                   /* parent_process     */
424 		0,                                        /* extension          */
425 		},
426 		{ /* folder_class */
427 		0,                                        /* unused             */
428 		}
429 	};
430 
431 WidgetClass xmlFolderWidgetClass = (WidgetClass)&xmlFolderClassRec;
432 
433 /*
434    Create and Destroy
435 */
436 
437 static void
ClassInitialize(void)438 ClassInitialize(void)
439 {
440   XmLInitialize();
441 
442   XtSetTypeConverter(XmRString, XmRCornerStyle,
443 		     CvtStringToCornerStyle, 0, 0, XtCacheNone, 0);
444   XtSetTypeConverter(XmRString, XmRFolderResizePolicy,
445 		     CvtStringToFolderResizePolicy, 0, 0, XtCacheNone, 0);
446   XtSetTypeConverter(XmRString, XmRTabPlacement,
447 		     CvtStringToTabPlacement, 0, 0, XtCacheNone, 0);
448 }
449 
450 static void
Initialize(Widget req,Widget newW,ArgList args,Cardinal * narg)451 Initialize(Widget req,
452 	   Widget newW,
453 	   ArgList args,
454 	   Cardinal *narg)
455 {
456   Display *dpy;
457   /*  Window root;*/
458   XmLFolderWidget f, request;
459 
460   f = (XmLFolderWidget)newW;
461   dpy = XtDisplay((Widget)f);
462   request = (XmLFolderWidget)req;
463 
464   if (f->core.width == 0)
465     f->core.width = 100;
466   if (f->core.height == 0)
467     f->core.height = 100;
468 
469   f->folder.gc = 0;
470 
471   f->folder.tabAllocCount = 32;
472   f->folder.tabs = (Widget *)malloc(sizeof(Widget) * 32);
473   f->folder.tabHeight = 0;
474   f->folder.tabWidth = 0;
475   f->folder.activeW = 0;
476   f->folder.focusW = 0;
477   f->folder.allowLayout = 1;
478   f->folder.activeRow = -1;
479   CopyFontList(f);
480 
481   if (f->folder.tabBarHeight)
482     {
483       XmLWarning((Widget)f, "Initialize() - can't set tabBarHeight");
484       f->folder.tabBarHeight = 0;
485     }
486   if (f->folder.tabCount)
487     {
488       XmLWarning((Widget)f, "Initialize() - can't set tabCount");
489       f->folder.tabCount = 0;
490     }
491   if (f->folder.activeTab != -1)
492     {
493       XmLWarning((Widget)f, "Initialize() - can't set activeTab");
494       f->folder.activeTab = -1;
495     }
496   if (f->folder.cornerDimension < 1)
497     {
498       XmLWarning((Widget)f, "Initialize() - cornerDimension can't be < 1");
499       f->folder.cornerDimension = 1;
500     }
501   f->folder.serverDrawsArcsLarge = ServerDrawsArcsLarge(dpy,
502 							f->folder.debugLevel);
503   if (f->folder.minTabWidth <= 0)
504     {
505       /* a quick hack to determine the minimum tab width - enough
506 	 to show at least one character of the tab string */
507       XmString st = XmStringCreateSimple("W");
508       f->folder.minTabWidth = XmStringWidth(f->folder.fontList, st);
509       XmStringFree(st);
510     }
511 }
512 
513 static void
Destroy(Widget w)514 Destroy(Widget w)
515 {
516   XmLFolderWidget f;
517   Display *dpy;
518 
519   f = (XmLFolderWidget)w;
520   dpy = XtDisplay(w);
521   if (f->folder.debugLevel)
522     fprintf(stderr, "Folder destroy: \n");
523   if (f->folder.tabs)
524     free((char *)f->folder.tabs);
525   if (f->folder.gc)
526     XFreeGC(dpy, f->folder.gc);
527   XmFontListFree(f->folder.fontList);
528 }
529 
530 /*
531   Geometry, Drawing, Entry and Picking
532   */
533 
534 static void
Realize(Widget w,XtValueMask * valueMask,XSetWindowAttributes * attr)535 Realize(Widget w,
536 	XtValueMask *valueMask,
537 	XSetWindowAttributes *attr)
538 {
539   XmLFolderWidget f;
540   Display *dpy;
541   WidgetClass superClass;
542   XtRealizeProc realize;
543   XGCValues values;
544   XtGCMask mask;
545 
546   f = (XmLFolderWidget)w;
547   dpy = XtDisplay(f);
548   superClass = xmlFolderWidgetClass->core_class.superclass;
549   realize = superClass->core_class.realize;
550   (*realize)(w, valueMask, attr);
551 
552   if (!f->folder.gc)
553     {
554       values.foreground = f->manager.foreground;
555       mask = GCForeground;
556       f->folder.gc = XCreateGC(dpy, XtWindow(f), mask, &values);
557       if (f->folder.autoSelect == True && f->folder.tabCount)
558 	XmLFolderSetActiveTab(w, 0, False);
559     }
560 }
561 
562 static void
Redisplay(Widget w,XExposeEvent * event,Region region)563 Redisplay(Widget w,
564 	  XExposeEvent *event,
565 	  Region region)
566 {
567   Display *dpy;
568   Window win;
569   XmLFolderWidget f;
570   XmLFolderConstraintRec *fc;
571   XRectangle eRect, rRect, rect;
572   /* XSegment *topSeg, *botSeg; */
573   /*  int tCount, bCount; */
574   Widget tab;
575   int i, st, ht; /*, x, y; */
576 
577   f = (XmLFolderWidget)w;
578   if (!XtIsRealized(w))
579     return;
580   if (!f->core.visible)
581     return;
582   dpy = XtDisplay(f);
583   win = XtWindow(f);
584   st = f->manager.shadow_thickness;
585   ht = f->folder.highlightThickness;
586 
587   if (event)
588     {
589       eRect.x = event->x;
590       eRect.y = event->y;
591       eRect.width = event->width;
592       eRect.height = event->height;
593       if (f->folder.debugLevel > 1)
594 	fprintf(stderr, "XmLFolder: Redisplay x %d y %d w %d h %d\n",
595 		event->x, event->y, event->width, event->height);
596     }
597   else
598     {
599       eRect.x = 0;
600       eRect.y = 0;
601       eRect.width = f->core.width;
602       eRect.height = f->core.height;
603     }
604   if (!eRect.width || !eRect.height)
605     return;
606 
607   if (f->folder.tabPlacement == XmFOLDER_TOP)
608     {
609       rRect.x = 0;
610       rRect.y = f->folder.tabHeight;
611       rRect.width = f->core.width;
612       rRect.height = f->core.height - f->folder.tabHeight;
613     }
614   else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
615     {
616       rRect.x = 0;
617       rRect.y = 0;
618       rRect.width = f->core.width;
619       rRect.height = f->core.height - f->folder.tabHeight;
620     }
621   if (f->folder.tabPlacement == XmFOLDER_LEFT)
622     {
623       rRect.x = f->folder.tabWidth;
624       rRect.y = 0;
625       rRect.width = f->core.width - f->folder.tabWidth;
626       rRect.height = f->core.height;
627     }
628   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
629     {
630       rRect.x = 0;
631       rRect.y = 0;
632       rRect.width = f->core.width - f->folder.tabWidth;
633       rRect.height = f->core.height;
634     }
635   if (XmLRectIntersect(&eRect, &rRect) != XmLRectOutside)
636     {
637       if (f->folder.tabPlacement == XmFOLDER_TOP ||
638 	  f->folder.tabPlacement == XmFOLDER_BOTTOM)
639 	DrawManagerShadowTopBottom(f, &rRect);
640       else
641 	DrawManagerShadowLeftRight(f, &rRect);
642     }
643 
644   if (!f->folder.tabCount)
645     return;
646 
647   rRect.x = 0;
648   rRect.y = 0;
649   rRect.width = 0;
650   rRect.height = 0;
651 
652 	/* Draw tabs */
653   for (i = 0; i < f->folder.tabCount; i++)
654     {
655       tab = f->folder.tabs[i];
656       if (!XtIsManaged(tab))
657 	continue;
658       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
659       GetTabRect(f, tab, &rRect, 0);
660 
661       /* include spacing in intersect test */
662       rect = rRect;
663       if (f->folder.tabPlacement == XmFOLDER_TOP ||
664 	  f->folder.tabPlacement == XmFOLDER_BOTTOM)
665 	rect.width += f->folder.spacing;
666       else
667 	rect.height += f->folder.spacing;
668 
669       /* include indent in intersect test */
670       if (f->folder.tabsPerRow)
671 	{
672 	  if (rRect.x == 2)
673 	    rect.x = 0;
674 	  if (rRect.y == 2)
675 	    rect.y = 0;
676 	  if (rRect.x + rRect.width == f->core.width - 2)
677 	    rect.width += 2;
678 	  if (rRect.y + rRect.height == f->core.height - 2)
679 	    rect.height += 2;
680 	}
681 
682       if (XmLRectIntersect(&eRect, &rect) == XmLRectOutside)
683 	continue;
684       if (event && XRectInRegion(region, rect.x, rect.y,
685 				 rect.width, rect.height) == RectangleOut)
686 	continue;
687 
688       if (f->folder.debugLevel > 1)
689 	fprintf(stderr, "XmLFolder: Redisplay tab for widget %d\n", i);
690       if (tab == f->folder.activeW)
691 	{
692 	  XtVaSetValues(tab,
693 			XmNbackground, f->core.background_pixel,
694 			XmNforeground, f->manager.foreground,
695 			NULL);
696 	}
697       else
698 	{
699 	  XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
700 	  XFillRectangle(dpy, win, f->folder.gc,
701 			 rRect.x, rRect.y, rRect.width, rRect.height);
702 	  XtVaSetValues(tab,
703 			XmNbackground, f->folder.inactiveBg,
704 			XmNforeground, f->folder.inactiveFg,
705 			NULL);
706 	}
707 
708       if (f->folder.tabPlacement == XmFOLDER_TOP ||
709 	  f->folder.tabPlacement == XmFOLDER_BOTTOM)
710 	{
711 	  if (f->folder.cornerStyle == XmCORNER_LINE)
712 	    DrawTabShadowLineTopBottom(f, tab);
713 	  else if (f->folder.cornerStyle == XmCORNER_ARC)
714 	    DrawTabShadowArcTopBottom(f, tab);
715 	  else
716 	    DrawTabShadowNoneTopBottom(f, tab);
717 	}
718       else
719 	{
720 	  if (f->folder.cornerStyle == XmCORNER_LINE)
721 	    DrawTabShadowLineLeftRight(f, tab);
722 	  else if (f->folder.cornerStyle == XmCORNER_ARC)
723 	    DrawTabShadowArcLeftRight(f, tab);
724 	  else
725 	    DrawTabShadowNoneLeftRight(f, tab);
726 	}
727 
728       if (f->folder.focusW == tab)
729 	DrawTabHighlight(f, tab);
730 
731       if (tab == f->folder.activeW &&
732 	  fc->folder.pix != XmUNSPECIFIED_PIXMAP &&
733 	  (fc->folder.maxPixWidth || fc->folder.maxPixHeight))
734 	DrawTabPixmap(f, tab, 1);
735       else if (tab != f->folder.activeW &&
736 	       fc->folder.inactPix != XmUNSPECIFIED_PIXMAP &&
737 	       (fc->folder.maxPixWidth || fc->folder.maxPixHeight))
738 	DrawTabPixmap(f, tab, 0);
739 
740       SetGC(f, GC_BLANK);
741 
742       /* draw indent */
743       if (f->folder.tabsPerRow)
744 	{
745 	  if (rRect.x == 2)
746 	    {
747 	      rect = rRect;
748 	      rect.x = 0;
749 	      rect.width = 2;
750 	      XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
751 			     rect.width, rect.height);
752 	    }
753 	  if (rRect.y == 2)
754 	    {
755 	      rect = rRect;
756 	      rect.y = 0;
757 	      rect.height = 2;
758 	      XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
759 			     rect.width, rect.height);
760 	    }
761 	  if (rRect.x + rRect.width == f->core.width - 2)
762 	    {
763 	      rect = rRect;
764 	      rect.x = f->core.width - 2;
765 	      rect.width = 2;
766 	      XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
767 			     rect.width, rect.height);
768 	    }
769 	  if (rRect.y + rRect.height == f->core.height - 2)
770 	    {
771 	      rect = rRect;
772 	      rect.y = f->core.height - 2;
773 	      rect.height = 2;
774 	      XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
775 			     rect.width, rect.height);
776 	    }
777 	}
778 
779       if (f->folder.spacing)
780 	{
781 	  if (f->folder.tabPlacement == XmFOLDER_TOP ||
782 	      f->folder.tabPlacement == XmFOLDER_BOTTOM)
783 	    XFillRectangle(dpy, win, f->folder.gc, rRect.x + rRect.width,
784 			   rRect.y, f->folder.spacing, rRect.height);
785 	  else
786 	    XFillRectangle(dpy, win, f->folder.gc, rRect.x,
787 			   rRect.y + rRect.height, rRect.width, f->folder.spacing);
788 	}
789 
790       SetGC(f, GC_UNSET);
791     }
792 
793   /* Draw empty area */
794   if (!f->folder.tabsPerRow)
795     {
796       if (f->folder.tabPlacement == XmFOLDER_TOP ||
797 	  f->folder.tabPlacement == XmFOLDER_BOTTOM)
798 	{
799 	  rRect.x += rRect.width + f->folder.spacing;
800 	  if ((int)f->core.width > rRect.x)
801 	    {
802 	      if (f->folder.tabPlacement == XmFOLDER_TOP)
803 		rRect.y = 0;
804 	      else
805 		rRect.y = f->core.height - f->folder.tabHeight;
806 	      rRect.width = f->core.width - rRect.x;
807 	      rRect.height = f->folder.tabHeight;
808 	      SetGC(f, GC_BLANK);
809 	      XFillRectangle(dpy, win, f->folder.gc,
810 			     rRect.x, rRect.y, rRect.width, rRect.height);
811 	      SetGC(f, GC_UNSET);
812 	    }
813 	}
814       else
815 	{
816 	  rRect.y += rRect.height + f->folder.spacing;
817 	  if ((int)f->core.height > rRect.y)
818 	    {
819 	      if (f->folder.tabPlacement == XmFOLDER_LEFT)
820 		rRect.x = 0;
821 	      else
822 		rRect.x = f->core.width - f->folder.tabWidth;
823 	      rRect.width = f->folder.tabWidth;
824 	      rRect.height = f->core.height - rRect.y;
825 	      SetGC(f, GC_BLANK);
826 	      XFillRectangle(dpy, win, f->folder.gc,
827 			     rRect.x, rRect.y, rRect.width, rRect.height);
828 	      SetGC(f, GC_UNSET);
829 	    }
830 	}
831     }
832 }
833 
834 static void
Layout(XmLFolderWidget f,int resizeIfNeeded)835 Layout(XmLFolderWidget f,
836        int resizeIfNeeded)
837 {
838   /*  Window win;*/
839 
840   if (!f->folder.allowLayout)
841     return;
842   f->folder.allowLayout = 0;
843   if (f->folder.tabPlacement == XmFOLDER_LEFT ||
844       f->folder.tabPlacement == XmFOLDER_RIGHT)
845     LayoutLeftRight(f, resizeIfNeeded);
846   else
847     LayoutTopBottom(f, resizeIfNeeded);
848   if (XtIsRealized((Widget)f) && f->core.visible)
849     XClearArea(XtDisplay(f), XtWindow(f), 0, 0, 0, 0, True);
850   f->folder.allowLayout = 1;
851 }
852 
853 static void
LayoutTopBottom(XmLFolderWidget f,int resizeIfNeeded)854 LayoutTopBottom(XmLFolderWidget f,
855 		int resizeIfNeeded)
856 {
857   Display *dpy;
858   Window root;
859   int i, tabNum, x, y, w, h, pad1, pad2;
860   int rowNum, numRows, rowHeight, rowX, rowY;
861   WidgetList children;
862   Widget tab, child;
863   XmLFolderConstraintRec *fc;
864   XtGeometryResult result;
865   unsigned int inactPixHeight, pixHeight;
866   unsigned int inactPixWidth, pixWidth;
867   unsigned int pixBW, pixDepth;
868   Dimension height, minHeight;
869   Dimension width, minWidth, borderWidth;
870   Dimension co;
871   int st, ht;
872   int tabFit = 0, tgtTabWidth = 0;
873   int tabPaddingWidth, tailSpace = 0;
874   Boolean map, isManaged;
875   struct
876   {
877     int width, height, numTabs, y;
878   } rows[MAX_TAB_ROWS];
879 
880   dpy = XtDisplay(f);
881   children = f->composite.children;
882   st = f->manager.shadow_thickness;
883   ht = f->folder.highlightThickness;
884 
885   /* calculate corner offset */
886   if (f->folder.cornerStyle == XmCORNER_LINE)
887     co = (Dimension)((double)f->folder.cornerDimension * .5 + .99);
888   else if (f->folder.cornerStyle == XmCORNER_ARC)
889     co = (Dimension)((double)f->folder.cornerDimension * .3 + .99);
890   else
891     co = 0;
892 
893   /* caculate tabHeight, minWidth, minHeight, row y positions, */
894   /* row heights and tab pixmap dimensions */
895   rowX = 0;
896   rowY = 0;
897   rowHeight = 0;
898   rowNum = 0;
899   tabNum = 0;
900   minWidth = 0;
901 
902   if (f->folder.tabCount && f->folder.resizePolicy == XmRESIZE_PACK)
903     {
904       int maxTabWidth = f->folder.maxTabWidth;
905       int tabEffCount = 0;
906 
907       for (i = 0; i < f->folder.tabCount; i++)
908 	{
909 	  tab = f->folder.tabs[i];
910 	  if (!XtIsManaged(tab))
911             continue;
912 	  tabEffCount++;
913 	}
914 
915       tabPaddingWidth = (st + co + f->folder.marginWidth + ht +
916 	      f->folder.tabs[0]->core.border_width) * 2;
917       if (maxTabWidth * tabEffCount > f->core.width)
918         {
919       	  tgtTabWidth = f->core.width/tabEffCount - tabPaddingWidth;
920 	  tailSpace = f->core.width % tabEffCount;
921 	  tabFit = 1;
922 
923 	  /* if tabs get too small */
924 	  if (tgtTabWidth < f->folder.minTabWidth) {
925 	    tgtTabWidth = f->folder.minTabWidth;
926 	    tabFit = 0;
927 	  }
928 	}
929       else
930         {
931       	  tgtTabWidth = maxTabWidth - tabPaddingWidth;
932 	  tabFit = 0;
933 	}
934     }
935 
936   for (i = 0; i < f->folder.tabCount; i++)
937     {
938       tab = f->folder.tabs[i];
939       if (!XtIsManaged(tab))
940 	continue;
941 
942       if (f->folder.resizePolicy == XmRESIZE_PACK)
943         {
944 	  if (tabFit)
945             {
946 	      XtVaSetValues(tab, XmNwidth,
947       		      tailSpace? tgtTabWidth+1: tgtTabWidth, NULL);
948 	      if (tailSpace)
949 	      	 tailSpace--;
950             }
951 	  else
952 	    {
953 	       XtVaSetValues(tab, XmNwidth, tgtTabWidth, NULL);
954 	    }
955 	}
956 
957       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
958 
959       /* check for start of a new row */
960       fc->folder.firstInRow = False;
961       if (!tabNum)
962 	fc->folder.firstInRow = True;
963       if (f->folder.tabsPerRow && tabNum == f->folder.tabsPerRow)
964 	{
965 	  fc->folder.firstInRow = True;
966 
967 	  /* store prev row values and start next row */
968 	  if (rowX)
969 	    rowX -= f->folder.spacing;
970 	  rows[rowNum].y = rowY;
971 	  rows[rowNum].width = rowX;
972 	  rows[rowNum].height = rowHeight;
973 	  rows[rowNum].numTabs = tabNum;
974 	  if (f->folder.debugLevel)
975 	    {
976 	      fprintf(stderr, "XmLFolder: Layout: ");
977 	      fprintf(stderr, "row %d: y %d w %d h %d numTabs %d\n",
978 		      rowNum, rowY, rowX, rowHeight, tabNum);
979 	    }
980 	  rowY += rowHeight;
981 	  rowHeight = 0;
982 	  if (rowX > (int)minWidth)
983 	    minWidth = rowX;
984 	  rowX = 0;
985 	  tabNum = 0;
986 	  rowNum++;
987 	  if (rowNum == MAX_TAB_ROWS - 1)
988 	    {
989 	      XmLWarning((Widget)f, "Layout ERROR - too many rows\n");
990 	      return;
991 	    }
992 	}
993 
994       /* make sure row height > maximum tab height */
995       height = co + st + tab->core.height + tab->core.border_width * 2 +
996 	f->folder.marginHeight * 2 + ht * 2;
997       if ((int)height > rowHeight)
998 	rowHeight = height;
999 
1000       /* calc pixmap dimensions/maximum pixmap height */
1001       fc->folder.pixWidth = 0;
1002       fc->folder.pixHeight = 0;
1003       fc->folder.inactPixWidth = 0;
1004       fc->folder.inactPixHeight = 0;
1005       fc->folder.maxPixWidth = 0;
1006       fc->folder.maxPixHeight = 0;
1007       if (fc->folder.pix != XmUNSPECIFIED_PIXMAP)
1008 	{
1009 	  XGetGeometry(dpy, fc->folder.pix, &root,
1010 		       &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth);
1011 	  fc->folder.pixWidth = pixWidth;
1012 	  fc->folder.maxPixWidth = pixWidth;
1013 	  fc->folder.pixHeight = pixHeight;
1014 	  fc->folder.maxPixHeight = pixHeight;
1015 	  height = co + st + pixHeight + f->folder.marginHeight * 2 + ht * 2;
1016 	  if ((int)height > rowHeight)
1017 	    rowHeight = height;
1018 	}
1019       if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP)
1020 	{
1021 	  XGetGeometry(dpy, fc->folder.inactPix, &root, &x, &y,
1022 		       &inactPixWidth, &inactPixHeight, &pixBW, &pixDepth);
1023 	  fc->folder.inactPixWidth = inactPixWidth;
1024 	  if (inactPixWidth > fc->folder.maxPixWidth)
1025 	    fc->folder.maxPixWidth = inactPixWidth;
1026 	  fc->folder.inactPixHeight = inactPixHeight;
1027 	  if (inactPixHeight > fc->folder.maxPixHeight)
1028 	    fc->folder.maxPixHeight = inactPixHeight;
1029 	  height = co + st + inactPixHeight +
1030 	    f->folder.marginHeight * 2 + ht * 2;
1031 	  if ((int)height > rowHeight)
1032 	    rowHeight = height;
1033 	}
1034 
1035       /* increment rowX to move on to the next tab */
1036       rowX += st * 2 + co * 2 + f->folder.marginWidth * 2 + ht * 2 +
1037 	XtWidth(tab) + tab->core.border_width * 2;
1038       if (fc->folder.maxPixWidth)
1039 	rowX += fc->folder.maxPixWidth + f->folder.pixmapMargin;
1040       rowX += f->folder.spacing;
1041 
1042       tabNum++;
1043       fc->folder.row = rowNum;
1044     }
1045 
1046   /* complete calcuations for last row */
1047   if (rowX)
1048     rowX -= f->folder.spacing;
1049   rows[rowNum].y = rowY;
1050   rows[rowNum].width = rowX;
1051   rows[rowNum].height = rowHeight;
1052   rows[rowNum].numTabs = tabNum;
1053   numRows = rowNum + 1;
1054   if (f->folder.debugLevel)
1055     {
1056       fprintf(stderr, "XmLFolder: Layout: ");
1057       fprintf(stderr, "row %d: y %d w %d h %d numTabs %d\n",
1058 	      rowNum, rowY, rowX, rowHeight, tabNum);
1059     }
1060   f->folder.tabHeight = rowY + rowHeight;
1061   f->folder.tabBarHeight = f->folder.tabHeight;
1062   minHeight = f->folder.tabHeight;
1063   if ((int)minWidth < rowX)
1064     minWidth = rowX;
1065 
1066   /* add space for indent of upper rows */
1067   if (f->folder.tabsPerRow && minWidth)
1068     minWidth += 4;
1069 
1070   if (f->folder.debugLevel)
1071     {
1072       fprintf(stderr, "XmLFolder: Layout: ");
1073       fprintf(stderr, "tab bar minimum w %d h %d\n",
1074 	      (int)minWidth, (int)minHeight);
1075     }
1076 
1077   /* calculate width and height of non-tab children ensure */
1078   /* minWidth > width and minHeight > height */
1079   for (i = 0; i < f->composite.num_children; i++)
1080     {
1081       child = children[i];
1082       if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1083 	continue;
1084 
1085       height = XtHeight(child) + f->folder.tabHeight + st * 2;
1086       if (XtIsWidget(child))
1087 	height += child->core.border_width * 2;
1088       if (height > minHeight)
1089 	minHeight = height;
1090 
1091       width = XtWidth(child) + st * 2;
1092       if (XtIsWidget(child))
1093 	width += child->core.border_width * 2;
1094       if (width > minWidth)
1095 	minWidth = width;
1096     }
1097 
1098   if (f->folder.debugLevel)
1099     {
1100       fprintf(stderr, "XmLFolder: Layout: ");
1101       fprintf(stderr, "with non-tabs minimum w %d h %d\n",
1102 	      (int)minWidth, (int)minHeight);
1103     }
1104 
1105   /* Resize folder if needed */
1106   if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE)
1107     {
1108       if (minWidth <= 0)
1109 	minWidth = 1;
1110       if (minHeight <= 0)
1111 	minHeight = 1;
1112       result = XtMakeResizeRequest((Widget)f, minWidth, minHeight,
1113 				   &width, &height);
1114       if (result == XtGeometryAlmost)
1115 	XtMakeResizeRequest((Widget)f, width, height, NULL, NULL);
1116     }
1117 
1118   /* move active row to bottom */
1119   tab = f->folder.activeW;
1120   if (tab)
1121     {
1122       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1123       rowNum = fc->folder.row;
1124       f->folder.activeRow = rowNum;
1125       rows[rowNum].y = f->folder.tabHeight - rows[rowNum].height;
1126       for (i = rowNum + 1; i < numRows; i++)
1127 	rows[i].y -= rows[rowNum].height;
1128     }
1129   else
1130     f->folder.activeRow = -1;
1131 
1132   /* configure tab children */
1133   for (i = 0; i < f->folder.tabCount; i++)
1134     {
1135       tab = f->folder.tabs[i];
1136       if (!XtIsManaged(tab))
1137 	continue;
1138       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1139       rowNum = fc->folder.row;
1140 
1141       /* calculate tab x */
1142       if (fc->folder.firstInRow == True)
1143 	{
1144 	  if (f->folder.tabsPerRow && rowNum != f->folder.activeRow)
1145 	    x = 2;
1146 	  else
1147 	    x = 0;
1148 	}
1149       fc->folder.x = x;
1150       x += st + co + f->folder.marginWidth + ht;
1151       if (fc->folder.maxPixWidth)
1152 	x += fc->folder.maxPixWidth + f->folder.pixmapMargin;
1153 
1154       /* calculate tab y and tab height */
1155       fc->folder.height = rows[rowNum].height;
1156       if (f->folder.tabPlacement == XmFOLDER_TOP)
1157 	{
1158 	  fc->folder.y = rows[rowNum].y;
1159 	  y = fc->folder.y + fc->folder.height - f->folder.marginHeight -
1160 	    ht - XtHeight(tab) - tab->core.border_width * 2;
1161 	}
1162       else
1163 	{
1164 	  fc->folder.y = f->core.height - rows[rowNum].y -
1165 	    rows[rowNum].height;
1166 	  y = fc->folder.y + f->folder.marginHeight + ht;
1167 	}
1168 
1169       /* calculate tab padding */
1170       pad1 = 0;
1171       pad2 = 0;
1172       w = f->core.width - rows[rowNum].width;
1173       if (rowNum != f->folder.activeRow)
1174 	w -= 4;
1175       if (f->folder.tabsPerRow && w > 0)
1176 	{
1177 	  pad1 = w / (rows[rowNum].numTabs * 2);
1178 	  pad2 = pad1;
1179 	  if (fc->folder.firstInRow == True)
1180 	    pad2 += w - (pad1 * rows[rowNum].numTabs * 2);
1181 	}
1182       x += pad1;
1183 
1184       /* move tab widget into place */
1185       XtMoveWidget(tab, x, y);
1186 
1187       /* calculate tab width and move to next tab */
1188       x += pad2 + XtWidth(tab) + tab->core.border_width * 2 + ht +
1189 	f->folder.marginWidth + co + st;
1190       fc->folder.width = x - fc->folder.x;
1191       x += f->folder.spacing;
1192     }
1193 
1194   /* configure non-tab children */
1195   for (i = 0; i < f->composite.num_children; i++)
1196     {
1197       child = children[i];
1198       if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1199 	continue;
1200       if (f->folder.resizePolicy == XmRESIZE_NONE)
1201 	continue;
1202 
1203       w = (int)f->core.width - st * 2;
1204       h = (int)f->core.height - (int)f->folder.tabHeight - st * 2;
1205       if (h <= 0 || w <= 0)
1206 	continue;
1207       /* manager widgets will not configure correctly unless they */
1208       /* are managed, so manage then unmapped if they are unmanaged */
1209       isManaged = True;
1210       if (!XtIsManaged(child))
1211 	{
1212 	  XtVaGetValues(child,
1213 			XmNmappedWhenManaged, &map,
1214 			NULL);
1215 	  XtVaSetValues(child,
1216 			XmNmappedWhenManaged, False,
1217 			NULL);
1218 	  XtManageChild(child);
1219 	  isManaged = False;
1220 	}
1221       x = st;
1222       if (f->folder.tabPlacement == XmFOLDER_TOP)
1223 	y = f->folder.tabHeight + st;
1224       else
1225 	y = st;
1226       width = w;
1227       height = h;
1228       borderWidth = 0;
1229       if (XtIsWidget(child))
1230 	borderWidth = child->core.border_width;
1231       XtConfigureWidget(child, x, y, width, height, borderWidth);
1232       if (isManaged == False)
1233 	{
1234 	  XtUnmanageChild(child);
1235 	  XtVaSetValues(child, XmNmappedWhenManaged, map, NULL);
1236 	}
1237     }
1238 }
1239 
1240 static void
LayoutLeftRight(XmLFolderWidget f,int resizeIfNeeded)1241 LayoutLeftRight(XmLFolderWidget f,
1242 		int resizeIfNeeded)
1243 {
1244   Display *dpy;
1245   Window root;
1246   int i, tabNum, x, y, w, h, pad1, pad2;
1247   int rowNum, numRows, rowWidth, rowX, rowY;
1248   WidgetList children;
1249   Widget tab, child;
1250   XmLFolderConstraintRec *fc;
1251   XtGeometryResult result;
1252   unsigned int inactPixHeight, pixHeight;
1253   unsigned int inactPixWidth, pixWidth;
1254   unsigned int pixBW, pixDepth;
1255   Dimension height, minHeight;
1256   Dimension width, minWidth, borderWidth;
1257   Dimension co;
1258   int st, ht;
1259   Boolean map, isManaged;
1260   struct
1261   {
1262     int width, height, numTabs, x;
1263   } rows[MAX_TAB_ROWS];
1264 
1265   dpy = XtDisplay(f);
1266   children = f->composite.children;
1267   st = f->manager.shadow_thickness;
1268   ht = f->folder.highlightThickness;
1269 
1270   /* calculate corner offset */
1271   if (f->folder.cornerStyle == XmCORNER_LINE)
1272     co = (Dimension)((double)f->folder.cornerDimension * .5 + .99);
1273   else if (f->folder.cornerStyle == XmCORNER_ARC)
1274     co = (Dimension)((double)f->folder.cornerDimension * .3 + .99);
1275   else
1276     co = 0;
1277 
1278   /* caculate tabWidth, minWidth, minHeight, row x positions, */
1279   /* row widths and tab pixmap dimensions */
1280   rowX = 0;
1281   rowY = 0;
1282   rowWidth = 0;
1283   rowNum = 0;
1284   tabNum = 0;
1285   minHeight = 0;
1286   for (i = 0; i < f->folder.tabCount; i++)
1287     {
1288       tab = f->folder.tabs[i];
1289       if (!XtIsManaged(tab))
1290 	continue;
1291       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1292 
1293       /* check for start of a new row */
1294       fc->folder.firstInRow = False;
1295       if (!tabNum)
1296 	fc->folder.firstInRow = True;
1297       if (f->folder.tabsPerRow && tabNum == f->folder.tabsPerRow)
1298 	{
1299 	  fc->folder.firstInRow = True;
1300 
1301 	  /* store prev row values and start next row */
1302 	  if (rowY)
1303 	    rowY -= f->folder.spacing;
1304 	  rows[rowNum].x = rowX;
1305 	  rows[rowNum].height = rowY;
1306 	  rows[rowNum].width = rowWidth;
1307 	  rows[rowNum].numTabs = tabNum;
1308 	  if (f->folder.debugLevel)
1309 	    {
1310 	      fprintf(stderr, "XmLFolder: Layout: ");
1311 	      fprintf(stderr, "row %d: x %d w %d h %d numTabs %d\n",
1312 		      rowNum, rowX, rowWidth, rowY, tabNum);
1313 	    }
1314 	  rowX += rowWidth;
1315 	  rowWidth = 0;
1316 	  if (rowY > (int)minHeight)
1317 	    minHeight = rowY;
1318 	  rowY = 0;
1319 	  tabNum = 0;
1320 	  rowNum++;
1321 	  if (rowNum == MAX_TAB_ROWS - 1)
1322 	    {
1323 	      XmLWarning((Widget)f, "Layout ERROR - too many rows\n");
1324 	      return;
1325 	    }
1326 	}
1327 
1328       /* make sure row width > maximum tab width */
1329       width = co + st + tab->core.width + tab->core.border_width * 2 +
1330 	f->folder.marginHeight * 2 + ht * 2;
1331       if ((int)width > rowWidth)
1332 	rowWidth = width;
1333 
1334       /* calc pixmap dimensions/maximum pixmap width */
1335       pixWidth = 0;
1336       pixHeight = 0;
1337       fc->folder.pixWidth = 0;
1338       fc->folder.pixHeight = 0;
1339       fc->folder.inactPixWidth = 0;
1340       fc->folder.inactPixHeight = 0;
1341       fc->folder.maxPixWidth = 0;
1342       fc->folder.maxPixHeight = 0;
1343       if (fc->folder.pix != XmUNSPECIFIED_PIXMAP)
1344 	{
1345 	  XGetGeometry(dpy, fc->folder.pix, &root,
1346 		       &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth);
1347 	  fc->folder.pixWidth = pixWidth;
1348 	  fc->folder.maxPixWidth = pixWidth;
1349 	  fc->folder.pixHeight = pixHeight;
1350 	  fc->folder.maxPixHeight = pixHeight;
1351 	  width = co + st + pixWidth + f->folder.marginHeight * 2 + ht * 2;
1352 	  if ((int)width > rowWidth)
1353 	    rowWidth = width;
1354 	}
1355       if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP)
1356 	{
1357 	  XGetGeometry(dpy, fc->folder.inactPix, &root, &x, &y,
1358 		       &inactPixWidth, &inactPixHeight, &pixBW, &pixDepth);
1359 	  fc->folder.inactPixWidth = inactPixWidth;
1360 	  if (inactPixWidth > fc->folder.maxPixWidth)
1361 	    fc->folder.maxPixWidth = inactPixWidth;
1362 	  fc->folder.inactPixHeight = inactPixHeight;
1363 	  if (inactPixHeight > fc->folder.maxPixHeight)
1364 	    fc->folder.maxPixHeight = inactPixHeight;
1365 	  width = co + st + inactPixWidth +
1366 	    f->folder.marginHeight * 2 + ht * 2;
1367 	  if ((int)width > rowWidth)
1368 	    rowWidth = width;
1369 	}
1370 
1371       /* increment rowY to move on to the next tab */
1372       rowY += st * 2 + co * 2 + f->folder.marginWidth * 2 + ht * 2 +
1373 	XtHeight(tab) + tab->core.border_width * 2;
1374 
1375       if (fc->folder.maxPixHeight)
1376 	rowY += fc->folder.maxPixHeight + f->folder.pixmapMargin;
1377       rowY += f->folder.spacing;
1378 
1379       tabNum++;
1380       fc->folder.row = rowNum;
1381     }
1382 
1383   /* complete calcuations for last row */
1384   if (rowY)
1385     rowY -= f->folder.spacing;
1386   rows[rowNum].x = rowX;
1387   rows[rowNum].height = rowY;
1388   rows[rowNum].width = rowWidth;
1389   rows[rowNum].numTabs = tabNum;
1390   numRows = rowNum + 1;
1391   if (f->folder.debugLevel)
1392     {
1393       fprintf(stderr, "XmLFolder: Layout: ");
1394       fprintf(stderr, "row %d: x %d w %d h %d numTabs %d\n",
1395 	      rowNum, rowX, rowWidth, rowY, tabNum);
1396     }
1397   f->folder.tabWidth = rowX + rowWidth;
1398   f->folder.tabBarHeight = f->folder.tabWidth;
1399   minWidth = f->folder.tabWidth;
1400   if ((int)minHeight < rowY)
1401     minHeight = rowY;
1402 
1403   /* add space for indent of upper rows */
1404   if (f->folder.tabsPerRow && minHeight)
1405     minHeight += 4;
1406 
1407   if (f->folder.debugLevel)
1408     {
1409       fprintf(stderr, "XmLFolder: Layout: ");
1410       fprintf(stderr, "tab bar minimum w %d h %d\n",
1411 	      (int)minWidth, (int)minHeight);
1412     }
1413 
1414   /* calculate width and height of non-tab children ensure */
1415   /* minWidth > width and minHeight > height */
1416   for (i = 0; i < f->composite.num_children; i++)
1417     {
1418       child = children[i];
1419       if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1420 	continue;
1421 
1422       height = XtHeight(child) + st * 2;
1423       if (XtIsWidget(child))
1424 	height += f->core.border_width * 2;
1425       if (height > minHeight)
1426 	minHeight = height;
1427 
1428       width = XtWidth(child) + f->folder.tabWidth + st * 2;
1429       if (XtIsWidget(child))
1430 	width += f->core.border_width * 2;
1431       if (width > minWidth)
1432 	minWidth = width;
1433     }
1434 
1435   if (f->folder.debugLevel)
1436     {
1437       fprintf(stderr, "XmLFolder: Layout: ");
1438       fprintf(stderr, "with non-tabs minimum w %d h %d\n",
1439 	      (int)minWidth, (int)minHeight);
1440     }
1441 
1442   /* Resize folder if needed */
1443   if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE)
1444     {
1445       if (minWidth <= 0)
1446 	minWidth = 1;
1447       if (minHeight <= 0)
1448 	minHeight = 1;
1449       result = XtMakeResizeRequest((Widget)f, minWidth, minHeight,
1450 				   &width, &height);
1451       if (result == XtGeometryAlmost)
1452 	XtMakeResizeRequest((Widget)f, width, height, NULL, NULL);
1453     }
1454   /* move active row to bottom */
1455   tab = f->folder.activeW;
1456   if (tab)
1457     {
1458       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1459       rowNum = fc->folder.row;
1460       f->folder.activeRow = rowNum;
1461       rows[rowNum].x = f->folder.tabWidth - rows[rowNum].width;
1462       for (i = rowNum + 1; i < numRows; i++)
1463 	rows[i].x -= rows[rowNum].width;
1464     }
1465   else
1466     f->folder.activeRow = -1;
1467 
1468   /* configure tab children */
1469   for (i = 0; i < f->folder.tabCount; i++)
1470     {
1471       tab = f->folder.tabs[i];
1472       if (!XtIsManaged(tab))
1473 	continue;
1474       fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1475       rowNum = fc->folder.row;
1476 
1477       /* calculate tab x */
1478       if (fc->folder.firstInRow == True)
1479 	{
1480 	  if (f->folder.tabsPerRow && rowNum != f->folder.activeRow)
1481 	    y = 2;
1482 	  else
1483 	    y = 0;
1484 	}
1485       fc->folder.y = y;
1486       y += st + co + f->folder.marginWidth + ht;
1487       if (fc->folder.maxPixHeight)
1488 	y += fc->folder.maxPixHeight + f->folder.pixmapMargin;
1489 
1490       /* calculate tab x and tab width */
1491       fc->folder.width = rows[rowNum].width;
1492       if (f->folder.tabPlacement == XmFOLDER_LEFT)
1493 	{
1494 	  fc->folder.x = rows[rowNum].x;
1495 	  x = fc->folder.x + fc->folder.width - f->folder.marginHeight -
1496 	    ht - XtWidth(tab) - tab->core.border_width * 2;
1497 	}
1498       else
1499 	{
1500 	  fc->folder.x = f->core.width - rows[rowNum].x -
1501 	    rows[rowNum].width;
1502 	  x = fc->folder.x + f->folder.marginHeight + ht;
1503 	}
1504 
1505       /* calculate tab padding */
1506       pad1 = 0;
1507       pad2 = 0;
1508       h = f->core.height - rows[rowNum].height;
1509       if (rowNum != f->folder.activeRow)
1510 	h -= 4;
1511       if (f->folder.tabsPerRow && h > 0)
1512 	{
1513 	  pad1 = h / (rows[rowNum].numTabs * 2);
1514 	  pad2 = pad1;
1515 	  if (fc->folder.firstInRow == True)
1516 	    pad2 += h - (pad1 * rows[rowNum].numTabs * 2);
1517 	}
1518       y += pad1;
1519 
1520       /* move tab widget into place */
1521       XtMoveWidget(tab, x, y);
1522 
1523       /* calculate tab height and move to next tab */
1524       y += pad2 + XtHeight(tab) + tab->core.border_width * 2 + ht +
1525 	f->folder.marginWidth + co + st;
1526       fc->folder.height = y - fc->folder.y;
1527       y += f->folder.spacing;
1528     }
1529 
1530   /* configure non-tab children */
1531   for (i = 0; i < f->composite.num_children; i++)
1532     {
1533       child = children[i];
1534       if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1535 	continue;
1536       if (f->folder.resizePolicy == XmRESIZE_NONE)
1537 	continue;
1538 
1539       w = (int)f->core.width - (int)f->folder.tabWidth - st * 2;
1540       h = (int)f->core.height - st * 2;
1541       if (h <= 0 || w <= 0)
1542 	continue;
1543       /* manager widgets will not configure correctly unless they */
1544       /* are managed, so manage then unmapped if they are unmanaged */
1545       isManaged = True;
1546       if (!XtIsManaged(child))
1547 	{
1548 	  XtVaGetValues(child,
1549 			XmNmappedWhenManaged, &map,
1550 			NULL);
1551 	  XtVaSetValues(child,
1552 			XmNmappedWhenManaged, False,
1553 			NULL);
1554 	  XtManageChild(child);
1555 	  isManaged = False;
1556 	}
1557       y = st;
1558       if (f->folder.tabPlacement == XmFOLDER_LEFT)
1559 	x = f->folder.tabWidth + st;
1560       else
1561 	x = st;
1562       width = w;
1563       height = h;
1564       borderWidth = 0;
1565       if (XtIsWidget(child))
1566 	borderWidth = child->core.border_width;
1567       XtConfigureWidget(child, x, y, width, height, borderWidth);
1568       if (isManaged == False)
1569 	{
1570 	  XtUnmanageChild(child);
1571 	  XtVaSetValues(child, XmNmappedWhenManaged, map, NULL);
1572 	}
1573     }
1574 }
1575 
1576 static void
Resize(Widget w)1577 Resize(Widget w)
1578 {
1579   XmLFolderWidget f;
1580 
1581   f = (XmLFolderWidget)w;
1582   Layout(f, 0);
1583 }
1584 
1585 static XtGeometryResult
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * allow)1586 GeometryManager(Widget w,
1587 		XtWidgetGeometry *request,
1588 		XtWidgetGeometry *allow)
1589 {
1590   XmLFolderWidget f;
1591 
1592   f = (XmLFolderWidget)XtParent(w);
1593   if (f->folder.resizePolicy != XmRESIZE_STATIC ||
1594       XtIsSubclass(w, xmPrimitiveWidgetClass))
1595     {
1596       if (request->request_mode & CWWidth)
1597 	w->core.width = request->width;
1598       if (request->request_mode & CWHeight)
1599 	w->core.height = request->height;
1600       if (request->request_mode & CWX)
1601 	w->core.x = request->x;
1602       if (request->request_mode & CWY)
1603 	w->core.y = request->y;
1604       if (request->request_mode & CWBorderWidth)
1605 	w->core.border_width = request->border_width;
1606       Layout(f, 1);
1607       return XtGeometryYes;
1608     }
1609   return XtGeometryNo;
1610 }
1611 
1612 static void
ChangeManaged(Widget w)1613 ChangeManaged(Widget w)
1614 {
1615   XmLFolderWidget f;
1616 
1617   f = (XmLFolderWidget)w;
1618   Layout(f, 1);
1619   _XmNavigChangeManaged(w);
1620 }
1621 
1622 static void
ConstraintInitialize(Widget req,Widget w,ArgList args,Cardinal * narg)1623 ConstraintInitialize(Widget req,
1624 		     Widget w,
1625 		     ArgList args,
1626 		     Cardinal *narg)
1627 {
1628   XmLFolderWidget f;
1629   XmLFolderConstraintRec *fc;
1630 
1631   if (!XtIsRectObj(w))
1632     return;
1633   f = (XmLFolderWidget)XtParent(w);
1634   if (f->folder.debugLevel)
1635     fprintf(stderr, "XmLFolder: Constraint Init\n");
1636   fc = (XmLFolderConstraintRec *)(w->core.constraints);
1637   fc->folder.x = 0;
1638   fc->folder.y = 0;
1639   fc->folder.width = 0;
1640   fc->folder.height = 0;
1641   fc->folder.maxPixWidth = 0;
1642   fc->folder.maxPixHeight = 0;
1643   fc->folder.row = -1;
1644   fc->folder.firstInRow = False;
1645   if (fc->folder.managedName)
1646     fc->folder.managedName = (char *)strdup(fc->folder.managedName);
1647   if (XtIsSubclass(w, xmPrimitiveWidgetClass))
1648     {
1649       XtOverrideTranslations(w, f->folder.primTrans);
1650       XtAddCallback(w, XmNactivateCallback, PrimActivate, 0);
1651       XtVaSetValues(w,
1652 		    XmNhighlightThickness, 0,
1653 		    XmNshadowThickness, 0,
1654 		    NULL);
1655       if (XtIsSubclass(w, xmLabelWidgetClass))
1656 	XtVaSetValues(w, XmNfillOnArm, False, NULL);
1657 
1658       /* add child to tabs list */
1659       if (f->folder.tabAllocCount < f->folder.tabCount + 1)
1660 	{
1661 	  f->folder.tabAllocCount *= 2;
1662 	  f->folder.tabs = (Widget *)realloc((char *)f->folder.tabs,
1663 					     sizeof(Widget) * f->folder.tabAllocCount);
1664 	}
1665       f->folder.tabs[f->folder.tabCount++] = w;
1666 
1667     }
1668   if (XmIsDrawnButton(w))
1669     SetTabPlacement(f, w);
1670 
1671 #ifdef XmLEVAL
1672   if (f->folder.tabCount > 6)
1673     {
1674       fprintf(stderr, "XmL: evaluation version only supports <= 6 tabs\n");
1675       exit(0);
1676     }
1677 #endif
1678 }
1679 
1680 static void
ConstraintDestroy(Widget w)1681 ConstraintDestroy(Widget w)
1682 {
1683   XmLFolderWidget f;
1684   XmLFolderConstraintRec *fc;
1685   int i, j, activePos;
1686 
1687   if (!XtIsRectObj(w))
1688     return;
1689   f = (XmLFolderWidget)XtParent(w);
1690   if (f->folder.debugLevel)
1691     fprintf(stderr, "XmLFolder: Constraint Destroy\n");
1692   if (f->folder.focusW == w)
1693     f->folder.focusW = 0;
1694   fc = (XmLFolderConstraintRec *)(w->core.constraints);
1695   if (fc->folder.managedName)
1696     free((char *)fc->folder.managedName);
1697   if (fc->folder.freePix == True)
1698     {
1699       if (fc->folder.pix != XmUNSPECIFIED_PIXMAP)
1700 	XFreePixmap(XtDisplay(w), fc->folder.pix);
1701       if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP)
1702 	XFreePixmap(XtDisplay(w), fc->folder.inactPix);
1703     }
1704   if (XtIsSubclass(w, xmPrimitiveWidgetClass))
1705     {
1706       XtRemoveCallback(w, XmNactivateCallback, PrimActivate, 0);
1707 
1708       /* remove child from tabs list and calculate active pos */
1709       activePos = -1;
1710       j = 0;
1711       for (i = 0; i < f->folder.tabCount; i++)
1712 	if (f->folder.tabs[i] != w)
1713 	  {
1714 	    if (f->folder.activeW == f->folder.tabs[i])
1715 	      activePos = j;
1716 	    f->folder.tabs[j++] = f->folder.tabs[i];
1717 	  }
1718       if (j != f->folder.tabCount - 1)
1719 	XmLWarning((Widget)f, "ConstraintDestroy() - bad child list");
1720       f->folder.tabCount = j;
1721       f->folder.activeTab = activePos;
1722       if (activePos == -1)
1723 	f->folder.activeW = 0;
1724     }
1725 }
1726 
1727 static void
DrawTabPixmap(XmLFolderWidget f,Widget tab,int active)1728 DrawTabPixmap(XmLFolderWidget f,
1729 	      Widget tab,
1730 	      int active)
1731 {
1732   Display *dpy;
1733   Window win;
1734   int x, y;
1735   Pixmap pixmap;
1736   Dimension pixWidth, pixHeight, ht;
1737   XmLFolderConstraintRec *fc;
1738 
1739   x = 0;
1740   y = 0;
1741   dpy = XtDisplay(f);
1742   win = XtWindow(f);
1743   fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1744   ht = f->folder.highlightThickness;
1745   if (active)
1746     {
1747       pixWidth = fc->folder.pixWidth;
1748       pixHeight = fc->folder.pixHeight;
1749       pixmap = fc->folder.pix;
1750     }
1751   else
1752     {
1753       pixWidth = fc->folder.inactPixWidth;
1754       pixHeight = fc->folder.inactPixHeight;
1755       pixmap = fc->folder.inactPix;
1756     }
1757   if (f->folder.tabPlacement == XmFOLDER_TOP)
1758     {
1759       x = tab->core.x - pixWidth - ht - f->folder.pixmapMargin;
1760       y = tab->core.y + tab->core.height - pixHeight;
1761     }
1762   else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1763     {
1764       x = tab->core.x - fc->folder.pixWidth - ht - f->folder.pixmapMargin;
1765       y = tab->core.y;
1766     }
1767   else if (f->folder.tabPlacement == XmFOLDER_LEFT)
1768     {
1769       x = tab->core.x + tab->core.width - pixWidth;
1770       y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht;
1771     }
1772   else if (f->folder.tabPlacement == XmFOLDER_RIGHT)
1773     {
1774       x = tab->core.x;
1775       y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht;
1776     }
1777   XCopyArea(dpy, pixmap, win, f->folder.gc, 0, 0, pixWidth, pixHeight, x, y);
1778 }
1779 
1780 static void
DrawManagerShadowTopBottom(XmLFolderWidget f,XRectangle * rect)1781 DrawManagerShadowTopBottom(XmLFolderWidget f,
1782 			   XRectangle *rect)
1783 {
1784   Display *dpy;
1785   Window win;
1786   XmLFolderConstraintRec *fc;
1787   XSegment *topSeg, *botSeg;
1788   int i, bCount, tCount, st, botOff, isManaged;
1789 
1790   dpy = XtDisplay(f);
1791   win = XtWindow(f);
1792   st = f->manager.shadow_thickness;
1793   if (!st)
1794     return;
1795   botOff = f->core.height - f->folder.tabHeight - 1;
1796 
1797   topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1798   botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1799 
1800   /* top shadow */
1801   fc = 0;
1802   if (f->folder.activeW)
1803     fc = (XmLFolderConstraintRec *)(f->folder.activeW->core.constraints);
1804   tCount = 0;
1805   if (fc)
1806     for (i = 0; i < st; i++)
1807       {
1808 	topSeg[tCount].x1 = rect->x + i;
1809 	topSeg[tCount].y1 = rect->y + i;
1810 	topSeg[tCount].x2 = fc->folder.x + i;
1811 	topSeg[tCount].y2 = rect->y + i;
1812 	if (rect->x != fc->folder.x)
1813 	  tCount++;
1814 	topSeg[tCount].x1 = rect->x + fc->folder.x +
1815 	  fc->folder.width - i - 1;
1816 	topSeg[tCount].y1 = rect->y + i;
1817 	topSeg[tCount].x2 = rect->x + rect->width - i - 1;
1818 	topSeg[tCount].y2 = rect->y + i;
1819 	if (fc->folder.x + fc->folder.width != rect->width)
1820 	  tCount++;
1821       }
1822   else
1823     for (i = 0; i < st; i++)
1824       {
1825 	topSeg[tCount].x1 = rect->x + i;
1826 	topSeg[tCount].y1 = rect->y + i;
1827 	topSeg[tCount].x2 = rect->x + rect->width - i - 1;
1828 	topSeg[tCount].y2 = rect->y + i;
1829 	tCount++;
1830       }
1831   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1832     for (i = 0 ; i < tCount; i++)
1833       {
1834 	topSeg[i].y1 = botOff - topSeg[i].y1;
1835 	topSeg[i].y2 = botOff - topSeg[i].y2;
1836       }
1837   if (tCount)
1838     {
1839       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1840 	SetGC(f, GC_SHADOWBOT);
1841       else
1842 	SetGC(f, GC_SHADOWTOP);
1843       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
1844       SetGC(f, GC_UNSET);
1845     }
1846 
1847   /* see if there's any composite widgets in the folder */
1848   isManaged = 0;
1849   for (i = 0; i < f->composite.num_children; i++)
1850     {
1851       Widget child = f->composite.children[i];
1852       if (!XtIsSubclass(child, xmPrimitiveWidgetClass) && XtIsManaged(child))
1853         {
1854 	  isManaged = 1;
1855 	  break;
1856 	}
1857 
1858     }
1859 
1860   /* no need to draw shadow for the manager area if
1861      there isn't any composite widgets in the folder */
1862   if (!isManaged)
1863     {
1864       free((char *)topSeg);
1865       free((char *)botSeg);
1866       return;
1867     }
1868 
1869   /* left shadow */
1870   tCount = 0;
1871   for (i = 0; i < st; i++)
1872     {
1873       topSeg[tCount].x1 = rect->x + i;
1874       topSeg[tCount].y1 = rect->y + i;
1875       topSeg[tCount].x2 = rect->x + i;
1876       topSeg[tCount].y2 = rect->y + rect->height - i - 1;
1877       tCount++;
1878     }
1879   if (tCount)
1880     {
1881       SetGC(f, GC_SHADOWTOP);
1882       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
1883       SetGC(f, GC_UNSET);
1884     }
1885 
1886   /* right shadow */
1887   bCount = 0;
1888   for (i = 0; i < st; i++)
1889     {
1890       botSeg[bCount].x1 = rect->x + rect->width - i - 1;
1891       botSeg[bCount].y1 = rect->y + i;
1892       botSeg[bCount].x2 = rect->x + rect->width - i - 1;
1893       botSeg[bCount].y2 = rect->y + rect->height - i - 1;
1894       bCount++;
1895     }
1896   if (bCount)
1897     {
1898       SetGC(f, GC_SHADOWBOT);
1899       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
1900       SetGC(f, GC_UNSET);
1901     }
1902 
1903   /* bottom shadow */
1904   bCount = 0;
1905   for (i = 0; i < st; i++)
1906     {
1907       botSeg[bCount].x1 = rect->x + i;
1908       botSeg[bCount].y1 = rect->y + rect->height - i - 1;
1909       botSeg[bCount].x2 = rect->x + rect->width - i - 1;
1910       botSeg[bCount].y2 = rect->y + rect->height - i - 1;
1911       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1912 	{
1913 	  botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
1914 	  botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
1915 	}
1916       bCount++;
1917     }
1918   if (bCount)
1919     {
1920       if (f->folder.tabPlacement == XmFOLDER_TOP)
1921 	SetGC(f, GC_SHADOWBOT);
1922       else
1923 	SetGC(f, GC_SHADOWTOP);
1924       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
1925       SetGC(f, GC_UNSET);
1926     }
1927   free((char *)topSeg);
1928   free((char *)botSeg);
1929 }
1930 
1931 static void
DrawManagerShadowLeftRight(XmLFolderWidget f,XRectangle * rect)1932 DrawManagerShadowLeftRight(XmLFolderWidget f,
1933 			   XRectangle *rect)
1934 {
1935   Display *dpy;
1936   Window win;
1937   XmLFolderConstraintRec *fc;
1938   XSegment *topSeg, *botSeg;
1939   int i, bCount, tCount, st, rightOff;
1940 
1941   dpy = XtDisplay(f);
1942   win = XtWindow(f);
1943   st = f->manager.shadow_thickness;
1944   if (!st)
1945     return;
1946   rightOff = f->core.width - f->folder.tabWidth - 1;
1947 
1948   topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1949   botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1950 
1951   /* left shadow */
1952   fc = 0;
1953   if (f->folder.activeW)
1954     fc = (XmLFolderConstraintRec *)(f->folder.activeW->core.constraints);
1955   tCount = 0;
1956   if (fc)
1957     for (i = 0; i < st; i++)
1958       {
1959 	topSeg[tCount].x1 = rect->x + i;
1960 	topSeg[tCount].y1 = rect->y + i;
1961 	topSeg[tCount].x2 = rect->x + i;
1962 	topSeg[tCount].y2 = fc->folder.y + i;
1963 	if (rect->y != fc->folder.y)
1964 	  tCount++;
1965 	topSeg[tCount].x1 = rect->x + i;
1966 	topSeg[tCount].y1 = rect->y + fc->folder.y +
1967 	  fc->folder.height - i - 1;
1968 	topSeg[tCount].x2 = rect->x + i;
1969 	topSeg[tCount].y2 = rect->y + rect->height - i - 1;
1970 	if (fc->folder.y + fc->folder.height != rect->height)
1971 	  tCount++;
1972       }
1973   else
1974     for (i = 0; i < st; i++)
1975       {
1976 	topSeg[tCount].x1 = rect->x + i;
1977 	topSeg[tCount].y1 = rect->y + i;
1978 	topSeg[tCount].x2 = rect->x + i;
1979 	topSeg[tCount].y2 = rect->y + rect->height - i - 1;
1980 	tCount++;
1981       }
1982   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
1983     for (i = 0 ; i < tCount; i++)
1984       {
1985 	topSeg[i].x1 = rightOff - topSeg[i].x1;
1986 	topSeg[i].x2 = rightOff - topSeg[i].x2;
1987       }
1988   if (tCount)
1989     {
1990       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
1991 	SetGC(f, GC_SHADOWBOT);
1992       else
1993 	SetGC(f, GC_SHADOWTOP);
1994       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
1995       SetGC(f, GC_UNSET);
1996     }
1997 
1998   /* top shadow */
1999   tCount = 0;
2000   for (i = 0; i < st; i++)
2001     {
2002       topSeg[tCount].x1 = rect->x + i;
2003       topSeg[tCount].y1 = rect->y + i;
2004       topSeg[tCount].x2 = rect->x + rect->width - i - 1;
2005       topSeg[tCount].y2 = rect->y + i;
2006       tCount++;
2007     }
2008   if (tCount)
2009     {
2010       SetGC(f, GC_SHADOWTOP);
2011       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2012       SetGC(f, GC_UNSET);
2013     }
2014 
2015   /* bottom shadow */
2016   bCount = 0;
2017   for (i = 0; i < st; i++)
2018     {
2019       botSeg[bCount].x1 = rect->x + i;
2020       botSeg[bCount].y1 = rect->y + rect->height - i - 1;
2021       botSeg[bCount].x2 = rect->x + rect->width - i - 1;
2022       botSeg[bCount].y2 = rect->y + rect->height - i - 1;
2023       bCount++;
2024     }
2025   if (bCount)
2026     {
2027       SetGC(f, GC_SHADOWBOT);
2028       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2029       SetGC(f, GC_UNSET);
2030     }
2031 
2032   /* right shadow */
2033   bCount = 0;
2034   for (i = 0; i < st; i++)
2035     {
2036       botSeg[bCount].x1 = rect->x + rect->width - i - 1;
2037       botSeg[bCount].y1 = rect->y + i;
2038       botSeg[bCount].x2 = rect->x + rect->width - i - 1;
2039       botSeg[bCount].y2 = rect->y + rect->height - i - 1;
2040       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2041 	{
2042 	  botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2043 	  botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2044 	}
2045       bCount++;
2046     }
2047   if (bCount)
2048     {
2049       if (f->folder.tabPlacement == XmFOLDER_LEFT)
2050 	SetGC(f, GC_SHADOWBOT);
2051       else
2052 	SetGC(f, GC_SHADOWTOP);
2053       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2054       SetGC(f, GC_UNSET);
2055     }
2056   free((char *)topSeg);
2057   free((char *)botSeg);
2058 }
2059 
2060 static void
DrawTabShadowArcTopBottom(XmLFolderWidget f,Widget w)2061 DrawTabShadowArcTopBottom(XmLFolderWidget f,
2062 			  Widget w)
2063 {
2064   XmLFolderConstraintRec *fc;
2065   Display *dpy;
2066   Window win;
2067   XSegment *topSeg, *botSeg;
2068   XRectangle rect, rect2;
2069   XArc arc;
2070   int tCount, bCount;
2071   int i, st, cd, botOff;
2072 
2073   dpy = XtDisplay(f);
2074   win = XtWindow(f);
2075   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2076   botOff = 2 * fc->folder.y + fc->folder.height - 1;
2077   st = f->manager.shadow_thickness;
2078   if (!st)
2079     return;
2080   cd = f->folder.cornerDimension;
2081 
2082   tCount = 0;
2083   bCount = 0;
2084   topSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2085   botSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2086   for (i = 0; i < st; i++)
2087     {
2088       /* left tab shadow */
2089       topSeg[tCount].x1 = fc->folder.x + i;
2090       topSeg[tCount].y1 = fc->folder.y + cd + st;
2091       topSeg[tCount].x2 = fc->folder.x + i;
2092       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1;
2093       if (w == f->folder.activeW)
2094 	topSeg[tCount].y2 += i;
2095       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2096 	{
2097 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2098 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2099 	}
2100       tCount++;
2101 
2102       /* right tab shadow */
2103       botSeg[bCount].x1 = fc->folder.x + fc->folder.width - i - 1;
2104       botSeg[bCount].y1 = fc->folder.y + cd + st;
2105       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - i - 1;
2106       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1;
2107       if (w == f->folder.activeW)
2108 	botSeg[bCount].y2 += i;
2109       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2110 	{
2111 	  botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2112 	  botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2113 	}
2114       bCount++;
2115     }
2116   if (tCount)
2117     {
2118       SetGC(f, GC_SHADOWTOP);
2119       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2120       SetGC(f, GC_UNSET);
2121     }
2122   if (bCount)
2123     {
2124       SetGC(f, GC_SHADOWBOT);
2125       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2126       SetGC(f, GC_UNSET);
2127     }
2128   tCount = 0;
2129   for (i = 0; i < st; i++)
2130     {
2131       /* top tab shadow */
2132       topSeg[tCount].x1 = fc->folder.x + cd + st;
2133       topSeg[tCount].y1 = fc->folder.y + i;
2134       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - cd - st - 1;
2135       topSeg[tCount].y2 = fc->folder.y + i;
2136       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2137 	{
2138 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2139 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2140 	}
2141       tCount++;
2142     }
2143   if (tCount)
2144     {
2145       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2146 	SetGC(f, GC_SHADOWBOT);
2147       else
2148 	SetGC(f, GC_SHADOWTOP);
2149       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2150       SetGC(f, GC_UNSET);
2151     }
2152   free((char *)topSeg);
2153   free((char *)botSeg);
2154 
2155   /* left corner blank background */
2156   rect.x = fc->folder.x;
2157   rect.y = fc->folder.y;
2158   rect.width = cd + st;
2159   rect.height = cd + st;
2160   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2161     rect.y = fc->folder.y + fc->folder.height - rect.height;
2162   SetGC(f, GC_BLANK);
2163   XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
2164 		 rect.width, rect.height);
2165   SetGC(f, GC_UNSET);
2166 
2167   /* left arc */
2168   /* various X Servers have problems drawing arcs - so set clip rect */
2169   /* and draw two circles, one smaller than the other, for corner */
2170   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted);
2171   arc.x = rect.x;
2172   arc.y = rect.y;
2173   arc.width = rect.width * 2;
2174   arc.height = rect.height * 2;
2175   if (f->folder.serverDrawsArcsLarge == True)
2176     {
2177       arc.width -= 1;
2178       arc.height -= 1;
2179     }
2180   arc.angle1 = 0 * 64;
2181   arc.angle2 = 360 * 64;
2182   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2183     arc.y = fc->folder.y + fc->folder.height - arc.height;
2184   SetGC(f, GC_SHADOWTOP);
2185   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2186 	   arc.angle1, arc.angle2);
2187   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2188 	   arc.angle1, arc.angle2);
2189   SetGC(f, GC_UNSET);
2190 
2191   rect2 = rect;
2192   rect2.x += st;
2193   rect2.width -= st;
2194   rect2.height -= st;
2195   if (f->folder.tabPlacement == XmFOLDER_TOP)
2196     rect2.y += st;
2197   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted);
2198   if (w == f->folder.activeW)
2199     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2200   else
2201     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2202   arc.x += st;
2203   arc.y += st;
2204   arc.width -= st * 2;
2205   arc.height -= st * 2;
2206   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2207 	   arc.angle1, arc.angle2);
2208   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2209 	   arc.angle1, arc.angle2);
2210   XSetClipMask(dpy, f->folder.gc, None);
2211 
2212   /* right corner blank background */
2213   rect.x = fc->folder.x + fc->folder.width - cd - st;
2214   SetGC(f, GC_BLANK);
2215   XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
2216 		 rect.width, rect.height);
2217   SetGC(f, GC_UNSET);
2218 
2219   /* right arc */
2220   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted);
2221   arc.x = rect.x - cd - st;
2222   arc.y = rect.y;
2223   arc.width = rect.width * 2;
2224   arc.height = rect.height * 2;
2225   if (f->folder.serverDrawsArcsLarge == True)
2226     {
2227       arc.width -= 1;
2228       arc.height -= 1;
2229     }
2230   arc.angle1 = 0 * 64;
2231   arc.angle2 = 360 * 64;
2232   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2233     arc.y = fc->folder.y + fc->folder.height - arc.height;
2234   SetGC(f, GC_SHADOWBOT);
2235   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2236 	   arc.angle1, arc.angle2);
2237   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2238 	   arc.angle1, arc.angle2);
2239   SetGC(f, GC_UNSET);
2240 
2241   rect2 = rect;
2242   rect2.width -= st;
2243   rect2.height -= st;
2244   if (f->folder.tabPlacement == XmFOLDER_TOP)
2245     rect2.y += st;
2246   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted);
2247   if (w == f->folder.activeW)
2248     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2249   else
2250     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2251   arc.x += st;
2252   arc.y += st;
2253   arc.width -= st * 2;
2254   arc.height -= st * 2;
2255   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2256 	   arc.angle1, arc.angle2);
2257   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2258 	   arc.angle1, arc.angle2);
2259   XSetClipMask(dpy, f->folder.gc, None);
2260 }
2261 
2262 static void
DrawTabShadowArcLeftRight(XmLFolderWidget f,Widget w)2263 DrawTabShadowArcLeftRight(XmLFolderWidget f,
2264 			  Widget w)
2265 {
2266   XmLFolderConstraintRec *fc;
2267   Display *dpy;
2268   Window win;
2269   XSegment *topSeg, *botSeg;
2270   XRectangle rect, rect2;
2271   XArc arc;
2272   int tCount, bCount;
2273   int i, st, cd, rightOff;
2274 
2275   dpy = XtDisplay(f);
2276   win = XtWindow(f);
2277   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2278   rightOff = 2 * fc->folder.x + fc->folder.width - 1;
2279   st = f->manager.shadow_thickness;
2280   if (!st)
2281     return;
2282   cd = f->folder.cornerDimension;
2283 
2284   tCount = 0;
2285   bCount = 0;
2286   topSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2287   botSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2288   for (i = 0; i < st; i++)
2289     {
2290       /* top tab shadow */
2291       topSeg[tCount].x1 = fc->folder.x + cd + st;
2292       topSeg[tCount].y1 = fc->folder.y + i;
2293       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1;
2294       if (w == f->folder.activeW)
2295 	topSeg[tCount].x2 += i;
2296       topSeg[tCount].y2 = fc->folder.y + i;
2297       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2298 	{
2299 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2300 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2301 	}
2302       tCount++;
2303 
2304       /* bottom tab shadow */
2305       botSeg[bCount].x1 = fc->folder.x + cd + st;
2306       botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1;
2307       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1;
2308       if (w == f->folder.activeW)
2309 	botSeg[bCount].x2 += i;
2310       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1;
2311       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2312 	{
2313 	  botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2314 	  botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2315 	}
2316       bCount++;
2317     }
2318   if (tCount)
2319     {
2320       SetGC(f, GC_SHADOWTOP);
2321       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2322       SetGC(f, GC_UNSET);
2323     }
2324   if (bCount)
2325     {
2326       SetGC(f, GC_SHADOWBOT);
2327       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2328       SetGC(f, GC_UNSET);
2329     }
2330   tCount = 0;
2331   for (i = 0; i < st; i++)
2332     {
2333       /* left tab shadow */
2334       topSeg[tCount].x1 = fc->folder.x + i;
2335       topSeg[tCount].y1 = fc->folder.y + cd + st;
2336       topSeg[tCount].x2 = fc->folder.x + i;
2337       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - cd - st - 1;
2338       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2339 	{
2340 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2341 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2342 	}
2343       tCount++;
2344     }
2345   if (tCount)
2346     {
2347       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2348 	SetGC(f, GC_SHADOWBOT);
2349       else
2350 	SetGC(f, GC_SHADOWTOP);
2351       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2352       SetGC(f, GC_UNSET);
2353     }
2354   free((char *)topSeg);
2355   free((char *)botSeg);
2356 
2357   /* top corner blank background */
2358   rect.x = fc->folder.x;
2359   rect.y = fc->folder.y;
2360   rect.width = cd + st;
2361   rect.height = cd + st;
2362   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2363     rect.x = fc->folder.x + fc->folder.width - rect.width;
2364   SetGC(f, GC_BLANK);
2365   XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
2366 		 rect.width, rect.height);
2367   SetGC(f, GC_UNSET);
2368 
2369   /* top arc */
2370   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted);
2371   arc.x = rect.x;
2372   arc.y = rect.y;
2373   arc.width = rect.width * 2;
2374   arc.height = rect.height * 2;
2375   if (f->folder.serverDrawsArcsLarge == True)
2376     {
2377       arc.width -= 1;
2378       arc.height -= 1;
2379     }
2380   arc.angle1 = 0 * 64;
2381   arc.angle2 = 360 * 64;
2382   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2383     arc.x = fc->folder.x + fc->folder.width - arc.width;
2384   SetGC(f, GC_SHADOWTOP);
2385   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2386 	   arc.angle1, arc.angle2);
2387   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2388 	   arc.angle1, arc.angle2);
2389   SetGC(f, GC_UNSET);
2390 
2391   rect2 = rect;
2392   rect2.width -= st;
2393   rect2.height -= st;
2394   rect2.y += st;
2395   if (f->folder.tabPlacement == XmFOLDER_LEFT)
2396     rect2.x += st;
2397   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted);
2398   if (w == f->folder.activeW)
2399     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2400   else
2401     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2402   arc.x += st;
2403   arc.y += st;
2404   arc.width -= st * 2;
2405   arc.height -= st * 2;
2406   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2407 	   arc.angle1, arc.angle2);
2408   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2409 	   arc.angle1, arc.angle2);
2410   XSetClipMask(dpy, f->folder.gc, None);
2411 
2412   /* bottom corner blank background */
2413   rect.y = fc->folder.y + fc->folder.height - cd - st;
2414   SetGC(f, GC_BLANK);
2415   XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y,
2416 		 rect.width, rect.height);
2417   SetGC(f, GC_UNSET);
2418 
2419   /* bottom arc */
2420   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted);
2421   arc.x = rect.x;
2422   arc.y = rect.y - cd - st;
2423   arc.width = rect.width * 2;
2424   arc.height = rect.height * 2;
2425   if (f->folder.serverDrawsArcsLarge == True)
2426     {
2427       arc.width -= 1;
2428       arc.height -= 1;
2429     }
2430   arc.angle1 = 0 * 64;
2431   arc.angle2 = 360 * 64;
2432   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2433     arc.x = fc->folder.x + fc->folder.width - arc.width;
2434   SetGC(f, GC_SHADOWBOT);
2435   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2436 	   arc.angle1, arc.angle2);
2437   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2438 	   arc.angle1, arc.angle2);
2439   SetGC(f, GC_UNSET);
2440 
2441   rect2 = rect;
2442   rect2.width -= st;
2443   rect2.height -= st;
2444   if (f->folder.tabPlacement == XmFOLDER_LEFT)
2445     rect2.x += st;
2446   XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted);
2447   if (w == f->folder.activeW)
2448     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2449   else
2450     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2451   arc.x += st;
2452   arc.y += st;
2453   arc.width -= st * 2;
2454   arc.height -= st * 2;
2455   XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2456 	   arc.angle1, arc.angle2);
2457   XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height,
2458 	   arc.angle1, arc.angle2);
2459   XSetClipMask(dpy, f->folder.gc, None);
2460 }
2461 
2462 static void
DrawTabShadowLineTopBottom(XmLFolderWidget f,Widget w)2463 DrawTabShadowLineTopBottom(XmLFolderWidget f,
2464 			   Widget w)
2465 {
2466   XmLFolderConstraintRec *fc;
2467   Display *dpy;
2468   Window win;
2469   XSegment *topSeg, *botSeg;
2470   XPoint points[4];
2471   int tCount, bCount, botOff, i, st, cd, y;
2472 
2473   dpy = XtDisplay(f);
2474   win = XtWindow(f);
2475   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2476   botOff = 2 * fc->folder.y + fc->folder.height - 1;
2477   st = f->manager.shadow_thickness;
2478   if (!st)
2479     return;
2480   cd = f->folder.cornerDimension;
2481 
2482   tCount = 0;
2483   bCount = 0;
2484   topSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2485   botSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2486   for (i = 0; i < st; i++)
2487     {
2488       /* left tab shadow */
2489       topSeg[tCount].x1 = fc->folder.x + i;
2490       topSeg[tCount].y1 = fc->folder.y + cd + st;
2491       topSeg[tCount].x2 = fc->folder.x + i;
2492       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1;
2493       if (w == f->folder.activeW)
2494 	topSeg[tCount].y2 += i;
2495       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2496 	{
2497 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2498 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2499 	}
2500       tCount++;
2501       /* right tab shadow */
2502       botSeg[bCount].x1 = fc->folder.x + fc->folder.width - i - 1;
2503       botSeg[bCount].y1 = fc->folder.y + cd + st;
2504       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - i - 1;
2505       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1;
2506       if (w == f->folder.activeW)
2507 	botSeg[bCount].y2 += i;
2508       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2509 	{
2510 	  botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2511 	  botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2512 	}
2513       bCount++;
2514     }
2515   if (tCount)
2516     {
2517       SetGC(f, GC_SHADOWTOP);
2518       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2519       SetGC(f, GC_UNSET);
2520     }
2521   if (bCount)
2522     {
2523       SetGC(f, GC_SHADOWBOT);
2524       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2525       SetGC(f, GC_UNSET);
2526     }
2527   tCount = 0;
2528   for (i = 0; i < st; i++)
2529     {
2530       /* top tab shadow */
2531       topSeg[tCount].x1 = fc->folder.x + cd + st;
2532       topSeg[tCount].y1 = fc->folder.y + i;
2533       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - cd - st - 1;
2534       topSeg[tCount].y2 = fc->folder.y + i;
2535       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2536 	{
2537 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2538 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2539 	}
2540       tCount++;
2541     }
2542   if (tCount)
2543     {
2544       if (f->folder.tabPlacement == XmFOLDER_TOP)
2545 	SetGC(f, GC_SHADOWTOP);
2546       else
2547 	SetGC(f, GC_SHADOWBOT);
2548       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2549       SetGC(f, GC_UNSET);
2550     }
2551   free((char *)topSeg);
2552   free((char *)botSeg);
2553 
2554   /* left top line */
2555   points[0].x = fc->folder.x;
2556   points[0].y = fc->folder.y + cd + st - 1;
2557   points[1].x = fc->folder.x + cd + st - 1;
2558   points[1].y = fc->folder.y;
2559   points[2].x = fc->folder.x + cd + st - 1;
2560   points[2].y = fc->folder.y + cd + st - 1;
2561   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2562     {
2563       points[0].y = botOff - points[0].y;
2564       points[1].y = botOff - points[1].y;
2565       points[2].y = botOff - points[2].y;
2566     }
2567   y = fc->folder.y;
2568   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2569     y = fc->folder.y + fc->folder.height - cd - st;
2570   SetGC(f, GC_BLANK);
2571   XFillRectangle(dpy, win, f->folder.gc, fc->folder.x, y, cd + st, cd + st);
2572   SetGC(f, GC_UNSET);
2573   SetGC(f, GC_SHADOWTOP);
2574   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2575 	       CoordModeOrigin);
2576   points[3].x = points[0].x;
2577   points[3].y = points[0].y;
2578   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2579   SetGC(f, GC_UNSET);
2580   if (w == f->folder.activeW)
2581     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2582   else
2583     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2584   points[0].x += st;
2585   points[1].y += st;
2586   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2587     points[1].y -= st * 2;
2588   XFillPolygon(dpy, win, f->folder.gc, points, 3,
2589 	       Nonconvex, CoordModeOrigin);
2590   points[3].x = points[0].x;
2591   points[3].y = points[0].y;
2592   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2593 
2594   /* right top line */
2595   points[0].x = fc->folder.x + fc->folder.width - 1;
2596   points[0].y = fc->folder.y + cd + st - 1;
2597   points[1].x = fc->folder.x + fc->folder.width - cd - st;
2598   points[1].y = fc->folder.y;
2599   points[2].x = fc->folder.x + fc->folder.width - cd - st;
2600   points[2].y = fc->folder.y + cd + st - 1;
2601   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2602     {
2603       points[0].y = botOff - points[0].y;
2604       points[1].y = botOff - points[1].y;
2605       points[2].y = botOff - points[2].y;
2606     }
2607   y = fc->folder.y;
2608   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2609     y = fc->folder.y + fc->folder.height - cd - st;
2610   SetGC(f, GC_BLANK);
2611   XFillRectangle(dpy, win, f->folder.gc, fc->folder.x + fc->folder.width -
2612 		 cd - st, y, cd + st, cd + st);
2613   SetGC(f, GC_UNSET);
2614   if (f->folder.tabPlacement == XmFOLDER_TOP)
2615     SetGC(f, GC_SHADOWTOP);
2616   else
2617     SetGC(f, GC_SHADOWBOT);
2618   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2619 	       CoordModeOrigin);
2620   points[3].x = points[0].x;
2621   points[3].y = points[0].y;
2622   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2623   SetGC(f, GC_UNSET);
2624   if (w == f->folder.activeW)
2625     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2626   else
2627     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2628   points[0].x -= st;
2629   points[1].y += st;
2630   if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2631     points[1].y -= st * 2;
2632   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2633 	       CoordModeOrigin);
2634   points[3].x = points[0].x;
2635   points[3].y = points[0].y;
2636   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2637 }
2638 
2639 static void
DrawTabShadowLineLeftRight(XmLFolderWidget f,Widget w)2640 DrawTabShadowLineLeftRight(XmLFolderWidget f,
2641 			   Widget w)
2642 {
2643   XmLFolderConstraintRec *fc;
2644   Display *dpy;
2645   Window win;
2646   XSegment *topSeg, *botSeg;
2647   XPoint points[4];
2648   int tCount, bCount, rightOff, i, st, cd, x;
2649 
2650   dpy = XtDisplay(f);
2651   win = XtWindow(f);
2652   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2653   rightOff = 2 * fc->folder.x + fc->folder.width - 1;
2654   st = f->manager.shadow_thickness;
2655   if (!st)
2656     return;
2657   cd = f->folder.cornerDimension;
2658 
2659   tCount = 0;
2660   bCount = 0;
2661   topSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2662   botSeg = (XSegment *)malloc(sizeof(XSegment) * st);
2663   for (i = 0; i < st; i++)
2664     {
2665       /* top tab shadow */
2666       topSeg[tCount].x1 = fc->folder.x + cd + st;
2667       topSeg[tCount].y1 = fc->folder.y + i;
2668       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1;
2669       if (w == f->folder.activeW)
2670 	topSeg[tCount].x2 += i;
2671       topSeg[tCount].y2 = fc->folder.y + i;
2672       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2673 	{
2674 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2675 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2676 	}
2677       tCount++;
2678       /* bottom tab shadow */
2679       botSeg[bCount].x1 = fc->folder.x + cd + st;
2680       botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1;
2681       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1;
2682       if (w == f->folder.activeW)
2683 	botSeg[bCount].x2 += i;
2684       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1;
2685       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2686 	{
2687 	  botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2688 	  botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2689 	}
2690       bCount++;
2691     }
2692   if (tCount)
2693     {
2694       SetGC(f, GC_SHADOWTOP);
2695       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2696       SetGC(f, GC_UNSET);
2697     }
2698   if (bCount)
2699     {
2700       SetGC(f, GC_SHADOWBOT);
2701       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2702       SetGC(f, GC_UNSET);
2703     }
2704   tCount = 0;
2705   for (i = 0; i < st; i++)
2706     {
2707       /* left tab shadow */
2708       topSeg[tCount].x1 = fc->folder.x + i;
2709       topSeg[tCount].y1 = fc->folder.y + cd + st;
2710       topSeg[tCount].x2 = fc->folder.x + i;
2711       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - cd - st - 1;
2712       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2713 	{
2714 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2715 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2716 	}
2717       tCount++;
2718     }
2719   if (tCount)
2720     {
2721       if (f->folder.tabPlacement == XmFOLDER_LEFT)
2722 	SetGC(f, GC_SHADOWTOP);
2723       else
2724 	SetGC(f, GC_SHADOWBOT);
2725       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2726       SetGC(f, GC_UNSET);
2727     }
2728   free((char *)topSeg);
2729   free((char *)botSeg);
2730 
2731   /* top line */
2732   points[0].x = fc->folder.x + cd + st - 1;
2733   points[0].y = fc->folder.y;
2734   points[1].x = fc->folder.x;
2735   points[1].y = fc->folder.y + cd + st - 1;
2736   points[2].x = fc->folder.x + cd + st - 1;
2737   points[2].y = fc->folder.y + cd + st - 1;
2738   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2739     {
2740       points[0].x = rightOff - points[0].x;
2741       points[1].x = rightOff - points[1].x;
2742       points[2].x = rightOff - points[2].x;
2743     }
2744   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2745     x = fc->folder.x + fc->folder.width - cd - st;
2746   else
2747     x = fc->folder.x;
2748   SetGC(f, GC_BLANK);
2749   XFillRectangle(dpy, win, f->folder.gc, x, fc->folder.y, cd + st, cd + st);
2750   SetGC(f, GC_UNSET);
2751   SetGC(f, GC_SHADOWTOP);
2752   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2753 	       CoordModeOrigin);
2754   points[3].x = points[0].x;
2755   points[3].y = points[0].y;
2756   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2757   SetGC(f, GC_UNSET);
2758   if (w == f->folder.activeW)
2759     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2760   else
2761     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2762   points[0].y += st;
2763   points[1].x += st;
2764   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2765     points[1].x -= st * 2;
2766   XFillPolygon(dpy, win, f->folder.gc, points, 3,
2767 	       Nonconvex, CoordModeOrigin);
2768   points[3].x = points[0].x;
2769   points[3].y = points[0].y;
2770   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2771 
2772   /* bottom line */
2773   points[0].x = fc->folder.x + cd + st - 1;
2774   points[0].y = fc->folder.y + fc->folder.height - 1;
2775   points[1].x = fc->folder.x;
2776   points[1].y = fc->folder.y + fc->folder.height - cd - st;
2777   points[2].x = fc->folder.x + cd + st - 1;
2778   points[2].y = fc->folder.y + fc->folder.height - cd - st;
2779   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2780     {
2781       points[0].x = rightOff - points[0].x;
2782       points[1].x = rightOff - points[1].x;
2783       points[2].x = rightOff - points[2].x;
2784     }
2785   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2786     x = fc->folder.x + fc->folder.width - cd - st;
2787   else
2788     x = fc->folder.x;
2789   SetGC(f, GC_BLANK);
2790   XFillRectangle(dpy, win, f->folder.gc, x, fc->folder.y +
2791 		 fc->folder.height - cd - st, cd + st, cd + st);
2792   SetGC(f, GC_UNSET);
2793   SetGC(f, GC_SHADOWBOT);
2794   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2795 	       CoordModeOrigin);
2796   points[3].x = points[0].x;
2797   points[3].y = points[0].y;
2798   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2799   SetGC(f, GC_UNSET);
2800   if (w == f->folder.activeW)
2801     XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
2802   else
2803     XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
2804   points[0].y -= st;
2805   points[1].x += st;
2806   if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2807     points[1].x -= st * 2;
2808   XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex,
2809 	       CoordModeOrigin);
2810   points[3].x = points[0].x;
2811   points[3].y = points[0].y;
2812   XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin);
2813 }
2814 
2815 static void
DrawTabShadowNoneTopBottom(XmLFolderWidget f,Widget w)2816 DrawTabShadowNoneTopBottom(XmLFolderWidget f,
2817 			   Widget w)
2818 {
2819   XmLFolderConstraintRec *fc;
2820   Display *dpy;
2821   Window win;
2822   XSegment *topSeg, *botSeg;
2823   int i, st, botOff, tCount, bCount;
2824 
2825   dpy = XtDisplay(f);
2826   win = XtWindow(f);
2827   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2828   botOff = 2 * fc->folder.y + fc->folder.height - 1;
2829   st = f->manager.shadow_thickness;
2830   if (!st)
2831     return;
2832 
2833   tCount = 0;
2834   bCount = 0;
2835   topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
2836   botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
2837   for (i = 0; i < st; i++)
2838     {
2839       /* left tab shadow */
2840       topSeg[tCount].x1 = fc->folder.x + i;
2841       topSeg[tCount].y1 = fc->folder.y + i;
2842       topSeg[tCount].x2 = fc->folder.x + i;
2843       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1;
2844       if (w == f->folder.activeW)
2845 	topSeg[tCount].y2 += i;
2846       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2847 	{
2848 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2849 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2850 	}
2851       tCount++;
2852 
2853       /* right tab shadow */
2854       botSeg[bCount].x1 = fc->folder.x + fc->folder.width - 1 - i;
2855       botSeg[bCount].y1 = fc->folder.y + i;
2856       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1 - i;
2857       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1;
2858       if (w == f->folder.activeW)
2859 	botSeg[bCount].y2 += i;
2860       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2861 	{
2862 	  botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2863 	  botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2864 	}
2865       bCount++;
2866     }
2867   if (tCount)
2868     {
2869       SetGC(f, GC_SHADOWTOP);
2870       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2871       SetGC(f, GC_UNSET);
2872     }
2873   if (bCount)
2874     {
2875       SetGC(f, GC_SHADOWBOT);
2876       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2877       SetGC(f, GC_UNSET);
2878     }
2879 
2880   tCount = 0;
2881   for (i = 0; i < st; i++)
2882     {
2883       /* top tab shadow */
2884       topSeg[tCount].x1 = fc->folder.x + i + 1;
2885       topSeg[tCount].y1 = fc->folder.y + i;
2886       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - i - 1;
2887       topSeg[tCount].y2 = fc->folder.y + i;
2888       if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
2889 	{
2890 	  topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2891 	  topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2892 	}
2893       tCount++;
2894     }
2895   if (tCount)
2896     {
2897       if (f->folder.tabPlacement == XmFOLDER_TOP)
2898 	SetGC(f, GC_SHADOWTOP);
2899       else
2900 	SetGC(f, GC_SHADOWBOT);
2901       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2902       SetGC(f, GC_UNSET);
2903     }
2904   free((char *)topSeg);
2905   free((char *)botSeg);
2906 }
2907 
2908 static void
DrawTabShadowNoneLeftRight(XmLFolderWidget f,Widget w)2909 DrawTabShadowNoneLeftRight(XmLFolderWidget f,
2910 			   Widget w)
2911 {
2912   XmLFolderConstraintRec *fc;
2913   Display *dpy;
2914   Window win;
2915   XSegment *topSeg, *botSeg;
2916   int i, st, rightOff, tCount, bCount;
2917 
2918   dpy = XtDisplay(f);
2919   win = XtWindow(f);
2920   fc = (XmLFolderConstraintRec *)(w->core.constraints);
2921   rightOff = 2 * fc->folder.x + fc->folder.width - 1;
2922   st = f->manager.shadow_thickness;
2923   if (!st)
2924     return;
2925 
2926   tCount = 0;
2927   bCount = 0;
2928   topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
2929   botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
2930   for (i = 0; i < st; i++)
2931     {
2932       /* bottom tab shadow */
2933       topSeg[tCount].x1 = fc->folder.x + i;
2934       topSeg[tCount].y1 = fc->folder.y + i;
2935       topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1;
2936       if (w == f->folder.activeW)
2937 	topSeg[tCount].x2 += i;
2938       topSeg[tCount].y2 = fc->folder.y + i;
2939       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2940 	{
2941 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2942 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2943 	}
2944       tCount++;
2945 
2946       /* top tab shadow */
2947       botSeg[bCount].x1 = fc->folder.x + i;
2948       botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1;
2949       botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1;
2950       if (w == f->folder.activeW)
2951 	botSeg[bCount].x2 += i;
2952       botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1;
2953       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2954 	{
2955 	  botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2956 	  botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2957 	}
2958       bCount++;
2959     }
2960   if (tCount)
2961     {
2962       SetGC(f, GC_SHADOWTOP);
2963       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2964       SetGC(f, GC_UNSET);
2965     }
2966   if (bCount)
2967     {
2968       SetGC(f, GC_SHADOWBOT);
2969       XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2970       SetGC(f, GC_UNSET);
2971     }
2972 
2973   tCount = 0;
2974   for (i = 0; i < st; i++)
2975     {
2976       /* left tab shadow */
2977       topSeg[tCount].x1 = fc->folder.x + i;
2978       topSeg[tCount].y1 = fc->folder.y + i + 1;
2979       topSeg[tCount].x2 = fc->folder.x + i;
2980       topSeg[tCount].y2 = fc->folder.y + fc->folder.height - i - 1;
2981       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2982 	{
2983 	  topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2984 	  topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2985 	}
2986       tCount++;
2987     }
2988   if (tCount)
2989     {
2990       if (f->folder.tabPlacement == XmFOLDER_RIGHT)
2991 	SetGC(f, GC_SHADOWBOT);
2992       else
2993 	SetGC(f, GC_SHADOWTOP);
2994       XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2995       SetGC(f, GC_UNSET);
2996     }
2997   free((char *)topSeg);
2998   free((char *)botSeg);
2999 }
3000 
3001 static void
SetGC(XmLFolderWidget f,int type)3002 SetGC(XmLFolderWidget f,
3003       int type)
3004 {
3005   Display *dpy;
3006   XGCValues values;
3007   XtGCMask mask;
3008 
3009   dpy = XtDisplay(f);
3010   if (type == GC_SHADOWBOT)
3011     {
3012       mask = GCForeground;
3013       values.foreground = f->manager.bottom_shadow_color;
3014       if (f->manager.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
3015 	{
3016 	  mask |= GCFillStyle | GCTile;
3017 	  values.fill_style = FillTiled;
3018 	  values.tile = f->manager.bottom_shadow_pixmap;
3019 	}
3020       XChangeGC(dpy, f->folder.gc, mask, &values);
3021     }
3022   else if (type == GC_SHADOWTOP)
3023     {
3024       mask = GCForeground;
3025       values.foreground = f->manager.top_shadow_color;
3026       if (f->manager.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
3027 	{
3028 	  mask |= GCFillStyle | GCTile;
3029 	  values.fill_style = FillTiled;
3030 	  values.tile = f->manager.top_shadow_pixmap;
3031 	}
3032       XChangeGC(dpy, f->folder.gc, mask, &values);
3033     }
3034   else if (type == GC_BLANK)
3035     {
3036       mask = GCForeground;
3037       values.foreground = f->folder.blankBg;
3038       if (f->folder.blankPix != XmUNSPECIFIED_PIXMAP)
3039 	{
3040 	  mask |= GCFillStyle | GCTile;
3041 	  values.fill_style = FillTiled;
3042 	  values.tile = f->folder.blankPix;
3043 	}
3044       XChangeGC(dpy, f->folder.gc, mask, &values);
3045     }
3046   else
3047     {
3048       mask = GCFillStyle;
3049       values.fill_style = FillSolid;
3050       XChangeGC(dpy, f->folder.gc, mask, &values);
3051     }
3052 }
3053 
3054 static void
DrawTabHighlight(XmLFolderWidget f,Widget w)3055 DrawTabHighlight(XmLFolderWidget f,
3056 		 Widget w)
3057 {
3058   XmLFolderConstraintRec *fc;
3059   Display *dpy;
3060   Window win;
3061   int ht;
3062 
3063   if (!XtIsRealized(w))
3064     return;
3065   if (!f->core.visible)
3066     return;
3067   dpy = XtDisplay(f);
3068   win = XtWindow(f);
3069   fc = (XmLFolderConstraintRec *)(w->core.constraints);
3070   ht = f->folder.highlightThickness;
3071   if (f->folder.focusW == w)
3072     XSetForeground(dpy, f->folder.gc, f->manager.highlight_color);
3073   else
3074     {
3075       if (f->folder.activeW == w)
3076 	XSetForeground(dpy, f->folder.gc, f->core.background_pixel);
3077       else
3078 	XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg);
3079     }
3080   XFillRectangle(dpy, win, f->folder.gc,
3081 		 w->core.x - ht, w->core.y - ht,
3082 		 XtWidth(w) + w->core.border_width * 2 + ht * 2,
3083 		 XtHeight(w) + w->core.border_width * 2 + ht * 2);
3084 }
3085 
3086 static void
SetTabPlacement(XmLFolderWidget f,Widget tab)3087 SetTabPlacement(XmLFolderWidget f,
3088 		Widget tab)
3089 {
3090   if (!XmIsDrawnButton(tab))
3091     return;
3092   if (f->folder.allowRotate == True &&
3093       f->folder.tabPlacement == XmFOLDER_LEFT)
3094     XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_UP);
3095   else if (f->folder.allowRotate == True &&
3096 	   f->folder.tabPlacement == XmFOLDER_RIGHT)
3097     XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_DOWN);
3098   else
3099     XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_RIGHT);
3100   if (XtIsRealized(tab))
3101     XClearArea(XtDisplay(tab), XtWindow(tab), 0, 0, 0, 0, True);
3102 }
3103 
3104 static void
GetTabRect(XmLFolderWidget f,Widget tab,XRectangle * rect,int includeShadow)3105 GetTabRect(XmLFolderWidget f,
3106 	   Widget tab,
3107 	   XRectangle *rect,
3108 	   int includeShadow)
3109 {
3110   XmLFolderConstraintRec *fc;
3111   int st;
3112 
3113   st = f->manager.shadow_thickness;
3114   fc = (XmLFolderConstraintRec *)(tab->core.constraints);
3115   rect->x = fc->folder.x;
3116   rect->y = fc->folder.y;
3117   rect->width = fc->folder.width;
3118   rect->height = fc->folder.height;
3119   if (includeShadow)
3120     {
3121       if (f->folder.tabPlacement == XmFOLDER_TOP)
3122 	rect->height += st;
3123       else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
3124 	{
3125 	  rect->y -= st;
3126 	  rect->height += st;
3127 	}
3128       else if (f->folder.tabPlacement == XmFOLDER_LEFT)
3129 	rect->width += st;
3130       else
3131 	{
3132 	  rect->x -= st;
3133 	  rect->width += st;
3134 	}
3135     }
3136 }
3137 
3138 static void
SetActiveTab(XmLFolderWidget f,Widget w,XEvent * event,Boolean notify)3139 SetActiveTab(XmLFolderWidget f,
3140 	     Widget w,
3141 	     XEvent *event,
3142 	     Boolean notify)
3143 {
3144   XmLFolderCallbackStruct cbs;
3145   XmLFolderConstraintRec *fc, *cfc;
3146   int i, j, pos;
3147   Display *dpy;
3148   Window win;
3149   Widget activeW, child, mw, managedW;
3150   WidgetList children;
3151   XRectangle rect;
3152   char *name, buf[256];
3153 
3154   win = (Window)NULL;
3155 
3156   if (f->folder.activeW == w)
3157     return;
3158   dpy = 0;
3159   if (XtIsRealized((Widget)f) && f->core.visible)
3160     {
3161       dpy = XtDisplay(f);
3162       win = XtWindow(f);
3163     }
3164 
3165   pos = -1;
3166   for (i = 0; i < f->folder.tabCount; i++)
3167     if (w == f->folder.tabs[i])
3168       pos = i;
3169 
3170   cbs.allowActivate = 1;
3171   cbs.layoutNeeded = 0;
3172   if (notify == True)
3173     {
3174       if (f->folder.debugLevel)
3175 	fprintf(stderr, "XmLFolder: activated %d\n", pos);
3176       cbs.reason = XmCR_ACTIVATE;
3177       cbs.event = event;
3178       cbs.pos = pos;
3179       XtCallCallbackList((Widget)f, f->folder.activateCallback, &cbs);
3180     }
3181   if (!cbs.allowActivate)
3182     return;
3183 
3184   /* redraw current active tab */
3185   activeW = f->folder.activeW;
3186   if (activeW && dpy)
3187     {
3188       GetTabRect(f, activeW, &rect, 1);
3189       XClearArea(dpy, win, rect.x, rect.y, rect.width,
3190 		 rect.height, True);
3191     }
3192 
3193   f->folder.activeTab = pos;
3194   f->folder.activeW = w;
3195   if (!w)
3196     return;
3197 
3198   /* Not sure this needs to be in the 3.0 (Microline) stuff */
3199   PrimFocusIn(w, NULL, NULL, NULL);
3200 
3201   /* if we selected a tab not in active row - move row into place */
3202   if (f->folder.tabsPerRow)
3203     {
3204       fc = (XmLFolderConstraintRec *)(w->core.constraints);
3205       if (fc->folder.row != f->folder.activeRow)
3206 	Layout(f, False);
3207     }
3208 
3209   /* manage this tabs managed widget if it exists */
3210   children = f->composite.children;
3211   f->folder.allowLayout = 0;
3212   for (i = 0; i < f->composite.num_children; i++)
3213     {
3214       child = children[i];
3215       if (!XtIsSubclass(child, xmPrimitiveWidgetClass))
3216 	continue;
3217       fc = (XmLFolderConstraintRec *)(child->core.constraints);
3218       managedW = 0;
3219       if (fc->folder.managedName)
3220 	{
3221 	  for (j = 0; j < f->composite.num_children; j++)
3222 	    {
3223 	      mw = children[j];
3224 	      if (XtIsSubclass(mw, xmPrimitiveWidgetClass))
3225 		continue;
3226 	      name = XtName(mw);
3227 	      if (name && !strcmp(name, fc->folder.managedName))
3228 		managedW = mw;
3229 	      cfc = (XmLFolderConstraintRec *)(mw->core.constraints);
3230 	      name = cfc->folder.managedName;
3231 	      if (name && !strcmp(name, fc->folder.managedName))
3232 		managedW = mw;
3233 	    }
3234 	  if (!managedW)
3235 	    {
3236 	      sprintf(buf, "SetActiveTab() - managed widget named ");
3237 	      strcat(buf, fc->folder.managedName);
3238 	      strcat(buf, " not found");
3239 	      XmLWarning(child, buf);
3240 	    }
3241 	}
3242       else
3243 	managedW = fc->folder.managedW;
3244       if (managedW)
3245 	{
3246 	  if (w == child && !XtIsManaged(managedW))
3247 	    XtManageChild(managedW);
3248 	  if (w != child && XtIsManaged(managedW))
3249 	    XtUnmanageChild(managedW);
3250 	}
3251     }
3252   f->folder.allowLayout = 1;
3253 
3254   /* redraw new active tab */
3255   if (dpy)
3256     {
3257       GetTabRect(f, w, &rect, 1);
3258       XClearArea(dpy, win, rect.x, rect.y, rect.width, rect.height, True);
3259       XmProcessTraversal(w, XmTRAVERSE_CURRENT);
3260     }
3261 
3262   if (cbs.layoutNeeded)
3263 	Layout(f, 0);
3264 }
3265 
3266 /*
3267    Utility
3268 */
3269 
3270 static void
GetCoreBackground(Widget w,int offset,XrmValue * value)3271 GetCoreBackground(Widget w,
3272 		  int offset,
3273 		  XrmValue *value)
3274 {
3275   value->addr = (caddr_t)&w->core.background_pixel;
3276 }
3277 
3278 static void
GetDefaultTabWidgetClass(Widget w,int offset,XrmValue * value)3279 GetDefaultTabWidgetClass(Widget w,
3280 		  int offset,
3281 		  XrmValue *value)
3282 {
3283   value->addr = (caddr_t)&xmDrawnButtonWidgetClass;
3284 }
3285 
3286 static void
GetManagerForeground(Widget w,int offset,XrmValue * value)3287 GetManagerForeground(Widget w,
3288 		     int offset,
3289 		     XrmValue *value)
3290 {
3291   XmLFolderWidget f;
3292 
3293   f = (XmLFolderWidget)w;
3294   value->addr = (caddr_t)&f->manager.foreground;
3295 }
3296 
3297 static Boolean
ServerDrawsArcsLarge(Display * dpy,int debug)3298 ServerDrawsArcsLarge(Display *dpy,
3299 		     int debug)
3300 {
3301   Pixmap pixmap;
3302   XImage *image;
3303   Window root;
3304   long pixel;
3305   int x, y, width, height, result;
3306   GC gc;
3307 
3308   root = DefaultRootWindow(dpy);
3309   width = 5;
3310   height = 5;
3311   pixmap = XCreatePixmap(dpy, root, width, height, 1);
3312   gc = XCreateGC(dpy, pixmap, 0L, NULL);
3313   XSetForeground(dpy, gc, 0L);
3314   XFillRectangle(dpy, pixmap, gc, 0, 0, width, height);
3315   XSetForeground(dpy, gc, 1L);
3316   XDrawArc(dpy, pixmap, gc, 0, 0, width, height, 0, 360 * 64);
3317   image = XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
3318   if (debug)
3319     {
3320       fprintf(stderr, "Test X server drawn arc (%d by %d):\n",
3321 	      width, height);
3322       for (y = 0; y < height; y++)
3323 	{
3324 	  fprintf(stderr, " ");
3325 	  for (x = 0; x < width; x++)
3326 	    {
3327 	      pixel = XGetPixel(image, x, y);
3328 	      if (pixel == 0L)
3329 		fprintf(stderr, ".");
3330 	      else
3331 		fprintf(stderr, "X");
3332 	    }
3333 	  fprintf(stderr, "\n");
3334 	}
3335     }
3336   if (XGetPixel(image, width - 1, height / 2) != 1L)
3337     {
3338       result = 1;
3339       if (debug)
3340 	fprintf(stderr, "X Server Draws Arcs 1 Pixel Large\n");
3341     }
3342   else
3343     {
3344       result = 0;
3345       if (debug)
3346 	fprintf(stderr, "X Server Draws Arcs Within Bounds\n");
3347     }
3348   XDestroyImage(image);
3349   XFreeGC(dpy, gc);
3350   XFreePixmap(dpy, pixmap);
3351   return result;
3352 }
3353 
3354 /*
3355    Getting and Setting Values
3356 */
3357 
3358 static Boolean
SetValues(Widget curW,Widget reqW,Widget newW,ArgList args,Cardinal * narg)3359 SetValues(Widget curW,
3360 	  Widget reqW,
3361 	  Widget newW,
3362 	  ArgList args,
3363 	  Cardinal *narg)
3364 {
3365   XmLFolderWidget f;
3366   XmLFolderWidget cur;
3367   int i;
3368   Boolean needsLayout, needsRedisplay;
3369 
3370   f = (XmLFolderWidget)newW;
3371   cur = (XmLFolderWidget)curW;
3372   needsLayout = False;
3373   needsRedisplay = False;
3374 #define NE(value) (f->value != cur->value)
3375   if (NE(folder.tabBarHeight))
3376     {
3377       XmLWarning((Widget)f, "SetValues() - can't set tabBarHeight");
3378       f->folder.tabBarHeight = cur->folder.tabBarHeight;
3379     }
3380   if (NE(folder.tabCount))
3381     {
3382       XmLWarning((Widget)f, "SetValues() - can't set tabCount");
3383       f->folder.tabCount = cur->folder.tabCount;
3384     }
3385   if (NE(folder.activeTab))
3386     {
3387       XmLWarning((Widget)f, "SetValues() - can't set activeTab");
3388       f->folder.activeTab = cur->folder.activeTab;
3389     }
3390   if (f->folder.cornerDimension < 1)
3391     {
3392       XmLWarning((Widget)f, "SetValues() - cornerDimension can't be < 1");
3393       f->folder.cornerDimension = cur->folder.cornerDimension;
3394     }
3395   if (NE(folder.tabPlacement) ||
3396       NE(folder.allowRotate))
3397     {
3398       f->folder.allowLayout = 0;
3399       for (i = 0; i < f->folder.tabCount; i++)
3400 	SetTabPlacement(f, f->folder.tabs[i]);
3401       f->folder.allowLayout = 1;
3402       needsLayout = True;
3403     }
3404   if (NE(folder.inactiveBg) ||
3405       NE(folder.blankBg) ||
3406       NE(folder.blankPix) ||
3407       NE(folder.inactiveFg))
3408     needsRedisplay = True;
3409   if (NE(folder.cornerDimension) ||
3410       NE(folder.cornerStyle) ||
3411       NE(folder.highlightThickness) ||
3412       NE(folder.marginHeight) ||
3413       NE(folder.marginWidth) ||
3414       NE(folder.pixmapMargin) ||
3415       NE(manager.shadow_thickness) ||
3416       NE(folder.tabsPerRow) ||
3417       NE(folder.spacing))
3418     needsLayout = True;
3419   if (NE(folder.fontList))
3420     {
3421       XmFontListFree(cur->folder.fontList);
3422       CopyFontList(f);
3423     }
3424 #undef NE
3425   if (needsLayout == True)
3426     Layout(f, 1);
3427   return needsRedisplay;
3428 }
3429 
3430 static void
CopyFontList(XmLFolderWidget f)3431 CopyFontList(XmLFolderWidget f)
3432 {
3433   if (!f->folder.fontList)
3434     f->folder.fontList = XmLFontListCopyDefault((Widget)f);
3435   else
3436     f->folder.fontList = XmFontListCopy(f->folder.fontList);
3437   if (!f->folder.fontList)
3438     XmLWarning((Widget)f, "- fatal error - font list NULL");
3439 }
3440 
3441 static Boolean
ConstraintSetValues(Widget curW,Widget reqW,Widget newW,ArgList args,Cardinal * narg)3442 ConstraintSetValues(Widget curW,
3443 		    Widget reqW,
3444 		    Widget newW,
3445 		    ArgList args,
3446 		    Cardinal *narg)
3447 {
3448   XmLFolderConstraintRec *cons, *curCons;
3449   XmLFolderWidget f;
3450   int i, hasLabelChange;
3451 
3452   f = (XmLFolderWidget)XtParent(newW);
3453   if (!XtIsRectObj(newW))
3454     return False;
3455   cons = (XmLFolderConstraintRec *)newW->core.constraints;
3456   curCons = (XmLFolderConstraintRec *)curW->core.constraints;
3457 #define NE(value) (cons->value != curCons->value)
3458   if (NE(folder.managedName))
3459     {
3460       if (curCons->folder.managedName)
3461 	free((char *)curCons->folder.managedName);
3462       if (cons->folder.managedName)
3463 	cons->folder.managedName = (char *)strdup(cons->folder.managedName);
3464     }
3465 #undef NE
3466   hasLabelChange = 0;
3467   if (XtIsSubclass(newW, xmPrimitiveWidgetClass))
3468     {
3469       for (i = 0; i < *narg; i++)
3470 	if (args[i].name && !strcmp(args[i].name, XmNlabelString))
3471 	  hasLabelChange = 1;
3472       if (hasLabelChange &&
3473 	  (f->folder.tabPlacement == XmFOLDER_LEFT ||
3474 	   f->folder.tabPlacement == XmFOLDER_RIGHT))
3475 	{
3476 	  f->folder.allowLayout = 0;
3477 	  for (i = 0; i < f->folder.tabCount; i++)
3478 	    SetTabPlacement(f, f->folder.tabs[i]);
3479 	  f->folder.allowLayout = 1;
3480 	}
3481     }
3482   if (hasLabelChange ||
3483       curCons->folder.pix != cons->folder.pix ||
3484       curCons->folder.inactPix != cons->folder.inactPix)
3485     Layout((XmLFolderWidget)XtParent(curW), 1);
3486   return False;
3487 }
3488 
3489 static Boolean
CvtStringToCornerStyle(Display * dpy,XrmValuePtr args,Cardinal * narg,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * data)3490 CvtStringToCornerStyle(Display *dpy,
3491 		       XrmValuePtr args,
3492 		       Cardinal *narg,
3493 		       XrmValuePtr fromVal,
3494 		       XrmValuePtr toVal,
3495 		       XtPointer *data)
3496 {
3497   static XmLStringToUCharMap map[] =
3498   {
3499     { "CORNER_NONE", XmCORNER_NONE },
3500     { "CORNER_LINE", XmCORNER_LINE },
3501     { "CORNER_ARC", XmCORNER_ARC },
3502     { 0, 0 },
3503   };
3504 
3505   return XmLCvtStringToUChar(dpy, "XmRCornerStyle", map, fromVal, toVal);
3506 }
3507 
3508 static Boolean
CvtStringToFolderResizePolicy(Display * dpy,XrmValuePtr args,Cardinal * narg,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * data)3509 CvtStringToFolderResizePolicy(Display *dpy,
3510 			      XrmValuePtr args,
3511 			      Cardinal *narg,
3512 			      XrmValuePtr fromVal,
3513 			      XrmValuePtr toVal,
3514 			      XtPointer *data)
3515 {
3516   static XmLStringToUCharMap map[] =
3517   {
3518     { "RESIZE_NONE", XmRESIZE_NONE },
3519     { "RESIZE_STATIC", XmRESIZE_STATIC },
3520     { "RESIZE_DYNAMIC", XmRESIZE_DYNAMIC },
3521     { "RESIZE_PACK", XmRESIZE_PACK },
3522     { 0, 0 },
3523   };
3524 
3525   return XmLCvtStringToUChar(dpy, "XmRFolderResizePolicy", map,
3526 			     fromVal, toVal);
3527 }
3528 
3529 static Boolean
CvtStringToTabPlacement(Display * dpy,XrmValuePtr args,Cardinal * narg,XrmValuePtr fromVal,XrmValuePtr toVal,XtPointer * data)3530 CvtStringToTabPlacement(Display *dpy,
3531 			XrmValuePtr args,
3532 			Cardinal *narg,
3533 			XrmValuePtr fromVal,
3534 			XrmValuePtr toVal,
3535 			XtPointer *data)
3536 {
3537   static XmLStringToUCharMap map[] =
3538   {
3539     { "FOLDER_TOP", XmFOLDER_TOP },
3540     { "FOLDER_LEFT", XmFOLDER_LEFT },
3541     { "FOLDER_BOTTOM", XmFOLDER_BOTTOM },
3542     { "FOLDER_RIGHT", XmFOLDER_RIGHT },
3543     { 0, 0 },
3544   };
3545 
3546   return XmLCvtStringToUChar(dpy, "XmRTabPlacement", map, fromVal, toVal);
3547 }
3548 
3549 /*
3550    Actions, Callbacks and Handlers
3551 */
3552 
3553 static void
Activate(Widget w,XEvent * event,String * params,Cardinal * nparam)3554 Activate(Widget w,
3555 	 XEvent *event,
3556 	 String *params,
3557 	 Cardinal *nparam)
3558 {
3559   XmLFolderWidget f;
3560   XButtonEvent *be;
3561   XRectangle rect;
3562   Widget tab;
3563   int i;
3564 
3565   f = (XmLFolderWidget)w;
3566   if (!event || event->type != ButtonPress)
3567     return;
3568   be = (XButtonEvent *)event;
3569   if (f->folder.debugLevel)
3570     fprintf(stderr, "XmLFolder: ButtonPress %d %d\n", be->x, be->y);
3571   for (i = 0; i < f->folder.tabCount; i++)
3572     {
3573       tab = f->folder.tabs[i];
3574       if (!XtIsManaged(tab) || !XtIsSensitive(tab))
3575 	continue;
3576       GetTabRect(f, tab, &rect, 0);
3577       if (be->x > rect.x && be->x < rect.x + (int)rect.width &&
3578 	  be->y > rect.y && be->y < rect.y + (int)rect.height)
3579 	{
3580 	  if (f->folder.debugLevel)
3581 	    fprintf(stderr, "XmLFolder: Pressed tab %d\n", i);
3582 	  SetActiveTab(f, tab, event, True);
3583 	  return;
3584 	}
3585     }
3586 }
3587 
3588 static void
PrimActivate(Widget w,XtPointer clientData,XtPointer callData)3589 PrimActivate(Widget w,
3590 	     XtPointer clientData,
3591 	     XtPointer callData)
3592 {
3593   XmLFolderWidget f;
3594   XmAnyCallbackStruct *cbs;
3595 
3596   f = (XmLFolderWidget)XtParent(w);
3597   cbs = (XmAnyCallbackStruct *)callData;
3598   SetActiveTab(f, w, cbs->event, True);
3599 }
3600 
3601 static void
PrimFocusIn(Widget w,XEvent * event,String * params,Cardinal * nparam)3602 PrimFocusIn(Widget w,
3603 	    XEvent *event,
3604 	    String *params,
3605 	    Cardinal *nparam)
3606 {
3607   XmLFolderWidget f;
3608   Widget prevW;
3609 
3610   f = (XmLFolderWidget)XtParent(w);
3611   prevW = f->folder.focusW;
3612   f->folder.focusW = w;
3613   DrawTabHighlight(f, w);
3614   if (prevW)
3615     DrawTabHighlight(f, prevW);
3616   XmProcessTraversal(w, XmTRAVERSE_CURRENT);
3617 }
3618 
3619 static void
PrimFocusOut(Widget w,XEvent * event,String * params,Cardinal * nparam)3620 PrimFocusOut(Widget w,
3621 	     XEvent *event,
3622 	     String *params,
3623 	     Cardinal *nparam)
3624 {
3625   XmLFolderWidget f;
3626   Widget prevW;
3627 
3628   f = (XmLFolderWidget)XtParent(w);
3629   prevW = f->folder.focusW;
3630   f->folder.focusW = 0;
3631   if (prevW)
3632     DrawTabHighlight(f, prevW);
3633   DrawTabHighlight(f, w);
3634 }
3635 
3636 /*
3637    Public Functions
3638 */
3639 
3640 Widget
XmLCreateFolder(Widget parent,char * name,ArgList arglist,Cardinal argcount)3641 XmLCreateFolder(Widget parent,
3642 		char *name,
3643 		ArgList arglist,
3644 		Cardinal argcount)
3645 {
3646   return XtCreateWidget(name, xmlFolderWidgetClass, parent,
3647 			arglist, argcount);
3648 }
3649 
3650 Widget
XmLFolderAddBitmapTab(Widget w,XmString string,char * bitmapBits,int bitmapWidth,int bitmapHeight)3651 XmLFolderAddBitmapTab(Widget w,
3652 		      XmString string,
3653 		      char *bitmapBits,
3654 		      int bitmapWidth,
3655 		      int bitmapHeight)
3656 {
3657   XmLFolderWidget f;
3658   Widget tab;
3659   Pixmap pix, inactPix;
3660   Window root;
3661   Display *dpy;
3662   int depth;
3663   char name[20];
3664 
3665   if (!XmLIsFolder(w))
3666     {
3667       XmLWarning(w, "AddBitmapTab() - widget not a XmLFolder");
3668       return 0;
3669     }
3670   f = (XmLFolderWidget)w;
3671   dpy = XtDisplay(w);
3672   root = DefaultRootWindow(dpy);
3673   depth = DefaultDepthOfScreen(XtScreen(w));
3674   pix = XCreatePixmapFromBitmapData(dpy, root, bitmapBits,
3675 				    bitmapWidth, bitmapHeight, f->manager.foreground,
3676 				    f->core.background_pixel, depth);
3677   inactPix = XCreatePixmapFromBitmapData(dpy, root, bitmapBits,
3678 					 bitmapWidth, bitmapHeight, f->folder.inactiveFg,
3679 					 f->folder.inactiveBg, depth);
3680   sprintf(name, "tab%d", f->folder.tabCount);
3681   tab = XtVaCreateManagedWidget(name,
3682 				f->folder.tabWidgetClass, w,
3683 				XmNfontList, f->folder.fontList,
3684 				XmNmarginWidth, 0,
3685 				XmNmarginHeight, 0,
3686 				XmNlabelString, string,
3687 				XmNtabPixmap, pix,
3688 				XmNtabInactivePixmap, inactPix,
3689 				XmNtabFreePixmaps, True,
3690 				NULL);
3691   return tab;
3692 }
3693 
3694 Widget
XmLFolderAddBitmapTabForm(Widget w,XmString string,char * bitmapBits,int bitmapWidth,int bitmapHeight)3695 XmLFolderAddBitmapTabForm(Widget w,
3696 			  XmString string,
3697 			  char *bitmapBits,
3698 			  int bitmapWidth,
3699 			  int bitmapHeight)
3700 {
3701   Widget form, tab;
3702   XmLFolderWidget f;
3703   char name[20];
3704 
3705   if (!XmLIsFolder(w))
3706     {
3707       XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder");
3708       return 0;
3709     }
3710   f = (XmLFolderWidget)w;
3711   tab = XmLFolderAddBitmapTab(w, string, bitmapBits,
3712 			      bitmapWidth, bitmapHeight);
3713   sprintf(name, "form%d", f->folder.tabCount);
3714   form = XtVaCreateManagedWidget(name,
3715 				 xmFormWidgetClass, w,
3716 				 XmNbackground, f->core.background_pixel,
3717 				 NULL);
3718   XtVaSetValues(tab, XmNtabManagedWidget, form, NULL);
3719   return form;
3720 }
3721 
3722 Widget
XmLFolderAddTab(Widget w,XmString string)3723 XmLFolderAddTab(Widget w,
3724 		XmString string)
3725 {
3726   Widget tab;
3727   XmLFolderWidget f;
3728   char name[20];
3729 
3730   if (!XmLIsFolder(w))
3731     {
3732       XmLWarning(w, "AddTab() - widget not a XmLFolder");
3733       return 0;
3734     }
3735   f = (XmLFolderWidget)w;
3736   sprintf(name, "tab%d", f->folder.tabCount);
3737   tab = XtVaCreateManagedWidget(name,
3738 				f->folder.tabWidgetClass, w,
3739 				XmNfontList, f->folder.fontList,
3740 				XmNmarginWidth, 0,
3741 				XmNmarginHeight, 0,
3742 				XmNlabelString, string,
3743 				NULL);
3744   return tab;
3745 }
3746 
3747 Widget
XmLFolderAddTabFromClass(Widget w,XmString string)3748 XmLFolderAddTabFromClass(Widget w,
3749 		XmString string)
3750 {
3751   Widget tab;
3752   XmLFolderWidget f;
3753   char name[20];
3754 
3755   if (!XmLIsFolder(w))
3756     {
3757       XmLWarning(w, "AddTab() - widget not a XmLFolder");
3758       return 0;
3759     }
3760   f = (XmLFolderWidget)w;
3761   sprintf(name, "tab%d", f->folder.tabCount);
3762 
3763   tab = XtVaCreateManagedWidget(name,
3764 								f->folder.tabWidgetClass,
3765 /*  								xmDrawnButtonWidgetClass,  */
3766 								w,
3767 								XmNfontList, f->folder.fontList,
3768 /* 				XmNmarginWidth, 0, */
3769 /* 				XmNmarginHeight, 0, */
3770 								XmNlabelString, string,
3771 								NULL);
3772   return tab;
3773 }
3774 
3775 Widget
XmLFolderAddTabForm(Widget w,XmString string)3776 XmLFolderAddTabForm(Widget w,
3777 		    XmString string)
3778 {
3779   Widget form, tab;
3780   XmLFolderWidget f;
3781   char name[20];
3782 
3783   if (!XmLIsFolder(w))
3784     {
3785       XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder");
3786       return 0;
3787     }
3788   f = (XmLFolderWidget)w;
3789   tab = XmLFolderAddTab(w, string);
3790   sprintf(name, "form%d", f->folder.tabCount);
3791   form = XtVaCreateManagedWidget(name,
3792 				 xmFormWidgetClass, w,
3793 				 XmNbackground, f->core.background_pixel,
3794 				 NULL);
3795   XtVaSetValues(tab, XmNtabManagedWidget, form, NULL);
3796   return form;
3797 }
3798 
3799 void
XmLFolderSetActiveTab(Widget w,int position,Boolean notify)3800 XmLFolderSetActiveTab(Widget w,
3801 		      int position,
3802 		      Boolean notify)
3803 {
3804   XmLFolderWidget f;
3805 
3806   if (!XmLIsFolder(w))
3807     {
3808       XmLWarning(w, "SetActiveTab() - widget not a XmLFolder");
3809       return;
3810     }
3811   f = (XmLFolderWidget)w;
3812   if (position < 0 || position >= f->folder.tabCount)
3813     {
3814       XmLWarning(w, "SetActiveTab() - invalid position");
3815       return;
3816     }
3817   SetActiveTab(f, f->folder.tabs[position], 0, notify);
3818 }
3819