blob: cd60794188ea267309ad3239ec507c14ab8906d9 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00002 *
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
Bram Moolenaar88c86eb2019-01-17 17:13:30 +010038# ifdef HAVE_X11_XPM_H
39# ifdef VMS
40# include <xpm.h>
41# else
42# include <X11/xpm.h>
43# endif
44# endif
Bram Moolenaarb7fcef52005-01-02 11:31:05 +000045#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
Bram Moolenaar5fffc132006-05-13 15:22:39 +000056 * implementation. Also missing in Motif 1.2 and earlier.
Bram Moolenaarb7fcef52005-01-02 11:31:05 +000057 *
58 * We neither use XmeGetPixmapData or _XmGetPixmapData, since with LessTif the
Bram Moolenaarc4568ab2018-11-16 16:21:05 +010059 * pixmap will not appear in its caches properly. We cache the interesting
Bram Moolenaarb7fcef52005-01-02 11:31:05 +000060 * values in XmEnhancedButtonPart instead ourself.
61 */
Bram Moolenaar5fffc132006-05-13 15:22:39 +000062#if defined(LESSTIF_VERSION) || (XmVersion <= 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +000063# 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
82extern Boolean _XmGetInDragMode(Widget widget);
83extern void _XmPrimitiveEnter(Widget wid,
84 XEvent * event,
85 String * params, Cardinal * num_params);
86extern void _XmPrimitiveLeave(Widget wid,
87 XEvent * event,
88 String * params, Cardinal * num_params);
89extern void _XmSetFocusFlag(Widget w, unsigned int mask, Boolean value);
90extern void _XmCalcLabelDimensions(Widget wid);
91
92/*
93 * Declaration of class methods.
94 */
95static void Destroy(Widget w);
96static void Initialize(Widget rq, Widget eb, ArgList args, Cardinal *n);
97static Boolean SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *n);
98static void Redisplay(Widget, XEvent *, Region);
99
100/*
101 * Declaration of action methods.
102 */
103static void Enter(Widget, XEvent *, String *, Cardinal *);
104static void Leave(Widget, XEvent *, String *, Cardinal *);
105static void BorderHighlight(Widget);
106static void BorderUnhighlight(Widget);
107
108/*
109 * 4 x 4 stipple for desensitized widgets
110 */
111#define stipple_width 4
112#define stipple_height 4
113static char stipple_bits[] = { 0x0a, 0x05, 0x0a, 0x05 };
114#define STIPPLE_BITMAP xmEnhancedButtonClassRec.enhancedbutton_class.stipple_bitmap
115
116/*
117 * Override actions.
118 */
119static XtActionsRec actionsList[] =
120{
121 {"Enter", Enter},
122 {"Leave", Leave},
123};
124
125static 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
Bram Moolenaar8b610cf2006-10-24 20:29:10 +0000147/* 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. */
149XmPrimitiveClassExtRec xmEnhancedButtonPrimClassExtRec =
150{
151 /* next_extension */ NULL,
Bram Moolenaarcc448b32010-07-14 16:52:17 +0200152 /* record_type */ NULLQUARK,
153 /* version */ XmPrimitiveClassExtVersion,
154 /* record_size */ sizeof(XmPrimitiveClassExtRec),
155 /* widget_baseline */ XmInheritBaselineProc,
Bram Moolenaar8b610cf2006-10-24 20:29:10 +0000156 /* widget_display_rect */ XmInheritDisplayRectProc,
157 /* widget_margins */ NULL
158};
159
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000160XmEnhancedButtonClassRec xmEnhancedButtonClassRec =
161{
162 {
163 /* core_class fields */
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000164 /* superclass */ (WidgetClass) & xmPushButtonClassRec,
165 /* class_name */ "XmEnhancedButton",
166 /* widget_size */ sizeof(XmEnhancedButtonRec),
167 /* class_initialize */ NULL,
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000168 /* class_part_initialize */ NULL,
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000169 /* 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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000196 },
197
198 /* primitive_class fields */
199 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000200 /* 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,
Bram Moolenaar8b610cf2006-10-24 20:29:10 +0000206 /* extension */ (XtPointer)&xmEnhancedButtonPrimClassExtRec,
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000207 },
208
209 /* label_class fields */
210 {
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000211 /* setOverrideCallback */ XmInheritSetOverrideCallback,
212 /* menuProcs */ XmInheritMenuProc,
213 /* translations */ XtInheritTranslations,
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000214 /* 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
229WidgetClass xmEnhancedButtonWidgetClass =
230 (WidgetClass)&xmEnhancedButtonClassRec;
231
232
233/*
234 * Create a slightly fainter pixmap to be shown on button entry.
235 */
236 static unsigned short
237bump_color(unsigned short value)
238{
239 int tmp = 2 * (((int) value - 65535) / 3) + 65535;
240
241 return tmp;
242}
243
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000244 static int
245alloc_color(Display *display,
246 Colormap colormap,
247 char *colorname,
248 XColor *xcolor,
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000249 void *closure UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000250{
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 */
266static 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
293set_pixmap(XmEnhancedButtonWidget eb)
294{
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000295 /* Configure defines XPMATTRIBUTES_TYPE as XpmAttributes or as
296 * XpmAttributes_21, depending on what is in Xm/XpmP.h. */
297 XPMATTRIBUTES_TYPE attr;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000298 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;
Bram Moolenaar7c626922005-02-07 22:01:03 +0000315 int status = 0;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000316 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;
Bram Moolenaar7c626922005-02-07 22:01:03 +0000322 char *fname = (char *) eb->enhancedbutton.pixmap_file;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000323 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;
Bram Moolenaar7c626922005-02-07 22:01:03 +0000337
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000338 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
Bram Moolenaar7c626922005-02-07 22:01:03 +0000346 /* 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
Bram Moolenaar84a05ac2013-05-06 04:24:17 +0200354 /* Setup color substitution table. */
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000355 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
Bram Moolenaar7c626922005-02-07 22:01:03 +0000370 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);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000374
Bram Moolenaar7c626922005-02-07 22:01:03 +0000375 /* If something failed, we will fill in the default pixmap. */
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000376 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
Bram Moolenaara53c60d2012-06-29 13:19:27 +0200384 /* TODO: does the shift depend on label_location somehow? */
385 shift = eb->primitive.shadow_thickness / 2;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000386
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;
Bram Moolenaar6f192452007-11-08 19:49:02 +0000400#ifdef XpmAllocColor /* SGI doesn't have it */
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000401 attr.valuemask = XpmColorSymbols | XpmCloseness | XpmAllocColor;
Bram Moolenaar6f192452007-11-08 19:49:02 +0000402 attr.alloc_color = alloc_color;
403#else
404 attr.valuemask = XpmColorSymbols | XpmCloseness;
405#endif
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000406 attr.closeness = 65535; /* accuracy isn't crucial */
407 attr.colorsymbols = color;
408 attr.numsymbols = XtNumber(color);
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000409
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
489draw_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
Bram Moolenaar6a1a3702006-05-13 13:41:03 +0000502#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000503 {
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
535draw_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
550draw_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 {
Bram Moolenaarb23c3382005-01-31 19:09:12 +0000562#ifdef UNHIGHLIGHTT
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000563 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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000600 static void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000601draw_pixmap(XmEnhancedButtonWidget eb,
602 XEvent *event UNUSED,
603 Region region UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000604{
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;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000647 if (depth == (int)eb->core.depth)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000648 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
659draw_label(XmEnhancedButtonWidget eb, XEvent *event, Region region)
660{
661 GC tmp_gc = NULL;
662 Boolean replaceGC = False;
663 Boolean deadjusted = False;
Bram Moolenaar6a1a3702006-05-13 13:41:03 +0000664#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000665 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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000737 static void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000738Enter(Widget wid,
739 XEvent *event,
740 String *params UNUSED,
741 Cardinal *num_params UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000742{
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 {
Bram Moolenaar6a1a3702006-05-13 13:41:03 +0000751#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000752 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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000826 static void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000827Leave(Widget wid,
828 XEvent *event,
829 String *params UNUSED,
830 Cardinal *num_params UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000831{
832 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)wid;
833 XmPushButtonCallbackStruct call_value;
834
835 if (Lab_IsMenupane(eb))
836 {
Bram Moolenaar6a1a3702006-05-13 13:41:03 +0000837#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000838 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
911set_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 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +0200928 * Please note that we manipulate the width only in case of push buttons
929 * not used in the context of a menu pane.
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000930 */
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
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000986 static void
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000987Initialize(Widget rq, Widget ebw, ArgList args UNUSED, Cardinal *n UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +0000988{
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
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001015 /* FIXME: this is not the perfect way to deal with menus, which do not
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001016 * 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
1033free_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
1057Destroy(Widget w)
1058{
1059 if (!XmIsEnhancedButton(w))
1060 return;
1061
1062 free_pixmaps((XmEnhancedButtonWidget)w);
1063}
1064
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001065 static Boolean
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001066SetValues(Widget current,
1067 Widget request UNUSED,
1068 Widget new,
1069 ArgList args UNUSED,
1070 Cardinal *n UNUSED)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001071{
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 /*
Bram Moolenaara38edcd2007-05-10 17:46:55 +00001107 * Artificially let the highlight appear if the mouse is over us.
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001108 */
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
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001120 if ((win_x > (int)r_width) || (win_y > (int)r_height))
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001121 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
1176Redisplay(Widget w, XEvent *event, Region region)
1177{
1178 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget) w;
Bram Moolenaar6a1a3702006-05-13 13:41:03 +00001179#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001180 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
Bram Moolenaar6a1a3702006-05-13 13:41:03 +00001191#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001192 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 {
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001268 adjust = 0;
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001269
Bram Moolenaar6a1a3702006-05-13 13:41:03 +00001270#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001271 /*
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 -
Bram Moolenaarfe86f2d2008-11-28 20:29:07 +00001280 (eb->pushbutton.default_button_shadow_thickness
1281 ? Xm3D_ENHANCE_PIXEL : 0));
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001282 break;
1283
1284 case XmINTERNAL_HIGHLIGHT:
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001285 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
Bram Moolenaar6a1a3702006-05-13 13:41:03 +00001317#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001318 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
Bram Moolenaar6a1a3702006-05-13 13:41:03 +00001393#if !defined(LESSTIF_VERSION) && (XmVersion > 1002)
Bram Moolenaarb7fcef52005-01-02 11:31:05 +00001394 /*
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
1433BorderHighlight(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
1442BorderUnhighlight(Widget w)
1443{
1444 XmEnhancedButtonWidget eb = (XmEnhancedButtonWidget)w;
1445
1446 (*(xmPushButtonClassRec.primitive_class.border_unhighlight))(w);
1447 draw_pixmap(eb, NULL, NULL);
1448}
Bram Moolenaar3a7c85b2005-02-05 21:39:53 +00001449
1450#endif /* FEAT_TOOLBAR */