428
+ − 1 /* Tabs Widget for XEmacs.
+ − 2 Copyright (C) 1999 Edward A. Falk
442
+ − 3
428
+ − 4 This file is part of XEmacs.
442
+ − 5
428
+ − 6 XEmacs is free software; you can redistribute it and/or modify it
+ − 7 under the terms of the GNU General Public License as published by the
+ − 8 Free Software Foundation; either version 2, or (at your option) any
+ − 9 later version.
442
+ − 10
428
+ − 11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 14 for more details.
442
+ − 15
428
+ − 16 You should have received a copy of the GNU General Public License
+ − 17 along with XEmacs; see the file COPYING. If not, write to
+ − 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 19 Boston, MA 02111-1307, USA. */
442
+ − 20
446
+ − 21 /* Synched up with: Tabs.c 1.27.
+ − 22
+ − 23 #### This file contains essential XEmacs related fixes to the original
+ − 24 verison of the Tabs widget. Be VERY careful about syncing if you ever
+ − 25 update to a more recent version. In general this is probably now a
+ − 26 bad idea. */
442
+ − 27
428
+ − 28 /*
+ − 29 * Tabs.c - Index Tabs composite widget
+ − 30 *
+ − 31 * Author: Edward A. Falk
+ − 32 * falk@falconer.vip.best.com
+ − 33 *
+ − 34 * Date: July 29, 1997
+ − 35 *
+ − 36 *
+ − 37 * Overall layout of this widget is as follows:
+ − 38 *
+ − 39 * ________ ,---------. _________
+ − 40 * | label || Label || Label | \ tabs
+ − 41 * |________|| ||_________| /
+ − 42 * |+----------------------------+| \
+ − 43 * || || |
+ − 44 * || child widget window || > frame
+ − 45 * |+----------------------------+| |
+ − 46 * +------------------------------+ /
+ − 47 *
+ − 48 * The height of the tabs includes the shadow width, top and bottom
+ − 49 * margins, and the height of the text.
+ − 50 *
+ − 51 * The height of the frame includes the top and bottom shadow width and the
+ − 52 * size of the child widget window.
+ − 53 *
+ − 54 * The tabs overlap the frame and each other vertically by the shadow
+ − 55 * width, so that when the topmost tab is drawn, it obliterates part of
+ − 56 * the frame.
+ − 57 */
+ − 58
434
+ − 59 /*
+ − 60 * TODO: min child height = tab height
428
+ − 61 */
+ − 62
+ − 63 #include <config.h>
+ − 64 #include <stdio.h>
+ − 65
+ − 66 #include <X11/Xlib.h>
+ − 67 #include <X11/IntrinsicP.h>
+ − 68 #include <X11/StringDefs.h>
448
+ − 69
+ − 70 #include "lwlib-internal.h"
428
+ − 71 #include "../src/xmu.h"
+ − 72 #include "xlwtabsP.h"
+ − 73 #include "xlwgcs.h"
+ − 74
+ − 75 #define MIN_WID 10
+ − 76 #define MIN_HGT 10
+ − 77 #define INDENT 3 /* tabs indented from edge by this much */
+ − 78 #define SPACING 0 /* distance between tabs */
+ − 79 #define SHADWID 1 /* default shadow width */
+ − 80 #define TABDELTA 2 /* top tab grows this many pixels */
+ − 81 #define TABLDELTA 2 /* top tab label offset this many pixels */
+ − 82
+ − 83
+ − 84 /****************************************************************
+ − 85 *
+ − 86 * IndexTabs Resources
+ − 87 *
+ − 88 ****************************************************************/
+ − 89
+ − 90 static char defaultTranslations[] = "\
+ − 91 <BtnUp>: select() \n\
+ − 92 <FocusIn>: highlight() \n\
+ − 93 <FocusOut>: unhighlight() \n\
+ − 94 <Key>Page_Up: page(up) \n\
+ − 95 <Key>KP_Page_Up: page(up) \n\
+ − 96 <Key>Prior: page(up) \n\
+ − 97 <Key>KP_Prior: page(up) \n\
+ − 98 <Key>Page_Down: page(down) \n\
+ − 99 <Key>KP_Page_Down: page(down) \n\
+ − 100 <Key>Next: page(down) \n\
+ − 101 <Key>KP_Next: page(down) \n\
+ − 102 <Key>Home: page(home) \n\
+ − 103 <Key>KP_Home: page(home) \n\
+ − 104 <Key>End: page(end) \n\
+ − 105 <Key>KP_End: page(end) \n\
+ − 106 <Key>Up: highlight(up) \n\
+ − 107 <Key>KP_Up: highlight(up) \n\
+ − 108 <Key>Down: highlight(down) \n\
+ − 109 <Key>KP_Down: highlight(down) \n\
+ − 110 <Key> : page(select) \n\
+ − 111 " ;
+ − 112
+ − 113 static char accelTable[] = " #augment\n\
+ − 114 <Key>Page_Up: page(up) \n\
+ − 115 <Key>KP_Page_Up: page(up) \n\
+ − 116 <Key>Prior: page(up) \n\
+ − 117 <Key>KP_Prior: page(up) \n\
+ − 118 <Key>Page_Down: page(down) \n\
+ − 119 <Key>KP_Page_Down: page(down) \n\
+ − 120 <Key>Next: page(down) \n\
+ − 121 <Key>KP_Next: page(down) \n\
+ − 122 <Key>Home: page(home) \n\
+ − 123 <Key>KP_Home: page(home) \n\
+ − 124 <Key>End: page(end) \n\
+ − 125 <Key>KP_End: page(end) \n\
+ − 126 <Key>Up: highlight(up) \n\
+ − 127 <Key>KP_Up: highlight(up) \n\
+ − 128 <Key>Down: highlight(down) \n\
+ − 129 <Key>KP_Down: highlight(down) \n\
+ − 130 <Key> : page(select) \n\
+ − 131 " ;
446
+ − 132 static XtAccelerators defaultAccelerators ; /* #### Never used */
428
+ − 133
+ − 134 #define offset(field) XtOffsetOf(TabsRec, tabs.field)
+ − 135 static XtResource resources[] = {
+ − 136
+ − 137 {XtNselectInsensitive, XtCSelectInsensitive, XtRBoolean, sizeof(Boolean),
+ − 138 offset(selectInsensitive), XtRImmediate, (XtPointer) True},
+ − 139 {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
+ − 140 offset(font), XtRString, (XtPointer) XtDefaultFont},
+ − 141 {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
+ − 142 offset(internalWidth), XtRImmediate, (XtPointer)4 },
+ − 143 {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
+ − 144 offset(internalHeight), XtRImmediate, (XtPointer)4 },
+ − 145 {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
+ − 146 XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate, (XtPointer)0},
+ − 147 {XtNtopWidget, XtCTopWidget, XtRWidget, sizeof(Widget),
+ − 148 offset(topWidget), XtRImmediate, NULL},
+ − 149 {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
+ − 150 offset(callbacks), XtRCallback, NULL},
+ − 151 {XtNpopdownCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
+ − 152 offset(popdownCallbacks), XtRCallback, NULL},
+ − 153 {XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, sizeof(Boolean),
+ − 154 offset(be_nice_to_cmap), XtRImmediate, (XtPointer) True},
+ − 155 {XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, sizeof(int),
+ − 156 offset(top_shadow_contrast), XtRImmediate, (XtPointer) 20},
+ − 157 {XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, sizeof(int),
+ − 158 offset(bot_shadow_contrast), XtRImmediate, (XtPointer) 40},
+ − 159 {XtNinsensitiveContrast, XtCInsensitiveContrast, XtRInt, sizeof(int),
+ − 160 offset(insensitive_contrast), XtRImmediate, (XtPointer) 33},
+ − 161 {XtNaccelerators, XtCAccelerators, XtRAcceleratorTable,sizeof(XtTranslations),
+ − 162 XtOffsetOf(TabsRec,core.accelerators), XtRString, accelTable},
+ − 163 };
+ − 164 #undef offset
+ − 165
+ − 166
+ − 167
+ − 168 /* constraint resources */
+ − 169
+ − 170 #define offset(field) XtOffsetOf(TabsConstraintsRec, tabs.field)
+ − 171 static XtResource tabsConstraintResources[] = {
+ − 172 {XtNtabLabel, XtCLabel, XtRString, sizeof(String),
+ − 173 offset(label), XtRString, NULL},
+ − 174 {XtNtabLeftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap),
+ − 175 offset(left_bitmap), XtRImmediate, None},
+ − 176 {XtNtabForeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ − 177 offset(foreground), XtRString, (XtPointer) XtDefaultForeground},
+ − 178 {XtNresizable, XtCResizable, XtRBoolean, sizeof(Boolean),
+ − 179 offset(resizable), XtRImmediate, (XtPointer) True},
+ − 180 } ;
+ − 181 #undef offset
+ − 182
+ − 183
+ − 184
+ − 185
+ − 186 #if !NeedFunctionPrototypes
+ − 187
+ − 188 /* FORWARD REFERENCES: */
+ − 189
+ − 190 /* member functions */
+ − 191
+ − 192 static void TabsClassInit();
+ − 193 static void TabsInit();
+ − 194 static void TabsResize();
+ − 195 static void TabsExpose();
+ − 196 static void TabsDestroy();
+ − 197 static void TabsRealize();
+ − 198 static Boolean TabsSetValues();
434
+ − 199 static Boolean TabsAcceptFocus();
428
+ − 200 static XtGeometryResult TabsQueryGeometry();
+ − 201 static XtGeometryResult TabsGeometryManager();
+ − 202 static void TabsChangeManaged();
+ − 203 static void TabsConstraintInitialize() ;
+ − 204 static Boolean TabsConstraintSetValues() ;
+ − 205
+ − 206 /* action procs */
+ − 207
+ − 208 static void TabsSelect() ;
+ − 209 static void TabsPage() ;
+ − 210 static void TabsHighlight() ;
+ − 211 static void TabsUnhighlight() ;
+ − 212
+ − 213 /* internal privates */
+ − 214
+ − 215 static void TabsAllocGCs() ; /* get rendering GCs */
+ − 216 static void TabsFreeGCs() ; /* return rendering GCs */
+ − 217 static void DrawTabs() ; /* draw all tabs */
+ − 218 static void DrawTab() ; /* draw one index tab */
+ − 219 static void DrawFrame() ; /* draw frame around contents */
+ − 220 static void DrawTrim() ; /* draw trim around a tab */
+ − 221 static void DrawBorder() ; /* draw border */
+ − 222 static void DrawHighlight() ; /* draw highlight */
+ − 223 static void UndrawTab() ; /* undraw interior of a tab */
+ − 224 static void TabWidth() ; /* recompute tab size */
+ − 225 static void GetPreferredSizes() ; /* query all children for their sizes */
+ − 226 static void MaxChild() ; /* find max preferred child size */
+ − 227 static int PreferredSize() ; /* compute preferred size */
+ − 228 static int PreferredSize2() ; /* compute preferred size */
+ − 229 static int PreferredSize3() ; /* compute preferred size */
+ − 230 static void MakeSizeRequest() ; /* try to change size */
+ − 231 static void getBitmapInfo() ;
+ − 232 static int TabLayout() ; /* lay out tabs */
+ − 233 static void TabsShuffleRows() ; /* bring current tab to bottom row */
+ − 234
+ − 235 static void TabsAllocFgGC() ;
+ − 236 static void TabsAllocGreyGC() ;
+ − 237
+ − 238 #else
+ − 239
+ − 240 static void TabsClassInit(void) ;
+ − 241 static void TabsInit( Widget req, Widget new, ArgList, Cardinal *nargs) ;
+ − 242 static void TabsConstraintInitialize(Widget, Widget, ArgList, Cardinal *) ;
+ − 243 static void TabsRealize(Widget, Mask *, XSetWindowAttributes *) ;
+ − 244 static void TabsDestroy( Widget w) ;
+ − 245 static void TabsResize( Widget w) ;
+ − 246 static void TabsExpose( Widget w, XEvent *event, Region region) ;
+ − 247 static Boolean TabsSetValues(Widget, Widget, Widget, ArgList, Cardinal *) ;
434
+ − 248 static Boolean TabsAcceptFocus(Widget, Time *);
428
+ − 249 static Boolean TabsConstraintSetValues(Widget, Widget, Widget,
+ − 250 ArgList, Cardinal *) ;
+ − 251 static XtGeometryResult TabsQueryGeometry(Widget,
+ − 252 XtWidgetGeometry *, XtWidgetGeometry *) ;
+ − 253 static XtGeometryResult TabsGeometryManager(Widget,
+ − 254 XtWidgetGeometry *, XtWidgetGeometry *) ;
+ − 255 static void TabsChangeManaged( Widget w) ;
+ − 256
+ − 257 static void TabsSelect(Widget, XEvent *, String *, Cardinal *) ;
+ − 258 static void TabsPage(Widget, XEvent *, String *, Cardinal *) ;
+ − 259 static void TabsHighlight(Widget, XEvent *, String *, Cardinal *) ;
+ − 260 static void TabsUnhighlight(Widget, XEvent *, String *, Cardinal *) ;
+ − 261
+ − 262 static void DrawTabs( TabsWidget tw, Bool labels) ;
+ − 263 static void DrawTab( TabsWidget tw, Widget child, Bool labels) ;
+ − 264 static void DrawFrame( TabsWidget tw) ;
+ − 265 static void DrawTrim( TabsWidget, int x, int y,
+ − 266 int wid, int hgt, Bool bottom, Bool undraw) ;
+ − 267 static void DrawBorder( TabsWidget tw, Widget child, Bool undraw) ;
+ − 268 static void DrawHighlight( TabsWidget tw, Widget child, Bool undraw) ;
+ − 269 static void UndrawTab( TabsWidget tw, Widget child) ;
+ − 270
+ − 271 static void TabWidth( Widget w) ;
448
+ − 272 static int TabLayout( TabsWidget, Dimension wid, Dimension hgt, Dimension *r_hgt,
428
+ − 273 Bool query_only) ;
+ − 274 static void GetPreferredSizes(TabsWidget) ;
434
+ − 275 static void MaxChild(TabsWidget, Widget except, Dimension, Dimension) ;
428
+ − 276 static void TabsShuffleRows( TabsWidget tw) ;
+ − 277 static int PreferredSize( TabsWidget,
+ − 278 Dimension *reply_width, Dimension *reply_height,
+ − 279 Dimension *reply_cw, Dimension *reply_ch) ;
448
+ − 280 static int PreferredSize2( TabsWidget, Dimension cw, Dimension ch,
428
+ − 281 Dimension *rw, Dimension *rh) ;
448
+ − 282 static int PreferredSize3( TabsWidget, Dimension wid, Dimension hgt,
428
+ − 283 Dimension *rw, Dimension *rh) ;
+ − 284 static void MakeSizeRequest(TabsWidget) ;
+ − 285
+ − 286 static void TabsAllocGCs(TabsWidget) ;
+ − 287 static void TabsFreeGCs(TabsWidget) ;
+ − 288 static void getBitmapInfo( TabsWidget tw, TabsConstraints tab) ;
+ − 289 static void TabsAllocFgGC( TabsWidget tw) ;
+ − 290 static void TabsAllocGreyGC( TabsWidget tw) ;
+ − 291
+ − 292 #endif
+ − 293
+ − 294 #define AddRect(i,xx,yy,w,h) \
+ − 295 do{rects[(i)].x=(xx); rects[i].y=(yy); \
+ − 296 rects[i].width=(w); rects[i].height=(h);}while(0)
+ − 297
+ − 298 static XtActionsRec actionsList[] =
+ − 299 {
+ − 300 {"select", TabsSelect},
+ − 301 {"page", TabsPage},
+ − 302 {"highlight", TabsHighlight},
+ − 303 {"unhighlight", TabsUnhighlight},
+ − 304 } ;
+ − 305
+ − 306
+ − 307 /****************************************************************
+ − 308 *
+ − 309 * Full class record constant
+ − 310 *
+ − 311 ****************************************************************/
+ − 312
+ − 313 #ifndef NEED_MOTIF
+ − 314 #define SuperClass (&constraintClassRec)
+ − 315 #else
+ − 316 #define SuperClass (&xmManagerClassRec)
+ − 317 #endif
+ − 318
+ − 319 TabsClassRec tabsClassRec = {
+ − 320 {
+ − 321 /* core_class fields */
+ − 322 /* superclass */ (WidgetClass) SuperClass,
+ − 323 /* class_name */ "Tabs",
+ − 324 /* widget_size */ sizeof(TabsRec),
+ − 325 /* class_initialize */ TabsClassInit,
+ − 326 /* class_part_init */ NULL, /* TODO? */
+ − 327 /* class_inited */ FALSE,
+ − 328 /* initialize */ TabsInit,
+ − 329 /* initialize_hook */ NULL,
+ − 330 /* realize */ TabsRealize,
+ − 331 /* actions */ actionsList,
+ − 332 /* num_actions */ XtNumber(actionsList),
+ − 333 /* resources */ resources,
+ − 334 /* num_resources */ XtNumber(resources),
+ − 335 /* xrm_class */ NULLQUARK,
+ − 336 /* compress_motion */ TRUE,
434
+ − 337 #if XtSpecificationRelease < 6
+ − 338 /* compress_exposure */ XtExposeCompressMaximal,
+ − 339 #else
+ − 340 /* compress_exposure */ XtExposeCompressMaximal|XtExposeNoRegion,
+ − 341 #endif
428
+ − 342 /* compress_enterleave*/ TRUE,
434
+ − 343 /* visible_interest */ TRUE,
428
+ − 344 /* destroy */ TabsDestroy,
+ − 345 /* resize */ TabsResize,
+ − 346 /* expose */ TabsExpose,
+ − 347 /* set_values */ TabsSetValues,
+ − 348 /* set_values_hook */ NULL,
+ − 349 /* set_values_almost */ XtInheritSetValuesAlmost,
+ − 350 /* get_values_hook */ NULL,
434
+ − 351 /* accept_focus */ TabsAcceptFocus,
428
+ − 352 /* version */ XtVersion,
+ − 353 /* callback_private */ NULL,
+ − 354 /* tm_table */ defaultTranslations,
+ − 355 /* query_geometry */ TabsQueryGeometry,
+ − 356 /* display_accelerator*/ XtInheritDisplayAccelerator,
+ − 357 /* extension */ NULL
+ − 358 },
+ − 359 {
+ − 360 /* composite_class fields */
+ − 361 /* geometry_manager */ TabsGeometryManager,
+ − 362 /* change_managed */ TabsChangeManaged,
+ − 363 /* insert_child */ XtInheritInsertChild, /* TODO? */
+ − 364 /* delete_child */ XtInheritDeleteChild, /* TODO? */
+ − 365 /* extension */ NULL
+ − 366 },
+ − 367 {
+ − 368 /* constraint_class fields */
+ − 369 /* subresources */ tabsConstraintResources,
+ − 370 /* subresource_count */ XtNumber(tabsConstraintResources),
+ − 371 /* constraint_size */ sizeof(TabsConstraintsRec),
+ − 372 /* initialize */ TabsConstraintInitialize,
+ − 373 /* destroy */ NULL,
+ − 374 /* set_values */ TabsConstraintSetValues,
+ − 375 /* extension */ NULL,
+ − 376 },
+ − 377 #ifdef NEED_MOTIF
+ − 378 /* Manager Class fields */
+ − 379 {
+ − 380 /* translations */ NULL,
+ − 381 /* syn_resources */ NULL,
+ − 382 /* num_syn_resources */ 0,
+ − 383 /* syn_constraint_resources */ NULL,
+ − 384 /* num_syn_constraint_resources */ 0,
+ − 385 /* parent_process */ XmInheritParentProcess,
+ − 386 /* extension */ NULL
+ − 387 },
+ − 388 #endif
+ − 389 {
+ − 390 /* Tabs class fields */
+ − 391 /* extension */ NULL,
+ − 392 }
+ − 393 };
+ − 394
+ − 395 WidgetClass tabsWidgetClass = (WidgetClass)&tabsClassRec;
+ − 396
446
+ − 397 #define TabsNumChildren(tw) (((TabsWidget)tw)->composite.num_children)
+ − 398 #define TabVisible(tab) \
+ − 399 (XtIsManaged(tab) && \
+ − 400 ((TabsConstraints)((tab)->core.constraints))->tabs.visible)
428
+ − 401
+ − 402
+ − 403 /****************************************************************
+ − 404 *
+ − 405 * Member Procedures
+ − 406 *
+ − 407 ****************************************************************/
+ − 408
+ − 409 static void
+ − 410 TabsClassInit(void)
+ − 411 {
+ − 412 defaultAccelerators = XtParseAcceleratorTable(accelTable) ;
+ − 413 /* TODO: register converter for labels? */
+ − 414 }
+ − 415
+ − 416
+ − 417
+ − 418 /* Init a newly created tabs widget. Compute height of tabs
+ − 419 * and optionally compute size of widget. */
+ − 420
+ − 421 /* ARGSUSED */
+ − 422
+ − 423 static void
2286
+ − 424 TabsInit(Widget request, Widget new, ArgList UNUSED (args),
+ − 425 Cardinal *UNUSED (num_args))
428
+ − 426 {
+ − 427 TabsWidget newTw = (TabsWidget)new;
+ − 428
+ − 429 newTw->tabs.numRows = 0 ;
446
+ − 430 newTw->tabs.realRows = 0;
428
+ − 431
+ − 432 GetPreferredSizes(newTw) ;
+ − 433
+ − 434 /* height is easy, it's the same for all tabs:
+ − 435 * TODO: font height + height of tallest bitmap.
+ − 436 */
+ − 437 newTw->tabs.tab_height = 2 * newTw->tabs.internalHeight + SHADWID ;
+ − 438
+ − 439 if( newTw->tabs.font != NULL )
+ − 440 newTw->tabs.tab_height += newTw->tabs.font->max_bounds.ascent +
+ − 441 newTw->tabs.font->max_bounds.descent ;
+ − 442
+ − 443 /* GC allocation is deferred until XtRealize() */
+ − 444
+ − 445 /* if size not explicitly set, set it to our preferred size now. */
+ − 446
+ − 447 if( request->core.width == 0 || request->core.height == 0 )
+ − 448 {
+ − 449 Dimension w,h ;
+ − 450 PreferredSize(newTw, &w, &h, NULL,NULL) ;
+ − 451 if( request->core.width == 0 ) new->core.width = w ;
+ − 452 if( request->core.height == 0 ) new->core.height = h ;
+ − 453 XtClass(new)->core_class.resize(new) ;
+ − 454 }
+ − 455
+ − 456 /* defer GC allocation, etc., until Realize() time. */
+ − 457 newTw->tabs.foregroundGC =
+ − 458 newTw->tabs.backgroundGC =
+ − 459 newTw->tabs.greyGC =
+ − 460 newTw->tabs.topGC =
+ − 461 newTw->tabs.botGC = None ;
+ − 462
+ − 463 newTw->tabs.grey50 = None ;
+ − 464
+ − 465 newTw->tabs.needs_layout = False ;
434
+ − 466
428
+ − 467 newTw->tabs.hilight = NULL ;
+ − 468
+ − 469 #ifdef NEED_MOTIF
+ − 470 newTw->manager.navigation_type = XmTAB_GROUP ;
+ − 471 newTw->manager.traversal_on = True ;
+ − 472 #endif
+ − 473 }
+ − 474
+ − 475
+ − 476 /* Init the constraint part of a new tab child. Compute the
+ − 477 * size of the tab.
+ − 478 */
+ − 479 /* ARGSUSED */
+ − 480 static void
2286
+ − 481 TabsConstraintInitialize(Widget UNUSED (request), Widget new,
+ − 482 ArgList UNUSED (args), Cardinal *UNUSED (num_args))
428
+ − 483 {
+ − 484 TabsConstraints tab = (TabsConstraints) new->core.constraints ;
+ − 485 tab->tabs.greyAlloc = False ; /* defer allocation of pixel */
446
+ − 486 tab->tabs.visible = False ;
428
+ − 487
+ − 488 getBitmapInfo((TabsWidget)XtParent(new), tab) ;
+ − 489 TabWidth(new) ;
+ − 490 }
+ − 491
+ − 492
+ − 493
+ − 494 /* Called when tabs widget first realized. Create the window
+ − 495 * and allocate the GCs
+ − 496 */
+ − 497
+ − 498 static void
+ − 499 TabsRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
+ − 500 {
+ − 501 TabsWidget tw = (TabsWidget) w;
+ − 502
+ − 503 attributes->bit_gravity = NorthWestGravity;
+ − 504 *valueMask |= CWBitGravity;
+ − 505
+ − 506 SuperClass->core_class.realize(w, valueMask, attributes);
+ − 507
+ − 508 TabsAllocGCs(tw) ;
+ − 509 }
+ − 510
+ − 511
+ − 512
+ − 513 static void
+ − 514 TabsDestroy(Widget w)
+ − 515 {
+ − 516 TabsFreeGCs((TabsWidget)w) ;
+ − 517 }
+ − 518
+ − 519
+ − 520 /* Parent has resized us. This will require that the tabs be
+ − 521 * laid out again.
+ − 522 */
+ − 523
+ − 524 static void
+ − 525 TabsResize(Widget w)
+ − 526 {
+ − 527 TabsWidget tw = (TabsWidget) w;
+ − 528 int i ;
+ − 529 int num_children = tw->composite.num_children ;
+ − 530 Widget *childP ;
2286
+ − 531 /* TabsConstraints tab ; */ /* #### unused */
428
+ − 532 Dimension cw,ch,bw ;
+ − 533
+ − 534 /* Our size has now been dictated by the parent. Lay out the
+ − 535 * tabs, lay out the frame, lay out the children. Remember
+ − 536 * that the tabs overlap each other and the frame by shadowWidth.
+ − 537 * Also, the top tab is larger than the others, so if there's only
+ − 538 * one row, the widget must be made taller to accommodate this.
+ − 539 *
+ − 540 * Once the tabs are laid out, if there is more than one
+ − 541 * row, we may need to shuffle the rows to bring the top tab
+ − 542 * to the bottom row.
+ − 543 */
+ − 544
434
+ − 545 tw->tabs.needs_layout = False ;
+ − 546
428
+ − 547 if( num_children > 0 && tw->composite.children != NULL )
+ − 548 {
+ − 549 /* Loop through the tabs and assign rows & x positions */
+ − 550 (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ;
446
+ − 551 num_children = TabsNumChildren (tw);
428
+ − 552
+ − 553 /* assign a top widget, bring it to bottom row. */
+ − 554 TabsShuffleRows(tw) ;
+ − 555
+ − 556 /* now assign child positions & sizes. Positions are all the
+ − 557 * same: just inside the frame. Sizes are also all the same.
+ − 558 */
+ − 559
+ − 560 tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ;
+ − 561 tw->tabs.child_height = ch =
448
+ − 562 tw->core.height < (tw->tabs.tab_total + 2 * SHADWID) ? 0 :
+ − 563 tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
428
+ − 564
+ − 565 for(i=0, childP=tw->composite.children;
434
+ − 566 i < num_children;
428
+ − 567 ++i, ++childP)
448
+ − 568 if( XtIsManaged(*childP) )
428
+ − 569 {
2286
+ − 570 /* tab = (TabsConstraints) (*childP)->core.constraints ; */
434
+ − 571 bw = (*childP)->core.border_width ;
448
+ − 572 /* Don't do anything if we can't see any of the child. */
+ − 573 if (ch >= bw*2 && ch > 0 && cw >= bw*2 && cw > 0)
+ − 574 XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
+ − 575 cw-bw*2,ch-bw*2, bw) ;
428
+ − 576 }
434
+ − 577 if( XtIsRealized(w) ) {
+ − 578 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 579 /* should not be necessary to explicitly repaint after a
+ − 580 * resize, but XEmacs folks tell me it is.
+ − 581 */
+ − 582 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 583 }
428
+ − 584 }
+ − 585 } /* Resize */
+ − 586
+ − 587
+ − 588
+ − 589 /* Redraw entire Tabs widget */
+ − 590
+ − 591 /* ARGSUSED */
+ − 592 static void
2286
+ − 593 TabsExpose(Widget w, XEvent *UNUSED (event), Region UNUSED (region))
428
+ − 594 {
+ − 595 TabsWidget tw = (TabsWidget) w;
+ − 596
+ − 597 if( tw->tabs.needs_layout )
+ − 598 XtClass(w)->core_class.resize(w) ;
+ − 599
+ − 600 DrawTabs(tw, True) ;
+ − 601 }
+ − 602
+ − 603
+ − 604 /* Called when any Tabs widget resources are changed. */
+ − 605
+ − 606 /* ARGSUSED */
+ − 607 static Boolean
2286
+ − 608 TabsSetValues(Widget current, Widget UNUSED (request), Widget new,
+ − 609 ArgList UNUSED (args), Cardinal *UNUSED (num_args))
428
+ − 610 {
430
+ − 611 TabsWidget curtw = (TabsWidget) current ;
+ − 612 TabsWidget tw = (TabsWidget) new ;
+ − 613 Boolean needRedraw = False ;
+ − 614 Widget *childP ;
+ − 615 int i ;
428
+ − 616
+ − 617
430
+ − 618 if( tw->tabs.font != curtw->tabs.font ||
+ − 619 tw->tabs.internalWidth != curtw->tabs.internalWidth ||
+ − 620 tw->tabs.internalHeight != curtw->tabs.internalHeight )
+ − 621 {
+ − 622 tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID ;
428
+ − 623
430
+ − 624 if( tw->tabs.font != NULL )
+ − 625 tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent +
+ − 626 tw->tabs.font->max_bounds.descent ;
428
+ − 627
430
+ − 628 /* Tab size has changed. Resize all tabs and request a new size */
+ − 629 for(i=0, childP=tw->composite.children;
647
+ − 630 i < (int) tw->composite.num_children;
430
+ − 631 ++i, ++childP)
+ − 632 if( XtIsManaged(*childP) )
+ − 633 TabWidth(*childP) ;
+ − 634 PreferredSize(tw, &tw->core.width, &tw->core.height, NULL,NULL) ;
+ − 635 needRedraw = True ;
+ − 636 tw->tabs.needs_layout = True ;
+ − 637 }
428
+ − 638
430
+ − 639 /* TODO: if any color changes, need to recompute GCs and redraw */
428
+ − 640
430
+ − 641 if( tw->core.background_pixel != curtw->core.background_pixel ||
432
+ − 642 tw->core.background_pixmap != curtw->core.background_pixmap ||
+ − 643 tw->tabs.font != curtw->tabs.font )
430
+ − 644 if( XtIsRealized(new) )
+ − 645 {
+ − 646 TabsFreeGCs(tw) ;
+ − 647 TabsAllocGCs(tw) ;
+ − 648 needRedraw = True ;
+ − 649 }
428
+ − 650
430
+ − 651 if( tw->core.sensitive != curtw->core.sensitive )
+ − 652 needRedraw = True ;
428
+ − 653
430
+ − 654 /* If top widget changes, need to change stacking order, redraw tabs.
+ − 655 * Window system will handle the redraws.
+ − 656 */
428
+ − 657
442
+ − 658 if( tw->tabs.topWidget != curtw->tabs.topWidget )
432
+ − 659 {
430
+ − 660 if( XtIsRealized(tw->tabs.topWidget) )
+ − 661 {
+ − 662 Widget w = tw->tabs.topWidget ;
+ − 663 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
428
+ − 664
430
+ − 665 XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
428
+ − 666 #ifdef NEED_MOTIF
430
+ − 667 XtVaSetValues(curtw->tabs.topWidget, XmNtraversalOn, False, 0) ;
+ − 668 XtVaSetValues(w, XmNtraversalOn, True, 0) ;
428
+ − 669 #endif
+ − 670
647
+ − 671 if( tab->tabs.row != (int) tw->tabs.numRows-1 )
430
+ − 672 TabsShuffleRows(tw) ;
428
+ − 673
430
+ − 674 needRedraw = True ;
+ − 675 }
+ − 676 else
+ − 677 tw->tabs.needs_layout = True ;
432
+ − 678 }
428
+ − 679
430
+ − 680 return needRedraw ;
428
+ − 681 }
+ − 682
+ − 683
+ − 684 /* Called when any child constraint resources change. */
+ − 685
+ − 686 /* ARGSUSED */
+ − 687 static Boolean
2286
+ − 688 TabsConstraintSetValues(Widget current, Widget UNUSED (request), Widget new,
+ − 689 ArgList UNUSED (args), Cardinal *UNUSED (num_args))
428
+ − 690 {
+ − 691 TabsWidget tw = (TabsWidget) XtParent(new) ;
+ − 692 TabsConstraints ctab = (TabsConstraints) current->core.constraints ;
+ − 693 TabsConstraints tab = (TabsConstraints) new->core.constraints ;
+ − 694
+ − 695
+ − 696 /* if label changes, need to re-layout the entire widget */
+ − 697 /* if foreground changes, need to redraw tab label */
+ − 698
+ − 699 /* TODO: only need resize of new bitmap has different dimensions
+ − 700 * from old bitmap.
+ − 701 */
+ − 702
+ − 703 if( tab->tabs.label != ctab->tabs.label || /* Tab size has changed. */
+ − 704 tab->tabs.left_bitmap != ctab->tabs.left_bitmap )
+ − 705 {
+ − 706 TabWidth(new) ;
+ − 707 tw->tabs.needs_layout = True ;
+ − 708
+ − 709 if( tab->tabs.left_bitmap != ctab->tabs.left_bitmap )
+ − 710 getBitmapInfo(tw, tab) ;
+ − 711
+ − 712 /* If there are no subclass ConstraintSetValues procedures remaining
+ − 713 * to be invoked, and if the preferred size has changed, ask
+ − 714 * for a resize.
+ − 715 */
+ − 716 if( XtClass((Widget)tw) == tabsWidgetClass )
+ − 717 MakeSizeRequest(tw) ;
+ − 718 }
+ − 719
+ − 720
+ − 721 /* The child widget itself never needs a redisplay, but the parent
+ − 722 * Tabs widget might.
+ − 723 */
+ − 724
+ − 725 if( XtIsRealized(new) )
+ − 726 {
+ − 727 if( tw->tabs.needs_layout ) {
+ − 728 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 729 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 730 }
+ − 731
+ − 732 else if( tab->tabs.foreground != ctab->tabs.foreground )
+ − 733 DrawTab(tw, new, True) ;
+ − 734 }
+ − 735
+ − 736 return False ;
+ − 737 }
+ − 738
+ − 739
434
+ − 740 static Boolean
2286
+ − 741 TabsAcceptFocus(Widget w, Time *UNUSED (t))
434
+ − 742 {
+ − 743 if( !w->core.being_destroyed && XtIsRealized(w) &&
+ − 744 XtIsSensitive(w) && XtIsManaged(w) && w->core.visible )
+ − 745 {
+ − 746 Widget p ;
+ − 747 for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ;
+ − 748 XtSetKeyboardFocus(p,w) ;
+ − 749 return True ;
+ − 750 }
+ − 751 else
+ − 752 return False ;
+ − 753 }
+ − 754
+ − 755
428
+ − 756
+ − 757 /*
+ − 758 * Return preferred size. Happily accept anything >= our preferred size.
+ − 759 * (TODO: is that the right thing to do? Should we always return "almost"
442
+ − 760 * if offered more than we need?)
428
+ − 761 */
+ − 762
+ − 763 static XtGeometryResult
+ − 764 TabsQueryGeometry(Widget w,
+ − 765 XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
+ − 766 {
+ − 767 register TabsWidget tw = (TabsWidget)w ;
+ − 768 XtGeometryMask mode = intended->request_mode ;
+ − 769
+ − 770 preferred->request_mode = CWWidth | CWHeight ;
+ − 771 PreferredSize(tw, &preferred->width, &preferred->height, NULL,NULL) ;
+ − 772
+ − 773 if( (!(mode & CWWidth) || intended->width == w->core.width) &&
+ − 774 (!(mode & CWHeight) || intended->height == w->core.height) )
+ − 775 return XtGeometryNo ;
+ − 776
+ − 777 if( (!(mode & CWWidth) || intended->width >= preferred->width) &&
+ − 778 (!(mode & CWHeight) || intended->height >= preferred->height) )
+ − 779 return XtGeometryYes;
+ − 780
+ − 781 return XtGeometryAlmost;
+ − 782 }
+ − 783
+ − 784
+ − 785
+ − 786 /*
+ − 787 * Geometry Manager; called when a child wants to be resized.
+ − 788 */
+ − 789
+ − 790 static XtGeometryResult
+ − 791 TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
+ − 792 {
+ − 793 TabsWidget tw = (TabsWidget) XtParent(w);
+ − 794 Dimension s = SHADWID ;
+ − 795 TabsConstraints tab = (TabsConstraints)w->core.constraints;
+ − 796 XtGeometryResult result ;
434
+ − 797 Dimension rw, rh ;
428
+ − 798
+ − 799 /* Position request always denied */
+ − 800
+ − 801 if( ((req->request_mode & CWX) && req->x != w->core.x) ||
+ − 802 ((req->request_mode & CWY) && req->y != w->core.y) ||
+ − 803 !tab->tabs.resizable )
+ − 804 return XtGeometryNo ;
+ − 805
+ − 806 /* Make all three fields in the request valid */
+ − 807 if( !(req->request_mode & CWWidth) )
+ − 808 req->width = w->core.width;
+ − 809 if( !(req->request_mode & CWHeight) )
+ − 810 req->height = w->core.height;
+ − 811 if( !(req->request_mode & CWBorderWidth) )
+ − 812 req->border_width = w->core.border_width;
+ − 813
+ − 814 if( req->width == w->core.width &&
+ − 815 req->height == w->core.height &&
+ − 816 req->border_width == w->core.border_width )
+ − 817 return XtGeometryNo ;
+ − 818
434
+ − 819 rw = req->width + 2 * req->border_width ;
+ − 820 rh = req->height + 2 * req->border_width ;
+ − 821
+ − 822 /* find out how big the children want to be now */
+ − 823 MaxChild(tw, w, rw, rh) ;
428
+ − 824
+ − 825
+ − 826 /* Size changes must see if the new size can be accommodated.
+ − 827 * The Tabs widget keeps all of its children the same
+ − 828 * size. A request to shrink will be accepted only if the
+ − 829 * new size is still big enough for all other children. A
+ − 830 * request to shrink that is not big enough for all children
434
+ − 831 * returns an "almost" response with the new proposed size
+ − 832 * or a "no" response if unable to shrink at all.
+ − 833 *
428
+ − 834 * A request to grow will be accepted only if the Tabs parent can
+ − 835 * grow to accommodate.
+ − 836 *
+ − 837 * TODO:
+ − 838 * We could get fancy here and re-arrange the tabs if it is
+ − 839 * necessary to compromise with the parent, but we'll save that
+ − 840 * for another day.
+ − 841 */
+ − 842
+ − 843 if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth))
+ − 844 {
+ − 845 Dimension cw,ch ; /* children's preferred size */
+ − 846 Dimension aw,ah ; /* available size we can give child */
+ − 847 Dimension th ; /* space used by tabs */
+ − 848 Dimension wid,hgt ; /* Tabs widget size */
+ − 849
434
+ − 850 cw = tw->tabs.max_cw ;
+ − 851 ch = tw->tabs.max_ch ;
428
+ − 852
434
+ − 853 /* find out what *my* resulting preferred size would be */
428
+ − 854
434
+ − 855 PreferredSize2(tw, cw, ch, &wid, &hgt) ;
+ − 856
+ − 857 /* Would my size change? If so, ask to be resized. */
428
+ − 858
+ − 859 if( wid != tw->core.width || hgt != tw->core.height )
+ − 860 {
+ − 861 Dimension oldWid = tw->core.width, oldHgt = tw->core.height ;
+ − 862 XtWidgetGeometry myrequest, myreply ;
+ − 863
+ − 864 myrequest.width = wid ;
+ − 865 myrequest.height = hgt ;
+ − 866 myrequest.request_mode = CWWidth | CWHeight ;
448
+ − 867
+ − 868 assert (wid > 0 && hgt > 0);
428
+ − 869 /* If child is only querying, or if we're going to have to
+ − 870 * offer the child a compromise, then make this a query only.
+ − 871 */
+ − 872
+ − 873 if( (req->request_mode & XtCWQueryOnly) || rw < cw || rh < ch )
+ − 874 myrequest.request_mode |= XtCWQueryOnly ;
+ − 875
+ − 876 result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
+ − 877
434
+ − 878 /* !$@# Athena Box widget changes the core size even if QueryOnly
428
+ − 879 * is set. I'm convinced this is a bug. At any rate, to work
+ − 880 * around the bug, we need to restore the core size after every
+ − 881 * query geometry request. This is only partly effective,
+ − 882 * as there may be other boxes further up the tree.
+ − 883 */
+ − 884 if( myrequest.request_mode & XtCWQueryOnly ) {
+ − 885 tw->core.width = oldWid ;
+ − 886 tw->core.height = oldHgt ;
+ − 887 }
+ − 888
+ − 889 /* based on the parent's response, determine what the
+ − 890 * resulting Tabs widget size would be.
+ − 891 */
+ − 892
+ − 893 switch( result ) {
+ − 894 case XtGeometryYes:
+ − 895 case XtGeometryDone:
434
+ − 896 tw->tabs.needs_layout = True ;
428
+ − 897 break ;
+ − 898
+ − 899 case XtGeometryNo:
+ − 900 wid = tw->core.width ;
+ − 901 hgt = tw->core.height ;
+ − 902 break ;
+ − 903
+ − 904 case XtGeometryAlmost:
+ − 905 wid = myreply.width ;
+ − 906 hgt = myreply.height ;
434
+ − 907 tw->tabs.needs_layout = True ;
+ − 908 break ;
428
+ − 909 }
+ − 910 }
+ − 911
+ − 912 /* Within the constraints imposed by the parent, what is
+ − 913 * the max size we can give the child?
+ − 914 */
+ − 915 (void) TabLayout(tw, wid, hgt, &th, True) ;
+ − 916 aw = wid - 2*s ;
+ − 917 ah = hgt - th - 2*s ;
+ − 918
+ − 919 /* OK, make our decision. If requested size is >= max sibling
+ − 920 * preferred size, AND requested size <= available size, then
+ − 921 * we accept. Otherwise, we offer a compromise.
+ − 922 */
+ − 923
+ − 924 if( rw == aw && rh == ah )
+ − 925 {
+ − 926 /* Acceptable. If this wasn't a query, change *all* children
+ − 927 * to this size.
+ − 928 */
+ − 929 if( req->request_mode & XtCWQueryOnly )
+ − 930 return XtGeometryYes ;
+ − 931 else
+ − 932 {
+ − 933 Widget *childP = tw->composite.children ;
+ − 934 int i,bw ;
+ − 935 w->core.border_width = req->border_width ;
446
+ − 936 for(i=TabsNumChildren (tw); --i >= 0; ++childP)
+ − 937 if( TabVisible(*childP) )
428
+ − 938 {
+ − 939 bw = (*childP)->core.border_width ;
+ − 940 XtConfigureWidget(*childP, s,tw->tabs.tab_total+s,
+ − 941 rw-2*bw, rh-2*bw, bw) ;
+ − 942 }
+ − 943 #ifdef COMMENT
+ − 944 /* TODO: under what conditions will we need to redraw? */
+ − 945 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 946 XtClass(tw)->core_class.expose((Widget)tw,NULL,NULL) ;
+ − 947 #endif /* COMMENT */
+ − 948 return XtGeometryDone ;
+ − 949 }
+ − 950 }
+ − 951
+ − 952 /* Cannot grant child's request. Describe what we *can* do
+ − 953 * and return counter-offer.
+ − 954 */
+ − 955 reply->width = aw - 2 * req->border_width ;
+ − 956 reply->height = ah - 2 * req->border_width ;
+ − 957 reply->border_width = req->border_width ;
+ − 958 reply->request_mode = CWWidth | CWHeight | CWBorderWidth ;
+ − 959 return XtGeometryAlmost ;
+ − 960 }
+ − 961
+ − 962 return XtGeometryYes ;
+ − 963 }
+ − 964
+ − 965
+ − 966
+ − 967
+ − 968 /* The number of children we manage has changed; recompute
+ − 969 * size from scratch.
+ − 970 */
+ − 971
+ − 972 static void
+ − 973 TabsChangeManaged(Widget w)
+ − 974 {
+ − 975 TabsWidget tw = (TabsWidget)w ;
+ − 976 Widget *childP = tw->composite.children ;
+ − 977 int i ;
+ − 978
+ − 979 if( tw->tabs.topWidget != NULL &&
+ − 980 ( !XtIsManaged(tw->tabs.topWidget) ||
+ − 981 tw->tabs.topWidget->core.being_destroyed ) )
+ − 982 tw->tabs.topWidget = NULL ;
+ − 983
440
+ − 984 /* Check whether the highlight tab is still valid. */
+ − 985 if( tw->tabs.hilight != NULL &&
+ − 986 ( !XtIsManaged(tw->tabs.hilight) ||
+ − 987 tw->tabs.hilight->core.being_destroyed ) )
+ − 988 tw->tabs.hilight = NULL ;
+ − 989
428
+ − 990 GetPreferredSizes(tw) ;
+ − 991 MakeSizeRequest(tw) ;
+ − 992
+ − 993 XtClass(w)->core_class.resize(w) ;
+ − 994 if( XtIsRealized(w) )
+ − 995 {
+ − 996 Display *dpy = XtDisplay(w) ;
+ − 997 XClearWindow(dpy, XtWindow(w)) ;
+ − 998 XtClass(w)->core_class.expose(w,NULL,NULL) ;
+ − 999
+ − 1000 /* make sure the top widget stays on top. This requires
+ − 1001 * making sure that all new children are realized first.
+ − 1002 */
+ − 1003 if( tw->tabs.topWidget != NULL && XtIsRealized(tw->tabs.topWidget) )
+ − 1004 {
446
+ − 1005 for(i=TabsNumChildren (tw); --i >= 0; ++childP)
428
+ − 1006 if( !XtIsRealized(*childP) )
+ − 1007 XtRealizeWidget(*childP) ;
+ − 1008
+ − 1009 XRaiseWindow(dpy, XtWindow(tw->tabs.topWidget)) ;
+ − 1010 }
+ − 1011 }
+ − 1012
+ − 1013 #ifdef NEED_MOTIF
+ − 1014 /* Only top widget may receive input */
+ − 1015
+ − 1016 for(childP = tw->composite.children, i=tw->composite.num_children;
+ − 1017 --i >= 0;
+ − 1018 ++childP)
+ − 1019 {
+ − 1020 XtVaSetValues(*childP, XmNtraversalOn, False, 0) ;
+ − 1021 }
+ − 1022
+ − 1023 if( tw->tabs.topWidget != NULL )
+ − 1024 XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ;
+ − 1025 #endif
+ − 1026 }
+ − 1027
+ − 1028
+ − 1029
+ − 1030
+ − 1031 /****************************************************************
+ − 1032 *
+ − 1033 * Action Procedures
+ − 1034 *
+ − 1035 ****************************************************************/
+ − 1036
+ − 1037
+ − 1038 /* User clicks on a tab, figure out which one it was. */
+ − 1039
+ − 1040 /* ARGSUSED */
+ − 1041 static void
2286
+ − 1042 TabsSelect(Widget w, XEvent *event, String *UNUSED (params),
+ − 1043 Cardinal *UNUSED (num_params))
428
+ − 1044 {
+ − 1045 TabsWidget tw = (TabsWidget) w ;
+ − 1046 Widget *childP ;
+ − 1047 Position x,y ;
+ − 1048 Dimension h = tw->tabs.tab_height ;
+ − 1049 int i ;
+ − 1050
+ − 1051 #ifdef NEED_MOTIF
+ − 1052 XmProcessTraversal (w, XmTRAVERSE_CURRENT) ;
+ − 1053 #endif
+ − 1054
+ − 1055 /* TODO: is there an Xmu function or something to do this instead? */
+ − 1056 switch( event->type ) {
+ − 1057 case ButtonPress:
+ − 1058 case ButtonRelease:
+ − 1059 x = event->xbutton.x ; y = event->xbutton.y ; break ;
+ − 1060 case KeyPress:
+ − 1061 case KeyRelease:
+ − 1062 x = event->xkey.x ; y = event->xkey.y ; break ;
+ − 1063 default:
+ − 1064 return ;
+ − 1065 }
+ − 1066
+ − 1067 /* TODO: determine which tab was clicked, if any. Set that
+ − 1068 * widget to be top of stacking order with XawTabsSetTop().
+ − 1069 */
+ − 1070 for(i=0, childP=tw->composite.children;
647
+ − 1071 i < (int) TabsNumChildren (tw);
428
+ − 1072 ++i, ++childP)
446
+ − 1073 if( TabVisible(*childP) )
428
+ − 1074 {
+ − 1075 TabsConstraints tab = (TabsConstraints)(*childP)->core.constraints;
+ − 1076 if( x > tab->tabs.x && x < tab->tabs.x + tab->tabs.width &&
+ − 1077 y > tab->tabs.y && y < tab->tabs.y + h )
+ − 1078 {
+ − 1079 if( *childP != tw->tabs.topWidget &&
+ − 1080 (XtIsSensitive(*childP) || tw->tabs.selectInsensitive) )
+ − 1081 XawTabsSetTop(*childP, True) ;
+ − 1082 break ;
+ − 1083 }
+ − 1084 }
+ − 1085 }
+ − 1086
+ − 1087
+ − 1088 /* User hits a key */
+ − 1089
+ − 1090 static void
2286
+ − 1091 TabsPage(Widget w, XEvent *UNUSED (event), String *params,
+ − 1092 Cardinal *num_params)
428
+ − 1093 {
+ − 1094 TabsWidget tw = (TabsWidget) w ;
430
+ − 1095 Widget newtop = NULL;
428
+ − 1096 Widget *childP ;
+ − 1097 int idx ;
446
+ − 1098 int nc = TabsNumChildren (tw) ;
428
+ − 1099
+ − 1100 if( nc <= 0 )
+ − 1101 return ;
+ − 1102
+ − 1103 if( *num_params < 1 ) {
+ − 1104 XtAppWarning(XtWidgetToApplicationContext(w),
+ − 1105 "Tabs: page() action called with no arguments") ;
+ − 1106 return ;
+ − 1107 }
+ − 1108
+ − 1109 if( tw->tabs.topWidget == NULL )
+ − 1110 tw->tabs.topWidget = tw->composite.children[0] ;
+ − 1111
+ − 1112 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
+ − 1113 if( tw->tabs.topWidget == *childP )
+ − 1114 break ;
+ − 1115
+ − 1116 switch( params[0][0] ) {
+ − 1117 case 'u': /* up */
+ − 1118 case 'U':
432
+ − 1119 if( --idx < 0 )
+ − 1120 idx = nc-1 ;
+ − 1121 newtop = tw->composite.children[idx] ;
428
+ − 1122 break ;
+ − 1123
+ − 1124 case 'd': /* down */
+ − 1125 case 'D':
+ − 1126 if( ++idx >= nc )
+ − 1127 idx = 0 ;
+ − 1128 newtop = tw->composite.children[idx] ;
+ − 1129 break ;
+ − 1130
+ − 1131 case 'h':
+ − 1132 case 'H':
432
+ − 1133 default:
428
+ − 1134 newtop = tw->composite.children[0] ;
+ − 1135 break ;
+ − 1136
+ − 1137 case 'e':
+ − 1138 case 'E':
+ − 1139 newtop = tw->composite.children[nc-1] ;
+ − 1140 break ;
+ − 1141
+ − 1142 case 's': /* selected */
+ − 1143 case 'S':
+ − 1144 if( (newtop = tw->tabs.hilight) == NULL )
+ − 1145 return ;
+ − 1146 break ;
+ − 1147 }
+ − 1148
+ − 1149 XawTabsSetTop(newtop, True) ;
+ − 1150 }
+ − 1151
+ − 1152
+ − 1153 /* User hits up/down key */
+ − 1154
+ − 1155 static void
2286
+ − 1156 TabsHighlight(Widget w, XEvent *UNUSED (event), String *params,
+ − 1157 Cardinal *num_params)
428
+ − 1158 {
+ − 1159 TabsWidget tw = (TabsWidget) w ;
430
+ − 1160 Widget newhl = NULL;
428
+ − 1161 Widget *childP ;
+ − 1162 int idx ;
446
+ − 1163 int nc = TabsNumChildren (tw) ;
428
+ − 1164
+ − 1165 if( nc <= 0 )
+ − 1166 return ;
+ − 1167
+ − 1168 if( *num_params < 1 )
+ − 1169 {
+ − 1170 if( tw->tabs.hilight != NULL )
+ − 1171 DrawHighlight(tw, tw->tabs.hilight, False) ;
+ − 1172 return ;
+ − 1173 }
+ − 1174
+ − 1175 if( tw->tabs.hilight == NULL )
+ − 1176 newhl = tw->composite.children[0] ;
+ − 1177
+ − 1178 else
+ − 1179 {
432
+ − 1180 /* find index of currently highlit child */
428
+ − 1181 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
+ − 1182 if( tw->tabs.hilight == *childP )
+ − 1183 break ;
+ − 1184
+ − 1185 switch( params[0][0] ) {
+ − 1186 case 'u': /* up */
+ − 1187 case 'U':
432
+ − 1188 if( --idx < 0 )
+ − 1189 idx = nc-1 ;
+ − 1190 newhl = tw->composite.children[idx] ;
428
+ − 1191 break ;
+ − 1192
+ − 1193 case 'd': /* down */
+ − 1194 case 'D':
+ − 1195 if( ++idx >= nc )
+ − 1196 idx = 0 ;
+ − 1197 newhl = tw->composite.children[idx] ;
+ − 1198 break ;
+ − 1199
+ − 1200 case 'h':
+ − 1201 case 'H':
+ − 1202 newhl = tw->composite.children[0] ;
+ − 1203 break ;
+ − 1204
+ − 1205 case 'e':
+ − 1206 case 'E':
+ − 1207 newhl = tw->composite.children[nc-1] ;
+ − 1208 break ;
432
+ − 1209
+ − 1210 default:
+ − 1211 newhl = tw->tabs.hilight ;
+ − 1212 break ;
428
+ − 1213 }
+ − 1214 }
+ − 1215
+ − 1216 XawTabsSetHighlight(w, newhl) ;
+ − 1217 }
+ − 1218
+ − 1219
+ − 1220
+ − 1221 static void
2286
+ − 1222 TabsUnhighlight(Widget w, XEvent *UNUSED (event), String *UNUSED (params),
+ − 1223 Cardinal *UNUSED (num_params))
428
+ − 1224 {
+ − 1225 TabsWidget tw = (TabsWidget) w ;
+ − 1226 int nc = tw->composite.num_children ;
+ − 1227
+ − 1228 if( nc <= 0 )
+ − 1229 return ;
+ − 1230
+ − 1231 if( tw->tabs.hilight != NULL )
+ − 1232 DrawHighlight(tw, tw->tabs.hilight, True) ;
+ − 1233 }
+ − 1234
+ − 1235
+ − 1236
+ − 1237
+ − 1238
+ − 1239 /****************************************************************
+ − 1240 *
+ − 1241 * Public Procedures
+ − 1242 *
+ − 1243 ****************************************************************/
+ − 1244
+ − 1245
+ − 1246 /* Set the top tab, optionally call all callbacks. */
+ − 1247 void
+ − 1248 XawTabsSetTop(Widget w, Bool callCallbacks)
+ − 1249 {
+ − 1250 TabsWidget tw = (TabsWidget)w->core.parent ;
+ − 1251 TabsConstraints tab ;
+ − 1252 Widget oldtop = tw->tabs.topWidget ;
+ − 1253
+ − 1254 if( !XtIsSubclass(w->core.parent, tabsWidgetClass) )
+ − 1255 {
434
+ − 1256 char line[256] ;
+ − 1257 sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ;
428
+ − 1258 XtAppWarning(XtWidgetToApplicationContext(w), line) ;
+ − 1259 return ;
+ − 1260 }
+ − 1261
+ − 1262 if( callCallbacks )
+ − 1263 XtCallCallbackList(w, tw->tabs.popdownCallbacks,
434
+ − 1264 (XtPointer)tw->tabs.topWidget) ;
428
+ − 1265
+ − 1266 if( !XtIsRealized(w) ) {
+ − 1267 tw->tabs.topWidget = w ;
+ − 1268 tw->tabs.needs_layout = True ;
440
+ − 1269 tw->tabs.hilight = NULL; /* The highlight tab might disappear. */
428
+ − 1270 return ;
+ − 1271 }
+ − 1272
+ − 1273 XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
+ − 1274 #ifdef NEED_MOTIF
+ − 1275 XtVaSetValues(oldtop, XmNtraversalOn, False, 0) ;
+ − 1276 XtVaSetValues(w, XmNtraversalOn, True, 0) ;
+ − 1277 #endif
+ − 1278
+ − 1279 tab = (TabsConstraints) w->core.constraints ;
440
+ − 1280
+ − 1281 /* Unhighlight before we start messing with the stacking order. */
+ − 1282 if( tw->tabs.hilight != NULL )
+ − 1283 {
+ − 1284 DrawHighlight(tw, tw->tabs.hilight, True) ;
+ − 1285 tw->tabs.hilight = NULL;
+ − 1286 }
+ − 1287
428
+ − 1288 if( tab->tabs.row == 0 )
+ − 1289 {
+ − 1290 /* Easy case; undraw current top, undraw new top, assign new
+ − 1291 * top, redraw all borders.
+ − 1292 * We *could* just erase and execute a full redraw, but I like to
+ − 1293 * reduce screen flicker.
+ − 1294 */
+ − 1295 UndrawTab(tw, oldtop) ; /* undraw old */
+ − 1296 DrawBorder(tw, oldtop, True) ;
+ − 1297 UndrawTab(tw, w) ; /* undraw new */
+ − 1298 DrawBorder(tw, w, True) ;
+ − 1299 tw->tabs.topWidget = w ;
+ − 1300 DrawTab(tw, oldtop, True) ; /* redraw old */
+ − 1301 DrawTab(tw, w, True) ; /* redraw new */
+ − 1302 DrawTabs(tw, False) ;
+ − 1303 }
+ − 1304 else
+ − 1305 {
+ − 1306 tw->tabs.topWidget = w ;
+ − 1307 TabsShuffleRows(tw) ;
+ − 1308 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 1309 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 1310 }
+ − 1311
+ − 1312 XawTabsSetHighlight((Widget)tw, w) ;
+ − 1313
+ − 1314 if( callCallbacks )
+ − 1315 XtCallCallbackList(w, tw->tabs.callbacks, (XtPointer)w) ;
+ − 1316 }
+ − 1317
+ − 1318
+ − 1319 /* Set the top tab, optionally call all callbacks. */
+ − 1320 void
+ − 1321 XawTabsSetHighlight(Widget t, Widget w)
+ − 1322 {
+ − 1323 TabsWidget tw = (TabsWidget)t ;
+ − 1324
+ − 1325 if( !XtIsSubclass(t, tabsWidgetClass) )
+ − 1326 return ;
+ − 1327
+ − 1328 if( XtIsRealized(t) && w != tw->tabs.hilight )
+ − 1329 {
+ − 1330 if( w != NULL )
+ − 1331 DrawHighlight(tw, w, False) ;
+ − 1332 }
+ − 1333
+ − 1334 tw->tabs.hilight = w ;
+ − 1335 }
+ − 1336
+ − 1337
+ − 1338
+ − 1339
+ − 1340 /****************************************************************
+ − 1341 *
+ − 1342 * Private Procedures
+ − 1343 *
+ − 1344 ****************************************************************/
+ − 1345
+ − 1346
+ − 1347 static void
+ − 1348 TabsAllocGCs(TabsWidget tw)
+ − 1349 {
+ − 1350 TabsAllocFgGC(tw) ;
+ − 1351 TabsAllocGreyGC(tw) ;
+ − 1352 tw->tabs.backgroundGC = AllocBackgroundGC((Widget)tw, None) ;
+ − 1353 tw->tabs.topGC = AllocTopShadowGC((Widget)tw,
+ − 1354 tw->tabs.top_shadow_contrast, tw->tabs.be_nice_to_cmap) ;
+ − 1355 tw->tabs.botGC = AllocBotShadowGC((Widget)tw,
+ − 1356 tw->tabs.bot_shadow_contrast, tw->tabs.be_nice_to_cmap) ;
+ − 1357 }
+ − 1358
+ − 1359
+ − 1360 static void
+ − 1361 TabsFreeGCs(TabsWidget tw)
+ − 1362 {
+ − 1363 Widget w = (Widget) tw;
+ − 1364
+ − 1365 XtReleaseGC(w, tw->tabs.foregroundGC) ;
+ − 1366 XtReleaseGC(w, tw->tabs.greyGC) ;
+ − 1367 XtReleaseGC(w, tw->tabs.backgroundGC) ;
+ − 1368 XtReleaseGC(w, tw->tabs.topGC) ;
+ − 1369 XtReleaseGC(w, tw->tabs.botGC) ;
+ − 1370 #ifdef HAVE_XMU
+ − 1371 XmuReleaseStippledPixmap(XtScreen(w), tw->tabs.grey50) ;
+ − 1372 #endif
+ − 1373 }
+ − 1374
+ − 1375
+ − 1376
+ − 1377
+ − 1378
+ − 1379 /* Redraw entire Tabs widget */
+ − 1380
+ − 1381 static void
+ − 1382 DrawTabs(TabsWidget tw, Bool labels)
+ − 1383 {
+ − 1384 Widget *childP ;
+ − 1385 int i,j ;
+ − 1386 Dimension s = SHADWID ;
+ − 1387 Dimension th = tw->tabs.tab_height ;
+ − 1388 Position y ;
+ − 1389 TabsConstraints tab ;
+ − 1390
+ − 1391 if( !XtIsRealized((Widget)tw))
+ − 1392 return ;
442
+ − 1393
428
+ − 1394 /* draw tabs and frames by row except for the top tab, which
+ − 1395 * is drawn last. (This is inefficiently written, but should not
+ − 1396 * be too slow as long as there are not a lot of rows.)
+ − 1397 */
+ − 1398
+ − 1399 y = tw->tabs.numRows == 1 ? TABDELTA : 0 ;
647
+ − 1400 for(i=0; i < (int) tw->tabs.numRows; ++i, y += th)
428
+ − 1401 {
446
+ − 1402 for( j=TabsNumChildren (tw), childP=tw->composite.children;
428
+ − 1403 --j >= 0; ++childP )
446
+ − 1404 if( TabVisible(*childP) )
428
+ − 1405 {
+ − 1406 tab = (TabsConstraints)(*childP)->core.constraints;
+ − 1407 if( tab->tabs.row == i && *childP != tw->tabs.topWidget )
+ − 1408 DrawTab(tw, *childP, labels) ;
+ − 1409 }
647
+ − 1410 if( i != (int) tw->tabs.numRows -1 )
428
+ − 1411 DrawTrim(tw, 0,y+th, tw->core.width, th+s, False,False) ;
+ − 1412 }
+ − 1413
+ − 1414 DrawFrame(tw) ;
+ − 1415
+ − 1416 /* and now the top tab */
+ − 1417 if( tw->tabs.topWidget != NULL )
+ − 1418 DrawTab(tw, tw->tabs.topWidget, labels) ;
+ − 1419 }
+ − 1420
+ − 1421
+ − 1422
+ − 1423 /* Draw one tab. Corners are rounded very slightly. */
+ − 1424
+ − 1425 static void
+ − 1426 DrawTab(TabsWidget tw, Widget child, Bool labels)
+ − 1427 {
+ − 1428 GC gc ;
+ − 1429 int x,y ;
+ − 1430
+ − 1431 if( !XtIsRealized((Widget)tw))
+ − 1432 return ;
+ − 1433
+ − 1434 DrawBorder(tw, child, False) ;
+ − 1435
+ − 1436 if( labels )
+ − 1437 {
+ − 1438 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1439 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1440 Window win = XtWindow((Widget)tw) ;
+ − 1441 String lbl = tab->tabs.label != NULL ?
+ − 1442 tab->tabs.label : XtName(child) ;
+ − 1443
+ − 1444 if( XtIsSensitive(child) )
+ − 1445 {
+ − 1446 gc = tw->tabs.foregroundGC ;
+ − 1447 XSetForeground(dpy, gc, tab->tabs.foreground) ;
+ − 1448 }
+ − 1449 else
+ − 1450 {
+ − 1451 /* grey pixel allocation deferred until now */
+ − 1452 if( !tab->tabs.greyAlloc )
+ − 1453 {
+ − 1454 if( tw->tabs.be_nice_to_cmap || tw->core.depth == 1 )
+ − 1455 tab->tabs.grey = tab->tabs.foreground ;
+ − 1456 else
+ − 1457 tab->tabs.grey = AllocGreyPixel((Widget)tw,
+ − 1458 tab->tabs.foreground,
+ − 1459 tw->core.background_pixel,
+ − 1460 tw->tabs.insensitive_contrast ) ;
+ − 1461 tab->tabs.greyAlloc = True ;
+ − 1462 }
+ − 1463 gc = tw->tabs.greyGC ;
+ − 1464 XSetForeground(dpy, gc, tab->tabs.grey) ;
+ − 1465 }
+ − 1466
+ − 1467 x = tab->tabs.x ;
+ − 1468 y = tab->tabs.y ;
+ − 1469 if( child == tw->tabs.topWidget )
+ − 1470 y -= TABLDELTA ;
+ − 1471
+ − 1472 if( tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0 )
+ − 1473 {
+ − 1474 if( tab->tabs.lbm_depth == 1 )
+ − 1475 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
434
+ − 1476 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
428
+ − 1477 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ;
+ − 1478 else
+ − 1479 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
434
+ − 1480 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
428
+ − 1481 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ;
+ − 1482 }
+ − 1483
+ − 1484 if( lbl != NULL && tw->tabs.font != NULL )
+ − 1485 XDrawString(dpy,win,gc,
+ − 1486 x+tab->tabs.l_x, y+tab->tabs.l_y,
+ − 1487 lbl, (int)strlen(lbl)) ;
+ − 1488 }
+ − 1489
+ − 1490 if( child == tw->tabs.hilight )
+ − 1491 DrawHighlight(tw, child, False) ;
+ − 1492 }
+ − 1493
+ − 1494
+ − 1495 /* draw frame all the way around the child windows. */
+ − 1496
+ − 1497 static void
+ − 1498 DrawFrame(TabsWidget tw)
+ − 1499 {
+ − 1500 GC topgc = tw->tabs.topGC ;
+ − 1501 GC botgc = tw->tabs.botGC ;
+ − 1502 Dimension s = SHADWID ;
+ − 1503 Dimension ch = tw->tabs.child_height ;
448
+ − 1504 if (ch > 0)
+ − 1505 Draw3dBox((Widget)tw, 0,tw->tabs.tab_total,
+ − 1506 tw->core.width, ch+2*s, s, topgc, botgc) ;
+ − 1507 else
+ − 1508 {
+ − 1509 Widget w = tw->tabs.topWidget ;
+ − 1510 if (w != NULL)
+ − 1511 {
+ − 1512 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
+ − 1513 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
+ − 1514 tab->tabs.x, 2*s, s, topgc, botgc);
+ − 1515 Draw3dBox((Widget)tw, tab->tabs.x + tab->tabs.width,
+ − 1516 tw->core.height - 2*s,
+ − 1517 tw->core.width - tab->tabs.x - tab->tabs.width, 2*s, s,
+ − 1518 topgc, botgc);
+ − 1519 }
+ − 1520 else
+ − 1521 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
+ − 1522 tw->core.width, 2*s, s, topgc, botgc) ;
+ − 1523 }
428
+ − 1524 }
+ − 1525
+ − 1526
+ − 1527 /* draw trim around a tab or underneath a row of tabs */
+ − 1528
+ − 1529 static void
+ − 1530 DrawTrim(TabsWidget tw, /* widget */
+ − 1531 int x, /* upper-left corner */
+ − 1532 int y,
+ − 1533 int wid, /* total size */
+ − 1534 int hgt,
+ − 1535 Bool bottom, /* draw bottom? */
+ − 1536 Bool undraw) /* undraw all */
+ − 1537 {
+ − 1538 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1539 Window win = XtWindow((Widget)tw) ;
+ − 1540 GC bggc = tw->tabs.backgroundGC ;
+ − 1541 GC topgc = undraw ? bggc : tw->tabs.topGC ;
+ − 1542 GC botgc = undraw ? bggc : tw->tabs.botGC ;
+ − 1543 if( bottom )
+ − 1544 XDrawLine(dpy,win,bggc, x,y+hgt-1, x+wid-1,y+hgt-1) ; /* bottom */
+ − 1545 XDrawLine(dpy,win,topgc, x,y+2, x,y+hgt-2) ; /* left */
+ − 1546 XDrawPoint(dpy,win,topgc, x+1,y+1) ; /* corner */
+ − 1547 XDrawLine(dpy,win,topgc, x+2,y, x+wid-3,y) ; /* top */
+ − 1548 XDrawLine(dpy,win,botgc, x+wid-2,y+1, x+wid-2,y+hgt-2) ; /* right */
+ − 1549 XDrawLine(dpy,win,botgc, x+wid-1,y+2, x+wid-1,y+hgt-2) ; /* right */
+ − 1550 }
+ − 1551
+ − 1552
+ − 1553 /* Draw one tab border. */
+ − 1554
+ − 1555 static void
+ − 1556 DrawBorder(TabsWidget tw, Widget child, Bool undraw)
+ − 1557 {
+ − 1558 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1559 Position x = tab->tabs.x ;
+ − 1560 Position y = tab->tabs.y ;
+ − 1561 Dimension twid = tab->tabs.width ;
+ − 1562 Dimension thgt = tw->tabs.tab_height ;
+ − 1563
+ − 1564 /* top tab requires a little special attention; it overlaps
+ − 1565 * neighboring tabs slightly, so the background must be cleared
+ − 1566 * in the region of the overlap to partially erase those neighbors.
+ − 1567 * TODO: is this worth doing with regions instead?
+ − 1568 */
+ − 1569 if( child == tw->tabs.topWidget )
+ − 1570 {
+ − 1571 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1572 Window win = XtWindow((Widget)tw) ;
+ − 1573 GC bggc = tw->tabs.backgroundGC ;
+ − 1574 XRectangle rects[3] ;
+ − 1575 x -= TABDELTA ;
+ − 1576 y -= TABDELTA ;
+ − 1577 twid += TABDELTA*2 ;
+ − 1578 thgt += TABDELTA ;
+ − 1579 AddRect(0, x,y+1,twid,TABDELTA) ;
+ − 1580 AddRect(1, x+1,y,TABDELTA,thgt) ;
+ − 1581 AddRect(2, x+twid-TABDELTA-1,y,TABDELTA,thgt) ;
+ − 1582 XFillRectangles(dpy,win,bggc, rects, 3) ;
+ − 1583 }
+ − 1584
+ − 1585 DrawTrim(tw, x,y,twid,thgt+1, child == tw->tabs.topWidget, undraw) ;
+ − 1586 }
+ − 1587
+ − 1588
+ − 1589 /* Draw highlight around tab that has focus */
+ − 1590
+ − 1591 static void
+ − 1592 DrawHighlight(TabsWidget tw, Widget child, Bool undraw)
+ − 1593 {
+ − 1594 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1595 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1596 Window win = XtWindow((Widget)tw) ;
+ − 1597 GC gc ;
+ − 1598 Position x = tab->tabs.x ;
+ − 1599 Position y = tab->tabs.y ;
+ − 1600 Dimension wid = tab->tabs.width ;
+ − 1601 Dimension hgt = tw->tabs.tab_height ;
+ − 1602 XPoint points[6] ;
+ − 1603
+ − 1604 /* top tab does not have a highlight */
+ − 1605
+ − 1606 if( child == tw->tabs.topWidget )
+ − 1607 return ;
+ − 1608
+ − 1609 if( undraw )
+ − 1610 gc = tw->tabs.backgroundGC ;
+ − 1611
+ − 1612 else if( XtIsSensitive(child) )
+ − 1613 {
+ − 1614 gc = tw->tabs.foregroundGC ;
+ − 1615 XSetForeground(dpy, gc, tab->tabs.foreground) ;
+ − 1616 }
+ − 1617 else
+ − 1618 {
+ − 1619 gc = tw->tabs.greyGC ;
+ − 1620 XSetForeground(dpy, gc, tab->tabs.grey) ;
+ − 1621 }
+ − 1622
+ − 1623 points[0].x = x+1 ; points[0].y = y+hgt-1 ;
+ − 1624 points[1].x = x+1 ; points[1].y = y+2 ;
+ − 1625 points[2].x = x+2 ; points[2].y = y+1 ;
+ − 1626 points[3].x = x+wid-4 ; points[3].y = y+1 ;
+ − 1627 points[4].x = x+wid-3 ; points[4].y = y+2 ;
+ − 1628 points[5].x = x+wid-3 ; points[5].y = y+hgt-1 ;
+ − 1629
+ − 1630 XDrawLines(dpy,win,gc, points,6, CoordModeOrigin) ;
+ − 1631 }
+ − 1632
+ − 1633
+ − 1634 /* Undraw one tab interior */
+ − 1635
+ − 1636 static void
+ − 1637 UndrawTab(TabsWidget tw, Widget child)
+ − 1638 {
+ − 1639 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1640 Position x = tab->tabs.x ;
+ − 1641 Position y = tab->tabs.y ;
+ − 1642 Dimension twid = tab->tabs.width ;
+ − 1643 Dimension thgt = tw->tabs.tab_height ;
+ − 1644 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1645 Window win = XtWindow((Widget)tw) ;
+ − 1646 GC bggc = tw->tabs.backgroundGC ;
+ − 1647
+ − 1648 XFillRectangle(dpy,win,bggc, x,y, twid,thgt) ;
+ − 1649 }
+ − 1650
+ − 1651
+ − 1652
+ − 1653
+ − 1654
+ − 1655 /* GEOMETRY UTILITIES */
+ − 1656
434
+ − 1657 /* Overview:
+ − 1658 *
+ − 1659 * MaxChild(): ask all children (except possibly one) their
+ − 1660 * preferred sizes, set max_cw, max_ch accordingly.
+ − 1661 *
+ − 1662 * GetPreferredSizes(): ask all children their preferred sizes,
+ − 1663 * set max_cw, max_ch accordingly.
+ − 1664 *
+ − 1665 * PreferredSize(): given max_cw, max_ch, return tabs widget
+ − 1666 * preferred size. Iterate with other widths in order to get
+ − 1667 * a reasonable aspect ratio.
+ − 1668 *
+ − 1669 * PreferredSize2(): Given child dimensions, return Tabs
+ − 1670 * widget dimensions.
+ − 1671 *
+ − 1672 * PreferredSize3(): Same, except given child dimensions plus
+ − 1673 * shadow.
+ − 1674 */
428
+ − 1675
434
+ − 1676
+ − 1677 /* Compute the width of one child's tab. Positions will be computed
428
+ − 1678 * elsewhere.
+ − 1679 *
+ − 1680 * height: font height + vertical_space*2 + shadowWid*2
+ − 1681 * width: string width + horizontal_space*2 + shadowWid*2
+ − 1682 *
+ − 1683 * All tabs are the same height, so that is computed elsewhere.
+ − 1684 */
+ − 1685
+ − 1686 static void
+ − 1687 TabWidth(Widget w)
+ − 1688 {
+ − 1689 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
+ − 1690 TabsWidget tw = (TabsWidget)XtParent(w) ;
+ − 1691 String lbl = tab->tabs.label != NULL ?
+ − 1692 tab->tabs.label : XtName(w) ;
+ − 1693 XFontStruct *font = tw->tabs.font ;
+ − 1694 int iw = tw->tabs.internalWidth ;
+ − 1695
+ − 1696 tab->tabs.width = iw + SHADWID*2 ;
+ − 1697 tab->tabs.l_x = tab->tabs.lbm_x = SHADWID + iw ;
+ − 1698
+ − 1699 if( tab->tabs.left_bitmap != None )
+ − 1700 {
+ − 1701 tab->tabs.width += tab->tabs.lbm_width + iw ;
+ − 1702 tab->tabs.l_x += tab->tabs.lbm_width + iw ;
+ − 1703 tab->tabs.lbm_y = (tw->tabs.tab_height - tab->tabs.lbm_height)/2 ;
+ − 1704 }
+ − 1705
+ − 1706 if( lbl != NULL && font != NULL )
+ − 1707 {
+ − 1708 tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ;
+ − 1709 tab->tabs.l_y = (tw->tabs.tab_height +
434
+ − 1710 tw->tabs.font->max_bounds.ascent -
428
+ − 1711 tw->tabs.font->max_bounds.descent)/2 ;
+ − 1712 }
+ − 1713 }
+ − 1714
+ − 1715
+ − 1716
+ − 1717 /* Lay out tabs to fit in given width. Compute x,y position and
+ − 1718 * row number for each tab. Return number of rows and total height
+ − 1719 * required by all tabs. If there is only one row, add TABDELTA
+ − 1720 * height to the total. Rows are assigned bottom to top.
+ − 1721 *
+ − 1722 * Tabs are indented from the edges by INDENT.
+ − 1723 *
+ − 1724 * TODO: if they require more than two rows and the total height:width
+ − 1725 * ratio is more than 2:1, then try something else.
+ − 1726 */
+ − 1727
+ − 1728 static int
448
+ − 1729 TabLayout(TabsWidget tw,
+ − 1730 Dimension wid,
+ − 1731 Dimension hgt,
+ − 1732 Dimension *reply_height, Bool query_only)
428
+ − 1733 {
446
+ − 1734 int i, row, done = 0, display_rows = 0 ;
428
+ − 1735 int num_children = tw->composite.num_children ;
+ − 1736 Widget *childP ;
+ − 1737 Dimension w ;
+ − 1738 Position x,y ;
+ − 1739 TabsConstraints tab ;
+ − 1740
+ − 1741 /* Algorithm: loop through children, assign X positions. If a tab
+ − 1742 * would extend beyond the right edge, start a new row. After all
+ − 1743 * rows are assigned, make a second pass and assign Y positions.
+ − 1744 */
+ − 1745
+ − 1746 if( num_children > 0 )
+ − 1747 {
+ − 1748 /* Loop through the tabs and see how much space they need. */
+ − 1749
+ − 1750 row = 0 ;
+ − 1751 x = INDENT ;
+ − 1752 y = 0 ;
+ − 1753 wid -= INDENT ;
+ − 1754 for(i=num_children, childP=tw->composite.children; --i >= 0; ++childP)
+ − 1755 if( XtIsManaged(*childP) )
+ − 1756 {
+ − 1757 tab = (TabsConstraints) (*childP)->core.constraints ;
+ − 1758 w = tab->tabs.width ;
446
+ − 1759
428
+ − 1760 if( x + w > wid ) { /* new row */
446
+ − 1761 if (y + tw->tabs.tab_height > hgt && !done)
+ − 1762 {
+ − 1763 display_rows = row;
+ − 1764 done = 1;
+ − 1765 }
+ − 1766 ++row;
428
+ − 1767 x = INDENT ;
+ − 1768 y += tw->tabs.tab_height ;
+ − 1769 }
+ − 1770 if( !query_only ) {
+ − 1771 tab->tabs.x = x ;
+ − 1772 tab->tabs.y = y ;
+ − 1773 tab->tabs.row = row ;
+ − 1774 }
+ − 1775 x += w + SPACING ;
446
+ − 1776 if (!query_only && !done)
+ − 1777 tab->tabs.visible = 1;
+ − 1778
428
+ − 1779 }
442
+ − 1780 /* If there was only one row, increase the height by TABDELTA */
446
+ − 1781 if( ++display_rows == 1 )
428
+ − 1782 {
446
+ − 1783 row++;
428
+ − 1784 y = TABDELTA ;
+ − 1785 if( !query_only )
+ − 1786 for(i=num_children, childP=tw->composite.children;
+ − 1787 --i >= 0 ; ++childP)
+ − 1788 if( XtIsManaged(*childP) )
+ − 1789 {
+ − 1790 tab = (TabsConstraints) (*childP)->core.constraints ;
+ − 1791 tab->tabs.y = y ;
+ − 1792 }
+ − 1793 }
+ − 1794 y += tw->tabs.tab_height ;
+ − 1795 }
+ − 1796 else
446
+ − 1797 display_rows = row = y = 0 ;
428
+ − 1798
+ − 1799 if( !query_only ) {
+ − 1800 tw->tabs.tab_total = y ;
446
+ − 1801 tw->tabs.numRows = display_rows ;
+ − 1802 tw->tabs.realRows = row;
428
+ − 1803 }
+ − 1804
+ − 1805 if( reply_height != NULL )
+ − 1806 *reply_height = y ;
+ − 1807
446
+ − 1808 return display_rows ;
428
+ − 1809 }
+ − 1810
+ − 1811
+ − 1812
+ − 1813 /* Find max preferred child size. Returned sizes include child
434
+ − 1814 * border widths.
428
+ − 1815 */
+ − 1816
+ − 1817 static void
+ − 1818 GetPreferredSizes(TabsWidget tw)
+ − 1819 {
434
+ − 1820 MaxChild(tw, NULL, 0,0) ;
428
+ − 1821 }
+ − 1822
+ − 1823
+ − 1824
+ − 1825 /* Find max preferred child size. Returned sizes include child
434
+ − 1826 * border widths. If except is non-null, don't ask that one.
+ − 1827 */
428
+ − 1828
+ − 1829 static void
434
+ − 1830 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
428
+ − 1831 {
434
+ − 1832 int i ;
+ − 1833 Widget *childP = tw->composite.children ;
+ − 1834 XtWidgetGeometry preferred ;
428
+ − 1835
+ − 1836 for(i=tw->composite.num_children; --i >=0; ++childP)
448
+ − 1837 if( TabVisible (*childP) /*XtIsManaged(*childP)*/ && *childP != except )
428
+ − 1838 {
434
+ − 1839 (void) XtQueryGeometry(*childP, NULL, &preferred) ;
+ − 1840 cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
+ − 1841 ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
428
+ − 1842 }
+ − 1843
+ − 1844 tw->tabs.max_cw = cw ;
+ − 1845 tw->tabs.max_ch = ch ;
+ − 1846 }
+ − 1847
+ − 1848
+ − 1849
+ − 1850 /* rotate row numbers to bring current widget to bottom row,
+ − 1851 * compute y positions for all tabs
+ − 1852 */
+ − 1853
+ − 1854 static void
+ − 1855 TabsShuffleRows(TabsWidget tw)
+ − 1856 {
+ − 1857 TabsConstraints tab ;
+ − 1858 int move ;
446
+ − 1859 int real_rows, display_rows ;
428
+ − 1860 Widget *childP ;
+ − 1861 Dimension th = tw->tabs.tab_height ;
+ − 1862 Position bottom ;
+ − 1863 int i ;
+ − 1864
+ − 1865 /* There must be a top widget. If not, assign one. */
+ − 1866 if( tw->tabs.topWidget == NULL && tw->composite.children != NULL )
446
+ − 1867 for(i=TabsNumChildren (tw), childP=tw->composite.children;
428
+ − 1868 --i >= 0;
+ − 1869 ++childP)
+ − 1870 if( XtIsManaged(*childP) ) {
+ − 1871 tw->tabs.topWidget = *childP ;
+ − 1872 break ;
+ − 1873 }
+ − 1874
+ − 1875 if( tw->tabs.topWidget != NULL )
+ − 1876 {
446
+ − 1877 display_rows = tw->tabs.numRows ;
+ − 1878 real_rows = tw->tabs.realRows ;
448
+ − 1879 assert( display_rows <= real_rows ) ;
428
+ − 1880
446
+ − 1881 if( real_rows > 1 )
428
+ − 1882 {
+ − 1883 tab = (TabsConstraints) tw->tabs.topWidget->core.constraints ;
+ − 1884 assert( tab != NULL ) ;
+ − 1885
446
+ − 1886 /* How far to move top row. The selected tab must be on
+ − 1887 the bottom row of the *visible* rows. */
+ − 1888 move = (real_rows + 1 - display_rows) - tab->tabs.row ;
+ − 1889 if (move < 0)
+ − 1890 move = real_rows - move;
428
+ − 1891 bottom = tw->tabs.tab_total - th ;
+ − 1892
446
+ − 1893 for(i=tw->composite.num_children, childP=tw->composite.children;
428
+ − 1894 --i >= 0;
+ − 1895 ++childP)
+ − 1896 if( XtIsManaged(*childP) )
+ − 1897 {
+ − 1898 tab = (TabsConstraints) (*childP)->core.constraints ;
446
+ − 1899 tab->tabs.row = (tab->tabs.row + move) % real_rows ;
428
+ − 1900 tab->tabs.y = bottom - tab->tabs.row * th ;
446
+ − 1901 tab->tabs.visible = (tab->tabs.row < display_rows);
428
+ − 1902 }
+ − 1903 }
+ − 1904 }
+ − 1905 }
+ − 1906
+ − 1907
434
+ − 1908 /* Find preferred size. Ask children, find size of largest,
428
+ − 1909 * add room for tabs & return. This can get a little involved,
+ − 1910 * as we don't want to have too many rows of tabs; we may widen
+ − 1911 * the widget to reduce # of rows.
434
+ − 1912 *
+ − 1913 * This function requires that max_cw, max_ch already be set.
428
+ − 1914 */
+ − 1915 static int
+ − 1916 PreferredSize(
+ − 1917 TabsWidget tw,
+ − 1918 Dimension *reply_width, /* total widget size */
+ − 1919 Dimension *reply_height,
+ − 1920 Dimension *reply_cw, /* child widget size */
+ − 1921 Dimension *reply_ch)
+ − 1922 {
+ − 1923 Dimension cw,ch ; /* child width, height */
+ − 1924 Dimension wid,hgt ;
+ − 1925 Dimension rwid,rhgt ;
+ − 1926 int nrow ;
+ − 1927
+ − 1928 wid = cw = tw->tabs.max_cw ;
+ − 1929 hgt = ch = tw->tabs.max_ch ;
+ − 1930
+ − 1931 nrow = PreferredSize2(tw, wid,hgt, &rwid, &rhgt) ;
+ − 1932
+ − 1933 /* Check for absurd results (more than 2 rows, high aspect
+ − 1934 * ratio). Try wider size if needed.
+ − 1935 * TODO: make sure this terminates.
+ − 1936 */
+ − 1937
+ − 1938 if( nrow > 2 && rhgt > rwid )
+ − 1939 {
+ − 1940 Dimension w0, w1 ;
434
+ − 1941 int maxloop = 20 ;
428
+ − 1942
+ − 1943 /* step 1: start doubling size until it's too big */
+ − 1944 do {
+ − 1945 w0 = wid ;
+ − 1946 wid = Max(wid*2, wid+20) ;
+ − 1947 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
+ − 1948 } while( nrow > 2 && rhgt > rwid ) ;
+ − 1949 w1 = wid ;
+ − 1950
+ − 1951 /* step 2: use Newton's method to find ideal size. Stop within
+ − 1952 * 8 pixels.
+ − 1953 */
434
+ − 1954 while( --maxloop > 0 && w1 > w0 + 8 )
428
+ − 1955 {
+ − 1956 wid = (w0+w1)/2 ;
+ − 1957 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
+ − 1958 if( nrow > 2 && rhgt > rwid )
+ − 1959 w0 = wid ;
+ − 1960 else
+ − 1961 w1 = wid ;
+ − 1962 }
+ − 1963 wid = w1 ;
+ − 1964 }
+ − 1965
+ − 1966 *reply_width = rwid ;
+ − 1967 *reply_height = rhgt ;
+ − 1968 if( reply_cw != NULL ) *reply_cw = cw ;
+ − 1969 if( reply_ch != NULL ) *reply_ch = ch ;
+ − 1970 return nrow ;
+ − 1971 }
+ − 1972
+ − 1973
+ − 1974 /* Find preferred size, given size of children. */
+ − 1975
+ − 1976 static int
+ − 1977 PreferredSize2(
+ − 1978 TabsWidget tw,
448
+ − 1979 Dimension cw, /* child width, height */
+ − 1980 Dimension ch,
428
+ − 1981 Dimension *reply_width, /* total widget size */
+ − 1982 Dimension *reply_height)
+ − 1983 {
+ − 1984 Dimension s = SHADWID ;
448
+ − 1985 int ret;
428
+ − 1986
+ − 1987 /* make room for shadow frame */
+ − 1988 cw += s*2 ;
+ − 1989 ch += s*2 ;
+ − 1990
448
+ − 1991 ret = PreferredSize3(tw, cw, ch, reply_width, reply_height) ;
+ − 1992
+ − 1993 assert (*reply_width > 0 && *reply_height > 0);
+ − 1994 return ret;
428
+ − 1995 }
+ − 1996
+ − 1997
+ − 1998 /* Find preferred size, given size of children+shadow. */
+ − 1999
+ − 2000 static int
+ − 2001 PreferredSize3(
+ − 2002 TabsWidget tw,
448
+ − 2003 Dimension wid, /* child width, height */
+ − 2004 Dimension hgt,
428
+ − 2005 Dimension *reply_width, /* total widget size */
+ − 2006 Dimension *reply_height)
+ − 2007 {
+ − 2008 Dimension th ; /* space used by tabs */
+ − 2009 int nrows ;
+ − 2010
+ − 2011 if( tw->composite.num_children > 0 )
+ − 2012 nrows = TabLayout(tw, wid, hgt, &th, True) ;
+ − 2013 else {
+ − 2014 th = 0 ;
+ − 2015 nrows = 0 ;
+ − 2016 }
+ − 2017
+ − 2018 *reply_width = Max(wid, MIN_WID) ;
+ − 2019 *reply_height = Max(th+hgt, MIN_HGT) ;
+ − 2020
+ − 2021 return nrows ;
+ − 2022 }
+ − 2023
+ − 2024
+ − 2025 static void
+ − 2026 MakeSizeRequest(TabsWidget tw)
+ − 2027 {
+ − 2028 Widget w = (Widget)tw ;
+ − 2029 XtWidgetGeometry request, reply ;
+ − 2030 XtGeometryResult result ;
+ − 2031 Dimension cw,ch ;
+ − 2032
+ − 2033 request.request_mode = CWWidth | CWHeight ;
+ − 2034 PreferredSize(tw, &request.width, &request.height, &cw, &ch) ;
+ − 2035
+ − 2036 if( request.width == tw->core.width &&
+ − 2037 request.height == tw->core.height )
+ − 2038 return ;
+ − 2039
+ − 2040 result = XtMakeGeometryRequest(w, &request, &reply) ;
+ − 2041
+ − 2042 if( result == XtGeometryAlmost )
+ − 2043 {
+ − 2044 /* Bugger. Didn't get what we want, but were offered a
+ − 2045 * compromise. If the width was too small, recompute
+ − 2046 * based on the too-small width and try again.
+ − 2047 * If the height was too small, make a wild-ass guess
+ − 2048 * at a wider width and try again.
+ − 2049 */
+ − 2050
+ − 2051 if( reply.width < request.width && reply.height >= request.height )
+ − 2052 {
+ − 2053 Dimension s = SHADWID ;
+ − 2054 ch += s*2 ;
+ − 2055 PreferredSize3(tw, reply.width,ch, &request.width, &request.height);
+ − 2056 result = XtMakeGeometryRequest(w, &request, &reply) ;
+ − 2057 if( result == XtGeometryAlmost )
+ − 2058 (void) XtMakeGeometryRequest(w, &reply, NULL) ;
+ − 2059 }
+ − 2060
+ − 2061 else
+ − 2062 (void) XtMakeGeometryRequest(w, &reply, NULL) ;
+ − 2063 }
+ − 2064 }
+ − 2065
+ − 2066
+ − 2067 static void
+ − 2068 getBitmapInfo(TabsWidget tw, TabsConstraints tab)
+ − 2069 {
+ − 2070 Window root ;
+ − 2071 int x,y ;
+ − 2072 unsigned int bw ;
+ − 2073
+ − 2074 if( tab->tabs.left_bitmap == None ||
+ − 2075 !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y,
434
+ − 2076 &tab->tabs.lbm_width, &tab->tabs.lbm_height,
428
+ − 2077 &bw, &tab->tabs.lbm_depth) )
+ − 2078 tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ;
+ − 2079 }
+ − 2080
+ − 2081
+ − 2082
+ − 2083
+ − 2084 /* Code copied & modified from Gcs.c. This version has dynamic
+ − 2085 * foreground.
+ − 2086 */
+ − 2087
+ − 2088 static void
+ − 2089 TabsAllocFgGC(TabsWidget tw)
+ − 2090 {
+ − 2091 Widget w = (Widget) tw;
+ − 2092 XGCValues values ;
+ − 2093
+ − 2094 values.background = tw->core.background_pixel ;
+ − 2095 values.font = tw->tabs.font->fid ;
+ − 2096 values.line_style = LineOnOffDash ;
+ − 2097 values.line_style = LineSolid ;
+ − 2098
+ − 2099 tw->tabs.foregroundGC =
+ − 2100 XtAllocateGC(w, w->core.depth,
+ − 2101 GCBackground|GCFont|GCLineStyle, &values,
+ − 2102 GCForeground,
+ − 2103 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2104 GCDashList|GCArcMode) ;
+ − 2105 }
+ − 2106
+ − 2107 static void
+ − 2108 TabsAllocGreyGC(TabsWidget tw)
+ − 2109 {
+ − 2110 Widget w = (Widget) tw;
+ − 2111 XGCValues values ;
+ − 2112
+ − 2113 values.background = tw->core.background_pixel ;
+ − 2114 values.font = tw->tabs.font->fid ;
+ − 2115 #ifdef HAVE_XMU
+ − 2116 if( tw->tabs.be_nice_to_cmap || w->core.depth == 1)
+ − 2117 {
+ − 2118 values.fill_style = FillStippled ;
+ − 2119 tw->tabs.grey50 =
+ − 2120 values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ;
+ − 2121
+ − 2122 tw->tabs.greyGC =
+ − 2123 XtAllocateGC(w, w->core.depth,
+ − 2124 GCBackground|GCFont|GCStipple|GCFillStyle, &values,
+ − 2125 GCForeground,
+ − 2126 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2127 GCDashList|GCArcMode) ;
+ − 2128 }
+ − 2129 else
+ − 2130 #endif
+ − 2131 {
+ − 2132 tw->tabs.greyGC =
+ − 2133 XtAllocateGC(w, w->core.depth,
+ − 2134 GCFont, &values,
+ − 2135 GCForeground,
+ − 2136 GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2137 GCDashList|GCArcMode) ;
+ − 2138 }
+ − 2139 }