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
+ − 424 TabsInit(Widget request, Widget new, ArgList args, Cardinal *num_args)
+ − 425 {
+ − 426 TabsWidget newTw = (TabsWidget)new;
+ − 427
+ − 428 newTw->tabs.numRows = 0 ;
446
+ − 429 newTw->tabs.realRows = 0;
428
+ − 430
+ − 431 GetPreferredSizes(newTw) ;
+ − 432
+ − 433 /* height is easy, it's the same for all tabs:
+ − 434 * TODO: font height + height of tallest bitmap.
+ − 435 */
+ − 436 newTw->tabs.tab_height = 2 * newTw->tabs.internalHeight + SHADWID ;
+ − 437
+ − 438 if( newTw->tabs.font != NULL )
+ − 439 newTw->tabs.tab_height += newTw->tabs.font->max_bounds.ascent +
+ − 440 newTw->tabs.font->max_bounds.descent ;
+ − 441
+ − 442 /* GC allocation is deferred until XtRealize() */
+ − 443
+ − 444 /* if size not explicitly set, set it to our preferred size now. */
+ − 445
+ − 446 if( request->core.width == 0 || request->core.height == 0 )
+ − 447 {
+ − 448 Dimension w,h ;
+ − 449 PreferredSize(newTw, &w, &h, NULL,NULL) ;
+ − 450 if( request->core.width == 0 ) new->core.width = w ;
+ − 451 if( request->core.height == 0 ) new->core.height = h ;
+ − 452 XtClass(new)->core_class.resize(new) ;
+ − 453 }
+ − 454
+ − 455 /* defer GC allocation, etc., until Realize() time. */
+ − 456 newTw->tabs.foregroundGC =
+ − 457 newTw->tabs.backgroundGC =
+ − 458 newTw->tabs.greyGC =
+ − 459 newTw->tabs.topGC =
+ − 460 newTw->tabs.botGC = None ;
+ − 461
+ − 462 newTw->tabs.grey50 = None ;
+ − 463
+ − 464 newTw->tabs.needs_layout = False ;
434
+ − 465
428
+ − 466 newTw->tabs.hilight = NULL ;
+ − 467
+ − 468 #ifdef NEED_MOTIF
+ − 469 newTw->manager.navigation_type = XmTAB_GROUP ;
+ − 470 newTw->manager.traversal_on = True ;
+ − 471 #endif
+ − 472 }
+ − 473
+ − 474
+ − 475 /* Init the constraint part of a new tab child. Compute the
+ − 476 * size of the tab.
+ − 477 */
+ − 478 /* ARGSUSED */
+ − 479 static void
+ − 480 TabsConstraintInitialize(Widget request, Widget new,
+ − 481 ArgList args, Cardinal *num_args)
+ − 482 {
+ − 483 TabsConstraints tab = (TabsConstraints) new->core.constraints ;
+ − 484 tab->tabs.greyAlloc = False ; /* defer allocation of pixel */
446
+ − 485 tab->tabs.visible = False ;
428
+ − 486
+ − 487 getBitmapInfo((TabsWidget)XtParent(new), tab) ;
+ − 488 TabWidth(new) ;
+ − 489 }
+ − 490
+ − 491
+ − 492
+ − 493 /* Called when tabs widget first realized. Create the window
+ − 494 * and allocate the GCs
+ − 495 */
+ − 496
+ − 497 static void
+ − 498 TabsRealize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
+ − 499 {
+ − 500 TabsWidget tw = (TabsWidget) w;
+ − 501
+ − 502 attributes->bit_gravity = NorthWestGravity;
+ − 503 *valueMask |= CWBitGravity;
+ − 504
+ − 505 SuperClass->core_class.realize(w, valueMask, attributes);
+ − 506
+ − 507 TabsAllocGCs(tw) ;
+ − 508 }
+ − 509
+ − 510
+ − 511
+ − 512 static void
+ − 513 TabsDestroy(Widget w)
+ − 514 {
+ − 515 TabsFreeGCs((TabsWidget)w) ;
+ − 516 }
+ − 517
+ − 518
+ − 519 /* Parent has resized us. This will require that the tabs be
+ − 520 * laid out again.
+ − 521 */
+ − 522
+ − 523 static void
+ − 524 TabsResize(Widget w)
+ − 525 {
+ − 526 TabsWidget tw = (TabsWidget) w;
+ − 527 int i ;
+ − 528 int num_children = tw->composite.num_children ;
+ − 529 Widget *childP ;
446
+ − 530 TabsConstraints tab ; /* #### unused */
428
+ − 531 Dimension cw,ch,bw ;
+ − 532
+ − 533 /* Our size has now been dictated by the parent. Lay out the
+ − 534 * tabs, lay out the frame, lay out the children. Remember
+ − 535 * that the tabs overlap each other and the frame by shadowWidth.
+ − 536 * Also, the top tab is larger than the others, so if there's only
+ − 537 * one row, the widget must be made taller to accommodate this.
+ − 538 *
+ − 539 * Once the tabs are laid out, if there is more than one
+ − 540 * row, we may need to shuffle the rows to bring the top tab
+ − 541 * to the bottom row.
+ − 542 */
+ − 543
434
+ − 544 tw->tabs.needs_layout = False ;
+ − 545
428
+ − 546 if( num_children > 0 && tw->composite.children != NULL )
+ − 547 {
+ − 548 /* Loop through the tabs and assign rows & x positions */
+ − 549 (void) TabLayout(tw, tw->core.width, tw->core.height, NULL, False) ;
446
+ − 550 num_children = TabsNumChildren (tw);
428
+ − 551
+ − 552 /* assign a top widget, bring it to bottom row. */
+ − 553 TabsShuffleRows(tw) ;
+ − 554
+ − 555 /* now assign child positions & sizes. Positions are all the
+ − 556 * same: just inside the frame. Sizes are also all the same.
+ − 557 */
+ − 558
+ − 559 tw->tabs.child_width = cw = tw->core.width - 2 * SHADWID ;
+ − 560 tw->tabs.child_height = ch =
448
+ − 561 tw->core.height < (tw->tabs.tab_total + 2 * SHADWID) ? 0 :
+ − 562 tw->core.height - tw->tabs.tab_total - 2 * SHADWID ;
428
+ − 563
+ − 564 for(i=0, childP=tw->composite.children;
434
+ − 565 i < num_children;
428
+ − 566 ++i, ++childP)
448
+ − 567 if( XtIsManaged(*childP) )
428
+ − 568 {
+ − 569 tab = (TabsConstraints) (*childP)->core.constraints ;
434
+ − 570 bw = (*childP)->core.border_width ;
448
+ − 571 /* Don't do anything if we can't see any of the child. */
+ − 572 if (ch >= bw*2 && ch > 0 && cw >= bw*2 && cw > 0)
+ − 573 XtConfigureWidget(*childP, SHADWID,tw->tabs.tab_total+SHADWID,
+ − 574 cw-bw*2,ch-bw*2, bw) ;
428
+ − 575 }
434
+ − 576 if( XtIsRealized(w) ) {
+ − 577 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 578 /* should not be necessary to explicitly repaint after a
+ − 579 * resize, but XEmacs folks tell me it is.
+ − 580 */
+ − 581 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 582 }
428
+ − 583 }
+ − 584 } /* Resize */
+ − 585
+ − 586
+ − 587
+ − 588 /* Redraw entire Tabs widget */
+ − 589
+ − 590 /* ARGSUSED */
+ − 591 static void
+ − 592 TabsExpose(Widget w, XEvent *event, Region region)
+ − 593 {
+ − 594 TabsWidget tw = (TabsWidget) w;
+ − 595
+ − 596 if( tw->tabs.needs_layout )
+ − 597 XtClass(w)->core_class.resize(w) ;
+ − 598
+ − 599 DrawTabs(tw, True) ;
+ − 600 }
+ − 601
+ − 602
+ − 603 /* Called when any Tabs widget resources are changed. */
+ − 604
+ − 605 /* ARGSUSED */
+ − 606 static Boolean
+ − 607 TabsSetValues(Widget current, Widget request, Widget new,
+ − 608 ArgList args, Cardinal *num_args)
+ − 609 {
430
+ − 610 TabsWidget curtw = (TabsWidget) current ;
+ − 611 TabsWidget tw = (TabsWidget) new ;
+ − 612 Boolean needRedraw = False ;
+ − 613 Widget *childP ;
+ − 614 int i ;
428
+ − 615
+ − 616
430
+ − 617 if( tw->tabs.font != curtw->tabs.font ||
+ − 618 tw->tabs.internalWidth != curtw->tabs.internalWidth ||
+ − 619 tw->tabs.internalHeight != curtw->tabs.internalHeight )
+ − 620 {
+ − 621 tw->tabs.tab_height = 2 * tw->tabs.internalHeight + SHADWID ;
428
+ − 622
430
+ − 623 if( tw->tabs.font != NULL )
+ − 624 tw->tabs.tab_height += tw->tabs.font->max_bounds.ascent +
+ − 625 tw->tabs.font->max_bounds.descent ;
428
+ − 626
430
+ − 627 /* Tab size has changed. Resize all tabs and request a new size */
+ − 628 for(i=0, childP=tw->composite.children;
+ − 629 i < tw->composite.num_children;
+ − 630 ++i, ++childP)
+ − 631 if( XtIsManaged(*childP) )
+ − 632 TabWidth(*childP) ;
+ − 633 PreferredSize(tw, &tw->core.width, &tw->core.height, NULL,NULL) ;
+ − 634 needRedraw = True ;
+ − 635 tw->tabs.needs_layout = True ;
+ − 636 }
428
+ − 637
430
+ − 638 /* TODO: if any color changes, need to recompute GCs and redraw */
428
+ − 639
430
+ − 640 if( tw->core.background_pixel != curtw->core.background_pixel ||
432
+ − 641 tw->core.background_pixmap != curtw->core.background_pixmap ||
+ − 642 tw->tabs.font != curtw->tabs.font )
430
+ − 643 if( XtIsRealized(new) )
+ − 644 {
+ − 645 TabsFreeGCs(tw) ;
+ − 646 TabsAllocGCs(tw) ;
+ − 647 needRedraw = True ;
+ − 648 }
428
+ − 649
430
+ − 650 if( tw->core.sensitive != curtw->core.sensitive )
+ − 651 needRedraw = True ;
428
+ − 652
430
+ − 653 /* If top widget changes, need to change stacking order, redraw tabs.
+ − 654 * Window system will handle the redraws.
+ − 655 */
428
+ − 656
442
+ − 657 if( tw->tabs.topWidget != curtw->tabs.topWidget )
432
+ − 658 {
430
+ − 659 if( XtIsRealized(tw->tabs.topWidget) )
+ − 660 {
+ − 661 Widget w = tw->tabs.topWidget ;
+ − 662 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
428
+ − 663
430
+ − 664 XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
428
+ − 665 #ifdef NEED_MOTIF
430
+ − 666 XtVaSetValues(curtw->tabs.topWidget, XmNtraversalOn, False, 0) ;
+ − 667 XtVaSetValues(w, XmNtraversalOn, True, 0) ;
428
+ − 668 #endif
+ − 669
430
+ − 670 if( tab->tabs.row != tw->tabs.numRows-1 )
+ − 671 TabsShuffleRows(tw) ;
428
+ − 672
430
+ − 673 needRedraw = True ;
+ − 674 }
+ − 675 else
+ − 676 tw->tabs.needs_layout = True ;
432
+ − 677 }
428
+ − 678
430
+ − 679 return needRedraw ;
428
+ − 680 }
+ − 681
+ − 682
+ − 683 /* Called when any child constraint resources change. */
+ − 684
+ − 685 /* ARGSUSED */
+ − 686 static Boolean
+ − 687 TabsConstraintSetValues(Widget current, Widget request, Widget new,
+ − 688 ArgList args, Cardinal *num_args)
+ − 689 {
+ − 690 TabsWidget tw = (TabsWidget) XtParent(new) ;
+ − 691 TabsConstraints ctab = (TabsConstraints) current->core.constraints ;
+ − 692 TabsConstraints tab = (TabsConstraints) new->core.constraints ;
+ − 693
+ − 694
+ − 695 /* if label changes, need to re-layout the entire widget */
+ − 696 /* if foreground changes, need to redraw tab label */
+ − 697
+ − 698 /* TODO: only need resize of new bitmap has different dimensions
+ − 699 * from old bitmap.
+ − 700 */
+ − 701
+ − 702 if( tab->tabs.label != ctab->tabs.label || /* Tab size has changed. */
+ − 703 tab->tabs.left_bitmap != ctab->tabs.left_bitmap )
+ − 704 {
+ − 705 TabWidth(new) ;
+ − 706 tw->tabs.needs_layout = True ;
+ − 707
+ − 708 if( tab->tabs.left_bitmap != ctab->tabs.left_bitmap )
+ − 709 getBitmapInfo(tw, tab) ;
+ − 710
+ − 711 /* If there are no subclass ConstraintSetValues procedures remaining
+ − 712 * to be invoked, and if the preferred size has changed, ask
+ − 713 * for a resize.
+ − 714 */
+ − 715 if( XtClass((Widget)tw) == tabsWidgetClass )
+ − 716 MakeSizeRequest(tw) ;
+ − 717 }
+ − 718
+ − 719
+ − 720 /* The child widget itself never needs a redisplay, but the parent
+ − 721 * Tabs widget might.
+ − 722 */
+ − 723
+ − 724 if( XtIsRealized(new) )
+ − 725 {
+ − 726 if( tw->tabs.needs_layout ) {
+ − 727 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 728 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 729 }
+ − 730
+ − 731 else if( tab->tabs.foreground != ctab->tabs.foreground )
+ − 732 DrawTab(tw, new, True) ;
+ − 733 }
+ − 734
+ − 735 return False ;
+ − 736 }
+ − 737
+ − 738
434
+ − 739 static Boolean
+ − 740 TabsAcceptFocus(Widget w, Time *t)
+ − 741 {
+ − 742 if( !w->core.being_destroyed && XtIsRealized(w) &&
+ − 743 XtIsSensitive(w) && XtIsManaged(w) && w->core.visible )
+ − 744 {
+ − 745 Widget p ;
+ − 746 for(p = XtParent(w); !XtIsShell(p); p = XtParent(p)) ;
+ − 747 XtSetKeyboardFocus(p,w) ;
+ − 748 return True ;
+ − 749 }
+ − 750 else
+ − 751 return False ;
+ − 752 }
+ − 753
+ − 754
428
+ − 755
+ − 756 /*
+ − 757 * Return preferred size. Happily accept anything >= our preferred size.
+ − 758 * (TODO: is that the right thing to do? Should we always return "almost"
442
+ − 759 * if offered more than we need?)
428
+ − 760 */
+ − 761
+ − 762 static XtGeometryResult
+ − 763 TabsQueryGeometry(Widget w,
+ − 764 XtWidgetGeometry *intended, XtWidgetGeometry *preferred)
+ − 765 {
+ − 766 register TabsWidget tw = (TabsWidget)w ;
+ − 767 XtGeometryMask mode = intended->request_mode ;
+ − 768
+ − 769 preferred->request_mode = CWWidth | CWHeight ;
+ − 770 PreferredSize(tw, &preferred->width, &preferred->height, NULL,NULL) ;
+ − 771
+ − 772 if( (!(mode & CWWidth) || intended->width == w->core.width) &&
+ − 773 (!(mode & CWHeight) || intended->height == w->core.height) )
+ − 774 return XtGeometryNo ;
+ − 775
+ − 776 if( (!(mode & CWWidth) || intended->width >= preferred->width) &&
+ − 777 (!(mode & CWHeight) || intended->height >= preferred->height) )
+ − 778 return XtGeometryYes;
+ − 779
+ − 780 return XtGeometryAlmost;
+ − 781 }
+ − 782
+ − 783
+ − 784
+ − 785 /*
+ − 786 * Geometry Manager; called when a child wants to be resized.
+ − 787 */
+ − 788
+ − 789 static XtGeometryResult
+ − 790 TabsGeometryManager(Widget w, XtWidgetGeometry *req, XtWidgetGeometry *reply)
+ − 791 {
+ − 792 TabsWidget tw = (TabsWidget) XtParent(w);
+ − 793 Dimension s = SHADWID ;
+ − 794 TabsConstraints tab = (TabsConstraints)w->core.constraints;
+ − 795 XtGeometryResult result ;
434
+ − 796 Dimension rw, rh ;
428
+ − 797
+ − 798 /* Position request always denied */
+ − 799
+ − 800 if( ((req->request_mode & CWX) && req->x != w->core.x) ||
+ − 801 ((req->request_mode & CWY) && req->y != w->core.y) ||
+ − 802 !tab->tabs.resizable )
+ − 803 return XtGeometryNo ;
+ − 804
+ − 805 /* Make all three fields in the request valid */
+ − 806 if( !(req->request_mode & CWWidth) )
+ − 807 req->width = w->core.width;
+ − 808 if( !(req->request_mode & CWHeight) )
+ − 809 req->height = w->core.height;
+ − 810 if( !(req->request_mode & CWBorderWidth) )
+ − 811 req->border_width = w->core.border_width;
+ − 812
+ − 813 if( req->width == w->core.width &&
+ − 814 req->height == w->core.height &&
+ − 815 req->border_width == w->core.border_width )
+ − 816 return XtGeometryNo ;
+ − 817
434
+ − 818 rw = req->width + 2 * req->border_width ;
+ − 819 rh = req->height + 2 * req->border_width ;
+ − 820
+ − 821 /* find out how big the children want to be now */
+ − 822 MaxChild(tw, w, rw, rh) ;
428
+ − 823
+ − 824
+ − 825 /* Size changes must see if the new size can be accommodated.
+ − 826 * The Tabs widget keeps all of its children the same
+ − 827 * size. A request to shrink will be accepted only if the
+ − 828 * new size is still big enough for all other children. A
+ − 829 * request to shrink that is not big enough for all children
434
+ − 830 * returns an "almost" response with the new proposed size
+ − 831 * or a "no" response if unable to shrink at all.
+ − 832 *
428
+ − 833 * A request to grow will be accepted only if the Tabs parent can
+ − 834 * grow to accommodate.
+ − 835 *
+ − 836 * TODO:
+ − 837 * We could get fancy here and re-arrange the tabs if it is
+ − 838 * necessary to compromise with the parent, but we'll save that
+ − 839 * for another day.
+ − 840 */
+ − 841
+ − 842 if (req->request_mode & (CWWidth | CWHeight | CWBorderWidth))
+ − 843 {
+ − 844 Dimension cw,ch ; /* children's preferred size */
+ − 845 Dimension aw,ah ; /* available size we can give child */
+ − 846 Dimension th ; /* space used by tabs */
+ − 847 Dimension wid,hgt ; /* Tabs widget size */
+ − 848
434
+ − 849 cw = tw->tabs.max_cw ;
+ − 850 ch = tw->tabs.max_ch ;
428
+ − 851
434
+ − 852 /* find out what *my* resulting preferred size would be */
428
+ − 853
434
+ − 854 PreferredSize2(tw, cw, ch, &wid, &hgt) ;
+ − 855
+ − 856 /* Would my size change? If so, ask to be resized. */
428
+ − 857
+ − 858 if( wid != tw->core.width || hgt != tw->core.height )
+ − 859 {
+ − 860 Dimension oldWid = tw->core.width, oldHgt = tw->core.height ;
+ − 861 XtWidgetGeometry myrequest, myreply ;
+ − 862
+ − 863 myrequest.width = wid ;
+ − 864 myrequest.height = hgt ;
+ − 865 myrequest.request_mode = CWWidth | CWHeight ;
448
+ − 866
+ − 867 assert (wid > 0 && hgt > 0);
428
+ − 868 /* If child is only querying, or if we're going to have to
+ − 869 * offer the child a compromise, then make this a query only.
+ − 870 */
+ − 871
+ − 872 if( (req->request_mode & XtCWQueryOnly) || rw < cw || rh < ch )
+ − 873 myrequest.request_mode |= XtCWQueryOnly ;
+ − 874
+ − 875 result = XtMakeGeometryRequest((Widget)tw, &myrequest, &myreply) ;
+ − 876
434
+ − 877 /* !$@# Athena Box widget changes the core size even if QueryOnly
428
+ − 878 * is set. I'm convinced this is a bug. At any rate, to work
+ − 879 * around the bug, we need to restore the core size after every
+ − 880 * query geometry request. This is only partly effective,
+ − 881 * as there may be other boxes further up the tree.
+ − 882 */
+ − 883 if( myrequest.request_mode & XtCWQueryOnly ) {
+ − 884 tw->core.width = oldWid ;
+ − 885 tw->core.height = oldHgt ;
+ − 886 }
+ − 887
+ − 888 /* based on the parent's response, determine what the
+ − 889 * resulting Tabs widget size would be.
+ − 890 */
+ − 891
+ − 892 switch( result ) {
+ − 893 case XtGeometryYes:
+ − 894 case XtGeometryDone:
434
+ − 895 tw->tabs.needs_layout = True ;
428
+ − 896 break ;
+ − 897
+ − 898 case XtGeometryNo:
+ − 899 wid = tw->core.width ;
+ − 900 hgt = tw->core.height ;
+ − 901 break ;
+ − 902
+ − 903 case XtGeometryAlmost:
+ − 904 wid = myreply.width ;
+ − 905 hgt = myreply.height ;
434
+ − 906 tw->tabs.needs_layout = True ;
+ − 907 break ;
428
+ − 908 }
+ − 909 }
+ − 910
+ − 911 /* Within the constraints imposed by the parent, what is
+ − 912 * the max size we can give the child?
+ − 913 */
+ − 914 (void) TabLayout(tw, wid, hgt, &th, True) ;
+ − 915 aw = wid - 2*s ;
+ − 916 ah = hgt - th - 2*s ;
+ − 917
+ − 918 /* OK, make our decision. If requested size is >= max sibling
+ − 919 * preferred size, AND requested size <= available size, then
+ − 920 * we accept. Otherwise, we offer a compromise.
+ − 921 */
+ − 922
+ − 923 if( rw == aw && rh == ah )
+ − 924 {
+ − 925 /* Acceptable. If this wasn't a query, change *all* children
+ − 926 * to this size.
+ − 927 */
+ − 928 if( req->request_mode & XtCWQueryOnly )
+ − 929 return XtGeometryYes ;
+ − 930 else
+ − 931 {
+ − 932 Widget *childP = tw->composite.children ;
+ − 933 int i,bw ;
+ − 934 w->core.border_width = req->border_width ;
446
+ − 935 for(i=TabsNumChildren (tw); --i >= 0; ++childP)
+ − 936 if( TabVisible(*childP) )
428
+ − 937 {
+ − 938 bw = (*childP)->core.border_width ;
+ − 939 XtConfigureWidget(*childP, s,tw->tabs.tab_total+s,
+ − 940 rw-2*bw, rh-2*bw, bw) ;
+ − 941 }
+ − 942 #ifdef COMMENT
+ − 943 /* TODO: under what conditions will we need to redraw? */
+ − 944 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 945 XtClass(tw)->core_class.expose((Widget)tw,NULL,NULL) ;
+ − 946 #endif /* COMMENT */
+ − 947 return XtGeometryDone ;
+ − 948 }
+ − 949 }
+ − 950
+ − 951 /* Cannot grant child's request. Describe what we *can* do
+ − 952 * and return counter-offer.
+ − 953 */
+ − 954 reply->width = aw - 2 * req->border_width ;
+ − 955 reply->height = ah - 2 * req->border_width ;
+ − 956 reply->border_width = req->border_width ;
+ − 957 reply->request_mode = CWWidth | CWHeight | CWBorderWidth ;
+ − 958 return XtGeometryAlmost ;
+ − 959 }
+ − 960
+ − 961 return XtGeometryYes ;
+ − 962 }
+ − 963
+ − 964
+ − 965
+ − 966
+ − 967 /* The number of children we manage has changed; recompute
+ − 968 * size from scratch.
+ − 969 */
+ − 970
+ − 971 static void
+ − 972 TabsChangeManaged(Widget w)
+ − 973 {
+ − 974 TabsWidget tw = (TabsWidget)w ;
+ − 975 Widget *childP = tw->composite.children ;
+ − 976 int i ;
+ − 977
+ − 978 if( tw->tabs.topWidget != NULL &&
+ − 979 ( !XtIsManaged(tw->tabs.topWidget) ||
+ − 980 tw->tabs.topWidget->core.being_destroyed ) )
+ − 981 tw->tabs.topWidget = NULL ;
+ − 982
440
+ − 983 /* Check whether the highlight tab is still valid. */
+ − 984 if( tw->tabs.hilight != NULL &&
+ − 985 ( !XtIsManaged(tw->tabs.hilight) ||
+ − 986 tw->tabs.hilight->core.being_destroyed ) )
+ − 987 tw->tabs.hilight = NULL ;
+ − 988
428
+ − 989 GetPreferredSizes(tw) ;
+ − 990 MakeSizeRequest(tw) ;
+ − 991
+ − 992 XtClass(w)->core_class.resize(w) ;
+ − 993 if( XtIsRealized(w) )
+ − 994 {
+ − 995 Display *dpy = XtDisplay(w) ;
+ − 996 XClearWindow(dpy, XtWindow(w)) ;
+ − 997 XtClass(w)->core_class.expose(w,NULL,NULL) ;
+ − 998
+ − 999 /* make sure the top widget stays on top. This requires
+ − 1000 * making sure that all new children are realized first.
+ − 1001 */
+ − 1002 if( tw->tabs.topWidget != NULL && XtIsRealized(tw->tabs.topWidget) )
+ − 1003 {
446
+ − 1004 for(i=TabsNumChildren (tw); --i >= 0; ++childP)
428
+ − 1005 if( !XtIsRealized(*childP) )
+ − 1006 XtRealizeWidget(*childP) ;
+ − 1007
+ − 1008 XRaiseWindow(dpy, XtWindow(tw->tabs.topWidget)) ;
+ − 1009 }
+ − 1010 }
+ − 1011
+ − 1012 #ifdef NEED_MOTIF
+ − 1013 /* Only top widget may receive input */
+ − 1014
+ − 1015 for(childP = tw->composite.children, i=tw->composite.num_children;
+ − 1016 --i >= 0;
+ − 1017 ++childP)
+ − 1018 {
+ − 1019 XtVaSetValues(*childP, XmNtraversalOn, False, 0) ;
+ − 1020 }
+ − 1021
+ − 1022 if( tw->tabs.topWidget != NULL )
+ − 1023 XtVaSetValues(tw->tabs.topWidget, XmNtraversalOn, True, 0) ;
+ − 1024 #endif
+ − 1025 }
+ − 1026
+ − 1027
+ − 1028
+ − 1029
+ − 1030 /****************************************************************
+ − 1031 *
+ − 1032 * Action Procedures
+ − 1033 *
+ − 1034 ****************************************************************/
+ − 1035
+ − 1036
+ − 1037 /* User clicks on a tab, figure out which one it was. */
+ − 1038
+ − 1039 /* ARGSUSED */
+ − 1040 static void
+ − 1041 TabsSelect(Widget w, XEvent *event, String *params, Cardinal *num_params)
+ − 1042 {
+ − 1043 TabsWidget tw = (TabsWidget) w ;
+ − 1044 Widget *childP ;
+ − 1045 Position x,y ;
+ − 1046 Dimension h = tw->tabs.tab_height ;
+ − 1047 int i ;
+ − 1048
+ − 1049 #ifdef NEED_MOTIF
+ − 1050 XmProcessTraversal (w, XmTRAVERSE_CURRENT) ;
+ − 1051 #endif
+ − 1052
+ − 1053 /* TODO: is there an Xmu function or something to do this instead? */
+ − 1054 switch( event->type ) {
+ − 1055 case ButtonPress:
+ − 1056 case ButtonRelease:
+ − 1057 x = event->xbutton.x ; y = event->xbutton.y ; break ;
+ − 1058 case KeyPress:
+ − 1059 case KeyRelease:
+ − 1060 x = event->xkey.x ; y = event->xkey.y ; break ;
+ − 1061 default:
+ − 1062 return ;
+ − 1063 }
+ − 1064
+ − 1065 /* TODO: determine which tab was clicked, if any. Set that
+ − 1066 * widget to be top of stacking order with XawTabsSetTop().
+ − 1067 */
+ − 1068 for(i=0, childP=tw->composite.children;
446
+ − 1069 i < TabsNumChildren (tw);
428
+ − 1070 ++i, ++childP)
446
+ − 1071 if( TabVisible(*childP) )
428
+ − 1072 {
+ − 1073 TabsConstraints tab = (TabsConstraints)(*childP)->core.constraints;
+ − 1074 if( x > tab->tabs.x && x < tab->tabs.x + tab->tabs.width &&
+ − 1075 y > tab->tabs.y && y < tab->tabs.y + h )
+ − 1076 {
+ − 1077 if( *childP != tw->tabs.topWidget &&
+ − 1078 (XtIsSensitive(*childP) || tw->tabs.selectInsensitive) )
+ − 1079 XawTabsSetTop(*childP, True) ;
+ − 1080 break ;
+ − 1081 }
+ − 1082 }
+ − 1083 }
+ − 1084
+ − 1085
+ − 1086 /* User hits a key */
+ − 1087
+ − 1088 static void
+ − 1089 TabsPage(Widget w, XEvent *event, String *params, Cardinal *num_params)
+ − 1090 {
+ − 1091 TabsWidget tw = (TabsWidget) w ;
430
+ − 1092 Widget newtop = NULL;
428
+ − 1093 Widget *childP ;
+ − 1094 int idx ;
446
+ − 1095 int nc = TabsNumChildren (tw) ;
428
+ − 1096
+ − 1097 if( nc <= 0 )
+ − 1098 return ;
+ − 1099
+ − 1100 if( *num_params < 1 ) {
+ − 1101 XtAppWarning(XtWidgetToApplicationContext(w),
+ − 1102 "Tabs: page() action called with no arguments") ;
+ − 1103 return ;
+ − 1104 }
+ − 1105
+ − 1106 if( tw->tabs.topWidget == NULL )
+ − 1107 tw->tabs.topWidget = tw->composite.children[0] ;
+ − 1108
+ − 1109 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
+ − 1110 if( tw->tabs.topWidget == *childP )
+ − 1111 break ;
+ − 1112
+ − 1113 switch( params[0][0] ) {
+ − 1114 case 'u': /* up */
+ − 1115 case 'U':
432
+ − 1116 if( --idx < 0 )
+ − 1117 idx = nc-1 ;
+ − 1118 newtop = tw->composite.children[idx] ;
428
+ − 1119 break ;
+ − 1120
+ − 1121 case 'd': /* down */
+ − 1122 case 'D':
+ − 1123 if( ++idx >= nc )
+ − 1124 idx = 0 ;
+ − 1125 newtop = tw->composite.children[idx] ;
+ − 1126 break ;
+ − 1127
+ − 1128 case 'h':
+ − 1129 case 'H':
432
+ − 1130 default:
428
+ − 1131 newtop = tw->composite.children[0] ;
+ − 1132 break ;
+ − 1133
+ − 1134 case 'e':
+ − 1135 case 'E':
+ − 1136 newtop = tw->composite.children[nc-1] ;
+ − 1137 break ;
+ − 1138
+ − 1139 case 's': /* selected */
+ − 1140 case 'S':
+ − 1141 if( (newtop = tw->tabs.hilight) == NULL )
+ − 1142 return ;
+ − 1143 break ;
+ − 1144 }
+ − 1145
+ − 1146 XawTabsSetTop(newtop, True) ;
+ − 1147 }
+ − 1148
+ − 1149
+ − 1150 /* User hits up/down key */
+ − 1151
+ − 1152 static void
+ − 1153 TabsHighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+ − 1154 {
+ − 1155 TabsWidget tw = (TabsWidget) w ;
430
+ − 1156 Widget newhl = NULL;
428
+ − 1157 Widget *childP ;
+ − 1158 int idx ;
446
+ − 1159 int nc = TabsNumChildren (tw) ;
428
+ − 1160
+ − 1161 if( nc <= 0 )
+ − 1162 return ;
+ − 1163
+ − 1164 if( *num_params < 1 )
+ − 1165 {
+ − 1166 if( tw->tabs.hilight != NULL )
+ − 1167 DrawHighlight(tw, tw->tabs.hilight, False) ;
+ − 1168 return ;
+ − 1169 }
+ − 1170
+ − 1171 if( tw->tabs.hilight == NULL )
+ − 1172 newhl = tw->composite.children[0] ;
+ − 1173
+ − 1174 else
+ − 1175 {
432
+ − 1176 /* find index of currently highlit child */
428
+ − 1177 for(idx=0, childP=tw->composite.children; idx < nc; ++idx, ++childP )
+ − 1178 if( tw->tabs.hilight == *childP )
+ − 1179 break ;
+ − 1180
+ − 1181 switch( params[0][0] ) {
+ − 1182 case 'u': /* up */
+ − 1183 case 'U':
432
+ − 1184 if( --idx < 0 )
+ − 1185 idx = nc-1 ;
+ − 1186 newhl = tw->composite.children[idx] ;
428
+ − 1187 break ;
+ − 1188
+ − 1189 case 'd': /* down */
+ − 1190 case 'D':
+ − 1191 if( ++idx >= nc )
+ − 1192 idx = 0 ;
+ − 1193 newhl = tw->composite.children[idx] ;
+ − 1194 break ;
+ − 1195
+ − 1196 case 'h':
+ − 1197 case 'H':
+ − 1198 newhl = tw->composite.children[0] ;
+ − 1199 break ;
+ − 1200
+ − 1201 case 'e':
+ − 1202 case 'E':
+ − 1203 newhl = tw->composite.children[nc-1] ;
+ − 1204 break ;
432
+ − 1205
+ − 1206 default:
+ − 1207 newhl = tw->tabs.hilight ;
+ − 1208 break ;
428
+ − 1209 }
+ − 1210 }
+ − 1211
+ − 1212 XawTabsSetHighlight(w, newhl) ;
+ − 1213 }
+ − 1214
+ − 1215
+ − 1216
+ − 1217 static void
+ − 1218 TabsUnhighlight(Widget w, XEvent *event, String *params, Cardinal *num_params)
+ − 1219 {
+ − 1220 TabsWidget tw = (TabsWidget) w ;
+ − 1221 int nc = tw->composite.num_children ;
+ − 1222
+ − 1223 if( nc <= 0 )
+ − 1224 return ;
+ − 1225
+ − 1226 if( tw->tabs.hilight != NULL )
+ − 1227 DrawHighlight(tw, tw->tabs.hilight, True) ;
+ − 1228 }
+ − 1229
+ − 1230
+ − 1231
+ − 1232
+ − 1233
+ − 1234 /****************************************************************
+ − 1235 *
+ − 1236 * Public Procedures
+ − 1237 *
+ − 1238 ****************************************************************/
+ − 1239
+ − 1240
+ − 1241 /* Set the top tab, optionally call all callbacks. */
+ − 1242 void
+ − 1243 XawTabsSetTop(Widget w, Bool callCallbacks)
+ − 1244 {
+ − 1245 TabsWidget tw = (TabsWidget)w->core.parent ;
+ − 1246 TabsConstraints tab ;
+ − 1247 Widget oldtop = tw->tabs.topWidget ;
+ − 1248
+ − 1249 if( !XtIsSubclass(w->core.parent, tabsWidgetClass) )
+ − 1250 {
434
+ − 1251 char line[256] ;
+ − 1252 sprintf(line, "XawTabsSetTop: widget \"%.64s\" is not the child of a tabs widget.", XtName(w)) ;
428
+ − 1253 XtAppWarning(XtWidgetToApplicationContext(w), line) ;
+ − 1254 return ;
+ − 1255 }
+ − 1256
+ − 1257 if( callCallbacks )
+ − 1258 XtCallCallbackList(w, tw->tabs.popdownCallbacks,
434
+ − 1259 (XtPointer)tw->tabs.topWidget) ;
428
+ − 1260
+ − 1261 if( !XtIsRealized(w) ) {
+ − 1262 tw->tabs.topWidget = w ;
+ − 1263 tw->tabs.needs_layout = True ;
440
+ − 1264 tw->tabs.hilight = NULL; /* The highlight tab might disappear. */
428
+ − 1265 return ;
+ − 1266 }
+ − 1267
+ − 1268 XRaiseWindow(XtDisplay(w), XtWindow(w)) ;
+ − 1269 #ifdef NEED_MOTIF
+ − 1270 XtVaSetValues(oldtop, XmNtraversalOn, False, 0) ;
+ − 1271 XtVaSetValues(w, XmNtraversalOn, True, 0) ;
+ − 1272 #endif
+ − 1273
+ − 1274 tab = (TabsConstraints) w->core.constraints ;
440
+ − 1275
+ − 1276 /* Unhighlight before we start messing with the stacking order. */
+ − 1277 if( tw->tabs.hilight != NULL )
+ − 1278 {
+ − 1279 DrawHighlight(tw, tw->tabs.hilight, True) ;
+ − 1280 tw->tabs.hilight = NULL;
+ − 1281 }
+ − 1282
428
+ − 1283 if( tab->tabs.row == 0 )
+ − 1284 {
+ − 1285 /* Easy case; undraw current top, undraw new top, assign new
+ − 1286 * top, redraw all borders.
+ − 1287 * We *could* just erase and execute a full redraw, but I like to
+ − 1288 * reduce screen flicker.
+ − 1289 */
+ − 1290 UndrawTab(tw, oldtop) ; /* undraw old */
+ − 1291 DrawBorder(tw, oldtop, True) ;
+ − 1292 UndrawTab(tw, w) ; /* undraw new */
+ − 1293 DrawBorder(tw, w, True) ;
+ − 1294 tw->tabs.topWidget = w ;
+ − 1295 DrawTab(tw, oldtop, True) ; /* redraw old */
+ − 1296 DrawTab(tw, w, True) ; /* redraw new */
+ − 1297 DrawTabs(tw, False) ;
+ − 1298 }
+ − 1299 else
+ − 1300 {
+ − 1301 tw->tabs.topWidget = w ;
+ − 1302 TabsShuffleRows(tw) ;
+ − 1303 XClearWindow(XtDisplay((Widget)tw), XtWindow((Widget)tw)) ;
+ − 1304 XtClass(tw)->core_class.expose((Widget)tw,NULL,None) ;
+ − 1305 }
+ − 1306
+ − 1307 XawTabsSetHighlight((Widget)tw, w) ;
+ − 1308
+ − 1309 if( callCallbacks )
+ − 1310 XtCallCallbackList(w, tw->tabs.callbacks, (XtPointer)w) ;
+ − 1311 }
+ − 1312
+ − 1313
+ − 1314 /* Set the top tab, optionally call all callbacks. */
+ − 1315 void
+ − 1316 XawTabsSetHighlight(Widget t, Widget w)
+ − 1317 {
+ − 1318 TabsWidget tw = (TabsWidget)t ;
+ − 1319
+ − 1320 if( !XtIsSubclass(t, tabsWidgetClass) )
+ − 1321 return ;
+ − 1322
+ − 1323 if( XtIsRealized(t) && w != tw->tabs.hilight )
+ − 1324 {
+ − 1325 if( w != NULL )
+ − 1326 DrawHighlight(tw, w, False) ;
+ − 1327 }
+ − 1328
+ − 1329 tw->tabs.hilight = w ;
+ − 1330 }
+ − 1331
+ − 1332
+ − 1333
+ − 1334
+ − 1335 /****************************************************************
+ − 1336 *
+ − 1337 * Private Procedures
+ − 1338 *
+ − 1339 ****************************************************************/
+ − 1340
+ − 1341
+ − 1342 static void
+ − 1343 TabsAllocGCs(TabsWidget tw)
+ − 1344 {
+ − 1345 TabsAllocFgGC(tw) ;
+ − 1346 TabsAllocGreyGC(tw) ;
+ − 1347 tw->tabs.backgroundGC = AllocBackgroundGC((Widget)tw, None) ;
+ − 1348 tw->tabs.topGC = AllocTopShadowGC((Widget)tw,
+ − 1349 tw->tabs.top_shadow_contrast, tw->tabs.be_nice_to_cmap) ;
+ − 1350 tw->tabs.botGC = AllocBotShadowGC((Widget)tw,
+ − 1351 tw->tabs.bot_shadow_contrast, tw->tabs.be_nice_to_cmap) ;
+ − 1352 }
+ − 1353
+ − 1354
+ − 1355 static void
+ − 1356 TabsFreeGCs(TabsWidget tw)
+ − 1357 {
+ − 1358 Widget w = (Widget) tw;
+ − 1359
+ − 1360 XtReleaseGC(w, tw->tabs.foregroundGC) ;
+ − 1361 XtReleaseGC(w, tw->tabs.greyGC) ;
+ − 1362 XtReleaseGC(w, tw->tabs.backgroundGC) ;
+ − 1363 XtReleaseGC(w, tw->tabs.topGC) ;
+ − 1364 XtReleaseGC(w, tw->tabs.botGC) ;
+ − 1365 #ifdef HAVE_XMU
+ − 1366 XmuReleaseStippledPixmap(XtScreen(w), tw->tabs.grey50) ;
+ − 1367 #endif
+ − 1368 }
+ − 1369
+ − 1370
+ − 1371
+ − 1372
+ − 1373
+ − 1374 /* Redraw entire Tabs widget */
+ − 1375
+ − 1376 static void
+ − 1377 DrawTabs(TabsWidget tw, Bool labels)
+ − 1378 {
+ − 1379 Widget *childP ;
+ − 1380 int i,j ;
+ − 1381 Dimension s = SHADWID ;
+ − 1382 Dimension th = tw->tabs.tab_height ;
+ − 1383 Position y ;
+ − 1384 TabsConstraints tab ;
+ − 1385
+ − 1386 if( !XtIsRealized((Widget)tw))
+ − 1387 return ;
442
+ − 1388
428
+ − 1389 /* draw tabs and frames by row except for the top tab, which
+ − 1390 * is drawn last. (This is inefficiently written, but should not
+ − 1391 * be too slow as long as there are not a lot of rows.)
+ − 1392 */
+ − 1393
+ − 1394 y = tw->tabs.numRows == 1 ? TABDELTA : 0 ;
+ − 1395 for(i=0; i<tw->tabs.numRows; ++i, y += th)
+ − 1396 {
446
+ − 1397 for( j=TabsNumChildren (tw), childP=tw->composite.children;
428
+ − 1398 --j >= 0; ++childP )
446
+ − 1399 if( TabVisible(*childP) )
428
+ − 1400 {
+ − 1401 tab = (TabsConstraints)(*childP)->core.constraints;
+ − 1402 if( tab->tabs.row == i && *childP != tw->tabs.topWidget )
+ − 1403 DrawTab(tw, *childP, labels) ;
+ − 1404 }
+ − 1405 if( i != tw->tabs.numRows -1 )
+ − 1406 DrawTrim(tw, 0,y+th, tw->core.width, th+s, False,False) ;
+ − 1407 }
+ − 1408
+ − 1409 DrawFrame(tw) ;
+ − 1410
+ − 1411 /* and now the top tab */
+ − 1412 if( tw->tabs.topWidget != NULL )
+ − 1413 DrawTab(tw, tw->tabs.topWidget, labels) ;
+ − 1414 }
+ − 1415
+ − 1416
+ − 1417
+ − 1418 /* Draw one tab. Corners are rounded very slightly. */
+ − 1419
+ − 1420 static void
+ − 1421 DrawTab(TabsWidget tw, Widget child, Bool labels)
+ − 1422 {
+ − 1423 GC gc ;
+ − 1424 int x,y ;
+ − 1425
+ − 1426 if( !XtIsRealized((Widget)tw))
+ − 1427 return ;
+ − 1428
+ − 1429 DrawBorder(tw, child, False) ;
+ − 1430
+ − 1431 if( labels )
+ − 1432 {
+ − 1433 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1434 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1435 Window win = XtWindow((Widget)tw) ;
+ − 1436 String lbl = tab->tabs.label != NULL ?
+ − 1437 tab->tabs.label : XtName(child) ;
+ − 1438
+ − 1439 if( XtIsSensitive(child) )
+ − 1440 {
+ − 1441 gc = tw->tabs.foregroundGC ;
+ − 1442 XSetForeground(dpy, gc, tab->tabs.foreground) ;
+ − 1443 }
+ − 1444 else
+ − 1445 {
+ − 1446 /* grey pixel allocation deferred until now */
+ − 1447 if( !tab->tabs.greyAlloc )
+ − 1448 {
+ − 1449 if( tw->tabs.be_nice_to_cmap || tw->core.depth == 1 )
+ − 1450 tab->tabs.grey = tab->tabs.foreground ;
+ − 1451 else
+ − 1452 tab->tabs.grey = AllocGreyPixel((Widget)tw,
+ − 1453 tab->tabs.foreground,
+ − 1454 tw->core.background_pixel,
+ − 1455 tw->tabs.insensitive_contrast ) ;
+ − 1456 tab->tabs.greyAlloc = True ;
+ − 1457 }
+ − 1458 gc = tw->tabs.greyGC ;
+ − 1459 XSetForeground(dpy, gc, tab->tabs.grey) ;
+ − 1460 }
+ − 1461
+ − 1462 x = tab->tabs.x ;
+ − 1463 y = tab->tabs.y ;
+ − 1464 if( child == tw->tabs.topWidget )
+ − 1465 y -= TABLDELTA ;
+ − 1466
+ − 1467 if( tab->tabs.left_bitmap != None && tab->tabs.lbm_width > 0 )
+ − 1468 {
+ − 1469 if( tab->tabs.lbm_depth == 1 )
+ − 1470 XCopyPlane(dpy, tab->tabs.left_bitmap, win,gc,
434
+ − 1471 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
428
+ − 1472 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y, 1L) ;
+ − 1473 else
+ − 1474 XCopyArea(dpy, tab->tabs.left_bitmap, win,gc,
434
+ − 1475 0,0, tab->tabs.lbm_width, tab->tabs.lbm_height,
428
+ − 1476 x+tab->tabs.lbm_x, y+tab->tabs.lbm_y) ;
+ − 1477 }
+ − 1478
+ − 1479 if( lbl != NULL && tw->tabs.font != NULL )
+ − 1480 XDrawString(dpy,win,gc,
+ − 1481 x+tab->tabs.l_x, y+tab->tabs.l_y,
+ − 1482 lbl, (int)strlen(lbl)) ;
+ − 1483 }
+ − 1484
+ − 1485 if( child == tw->tabs.hilight )
+ − 1486 DrawHighlight(tw, child, False) ;
+ − 1487 }
+ − 1488
+ − 1489
+ − 1490 /* draw frame all the way around the child windows. */
+ − 1491
+ − 1492 static void
+ − 1493 DrawFrame(TabsWidget tw)
+ − 1494 {
+ − 1495 GC topgc = tw->tabs.topGC ;
+ − 1496 GC botgc = tw->tabs.botGC ;
+ − 1497 Dimension s = SHADWID ;
+ − 1498 Dimension ch = tw->tabs.child_height ;
448
+ − 1499 if (ch > 0)
+ − 1500 Draw3dBox((Widget)tw, 0,tw->tabs.tab_total,
+ − 1501 tw->core.width, ch+2*s, s, topgc, botgc) ;
+ − 1502 else
+ − 1503 {
+ − 1504 Widget w = tw->tabs.topWidget ;
+ − 1505 if (w != NULL)
+ − 1506 {
+ − 1507 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
+ − 1508 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
+ − 1509 tab->tabs.x, 2*s, s, topgc, botgc);
+ − 1510 Draw3dBox((Widget)tw, tab->tabs.x + tab->tabs.width,
+ − 1511 tw->core.height - 2*s,
+ − 1512 tw->core.width - tab->tabs.x - tab->tabs.width, 2*s, s,
+ − 1513 topgc, botgc);
+ − 1514 }
+ − 1515 else
+ − 1516 Draw3dBox((Widget)tw, 0,tw->core.height - 2*s,
+ − 1517 tw->core.width, 2*s, s, topgc, botgc) ;
+ − 1518 }
428
+ − 1519 }
+ − 1520
+ − 1521
+ − 1522 /* draw trim around a tab or underneath a row of tabs */
+ − 1523
+ − 1524 static void
+ − 1525 DrawTrim(TabsWidget tw, /* widget */
+ − 1526 int x, /* upper-left corner */
+ − 1527 int y,
+ − 1528 int wid, /* total size */
+ − 1529 int hgt,
+ − 1530 Bool bottom, /* draw bottom? */
+ − 1531 Bool undraw) /* undraw all */
+ − 1532 {
+ − 1533 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1534 Window win = XtWindow((Widget)tw) ;
+ − 1535 GC bggc = tw->tabs.backgroundGC ;
+ − 1536 GC topgc = undraw ? bggc : tw->tabs.topGC ;
+ − 1537 GC botgc = undraw ? bggc : tw->tabs.botGC ;
+ − 1538 if( bottom )
+ − 1539 XDrawLine(dpy,win,bggc, x,y+hgt-1, x+wid-1,y+hgt-1) ; /* bottom */
+ − 1540 XDrawLine(dpy,win,topgc, x,y+2, x,y+hgt-2) ; /* left */
+ − 1541 XDrawPoint(dpy,win,topgc, x+1,y+1) ; /* corner */
+ − 1542 XDrawLine(dpy,win,topgc, x+2,y, x+wid-3,y) ; /* top */
+ − 1543 XDrawLine(dpy,win,botgc, x+wid-2,y+1, x+wid-2,y+hgt-2) ; /* right */
+ − 1544 XDrawLine(dpy,win,botgc, x+wid-1,y+2, x+wid-1,y+hgt-2) ; /* right */
+ − 1545 }
+ − 1546
+ − 1547
+ − 1548 /* Draw one tab border. */
+ − 1549
+ − 1550 static void
+ − 1551 DrawBorder(TabsWidget tw, Widget child, Bool undraw)
+ − 1552 {
+ − 1553 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1554 Position x = tab->tabs.x ;
+ − 1555 Position y = tab->tabs.y ;
+ − 1556 Dimension twid = tab->tabs.width ;
+ − 1557 Dimension thgt = tw->tabs.tab_height ;
+ − 1558
+ − 1559 /* top tab requires a little special attention; it overlaps
+ − 1560 * neighboring tabs slightly, so the background must be cleared
+ − 1561 * in the region of the overlap to partially erase those neighbors.
+ − 1562 * TODO: is this worth doing with regions instead?
+ − 1563 */
+ − 1564 if( child == tw->tabs.topWidget )
+ − 1565 {
+ − 1566 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1567 Window win = XtWindow((Widget)tw) ;
+ − 1568 GC bggc = tw->tabs.backgroundGC ;
+ − 1569 XRectangle rects[3] ;
+ − 1570 x -= TABDELTA ;
+ − 1571 y -= TABDELTA ;
+ − 1572 twid += TABDELTA*2 ;
+ − 1573 thgt += TABDELTA ;
+ − 1574 AddRect(0, x,y+1,twid,TABDELTA) ;
+ − 1575 AddRect(1, x+1,y,TABDELTA,thgt) ;
+ − 1576 AddRect(2, x+twid-TABDELTA-1,y,TABDELTA,thgt) ;
+ − 1577 XFillRectangles(dpy,win,bggc, rects, 3) ;
+ − 1578 }
+ − 1579
+ − 1580 DrawTrim(tw, x,y,twid,thgt+1, child == tw->tabs.topWidget, undraw) ;
+ − 1581 }
+ − 1582
+ − 1583
+ − 1584 /* Draw highlight around tab that has focus */
+ − 1585
+ − 1586 static void
+ − 1587 DrawHighlight(TabsWidget tw, Widget child, Bool undraw)
+ − 1588 {
+ − 1589 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1590 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1591 Window win = XtWindow((Widget)tw) ;
+ − 1592 GC gc ;
+ − 1593 Position x = tab->tabs.x ;
+ − 1594 Position y = tab->tabs.y ;
+ − 1595 Dimension wid = tab->tabs.width ;
+ − 1596 Dimension hgt = tw->tabs.tab_height ;
+ − 1597 XPoint points[6] ;
+ − 1598
+ − 1599 /* top tab does not have a highlight */
+ − 1600
+ − 1601 if( child == tw->tabs.topWidget )
+ − 1602 return ;
+ − 1603
+ − 1604 if( undraw )
+ − 1605 gc = tw->tabs.backgroundGC ;
+ − 1606
+ − 1607 else if( XtIsSensitive(child) )
+ − 1608 {
+ − 1609 gc = tw->tabs.foregroundGC ;
+ − 1610 XSetForeground(dpy, gc, tab->tabs.foreground) ;
+ − 1611 }
+ − 1612 else
+ − 1613 {
+ − 1614 gc = tw->tabs.greyGC ;
+ − 1615 XSetForeground(dpy, gc, tab->tabs.grey) ;
+ − 1616 }
+ − 1617
+ − 1618 points[0].x = x+1 ; points[0].y = y+hgt-1 ;
+ − 1619 points[1].x = x+1 ; points[1].y = y+2 ;
+ − 1620 points[2].x = x+2 ; points[2].y = y+1 ;
+ − 1621 points[3].x = x+wid-4 ; points[3].y = y+1 ;
+ − 1622 points[4].x = x+wid-3 ; points[4].y = y+2 ;
+ − 1623 points[5].x = x+wid-3 ; points[5].y = y+hgt-1 ;
+ − 1624
+ − 1625 XDrawLines(dpy,win,gc, points,6, CoordModeOrigin) ;
+ − 1626 }
+ − 1627
+ − 1628
+ − 1629 /* Undraw one tab interior */
+ − 1630
+ − 1631 static void
+ − 1632 UndrawTab(TabsWidget tw, Widget child)
+ − 1633 {
+ − 1634 TabsConstraints tab = (TabsConstraints)child->core.constraints;
+ − 1635 Position x = tab->tabs.x ;
+ − 1636 Position y = tab->tabs.y ;
+ − 1637 Dimension twid = tab->tabs.width ;
+ − 1638 Dimension thgt = tw->tabs.tab_height ;
+ − 1639 Display *dpy = XtDisplay((Widget)tw) ;
+ − 1640 Window win = XtWindow((Widget)tw) ;
+ − 1641 GC bggc = tw->tabs.backgroundGC ;
+ − 1642
+ − 1643 XFillRectangle(dpy,win,bggc, x,y, twid,thgt) ;
+ − 1644 }
+ − 1645
+ − 1646
+ − 1647
+ − 1648
+ − 1649
+ − 1650 /* GEOMETRY UTILITIES */
+ − 1651
434
+ − 1652 /* Overview:
+ − 1653 *
+ − 1654 * MaxChild(): ask all children (except possibly one) their
+ − 1655 * preferred sizes, set max_cw, max_ch accordingly.
+ − 1656 *
+ − 1657 * GetPreferredSizes(): ask all children their preferred sizes,
+ − 1658 * set max_cw, max_ch accordingly.
+ − 1659 *
+ − 1660 * PreferredSize(): given max_cw, max_ch, return tabs widget
+ − 1661 * preferred size. Iterate with other widths in order to get
+ − 1662 * a reasonable aspect ratio.
+ − 1663 *
+ − 1664 * PreferredSize2(): Given child dimensions, return Tabs
+ − 1665 * widget dimensions.
+ − 1666 *
+ − 1667 * PreferredSize3(): Same, except given child dimensions plus
+ − 1668 * shadow.
+ − 1669 */
428
+ − 1670
434
+ − 1671
+ − 1672 /* Compute the width of one child's tab. Positions will be computed
428
+ − 1673 * elsewhere.
+ − 1674 *
+ − 1675 * height: font height + vertical_space*2 + shadowWid*2
+ − 1676 * width: string width + horizontal_space*2 + shadowWid*2
+ − 1677 *
+ − 1678 * All tabs are the same height, so that is computed elsewhere.
+ − 1679 */
+ − 1680
+ − 1681 static void
+ − 1682 TabWidth(Widget w)
+ − 1683 {
+ − 1684 TabsConstraints tab = (TabsConstraints) w->core.constraints ;
+ − 1685 TabsWidget tw = (TabsWidget)XtParent(w) ;
+ − 1686 String lbl = tab->tabs.label != NULL ?
+ − 1687 tab->tabs.label : XtName(w) ;
+ − 1688 XFontStruct *font = tw->tabs.font ;
+ − 1689 int iw = tw->tabs.internalWidth ;
+ − 1690
+ − 1691 tab->tabs.width = iw + SHADWID*2 ;
+ − 1692 tab->tabs.l_x = tab->tabs.lbm_x = SHADWID + iw ;
+ − 1693
+ − 1694 if( tab->tabs.left_bitmap != None )
+ − 1695 {
+ − 1696 tab->tabs.width += tab->tabs.lbm_width + iw ;
+ − 1697 tab->tabs.l_x += tab->tabs.lbm_width + iw ;
+ − 1698 tab->tabs.lbm_y = (tw->tabs.tab_height - tab->tabs.lbm_height)/2 ;
+ − 1699 }
+ − 1700
+ − 1701 if( lbl != NULL && font != NULL )
+ − 1702 {
+ − 1703 tab->tabs.width += XTextWidth( font, lbl, (int)strlen(lbl) ) + iw ;
+ − 1704 tab->tabs.l_y = (tw->tabs.tab_height +
434
+ − 1705 tw->tabs.font->max_bounds.ascent -
428
+ − 1706 tw->tabs.font->max_bounds.descent)/2 ;
+ − 1707 }
+ − 1708 }
+ − 1709
+ − 1710
+ − 1711
+ − 1712 /* Lay out tabs to fit in given width. Compute x,y position and
+ − 1713 * row number for each tab. Return number of rows and total height
+ − 1714 * required by all tabs. If there is only one row, add TABDELTA
+ − 1715 * height to the total. Rows are assigned bottom to top.
+ − 1716 *
+ − 1717 * Tabs are indented from the edges by INDENT.
+ − 1718 *
+ − 1719 * TODO: if they require more than two rows and the total height:width
+ − 1720 * ratio is more than 2:1, then try something else.
+ − 1721 */
+ − 1722
+ − 1723 static int
448
+ − 1724 TabLayout(TabsWidget tw,
+ − 1725 Dimension wid,
+ − 1726 Dimension hgt,
+ − 1727 Dimension *reply_height, Bool query_only)
428
+ − 1728 {
446
+ − 1729 int i, row, done = 0, display_rows = 0 ;
428
+ − 1730 int num_children = tw->composite.num_children ;
+ − 1731 Widget *childP ;
+ − 1732 Dimension w ;
+ − 1733 Position x,y ;
+ − 1734 TabsConstraints tab ;
+ − 1735
+ − 1736 /* Algorithm: loop through children, assign X positions. If a tab
+ − 1737 * would extend beyond the right edge, start a new row. After all
+ − 1738 * rows are assigned, make a second pass and assign Y positions.
+ − 1739 */
+ − 1740
+ − 1741 if( num_children > 0 )
+ − 1742 {
+ − 1743 /* Loop through the tabs and see how much space they need. */
+ − 1744
+ − 1745 row = 0 ;
+ − 1746 x = INDENT ;
+ − 1747 y = 0 ;
+ − 1748 wid -= INDENT ;
+ − 1749 for(i=num_children, childP=tw->composite.children; --i >= 0; ++childP)
+ − 1750 if( XtIsManaged(*childP) )
+ − 1751 {
+ − 1752 tab = (TabsConstraints) (*childP)->core.constraints ;
+ − 1753 w = tab->tabs.width ;
446
+ − 1754
428
+ − 1755 if( x + w > wid ) { /* new row */
446
+ − 1756 if (y + tw->tabs.tab_height > hgt && !done)
+ − 1757 {
+ − 1758 display_rows = row;
+ − 1759 done = 1;
+ − 1760 }
+ − 1761 ++row;
428
+ − 1762 x = INDENT ;
+ − 1763 y += tw->tabs.tab_height ;
+ − 1764 }
+ − 1765 if( !query_only ) {
+ − 1766 tab->tabs.x = x ;
+ − 1767 tab->tabs.y = y ;
+ − 1768 tab->tabs.row = row ;
+ − 1769 }
+ − 1770 x += w + SPACING ;
446
+ − 1771 if (!query_only && !done)
+ − 1772 tab->tabs.visible = 1;
+ − 1773
428
+ − 1774 }
442
+ − 1775 /* If there was only one row, increase the height by TABDELTA */
446
+ − 1776 if( ++display_rows == 1 )
428
+ − 1777 {
446
+ − 1778 row++;
428
+ − 1779 y = TABDELTA ;
+ − 1780 if( !query_only )
+ − 1781 for(i=num_children, childP=tw->composite.children;
+ − 1782 --i >= 0 ; ++childP)
+ − 1783 if( XtIsManaged(*childP) )
+ − 1784 {
+ − 1785 tab = (TabsConstraints) (*childP)->core.constraints ;
+ − 1786 tab->tabs.y = y ;
+ − 1787 }
+ − 1788 }
+ − 1789 y += tw->tabs.tab_height ;
+ − 1790 }
+ − 1791 else
446
+ − 1792 display_rows = row = y = 0 ;
428
+ − 1793
+ − 1794 if( !query_only ) {
+ − 1795 tw->tabs.tab_total = y ;
446
+ − 1796 tw->tabs.numRows = display_rows ;
+ − 1797 tw->tabs.realRows = row;
428
+ − 1798 }
+ − 1799
+ − 1800 if( reply_height != NULL )
+ − 1801 *reply_height = y ;
+ − 1802
446
+ − 1803 return display_rows ;
428
+ − 1804 }
+ − 1805
+ − 1806
+ − 1807
+ − 1808 /* Find max preferred child size. Returned sizes include child
434
+ − 1809 * border widths.
428
+ − 1810 */
+ − 1811
+ − 1812 static void
+ − 1813 GetPreferredSizes(TabsWidget tw)
+ − 1814 {
434
+ − 1815 MaxChild(tw, NULL, 0,0) ;
428
+ − 1816 }
+ − 1817
+ − 1818
+ − 1819
+ − 1820 /* Find max preferred child size. Returned sizes include child
434
+ − 1821 * border widths. If except is non-null, don't ask that one.
+ − 1822 */
428
+ − 1823
+ − 1824 static void
434
+ − 1825 MaxChild(TabsWidget tw, Widget except, Dimension cw, Dimension ch)
428
+ − 1826 {
434
+ − 1827 int i ;
+ − 1828 Widget *childP = tw->composite.children ;
+ − 1829 XtWidgetGeometry preferred ;
428
+ − 1830
+ − 1831 for(i=tw->composite.num_children; --i >=0; ++childP)
448
+ − 1832 if( TabVisible (*childP) /*XtIsManaged(*childP)*/ && *childP != except )
428
+ − 1833 {
434
+ − 1834 (void) XtQueryGeometry(*childP, NULL, &preferred) ;
+ − 1835 cw = Max(cw, preferred.width + preferred.border_width * 2 ) ;
+ − 1836 ch = Max(ch, preferred.height + preferred.border_width * 2 ) ;
428
+ − 1837 }
+ − 1838
+ − 1839 tw->tabs.max_cw = cw ;
+ − 1840 tw->tabs.max_ch = ch ;
+ − 1841 }
+ − 1842
+ − 1843
+ − 1844
+ − 1845 /* rotate row numbers to bring current widget to bottom row,
+ − 1846 * compute y positions for all tabs
+ − 1847 */
+ − 1848
+ − 1849 static void
+ − 1850 TabsShuffleRows(TabsWidget tw)
+ − 1851 {
+ − 1852 TabsConstraints tab ;
+ − 1853 int move ;
446
+ − 1854 int real_rows, display_rows ;
428
+ − 1855 Widget *childP ;
+ − 1856 Dimension th = tw->tabs.tab_height ;
+ − 1857 Position bottom ;
+ − 1858 int i ;
+ − 1859
+ − 1860 /* There must be a top widget. If not, assign one. */
+ − 1861 if( tw->tabs.topWidget == NULL && tw->composite.children != NULL )
446
+ − 1862 for(i=TabsNumChildren (tw), childP=tw->composite.children;
428
+ − 1863 --i >= 0;
+ − 1864 ++childP)
+ − 1865 if( XtIsManaged(*childP) ) {
+ − 1866 tw->tabs.topWidget = *childP ;
+ − 1867 break ;
+ − 1868 }
+ − 1869
+ − 1870 if( tw->tabs.topWidget != NULL )
+ − 1871 {
446
+ − 1872 display_rows = tw->tabs.numRows ;
+ − 1873 real_rows = tw->tabs.realRows ;
448
+ − 1874 assert( display_rows <= real_rows ) ;
428
+ − 1875
446
+ − 1876 if( real_rows > 1 )
428
+ − 1877 {
+ − 1878 tab = (TabsConstraints) tw->tabs.topWidget->core.constraints ;
+ − 1879 assert( tab != NULL ) ;
+ − 1880
446
+ − 1881 /* How far to move top row. The selected tab must be on
+ − 1882 the bottom row of the *visible* rows. */
+ − 1883 move = (real_rows + 1 - display_rows) - tab->tabs.row ;
+ − 1884 if (move < 0)
+ − 1885 move = real_rows - move;
428
+ − 1886 bottom = tw->tabs.tab_total - th ;
+ − 1887
446
+ − 1888 for(i=tw->composite.num_children, childP=tw->composite.children;
428
+ − 1889 --i >= 0;
+ − 1890 ++childP)
+ − 1891 if( XtIsManaged(*childP) )
+ − 1892 {
+ − 1893 tab = (TabsConstraints) (*childP)->core.constraints ;
446
+ − 1894 tab->tabs.row = (tab->tabs.row + move) % real_rows ;
428
+ − 1895 tab->tabs.y = bottom - tab->tabs.row * th ;
446
+ − 1896 tab->tabs.visible = (tab->tabs.row < display_rows);
428
+ − 1897 }
+ − 1898 }
+ − 1899 }
+ − 1900 }
+ − 1901
+ − 1902
434
+ − 1903 /* Find preferred size. Ask children, find size of largest,
428
+ − 1904 * add room for tabs & return. This can get a little involved,
+ − 1905 * as we don't want to have too many rows of tabs; we may widen
+ − 1906 * the widget to reduce # of rows.
434
+ − 1907 *
+ − 1908 * This function requires that max_cw, max_ch already be set.
428
+ − 1909 */
+ − 1910 static int
+ − 1911 PreferredSize(
+ − 1912 TabsWidget tw,
+ − 1913 Dimension *reply_width, /* total widget size */
+ − 1914 Dimension *reply_height,
+ − 1915 Dimension *reply_cw, /* child widget size */
+ − 1916 Dimension *reply_ch)
+ − 1917 {
+ − 1918 Dimension cw,ch ; /* child width, height */
+ − 1919 Dimension wid,hgt ;
+ − 1920 Dimension rwid,rhgt ;
+ − 1921 int nrow ;
+ − 1922
+ − 1923 wid = cw = tw->tabs.max_cw ;
+ − 1924 hgt = ch = tw->tabs.max_ch ;
+ − 1925
+ − 1926 nrow = PreferredSize2(tw, wid,hgt, &rwid, &rhgt) ;
+ − 1927
+ − 1928 /* Check for absurd results (more than 2 rows, high aspect
+ − 1929 * ratio). Try wider size if needed.
+ − 1930 * TODO: make sure this terminates.
+ − 1931 */
+ − 1932
+ − 1933 if( nrow > 2 && rhgt > rwid )
+ − 1934 {
+ − 1935 Dimension w0, w1 ;
434
+ − 1936 int maxloop = 20 ;
428
+ − 1937
+ − 1938 /* step 1: start doubling size until it's too big */
+ − 1939 do {
+ − 1940 w0 = wid ;
+ − 1941 wid = Max(wid*2, wid+20) ;
+ − 1942 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
+ − 1943 } while( nrow > 2 && rhgt > rwid ) ;
+ − 1944 w1 = wid ;
+ − 1945
+ − 1946 /* step 2: use Newton's method to find ideal size. Stop within
+ − 1947 * 8 pixels.
+ − 1948 */
434
+ − 1949 while( --maxloop > 0 && w1 > w0 + 8 )
428
+ − 1950 {
+ − 1951 wid = (w0+w1)/2 ;
+ − 1952 nrow = PreferredSize2(tw, wid,hgt, &rwid,&rhgt) ;
+ − 1953 if( nrow > 2 && rhgt > rwid )
+ − 1954 w0 = wid ;
+ − 1955 else
+ − 1956 w1 = wid ;
+ − 1957 }
+ − 1958 wid = w1 ;
+ − 1959 }
+ − 1960
+ − 1961 *reply_width = rwid ;
+ − 1962 *reply_height = rhgt ;
+ − 1963 if( reply_cw != NULL ) *reply_cw = cw ;
+ − 1964 if( reply_ch != NULL ) *reply_ch = ch ;
+ − 1965 return nrow ;
+ − 1966 }
+ − 1967
+ − 1968
+ − 1969 /* Find preferred size, given size of children. */
+ − 1970
+ − 1971 static int
+ − 1972 PreferredSize2(
+ − 1973 TabsWidget tw,
448
+ − 1974 Dimension cw, /* child width, height */
+ − 1975 Dimension ch,
428
+ − 1976 Dimension *reply_width, /* total widget size */
+ − 1977 Dimension *reply_height)
+ − 1978 {
+ − 1979 Dimension s = SHADWID ;
448
+ − 1980 int ret;
428
+ − 1981
+ − 1982 /* make room for shadow frame */
+ − 1983 cw += s*2 ;
+ − 1984 ch += s*2 ;
+ − 1985
448
+ − 1986 ret = PreferredSize3(tw, cw, ch, reply_width, reply_height) ;
+ − 1987
+ − 1988 assert (*reply_width > 0 && *reply_height > 0);
+ − 1989 return ret;
428
+ − 1990 }
+ − 1991
+ − 1992
+ − 1993 /* Find preferred size, given size of children+shadow. */
+ − 1994
+ − 1995 static int
+ − 1996 PreferredSize3(
+ − 1997 TabsWidget tw,
448
+ − 1998 Dimension wid, /* child width, height */
+ − 1999 Dimension hgt,
428
+ − 2000 Dimension *reply_width, /* total widget size */
+ − 2001 Dimension *reply_height)
+ − 2002 {
+ − 2003 Dimension th ; /* space used by tabs */
+ − 2004 int nrows ;
+ − 2005
+ − 2006 if( tw->composite.num_children > 0 )
+ − 2007 nrows = TabLayout(tw, wid, hgt, &th, True) ;
+ − 2008 else {
+ − 2009 th = 0 ;
+ − 2010 nrows = 0 ;
+ − 2011 }
+ − 2012
+ − 2013 *reply_width = Max(wid, MIN_WID) ;
+ − 2014 *reply_height = Max(th+hgt, MIN_HGT) ;
+ − 2015
+ − 2016 return nrows ;
+ − 2017 }
+ − 2018
+ − 2019
+ − 2020 static void
+ − 2021 MakeSizeRequest(TabsWidget tw)
+ − 2022 {
+ − 2023 Widget w = (Widget)tw ;
+ − 2024 XtWidgetGeometry request, reply ;
+ − 2025 XtGeometryResult result ;
+ − 2026 Dimension cw,ch ;
+ − 2027
+ − 2028 request.request_mode = CWWidth | CWHeight ;
+ − 2029 PreferredSize(tw, &request.width, &request.height, &cw, &ch) ;
+ − 2030
+ − 2031 if( request.width == tw->core.width &&
+ − 2032 request.height == tw->core.height )
+ − 2033 return ;
+ − 2034
+ − 2035 result = XtMakeGeometryRequest(w, &request, &reply) ;
+ − 2036
+ − 2037 if( result == XtGeometryAlmost )
+ − 2038 {
+ − 2039 /* Bugger. Didn't get what we want, but were offered a
+ − 2040 * compromise. If the width was too small, recompute
+ − 2041 * based on the too-small width and try again.
+ − 2042 * If the height was too small, make a wild-ass guess
+ − 2043 * at a wider width and try again.
+ − 2044 */
+ − 2045
+ − 2046 if( reply.width < request.width && reply.height >= request.height )
+ − 2047 {
+ − 2048 Dimension s = SHADWID ;
+ − 2049 ch += s*2 ;
+ − 2050 PreferredSize3(tw, reply.width,ch, &request.width, &request.height);
+ − 2051 result = XtMakeGeometryRequest(w, &request, &reply) ;
+ − 2052 if( result == XtGeometryAlmost )
+ − 2053 (void) XtMakeGeometryRequest(w, &reply, NULL) ;
+ − 2054 }
+ − 2055
+ − 2056 else
+ − 2057 (void) XtMakeGeometryRequest(w, &reply, NULL) ;
+ − 2058 }
+ − 2059 }
+ − 2060
+ − 2061
+ − 2062 static void
+ − 2063 getBitmapInfo(TabsWidget tw, TabsConstraints tab)
+ − 2064 {
+ − 2065 Window root ;
+ − 2066 int x,y ;
+ − 2067 unsigned int bw ;
+ − 2068
+ − 2069 if( tab->tabs.left_bitmap == None ||
+ − 2070 !XGetGeometry(XtDisplay(tw), tab->tabs.left_bitmap, &root, &x, &y,
434
+ − 2071 &tab->tabs.lbm_width, &tab->tabs.lbm_height,
428
+ − 2072 &bw, &tab->tabs.lbm_depth) )
+ − 2073 tab->tabs.lbm_width = tab->tabs.lbm_height = 0 ;
+ − 2074 }
+ − 2075
+ − 2076
+ − 2077
+ − 2078
+ − 2079 /* Code copied & modified from Gcs.c. This version has dynamic
+ − 2080 * foreground.
+ − 2081 */
+ − 2082
+ − 2083 static void
+ − 2084 TabsAllocFgGC(TabsWidget tw)
+ − 2085 {
+ − 2086 Widget w = (Widget) tw;
+ − 2087 XGCValues values ;
+ − 2088
+ − 2089 values.background = tw->core.background_pixel ;
+ − 2090 values.font = tw->tabs.font->fid ;
+ − 2091 values.line_style = LineOnOffDash ;
+ − 2092 values.line_style = LineSolid ;
+ − 2093
+ − 2094 tw->tabs.foregroundGC =
+ − 2095 XtAllocateGC(w, w->core.depth,
+ − 2096 GCBackground|GCFont|GCLineStyle, &values,
+ − 2097 GCForeground,
+ − 2098 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2099 GCDashList|GCArcMode) ;
+ − 2100 }
+ − 2101
+ − 2102 static void
+ − 2103 TabsAllocGreyGC(TabsWidget tw)
+ − 2104 {
+ − 2105 Widget w = (Widget) tw;
+ − 2106 XGCValues values ;
+ − 2107
+ − 2108 values.background = tw->core.background_pixel ;
+ − 2109 values.font = tw->tabs.font->fid ;
+ − 2110 #ifdef HAVE_XMU
+ − 2111 if( tw->tabs.be_nice_to_cmap || w->core.depth == 1)
+ − 2112 {
+ − 2113 values.fill_style = FillStippled ;
+ − 2114 tw->tabs.grey50 =
+ − 2115 values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ;
+ − 2116
+ − 2117 tw->tabs.greyGC =
+ − 2118 XtAllocateGC(w, w->core.depth,
+ − 2119 GCBackground|GCFont|GCStipple|GCFillStyle, &values,
+ − 2120 GCForeground,
+ − 2121 GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2122 GCDashList|GCArcMode) ;
+ − 2123 }
+ − 2124 else
+ − 2125 #endif
+ − 2126 {
+ − 2127 tw->tabs.greyGC =
+ − 2128 XtAllocateGC(w, w->core.depth,
+ − 2129 GCFont, &values,
+ − 2130 GCForeground,
+ − 2131 GCBackground|GCSubwindowMode|GCGraphicsExposures|GCDashOffset|
+ − 2132 GCDashList|GCArcMode) ;
+ − 2133 }
+ − 2134 }