1 /***********************************************************
2 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4 Copyright 1992, 1993 by Kaleb Keithley
5 
6                         All Rights Reserved
7 
8 Permission to use, copy, modify, and distribute this software and its
9 documentation for any purpose and without fee is hereby granted,
10 provided that the above copyright notice appear in all copies and that
11 both that copyright notice and this permission notice appear in
12 supporting documentation, and that the names of Digital, MIT, or Kaleb
13 Keithley not be used in advertising or publicity pertaining to distribution
14 of the software without specific, written prior permission.
15 
16 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 SOFTWARE.
23 
24 ******************************************************************/
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include <X11/Xaw3dxft/Xaw3dP.h>
30 #include <X11/Xlib.h>
31 #include <X11/StringDefs.h>
32 #include <X11/IntrinsicP.h>
33 #include <X11/Xaw3dxft/XawInit.h>
34 #include <X11/Xaw3dxft/ThreeDP.h>
35 #include <X11/Xaw3dxft/SimpleMenP.h>
36 #include <X11/Xaw3dxft/SmeThreeDP.h>
37 #include <X11/Xosdefs.h>
38 
39 /* Initialization of defaults */
40 
41 #define XtNtopShadowPixmap "topShadowPixmap"
42 #define XtCTopShadowPixmap "TopShadowPixmap"
43 #define XtNbottomShadowPixmap "bottomShadowPixmap"
44 #define XtCBottomShadowPixmap "BottomShadowPixmap"
45 #define XtNshadowed "shadowed"
46 #define XtCShadowed "Shadowed"
47 
48 #define offset(field) XtOffsetOf(SmeThreeDRec, field)
49 
50 static XtResource resources[] = {
51     {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
52 	offset(sme_threeD.shadow_width), XtRImmediate, (XtPointer) 2},
53     {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel),
54 	offset(sme_threeD.top_shadow_pixel), XtRString, XtDefaultForeground},
55     {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel),
56 	offset(sme_threeD.bot_shadow_pixel), XtRString, XtDefaultForeground},
57     {XtNtopShadowPixmap, XtCTopShadowPixmap, XtRPixmap, sizeof(Pixmap),
58 	offset(sme_threeD.top_shadow_pxmap), XtRImmediate, (XtPointer) NULL},
59     {XtNbottomShadowPixmap, XtCBottomShadowPixmap, XtRPixmap, sizeof(Pixmap),
60 	offset(sme_threeD.bot_shadow_pxmap), XtRImmediate, (XtPointer) NULL},
61     {XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, sizeof(int),
62 	offset(sme_threeD.top_shadow_contrast), XtRImmediate, (XtPointer) 20},
63     {XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, sizeof(int),
64 	offset(sme_threeD.bot_shadow_contrast), XtRImmediate, (XtPointer) 40},
65     {XtNuserData, XtCUserData, XtRPointer, sizeof(XtPointer),
66 	offset(sme_threeD.user_data), XtRPointer, (XtPointer) NULL},
67     {XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, sizeof(Boolean),
68 	offset(sme_threeD.be_nice_to_cmap), XtRImmediate, (XtPointer) True},
69     {XtNshadowed, XtCShadowed, XtRBoolean, sizeof(Boolean),
70 	offset(sme_threeD.shadowed), XtRImmediate, (XtPointer) False},
71     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
72 	XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
73 	(XtPointer)0}
74 };
75 
76 #undef offset
77 
78 static void Initialize(Widget, Widget, ArgList, Cardinal *);
79 static void Destroy(Widget);
80 static void ClassPartInitialize(WidgetClass);
81 static void _XawSme3dDrawShadows(Widget);
82 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
83 
84 SmeThreeDClassRec smeThreeDClassRec = {
85     { /* core fields */
86     /* superclass		*/	(WidgetClass) &smeClassRec,
87     /* class_name		*/	"SmeThreeD",
88     /* widget_size		*/	sizeof(SmeThreeDRec),
89     /* class_initialize		*/	NULL,
90     /* class_part_initialize	*/	ClassPartInitialize,
91     /* class_inited		*/	FALSE,
92     /* initialize		*/	Initialize,
93     /* initialize_hook		*/	NULL,
94     /* realize			*/	NULL,
95     /* actions			*/	NULL,
96     /* num_actions		*/	0,
97     /* resources		*/	resources,
98     /* resource_count		*/	XtNumber(resources),
99     /* xrm_class		*/	NULLQUARK,
100     /* compress_motion		*/	TRUE,
101     /* compress_exposure	*/	TRUE,
102     /* compress_enterleave	*/	TRUE,
103     /* visible_interest		*/	FALSE,
104     /* destroy			*/	Destroy,
105     /* resize			*/	XtInheritResize,
106     /* expose			*/	NULL,
107     /* set_values		*/	SetValues,
108     /* set_values_hook		*/	NULL,
109     /* set_values_almost	*/	XtInheritSetValuesAlmost,
110     /* get_values_hook		*/	NULL,
111     /* accept_focus		*/	NULL,
112     /* version			*/	XtVersion,
113     /* callback_private		*/	NULL,
114     /* tm_table			*/	NULL,
115     /* query_geometry           */	XtInheritQueryGeometry,
116     /* display_accelerator      */	NULL,
117     /* extension                */	NULL
118     },
119     { /* Menu Entry fields */
120     /* highlight                */      XtInheritHighlight,
121     /* unhighlight              */      XtInheritUnhighlight,
122     /* notify                   */      XtInheritNotify,
123     /* extension                */      NULL
124     },
125     { /* threeD fields */
126     /* shadow draw              */      _XawSme3dDrawShadows
127     }
128 };
129 
130 WidgetClass smeThreeDObjectClass = (WidgetClass) &smeThreeDClassRec;
131 
132 /****************************************************************
133  *
134  * Private Procedures
135  *
136  ****************************************************************/
137 
138 
139 #define shadowpm_width 8
140 #define shadowpm_height 8
141 static char shadowpm_bits[] = {
142     0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55};
143 
144 static char mtshadowpm_bits[] = {
145     0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24};
146 
147 static char mbshadowpm_bits[] = {
148     0x6d, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb};
149 
150 /* ARGSUSED */
151 static void
AllocTopShadowGC(Widget w)152 AllocTopShadowGC (Widget w)
153 {
154     SmeThreeDObject	tdo = (SmeThreeDObject) w;
155     Screen		*scn = XtScreenOfObject (w);
156     XtGCMask		valuemask;
157     XGCValues		myXGCV;
158 
159     if (tdo->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) {
160 	valuemask = GCTile | GCFillStyle;
161 	myXGCV.tile = tdo->sme_threeD.top_shadow_pxmap;
162 	myXGCV.fill_style = FillTiled;
163     } else {
164 	valuemask = GCForeground;
165 	myXGCV.foreground = tdo->sme_threeD.top_shadow_pixel;
166     }
167     tdo->sme_threeD.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
168 }
169 
170 /* ARGSUSED */
171 static void
AllocBotShadowGC(Widget w)172 AllocBotShadowGC (Widget w)
173 {
174     SmeThreeDObject	tdo = (SmeThreeDObject) w;
175     Screen		*scn = XtScreenOfObject (w);
176     XtGCMask		valuemask;
177     XGCValues		myXGCV;
178 
179     if (tdo->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) {
180 	valuemask = GCTile | GCFillStyle;
181 	myXGCV.tile = tdo->sme_threeD.bot_shadow_pxmap;
182 	myXGCV.fill_style = FillTiled;
183     } else {
184 	valuemask = GCForeground;
185 	myXGCV.foreground = tdo->sme_threeD.bot_shadow_pixel;
186     }
187     tdo->sme_threeD.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
188 }
189 
190 /* ARGSUSED */
191 static void
AllocEraseGC(Widget w)192 AllocEraseGC (Widget w)
193 {
194     Widget		parent = XtParent (w);
195     SmeThreeDObject	tdo = (SmeThreeDObject) w;
196     XtGCMask		valuemask;
197     XGCValues		myXGCV;
198 
199     valuemask = GCForeground;
200     myXGCV.foreground = parent->core.background_pixel;
201     tdo->sme_threeD.erase_GC = XtGetGC(w, valuemask, &myXGCV);
202 }
203 
204 /* ARGSUSED */
205 static void
AllocTopShadowPixmap(Widget new)206 AllocTopShadowPixmap (Widget new)
207 {
208     SmeThreeDObject	tdo = (SmeThreeDObject) new;
209     Widget		parent = XtParent (new);
210     Display		*dpy = XtDisplayOfObject (new);
211     Screen		*scn = XtScreenOfObject (new);
212     unsigned long	top_fg_pixel = 0, top_bg_pixel = 0;
213     char		*pm_data;
214     Boolean		create_pixmap = FALSE;
215 
216     /*
217      * I know, we're going to create two pixmaps for each and every
218      * shadow'd widget.  Yeuck.  I'm semi-relying on server side
219      * pixmap cacheing.
220      */
221 
222     if (DefaultDepthOfScreen (scn) == 1) {
223 	top_fg_pixel = BlackPixelOfScreen (scn);
224 	top_bg_pixel = WhitePixelOfScreen (scn);
225 	pm_data = mtshadowpm_bits;
226 	create_pixmap = TRUE;
227     } else if (tdo->sme_threeD.be_nice_to_cmap) {
228 	if (parent->core.background_pixel == WhitePixelOfScreen (scn)) {
229 	    top_fg_pixel = WhitePixelOfScreen (scn);
230 	    top_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
231 	} else if (parent->core.background_pixel == BlackPixelOfScreen (scn)) {
232 	    top_fg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
233 	    top_bg_pixel = WhitePixelOfScreen (scn);
234 	} else {
235 	    top_fg_pixel = parent->core.background_pixel;
236 	    top_bg_pixel = WhitePixelOfScreen (scn);
237 	}
238 #ifndef XAW_GRAY_BLKWHT_STIPPLES
239 	if (parent->core.background_pixel == WhitePixelOfScreen (scn) ||
240 	    parent->core.background_pixel == BlackPixelOfScreen (scn)) {
241 	    pm_data = mtshadowpm_bits;
242        } else
243 #endif
244 	    pm_data = shadowpm_bits;
245 
246 	create_pixmap = TRUE;
247     }
248 
249     if (create_pixmap)
250 	tdo->sme_threeD.top_shadow_pxmap = XCreatePixmapFromBitmapData (dpy,
251 			RootWindowOfScreen (scn),
252 			pm_data,
253 			shadowpm_width,
254 			shadowpm_height,
255 			top_fg_pixel,
256 			top_bg_pixel,
257 			DefaultDepthOfScreen (scn));
258 }
259 
260 /* ARGSUSED */
261 static void
AllocBotShadowPixmap(Widget new)262 AllocBotShadowPixmap (Widget new)
263 {
264     SmeThreeDObject	tdo = (SmeThreeDObject) new;
265     Widget		parent = XtParent (new);
266     Display		*dpy = XtDisplayOfObject (new);
267     Screen		*scn = XtScreenOfObject (new);
268     unsigned long	bot_fg_pixel = 0, bot_bg_pixel = 0;
269     char		*pm_data;
270     Boolean		create_pixmap = FALSE;
271 
272     if (DefaultDepthOfScreen (scn) == 1) {
273 	bot_fg_pixel = BlackPixelOfScreen (scn);
274 	bot_bg_pixel = WhitePixelOfScreen (scn);
275 	pm_data = mbshadowpm_bits;
276 	create_pixmap = TRUE;
277     } else if (tdo->sme_threeD.be_nice_to_cmap) {
278 	if (parent->core.background_pixel == WhitePixelOfScreen (scn)) {
279 	    bot_fg_pixel = grayPixel( WhitePixelOfScreen (scn), dpy, scn);
280 	    bot_bg_pixel = BlackPixelOfScreen (scn);
281 	} else if (parent->core.background_pixel == BlackPixelOfScreen (scn)) {
282 	    bot_fg_pixel = BlackPixelOfScreen (scn);
283 	    bot_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
284 	} else {
285 	    bot_fg_pixel = parent->core.background_pixel;
286 	    bot_bg_pixel = BlackPixelOfScreen (scn);
287 	}
288 #ifndef XAW_GRAY_BLKWHT_STIPPLES
289 	if (parent->core.background_pixel == WhitePixelOfScreen (scn) ||
290 	    parent->core.background_pixel == BlackPixelOfScreen (scn)) {
291 	    pm_data = mbshadowpm_bits;
292 	} else
293 #endif
294 	    pm_data = shadowpm_bits;
295 
296 	create_pixmap = TRUE;
297     }
298 
299     if (create_pixmap)
300 	tdo->sme_threeD.bot_shadow_pxmap = XCreatePixmapFromBitmapData (dpy,
301 			RootWindowOfScreen (scn),
302 			pm_data,
303 			shadowpm_width,
304 			shadowpm_height,
305 			bot_fg_pixel,
306 			bot_bg_pixel,
307 			DefaultDepthOfScreen (scn));
308 }
309 
310 /* ARGSUSED */
311 void
XawSme3dComputeTopShadowRGB(Widget new,XColor * xcol_out)312 XawSme3dComputeTopShadowRGB (Widget new, XColor *xcol_out)
313 {
314     if (XtIsSubclass (new, smeThreeDObjectClass)) {
315 	SmeThreeDObject tdo = (SmeThreeDObject) new;
316 	Widget w = XtParent (new);
317 	XColor get_c;
318 	double contrast;
319 	Display *dpy = XtDisplayOfObject (new);
320 	Screen *scn = XtScreenOfObject (new);
321 	Colormap cmap = w->core.colormap;
322 
323 	get_c.pixel = w->core.background_pixel;
324 	if (get_c.pixel == WhitePixelOfScreen (scn) ||
325 	    get_c.pixel == BlackPixelOfScreen (scn)) {
326 	    contrast = (100 - tdo->sme_threeD.top_shadow_contrast) / 100.0;
327 	    xcol_out->red   = contrast * 65535.0;
328 	    xcol_out->green = contrast * 65535.0;
329 	    xcol_out->blue  = contrast * 65535.0;
330 	} else {
331 	    contrast = 1.0 + tdo->sme_threeD.top_shadow_contrast / 100.0;
332 	    XQueryColor (dpy, cmap, &get_c);
333 #define MIN(x,y) (unsigned short) (x < y) ? x : y
334 	    xcol_out->red   = MIN (65535, (int) (contrast * (double) get_c.red));
335 	    xcol_out->green = MIN (65535, (int) (contrast * (double) get_c.green));
336 	    xcol_out->blue  = MIN (65535, (int) (contrast * (double) get_c.blue));
337 #undef MIN
338 	}
339     } else
340 	xcol_out->red = xcol_out->green = xcol_out->blue = 0;
341 }
342 
343 /* ARGSUSED */
344 static void
AllocTopShadowPixel(Widget new)345 AllocTopShadowPixel (Widget new)
346 {
347     XColor set_c;
348     SmeThreeDObject tdo = (SmeThreeDObject) new;
349     Widget w = XtParent (new);
350     Display *dpy = XtDisplayOfObject (new);
351     Colormap cmap = w->core.colormap;
352 
353     XawSme3dComputeTopShadowRGB (new, &set_c);
354     (void) XAllocColor (dpy, cmap, &set_c);
355     tdo->sme_threeD.top_shadow_pixel = set_c.pixel;
356 }
357 
358 
359 /* ARGSUSED */
360 void
XawSme3dComputeBottomShadowRGB(Widget new,XColor * xcol_out)361 XawSme3dComputeBottomShadowRGB (Widget new, XColor *xcol_out)
362 {
363     if (XtIsSubclass (new, smeThreeDObjectClass)) {
364 	SmeThreeDObject tdo = (SmeThreeDObject) new;
365 	Widget w = XtParent (new);
366 	XColor get_c;
367 	double contrast;
368 	Display *dpy = XtDisplayOfObject (new);
369 	Screen *scn = XtScreenOfObject (new);
370 	Colormap cmap = w->core.colormap;
371 
372 	get_c.pixel = w->core.background_pixel;
373 	if (get_c.pixel == WhitePixelOfScreen (scn) ||
374 	    get_c.pixel == BlackPixelOfScreen (scn)) {
375 	    contrast = tdo->sme_threeD.bot_shadow_contrast / 100.0;
376 	    xcol_out->red   = contrast * 65535.0;
377 	    xcol_out->green = contrast * 65535.0;
378 	    xcol_out->blue  = contrast * 65535.0;
379 	} else {
380 	    XQueryColor (dpy, cmap, &get_c);
381 	    contrast = (100 - tdo->sme_threeD.bot_shadow_contrast) / 100.0;
382 	    xcol_out->red   = contrast * get_c.red;
383 	    xcol_out->green = contrast * get_c.green;
384 	    xcol_out->blue  = contrast * get_c.blue;
385 	}
386     } else
387 	xcol_out->red = xcol_out->green = xcol_out->blue = 0;
388 }
389 
390 /* ARGSUSED */
391 static void
AllocBotShadowPixel(Widget new)392 AllocBotShadowPixel (Widget new)
393 {
394     XColor set_c;
395     SmeThreeDObject tdo = (SmeThreeDObject) new;
396     Widget w = XtParent (new);
397     Display *dpy = XtDisplayOfObject (new);
398     Colormap cmap = w->core.colormap;
399 
400     XawSme3dComputeBottomShadowRGB (new, &set_c);
401     (void) XAllocColor (dpy, cmap, &set_c);
402     tdo->sme_threeD.bot_shadow_pixel = set_c.pixel;
403 }
404 
405 
406 /* ARGSUSED */
407 static void
ClassPartInitialize(WidgetClass wc)408 ClassPartInitialize (WidgetClass wc)
409 {
410     SmeThreeDClassRec *tdwc = (SmeThreeDClassRec *) wc;
411     SmeThreeDClassRec *super =
412 	(SmeThreeDClassRec *) tdwc->rect_class.superclass;
413 
414     if (tdwc->sme_threeD_class.shadowdraw == XtInheritXawSme3dShadowDraw)
415 	tdwc->sme_threeD_class.shadowdraw = super->sme_threeD_class.shadowdraw;
416 }
417 
418 /* ARGSUSED */
419 static void
Initialize(Widget request,Widget new,ArgList args,Cardinal * num_args)420 Initialize (Widget request, Widget new, ArgList args, Cardinal *num_args)
421 {
422     SmeThreeDObject 	w = (SmeThreeDObject) new;
423     Screen		*scr = XtScreenOfObject (new);
424 
425     if (w->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scr) == 1) {
426 	AllocTopShadowPixmap (new);
427 	AllocBotShadowPixmap (new);
428     } else {
429 	if (w->sme_threeD.top_shadow_pixel == w->sme_threeD.bot_shadow_pixel) {
430 	    AllocTopShadowPixel (new);
431 	    AllocBotShadowPixel (new);
432 	}
433 	w->sme_threeD.top_shadow_pxmap = w->sme_threeD.bot_shadow_pxmap = 0;
434     }
435     AllocTopShadowGC (new);
436     AllocBotShadowGC (new);
437     AllocEraseGC (new);
438 }
439 
440 static void
Destroy(Widget gw)441 Destroy (Widget gw)
442 {
443     SmeThreeDObject w = (SmeThreeDObject) gw;
444     XtReleaseGC (gw, w->sme_threeD.top_shadow_GC);
445     XtReleaseGC (gw, w->sme_threeD.bot_shadow_GC);
446     XtReleaseGC (gw, w->sme_threeD.erase_GC);
447     if (w->sme_threeD.top_shadow_pxmap)
448 	XFreePixmap (XtDisplayOfObject (gw), w->sme_threeD.top_shadow_pxmap);
449     if (w->sme_threeD.bot_shadow_pxmap)
450 	XFreePixmap (XtDisplayOfObject (gw), w->sme_threeD.bot_shadow_pxmap);
451 }
452 
453 /* ARGSUSED */
454 static Boolean
SetValues(Widget gcurrent,Widget grequest,Widget gnew,ArgList args,Cardinal * num_args)455 SetValues (Widget gcurrent, Widget grequest, Widget gnew, ArgList args, Cardinal *num_args)
456 {
457     SmeThreeDObject current = (SmeThreeDObject) gcurrent;
458     SmeThreeDObject new = (SmeThreeDObject) gnew;
459     Boolean redisplay = FALSE;
460     Boolean alloc_top_pixel = FALSE;
461     Boolean alloc_bot_pixel = FALSE;
462     Boolean alloc_top_pixmap = FALSE;
463     Boolean alloc_bot_pixmap = FALSE;
464 
465 #if 0
466     (*threeDWidgetClass->core_class.superclass->core_class.set_values)
467 	(gcurrent, grequest, gnew, NULL, 0);
468 #endif
469     if (new->sme_threeD.shadow_width != current->sme_threeD.shadow_width)
470 	redisplay = TRUE;
471     if (new->sme_threeD.be_nice_to_cmap != current->sme_threeD.be_nice_to_cmap) {
472 	if (new->sme_threeD.be_nice_to_cmap) {
473 	    alloc_top_pixmap = TRUE;
474 	    alloc_bot_pixmap = TRUE;
475 	} else {
476 	    alloc_top_pixel = TRUE;
477 	    alloc_bot_pixel = TRUE;
478 	}
479 	redisplay = TRUE;
480     }
481     if (!new->sme_threeD.be_nice_to_cmap &&
482 	new->sme_threeD.top_shadow_contrast != current->sme_threeD.top_shadow_contrast)
483 	alloc_top_pixel = TRUE;
484     if (!new->sme_threeD.be_nice_to_cmap &&
485 	new->sme_threeD.bot_shadow_contrast != current->sme_threeD.bot_shadow_contrast)
486 	alloc_bot_pixel = TRUE;
487     if (alloc_top_pixel)
488 	AllocTopShadowPixel (gnew);
489     if (alloc_bot_pixel)
490 	AllocBotShadowPixel (gnew);
491     if (alloc_top_pixmap)
492 	AllocTopShadowPixmap (gnew);
493     if (alloc_bot_pixmap)
494 	AllocBotShadowPixmap (gnew);
495     if (!new->sme_threeD.be_nice_to_cmap &&
496 	new->sme_threeD.top_shadow_pixel != current->sme_threeD.top_shadow_pixel)
497 	alloc_top_pixel = TRUE;
498     if (!new->sme_threeD.be_nice_to_cmap &&
499 	new->sme_threeD.bot_shadow_pixel != current->sme_threeD.bot_shadow_pixel)
500 	alloc_bot_pixel = TRUE;
501     if (new->sme_threeD.be_nice_to_cmap) {
502 	if (alloc_top_pixmap) {
503 	    XtReleaseGC (gcurrent, current->sme_threeD.top_shadow_GC);
504 	    AllocTopShadowGC (gnew);
505 	    redisplay = True;
506 	}
507 	if (alloc_bot_pixmap) {
508 	    XtReleaseGC (gcurrent, current->sme_threeD.bot_shadow_GC);
509 	    AllocBotShadowGC (gnew);
510 	    redisplay = True;
511 	}
512     } else {
513 	if (alloc_top_pixel) {
514 	    if (new->sme_threeD.top_shadow_pxmap) {
515 		XFreePixmap (XtDisplayOfObject (gnew), new->sme_threeD.top_shadow_pxmap);
516 		new->sme_threeD.top_shadow_pxmap = (Pixmap) NULL;
517 	    }
518 	    XtReleaseGC (gcurrent, current->sme_threeD.top_shadow_GC);
519 	    AllocTopShadowGC (gnew);
520 	    redisplay = True;
521 	}
522 	if (alloc_bot_pixel) {
523 	    if (new->sme_threeD.bot_shadow_pxmap) {
524 		XFreePixmap (XtDisplayOfObject (gnew), new->sme_threeD.bot_shadow_pxmap);
525 		new->sme_threeD.bot_shadow_pxmap = (Pixmap) NULL;
526 	    }
527 	    XtReleaseGC (gcurrent, current->sme_threeD.bot_shadow_GC);
528 	    AllocBotShadowGC (gnew);
529 	    redisplay = True;
530 	}
531     }
532     return (redisplay);
533 }
534 
535 /* ARGSUSED */
536 static void
_XawSme3dDrawShadows(Widget gw)537 _XawSme3dDrawShadows(Widget gw)
538 {
539     SmeThreeDObject tdo = (SmeThreeDObject) gw;
540     SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(gw);
541     ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD;
542     Dimension s = tdo->sme_threeD.shadow_width;
543     Dimension ps = tdw->threeD.shadow_width;
544     XPoint pt[6];
545 
546     /*
547      * draw the shadows using the core part width and height,
548      * and the threeD part shadow_width.
549      *
550      * no point to do anything if the shadow_width is 0 or the
551      * widget has not been realized.
552      */
553     if (s > 0 && XtIsRealized(gw))
554     {
555 	Dimension	h = tdo->rectangle.height;
556 	Dimension	w = tdo->rectangle.width - ps;
557 	Dimension	x = tdo->rectangle.x + ps;
558 	Dimension	y = tdo->rectangle.y;
559 	Display		*dpy = XtDisplayOfObject(gw);
560 	Window		win = XtWindowOfObject(gw);
561 	GC		top, bot;
562 
563 	if (tdo->sme_threeD.shadowed)
564 	{
565 	    top = tdo->sme_threeD.top_shadow_GC;
566 	    bot = tdo->sme_threeD.bot_shadow_GC;
567 	}
568 	else
569 	    top = bot = tdo->sme_threeD.erase_GC;
570 
571 	/* top-left shadow */
572 	pt[0].x = x;		pt[0].y = y + h;
573 	pt[1].x = x;		pt[1].y = y;
574 	pt[2].x = w;		pt[2].y = y;
575 	pt[3].x = w - s;	pt[3].y = y + s;
576 	pt[4].x = ps + s;       pt[4].y = y + s;
577 	pt[5].x = ps + s;       pt[5].y = y + h - s;
578 	XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin);
579 
580 	/* bottom-right shadow */
581 /*	pt[0].x = x;		pt[0].y = y + h;	*/
582 	pt[1].x = w;		pt[1].y = y + h;
583 /*	pt[2].x = w;		pt[2].y = y;		*/
584 /*	pt[3].x = w - s;	pt[3].y = y + s;	*/
585 	pt[4].x = w - s;	pt[4].y = y + h - s;
586 /*	pt[5].x = ps + s;	pt[5].y = y + h - s;	*/
587 	XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
588     }
589 }
590 
591