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