UNIXworkcode

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * In addition, as a special exception to the GNU GPL, the copyright holders * give permission to link the code of this program with the Motif and Open * Motif libraries (or with modified versions of these that use the same * license), and distribute linked combinations including the two. You * must obey the GNU General Public License in all respects for all of * the code used other than linking with Motif/Open Motif. If you modify * this file, you may extend this exception to your version of the file, * but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. * * ***** END LICENSE BLOCK ***** */ #include "FolderP.h" #include <X11/StringDefs.h> #include <Xm/DrawnB.h> #include <Xm/Label.h> #include <Xm/Form.h> #include <stdio.h> #include <stdlib.h> #ifdef SUNOS4 int fprintf(FILE *, char *, ...); #endif /* Create and Destroy */ static void ClassInitialize(); static void Initialize(Widget req, Widget newW, ArgList args, Cardinal *nargs); static void Destroy(Widget w); /* Geometry, Drawing, Entry and Picking */ static void Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attr); static void Redisplay(Widget w, XExposeEvent *event, Region region); static void Layout(XmLFolderWidget f, int resizeIfNeeded); static void LayoutTopBottom(XmLFolderWidget f, int resizeIfNeeded); static void LayoutLeftRight(XmLFolderWidget f, int resizeIfNeeded); static void Resize(Widget w); static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *); static void ChangeManaged(Widget w); static void ConstraintInitialize(Widget, Widget w, ArgList args, Cardinal *nargs); static void ConstraintDestroy(Widget w); static void SetActiveTab(XmLFolderWidget f, Widget w, XEvent *event, Boolean notify); static void DrawTabPixmap(XmLFolderWidget f, Widget tab, int active); static void DrawManagerShadowLeftRight(XmLFolderWidget f, XRectangle *rect); static void DrawManagerShadowTopBottom(XmLFolderWidget f, XRectangle *rect); static void DrawTabHighlight(XmLFolderWidget f, Widget w); static void SetTabPlacement(XmLFolderWidget f, Widget tab); static void GetTabRect(XmLFolderWidget f, Widget tab, XRectangle *rect, int includeShadow); static void DrawTabShadowArcTopBottom(XmLFolderWidget f, Widget w); static void DrawTabShadowArcLeftRight(XmLFolderWidget f, Widget w); static void DrawTabShadowLineTopBottom(XmLFolderWidget f, Widget w); static void DrawTabShadowLineLeftRight(XmLFolderWidget f, Widget w); static void DrawTabShadowNoneTopBottom(XmLFolderWidget f, Widget w); static void DrawTabShadowNoneLeftRight(XmLFolderWidget f, Widget w); static void SetGC(XmLFolderWidget f, int type); /* Getting and Setting Values */ static Boolean SetValues(Widget curW, Widget reqW, Widget newW, ArgList args, Cardinal *nargs); static Boolean ConstraintSetValues(Widget curW, Widget, Widget newW, ArgList, Cardinal *); static void CopyRenderTable(XmLFolderWidget f); static Boolean CvtStringToCornerStyle(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToFolderResizePolicy(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToTabPlacement(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); /* Utility */ static void GetCoreBackground(Widget w, int, XrmValue *value); static void GetDefaultTabWidgetClass(Widget w, int, XrmValue *value); static void GetManagerForeground(Widget w, int, XrmValue *value); static Boolean ServerDrawsArcsLarge(Display *dpy, int debug); static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value); /* Actions, Callbacks and Handlers */ static void Activate(Widget w, XEvent *event, String *, Cardinal *); static void PrimActivate(Widget w, XtPointer, XtPointer); static void PrimFocusIn(Widget w, XEvent *event, String *, Cardinal *); static void PrimFocusOut(Widget w, XEvent *event, String *, Cardinal *); static XtActionsRec actions[] = { { "XmLFolderActivate", Activate }, { "XmLFolderPrimFocusIn", PrimFocusIn }, { "XmLFolderPrimFocusOut", PrimFocusOut }, }; #define MAX_TAB_ROWS 64 #define GC_SHADOWBOT 0 #define GC_SHADOWTOP 1 #define GC_BLANK 2 #define GC_UNSET 3 /* Folder Translations */ static char translations[] = "<Btn1Down>: XmLFolderActivate()\n\ <EnterWindow>: ManagerEnter()\n\ <LeaveWindow>: ManagerLeave()\n\ <FocusOut>: ManagerFocusOut()\n\ <FocusIn>: ManagerFocusIn()"; /* Primitive Child Translations */ static char primTranslations[] = "<FocusIn>: XmLFolderPrimFocusIn() PrimitiveFocusIn()\n\ <FocusOut>: XmLFolderPrimFocusOut() PrimitiveFocusOut()"; static XtResource resources[] = { /* Folder Resources */ { XmNtabWidgetClass, XmCTabWidgetClass, XmRWidgetClass, sizeof(WidgetClass), XtOffset(XmLFolderWidget, folder.tabWidgetClass), XmRCallProc, (XtPointer)GetDefaultTabWidgetClass, }, { XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLFolderWidget, folder.activateCallback), XmRImmediate, (XtPointer)0, }, { XmNactiveTab, XmCActiveTab, XmRInt, sizeof(int), XtOffset(XmLFolderWidget, folder.activeTab), XmRImmediate, (XtPointer)-1, }, { XmNautoSelect, XmCAutoSelect, XmRBoolean, sizeof(Boolean), XtOffset(XmLFolderWidget, folder.autoSelect), XmRImmediate, (XtPointer)True, }, { XmNblankBackground, XmCBlankBackground, XmRPixel, sizeof(Pixel), XtOffset(XmLFolderWidget, folder.blankBg), XmRCallProc, (XtPointer)GetCoreBackground, }, { XmNblankBackgroundPixmap, XmCBlankBackgroundPixmap, XmRManForegroundPixmap, sizeof(Pixmap), XtOffset(XmLFolderWidget, folder.blankPix), XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP, }, { XmNcornerDimension, XmCCornerDimension, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.cornerDimension), XmRImmediate, (XtPointer)2, }, { XmNcornerStyle, XmCCornerStyle, XmRCornerStyle, sizeof(unsigned char), XtOffset(XmLFolderWidget, folder.cornerStyle), XmRImmediate, (XtPointer)XmCORNER_ARC, }, { "pri.vate","Pri.vate",XmRBoolean, sizeof(Boolean), XtOffset(XmLFolderWidget, folder.check_set_render_table), XmRImmediate, (XtPointer) False }, { XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), XtOffset(XmLFolderWidget, folder.renderTable), XmRCallProc, (XtPointer)CheckSetRenderTable, }, { XmNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable), XtOffset(XmLFolderWidget, folder.renderTable), XmRCallProc, (XtPointer)CheckSetRenderTable, }, { XmNhighlightThickness, XmCHighlightThickness, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.highlightThickness), XmRImmediate, (XtPointer)2, }, { XmNinactiveBackground, XmCInactiveBackground, XmRPixel, sizeof(Pixel), XtOffset(XmLFolderWidget, folder.inactiveBg), XmRCallProc, (XtPointer)GetCoreBackground, }, { XmNinactiveForeground, XmCInactiveForeground, XmRPixel, sizeof(Pixel), XtOffset(XmLFolderWidget, folder.inactiveFg), XmRCallProc, (XtPointer)GetManagerForeground, }, { XmNmarginHeight, XmCMarginHeight, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.marginHeight), XmRImmediate, (XtPointer)0, }, { XmNmarginWidth, XmCMarginWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.marginWidth), XmRImmediate, (XtPointer)0, }, { XmNminTabWidth, XmCminTabWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.minTabWidth), XmRImmediate, (XtPointer)0, }, { XmNmaxTabWidth, XmCmaxTabWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.maxTabWidth), XmRImmediate, (XtPointer)100, }, { XmNpixmapMargin, XmCPixmapMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.pixmapMargin), XmRImmediate, (XtPointer)2, }, { XmNresizePolicy, XmCFolderResizePolicy, XmRFolderResizePolicy, sizeof(unsigned char), XtOffset(XmLFolderWidget, folder.resizePolicy), XmRImmediate, (XtPointer)XmRESIZE_STATIC, }, { XmNrotateWhenLeftRight, XmCRotateWhenLeftRight, XmRBoolean, sizeof(Boolean), XtOffset(XmLFolderWidget, folder.allowRotate), XmRImmediate, (XtPointer)True, }, { XmNspacing, XmCSpacing, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.spacing), XmRImmediate, (XtPointer)0, }, { XmNtabBarHeight, XmCTabBarHeight, XmRDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, folder.tabBarHeight), XmRImmediate, (XtPointer)0, }, { XmNtabCount, XmCTabCount, XmRInt, sizeof(int), XtOffset(XmLFolderWidget, folder.tabCount), XmRImmediate, (XtPointer)0, }, { XmNtabPlacement, XmCTabPlacement, XmRTabPlacement, sizeof(unsigned char), XtOffset(XmLFolderWidget, folder.tabPlacement), XmRImmediate, (XtPointer)XmFOLDER_TOP, }, { XmNtabsPerRow, XmCTabsPerRow, XmRInt, sizeof(int), XtOffset(XmLFolderWidget, folder.tabsPerRow), XmRImmediate, (XtPointer)0, }, { XmNtabWidgetList, XmCReadOnly, XmRPointer, sizeof(XtPointer), XtOffset(XmLFolderWidget, folder.tabs), XmRImmediate, (XtPointer)0, }, { XmNtabTranslations, XmCTranslations, XmRTranslationTable, sizeof(XtTranslations), XtOffset(XmLFolderWidget, folder.primTrans), XmRString, (XtPointer)primTranslations, }, { XmNdebugLevel, XmCDebugLevel, XmRInt, sizeof(int), XtOffset(XmLFolderWidget, folder.debugLevel), XmRImmediate, (XtPointer)0, }, /* Overridden inherited resources */ { XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffset(XmLFolderWidget, manager.shadow_thickness), XmRImmediate, (XtPointer)2, }, }; static XtResource constraint_resources[] = { /* Folder Constraint Resources */ { XmNtabFreePixmaps, XmCTabFreePixmaps, XmRBoolean, sizeof(Boolean), XtOffset(XmLFolderConstraintPtr, folder.freePix), XmRImmediate, (XtPointer)False, }, { XmNtabInactivePixmap, XmCTabInactivePixmap, XmRPrimForegroundPixmap, sizeof(Pixmap), XtOffset(XmLFolderConstraintPtr, folder.inactPix), XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP, }, { XmNtabManagedName, XmCTabManagedName, XmRString, sizeof(char *), XtOffset(XmLFolderConstraintPtr, folder.managedName), XmRImmediate, (XtPointer)0, }, { XmNtabManagedWidget, XmCTabManagedWidget, XmRWidget, sizeof(Widget), XtOffset(XmLFolderConstraintPtr, folder.managedW), XmRImmediate, (XtPointer)0, }, { XmNtabPixmap, XmCTabPixmap, XmRPrimForegroundPixmap, sizeof(Pixmap), XtOffset(XmLFolderConstraintPtr, folder.pix), XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP, }, }; XmLFolderClassRec xmlFolderClassRec = { { /* core_class */ (WidgetClass)&xmManagerClassRec, /* superclass */ "XmLFolder", /* class_name */ sizeof(XmLFolderRec), /* widget_size */ ClassInitialize, /* class_init */ 0, /* class_part_init */ FALSE, /* class_inited */ (XtInitProc)Initialize, /* initialize */ 0, /* initialize_hook */ (XtRealizeProc)Realize, /* realize */ (XtActionList)actions, /* actions */ (Cardinal)XtNumber(actions), /* num_actions */ (XtResource *)resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMultiple, /* compress_exposure */ TRUE, /* compress_enterlv */ TRUE, /* visible_interest */ (XtWidgetProc)Destroy, /* destroy */ (XtWidgetProc)Resize, /* resize */ (XtExposeProc)Redisplay, /* expose */ (XtSetValuesFunc)SetValues, /* set_values */ 0, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ 0, /* get_values_hook */ 0, /* accept_focus */ XtVersion, /* version */ 0, /* callback_private */ translations, /* tm_table */ 0, /* query_geometry */ 0, /* display_acceleratr */ 0, /* extension */ }, { /* composite_class */ (XtGeometryHandler)GeometryManager, /* geometry_manager */ (XtWidgetProc)ChangeManaged, /* change_managed */ XtInheritInsertChild, /* insert_child */ XtInheritDeleteChild, /* delete_child */ 0, /* extension */ }, { /* constraint_class */ (XtResource *)constraint_resources, /* subresources */ XtNumber(constraint_resources), /* subresource_count */ sizeof(XmLFolderConstraintRec), /* constraint_size */ (XtInitProc)ConstraintInitialize, /* initialize */ (XtWidgetProc)ConstraintDestroy, /* destroy */ (XtSetValuesFunc)ConstraintSetValues, /* set_values */ 0, /* extension */ }, { /* manager_class */ XtInheritTranslations, /* translations */ 0, /* syn resources */ 0, /* num syn_resources */ 0, /* get_cont_resources */ 0, /* num_get_cont_resrc */ XmInheritParentProcess, /* parent_process */ 0, /* extension */ }, { /* folder_class */ 0, /* unused */ } }; WidgetClass xmlFolderWidgetClass = (WidgetClass)&xmlFolderClassRec; static void CheckSetRenderTable(Widget wid, int offset, XrmValue *value) { XmLFolderWidget lw = (XmLFolderWidget)wid; /* Check if been here before */ if (lw->folder.check_set_render_table) value->addr = NULL; else { lw->folder.check_set_render_table = True; value->addr = (char*)&(lw->folder.renderTable); } } /* Create and Destroy */ static void ClassInitialize(void) { XmLInitialize(); XtSetTypeConverter(XmRString, XmRCornerStyle, CvtStringToCornerStyle, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRFolderResizePolicy, CvtStringToFolderResizePolicy, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRTabPlacement, CvtStringToTabPlacement, 0, 0, XtCacheNone, 0); } static void Initialize(Widget req, Widget newW, ArgList args, Cardinal *narg) { Display *dpy; /* Window root;*/ XmLFolderWidget f; f = (XmLFolderWidget)newW; dpy = XtDisplay((Widget)f); if (f->core.width == 0) f->core.width = 100; if (f->core.height == 0) f->core.height = 100; f->folder.gc = 0; f->folder.tabAllocCount = 32; f->folder.tabs = (Widget *)malloc(sizeof(Widget) * 32); f->folder.tabHeight = 0; f->folder.tabWidth = 0; f->folder.activeW = 0; f->folder.focusW = 0; f->folder.allowLayout = 1; f->folder.activeRow = -1; CopyRenderTable(f); if (f->folder.tabBarHeight) { XmLWarning((Widget)f, "Initialize() - can''t set tabBarHeight"); f->folder.tabBarHeight = 0; } if (f->folder.tabCount) { XmLWarning((Widget)f, "Initialize() - can''t set tabCount"); f->folder.tabCount = 0; } if (f->folder.activeTab != -1) { XmLWarning((Widget)f, "Initialize() - can''t set activeTab"); f->folder.activeTab = -1; } if (f->folder.cornerDimension < 1) { XmLWarning((Widget)f, "Initialize() - cornerDimension can''t be < 1"); f->folder.cornerDimension = 1; } f->folder.serverDrawsArcsLarge = ServerDrawsArcsLarge(dpy, f->folder.debugLevel); if (f->folder.minTabWidth <= 0) { /* a quick hack to determine the minimum tab width - enough to show at least one character of the tab string */ XmString st = XmStringCreateSimple("W"); f->folder.minTabWidth = XmStringWidth(f->folder.renderTable, st); XmStringFree(st); } } static void Destroy(Widget w) { XmLFolderWidget f; Display *dpy; f = (XmLFolderWidget)w; dpy = XtDisplay(w); if (f->folder.debugLevel) fprintf(stderr, "Folder destroy: \n"); if (f->folder.tabs) free((char *)f->folder.tabs); if (f->folder.gc) XFreeGC(dpy, f->folder.gc); XmRenderTableFree(f->folder.renderTable); } /* Geometry, Drawing, Entry and Picking */ static void Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attr) { XmLFolderWidget f; Display *dpy; WidgetClass superClass; XtRealizeProc realize; XGCValues values; XtGCMask mask; f = (XmLFolderWidget)w; dpy = XtDisplay(f); superClass = xmlFolderWidgetClass->core_class.superclass; realize = superClass->core_class.realize; (*realize)(w, valueMask, attr); if (!f->folder.gc) { values.foreground = f->manager.foreground; mask = GCForeground; f->folder.gc = XCreateGC(dpy, XtWindow(f), mask, &values); if (f->folder.autoSelect == True && f->folder.tabCount) XmLFolderSetActiveTab(w, 0, False); } } static void Redisplay(Widget w, XExposeEvent *event, Region region) { Display *dpy; Window win; XmLFolderWidget f; XmLFolderConstraintRec *fc; XRectangle eRect, rRect, rect; /* XSegment *topSeg, *botSeg; */ /* int tCount, bCount; */ Widget tab; int i; f = (XmLFolderWidget)w; if (!XtIsRealized(w)) return; if (!f->core.visible) return; dpy = XtDisplay(f); win = XtWindow(f); if (event) { eRect.x = event->x; eRect.y = event->y; eRect.width = event->width; eRect.height = event->height; if (f->folder.debugLevel > 1) fprintf(stderr, "XmLFolder: Redisplay x %d y %d w %d h %d\n", event->x, event->y, event->width, event->height); } else { eRect.x = 0; eRect.y = 0; eRect.width = f->core.width; eRect.height = f->core.height; } if (!eRect.width || !eRect.height) return; if (f->folder.tabPlacement == XmFOLDER_TOP) { rRect.x = 0; rRect.y = f->folder.tabHeight; rRect.width = f->core.width; rRect.height = f->core.height - f->folder.tabHeight; } else if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { rRect.x = 0; rRect.y = 0; rRect.width = f->core.width; rRect.height = f->core.height - f->folder.tabHeight; } if (f->folder.tabPlacement == XmFOLDER_LEFT) { rRect.x = f->folder.tabWidth; rRect.y = 0; rRect.width = f->core.width - f->folder.tabWidth; rRect.height = f->core.height; } if (f->folder.tabPlacement == XmFOLDER_RIGHT) { rRect.x = 0; rRect.y = 0; rRect.width = f->core.width - f->folder.tabWidth; rRect.height = f->core.height; } if (XmLRectIntersect(&eRect, &rRect) != XmLRectOutside) { if (f->folder.tabPlacement == XmFOLDER_TOP || f->folder.tabPlacement == XmFOLDER_BOTTOM) DrawManagerShadowTopBottom(f, &rRect); else DrawManagerShadowLeftRight(f, &rRect); } if (!f->folder.tabCount) return; rRect.x = 0; rRect.y = 0; rRect.width = 0; rRect.height = 0; /* Draw tabs */ for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; fc = (XmLFolderConstraintRec *)(tab->core.constraints); GetTabRect(f, tab, &rRect, 0); /* include spacing in intersect test */ rect = rRect; if (f->folder.tabPlacement == XmFOLDER_TOP || f->folder.tabPlacement == XmFOLDER_BOTTOM) rect.width += f->folder.spacing; else rect.height += f->folder.spacing; /* include indent in intersect test */ if (f->folder.tabsPerRow) { if (rRect.x == 2) rect.x = 0; if (rRect.y == 2) rect.y = 0; if (rRect.x + rRect.width == f->core.width - 2) rect.width += 2; if (rRect.y + rRect.height == f->core.height - 2) rect.height += 2; } if (XmLRectIntersect(&eRect, &rect) == XmLRectOutside) continue; if (event && XRectInRegion(region, rect.x, rect.y, rect.width, rect.height) == RectangleOut) continue; if (f->folder.debugLevel > 1) fprintf(stderr, "XmLFolder: Redisplay tab for widget %d\n", i); if (tab == f->folder.activeW) { XtVaSetValues(tab, XmNbackground, f->core.background_pixel, XmNforeground, f->manager.foreground, NULL); } else { XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); XFillRectangle(dpy, win, f->folder.gc, rRect.x, rRect.y, rRect.width, rRect.height); XtVaSetValues(tab, XmNbackground, f->folder.inactiveBg, XmNforeground, f->folder.inactiveFg, NULL); } if (f->folder.tabPlacement == XmFOLDER_TOP || f->folder.tabPlacement == XmFOLDER_BOTTOM) { if (f->folder.cornerStyle == XmCORNER_LINE) DrawTabShadowLineTopBottom(f, tab); else if (f->folder.cornerStyle == XmCORNER_ARC) DrawTabShadowArcTopBottom(f, tab); else DrawTabShadowNoneTopBottom(f, tab); } else { if (f->folder.cornerStyle == XmCORNER_LINE) DrawTabShadowLineLeftRight(f, tab); else if (f->folder.cornerStyle == XmCORNER_ARC) DrawTabShadowArcLeftRight(f, tab); else DrawTabShadowNoneLeftRight(f, tab); } if (f->folder.focusW == tab) DrawTabHighlight(f, tab); if (tab == f->folder.activeW && fc->folder.pix != XmUNSPECIFIED_PIXMAP && (fc->folder.maxPixWidth || fc->folder.maxPixHeight)) DrawTabPixmap(f, tab, 1); else if (tab != f->folder.activeW && fc->folder.inactPix != XmUNSPECIFIED_PIXMAP && (fc->folder.maxPixWidth || fc->folder.maxPixHeight)) DrawTabPixmap(f, tab, 0); SetGC(f, GC_BLANK); /* draw indent */ if (f->folder.tabsPerRow) { if (rRect.x == 2) { rect = rRect; rect.x = 0; rect.width = 2; XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); } if (rRect.y == 2) { rect = rRect; rect.y = 0; rect.height = 2; XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); } if (rRect.x + rRect.width == f->core.width - 2) { rect = rRect; rect.x = f->core.width - 2; rect.width = 2; XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); } if (rRect.y + rRect.height == f->core.height - 2) { rect = rRect; rect.y = f->core.height - 2; rect.height = 2; XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); } } if (f->folder.spacing) { if (f->folder.tabPlacement == XmFOLDER_TOP || f->folder.tabPlacement == XmFOLDER_BOTTOM) XFillRectangle(dpy, win, f->folder.gc, rRect.x + rRect.width, rRect.y, f->folder.spacing, rRect.height); else XFillRectangle(dpy, win, f->folder.gc, rRect.x, rRect.y + rRect.height, rRect.width, f->folder.spacing); } SetGC(f, GC_UNSET); } /* Draw empty area */ if (!f->folder.tabsPerRow) { if (f->folder.tabPlacement == XmFOLDER_TOP || f->folder.tabPlacement == XmFOLDER_BOTTOM) { rRect.x += rRect.width + f->folder.spacing; if ((int)f->core.width > rRect.x) { if (f->folder.tabPlacement == XmFOLDER_TOP) rRect.y = 0; else rRect.y = f->core.height - f->folder.tabHeight; rRect.width = f->core.width - rRect.x; rRect.height = f->folder.tabHeight; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rRect.x, rRect.y, rRect.width, rRect.height); SetGC(f, GC_UNSET); } } else { rRect.y += rRect.height + f->folder.spacing; if ((int)f->core.height > rRect.y) { if (f->folder.tabPlacement == XmFOLDER_LEFT) rRect.x = 0; else rRect.x = f->core.width - f->folder.tabWidth; rRect.width = f->folder.tabWidth; rRect.height = f->core.height - rRect.y; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rRect.x, rRect.y, rRect.width, rRect.height); SetGC(f, GC_UNSET); } } } } static void Layout(XmLFolderWidget f, int resizeIfNeeded) { /* Window win;*/ if (!f->folder.allowLayout) return; f->folder.allowLayout = 0; if (f->folder.tabPlacement == XmFOLDER_LEFT || f->folder.tabPlacement == XmFOLDER_RIGHT) LayoutLeftRight(f, resizeIfNeeded); else LayoutTopBottom(f, resizeIfNeeded); if (XtIsRealized((Widget)f) && f->core.visible) XClearArea(XtDisplay(f), XtWindow(f), 0, 0, 0, 0, True); f->folder.allowLayout = 1; } static void LayoutTopBottom(XmLFolderWidget f, int resizeIfNeeded) { Display *dpy; Window root; int i, tabNum, x, y, w, h, pad1, pad2; int rowNum, numRows, rowHeight, rowX, rowY; WidgetList children; Widget tab, child; XmLFolderConstraintRec *fc; XtGeometryResult result; unsigned int inactPixHeight, pixHeight; unsigned int inactPixWidth, pixWidth; unsigned int pixBW, pixDepth; Dimension height, minHeight; Dimension width, minWidth, borderWidth; Dimension co; int st, ht; int tabFit = 0, tgtTabWidth = 0; int tabPaddingWidth, tailSpace = 0; Boolean map, isManaged; struct { int width, height, numTabs, y; } rows[MAX_TAB_ROWS]; dpy = XtDisplay(f); children = f->composite.children; st = f->manager.shadow_thickness; ht = f->folder.highlightThickness; /* calculate corner offset */ if (f->folder.cornerStyle == XmCORNER_LINE) co = (Dimension)((double)f->folder.cornerDimension * .5 + .99); else if (f->folder.cornerStyle == XmCORNER_ARC) co = (Dimension)((double)f->folder.cornerDimension * .3 + .99); else co = 0; /* caculate tabHeight, minWidth, minHeight, row y positions, */ /* row heights and tab pixmap dimensions */ rowX = 0; rowY = 0; rowHeight = 0; rowNum = 0; tabNum = 0; minWidth = 0; if (f->folder.tabCount && f->folder.resizePolicy == XmRESIZE_PACK) { int maxTabWidth = f->folder.maxTabWidth; int tabEffCount = 0; for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; tabEffCount++; } tabPaddingWidth = (st + co + f->folder.marginWidth + ht + f->folder.tabs[0]->core.border_width) * 2; if (maxTabWidth * tabEffCount > f->core.width) { tgtTabWidth = f->core.width/tabEffCount - tabPaddingWidth; tailSpace = f->core.width % tabEffCount; tabFit = 1; /* if tabs get too small */ if (tgtTabWidth < f->folder.minTabWidth) { tgtTabWidth = f->folder.minTabWidth; tabFit = 0; } } else { tgtTabWidth = maxTabWidth - tabPaddingWidth; tabFit = 0; } } for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; if (f->folder.resizePolicy == XmRESIZE_PACK) { if (tabFit) { XtVaSetValues(tab, XmNwidth, tailSpace? tgtTabWidth+1: tgtTabWidth, NULL); if (tailSpace) tailSpace--; } else { XtVaSetValues(tab, XmNwidth, tgtTabWidth, NULL); } } fc = (XmLFolderConstraintRec *)(tab->core.constraints); /* check for start of a new row */ fc->folder.firstInRow = False; if (!tabNum) fc->folder.firstInRow = True; if (f->folder.tabsPerRow && tabNum == f->folder.tabsPerRow) { fc->folder.firstInRow = True; /* store prev row values and start next row */ if (rowX) rowX -= f->folder.spacing; rows[rowNum].y = rowY; rows[rowNum].width = rowX; rows[rowNum].height = rowHeight; rows[rowNum].numTabs = tabNum; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "row %d: y %d w %d h %d numTabs %d\n", rowNum, rowY, rowX, rowHeight, tabNum); } rowY += rowHeight; rowHeight = 0; if (rowX > (int)minWidth) minWidth = rowX; rowX = 0; tabNum = 0; rowNum++; if (rowNum == MAX_TAB_ROWS - 1) { XmLWarning((Widget)f, "Layout ERROR - too many rows\n"); return; } } /* make sure row height > maximum tab height */ height = co + st + tab->core.height + tab->core.border_width * 2 + f->folder.marginHeight * 2 + ht * 2; if ((int)height > rowHeight) rowHeight = height; /* calc pixmap dimensions/maximum pixmap height */ fc->folder.pixWidth = 0; fc->folder.pixHeight = 0; fc->folder.inactPixWidth = 0; fc->folder.inactPixHeight = 0; fc->folder.maxPixWidth = 0; fc->folder.maxPixHeight = 0; if (fc->folder.pix != XmUNSPECIFIED_PIXMAP) { XGetGeometry(dpy, fc->folder.pix, &root, &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth); fc->folder.pixWidth = pixWidth; fc->folder.maxPixWidth = pixWidth; fc->folder.pixHeight = pixHeight; fc->folder.maxPixHeight = pixHeight; height = co + st + pixHeight + f->folder.marginHeight * 2 + ht * 2; if ((int)height > rowHeight) rowHeight = height; } if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP) { XGetGeometry(dpy, fc->folder.inactPix, &root, &x, &y, &inactPixWidth, &inactPixHeight, &pixBW, &pixDepth); fc->folder.inactPixWidth = inactPixWidth; if (inactPixWidth > fc->folder.maxPixWidth) fc->folder.maxPixWidth = inactPixWidth; fc->folder.inactPixHeight = inactPixHeight; if (inactPixHeight > fc->folder.maxPixHeight) fc->folder.maxPixHeight = inactPixHeight; height = co + st + inactPixHeight + f->folder.marginHeight * 2 + ht * 2; if ((int)height > rowHeight) rowHeight = height; } /* increment rowX to move on to the next tab */ rowX += st * 2 + co * 2 + f->folder.marginWidth * 2 + ht * 2 + XtWidth(tab) + tab->core.border_width * 2; if (fc->folder.maxPixWidth) rowX += fc->folder.maxPixWidth + f->folder.pixmapMargin; rowX += f->folder.spacing; tabNum++; fc->folder.row = rowNum; } /* complete calcuations for last row */ if (rowX) rowX -= f->folder.spacing; rows[rowNum].y = rowY; rows[rowNum].width = rowX; rows[rowNum].height = rowHeight; rows[rowNum].numTabs = tabNum; numRows = rowNum + 1; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "row %d: y %d w %d h %d numTabs %d\n", rowNum, rowY, rowX, rowHeight, tabNum); } f->folder.tabHeight = rowY + rowHeight; f->folder.tabBarHeight = f->folder.tabHeight; minHeight = f->folder.tabHeight; if ((int)minWidth < rowX) minWidth = rowX; /* add space for indent of upper rows */ if (f->folder.tabsPerRow && minWidth) minWidth += 4; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "tab bar minimum w %d h %d\n", (int)minWidth, (int)minHeight); } /* calculate width and height of non-tab children ensure */ /* minWidth > width and minHeight > height */ for (i = 0; i < f->composite.num_children; i++) { child = children[i]; if (XtIsSubclass(child, xmPrimitiveWidgetClass)) continue; height = XtHeight(child) + f->folder.tabHeight + st * 2; if (XtIsWidget(child)) height += child->core.border_width * 2; if (height > minHeight) minHeight = height; width = XtWidth(child) + st * 2; if (XtIsWidget(child)) width += child->core.border_width * 2; if (width > minWidth) minWidth = width; } if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "with non-tabs minimum w %d h %d\n", (int)minWidth, (int)minHeight); } /* Resize folder if needed */ if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE) { if (minWidth <= 0) minWidth = 1; if (minHeight <= 0) minHeight = 1; result = XtMakeResizeRequest((Widget)f, minWidth, minHeight, &width, &height); if (result == XtGeometryAlmost) XtMakeResizeRequest((Widget)f, width, height, NULL, NULL); } /* move active row to bottom */ tab = f->folder.activeW; if (tab) { fc = (XmLFolderConstraintRec *)(tab->core.constraints); rowNum = fc->folder.row; f->folder.activeRow = rowNum; rows[rowNum].y = f->folder.tabHeight - rows[rowNum].height; for (i = rowNum + 1; i < numRows; i++) rows[i].y -= rows[rowNum].height; } else f->folder.activeRow = -1; /* configure tab children */ for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; fc = (XmLFolderConstraintRec *)(tab->core.constraints); rowNum = fc->folder.row; /* calculate tab x */ if (fc->folder.firstInRow == True) { if (f->folder.tabsPerRow && rowNum != f->folder.activeRow) x = 2; else x = 0; } fc->folder.x = x; x += st + co + f->folder.marginWidth + ht; if (fc->folder.maxPixWidth) x += fc->folder.maxPixWidth + f->folder.pixmapMargin; /* calculate tab y and tab height */ fc->folder.height = rows[rowNum].height; if (f->folder.tabPlacement == XmFOLDER_TOP) { fc->folder.y = rows[rowNum].y; y = fc->folder.y + fc->folder.height - f->folder.marginHeight - ht - XtHeight(tab) - tab->core.border_width * 2; } else { fc->folder.y = f->core.height - rows[rowNum].y - rows[rowNum].height; y = fc->folder.y + f->folder.marginHeight + ht; } /* calculate tab padding */ pad1 = 0; pad2 = 0; w = f->core.width - rows[rowNum].width; if (rowNum != f->folder.activeRow) w -= 4; if (f->folder.tabsPerRow && w > 0) { pad1 = w / (rows[rowNum].numTabs * 2); pad2 = pad1; if (fc->folder.firstInRow == True) pad2 += w - (pad1 * rows[rowNum].numTabs * 2); } x += pad1; /* move tab widget into place */ XtMoveWidget(tab, x, y); /* calculate tab width and move to next tab */ x += pad2 + XtWidth(tab) + tab->core.border_width * 2 + ht + f->folder.marginWidth + co + st; fc->folder.width = x - fc->folder.x; x += f->folder.spacing; } /* configure non-tab children */ for (i = 0; i < f->composite.num_children; i++) { child = children[i]; if (XtIsSubclass(child, xmPrimitiveWidgetClass)) continue; if (f->folder.resizePolicy == XmRESIZE_NONE) continue; w = (int)f->core.width - st * 2; h = (int)f->core.height - (int)f->folder.tabHeight - st * 2; if (h <= 0 || w <= 0) continue; /* manager widgets will not configure correctly unless they */ /* are managed, so manage then unmapped if they are unmanaged */ isManaged = True; if (!XtIsManaged(child)) { XtVaGetValues(child, XmNmappedWhenManaged, &map, NULL); XtVaSetValues(child, XmNmappedWhenManaged, False, NULL); XtManageChild(child); isManaged = False; } x = st; if (f->folder.tabPlacement == XmFOLDER_TOP) y = f->folder.tabHeight + st; else y = st; width = w; height = h; borderWidth = 0; if (XtIsWidget(child)) borderWidth = child->core.border_width; XtConfigureWidget(child, x, y, width, height, borderWidth); if (isManaged == False) { XtUnmanageChild(child); XtVaSetValues(child, XmNmappedWhenManaged, map, NULL); } } } static void LayoutLeftRight(XmLFolderWidget f, int resizeIfNeeded) { Display *dpy; Window root; int i, tabNum, x, y, w, h, pad1, pad2; int rowNum, numRows, rowWidth, rowX, rowY; WidgetList children; Widget tab, child; XmLFolderConstraintRec *fc; XtGeometryResult result; unsigned int inactPixHeight, pixHeight; unsigned int inactPixWidth, pixWidth; unsigned int pixBW, pixDepth; Dimension height, minHeight; Dimension width, minWidth, borderWidth; Dimension co; int st, ht; Boolean map, isManaged; struct { int width, height, numTabs, x; } rows[MAX_TAB_ROWS]; dpy = XtDisplay(f); children = f->composite.children; st = f->manager.shadow_thickness; ht = f->folder.highlightThickness; /* calculate corner offset */ if (f->folder.cornerStyle == XmCORNER_LINE) co = (Dimension)((double)f->folder.cornerDimension * .5 + .99); else if (f->folder.cornerStyle == XmCORNER_ARC) co = (Dimension)((double)f->folder.cornerDimension * .3 + .99); else co = 0; /* caculate tabWidth, minWidth, minHeight, row x positions, */ /* row widths and tab pixmap dimensions */ rowX = 0; rowY = 0; rowWidth = 0; rowNum = 0; tabNum = 0; minHeight = 0; for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; fc = (XmLFolderConstraintRec *)(tab->core.constraints); /* check for start of a new row */ fc->folder.firstInRow = False; if (!tabNum) fc->folder.firstInRow = True; if (f->folder.tabsPerRow && tabNum == f->folder.tabsPerRow) { fc->folder.firstInRow = True; /* store prev row values and start next row */ if (rowY) rowY -= f->folder.spacing; rows[rowNum].x = rowX; rows[rowNum].height = rowY; rows[rowNum].width = rowWidth; rows[rowNum].numTabs = tabNum; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "row %d: x %d w %d h %d numTabs %d\n", rowNum, rowX, rowWidth, rowY, tabNum); } rowX += rowWidth; rowWidth = 0; if (rowY > (int)minHeight) minHeight = rowY; rowY = 0; tabNum = 0; rowNum++; if (rowNum == MAX_TAB_ROWS - 1) { XmLWarning((Widget)f, "Layout ERROR - too many rows\n"); return; } } /* make sure row width > maximum tab width */ width = co + st + tab->core.width + tab->core.border_width * 2 + f->folder.marginHeight * 2 + ht * 2; if ((int)width > rowWidth) rowWidth = width; /* calc pixmap dimensions/maximum pixmap width */ pixWidth = 0; pixHeight = 0; fc->folder.pixWidth = 0; fc->folder.pixHeight = 0; fc->folder.inactPixWidth = 0; fc->folder.inactPixHeight = 0; fc->folder.maxPixWidth = 0; fc->folder.maxPixHeight = 0; if (fc->folder.pix != XmUNSPECIFIED_PIXMAP) { XGetGeometry(dpy, fc->folder.pix, &root, &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth); fc->folder.pixWidth = pixWidth; fc->folder.maxPixWidth = pixWidth; fc->folder.pixHeight = pixHeight; fc->folder.maxPixHeight = pixHeight; width = co + st + pixWidth + f->folder.marginHeight * 2 + ht * 2; if ((int)width > rowWidth) rowWidth = width; } if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP) { XGetGeometry(dpy, fc->folder.inactPix, &root, &x, &y, &inactPixWidth, &inactPixHeight, &pixBW, &pixDepth); fc->folder.inactPixWidth = inactPixWidth; if (inactPixWidth > fc->folder.maxPixWidth) fc->folder.maxPixWidth = inactPixWidth; fc->folder.inactPixHeight = inactPixHeight; if (inactPixHeight > fc->folder.maxPixHeight) fc->folder.maxPixHeight = inactPixHeight; width = co + st + inactPixWidth + f->folder.marginHeight * 2 + ht * 2; if ((int)width > rowWidth) rowWidth = width; } /* increment rowY to move on to the next tab */ rowY += st * 2 + co * 2 + f->folder.marginWidth * 2 + ht * 2 + XtHeight(tab) + tab->core.border_width * 2; if (fc->folder.maxPixHeight) rowY += fc->folder.maxPixHeight + f->folder.pixmapMargin; rowY += f->folder.spacing; tabNum++; fc->folder.row = rowNum; } /* complete calcuations for last row */ if (rowY) rowY -= f->folder.spacing; rows[rowNum].x = rowX; rows[rowNum].height = rowY; rows[rowNum].width = rowWidth; rows[rowNum].numTabs = tabNum; numRows = rowNum + 1; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "row %d: x %d w %d h %d numTabs %d\n", rowNum, rowX, rowWidth, rowY, tabNum); } f->folder.tabWidth = rowX + rowWidth; f->folder.tabBarHeight = f->folder.tabWidth; minWidth = f->folder.tabWidth; if ((int)minHeight < rowY) minHeight = rowY; /* add space for indent of upper rows */ if (f->folder.tabsPerRow && minHeight) minHeight += 4; if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "tab bar minimum w %d h %d\n", (int)minWidth, (int)minHeight); } /* calculate width and height of non-tab children ensure */ /* minWidth > width and minHeight > height */ for (i = 0; i < f->composite.num_children; i++) { child = children[i]; if (XtIsSubclass(child, xmPrimitiveWidgetClass)) continue; height = XtHeight(child) + st * 2; if (XtIsWidget(child)) height += f->core.border_width * 2; if (height > minHeight) minHeight = height; width = XtWidth(child) + f->folder.tabWidth + st * 2; if (XtIsWidget(child)) width += f->core.border_width * 2; if (width > minWidth) minWidth = width; } if (f->folder.debugLevel) { fprintf(stderr, "XmLFolder: Layout: "); fprintf(stderr, "with non-tabs minimum w %d h %d\n", (int)minWidth, (int)minHeight); } /* Resize folder if needed */ if (resizeIfNeeded && f->folder.resizePolicy != XmRESIZE_NONE) { if (minWidth <= 0) minWidth = 1; if (minHeight <= 0) minHeight = 1; result = XtMakeResizeRequest((Widget)f, minWidth, minHeight, &width, &height); if (result == XtGeometryAlmost) XtMakeResizeRequest((Widget)f, width, height, NULL, NULL); } /* move active row to bottom */ tab = f->folder.activeW; if (tab) { fc = (XmLFolderConstraintRec *)(tab->core.constraints); rowNum = fc->folder.row; f->folder.activeRow = rowNum; rows[rowNum].x = f->folder.tabWidth - rows[rowNum].width; for (i = rowNum + 1; i < numRows; i++) rows[i].x -= rows[rowNum].width; } else f->folder.activeRow = -1; /* configure tab children */ for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab)) continue; fc = (XmLFolderConstraintRec *)(tab->core.constraints); rowNum = fc->folder.row; /* calculate tab x */ if (fc->folder.firstInRow == True) { if (f->folder.tabsPerRow && rowNum != f->folder.activeRow) y = 2; else y = 0; } fc->folder.y = y; y += st + co + f->folder.marginWidth + ht; if (fc->folder.maxPixHeight) y += fc->folder.maxPixHeight + f->folder.pixmapMargin; /* calculate tab x and tab width */ fc->folder.width = rows[rowNum].width; if (f->folder.tabPlacement == XmFOLDER_LEFT) { fc->folder.x = rows[rowNum].x; x = fc->folder.x + fc->folder.width - f->folder.marginHeight - ht - XtWidth(tab) - tab->core.border_width * 2; } else { fc->folder.x = f->core.width - rows[rowNum].x - rows[rowNum].width; x = fc->folder.x + f->folder.marginHeight + ht; } /* calculate tab padding */ pad1 = 0; pad2 = 0; h = f->core.height - rows[rowNum].height; if (rowNum != f->folder.activeRow) h -= 4; if (f->folder.tabsPerRow && h > 0) { pad1 = h / (rows[rowNum].numTabs * 2); pad2 = pad1; if (fc->folder.firstInRow == True) pad2 += h - (pad1 * rows[rowNum].numTabs * 2); } y += pad1; /* move tab widget into place */ XtMoveWidget(tab, x, y); /* calculate tab height and move to next tab */ y += pad2 + XtHeight(tab) + tab->core.border_width * 2 + ht + f->folder.marginWidth + co + st; fc->folder.height = y - fc->folder.y; y += f->folder.spacing; } /* configure non-tab children */ for (i = 0; i < f->composite.num_children; i++) { child = children[i]; if (XtIsSubclass(child, xmPrimitiveWidgetClass)) continue; if (f->folder.resizePolicy == XmRESIZE_NONE) continue; w = (int)f->core.width - (int)f->folder.tabWidth - st * 2; h = (int)f->core.height - st * 2; if (h <= 0 || w <= 0) continue; /* manager widgets will not configure correctly unless they */ /* are managed, so manage then unmapped if they are unmanaged */ isManaged = True; if (!XtIsManaged(child)) { XtVaGetValues(child, XmNmappedWhenManaged, &map, NULL); XtVaSetValues(child, XmNmappedWhenManaged, False, NULL); XtManageChild(child); isManaged = False; } y = st; if (f->folder.tabPlacement == XmFOLDER_LEFT) x = f->folder.tabWidth + st; else x = st; width = w; height = h; borderWidth = 0; if (XtIsWidget(child)) borderWidth = child->core.border_width; XtConfigureWidget(child, x, y, width, height, borderWidth); if (isManaged == False) { XtUnmanageChild(child); XtVaSetValues(child, XmNmappedWhenManaged, map, NULL); } } } static void Resize(Widget w) { XmLFolderWidget f; f = (XmLFolderWidget)w; Layout(f, 0); } static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *allow) { XmLFolderWidget f; f = (XmLFolderWidget)XtParent(w); if (f->folder.resizePolicy != XmRESIZE_STATIC || XtIsSubclass(w, xmPrimitiveWidgetClass)) { if (request->request_mode & CWWidth) w->core.width = request->width; if (request->request_mode & CWHeight) w->core.height = request->height; if (request->request_mode & CWX) w->core.x = request->x; if (request->request_mode & CWY) w->core.y = request->y; if (request->request_mode & CWBorderWidth) w->core.border_width = request->border_width; Layout(f, 1); return XtGeometryYes; } return XtGeometryNo; } static void ChangeManaged(Widget w) { XmLFolderWidget f; f = (XmLFolderWidget)w; Layout(f, 1); _XmNavigChangeManaged(w); } static void ConstraintInitialize(Widget req, Widget w, ArgList args, Cardinal *narg) { XmLFolderWidget f; XmLFolderConstraintRec *fc; if (!XtIsRectObj(w)) return; f = (XmLFolderWidget)XtParent(w); if (f->folder.debugLevel) fprintf(stderr, "XmLFolder: Constraint Init\n"); fc = (XmLFolderConstraintRec *)(w->core.constraints); fc->folder.x = 0; fc->folder.y = 0; fc->folder.width = 0; fc->folder.height = 0; fc->folder.maxPixWidth = 0; fc->folder.maxPixHeight = 0; fc->folder.row = -1; fc->folder.firstInRow = False; if (fc->folder.managedName) fc->folder.managedName = (char *)strdup(fc->folder.managedName); if (XtIsSubclass(w, xmPrimitiveWidgetClass)) { XtOverrideTranslations(w, f->folder.primTrans); XtAddCallback(w, XmNactivateCallback, PrimActivate, 0); XtVaSetValues(w, XmNhighlightThickness, 0, XmNshadowThickness, 0, NULL); if (XtIsSubclass(w, xmLabelWidgetClass)) XtVaSetValues(w, XmNfillOnArm, False, NULL); /* add child to tabs list */ if (f->folder.tabAllocCount < f->folder.tabCount + 1) { f->folder.tabAllocCount *= 2; f->folder.tabs = (Widget *)realloc((char *)f->folder.tabs, sizeof(Widget) * f->folder.tabAllocCount); } f->folder.tabs[f->folder.tabCount++] = w; } if (XmIsDrawnButton(w)) SetTabPlacement(f, w); #ifdef XmLEVAL if (f->folder.tabCount > 6) { fprintf(stderr, "XmL: evaluation version only supports <= 6 tabs\n"); exit(0); } #endif } static void ConstraintDestroy(Widget w) { XmLFolderWidget f; XmLFolderConstraintRec *fc; int i, j, activePos; if (!XtIsRectObj(w)) return; f = (XmLFolderWidget)XtParent(w); if (f->folder.debugLevel) fprintf(stderr, "XmLFolder: Constraint Destroy\n"); if (f->folder.focusW == w) f->folder.focusW = 0; fc = (XmLFolderConstraintRec *)(w->core.constraints); if (fc->folder.managedName) free((char *)fc->folder.managedName); if (fc->folder.freePix == True) { if (fc->folder.pix != XmUNSPECIFIED_PIXMAP) XFreePixmap(XtDisplay(w), fc->folder.pix); if (fc->folder.inactPix != XmUNSPECIFIED_PIXMAP) XFreePixmap(XtDisplay(w), fc->folder.inactPix); } if (XtIsSubclass(w, xmPrimitiveWidgetClass)) { XtRemoveCallback(w, XmNactivateCallback, PrimActivate, 0); /* remove child from tabs list and calculate active pos */ activePos = -1; j = 0; for (i = 0; i < f->folder.tabCount; i++) if (f->folder.tabs[i] != w) { if (f->folder.activeW == f->folder.tabs[i]) activePos = j; f->folder.tabs[j++] = f->folder.tabs[i]; } if (j != f->folder.tabCount - 1) XmLWarning((Widget)f, "ConstraintDestroy() - bad child list"); f->folder.tabCount = j; f->folder.activeTab = activePos; if (activePos == -1) f->folder.activeW = 0; } } static void DrawTabPixmap(XmLFolderWidget f, Widget tab, int active) { Display *dpy; Window win; int x, y; Pixmap pixmap; Dimension pixWidth, pixHeight, ht; XmLFolderConstraintRec *fc; x = 0; y = 0; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(tab->core.constraints); ht = f->folder.highlightThickness; if (active) { pixWidth = fc->folder.pixWidth; pixHeight = fc->folder.pixHeight; pixmap = fc->folder.pix; } else { pixWidth = fc->folder.inactPixWidth; pixHeight = fc->folder.inactPixHeight; pixmap = fc->folder.inactPix; } if (f->folder.tabPlacement == XmFOLDER_TOP) { x = tab->core.x - pixWidth - ht - f->folder.pixmapMargin; y = tab->core.y + tab->core.height - pixHeight; } else if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { x = tab->core.x - fc->folder.pixWidth - ht - f->folder.pixmapMargin; y = tab->core.y; } else if (f->folder.tabPlacement == XmFOLDER_LEFT) { x = tab->core.x + tab->core.width - pixWidth; y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht; } else if (f->folder.tabPlacement == XmFOLDER_RIGHT) { x = tab->core.x; y = tab->core.y - pixHeight - f->folder.pixmapMargin - ht; } XCopyArea(dpy, pixmap, win, f->folder.gc, 0, 0, pixWidth, pixHeight, x, y); } static void DrawManagerShadowTopBottom(XmLFolderWidget f, XRectangle *rect) { Display *dpy; Window win; XmLFolderConstraintRec *fc; XSegment *topSeg, *botSeg; int i, bCount, tCount, st, botOff, isManaged; dpy = XtDisplay(f); win = XtWindow(f); st = f->manager.shadow_thickness; if (!st) return; botOff = f->core.height - f->folder.tabHeight - 1; topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); /* top shadow */ fc = 0; if (f->folder.activeW) fc = (XmLFolderConstraintRec *)(f->folder.activeW->core.constraints); tCount = 0; if (fc) for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = rect->y + i; if (rect->x != fc->folder.x) tCount++; topSeg[tCount].x1 = rect->x + fc->folder.x + fc->folder.width - i - 1; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + rect->width - i - 1; topSeg[tCount].y2 = rect->y + i; if (fc->folder.x + fc->folder.width != rect->width) tCount++; } else for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + rect->width - i - 1; topSeg[tCount].y2 = rect->y + i; tCount++; } if (f->folder.tabPlacement == XmFOLDER_BOTTOM) for (i = 0 ; i < tCount; i++) { topSeg[i].y1 = botOff - topSeg[i].y1; topSeg[i].y2 = botOff - topSeg[i].y2; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_BOTTOM) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } /* see if there's any composite widgets in the folder */ isManaged = 0; for (i = 0; i < f->composite.num_children; i++) { Widget child = f->composite.children[i]; if (!XtIsSubclass(child, xmPrimitiveWidgetClass) && XtIsManaged(child)) { isManaged = 1; break; } } /* no need to draw shadow for the manager area if there isn't any composite widgets in the folder */ if (!isManaged) { free((char *)topSeg); free((char *)botSeg); return; } /* left shadow */ tCount = 0; for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + i; topSeg[tCount].y2 = rect->y + rect->height - i - 1; tCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } /* right shadow */ bCount = 0; for (i = 0; i < st; i++) { botSeg[bCount].x1 = rect->x + rect->width - i - 1; botSeg[bCount].y1 = rect->y + i; botSeg[bCount].x2 = rect->x + rect->width - i - 1; botSeg[bCount].y2 = rect->y + rect->height - i - 1; bCount++; } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } /* bottom shadow */ bCount = 0; for (i = 0; i < st; i++) { botSeg[bCount].x1 = rect->x + i; botSeg[bCount].y1 = rect->y + rect->height - i - 1; botSeg[bCount].x2 = rect->x + rect->width - i - 1; botSeg[bCount].y2 = rect->y + rect->height - i - 1; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { botSeg[bCount].y1 = botOff - botSeg[bCount].y1; botSeg[bCount].y2 = botOff - botSeg[bCount].y2; } bCount++; } if (bCount) { if (f->folder.tabPlacement == XmFOLDER_TOP) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); } static void DrawManagerShadowLeftRight(XmLFolderWidget f, XRectangle *rect) { Display *dpy; Window win; XmLFolderConstraintRec *fc; XSegment *topSeg, *botSeg; int i, bCount, tCount, st, rightOff; dpy = XtDisplay(f); win = XtWindow(f); st = f->manager.shadow_thickness; if (!st) return; rightOff = f->core.width - f->folder.tabWidth - 1; topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); /* left shadow */ fc = 0; if (f->folder.activeW) fc = (XmLFolderConstraintRec *)(f->folder.activeW->core.constraints); tCount = 0; if (fc) for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + i; topSeg[tCount].y2 = fc->folder.y + i; if (rect->y != fc->folder.y) tCount++; topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + fc->folder.y + fc->folder.height - i - 1; topSeg[tCount].x2 = rect->x + i; topSeg[tCount].y2 = rect->y + rect->height - i - 1; if (fc->folder.y + fc->folder.height != rect->height) tCount++; } else for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + i; topSeg[tCount].y2 = rect->y + rect->height - i - 1; tCount++; } if (f->folder.tabPlacement == XmFOLDER_RIGHT) for (i = 0 ; i < tCount; i++) { topSeg[i].x1 = rightOff - topSeg[i].x1; topSeg[i].x2 = rightOff - topSeg[i].x2; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_RIGHT) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } /* top shadow */ tCount = 0; for (i = 0; i < st; i++) { topSeg[tCount].x1 = rect->x + i; topSeg[tCount].y1 = rect->y + i; topSeg[tCount].x2 = rect->x + rect->width - i - 1; topSeg[tCount].y2 = rect->y + i; tCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } /* bottom shadow */ bCount = 0; for (i = 0; i < st; i++) { botSeg[bCount].x1 = rect->x + i; botSeg[bCount].y1 = rect->y + rect->height - i - 1; botSeg[bCount].x2 = rect->x + rect->width - i - 1; botSeg[bCount].y2 = rect->y + rect->height - i - 1; bCount++; } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } /* right shadow */ bCount = 0; for (i = 0; i < st; i++) { botSeg[bCount].x1 = rect->x + rect->width - i - 1; botSeg[bCount].y1 = rect->y + i; botSeg[bCount].x2 = rect->x + rect->width - i - 1; botSeg[bCount].y2 = rect->y + rect->height - i - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { botSeg[bCount].x1 = rightOff - botSeg[bCount].x1; botSeg[bCount].x2 = rightOff - botSeg[bCount].x2; } bCount++; } if (bCount) { if (f->folder.tabPlacement == XmFOLDER_LEFT) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); } static void DrawTabShadowArcTopBottom(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; XRectangle rect, rect2; XArc arc; int tCount, bCount; int i, st, cd, botOff; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); botOff = 2 * fc->folder.y + fc->folder.height - 1; st = f->manager.shadow_thickness; if (!st) return; cd = f->folder.cornerDimension; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st); botSeg = (XSegment *)malloc(sizeof(XSegment) * st); for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + cd + st; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) topSeg[tCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; /* right tab shadow */ botSeg[bCount].x1 = fc->folder.x + fc->folder.width - i - 1; botSeg[bCount].y1 = fc->folder.y + cd + st; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - i - 1; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) botSeg[bCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { botSeg[bCount].y1 = botOff - botSeg[bCount].y1; botSeg[bCount].y2 = botOff - botSeg[bCount].y2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* top tab shadow */ topSeg[tCount].x1 = fc->folder.x + cd + st; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - cd - st - 1; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_BOTTOM) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); /* left corner blank background */ rect.x = fc->folder.x; rect.y = fc->folder.y; rect.width = cd + st; rect.height = cd + st; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) rect.y = fc->folder.y + fc->folder.height - rect.height; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); SetGC(f, GC_UNSET); /* left arc */ /* various X Servers have problems drawing arcs - so set clip rect */ /* and draw two circles, one smaller than the other, for corner */ XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted); arc.x = rect.x; arc.y = rect.y; arc.width = rect.width * 2; arc.height = rect.height * 2; if (f->folder.serverDrawsArcsLarge == True) { arc.width -= 1; arc.height -= 1; } arc.angle1 = 0 * 64; arc.angle2 = 360 * 64; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) arc.y = fc->folder.y + fc->folder.height - arc.height; SetGC(f, GC_SHADOWTOP); XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); SetGC(f, GC_UNSET); rect2 = rect; rect2.x += st; rect2.width -= st; rect2.height -= st; if (f->folder.tabPlacement == XmFOLDER_TOP) rect2.y += st; XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); arc.x += st; arc.y += st; arc.width -= st * 2; arc.height -= st * 2; XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XSetClipMask(dpy, f->folder.gc, None); /* right corner blank background */ rect.x = fc->folder.x + fc->folder.width - cd - st; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); SetGC(f, GC_UNSET); /* right arc */ XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted); arc.x = rect.x - cd - st; arc.y = rect.y; arc.width = rect.width * 2; arc.height = rect.height * 2; if (f->folder.serverDrawsArcsLarge == True) { arc.width -= 1; arc.height -= 1; } arc.angle1 = 0 * 64; arc.angle2 = 360 * 64; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) arc.y = fc->folder.y + fc->folder.height - arc.height; SetGC(f, GC_SHADOWBOT); XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); SetGC(f, GC_UNSET); rect2 = rect; rect2.width -= st; rect2.height -= st; if (f->folder.tabPlacement == XmFOLDER_TOP) rect2.y += st; XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); arc.x += st; arc.y += st; arc.width -= st * 2; arc.height -= st * 2; XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XSetClipMask(dpy, f->folder.gc, None); } static void DrawTabShadowArcLeftRight(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; XRectangle rect, rect2; XArc arc; int tCount, bCount; int i, st, cd, rightOff; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); rightOff = 2 * fc->folder.x + fc->folder.width - 1; st = f->manager.shadow_thickness; if (!st) return; cd = f->folder.cornerDimension; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st); botSeg = (XSegment *)malloc(sizeof(XSegment) * st); for (i = 0; i < st; i++) { /* top tab shadow */ topSeg[tCount].x1 = fc->folder.x + cd + st; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) topSeg[tCount].x2 += i; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; /* bottom tab shadow */ botSeg[bCount].x1 = fc->folder.x + cd + st; botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) botSeg[bCount].x2 += i; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { botSeg[bCount].x1 = rightOff - botSeg[bCount].x1; botSeg[bCount].x2 = rightOff - botSeg[bCount].x2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + cd + st; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - cd - st - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_RIGHT) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); /* top corner blank background */ rect.x = fc->folder.x; rect.y = fc->folder.y; rect.width = cd + st; rect.height = cd + st; if (f->folder.tabPlacement == XmFOLDER_RIGHT) rect.x = fc->folder.x + fc->folder.width - rect.width; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); SetGC(f, GC_UNSET); /* top arc */ XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted); arc.x = rect.x; arc.y = rect.y; arc.width = rect.width * 2; arc.height = rect.height * 2; if (f->folder.serverDrawsArcsLarge == True) { arc.width -= 1; arc.height -= 1; } arc.angle1 = 0 * 64; arc.angle2 = 360 * 64; if (f->folder.tabPlacement == XmFOLDER_RIGHT) arc.x = fc->folder.x + fc->folder.width - arc.width; SetGC(f, GC_SHADOWTOP); XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); SetGC(f, GC_UNSET); rect2 = rect; rect2.width -= st; rect2.height -= st; rect2.y += st; if (f->folder.tabPlacement == XmFOLDER_LEFT) rect2.x += st; XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); arc.x += st; arc.y += st; arc.width -= st * 2; arc.height -= st * 2; XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XSetClipMask(dpy, f->folder.gc, None); /* bottom corner blank background */ rect.y = fc->folder.y + fc->folder.height - cd - st; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, rect.x, rect.y, rect.width, rect.height); SetGC(f, GC_UNSET); /* bottom arc */ XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect, 1, Unsorted); arc.x = rect.x; arc.y = rect.y - cd - st; arc.width = rect.width * 2; arc.height = rect.height * 2; if (f->folder.serverDrawsArcsLarge == True) { arc.width -= 1; arc.height -= 1; } arc.angle1 = 0 * 64; arc.angle2 = 360 * 64; if (f->folder.tabPlacement == XmFOLDER_RIGHT) arc.x = fc->folder.x + fc->folder.width - arc.width; SetGC(f, GC_SHADOWBOT); XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); SetGC(f, GC_UNSET); rect2 = rect; rect2.width -= st; rect2.height -= st; if (f->folder.tabPlacement == XmFOLDER_LEFT) rect2.x += st; XSetClipRectangles(dpy, f->folder.gc, 0, 0, &rect2, 1, Unsorted); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); arc.x += st; arc.y += st; arc.width -= st * 2; arc.height -= st * 2; XFillArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XDrawArc(dpy, win, f->folder.gc, arc.x, arc.y, arc.width, arc.height, arc.angle1, arc.angle2); XSetClipMask(dpy, f->folder.gc, None); } static void DrawTabShadowLineTopBottom(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; XPoint points[4]; int tCount, bCount, botOff, i, st, cd, y; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); botOff = 2 * fc->folder.y + fc->folder.height - 1; st = f->manager.shadow_thickness; if (!st) return; cd = f->folder.cornerDimension; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st); botSeg = (XSegment *)malloc(sizeof(XSegment) * st); for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + cd + st; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) topSeg[tCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; /* right tab shadow */ botSeg[bCount].x1 = fc->folder.x + fc->folder.width - i - 1; botSeg[bCount].y1 = fc->folder.y + cd + st; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - i - 1; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) botSeg[bCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { botSeg[bCount].y1 = botOff - botSeg[bCount].y1; botSeg[bCount].y2 = botOff - botSeg[bCount].y2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* top tab shadow */ topSeg[tCount].x1 = fc->folder.x + cd + st; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - cd - st - 1; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_TOP) SetGC(f, GC_SHADOWTOP); else SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); /* left top line */ points[0].x = fc->folder.x; points[0].y = fc->folder.y + cd + st - 1; points[1].x = fc->folder.x + cd + st - 1; points[1].y = fc->folder.y; points[2].x = fc->folder.x + cd + st - 1; points[2].y = fc->folder.y + cd + st - 1; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { points[0].y = botOff - points[0].y; points[1].y = botOff - points[1].y; points[2].y = botOff - points[2].y; } y = fc->folder.y; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) y = fc->folder.y + fc->folder.height - cd - st; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, fc->folder.x, y, cd + st, cd + st); SetGC(f, GC_UNSET); SetGC(f, GC_SHADOWTOP); XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); SetGC(f, GC_UNSET); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); points[0].x += st; points[1].y += st; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) points[1].y -= st * 2; XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); /* right top line */ points[0].x = fc->folder.x + fc->folder.width - 1; points[0].y = fc->folder.y + cd + st - 1; points[1].x = fc->folder.x + fc->folder.width - cd - st; points[1].y = fc->folder.y; points[2].x = fc->folder.x + fc->folder.width - cd - st; points[2].y = fc->folder.y + cd + st - 1; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { points[0].y = botOff - points[0].y; points[1].y = botOff - points[1].y; points[2].y = botOff - points[2].y; } y = fc->folder.y; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) y = fc->folder.y + fc->folder.height - cd - st; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, fc->folder.x + fc->folder.width - cd - st, y, cd + st, cd + st); SetGC(f, GC_UNSET); if (f->folder.tabPlacement == XmFOLDER_TOP) SetGC(f, GC_SHADOWTOP); else SetGC(f, GC_SHADOWBOT); XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); SetGC(f, GC_UNSET); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); points[0].x -= st; points[1].y += st; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) points[1].y -= st * 2; XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); } static void DrawTabShadowLineLeftRight(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; XPoint points[4]; int tCount, bCount, rightOff, i, st, cd, x; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); rightOff = 2 * fc->folder.x + fc->folder.width - 1; st = f->manager.shadow_thickness; if (!st) return; cd = f->folder.cornerDimension; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st); botSeg = (XSegment *)malloc(sizeof(XSegment) * st); for (i = 0; i < st; i++) { /* top tab shadow */ topSeg[tCount].x1 = fc->folder.x + cd + st; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) topSeg[tCount].x2 += i; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; /* bottom tab shadow */ botSeg[bCount].x1 = fc->folder.x + cd + st; botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) botSeg[bCount].x2 += i; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { botSeg[bCount].x1 = rightOff - botSeg[bCount].x1; botSeg[bCount].x2 = rightOff - botSeg[bCount].x2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + cd + st; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - cd - st - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_LEFT) SetGC(f, GC_SHADOWTOP); else SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); /* top line */ points[0].x = fc->folder.x + cd + st - 1; points[0].y = fc->folder.y; points[1].x = fc->folder.x; points[1].y = fc->folder.y + cd + st - 1; points[2].x = fc->folder.x + cd + st - 1; points[2].y = fc->folder.y + cd + st - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { points[0].x = rightOff - points[0].x; points[1].x = rightOff - points[1].x; points[2].x = rightOff - points[2].x; } if (f->folder.tabPlacement == XmFOLDER_RIGHT) x = fc->folder.x + fc->folder.width - cd - st; else x = fc->folder.x; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, x, fc->folder.y, cd + st, cd + st); SetGC(f, GC_UNSET); SetGC(f, GC_SHADOWTOP); XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); SetGC(f, GC_UNSET); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); points[0].y += st; points[1].x += st; if (f->folder.tabPlacement == XmFOLDER_RIGHT) points[1].x -= st * 2; XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); /* bottom line */ points[0].x = fc->folder.x + cd + st - 1; points[0].y = fc->folder.y + fc->folder.height - 1; points[1].x = fc->folder.x; points[1].y = fc->folder.y + fc->folder.height - cd - st; points[2].x = fc->folder.x + cd + st - 1; points[2].y = fc->folder.y + fc->folder.height - cd - st; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { points[0].x = rightOff - points[0].x; points[1].x = rightOff - points[1].x; points[2].x = rightOff - points[2].x; } if (f->folder.tabPlacement == XmFOLDER_RIGHT) x = fc->folder.x + fc->folder.width - cd - st; else x = fc->folder.x; SetGC(f, GC_BLANK); XFillRectangle(dpy, win, f->folder.gc, x, fc->folder.y + fc->folder.height - cd - st, cd + st, cd + st); SetGC(f, GC_UNSET); SetGC(f, GC_SHADOWBOT); XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); SetGC(f, GC_UNSET); if (w == f->folder.activeW) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); points[0].y -= st; points[1].x += st; if (f->folder.tabPlacement == XmFOLDER_RIGHT) points[1].x -= st * 2; XFillPolygon(dpy, win, f->folder.gc, points, 3, Nonconvex, CoordModeOrigin); points[3].x = points[0].x; points[3].y = points[0].y; XDrawLines(dpy, win, f->folder.gc, points, 4, CoordModeOrigin); } static void DrawTabShadowNoneTopBottom(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; int i, st, botOff, tCount, bCount; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); botOff = 2 * fc->folder.y + fc->folder.height - 1; st = f->manager.shadow_thickness; if (!st) return; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) topSeg[tCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; /* right tab shadow */ botSeg[bCount].x1 = fc->folder.x + fc->folder.width - 1 - i; botSeg[bCount].y1 = fc->folder.y + i; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1 - i; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - 1; if (w == f->folder.activeW) botSeg[bCount].y2 += i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { botSeg[bCount].y1 = botOff - botSeg[bCount].y1; botSeg[bCount].y2 = botOff - botSeg[bCount].y2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* top tab shadow */ topSeg[tCount].x1 = fc->folder.x + i + 1; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - i - 1; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { topSeg[tCount].y1 = botOff - topSeg[tCount].y1; topSeg[tCount].y2 = botOff - topSeg[tCount].y2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_TOP) SetGC(f, GC_SHADOWTOP); else SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); } static void DrawTabShadowNoneLeftRight(XmLFolderWidget f, Widget w) { XmLFolderConstraintRec *fc; Display *dpy; Window win; XSegment *topSeg, *botSeg; int i, st, rightOff, tCount, bCount; dpy = XtDisplay(f); win = XtWindow(f); fc = (XmLFolderConstraintRec *)(w->core.constraints); rightOff = 2 * fc->folder.x + fc->folder.width - 1; st = f->manager.shadow_thickness; if (!st) return; tCount = 0; bCount = 0; topSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); botSeg = (XSegment *)malloc(sizeof(XSegment) * st * 2); for (i = 0; i < st; i++) { /* bottom tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + i; topSeg[tCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) topSeg[tCount].x2 += i; topSeg[tCount].y2 = fc->folder.y + i; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; /* top tab shadow */ botSeg[bCount].x1 = fc->folder.x + i; botSeg[bCount].y1 = fc->folder.y + fc->folder.height - i - 1; botSeg[bCount].x2 = fc->folder.x + fc->folder.width - 1; if (w == f->folder.activeW) botSeg[bCount].x2 += i; botSeg[bCount].y2 = fc->folder.y + fc->folder.height - i - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { botSeg[bCount].x1 = rightOff - botSeg[bCount].x1; botSeg[bCount].x2 = rightOff - botSeg[bCount].x2; } bCount++; } if (tCount) { SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } if (bCount) { SetGC(f, GC_SHADOWBOT); XDrawSegments(dpy, win, f->folder.gc, botSeg, bCount); SetGC(f, GC_UNSET); } tCount = 0; for (i = 0; i < st; i++) { /* left tab shadow */ topSeg[tCount].x1 = fc->folder.x + i; topSeg[tCount].y1 = fc->folder.y + i + 1; topSeg[tCount].x2 = fc->folder.x + i; topSeg[tCount].y2 = fc->folder.y + fc->folder.height - i - 1; if (f->folder.tabPlacement == XmFOLDER_RIGHT) { topSeg[tCount].x1 = rightOff - topSeg[tCount].x1; topSeg[tCount].x2 = rightOff - topSeg[tCount].x2; } tCount++; } if (tCount) { if (f->folder.tabPlacement == XmFOLDER_RIGHT) SetGC(f, GC_SHADOWBOT); else SetGC(f, GC_SHADOWTOP); XDrawSegments(dpy, win, f->folder.gc, topSeg, tCount); SetGC(f, GC_UNSET); } free((char *)topSeg); free((char *)botSeg); } static void SetGC(XmLFolderWidget f, int type) { Display *dpy; XGCValues values; XtGCMask mask; dpy = XtDisplay(f); if (type == GC_SHADOWBOT) { mask = GCForeground; values.foreground = f->manager.bottom_shadow_color; if (f->manager.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP) { mask |= GCFillStyle | GCTile; values.fill_style = FillTiled; values.tile = f->manager.bottom_shadow_pixmap; } XChangeGC(dpy, f->folder.gc, mask, &values); } else if (type == GC_SHADOWTOP) { mask = GCForeground; values.foreground = f->manager.top_shadow_color; if (f->manager.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP) { mask |= GCFillStyle | GCTile; values.fill_style = FillTiled; values.tile = f->manager.top_shadow_pixmap; } XChangeGC(dpy, f->folder.gc, mask, &values); } else if (type == GC_BLANK) { mask = GCForeground; values.foreground = f->folder.blankBg; if (f->folder.blankPix != XmUNSPECIFIED_PIXMAP) { mask |= GCFillStyle | GCTile; values.fill_style = FillTiled; values.tile = f->folder.blankPix; } XChangeGC(dpy, f->folder.gc, mask, &values); } else { mask = GCFillStyle; values.fill_style = FillSolid; XChangeGC(dpy, f->folder.gc, mask, &values); } } static void DrawTabHighlight(XmLFolderWidget f, Widget w) { Display *dpy; Window win; int ht; if (!XtIsRealized(w)) return; if (!f->core.visible) return; dpy = XtDisplay(f); win = XtWindow(f); ht = f->folder.highlightThickness; if (f->folder.focusW == w) XSetForeground(dpy, f->folder.gc, f->manager.highlight_color); else { if (f->folder.activeW == w) XSetForeground(dpy, f->folder.gc, f->core.background_pixel); else XSetForeground(dpy, f->folder.gc, f->folder.inactiveBg); } XFillRectangle(dpy, win, f->folder.gc, w->core.x - ht, w->core.y - ht, XtWidth(w) + w->core.border_width * 2 + ht * 2, XtHeight(w) + w->core.border_width * 2 + ht * 2); } static void SetTabPlacement(XmLFolderWidget f, Widget tab) { if (!XmIsDrawnButton(tab)) return; if (f->folder.allowRotate == True && f->folder.tabPlacement == XmFOLDER_LEFT) XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_UP); else if (f->folder.allowRotate == True && f->folder.tabPlacement == XmFOLDER_RIGHT) XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_DOWN); else XmLDrawnButtonSetType(tab, XmDRAWNB_STRING, XmDRAWNB_RIGHT); if (XtIsRealized(tab)) XClearArea(XtDisplay(tab), XtWindow(tab), 0, 0, 0, 0, True); } static void GetTabRect(XmLFolderWidget f, Widget tab, XRectangle *rect, int includeShadow) { XmLFolderConstraintRec *fc; int st; st = f->manager.shadow_thickness; fc = (XmLFolderConstraintRec *)(tab->core.constraints); rect->x = fc->folder.x; rect->y = fc->folder.y; rect->width = fc->folder.width; rect->height = fc->folder.height; if (includeShadow) { if (f->folder.tabPlacement == XmFOLDER_TOP) rect->height += st; else if (f->folder.tabPlacement == XmFOLDER_BOTTOM) { rect->y -= st; rect->height += st; } else if (f->folder.tabPlacement == XmFOLDER_LEFT) rect->width += st; else { rect->x -= st; rect->width += st; } } } static void SetActiveTab(XmLFolderWidget f, Widget w, XEvent *event, Boolean notify) { XmLFolderCallbackStruct cbs; XmLFolderConstraintRec *fc, *cfc; int i, j, pos; Display *dpy; Window win; Widget activeW, child, mw, managedW; WidgetList children; XRectangle rect; char *name, buf[256]; win = (Window)NULL; if (f->folder.activeW == w) return; dpy = 0; if (XtIsRealized((Widget)f) && f->core.visible) { dpy = XtDisplay(f); win = XtWindow(f); } pos = -1; for (i = 0; i < f->folder.tabCount; i++) if (w == f->folder.tabs[i]) pos = i; cbs.allowActivate = 1; cbs.layoutNeeded = 0; if (notify == True) { if (f->folder.debugLevel) fprintf(stderr, "XmLFolder: activated %d\n", pos); cbs.reason = XmCR_ACTIVATE; cbs.event = event; cbs.pos = pos; XtCallCallbackList((Widget)f, f->folder.activateCallback, &cbs); } if (!cbs.allowActivate) return; /* redraw current active tab */ activeW = f->folder.activeW; if (activeW && dpy) { GetTabRect(f, activeW, &rect, 1); XClearArea(dpy, win, rect.x, rect.y, rect.width, rect.height, True); } f->folder.activeTab = pos; f->folder.activeW = w; if (!w) return; /* Not sure this needs to be in the 3.0 (Microline) stuff */ PrimFocusIn(w, NULL, NULL, NULL); /* if we selected a tab not in active row - move row into place */ if (f->folder.tabsPerRow) { fc = (XmLFolderConstraintRec *)(w->core.constraints); if (fc->folder.row != f->folder.activeRow) Layout(f, False); } /* manage this tabs managed widget if it exists */ children = f->composite.children; f->folder.allowLayout = 0; for (i = 0; i < f->composite.num_children; i++) { child = children[i]; if (!XtIsSubclass(child, xmPrimitiveWidgetClass)) continue; fc = (XmLFolderConstraintRec *)(child->core.constraints); managedW = 0; if (fc->folder.managedName) { for (j = 0; j < f->composite.num_children; j++) { mw = children[j]; if (XtIsSubclass(mw, xmPrimitiveWidgetClass)) continue; name = XtName(mw); if (name && !strcmp(name, fc->folder.managedName)) managedW = mw; cfc = (XmLFolderConstraintRec *)(mw->core.constraints); name = cfc->folder.managedName; if (name && !strcmp(name, fc->folder.managedName)) managedW = mw; } if (!managedW) { sprintf(buf, "SetActiveTab() - managed widget named "); strcat(buf, fc->folder.managedName); strcat(buf, " not found"); XmLWarning(child, buf); } } else managedW = fc->folder.managedW; if (managedW) { if (w == child && !XtIsManaged(managedW)) XtManageChild(managedW); if (w != child && XtIsManaged(managedW)) XtUnmanageChild(managedW); } } f->folder.allowLayout = 1; /* redraw new active tab */ if (dpy) { GetTabRect(f, w, &rect, 1); XClearArea(dpy, win, rect.x, rect.y, rect.width, rect.height, True); XmProcessTraversal(w, XmTRAVERSE_CURRENT); } if (cbs.layoutNeeded) Layout(f, 0); } /* Utility */ static void GetCoreBackground(Widget w, int offset, XrmValue *value) { value->addr = (caddr_t)&w->core.background_pixel; } static void GetDefaultTabWidgetClass(Widget w, int offset, XrmValue *value) { value->addr = (caddr_t)&xmDrawnButtonWidgetClass; } static void GetManagerForeground(Widget w, int offset, XrmValue *value) { XmLFolderWidget f; f = (XmLFolderWidget)w; value->addr = (caddr_t)&f->manager.foreground; } static Boolean ServerDrawsArcsLarge(Display *dpy, int debug) { Pixmap pixmap; XImage *image; Window root; long pixel; int x, y, width, height, result; GC gc; root = DefaultRootWindow(dpy); width = 5; height = 5; pixmap = XCreatePixmap(dpy, root, width, height, 1); gc = XCreateGC(dpy, pixmap, 0L, NULL); XSetForeground(dpy, gc, 0L); XFillRectangle(dpy, pixmap, gc, 0, 0, width, height); XSetForeground(dpy, gc, 1L); XDrawArc(dpy, pixmap, gc, 0, 0, width, height, 0, 360 * 64); image = XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap); if (debug) { fprintf(stderr, "Test X server drawn arc (%d by %d):\n", width, height); for (y = 0; y < height; y++) { fprintf(stderr, " "); for (x = 0; x < width; x++) { pixel = XGetPixel(image, x, y); if (pixel == 0L) fprintf(stderr, "."); else fprintf(stderr, "X"); } fprintf(stderr, "\n"); } } if (XGetPixel(image, width - 1, height / 2) != 1L) { result = 1; if (debug) fprintf(stderr, "X Server Draws Arcs 1 Pixel Large\n"); } else { result = 0; if (debug) fprintf(stderr, "X Server Draws Arcs Within Bounds\n"); } XDestroyImage(image); XFreeGC(dpy, gc); XFreePixmap(dpy, pixmap); return result; } /* Getting and Setting Values */ static Boolean SetValues(Widget curW, Widget reqW, Widget newW, ArgList args, Cardinal *narg) { XmLFolderWidget f; XmLFolderWidget cur; int i; Boolean needsLayout, needsRedisplay; f = (XmLFolderWidget)newW; cur = (XmLFolderWidget)curW; needsLayout = False; needsRedisplay = False; #define NE(value) (f->value != cur->value) if (NE(folder.tabBarHeight)) { XmLWarning((Widget)f, "SetValues() - can''t set tabBarHeight"); f->folder.tabBarHeight = cur->folder.tabBarHeight; } if (NE(folder.tabCount)) { XmLWarning((Widget)f, "SetValues() - can''t set tabCount"); f->folder.tabCount = cur->folder.tabCount; } if (NE(folder.activeTab)) { XmLWarning((Widget)f, "SetValues() - can''t set activeTab"); f->folder.activeTab = cur->folder.activeTab; } if (f->folder.cornerDimension < 1) { XmLWarning((Widget)f, "SetValues() - cornerDimension can''t be < 1"); f->folder.cornerDimension = cur->folder.cornerDimension; } if (NE(folder.tabPlacement) || NE(folder.allowRotate)) { f->folder.allowLayout = 0; for (i = 0; i < f->folder.tabCount; i++) SetTabPlacement(f, f->folder.tabs[i]); f->folder.allowLayout = 1; needsLayout = True; } if (NE(folder.inactiveBg) || NE(folder.blankBg) || NE(folder.blankPix) || NE(folder.inactiveFg)) needsRedisplay = True; if (NE(folder.cornerDimension) || NE(folder.cornerStyle) || NE(folder.highlightThickness) || NE(folder.marginHeight) || NE(folder.marginWidth) || NE(folder.pixmapMargin) || NE(manager.shadow_thickness) || NE(folder.tabsPerRow) || NE(folder.spacing)) needsLayout = True; if (NE(folder.renderTable)) { XmRenderTableFree(cur->folder.renderTable); CopyRenderTable(f); } #undef NE if (needsLayout == True) Layout(f, 1); return needsRedisplay; } static void CopyRenderTable(XmLFolderWidget f) { if (!f->folder.renderTable) f->folder.renderTable = XmLRenderTableCopyDefault((Widget)f); else f->folder.renderTable = XmRenderTableCopy(f->folder.renderTable, NULL, 0); if (!f->folder.renderTable) XmLWarning((Widget)f, "- fatal error - font list NULL"); } static Boolean ConstraintSetValues(Widget curW, Widget reqW, Widget newW, ArgList args, Cardinal *narg) { XmLFolderConstraintRec *cons, *curCons; XmLFolderWidget f; int i, hasLabelChange; f = (XmLFolderWidget)XtParent(newW); if (!XtIsRectObj(newW)) return False; cons = (XmLFolderConstraintRec *)newW->core.constraints; curCons = (XmLFolderConstraintRec *)curW->core.constraints; #define NE(value) (cons->value != curCons->value) if (NE(folder.managedName)) { if (curCons->folder.managedName) free((char *)curCons->folder.managedName); if (cons->folder.managedName) cons->folder.managedName = (char *)strdup(cons->folder.managedName); } #undef NE hasLabelChange = 0; if (XtIsSubclass(newW, xmPrimitiveWidgetClass)) { for (i = 0; i < *narg; i++) if (args[i].name && !strcmp(args[i].name, XmNlabelString)) hasLabelChange = 1; if (hasLabelChange && (f->folder.tabPlacement == XmFOLDER_LEFT || f->folder.tabPlacement == XmFOLDER_RIGHT)) { f->folder.allowLayout = 0; for (i = 0; i < f->folder.tabCount; i++) SetTabPlacement(f, f->folder.tabs[i]); f->folder.allowLayout = 1; } } if (hasLabelChange || curCons->folder.pix != cons->folder.pix || curCons->folder.inactPix != cons->folder.inactPix) Layout((XmLFolderWidget)XtParent(curW), 1); return False; } static Boolean CvtStringToCornerStyle(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "CORNER_NONE", XmCORNER_NONE }, { "CORNER_LINE", XmCORNER_LINE }, { "CORNER_ARC", XmCORNER_ARC }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRCornerStyle", map, fromVal, toVal); } static Boolean CvtStringToFolderResizePolicy(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "RESIZE_NONE", XmRESIZE_NONE }, { "RESIZE_STATIC", XmRESIZE_STATIC }, { "RESIZE_DYNAMIC", XmRESIZE_DYNAMIC }, { "RESIZE_PACK", XmRESIZE_PACK }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRFolderResizePolicy", map, fromVal, toVal); } static Boolean CvtStringToTabPlacement(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "FOLDER_TOP", XmFOLDER_TOP }, { "FOLDER_LEFT", XmFOLDER_LEFT }, { "FOLDER_BOTTOM", XmFOLDER_BOTTOM }, { "FOLDER_RIGHT", XmFOLDER_RIGHT }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRTabPlacement", map, fromVal, toVal); } /* Actions, Callbacks and Handlers */ static void Activate(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLFolderWidget f; XButtonEvent *be; XRectangle rect; Widget tab; int i; f = (XmLFolderWidget)w; if (!event || event->type != ButtonPress) return; be = (XButtonEvent *)event; if (f->folder.debugLevel) fprintf(stderr, "XmLFolder: ButtonPress %d %d\n", be->x, be->y); for (i = 0; i < f->folder.tabCount; i++) { tab = f->folder.tabs[i]; if (!XtIsManaged(tab) || !XtIsSensitive(tab)) continue; GetTabRect(f, tab, &rect, 0); if (be->x > rect.x && be->x < rect.x + (int)rect.width && be->y > rect.y && be->y < rect.y + (int)rect.height) { if (f->folder.debugLevel) fprintf(stderr, "XmLFolder: Pressed tab %d\n", i); SetActiveTab(f, tab, event, True); return; } } } static void PrimActivate(Widget w, XtPointer clientData, XtPointer callData) { XmLFolderWidget f; XmAnyCallbackStruct *cbs; f = (XmLFolderWidget)XtParent(w); cbs = (XmAnyCallbackStruct *)callData; SetActiveTab(f, w, cbs->event, True); } static void PrimFocusIn(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLFolderWidget f; Widget prevW; f = (XmLFolderWidget)XtParent(w); prevW = f->folder.focusW; f->folder.focusW = w; DrawTabHighlight(f, w); if (prevW) DrawTabHighlight(f, prevW); XmProcessTraversal(w, XmTRAVERSE_CURRENT); } static void PrimFocusOut(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLFolderWidget f; Widget prevW; f = (XmLFolderWidget)XtParent(w); prevW = f->folder.focusW; f->folder.focusW = 0; if (prevW) DrawTabHighlight(f, prevW); DrawTabHighlight(f, w); } /* Public Functions */ Widget XmLCreateFolder(Widget parent, char *name, ArgList arglist, Cardinal argcount) { return XtCreateWidget(name, xmlFolderWidgetClass, parent, arglist, argcount); } Widget XmLFolderAddBitmapTab(Widget w, XmString string, char *bitmapBits, int bitmapWidth, int bitmapHeight) { XmLFolderWidget f; Widget tab; Pixmap pix, inactPix; Window root; Display *dpy; int depth; char name[20]; if (!XmLIsFolder(w)) { XmLWarning(w, "AddBitmapTab() - widget not a XmLFolder"); return 0; } f = (XmLFolderWidget)w; dpy = XtDisplay(w); root = DefaultRootWindow(dpy); depth = DefaultDepthOfScreen(XtScreen(w)); pix = XCreatePixmapFromBitmapData(dpy, root, bitmapBits, bitmapWidth, bitmapHeight, f->manager.foreground, f->core.background_pixel, depth); inactPix = XCreatePixmapFromBitmapData(dpy, root, bitmapBits, bitmapWidth, bitmapHeight, f->folder.inactiveFg, f->folder.inactiveBg, depth); sprintf(name, "tab%d", f->folder.tabCount); tab = XtVaCreateManagedWidget(name, f->folder.tabWidgetClass, w, XmNrenderTable, f->folder.renderTable, XmNmarginWidth, 0, XmNmarginHeight, 0, XmNlabelString, string, XmNtabPixmap, pix, XmNtabInactivePixmap, inactPix, XmNtabFreePixmaps, True, NULL); return tab; } Widget XmLFolderAddBitmapTabForm(Widget w, XmString string, char *bitmapBits, int bitmapWidth, int bitmapHeight) { Widget form, tab; XmLFolderWidget f; char name[20]; if (!XmLIsFolder(w)) { XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder"); return 0; } f = (XmLFolderWidget)w; tab = XmLFolderAddBitmapTab(w, string, bitmapBits, bitmapWidth, bitmapHeight); sprintf(name, "form%d", f->folder.tabCount); form = XtVaCreateManagedWidget(name, xmFormWidgetClass, w, XmNbackground, f->core.background_pixel, NULL); XtVaSetValues(tab, XmNtabManagedWidget, form, NULL); return form; } Widget XmLFolderAddTab(Widget w, XmString string) { Widget tab; XmLFolderWidget f; char name[20]; if (!XmLIsFolder(w)) { XmLWarning(w, "AddTab() - widget not a XmLFolder"); return 0; } f = (XmLFolderWidget)w; sprintf(name, "tab%d", f->folder.tabCount); tab = XtVaCreateManagedWidget(name, f->folder.tabWidgetClass, w, XmNrenderTable, f->folder.renderTable, XmNmarginWidth, 0, XmNmarginHeight, 0, XmNlabelString, string, NULL); return tab; } Widget XmLFolderAddTabFromClass(Widget w, XmString string) { Widget tab; XmLFolderWidget f; char name[20]; if (!XmLIsFolder(w)) { XmLWarning(w, "AddTab() - widget not a XmLFolder"); return 0; } f = (XmLFolderWidget)w; sprintf(name, "tab%d", f->folder.tabCount); tab = XtVaCreateManagedWidget(name, f->folder.tabWidgetClass, /* xmDrawnButtonWidgetClass, */ w, XmNrenderTable, f->folder.renderTable, /* XmNmarginWidth, 0, */ /* XmNmarginHeight, 0, */ XmNlabelString, string, NULL); return tab; } Widget XmLFolderAddTabForm(Widget w, XmString string) { Widget form, tab; XmLFolderWidget f; char name[20]; if (!XmLIsFolder(w)) { XmLWarning(w, "AddBitmapTabForm() - widget not a XmLFolder"); return 0; } f = (XmLFolderWidget)w; tab = XmLFolderAddTab(w, string); sprintf(name, "form%d", f->folder.tabCount); form = XtVaCreateManagedWidget(name, xmFormWidgetClass, w, XmNbackground, f->core.background_pixel, NULL); XtVaSetValues(tab, XmNtabManagedWidget, form, NULL); return form; } void XmLFolderSetActiveTab(Widget w, int position, Boolean notify) { XmLFolderWidget f; if (!XmLIsFolder(w)) { XmLWarning(w, "SetActiveTab() - widget not a XmLFolder"); return; } f = (XmLFolderWidget)w; if (position < 0 || position >= f->folder.tabCount) { XmLWarning(w, "SetActiveTab() - invalid position"); return; } SetActiveTab(f, f->folder.tabs[position], 0, notify); }