1 /*
2 * $KK: ThreeD.c,v 0.3 92/11/04 xx:xx:xx keithley Exp $
3 */
4 
5 /***********************************************************
6 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
7 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
8 Copyright 1992 by Kaleb Keithley
9 
10                         All Rights Reserved
11 
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital, MIT, or Kaleb
17 Keithley not be used in advertising or publicity pertaining to distribution
18 of the software without specific, written prior permission.
19 
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 SOFTWARE.
27 
28 ******************************************************************/
29 
30 /*
31  * Portions Copyright (c) 2003 David J. Hawkey Jr.
32  * Rights, permissions, and disclaimer per the above DEC/MIT license.
33  */
34 
35 #include "Xaw3dP.h"
36 #include <X11/Xlib.h>
37 #include <X11/StringDefs.h>
38 #include <X11/IntrinsicP.h>
39 #include <X11/Xaw3d/XawInit.h>
40 #include <X11/Xaw3d/ThreeDP.h>
41 #include <X11/Xosdefs.h>
42 
43 /* Initialization of defaults */
44 
45 #define XtNtopShadowPixmap "topShadowPixmap"
46 #define XtCTopShadowPixmap "TopShadowPixmap"
47 #define XtNbottomShadowPixmap "bottomShadowPixmap"
48 #define XtCBottomShadowPixmap "BottomShadowPixmap"
49 
50 static char defRelief[] = "Raised";
51 
52 #define offset(field) XtOffsetOf(ThreeDRec, field)
53 
54 static XtResource resources[] = {
55     {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
56 	offset(threeD.shadow_width), XtRImmediate, (XtPointer) 2},
57     {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel),
58 	offset(threeD.top_shadow_pixel), XtRString, XtDefaultForeground},
59     {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel),
60 	offset(threeD.bot_shadow_pixel), XtRString, XtDefaultForeground},
61     {XtNtopShadowPixmap, XtCTopShadowPixmap, XtRPixmap, sizeof(Pixmap),
62 	offset(threeD.top_shadow_pxmap), XtRImmediate, (XtPointer) NULL},
63     {XtNbottomShadowPixmap, XtCBottomShadowPixmap, XtRPixmap, sizeof(Pixmap),
64 	offset(threeD.bot_shadow_pxmap), XtRImmediate, (XtPointer) NULL},
65     {XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, sizeof(int),
66 	offset(threeD.top_shadow_contrast), XtRImmediate, (XtPointer) 20},
67     {XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, sizeof(int),
68 	offset(threeD.bot_shadow_contrast), XtRImmediate, (XtPointer) 40},
69     {XtNuserData, XtCUserData, XtRPointer, sizeof(XtPointer),
70 	offset(threeD.user_data), XtRPointer, (XtPointer) NULL},
71     {XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, sizeof(Boolean),
72 	offset(threeD.be_nice_to_cmap), XtRImmediate, (XtPointer) True},
73     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
74 	XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
75 	(XtPointer)0},
76     {XtNrelief, XtCRelief, XtRRelief, sizeof(XtRelief),
77 	offset(threeD.relief), XtRString, (XtPointer) defRelief}
78 };
79 
80 #undef offset
81 
82 static void ClassInitialize(), ClassPartInitialize(), Initialize(), Destroy();
83 static void Redisplay(), Realize(), _Xaw3dDrawShadows();
84 static Boolean SetValues();
85 
86 ThreeDClassRec threeDClassRec = {
87     { /* core fields */
88     /* superclass		*/	(WidgetClass) &simpleClassRec,
89     /* class_name		*/	"ThreeD",
90     /* widget_size		*/	sizeof(ThreeDRec),
91     /* class_initialize		*/	ClassInitialize,
92     /* class_part_initialize	*/	ClassPartInitialize,
93     /* class_inited		*/	FALSE,
94     /* initialize		*/	Initialize,
95     /* initialize_hook		*/	NULL,
96     /* realize			*/	Realize,
97     /* actions			*/	NULL,
98     /* num_actions		*/	0,
99     /* resources		*/	resources,
100     /* resource_count		*/	XtNumber(resources),
101     /* xrm_class		*/	NULLQUARK,
102     /* compress_motion		*/	TRUE,
103     /* compress_exposure	*/	TRUE,
104     /* compress_enterleave	*/	TRUE,
105     /* visible_interest		*/	FALSE,
106     /* destroy			*/	Destroy,
107     /* resize			*/	XtInheritResize,
108     /* expose			*/	Redisplay,
109     /* set_values		*/	SetValues,
110     /* set_values_hook		*/	NULL,
111     /* set_values_almost	*/	XtInheritSetValuesAlmost,
112     /* get_values_hook		*/	NULL,
113     /* accept_focus		*/	NULL,
114     /* version			*/	XtVersion,
115     /* callback_private		*/	NULL,
116     /* tm_table			*/	NULL,
117     /* query_geometry           */	XtInheritQueryGeometry,
118     /* display_accelerator      */	XtInheritDisplayAccelerator,
119     /* extension                */	NULL
120     },
121     { /* simple fields */
122     /* change_sensitive         */      XtInheritChangeSensitive
123     },
124     { /* threeD fields */
125     /* shadow draw              */      _Xaw3dDrawShadows
126     }
127 };
128 
129 WidgetClass threeDWidgetClass = (WidgetClass) &threeDClassRec;
130 
131 /****************************************************************
132  *
133  * Private Procedures
134  *
135  ****************************************************************/
136 
137 #define mbshadowpm_size 3
138 static char mbshadowpm_bits[] = {0x05, 0x03, 0x06};
139 
140 #define mtshadowpm_size 3
141 static char mtshadowpm_bits[] = {0x02, 0x04, 0x01};
142 
143 #define shadowpm_size 2
144 static char shadowpm_bits[] = {0x02, 0x01};
145 
146 /* ARGSUSED */
AllocTopShadowGC(w)147 static void AllocTopShadowGC (w)
148     Widget w;
149 {
150     ThreeDWidget	tdw = (ThreeDWidget) w;
151     Screen		*scn = XtScreen (w);
152     XtGCMask		valuemask;
153     XGCValues		myXGCV;
154 
155     if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) {
156 	valuemask = GCTile | GCFillStyle;
157 	myXGCV.tile = tdw->threeD.top_shadow_pxmap;
158 	myXGCV.fill_style = FillTiled;
159     } else {
160 	valuemask = GCForeground;
161 	myXGCV.foreground = tdw->threeD.top_shadow_pixel;
162     }
163     tdw->threeD.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
164 }
165 
166 /* ARGSUSED */
AllocBotShadowGC(w)167 static void AllocBotShadowGC (w)
168     Widget w;
169 {
170     ThreeDWidget	tdw = (ThreeDWidget) w;
171     Screen		*scn = XtScreen (w);
172     XtGCMask		valuemask;
173     XGCValues		myXGCV;
174 
175     if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) {
176 	valuemask = GCTile | GCFillStyle;
177 	myXGCV.tile = tdw->threeD.bot_shadow_pxmap;
178 	myXGCV.fill_style = FillTiled;
179     } else {
180 	valuemask = GCForeground;
181 	myXGCV.foreground = tdw->threeD.bot_shadow_pixel;
182     }
183     tdw->threeD.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV);
184 }
185 
186 /* ARGSUSED */
AllocTopShadowPixmap(new)187 static void AllocTopShadowPixmap (new)
188     Widget new;
189 {
190     ThreeDWidget	tdw = (ThreeDWidget) new;
191     Display		*dpy = XtDisplay (new);
192     Screen		*scn = XtScreen (new);
193     unsigned long	top_fg_pixel = 0, top_bg_pixel = 0;
194     char		*pm_data = NULL;
195     Boolean		create_pixmap = FALSE;
196     unsigned int        pm_size;
197 
198     /*
199      * I know, we're going to create two pixmaps for each and every
200      * shadow'd widget.  Yeuck.  I'm semi-relying on server side
201      * pixmap cacheing.
202      */
203 
204     if (DefaultDepthOfScreen (scn) == 1) {
205 	top_fg_pixel = BlackPixelOfScreen (scn);
206 	top_bg_pixel = WhitePixelOfScreen (scn);
207 	pm_data = mtshadowpm_bits;
208         pm_size = mtshadowpm_size;
209 	create_pixmap = TRUE;
210     } else if (tdw->threeD.be_nice_to_cmap) {
211 	if (tdw->core.background_pixel == WhitePixelOfScreen (scn)) {
212 	    top_fg_pixel = WhitePixelOfScreen (scn);
213 	    top_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
214 	} else if (tdw->core.background_pixel == BlackPixelOfScreen (scn)) {
215 	    top_fg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
216 	    top_bg_pixel = WhitePixelOfScreen (scn);
217 	} else {
218 	    top_fg_pixel = tdw->core.background_pixel;
219 	    top_bg_pixel = WhitePixelOfScreen (scn);
220 	}
221 #ifndef XAW_GRAY_BLKWHT_STIPPLES
222 	if (tdw->core.background_pixel == WhitePixelOfScreen (scn) ||
223 	    tdw->core.background_pixel == BlackPixelOfScreen (scn)) {
224 	    pm_data = mtshadowpm_bits;
225        	    pm_size = mtshadowpm_size;
226        } else
227 #endif
228        {
229        	    pm_data = shadowpm_bits;
230             pm_size = shadowpm_size;
231        }
232 
233 	create_pixmap = TRUE;
234     } else {
235 	pm_size = 0; /* keep gcc happy */
236     }
237 
238     if (create_pixmap)
239 	tdw->threeD.top_shadow_pxmap = XCreatePixmapFromBitmapData (dpy,
240 			RootWindowOfScreen (scn),
241 			pm_data,
242 			pm_size,
243 			pm_size,
244 			top_fg_pixel,
245 			top_bg_pixel,
246 			DefaultDepthOfScreen (scn));
247 }
248 
249 /* ARGSUSED */
AllocBotShadowPixmap(new)250 static void AllocBotShadowPixmap (new)
251     Widget new;
252 {
253     ThreeDWidget	tdw = (ThreeDWidget) new;
254     Display		*dpy = XtDisplay (new);
255     Screen		*scn = XtScreen (new);
256     unsigned long	bot_fg_pixel = 0, bot_bg_pixel = 0;
257     char		*pm_data = NULL;
258     Boolean		create_pixmap = FALSE;
259     unsigned int        pm_size;
260 
261     if (DefaultDepthOfScreen (scn) == 1) {
262 	bot_fg_pixel = BlackPixelOfScreen (scn);
263 	bot_bg_pixel = WhitePixelOfScreen (scn);
264 	pm_data = mbshadowpm_bits;
265         pm_size = mbshadowpm_size;
266 	create_pixmap = TRUE;
267     } else if (tdw->threeD.be_nice_to_cmap) {
268 	if (tdw->core.background_pixel == WhitePixelOfScreen (scn)) {
269 	    bot_fg_pixel = grayPixel( WhitePixelOfScreen (scn), dpy, scn);
270 	    bot_bg_pixel = BlackPixelOfScreen (scn);
271 	} else if (tdw->core.background_pixel == BlackPixelOfScreen (scn)) {
272 	    bot_fg_pixel = BlackPixelOfScreen (scn);
273 	    bot_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn);
274 	} else {
275 	    bot_fg_pixel = tdw->core.background_pixel;
276 	    bot_bg_pixel = BlackPixelOfScreen (scn);
277 	}
278 #ifndef XAW_GRAY_BLKWHT_STIPPLES
279 	if (tdw->core.background_pixel == WhitePixelOfScreen (scn) ||
280 	    tdw->core.background_pixel == BlackPixelOfScreen (scn)) {
281 	    pm_data = mbshadowpm_bits;
282 	    pm_size = mbshadowpm_size;
283 	} else
284 #endif
285         {
286 	    pm_data = shadowpm_bits;
287 	    pm_size = shadowpm_size;
288         }
289 	create_pixmap = TRUE;
290     } else {
291 	pm_size = 0; /* keep gcc happy */
292     }
293 
294     if (create_pixmap)
295 	tdw->threeD.bot_shadow_pxmap = XCreatePixmapFromBitmapData (dpy,
296 			RootWindowOfScreen (scn),
297 			pm_data,
298 			pm_size,
299 			pm_size,
300 			bot_fg_pixel,
301 			bot_bg_pixel,
302 			DefaultDepthOfScreen (scn));
303 }
304 
305 /* ARGSUSED */
Xaw3dComputeTopShadowRGB(new,xcol_out)306 void Xaw3dComputeTopShadowRGB (new, xcol_out)
307     Widget new;
308     XColor *xcol_out;
309 {
310     if (XtIsSubclass (new, threeDWidgetClass)) {
311 	ThreeDWidget tdw = (ThreeDWidget) new;
312 	XColor get_c;
313 	double contrast;
314 	Display *dpy = XtDisplay (new);
315 	Screen *scn = XtScreen (new);
316 	Colormap cmap = new->core.colormap;
317 
318 	get_c.pixel = tdw->core.background_pixel;
319 	if (get_c.pixel == WhitePixelOfScreen (scn) ||
320 	    get_c.pixel == BlackPixelOfScreen (scn)) {
321 	    contrast = (100 - tdw->threeD.top_shadow_contrast) / 100.0;
322 	    xcol_out->red   = contrast * 65535.0;
323 	    xcol_out->green = contrast * 65535.0;
324 	    xcol_out->blue  = contrast * 65535.0;
325 	} else {
326 	    contrast = 1.0 + tdw->threeD.top_shadow_contrast / 100.0;
327 	    XQueryColor (dpy, cmap, &get_c);
328 #define MIN(x,y) (unsigned short) (x < y) ? x : y
329 	    xcol_out->red   = MIN (65535, (int) (contrast * (double) get_c.red));
330 	    xcol_out->green = MIN (65535, (int) (contrast * (double) get_c.green));
331 	    xcol_out->blue  = MIN (65535, (int) (contrast * (double) get_c.blue));
332 #undef MIN
333 	}
334     } else
335 	xcol_out->red = xcol_out->green = xcol_out->blue = 0;
336 }
337 
338 /* ARGSUSED */
AllocTopShadowPixel(new)339 static void AllocTopShadowPixel (new)
340     Widget new;
341 {
342     XColor set_c;
343     ThreeDWidget tdw = (ThreeDWidget) new;
344     Display *dpy = XtDisplay (new);
345     Screen *scn = XtScreen (new);
346     Colormap cmap = new->core.colormap;
347 
348     Xaw3dComputeTopShadowRGB (new, &set_c);
349     (void) XAllocColor (dpy, cmap, &set_c);
350     tdw->threeD.top_shadow_pixel = set_c.pixel;
351 }
352 
353 /* ARGSUSED */
Xaw3dComputeBottomShadowRGB(new,xcol_out)354 void Xaw3dComputeBottomShadowRGB (new, xcol_out)
355     Widget new;
356     XColor *xcol_out;
357 {
358     if (XtIsSubclass (new, threeDWidgetClass)) {
359 	ThreeDWidget tdw = (ThreeDWidget) new;
360 	XColor get_c;
361 	double contrast;
362 	Display *dpy = XtDisplay (new);
363 	Screen *scn = XtScreen (new);
364 	Colormap cmap = new->core.colormap;
365 
366 	get_c.pixel = tdw->core.background_pixel;
367 	if (get_c.pixel == WhitePixelOfScreen (scn) ||
368 	    get_c.pixel == BlackPixelOfScreen (scn)) {
369 	    contrast = tdw->threeD.bot_shadow_contrast / 100.0;
370 	    xcol_out->red   = contrast * 65535.0;
371 	    xcol_out->green = contrast * 65535.0;
372 	    xcol_out->blue  = contrast * 65535.0;
373 	} else {
374 	    XQueryColor (dpy, cmap, &get_c);
375 	    contrast = (100 - tdw->threeD.bot_shadow_contrast) / 100.0;
376 	    xcol_out->red   = contrast * get_c.red;
377 	    xcol_out->green = contrast * get_c.green;
378 	    xcol_out->blue  = contrast * get_c.blue;
379 	}
380     } else
381 	xcol_out->red = xcol_out->green = xcol_out->blue = 0;
382 }
383 
384 /* ARGSUSED */
AllocBotShadowPixel(new)385 static void AllocBotShadowPixel (new)
386     Widget new;
387 {
388     XColor set_c;
389     ThreeDWidget tdw = (ThreeDWidget) new;
390     Display *dpy = XtDisplay (new);
391     Screen *scn = XtScreen (new);
392     Colormap cmap = new->core.colormap;
393 
394     Xaw3dComputeBottomShadowRGB (new, &set_c);
395     (void) XAllocColor (dpy, cmap, &set_c);
396     tdw->threeD.bot_shadow_pixel = set_c.pixel;
397 }
398 
399 
400 static XrmQuark	XtQReliefNone, XtQReliefRaised, XtQReliefSunken,
401 		XtQReliefRidge, XtQReliefGroove;
402 
403 #define	done(address, type) { \
404 	  toVal->size = sizeof(type); \
405 	  toVal->addr = (XPointer) address; \
406 	  return; \
407 	}
408 
409 /* ARGSUSED */
_CvtStringToRelief(args,num_args,fromVal,toVal)410 static void _CvtStringToRelief(args, num_args, fromVal, toVal)
411     XrmValuePtr args;          /* unused */
412     Cardinal    *num_args;      /* unused */
413     XrmValuePtr fromVal;
414     XrmValuePtr toVal;
415 {
416     static XtRelief relief;
417     XrmQuark q;
418     char lowerName[1000];
419 
420     XmuCopyISOLatin1Lowered (lowerName, (char*)fromVal->addr);
421     q = XrmStringToQuark(lowerName);
422     if (q == XtQReliefNone) {
423        relief = XtReliefNone;
424        done(&relief, XtRelief);
425     }
426     if (q == XtQReliefRaised) {
427        relief = XtReliefRaised;
428        done(&relief, XtRelief);
429     }
430     if (q == XtQReliefSunken) {
431        relief = XtReliefSunken;
432        done(&relief, XtRelief);
433     }
434     if (q == XtQReliefRidge) {
435        relief = XtReliefRidge;
436        done(&relief, XtRelief);
437     }
438     if (q == XtQReliefGroove) {
439        relief = XtReliefGroove;
440        done(&relief, XtRelief);
441     }
442     XtStringConversionWarning(fromVal->addr, "relief");
443     toVal->addr = NULL;
444     toVal->size = 0;
445 }
446 
ClassInitialize()447 static void ClassInitialize()
448 {
449     XawInitializeWidgetSet();
450     XtQReliefNone   = XrmPermStringToQuark("none");
451     XtQReliefRaised = XrmPermStringToQuark("raised");
452     XtQReliefSunken = XrmPermStringToQuark("sunken");
453     XtQReliefRidge  = XrmPermStringToQuark("ridge");
454     XtQReliefGroove = XrmPermStringToQuark("groove");
455 
456     XtAddConverter( XtRString, XtRRelief, _CvtStringToRelief,
457                    (XtConvertArgList)NULL, 0 );
458 }
459 
460 
461 /* ARGSUSED */
ClassPartInitialize(wc)462 static void ClassPartInitialize (wc)
463     WidgetClass	wc;
464 
465 {
466     ThreeDClassRec *tdwc = (ThreeDClassRec*) wc;
467     ThreeDClassRec *super = (ThreeDClassRec*) tdwc->core_class.superclass;
468 
469     if (tdwc->threeD_class.shadowdraw == XtInheritXaw3dShadowDraw)
470 	tdwc->threeD_class.shadowdraw = super->threeD_class.shadowdraw;
471 }
472 
473 
474 /* ARGSUSED */
Initialize(request,new,args,num_args)475 static void Initialize (request, new, args, num_args)
476     Widget request, new;
477     ArgList args;
478     Cardinal *num_args;
479 {
480     ThreeDWidget 	tdw = (ThreeDWidget) new;
481     Screen		*scr = XtScreen (new);
482 
483     if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scr) == 1) {
484 	AllocTopShadowPixmap (new);
485 	AllocBotShadowPixmap (new);
486     } else {
487 	if (tdw->threeD.top_shadow_pixel == tdw->threeD.bot_shadow_pixel) {
488 	    /*
489 		Eeek.  We're probably going to XQueryColor() twice
490 		for each widget.  Necessary because you can set the
491 		top and bottom shadows independent of each other in
492 		SetValues.  Some cacheing would certainly help...
493 	    */
494 	    AllocTopShadowPixel (new);
495 	    AllocBotShadowPixel (new);
496 	}
497 	tdw->threeD.top_shadow_pxmap = tdw->threeD.bot_shadow_pxmap = (Pixmap) 0;
498     }
499     AllocTopShadowGC (new);
500     AllocBotShadowGC (new);
501 }
502 
Realize(gw,valueMask,attrs)503 static void Realize (gw, valueMask, attrs)
504     Widget gw;
505     XtValueMask *valueMask;
506     XSetWindowAttributes *attrs;
507 {
508  /*
509   * This is necessary because Simple doesn't have a realize method
510   * XtInheritRealize in the ThreeD class record doesn't work.  This
511   * daisychains through Simple to the Core class realize method
512   */
513     (*threeDWidgetClass->core_class.superclass->core_class.realize)
514 	 (gw, valueMask, attrs);
515 }
516 
Destroy(w)517 static void Destroy (w)
518      Widget w;
519 {
520     ThreeDWidget tdw = (ThreeDWidget) w;
521     XtReleaseGC (w, tdw->threeD.top_shadow_GC);
522     XtReleaseGC (w, tdw->threeD.bot_shadow_GC);
523     if (tdw->threeD.top_shadow_pxmap)
524 	XFreePixmap (XtDisplay (w), tdw->threeD.top_shadow_pxmap);
525     if (tdw->threeD.bot_shadow_pxmap)
526 	XFreePixmap (XtDisplay (w), tdw->threeD.bot_shadow_pxmap);
527 }
528 
529 /* ARGSUSED */
Redisplay(w,event,region)530 static void Redisplay (w, event, region)
531     Widget w;
532     XEvent *event;		/* unused */
533     Region region;		/* unused */
534 {
535     ThreeDWidget tdw = (ThreeDWidget) w;
536 
537     _Xaw3dDrawShadows (w, event, region, tdw->threeD.relief, True);
538 }
539 
540 /* ARGSUSED */
SetValues(gcurrent,grequest,gnew,args,num_args)541 static Boolean SetValues (gcurrent, grequest, gnew, args, num_args)
542     Widget gcurrent, grequest, gnew;
543     ArgList args;
544     Cardinal *num_args;
545 {
546     ThreeDWidget current = (ThreeDWidget) gcurrent;
547     ThreeDWidget new = (ThreeDWidget) gnew;
548     Boolean redisplay = FALSE;
549     Boolean alloc_top_pixel = FALSE;
550     Boolean alloc_bot_pixel = FALSE;
551     Boolean alloc_top_pxmap = FALSE;
552     Boolean alloc_bot_pxmap = FALSE;
553 
554     (*threeDWidgetClass->core_class.superclass->core_class.set_values)
555 	(gcurrent, grequest, gnew, NULL, 0);
556     if (new->threeD.relief != current->threeD.relief)
557 	redisplay = TRUE;
558     if (new->threeD.shadow_width != current->threeD.shadow_width)
559 	redisplay = TRUE;
560     if (new->threeD.be_nice_to_cmap != current->threeD.be_nice_to_cmap) {
561 	if (new->threeD.be_nice_to_cmap) {
562 	    alloc_top_pxmap = TRUE;
563 	    alloc_bot_pxmap = TRUE;
564 	} else {
565 	    alloc_top_pixel = TRUE;
566 	    alloc_bot_pixel = TRUE;
567 	}
568 	redisplay = TRUE;
569     }
570     if (!new->threeD.be_nice_to_cmap &&
571 	new->threeD.top_shadow_contrast != current->threeD.top_shadow_contrast)
572 	alloc_top_pixel = TRUE;
573     if (!new->threeD.be_nice_to_cmap &&
574 	new->threeD.bot_shadow_contrast != current->threeD.bot_shadow_contrast)
575 	alloc_bot_pixel = TRUE;
576     if (alloc_top_pixel)
577 	AllocTopShadowPixel (gnew);
578     if (alloc_bot_pixel)
579 	AllocBotShadowPixel (gnew);
580     if (alloc_top_pxmap)
581 	AllocTopShadowPixmap (gnew);
582     if (alloc_bot_pxmap)
583 	AllocBotShadowPixmap (gnew);
584     if (!new->threeD.be_nice_to_cmap &&
585 	new->threeD.top_shadow_pixel != current->threeD.top_shadow_pixel)
586 	alloc_top_pixel = TRUE;
587     if (!new->threeD.be_nice_to_cmap &&
588 	new->threeD.bot_shadow_pixel != current->threeD.bot_shadow_pixel)
589 	alloc_bot_pixel = TRUE;
590     if (new->threeD.be_nice_to_cmap) {
591 	if (alloc_top_pxmap) {
592 	    XtReleaseGC (gcurrent, current->threeD.top_shadow_GC);
593 	    AllocTopShadowGC (gnew);
594 	    redisplay = True;
595 	}
596 	if (alloc_bot_pxmap) {
597 	    XtReleaseGC (gcurrent, current->threeD.bot_shadow_GC);
598 	    AllocBotShadowGC (gnew);
599 	    redisplay = True;
600 	}
601     } else {
602 	if (alloc_top_pixel) {
603 	    if (new->threeD.top_shadow_pxmap) {
604 		XFreePixmap (XtDisplay (gnew), new->threeD.top_shadow_pxmap);
605 		new->threeD.top_shadow_pxmap = (Pixmap) NULL;
606 	    }
607 	    XtReleaseGC (gcurrent, current->threeD.top_shadow_GC);
608 	    AllocTopShadowGC (gnew);
609 	    redisplay = True;
610 	}
611 	if (alloc_bot_pixel) {
612 	    if (new->threeD.bot_shadow_pxmap) {
613 		XFreePixmap (XtDisplay (gnew), new->threeD.bot_shadow_pxmap);
614 		new->threeD.bot_shadow_pxmap = (Pixmap) NULL;
615 	    }
616 	    XtReleaseGC (gcurrent, current->threeD.bot_shadow_GC);
617 	    AllocBotShadowGC (gnew);
618 	    redisplay = True;
619 	}
620     }
621     return (redisplay);
622 }
623 
624 /* ARGSUSED */
625 static void
_Xaw3dDrawShadows(gw,event,region,relief,out)626 _Xaw3dDrawShadows (gw, event, region, relief, out)
627     Widget gw;
628     XEvent *event;
629     Region region;
630     XtRelief relief;
631     Boolean out;
632 {
633     XPoint	pt[6];
634     ThreeDWidget tdw = (ThreeDWidget) gw;
635     Dimension	s = tdw->threeD.shadow_width;
636 
637     /*
638      * Draw the shadows using the core part width and height,
639      * and the threeD part relief and shadow_width.
640      * No point to do anything if the shadow_width is 0 or the
641      * widget has not been realized.
642      */
643     if ((s > 0) && XtIsRealized (gw)) {
644 	Dimension	h = tdw->core.height;
645 	Dimension	w = tdw->core.width;
646 	Dimension	hms = h - s;
647 	Dimension	wms = w - s;
648 	Display		*dpy = XtDisplay (gw);
649 	Window		win = XtWindow (gw);
650 	GC		realtop = tdw->threeD.top_shadow_GC;
651 	GC		realbot = tdw->threeD.bot_shadow_GC;
652 	GC		top, bot;
653 
654 	if (out) {
655 	    top = tdw->threeD.top_shadow_GC;
656 	    bot = tdw->threeD.bot_shadow_GC;
657 	} else {
658 	    top = tdw->threeD.bot_shadow_GC;
659 	    bot = tdw->threeD.top_shadow_GC;
660 	}
661 
662 	if (relief == XtReliefRaised || relief == XtReliefSunken) {
663 	    /* top-left shadow */
664 	    if ((region == NULL) ||
665 		    (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
666 		    (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) {
667 		pt[0].x = 0;	pt[0].y = h;
668 		pt[1].x =	pt[1].y = 0;
669 		pt[2].x = w;	pt[2].y = 0;
670 		pt[3].x = wms;	pt[3].y = s;
671 		pt[4].x =	pt[4].y = s;
672 		pt[5].x = s;	pt[5].y = hms;
673 		XFillPolygon (dpy, win,
674 			(relief == XtReliefRaised) ? top : bot,
675 			pt, 6, Complex, CoordModeOrigin);
676 	    }
677 
678 	    /* bottom-right shadow */
679 	    if ((region == NULL) ||
680 		    (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
681 		    (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) {
682 		pt[0].x = 0;	pt[0].y = h;
683 		pt[1].x = w;	pt[1].y = h;
684 		pt[2].x = w;	pt[2].y = 0;
685 		pt[3].x = wms;	pt[3].y = s;
686 		pt[4].x = wms;	pt[4].y = hms;
687 		pt[5].x = s;	pt[5].y = hms;
688 		XFillPolygon (dpy, win,
689 			(relief == XtReliefRaised) ? bot : top,
690 			pt, 6, Complex, CoordModeOrigin);
691 	    }
692 	} else if (relief == XtReliefRidge || relief == XtReliefGroove) {
693 	    /* split the shadow width */
694 	    s /= 2;	hms = h - s;	wms = w - s;
695 
696 	    /* outer top-left shadow */
697 	    if ((region == NULL) ||
698 		    (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
699 		    (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) {
700 		pt[0].x = 0;	pt[0].y = h;
701 		pt[1].x =	pt[1].y = 0;
702 		pt[2].x = w;	pt[2].y = 0;
703 		pt[3].x = wms;	pt[3].y = s;
704 		pt[4].x =	pt[4].y = s;
705 		pt[5].x = s;	pt[5].y = hms;
706 		XFillPolygon (dpy, win,
707 			(relief == XtReliefRidge) ? realtop : realbot,
708 			pt, 6, Complex, CoordModeOrigin);
709 	    }
710 
711 	    /* outer bottom-right shadow */
712 	    if ((region == NULL) ||
713 		    (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
714 		    (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) {
715 		pt[0].x = 0;	pt[0].y = h;
716 		pt[1].x = w;	pt[1].y = h;
717 		pt[2].x = w;	pt[2].y = 0;
718 		pt[3].x = wms;	pt[3].y = s;
719 		pt[4].x = wms;	pt[4].y = hms;
720 		pt[5].x = s;	pt[5].y = hms;
721 		XFillPolygon (dpy, win,
722 			(relief == XtReliefRidge) ? realbot : realtop,
723 			pt, 6, Complex, CoordModeOrigin);
724 	    }
725 
726 	    /* inner top-left shadow */
727 	    if ((region == NULL) ||
728 		    (XRectInRegion (region, 0, 0, w, s) != RectangleOut) ||
729 		    (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) {
730 		pt[0].x = s;		pt[0].y = h;
731 		pt[1].x =		pt[1].y = s;
732 		pt[2].x = w;		pt[2].y = s;
733 		pt[3].x = wms;		pt[3].y = s * 2;
734 		pt[4].x =		pt[4].y = s * 2;
735 		pt[5].x = s * 2;	pt[5].y = hms;
736 		XFillPolygon (dpy, win,
737 			(relief == XtReliefRidge) ? bot: top,
738 			pt, 6, Complex, CoordModeOrigin);
739 	    }
740 
741 	    /* inner bottom-right shadow */
742 	    if ((region == NULL) ||
743 		    (XRectInRegion (region, 0, hms, w, s) != RectangleOut) ||
744 		    (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) {
745 		pt[0].x = s;		pt[0].y = hms;
746 		pt[1].x = wms;		pt[1].y = hms;
747 		pt[2].x = wms;		pt[2].y = s;
748 		pt[3].x = wms - s;	pt[3].y = s * 2;
749 		pt[4].x = wms - s;	pt[4].y = hms - s;
750 		pt[5].x = s * 2;	pt[5].y = hms - s;
751 		XFillPolygon (dpy, win,
752 			(relief == XtReliefRidge) ? top : bot,
753 			pt, 6, Complex, CoordModeOrigin);
754 	    }
755 	}
756     }
757 }
758 
759 /*
760  * _ShadowSurroundedBox() is somewhat redundant with _Xaw3dDrawShadows(),
761  * but has a more explicit interface, and ignores threeD part relief.
762  */
763 
764 /* ARGSUSED */
765 void
_ShadowSurroundedBox(gw,tdw,x0,y0,x1,y1,relief,out)766 _ShadowSurroundedBox(gw, tdw, x0, y0, x1, y1, relief, out)
767 Widget gw;
768 ThreeDWidget tdw;
769 Position x0, y0, x1, y1;
770 XtRelief relief;	/* unused */
771 Boolean out;
772 {
773     XPoint pt[6];
774     Dimension s = tdw->threeD.shadow_width;
775 
776     /*
777      * Draw the shadows using the core part width and height,
778      * and the threeD part shadow_width.
779      * No point to do anything if the shadow_width is 0 or the
780      * widget has not been realized.
781      */
782     if ((s > 0) && XtIsRealized(gw))
783     {
784 	Dimension h = y1 - y0;
785 	Dimension w = x1 - x0;
786 	Dimension wms = w - s;
787 	Dimension hms = h - s;
788 	Dimension sm = (s > 1 ? s / 2 : 1);
789 	Dimension wmsm = w - sm;
790 	Dimension hmsm = h - sm;
791 	Display *dpy = XtDisplay(gw);
792 	Window win = XtWindow(gw);
793 	GC top, bot;
794 
795 	if (out)
796 	{
797 	    top = tdw->threeD.top_shadow_GC;
798 	    bot = tdw->threeD.bot_shadow_GC;
799 	}
800 	else
801 	{
802 	    top = tdw->threeD.bot_shadow_GC;
803 	    bot = tdw->threeD.top_shadow_GC;
804 	}
805 
806 	/* top-left shadow */
807 	pt[0].x = x0;		pt[0].y = y0 + h;
808 	pt[1].x = x0;		pt[1].y = y0;
809 	pt[2].x = x0 + w;	pt[2].y = y0;
810 	pt[3].x = x0 + wmsm;	pt[3].y = y0 + sm - 1;
811 	pt[4].x = x0 + sm;	pt[4].y = y0 + sm;
812 	pt[5].x = x0 + sm - 1;	pt[5].y = y0 + hmsm;
813 	XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin);
814 	if (s > 1)
815 	{
816 	    pt[0].x = x0 + s - 1;	pt[0].y = y0 + hms;
817 	    pt[1].x = x0 + s;		pt[1].y = y0 + s;
818 	    pt[2].x = x0 + wms;		pt[2].y = y0 + s - 1;
819 	    XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin);
820 	}
821 
822 	/* bottom-right shadow */
823 	pt[0].x = x0;		pt[0].y = y0 + h;
824 	pt[1].x = x0 + w;	pt[1].y = y0 + h;
825 	pt[2].x = x0 + w;	pt[2].y = y0;
826 	pt[3].x = x0 + wmsm;	pt[3].y = y0 + sm - 1;
827 	pt[4].x = x0 + wmsm;	pt[4].y = y0 + hmsm;
828 	pt[5].x = x0 + sm - 1;	pt[5].y = y0 + hmsm;
829 	XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
830 	if (s > 1)
831 	{
832 	    pt[0].x = x0 + s - 1;	pt[0].y = y0 + hms;
833 	    pt[1].x = x0 + wms;		pt[1].y = y0 + hms;
834 	    pt[2].x = x0 + wms;		pt[2].y = y0 + s - 1;
835 	    XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin);
836 	}
837     }
838 }
839 
840