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