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