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 <martin@dalecki.de> 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 76extern Boolean _XmGetInDragMode(Widget widget); 77extern void _XmPrimitiveEnter(Widget wid, 78 XEvent * event, 79 String * params, Cardinal * num_params); 80extern void _XmPrimitiveLeave(Widget wid, 81 XEvent * event, 82 String * params, Cardinal * num_params); 83extern void _XmSetFocusFlag(Widget w, unsigned int mask, Boolean value); 84extern void _XmCalcLabelDimensions(Widget wid); 85 86/* 87 * Declaration of class methods. 88 */ 89static void Destroy(Widget w); 90static void Initialize(Widget rq, Widget eb, ArgList args, Cardinal *n); 91static Boolean SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *n); 92static void Redisplay(Widget, XEvent *, Region); 93 94/* 95 * Declaration of action methods. 96 */ 97static void Enter(Widget, XEvent *, String *, Cardinal *); 98static void Leave(Widget, XEvent *, String *, Cardinal *); 99static void BorderHighlight(Widget); 100static void BorderUnhighlight(Widget); 101 102/* 103 * 4 x 4 stipple for desensitized widgets 104 */ 105#define stipple_width 4 106#define stipple_height 4 107static char stipple_bits[] = { 0x0a, 0x05, 0x0a, 0x05 }; 108#define STIPPLE_BITMAP xmEnhancedButtonClassRec.enhancedbutton_class.stipple_bitmap 109 110/* 111 * Override actions. 112 */ 113static XtActionsRec actionsList[] = 114{ 115 {"Enter", Enter}, 116 {"Leave", Leave}, 117}; 118 119static 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. */ 143XmPrimitiveClassExtRec 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 154XmEnhancedButtonClassRec 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 223WidgetClass xmEnhancedButtonWidgetClass = 224 (WidgetClass)&xmEnhancedButtonClassRec; 225 226 227/* 228 * Create a slightly fainter pixmap to be shown on button entry. 229 */ 230 static unsigned short 231bump_color(unsigned short value) 232{ 233 int tmp = 2 * (((int) value - 65535) / 3) + 65535; 234 235 return tmp; 236} 237 238 static int 239alloc_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 */ 260static 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 287set_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 subsititution 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 if (eb->enhancedbutton.label_location == (int)XmTOP 379 || eb->enhancedbutton.label_location == (int)XmBOTTOM) 380 shift = eb->primitive.shadow_thickness / 2; 381 else 382 shift = eb->primitive.shadow_thickness / 2; 383 384 if (shift < 1) 385 shift = 1; 386 387 sen_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 388 389 XSetForeground(dpy, gc, eb->core.background_pixel); 390 XFillRectangle(dpy, sen_pix, gc, 0, 0, width + shift, height + shift); 391 XSetClipMask(dpy, gc, mask); 392 XSetClipOrigin(dpy, gc, shift, shift); 393 XCopyArea(dpy, pix, sen_pix, gc, 0, 0, width, height, shift, shift); 394 395 /* Create the "highlight" pixmap. */ 396 color[4].pixel = eb->primitive.bottom_shadow_color; 397#ifdef XpmAllocColor /* SGI doesn't have it */ 398 attr.valuemask = XpmColorSymbols | XpmCloseness | XpmAllocColor; 399 attr.alloc_color = alloc_color; 400#else 401 attr.valuemask = XpmColorSymbols | XpmCloseness; 402#endif 403 attr.closeness = 65535; /* accuracy isn't crucial */ 404 attr.colorsymbols = color; 405 attr.numsymbols = XtNumber(color); 406 407 status = XpmCreatePixmapFromData(dpy, root, data, &pix, NULL, &attr); 408 XpmFreeAttributes(&attr); 409 410 high_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 411 412#if 1 413 XSetForeground(dpy, gc, eb->core.background_pixel); 414#else 415 XSetForeground(dpy, gc, eb->primitive.top_shadow_color); 416#endif 417 XSetClipMask(dpy, gc, None); 418 XFillRectangle(dpy, high_pix, gc, 0, 0, width + shift, height + shift); 419 XSetClipMask(dpy, gc, mask); 420 XSetClipOrigin(dpy, gc, 0, 0); 421 XCopyArea(dpy, pix, high_pix, gc, 0, 0, width, height, 0, 0); 422 423 arm_pix = XCreatePixmap(dpy, pix, width + shift, height + shift, depth); 424 425 if (eb->pushbutton.fill_on_arm) 426 XSetForeground(dpy, gc, eb->pushbutton.arm_color); 427 else 428 XSetForeground(dpy, gc, eb->core.background_pixel); 429 XSetClipOrigin(dpy, gc, shift, shift); 430 XSetClipMask(dpy, gc, None); 431 XFillRectangle(dpy, arm_pix, gc, 0, 0, width + shift, height + shift); 432 XSetClipMask(dpy, gc, mask); 433 XSetClipOrigin(dpy, gc, 2 * shift, 2 * shift); 434 XCopyArea(dpy, pix, arm_pix, gc, 0, 0, width, height, 2 * shift, 2 * shift); 435 436 XFreePixmap(dpy, pix); 437 XFreePixmap(dpy, mask); 438 439 /* Create the "insensitive" pixmap. */ 440 attr.valuemask = XpmColorSymbols | XpmCloseness | XpmColorKey; 441 attr.closeness = 65535; /* accuracy isn't crucial */ 442 attr.colorsymbols = color; 443 attr.numsymbols = sizeof(color) / sizeof(color[0]); 444 attr.color_key = XPM_MONO; 445 status = XpmCreatePixmapFromData(dpy, root, data, &pix, &mask, &attr); 446 447 /* Need to create new Pixmaps with the mask applied. */ 448 449 ins_pix = XCreatePixmap(dpy, root, width + shift, height + shift, depth); 450 451 XSetForeground(dpy, gc, eb->core.background_pixel); 452 XSetClipOrigin(dpy, gc, 0, 0); 453 XSetClipMask(dpy, gc, None); 454 XFillRectangle(dpy, ins_pix, gc, 0, 0, width + shift, height + shift); 455 XSetClipMask(dpy, gc, mask); 456 XSetForeground(dpy, gc, eb->primitive.top_shadow_color); 457 XSetClipOrigin(dpy, gc, 2 * shift, 2 * shift); 458 XFillRectangle(dpy, ins_pix, gc, 2 * shift, 2 * shift, width, height); 459 XSetForeground(dpy, gc, eb->primitive.bottom_shadow_color); 460 XSetClipOrigin(dpy, gc, shift, shift); 461 XFillRectangle(dpy, ins_pix, gc, 0, 0, width + shift, height + shift); 462 XtReleaseGC((Widget) eb, gc); 463 464 XpmFreeAttributes(&attr); 465 466 eb->enhancedbutton.pixmap_depth = depth; 467 eb->enhancedbutton.pixmap_width = width; 468 eb->enhancedbutton.pixmap_height = height; 469 eb->enhancedbutton.normal_pixmap = sen_pix; 470 eb->enhancedbutton.highlight_pixmap = high_pix; 471 eb->enhancedbutton.insensitive_pixmap = ins_pix; 472 eb->enhancedbutton.armed_pixmap = arm_pix; 473 474 eb->enhancedbutton.doing_setvalues = True; 475 eb->enhancedbutton.doing_setvalues = False; 476 477 XFreePixmap(dpy, pix); 478 XFreePixmap(dpy, mask); 479} 480 481#define BUTTON_MASK ( \ 482 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask \ 483) 484 485 static void 486draw_shadows(XmEnhancedButtonWidget eb) 487{ 488 GC top_gc; 489 GC bottom_gc; 490 Boolean etched_in; 491 492 if (!eb->primitive.shadow_thickness) 493 return; 494 495 if ((eb->core.width <= 2 * eb->primitive.highlight_thickness) 496 || (eb->core.height <= 2 * eb->primitive.highlight_thickness)) 497 return; 498 499#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 500 { 501 XmDisplay dpy; 502 503 dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(eb)); 504 etched_in = dpy->display.enable_etched_in_menu; 505 } 506#else 507 etched_in = False; 508#endif 509 if (!etched_in ^ eb->pushbutton.armed) 510 { 511 top_gc = eb->primitive.top_shadow_GC; 512 bottom_gc = eb->primitive.bottom_shadow_GC; 513 } 514 else 515 { 516 top_gc = eb->primitive.bottom_shadow_GC; 517 bottom_gc = eb->primitive.top_shadow_GC; 518 } 519 520 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 521 top_gc, 522 bottom_gc, 523 eb->primitive.highlight_thickness, 524 eb->primitive.highlight_thickness, 525 eb->core.width - 2 * eb->primitive.highlight_thickness, 526 eb->core.height - 2 * eb->primitive.highlight_thickness, 527 eb->primitive.shadow_thickness, 528 (unsigned)(etched_in ? XmSHADOW_IN : XmSHADOW_OUT)); 529} 530 531 static void 532draw_highlight(XmEnhancedButtonWidget eb) 533{ 534 eb->primitive.highlighted = True; 535 eb->primitive.highlight_drawn = True; 536 537 if (!XtWidth(eb) || !XtHeight(eb) || !eb->primitive.highlight_thickness) 538 return; 539 540 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 541 eb->primitive.highlight_GC, 0, 0, 542 XtWidth(eb), XtHeight(eb), 543 eb->primitive.highlight_thickness); 544} 545 546 static void 547draw_unhighlight(XmEnhancedButtonWidget eb) 548{ 549 GC manager_background_GC; 550 551 eb->primitive.highlighted = False; 552 eb->primitive.highlight_drawn = False; 553 554 if (!XtWidth(eb) || !XtHeight(eb) || !eb->primitive.highlight_thickness) 555 return; 556 557 if (XmIsManager(eb->core.parent)) 558 { 559#ifdef UNHIGHLIGHTT 560 XmSpecifyUnhighlightTrait UnhighlightT; 561 562 if (((UnhighlightT = (XmSpecifyUnhighlightTrait) XmeTraitGet((XtPointer) 563 XtClass(eb->core.parent), XmQTspecifyUnhighlight)) 564 != NULL) && (UnhighlightT->getUnhighlightGC != NULL)) 565 { 566 /* if unhighlight trait in parent use specified GC... */ 567 manager_background_GC = 568 UnhighlightT->getUnhighlightGC(eb->core.parent, (Widget) eb); 569 } 570 else 571 { 572 /* ...otherwise, use parent's background GC */ 573 manager_background_GC = ((XmManagerWidget) 574 (eb->core.parent))->manager.background_GC; 575 } 576#else 577 manager_background_GC = ((XmManagerWidget) 578 (eb->core.parent))->manager.background_GC; 579#endif 580 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 581 manager_background_GC, 582 0, 0, XtWidth(eb), XtHeight(eb), 583 eb->primitive.highlight_thickness); 584 if (!eb->pushbutton.armed && eb->primitive.shadow_thickness) 585 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 586 eb->primitive.highlight_thickness, 587 eb->primitive.highlight_thickness, 588 eb->core.width - 2 * eb->primitive.highlight_thickness, 589 eb->core.height - 2 * eb->primitive.highlight_thickness, 590 eb->primitive.shadow_thickness); 591 } 592 else 593 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 0, 0, XtWidth(eb), 594 XtHeight(eb), eb->primitive.highlight_thickness); 595} 596 597 static void 598draw_pixmap(XmEnhancedButtonWidget eb, 599 XEvent *event UNUSED, 600 Region region UNUSED) 601{ 602 Pixmap pix; 603 GC gc = eb->label.normal_GC; 604 int depth; 605 Cardinal width; 606 Cardinal height; 607 Cardinal w; 608 Cardinal h; 609 int x; 610 int y; 611 612 if (!XtIsSensitive((Widget) eb)) 613 pix = eb->enhancedbutton.insensitive_pixmap; 614 else 615 { 616 if (eb->primitive.highlighted && !eb->pushbutton.armed) 617 pix = eb->enhancedbutton.highlight_pixmap; 618 else if (eb->pushbutton.armed) 619 pix = eb->enhancedbutton.armed_pixmap; 620 else 621 pix = eb->enhancedbutton.normal_pixmap; 622 } 623 624 if (pix == None || !eb->enhancedbutton.pixmap_data) 625 return; 626 627 depth = eb->enhancedbutton.pixmap_depth; 628 w = eb->enhancedbutton.pixmap_width; 629 h = eb->enhancedbutton.pixmap_height; 630 631 gc = eb->label.normal_GC; 632 x = eb->primitive.highlight_thickness 633 + eb->primitive.shadow_thickness 634 + eb->label.margin_width; 635 y = eb->primitive.highlight_thickness 636 + eb->primitive.shadow_thickness 637 + eb->label.margin_height; 638 width = eb->core.width - 2 * x; 639 if (w < width) 640 width = w; 641 height = eb->core.height - 2 * y; 642 if (h < height) 643 height = h; 644 if (depth == (int)eb->core.depth) 645 XCopyArea(XtDisplay(eb), pix, XtWindow(eb), gc, 0, 0, 646 width, height, x, y); 647 else if (depth == 1) 648 XCopyPlane(XtDisplay(eb), pix, XtWindow(eb), gc, 0, 0, 649 width, height, x, y, (unsigned long)1); 650} 651 652/* 653 * Draw the label contained in the pushbutton. 654 */ 655 static void 656draw_label(XmEnhancedButtonWidget eb, XEvent *event, Region region) 657{ 658 GC tmp_gc = NULL; 659 Boolean replaceGC = False; 660 Boolean deadjusted = False; 661#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 662 XmDisplay dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); 663 Boolean etched_in = dpy->display.enable_etched_in_menu; 664#else 665 Boolean etched_in = False; 666#endif 667 668 if (eb->pushbutton.armed 669 && ((!Lab_IsMenupane(eb) && eb->pushbutton.fill_on_arm) 670 || (Lab_IsMenupane(eb) && etched_in))) 671 { 672 if (eb->label.label_type == (int)XmSTRING 673 && eb->pushbutton.arm_color == eb->primitive.foreground) 674 { 675 tmp_gc = eb->label.normal_GC; 676 eb->label.normal_GC = eb->pushbutton.background_gc; 677 replaceGC = True; 678 } 679 } 680 681 /* 682 * If the button contains a labeled pixmap, we will take it instead of our 683 * own pixmap. 684 */ 685 686 if (eb->label.label_type == (int)XmPIXMAP) 687 { 688 if (eb->pushbutton.armed) 689 { 690 if (eb->pushbutton.arm_pixmap != XmUNSPECIFIED_PIXMAP) 691 eb->label.pixmap = eb->pushbutton.arm_pixmap; 692 else 693 eb->label.pixmap = eb->pushbutton.unarm_pixmap; 694 } 695 else 696 /* pushbutton is not armed */ 697 eb->label.pixmap = eb->pushbutton.unarm_pixmap; 698 } 699 700 /* 701 * Temporarily remove the Xm3D_ENHANCE_PIXEL hack ("adjustment") from the 702 * margin values, so we don't confuse Label. 703 */ 704 if (eb->pushbutton.default_button_shadow_thickness > 0) 705 { 706 deadjusted = True; 707 Lab_MarginLeft(eb) -= Xm3D_ENHANCE_PIXEL; 708 Lab_MarginRight(eb) -= Xm3D_ENHANCE_PIXEL; 709 Lab_MarginTop(eb) -= Xm3D_ENHANCE_PIXEL; 710 Lab_MarginBottom(eb) -= Xm3D_ENHANCE_PIXEL; 711 } 712 713 { 714 XtExposeProc expose; 715 716 XtProcessLock(); 717 expose = xmLabelClassRec.core_class.expose; 718 XtProcessUnlock(); 719 (*expose)((Widget) eb, event, region); 720 } 721 722 if (deadjusted) 723 { 724 Lab_MarginLeft(eb) += Xm3D_ENHANCE_PIXEL; 725 Lab_MarginRight(eb) += Xm3D_ENHANCE_PIXEL; 726 Lab_MarginTop(eb) += Xm3D_ENHANCE_PIXEL; 727 Lab_MarginBottom(eb) += Xm3D_ENHANCE_PIXEL; 728 } 729 730 if (replaceGC) 731 eb->label.normal_GC = tmp_gc; 732} 733 734 static void 735Enter(Widget wid, 736 XEvent *event, 737 String *params UNUSED, 738 Cardinal *num_params UNUSED) 739{ 740 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) wid; 741 XmPushButtonCallbackStruct call_value; 742 743 if (Lab_IsMenupane(eb)) 744 { 745 if ((((ShellWidget) XtParent(XtParent(eb)))->shell.popped_up) 746 && _XmGetInDragMode((Widget) eb)) 747 { 748#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 749 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); 750 Boolean etched_in = dpy->display.enable_etched_in_menu; 751#else 752 Boolean etched_in = False; 753#endif 754 755 if (eb->pushbutton.armed) 756 return; 757 758 /* ...so KHelp event is delivered correctly. */ 759 _XmSetFocusFlag(XtParent(XtParent(eb)), XmFOCUS_IGNORE, TRUE); 760 XtSetKeyboardFocus(XtParent(XtParent(eb)), (Widget) eb); 761 _XmSetFocusFlag(XtParent(XtParent(eb)), XmFOCUS_IGNORE, FALSE); 762 763 eb->pushbutton.armed = TRUE; 764 765 ((XmManagerWidget) XtParent(wid))->manager.active_child = wid; 766 767 /* etched in menu button */ 768 if (etched_in && !XmIsTearOffButton(eb)) 769 { 770 XFillRectangle(XtDisplay(eb), XtWindow(eb), 771 eb->pushbutton.fill_gc, 772 0, 0, eb->core.width, eb->core.height); 773 draw_label(eb, event, NULL); 774 draw_pixmap(eb, event, NULL); 775 } 776 777 if ((eb->core.width > 2 * eb->primitive.highlight_thickness) 778 && (eb->core.height > 779 2 * eb->primitive.highlight_thickness)) 780 { 781 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 782 eb->primitive.top_shadow_GC, 783 eb->primitive.bottom_shadow_GC, 784 eb->primitive.highlight_thickness, 785 eb->primitive.highlight_thickness, 786 eb->core.width - 2 * eb->primitive.highlight_thickness, 787 eb->core.height - 2 * eb->primitive.highlight_thickness, 788 eb->primitive.shadow_thickness, 789 (unsigned)(etched_in ? XmSHADOW_IN : XmSHADOW_OUT)); 790 } 791 792 if (eb->pushbutton.arm_callback) 793 { 794 XFlush(XtDisplay(eb)); 795 796 call_value.reason = (int)XmCR_ARM; 797 call_value.event = event; 798 XtCallCallbackList((Widget) eb, 799 eb->pushbutton.arm_callback, 800 &call_value); 801 } 802 } 803 } 804 else 805 { 806 XtExposeProc expose; 807 808 _XmPrimitiveEnter((Widget) eb, event, NULL, NULL); 809 if (eb->pushbutton.armed == TRUE) 810 { 811 XtProcessLock(); 812 expose = XtClass(eb)->core_class.expose; 813 XtProcessUnlock(); 814 (*expose) (wid, event, (Region) NULL); 815 } 816 817 draw_highlight(eb); 818 draw_shadows(eb); 819 draw_pixmap(eb, event, NULL); 820 } 821} 822 823 static void 824Leave(Widget wid, 825 XEvent *event, 826 String *params UNUSED, 827 Cardinal *num_params UNUSED) 828{ 829 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)wid; 830 XmPushButtonCallbackStruct call_value; 831 832 if (Lab_IsMenupane(eb)) 833 { 834#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 835 XmDisplay dpy = (XmDisplay) XmGetXmDisplay(XtDisplay(wid)); 836 Boolean etched_in = dpy->display.enable_etched_in_menu; 837#else 838 Boolean etched_in = False; 839#endif 840 841 if (_XmGetInDragMode((Widget)eb) 842 && eb->pushbutton.armed 843 && ( /* !ActiveTearOff || */ 844 event->xcrossing.mode == NotifyNormal)) 845 { 846 eb->pushbutton.armed = FALSE; 847 848 ((XmManagerWidget) XtParent(wid))->manager.active_child = NULL; 849 850 if (etched_in && !XmIsTearOffButton(eb)) 851 { 852 XFillRectangle(XtDisplay(eb), XtWindow(eb), 853 eb->pushbutton.background_gc, 854 0, 0, eb->core.width, eb->core.height); 855 draw_label(eb, event, NULL); 856 draw_pixmap(eb, event, NULL); 857 } 858 else 859 XmeClearBorder 860 (XtDisplay(eb), XtWindow(eb), 861 eb->primitive.highlight_thickness, 862 eb->primitive.highlight_thickness, 863 eb->core.width - 864 2 * eb->primitive.highlight_thickness, 865 eb->core.height - 866 2 * eb->primitive.highlight_thickness, 867 eb->primitive.shadow_thickness); 868 869 if (eb->pushbutton.disarm_callback) 870 { 871 XFlush(XtDisplay(eb)); 872 873 call_value.reason = (int)XmCR_DISARM; 874 call_value.event = event; 875 XtCallCallbackList((Widget) eb, 876 eb->pushbutton.disarm_callback, 877 &call_value); 878 } 879 } 880 } 881 else 882 { 883 _XmPrimitiveLeave((Widget) eb, event, NULL, NULL); 884 885 if (eb->pushbutton.armed == TRUE) 886 { 887 XtExposeProc expose; 888 eb->pushbutton.armed = FALSE; 889 XtProcessLock(); 890 expose = XtClass(eb)->core_class.expose; 891 XtProcessUnlock(); 892 (*expose) (wid, event, (Region)NULL); 893 draw_unhighlight(eb); 894 draw_pixmap(eb, event, NULL); 895 eb->pushbutton.armed = TRUE; 896 } 897 else 898 { 899 draw_unhighlight(eb); 900 draw_pixmap(eb, event, NULL); 901 } 902 } 903} 904 905#define IsNull(p) ((p) == XmUNSPECIFIED_PIXMAP) 906 907 static void 908set_size(XmEnhancedButtonWidget newtb) 909{ 910 unsigned int w = 0; 911 unsigned int h = 0; 912 913 _XmCalcLabelDimensions((Widget) newtb); 914 915 /* Find out how big the pixmap is */ 916 if (newtb->enhancedbutton.pixmap_data 917 && !IsNull(newtb->label.pixmap) 918 && !IsNull(newtb->enhancedbutton.normal_pixmap)) 919 { 920 w = newtb->enhancedbutton.pixmap_width; 921 h = newtb->enhancedbutton.pixmap_height; 922 } 923 924 /* 925 * Plase note that we manipulate the width only in case of push buttons not 926 * used in the context of a menu pane. 927 */ 928 if (Lab_IsMenupane(newtb)) 929 { 930 newtb->label.margin_left = w + 2 * (newtb->primitive.shadow_thickness 931 + newtb->primitive.highlight_thickness) 932 + newtb->label.margin_width; 933 } 934 else 935 { 936 newtb->label.margin_left = w; 937 newtb->core.width = w + 2 * (newtb->primitive.shadow_thickness 938 + newtb->primitive.highlight_thickness 939 + newtb->label.margin_width) 940 + newtb->label.TextRect.width; 941 942 if (newtb->label.TextRect.width > 0) 943 { 944 newtb->label.margin_left += newtb->label.margin_width 945 + newtb->primitive.shadow_thickness; 946 newtb->core.width += newtb->label.margin_width 947 + newtb->primitive.shadow_thickness; 948 } 949 } 950 if (newtb->label.TextRect.height < h) 951 { 952 newtb->core.height = h + 2 * (newtb->primitive.shadow_thickness 953 + newtb->primitive.highlight_thickness 954 + newtb->label.margin_height); 955 } 956 else 957 { 958 /* FIXME: We should calculate an drawing offset for the pixmap here to 959 * adjust it. */ 960 } 961 962#if 0 963 printf("%d %d %d %d %d %d - %d %d\n", newtb->enhancedbutton.normal_pixmap, 964 h, newtb->core.height, 965 newtb->primitive.shadow_thickness, 966 newtb->primitive.highlight_thickness, 967 newtb->label.margin_height, 968 newtb->core.width, 969 newtb->core.height); 970#endif 971 972 /* Invoke Label's Resize procedure. */ 973 { 974 XtWidgetProc resize; 975 XtProcessLock(); 976 resize = xmLabelClassRec.core_class.resize; 977 XtProcessUnlock(); 978 979 (* resize) ((Widget) newtb); 980 } 981} 982 983 static void 984Initialize(Widget rq, Widget ebw, ArgList args UNUSED, Cardinal *n UNUSED) 985{ 986 XmEnhancedButtonWidget request = (XmEnhancedButtonWidget)rq; 987 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)ebw; 988 XtWidgetProc resize; 989 990 XtProcessLock(); 991 resize = xmLabelClassRec.core_class.resize; 992 XtProcessUnlock(); 993 994 /* Create a bitmap for stippling (Drawable resources are cheap). */ 995 if (STIPPLE_BITMAP == None) 996 { 997 Display *dpy = XtDisplay((Widget) request); 998 Window rootW = DefaultRootWindow(dpy); 999 1000 STIPPLE_BITMAP = XCreateBitmapFromData(dpy, rootW, stipple_bits, 1001 stipple_width, stipple_height); 1002 } 1003 eb->enhancedbutton.doing_setvalues = False; 1004 1005 /* First see what type of extended label this is. 1006 */ 1007 if (eb->enhancedbutton.pixmap_data) 1008 { 1009 XmString str; 1010 set_pixmap(eb); 1011 1012 /* FIXME: this is not the perfect way to deal with menues, which do not 1013 * have any string set right now. */ 1014 str = XmStringCreateLocalized(""); 1015 XtVaSetValues((Widget) eb, XmNlabelString, str, NULL); 1016 XmStringFree(str); 1017 } 1018 eb->label.pixmap = eb->enhancedbutton.normal_pixmap; 1019 1020 if (request->core.width == 0) 1021 eb->core.width = 0; 1022 if (request->core.height == 0) 1023 eb->core.height = 0; 1024 set_size(eb); 1025 1026 (* resize)((Widget)eb); 1027} 1028 1029 static void 1030free_pixmaps(XmEnhancedButtonWidget eb) 1031{ 1032 /* 1033 * Clear the old pixmaps. 1034 */ 1035 Pixmap norm_pix = eb->enhancedbutton.normal_pixmap; 1036 Pixmap arm_pix = eb->enhancedbutton.armed_pixmap; 1037 Pixmap insen_pix = eb->enhancedbutton.insensitive_pixmap; 1038 Pixmap high_pix = eb->enhancedbutton.highlight_pixmap; 1039 1040 if (norm_pix != None && norm_pix != XmUNSPECIFIED_PIXMAP) 1041 XFreePixmap(XtDisplay(eb), norm_pix); 1042 1043 if (arm_pix != None && arm_pix != XmUNSPECIFIED_PIXMAP) 1044 XFreePixmap(XtDisplay(eb), arm_pix); 1045 1046 if (insen_pix != None && insen_pix != XmUNSPECIFIED_PIXMAP) 1047 XFreePixmap(XtDisplay(eb), insen_pix); 1048 1049 if (high_pix != None && high_pix != XmUNSPECIFIED_PIXMAP) 1050 XFreePixmap(XtDisplay(eb), high_pix); 1051} 1052 1053 static void 1054Destroy(Widget w) 1055{ 1056 if (!XmIsEnhancedButton(w)) 1057 return; 1058 1059 free_pixmaps((XmEnhancedButtonWidget)w); 1060} 1061 1062 static Boolean 1063SetValues(Widget current, 1064 Widget request UNUSED, 1065 Widget new, 1066 ArgList args UNUSED, 1067 Cardinal *n UNUSED) 1068{ 1069 XmEnhancedButtonWidget cur = (XmEnhancedButtonWidget) current; 1070 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) new; 1071 Boolean redraw = False; 1072 Boolean change = True; 1073 Display *dpy = XtDisplay(current); 1074 1075#define NOT_EQUAL(field) (cur->field != eb->field) 1076 1077 /* 1078 * Make sure that lost sensitivity is causing the border to vanish as well. 1079 */ 1080 if (NOT_EQUAL(core.sensitive) && !Lab_IsMenupane(current)) 1081 { 1082 if (cur->core.sensitive == True) 1083 { 1084 draw_unhighlight(eb); 1085 } 1086 else 1087 { 1088 int r_x; 1089 int r_y; 1090 unsigned int r_height; 1091 unsigned int r_width; 1092 unsigned int r_border; 1093 unsigned int r_depth; 1094 int root_x; 1095 int root_y; 1096 int win_x; 1097 int win_y; 1098 Window root; 1099 Window root_q; 1100 Window child; 1101 unsigned int mask; 1102 1103 /* 1104 * Artificially let the highlight appear if the mouse is over us. 1105 */ 1106 /* Best way to get the root window of object: */ 1107 XGetGeometry(dpy, XtWindow(cur), &root, &r_x, &r_y, &r_width, 1108 &r_height, &r_border, &r_depth); 1109 XQueryPointer(XtDisplay(cur), XtWindow(cur), &root_q, &child, 1110 &root_x, &root_y, &win_x, &win_y, &mask); 1111 1112 if (root == root_q) 1113 { 1114 if ((win_x < 0) || (win_y < 0)) 1115 return False; 1116 1117 if ((win_x > (int)r_width) || (win_y > (int)r_height)) 1118 return False; 1119 draw_highlight(eb); 1120 draw_shadows(eb); 1121 } 1122 } 1123 1124 return True; 1125 } 1126 1127 /* 1128 * Check for changed ExtLabelString. 1129 */ 1130 if (NOT_EQUAL(primitive.shadow_thickness)) 1131 { 1132 redraw = True; 1133 /* Don't change the pixmaps */ 1134 change = False; 1135 } 1136 1137 if (NOT_EQUAL(primitive.foreground)) 1138 redraw = True; 1139 if (NOT_EQUAL(core.background_pixel)) 1140 redraw = True; 1141 if (NOT_EQUAL(pushbutton.fill_on_arm)) 1142 redraw = True; 1143 if (NOT_EQUAL(enhancedbutton.spacing)) 1144 redraw = True; 1145 if (NOT_EQUAL(enhancedbutton.label_location)) 1146 { 1147 redraw = True; 1148 change = False; 1149 } 1150 if (NOT_EQUAL(label._label)) 1151 { 1152 redraw = True; 1153 set_size(eb); 1154 } 1155 1156 if (redraw == True) 1157 { 1158 if (change) 1159 set_pixmap(eb); 1160 if (eb->primitive.highlighted) 1161 eb->label.pixmap = eb->enhancedbutton.highlight_pixmap; 1162 else 1163 eb->label.pixmap = eb->enhancedbutton.normal_pixmap; 1164 if (change) 1165 set_size(eb); 1166 redraw = False; 1167 } 1168 1169 return redraw; 1170} 1171 1172 static void 1173Redisplay(Widget w, XEvent *event, Region region) 1174{ 1175 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) w; 1176#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1177 XmDisplay dpy; 1178 XtEnum default_button_emphasis; 1179#endif 1180 XRectangle box; 1181 int dx; 1182 int adjust; 1183 short fill = 0; 1184 1185 if (!XtIsRealized((Widget)eb)) 1186 return; 1187 1188#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1189 dpy = (XmDisplay)XmGetXmDisplay(XtDisplay(eb)); 1190 default_button_emphasis = dpy->display.default_button_emphasis; 1191#endif 1192 1193 /* 1194 * Compute the area allocated to the label of the pushbutton; fill in the 1195 * dimensions in the box. 1196 */ 1197 1198 if ((eb->pushbutton.arm_color == eb->primitive.top_shadow_color) 1199 || (eb->pushbutton.arm_color == eb->primitive.bottom_shadow_color)) 1200 fill = 1; 1201 1202 if (eb->pushbutton.compatible) 1203 adjust = eb->pushbutton.show_as_default; 1204 else 1205 adjust = eb->pushbutton.default_button_shadow_thickness; 1206 1207 if (adjust > 0) 1208 { 1209 adjust = adjust + eb->primitive.shadow_thickness; 1210 adjust = (adjust << 1); 1211 dx = eb->primitive.highlight_thickness + adjust + fill; 1212 } 1213 else 1214 dx = (eb->primitive.highlight_thickness 1215 + eb->primitive.shadow_thickness + fill); 1216 1217 box.x = dx; 1218 box.y = dx; 1219 adjust = (dx << 1); 1220 box.width = eb->core.width - adjust; 1221 box.height = eb->core.height - adjust; 1222 1223 /* 1224 * Redraw the background. 1225 */ 1226 if (!Lab_IsMenupane(eb)) 1227 { 1228 GC gc; 1229 1230 /* Don't shade if the button contains a label with a pixmap, since 1231 * there is no variant of the label available with the needed 1232 * background. 1233 */ 1234 if (eb->pushbutton.armed && eb->pushbutton.fill_on_arm) 1235 { 1236 if (eb->label.label_type == (int)XmPIXMAP) 1237 { 1238 if (eb->pushbutton.arm_pixmap != XmUNSPECIFIED_PIXMAP) 1239 gc = eb->pushbutton.fill_gc; 1240 else 1241 gc = eb->pushbutton.background_gc; 1242 } 1243 else 1244 gc = eb->pushbutton.fill_gc; 1245 } 1246 else 1247 gc = eb->pushbutton.background_gc; 1248 /* really need to fill with background if not armed ? */ 1249 if (gc) 1250 XFillRectangle(XtDisplay(eb), XtWindow(eb), gc, 1251 box.x, box.y, box.width, box.height); 1252 } 1253 1254 draw_label(eb, event, region); 1255 1256 if (Lab_IsMenupane(eb)) 1257 { 1258 if (eb->pushbutton.armed) 1259 (*(((XmPushButtonWidgetClass)XtClass(eb)) 1260 ->primitive_class.border_highlight))(w); 1261 draw_pixmap(eb, event, region); 1262 } 1263 else 1264 { 1265 adjust = 0; 1266 1267#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1268 /* 1269 * NOTE: PushButton has two types of shadows: primitive-shadow and 1270 * default-button-shadow. If pushbutton is in a menu only primitive 1271 * shadows are drawn. 1272 */ 1273 switch (default_button_emphasis) 1274 { 1275 case XmEXTERNAL_HIGHLIGHT: 1276 adjust = (eb->primitive.highlight_thickness - 1277 (eb->pushbutton.default_button_shadow_thickness 1278 ? Xm3D_ENHANCE_PIXEL : 0)); 1279 break; 1280 1281 case XmINTERNAL_HIGHLIGHT: 1282 break; 1283 1284 default: 1285 assert(FALSE); 1286 return; 1287 } 1288#endif 1289 1290 /* 1291 * Clear the area not occupied by label with parents background color. 1292 * Label will invoke BorderUnhighlight() on the highlight_thickness 1293 * area, which is redundant when XmEXTERNAL_HIGHLIGHT default button 1294 * shadow emphasis is used. 1295 */ 1296 if (box.x > adjust) 1297 { 1298 int borderwidth =box.x - adjust; 1299 int rectwidth = eb->core.width - 2 * adjust; 1300 int rectheight = eb->core.height - 2 * adjust; 1301 1302 if (XmIsManager(XtParent(eb))) 1303 { 1304 XmeDrawHighlight(XtDisplay(eb), XtWindow(eb), 1305 XmParentBackgroundGC(eb), 1306 adjust, adjust, rectwidth, rectheight, borderwidth); 1307 } 1308 else 1309 { 1310 XmeClearBorder(XtDisplay(eb), XtWindow(eb), 1311 adjust, adjust, rectwidth, rectheight, borderwidth); 1312 } 1313 1314#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1315 switch (default_button_emphasis) 1316 { 1317 case XmINTERNAL_HIGHLIGHT: 1318 /* The call above erases the border highlighting. */ 1319 if (eb->primitive.highlight_drawn) 1320 (*(((XmPushButtonWidgetClass) XtClass (eb)) 1321 ->primitive_class.border_highlight)) ((Widget) eb) ; 1322 break; 1323 1324 default: 1325 break; 1326 } 1327#endif 1328 } 1329 1330 if (eb->pushbutton.default_button_shadow_thickness) 1331 { 1332 if (eb->pushbutton.show_as_default) 1333 { 1334 /* 1335 * - get the topShadowColor and bottomShadowColor from the 1336 * parent; use those colors to construct top and bottom gc; 1337 * use these GCs to draw the shadows of the button. 1338 * 1339 * - Should not be called if pushbutton is in a row column or 1340 * in a menu. 1341 * 1342 * - Should be called only if a defaultbuttonshadow is to be 1343 * drawn. 1344 */ 1345 GC top_gc; 1346 GC bottom_gc; 1347 int default_button_shadow_thickness; 1348 int x, y, width, height, delta; 1349 Widget parent; 1350 1351 if (eb->pushbutton.compatible 1352 && (eb->pushbutton.show_as_default == 0)) 1353 return; 1354 1355 if (!eb->pushbutton.compatible 1356 && (eb->pushbutton.default_button_shadow_thickness 1357 == 0)) 1358 return; 1359 1360 delta = eb->primitive.highlight_thickness; 1361 1362 /* 1363 * May need more complex computation for getting the GCs. 1364 */ 1365 parent = XtParent(eb); 1366 if (XmIsManager(parent)) 1367 { 1368 /* Use the parent's GC so monochrome works. */ 1369 bottom_gc = XmParentTopShadowGC(eb); 1370 top_gc = XmParentBottomShadowGC(eb); 1371 } 1372 else 1373 { 1374 /* Use your own pixel for drawing. */ 1375 bottom_gc = eb->primitive.top_shadow_GC; 1376 top_gc = eb->primitive.bottom_shadow_GC; 1377 } 1378 1379 if ((bottom_gc == None) || (top_gc == None)) 1380 return; 1381 1382 1383 if (eb->pushbutton.compatible) 1384 default_button_shadow_thickness = 1385 eb->pushbutton.show_as_default; 1386 else 1387 default_button_shadow_thickness = 1388 eb->pushbutton.default_button_shadow_thickness; 1389 1390#if !defined(LESSTIF_VERSION) && (XmVersion > 1002) 1391 /* 1392 * Compute location of bounding box to contain the 1393 * defaultButtonShadow. 1394 */ 1395 switch (default_button_emphasis) 1396 { 1397 case XmEXTERNAL_HIGHLIGHT: 1398 delta = eb->primitive.highlight_thickness; 1399 break; 1400 1401 case XmINTERNAL_HIGHLIGHT: 1402 delta = Xm3D_ENHANCE_PIXEL; 1403 break; 1404 1405 default: 1406 assert(FALSE); 1407 return; 1408 } 1409#endif 1410 1411 x = y = delta; 1412 width = eb->core.width - 2 * delta; 1413 height = eb->core.height - 2 * delta; 1414 1415 if ((width > 0) && (height > 0)) 1416 XmeDrawShadows(XtDisplay(eb), XtWindow(eb), 1417 top_gc, bottom_gc, x, y, width, height, 1418 default_button_shadow_thickness, 1419 (unsigned)XmSHADOW_OUT); 1420 } 1421 } 1422 1423 if (eb->primitive.highlight_drawn) 1424 draw_shadows(eb); 1425 draw_pixmap(eb, event, region); 1426 } 1427} 1428 1429 static void 1430BorderHighlight(Widget w) 1431{ 1432 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)w; 1433 1434 (*(xmPushButtonClassRec.primitive_class.border_highlight))(w); 1435 draw_pixmap(eb, NULL, NULL); 1436} 1437 1438 static void 1439BorderUnhighlight(Widget w) 1440{ 1441 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)w; 1442 1443 (*(xmPushButtonClassRec.primitive_class.border_unhighlight))(w); 1444 draw_pixmap(eb, NULL, NULL); 1445} 1446 1447#endif /* FEAT_TOOLBAR */ 1448