1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 /* 10 * 11 * (C) 2002,2005 by Marcin Dalecki <[email protected]> 12 * 13 * MARCIN DALECKI ASSUMES NO RESPONSIBILITY FOR THE USE OR INABILITY TO USE ANY 14 * OF THIS SOFTWARE . THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 15 * KIND, AND MARCIN DALECKI EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES, 16 * INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 * FITNESS FOR A PARTICULAR PURPOSE. 18 */ 19 20 /* 21 * Enhanced Motif PushButton widget with move over behavior. 22 */ 23 24 #include "vim.h" 25 26 #ifdef FEAT_TOOLBAR 27 28 #include <Xm/XmP.h> 29 #include <Xm/DrawP.h> 30 #if defined(HAVE_XM_TRAITP_H) && defined(HAVE_XM_MANAGER_H) \ 31 && defined(HAVE_XM_UNHIGHLIGHTT_H) && defined(HAVE_XM_XPMP_H) 32 # include <Xm/TraitP.h> 33 # include <Xm/Manager.h> 34 # include <Xm/UnhighlightT.h> 35 # include <Xm/XpmP.h> 36 # define UNHIGHLIGHTT 37 #else 38 # include <X11/xpm.h> 39 #endif 40 #include <Xm/ManagerP.h> 41 #include <Xm/Display.h> 42 #include <Xm/DisplayP.h> 43 44 #include <X11/Shell.h> 45 #include <X11/ShellP.h> 46 47 #include "gui_xmebwp.h" 48 49 /* Provide some missing wrappers, which are missed from the LessTif 50 * implementation. Also missing in Motif 1.2 and earlier. 51 * 52 * We neither use XmeGetPixmapData or _XmGetPixmapData, since with LessTif the 53 * pixmap will not appear in it's caches properly. We cache the interesting 54 * values in XmEnhancedButtonPart instead ourself. 55 */ 56 #if defined(LESSTIF_VERSION) || (XmVersion <= 1002) 57 # ifndef Lab_IsMenupane 58 # define Lab_IsMenupane(w) (Lab_MenuType(w) == (int)XmMENU_POPUP || \ 59 Lab_MenuType(w) == (int)XmMENU_PULLDOWN) 60 # endif 61 # define XmeClearBorder _XmClearBorder 62 # define XmeDrawShadows _XmDrawShadows 63 # define XmeDrawHighlight(a, b, c, d, e, f, g, h) \ 64 _XmDrawHighlight(a, b, c, d, e, f, g, h, LineSolid) 65 #endif 66 67 /* 68 * Motif internals we have to cheat around with. 69 */ 70 71 /* Hopefully this will never change... */ 72 #ifndef XmFOCUS_IGNORE 73 # define XmFOCUS_IGNORE 1<<1 74 #endif 75 76 extern Boolean _XmGetInDragMode(Widget widget); 77 extern void _XmPrimitiveEnter(Widget wid, 78 XEvent * event, 79 String * params, Cardinal * num_params); 80 extern void _XmPrimitiveLeave(Widget wid, 81 XEvent * event, 82 String * params, Cardinal * num_params); 83 extern void _XmSetFocusFlag(Widget w, unsigned int mask, Boolean value); 84 extern void _XmCalcLabelDimensions(Widget wid); 85 86 /* 87 * Declaration of class methods. 88 */ 89 static void Destroy(Widget w); 90 static void Initialize(Widget rq, Widget eb, ArgList args, Cardinal *n); 91 static Boolean SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *n); 92 static void Redisplay(Widget, XEvent *, Region); 93 94 /* 95 * Declaration of action methods. 96 */ 97 static void Enter(Widget, XEvent *, String *, Cardinal *); 98 static void Leave(Widget, XEvent *, String *, Cardinal *); 99 static void BorderHighlight(Widget); 100 static void BorderUnhighlight(Widget); 101 102 /* 103 * 4 x 4 stipple for desensitized widgets 104 */ 105 #define stipple_width 4 106 #define stipple_height 4 107 static char stipple_bits[] = { 0x0a, 0x05, 0x0a, 0x05 }; 108 #define STIPPLE_BITMAP xmEnhancedButtonClassRec.enhancedbutton_class.stipple_bitmap 109 110 /* 111 * Override actions. 112 */ 113 static XtActionsRec actionsList[] = 114 { 115 {"Enter", Enter}, 116 {"Leave", Leave}, 117 }; 118 119 static XtResource resources[] = 120 { 121 { 122 XmNpixmapData, XmCPixmap, XmRString, sizeof(String), 123 XtOffsetOf(XmEnhancedButtonRec, enhancedbutton.pixmap_data), 124 XmRImmediate, (XtPointer) NULL 125 }, { 126 XmNpixmapFile, XmCPixmap, XmRString, sizeof(String), 127 XtOffsetOf(XmEnhancedButtonRec, enhancedbutton.pixmap_file), 128 XmRImmediate, (XtPointer) NULL 129 }, { 130 XmNspacing, XmCSpacing, XmRHorizontalDimension, sizeof(Dimension), 131 XtOffsetOf(XmEnhancedButtonRec, enhancedbutton.spacing), 132 XmRImmediate, (XtPointer) 2 133 }, 134 { 135 XmNlabelLocation, XmCLocation, XmRInt, sizeof(int), 136 XtOffsetOf(XmEnhancedButtonRec, enhancedbutton.label_location), 137 XtRImmediate, (XtPointer) XmRIGHT 138 } 139 }; 140 141 /* This is needed to work around a bug in Lesstif 2, leaving the extension 142 * NULL somehow results in getting it set to an invalid pointer. */ 143 XmPrimitiveClassExtRec xmEnhancedButtonPrimClassExtRec = 144 { 145 /* next_extension */ NULL, 146 /* record_type */ NULLQUARK, 147 /* version */ XmPrimitiveClassExtVersion, 148 /* record_size */ sizeof(XmPrimitiveClassExtRec), 149 /* widget_baseline */ XmInheritBaselineProc, 150 /* widget_display_rect */ XmInheritDisplayRectProc, 151 /* widget_margins */ NULL 152 }; 153 154 XmEnhancedButtonClassRec xmEnhancedButtonClassRec = 155 { 156 { 157 /* core_class fields */ 158 /* superclass */ (WidgetClass) & xmPushButtonClassRec, 159 /* class_name */ "XmEnhancedButton", 160 /* widget_size */ sizeof(XmEnhancedButtonRec), 161 /* class_initialize */ NULL, 162 /* class_part_initialize */ NULL, 163 /* class_inited */ False, 164 /* initialize */ Initialize, 165 /* initialize_hook */ NULL, 166 /* realize */ XtInheritRealize, 167 /* actions */ actionsList, 168 /* num_actions */ XtNumber(actionsList), 169 /* resources */ resources, 170 /* num_resources */ XtNumber(resources), 171 /* xrm_class */ NULLQUARK, 172 /* compress_motion */ True, 173 /* compress_exposure */ XtExposeCompressMaximal, 174 /* compress_enterleave */ True, 175 /* visible_interest */ False, 176 /* destroy */ Destroy, 177 /* resize */ XtInheritResize, 178 /* expose */ Redisplay, 179 /* set_values */ SetValues, 180 /* set_values_hook */ NULL, 181 /* set_values_almost */ XtInheritSetValuesAlmost, 182 /* get_values_hook */ NULL, 183 /* accept_focus */ XtInheritAcceptFocus, 184 /* version */ XtVersion, 185 /* callback_private */ NULL, 186 /* tm_table */ NULL, 187 /* query_geometry */ NULL, 188 /* display_accelerator */ XtInheritDisplayAccelerator, 189 /* extension */ NULL 190 }, 191 192 /* primitive_class fields */ 193 { 194 /* border highlight */ BorderHighlight, 195 /* border_unhighlight */ BorderUnhighlight, 196 /* translations */ XtInheritTranslations, 197 /* arm and activate */ XmInheritArmAndActivate, 198 /* synthetic resources */ NULL, 199 /* number of syn res */ 0, 200 /* extension */ (XtPointer)&xmEnhancedButtonPrimClassExtRec, 201 }, 202 203 /* label_class fields */ 204 { 205 /* setOverrideCallback */ XmInheritSetOverrideCallback, 206 /* menuProcs */ XmInheritMenuProc, 207 /* translations */ XtInheritTranslations, 208 /* extension */ NULL, 209 }, 210 211 /* pushbutton_class record */ 212 { 213 /* extension */ (XtPointer) NULL, 214 }, 215 216 /* enhancedbutton_class fields */ 217 { 218 /* stipple_bitmap */ None 219 } 220 }; 221 222 223 WidgetClass xmEnhancedButtonWidgetClass = 224 (WidgetClass)&xmEnhancedButtonClassRec; 225 226 227 /* 228 * Create a slightly fainter pixmap to be shown on button entry. 229 */ 230 static unsigned short 231 bump_color(unsigned short value) 232 { 233 int tmp = 2 * (((int) value - 65535) / 3) + 65535; 234 235 return tmp; 236 } 237 238 static int 239 alloc_color(Display *display, 240 Colormap colormap, 241 char *colorname, 242 XColor *xcolor, 243 void *closure UNUSED) 244 { 245 int status; 246 247 if (colorname) 248 if (!XParseColor(display, colormap, colorname, xcolor)) 249 return -1; 250 251 xcolor->red = bump_color(xcolor->red); 252 xcolor->green = bump_color(xcolor->green); 253 xcolor->blue = bump_color(xcolor->blue); 254 255 status = XAllocColor(display, colormap, xcolor); 256 return status != 0 ? 1 : 0; 257 } 258 259 /* XPM */ 260 static char * blank_xpm[] = 261 { 262 /* width height ncolors cpp [x_hot y_hot] */ 263 "12 12 4 1 0 0", 264 /* colors */ 265 " s iconColor1 m black c #000000", 266 ". s none m none c none", 267 "X s topShadowColor m none c #DCDEE5", 268 "o s bottomShadowColor m black c #5D6069", 269 /* pixels */ 270 " ..", 271 " XXXXXXXX ..", 272 " X....... o.", 273 " X....... o.", 274 " X....... o.", 275 " X....... o.", 276 " X....... o.", 277 " X....... o.", 278 " X....... o.", 279 " o.", 280 "..ooooooooo.", 281 "............"}; 282 283 /* 284 * Set the pixmap. 285 */ 286 static void 287 set_pixmap(XmEnhancedButtonWidget eb) 288 { 289 /* Configure defines XPMATTRIBUTES_TYPE as XpmAttributes or as 290 * XpmAttributes_21, depending on what is in Xm/XpmP.h. */ 291 XPMATTRIBUTES_TYPE attr; 292 Pixmap sen_pix; 293 Window root; 294 static XpmColorSymbol color[8] = { 295 {"none", "none", 0}, 296 {"None", "none", 0}, 297 {"background", NULL, 0}, 298 {"foreground", NULL, 0}, 299 {"bottomShadowColor", NULL, 0}, 300 {"topShadowColor", NULL, 0}, 301 {"highlightColor", NULL, 0}, 302 {"armColor", NULL, 0} 303 }; 304 int scr; 305 Display *dpy = XtDisplay(eb); 306 int x; 307 int y; 308 unsigned int height, width, border, depth; 309 int status = 0; 310 Pixmap mask; 311 Pixmap pix = None; 312 Pixmap arm_pix = None; 313 Pixmap ins_pix = None; 314 Pixmap high_pix = None; 315 char **data = (char **) eb->enhancedbutton.pixmap_data; 316 char *fname = (char *) eb->enhancedbutton.pixmap_file; 317 int shift; 318 GC gc; 319 320 /* Make sure there is a default value for the pixmap. 321 */ 322 if (!data) 323 return; 324 325 gc = XtGetGC((Widget)eb, (XtGCMask)0, NULL); 326 327 scr = DefaultScreen(dpy); 328 root = RootWindow(dpy, scr); 329 330 eb->label.pixmap = None; 331 332 eb->enhancedbutton.pixmap_depth = 0; 333 eb->enhancedbutton.pixmap_width = 0; 334 eb->enhancedbutton.pixmap_height = 0; 335 eb->enhancedbutton.normal_pixmap = None; 336 eb->enhancedbutton.armed_pixmap = None; 337 eb->enhancedbutton.highlight_pixmap = None; 338 eb->enhancedbutton.insensitive_pixmap = None; 339 340 /* We use dynamic colors, get them now. */ 341 motif_get_toolbar_colors( 342 &eb->core.background_pixel, 343 &eb->primitive.foreground, 344 &eb->primitive.bottom_shadow_color, 345 &eb->primitive.top_shadow_color, 346 &eb->primitive.highlight_color); 347 348 /* Setup color substitution table. */ 349 color[0].pixel = eb->core.background_pixel; 350 color[1].pixel = eb->core.background_pixel; 351 color[2].pixel = eb->core.background_pixel; 352 color[3].pixel = eb->primitive.foreground; 353 color[4].pixel = eb->core.background_pixel; 354 color[5].pixel = eb->primitive.top_shadow_color; 355 color[6].pixel = eb->primitive.highlight_color; 356 color[7].pixel = eb->pushbutton.arm_color; 357 358 /* Create the "sensitive" pixmap. */ 359 attr.valuemask = XpmColorSymbols | XpmCloseness; 360 attr.closeness = 65535; /* accuracy isn't crucial */ 361 attr.colorsymbols = color; 362 attr.numsymbols = XtNumber(color); 363 364 if (fname) 365 status = XpmReadFileToPixmap(dpy, root, fname, &pix, &mask, &attr); 366 if (!fname || status != XpmSuccess) 367 status = XpmCreatePixmapFromData(dpy, root, data, &pix, &mask, &attr); 368 369 /* If something failed, we will fill in the default pixmap. */ 370 if (status != XpmSuccess) 371 status = XpmCreatePixmapFromData(dpy, root, blank_xpm, &pix, 372 &mask, &attr); 373 374 XpmFreeAttributes(&attr); 375 376 XGetGeometry(dpy, pix, &root, &x, &y, &width, &height, &border, &depth); 377 378 /* TODO: does the shift depend on label_location somehow? */ 379 shift = eb->primitive.shadow_thickness / 2; 380 381 if (shift < 1) 382 shift = 1; 383 384 sen_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 385 386 XSetForeground(dpy, gc, eb->core.background_pixel); 387 XFillRectangle(dpy, sen_pix, gc, 0, 0, width + shift, height + shift); 388 XSetClipMask(dpy, gc, mask); 389 XSetClipOrigin(dpy, gc, shift, shift); 390 XCopyArea(dpy, pix, sen_pix, gc, 0, 0, width, height, shift, shift); 391 392 /* Create the "highlight" pixmap. */ 393 color[4].pixel = eb->primitive.bottom_shadow_color; 394 #ifdef XpmAllocColor /* SGI doesn't have it */ 395 attr.valuemask = XpmColorSymbols | XpmCloseness | XpmAllocColor; 396 attr.alloc_color = alloc_color; 397 #else 398 attr.valuemask = XpmColorSymbols | XpmCloseness; 399 #endif 400 attr.closeness = 65535; /* accuracy isn't crucial */ 401 attr.colorsymbols = color; 402 attr.numsymbols = XtNumber(color); 403 404 status = XpmCreatePixmapFromData(dpy, root, data, &pix, NULL, &attr); 405 XpmFreeAttributes(&attr); 406 407 high_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 408 409 #if 1 410 XSetForeground(dpy, gc, eb->core.background_pixel); 411 #else 412 XSetForeground(dpy, gc, eb->primitive.top_shadow_color); 413 #endif 414 XSetClipMask(dpy, gc, None); 415 XFillRectangle(dpy, high_pix, gc, 0, 0, width + shift, height + shift); 416 XSetClipMask(dpy, gc, mask); 417 XSetClipOrigin(dpy, gc, 0, 0); 418 XCopyArea(dpy, pix, high_pix, gc, 0, 0, width, height, 0, 0); 419 420 arm_pix = XCreatePixmap(dpy, pix, width + shift, height + shift, depth); 421 422 if (eb->pushbutton.fill_on_arm) 423 XSetForeground(dpy, gc, eb->pushbutton.arm_color); 424 else 425 XSetForeground(dpy, gc, eb->core.background_pixel); 426 XSetClipOrigin(dpy, gc, shift, shift); 427 XSetClipMask(dpy, gc, None); 428 XFillRectangle(dpy, arm_pix, gc, 0, 0, width + shift, height + shift); 429 XSetClipMask(dpy, gc, mask); 430 XSetClipOrigin(dpy, gc, 2 * shift, 2 * shift); 431 XCopyArea(dpy, pix, arm_pix, gc, 0, 0, width, height, 2 * shift, 2 * shift); 432 433 XFreePixmap(dpy, pix); 434 XFreePixmap(dpy, mask); 435 436 /* Create the "insensitive" pixmap. */ 437 attr.valuemask = XpmColorSymbols | XpmCloseness | XpmColorKey; 438 attr.closeness = 65535; /* accuracy isn't crucial */ 439 attr.colorsymbols = color; 440 attr.numsymbols = sizeof(color) / sizeof(color[0]); 441 attr.color_key = XPM_MONO; 442 status = XpmCreatePixmapFromData(dpy, root, data, &pix, &mask, &attr); 443 444 /* Need to create new Pixmaps with the mask applied. */ 445 446 ins_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 447 448 XSetForeground(dpy, gc, eb->core.background_pixel); 449 XSetClipOrigin(dpy, gc, 0, 0); 450 XSetClipMask(dpy, gc, None); 451 XFillRectangle(dpy, ins_pix, gc, 0, 0, width + shift, height + shift); 452 XSetClipMask(dpy, gc, mask); 453 XSetForeground(dpy, gc, eb->primitive.top_shadow_color); 454 XSetClipOrigin(dpy, gc, 2 * shift, 2 * shift); 455 XFillRectangle(dpy, ins_pix, gc, 2 * shift, 2 * shift, width, height); 456 XSetForeground(dpy, gc, eb->primitive.bottom_shadow_color); 457 XSetClipOrigin(dpy, gc, shift, shift); 458 XFillRectangle(dpy, ins_pix, gc, 0, 0, width + shift, height + shift); 459 XtReleaseGC((Widget) eb, gc); 460 461 XpmFreeAttributes(&attr); 462 463 eb->enhancedbutton.pixmap_depth = depth; 464 eb->enhancedbutton.pixmap_width = width; 465 eb->enhancedbutton.pixmap_height = height; 466 eb->enhancedbutton.normal_pixmap = sen_pix; 467 eb->enhancedbutton.highlight_pixmap = high_pix; 468 eb->enhancedbutton.insensitive_pixmap = ins_pix; 469 eb->enhancedbutton.armed_pixmap = arm_pix; 470 471 eb->enhancedbutton.doing_setvalues = True; 472 eb->enhancedbutton.doing_setvalues = False; 473 474 XFreePixmap(dpy, pix); 475 XFreePixmap(dpy, mask); 476 } 477 478 #define BUTTON_MASK ( \ 479 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask \ 480 ) 481 482 static void 483 draw_shadows(XmEnhancedButtonWidget eb) 484 { 485 GC top_gc; 486 GC bottom_gc; 487 Boolean etched_in; 488 489 if (!eb->primitive.shadow_thickness) 490 return; 491 492 if ((eb->core.width <= 2 * eb->primitive.highlight_thickness) 493 || (eb->core.height <= 2 * eb->primitive.highlight_thickness)) 494 return; 495 496 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 497 { 498 XmDisplay dpy; 499 500 dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(eb)); 501 etched_in = dpy->display.enable_etched_in_menu; 502 } 503 #else 504 etched_in = False; 505 #endif 506 if (!etched_in ^ eb->pushbutton.armed) 507 { 508 top_gc = eb->primitive.top_shadow_GC; 509 bottom_gc = eb->primitive.bottom_shadow_GC; 510 } 511 else 512 { 513 top_gc = eb->primitive.bottom_shadow_GC; 514 bottom_gc = eb->primitive.top_shadow_GC; 515 } 516 517 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 518 top_gc, 519 bottom_gc, 520 eb->primitive.highlight_thickness, 521 eb->primitive.highlight_thickness, 522 eb->core.width - 2 * eb->primitive.highlight_thickness, 523 eb->core.height - 2 * eb->primitive.highlight_thickness, 524 eb->primitive.shadow_thickness, 525 (unsigned)(etched_in ? XmSHADOW_IN : XmSHADOW_OUT)); 526 } 527 528 static void 529 draw_highlight(XmEnhancedButtonWidget eb) 530 { 531 eb->primitive.highlighted = True; 532 eb->primitive.highlight_drawn = True; 533 534 if (!XtWidth(eb) || !XtHeight(eb) || !eb->primitive.highlight_thickness) 535 return; 536 537 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 538 eb->primitive.highlight_GC, 0, 0, 539 XtWidth(eb), XtHeight(eb), 540 eb->primitive.highlight_thickness); 541 } 542 543 static void 544 draw_unhighlight(XmEnhancedButtonWidget eb) 545 { 546 GC manager_background_GC; 547 548 eb->primitive.highlighted = False; 549 eb->primitive.highlight_drawn = False; 550 551 if (!XtWidth(eb) || !XtHeight(eb) || !eb->primitive.highlight_thickness) 552 return; 553 554 if (XmIsManager(eb->core.parent)) 555 { 556 #ifdef UNHIGHLIGHTT 557 XmSpecifyUnhighlightTrait UnhighlightT; 558 559 if (((UnhighlightT = (XmSpecifyUnhighlightTrait) XmeTraitGet((XtPointer) 560 XtClass(eb->core.parent), XmQTspecifyUnhighlight)) 561 != NULL) && (UnhighlightT->getUnhighlightGC != NULL)) 562 { 563 /* if unhighlight trait in parent use specified GC... */ 564 manager_background_GC = 565 UnhighlightT->getUnhighlightGC(eb->core.parent, (Widget) eb); 566 } 567 else 568 { 569 /* ...otherwise, use parent's background GC */ 570 manager_background_GC = ((XmManagerWidget) 571 (eb->core.parent))->manager.background_GC; 572 } 573 #else 574 manager_background_GC = ((XmManagerWidget) 575 (eb->core.parent))->manager.background_GC; 576 #endif 577 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 578 manager_background_GC, 579 0, 0, XtWidth(eb), XtHeight(eb), 580 eb->primitive.highlight_thickness); 581 if (!eb->pushbutton.armed && eb->primitive.shadow_thickness) 582 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 583 eb->primitive.highlight_thickness, 584 eb->primitive.highlight_thickness, 585 eb->core.width - 2 * eb->primitive.highlight_thickness, 586 eb->core.height - 2 * eb->primitive.highlight_thickness, 587 eb->primitive.shadow_thickness); 588 } 589 else 590 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 0, 0, XtWidth(eb), 591 XtHeight(eb), eb->primitive.highlight_thickness); 592 } 593 594 static void 595 draw_pixmap(XmEnhancedButtonWidget eb, 596 XEvent *event UNUSED, 597 Region region UNUSED) 598 { 599 Pixmap pix; 600 GC gc = eb->label.normal_GC; 601 int depth; 602 Cardinal width; 603 Cardinal height; 604 Cardinal w; 605 Cardinal h; 606 int x; 607 int y; 608 609 if (!XtIsSensitive((Widget) eb)) 610 pix = eb->enhancedbutton.insensitive_pixmap; 611 else 612 { 613 if (eb->primitive.highlighted && !eb->pushbutton.armed) 614 pix = eb->enhancedbutton.highlight_pixmap; 615 else if (eb->pushbutton.armed) 616 pix = eb->enhancedbutton.armed_pixmap; 617 else 618 pix = eb->enhancedbutton.normal_pixmap; 619 } 620 621 if (pix == None || !eb->enhancedbutton.pixmap_data) 622 return; 623 624 depth = eb->enhancedbutton.pixmap_depth; 625 w = eb->enhancedbutton.pixmap_width; 626 h = eb->enhancedbutton.pixmap_height; 627 628 gc = eb->label.normal_GC; 629 x = eb->primitive.highlight_thickness 630 + eb->primitive.shadow_thickness 631 + eb->label.margin_width; 632 y = eb->primitive.highlight_thickness 633 + eb->primitive.shadow_thickness 634 + eb->label.margin_height; 635 width = eb->core.width - 2 * x; 636 if (w < width) 637 width = w; 638 height = eb->core.height - 2 * y; 639 if (h < height) 640 height = h; 641 if (depth == (int)eb->core.depth) 642 XCopyArea(XtDisplay(eb), pix, XtWindow(eb), gc, 0, 0, 643 width, height, x, y); 644 else if (depth == 1) 645 XCopyPlane(XtDisplay(eb), pix, XtWindow(eb), gc, 0, 0, 646 width, height, x, y, (unsigned long)1); 647 } 648 649 /* 650 * Draw the label contained in the pushbutton. 651 */ 652 static void 653 draw_label(XmEnhancedButtonWidget eb, XEvent *event, Region region) 654 { 655 GC tmp_gc = NULL; 656 Boolean replaceGC = False; 657 Boolean deadjusted = False; 658 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 659 XmDisplay dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); 660 Boolean etched_in = dpy->display.enable_etched_in_menu; 661 #else 662 Boolean etched_in = False; 663 #endif 664 665 if (eb->pushbutton.armed 666 && ((!Lab_IsMenupane(eb) && eb->pushbutton.fill_on_arm) 667 || (Lab_IsMenupane(eb) && etched_in))) 668 { 669 if (eb->label.label_type == (int)XmSTRING 670 && eb->pushbutton.arm_color == eb->primitive.foreground) 671 { 672 tmp_gc = eb->label.normal_GC; 673 eb->label.normal_GC = eb->pushbutton.background_gc; 674 replaceGC = True; 675 } 676 } 677 678 /* 679 * If the button contains a labeled pixmap, we will take it instead of our 680 * own pixmap. 681 */ 682 683 if (eb->label.label_type == (int)XmPIXMAP) 684 { 685 if (eb->pushbutton.armed) 686 { 687 if (eb->pushbutton.arm_pixmap != XmUNSPECIFIED_PIXMAP) 688 eb->label.pixmap = eb->pushbutton.arm_pixmap; 689 else 690 eb->label.pixmap = eb->pushbutton.unarm_pixmap; 691 } 692 else 693 /* pushbutton is not armed */ 694 eb->label.pixmap = eb->pushbutton.unarm_pixmap; 695 } 696 697 /* 698 * Temporarily remove the Xm3D_ENHANCE_PIXEL hack ("adjustment") from the 699 * margin values, so we don't confuse Label. 700 */ 701 if (eb->pushbutton.default_button_shadow_thickness > 0) 702 { 703 deadjusted = True; 704 Lab_MarginLeft(eb) -= Xm3D_ENHANCE_PIXEL; 705 Lab_MarginRight(eb) -= Xm3D_ENHANCE_PIXEL; 706 Lab_MarginTop(eb) -= Xm3D_ENHANCE_PIXEL; 707 Lab_MarginBottom(eb) -= Xm3D_ENHANCE_PIXEL; 708 } 709 710 { 711 XtExposeProc expose; 712 713 XtProcessLock(); 714 expose = xmLabelClassRec.core_class.expose; 715 XtProcessUnlock(); 716 (*expose)((Widget) eb, event, region); 717 } 718 719 if (deadjusted) 720 { 721 Lab_MarginLeft(eb) += Xm3D_ENHANCE_PIXEL; 722 Lab_MarginRight(eb) += Xm3D_ENHANCE_PIXEL; 723 Lab_MarginTop(eb) += Xm3D_ENHANCE_PIXEL; 724 Lab_MarginBottom(eb) += Xm3D_ENHANCE_PIXEL; 725 } 726 727 if (replaceGC) 728 eb->label.normal_GC = tmp_gc; 729 } 730 731 static void 732 Enter(Widget wid, 733 XEvent *event, 734 String *params UNUSED, 735 Cardinal *num_params UNUSED) 736 { 737 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) wid; 738 XmPushButtonCallbackStruct call_value; 739 740 if (Lab_IsMenupane(eb)) 741 { 742 if ((((ShellWidget) XtParent(XtParent(eb)))->shell.popped_up) 743 && _XmGetInDragMode((Widget) eb)) 744 { 745 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 746 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); 747 Boolean etched_in = dpy->display.enable_etched_in_menu; 748 #else 749 Boolean etched_in = False; 750 #endif 751 752 if (eb->pushbutton.armed) 753 return; 754 755 /* ...so KHelp event is delivered correctly. */ 756 _XmSetFocusFlag(XtParent(XtParent(eb)), XmFOCUS_IGNORE, TRUE); 757 XtSetKeyboardFocus(XtParent(XtParent(eb)), (Widget) eb); 758 _XmSetFocusFlag(XtParent(XtParent(eb)), XmFOCUS_IGNORE, FALSE); 759 760 eb->pushbutton.armed = TRUE; 761 762 ((XmManagerWidget) XtParent(wid))->manager.active_child = wid; 763 764 /* etched in menu button */ 765 if (etched_in && !XmIsTearOffButton(eb)) 766 { 767 XFillRectangle(XtDisplay(eb), XtWindow(eb), 768 eb->pushbutton.fill_gc, 769 0, 0, eb->core.width, eb->core.height); 770 draw_label(eb, event, NULL); 771 draw_pixmap(eb, event, NULL); 772 } 773 774 if ((eb->core.width > 2 * eb->primitive.highlight_thickness) 775 && (eb->core.height > 776 2 * eb->primitive.highlight_thickness)) 777 { 778 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 779 eb->primitive.top_shadow_GC, 780 eb->primitive.bottom_shadow_GC, 781 eb->primitive.highlight_thickness, 782 eb->primitive.highlight_thickness, 783 eb->core.width - 2 * eb->primitive.highlight_thickness, 784 eb->core.height - 2 * eb->primitive.highlight_thickness, 785 eb->primitive.shadow_thickness, 786 (unsigned)(etched_in ? XmSHADOW_IN : XmSHADOW_OUT)); 787 } 788 789 if (eb->pushbutton.arm_callback) 790 { 791 XFlush(XtDisplay(eb)); 792 793 call_value.reason = (int)XmCR_ARM; 794 call_value.event = event; 795 XtCallCallbackList((Widget) eb, 796 eb->pushbutton.arm_callback, 797 &call_value); 798 } 799 } 800 } 801 else 802 { 803 XtExposeProc expose; 804 805 _XmPrimitiveEnter((Widget) eb, event, NULL, NULL); 806 if (eb->pushbutton.armed == TRUE) 807 { 808 XtProcessLock(); 809 expose = XtClass(eb)->core_class.expose; 810 XtProcessUnlock(); 811 (*expose) (wid, event, (Region) NULL); 812 } 813 814 draw_highlight(eb); 815 draw_shadows(eb); 816 draw_pixmap(eb, event, NULL); 817 } 818 } 819 820 static void 821 Leave(Widget wid, 822 XEvent *event, 823 String *params UNUSED, 824 Cardinal *num_params UNUSED) 825 { 826 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)wid; 827 XmPushButtonCallbackStruct call_value; 828 829 if (Lab_IsMenupane(eb)) 830 { 831 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 832 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); 833 Boolean etched_in = dpy->display.enable_etched_in_menu; 834 #else 835 Boolean etched_in = False; 836 #endif 837 838 if (_XmGetInDragMode((Widget)eb) 839 && eb->pushbutton.armed 840 && ( /* !ActiveTearOff || */ 841 event->xcrossing.mode == NotifyNormal)) 842 { 843 eb->pushbutton.armed = FALSE; 844 845 ((XmManagerWidget) XtParent(wid))->manager.active_child = NULL; 846 847 if (etched_in && !XmIsTearOffButton(eb)) 848 { 849 XFillRectangle(XtDisplay(eb), XtWindow(eb), 850 eb->pushbutton.background_gc, 851 0, 0, eb->core.width, eb->core.height); 852 draw_label(eb, event, NULL); 853 draw_pixmap(eb, event, NULL); 854 } 855 else 856 XmeClearBorder 857 (XtDisplay(eb), XtWindow(eb), 858 eb->primitive.highlight_thickness, 859 eb->primitive.highlight_thickness, 860 eb->core.width - 861 2 * eb->primitive.highlight_thickness, 862 eb->core.height - 863 2 * eb->primitive.highlight_thickness, 864 eb->primitive.shadow_thickness); 865 866 if (eb->pushbutton.disarm_callback) 867 { 868 XFlush(XtDisplay(eb)); 869 870 call_value.reason = (int)XmCR_DISARM; 871 call_value.event = event; 872 XtCallCallbackList((Widget) eb, 873 eb->pushbutton.disarm_callback, 874 &call_value); 875 } 876 } 877 } 878 else 879 { 880 _XmPrimitiveLeave((Widget) eb, event, NULL, NULL); 881 882 if (eb->pushbutton.armed == TRUE) 883 { 884 XtExposeProc expose; 885 eb->pushbutton.armed = FALSE; 886 XtProcessLock(); 887 expose = XtClass(eb)->core_class.expose; 888 XtProcessUnlock(); 889 (*expose) (wid, event, (Region)NULL); 890 draw_unhighlight(eb); 891 draw_pixmap(eb, event, NULL); 892 eb->pushbutton.armed = TRUE; 893 } 894 else 895 { 896 draw_unhighlight(eb); 897 draw_pixmap(eb, event, NULL); 898 } 899 } 900 } 901 902 #define IsNull(p) ((p) == XmUNSPECIFIED_PIXMAP) 903 904 static void 905 set_size(XmEnhancedButtonWidget newtb) 906 { 907 unsigned int w = 0; 908 unsigned int h = 0; 909 910 _XmCalcLabelDimensions((Widget) newtb); 911 912 /* Find out how big the pixmap is */ 913 if (newtb->enhancedbutton.pixmap_data 914 && !IsNull(newtb->label.pixmap) 915 && !IsNull(newtb->enhancedbutton.normal_pixmap)) 916 { 917 w = newtb->enhancedbutton.pixmap_width; 918 h = newtb->enhancedbutton.pixmap_height; 919 } 920 921 /* 922 * Please note that we manipulate the width only in case of push buttons 923 * not used in the context of a menu pane. 924 */ 925 if (Lab_IsMenupane(newtb)) 926 { 927 newtb->label.margin_left = w + 2 * (newtb->primitive.shadow_thickness 928 + newtb->primitive.highlight_thickness) 929 + newtb->label.margin_width; 930 } 931 else 932 { 933 newtb->label.margin_left = w; 934 newtb->core.width = w + 2 * (newtb->primitive.shadow_thickness 935 + newtb->primitive.highlight_thickness 936 + newtb->label.margin_width) 937 + newtb->label.TextRect.width; 938 939 if (newtb->label.TextRect.width > 0) 940 { 941 newtb->label.margin_left += newtb->label.margin_width 942 + newtb->primitive.shadow_thickness; 943 newtb->core.width += newtb->label.margin_width 944 + newtb->primitive.shadow_thickness; 945 } 946 } 947 if (newtb->label.TextRect.height < h) 948 { 949 newtb->core.height = h + 2 * (newtb->primitive.shadow_thickness 950 + newtb->primitive.highlight_thickness 951 + newtb->label.margin_height); 952 } 953 else 954 { 955 /* FIXME: We should calculate an drawing offset for the pixmap here to 956 * adjust it. */ 957 } 958 959 #if 0 960 printf("%d %d %d %d %d %d - %d %d\n", newtb->enhancedbutton.normal_pixmap, 961 h, newtb->core.height, 962 newtb->primitive.shadow_thickness, 963 newtb->primitive.highlight_thickness, 964 newtb->label.margin_height, 965 newtb->core.width, 966 newtb->core.height); 967 #endif 968 969 /* Invoke Label's Resize procedure. */ 970 { 971 XtWidgetProc resize; 972 XtProcessLock(); 973 resize = xmLabelClassRec.core_class.resize; 974 XtProcessUnlock(); 975 976 (* resize) ((Widget) newtb); 977 } 978 } 979 980 static void 981 Initialize(Widget rq, Widget ebw, ArgList args UNUSED, Cardinal *n UNUSED) 982 { 983 XmEnhancedButtonWidget request = (XmEnhancedButtonWidget)rq; 984 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)ebw; 985 XtWidgetProc resize; 986 987 XtProcessLock(); 988 resize = xmLabelClassRec.core_class.resize; 989 XtProcessUnlock(); 990 991 /* Create a bitmap for stippling (Drawable resources are cheap). */ 992 if (STIPPLE_BITMAP == None) 993 { 994 Display *dpy = XtDisplay((Widget) request); 995 Window rootW = DefaultRootWindow(dpy); 996 997 STIPPLE_BITMAP = XCreateBitmapFromData(dpy, rootW, stipple_bits, 998 stipple_width, stipple_height); 999 } 1000 eb->enhancedbutton.doing_setvalues = False; 1001 1002 /* First see what type of extended label this is. 1003 */ 1004 if (eb->enhancedbutton.pixmap_data) 1005 { 1006 XmString str; 1007 set_pixmap(eb); 1008 1009 /* FIXME: this is not the perfect way to deal with menus, which do not 1010 * have any string set right now. */ 1011 str = XmStringCreateLocalized(""); 1012 XtVaSetValues((Widget) eb, XmNlabelString, str, NULL); 1013 XmStringFree(str); 1014 } 1015 eb->label.pixmap = eb->enhancedbutton.normal_pixmap; 1016 1017 if (request->core.width == 0) 1018 eb->core.width = 0; 1019 if (request->core.height == 0) 1020 eb->core.height = 0; 1021 set_size(eb); 1022 1023 (* resize)((Widget)eb); 1024 } 1025 1026 static void 1027 free_pixmaps(XmEnhancedButtonWidget eb) 1028 { 1029 /* 1030 * Clear the old pixmaps. 1031 */ 1032 Pixmap norm_pix = eb->enhancedbutton.normal_pixmap; 1033 Pixmap arm_pix = eb->enhancedbutton.armed_pixmap; 1034 Pixmap insen_pix = eb->enhancedbutton.insensitive_pixmap; 1035 Pixmap high_pix = eb->enhancedbutton.highlight_pixmap; 1036 1037 if (norm_pix != None && norm_pix != XmUNSPECIFIED_PIXMAP) 1038 XFreePixmap(XtDisplay(eb), norm_pix); 1039 1040 if (arm_pix != None && arm_pix != XmUNSPECIFIED_PIXMAP) 1041 XFreePixmap(XtDisplay(eb), arm_pix); 1042 1043 if (insen_pix != None && insen_pix != XmUNSPECIFIED_PIXMAP) 1044 XFreePixmap(XtDisplay(eb), insen_pix); 1045 1046 if (high_pix != None && high_pix != XmUNSPECIFIED_PIXMAP) 1047 XFreePixmap(XtDisplay(eb), high_pix); 1048 } 1049 1050 static void 1051 Destroy(Widget w) 1052 { 1053 if (!XmIsEnhancedButton(w)) 1054 return; 1055 1056 free_pixmaps((XmEnhancedButtonWidget)w); 1057 } 1058 1059 static Boolean 1060 SetValues(Widget current, 1061 Widget request UNUSED, 1062 Widget new, 1063 ArgList args UNUSED, 1064 Cardinal *n UNUSED) 1065 { 1066 XmEnhancedButtonWidget cur = (XmEnhancedButtonWidget) current; 1067 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) new; 1068 Boolean redraw = False; 1069 Boolean change = True; 1070 Display *dpy = XtDisplay(current); 1071 1072 #define NOT_EQUAL(field) (cur->field != eb->field) 1073 1074 /* 1075 * Make sure that lost sensitivity is causing the border to vanish as well. 1076 */ 1077 if (NOT_EQUAL(core.sensitive) && !Lab_IsMenupane(current)) 1078 { 1079 if (cur->core.sensitive == True) 1080 { 1081 draw_unhighlight(eb); 1082 } 1083 else 1084 { 1085 int r_x; 1086 int r_y; 1087 unsigned int r_height; 1088 unsigned int r_width; 1089 unsigned int r_border; 1090 unsigned int r_depth; 1091 int root_x; 1092 int root_y; 1093 int win_x; 1094 int win_y; 1095 Window root; 1096 Window root_q; 1097 Window child; 1098 unsigned int mask; 1099 1100 /* 1101 * Artificially let the highlight appear if the mouse is over us. 1102 */ 1103 /* Best way to get the root window of object: */ 1104 XGetGeometry(dpy, XtWindow(cur), &root, &r_x, &r_y, &r_width, 1105 &r_height, &r_border, &r_depth); 1106 XQueryPointer(XtDisplay(cur), XtWindow(cur), &root_q, &child, 1107 &root_x, &root_y, &win_x, &win_y, &mask); 1108 1109 if (root == root_q) 1110 { 1111 if ((win_x < 0) || (win_y < 0)) 1112 return False; 1113 1114 if ((win_x > (int)r_width) || (win_y > (int)r_height)) 1115 return False; 1116 draw_highlight(eb); 1117 draw_shadows(eb); 1118 } 1119 } 1120 1121 return True; 1122 } 1123 1124 /* 1125 * Check for changed ExtLabelString. 1126 */ 1127 if (NOT_EQUAL(primitive.shadow_thickness)) 1128 { 1129 redraw = True; 1130 /* Don't change the pixmaps */ 1131 change = False; 1132 } 1133 1134 if (NOT_EQUAL(primitive.foreground)) 1135 redraw = True; 1136 if (NOT_EQUAL(core.background_pixel)) 1137 redraw = True; 1138 if (NOT_EQUAL(pushbutton.fill_on_arm)) 1139 redraw = True; 1140 if (NOT_EQUAL(enhancedbutton.spacing)) 1141 redraw = True; 1142 if (NOT_EQUAL(enhancedbutton.label_location)) 1143 { 1144 redraw = True; 1145 change = False; 1146 } 1147 if (NOT_EQUAL(label._label)) 1148 { 1149 redraw = True; 1150 set_size(eb); 1151 } 1152 1153 if (redraw == True) 1154 { 1155 if (change) 1156 set_pixmap(eb); 1157 if (eb->primitive.highlighted) 1158 eb->label.pixmap = eb->enhancedbutton.highlight_pixmap; 1159 else 1160 eb->label.pixmap = eb->enhancedbutton.normal_pixmap; 1161 if (change) 1162 set_size(eb); 1163 redraw = False; 1164 } 1165 1166 return redraw; 1167 } 1168 1169 static void 1170 Redisplay(Widget w, XEvent *event, Region region) 1171 { 1172 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) w; 1173 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1174 XmDisplay dpy; 1175 XtEnum default_button_emphasis; 1176 #endif 1177 XRectangle box; 1178 int dx; 1179 int adjust; 1180 short fill = 0; 1181 1182 if (!XtIsRealized((Widget)eb)) 1183 return; 1184 1185 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1186 dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); 1187 default_button_emphasis = dpy->display.default_button_emphasis; 1188 #endif 1189 1190 /* 1191 * Compute the area allocated to the label of the pushbutton; fill in the 1192 * dimensions in the box. 1193 */ 1194 1195 if ((eb->pushbutton.arm_color == eb->primitive.top_shadow_color) 1196 || (eb->pushbutton.arm_color == eb->primitive.bottom_shadow_color)) 1197 fill = 1; 1198 1199 if (eb->pushbutton.compatible) 1200 adjust = eb->pushbutton.show_as_default; 1201 else 1202 adjust = eb->pushbutton.default_button_shadow_thickness; 1203 1204 if (adjust > 0) 1205 { 1206 adjust = adjust + eb->primitive.shadow_thickness; 1207 adjust = (adjust << 1); 1208 dx = eb->primitive.highlight_thickness + adjust + fill; 1209 } 1210 else 1211 dx = (eb->primitive.highlight_thickness 1212 + eb->primitive.shadow_thickness + fill); 1213 1214 box.x = dx; 1215 box.y = dx; 1216 adjust = (dx << 1); 1217 box.width = eb->core.width - adjust; 1218 box.height = eb->core.height - adjust; 1219 1220 /* 1221 * Redraw the background. 1222 */ 1223 if (!Lab_IsMenupane(eb)) 1224 { 1225 GC gc; 1226 1227 /* Don't shade if the button contains a label with a pixmap, since 1228 * there is no variant of the label available with the needed 1229 * background. 1230 */ 1231 if (eb->pushbutton.armed && eb->pushbutton.fill_on_arm) 1232 { 1233 if (eb->label.label_type == (int)XmPIXMAP) 1234 { 1235 if (eb->pushbutton.arm_pixmap != XmUNSPECIFIED_PIXMAP) 1236 gc = eb->pushbutton.fill_gc; 1237 else 1238 gc = eb->pushbutton.background_gc; 1239 } 1240 else 1241 gc = eb->pushbutton.fill_gc; 1242 } 1243 else 1244 gc = eb->pushbutton.background_gc; 1245 /* really need to fill with background if not armed ? */ 1246 if (gc) 1247 XFillRectangle(XtDisplay(eb), XtWindow(eb), gc, 1248 box.x, box.y, box.width, box.height); 1249 } 1250 1251 draw_label(eb, event, region); 1252 1253 if (Lab_IsMenupane(eb)) 1254 { 1255 if (eb->pushbutton.armed) 1256 (*(((XmPushButtonWidgetClass)XtClass(eb)) 1257 ->primitive_class.border_highlight))(w); 1258 draw_pixmap(eb, event, region); 1259 } 1260 else 1261 { 1262 adjust = 0; 1263 1264 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1265 /* 1266 * NOTE: PushButton has two types of shadows: primitive-shadow and 1267 * default-button-shadow. If pushbutton is in a menu only primitive 1268 * shadows are drawn. 1269 */ 1270 switch (default_button_emphasis) 1271 { 1272 case XmEXTERNAL_HIGHLIGHT: 1273 adjust = (eb->primitive.highlight_thickness - 1274 (eb->pushbutton.default_button_shadow_thickness 1275 ? Xm3D_ENHANCE_PIXEL : 0)); 1276 break; 1277 1278 case XmINTERNAL_HIGHLIGHT: 1279 break; 1280 1281 default: 1282 assert(FALSE); 1283 return; 1284 } 1285 #endif 1286 1287 /* 1288 * Clear the area not occupied by label with parents background color. 1289 * Label will invoke BorderUnhighlight() on the highlight_thickness 1290 * area, which is redundant when XmEXTERNAL_HIGHLIGHT default button 1291 * shadow emphasis is used. 1292 */ 1293 if (box.x > adjust) 1294 { 1295 int borderwidth =box.x - adjust; 1296 int rectwidth = eb->core.width - 2 * adjust; 1297 int rectheight = eb->core.height - 2 * adjust; 1298 1299 if (XmIsManager(XtParent(eb))) 1300 { 1301 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 1302 XmParentBackgroundGC(eb), 1303 adjust, adjust, rectwidth, rectheight, borderwidth); 1304 } 1305 else 1306 { 1307 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 1308 adjust, adjust, rectwidth, rectheight, borderwidth); 1309 } 1310 1311 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1312 switch (default_button_emphasis) 1313 { 1314 case XmINTERNAL_HIGHLIGHT: 1315 /* The call above erases the border highlighting. */ 1316 if (eb->primitive.highlight_drawn) 1317 (*(((XmPushButtonWidgetClass) XtClass (eb)) 1318 ->primitive_class.border_highlight)) ((Widget) eb) ; 1319 break; 1320 1321 default: 1322 break; 1323 } 1324 #endif 1325 } 1326 1327 if (eb->pushbutton.default_button_shadow_thickness) 1328 { 1329 if (eb->pushbutton.show_as_default) 1330 { 1331 /* 1332 * - get the topShadowColor and bottomShadowColor from the 1333 * parent; use those colors to construct top and bottom gc; 1334 * use these GCs to draw the shadows of the button. 1335 * 1336 * - Should not be called if pushbutton is in a row column or 1337 * in a menu. 1338 * 1339 * - Should be called only if a defaultbuttonshadow is to be 1340 * drawn. 1341 */ 1342 GC top_gc; 1343 GC bottom_gc; 1344 int default_button_shadow_thickness; 1345 int x, y, width, height, delta; 1346 Widget parent; 1347 1348 if (eb->pushbutton.compatible 1349 && (eb->pushbutton.show_as_default == 0)) 1350 return; 1351 1352 if (!eb->pushbutton.compatible 1353 && (eb->pushbutton.default_button_shadow_thickness 1354 == 0)) 1355 return; 1356 1357 delta = eb->primitive.highlight_thickness; 1358 1359 /* 1360 * May need more complex computation for getting the GCs. 1361 */ 1362 parent = XtParent(eb); 1363 if (XmIsManager(parent)) 1364 { 1365 /* Use the parent's GC so monochrome works. */ 1366 bottom_gc = XmParentTopShadowGC(eb); 1367 top_gc = XmParentBottomShadowGC(eb); 1368 } 1369 else 1370 { 1371 /* Use your own pixel for drawing. */ 1372 bottom_gc = eb->primitive.top_shadow_GC; 1373 top_gc = eb->primitive.bottom_shadow_GC; 1374 } 1375 1376 if ((bottom_gc == None) || (top_gc == None)) 1377 return; 1378 1379 1380 if (eb->pushbutton.compatible) 1381 default_button_shadow_thickness = 1382 eb->pushbutton.show_as_default; 1383 else 1384 default_button_shadow_thickness = 1385 eb->pushbutton.default_button_shadow_thickness; 1386 1387 #if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1388 /* 1389 * Compute location of bounding box to contain the 1390 * defaultButtonShadow. 1391 */ 1392 switch (default_button_emphasis) 1393 { 1394 case XmEXTERNAL_HIGHLIGHT: 1395 delta = eb->primitive.highlight_thickness; 1396 break; 1397 1398 case XmINTERNAL_HIGHLIGHT: 1399 delta = Xm3D_ENHANCE_PIXEL; 1400 break; 1401 1402 default: 1403 assert(FALSE); 1404 return; 1405 } 1406 #endif 1407 1408 x = y = delta; 1409 width = eb->core.width - 2 * delta; 1410 height = eb->core.height - 2 * delta; 1411 1412 if ((width > 0) && (height > 0)) 1413 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 1414 top_gc, bottom_gc, x, y, width, height, 1415 default_button_shadow_thickness, 1416 (unsigned)XmSHADOW_OUT); 1417 } 1418 } 1419 1420 if (eb->primitive.highlight_drawn) 1421 draw_shadows(eb); 1422 draw_pixmap(eb, event, region); 1423 } 1424 } 1425 1426 static void 1427 BorderHighlight(Widget w) 1428 { 1429 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)w; 1430 1431 (*(xmPushButtonClassRec.primitive_class.border_highlight))(w); 1432 draw_pixmap(eb, NULL, NULL); 1433 } 1434 1435 static void 1436 BorderUnhighlight(Widget w) 1437 { 1438 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)w; 1439 1440 (*(xmPushButtonClassRec.primitive_class.border_unhighlight))(w); 1441 draw_pixmap(eb, NULL, NULL); 1442 } 1443 1444 #endif /* FEAT_TOOLBAR */ 1445