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