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