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