/* * Motif * * Copyright (c) 1987-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA * */ /* * COPYRIGHT NOTICE * Copyright (c) 1995 Integrated Computer Solutions */ /* * SYMBOLS * ======= * * DEMO - Controls if this is a demo version or not * SCROLLED_LAYOUT - Controls if the scrolled layout features are supported * OVERLAYED_LAYOUT - Controls if the overlayed layout is supported * */ #ifdef HAVE_CONFIG_H #include #endif #include #include "XmI.h" #include #ifdef SCROLLED_LAYOUT #include #endif #include #include #include #include #define FIX_1503 #ifdef USE_XFT #include #endif #define _XiBoolean Boolean typedef enum {XiQUAD_1, XiQUAD_2, XiQUAD_3, XiQUAD_4} XiQuadrant; #ifdef FIX_1381 typedef enum {normal, insensitive, shadow} GC_type; #endif typedef struct _XmTabRect { int x, y; int width, height; int row, column; } XiTabRect; typedef struct _XmCache { XImage *pixmap; XImage *label; Boolean sensitive; } XiCache; #ifdef _ARGS #undef _ARGS #endif #ifndef _NO_PROTO #define _ARGS(a) a #else #define _ARGS(a) () #endif extern XmTabAttributes _XmTabbedStackListGet _ARGS((XmTabbedStackList, int)); extern XmTabAttributes _XmTabbedStackListArray _ARGS((XmTabbedStackList)); extern int _XmTabbedStackListCount _ARGS((XmTabbedStackList)); #ifndef _NO_PROTO static void ClassInitialize (void); static void ClassPartInitialize(WidgetClass w_class); static void TabCanvasClassInitialize (void); #else static void ClassPartInitialize(); static void ClassInitialize (); static void TabCanvasClassInitialize (); #endif static void Initialize _ARGS((Widget, Widget, ArgList, Cardinal*)); static void Destroy _ARGS((Widget)); static void Resize _ARGS((Widget)); static Boolean SetValues _ARGS((Widget, Widget, Widget, ArgList, Cardinal*)); static XtGeometryResult QueryGeometry _ARGS((Widget, XtWidgetGeometry*, XtWidgetGeometry*)); static void Realize _ARGS((Widget, XtValueMask*, XSetWindowAttributes*)); static void BorderHighlight _ARGS((Widget)); static void BorderUnhighlight _ARGS((Widget)); static void XmTabBoxArmAndActivate _ARGS((Widget, XEvent*, String*,Cardinal*)); static void _XmTabBoxTraverseRight _ARGS((Widget, XEvent*, String*,Cardinal*)); static void _XmTabBoxTraverseLeft _ARGS((Widget, XEvent*, String*, Cardinal*)); static void _XmTabBoxTraverseUp _ARGS((Widget, XEvent*, String*, Cardinal*)); static void _XmTabBoxTraverseDown _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxArmTab _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxSelectTab _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraverseRight _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraverseLeft _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraverseUp _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraverseDown _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraversePrevious _ARGS((Widget, XEvent*, String*, Cardinal*)); static void XmTabBoxTraverseNext _ARGS((Widget, XEvent*, String*, Cardinal*)); static void CalcTabSize _ARGS((XmTabBoxWidget, XmTabAttributes, XmTabOrientation, XmFontList, int, int, int, int, int, int, Dimension*, Dimension*)); static void CalcStackedGeometry _ARGS((XmTabBoxWidget, XRectangle*)); static void HorizontalStackedLayout _ARGS((XmTabBoxWidget, _XiBoolean)); static void HorizontalStackedRedisplay _ARGS((XmTabBoxWidget)); static void VerticalStackedRedisplay _ARGS((XmTabBoxWidget)); static void VerticalStackedLayout _ARGS((XmTabBoxWidget, _XiBoolean)); static void CalcUnlimitedGeometry _ARGS((XmTabBoxWidget, XRectangle*)); static void CalcGeometry _ARGS((XmTabBoxWidget, XRectangle*)); static void HorizontalBasicLayout _ARGS((XmTabBoxWidget)); static void VerticalBasicLayout _ARGS((XmTabBoxWidget)); static void Layout _ARGS((XmTabBoxWidget)); static void Redisplay _ARGS((Widget, XEvent*, Region)); static void RedisplayTabs _ARGS((XmTabBoxWidget, Region)); static void DrawTab _ARGS((XmTabBoxWidget, XmTabAttributes, XiTabRect*, _XiBoolean, _XiBoolean)); static Boolean CvtStringToTabOrientation _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); static Boolean CvtStringToTabSide _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); static Boolean CvtStringToTabStyle _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); static Boolean CvtStringToTabMode _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); static Boolean CvtStringToTabEdge _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); #ifdef SCROLLED_LAYOUT static Boolean CvtStringToArrowPlacement _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); #endif static Boolean CvtStringToTabList _ARGS((Display*, XrmValue*, Cardinal*, XrmValue*, XrmValue*, XtPointer*)); static void CvtDestroyTabList _ARGS((XtAppContext, XrmValue*, XtPointer, XrmValue*, Cardinal*)); static void XiDrawCorner _ARGS((Display*, Drawable, GC, GC, int, int, unsigned int, unsigned int, unsigned int, XiQuadrant)); static void HorizontalBasicRedisplay _ARGS((XmTabBoxWidget)); static void VerticalBasicRedisplay _ARGS((XmTabBoxWidget)); static XImage *XiRotateImage _ARGS((XmTabBoxWidget, XImage*, int)); static void CalcCornerSize _ARGS((XmTabBoxWidget)); static int XiXYtoTab _ARGS((XmTabBoxWidget, int, int)); static void CalcTabGeometry _ARGS((XmTabBoxWidget)); static int CalcGeometryMinor _ARGS((XmTabBoxWidget, int)); static int CalcGeometryMajor _ARGS((XmTabBoxWidget, int)); static void CallCallbacks _ARGS((XmTabBoxWidget, XEvent*, int, int)); #ifdef FIX_1381 static void SetRightGC(XmTabBoxWidget tab, GC gc, GC_type); #endif static void DrawVerticalTab _ARGS((XmTabBoxWidget, XmTabAttributes, GC, _XiBoolean, int, int, int, _XiBoolean, int, int, XRectangle*, _XiBoolean, _XiBoolean)); static void DrawLeftToRightTab _ARGS((XmTabBoxWidget, XmTabAttributes, GC, _XiBoolean, int, int, int, _XiBoolean, int, int, XRectangle*)); static void DrawRightToLeftTab _ARGS((XmTabBoxWidget, XmTabAttributes, GC, _XiBoolean, int, int, int, _XiBoolean, int, int, XRectangle*, _XiBoolean)); static void DrawTopToBottomTab _ARGS((XmTabBoxWidget, XmTabAttributes, GC, _XiBoolean, int, int, int, _XiBoolean, int, int, XRectangle*, _XiBoolean)); static void DrawBottomToTopTab _ARGS((XmTabBoxWidget, XmTabAttributes, GC, _XiBoolean, int, int, int, _XiBoolean, int, int, XRectangle*, _XiBoolean)); static void FillRoundedTab _ARGS((XmTabBoxWidget, GC, XiTabRect*, XmTabEdge)); static void FillBeveledTab _ARGS((XmTabBoxWidget, GC, XiTabRect*, XmTabEdge)); static XmTabAttributes GetTabInfo _ARGS((XmTabBoxWidget, int, int)); static int GetTabIndex _ARGS((XmTabBoxWidget, int, int)); static void SelectTab _ARGS((XmTabBoxWidget, XEvent*, int, int)); static Boolean IsTabSensitive _ARGS((XmTabBoxWidget, int)); static Widget XiGCParent _ARGS((XmTabBoxWidget)); static void ResetImageCache _ARGS((XmTabBoxWidget)); static void FreeImageCache _ARGS((XmTabBoxWidget)); static int InfoToIndex _ARGS((XmTabBoxWidget, XmTabAttributes)); static Visual* GetShellVisual _ARGS((Widget)); static void CheckSetRenderTable(Widget wid, int offs, XrmValue *value); #define CachePixmap(t,i) XmTabBox__cache((t))[InfoToIndex(t,i)].pixmap #define CacheLabel(t,i) XmTabBox__cache((t))[InfoToIndex(t,i)].label #define CacheSensitive(t,i) XmTabBox__cache((t))[InfoToIndex(t,i)].sensitive #ifndef AssignMax #define AssignMax(x,y) if((y)>(x)) (x)=(y); else #endif #ifndef AssignMin #define AssignMin(x,y) if((y)<(x)) (x)=(y); else #endif #ifndef Max #define Max(x,y) (((x)>(y))?(x):(y)) #endif #define XiRectInRegion(r,x,y,w,h) ((r) == False ? RectangleIn : \ XRectInRegion(r,x,y,w,h)) #define XiCanvas(x) (XtWindow(XmTabBox__canvas((x)))) #define XiTabParent(x) ((XmTabBoxWidget) XtParent(x)) #define XImageWidth(i) (i)->width #define XImageHeight(i) (i)->height #define XImageDepth(i) (i)->depth; #define XiTabDegree(x) ((x) == XmTABS_RIGHT_TO_LEFT ? 180 \ : ((x) == XmTABS_TOP_TO_BOTTOM ? 90 \ : ((x) == XmTABS_BOTTOM_TO_TOP ? 270 : 0))) #define ValidPixmap(p) ((p) != (Pixmap)NULL && \ (p) != (Pixmap)XmUNSPECIFIED_PIXMAP && \ (p) != XmPIXMAP_DYNAMIC ) #define XiCalcTabSize(t,i,w,h) \ CalcTabSize((t),(i), XmTabBox_tab_orientation((t)), \ XmTabBox_font_list((t)), (t)->manager.shadow_thickness, \ XmTabBox_highlight_thickness((t)), \ XmTabBox_tab_margin_width((t)), \ XmTabBox_tab_margin_height((t)), \ XmTabBox_tab_label_spacing((t)), \ XmTabBox__corner_size((t)), (w), (h)) #define SetSolidGC(d,g,p) \ { \ XGCValues _macro_gc_values; \ _macro_gc_values.foreground = (p); \ _macro_gc_values.fill_style = FillSolid; \ XChangeGC((d),(g), GCForeground | GCFillStyle, &_macro_gc_values); \ } #define SetTiledGC(d,g,p) \ { \ XGCValues _macro_gc_values; \ _macro_gc_values.tile = (p); \ _macro_gc_values.fill_style = FillTiled; \ XChangeGC((d),(g), GCTile | GCFillStyle, &_macro_gc_values); \ } #define SetTiledXYGC(d,g,p,x,y) \ { \ XGCValues _macro_gc_values; \ _macro_gc_values.tile = (p); \ _macro_gc_values.fill_style = FillTiled; \ _macro_gc_values.ts_x_origin = (x); \ _macro_gc_values.ts_y_origin = (y); \ XChangeGC((d),(g), GCTile | GCFillStyle | GCTileStipXOrigin | \ GCTileStipYOrigin, &_macro_gc_values); \ } #define SetStippledGC(d,g,p) \ { \ XGCValues _macro_gc_values; \ _macro_gc_values.stipple = (p); \ _macro_gc_values.fill_style = FillStippled; \ _macro_gc_values.ts_x_origin = (x); \ _macro_gc_values.ts_y_origin = (y); \ XChangeGC((d),(g), GCStipple | GCFillStyle | GCTileStipXOrigin | \ GCTileStipYOrigin, &_macro_gc_values); \ } #define SetStippledXYGC(d,g,p,x,y) \ { \ XGCValues _macro_gc_values; \ _macro_gc_values.stipple = (p); \ _macro_gc_values.fill_style = FillStippled; \ _macro_gc_values.ts_x_origin = (x); \ _macro_gc_values.ts_y_origin = (y); \ XChangeGC((d),(g), GCStipple | GCFillStyle | GCTileStipXOrigin | \ GCTileStipYOrigin, &_macro_gc_values); \ } #define XiBackgroundSpecified(i) \ ((i)->background != XmCOLOR_DYNAMIC || \ ValidPixmap((i)->background_pixmap)) #define SetBackgroundGC(t,i,g) \ { \ if( ValidPixmap((i)->background_pixmap) ) \ { \ SetTiledGC(XtDisplay(t), (g), (i)->background_pixmap); \ } \ else \ { \ SetSolidGC(XtDisplay(t), (g), (i)->background); \ }\ } #define XiSelectSpecified(t) \ (XmTabBox_select_color((t)) != XmCOLOR_DYNAMIC || \ ValidPixmap(XmTabBox_select_pixmap((t)))) #define SetSelectGC(t,g) \ { \ if( ValidPixmap(XmTabBox_select_pixmap((t))) ) \ { \ SetTiledGC(XtDisplay(t), (g), XmTabBox_select_pixmap((t))); \ } \ else \ { \ SetSolidGC(XtDisplay(t), (g), XmTabBox_select_color((t))); \ }\ } #define XiChildSpecified(c) \ (XmTabStackC_tab_background(c) != XmCOLOR_DYNAMIC || \ ValidPixmap(XmTabStackC_tab_background_pixmap(c))) #define RemoveStipple(d,g) XSetFillStyle((d),(g), FillSolid) static XtActionsRec actions[] = { { "XmTabBoxArmAndActivate", (XtActionProc) XmTabBoxArmAndActivate }, { "XmTabBoxArmTab", (XtActionProc) XmTabBoxArmTab }, { "XmTabBoxSelectTab", (XtActionProc) XmTabBoxSelectTab }, { "XmTabBoxTraverseRight", (XtActionProc) XmTabBoxTraverseRight }, { "XmTabBoxTraverseLeft", (XtActionProc) XmTabBoxTraverseLeft }, { "XmTabBoxTraverseUp", (XtActionProc) XmTabBoxTraverseUp }, { "XmTabBoxTraverseDown", (XtActionProc) XmTabBoxTraverseDown }, { "XmTabBoxTraversePrevious", (XtActionProc) XmTabBoxTraversePrevious }, { "XmTabBoxTraverseNext", (XtActionProc) XmTabBoxTraverseNext }, }; static char traversal_translations[] = "osfRight: XmTabBoxTraverseRight()\n\ osfLeft: XmTabBoxTraverseLeft()\n\ osfUp: XmTabBoxTraverseUp()\n\ osfDown: XmTabBoxTraverseDown()\n\ ~c s Tab: PrimitivePrevTabGroup()\n\ ~c ~s Tab: PrimitiveNextTabGroup()\n\ c s Tab: PrimitivePrevTabGroup()\n\ c ~s Tab: PrimitiveNextTabGroup()\n\ osfHelp: PrimitiveHelp()\n\ : PrimitiveFocusIn()\n\ : PrimitiveFocusOut()\n\ : PrimitiveEnter()\n\ : PrimitiveLeave()\n\ : PrimitiveUnmap()"; static char canvas_translations[] = ": XmTabBoxArmTab()\n\ : XmTabBoxSelectTab()\n\ osfActivate: XmTabBoxArmAndActivate()\n\ space: XmTabBoxArmAndActivate()"; /* because this is a private widget for the TabStack, the resources are ** assumed already to be in pixels */ static XtResource resources[] = { /* Inherit (but changed default) resources */ { XmNshadowThickness, XmCShadowThickness, XmRDimension, sizeof(Dimension), XtOffsetOf(XmManagerRec, manager.shadow_thickness), XmRImmediate, (XtPointer) 2 }, /* TabBox Resources */ { XmNtabStyle, XmCTabStyle, XmRTabStyle, sizeof(XmTabStyle), XtOffsetOf(XmTabBoxRec, tab_box.tab_style), XmRImmediate, (XtPointer) XmTABS_BEVELED }, { XmNtabMode, XmCTabMode, XmRTabMode, sizeof(XmTabMode), XtOffsetOf(XmTabBoxRec, tab_box.tab_mode), XmRImmediate, (XtPointer) XmTABS_BASIC }, { XmNtabList, XmCTabList, XmRTabList, sizeof(XmTabbedStackList), XtOffsetOf(XmTabBoxRec, tab_box.tab_list), XmRImmediate, (XtPointer) NULL }, { XmNtabOrientation, XmCTabOrientation, XmRTabOrientation, sizeof(XmTabOrientation), XtOffsetOf(XmTabBoxRec, tab_box.tab_orientation), XmRImmediate, (XtPointer) XmTABS_LEFT_TO_RIGHT }, { XmNtabAutoSelect, XmCTabAutoSelect, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmTabBoxRec, tab_box.tab_auto_select), XmRImmediate, (XtPointer) True }, { XmNorientation, XmCOrientation, XmROrientation, sizeof(unsigned char), XtOffsetOf(XmTabBoxRec, tab_box.orientation), XmRImmediate, (XtPointer) XmHORIZONTAL }, { XmNuniformTabSize, XmCUniformTabSize, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmTabBoxRec, tab_box.uniform_tab_size), XmRImmediate, (XtPointer) True }, { XmNtabSelectColor, XmCTabSelectColor, XmRXmPixel, sizeof(Pixel), XtOffsetOf(XmTabBoxRec, tab_box.select_color), XmRImmediate, (XtPointer) XmCOLOR_DYNAMIC }, { XmNtabSelectPixmap, XmCTabSelectPixmap, XmRXmPixmap, sizeof(Pixel), XtOffsetOf(XmTabBoxRec, tab_box.select_pixmap), XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP }, { XmNtabMarginWidth, XmCMarginWidth, XmRDimension, sizeof(Dimension), XtOffsetOf(XmTabBoxRec, tab_box.tab_margin_width), XmRImmediate, (XtPointer) 2 }, { XmNtabMarginHeight, XmCMarginHeight, XmRDimension, sizeof(Dimension), XtOffsetOf(XmTabBoxRec, tab_box.tab_margin_height), XmRImmediate, (XtPointer) 2 }, { XmNtabLabelSpacing, XmCTabLabelSpacing, XmRDimension, sizeof(Dimension), XtOffsetOf(XmTabBoxRec, tab_box.tab_label_spacing), XmRImmediate, (XtPointer) 2 }, { XmNtabCornerPercent, XmCTabCornerPercent, XmRInt, sizeof(int), XtOffsetOf(XmTabBoxRec, tab_box.tab_corner_percent), XmRImmediate, (XtPointer) 40 }, { XmNnumStacks, XmCNumStacks, XmRInt, sizeof(int), XtOffsetOf(XmTabBoxRec, tab_box.num_stacks), XmRImmediate, (XtPointer) 5 }, #ifdef SCROLLED_LAYOUT { XmNtabArrowPlacement, XmCTabArrowPlacement, XmRTabArrowPlacement, sizeof(int), XtOffsetOf(XmTabBoxRec, tab_box.arrow_placement), XmRImmediate, (XtPointer) XmTAB_ARROWS_ON_LEFT }, #endif { XmNtabEdge, XmCTabEdge, XmRTabEdge, sizeof(XmTabEdge), XtOffsetOf(XmTabBoxRec, tab_box.tab_edge), XmRImmediate, (XtPointer) XmTAB_EDGE_BOTTOM_RIGHT }, { XmNtabOffset, XmCTabOffset, XmRDimension, sizeof(Dimension), XtOffsetOf(XmTabBoxRec, tab_box.tab_offset), XmRImmediate, (XtPointer) 10 }, { "pri.vate", "Pri.vate", XmRBoolean, sizeof(Boolean), XtOffsetOf(XmTabBoxRec, tab_box.check_set_render_table), XmRImmediate, (XtPointer) False }, { XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), XtOffsetOf(XmTabBoxRec, tab_box.font_list), XmRCallProc, (XtPointer) CheckSetRenderTable }, { XmNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable), XtOffsetOf(XmTabBoxRec, tab_box.font_list), XmRCallProc, (XtPointer) CheckSetRenderTable }, { XmNhighlightThickness, XmCHighlightThickness, XmRDimension, sizeof(Dimension), XtOffsetOf(XmTabBoxRec, tab_box.highlight_thickness), XmRImmediate, (XtPointer) 2 }, { XmNstackedEffect, XmCStackedEffect, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmTabBoxRec, tab_box.stacked_effect), XmRImmediate, (XtPointer) True }, { XmNuseImageCache, XmCUseImageCache, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmTabBoxRec, tab_box.use_image_cache), XmRImmediate, (XtPointer) True }, { XmNselectedIndex, XmCSelectedIndex, XmRInt, sizeof(int), XtOffsetOf(XmTabBoxRec, tab_box.selected_index), XmRImmediate, (XtPointer) -1 }, { XmNtraversalIndex, XmCTraversalIndex, XmRInt, sizeof(int), XtOffsetOf(XmTabBoxRec, tab_box.traversal_index), XmRImmediate, (XtPointer) -1 }, { XmNselectCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmTabBoxRec, tab_box.select_callback), XmRImmediate, (XtPointer) NULL }, { XmNunselectCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffsetOf(XmTabBoxRec, tab_box.unselect_callback), XmRImmediate, (XtPointer) NULL } }; typedef struct _XiTabCanvasClassPart { XtPointer extension; } XiTabCanvasClassPart; typedef struct _XiTabCanvasClassRec { CoreClassPart core_class; XmPrimitiveClassPart primitive_class; XiTabCanvasClassPart canvas_class; } XiTabCanvasClassRec; typedef struct _XiTabCanvasPart { XtPointer extension; } XiTabCanvasPart; typedef struct _XiTabCanvasRec { CorePart core; XmPrimitivePart primitive; XiTabCanvasPart canvas; } XiTabCanvasRec; XiTabCanvasClassRec xmTabCanvasClassRec = { { /* Core Fields */ /* superclass */ (WidgetClass) &xmPrimitiveClassRec, /* class_name */ "XiTabCanvas", /* widget_size */ sizeof(XiTabCanvasRec), /* class_initialize */ TabCanvasClassInitialize, /* chained class init */ ClassPartInitialize, /* class_inited */ False, /* initialize */ NULL, /* initialize hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ NULL, /* num_resources */ 0, /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ XtExposeCompressMultiple, /* compress enter/exit*/ True, /* visible_interest */ False, /* destroy */ NULL, /* resize */ NULL, /* expose */ Redisplay, /* set_values */ NULL, /* set values hook */ NULL, /* set values almost */ XtInheritSetValuesAlmost, /* get values hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback offsetlst */ NULL, /* default trans */ canvas_translations, /* query geo proc */ QueryGeometry, /* display accelerator*/ NULL, /* extension record */ (XtPointer) NULL }, { /* OSF/Motif Primitive Fields */ /* border_highlight */ BorderHighlight, /* border_unhighlight */ BorderUnhighlight, /* translations */ traversal_translations, /* arm_and_activate */ NULL, /* syn resources */ NULL, /* num syn_resources */ 0, /* extension */ NULL }, { /* EPak Tab Canvas Fields */ /* extension */ NULL } }; XmTabBoxClassRec xmTabBoxClassRec = { { /* Core Fields */ /* superclass */ (WidgetClass) &xmManagerClassRec, /* class_name */ "XmTabBox", /* widget_size */ sizeof(XmTabBoxRec), /* class_initialize */ ClassInitialize, /* class_part_initial */ NULL, /* class_inited */ False, /* initialize */ Initialize, /* initialize hook */ NULL, /* realize */ Realize, /* actions */ actions, /* num_actions */ XtNumber(actions), /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ XtExposeCompressMultiple, /* compress enter/exit*/ True, /* visible_interest */ False, /* destroy */ Destroy, /* resize */ Resize, /* expose */ NULL, /* set_values */ SetValues, /* set values hook */ NULL, /* set values almost */ XtInheritSetValuesAlmost, /* get values hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback offsetlst */ NULL, /* default trans */ XtInheritTranslations, /* query geo proc */ QueryGeometry, /* display accelerator*/ NULL, /* extension record */ (XtPointer) NULL }, { /* Composite Fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ (XtPointer) NULL }, { /* Constraint Fields */ /* resources */ NULL, /* num_resources */ 0, /* constraint_size */ sizeof (XmManagerConstraintRec), /* initialize */ NULL, /* destroy */ NULL, /* set_values */ NULL, /* extension */ (XtPointer) NULL }, { /* OSF/Motif Manager Fields */ /* translations */ XtInheritTranslations, /* syn_resources */ NULL, /* num_syn_resources */ 0, /* syn_resources */ NULL, /* num_syn_resources */ 0, /* parent_process */ XmInheritParentProcess, /* extension */ (XtPointer) NULL }, { /* EPak Tab Box Fields */ /* extension */ (XtPointer) NULL } }; WidgetClass xmTabCanvasWidgetClass = (WidgetClass) &xmTabCanvasClassRec; WidgetClass xmTabBoxWidgetClass = (WidgetClass) &xmTabBoxClassRec; static void #ifndef _NO_PROTO TabCanvasClassInitialize(void) #else TabCanvasClassInitialize() #endif { /* do nothing */ } /* * ClassPartInitialize sets up the fast subclassing for the widget. */ static void #ifdef _NO_PROTO ClassPartInitialize(w_class) WidgetClass w_class ; #else ClassPartInitialize(WidgetClass w_class) #endif /* _NO_PROTO */ { _XmFastSubclassInit (w_class, XmTABBOX_BIT); } static void #ifndef _NO_PROTO ClassInitialize(void) #else ClassInitialize() #endif { XtSetTypeConverter(XmRString, XmRTabOrientation, CvtStringToTabOrientation, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XmRString, XmRTabStyle, CvtStringToTabStyle, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XmRString, XmRTabMode, CvtStringToTabMode, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XmRString, XmRTabEdge, CvtStringToTabEdge, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XmRString, XmRTabSide, CvtStringToTabSide, NULL, 0, XtCacheNone, NULL); #ifdef SCROLLED_LAYOUT XtSetTypeConverter(XmRString, XmRTabArrowPlacement, CvtStringToArrowPlacement, NULL, 0, XtCacheNone, NULL); #endif XtSetTypeConverter(XmRString, XmRTabList, CvtStringToTabList, NULL, 0, XtCacheNone, CvtDestroyTabList); } static void #ifndef _NO_PROTO Initialize(Widget request, Widget set, ArgList arg_list, Cardinal *arg_cnt) #else Initialize(request, set, arg_list, arg_cnt) Widget request, set; ArgList arg_list; Cardinal *arg_cnt; #endif { XmTabBoxWidget st = (XmTabBoxWidget) set; XRectangle want; ArgList filtered_args; Cardinal num_filtered_args; XmTabBox__inited(st) = False; /* * Lets start by first making a copy of our TabList. We do this so * that we are not sharing memory with the user. */ XmTabBox_tab_list(st) = XmTabbedStackListCopy(XmTabBox_tab_list(st)); /* * Now lets see if the creator set our font list and if not lets * grab the default. */ if( XmTabBox_font_list(st) == NULL ) { XmTabBox_font_list(st) = XmeGetDefaultRenderTable((Widget) st, XmLABEL_FONTLIST); } XmTabBox_font_list(st) = XmFontListCopy(XmTabBox_font_list(st)); _XmFilterArgs(arg_list, *arg_cnt, xm_std_filter, &filtered_args, &num_filtered_args); XmTabBox__canvas(st) = XtCreateManagedWidget("canvas", xmTabCanvasWidgetClass, set, filtered_args, num_filtered_args); #ifdef SCROLLED_LAYOUT XmTabBox__left_arrow(st) = XtCreateWidget("leftArrow", xmArrowButtonWidgetClass, set, filtered_args, num_filtered_args); XmTabBox__right_arrow(st) = XtCreateWidget("rightArrow", xmArrowButtonWidgetClass, set, filtered_args, num_filtered_args); #endif XtFree((XtPointer)filtered_args); XmTabBox__bitmap(st) = XmUNSPECIFIED_PIXMAP; XmTabBox__bitmap_width(st) = XmTabBox__bitmap_height(st) = 0; XmTabBox__zero_GC(st) = NULL; XmTabBox__one_GC(st) = NULL; XmTabBox__tab_GC(st) = NULL; XmTabBox__text_GC(st) = NULL; XmTabBox__wanted(st) = (XRectangle*) NULL; XmTabBox__num_wanted(st) = 0; XmTabBox__actual(st) = (XiTabRect*) NULL; XmTabBox__num_actual(st) = 0; XmTabBox__scroll_x(st) = 0; XmTabBox__selected(st) = -1; XmTabBox__keyboard(st) = -1; XmTabBox__armed_tab(st) = -1; XmTabBox__num_columns(st) = 0; XmTabBox__num_rows(st) = 0; XmTabBox__gray_stipple(st) = XmGetPixmapByDepth(XtScreen(st), "50_foreground", 1, 0, 1); XmTabBox__cache(st) = NULL; XmTabBox__cache_size(st) = 0; CalcCornerSize(st); CalcGeometry(st, &want); if( XtWidth(request) == 0 ) { set->core.width = want.width; } if( XtHeight(request) == 0 ) { set->core.height = want.height; } Resize((Widget) st); XmTabBox__inited(st) = True; } static void Realize(Widget widget, XtValueMask *value_mask, XSetWindowAttributes *attributes) { XmTabBoxWidget tb = (XmTabBoxWidget) widget; XGCValues gcValues; XFontStruct *font = NULL; XtGCMask gcMask; XtRealizeProc realize; _XmProcessLock(); realize = xmTabBoxWidgetClass->core_class.superclass->core_class.realize; _XmProcessUnlock(); (*realize) (widget, value_mask, attributes); /* * Now lets create a GC that we will use for drawing. We create * this GC as opposed to share it because we will be changing * attributes of it a, what seems like, random. */ XmeRenderTableGetDefaultFont(XmTabBox_font_list(tb), &font); gcValues.background = tb->core.background_pixel; gcMask = GCBackground; if (font) { gcValues.font = font->fid; gcMask |= GCFont; } /* CR03128 */ XmTabBox__tab_GC(tb) = XmTabBox__text_GC(tb) = XtGetGC(widget, gcMask, &gcValues); } static void #ifndef _NO_PROTO Destroy(Widget widget) #else Destroy(widget) Widget widget; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; XmTabbedStackListFree(XmTabBox_tab_list(tab)); XmFontListFree(XmTabBox_font_list(tab)); if( ValidPixmap(XmTabBox__bitmap(tab)) ) { XFreePixmap(XtDisplay(tab), XmTabBox__bitmap(tab)); } if( XmTabBox__zero_GC(tab) != NULL ) { XFreeGC(XtDisplay(tab), XmTabBox__zero_GC(tab)); } if( XmTabBox__one_GC(tab) != NULL ) { XFreeGC(XtDisplay(tab), XmTabBox__one_GC(tab)); } if( ValidPixmap(XmTabBox__gray_stipple(tab)) ) { XmDestroyPixmap(XtScreen(tab), XmTabBox__gray_stipple(tab)); } if( XmTabBox__cache(tab) != NULL ) { FreeImageCache(tab); } /* CR03218 */ if(XmTabBox__tab_GC(tab)) XtReleaseGC((Widget)tab, XmTabBox__tab_GC(tab)); XtFree((XtPointer) XmTabBox__actual(tab)); XtFree((XtPointer) XmTabBox__wanted(tab)); } static void #ifndef _NO_PROTO Resize(Widget widget) #else Resize(widget) Widget widget; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; Layout(tab); XtConfigureWidget(XmTabBox__canvas(tab), 0, 0, XtWidth(tab), XtHeight(tab), 0); if( XtIsRealized(XmTabBox__canvas(tab)) ) { XClearWindow(XtDisplay(widget), XiCanvas(tab)); Redisplay(XmTabBox__canvas(tab), NULL, False); } } static void #ifndef _NO_PROTO Redisplay(Widget widget, XEvent *event, Region region) #else Redisplay(widget, event, region) Widget widget; XEvent *event; Region region; #endif { Widget parent; XmTabBoxWidget tab = (XmTabBoxWidget) XtParent(widget); XmTabbedStackList list = XmTabBox_tab_list(tab); int count = _XmTabbedStackListCount(list), shadow = tab->manager.shadow_thickness; GC gc = XmTabBox__tab_GC(tab); Pixel pixel= 0 ; Pixmap pixmap= 0 ; XGCValues gcValues; /* CR03218 begin */ Boolean getNewGC = False; if(gc) { XGetGCValues(XtDisplay(widget), gc, GCBackground, &gcValues); if (tab->core.background_pixel != gcValues.background) { XtReleaseGC(widget, gc); getNewGC = True; } } else getNewGC = True; if (getNewGC) { XFontStruct *font = NULL; XtGCMask gcMask; XmeRenderTableGetDefaultFont(XmTabBox_font_list(tab), &font); gcValues.background = tab->core.background_pixel; gcMask = GCBackground; if (font) { gcValues.font = font->fid; gcMask |= GCFont; } XmTabBox__tab_GC(tab) = XmTabBox__text_GC(tab) = XtGetGC((Widget)tab, gcMask, &gcValues); } /* CR03218 end */ if( XmTabBox__inited(tab) == False ) return; /* * The first thing we want to do is fill in our background with the * same color/pixmap our parent has. This will give us a "see-through" * appearance. */ parent = XtParent(tab); /* * If our parent happens to be a tab stack then we know that we * actually want to look at the background of its parent. */ if( XmIsTabStack(parent) ) { parent = XtParent(parent); pixmap = parent->core.background_pixmap; pixel = parent->core.background_pixel; /* * If we are the grand child of a tab stack then we want to use * the background color of the active child. */ if( XmIsTabStack(parent) ) { XmTabStackWidget ts = (XmTabStackWidget) parent; Widget child; if( (child = ts->tab_stack._active_child) != NULL && XiChildSpecified(child) ) { pixel = XmTabStackC_tab_background(child); if( ValidPixmap(XmTabStackC_tab_background_pixmap(child)) ) { pixmap = XmTabStackC_tab_background_pixmap(child); } else { pixmap = XmUNSPECIFIED_PIXMAP; } } } } if( ValidPixmap(pixmap) ) { Widget kid; int x = 0, y = 0; /* * What we need to do here is find out the offset for the * tile. To do this we need to walk up our hierarchy until * we come accross our parent. */ for( kid = widget; kid != parent; kid = XtParent(kid) ) { x += kid->core.x; y += kid->core.y; } SetTiledXYGC(XtDisplay(tab), gc, pixmap, -x, -y); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } /* * Well if we have a region then lets set our clipping region so we * confine our drawing to that area. */ if( region != False ) { XSetRegion(XtDisplay(tab), XmTabBox__tab_GC(tab), region); XSetRegion(XtDisplay(tab), tab->manager.bottom_shadow_GC, region); XSetRegion(XtDisplay(tab), tab->manager.top_shadow_GC, region); XSetRegion(XtDisplay(tab), tab->manager.background_GC, region); } else { XSetClipMask(XtDisplay(tab), gc, None); XSetClipMask(XtDisplay(tab), tab->manager.bottom_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.top_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.background_GC, None); } if( XmTabBox_tab_mode(tab) != XmTABS_STACKED && XmTabBox_tab_mode(tab) != XmTABS_STACKED_STATIC ) { if( event == NULL || event->xany.type != Expose ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, 0, 0, XtWidth(widget), XtHeight(widget)); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); } } /* * Lets check something real quick first. If we do not have any * tabs then what we want to do is just draw a shadow line as an * edge. */ if( count == 0 ) { /* * It seems that we have no tabs so lets draw just the shadow * line with the correct GC in the correct place. */ switch( XmTabBox_tab_edge(tab) ) { case XmTAB_EDGE_BOTTOM_RIGHT: default: /* * Well if appears that we need to draw the shadow line either * on the bottom or the right so lets check our orientation * to decide which one. */ if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { /* * Here we need to draw a shadow along the bottom * edge of our window and a beveled corner on the * right side. */ XFillRectangle(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, 0, (int)XtHeight(widget) - shadow, XtWidth(widget), shadow); XmDrawBevel(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(widget) - shadow, (int)XtHeight(widget) - shadow, shadow, XmBEVEL_BOTH); } else { /* * Here we need to draw a shadow along the right side and * a beveled corner on the bottom. */ XFillRectangle(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, (int)XtWidth(widget) - shadow, 0, shadow, XtHeight(widget)); XmDrawBevel(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(widget) - shadow, (int)XtHeight(widget) - shadow, shadow, XmBEVEL_BOTH); } break; case XmTAB_EDGE_TOP_LEFT: /* * Well if appears that we need to draw the shadow line either * on the top or the left side so lets check our orientation * to decide which one. */ if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { /* * Here we need to draw a line across the top of our * window and a corner in the left. */ XFillRectangle(XtDisplay(widget), XtWindow(widget), tab->manager.bottom_shadow_GC, 0, 0, XtWidth(widget), shadow); XmDrawBevel(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, 0, 0, shadow, XmBEVEL_BOTH); } else { /* * Here we need a shadow along our windows left edge and * a coner towards the top. */ XFillRectangle(XtDisplay(widget), XtWindow(widget), tab->manager.bottom_shadow_GC, 0, 0, shadow, XtHeight(widget)); XmDrawBevel(XtDisplay(widget), XtWindow(widget), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, 0, 0, shadow, XmBEVEL_BOTH); } break; } if( region != False ) { XSetClipMask(XtDisplay(tab), XmTabBox__tab_GC(tab), None); XSetClipMask(XtDisplay(tab), tab->manager.bottom_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.top_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.background_GC, None); } return; } /* * Well if we have a region then lets set our clipping region so we * confine our drawing to that area. */ if( region != False ) { XSetRegion(XtDisplay(tab), XmTabBox__tab_GC(tab), region); XSetRegion(XtDisplay(tab), tab->manager.bottom_shadow_GC, region); XSetRegion(XtDisplay(tab), tab->manager.top_shadow_GC, region); XSetRegion(XtDisplay(tab), tab->manager.background_GC, region); } /* * Call this handy dandy tab redisplay routine. This is kindof the * equivalent to XmRedisplayGadgets. */ RedisplayTabs(tab, region); /* * Now lets do the orientation/mode dependant redisplay part. */ if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: HorizontalBasicRedisplay(tab); break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: HorizontalStackedRedisplay(tab); break; case XmTABS_OVERLAYED: break; case XmTABS_SCROLLED: break; } } else { switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: VerticalBasicRedisplay(tab); break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: VerticalStackedRedisplay(tab); break; case XmTABS_OVERLAYED: break; case XmTABS_SCROLLED: break; } } /* * If we set a clipping are, be sure to unset it since we are probably * using shared GCs. */ if( region != False ) { XSetClipMask(XtDisplay(tab), XmTabBox__tab_GC(tab), None); XSetClipMask(XtDisplay(tab), tab->manager.bottom_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.top_shadow_GC, None); XSetClipMask(XtDisplay(tab), tab->manager.background_GC, None); } } #define cfield(f) XmTabBox_##f(c_tab) #define rfield(f) XmTabBox_##f(r_tab) #define sfield(f) XmTabBox_##f(s_tab) static Boolean #ifndef _NO_PROTO SetValues(Widget current, Widget request, Widget set, ArgList arg_list, Cardinal *arg_cnt) #else SetValues(current, request, set, arg_list, arg_cnt) Widget current, request, set; ArgList arg_list; Cardinal *arg_cnt; #endif { XmTabBoxWidget c_tab = (XmTabBoxWidget) current, s_tab = (XmTabBoxWidget) set; Boolean need_layout = False, need_resize = False, clear_cache = False; ArgList filtered_args = NULL; Cardinal num_filtered_args = 0; /* * First lets start by passing down our resources to our children. */ if( XmTabBox__inited(s_tab) && XmTabBox__canvas(s_tab) != NULL ) { _XmFilterArgs(arg_list, *arg_cnt, xm_std_filter, &filtered_args, &num_filtered_args); XtSetValues(XmTabBox__canvas(s_tab), filtered_args, num_filtered_args); #ifdef SCROLLED_LAYOUT XtSetValues(XmTabBox__left_arrow(s_tab), filtered_args, num_filtered_args); XtSetValues(XmTabBox__right_arrow(s_tab), filtered_args, num_filtered_args); #endif XtFree((XtPointer)filtered_args); } if( XmTabBox_tab_list(c_tab) != XmTabBox_tab_list(s_tab) ) { if( XmTabbedStackListCompare(XmTabBox_tab_list(s_tab), XmTabBox_tab_list(c_tab)) == XmTAB_CMP_SIZE ) { clear_cache = True; need_resize = True; } XmTabbedStackListFree(XmTabBox_tab_list(c_tab)); XmTabBox_tab_list(c_tab) = (XmTabbedStackList) NULL; XmTabBox_tab_list(s_tab) = XmTabbedStackListCopy(XmTabBox_tab_list(s_tab)); CalcTabGeometry(s_tab); need_layout = True; } if( sfield(_selected) > _XmTabbedStackListCount(sfield(tab_list)) ) { sfield(_selected) = -1; if( _XmTabbedStackListCount(sfield(tab_list)) > 0 ) { sfield(_selected) = 0; } need_layout = True; } if( sfield(_keyboard) > _XmTabbedStackListCount(sfield(tab_list)) ) { sfield(_keyboard) = -1; if( _XmTabbedStackListCount(sfield(tab_list)) > 0 ) { sfield(_keyboard) = 0; } need_layout = True; } if( sfield(selected_index) != -1 || sfield(traversal_index) != -1 ) { sfield(_selected) = sfield(selected_index); sfield(_keyboard) = sfield(traversal_index); sfield(selected_index) = -1; sfield(traversal_index) = -1; need_layout = True; } if( cfield(font_list) != sfield(font_list) ) { XmFontListFree(cfield(font_list)); cfield(font_list) = (XmFontList) NULL; if( sfield(font_list) == NULL ) { sfield(font_list) = XmeGetDefaultRenderTable(set, XmLABEL_FONTLIST); } sfield(font_list) == XmFontListCopy(sfield(font_list)); need_layout = True; need_resize = True; } if( c_tab->manager.shadow_thickness != s_tab->manager.shadow_thickness || cfield(tab_style) != sfield(tab_style) || cfield(tab_mode) != sfield(tab_mode) || cfield(tab_orientation) != sfield(tab_orientation) || cfield(orientation) != sfield(orientation) || cfield(uniform_tab_size) != sfield(uniform_tab_size) || cfield(tab_margin_width) != sfield(tab_margin_width) || cfield(tab_margin_height) != sfield(tab_margin_height) || cfield(tab_label_spacing) != sfield(tab_label_spacing) || cfield(tab_corner_percent) != sfield(tab_corner_percent) || #ifdef SCROLLED_LAYOUT cfield(arrow_placement) != sfield(arrow_placement) || #endif cfield(tab_edge) != sfield(tab_edge) || cfield(tab_offset) != sfield(tab_offset) || cfield(highlight_thickness) != sfield(highlight_thickness) ) { need_layout = True; need_resize = True; } if( cfield(tab_orientation) != sfield(tab_orientation) ) { clear_cache = True; } if( cfield(use_image_cache) != sfield(use_image_cache) ) { if( sfield(use_image_cache) ) { clear_cache = True; } else { FreeImageCache(s_tab); clear_cache = False; } } if( clear_cache ) ResetImageCache(s_tab); if( need_layout ) { Resize(set); } /* * Now lets check to see if we are supposed to pick a new size, and * if we are lets find out that size. */ if( need_resize ) { XRectangle geom; CalcGeometry(s_tab, &geom); /* * Now that we know the size that we want to be lets set the * width and height for ourselves so the geometry can be * passed up to our parent. If that size is accepted we * should get a resize callback. */ if( XtWidth(request) == XtWidth(current) ) { s_tab->core.width = geom.width; } if( XtHeight(request) == XtHeight(current) ) { s_tab->core.height = geom.height; } } return( need_layout || need_resize ); } #undef cfield #undef rfield #undef sfield static XtGeometryResult #ifndef _NO_PROTO QueryGeometry(Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *allowed) #else QueryGeometry(widget, request, allowed) Widget widget; XtWidgetGeometry *request, *allowed; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; XRectangle rect; /* * Lets start with the easy case. If they gave us nothing then * lets return to them the geometry that we really want. */ if( request == NULL || request->request_mode == 0 ) { CalcGeometry(tab, &rect); allowed->request_mode = CWWidth | CWHeight; allowed->width = rect.width; allowed->height = rect.height; return( XtGeometryAlmost ); } /* * If we got here that means that they are asking us something so * lets see what they want. We will first check if they are * inquering about something other then width and height, because * we only care about width and height. If they give us something * else we will gladly accept it. */ if( !(request->request_mode & (CWWidth | CWHeight)) ) { /* * Ok it appears that they only care about attributes that we * do not care about so lets just return them a big YES. */ return( XtGeometryYes ); } /* * Now comes the big work. It appears that they gave us a partial * or suggested geometry and they want to know how we will react to * that geometry. Since we have an orientation we will take our * major dimension and give that priority. */ *allowed = *request; allowed->request_mode |= (CWWidth | CWHeight); if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { if( request->request_mode & CWWidth ) { /* * They gave us a width so lets take that width and figure * out our minor dimension using that width. */ allowed->height = CalcGeometryMinor(tab, (int)request->width); } else if( request->request_mode & CWHeight ) { /* * Well it looks like they gave us the minor geometry they * want us to fit into so lets calculate the major. */ allowed->width = CalcGeometryMinor(tab, (int)request->height); } } else { if( request->request_mode & CWHeight ) { /* * They gave us a height so lets take that height and figure * out our minor dimension using that height. */ allowed->width = CalcGeometryMinor(tab, (int)request->height); } else if( request->request_mode & CWWidth ) { /* * Well it looks like they gave us the minor geometry they * want us to fit into so lets calculate the major. */ allowed->height = CalcGeometryMajor(tab, request->width); } } if( XmCompareXtWidgetGeometryToWidget(allowed, widget) ) { return( XtGeometryNo ); } if( XmCompareXtWidgetGeometry(request, allowed) ) return( XtGeometryYes ); return( XtGeometryAlmost ); } #define XmTAB_HIGHLIGHT_RECT 0 #define XmTAB_TEXT_RECT 1 static XRectangle* #ifndef _NO_PROTO GetTabRectangle(XmTabBoxWidget tab, int type, XiTabRect *draw) #else GetTabRectangle(tab, type, draw) XmTabBoxWidget tab; int type; XiTabRect *draw; #endif { static XRectangle rect; int highlight = XmTabBox_highlight_thickness(tab), shadow = tab->manager.shadow_thickness, margin_height = XmTabBox_tab_margin_height(tab), margin_width = XmTabBox_tab_margin_width(tab), spacing = XmTabBox_tab_label_spacing(tab), size, horiz, vert; if( draw == NULL ) { if( XmTabBox__keyboard(tab) >= 0 ) { draw = &(XmTabBox__actual(tab)[XmTabBox__keyboard(tab)]); } else { rect.x = rect.y = 0; rect.width = rect.height = 0; } } size = XmTabBox__corner_size(tab); if( draw->width < draw->height ) { AssignMin(size,(int)(draw->width/2)); } else { AssignMin(size,(int)draw->height/2); } margin_width += shadow; margin_height += shadow; if( type == XmTAB_HIGHLIGHT_RECT ) { horiz = Max(size, margin_width); vert = Max(size, margin_height); } else { horiz = Max(size, margin_width) + highlight + spacing; vert = Max(size, margin_height) + highlight + spacing; } switch( XmTabBox_tab_orientation(tab) ) { case XmTABS_LEFT_TO_RIGHT: case XmTABS_RIGHT_TO_LEFT: default: break; case XmTABS_TOP_TO_BOTTOM: case XmTABS_BOTTOM_TO_TOP: { int tmp = horiz; horiz = vert; vert = tmp; } break; } rect.x = draw->x + horiz; rect.y = draw->y + vert; rect.width = draw->width - (2 * horiz); rect.height = draw->height - (2 * vert); return( &rect ); } static void #ifndef _NO_PROTO DrawBorder(XmTabBoxWidget tab, GC gc, int idx) #else DrawBorder(tab, gc, idx) XmTabBoxWidget tab; GC gc; int idx; #endif { int highlight = XmTabBox_highlight_thickness(tab); XiTabRect *geometry; XRectangle *draw, rect[4]; XmTabAttributes info; if( idx < 0 ) { if( XmTabBox__keyboard(tab) < 0 ) return; geometry = &(XmTabBox__actual(tab)[XmTabBox__keyboard(tab)]); idx = XmTabBox__keyboard(tab); } else { geometry = &(XmTabBox__actual(tab)[idx]); } if( gc == tab->manager.background_GC && (((info = _XmTabbedStackListGet(XmTabBox_tab_list(tab), idx)) != NULL && XiBackgroundSpecified(info)) || (idx == XmTabBox__selected(tab) && XiSelectSpecified(tab))) ) { gc = XmTabBox__tab_GC(tab); if( idx == XmTabBox__selected(tab) && XiSelectSpecified(tab) ) { SetSelectGC(tab, gc); } else { SetBackgroundGC(tab, info, gc); } } draw = GetTabRectangle(tab, XmTAB_HIGHLIGHT_RECT, geometry); rect[0].x = draw->x; rect[0].y = draw->y; rect[0].width = Max((int)draw->width, 1); rect[0].height = highlight; rect[1].x = rect[0].x; rect[1].y = rect[0].y; rect[1].width = highlight; rect[1].height = Max((int)draw->height, 1); rect[2].x = rect[0].x + (int)draw->width - highlight; rect[2].y = rect[0].y; rect[2].width = highlight; rect[2].height = Max((int)draw->height, 1); rect[3].x = rect[0].x; rect[3].y = rect[0].y + (int)draw->height - highlight; rect[3].width = Max((int)draw->width, 1); rect[3].height = highlight; XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, 4); } static void #ifndef _NO_PROTO BorderHighlight(Widget widget) #else BorderHighlight(widget) Widget widget; #endif { XmTabBoxWidget tab = XiTabParent(widget); DrawBorder(tab, tab->manager.highlight_GC, -1); } static void #ifndef _NO_PROTO BorderUnhighlight(Widget widget) #else BorderUnhighlight(widget) Widget widget; #endif { XmTabBoxWidget tab = XiTabParent(widget); DrawBorder(tab, tab->manager.background_GC, -1); } /* * Function: * XmTabBoxArmAndActivate(widget, event, params, num_params) * Description: * This action is activate when keyboard traversal is used to * select a tab. This action selects the tabs and calls the * unselect and select callbacks. * Input: * widget : Widget - the XiTabCanvas * event : XEvent* - unused * params : String* - unused * num_params : Cardinal* - unused * Output: * None. */ /* ARGSUSED */ static void #ifndef _NO_PROTO XmTabBoxArmAndActivate(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxArmAndActivate(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old = XmTabBox__selected(tab), idx = XmTabBox__keyboard(tab); SelectTab(tab, event, old, idx); } /* ARGSUSED */ static void #ifndef _NO_PROTO XmTabBoxArmTab(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxArmTab(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old, idx; XmProcessTraversal(widget, XmTRAVERSE_CURRENT); if( event == NULL || event->xany.type != ButtonPress ) return; idx = XmTabBox__armed_tab(tab) = XiXYtoTab(tab, event->xbutton.x, event->xbutton.y); if( !IsTabSensitive(tab, idx) ) return; XmTabBox__armed_tab(tab) = idx; old = XmTabBox__keyboard(tab); if( idx != -1 && idx != old ) { DrawBorder(tab, tab->manager.background_GC, old); DrawBorder(tab, tab->manager.highlight_GC, idx); XmTabBox__keyboard(tab) = idx; } } /* * Function: * XmTabBoxSelected(widget, event, params, num_params) * Description: * This action selects a tab and calls the select and unselect * callbacks. * Input: * widget : Widget - the XiTabCanvas * event : XEvent* - the event that triggered the action * params : String* - unused * num_params : Cardinal* - unused * Output: * None. */ /* ARGSUSED */ static void #ifndef _NO_PROTO XmTabBoxSelectTab(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxSelectTab(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int idx; /* * First lets do a quick check to make sure that we have an event we * can deal with and that we have an armed tab. */ if( event == NULL || event->xany.type != ButtonRelease || XmTabBox__armed_tab(tab) == -1 ) return; /* * Lets find out which tab was activated by converting the event * x, y to a tab index. */ idx = XiXYtoTab(tab, event->xbutton.x, event->xbutton.y); /* * First lets make sure that we are trying to select the right tab * we do this my making sure it is not already selected and by * making sure it is the currently armed tab. */ if( idx == XmTabBox__selected(tab) || idx != XmTabBox__armed_tab(tab) || !IsTabSensitive(tab, idx) ) { XmTabBox__armed_tab(tab) = -1; return; } XmTabBox__armed_tab(tab) = -1; SelectTab(tab, event, XmTabBox__selected(tab), idx); } static void #ifndef _NO_PROTO _XmTabBoxTraverseRight(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else _XmTabBoxTraverseRight(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old, old_selected, set, col; switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_SCROLLED: case XmTABS_OVERLAYED: default: XmTabBoxTraverseNext(widget, event, params, num_params); return; break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: old = XmTabBox__keyboard(tab); col = XmTabBox__actual(tab)[old].column; do { set = GetTabIndex(tab, XmTabBox__actual(tab)[old].row, ++col); if( set < 0 ) return; } while( !IsTabSensitive(tab, set) ); if( set < 0 || set == old ) return; old_selected = XmTabBox__selected(tab); XmTabBox__keyboard(tab) = set; DrawBorder(tab, tab->manager.background_GC, old); if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, set); } else { DrawBorder(tab, tab->manager.highlight_GC, set); } break; } } /* argsused */ static void #ifndef _NO_PROTO XmTabBoxTraverseRight(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraverseRight(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); if( XmTabBox_orientation(tab) == XmVERTICAL ) { _XmTabBoxTraverseDown(widget, event, params, num_params); } else { _XmTabBoxTraverseRight(widget, event, params, num_params); } } static void #ifndef _NO_PROTO _XmTabBoxTraverseLeft(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else _XmTabBoxTraverseLeft(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old, old_selected, set, col; switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_SCROLLED: case XmTABS_OVERLAYED: default: XmTabBoxTraversePrevious(widget, event, params, num_params); return; break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: old = XmTabBox__keyboard(tab); col = XmTabBox__actual(tab)[old].column; do { set = GetTabIndex(tab, XmTabBox__actual(tab)[old].row, --col); if( set < 0 ) return; } while( !IsTabSensitive(tab, set) ); if( set < 0 || set == old ) return; old_selected = XmTabBox__selected(tab); XmTabBox__keyboard(tab) = set; DrawBorder(tab, tab->manager.background_GC, old); if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, set); } else { DrawBorder(tab, tab->manager.highlight_GC, set); } break; } } static void #ifndef _NO_PROTO XmTabBoxTraverseLeft(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraverseLeft(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); if( XmTabBox_orientation(tab) == XmVERTICAL ) { _XmTabBoxTraverseUp(widget, event, params, num_params); } else { _XmTabBoxTraverseLeft(widget, event, params, num_params); } } static void #ifndef _NO_PROTO _XmTabBoxTraverseUp(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else _XmTabBoxTraverseUp(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old, old_selected, set, old_row, new_row; switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_SCROLLED: case XmTABS_OVERLAYED: default: XmTabBoxTraversePrevious(widget, event, params, num_params); return; break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: old = XmTabBox__keyboard(tab); new_row = old_row = XmTabBox__actual(tab)[old].row; do { if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { do { new_row++; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED && XmTabBox_tab_auto_select(tab) ) { if( new_row >= XmTabBox__num_rows(tab) ) { new_row = 0; } } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( set >= 0 && !IsTabSensitive(tab, set) && new_row != old_row ); } else { do { new_row--; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED && XmTabBox_tab_auto_select(tab) ) { if( new_row < 0 ) { new_row = XmTabBox__num_rows(tab) - 1; } } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( set >= 0 && !IsTabSensitive(tab, set) && new_row != old_row ); } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( new_row >= 0 && new_row < XmTabBox__num_rows(tab) && set < 0 ); if( set < 0 || set == old || new_row == old_row ) return; old_selected = XmTabBox__selected(tab); XmTabBox__keyboard(tab) = set; DrawBorder(tab, tab->manager.background_GC, old); if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, set); } else { DrawBorder(tab, tab->manager.highlight_GC, set); } break; } } static void #ifndef _NO_PROTO XmTabBoxTraverseUp(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraverseUp(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); if( XmTabBox_orientation(tab) == XmVERTICAL ) { _XmTabBoxTraverseLeft(widget, event, params, num_params); } else { _XmTabBoxTraverseUp(widget, event, params, num_params); } } static void #ifndef _NO_PROTO _XmTabBoxTraverseDown(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else _XmTabBoxTraverseDown(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int old, old_selected, set, new_row, old_row; switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_SCROLLED: case XmTABS_OVERLAYED: default: XmTabBoxTraverseNext(widget, event, params, num_params); return; break; case XmTABS_STACKED: case XmTABS_STACKED_STATIC: old = XmTabBox__keyboard(tab); new_row = old_row = XmTabBox__actual(tab)[old].row ; do { if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { do { new_row--; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED && XmTabBox_tab_auto_select(tab) ) { if( new_row < 0 ) { new_row = XmTabBox__num_rows(tab) - 1; } } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( set >= 0 && !IsTabSensitive(tab, set) && new_row != old_row ); } else { do { new_row++; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED && XmTabBox_tab_auto_select(tab) ) { if( new_row >= XmTabBox__num_rows(tab) ) { new_row = 0; } } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( set >= 0 && !IsTabSensitive(tab, set) && new_row != old_row ); } set = GetTabIndex(tab, new_row, XmTabBox__actual(tab)[old].column); } while( new_row >= 0 && new_row < XmTabBox__num_rows(tab) && set < 0 ); if( set < 0 || set == old || new_row == old_row ) return; old_selected = XmTabBox__selected(tab); XmTabBox__keyboard(tab) = set; DrawBorder(tab, tab->manager.background_GC, old); if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, set); } else { DrawBorder(tab, tab->manager.highlight_GC, set); } break; } } static void #ifndef _NO_PROTO XmTabBoxTraverseDown(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraverseDown(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); if( XmTabBox_orientation(tab) == XmVERTICAL ) { _XmTabBoxTraverseRight(widget, event, params, num_params); } else { _XmTabBoxTraverseDown(widget, event, params, num_params); } } /* ARGSUSED */ static void #ifndef _NO_PROTO XmTabBoxTraversePrevious(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraversePrevious(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), idx, old, tmp, old_selected; if( cnt == 0 ) return; old = XmTabBox__keyboard(tab); old_selected = XmTabBox__selected(tab); idx = old; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC ) { do { tmp = idx; idx = tmp - 1; if( idx < 0 ) idx = cnt - 1; if( idx == tmp ) return; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC ) { if( XmTabBox__actual(tab)[idx].row != XmTabBox__actual(tab)[tmp].row && XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { int row = XmTabBox__actual(tab)[tmp].row + 1, col; if ( row >= XmTabBox__num_rows(tab) ) row = 0; for( col = XmTabBox__num_columns(tab) - 1; col > 0 && (idx = GetTabIndex(tab, row, col)) < 0; --col ); } } } while( !IsTabSensitive(tab, idx) && idx != old ); } else { do { idx = idx - 1; if( idx < 0 ) idx = cnt - 1; } while( !IsTabSensitive(tab, idx) && idx != old ); } if( idx < 0 || idx == old ) return; DrawBorder(tab, tab->manager.background_GC, old); XmTabBox__keyboard(tab) = idx; if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, idx); } else { DrawBorder(tab, tab->manager.highlight_GC, idx); } } /* ARGSUSED */ static void #ifndef _NO_PROTO XmTabBoxTraverseNext(Widget widget, XEvent *event, String *params, Cardinal *num_params) #else XmTabBoxTraverseNext(widget, event, params, num_params) Widget widget; XEvent *event; String *params; Cardinal *num_params; #endif { XmTabBoxWidget tab = XiTabParent(widget); int cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), idx, old, tmp, old_selected; if( cnt == 0 ) return; old = XmTabBox__keyboard(tab); old_selected = XmTabBox__selected(tab); idx = old; if( XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC ) { do { tmp = idx; idx = (idx + 1) % cnt; if( XmTabBox__actual(tab)[idx].row != XmTabBox__actual(tab)[tmp].row && XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { int row = XmTabBox__actual(tab)[tmp].row - 1; if( row < 0 ) row = XmTabBox__num_rows(tab) - 1; idx = GetTabIndex(tab, row, 0); } } while( !IsTabSensitive(tab, idx) && idx != old ); } else { do { idx = (idx + 1) % cnt; } while( !IsTabSensitive(tab, idx) && idx != old ); } if( idx < 0 || idx == old ) return; DrawBorder(tab, tab->manager.background_GC, old); XmTabBox__keyboard(tab) = idx; if( XmTabBox_tab_auto_select(tab) ) { SelectTab(tab, event, old_selected, idx); } else { DrawBorder(tab, tab->manager.highlight_GC, idx); } } static void #ifndef _NO_PROTO CalcTabSize(XmTabBoxWidget tab, XmTabAttributes info, XmTabOrientation orientation, XmFontList font_list, int shadow_thickness, int highlight_thickness, int margin_width, int margin_height, int spacing, int corner_size, Dimension *width, Dimension *height) #else CalcTabSize(tab, info, orientation, font_list, shadow_thickness, highlight_thickness, margin_width, margin_height, spacing, corner_size, width, height) XmTabBoxWidget tab; XmTabAttributes info; XmTabOrientation orientation; XmFontList font_list; int shadow_thickness, highlight_thickness, margin_width, margin_height, spacing, corner_size; Dimension *width, *height; #endif { Boolean have_label = False, have_pixmap = False; Dimension _width = 0, _height = 0; /* * First lets take the quick out if we were not given a valid * tab. */ if( info == NULL ) { *width = *height = 0; return; } /* * The size of a tab is determined by the combined geometry of ... * * - Label (if visible) * - Pixmap (if visible) * - highlight border (width/height) * - margins (width/height) * - shadows (width/height) * - corner size * */ /* * Lets first see if we have a visible label string and if so lets * add it to the size of the tab. */ if( info->label_string != NULL && info->pixmap_placement != XmPIXMAP_ONLY ) { Dimension string_width = 0, string_height = 0; /* * We have a label String so lets find out its dimensions and * add them to the size of the tab. */ XmStringExtent(font_list, info->label_string, &string_width, &string_height); _width += string_width; AssignMax(_height, string_height); have_label = True; } /* * Now lets check to see if we have to deal with a pixmap, and if * so lets do that. */ if( ValidPixmap(info->label_pixmap) && info->pixmap_placement != XmPIXMAP_NONE ) { Window window_unused; int int_unused; unsigned int uint_unused, width_return, height_return; /* * We have a pixmap, so lets see what the size of this pixmap * is. */ XGetGeometry(XtDisplay(tab), info->label_pixmap, &window_unused, &int_unused, &int_unused, &width_return, &height_return, &uint_unused, &uint_unused); /* * We will add the geometry for the pixmap to the overall geometry * based on the placement of the pixmap in relation to the * label string. */ switch( info->pixmap_placement ) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: _height += height_return; AssignMax(_width, width_return); break; case XmPIXMAP_RIGHT: case XmPIXMAP_LEFT: case XmPIXMAP_ONLY: _width += width_return; AssignMax(_height, height_return); break; case XmPIXMAP_NONE: default: /* notreached */ break; } have_pixmap = True; } /* * If we have both a label and a pixmap we need to accomidate some * spacing between them so lets check if we have them and add the * space to the appropriate place. */ if( have_label && have_pixmap ) { switch( info->pixmap_placement ) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: _height += spacing; break; case XmPIXMAP_LEFT: case XmPIXMAP_RIGHT: _width += spacing; break; case XmPIXMAP_NONE: case XmPIXMAP_ONLY: default: /* notreached */ break; } } /* * Lets add shadow thickness to our margin, because we are going to * consider both of them to see if we should use them or the * corner size. */ margin_width += shadow_thickness; margin_height += shadow_thickness; /* * Now lets add room for the traversal highlight and margins * around the label/pixmap. */ AssignMax(margin_width, corner_size); AssignMax(margin_height, corner_size); _height += 2 * (highlight_thickness + margin_height + spacing); _width += 2 * (highlight_thickness + margin_width + spacing); /* * Now lets set the result depending on the orientation of the * tab. */ switch( orientation ) { case XmTABS_TOP_TO_BOTTOM: case XmTABS_BOTTOM_TO_TOP: *width = _height; *height = _width; break; default: *width = _width; *height = _height; break; } } static void #ifndef _NO_PROTO CalcUnlimitedGeometry(XmTabBoxWidget tab, XRectangle *geometry) #else CalcUnlimitedGeometry(tab, geometry) XmTabBoxWidget tab; XRectangle *geometry; #endif { XmTabbedStackList list = XmTabBox_tab_list(tab); XmTabAttributes info; int i, count = _XmTabbedStackListCount(list), width, height, max_width, max_height, tab_width, tab_height; Boolean uniform_size; /* * Start by initializing the geometry variables. Although we are * calling these things width and height the may be revered depending * on the orientation of this thing. */ width = height = max_width = max_height = 0; /* * Now lets cashe some values so we don't have to look them up * or calculate them. */ uniform_size = XmTabBox_uniform_tab_size(tab); for( i = 0; i < count; ++i ) { Dimension d_width = 0, d_height = 0; /* * First the easy part, lets grabs tab and calculate its size. */ info = _XmTabbedStackListGet(list, i); XiCalcTabSize(tab, info, &d_width, &d_height); tab_width = (int) d_width; tab_height = (int) d_height; /* * Now that we know the size of this tab, we need to check what * that means. Because if we are going to a uniform look part * of that geometry may be droped. */ if( uniform_size ) { /* * If we are calculating for unform sized tabs then lets * just capture the max width and height of all the tabs * to use in calculations later. */ AssignMax(max_width, tab_width); AssignMax(max_height, tab_height); } else { /* * If we are not doing uniform tabs that means that the * major dimension of the tabs can vary. */ XmTabBox__wanted(tab)[i].width = tab_width; XmTabBox__wanted(tab)[i].height = tab_height; if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { width += tab_width; AssignMax(height, tab_height); } else { height += tab_height; AssignMax(width, tab_width); } } } /* * Now the big check. If we are dealing with uniform size tabs * then we want to calculate the width/height that we need based * on the max_width/max_height of all the tabs. */ if( uniform_size ) { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { width = count * max_width; height = max_height; } else { height = count * max_height; width = max_width; } for( i = 0; i < count; ++i ) { XmTabBox__wanted(tab)[i].width = max_width; XmTabBox__wanted(tab)[i].height = max_height; } } geometry->width = width; geometry->height = height; } /* * Function: * CalcGeometry(tab, geometry) * Description: * Calculates the desired geometry given no size constraints. * Input: * tab : XmTabBoxWidget - the tab box to work with * geometry : XRectangle* - returns the desired geometry * Output: * None. */ static void #ifndef _NO_PROTO CalcGeometry(XmTabBoxWidget tab, XRectangle *geometry) #else CalcGeometry(tab, geometry) XmTabBoxWidget tab; XRectangle *geometry; #endif { int count = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); /* * Lets start with the easy case. This is the case where we do not * have any tabs. In this case our desired size is simple the * room we need to draw single line shadow. */ if( count == 0 ) { /* * We have no tabs so the size we want is twice our shadow thinkness * in our major dimension and our shadow thickness in our minor * dimension. */ geometry->x = geometry->y = 0; if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { geometry->width = 2 * tab->manager.shadow_thickness; geometry->height = tab->manager.shadow_thickness; } else { geometry->width = tab->manager.shadow_thickness; geometry->height = 2 * tab->manager.shadow_thickness; } /* * One thing before we leave. If we have no tabs lets make * sure to "zero" out the index to the tab with keyboard * traversal and selected. */ XmTabBox__keyboard(tab) = -1; XmTabBox__selected(tab) = -1; /* * Since this is the easy case we are done, so lets just hop * out of this routine. */ return; } /* * The first thing we will do is calculate the size of each of the * tabs. We do this via this handy dandy Tab Calculation routine. */ CalcTabGeometry(tab); /* * Now lets make sure that we have a tab marked for both keyboard * traversal and selected. */ if( XmTabBox__keyboard(tab) < 0 ) XmTabBox__keyboard(tab) = 0; if( XmTabBox__selected(tab) < 0 ) XmTabBox__selected(tab) = 0; switch( XmTabBox_tab_mode(tab) ) { case XmTABS_STACKED: case XmTABS_STACKED_STATIC: CalcStackedGeometry(tab, geometry); break; case XmTABS_BASIC: case XmTABS_SCROLLED: case XmTABS_OVERLAYED: default: CalcUnlimitedGeometry(tab, geometry); break; } if( geometry->width == 0 ) geometry->width = 20; if( geometry->height == 0 ) geometry->height = 20; } static void #ifndef _NO_PROTO DrawSegments(XmTabBoxWidget tab, XmTabAttributes info, XiTabRect *geometry, XmTabEdge edge, int corner_size, int shadow, int selected) #else DrawSegments(tab, info, geometry, edge, corner_size, shadow, selected) XmTabBoxWidget tab; XmTabAttributes info; XiTabRect *geometry; XmTabEdge edge; int corner_size, shadow, selected; #endif { int size, cnt = 2; XRectangle rect[3]; Boolean stacked; GC gc = (GC)NULL; stacked = (XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC); /* * Lets set up the GC used to draw the shadow that may or may not be * visible depending on the selected state. */ if( selected ) { if( XiSelectSpecified(tab) ) { gc = XmTabBox__tab_GC(tab); SetSelectGC(tab, gc); } else { if( XiBackgroundSpecified(info) ) { gc = XmTabBox__tab_GC(tab); SetBackgroundGC(tab, info, gc); } else { gc = tab->manager.background_GC; } } } size = corner_size; switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, (int) geometry->height - size); rect[0].x = geometry->x + geometry->width - shadow; rect[0].y = geometry->y; rect[0].width = shadow; rect[0].height = (int) geometry->height - size; rect[1].x = geometry->x + size; rect[1].y = geometry->y + (int)geometry->height - shadow; rect[1].width = (int)geometry->width - (2 * size); rect[1].height = shadow; if( !selected && geometry->row == 0 ) { if( (geometry->column == 0 && !LayoutIsRtoLP(tab)) || ((geometry->column == XmTabBox__num_columns(tab)-1) && LayoutIsRtoLP(tab)) ) { rect[2].x = geometry->x + shadow; rect[2].width = (int)geometry->width - shadow; } else { rect[2].x = geometry->x; rect[2].width = geometry->width; } rect[2].y = geometry->y; rect[2].height = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, rect, cnt); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + shadow, geometry->y, (int)geometry->width - 2*shadow, shadow); if( geometry->row == 0 && ((geometry->column > 0 && !LayoutIsRtoLP(tab)) || ((geometry->column < XmTabBox__num_columns(tab)-1) && LayoutIsRtoLP(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTH); } } else if(geometry->row == 0 && ((geometry->column == 0 && !LayoutIsRtoLP(tab)) || ((geometry->column == XmTabBox__num_columns(tab)-1) && LayoutIsRtoLP(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTH); } } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, geometry->x, geometry->y, (int)geometry->width - size, shadow); rect[0].x = geometry->x; rect[0].y = geometry->y + (int)geometry->height - shadow; rect[0].width = (int)geometry->width - size; rect[0].height = shadow; rect[1].x = geometry->x + (int)geometry->width - shadow; rect[1].y = geometry->y + size; rect[1].width = shadow; rect[1].height = (int)geometry->height - (2 * size); if( !selected && geometry->row == 0 ) { if( geometry->column == 0 ) { rect[2].y = geometry->y + shadow; rect[2].height = (int)geometry->height - shadow; } else { rect[2].y = geometry->y; rect[2].height = geometry->height; } rect[2].x = geometry->x; rect[2].width = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, rect, cnt); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y + shadow, shadow, (int)geometry->height - 2*shadow); if( geometry->column != 0 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTH); } } else if( geometry->row == 0 && geometry->column == 0 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTTOM); } } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + size, shadow, (int)geometry->height - size); rect[0].x = geometry->x; rect[0].y = geometry->y + size; rect[0].width = shadow; rect[0].height = (int) geometry->height - size; rect[1].x = geometry->x + size; rect[1].y = geometry->y; rect[1].width = (int)geometry->width - (2 * size); rect[1].height = shadow; if( !selected && geometry->row == 0 ) { rect[2].x = geometry->x; rect[2].y = geometry->y + (int)geometry->height - shadow; rect[2].width = geometry->width; rect[2].height = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, rect, cnt); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + shadow, geometry->y + (int)geometry->height - shadow, (int)geometry->width - 2*shadow, shadow); if( (!stacked && (((geometry->column != XmTabBox__num_columns(tab) - 1) && !LayoutIsRtoLP(tab)) || (geometry->column != 0 && LayoutIsRtoLP(tab)))) || (stacked && geometry->row == 0 && (((geometry->column != XmTabBox__num_columns(tab) - 1) && !LayoutIsRtoLP(tab)) || XmTabBox__num_rows(tab) == 1 || !XmTabBox_stacked_effect(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } else if( (stacked && XmTabBox_stacked_effect(tab) && XmTabBox__num_rows(tab) > 1 && geometry->row == 0 && ((geometry->column == XmTabBox__num_columns(tab) - 1 && !LayoutIsRtoLP(tab)) || (geometry->column == 0 && LayoutIsRtoLP(tab)))) || (!stacked && ((geometry->column == XmTabBox__num_columns(tab) - 1 && !LayoutIsRtoLP(tab)) || (geometry->column == 0 && LayoutIsRtoLP(tab))))) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, geometry->x + size, geometry->y + (int)geometry->height - shadow, (int)geometry->width - size, shadow); rect[0].x = geometry->x + size; rect[0].y = geometry->y; rect[0].width = (int)geometry->width - size; rect[0].height = shadow; rect[1].x = geometry->x; rect[1].y = geometry->y + size; rect[1].width = shadow; rect[1].height = (int)geometry->height - (2 * size); if( !selected && geometry->row == 0 ) { rect[2].x = geometry->x + (int)geometry->width - shadow; rect[2].y = geometry->y; rect[2].width = shadow; rect[2].height = geometry->height; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, rect, cnt); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + (int)geometry->width - shadow, geometry->y + shadow, shadow, (int)geometry->height - 2*shadow); if( !stacked || (stacked && geometry->row == 0 && (geometry->column != XmTabBox__num_columns(tab) - 1 || XmTabBox__num_rows(tab) == 1 || !XmTabBox_stacked_effect(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } else if( stacked && XmTabBox_stacked_effect(tab) && XmTabBox__num_rows(tab) > 1 && geometry->row == 0 && geometry->column == XmTabBox__num_columns(tab) - 1 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } break; } } static void #ifndef _NO_PROTO DrawSquareShadows(XmTabBoxWidget tab, XmTabAttributes info, XiTabRect *geometry, Boolean selected, XmTabEdge edge, Dimension shadow) #else DrawSquareShadows(tab, info, geometry, selected, edge, shadow) XmTabBoxWidget tab; XmTabAttributes info; XiTabRect *geometry; Boolean selected; XmTabEdge edge; Dimension shadow; #endif { XRectangle rt[3]; GC gc = (GC)NULL; Boolean stacked; int cnt = 2; stacked = (XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC); /* * Lets set up the GC used to draw the shadow that may or may not be * visible depending on the selected state. */ if( selected ) { if( XiSelectSpecified(tab) ) { gc = XmTabBox__tab_GC(tab); SetSelectGC(tab, gc); } else { if( XiBackgroundSpecified(info) ) { gc = XmTabBox__tab_GC(tab); SetBackgroundGC(tab, info, gc); } else { gc = tab->manager.background_GC; } } } switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, (int)geometry->height - shadow); rt[0].x = geometry->x + (int)geometry->width - shadow; rt[0].y = geometry->y; rt[0].width = shadow; rt[0].height = geometry->height; rt[1].x = geometry->x + shadow; rt[1].y = geometry->y + (int) geometry->height - shadow; rt[1].width = (int)geometry->width - shadow; rt[1].height = shadow; if( !selected && geometry->row == 0 ) { if( (geometry->column == 0 && !LayoutIsRtoL(tab)) || ((geometry->column == XmTabBox__num_columns(tab)-1) && LayoutIsRtoLP(tab))) { rt[2].x = geometry->x + shadow; rt[2].width = (int)geometry->width - shadow; } else { rt[2].x = geometry->x; rt[2].width = geometry->width; } rt[2].y = geometry->y; rt[2].height = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, rt, cnt); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTH); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + shadow, geometry->y, (int)geometry->width - 2*shadow, shadow); if( geometry->column == 0 && geometry->column > 0 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTH); } } else if( geometry->row == 0 ) { if (geometry->column == 0 && !LayoutIsRtoLP(tab)) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTTOM); } else if (geometry->column == XmTabBox__num_columns(tab)-1 && LayoutIsRtoLP(tab)) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTTOM); return; } } } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, geometry->x, geometry->y, (int)geometry->width - shadow, shadow); rt[0].x = geometry->x + (int)geometry->width - shadow; rt[0].y = geometry->y + shadow; rt[0].width = shadow; rt[0].height = geometry->height - shadow; rt[1].x = geometry->x; rt[1].y = geometry->y + (int) geometry->height - shadow; rt[1].width = (int)geometry->width - shadow; rt[1].height = shadow; if( !selected && geometry->row == 0 ) { if( geometry->column == 0 ) { rt[2].y = geometry->y + shadow; rt[2].height = (int)geometry->height - shadow; } else { rt[2].y = geometry->y; rt[2].height = geometry->height; } rt[2].x = geometry->x; rt[2].width = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, rt, cnt); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y, shadow, XmBEVEL_BOTH); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y + shadow, shadow, (int)geometry->height - 2*shadow); if( geometry->column != 0 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTH); } } else if( geometry->row == 0 && geometry->column == 0 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, shadow, XmBEVEL_BOTTOM); } } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y, shadow, (int)geometry->height); rt[0].x = geometry->x; rt[0].y = geometry->y; rt[0].width = shadow; rt[0].height = geometry->height; rt[1].x = geometry->x; rt[1].y = geometry->y; rt[1].width = (int)geometry->width - shadow; rt[1].height = shadow; if( !selected && geometry->row == 0 ) { rt[2].x = geometry->x; rt[2].y = geometry->y + (int)geometry->height - shadow; rt[2].width = geometry->width; rt[2].height = shadow; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, rt, cnt); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y, shadow, XmBEVEL_TOP); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + shadow, geometry->y + (int)geometry->height - shadow, (int)geometry->width - 2*shadow, shadow); if (LayoutIsRtoLP(tab)) { if (geometry->column != 0 && geometry->row == 0) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTH); } } else { if( (!stacked && ((((geometry->column != XmTabBox__num_columns(tab) - 1) && !LayoutIsRtoLP(tab))) || (geometry->column != 0 && LayoutIsRtoLP(tab)))) || (stacked && geometry->row == 0 && (geometry->column != XmTabBox__num_columns(tab) - 1 || (XmTabBox__num_rows(tab) == 1) || !XmTabBox_stacked_effect(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTH); } } } else if( (stacked && XmTabBox_stacked_effect(tab) && XmTabBox__num_rows(tab) > 1 && geometry->row == 0 && ((geometry->column == XmTabBox__num_columns(tab) - 1 && !LayoutIsRtoLP(tab)) || (geometry->column == 0 && LayoutIsRtoLP(tab)))) || (!stacked && ((geometry->column == XmTabBox__num_columns(tab) - 1 && !LayoutIsRtoLP(tab)) || (geometry->column == 0 && LayoutIsRtoLP(tab))))) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, geometry->x + shadow, geometry->y + (int)geometry->height - shadow, (int)geometry->width - shadow, shadow); rt[0].x = geometry->x; rt[0].y = geometry->y; rt[0].width = shadow; rt[0].height = (int)geometry->height - shadow; rt[1].x = geometry->x; rt[1].y = geometry->y; rt[1].width = geometry->width; rt[1].height = shadow; if( !selected && geometry->row == 0 ) { rt[2].x = geometry->x + (int)geometry->width - shadow; rt[2].y = geometry->y; rt[2].width = shadow; rt[2].height = geometry->height; cnt = 3; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, rt, cnt); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTH); if( selected ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + (int)geometry->width - shadow, geometry->y + shadow, shadow, (int)geometry->height - 2*shadow); if( !stacked || (stacked && geometry->row == 0 && (geometry->column != XmTabBox__num_columns(tab) - 1 || XmTabBox__num_rows(tab) == 1 || !XmTabBox_stacked_effect(tab))) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTH); } } else if( stacked && XmTabBox_stacked_effect(tab) && XmTabBox__num_rows(tab) > 1 && geometry->row == 0 && geometry->column == XmTabBox__num_columns(tab) - 1 ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - shadow, geometry->y + (int)geometry->height - shadow, shadow, XmBEVEL_BOTTOM); } } break; } } static void #ifndef _NO_PROTO DrawRoundedShadows(XmTabBoxWidget tab, XmTabAttributes info, XiTabRect *geometry, Boolean selected, XmTabEdge edge, int shadow) #else DrawRoundedShadows(tab, info, geometry, selected, edge, shadow) XmTabBoxWidget tab; XmTabAttributes info; XiTabRect *geometry; Boolean selected; XmTabEdge edge; int shadow; #endif { int size; size = XmTabBox__corner_size(tab); if( geometry->width < geometry->height ) { if( size > (int)geometry->width/2 ) size = (int)geometry->width/2; } else { if( size > (int)geometry->height/2 ) size = (int)geometry->height/2; } DrawSegments(tab, info, geometry, edge, size, shadow, selected); switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y + (int)geometry->height - size, size, size, tab->manager.shadow_thickness, XiQUAD_3); XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - size, geometry->y + (int)geometry->height - size, size, size, tab->manager.shadow_thickness, XiQUAD_4); } else { XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - size, geometry->y, size, size, tab->manager.shadow_thickness, XiQUAD_1); XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - size, geometry->y + (int)geometry->height - size, size, size, tab->manager.shadow_thickness, XiQUAD_4); } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x + (int)geometry->width - size, geometry->y, size, size, tab->manager.shadow_thickness, XiQUAD_1); XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, size, size, tab->manager.shadow_thickness, XiQUAD_2); } else { XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y, size, size, tab->manager.shadow_thickness, XiQUAD_2); XiDrawCorner(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, geometry->x, geometry->y + (int)geometry->height - size, size, size, tab->manager.shadow_thickness, XiQUAD_3); } break; } } static void #ifndef _NO_PROTO DrawBeveledShadows(XmTabBoxWidget tab, XmTabAttributes info, XiTabRect *geometry, Boolean selected, XmTabEdge edge, int shadow) #else DrawBeveledShadows(tab, info, geometry, selected, edge, shadow) XmTabBoxWidget tab; XmTabAttributes info; XiTabRect *geometry; Boolean selected; XmTabEdge edge; int shadow; #endif { int size; XPoint pt[4]; size = XmTabBox__corner_size(tab); if( geometry->width < geometry->height ) { if( size > (int)geometry->width/2 ) size = (int)geometry->width/2; } else { if( size > (int)geometry->height/2 ) size = (int)geometry->height/2; } DrawSegments(tab, info, geometry, edge, size, shadow, selected); switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { pt[0].x = geometry->x; pt[0].y = geometry->y + (int)geometry->height - size; pt[1].x = geometry->x + size; pt[1].y = geometry->y + (int)geometry->height; pt[2].x = geometry->x + size; pt[2].y = geometry->y + (int)geometry->height - shadow; pt[3].x = geometry->x + shadow; pt[3].y = geometry->y + (int)geometry->height - size; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, pt, 4, Convex, CoordModeOrigin); pt[0].x = geometry->x + (int)geometry->width; pt[0].y = geometry->y + (int)geometry->height - size; pt[1].x = geometry->x + (int)geometry->width - size; pt[1].y = geometry->y + (int)geometry->height; pt[2].x = geometry->x + (int)geometry->width - size; pt[2].y = geometry->y + (int)geometry->height - shadow; pt[3].x = geometry->x + (int)geometry->width - shadow; pt[3].y = geometry->y + (int)geometry->height - size; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, pt, 4, Convex, CoordModeOrigin); } else { pt[0].x = geometry->x + (int)geometry->width - size; pt[0].y = geometry->y; pt[1].x = geometry->x + (int)geometry->width; pt[1].y = geometry->y + size; pt[2].x = pt[1].x - shadow; pt[2].y = pt[1].y; pt[3].x = pt[0].x; pt[3].y = pt[0].y + shadow; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, pt, 4, Convex, CoordModeOrigin); pt[0].x = geometry->x + (int)geometry->width - size; pt[0].y = geometry->y + (int)geometry->height; pt[1].x = geometry->x + (int)geometry->width; pt[1].y = geometry->y + (int)geometry->height - size; pt[2].x = pt[1].x - shadow; pt[2].y = pt[1].y; pt[3].x = pt[0].x; pt[3].y = pt[0].y - shadow; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, pt, 4, Convex, CoordModeOrigin); } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { pt[0].x = geometry->x; pt[0].y = geometry->y + size; pt[1].x = geometry->x + size; pt[1].y = geometry->y; pt[2].x = geometry->x + size; pt[2].y = geometry->y + shadow; pt[3].x = geometry->x + shadow; pt[3].y = geometry->y + size; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, pt, 4, Convex, CoordModeOrigin); pt[0].x = geometry->x + (int)geometry->width; pt[0].y = geometry->y + size; pt[1].x = geometry->x + (int)geometry->width - size; pt[1].y = geometry->y; pt[2].x = geometry->x + (int)geometry->width - size; pt[2].y = geometry->y + shadow; pt[3].x = geometry->x + (int)geometry->width - shadow; pt[3].y = geometry->y + size; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, pt, 4, Convex, CoordModeOrigin); } else { pt[0].x = geometry->x + size; pt[0].y = geometry->y; pt[1].x = geometry->x; pt[1].y = geometry->y + size; pt[2].x = pt[1].x + shadow; pt[2].y = pt[1].y; pt[3].x = pt[0].x; pt[3].y = pt[0].y + shadow; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, pt, 4, Convex, CoordModeOrigin); pt[0].x = geometry->x + size; pt[0].y = geometry->y + (int)geometry->height; pt[1].x = geometry->x; pt[1].y = geometry->y + (int)geometry->height - size; pt[2].x = pt[1].x + shadow; pt[2].y = pt[1].y; pt[3].x = pt[0].x; pt[3].y = pt[0].y - shadow; XFillPolygon(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, pt, 4, Convex, CoordModeOrigin); } break; } } static void #ifndef _NO_PROTO DrawTab(XmTabBoxWidget tab, XmTabAttributes info, XiTabRect *geometry, Boolean selected, Boolean keyboard) #else DrawTab(tab, info, geometry, selected, keyboard) XmTabBoxWidget tab; XmTabAttributes info; XiTabRect *geometry; Boolean selected, keyboard; #endif { XmTabEdge edge = XmTabBox_tab_edge(tab); Widget canvas = XmTabBox__canvas(tab); XmFontList font_list = XmTabBox_font_list(tab); Dimension shadow_thickness = tab->manager.shadow_thickness, margin_width = XmTabBox_tab_margin_width(tab), margin_height = XmTabBox_tab_margin_width(tab), size = XmTabBox__corner_size(tab); XRectangle *clip; int pix_width = 0, pix_height = 0, pix_depth = 0, label_width = 0, label_height = 0, row; Boolean have_pixmap = False, have_label = False; GC gc = XmTabBox__tab_GC(tab); XmTabAttributes above; /* * Lets do the quick check here. If we are not realized then there is * really nothing to draw so lets just leave. */ if( !XtIsRealized(canvas) || info == NULL ) return; if( (XmTabBox_tab_mode(tab) == XmTABS_STACKED || XmTabBox_tab_mode(tab) == XmTABS_STACKED_STATIC) && XmTabBox_tab_style(tab) != XmTABS_SQUARED ) { row = geometry->row; do { if( LayoutIsRtoLP(tab) ) above = GetTabInfo(tab, ++row, geometry->column-1); else above = GetTabInfo(tab, ++row, geometry->column); } while( above == NULL && row < XmTabBox__num_rows(tab) ); if( above != NULL ) { /* * Ok, what is happening here is that we are in a stacked layout * and we have a tab that is above us. This means that we * need to fill in our upper corner with this tabs color. */ if( XiBackgroundSpecified(above) ) { SetBackgroundGC(tab, above, gc); } else { if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledXYGC(XtDisplay(tab), gc, tab->core.background_pixmap, -(tab->core.x), -(tab->core.y)); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } } } else { Widget gcParent = XiGCParent(tab); Pixel pixel; Pixmap pixmap; XtVaGetValues(gcParent, XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledXYGC(XtDisplay(tab), gc, pixmap, -(tab->core.x), -(tab->core.y)); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + geometry->width - size, geometry->y, size, size); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y + geometry->height - size, size, size); } } else { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + geometry->width - size, geometry->y + geometry->height - size, size, size); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + geometry->width - size, geometry->y + geometry->height - size, size, size); } } row = geometry->row; do { if( LayoutIsRtoLP(tab) ) above = GetTabInfo(tab, ++row, geometry->column); else above = GetTabInfo(tab, ++row, geometry->column - 1); } while( above == NULL && row < XmTabBox__num_rows(tab) ); if( above != NULL ) { /* * Ok, what is happening here is that we are in a stacked layout * and we have a tab that is above us. This means that we * need to fill in our upper corner with this tabs color. */ if( XiBackgroundSpecified(above) ) { SetBackgroundGC(tab, above, gc); } else { if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledXYGC(XtDisplay(tab), gc, tab->core.background_pixmap, -(tab->core.x), -(tab->core.y)); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } } } else { Widget gcParent = XiGCParent(tab); Pixel pixel; Pixmap pixmap; XtVaGetValues(gcParent, XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledXYGC(XtDisplay(tab), gc, pixmap, -(tab->core.x), -(tab->core.y)); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y, size, size); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y, size, size); } } else { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x, geometry->y + geometry->height - size, size, size); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, geometry->x + geometry->width - size, geometry->y, size, size); } } } if( selected && XiSelectSpecified(tab) ) { #ifdef FIX_1503 SetSelectGC(tab, XmTabBox__tab_GC(tab)); #else SetSelectGC(tab, tab->manager.background_GC); #endif } else { /* * Lets see if we need to fill in the background color of this tab, or * if it wants the same color as its parent. */ if( XiBackgroundSpecified(info) ) { /* * It appears that this tab wants its background filled in * to a specific color so lets do that. */ #ifdef FIX_1503 SetBackgroundGC(tab, info, XmTabBox__tab_GC(tab)); #else SetBackgroundGC(tab, info, tab->manager.background_GC); #endif } else { if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledXYGC(XtDisplay(tab), gc, tab->core.background_pixmap, -(tab->core.x), -(tab->core.y)); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } } } switch( XmTabBox_tab_style(tab) ) { case XmTABS_SQUARED: #ifdef FIX_1503 XFillRectangle(XtDisplay(tab), XiCanvas(tab), XmTabBox__tab_GC(tab), geometry->x, geometry->y, geometry->width, geometry->height); #else XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.background_GC, geometry->x, geometry->y, geometry->width, geometry->height); #endif break; case XmTABS_ROUNDED: #ifdef FIX_1503 FillRoundedTab(tab, XmTabBox__tab_GC(tab), geometry, edge); #else FillRoundedTab(tab, tab->manager.background_GC, geometry, edge); #endif break; case XmTABS_BEVELED: #ifdef FIX_1503 FillBeveledTab(tab, XmTabBox__tab_GC(tab), geometry, edge); #else FillBeveledTab(tab, tab->manager.background_GC, geometry, edge); #endif break; } /* * The first thing that we will draw is the shadows around the tab. * We have a lot of nifty routines to do this. Maybe will add more * someday. */ switch( XmTabBox_tab_style(tab) ) { case XmTABS_SQUARED: DrawSquareShadows(tab, info, geometry, selected, edge, shadow_thickness); break; case XmTABS_ROUNDED: DrawRoundedShadows(tab, info, geometry, selected, edge, shadow_thickness); break; case XmTABS_BEVELED: DrawBeveledShadows(tab, info, geometry, selected, edge, shadow_thickness); break; default: break; } gc = XmTabBox__text_GC(tab); /* * Now comes the hard part we need to draw the label. The label * consists of an XmString and a pixmap, both of which are optional. * * First lets calculate the size of both the label and the pixmap * so that we can calculate the amount of space we will need to * display the entire tab label. */ if( ValidPixmap(info->label_pixmap) && info->pixmap_placement != XmPIXMAP_NONE ) { Window window_unused; int int_unused; unsigned int uint_unused, width_return, height_return, depth_return; have_pixmap = True; XGetGeometry(XtDisplay(tab), info->label_pixmap, &window_unused, &int_unused, &int_unused, &width_return, &height_return, &uint_unused, &depth_return); pix_depth = depth_return; pix_width = width_return; pix_height = height_return; } else { pix_depth = 0; pix_width = 0; pix_height = 0; } if( info->label_string != NULL && info->pixmap_placement != XmPIXMAP_ONLY ) { Dimension string_width, string_height; have_label = True; XmStringExtent(font_list, info->label_string, &string_width, &string_height); label_width = string_width; label_height = string_height; } else { label_width = 0; label_height = 0; } SetSolidGC(XtDisplay(tab), gc, (info->foreground == XmCOLOR_DYNAMIC ? tab->manager.foreground : info->foreground)); margin_width += shadow_thickness; margin_height += shadow_thickness; AssignMax(margin_width, size); AssignMax(margin_height, size); /* * Now lets calculate the cliping rectangle for the area in which * text and images can be drawn. And since all we have left * to draw is text and images lets assign this rectangle as the * cliping area for our drawing GC. */ clip = GetTabRectangle(tab, XmTAB_TEXT_RECT, geometry); XSetClipRectangles(XtDisplay(tab), gc, 0, 0, clip, 1, YXBanded); switch( XmTabBox_tab_orientation(tab) ) { case XmTABS_LEFT_TO_RIGHT: default: DrawLeftToRightTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip); break; case XmTABS_RIGHT_TO_LEFT: DrawRightToLeftTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip, selected); break; case XmTABS_TOP_TO_BOTTOM: DrawTopToBottomTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip, selected); break; case XmTABS_BOTTOM_TO_TOP: DrawBottomToTopTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip, selected); break; } /* * The final bit of draw we have to do is to add the highlight * border to the tab if it currently has keyboard traversal. */ if( keyboard && Prim_HaveTraversal(XmTabBox__canvas(tab)) ) { BorderHighlight(XmTabBox__canvas(tab)); } /* * Now that our drawing is done lets be sure to zero out the * clipping area for our GC. */ XSetClipMask(XtDisplay(tab), gc, None); } #define XiCvtDone(type, value) \ { \ if( to->addr != NULL ) \ { \ if( to->size < sizeof(type) ) \ { \ to->size = sizeof(type); \ return( False ); \ } \ *(type*)(to->addr) = (value); \ } \ else \ { \ static type static_val; \ static_val = (value); \ to->addr = (XtPointer) &static_val; \ } \ to->size = sizeof(type); \ return( True ); \ } /* ARGSUSED */ static Boolean #ifndef _NO_PROTO CvtStringToTabOrientation(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabOrientation(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTABS_TOP_TO_BOTTOM; String str = (String) (from->addr); if( XmCompareISOLatin1(str, "ORIENTATION_DYNAMIC") == 0 || XmCompareISOLatin1(str, "XiTABS_ORIENTATION_DYNAMIC") == 0 ) { result = XmTAB_ORIENTATION_DYNAMIC; } else if( XmCompareISOLatin1(str, "TOP_TO_BOTTOM") == 0 || XmCompareISOLatin1(str, "XmTABS_TOP_TO_BOTTOM") == 0 ) { result = XmTABS_TOP_TO_BOTTOM; } else if( XmCompareISOLatin1(str, "BOTTOM_TO_TOP") == 0 || XmCompareISOLatin1(str, "XmTABS_BOTTOM_TO_TOP") == 0 ) { result = XmTABS_BOTTOM_TO_TOP; } else if( XmCompareISOLatin1(str, "LEFT_TO_RIGHT") == 0 || XmCompareISOLatin1(str, "XmTABS_LEFT_TO_RIGHT") == 0 ) { result = XmTABS_LEFT_TO_RIGHT; } else if( XmCompareISOLatin1(str, "RIGHT_TO_LEFT") == 0 || XmCompareISOLatin1(str, "XmTABS_RIGHT_TO_LEFT") == 0 ) { result = XmTABS_RIGHT_TO_LEFT; } else { XtDisplayStringConversionWarning(dpy, str, XmRTabOrientation); return( False ); } XiCvtDone(int, result); } static Boolean #ifndef _NO_PROTO CvtStringToTabSide(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabSide(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTABS_ON_TOP; String str = (String) (from->addr); if( XmCompareISOLatin1(str, "ON_TOP") == 0 || XmCompareISOLatin1(str, "XmTABS_ON_TOP") == 0 ) { result = XmTABS_ON_TOP; } else if( XmCompareISOLatin1(str, "ON_BOTTOM") == 0 || XmCompareISOLatin1(str, "XmTABS_ON_BOTTOM") == 0 ) { result = XmTABS_ON_BOTTOM; } else if( XmCompareISOLatin1(str, "ON_LEFT") == 0 || XmCompareISOLatin1(str, "XmTABS_ON_LEFT") == 0 ) { result = XmTABS_ON_LEFT; } else if( XmCompareISOLatin1(str, "ON_RIGHT") == 0 || XmCompareISOLatin1(str, "XmTABS_ON_RIGHT") == 0 ) { result = XmTABS_ON_RIGHT; } else { XtDisplayStringConversionWarning(dpy, str, XmRTabSide); return( False ); } XiCvtDone(int, result); } /* ARGSUSED */ static Boolean #ifndef _NO_PROTO CvtStringToTabStyle(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabStyle(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTABS_BEVELED; String str = (String) (from->addr); if( XmCompareISOLatin1(str, "SQUARED") == 0 || XmCompareISOLatin1(str, "XmTABS_SQUARED") == 0 ) { result = XmTABS_SQUARED; } else if( XmCompareISOLatin1(str, "ROUNDED") == 0 || XmCompareISOLatin1(str, "XmTABS_ROUNDED") == 0 ) { result = XmTABS_ROUNDED; } else if( XmCompareISOLatin1(str, "BEVELED") == 0 || XmCompareISOLatin1(str, "XmTABS_BEVELED") == 0 ) { result = XmTABS_BEVELED; } else { XtDisplayStringConversionWarning(dpy, str, XmRTabStyle); return( False ); } XiCvtDone(int, result); } /* ARGSUSED */ static Boolean #ifndef _NO_PROTO CvtStringToTabMode(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabMode(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTABS_BASIC; String str = (String) from->addr; if( XmCompareISOLatin1(str, "BASIC") == 0 || XmCompareISOLatin1(str, "XmTABS_BASIC") == 0 ) { } else if( XmCompareISOLatin1(str, "STACKED") == 0 || XmCompareISOLatin1(str, "XmTABS_STACKED") == 0 ) { result = XmTABS_STACKED; } else if( XmCompareISOLatin1(str, "STACKED_STATIC") == 0 || XmCompareISOLatin1(str, "XmTABS_STACKED_STATIC") == 0 ) { result = XmTABS_STACKED_STATIC; } #ifdef SCROLLED_LAYOUT else if( XmCompareISOLatin1(str, "SCROLLED") == 0 || XmCompareISOLatin1(str, "XmTABS_SCROLLED") == 0 ) { result = XmTABS_SCROLLED; } #endif #ifdef OVERLAYED_LAYOUT else if( XmCompareISOLatin1(str, "OVERLAYED") == 0 || XmCompareISOLatin1(str, "XmTABS_OVERLAYED") == 0 ) { result = XmTABS_OVERLAYED; } #endif else { XtDisplayStringConversionWarning(dpy, str, XmRTabMode); return( False ); } XiCvtDone(int, result); } /* ARGSUSED */ static Boolean #ifndef _NO_PROTO CvtStringToTabEdge(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabEdge(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTAB_EDGE_BOTTOM_RIGHT; String str = (String) (from->addr); if( XmCompareISOLatin1(str, "EDGE_TOP_LEFT") == 0 || XmCompareISOLatin1(str, "XmTAB_EDGE_TOP_LEFT") == 0 ) { result = XmTAB_EDGE_TOP_LEFT; } else if( XmCompareISOLatin1(str, "EDGE_BOTTOM_RIGHT") == 0 || XmCompareISOLatin1(str, "XiTABS_EDGE_BOTTOM_RIGHT") == 0 ) { result = XmTAB_EDGE_BOTTOM_RIGHT; } else if( XmCompareISOLatin1(str, "bottom") == 0 ) { result = XmTAB_EDGE_TOP_LEFT; } else if( XmCompareISOLatin1(str, "right") == 0 ) { result = XmTAB_EDGE_BOTTOM_RIGHT; } else { XtDisplayStringConversionWarning(dpy, str, XmRTabEdge); return( False ); } XiCvtDone(int, result); } #ifdef SCROLLED_LAYOUT static Boolean #ifndef _NO_PROTO CvtStringToArrowPlacement(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToArrowPlacement(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { static int result = XmTAB_ARROWS_ON_LEFT; String str = (String) (from->addr); if( XmCompareISOLatin1(str, "left") == 0 || XmCompareISOLatin1(str, "tab_arrows_on_left") == 0 ) { result = XmTAB_ARROWS_ON_LEFT; } else if( XmCompareISOLatin1(str, "right") == 0 || XmCompareISOLatin1(str, "tab_arrows_on_right") == 0 ) { result = XmTAB_ARROWS_ON_RIGHT; } else if( XmCompareISOLatin1(str, "split") == 0 || XmCompareISOLatin1(str, "tab_arrows_split") == 0 ) { result = XmTAB_ARROWS_SPLIT; } else { XtDisplayStringConversionWarning(dpy, str, XmRTabArrowPlacement); return( False ); } XiCvtDone(int, result); } #endif /* ARGSUSED */ static Boolean #ifndef _NO_PROTO CvtStringToTabList(Display *dpy, XrmValue *arg_list, Cardinal *arg_cnt, XrmValue *from, XrmValue *to, XtPointer *data) #else CvtStringToTabList(dpy, arg_list, arg_cnt, from, to, data) Display *dpy; XrmValue *arg_list; Cardinal *arg_cnt; XrmValue *from, *to; XtPointer *data; #endif { return( False ); } /* ARGSUSED */ static void #ifndef _NO_PROTO CvtDestroyTabList(XtAppContext app_context, XrmValue *to, XtPointer data, XrmValue *args, Cardinal *num_args) #else CvtDestroyTabList(app_context, to, data, args, num_args) XtAppContext app_context; XrmValue *to; XtPointer data; XrmValue *args; Cardinal *num_args; #endif { } static short XiCosSinData[][2] = { { 1000, 0 }, { 998, 52 }, { 994, 104 }, { 987, 156 }, { 978, 207 }, { 965, 258 }, { 951, 309 }, { 933, 358 }, { 913, 406 }, { 891, 453 }, { 866, 499 }, { 838, 544 }, { 809, 587 }, { 777, 629 }, { 743, 669 }, { 707, 707 }, { 669, 743 }, { 629, 777 }, { 587, 809 }, { 544, 838 }, { 500, 866 }, { 453, 891 }, { 406, 913 }, { 358, 933 }, { 309, 951 }, { 258, 965 }, { 207, 978 }, { 156, 987 }, { 104, 994 }, { 52, 998 }, { 0, 1000 }}; #define NUM_PTS 31 #define NUM_PTSx2 62 #define HALF_PTS 16 #define HALF_PTSx2 32 #define NUM_PTSp1 32 static void #ifndef _NO_PROTO XiDrawCorner(Display *dpy, Drawable d, GC top_gc, GC bottom_gc, int x, int y, unsigned int width, unsigned int height, unsigned int size, XiQuadrant quadrant) #else XiDrawCorner(dpy, d, top_gc, bottom_gc, x, y, width, height, size, quadrant) Display *dpy; Drawable d; GC top_gc, bottom_gc; int x, y; unsigned int width, height, size; XiQuadrant quadrant; #endif { XPoint pt[NUM_PTSx2]; int i, xrad1, xrad2, yrad1, yrad2, tmp; xrad1 = width; xrad2 = width - size; yrad1 = height; yrad2 = height - size; switch( quadrant ) { case XiQUAD_1: y += height; for( i = 0; i < HALF_PTS; ++i ) { pt[i].x = x + XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y - XiCosSinData[i][1] * yrad1 / 1000; pt[HALF_PTSx2-1-i].x = x + XiCosSinData[i][0] * xrad2 / 1000; pt[HALF_PTSx2-1-i].y = y - XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, bottom_gc, pt, HALF_PTSx2, Nonconvex, CoordModeOrigin); for( tmp = 0, i = HALF_PTS-1; i < NUM_PTS; ++i, ++tmp ) { pt[tmp].x = x + XiCosSinData[i][0] * xrad1 / 1000; pt[tmp].y = y - XiCosSinData[i][1] * yrad1 / 1000; pt[HALF_PTSx2-1-tmp].x = x + XiCosSinData[i][0] * xrad2 / 1000; pt[HALF_PTSx2-1-tmp].y = y - XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, top_gc, pt, HALF_PTSx2, Nonconvex, CoordModeOrigin); break; case XiQUAD_2: x += width; y += height; for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x - XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y - XiCosSinData[i][1] * yrad1 / 1000; pt[NUM_PTSx2-1-i].x = x - (int)XiCosSinData[i][0] * xrad2 / 1000; pt[NUM_PTSx2-1-i].y = y - (int)XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, top_gc, pt, NUM_PTSx2, Nonconvex, CoordModeOrigin); break; case XiQUAD_3: x += width; for( i = 0; i < HALF_PTS; ++i ) { pt[i].x = x - XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y + XiCosSinData[i][1] * yrad1 / 1000; pt[HALF_PTSx2-1-i].x = x - XiCosSinData[i][0] * xrad2 / 1000; pt[HALF_PTSx2-1-i].y = y + XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, top_gc, pt, HALF_PTSx2, Nonconvex, CoordModeOrigin); for( tmp = 0, i = HALF_PTS-1; i < NUM_PTS; ++i, ++tmp ) { pt[tmp].x = x - XiCosSinData[i][0] * xrad1 / 1000; pt[tmp].y = y + XiCosSinData[i][1] * yrad1 / 1000; pt[HALF_PTSx2-1-tmp].x = x - XiCosSinData[i][0] * xrad2 / 1000; pt[HALF_PTSx2-1-tmp].y = y + XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, bottom_gc, pt, HALF_PTSx2, Nonconvex, CoordModeOrigin); break; case XiQUAD_4: for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x + XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y + XiCosSinData[i][1] * yrad1 / 1000; pt[NUM_PTSx2-1-i].x = x + XiCosSinData[i][0] * xrad2 / 1000; pt[NUM_PTSx2-1-i].y = y + XiCosSinData[i][1] * yrad2 / 1000; } XFillPolygon(dpy, d, bottom_gc, pt, NUM_PTSx2, Nonconvex, CoordModeOrigin); break; default: break; } } static void #ifndef _NO_PROTO XiFillCorner(Display *dpy, Drawable d, GC gc, int x, int y, unsigned int width, unsigned int height, XiQuadrant quadrant) #else XiFillCorner(dpy, d, gc, x, y, width, height, quadrant) Display *dpy; Drawable d; GC gc; int x, y; unsigned int width, height; XiQuadrant quadrant; #endif { XPoint pt[NUM_PTSp1]; int i, xrad1, yrad1; xrad1 = width; yrad1 = height; switch( quadrant ) { case XiQUAD_1: y += height; for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x + XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y - XiCosSinData[i][1] * yrad1 / 1000; } pt[i].x = x; pt[i++].y = y + height; XFillPolygon(dpy, d, gc, pt, i, Nonconvex, CoordModeOrigin); break; case XiQUAD_2: x += width; y += height; for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x - XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y - XiCosSinData[i][1] * yrad1 / 1000; } pt[i].x = x + width; pt[i++].y = y + height; XFillPolygon(dpy, d, gc, pt, i, Nonconvex, CoordModeOrigin); break; case XiQUAD_3: x += width; for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x - XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y + XiCosSinData[i][1] * yrad1 / 1000; } pt[i].x = x + width; pt[i++].y = y; XFillPolygon(dpy, d, gc, pt, i, Nonconvex, CoordModeOrigin); break; case XiQUAD_4: for( i = 0; i < NUM_PTS; ++i ) { pt[i].x = x + XiCosSinData[i][0] * xrad1 / 1000; pt[i].y = y + XiCosSinData[i][1] * yrad1 / 1000; } pt[i].x = x; pt[i++].y = y; XFillPolygon(dpy, d, gc, pt, i, Nonconvex, CoordModeOrigin); break; default: break; } } static void #ifndef _NO_PROTO HorizontalBasicLayout(XmTabBoxWidget tab) #else HorizontalBasicLayout(tab) XmTabBoxWidget tab; #endif { int i, x, height, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); XiTabRect *actual = XmTabBox__actual(tab); XRectangle *wanted = XmTabBox__wanted(tab); x = LayoutIsRtoLP(tab) ? (tab->core.width - wanted[0].width) : 0; height = XtHeight(tab); for( i = 0; i < cnt; ++i ) { actual[i].x = x; actual[i].y = 0; actual[i].width = wanted[i].width; actual[i].height = height; actual[i].row = 0; actual[i].column = i; if (i < cnt-1) x += LayoutIsRtoLP(tab) ? -actual[i+1].width : actual[i].width; } XmTabBox__num_rows(tab) = 1; XmTabBox__num_columns(tab) = i; } static void #ifndef _NO_PROTO VerticalBasicLayout(XmTabBoxWidget tab) #else VerticalBasicLayout(tab) XmTabBoxWidget tab; #endif { int i, y, width, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); XiTabRect *actual = XmTabBox__actual(tab); XRectangle *wanted = XmTabBox__wanted(tab); y = 0; width = XtWidth(tab); for( i = 0; i < cnt; ++i ) { actual[i].x = 0; actual[i].y = y; actual[i].width = width; actual[i].height = wanted[i].height; actual[i].row = 0; actual[i].column = i; y += actual[i].height; } XmTabBox__num_rows(tab) = 1; XmTabBox__num_columns(tab) = i; } static void #ifndef _NO_PROTO Layout(XmTabBoxWidget tab) #else Layout(tab) XmTabBoxWidget tab; #endif { XmTabbedStackList list = XmTabBox_tab_list(tab); int count = _XmTabbedStackListCount(list); XRectangle geometry; if( count == 0 ) { XmTabBox__num_columns(tab) = 0; XmTabBox__num_rows(tab) = 0; return; } if( count > XmTabBox__num_actual(tab) ) { XmTabBox__num_actual(tab) = count; XmTabBox__actual(tab) = (XiTabRect*) XtRealloc((XtPointer) XmTabBox__actual(tab), sizeof(XiTabRect) * count); } switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: CalcGeometry(tab, &geometry); if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { HorizontalBasicLayout(tab); } else { VerticalBasicLayout(tab); } break; case XmTABS_STACKED: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { HorizontalStackedLayout(tab, False); } else { VerticalStackedLayout(tab, False); } break; case XmTABS_STACKED_STATIC: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { HorizontalStackedLayout(tab, True); } else { VerticalStackedLayout(tab, True); } break; case XmTABS_SCROLLED: break; case XmTABS_OVERLAYED: break; } } /* * Function: * HorizontalBasicRedisplay(tab) * Description: * This function performs the basic tab redisplay in the horizontal * direction. * Input: * tab : XtTabBoxWidget - the tab box to redisplay * Output: * None. */ static void #ifndef _NO_PROTO HorizontalBasicRedisplay(XmTabBoxWidget tab) #else HorizontalBasicRedisplay(tab) XmTabBoxWidget tab; #endif { XiTabRect *geom; int count = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), x, shadow = tab->manager.shadow_thickness; geom = XmTabBox__actual(tab); x = geom[count-1].x + geom[count-1].width; /* * Now that we are done with the tabs we need to complete the line * from the last tab to the edge of the widget. */ if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { if (LayoutIsRtoLP(tab)) XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, 0, (int)XtHeight(tab) - shadow, geom[count-1].x, shadow); else XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, x, (int)XtHeight(tab) - shadow, (int)XtWidth(tab) - x, shadow); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - shadow, shadow, XmBEVEL_BOTTOM); } else { if (LayoutIsRtoLP(tab)) XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, 0, 0, geom[count-1].x, shadow); else XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, x, 0, (int)XtWidth(tab) - x, shadow); } } /* * Function: * VerticalBasicRedisplay(tab) * Description: * This function performs the basic tab redisplay in the Vertical * direction. * Input: * tab : XtTabBoxWidget - the tab box to redisplay * Output: * None. */ static void #ifndef _NO_PROTO VerticalBasicRedisplay(XmTabBoxWidget tab) #else VerticalBasicRedisplay(tab) XmTabBoxWidget tab; #endif { XiTabRect *geom; int count = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), y, shadow = tab->manager.shadow_thickness; geom = XmTabBox__actual(tab); y = geom[count-1].y + geom[count-1].height; /* * Now that we are done with the tabs we need to complete the line * from the last tab to the edge of the widget. */ if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, (int)XtWidth(tab) - shadow, y, shadow, (int)XtHeight(tab) - y); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - shadow, shadow, XmBEVEL_BOTTOM); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, 0, y, shadow, (int)XtHeight(tab) - y); } } /* * Function: * XiRotateImage(tab, src, degree) * Description: * Returns a new XImage which is the given image rotate by either * 0 (a strait copy), 90, 180, or 270 degrees. * Input: * tab : XmTabBoxWidget - used for reference * src : XImage* - the image to rotate * degree : int - how many degrees to rotate "floored" * to the nearest 90 * Output: * XImage* - and new allocated, rotated copy of the image */ static XImage* #ifndef _NO_PROTO XiRotateImage(XmTabBoxWidget tab, XImage *src, int degree) #else XiRotateImage(tab, src, degree) XmTabBoxWidget tab; XImage *src; int degree; #endif { XImage *dst; char *data; int x, y, width, height, depth, tmp; if( src == NULL ) return( NULL ); width = XImageWidth(src); height = XImageHeight(src); depth = XImageDepth(src); if( depth < 8 ) { int cnt = 8/depth; if( degree == 0 || degree == 180 ) { tmp = (width/cnt) + ((width % cnt != 0) ? 1 : 0); tmp = tmp * height; } else { tmp = (height/cnt) + ((height % cnt != 0) ? 1 : 0); tmp = tmp * width; } } else { tmp = width * height * depth; } data = (char*) XtMalloc(tmp); if( degree == 0 || degree == 180 ) { dst = XCreateImage(XtDisplay(tab), GetShellVisual((Widget)tab), depth, (depth == 1 ? XYBitmap : XYPixmap), 0, data, width, height, 8, 0); if( degree == 180 ) { for( y = 0; y < height; ++y ) { for( x = 0; x < width; ++x ) { XPutPixel(dst, (width-1-x), (height-1-y), XGetPixel(src, x, y)); } } } else { for( y = 0; y < height; ++y ) { for( x = 0; x < width; ++x ) { XPutPixel(dst, x, y, XGetPixel(src, x, y)); } } } } else { dst = XCreateImage(XtDisplay(tab), GetShellVisual((Widget)tab), depth, (depth == 1 ? XYBitmap : XYPixmap), 0, data, height, width, 8, 0); if( degree == 90 ) { for( y = 0; y < height; ++y ) { for( x = 0; x < width; ++x ) { XPutPixel(dst, (height-1-y), x, XGetPixel(src, x, y)); } } } else { for( y = 0; y < height; ++y ) { for( x = 0; x < width; ++x ) { XPutPixel(dst, y, (width-1-x), XGetPixel(src, x, y)); } } } } return( dst ); } static void #ifndef _NO_PROTO CalcCornerSize(XmTabBoxWidget tab) #else CalcCornerSize(tab) XmTabBoxWidget tab; #endif { XmFontContext fc; XmFontListEntry entry; XmFontType font_type; XtPointer value; int tmp, size = 0; XmFontListInitFontContext(&fc, XmTabBox_font_list(tab)); while( (entry = XmFontListNextEntry(fc)) != NULL ) { value = (XtPointer) XmFontListEntryGetFont(entry, &font_type); if( font_type == XmFONT_IS_FONT ) { XFontStruct *font; font = (XFontStruct*) value; tmp = font->ascent + font->descent; AssignMax(size, tmp); } #ifdef USE_XFT else if (1/*font_type == XmFONT_IS_XFT*/) { tmp = ((XftFont*)value)->ascent + ((XftFont*)value)->descent; AssignMax(size, tmp); } #endif else { XFontSetExtents *extents; extents = XExtentsOfFontSet((XFontSet) value); tmp = extents->max_logical_extent.height; AssignMax(size, tmp); } } XmFontListFreeFontContext(fc); XmTabBox__corner_size(tab) = size * XmTabBox_tab_corner_percent(tab)/ 100; } static int #ifndef _NO_PROTO XiXYtoTab(XmTabBoxWidget tab, int x, int y) #else XiXYtoTab(tab, x, y) XmTabBoxWidget tab; int x, y; #endif { int i, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), row = -1, idx; XiTabRect *area = XmTabBox__actual(tab); for( i = 0; i < cnt; ++i ) { if( x < area[i].x || x > (area[i].x + (int)area[i].width) || y < area[i].y || y > (area[i].y + (int)area[i].height) ) { continue; } return( i ); } /* * If we are in a stacked mode then we will do some more checking, * however if we are not in a stacked mode then we are done. */ if( XmTabBox_tab_mode(tab) != XmTABS_STACKED && XmTabBox_tab_mode(tab) != XmTABS_STACKED_STATIC ) { return( -1 ); } if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { /* * Since we are in a stacked mode it is possible that we clicked in * a partial row. So lets start by finding out which partial row * we clicked in. This is done by just looking at the height * component of the tabs. */ for( i = 0; i < cnt; ++i ) { if( y >= area[i].y && y <= (area[i].y + (int)area[i].height) ) { /* * We found the row we care about. */ row = area[i].row; break; } } /* * If we did not click in a row, or if that row is the last row we are * done. */ if( row == -1 || row == (XmTabBox__num_rows(tab) - 1) ) return( -1 ); /* * Now we want to walk through all the columns of the previous row and * see if the x position is in those columns. And if we find a match * we found a winner. */ for( i = 0, ++row, idx = 0; idx >= 0 && i < XmTabBox__num_columns(tab); ++i ) { idx = GetTabIndex(tab, row, i); if( idx < 0 || x < area[i].x || x > (area[i].x + area[i].width) ) { continue; } return( idx ); } } else { /* * Since we are in a stacked mode it is possible that we clicked in * a partial row. So lets start by finding out which partial row * we clicked in. This is done by just looking at the height * component of the tabs. */ for( i = 0; i < cnt; ++i ) { if( x >= area[i].x && x <= (area[i].x + (int)area[i].width) ) { /* * We found the row we care about. */ row = area[i].row; break; } } /* * If we did not click in a row, or if that row is the last row we are * done. */ if( row == -1 || row == (XmTabBox__num_rows(tab) - 1) ) return( -1 ); /* * Now we want to walk through all the columns of the previous row and * see if the x position is in those columns. And if we find a match * we found a winner. */ for( i = 0, ++row, idx = 0; idx >= 0 && i < XmTabBox__num_columns(tab); ++i ) { idx = GetTabIndex(tab, row, i); if( idx < 0 || y < area[i].y || y > (area[i].y + area[i].height) ) { continue; } return( idx ); } } /* * If we get here we really did not find a match. */ return( -1 ); } /* * Function: * CalcTabGeometry(XmTabBoxWidget tab) * Description: * This function calculates and caches the geometry for all the tabs, * taking into account the XmNuniformTabSize resource. * Input: * tab : XmTabBoxWidget - the tab box who needs the geometries * calculated. * Output: * None. */ static void #ifndef _NO_PROTO CalcTabGeometry(XmTabBoxWidget tab) #else CalcTabGeometry(tab) XmTabBoxWidget tab; #endif { XmTabbedStackList list = XmTabBox_tab_list(tab); XmTabAttributes info; Dimension width, height, max_width = 0, max_height = 0; int count = _XmTabbedStackListCount(XmTabBox_tab_list(tab)), i; XRectangle *geom; /* * First lets see if we have enough room to cache all the geometries * and if not lets increase our cache so there is room. */ if( count > XmTabBox__num_wanted(tab) ) { XmTabBox__num_wanted(tab) = count; XmTabBox__wanted(tab) = (XRectangle*) XtRealloc((XtPointer)XmTabBox__wanted(tab), sizeof(XRectangle) * count); } geom = XmTabBox__wanted(tab); /* * Now that we have enough space to cache all the Tab sizes we * need to walk through and calculate the size of all the tabs. */ for( i = 0; i < count; ++i ) { /* * Now lets get the info for a tab and send it off to this handy * dandy tab size calculator. */ info = _XmTabbedStackListGet(list, i); XiCalcTabSize(tab, info, &width, &height); /* * Now lets do a quick check here to see if we are going to be * making the tabs uniform and if so lets capture the maximum * width and height of the tabs. */ if( XmTabBox_uniform_tab_size(tab) ) { AssignMax(max_width, width); AssignMax(max_height, height); } else { /* * Since we are not doing uniform sized tabs here we can * assign the values from our size calculation to the * geometry cache. */ geom[i].width = width; geom[i].height = height; } } /* * Well if we are doing uniform tab sizes then we need to make * one more pass over the tab geometry cache assigning the * same width and height to each tab. */ if( XmTabBox_uniform_tab_size(tab) ) { for( i = 0; i < count; ++i ) { geom[i].width = max_width; geom[i].height = max_height; } } } /* * Function: * CalcGeometryMinor(tab, major_d) * Description: * Given the major Dimension calculates the needed minor dimension to * display correctly. * Input: * tab : XmTabBoxWidget - the tab box to work with * major_d : int - the major dimension * Output: * int - the desired minor dimension given the major dimension */ static int #ifndef _NO_PROTO CalcGeometryMinor(XmTabBoxWidget tab, int major_d) #else CalcGeometryMinor(tab, major_d) XmTabBoxWidget tab; int major_d; #endif { XmTabbedStackList list = XmTabBox_tab_list(tab); int count = _XmTabbedStackListCount(list), i, max; XRectangle *geom; /* * First lets check if we have any tabs, because if we do not, then * our minor dimension becomes real easy ... all it is is our * shadow thickness. */ if( count == 0 ) { /* * We do not have any tabs so we want to be the hieght of the * shadow. */ return( tab->manager.shadow_thickness ); } if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { /* * Ok, what is happening here is that we have a width and given this * width we want to see what height we will be. We will start with * the easy check, i.e do we have any tabs. */ /* * We have kids, so what we need to do is fake a given layout with * the specified width but allowing our height to grow. */ switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_OVERLAYED: case XmTABS_SCROLLED: default: /* * This is the simple layout case where all the tabs are in * one row. So for these layouts all we have to do is find * the maximum height of all the tabs. */ for( i = 0, max = 0, geom = XmTabBox__wanted(tab); i < count; ++i ) { AssignMax(max, (int)geom[i].height); } return( max ); case XmTABS_STACKED: case XmTABS_STACKED_STATIC: { int per_line, num_rows, tmp, tab_width, tab_height, offset = XmTabBox_tab_offset(tab); tab_height = XmTabBox__wanted(tab)[0].height; tab_width = XmTabBox__wanted(tab)[0].width; per_line = count; num_rows = (int)(count/per_line) + (count % per_line > 0 ? 1 : 0); tmp = (per_line * tab_width) + (num_rows * offset); while( per_line > 1 && tmp > major_d ) { per_line--; num_rows = (int)(count/per_line) + (count % per_line > 0 ? 1 : 0); tmp = (per_line * tab_width) + (num_rows * offset); } return( num_rows * tab_height ); } } } /* orientation == XmVERTICAL */ switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_OVERLAYED: case XmTABS_SCROLLED: default: for( i = 0, max = 0, geom = XmTabBox__wanted(tab); i < count; ++i ) { AssignMax(max, (int)geom[i].width); } return( max ); case XmTABS_STACKED: case XmTABS_STACKED_STATIC: { int per_line, num_rows, tmp, tab_width, tab_height, offset = XmTabBox_tab_offset(tab); tab_height = XmTabBox__wanted(tab)[0].height; tab_width = XmTabBox__wanted(tab)[0].width; per_line = count; num_rows = (int)(count/per_line) + (count % per_line > 0 ? 1 : 0); tmp = (per_line * tab_height) + (num_rows * offset); while( per_line > 1 && tmp > major_d ) { per_line--; num_rows = (int)(count/per_line) + (count % per_line > 0 ? 1 : 0); tmp = (per_line * tab_height) + (num_rows * offset); } return( num_rows * tab_width ); } } } static int CalcGeometryMajor(XmTabBoxWidget tab, int minor_d) { XmTabbedStackList list = XmTabBox_tab_list(tab); int count = _XmTabbedStackListCount(list), i, max, total, num_rows; int tmp=0, offset = XmTabBox_tab_offset(tab), num_cols; XRectangle *geom; if( count == 0 ) { /* * We don't have any children so our major dimension is simply * our shadow. */ return( tab->manager.shadow_thickness ); } geom = XmTabBox__wanted(tab); /* * Here the taks is to calculate the major dimension given the * minor one. */ if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_OVERLAYED: case XmTABS_SCROLLED: default: /* * For this case the major dimension is simply the length * of all the tabs in one row, reguardless of what the minor * dimension is so lets figure this out. */ for( i = 0, max = 0, total = 0; i < count; ++i ) { total += geom[i].width; AssignMax(max, (int)geom[i].width); } if( XmTabBox_uniform_tab_size(tab) ) { return( max * count ); } return( total ); case XmTABS_STACKED: case XmTABS_STACKED_STATIC: /* * This case is a little harder here. What we want to do is * say given this height how wide do we want to be. So the * first thing we need to do is find the height of our rows * so we know how many we can fit. */ for( i = 0, max = 1; i < count; ++i ) { AssignMax(max, (int)geom[i].height); AssignMax(tmp, (int)geom[i].width); } num_rows = minor_d/ max; AssignMax(num_rows, 1); /* * Now that we know how many rows we are allowed all we * have to do is partition the tabs between the rows and * add on room for the stagger (if needed). */ num_cols = (int)(count/num_rows) + (count % num_rows > 0 ? 1 : 0); total = num_cols * tmp + (num_rows - 1) * offset; return( total ); } } /* Vertical Orientation */ switch( XmTabBox_tab_mode(tab) ) { case XmTABS_BASIC: case XmTABS_OVERLAYED: case XmTABS_SCROLLED: default: /* * For this case the major dimension is simply the length * of all the tabs in one row, reguardless of what the minor * dimension is so lets figure this out. */ for( i = 0, max = 0, total = 0; i < count; ++i ) { total += geom[i].height; AssignMax(max, (int)geom[i].height); } if( XmTabBox_uniform_tab_size(tab) ) { return( max * count ); } return( total ); case XmTABS_STACKED: case XmTABS_STACKED_STATIC: /* * This case is a little harder here. What we want to do is * say given this height how wide do we want to be. So the * first thing we need to do is find the height of our rows * so we know how many we can fit. */ for( i = 0, max = 1; i < count; ++i ) { AssignMax(max, (int)geom[i].width); AssignMax(tmp, (int)geom[i].height); } num_rows = minor_d/ max; AssignMax(num_rows, 1); /* * Now that we know how many rows we are allowed all we * have to do is partition the tabs between the rows and * add on room for the stagger (if needed). */ num_cols = (int)(count/num_rows) + (count % num_rows > 0 ? 1 : 0); total = num_cols * tmp + (num_rows - 1) * offset; return( total ); } } /* * Function: * CallCallbacks(tab, event, from, to) * Description: * Calls the unselect and select callbacks for the XmTabBox * Input: * tab : XmTabBoxWidget - the tab box widget * event : XEvent* - passed through * from : int - the old selected tab * to : int - the new selected tab * Output: * None. */ static void CallCallbacks(XmTabBoxWidget tab, XEvent *event, int from, int to) { XmTabBoxCallbackStruct cbdata; cbdata.reason = XmCR_TAB_UNSELECTED; cbdata.event = event; cbdata.tab_index = from; cbdata.old_index = from; XtCallCallbackList((Widget)tab, XmTabBox_unselect_callback(tab), (XtPointer)&cbdata); cbdata.reason = XmCR_TAB_SELECTED; cbdata.event = event; cbdata.tab_index = to; cbdata.old_index = from; XtCallCallbackList((Widget)tab, XmTabBox_select_callback(tab), (XtPointer)&cbdata); } #ifdef FIX_1381 static void SetRightGC(XmTabBoxWidget tab, GC gc, GC_type gc_type) { XGCValues values; XtGCMask valueMask; static Pixel p = 0; static GC_type last = normal; valueMask = GCForeground; switch( gc_type ) { case normal: if (last !=normal) { values.foreground = p; XChangeGC(XtDisplay(tab),gc, valueMask, &values); } last = normal; break; case insensitive: if (last == normal) p=values.foreground; values.foreground = tab->manager.bottom_shadow_color; XChangeGC(XtDisplay(tab),gc, valueMask, &values); last = insensitive; break; case shadow: if (last == normal) p=values.foreground; values.foreground = tab->manager.top_shadow_color; XChangeGC(XtDisplay(tab),gc, valueMask, &values); last = shadow; break; default: break; } } #endif /* ARGSUSED */ static void DrawLeftToRightTab(XmTabBoxWidget tab, XmTabAttributes info, GC gc, Boolean have_pixmap, int pix_width, int pix_height, int pix_depth, Boolean have_label, int label_width, int label_height, XRectangle *clip) { XRectangle draw; XmFontList font_list = XmTabBox_font_list(tab); int x, y, tmp, spacing = XmTabBox_tab_label_spacing(tab); Boolean sensitive; x = draw.x = clip->x; y = draw.y = clip->y; draw.width = clip->width; draw.height = clip->height; sensitive = XtIsSensitive((Widget)tab) && info->sensitive; /* * If we are drawing both a pixmap and a label then we want to * give priority to the pixmap and align the text in the * rest of the mess. */ if( have_pixmap ) { /* * We have a pixmap, so lets figure out where we want the * pixmap to be placed. */ switch( info->pixmap_placement ) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: case XmPIXMAP_ONLY: default: /* * In these cases we want to look at the alignment of the * tab to determine where we want to place the pixmap. */ switch( info->label_alignment ) { case XmALIGNMENT_BEGINNING: /* * For this alignment we want to slam the pixmap * to the left of the cliping area. */ x = clip->x; break; case XmALIGNMENT_CENTER: default: /* * For this alignment we want to center the pixmap * in the cliping area. */ x = clip->x + ((int)clip->width - pix_width)/ 2; break; case XmALIGNMENT_END: /* * for this alignment we want to slam the pixmap * to the right of the cliping area. */ x = clip->x + (int)clip->width - pix_width; break; } /* * Since the pixmap will affect the amount of vertical * space that I have to place my text lets calculate * what space I have left over (if any) for my text. */ if( (tmp = (int)draw.height - (pix_height + spacing)) < 0 ) { draw.height = 0; } else { draw.height = tmp; } /* * OK now that we know how we want this pixmap positioned * horizontally lets see what we want to do with it * vertically. If we have no label then just center it. */ if( info->label_string == NULL ) { y = clip->y + ((int)clip->height - pix_height)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_TOP: default: y = clip->y; draw.y = y + pix_height + spacing; break; case XmPIXMAP_BOTTOM: y = clip->y + (int)clip->height - pix_height; break; case XmPIXMAP_ONLY: y = clip->y + ((int)clip->height - pix_height)/2; break; } } break; case XmPIXMAP_LEFT: case XmPIXMAP_RIGHT: /* * For this case we want to slam the pixmap to the * left of the clipping area and center it in the * vertical space. */ if( info->label_string == NULL ) { x = clip->x + ((int)clip->width - pix_width)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_LEFT: x = clip->x; draw.x = x + pix_width + spacing; break; case XmPIXMAP_RIGHT: x = clip->x + (int)clip->width - pix_width; break; default: break; } } y = clip->y + ((int)clip->height - pix_height)/2; /* * Since the pixmap will affect the amount of vertical * space that I have to place my text lets calculate * what space I have left over (if any) for my text. */ if( (tmp = (int)draw.width - (pix_width + spacing)) < 0 ) { draw.width = 0; } else { draw.width = tmp; } break; case XmPIXMAP_NONE: /* notreached */ break; } } /* * Now that we know where we are going to draw the pixmap, lets * go ahead and draw the bloody thing. We do a quick check here * to see if we are dealing with a bitmap or a pixmap to * see if we should be copying a plane or and area. Also be sure * to to an XCopyArea if the depth of the pixmap matches the * depth of the canvas. */ if( ValidPixmap(info->label_pixmap) && info->pixmap_placement != XmPIXMAP_NONE ) { if( pix_depth == 1 ) { XCopyPlane(XtDisplay(tab), info->label_pixmap, XiCanvas(tab), gc, 0, 0, pix_width, pix_height, x, y, 1); } else if( pix_depth == XmTabBox__canvas(tab)->core.depth ) { XCopyArea(XtDisplay(tab), info->label_pixmap, XiCanvas(tab), gc, 0, 0, pix_width, pix_height, x, y); } } if( !sensitive ) { /* * Since we are working with a non-sensitve tab, then we need to * stipple the the pixmap, and the only way to do that is * to copy a chess board pattern (the gray stipple) over the pixmap * we just drew. */ SetStippledGC(XtDisplay(tab), tab->manager.background_GC, XmTabBox__gray_stipple(tab)); XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.background_GC, x, y, pix_width, pix_height); RemoveStipple(XtDisplay(tab), tab->manager.background_GC); } /* * Now that we are done drawing the pixmap (if we have one) we * need to draw the textual label (if we have one). */ if( have_label ) { /* * First if we have a pixmap we need to reset our clipping * area to account for the space the pixmap took up. */ if( have_pixmap ) { XSetClipRectangles(XtDisplay(tab), gc, 0, 0, &draw, 1, YXBanded); } /* * Now that we know the rectangle that we are going to * draw the text in lets calculate that x and y position * at which we are going to draw the text. For text it is * real easy we are always going to center the text in the * vertical space and align it according to the alignment * specfified. */ y = draw.y + ((int)draw.height - label_height)/2; /* * Now that we know where the text is going to go, lets * go ahead and draw it. */ if( !sensitive ) { #ifndef FIX_1381 SetStippledGC(XtDisplay(tab), gc, XmTabBox__gray_stipple(tab)); #else /*Draw shadow for insensitive text*/ SetRightGC(tab, gc, shadow); XmStringDraw(XtDisplay(tab), XiCanvas(tab), font_list, info->label_string, gc, draw.x+1, (Position)y+1, draw.width, info->label_alignment, info->string_direction, NULL); SetRightGC(tab, gc, insensitive); #endif } else { #ifndef FIX_1381 RemoveStipple(XtDisplay(tab), gc); #else SetRightGC(tab, gc, normal); #endif } XmStringDraw(XtDisplay(tab), XiCanvas(tab), font_list, info->label_string, gc, draw.x, (Position)y, draw.width, info->label_alignment, info->string_direction, NULL); } } /* * Function: * DrawRightToLeftTab(tab, info, gc, have_pixmap, pix_width, pix_height, * pix_depth, have_label, label_width, label_height, * clip); * Description: * Draw the pixmap and text for a tab withing the clipping rectangle * passed in as "clip". * Input: * tab : XmTabBoxWidget - the tab box that drawing * gc : GC - the GC to draw with * have_pixmap : Boolean - do we need to draw a pixmap ? * pix_width, * pix_height, * pix_depth : int - pixmap information * have_label : Boolean - do we need to draw a label string ? * label_width, * label_height : int - label string information * clip : XRectangle* - the clip rectangle to draw into * Output: * None. */ /* ARGSUSED */ static void DrawRightToLeftTab(XmTabBoxWidget tab, XmTabAttributes info, GC gc, Boolean have_pixmap, int pix_width, int pix_height, int pix_depth, Boolean have_label, int label_width, int label_height, XRectangle *clip, Boolean selected) { XRectangle draw; XmFontList font_list = XmTabBox_font_list(tab); int x, y, tmp, spacing = XmTabBox_tab_label_spacing(tab); XImage *src_ximage, *dst_ximage; Pixmap bitmap; Boolean sensitive; x = draw.x = clip->x; y = draw.y = clip->y; draw.width = clip->width; draw.height = clip->height; sensitive = XtIsSensitive((Widget)tab) && info->sensitive; /* * First lets check if we have a pixmap to draw and if we do * lets rotate and draw it. */ if( have_pixmap ) { /* * We do have a pixmap so we will start by rotating the pixmap * to the correct orientation. */ src_ximage = NULL; if( !XmTabBox_use_image_cache(tab) || (dst_ximage = CachePixmap(tab,info)) == NULL ) { src_ximage = XGetImage(XtDisplay(tab), info->label_pixmap, 0, 0, pix_width, pix_height, AllPlanes, XYPixmap); dst_ximage = XiRotateImage(tab, src_ximage, XiTabDegree(XmTabBox_tab_orientation(tab))); if( XmTabBox_use_image_cache(tab) ) { CachePixmap(tab,info) = dst_ximage; } } /* * Now that we have the rotated image lets snarf the width and height * back into local cache. */ pix_width = XImageWidth(dst_ximage); pix_height = XImageHeight(dst_ximage); /* * Now lets look at the pixmap placement to determine where we want * to place the pixmap. */ switch( info->pixmap_placement ) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: case XmPIXMAP_ONLY: default: /* * Now that we have rotate the ximage lets cache the width * and hieght of that image away for use. */ pix_width = XImageWidth(dst_ximage); pix_height = XImageHeight(dst_ximage); /* * In these cases we want to look at the alignment of the * tab to determine where we want to place the pixmap * vertically. */ switch( info->label_alignment ) { case XmALIGNMENT_BEGINNING: /* * For this alignement we want to slam the pixmap * to the top of the clipping area. */ x = clip->x + (int)clip->width - pix_width; break; case XmALIGNMENT_CENTER: default: /* * For this case we want to center the pixmap in * the vertical space. */ x = clip->x + ((int)clip->width - pix_width)/2; break; case XmALIGNMENT_END: /* * For this alignment we want to slam the pixmap * to the bottom of the clipping area. */ x = clip->x; break; } /* * Since the pixmap will affect the amount of vertical * space to place the text lets calculate what space is * left for the text. */ if( (tmp = (int)draw.height - (pix_height + spacing)) < 0 ) { draw.height = 0; } else { draw.height = tmp; } /* * Ok now that we have positioned the pixmap horizontally * lets see what we want to do with it vertically. If * we have not label then center it. */ if( info->label_string == NULL ) { y = clip->y + ((int)clip->height - pix_height)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_TOP: default: y = clip->y + (int)clip->height - pix_height; break; case XmPIXMAP_BOTTOM: y = clip->y; draw.y = y+ pix_height + spacing; break; case XmPIXMAP_ONLY: y = clip->y + ((int)clip->height - pix_height)/2; break; } } break; case XmPIXMAP_LEFT: case XmPIXMAP_RIGHT: /* * For this case we want to slam the pixmap to either the * top or bottom of the clipping area and center it in * the horizontal space. */ if( info->label_string == NULL ) { x = clip->x + ((int)clip->width - pix_width)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_LEFT: x = clip->x + (int)clip->width - pix_width; break; case XmPIXMAP_RIGHT: x = clip->x; draw.x = x + pix_width + spacing; break; default: break; } } y = clip->y + ((int)clip->height - pix_width)/2; /* * Since the pixmap will affect the amount of * vertical space that the text will have lets * calculate what space is left. */ if( (tmp = (int)draw.width - (pix_width + spacing)) < 0 ) { draw.width = 0; } else { draw.width = tmp; } break; case XmPIXMAP_NONE: /* notreached */ break; } /* * Now that we know where the image is supposed to go, lets * draw the thing. */ XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, pix_width, pix_height); if( !sensitive ) { /* * Since we are working with a non-sensitive tab, then we need to * stipple the the pixmap, and the only way to do that is * to copy a chess board pattern (the gray stipple) over the pixmap * we just drew. */ SetStippledGC(XtDisplay(tab), tab->manager.background_GC, XmTabBox__gray_stipple(tab)); XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.background_GC, x, y, pix_width, pix_height); RemoveStipple(XtDisplay(tab), tab->manager.background_GC); } /* * We are done with the XImages now so lets destroy the * ximages we used to rotate the pixmap. */ if( src_ximage != NULL ) XDestroyImage(src_ximage); if( !XmTabBox_use_image_cache(tab) && dst_ximage != NULL ) { XDestroyImage(dst_ximage); } } /* * Now that we have drawn the pixmap it is time to deal with the * label string. */ if( !have_label || info->label_string == NULL ) return; /* * If we have a pixmap then the clipping area was modified so * we need to set the clip rectangle to that for the text. */ if( have_pixmap ) { XSetClipRectangles(XtDisplay(tab), gc, 0, 0, &draw, 1, YXBanded); } /* * Now we have to render and rotate the label string. To do this * we need to first set up a few things like the pixmap to render * into and GC used to draw into a bitmap. We will start by * making sure that we have a pixmap large enough to * accomidate the string we are about to render. */ src_ximage = NULL; if( !XmTabBox_use_image_cache(tab) || (sensitive != CacheSensitive(tab,info)) || (dst_ximage = CacheLabel(tab, info)) == NULL ) { if( ValidPixmap(XmTabBox__bitmap(tab)) && (XmTabBox__bitmap_width(tab) < label_width || XmTabBox__bitmap_height(tab) < label_height) ) { /* * As it turns out our pixmap is not large enough to * hold the rendered text. So we will destroy the * current pixmap so that we will allocate a pixmap * of the correct size below. */ XFreePixmap(XtDisplay(tab), XmTabBox__bitmap(tab)); XmTabBox__bitmap(tab) = XmUNSPECIFIED_PIXMAP; } /* * If we do not have a bitmap to render the text into * lets create one now. */ if( !ValidPixmap(XmTabBox__bitmap(tab)) ) { XmTabBox__bitmap(tab) = XCreatePixmap(XtDisplay(tab), XiCanvas(tab), #ifndef FIX_1381 label_width, label_height, 1); #else label_width, label_height, XmTabBox__canvas(tab)->core.depth); #endif XmTabBox__bitmap_width(tab) = label_width; XmTabBox__bitmap_height(tab) = label_height; } bitmap = XmTabBox__bitmap(tab); /* * Now that we have a bitmap to render the text into lets make sure * that we have GC that we can use to render the text. We need two * GC, one to clear the pixmap the other to draw into it. */ if( XmTabBox__zero_GC(tab) == NULL ) { /* * We do not yet have either of the GC created so lets go * ahead and create them now. */ XFontStruct *font = NULL; XGCValues gcValues; unsigned long gcMask; #ifndef FIX_1381 gcValues.foreground = 0; gcValues.background = 0; #else gcValues.background = tab->core.background_pixel; gcValues.foreground = tab->core.background_pixel; #endif XmTabBox__zero_GC(tab) = XCreateGC(XtDisplay(tab), bitmap, GCForeground | GCBackground, &gcValues); XmeRenderTableGetDefaultFont(font_list, &font); gcValues.foreground = 1; gcValues.background = 0; gcMask = GCForeground | GCBackground; if (font) { gcValues.font = font->fid; gcMask |= GCFont; } XmTabBox__one_GC(tab) = XCreateGC(XtDisplay(tab), bitmap, gcMask, &gcValues); } /* * Now we have all that we need to render the label string, so now * lets do it. What we need to do if first zero the pixmap and * then render the text. */ XFillRectangle(XtDisplay(tab), bitmap, XmTabBox__zero_GC(tab), 0, 0, label_width, label_height); if( !sensitive ) { #ifndef FIX_1381 SetStippledGC(XtDisplay(tab), XmTabBox__one_GC(tab), XmTabBox__gray_stipple(tab)); #else /*Draw shadow for insensitive text*/ SetRightGC(tab, XmTabBox__one_GC(tab), shadow); XmStringDraw(XtDisplay(tab), bitmap, font_list, info->label_string, XmTabBox__one_GC(tab), -1, -1, (Dimension)label_width, info->label_alignment, info->string_direction, NULL); SetRightGC(tab, XmTabBox__one_GC(tab), insensitive); #endif } else { #ifndef FIX_1381 RemoveStipple(XtDisplay(tab), XmTabBox__one_GC(tab)); #else SetRightGC(tab, XmTabBox__one_GC(tab), normal); #endif } XmStringDraw(XtDisplay(tab), bitmap, font_list, info->label_string, XmTabBox__one_GC(tab), 0, 0, (Dimension)label_width, info->label_alignment, info->string_direction, NULL); /* * Now that the label string is rendered we need to grab it back * into an XImage so that we can rotate it. */ src_ximage = XGetImage(XtDisplay(tab), bitmap, 0, 0, label_width, #ifndef FIX_1381 label_height, 1, XYPixmap); #else label_height, AllPlanes, XYPixmap); #endif dst_ximage = XiRotateImage(tab, src_ximage, XiTabDegree(XmTabBox_tab_orientation(tab))); if( XmTabBox_use_image_cache(tab) ) { CacheLabel(tab, info) = dst_ximage; CacheSensitive(tab,info) = sensitive; } } /* * Now that the text is rotated lets snarf the label width and height * back from the image. */ label_width = XImageWidth(dst_ximage); label_height = XImageHeight(dst_ximage); /* * Now we need to find out where we want to but the text. We know that * we want to center the text in the horizontal space that we have left, * then we want to use the alignment value to determine what to * do with the vertical space. */ y = draw.y + ((int)draw.height - label_height)/2; switch( info->label_alignment ) { case XmALIGNMENT_BEGINNING: /* * Here we want to slam the text to the top of the clipping * area. */ x = draw.x + (int)draw.width - label_width; break; case XmALIGNMENT_CENTER: default: /* * Here we want to center the text in the clipping area. */ x = draw.x + ((int)draw.width - label_width)/2; break; case XmALIGNMENT_END: /* * Here we want to slam the text to the bottom of the * clipping area. */ x = draw.x; break; } /* * Now that we know where we want the text lets push that * XImage over the wire. But first we need to check if we should * mask out the text so that the background pixmap show through. */ if( ValidPixmap(tab->core.background_pixmap) || XiBackgroundSpecified(info) || (selected && XiSelectSpecified(tab)) ) { /* * It appears that we have a background pixmap so what we * want to do is set the clip mask such that we only draw the * text and not the rectangle around it. * * What we are going to do is create a bitmap and draw the text * into this pixmap to create a GC clipping mask. */ Pixmap pix = XCreatePixmap(XtDisplay(tab), (XtIsRealized((Widget)tab) ? XtWindow(tab) : RootWindowOfScreen(XtScreen(tab))), label_width, label_height, 1); /* * Left first clear out the clipping mask and then draw the text * into it. */ XFillRectangle(XtDisplay(tab), pix, XmTabBox__zero_GC(tab), 0, 0, label_width, label_height); XPutImage(XtDisplay(tab), pix, XmTabBox__one_GC(tab), dst_ximage, 0, 0, 0, 0, label_width, label_height); /* * Now that we have the clipping mask lets set the mask to the GC * and then put the image that is the text to the display using this * clipping mask. */ XSetClipMask(XtDisplay(tab), gc, pix); XSetClipOrigin(XtDisplay(tab), gc, x, y); XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, label_width, label_height); /* * We are done with this cliping mask so lets destroy the pixmap. */ XFreePixmap(XtDisplay(tab), pix); } else { XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, label_width, label_height); } /* * Now that we are done with the XImages used for rotating the * text lets delete them. */ if( src_ximage != NULL ) XDestroyImage(src_ximage); if( !XmTabBox_use_image_cache(tab) && dst_ximage != NULL ) { XDestroyImage(dst_ximage); } } /* * Function: * DrawBottomToTopTab(tab, info, gc, have_pixmap, pix_width, pix_height, * pix_depth, have_label, label_width, label_height, * clip); * Description: * Draw the pixmap and text for a tab withing the clipping rectangle * passed in as "clip". * Input: * tab : XmTabBoxWidget - the tab box that drawing * gc : GC - the GC to draw with * have_pixmap : Boolean - do we need to draw a pixmap ? * pix_width, * pix_height, * pix_depth : int - pixmap information * have_label : Boolean - do we need to draw a label string ? * label_width, * label_height : int - label string information * clip : XRectangle* - the clip rectangle to draw into * Output: * None. */ static void DrawBottomToTopTab(XmTabBoxWidget tab, XmTabAttributes info, GC gc, Boolean have_pixmap, int pix_width, int pix_height, int pix_depth, Boolean have_label, int label_width, int label_height, XRectangle *clip, Boolean selected) { DrawVerticalTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip, False, selected); } /* * Function: * DrawTopToBottomTab(tab, info, gc, have_pixmap, pix_width, pix_height, * pix_depth, have_label, label_width, label_height, * clip); * Description: * Draw the pixmap and text for a tab withing the clipping rectangle * passed in as "clip". * Input: * tab : XmTabBoxWidget - the tab box that drawing * gc : GC - the GC to draw with * have_pixmap : Boolean - do we need to draw a pixmap ? * pix_width, * pix_height, * pix_depth : int - pixmap information * have_label : Boolean - do we need to draw a label string ? * label_width, * label_height : int - label string information * clip : XRectangle* - the clip rectangle to draw into * Output: * None. */ static void DrawTopToBottomTab(XmTabBoxWidget tab, XmTabAttributes info, GC gc, Boolean have_pixmap, int pix_width, int pix_height, int pix_depth, Boolean have_label, int label_width, int label_height, XRectangle *clip, Boolean selected) { DrawVerticalTab(tab, info, gc, have_pixmap, pix_width, pix_height, pix_depth, have_label, label_width, label_height, clip, True, selected); } /* * Function: * DrawVerticalTab(tab, info, gc, have_pixmap, pix_width, pix_height, * pix_depth, have_label, label_width, label_height, * clip, top_to_bottom); * Description: * Draw the pixmap and text for a tab withing the clipping rectangle * passed in as "clip". * Input: * tab : XmTabBoxWidget - the tab box that drawing * gc : GC - the GC to draw with * have_pixmap : Boolean - do we need to draw a pixmap ? * pix_width, * pix_height, * pix_depth : int - pixmap information * have_label : Boolean - do we need to draw a label string ? * label_width, * label_height : int - label string information * clip : XRectangle* - the clip rectangle to draw into * top_to_bottom : Boolean - drawing top to bottom(True) or * bottom to top(False) * Output: * None. */ /* ARGSUSED */ static void DrawVerticalTab(XmTabBoxWidget tab, XmTabAttributes info, GC gc, Boolean have_pixmap, int pix_width, int pix_height, int pix_depth, Boolean have_label, int label_width, int label_height, XRectangle *clip, Boolean top_to_bottom, Boolean selected) { XRectangle draw; XmFontList font_list = XmTabBox_font_list(tab); int x, y, tmp, spacing = XmTabBox_tab_label_spacing(tab); XImage *src_ximage, *dst_ximage; Pixmap bitmap; Boolean sensitive; x = draw.x = clip->x; y = draw.y = clip->y; draw.width = clip->width; draw.height = clip->height; sensitive = XtIsSensitive((Widget)tab) && info->sensitive; /* * First lets check if we have a pixmap to draw and if we do * lets rotate and draw it. */ if( have_pixmap ) { /* * We do have a pixmap so we will start by rotating the pixmap * to the correct orientation. */ src_ximage = NULL; if( !XmTabBox_use_image_cache(tab) || (dst_ximage = CachePixmap(tab,info)) == NULL ) { src_ximage = XGetImage(XtDisplay(tab), info->label_pixmap, 0, 0, pix_width, pix_height, AllPlanes, XYPixmap); dst_ximage = XiRotateImage(tab, src_ximage, XiTabDegree(XmTabBox_tab_orientation(tab))); if( XmTabBox_use_image_cache(tab) ) { CachePixmap(tab,info) = dst_ximage; } } /* * Now that we have the rotated image lets snarf the width and height * back into local cache. */ pix_width = XImageWidth(dst_ximage); pix_height = XImageHeight(dst_ximage); /* * Now lets look at the pixmap placement to determine where we want * to place the pixmap. */ switch( info->pixmap_placement ) { case XmPIXMAP_TOP: case XmPIXMAP_BOTTOM: case XmPIXMAP_ONLY: default: /* * Now that we have rotate the ximage lets cache the width * and hieght of that image away for use. */ pix_width = XImageWidth(dst_ximage); pix_height = XImageHeight(dst_ximage); /* * In these cases we want to look at the alignment of the * tab to determine where we want to place the pixmap * vertically. */ switch( info->label_alignment ) { case XmALIGNMENT_BEGINNING: /* * For this alignement we want to slam the pixmap * to the top of the clipping area. */ if( top_to_bottom ) { y = clip->y; } else { y = clip->y + (int)clip->height - pix_height; } break; case XmALIGNMENT_CENTER: default: /* * For this case we want to center the pixmap in * the vertical space. */ y = clip->y + ((int)clip->height - pix_height)/2; break; case XmALIGNMENT_END: /* * For this alignment we want to slam the pixmap * to the bottom of the clipping area. */ if( top_to_bottom ) { y = clip->y + (int)clip->height - pix_height; } else { y = clip->y; } break; } /* * Since the pixmap will affect the amount of horizontal * space to place the text lets calculate what space is * left for the text. */ if( (tmp = (int)draw.width - (pix_width + spacing)) < 0 ) { draw.width = 0; } else { draw.width = tmp; } /* * Ok now that we have positioned the pixmap vertically * lets see what we want to do with it horizontally. If * we have not label then center it. */ if( info->label_string == NULL ) { x = clip->x + ((int)clip->width - pix_width)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_TOP: default: if( top_to_bottom ) { x = clip->x + (int)clip->width - pix_width; } else { x = clip->x; draw.x = x + pix_width + spacing; } break; case XmPIXMAP_BOTTOM: if( top_to_bottom ) { x = clip->x; draw.x = x + pix_width + spacing; } else { x = clip->x + (int)clip->width - pix_width; } break; case XmPIXMAP_ONLY: x = clip->x + ((int)clip->width - pix_width)/2; break; } } break; case XmPIXMAP_LEFT: case XmPIXMAP_RIGHT: /* * For this case we want to slam the pixmap to either the * top or bottom of the clipping area and center it in * the horizontal space. */ if( info->label_string == NULL ) { y = clip->y + ((int)clip->height - pix_height)/2; } else { switch( info->pixmap_placement ) { case XmPIXMAP_LEFT: if( top_to_bottom ) { y = clip->y; draw.y = y + pix_height + spacing; } else { y = clip->y + (int)clip->height - pix_height; } break; case XmPIXMAP_RIGHT: if( top_to_bottom ) { y = clip->y + (int)clip->height - pix_height; } else { y = clip->y; draw.y = y + pix_height + spacing; } break; default: break; } } x = clip->x + ((int)clip->width - pix_width)/2; /* * Since the pixmap will affect the amount of * vertical space that the text will have lets * calculate what space is left. */ if( (tmp = (int)draw.height - (pix_height + spacing)) < 0 ) { draw.height = 0; } else { draw.height = tmp; } break; case XmPIXMAP_NONE: /* notreached */ break; } /* * Now that we know where the image is supposed to go, lets * draw the thing. */ XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, pix_width, pix_height); if( !sensitive ) { /* * Since we are working with a non-sensitive tab, then we need to * stipple the the pixmap, and the only way to do that is * to copy a chess board pattern (the gray stipple) over the pixmap * we just drew. */ SetStippledGC(XtDisplay(tab), tab->manager.background_GC, XmTabBox__gray_stipple(tab)); XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.background_GC, x, y, pix_width, pix_height); RemoveStipple(XtDisplay(tab), tab->manager.background_GC); } /* * We are done with the XImages now so lets destroy the * ximages we used to rotate the pixmap. */ if( src_ximage != NULL ) XDestroyImage(src_ximage); if( !XmTabBox_use_image_cache(tab) && dst_ximage != NULL ) { XDestroyImage(dst_ximage); } } /* * Now that we have drawn the pixmap it is time to deal with the * label string. */ if( !have_label || info->label_string == NULL ) return; /* * If we have a pixmap then the clipping area was modified so * we need to set the clip rectangle to that for the text. */ if( have_pixmap ) { XSetClipRectangles(XtDisplay(tab), gc, 0, 0, &draw, 1, YXBanded); } src_ximage = NULL; if( !XmTabBox_use_image_cache(tab) || (sensitive != CacheSensitive(tab,info)) || (dst_ximage = CacheLabel(tab, info)) == NULL ) { /* * Now we have to render and rotate the label string. To do this * we need to first set up a few things like the pixmap to render * into and GC used to draw into a bitmap. We will start by * making sure that we have a pixmap large enough to * accomidate the string we are about to render. */ if( ValidPixmap(XmTabBox__bitmap(tab)) && (XmTabBox__bitmap_width(tab) < label_width || XmTabBox__bitmap_height(tab) < label_height) ) { /* * As it turns out our pixmap is not large enough to * hold the rendered text. So we will destroy the * current pixmap so that we will allocate a pixmap * of the correct size below. */ XFreePixmap(XtDisplay(tab), XmTabBox__bitmap(tab)); XmTabBox__bitmap(tab) = XmUNSPECIFIED_PIXMAP; } /* * If we do not have a bitmap to render the text into * lets create one now. */ if( !ValidPixmap(XmTabBox__bitmap(tab)) ) { XmTabBox__bitmap(tab) = XCreatePixmap(XtDisplay(tab), XiCanvas(tab), #ifndef FIX_1381 label_width, label_height, 1); #else label_width, label_height, XmTabBox__canvas(tab)->core.depth); #endif XmTabBox__bitmap_width(tab) = label_width; XmTabBox__bitmap_height(tab) = label_height; } bitmap = XmTabBox__bitmap(tab); /* * Now that we have a bitmap to render the text into lets make sure * that we have GC that we can use to render the text. We need two * GC, one to clear the pixmap the other to draw into it. */ if( XmTabBox__zero_GC(tab) == NULL ) { /* * We do not yet have either of the GC created so lets go * ahead and create them now. */ XFontStruct *font = NULL; XGCValues gcValues; unsigned long gcMask; #ifndef FIX_1381 gcValues.foreground = 0; gcValues.background = 0; #else gcValues.background = tab->core.background_pixel; gcValues.foreground = tab->core.background_pixel; #endif XmTabBox__zero_GC(tab) = XCreateGC(XtDisplay(tab), bitmap, GCForeground | GCBackground, &gcValues); XmeRenderTableGetDefaultFont(font_list, &font); gcValues.foreground = 1; gcValues.background = 0; gcMask = GCForeground | GCBackground; if (font) { gcValues.font = font->fid; gcMask |= GCFont; } XmTabBox__one_GC(tab) = XCreateGC(XtDisplay(tab), bitmap, gcMask, &gcValues); } /* * Now we have all that we need to render the label string, so now * lets do it. What we need to do if first zero the pixmap and * then render the text. */ XFillRectangle(XtDisplay(tab), bitmap, XmTabBox__zero_GC(tab), 0, 0, label_width, label_height); if( !sensitive ) { #ifndef FIX_1381 SetStippledGC(XtDisplay(tab), XmTabBox__one_GC(tab), XmTabBox__gray_stipple(tab)); #else /*Draw shadow for insensitive text*/ /*text will be rotated below but shadow should be always under the text*/ int x,y; if (XmTabBox_tab_orientation(tab)==XmTABS_TOP_TO_BOTTOM){ x=1; y=-1; } else { x=-1; y=1; } SetRightGC(tab, XmTabBox__one_GC(tab), shadow); XmStringDraw(XtDisplay(tab), bitmap, font_list, info->label_string, XmTabBox__one_GC(tab), x, y, (Dimension)label_width, info->label_alignment, info->string_direction, NULL); SetRightGC(tab, XmTabBox__one_GC(tab), insensitive); #endif } else { #ifndef FIX_1381 RemoveStipple(XtDisplay(tab), XmTabBox__one_GC(tab)); #else SetRightGC(tab, XmTabBox__one_GC(tab), normal); #endif } XmStringDraw(XtDisplay(tab), bitmap, font_list, info->label_string, XmTabBox__one_GC(tab), 0, 0, (Dimension)label_width, info->label_alignment, info->string_direction, NULL); /* * Now that the label string is rendered we need to grab it back * into an XImage so that we can rotate it. */ src_ximage = XGetImage(XtDisplay(tab), bitmap, 0, 0, label_width, #ifndef FIX_1381 label_height, 1, XYPixmap); #else label_height, AllPlanes, XYPixmap); #endif dst_ximage = XiRotateImage(tab, src_ximage, XiTabDegree(XmTabBox_tab_orientation(tab))); if( XmTabBox_use_image_cache(tab) ) { CacheLabel(tab, info) = dst_ximage; CacheSensitive(tab,info) = sensitive; } } /* * Now that the text is rotated lets snarf the label width and height * back from the image. */ if (dst_ximage) { label_width = XImageWidth(dst_ximage); label_height = XImageHeight(dst_ximage); } else { label_width = 0; label_height = 0; } /* * Now we need to find out where we want to but the text. We know that * we want to center the text in the horizontal space that we have left, * then we want to use the alignment value to determine what to * do with the vertical space. */ x = draw.x + ((int)draw.width - label_width)/2; switch( info->label_alignment ) { case XmALIGNMENT_BEGINNING: /* * Here we want to slam the text to the top of the clipping * area. */ if( top_to_bottom ) { y = draw.y; } else { y = draw.y + (int)draw.height - label_height; } break; case XmALIGNMENT_CENTER: default: /* * Here we want to center the text in the clipping area. */ y = draw.y + ((int)draw.height - label_height)/2; break; case XmALIGNMENT_END: /* * Here we want to slam the text to the bottom of the * clipping area. */ if( top_to_bottom ) { y = draw.y + (int)draw.height - label_height; } else { y = draw.y; } break; } /* * Now that we know where we want the text lets push that * XImage over the wire. But first we need to check if we should * mask out the text so that the background pixmap show through. */ if( ValidPixmap(tab->core.background_pixmap) || XiBackgroundSpecified(info) || (selected && XiSelectSpecified(tab)) ) { /* * It appears that we have a background pixmap so what we * want to do is set the clip mask such that we only draw the * text and not the rectangle around it. * * What we are going to do is create a bitmap and draw the text * into this pixmap to create a GC clipping mask. */ Pixmap pix = XCreatePixmap(XtDisplay(tab), (XtIsRealized((Widget)tab) ? XtWindow(tab) : RootWindowOfScreen(XtScreen(tab))), label_width, label_height, 1); /* * Left first clear out the clipping mask and then draw the text * into it. */ XFillRectangle(XtDisplay(tab), pix, XmTabBox__zero_GC(tab), 0, 0, label_width, label_height); XPutImage(XtDisplay(tab), pix, XmTabBox__one_GC(tab), dst_ximage, 0, 0, 0, 0, label_width, label_height); /* * Now that we have the clipping mask lets set the mask to the GC * and then put the image that is the text to the display using this * clipping mask. */ XSetClipMask(XtDisplay(tab), gc, pix); XSetClipOrigin(XtDisplay(tab), gc, x, y); XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, label_width, label_height); /* * We are done with this cliping mask so lets destroy the pixmap. */ XFreePixmap(XtDisplay(tab), pix); } else { if (dst_ximage) XPutImage(XtDisplay(tab), XiCanvas(tab), gc, dst_ximage, 0, 0, x, y, label_width, label_height); } /* * Now that we are done with the XImages used for rotating the * text lets delete them. */ if( src_ximage != NULL ) XDestroyImage(src_ximage); if( !XmTabBox_use_image_cache(tab) && dst_ximage != NULL ) { XDestroyImage(dst_ximage); } } static void FillRoundedTab(XmTabBoxWidget tab, GC gc, XiTabRect *geometry, XmTabEdge edge) { XRectangle rect[2]; int x = geometry->x, y = geometry->y, width = geometry->width, height = geometry->height, side; side = XmTabBox__corner_size(tab); if( width < height ) { AssignMin(side, (width/2)); } else { AssignMin(side, (height/2)); } switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { rect[0].x = x; rect[0].y = y; rect[0].width = width; rect[0].height = height - side; rect[1].x = x + side; rect[1].y = y + height - side; rect[1].width = width - (2 * side); rect[1].height = side; XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x, y + height - side, side, side, XiQUAD_3); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x + width - side, y + height - side, side, side, XiQUAD_4); } else { rect[0].x = x; rect[0].y = y; rect[0].width = width - side; rect[0].height = height; rect[1].x = x + width - side; rect[1].y = y + side; rect[1].width = side; rect[1].height = height - (2 * side); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x + width - side, y, side, side, XiQUAD_1); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x + width - side, y + height - side, side, side, XiQUAD_4); } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { rect[0].x = x; rect[0].y = y + side; rect[0].width = width; rect[0].height = height - side; rect[1].x = x + side; rect[1].y = y; rect[1].width = width - (2 * side); rect[1].height = side; XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x + width - side, y, side, side, XiQUAD_1); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x, y, side, side, XiQUAD_2); } else { rect[0].x = x + side; rect[0].y = y; rect[0].width = width - side; rect[0].height = height; rect[1].x = x; rect[1].y = y + side; rect[1].width = side; rect[1].height = height - (2 * side); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x, y, side, side, XiQUAD_2); XiFillCorner(XtDisplay(tab), XiCanvas(tab), gc, x, y + height - side, side, side, XiQUAD_3); } break; } XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, 2); } static void FillBeveledTab(XmTabBoxWidget tab, GC gc, XiTabRect *geometry, XmTabEdge edge) { XPoint pt[6]; int x = geometry->x, y = geometry->y, width = geometry->width, height = geometry->height, side; side = XmTabBox__corner_size(tab); if( width < height ) { AssignMin(side, (width/2)); } else { AssignMin(side, (height/2)); } switch( edge ) { case XmTAB_EDGE_TOP_LEFT: default: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { pt[0].x = x; pt[0].y = y; pt[1].x = x; pt[1].y = y + height - side; pt[2].x = x + side; pt[2].y = y + height; pt[3].x = x + width - side; pt[3].y = y + height; pt[4].x = x + width; pt[4].y = y + height - side; pt[5].x = x + width; pt[5].y = y; } else { pt[0].x = x; pt[0].y = y; pt[1].x = x + width - side; pt[1].y = y; pt[2].x = x + width; pt[2].y = y + side; pt[3].x = x + width; pt[3].y = y + height - side; pt[4].x = x + width - side; pt[4].y = y + height; pt[5].x = x; pt[5].y = y + height; } break; case XmTAB_EDGE_BOTTOM_RIGHT: if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { pt[0].x = x; pt[0].y = y + height; pt[1].x = x; pt[1].y = y + side; pt[2].x = x + side; pt[2].y = y; pt[3].x = x + width - side; pt[3].y = y; pt[4].x = x + width; pt[4].y = y + side; pt[5].x = x + width; pt[5].y = y + height; } else { pt[0].x = x + width; pt[0].y = y + height; pt[1].x = x + side; pt[1].y = y + height; pt[2].x = x; pt[2].y = y + height - side; pt[3].x = x; pt[3].y = y + side; pt[4].x = x + side; pt[4].y = y; pt[5].x = x + width; pt[5].y = y; } break; } XFillPolygon(XtDisplay(tab), XiCanvas(tab), gc, pt, 6, Nonconvex, CoordModeOrigin); } int XmTabBoxGetIndex(Widget widget, int x, int y) { return( XiXYtoTab((XmTabBoxWidget)widget, x, y) ); } static void CalcStackedGeometry(XmTabBoxWidget tab, XRectangle *rect) { XmTabbedStackList list = XmTabBox_tab_list(tab); XmTabAttributes info; int i, count = _XmTabbedStackListCount(list), max_width, max_height, tab_width, tab_height, num_stacks = XmTabBox_num_stacks(tab); Dimension d_width, d_height; /* * Calculating the geometry we want for the stack layout turns * out to be straight forward. What we do is find calculate the * size of the largest tab and then use that to calculate the * geometry we want. */ max_width = max_height = 0; for( i = 0; i < count; ++i ) { info = _XmTabbedStackListGet(list, i); XiCalcTabSize(tab, info, &d_width, &d_height); AssignMax(max_width, (int)d_width); AssignMax(max_height, (int)d_height); XmTabBox__wanted(tab)[i].width = d_width; XmTabBox__wanted(tab)[i].height = d_height; } /* * Since we are in stacked modes, all tabs must be the same size. */ for( i = 0; i < count; ++i ) { XmTabBox__wanted(tab)[i].width = max_width; XmTabBox__wanted(tab)[i].height = max_height; } /* * Now that we know what the max tab's size is so lets use that and * the XmNnumStacks resource to figure out the size that we want to * be. */ if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { tab_width = num_stacks * max_width; tab_height = ((int)(count/num_stacks) + (count%num_stacks ? 1 : 0)) * max_height; } else { tab_height = num_stacks * max_height; tab_width = ((int)(count/num_stacks) + (count%num_stacks ? 1 : 0)) * max_width; } rect->width = tab_width; rect->height = tab_height; } static void HorizontalStackedLayout(XmTabBoxWidget tab, Boolean is_static) { int i, x, y, width, per_line, num_rows, tab_width, tab_height, tmp, on_line, start_x, offset, row, idx, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); XiTabRect *actual = XmTabBox__actual(tab); XRectangle *wanted = XmTabBox__wanted(tab); if( cnt == 0 ) return; offset = XmTabBox_tab_offset(tab); width = XtWidth(tab); tab_width = 0; for( i = 0; i < cnt; ++i ) { AssignMax(tab_width, (int)wanted[i].width); } /* * Since we are doing a stacked layout we know that uniform tab * size are a must, so lets find out how many tabs we can fit on * a line. */ per_line = cnt; num_rows = (int)(cnt/per_line) + (cnt % per_line > 0 ? 1 : 0); tmp = (per_line * tab_width) + (num_rows * offset); while( per_line > 1 && tmp > width ) { per_line--; num_rows = (int)(cnt/per_line) + (cnt % per_line > 0 ? 1 : 0); tmp = (per_line * tab_width) + (num_rows * offset); } AssignMax(num_rows, 1); AssignMax(per_line, 1); tab_height = ((int)XtHeight(tab))/ num_rows; if( num_rows > 1 ) { tab_width = (((int)XtWidth(tab)) - ((num_rows-1) * offset))/per_line; } AssignMax(tab_height, 1); AssignMax(tab_width, 1); /* * Now that we know what size each tab is going to be, we need to * the location for each tab. This is done differently depending * if we are doing a static or dynamic stacked layout. For the * static layout the tabs are always in the same location so we * can choose a row/column as we place them. For the dynamic we * will first choose a row column and then a pixel location. */ if( is_static ) { start_x = x = (LayoutIsRtoLP(tab) ? (per_line-1) * tab_width + offset * (num_rows-1) : 0); on_line = 0; row = 0; if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { y = (int) XtHeight(tab) - tab_height; for( i = 0; i < cnt; ++i ) { actual[i].x = x; actual[i].y = y; actual[i].width = tab_width; actual[i].height = tab_height; actual[i].row = row; actual[i].column = on_line; if( ++on_line >= per_line ) { on_line = 0; start_x += (LayoutIsRtoLP(tab) ? -offset : offset); x = start_x; y -= tab_height; row++; } else { x += (LayoutIsRtoLP(tab) ? -tab_width : tab_width); } } } else { y = 0; for( i = 0; i < cnt; ++i ) { actual[i].x = x; actual[i].y = y; actual[i].width = tab_width; actual[i].height = tab_height; actual[i].row = row; actual[i].column = on_line; if( ++on_line >= per_line ) { on_line = 0; start_x += (LayoutIsRtoLP(tab) ? -offset : offset); x = start_x; y += tab_height; row++; } else { x += (LayoutIsRtoLP(tab) ? -tab_width : tab_width); } } } XmTabBox__num_rows(tab) = num_rows; XmTabBox__num_columns(tab) = per_line; } else { /* * The challenge here is to make sure that the selected tab is * always on row 0. So the first thing we need to do is break up * the tabs into rows. */ start_x = x = (LayoutIsRtoLP(tab) ? (per_line-1)*tab_width + offset*(num_rows-1) : 0); on_line = 0; row = 0; if( XmTabBox__selected(tab) < 0 ) { idx = 0; } else { idx = (int)(XmTabBox__selected(tab)/ per_line) * per_line; } if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { y = (int) XtHeight(tab) - tab_height; for( i = 0; i < cnt; ++i ) { actual[idx].x = x; actual[idx].y = y; actual[idx].width = tab_width; actual[idx].height = tab_height; actual[idx].row = row; actual[idx++].column = on_line; if( ++on_line >= per_line || idx >= cnt ) { on_line = 0; start_x += LayoutIsRtoLP(tab) ? -offset : offset; x = start_x; y -= tab_height; row++; } else { x += LayoutIsRtoLP(tab) ? -tab_width : tab_width; } if( idx >= cnt ) idx = 0; } } else { y = 0; for( i = 0; i < cnt; ++i ) { actual[idx].x = x; actual[idx].y = y; actual[idx].width = tab_width; actual[idx].height = tab_height; actual[idx].row = row; actual[idx++].column = on_line; if( ++on_line >= per_line || idx >= cnt ) { on_line = 0; start_x += LayoutIsRtoLP(tab) ? -offset : offset; x = start_x; y += tab_height; row++; } else { x += LayoutIsRtoLP(tab) ? -tab_width : tab_width; } if( idx >= cnt ) idx = 0; } } XmTabBox__num_rows(tab) = num_rows; XmTabBox__num_columns(tab) = per_line; } } static void VerticalStackedLayout(XmTabBoxWidget tab, Boolean is_static) { int i, x, y, height, per_line, num_rows, tab_width, tab_height, tmp, on_line, start_y, offset, row, idx, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); XiTabRect *actual = XmTabBox__actual(tab); XRectangle *wanted = XmTabBox__wanted(tab); if( cnt == 0 ) return; offset = XmTabBox_tab_offset(tab); height = XtHeight(tab); tab_height = 0; for( i = 0; i < cnt; ++i ) { AssignMax(tab_height, (int)wanted[i].height); } per_line = cnt; num_rows = (int)(cnt/per_line) + (cnt % per_line > 0 ? 1 : 0); tmp = (per_line * tab_height) + (num_rows * offset); while( per_line > 1 && tmp > height ) { per_line--; num_rows = (int)(cnt/per_line) + (cnt % per_line > 0 ? 1 : 0); tmp = (per_line * tab_height) + (num_rows * offset); } AssignMax(num_rows, 1); AssignMax(per_line, 1); if( num_rows > 1 ) { tab_height = (((int)XtHeight(tab)) - ((num_rows-1) * offset))/per_line; } tab_width = ((int)XtWidth(tab))/num_rows; AssignMax(tab_height, 1); AssignMax(tab_width, 1); /* * Now that we know what size each tab is going to be, we need to * the location for each tab. This is done differently depending * if we are doing a static or dynamic stacked layout. For the * static layout the tabs are always in the same location so we * can choose a row/column as we place them. For the dynamic we * will first choose a row column and then a pixel location. */ if( is_static ) { start_y = y = 0; on_line = 0; row = 0; if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { x = (int)XtWidth(tab) - tab_width; for( i = 0; i < cnt; ++i ) { actual[i].x = x; actual[i].y = y; actual[i].width = tab_width; actual[i].height = tab_height; actual[i].row = row; actual[i].column = on_line; if( ++on_line >= per_line ) { on_line = 0; start_y += offset; y = start_y; x -= tab_width; row++; } else { y += tab_height; } } } else { x = 0; for( i = 0; i < cnt; ++i ) { actual[i].x = x; actual[i].y = y; actual[i].width = tab_width; actual[i].height = tab_height; actual[i].row = row; actual[i].column = on_line; if( ++on_line >= per_line ) { on_line = 0; start_y += offset; y = start_y; x += tab_width; row++; } else { y += tab_height; } } } XmTabBox__num_rows(tab) = num_rows; XmTabBox__num_columns(tab) = per_line; } else { /* * The challenge here is to make sure that the selected tab is * always on row 0. So the first thing we need to do is break up * the tabs into rows. */ start_y = y = 0; on_line = 0; row = 0; if( XmTabBox__selected(tab) < 0 ) { idx = 0; } else { idx = (int)(XmTabBox__selected(tab)/ per_line) * per_line; } if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { x = (int)XtWidth(tab) - tab_width; for( i = 0; i < cnt; ++i ) { actual[idx].x = x; actual[idx].y = y; actual[idx].width = tab_width; actual[idx].height = tab_height; actual[idx].row = row; actual[idx++].column = on_line; if( ++on_line >= per_line || idx >= cnt ) { on_line = 0; start_y += offset; y = start_y; x -= tab_width; row++; } else { y += tab_height; } if( idx >= cnt ) idx = 0; } } else { x = 0; for( i = 0; i < cnt; ++i ) { actual[idx].x = x; actual[idx].y = y; actual[idx].width = tab_width; actual[idx].height = tab_height; actual[idx].row = row; actual[idx++].column = on_line; if( ++on_line >= per_line || idx >= cnt ) { on_line = 0; start_y += offset; y = start_y; x += tab_width; row++; } else { y += tab_height; } if( idx >= cnt ) idx = 0; } } XmTabBox__num_rows(tab) = num_rows; XmTabBox__num_columns(tab) = per_line; } } /* * Function: * RedisplayTabs(tab, region) * Description: * Walks the list of tabs and redisplays any tab that intersets with * the given region. If the region specified is "False" then all tabs * are exposed (see macro XiRectInRegion). * Input: * tab : XmTabBoxWidget - tab box, whose tabs need redisplayed * region : Region - the region to expose or False for all * Output: * None. */ static void RedisplayTabs(XmTabBoxWidget tab, Region region) { XiTabRect *geom; int i, count = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); XmTabAttributes info; /* * Now lets walk through our list of tabs and redisplay any tab that * lies in the region. */ geom = XmTabBox__actual(tab); for( i = 0; i < count; ++i ) { if( XiRectInRegion(region, geom[i].x, geom[i].y, geom[i].width, geom[i].height) ) { info = _XmTabbedStackListGet(XmTabBox_tab_list(tab), i); DrawTab(tab, info, &(geom[i]), (Boolean)(XmTabBox__selected(tab) == i), (Boolean)(XmTabBox__keyboard(tab) == i)); } } } static void HorizontalStackedBottomEdgeRedisplay(XmTabBoxWidget tab) { XmTabbedStackList list = XmTabBox_tab_list(tab); int i, count = _XmTabbedStackListCount(list), row = 0, col, shadow = tab->manager.shadow_thickness, x, height, offset, idx, below, corner, cnt, first, last, x1, x2; XmTabAttributes info; XiTabRect *geom; GC gc = XmTabBox__tab_GC(tab); Boolean do_top, do_bottom; #define _NUM_RECTS 10 XRectangle rect[_NUM_RECTS], top = {0, 0, 0, 0}, bottom = {0, 0, 0, 0}; /* * What we need to do in this mode is to extend the right most tab * on each row to the bottom of the widget(minus the shadow). Besides * the bcakground of the widget we also need to extend the shadow. */ offset = XmTabBox_tab_offset(tab); geom = XmTabBox__actual(tab); /* * First the quick check. If we only have one row then all we need to do * is draw the base line from the end of the last tab to the right edge. */ if( XmTabBox__num_rows(tab) == 1 && (idx = GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1)) >= 0 ) { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } x = geom[idx].x + geom[idx].width; XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, x, (int)XtHeight(tab) - shadow, (int)XtWidth(tab) - x, shadow); XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, x, 0, (int)XtWidth(tab) - x, (int)XtHeight(tab) - shadow); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - shadow, shadow, XmBEVEL_BOTTOM); return; } for( i = 0; i < count; ++i ) { corner = GetTabIndex(tab, geom[i].row-1, geom[i].column+1); below = GetTabIndex(tab, geom[i].row-1, geom[i].column); if( geom[i].row > 0 && (corner < 0 || below < 0) ) { cnt = 0; do_top = do_bottom = False; info = _XmTabbedStackListGet(list, i); if( XiBackgroundSpecified(info) ) { SetBackgroundGC(tab, info, gc); } else if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledGC(XtDisplay(tab), gc, tab->core.background_pixmap); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } for( height = geom[i].height, row = geom[i].row - 2; row >= 0 && GetTabIndex(tab, row, geom[i].column+1) < 0; row--, height += geom[i].height ); if( corner < 0 ) { if (LayoutIsRtoLP(tab)) { rect[cnt].x = geom[i].x; rect[cnt].y = geom[i].y + geom[i].height; rect[cnt].width = offset; rect[cnt++].height = height; bottom.x = geom[i].x; bottom.y = geom[i].y + geom[i].height; } else { rect[cnt].x = geom[i].x + geom[i].width - offset; rect[cnt].y = geom[i].y + geom[i].height; rect[cnt].width = offset; rect[cnt++].height = height; bottom.x = geom[i].x + geom[i].width - shadow; bottom.y = geom[i].y + geom[i].height; } bottom.width = shadow; bottom.height = height; do_bottom = True; } if( below < 0 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = geom[i].x + offset; } else { rect[cnt].x = geom[i].x; } rect[cnt].y = geom[i].y + geom[i].height; rect[cnt].width = geom[i].width - offset; rect[cnt].height = geom[i].height; cnt++; if( LayoutIsRtoLP(tab) ) { top.x = geom[i].x + geom[i].width - shadow; } else { top.x = geom[i].x; } top.y = geom[i].y + geom[i].height; top.width = shadow; top.height = geom[i].height; do_top = True; if( geom[i].row > 1 && geom[i].column == XmTabBox__num_columns(tab) - 1 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = offset; } else { rect[cnt].x = geom[i].x + geom[i].width - (2*offset); } rect[cnt].y = geom[i].y + geom[i].height; rect[cnt].width = offset; rect[cnt].height = (int)XtHeight(tab) - rect[cnt].y; cnt++; } } XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); if( do_bottom ) { if( LayoutIsRtoLP(tab) ) XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, bottom.x, bottom.y, bottom.width, bottom.height); else XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, bottom.x, bottom.y, bottom.width, bottom.height); } if( do_top ) { if( LayoutIsRtoLP(tab) ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, top.x, top.y, top.width, top.height); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, top.x, top.y, top.width, top.height); } } } } /* * Now that all the tab stuff is done, lets clear all the background * areas to our parents background color. */ { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } cnt = 0; if (LayoutIsRtoLP(tab)) { for( i = 1; i < XmTabBox__num_rows(tab); ++i, x -= offset ) { if( (idx = GetTabIndex(tab, i, 0)) < 0 ) continue; rect[cnt].x = geom[idx].x + geom[idx].width; rect[cnt].y = geom[idx].y; rect[cnt].width = XtWidth(tab) - geom[idx].x; rect[cnt++].height = geom[idx].height; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } else { x = offset; for( i = 1; i < XmTabBox__num_rows(tab); ++i, x += offset ) { if( (idx = GetTabIndex(tab, i, 0)) < 0 ) continue; rect[cnt].x = 0; rect[cnt].y = geom[idx].y; rect[cnt].width = x; rect[cnt++].height = geom[idx].height; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } /* * We need to clear any area on the right side of the tabs. To do this * we find the tab in the upper right corner and clear down to the * bottom and then check the top row to see if it is full. */ last = -1; col = XmTabBox__num_columns(tab) - 1; for( i = 0; i < XmTabBox__num_rows(tab); ++i ) { if( (idx = GetTabIndex(tab, i, col)) >= 0 ) { last = idx; } } if( last != -1 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = 0; rect[cnt].y = 0; rect[cnt].width = geom[last].x; rect[cnt++].height = XtHeight(tab); last = GetTabIndex(tab, 0, 0); } rect[cnt].x = geom[last].x + geom[last].width; rect[cnt].y = 0; rect[cnt].width = (int)XtWidth(tab) - rect[cnt].x; rect[cnt++].height = XtHeight(tab); if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } row = XmTabBox__num_rows(tab) - 1; col = XmTabBox__num_columns(tab) - 1; last = -1; if( GetTabIndex(tab, row, col) < 0 ) { for( i = col; i >= 0 && last < 0; last = GetTabIndex(tab, row, --i) ); if( last >= 0 ) { if (LayoutIsRtoLP(tab)) { rect[cnt].x = 0; rect[cnt].width = geom[last].x; } else { rect[cnt].x = geom[last].x + geom[last].width; rect[cnt].width = (int)XtWidth(tab) - rect[cnt].x; } rect[cnt].y = 0; rect[cnt++].height = geom[last].height; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } if( cnt > 0 ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } /* * If the users wants the special stacked effect then we are done so * lets get out of here. */ if( GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1) >= 0 && XmTabBox_stacked_effect(tab) ) return; /* * Now that we have all the tabs drawn we want to complete the * shadow line from the last tab in the first row to the last * tab in the last row. Lets start by finding the last tab in the * first row and the last tab in the last row. */ first = GetTabIndex(tab, 0, 0);; for( i = 0; i < XmTabBox__num_columns(tab); ++i ) { if( (idx = GetTabIndex(tab, 0, i)) < 0 ) break; first = idx; } if( XmTabBox_stacked_effect(tab) ) { if( first < 0 ) return; /* * If we got here that means that we are doing the stacked effect * and that row 0 is not complete. What this means is that we * need to do is draw a line from the last tab in row 0 to the * location where the row should end. */ if( LayoutIsRtoLP(tab) ) { x1 = offset * ((XmTabBox__num_rows(tab) - 1)); x2 = geom[first].x; } else { x1 = geom[first].x + geom[first].width; x2 = XmTabBox__num_columns(tab) * geom[first].width; } } else { x1 = geom[first].x + geom[first].width; x2 = XtWidth(tab); } /* * Now that we know what we are dealing with all we have to do * is draw the line. */ XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, x1, (int)XtHeight(tab) - shadow, x2 - x1, shadow); if( !LayoutIsRtoLP(tab) ) { XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, x2 - shadow, (int)XtHeight(tab) - shadow, shadow, XmBEVEL_BOTTOM); } } static void HorizontalStackedTopEdgeRedisplay(XmTabBoxWidget tab) { XmTabbedStackList list = XmTabBox_tab_list(tab); int i, count = _XmTabbedStackListCount(list), row = 0, col, shadow = tab->manager.shadow_thickness, x, height, offset, idx, below, corner, cnt, first, last, x1, x2; XmTabAttributes info; XiTabRect *geom; GC gc = XmTabBox__tab_GC(tab); Boolean do_top, do_bottom; #define _NUM_RECTS 10 XRectangle rect[_NUM_RECTS], top = {0, 0, 0, 0}, bottom = {0, 0, 0, 0}; offset = XmTabBox_tab_offset(tab); geom = XmTabBox__actual(tab); /* * First the quick check. If we only have one row then all we need to do * is draw the base line from the end of the last tab to the right edge. */ if( XmTabBox__num_rows(tab) == 1 && (idx = GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1)) >= 0 ) { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } x = geom[idx].x + geom[idx].width; XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, x, 0, (int)XtWidth(tab) - x, shadow); XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, x, shadow, (int)XtWidth(tab) - x, (int)XtHeight(tab) - shadow); return; } for( i = 0; i < count; ++i ) { corner = GetTabIndex(tab, geom[i].row-1, geom[i].column+1); below = GetTabIndex(tab, geom[i].row-1, geom[i].column); if( geom[i].row > 0 && (corner < 0 || below < 0) ) { cnt = 0; do_top = do_bottom = False; info = _XmTabbedStackListGet(list, i); if( XiBackgroundSpecified(info) ) { SetBackgroundGC(tab, info, gc); } else if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledGC(XtDisplay(tab), gc, tab->core.background_pixmap); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } for( height = geom[i].height, row = geom[i].row - 2; row >= 0 && GetTabIndex(tab, row, geom[i].column+1) < 0; row--, height += geom[i].height ); if( corner < 0 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = geom[i].x; bottom.x = geom[i].x; } else { rect[cnt].x = geom[i].x + geom[i].width - offset; bottom.x = geom[i].x + geom[i].width - shadow; } rect[cnt].y = geom[i].y - height; rect[cnt].width = offset; rect[cnt++].height = height; bottom.y = geom[i].y - height; bottom.width = shadow; bottom.height = height; do_bottom = True; } if( below < 0 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = geom[i].x + offset; } else { rect[cnt].x = geom[i].x; } rect[cnt].y = geom[i].y - geom[i].height; rect[cnt].width = geom[i].width - offset; rect[cnt++].height = geom[i].height; if( LayoutIsRtoLP(tab) ) { top.x = geom[i].x + geom[i].width - shadow; } else { top.x = geom[i].x; } top.y = geom[i].y - geom[i].height; top.width = shadow; top.height = geom[i].height; do_top = True; if( geom[i].row > 1 && geom[i].column == XmTabBox__num_columns(tab) - 1 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = offset; } else { rect[cnt].x = geom[i].x + geom[i].width - (2*offset); } rect[cnt].y = 0; rect[cnt].width = offset; rect[cnt].height = geom[i].y; cnt++; } } XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); if( do_bottom ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), LayoutIsRtoLP(tab) ? tab->manager.top_shadow_GC : tab->manager.bottom_shadow_GC, bottom.x, bottom.y, bottom.width, bottom.height); } if( do_top ) { if( LayoutIsRtoLP(tab) ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, top.x, top.y, top.width, top.height); } else { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, top.x, top.y, top.width, top.height); } } } } /* * Now that all the tab stuff is done, lets clear all the background * areas to our parents background color. */ { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } x = offset; cnt = 0; for( i = 1; i < XmTabBox__num_rows(tab); ++i, x += offset ) { if( (idx = GetTabIndex(tab, i, 0)) < 0 ) continue; rect[cnt].x = LayoutIsRtoLP(tab) ? geom[idx].x + geom[idx].width : 0; rect[cnt].y = geom[idx].y; rect[cnt].width = x; rect[cnt++].height = geom[idx].height; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } /* * We need to clear any area on the right side of the tabs. To do this * we find the tab in the upper right corner and clear down to the * bottom and then check the top row to see if it is full. */ last = -1; col = XmTabBox__num_columns(tab) - 1; for( i = 0; i < XmTabBox__num_rows(tab); ++i ) { if( (idx = GetTabIndex(tab, i, col)) >= 0 ) { last = idx; } } if( last != -1 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = 0; rect[cnt].y = 0; rect[cnt].width = geom[last].x; rect[cnt++].height = XtHeight(tab); last = GetTabIndex(tab, 0, 0); } rect[cnt].x = geom[last].x + geom[last].width; rect[cnt].y = 0; rect[cnt].width = (int)XtWidth(tab) - rect[cnt].x; rect[cnt++].height = XtHeight(tab); if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } row = XmTabBox__num_rows(tab) - 1; col = XmTabBox__num_columns(tab) - 1; last = -1; if( GetTabIndex(tab, row, col) < 0 ) { for( i = col; i >= 0 && last < 0; last = GetTabIndex(tab, row, --i) ); if( last >= 0 ) { if( LayoutIsRtoLP(tab) ) { rect[cnt].x = 0; rect[cnt].y = (int)XtHeight(tab) - geom[last].height; rect[cnt].width = geom[last].x; rect[cnt++].height = geom[last].height; } else { rect[cnt].x = geom[last].x + geom[last].width; rect[cnt].y = (int)XtHeight(tab) - geom[last].height; rect[cnt].width = (int)XtWidth(tab) - rect[cnt].x; rect[cnt++].height = geom[last].height; } if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } if( cnt > 0 ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } /* * If the users wants the special stacked effect then we are done so * lets get out of here. */ if( GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1) >= 0 && XmTabBox_stacked_effect(tab) ) return; /* * Now that we have all the tabs drawn we want to complete the * shadow line from the last tab in the first row to the last * tab in the last row. Lets start by finding the last tab in the * first row and the last tab in the last row. */ first = GetTabIndex(tab, 0, 0);; for( i = 0; i < XmTabBox__num_columns(tab); ++i ) { if( (idx = GetTabIndex(tab, 0, i)) < 0 ) break; first = idx; } if( XmTabBox_stacked_effect(tab) ) { if( first < 0 ) return; /* * If we got here that means that we are doing the stacked effect * and that row 0 is not complete. What this means is that we * need to do is draw a line from the last tab in row 0 to the * location where the row should end. */ if( LayoutIsRtoLP(tab) ) { x1 = offset * (XmTabBox__num_rows(tab) - 1) + shadow; x2 = geom[first].x; XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, x1 - shadow, 0, shadow, XmBEVEL_BOTH); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, tab->manager.top_shadow_GC, x2, 0, shadow, XmBEVEL_BOTH); } else { x1 = geom[first].x + geom[first].width; x2 = XmTabBox__num_columns(tab) * geom[first].width; } } else { x1 = geom[first].x + geom[first].width; x2 = XtWidth(tab); } /* * Now that we know what we are dealing with all we have to do * is draw the line. */ XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, x1, 0, x2 - x1, shadow); } static void HorizontalStackedRedisplay(XmTabBoxWidget tab) { if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { HorizontalStackedBottomEdgeRedisplay(tab); } else { HorizontalStackedTopEdgeRedisplay(tab); } } static void VerticalStackedRightEdgeRedisplay(XmTabBoxWidget tab) { XmTabbedStackList list = XmTabBox_tab_list(tab); int i, count = _XmTabbedStackListCount(list), row = 0, col, shadow = tab->manager.shadow_thickness, y, width, offset, idx, below, corner, cnt = 0, first, last, y1, y2; XmTabAttributes info; XiTabRect *geom; GC gc = XmTabBox__tab_GC(tab); Boolean do_top, do_bottom; #define _NUM_RECTS 10 XRectangle rect[_NUM_RECTS], top = {0, 0, 0, 0}, bottom = {0, 0, 0, 0}; /* * What we need to do in this mode is to extend the right most tab * on each row to the bottom of the widget(minus the shadow). Besides * the bcakground of the widget we also need to extend the shadow. */ offset = XmTabBox_tab_offset(tab); geom = XmTabBox__actual(tab); /* * First the quick check. If we only have one row then all we need to do * is draw the base line from the end of the last tab to the right edge. */ if( XmTabBox__num_rows(tab) == 1 && (idx = GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1)) >= 0 ) { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } y = geom[idx].y + geom[idx].height; XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, (int)XtWidth(tab) - shadow, y, shadow, (int)XtHeight(tab) - y); XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, 0, y, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - y); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - shadow, shadow, XmBEVEL_BOTTOM); return; } for( i = 0; i < count; ++i ) { corner = GetTabIndex(tab, geom[i].row-1, geom[i].column+1); below = GetTabIndex(tab, geom[i].row-1, geom[i].column); if( geom[i].row > 0 && (corner < 0 || below < 0) ) { cnt = 0; do_top = do_bottom = False; info = _XmTabbedStackListGet(list, i); if( XiBackgroundSpecified(info) ) { SetBackgroundGC(tab, info, gc); } else if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledGC(XtDisplay(tab), gc, tab->core.background_pixmap); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } for( width = geom[i].width, row = geom[i].row - 2; row >= 0 && GetTabIndex(tab, row, geom[i].column+1) < 0; row--, width += geom[i].width ); if( corner < 0 ) { rect[cnt].x = geom[i].x + geom[i].width; rect[cnt].y = geom[i].y + geom[i].height- offset; rect[cnt].width = width; rect[cnt++].height = offset; bottom.x = geom[i].x + geom[i].width; bottom.y = geom[i].y + geom[i].height - shadow; bottom.width = width; bottom.height = shadow; do_bottom = True; } if( below < 0 ) { rect[cnt].x = geom[i].x + geom[i].width; rect[cnt].y = geom[i].y; rect[cnt].width = geom[i].width; rect[cnt++].height = geom[i].height - offset; top.x = geom[i].x + geom[i].width; top.y = geom[i].y; top.width = geom[i].width; top.height = shadow; do_top = True; if( geom[i].row > 1 && geom[i].column == XmTabBox__num_columns(tab) - 1 ) { rect[cnt].x = geom[i].x + geom[i].width; rect[cnt].y = geom[i].y + geom[i].height - (2*offset); rect[cnt].width = (int)XtWidth(tab) - rect[cnt].x; rect[cnt].height = offset; cnt++; } } XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); if( do_bottom ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, bottom.x, bottom.y, bottom.width, bottom.height); } if( do_top ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, top.x, top.y, top.width, top.height); } } } /* * Now that all the tab stuff is done, lets clear all the background * areas to our parents background color. */ { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } y = offset; cnt = 0; for( i = 1; i < XmTabBox__num_rows(tab); ++i, y += offset ) { if( (idx = GetTabIndex(tab, i, 0)) < 0 ) continue; rect[cnt].x = geom[idx].x; rect[cnt].y = 0; rect[cnt].width = geom[idx].width; rect[cnt++].height = y; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } /* * We need to clear any area on the right side of the tabs. To do this * we find the tab in the upper right corner and clear down to the * bottom and then check the top row to see if it is full. */ last = -1; col = XmTabBox__num_columns(tab) - 1; for( i = 0; i < XmTabBox__num_rows(tab); ++i ) { if( (idx = GetTabIndex(tab, i, col)) >= 0 ) { last = idx; } } if( last != -1 ) { rect[cnt].x = 0; rect[cnt].y = geom[last].y + geom[last].height; rect[cnt].width = XtWidth(tab); rect[cnt].height = (int)XtHeight(tab) - rect[cnt].y; cnt++; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } row = XmTabBox__num_rows(tab) - 1; col = XmTabBox__num_columns(tab) - 1; last = -1; if( GetTabIndex(tab, row, col) < 0 ) { for( i = col; i >= 0 && last < 0; last = GetTabIndex(tab, row, --i) ); if( last >= 0 ) { rect[cnt].x = 0; rect[cnt].y = geom[last].y + geom[last].height; rect[cnt].width = geom[last].width; rect[cnt].height = (int)XtHeight(tab) - rect[cnt].y; cnt++; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } if( cnt > 0 ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } /* * If the users wants the special stacked effect then we are done so * lets get out of here. */ if( GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1) >= 0 && XmTabBox_stacked_effect(tab) ) return; /* * Now that we have all the tabs drawn we want to complete the * shadow line from the last tab in the first row to the last * tab in the last row. Lets start by finding the last tab in the * first row and the last tab in the last row. */ first = GetTabIndex(tab, 0, 0);; for( i = 0; i < XmTabBox__num_columns(tab); ++i ) { if( (idx = GetTabIndex(tab, 0, i)) < 0 ) break; first = idx; } if( XmTabBox_stacked_effect(tab) ) { if( first < 0 ) return; /* * If we got here that means that we are doing the stacked effect * and that row 0 is not complete. What this means is that we * need to do is draw a line from the last tab in row 0 to the * location where the row should end. */ y1 = geom[first].y + geom[first].height; y2 = XmTabBox__num_columns(tab) * geom[first].height; } else { y1 = geom[first].y + geom[first].height; y2 = XtHeight(tab); } /* * Now that we know what we are dealing with all we have to do * is draw the line. */ XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, (int)XtWidth(tab) - shadow, y1, shadow, y2 - y1); XmDrawBevel(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, tab->manager.bottom_shadow_GC, (int)XtWidth(tab) - shadow, y2 - shadow, shadow, XmBEVEL_BOTTOM); } static void VerticalStackedLeftEdgeRedisplay(XmTabBoxWidget tab) { XmTabbedStackList list = XmTabBox_tab_list(tab); int i, count = _XmTabbedStackListCount(list), row = 0, col, shadow = tab->manager.shadow_thickness, y, width, offset, idx, below, corner, cnt = 0, first, last, y1, y2; XmTabAttributes info; XiTabRect *geom; GC gc = XmTabBox__tab_GC(tab); Boolean do_top, do_bottom; #define _NUM_RECTS 10 XRectangle rect[_NUM_RECTS], top = {0, 0, 0, 0}, bottom = {0, 0, 0, 0}; offset = XmTabBox_tab_offset(tab); geom = XmTabBox__actual(tab); if( XmTabBox__num_rows(tab) == 1 && (idx = GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1)) >= 0 ) { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } y = geom[idx].y + geom[idx].height; XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, 0, y, shadow, (int)XtHeight(tab) - y); XFillRectangle(XtDisplay(tab), XiCanvas(tab), gc, shadow, y, (int)XtWidth(tab) - shadow, (int)XtHeight(tab) - y); return; } for( i = 0; i < count; ++i ) { corner = GetTabIndex(tab, geom[i].row-1, geom[i].column+1); below = GetTabIndex(tab, geom[i].row-1, geom[i].column); if( geom[i].row > 0 && (corner < 0 || below < 0) ) { cnt = 0; do_top = do_bottom = False; info = _XmTabbedStackListGet(list, i); if( XiBackgroundSpecified(info) ) { SetBackgroundGC(tab, info, gc); } else if( ValidPixmap(tab->core.background_pixmap) ) { SetTiledGC(XtDisplay(tab), gc, tab->core.background_pixmap); } else { SetSolidGC(XtDisplay(tab), gc, tab->core.background_pixel); } for( width = geom[i].width, row = geom[i].row - 2; row >= 0 && GetTabIndex(tab, row, geom[i].column+1) < 0; row--, width += geom[i].width ); if( corner < 0 ) { rect[cnt].x = geom[i].x - width; rect[cnt].y = geom[i].y + geom[i].height - offset; rect[cnt].width = width; rect[cnt++].height = offset; bottom.x = geom[i].x - width; bottom.y = geom[i].y + geom[i].height - shadow; bottom.width = width; bottom.height = shadow; do_bottom = True; } if( below < 0 ) { rect[cnt].x = geom[i].x - geom[i].width; rect[cnt].y = geom[i].y; rect[cnt].width = geom[i].width; rect[cnt++].height = geom[i].height - offset; top.x = geom[i].x - geom[i].width; top.y = geom[i].y; top.width = geom[i].width; top.height = shadow; do_top = True; if( geom[i].row > 1 && geom[i].column == XmTabBox__num_columns(tab) - 1 ) { rect[cnt].x = 0; rect[cnt].y = geom[i].y + geom[i].height - (2*offset); rect[cnt].width = geom[i].x; rect[cnt].height = offset; cnt++; } } XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); if( do_bottom ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, bottom.x, bottom.y, bottom.width, bottom.height); } if( do_top ) { XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.top_shadow_GC, top.x, top.y, top.width, top.height); } } } /* * Now that all the tab stuff is done, lets clear all the background * areas to our parents background color. */ { Pixel pixel; Pixmap pixmap; XtVaGetValues(XiGCParent(tab), XmNbackground, &pixel, XmNbackgroundPixmap, &pixmap, NULL); if( ValidPixmap(pixmap) ) { SetTiledGC(XtDisplay(tab), gc, pixmap); } else { SetSolidGC(XtDisplay(tab), gc, pixel); } } y = offset; cnt = 0; for( i = 1; i < XmTabBox__num_rows(tab); ++i, y += offset ) { if( (idx = GetTabIndex(tab, i, 0)) < 0 ) continue; rect[cnt].x = geom[idx].x; rect[cnt].y = 0; rect[cnt].width = geom[idx].width; rect[cnt++].height = y; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } /* * We need to clear any area on the right side of the tabs. To do this * we find the tab in the upper right corner and clear down to the * bottom and then check the top row to see if it is full. */ last = -1; col = XmTabBox__num_columns(tab) - 1; for( i = 0; i < XmTabBox__num_rows(tab); ++i ) { if( (idx = GetTabIndex(tab, i, col)) >= 0 ) { last = idx; } } if( last != -1 ) { rect[cnt].x = 0; rect[cnt].y = geom[last].y + geom[last].height; rect[cnt].width = XtWidth(tab); rect[cnt].height = (int)XtHeight(tab) - rect[cnt].y; cnt++; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } row = XmTabBox__num_rows(tab) - 1; col = XmTabBox__num_columns(tab) - 1; last = -1; if( GetTabIndex(tab, row, col) < 0 ) { for( i = col; i >= 0 && last < 0; last = GetTabIndex(tab, row, --i) ); if( last >= 0 ) { rect[cnt].x = (int)XtWidth(tab) - geom[last].width; rect[cnt].y = geom[last].y + geom[last].height; rect[cnt].width = geom[last].width; rect[cnt].height = (int)XtHeight(tab) - rect[cnt].y; cnt++; if( cnt >= _NUM_RECTS ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } } } if( cnt > 0 ) { XFillRectangles(XtDisplay(tab), XiCanvas(tab), gc, rect, cnt); cnt=0; } /* * If the users wants the special stacked effect then we are done so * lets get out of here. */ if( GetTabIndex(tab, 0, XmTabBox__num_columns(tab) - 1) >= 0 && XmTabBox_stacked_effect(tab) ) return; /* * Now that we have all the tabs drawn we want to complete the * shadow line from the last tab in the first row to the last * tab in the last row. Lets start by finding the last tab in the * first row and the last tab in the last row. */ first = GetTabIndex(tab, 0, 0);; for( i = 0; i < XmTabBox__num_columns(tab); ++i ) { if( (idx = GetTabIndex(tab, 0, i)) < 0 ) break; first = idx; } if( XmTabBox_stacked_effect(tab) ) { if( first < 0 ) return; /* * If we got here that means that we are doing the stacked effect * and that row 0 is not complete. What this means is that we * need to do is draw a line from the last tab in row 0 to the * location where the row should end. */ y1 = geom[first].y + geom[first].height; y2 = XmTabBox__num_columns(tab) * geom[first].height; } else { y1 = geom[first].y + geom[first].height; y2 = XtHeight(tab); } /* * Now that we know what we are dealing with all we have to do * is draw the line. */ XFillRectangle(XtDisplay(tab), XiCanvas(tab), tab->manager.bottom_shadow_GC, 0, y1, shadow, y2 - y1); } static void VerticalStackedRedisplay(XmTabBoxWidget tab) { if( XmTabBox_tab_edge(tab) == XmTAB_EDGE_BOTTOM_RIGHT ) { VerticalStackedRightEdgeRedisplay(tab); } else { VerticalStackedLeftEdgeRedisplay(tab); } } static XmTabAttributes GetTabInfo(XmTabBoxWidget tab, int row, int column) { int idx = GetTabIndex(tab, row, column); if( idx < 0 ) return( NULL ); return( _XmTabbedStackListGet(XmTabBox_tab_list(tab), idx) ); } static int GetTabIndex(XmTabBoxWidget tab, int row, int column) { XmTabbedStackList list = XmTabBox_tab_list(tab); int i, count = _XmTabbedStackListCount(list); XiTabRect *rect = XmTabBox__actual(tab); if( row < 0 || column < 0 || count < 1 ) return( -1 ); for( i = 0; i < count; ++i ) { if( row == rect[i].row && column == rect[i].column ) { return( i ); } } return( -1 ); } static void SelectTab(XmTabBoxWidget tab, XEvent *event, int old, int set) { int old_row, set_row; if( old == set ) return; XmTabBox__selected(tab) = set; old_row = set_row = XmTabBox__actual(tab)[set].row; if( old >= 0 ) { old_row = XmTabBox__actual(tab)[old].row; } if( XmTabBox_tab_mode(tab) == XmTABS_STACKED && old_row != set_row ) { Layout(tab); if( XtIsRealized((Widget)tab) ) { Redisplay(XmTabBox__canvas(tab), NULL, False); } } else { if( old != -1 ) { DrawTab(tab, _XmTabbedStackListGet(XmTabBox_tab_list(tab), old), &(XmTabBox__actual(tab)[old]), False, False); } DrawTab(tab, _XmTabbedStackListGet(XmTabBox_tab_list(tab), set), &(XmTabBox__actual(tab)[set]), True, True); } CallCallbacks(tab, event, old, set); } void _XmTabBoxSelectTab(Widget widget, int idx) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) || idx < 0 || idx >=_XmTabbedStackListCount(XmTabBox_tab_list(tab)) ) return; SelectTab(tab, NULL, XmTabBox__selected(tab), idx); } static Boolean IsTabSensitive(XmTabBoxWidget tab, int idx) { XmTabAttributes info = _XmTabbedStackListGet(XmTabBox_tab_list(tab), idx); if( info != NULL ) return( info->sensitive ); return( False ); } void _XmTabBoxStackedGeometry(XmTabBoxWidget tab, Dimension size, XRectangle *rect) { XmTabbedStackList list = XmTabBox_tab_list(tab); XmTabAttributes info; int i, count = _XmTabbedStackListCount(list), max_width, max_height, tab_width, tab_height, num_cols, num_rows, offset; Dimension d_width, d_height; if( count == 0 ) { if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { rect->width = 2 * tab->manager.shadow_thickness; rect->height = tab->manager.shadow_thickness; } else { rect->width = tab->manager.shadow_thickness; rect->height = 2 * tab->manager.shadow_thickness; } if( rect->width < 1 ) rect->width = 1; if( rect->height < 1 ) rect->height = 1; return; } /* * Calculating the geometry we want for the stack layout turns * out to be straight forward. What we do is find calculate the * size of the largest tab and then use that to calculate the * geometry we want. */ max_width = max_height = 1; for( i = 0; i < count; ++i ) { info = _XmTabbedStackListGet(list, i); XiCalcTabSize(tab, info, &d_width, &d_height); AssignMax(max_width, (int)d_width); AssignMax(max_height, (int)d_height); } if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { /* * Now that we know how big the tabs are lets see how many can fit in * the available space. */ num_cols = (int)size / max_width; AssignMax(num_cols, 1); /* * Now we know how many fit per row, so what we now need to do is * how many rows we need. */ num_rows = (count/ num_cols) + ((count % num_cols == 0) ? 0 : 1); /* * Now that we know how many rows and columns we need we can calculate * overall size. */ offset = XmTabBox_tab_offset(tab); tab_width = size + ((num_rows - 1) * offset); tab_height = num_rows * max_height; } else { num_cols = (int)size/ max_height; AssignMax(num_cols, 1); num_rows = (count/ num_cols) + ((count % num_cols == 0) ? 0 : 1); offset = XmTabBox_tab_offset(tab); tab_width = num_rows * max_width; tab_height = size + ((num_rows - 1) * offset); } rect->width = tab_width; rect->height = tab_height; } int XmTabBoxGetNumRows(Widget widget) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) ) return( 0 ); return( XmTabBox__num_rows(tab) ); } int XmTabBoxGetNumColumns(Widget widget) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) ) return( 0 ); return( XmTabBox__num_columns(tab) ); } void _XmTabBoxGetNumRowsColumns(Widget widget, int size, int *num_rows, int *num_cols) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; int i, max, _num_rows, _num_cols, tmp, offset, cnt; XRectangle *wanted = XmTabBox__wanted(tab); *num_rows = 0; *num_cols = 0; if( !XmIsTabBox(widget) || (cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab))) == 0 || (XmTabBox_tab_mode(tab) != XmTABS_STACKED && XmTabBox_tab_mode(tab) != XmTABS_STACKED_STATIC) ) { return; } offset = XmTabBox_tab_offset(tab); max = 0; if( XmTabBox_orientation(tab) == XmHORIZONTAL ) { for( i = 0; i < cnt; ++i ) { AssignMax(max, (int)wanted[i].width); } } else { for( i = 0; i < cnt; ++i ) { AssignMax(max, (int)wanted[i].height); } } _num_cols = cnt; _num_rows = (int)(cnt/ _num_cols) + (cnt % _num_cols > 0 ? 1 : 0); tmp = (_num_cols * max) + (_num_rows * offset); while( _num_cols > 1 && tmp > size ) { _num_cols--; _num_rows = (int)(cnt/ _num_cols) + (cnt % _num_cols > 0 ? 1 : 0); tmp = (_num_cols * max) + (_num_rows * offset); } *num_rows = _num_rows; *num_cols = _num_cols; } int #ifndef _NO_PROTO XmTabBoxGetNumTabs(Widget widget) #else XmTabBoxGetNumTabs(widget) Widget widget; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) ) return( 0 ); return( _XmTabbedStackListCount(XmTabBox_tab_list(tab)) ); } int #ifndef _NO_PROTO _XiGetTabIndex(Widget tab, int row, int column) #else _XiGetTabIndex(tab, row, column) XmTabBoxWidget tab; int row, column; #endif { if( !XmIsTabBox(tab) ) return( -1 ); return( GetTabIndex((XmTabBoxWidget)tab, row, column) ); } int #ifndef _NO_PROTO _XmTabBoxGetTabWidth(Widget widget, int idx) #else _XmTabBoxGetTabWidth(widget, idx) Widget widget; int idx; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) || idx < 0 || idx > _XmTabbedStackListCount(XmTabBox_tab_list(tab)) ) return( -1 ); return( XmTabBox__actual(tab)[idx].width ); } int #ifndef _NO_PROTO _XmTabBoxGetTabHeight(Widget widget, int idx) #else _XmTabBoxGetTabHeight(widget, idx) Widget widget; int idx; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) || idx < 0 || idx > _XmTabbedStackListCount(XmTabBox_tab_list(tab)) ) return( -1 ); return( XmTabBox__actual(tab)[idx].height ); } static Widget #ifndef _NO_PROTO XiGCParent(XmTabBoxWidget tab) #else XiGCParent(tab) XmTabBoxWidget tab; #endif { Widget parent = XtParent(tab); if( XmIsTabStack(parent) ) { return( XtParent(parent) ); } return( parent ); } int #ifndef _NO_PROTO XmTabBoxGetTabRow(Widget widget, int idx) #else XmTabBoxGetTabRow(widget, idx) Widget widget; int idx; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) || idx < 0 || idx > _XmTabbedStackListCount(XmTabBox_tab_list(tab)) ) return( -1 ); return( XmTabBox__actual(tab)[idx].row ); } static void #ifndef _NO_PROTO ResetImageCache(XmTabBoxWidget tab) #else ResetImageCache(tab) XmTabBoxWidget tab; #endif { int i, cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); /* * First thing we will do is clear any existing cache. */ if( XmTabBox__cache_size(tab) > 0 ) { for( i = 0; i < XmTabBox__cache_size(tab); ++i ) { if( XmTabBox__cache(tab)[i].pixmap != NULL ) { XDestroyImage(XmTabBox__cache(tab)[i].pixmap); } if( XmTabBox__cache(tab)[i].label != NULL ) { XDestroyImage(XmTabBox__cache(tab)[i].label); } } } /* * If we have no tabs then we will free the cache. */ if( XmTabBox_tab_list(tab) == NULL || cnt == 0 ) { XtFree((XtPointer) XmTabBox__cache(tab)); XmTabBox__cache(tab) = NULL; XmTabBox__cache_size(tab) = 0; return; } /* * If we got here that means that we actually have some items so lets * size our cache to the correct size. */ if( cnt != XmTabBox__cache_size(tab) ) { XmTabBox__cache_size(tab) = cnt; XmTabBox__cache(tab) = (XiCache*) XtRealloc((XtPointer)XmTabBox__cache(tab), sizeof(XiCache) * cnt); } /* * Then lets zero the cache out. */ for( i = 0; i < cnt; ++i ) { XmTabBox__cache(tab)[i].pixmap = NULL; XmTabBox__cache(tab)[i].label = NULL; XmTabBox__cache(tab)[i].sensitive = False; } } static void #ifndef _NO_PROTO FreeImageCache(XmTabBoxWidget tab) #else FreeImageCache(tab) XmTabBoxWidget tab; #endif { int i; /* * First thing we will do is clear any existing cache. */ if( XmTabBox__cache_size(tab) > 0 ) { for( i = 0; i < XmTabBox__cache_size(tab); ++i ) { if( XmTabBox__cache(tab)[i].pixmap != NULL ) { XDestroyImage(XmTabBox__cache(tab)[i].pixmap); } if( XmTabBox__cache(tab)[i].label != NULL ) { XDestroyImage(XmTabBox__cache(tab)[i].label); } } } XtFree((XtPointer) XmTabBox__cache(tab)); XmTabBox__cache(tab) = NULL; XmTabBox__cache_size(tab) = 0; } static int #ifndef _NO_PROTO InfoToIndex(XmTabBoxWidget tab, XmTabAttributes info) #else InfoToIndex(tab, info) XmTabBoxWidget tab; XmTabAttributes info; #endif { return( (int)(info - _XmTabbedStackListArray(XmTabBox_tab_list(tab))) ); } Widget #ifndef _NO_PROTO _XmTabBoxCanvas(Widget widget) #else _XmTabBoxCanvas(widget) Widget widget; #endif { XmTabBoxWidget tab = (XmTabBoxWidget) widget; if( !XmIsTabBox(widget) ) return( NULL ); return( XmTabBox__canvas(tab) ); } int _XmTabBoxGetMaxTabWidth(Widget widget) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; int i, max = 0, cnt; XRectangle *wanted; if( !XmIsTabBox(widget) ) return( 0 ); cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); wanted = XmTabBox__wanted(tab); for( i = 0; i < cnt; ++i ) { AssignMax(max, (int)wanted[i].width); } return( max ); } int _XmTabBoxGetMaxTabHeight(Widget widget) { XmTabBoxWidget tab = (XmTabBoxWidget) widget; int i, max = 0, cnt; XRectangle *wanted; if( !XmIsTabBox(widget) ) return( 0 ); cnt = _XmTabbedStackListCount(XmTabBox_tab_list(tab)); wanted = XmTabBox__wanted(tab); for( i = 0; i < cnt; ++i ) { AssignMax(max, (int)wanted[i].height); } return( max ); } int #ifndef _NO_PROTO XmTabBoxXYToIndex(Widget widget, int x, int y) #else XmTabBoxXYToIndex(widget, x, y) Widget widget; int x, y; #endif { if( !XmIsTabBox(widget) ) return( -1 ); return( XiXYtoTab((XmTabBoxWidget)widget, x, y) ); } static Visual* GetShellVisual(Widget widget) { Visual *visual; if( widget == NULL ) { return( NULL ); } if( XtIsShell(widget) ) { XtVaGetValues(widget, XmNvisual, &visual, NULL); return( visual ); } visual = GetShellVisual(XtParent(widget)); if( visual == NULL ) { return( DefaultVisualOfScreen(XtScreen(widget)) ); } return( visual ); } /* * XmRCallProc routine for checking font_list before setting it to NULL * If "check_set_render_table" is True, then function has * been called twice on same widget, thus resource needs to be set NULL, * otherwise leave it alone. */ /*ARGSUSED*/ static void CheckSetRenderTable(Widget wid, int offs, XrmValue *value) { XmTabBoxWidget tb = (XmTabBoxWidget)wid; /* Check if been here before */ if (tb->tab_box.check_set_render_table) value->addr = NULL; else { tb->tab_box.check_set_render_table = True; value->addr = (char*)&(tb->tab_box.font_list); } } Widget XmCreateTabBox(Widget parent, String name, ArgList arg_list, Cardinal arg_cnt) { return( XtCreateWidget(name, xmTabBoxWidgetClass, parent, arg_list, arg_cnt) ); }