Don't use -import argument as fprintf format
[nedit.git] / Microline / XmL / Folder.c
blob270cf96bc4a593b33d4f9d2e66a937a98ec2f6e5
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>.
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.
23 * Contributor(s):
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.
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.
47 * ***** END LICENSE BLOCK ***** */
49 #include "FolderP.h"
50 #include <X11/StringDefs.h>
51 #include <Xm/DrawnB.h>
52 #include <Xm/Label.h>
53 #include <Xm/Form.h>
55 #include <stdio.h>
56 #include <stdlib.h>
58 #ifdef SUNOS4
59 int fprintf(FILE *, char *, ...);
60 #endif
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);
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);
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);
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);
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 *);
127 static XtActionsRec actions[] =
129 { "XmLFolderActivate", Activate },
130 { "XmLFolderPrimFocusIn", PrimFocusIn },
131 { "XmLFolderPrimFocusOut", PrimFocusOut },
134 #define MAX_TAB_ROWS 64
136 #define GC_SHADOWBOT 0
137 #define GC_SHADOWTOP 1
138 #define GC_BLANK 2
139 #define GC_UNSET 3
141 /* Folder Translations */
143 static char translations[] =
144 "<Btn1Down>: XmLFolderActivate()\n\
145 <EnterWindow>: ManagerEnter()\n\
146 <LeaveWindow>: ManagerLeave()\n\
147 <FocusOut>: ManagerFocusOut()\n\
148 <FocusIn>: ManagerFocusIn()";
150 /* Primitive Child Translations */
152 static char primTranslations[] =
153 "<FocusIn>: XmLFolderPrimFocusIn() PrimitiveFocusIn()\n\
154 <FocusOut>: XmLFolderPrimFocusOut() PrimitiveFocusOut()";
156 static XtResource resources[] =
158 /* Folder Resources */
160 XmNtabWidgetClass, XmCTabWidgetClass,
161 XmRWidgetClass, sizeof(WidgetClass),
162 XtOffset(XmLFolderWidget, folder.tabWidgetClass),
163 XmRCallProc, (XtPointer)GetDefaultTabWidgetClass,
166 XmNactivateCallback, XmCCallback,
167 XmRCallback, sizeof(XtCallbackList),
168 XtOffset(XmLFolderWidget, folder.activateCallback),
169 XmRImmediate, (XtPointer)0,
172 XmNactiveTab, XmCActiveTab,
173 XmRInt, sizeof(int),
174 XtOffset(XmLFolderWidget, folder.activeTab),
175 XmRImmediate, (XtPointer)-1,
178 XmNautoSelect, XmCAutoSelect,
179 XmRBoolean, sizeof(Boolean),
180 XtOffset(XmLFolderWidget, folder.autoSelect),
181 XmRImmediate, (XtPointer)True,
184 XmNblankBackground, XmCBlankBackground,
185 XmRPixel, sizeof(Pixel),
186 XtOffset(XmLFolderWidget, folder.blankBg),
187 XmRCallProc, (XtPointer)GetCoreBackground,
190 XmNblankBackgroundPixmap, XmCBlankBackgroundPixmap,
191 XmRManForegroundPixmap, sizeof(Pixmap),
192 XtOffset(XmLFolderWidget, folder.blankPix),
193 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
196 XmNcornerDimension, XmCCornerDimension,
197 XmRDimension, sizeof(Dimension),
198 XtOffset(XmLFolderWidget, folder.cornerDimension),
199 XmRImmediate, (XtPointer)2,
202 XmNcornerStyle, XmCCornerStyle,
203 XmRCornerStyle, sizeof(unsigned char),
204 XtOffset(XmLFolderWidget, folder.cornerStyle),
205 XmRImmediate, (XtPointer)XmCORNER_ARC,
208 XmNfontList, XmCFontList,
209 XmRFontList, sizeof(XmFontList),
210 XtOffset(XmLFolderWidget, folder.fontList),
211 XmRImmediate, (XtPointer)0,
214 XmNhighlightThickness, XmCHighlightThickness,
215 XmRDimension, sizeof(Dimension),
216 XtOffset(XmLFolderWidget, folder.highlightThickness),
217 XmRImmediate, (XtPointer)2,
220 XmNinactiveBackground, XmCInactiveBackground,
221 XmRPixel, sizeof(Pixel),
222 XtOffset(XmLFolderWidget, folder.inactiveBg),
223 XmRCallProc, (XtPointer)GetCoreBackground,
226 XmNinactiveForeground, XmCInactiveForeground,
227 XmRPixel, sizeof(Pixel),
228 XtOffset(XmLFolderWidget, folder.inactiveFg),
229 XmRCallProc, (XtPointer)GetManagerForeground,
232 XmNmarginHeight, XmCMarginHeight,
233 XmRDimension, sizeof(Dimension),
234 XtOffset(XmLFolderWidget, folder.marginHeight),
235 XmRImmediate, (XtPointer)0,
238 XmNmarginWidth, XmCMarginWidth,
239 XmRDimension, sizeof(Dimension),
240 XtOffset(XmLFolderWidget, folder.marginWidth),
241 XmRImmediate, (XtPointer)0,
244 XmNminTabWidth, XmCminTabWidth,
245 XmRDimension, sizeof(Dimension),
246 XtOffset(XmLFolderWidget, folder.minTabWidth),
247 XmRImmediate, (XtPointer)0,
250 XmNmaxTabWidth, XmCmaxTabWidth,
251 XmRDimension, sizeof(Dimension),
252 XtOffset(XmLFolderWidget, folder.maxTabWidth),
253 XmRImmediate, (XtPointer)100,
256 XmNpixmapMargin, XmCPixmapMargin,
257 XmRDimension, sizeof(Dimension),
258 XtOffset(XmLFolderWidget, folder.pixmapMargin),
259 XmRImmediate, (XtPointer)2,
262 XmNresizePolicy, XmCFolderResizePolicy,
263 XmRFolderResizePolicy, sizeof(unsigned char),
264 XtOffset(XmLFolderWidget, folder.resizePolicy),
265 XmRImmediate, (XtPointer)XmRESIZE_STATIC,
268 XmNrotateWhenLeftRight, XmCRotateWhenLeftRight,
269 XmRBoolean, sizeof(Boolean),
270 XtOffset(XmLFolderWidget, folder.allowRotate),
271 XmRImmediate, (XtPointer)True,
274 XmNspacing, XmCSpacing,
275 XmRDimension, sizeof(Dimension),
276 XtOffset(XmLFolderWidget, folder.spacing),
277 XmRImmediate, (XtPointer)0,
280 XmNtabBarHeight, XmCTabBarHeight,
281 XmRDimension, sizeof(Dimension),
282 XtOffset(XmLFolderWidget, folder.tabBarHeight),
283 XmRImmediate, (XtPointer)0,
286 XmNtabCount, XmCTabCount,
287 XmRInt, sizeof(int),
288 XtOffset(XmLFolderWidget, folder.tabCount),
289 XmRImmediate, (XtPointer)0,
292 XmNtabPlacement, XmCTabPlacement,
293 XmRTabPlacement, sizeof(unsigned char),
294 XtOffset(XmLFolderWidget, folder.tabPlacement),
295 XmRImmediate, (XtPointer)XmFOLDER_TOP,
298 XmNtabsPerRow, XmCTabsPerRow,
299 XmRInt, sizeof(int),
300 XtOffset(XmLFolderWidget, folder.tabsPerRow),
301 XmRImmediate, (XtPointer)0,
304 XmNtabWidgetList, XmCReadOnly,
305 XmRPointer, sizeof(XtPointer),
306 XtOffset(XmLFolderWidget, folder.tabs),
307 XmRImmediate, (XtPointer)0,
310 XmNtabTranslations, XmCTranslations,
311 XmRTranslationTable, sizeof(XtTranslations),
312 XtOffset(XmLFolderWidget, folder.primTrans),
313 XmRString, (XtPointer)primTranslations,
316 XmNdebugLevel, XmCDebugLevel,
317 XmRInt, sizeof(int),
318 XtOffset(XmLFolderWidget, folder.debugLevel),
319 XmRImmediate, (XtPointer)0,
321 /* Overridden inherited resources */
323 XmNshadowThickness, XmCShadowThickness,
324 XmRHorizontalDimension, sizeof(Dimension),
325 XtOffset(XmLFolderWidget, manager.shadow_thickness),
326 XmRImmediate, (XtPointer)2,
330 static XtResource constraint_resources[] =
332 /* Folder Constraint Resources */
334 XmNtabFreePixmaps, XmCTabFreePixmaps,
335 XmRBoolean, sizeof(Boolean),
336 XtOffset(XmLFolderConstraintPtr, folder.freePix),
337 XmRImmediate, (XtPointer)False,
340 XmNtabInactivePixmap, XmCTabInactivePixmap,
341 XmRPrimForegroundPixmap, sizeof(Pixmap),
342 XtOffset(XmLFolderConstraintPtr, folder.inactPix),
343 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
346 XmNtabManagedName, XmCTabManagedName,
347 XmRString, sizeof(char *),
348 XtOffset(XmLFolderConstraintPtr, folder.managedName),
349 XmRImmediate, (XtPointer)0,
352 XmNtabManagedWidget, XmCTabManagedWidget,
353 XmRWidget, sizeof(Widget),
354 XtOffset(XmLFolderConstraintPtr, folder.managedW),
355 XmRImmediate, (XtPointer)0,
358 XmNtabPixmap, XmCTabPixmap,
359 XmRPrimForegroundPixmap, sizeof(Pixmap),
360 XtOffset(XmLFolderConstraintPtr, folder.pix),
361 XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
365 XmLFolderClassRec xmlFolderClassRec =
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 */
401 { /* composite_class */
402 (XtGeometryHandler)GeometryManager, /* geometry_manager */
403 (XtWidgetProc)ChangeManaged, /* change_managed */
404 XtInheritInsertChild, /* insert_child */
405 XtInheritDeleteChild, /* delete_child */
406 0, /* extension */
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 */
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 */
426 { /* folder_class */
427 0, /* unused */
431 WidgetClass xmlFolderWidgetClass = (WidgetClass)&xmlFolderClassRec;
434 Create and Destroy
437 static void
438 ClassInitialize(void)
440 XmLInitialize();
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);
450 static void
451 Initialize(Widget req,
452 Widget newW,
453 ArgList args,
454 Cardinal *narg)
456 Display *dpy;
457 /* Window root;*/
458 XmLFolderWidget f, request;
460 f = (XmLFolderWidget)newW;
461 dpy = XtDisplay((Widget)f);
462 request = (XmLFolderWidget)req;
464 if (f->core.width == 0)
465 f->core.width = 100;
466 if (f->core.height == 0)
467 f->core.height = 100;
469 f->folder.gc = 0;
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);
481 if (f->folder.tabBarHeight)
483 XmLWarning((Widget)f, "Initialize() - can't set tabBarHeight");
484 f->folder.tabBarHeight = 0;
486 if (f->folder.tabCount)
488 XmLWarning((Widget)f, "Initialize() - can't set tabCount");
489 f->folder.tabCount = 0;
491 if (f->folder.activeTab != -1)
493 XmLWarning((Widget)f, "Initialize() - can't set activeTab");
494 f->folder.activeTab = -1;
496 if (f->folder.cornerDimension < 1)
498 XmLWarning((Widget)f, "Initialize() - cornerDimension can't be < 1");
499 f->folder.cornerDimension = 1;
501 f->folder.serverDrawsArcsLarge = ServerDrawsArcsLarge(dpy,
502 f->folder.debugLevel);
503 if (f->folder.minTabWidth <= 0)
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);
513 static void
514 Destroy(Widget w)
516 XmLFolderWidget f;
517 Display *dpy;
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);
531 Geometry, Drawing, Entry and Picking
534 static void
535 Realize(Widget w,
536 XtValueMask *valueMask,
537 XSetWindowAttributes *attr)
539 XmLFolderWidget f;
540 Display *dpy;
541 WidgetClass superClass;
542 XtRealizeProc realize;
543 XGCValues values;
544 XtGCMask mask;
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);
552 if (!f->folder.gc)
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);
562 static void
563 Redisplay(Widget w,
564 XExposeEvent *event,
565 Region region)
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; */
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;
587 if (event)
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);
597 else
599 eRect.x = 0;
600 eRect.y = 0;
601 eRect.width = f->core.width;
602 eRect.height = f->core.height;
604 if (!eRect.width || !eRect.height)
605 return;
607 if (f->folder.tabPlacement == XmFOLDER_TOP)
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;
614 else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
616 rRect.x = 0;
617 rRect.y = 0;
618 rRect.width = f->core.width;
619 rRect.height = f->core.height - f->folder.tabHeight;
621 if (f->folder.tabPlacement == XmFOLDER_LEFT)
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;
628 if (f->folder.tabPlacement == XmFOLDER_RIGHT)
630 rRect.x = 0;
631 rRect.y = 0;
632 rRect.width = f->core.width - f->folder.tabWidth;
633 rRect.height = f->core.height;
635 if (XmLRectIntersect(&eRect, &rRect) != XmLRectOutside)
637 if (f->folder.tabPlacement == XmFOLDER_TOP ||
638 f->folder.tabPlacement == XmFOLDER_BOTTOM)
639 DrawManagerShadowTopBottom(f, &rRect);
640 else
641 DrawManagerShadowLeftRight(f, &rRect);
644 if (!f->folder.tabCount)
645 return;
647 rRect.x = 0;
648 rRect.y = 0;
649 rRect.width = 0;
650 rRect.height = 0;
652 /* Draw tabs */
653 for (i = 0; i < f->folder.tabCount; i++)
655 tab = f->folder.tabs[i];
656 if (!XtIsManaged(tab))
657 continue;
658 fc = (XmLFolderConstraintRec *)(tab->core.constraints);
659 GetTabRect(f, tab, &rRect, 0);
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;
669 /* include indent in intersect test */
670 if (f->folder.tabsPerRow)
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;
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;
688 if (f->folder.debugLevel > 1)
689 fprintf(stderr, "XmLFolder: Redisplay tab for widget %d\n", i);
690 if (tab == f->folder.activeW)
692 XtVaSetValues(tab,
693 XmNbackground, f->core.background_pixel,
694 XmNforeground, f->manager.foreground,
695 NULL);
697 else
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);
708 if (f->folder.tabPlacement == XmFOLDER_TOP ||
709 f->folder.tabPlacement == XmFOLDER_BOTTOM)
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);
718 else
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);
728 if (f->folder.focusW == tab)
729 DrawTabHighlight(f, tab);
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);
740 SetGC(f, GC_BLANK);
742 /* draw indent */
743 if (f->folder.tabsPerRow)
745 if (rRect.x == 2)
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);
753 if (rRect.y == 2)
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);
761 if (rRect.x + rRect.width == f->core.width - 2)
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);
769 if (rRect.y + rRect.height == f->core.height - 2)
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);
779 if (f->folder.spacing)
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);
790 SetGC(f, GC_UNSET);
793 /* Draw empty area */
794 if (!f->folder.tabsPerRow)
796 if (f->folder.tabPlacement == XmFOLDER_TOP ||
797 f->folder.tabPlacement == XmFOLDER_BOTTOM)
799 rRect.x += rRect.width + f->folder.spacing;
800 if ((int)f->core.width > rRect.x)
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);
814 else
816 rRect.y += rRect.height + f->folder.spacing;
817 if ((int)f->core.height > rRect.y)
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);
834 static void
835 Layout(XmLFolderWidget f,
836 int resizeIfNeeded)
838 /* Window win;*/
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;
853 static void
854 LayoutTopBottom(XmLFolderWidget f,
855 int resizeIfNeeded)
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
877 int width, height, numTabs, y;
878 } rows[MAX_TAB_ROWS];
880 dpy = XtDisplay(f);
881 children = f->composite.children;
882 st = f->manager.shadow_thickness;
883 ht = f->folder.highlightThickness;
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;
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;
902 if (f->folder.tabCount && f->folder.resizePolicy == XmRESIZE_PACK)
904 int maxTabWidth = f->folder.maxTabWidth;
905 int tabEffCount = 0;
907 for (i = 0; i < f->folder.tabCount; i++)
909 tab = f->folder.tabs[i];
910 if (!XtIsManaged(tab))
911 continue;
912 tabEffCount++;
915 tabPaddingWidth = (st + co + f->folder.marginWidth + ht +
916 f->folder.tabs[0]->core.border_width) * 2;
917 if (maxTabWidth * tabEffCount > f->core.width)
919 tgtTabWidth = f->core.width/tabEffCount - tabPaddingWidth;
920 tailSpace = f->core.width % tabEffCount;
921 tabFit = 1;
923 /* if tabs get too small */
924 if (tgtTabWidth < f->folder.minTabWidth) {
925 tgtTabWidth = f->folder.minTabWidth;
926 tabFit = 0;
929 else
931 tgtTabWidth = maxTabWidth - tabPaddingWidth;
932 tabFit = 0;
936 for (i = 0; i < f->folder.tabCount; i++)
938 tab = f->folder.tabs[i];
939 if (!XtIsManaged(tab))
940 continue;
942 if (f->folder.resizePolicy == XmRESIZE_PACK)
944 if (tabFit)
946 XtVaSetValues(tab, XmNwidth,
947 tailSpace? tgtTabWidth+1: tgtTabWidth, NULL);
948 if (tailSpace)
949 tailSpace--;
951 else
953 XtVaSetValues(tab, XmNwidth, tgtTabWidth, NULL);
957 fc = (XmLFolderConstraintRec *)(tab->core.constraints);
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)
965 fc->folder.firstInRow = True;
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)
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);
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)
989 XmLWarning((Widget)f, "Layout ERROR - too many rows\n");
990 return;
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;
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)
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;
1019 if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP)
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;
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;
1042 tabNum++;
1043 fc->folder.row = rowNum;
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)
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);
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;
1066 /* add space for indent of upper rows */
1067 if (f->folder.tabsPerRow && minWidth)
1068 minWidth += 4;
1070 if (f->folder.debugLevel)
1072 fprintf(stderr, "XmLFolder: Layout: ");
1073 fprintf(stderr, "tab bar minimum w %d h %d\n",
1074 (int)minWidth, (int)minHeight);
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++)
1081 child = children[i];
1082 if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1083 continue;
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;
1091 width = XtWidth(child) + st * 2;
1092 if (XtIsWidget(child))
1093 width += child->core.border_width * 2;
1094 if (width > minWidth)
1095 minWidth = width;
1098 if (f->folder.debugLevel)
1100 fprintf(stderr, "XmLFolder: Layout: ");
1101 fprintf(stderr, "with non-tabs minimum w %d h %d\n",
1102 (int)minWidth, (int)minHeight);
1105 /* Resize folder if needed */
1106 if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE)
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);
1118 /* move active row to bottom */
1119 tab = f->folder.activeW;
1120 if (tab)
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;
1129 else
1130 f->folder.activeRow = -1;
1132 /* configure tab children */
1133 for (i = 0; i < f->folder.tabCount; i++)
1135 tab = f->folder.tabs[i];
1136 if (!XtIsManaged(tab))
1137 continue;
1138 fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1139 rowNum = fc->folder.row;
1141 /* calculate tab x */
1142 if (fc->folder.firstInRow == True)
1144 if (f->folder.tabsPerRow && rowNum != f->folder.activeRow)
1145 x = 2;
1146 else
1147 x = 0;
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;
1154 /* calculate tab y and tab height */
1155 fc->folder.height = rows[rowNum].height;
1156 if (f->folder.tabPlacement == XmFOLDER_TOP)
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;
1162 else
1164 fc->folder.y = f->core.height - rows[rowNum].y -
1165 rows[rowNum].height;
1166 y = fc->folder.y + f->folder.marginHeight + ht;
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)
1177 pad1 = w / (rows[rowNum].numTabs * 2);
1178 pad2 = pad1;
1179 if (fc->folder.firstInRow == True)
1180 pad2 += w - (pad1 * rows[rowNum].numTabs * 2);
1182 x += pad1;
1184 /* move tab widget into place */
1185 XtMoveWidget(tab, x, y);
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;
1194 /* configure non-tab children */
1195 for (i = 0; i < f->composite.num_children; i++)
1197 child = children[i];
1198 if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1199 continue;
1200 if (f->folder.resizePolicy == XmRESIZE_NONE)
1201 continue;
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))
1212 XtVaGetValues(child,
1213 XmNmappedWhenManaged, &map,
1214 NULL);
1215 XtVaSetValues(child,
1216 XmNmappedWhenManaged, False,
1217 NULL);
1218 XtManageChild(child);
1219 isManaged = False;
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)
1234 XtUnmanageChild(child);
1235 XtVaSetValues(child, XmNmappedWhenManaged, map, NULL);
1240 static void
1241 LayoutLeftRight(XmLFolderWidget f,
1242 int resizeIfNeeded)
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
1262 int width, height, numTabs, x;
1263 } rows[MAX_TAB_ROWS];
1265 dpy = XtDisplay(f);
1266 children = f->composite.children;
1267 st = f->manager.shadow_thickness;
1268 ht = f->folder.highlightThickness;
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;
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++)
1288 tab = f->folder.tabs[i];
1289 if (!XtIsManaged(tab))
1290 continue;
1291 fc = (XmLFolderConstraintRec *)(tab->core.constraints);
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)
1299 fc->folder.firstInRow = True;
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)
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);
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)
1323 XmLWarning((Widget)f, "Layout ERROR - too many rows\n");
1324 return;
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;
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)
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;
1355 if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP)
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;
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;
1375 if (fc->folder.maxPixHeight)
1376 rowY += fc->folder.maxPixHeight + f->folder.pixmapMargin;
1377 rowY += f->folder.spacing;
1379 tabNum++;
1380 fc->folder.row = rowNum;
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)
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);
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;
1403 /* add space for indent of upper rows */
1404 if (f->folder.tabsPerRow && minHeight)
1405 minHeight += 4;
1407 if (f->folder.debugLevel)
1409 fprintf(stderr, "XmLFolder: Layout: ");
1410 fprintf(stderr, "tab bar minimum w %d h %d\n",
1411 (int)minWidth, (int)minHeight);
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++)
1418 child = children[i];
1419 if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1420 continue;
1422 height = XtHeight(child) + st * 2;
1423 if (XtIsWidget(child))
1424 height += f->core.border_width * 2;
1425 if (height > minHeight)
1426 minHeight = height;
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;
1435 if (f->folder.debugLevel)
1437 fprintf(stderr, "XmLFolder: Layout: ");
1438 fprintf(stderr, "with non-tabs minimum w %d h %d\n",
1439 (int)minWidth, (int)minHeight);
1442 /* Resize folder if needed */
1443 if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE)
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);
1454 /* move active row to bottom */
1455 tab = f->folder.activeW;
1456 if (tab)
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;
1465 else
1466 f->folder.activeRow = -1;
1468 /* configure tab children */
1469 for (i = 0; i < f->folder.tabCount; i++)
1471 tab = f->folder.tabs[i];
1472 if (!XtIsManaged(tab))
1473 continue;
1474 fc = (XmLFolderConstraintRec *)(tab->core.constraints);
1475 rowNum = fc->folder.row;
1477 /* calculate tab x */
1478 if (fc->folder.firstInRow == True)
1480 if (f->folder.tabsPerRow && rowNum != f->folder.activeRow)
1481 y = 2;
1482 else
1483 y = 0;
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;
1490 /* calculate tab x and tab width */
1491 fc->folder.width = rows[rowNum].width;
1492 if (f->folder.tabPlacement == XmFOLDER_LEFT)
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;
1498 else
1500 fc->folder.x = f->core.width - rows[rowNum].x -
1501 rows[rowNum].width;
1502 x = fc->folder.x + f->folder.marginHeight + ht;
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)
1513 pad1 = h / (rows[rowNum].numTabs * 2);
1514 pad2 = pad1;
1515 if (fc->folder.firstInRow == True)
1516 pad2 += h - (pad1 * rows[rowNum].numTabs * 2);
1518 y += pad1;
1520 /* move tab widget into place */
1521 XtMoveWidget(tab, x, y);
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;
1530 /* configure non-tab children */
1531 for (i = 0; i < f->composite.num_children; i++)
1533 child = children[i];
1534 if (XtIsSubclass(child, xmPrimitiveWidgetClass))
1535 continue;
1536 if (f->folder.resizePolicy == XmRESIZE_NONE)
1537 continue;
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))
1548 XtVaGetValues(child,
1549 XmNmappedWhenManaged, &map,
1550 NULL);
1551 XtVaSetValues(child,
1552 XmNmappedWhenManaged, False,
1553 NULL);
1554 XtManageChild(child);
1555 isManaged = False;
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)
1570 XtUnmanageChild(child);
1571 XtVaSetValues(child, XmNmappedWhenManaged, map, NULL);
1576 static void
1577 Resize(Widget w)
1579 XmLFolderWidget f;
1581 f = (XmLFolderWidget)w;
1582 Layout(f, 0);
1585 static XtGeometryResult
1586 GeometryManager(Widget w,
1587 XtWidgetGeometry *request,
1588 XtWidgetGeometry *allow)
1590 XmLFolderWidget f;
1592 f = (XmLFolderWidget)XtParent(w);
1593 if (f->folder.resizePolicy != XmRESIZE_STATIC ||
1594 XtIsSubclass(w, xmPrimitiveWidgetClass))
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;
1609 return XtGeometryNo;
1612 static void
1613 ChangeManaged(Widget w)
1615 XmLFolderWidget f;
1617 f = (XmLFolderWidget)w;
1618 Layout(f, 1);
1619 _XmNavigChangeManaged(w);
1622 static void
1623 ConstraintInitialize(Widget req,
1624 Widget w,
1625 ArgList args,
1626 Cardinal *narg)
1628 XmLFolderWidget f;
1629 XmLFolderConstraintRec *fc;
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))
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);
1658 /* add child to tabs list */
1659 if (f->folder.tabAllocCount < f->folder.tabCount + 1)
1661 f->folder.tabAllocCount *= 2;
1662 f->folder.tabs = (Widget *)realloc((char *)f->folder.tabs,
1663 sizeof(Widget) * f->folder.tabAllocCount);
1665 f->folder.tabs[f->folder.tabCount++] = w;
1668 if (XmIsDrawnButton(w))
1669 SetTabPlacement(f, w);
1671 #ifdef XmLEVAL
1672 if (f->folder.tabCount > 6)
1674 fprintf(stderr, "XmL: evaluation version only supports <= 6 tabs\n");
1675 exit(0);
1677 #endif
1680 static void
1681 ConstraintDestroy(Widget w)
1683 XmLFolderWidget f;
1684 XmLFolderConstraintRec *fc;
1685 int i, j, activePos;
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)
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);
1704 if (XtIsSubclass(w, xmPrimitiveWidgetClass))
1706 XtRemoveCallback(w, XmNactivateCallback, PrimActivate, 0);
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)
1714 if (f->folder.activeW == f->folder.tabs[i])
1715 activePos = j;
1716 f->folder.tabs[j++] = f->folder.tabs[i];
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;
1727 static void
1728 DrawTabPixmap(XmLFolderWidget f,
1729 Widget tab,
1730 int active)
1732 Display *dpy;
1733 Window win;
1734 int x, y;
1735 Pixmap pixmap;
1736 Dimension pixWidth, pixHeight, ht;
1737 XmLFolderConstraintRec *fc;
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)
1747 pixWidth = fc->folder.pixWidth;
1748 pixHeight = fc->folder.pixHeight;
1749 pixmap = fc->folder.pix;
1751 else
1753 pixWidth = fc->folder.inactPixWidth;
1754 pixHeight = fc->folder.inactPixHeight;
1755 pixmap = fc->folder.inactPix;
1757 if (f->folder.tabPlacement == XmFOLDER_TOP)
1759 x = tab->core.x - pixWidth - ht - f->folder.pixmapMargin;
1760 y = tab->core.y + tab->core.height - pixHeight;
1762 else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1764 x = tab->core.x - fc->folder.pixWidth - ht - f->folder.pixmapMargin;
1765 y = tab->core.y;
1767 else if (f->folder.tabPlacement == XmFOLDER_LEFT)
1769 x = tab->core.x + tab->core.width - pixWidth;
1770 y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht;
1772 else if (f->folder.tabPlacement == XmFOLDER_RIGHT)
1774 x = tab->core.x;
1775 y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht;
1777 XCopyArea(dpy, pixmap, win, f->folder.gc, 0, 0, pixWidth, pixHeight, x, y);
1780 static void
1781 DrawManagerShadowTopBottom(XmLFolderWidget f,
1782 XRectangle *rect)
1784 Display *dpy;
1785 Window win;
1786 XmLFolderConstraintRec *fc;
1787 XSegment *topSeg, *botSeg;
1788 int i, bCount, tCount, st, botOff, isManaged;
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;
1797 topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1798 botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
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++)
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++;
1822 else
1823 for (i = 0; i < st; i++)
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++;
1831 if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
1832 for (i = 0 ; i < tCount; i++)
1834 topSeg[i].y1 = botOff - topSeg[i].y1;
1835 topSeg[i].y2 = botOff - topSeg[i].y2;
1837 if (tCount)
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);
1847 /* see if there's any composite widgets in the folder */
1848 isManaged = 0;
1849 for (i = 0; i < f->composite.num_children; i++)
1851 Widget child = f->composite.children[i];
1852 if (!XtIsSubclass(child, xmPrimitiveWidgetClass) && XtIsManaged(child))
1854 isManaged = 1;
1855 break;
1860 /* no need to draw shadow for the manager area if
1861 there isn't any composite widgets in the folder */
1862 if (!isManaged)
1864 free((char *)topSeg);
1865 free((char *)botSeg);
1866 return;
1869 /* left shadow */
1870 tCount = 0;
1871 for (i = 0; i < st; i++)
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++;
1879 if (tCount)
1881 SetGC(f, GC_SHADOWTOP);
1882 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
1883 SetGC(f, GC_UNSET);
1886 /* right shadow */
1887 bCount = 0;
1888 for (i = 0; i < st; i++)
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++;
1896 if (bCount)
1898 SetGC(f, GC_SHADOWBOT);
1899 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
1900 SetGC(f, GC_UNSET);
1903 /* bottom shadow */
1904 bCount = 0;
1905 for (i = 0; i < st; i++)
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)
1913 botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
1914 botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
1916 bCount++;
1918 if (bCount)
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);
1927 free((char *)topSeg);
1928 free((char *)botSeg);
1931 static void
1932 DrawManagerShadowLeftRight(XmLFolderWidget f,
1933 XRectangle *rect)
1935 Display *dpy;
1936 Window win;
1937 XmLFolderConstraintRec *fc;
1938 XSegment *topSeg, *botSeg;
1939 int i, bCount, tCount, st, rightOff;
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;
1948 topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
1949 botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2);
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++)
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++;
1973 else
1974 for (i = 0; i < st; i++)
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++;
1982 if (f->folder.tabPlacement == XmFOLDER_RIGHT)
1983 for (i = 0 ; i < tCount; i++)
1985 topSeg[i].x1 = rightOff - topSeg[i].x1;
1986 topSeg[i].x2 = rightOff - topSeg[i].x2;
1988 if (tCount)
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);
1998 /* top shadow */
1999 tCount = 0;
2000 for (i = 0; i < st; i++)
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++;
2008 if (tCount)
2010 SetGC(f, GC_SHADOWTOP);
2011 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2012 SetGC(f, GC_UNSET);
2015 /* bottom shadow */
2016 bCount = 0;
2017 for (i = 0; i < st; i++)
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++;
2025 if (bCount)
2027 SetGC(f, GC_SHADOWBOT);
2028 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2029 SetGC(f, GC_UNSET);
2032 /* right shadow */
2033 bCount = 0;
2034 for (i = 0; i < st; i++)
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)
2042 botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2043 botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2045 bCount++;
2047 if (bCount)
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);
2056 free((char *)topSeg);
2057 free((char *)botSeg);
2060 static void
2061 DrawTabShadowArcTopBottom(XmLFolderWidget f,
2062 Widget w)
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;
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;
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++)
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)
2097 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2098 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2100 tCount++;
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)
2111 botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2112 botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2114 bCount++;
2116 if (tCount)
2118 SetGC(f, GC_SHADOWTOP);
2119 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2120 SetGC(f, GC_UNSET);
2122 if (bCount)
2124 SetGC(f, GC_SHADOWBOT);
2125 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2126 SetGC(f, GC_UNSET);
2128 tCount = 0;
2129 for (i = 0; i < st; i++)
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)
2138 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2139 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2141 tCount++;
2143 if (tCount)
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);
2152 free((char *)topSeg);
2153 free((char *)botSeg);
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);
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)
2177 arc.width -= 1;
2178 arc.height -= 1;
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);
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);
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);
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)
2227 arc.width -= 1;
2228 arc.height -= 1;
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);
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);
2262 static void
2263 DrawTabShadowArcLeftRight(XmLFolderWidget f,
2264 Widget w)
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;
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;
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++)
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)
2299 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2300 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2302 tCount++;
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)
2313 botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2314 botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2316 bCount++;
2318 if (tCount)
2320 SetGC(f, GC_SHADOWTOP);
2321 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2322 SetGC(f, GC_UNSET);
2324 if (bCount)
2326 SetGC(f, GC_SHADOWBOT);
2327 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2328 SetGC(f, GC_UNSET);
2330 tCount = 0;
2331 for (i = 0; i < st; i++)
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)
2340 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2341 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2343 tCount++;
2345 if (tCount)
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);
2354 free((char *)topSeg);
2355 free((char *)botSeg);
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);
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)
2377 arc.width -= 1;
2378 arc.height -= 1;
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);
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);
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);
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)
2427 arc.width -= 1;
2428 arc.height -= 1;
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);
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);
2462 static void
2463 DrawTabShadowLineTopBottom(XmLFolderWidget f,
2464 Widget w)
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;
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;
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++)
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)
2497 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2498 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
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)
2510 botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2511 botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2513 bCount++;
2515 if (tCount)
2517 SetGC(f, GC_SHADOWTOP);
2518 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2519 SetGC(f, GC_UNSET);
2521 if (bCount)
2523 SetGC(f, GC_SHADOWBOT);
2524 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2525 SetGC(f, GC_UNSET);
2527 tCount = 0;
2528 for (i = 0; i < st; i++)
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)
2537 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2538 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2540 tCount++;
2542 if (tCount)
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);
2551 free((char *)topSeg);
2552 free((char *)botSeg);
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)
2563 points[0].y = botOff - points[0].y;
2564 points[1].y = botOff - points[1].y;
2565 points[2].y = botOff - points[2].y;
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);
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)
2603 points[0].y = botOff - points[0].y;
2604 points[1].y = botOff - points[1].y;
2605 points[2].y = botOff - points[2].y;
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);
2639 static void
2640 DrawTabShadowLineLeftRight(XmLFolderWidget f,
2641 Widget w)
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;
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;
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++)
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)
2674 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2675 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
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)
2687 botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2688 botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2690 bCount++;
2692 if (tCount)
2694 SetGC(f, GC_SHADOWTOP);
2695 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2696 SetGC(f, GC_UNSET);
2698 if (bCount)
2700 SetGC(f, GC_SHADOWBOT);
2701 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2702 SetGC(f, GC_UNSET);
2704 tCount = 0;
2705 for (i = 0; i < st; i++)
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)
2714 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2715 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2717 tCount++;
2719 if (tCount)
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);
2728 free((char *)topSeg);
2729 free((char *)botSeg);
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)
2740 points[0].x = rightOff - points[0].x;
2741 points[1].x = rightOff - points[1].x;
2742 points[2].x = rightOff - points[2].x;
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);
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)
2781 points[0].x = rightOff - points[0].x;
2782 points[1].x = rightOff - points[1].x;
2783 points[2].x = rightOff - points[2].x;
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);
2815 static void
2816 DrawTabShadowNoneTopBottom(XmLFolderWidget f,
2817 Widget w)
2819 XmLFolderConstraintRec *fc;
2820 Display *dpy;
2821 Window win;
2822 XSegment *topSeg, *botSeg;
2823 int i, st, botOff, tCount, bCount;
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;
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++)
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)
2848 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2849 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2851 tCount++;
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)
2862 botSeg[bCount].y1 = botOff - botSeg[bCount].y1;
2863 botSeg[bCount].y2 = botOff - botSeg[bCount].y2;
2865 bCount++;
2867 if (tCount)
2869 SetGC(f, GC_SHADOWTOP);
2870 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2871 SetGC(f, GC_UNSET);
2873 if (bCount)
2875 SetGC(f, GC_SHADOWBOT);
2876 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2877 SetGC(f, GC_UNSET);
2880 tCount = 0;
2881 for (i = 0; i < st; i++)
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)
2890 topSeg[tCount].y1 = botOff - topSeg[tCount].y1;
2891 topSeg[tCount].y2 = botOff - topSeg[tCount].y2;
2893 tCount++;
2895 if (tCount)
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);
2904 free((char *)topSeg);
2905 free((char *)botSeg);
2908 static void
2909 DrawTabShadowNoneLeftRight(XmLFolderWidget f,
2910 Widget w)
2912 XmLFolderConstraintRec *fc;
2913 Display *dpy;
2914 Window win;
2915 XSegment *topSeg, *botSeg;
2916 int i, st, rightOff, tCount, bCount;
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;
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++)
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)
2941 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2942 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2944 tCount++;
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)
2955 botSeg[bCount].x1 = rightOff - botSeg[bCount].x1;
2956 botSeg[bCount].x2 = rightOff - botSeg[bCount].x2;
2958 bCount++;
2960 if (tCount)
2962 SetGC(f, GC_SHADOWTOP);
2963 XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount);
2964 SetGC(f, GC_UNSET);
2966 if (bCount)
2968 SetGC(f, GC_SHADOWBOT);
2969 XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount);
2970 SetGC(f, GC_UNSET);
2973 tCount = 0;
2974 for (i = 0; i < st; i++)
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)
2983 topSeg[tCount].x1 = rightOff - topSeg[tCount].x1;
2984 topSeg[tCount].x2 = rightOff - topSeg[tCount].x2;
2986 tCount++;
2988 if (tCount)
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);
2997 free((char *)topSeg);
2998 free((char *)botSeg);
3001 static void
3002 SetGC(XmLFolderWidget f,
3003 int type)
3005 Display *dpy;
3006 XGCValues values;
3007 XtGCMask mask;
3009 dpy = XtDisplay(f);
3010 if (type == GC_SHADOWBOT)
3012 mask = GCForeground;
3013 values.foreground = f->manager.bottom_shadow_color;
3014 if (f->manager.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
3016 mask |= GCFillStyle | GCTile;
3017 values.fill_style = FillTiled;
3018 values.tile = f->manager.bottom_shadow_pixmap;
3020 XChangeGC(dpy, f->folder.gc, mask, &values);
3022 else if (type == GC_SHADOWTOP)
3024 mask = GCForeground;
3025 values.foreground = f->manager.top_shadow_color;
3026 if (f->manager.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
3028 mask |= GCFillStyle | GCTile;
3029 values.fill_style = FillTiled;
3030 values.tile = f->manager.top_shadow_pixmap;
3032 XChangeGC(dpy, f->folder.gc, mask, &values);
3034 else if (type == GC_BLANK)
3036 mask = GCForeground;
3037 values.foreground = f->folder.blankBg;
3038 if (f->folder.blankPix != XmUNSPECIFIED_PIXMAP)
3040 mask |= GCFillStyle | GCTile;
3041 values.fill_style = FillTiled;
3042 values.tile = f->folder.blankPix;
3044 XChangeGC(dpy, f->folder.gc, mask, &values);
3046 else
3048 mask = GCFillStyle;
3049 values.fill_style = FillSolid;
3050 XChangeGC(dpy, f->folder.gc, mask, &values);
3054 static void
3055 DrawTabHighlight(XmLFolderWidget f,
3056 Widget w)
3058 XmLFolderConstraintRec *fc;
3059 Display *dpy;
3060 Window win;
3061 int ht;
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
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);
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);
3086 static void
3087 SetTabPlacement(XmLFolderWidget f,
3088 Widget tab)
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);
3104 static void
3105 GetTabRect(XmLFolderWidget f,
3106 Widget tab,
3107 XRectangle *rect,
3108 int includeShadow)
3110 XmLFolderConstraintRec *fc;
3111 int st;
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)
3121 if (f->folder.tabPlacement == XmFOLDER_TOP)
3122 rect->height += st;
3123 else if (f->folder.tabPlacement == XmFOLDER_BOTTOM)
3125 rect->y -= st;
3126 rect->height += st;
3128 else if (f->folder.tabPlacement == XmFOLDER_LEFT)
3129 rect->width += st;
3130 else
3132 rect->x -= st;
3133 rect->width += st;
3138 static void
3139 SetActiveTab(XmLFolderWidget f,
3140 Widget w,
3141 XEvent *event,
3142 Boolean notify)
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];
3154 win = (Window)NULL;
3156 if (f->folder.activeW == w)
3157 return;
3158 dpy = 0;
3159 if (XtIsRealized((Widget)f) && f->core.visible)
3161 dpy = XtDisplay(f);
3162 win = XtWindow(f);
3165 pos = -1;
3166 for (i = 0; i < f->folder.tabCount; i++)
3167 if (w == f->folder.tabs[i])
3168 pos = i;
3170 cbs.allowActivate = 1;
3171 cbs.layoutNeeded = 0;
3172 if (notify == True)
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);
3181 if (!cbs.allowActivate)
3182 return;
3184 /* redraw current active tab */
3185 activeW = f->folder.activeW;
3186 if (activeW && dpy)
3188 GetTabRect(f, activeW, &rect, 1);
3189 XClearArea(dpy, win, rect.x, rect.y, rect.width,
3190 rect.height, True);
3193 f->folder.activeTab = pos;
3194 f->folder.activeW = w;
3195 if (!w)
3196 return;
3198 /* Not sure this needs to be in the 3.0 (Microline) stuff */
3199 PrimFocusIn(w, NULL, NULL, NULL);
3201 /* if we selected a tab not in active row - move row into place */
3202 if (f->folder.tabsPerRow)
3204 fc = (XmLFolderConstraintRec *)(w->core.constraints);
3205 if (fc->folder.row != f->folder.activeRow)
3206 Layout(f, False);
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++)
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)
3221 for (j = 0; j < f->composite.num_children; j++)
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;
3234 if (!managedW)
3236 sprintf(buf, "SetActiveTab() - managed widget named ");
3237 strcat(buf, fc->folder.managedName);
3238 strcat(buf, " not found");
3239 XmLWarning(child, buf);
3242 else
3243 managedW = fc->folder.managedW;
3244 if (managedW)
3246 if (w == child && !XtIsManaged(managedW))
3247 XtManageChild(managedW);
3248 if (w != child && XtIsManaged(managedW))
3249 XtUnmanageChild(managedW);
3252 f->folder.allowLayout = 1;
3254 /* redraw new active tab */
3255 if (dpy)
3257 GetTabRect(f, w, &rect, 1);
3258 XClearArea(dpy, win, rect.x, rect.y, rect.width, rect.height, True);
3259 XmProcessTraversal(w, XmTRAVERSE_CURRENT);
3262 if (cbs.layoutNeeded)
3263 Layout(f, 0);
3267 Utility
3270 static void
3271 GetCoreBackground(Widget w,
3272 int offset,
3273 XrmValue *value)
3275 value->addr = (caddr_t)&w->core.background_pixel;
3278 static void
3279 GetDefaultTabWidgetClass(Widget w,
3280 int offset,
3281 XrmValue *value)
3283 value->addr = (caddr_t)&xmDrawnButtonWidgetClass;
3286 static void
3287 GetManagerForeground(Widget w,
3288 int offset,
3289 XrmValue *value)
3291 XmLFolderWidget f;
3293 f = (XmLFolderWidget)w;
3294 value->addr = (caddr_t)&f->manager.foreground;
3297 static Boolean
3298 ServerDrawsArcsLarge(Display *dpy,
3299 int debug)
3301 Pixmap pixmap;
3302 XImage *image;
3303 Window root;
3304 long pixel;
3305 int x, y, width, height, result;
3306 GC gc;
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)
3320 fprintf(stderr, "Test X server drawn arc (%d by %d):\n",
3321 width, height);
3322 for (y = 0; y < height; y++)
3324 fprintf(stderr, " ");
3325 for (x = 0; x < width; x++)
3327 pixel = XGetPixel(image, x, y);
3328 if (pixel == 0L)
3329 fprintf(stderr, ".");
3330 else
3331 fprintf(stderr, "X");
3333 fprintf(stderr, "\n");
3336 if (XGetPixel(image, width - 1, height / 2) != 1L)
3338 result = 1;
3339 if (debug)
3340 fprintf(stderr, "X Server Draws Arcs 1 Pixel Large\n");
3342 else
3344 result = 0;
3345 if (debug)
3346 fprintf(stderr, "X Server Draws Arcs Within Bounds\n");
3348 XDestroyImage(image);
3349 XFreeGC(dpy, gc);
3350 XFreePixmap(dpy, pixmap);
3351 return result;
3355 Getting and Setting Values
3358 static Boolean
3359 SetValues(Widget curW,
3360 Widget reqW,
3361 Widget newW,
3362 ArgList args,
3363 Cardinal *narg)
3365 XmLFolderWidget f;
3366 XmLFolderWidget cur;
3367 int i;
3368 Boolean needsLayout, needsRedisplay;
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))
3377 XmLWarning((Widget)f, "SetValues() - can't set tabBarHeight");
3378 f->folder.tabBarHeight = cur->folder.tabBarHeight;
3380 if (NE(folder.tabCount))
3382 XmLWarning((Widget)f, "SetValues() - can't set tabCount");
3383 f->folder.tabCount = cur->folder.tabCount;
3385 if (NE(folder.activeTab))
3387 XmLWarning((Widget)f, "SetValues() - can't set activeTab");
3388 f->folder.activeTab = cur->folder.activeTab;
3390 if (f->folder.cornerDimension < 1)
3392 XmLWarning((Widget)f, "SetValues() - cornerDimension can't be < 1");
3393 f->folder.cornerDimension = cur->folder.cornerDimension;
3395 if (NE(folder.tabPlacement) ||
3396 NE(folder.allowRotate))
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;
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))
3421 XmFontListFree(cur->folder.fontList);
3422 CopyFontList(f);
3424 #undef NE
3425 if (needsLayout == True)
3426 Layout(f, 1);
3427 return needsRedisplay;
3430 static void
3431 CopyFontList(XmLFolderWidget f)
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");
3441 static Boolean
3442 ConstraintSetValues(Widget curW,
3443 Widget reqW,
3444 Widget newW,
3445 ArgList args,
3446 Cardinal *narg)
3448 XmLFolderConstraintRec *cons, *curCons;
3449 XmLFolderWidget f;
3450 int i, hasLabelChange;
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))
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);
3465 #undef NE
3466 hasLabelChange = 0;
3467 if (XtIsSubclass(newW, xmPrimitiveWidgetClass))
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))
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;
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;
3489 static Boolean
3490 CvtStringToCornerStyle(Display *dpy,
3491 XrmValuePtr args,
3492 Cardinal *narg,
3493 XrmValuePtr fromVal,
3494 XrmValuePtr toVal,
3495 XtPointer *data)
3497 static XmLStringToUCharMap map[] =
3499 { "CORNER_NONE", XmCORNER_NONE },
3500 { "CORNER_LINE", XmCORNER_LINE },
3501 { "CORNER_ARC", XmCORNER_ARC },
3502 { 0, 0 },
3505 return XmLCvtStringToUChar(dpy, "XmRCornerStyle", map, fromVal, toVal);
3508 static Boolean
3509 CvtStringToFolderResizePolicy(Display *dpy,
3510 XrmValuePtr args,
3511 Cardinal *narg,
3512 XrmValuePtr fromVal,
3513 XrmValuePtr toVal,
3514 XtPointer *data)
3516 static XmLStringToUCharMap map[] =
3518 { "RESIZE_NONE", XmRESIZE_NONE },
3519 { "RESIZE_STATIC", XmRESIZE_STATIC },
3520 { "RESIZE_DYNAMIC", XmRESIZE_DYNAMIC },
3521 { "RESIZE_PACK", XmRESIZE_PACK },
3522 { 0, 0 },
3525 return XmLCvtStringToUChar(dpy, "XmRFolderResizePolicy", map,
3526 fromVal, toVal);
3529 static Boolean
3530 CvtStringToTabPlacement(Display *dpy,
3531 XrmValuePtr args,
3532 Cardinal *narg,
3533 XrmValuePtr fromVal,
3534 XrmValuePtr toVal,
3535 XtPointer *data)
3537 static XmLStringToUCharMap map[] =
3539 { "FOLDER_TOP", XmFOLDER_TOP },
3540 { "FOLDER_LEFT", XmFOLDER_LEFT },
3541 { "FOLDER_BOTTOM", XmFOLDER_BOTTOM },
3542 { "FOLDER_RIGHT", XmFOLDER_RIGHT },
3543 { 0, 0 },
3546 return XmLCvtStringToUChar(dpy, "XmRTabPlacement", map, fromVal, toVal);
3550 Actions, Callbacks and Handlers
3553 static void
3554 Activate(Widget w,
3555 XEvent *event,
3556 String *params,
3557 Cardinal *nparam)
3559 XmLFolderWidget f;
3560 XButtonEvent *be;
3561 XRectangle rect;
3562 Widget tab;
3563 int i;
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++)
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)
3580 if (f->folder.debugLevel)
3581 fprintf(stderr, "XmLFolder: Pressed tab %d\n", i);
3582 SetActiveTab(f, tab, event, True);
3583 return;
3588 static void
3589 PrimActivate(Widget w,
3590 XtPointer clientData,
3591 XtPointer callData)
3593 XmLFolderWidget f;
3594 XmAnyCallbackStruct *cbs;
3596 f = (XmLFolderWidget)XtParent(w);
3597 cbs = (XmAnyCallbackStruct *)callData;
3598 SetActiveTab(f, w, cbs->event, True);
3601 static void
3602 PrimFocusIn(Widget w,
3603 XEvent *event,
3604 String *params,
3605 Cardinal *nparam)
3607 XmLFolderWidget f;
3608 Widget prevW;
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);
3619 static void
3620 PrimFocusOut(Widget w,
3621 XEvent *event,
3622 String *params,
3623 Cardinal *nparam)
3625 XmLFolderWidget f;
3626 Widget prevW;
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);
3637 Public Functions
3640 Widget
3641 XmLCreateFolder(Widget parent,
3642 char *name,
3643 ArgList arglist,
3644 Cardinal argcount)
3646 return XtCreateWidget(name, xmlFolderWidgetClass, parent,
3647 arglist, argcount);
3650 Widget
3651 XmLFolderAddBitmapTab(Widget w,
3652 XmString string,
3653 char *bitmapBits,
3654 int bitmapWidth,
3655 int bitmapHeight)
3657 XmLFolderWidget f;
3658 Widget tab;
3659 Pixmap pix, inactPix;
3660 Window root;
3661 Display *dpy;
3662 int depth;
3663 char name[20];
3665 if (!XmLIsFolder(w))
3667 XmLWarning(w, "AddBitmapTab() - widget not a XmLFolder");
3668 return 0;
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;
3694 Widget
3695 XmLFolderAddBitmapTabForm(Widget w,
3696 XmString string,
3697 char *bitmapBits,
3698 int bitmapWidth,
3699 int bitmapHeight)
3701 Widget form, tab;
3702 XmLFolderWidget f;
3703 char name[20];
3705 if (!XmLIsFolder(w))
3707 XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder");
3708 return 0;
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;
3722 Widget
3723 XmLFolderAddTab(Widget w,
3724 XmString string)
3726 Widget tab;
3727 XmLFolderWidget f;
3728 char name[20];
3730 if (!XmLIsFolder(w))
3732 XmLWarning(w, "AddTab() - widget not a XmLFolder");
3733 return 0;
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;
3747 Widget
3748 XmLFolderAddTabFromClass(Widget w,
3749 XmString string)
3751 Widget tab;
3752 XmLFolderWidget f;
3753 char name[20];
3755 if (!XmLIsFolder(w))
3757 XmLWarning(w, "AddTab() - widget not a XmLFolder");
3758 return 0;
3760 f = (XmLFolderWidget)w;
3761 sprintf(name, "tab%d", f->folder.tabCount);
3763 tab = XtVaCreateManagedWidget(name,
3764 f->folder.tabWidgetClass,
3765 /* xmDrawnButtonWidgetClass, */
3767 XmNfontList, f->folder.fontList,
3768 /* XmNmarginWidth, 0, */
3769 /* XmNmarginHeight, 0, */
3770 XmNlabelString, string,
3771 NULL);
3772 return tab;
3775 Widget
3776 XmLFolderAddTabForm(Widget w,
3777 XmString string)
3779 Widget form, tab;
3780 XmLFolderWidget f;
3781 char name[20];
3783 if (!XmLIsFolder(w))
3785 XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder");
3786 return 0;
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;
3799 void
3800 XmLFolderSetActiveTab(Widget w,
3801 int position,
3802 Boolean notify)
3804 XmLFolderWidget f;
3806 if (!XmLIsFolder(w))
3808 XmLWarning(w, "SetActiveTab() - widget not a XmLFolder");
3809 return;
3811 f = (XmLFolderWidget)w;
3812 if (position < 0 || position >= f->folder.tabCount)
3814 XmLWarning(w, "SetActiveTab() - invalid position");
3815 return;
3817 SetActiveTab(f, f->folder.tabs[position], 0, notify);