UNIXworkcode

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