1 /*
2  *  Copyright (C) 1995, 1996  Karl-Johan Johnsson.
3  */
4 
5 #include <X11/IntrinsicP.h>
6 #include <X11/StringDefs.h>
7 
8 #include "Compat.h"
9 #include "ShadowP.h"
10 #include "Util.h"
11 
12 static XtResource resources[] = {
13     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
14      XtOffsetOf(ShadowRec, core.border_width), XtRImmediate, (XtPointer)0},
15 #define offset(field) XtOffsetOf(ShadowRec, shadow.field)
16     {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension),
17      offset(shadow_width), XtRImmediate, (XtPointer)2},
18     {XtNallocArmColor, XtCAllocArmColor, XtRBoolean, sizeof(Boolean),
19      offset(alloc_arm_color), XtRImmediate, (XtPointer)True},
20     {XtNallocArmPixmap, XtCAllocArmPixmap, XtRBoolean, sizeof(Boolean),
21      offset(alloc_arm_pixmap), XtRImmediate, (XtPointer)True},
22     {XtNallocShadowColors, XtCAllocShadowColors, XtRBoolean, sizeof(Boolean),
23      offset(alloc_shadow_colors), XtRImmediate, (XtPointer)True},
24     {XtNuseLineShadows, XtCUseLineShadows, XtRBoolean, sizeof(Boolean),
25      offset(use_lines), XtRImmediate, (XtPointer)False},
26 #undef offset
27 };
28 
29 static void	ClassPartInitialize(WidgetClass);
30 static void	Initialize(Widget, Widget, ArgList, Cardinal*);
31 static void	Destroy(Widget);
32 static void	Realize(Widget, XtValueMask*, XSetWindowAttributes*);
33 static Boolean	SetValues(Widget, Widget, Widget, ArgList, Cardinal*);
34 static Boolean	AllocShadowColors(ShadowWidget, XColor*);
35 static void	AllocShadowPixmaps(ShadowWidget, Pixel);
36 static Boolean	AllocArmColor(ShadowWidget, XColor*);
37 static void	AllocArmPixmap(ShadowWidget, Pixel);
38 static void	AllocGCs(ShadowWidget);
39 
40 ShadowClassRec shadowClassRec = {
41     { /* core fields */
42         (WidgetClass) &widgetClassRec,  /* superclass                   */
43         "Shadow",                       /* class_name                   */
44         sizeof(ShadowRec),	        /* widget_size                  */
45         NULL,				/* class_initialize             */
46         ClassPartInitialize,            /* class_part_initialize        */
47         FALSE,                          /* class_inited                 */
48         Initialize,                     /* initialize                   */
49         NULL,                           /* initialize_hook              */
50         Realize,			/* realize                      */
51         NULL,                           /* actions                      */
52         0,                              /* num_actions                  */
53         resources,                      /* resources                    */
54         XtNumber(resources),            /* num_resources                */
55         NULLQUARK,                      /* xrm_class                    */
56         TRUE,                           /* compress_motion              */
57         TRUE,                           /* compress_exposure            */
58         TRUE,                           /* compress_enterleave          */
59         FALSE,                          /* visible_interest             */
60         Destroy,                        /* destroy                      */
61         NULL,                           /* resize                       */
62         NULL,                           /* expose                       */
63         SetValues,                      /* set_values                   */
64         NULL,                           /* set_values_hook              */
65         XtInheritSetValuesAlmost,       /* set_values_almost            */
66         NULL,                           /* get_values_hook              */
67         NULL,                           /* accept_focus                 */
68         XtVersion,                      /* version                      */
69         NULL,                           /* callback_private             */
70         NULL,                           /* tm_table                     */
71         NULL,                           /* query_geometry               */
72         XtInheritDisplayAccelerator,    /* display_accelerator          */
73         NULL                            /* extension                    */
74     },
75     { /* shadow fields */
76 	XtOffsetOf(CoreRec, core.background_pixel), /* pixel_offset	*/
77 	False,				/* use_arm_for_background	*/
78 	AllocShadowColors,		/* alloc_shadow_colors		*/
79 	AllocShadowPixmaps,		/* alloc_shadow_pixmaps		*/
80 	AllocArmColor,			/* alloc_arm_color		*/
81 	AllocArmPixmap,			/* alloc_arm_pixmap		*/
82 	AllocGCs,			/* alloc_gcs			*/
83 	NULL,				/* extension			*/
84     }
85 };
86 
87 WidgetClass shadowWidgetClass = (WidgetClass)&shadowClassRec;
88 
89 /*************************************************************************/
90 
get_pixel(ShadowWidget w)91 static Pixel get_pixel(ShadowWidget w)
92 {
93     ShadowWidgetClass	class = (ShadowWidgetClass)XtClass(w);
94     Cardinal		offset = class->shadow_class.pixel_offset;
95 
96     return *(Pixel *)((char *)w + offset);
97 }
98 
99 typedef struct pixmap_cache_ref {
100     struct pixmap_cache_ref	*next;
101     struct pixmap_cache_ref	*prev;
102     Screen	*screen;
103     Pixmap	pixmap;
104     Pixel	fg;
105     Pixel	bg;
106     int		depth;
107     int		size;
108     int		ref_count;
109 } PixmapCacheRef;
110 
111 static PixmapCacheRef *pixmap_cache;
112 
CacheCreatePixmap(ShadowWidget w,int size,Pixel fg,Pixel bg)113 static Pixmap CacheCreatePixmap(ShadowWidget w, int size, Pixel fg, Pixel bg)
114 {
115     static char		bitmap2by2_data[] = {0x01, 0x02};
116     static char		bitmap4by4_data[] = {0x08, 0x02, 0x04, 0x01};
117     Display		*disp = XtDisplay(w);
118     Screen		*screen = XtScreen(w);
119     PixmapCacheRef	*loop;
120     char		*bitmap_data;
121 
122     for (loop = pixmap_cache ; loop ; loop = loop->next)
123 	if (loop->screen == screen && loop->fg == fg && loop->bg == bg &&
124 	    loop->depth == w->core.depth && loop->size == size) {
125 	    loop->ref_count++;
126 	    return loop->pixmap;
127 	}
128 
129     switch (size) {
130     case 2:
131 	bitmap_data = bitmap2by2_data;
132 	break;
133     case 4:
134 	bitmap_data = bitmap4by4_data;
135 	break;
136     default:
137 	return None;
138     }
139 
140     loop = (PixmapCacheRef *)XtMalloc(sizeof(PixmapCacheRef));
141     loop->next = pixmap_cache;
142     loop->prev = NULL;
143     loop->screen = screen;
144     loop->depth = w->core.depth;
145     loop->size = size;
146     loop->fg = fg;
147     loop->bg = bg;
148     loop->ref_count = 1;
149 
150     loop->pixmap =
151 	XCreatePixmapFromBitmapData(disp, RootWindowOfScreen(screen),
152 				    bitmap_data, size, size, fg, bg,
153 				    w->core.depth);
154     if (pixmap_cache)
155 	pixmap_cache->prev = loop;
156     pixmap_cache = loop;
157 
158     return loop->pixmap;
159 }
160 
CacheFreePixmap(ShadowWidget w,Pixmap pixmap)161 static void CacheFreePixmap(ShadowWidget w, Pixmap pixmap)
162 {
163     Display		*disp = XtDisplay(w);
164     Screen		*screen = XtScreen(w);
165     PixmapCacheRef	*loop;
166 
167     for (loop = pixmap_cache ; loop ; loop = loop->next)
168 	if (loop->screen == screen && loop->pixmap == pixmap) {
169 	    PixmapCacheRef	*prev = loop->prev;
170 
171 	    loop->ref_count--;
172 	    if (loop->ref_count != 0)
173 		break;
174 
175 	    XFreePixmap(disp, loop->pixmap);
176 
177 	    if (prev) {
178 		prev->next = loop->next;
179 		if (loop->next)
180 		    loop->next->prev = prev;
181 	    } else {
182 		pixmap_cache = loop->next;
183 		if (pixmap_cache)
184 		    pixmap_cache->prev = NULL;
185 	    }
186 	    XtFree((char *)loop);
187 	    break;
188 	}
189 }
190 
191 /*************************************************************************/
192 
193 #define MIN(a, b) ((a) < (b) ? (a) : (b))
AllocShadowColors(ShadowWidget w,XColor * col)194 static Boolean AllocShadowColors(ShadowWidget w, XColor *col)
195 {
196     Display	*disp = XtDisplay(w);
197     Colormap	cmap = w->core.colormap;
198     XColor	sh_col;
199 
200     if ((col->red > 0xefff && col->green > 0xefff && col->blue > 0xefff) ||
201 	(col->red < 0x1000 && col->green < 0x1000 && col->blue < 0x1000)) {
202 	sh_col.red   = 65535L * 4 / 5;
203         sh_col.green = 65535L * 4 / 5;
204         sh_col.blue  = 65535L * 4 / 5;
205         if (!XAllocColor(disp, cmap, &sh_col))
206 	    return False;
207 	w->shadow.light_pixel = sh_col.pixel;
208 
209         sh_col.red   = 65535L * 3 /5;
210         sh_col.green = 65535L * 3 /5;
211         sh_col.blue  = 65535L * 3 /5;
212         if (!XAllocColor(disp, cmap, &sh_col)) {
213 	    unsigned long	tmp = w->shadow.light_pixel;
214 
215 	    XFreeColors(disp, cmap, &tmp, 1, 0);
216 	    return False;
217 	}
218         w->shadow.dark_pixel = sh_col.pixel;
219     } else {
220         sh_col.red   = MIN (65535, 6 * (long)col->red   / 5);
221         sh_col.green = MIN (65535, 6 * (long)col->green / 5);
222         sh_col.blue  = MIN (65535, 6 * (long)col->blue  / 5);
223         if (!XAllocColor(disp, cmap, &sh_col))
224 	    return False;
225         w->shadow.light_pixel = sh_col.pixel;
226 
227         sh_col.red   = MIN (65535, 3 * (long)col->red   / 5);
228         sh_col.green = MIN (65535, 3 * (long)col->green / 5);
229         sh_col.blue  = MIN (65535, 3 * (long)col->blue  / 5);
230         if (!XAllocColor(disp, cmap, &sh_col)) {
231 	    unsigned long	tmp = w->shadow.light_pixel;
232 
233 	    XFreeColors(disp, cmap, &tmp, 1, 0);
234 	    return False;
235 	}
236         w->shadow.dark_pixel = sh_col.pixel;
237     }
238 
239     return True;
240 }
241 #undef MIN
242 
AllocShadowPixmaps(ShadowWidget w,Pixel pix)243 static void AllocShadowPixmaps(ShadowWidget w, Pixel pix)
244 {
245     if (w->core.depth == 1)
246 	w->shadow.light_pixmap = CacheCreatePixmap(w, 2, 0, 1);
247     else {
248 	Screen	*screen = XtScreen(w);
249 	Visual	*visual = get_visual((Widget)w);
250 	Pixel	black, white;
251 
252 	black_and_white(screen, visual, &black, &white);
253 	w->shadow.light_pixmap = CacheCreatePixmap(w, 2, pix, white);
254 	w->shadow.dark_pixmap  = CacheCreatePixmap(w, 2, pix, black);
255     }
256 }
257 
AllocArmColor(ShadowWidget w,XColor * col)258 static Boolean AllocArmColor(ShadowWidget w, XColor *col)
259 {
260     Display	*disp = XtDisplay(w);
261     Colormap	cmap = w->core.colormap;
262     XColor	arm_col;
263     long	t, r, g, b;
264 
265     t = col->red + col->green + col->blue;
266     t /= 3;
267     r = 3 * t / 4 + 3 * ((long)col->red   - t) / 2;
268     g = 3 * t / 4 + 3 * ((long)col->green - t) / 2;
269     b = 3 * t / 4 + 3 * ((long)col->blue  - t) / 2;
270     if (r < 0)
271 	r = 0;
272     else if (r > 65535)
273 	r = 65535;
274     if (g < 0)
275 	g = 0;
276     else if (g > 65535)
277 	g = 65535;
278     if (b < 0)
279 	b = 0;
280     else if (b > 65535)
281 	b = 65535;
282 
283     arm_col.red   = r;
284     arm_col.green = g;
285     arm_col.blue  = b;
286     if (!XAllocColor(disp, cmap, &arm_col))
287 	return False;
288     w->shadow.arm_pixel = arm_col.pixel;
289 
290     return True;
291 }
292 
AllocArmPixmap(ShadowWidget w,Pixel pix)293 static void AllocArmPixmap(ShadowWidget w, Pixel pix)
294 {
295     if (w->core.depth == 1)
296 	w->shadow.arm_pixmap = CacheCreatePixmap(w, 4, 0, 1);
297     else
298 	w->shadow.arm_pixmap =
299 	    CacheCreatePixmap(w, 4, get_black((Widget)w), pix);
300 }
301 
AllocGCs(ShadowWidget w)302 static void AllocGCs(ShadowWidget w)
303 {
304     ShadowWidgetClass	class = (ShadowWidgetClass)XtClass(w);
305     XGCValues		values;
306 
307     if (w->shadow.alloced_shadow_pixels) {
308 	values.line_width = 1;
309 	values.foreground = w->shadow.light_pixel;
310 	w->shadow.light_gc =
311 	    XtGetGC((Widget)w, GCForeground | GCLineWidth, &values);
312 	values.foreground = w->shadow.dark_pixel;
313 	w->shadow.dark_gc =
314 	    XtGetGC((Widget)w, GCForeground | GCLineWidth, &values);
315     } else if (w->shadow.line_mode) {
316 	Pixel	pix = get_pixel(w);
317 
318 	/* depth == 1... */
319 	values.foreground = (pix == 1) ? 0 : 1;
320 	values.line_width = 1;
321 	w->shadow.light_gc =
322 	    XtGetGC((Widget)w, GCForeground | GCLineWidth, &values);
323 	values.line_width = w->shadow.shadow_width;
324 	w->shadow.dark_gc =
325 	    XtGetGC((Widget)w, GCForeground | GCLineWidth, &values);
326     } else {
327 	Screen	*scr = XtScreen(w);
328 	Visual	*vis = get_visual((Widget)w);
329 	Pixel	black, white;
330 
331 	black_and_white(scr, vis, &black, &white);
332 	values.line_width = 1;
333 	if (w->shadow.light_pixmap == None) {
334 	    values.foreground =
335 		(w->core.background_pixel == black) ? white : black;
336 	    w->shadow.light_gc =
337 		XtGetGC((Widget)w, GCLineWidth | GCForeground, &values);
338 	} else {
339 	    values.fill_style = FillTiled;
340 	    values.tile = w->shadow.light_pixmap;
341 	    w->shadow.light_gc =
342 		XtGetGC((Widget)w,
343 			GCLineWidth | GCFillStyle | GCTile,
344 			&values);
345 	}
346 
347 	if (w->shadow.dark_pixmap == None) {
348 	    values.foreground =
349 		(w->core.background_pixel == black) ? white : black;
350 	    w->shadow.dark_gc =
351 		XtGetGC((Widget)w, GCLineWidth | GCForeground, &values);
352 	} else {
353 	    values.fill_style = FillTiled;
354 	    values.tile = w->shadow.dark_pixmap;
355 	    w->shadow.dark_gc =
356 		XtGetGC((Widget)w,
357 			GCLineWidth | GCFillStyle | GCTile,
358 			&values);
359 	}
360     }
361 
362     if (class->shadow_class.use_arm_for_background)
363 	return;
364 
365     if (w->shadow.alloced_arm_pixel) {
366 	values.line_width = 1;
367 	values.foreground = w->shadow.arm_pixel;
368 	w->shadow.arm_gc =
369 	    XtGetGC((Widget)w, GCForeground | GCLineWidth, &values);
370     } else if (w->shadow.arm_pixmap != None) {
371 	values.line_width = 1;
372 	values.tile = w->shadow.arm_pixmap;
373 	values.fill_style = FillTiled;
374 	w->shadow.arm_gc =
375 	    XtGetGC((Widget)w, GCFillStyle | GCTile| GCLineWidth, &values);
376     }
377 }
378 
379 /*************************************************************************/
380 
ClassPartInitialize(WidgetClass gclass)381 static void ClassPartInitialize(WidgetClass gclass)
382 {
383     ShadowClassRec	*class, *super;
384 
385     class = (ShadowClassRec *)gclass;
386     super = (ShadowClassRec *)class->core_class.superclass;
387 
388     if (class->shadow_class.pixel_offset == XtInheritPixelOffset)
389 	class->shadow_class.pixel_offset = super->shadow_class.pixel_offset;
390     if (class->shadow_class.alloc_shadow_colors == XtInheritAllocShadowColors)
391 	class->shadow_class.alloc_shadow_colors =
392 	    super->shadow_class.alloc_shadow_colors;
393     if (class->shadow_class.alloc_shadow_pixmaps ==
394 	XtInheritAllocShadowPixmaps)
395 	class->shadow_class.alloc_shadow_pixmaps =
396 	    super->shadow_class.alloc_shadow_pixmaps;
397     if (class->shadow_class.alloc_arm_color == XtInheritAllocArmColor)
398 	class->shadow_class.alloc_arm_color =
399 	    super->shadow_class.alloc_arm_color;
400     if (class->shadow_class.alloc_arm_pixmap == XtInheritAllocArmPixmap)
401 	class->shadow_class.alloc_arm_pixmap =
402 	    super->shadow_class.alloc_arm_pixmap;
403     if (class->shadow_class.alloc_gcs == XtInheritAllocGCs)
404 	class->shadow_class.alloc_gcs = super->shadow_class.alloc_gcs;
405 }
406 
Initialize(Widget grequest,Widget gnew,ArgList args,Cardinal * no_args)407 static void Initialize(Widget grequest, Widget gnew,
408 		       ArgList args, Cardinal *no_args)
409 {
410     ShadowWidget	new = (ShadowWidget)gnew;
411     ShadowWidgetClass	class = (ShadowWidgetClass)XtClass(new);
412     Display		*disp = XtDisplay(new);
413     Colormap		cmap = new->core.colormap;
414     XColor		col;
415     Boolean		query_done = False;
416 
417     new->shadow.light_pixmap = None;
418     new->shadow.dark_pixmap  = None;
419     new->shadow.arm_pixmap   = None;
420     new->shadow.light_gc = (GC)0;
421     new->shadow.dark_gc  = (GC)0;
422     new->shadow.arm_gc   = (GC)0;
423     new->shadow.line_mode = False;
424     new->shadow.alloced_shadow_pixels = False;
425     new->shadow.alloced_arm_pixel = False;
426     col.pixel = get_pixel(new);
427 
428     if (new->shadow.alloc_shadow_colors && new->core.depth != 1 &&
429 	class->shadow_class.alloc_shadow_colors) {
430 	XQueryColor(disp, cmap, &col);
431 	query_done = True;
432 	if (class->shadow_class.alloc_shadow_colors(new, &col))
433 	    new->shadow.alloced_shadow_pixels = True;
434     }
435 
436     if (!new->shadow.alloced_shadow_pixels)
437 	if (new->shadow.use_lines && new->core.depth == 1)
438 	    new->shadow.line_mode = True;
439 	else if (class->shadow_class.alloc_shadow_pixmaps)
440 	    class->shadow_class.alloc_shadow_pixmaps(new, col.pixel);
441 
442     if (new->shadow.alloc_arm_color && class->shadow_class.alloc_arm_color &&
443 	new->core.depth != 1) {
444 	if (!query_done)
445 	    XQueryColor(disp, cmap, &col);
446 	if (class->shadow_class.alloc_arm_color(new, &col))
447 	    new->shadow.alloced_arm_pixel = True;
448     }
449 
450     if (!new->shadow.alloced_arm_pixel && new->shadow.alloc_arm_pixmap &&
451 	class->shadow_class.alloc_arm_pixmap)
452 	class->shadow_class.alloc_arm_pixmap(new, col.pixel);
453 
454     if (class->shadow_class.alloc_gcs)
455 	class->shadow_class.alloc_gcs(new);
456 }
457 
Realize(Widget gw,XtValueMask * mask,XSetWindowAttributes * attributes)458 static void Realize(Widget gw, XtValueMask *mask,
459 		    XSetWindowAttributes *attributes)
460 {
461     ShadowWidget	w = (ShadowWidget)gw;
462     ShadowWidgetClass	class = (ShadowWidgetClass)XtClass(w);
463 
464     if (class->shadow_class.use_arm_for_background)
465 	if (w->shadow.arm_pixmap != None) {
466 	    *mask |= CWBackPixmap;
467 	    *mask &= ~CWBackPixel;
468 	    attributes->background_pixmap = w->shadow.arm_pixmap;
469 	} else if (w->shadow.alloced_arm_pixel) {
470 	    *mask |= CWBackPixel;
471 	    attributes->background_pixel = w->shadow.arm_pixel;
472 	}
473 
474     coreWidgetClass->core_class.realize((Widget)w, mask, attributes);
475 }
476 
Destroy(Widget gw)477 static void Destroy(Widget gw)
478 {
479     ShadowWidget	w = (ShadowWidget)gw;
480     Display		*disp = XtDisplay(w);
481     unsigned long	pixels[3];
482     int			n = 0;
483 
484     if (w->shadow.light_gc != 0)
485 	XtReleaseGC((Widget)w, w->shadow.light_gc);
486     if (w->shadow.dark_gc != 0)
487 	XtReleaseGC((Widget)w, w->shadow.dark_gc);
488     if (w->shadow.arm_gc != 0)
489 	XtReleaseGC((Widget)w, w->shadow.arm_gc);
490     if (w->shadow.light_pixmap != None)
491 	CacheFreePixmap(w, w->shadow.light_pixmap);
492     if (w->shadow.dark_pixmap != None)
493 	CacheFreePixmap(w, w->shadow.dark_pixmap);
494     if (w->shadow.arm_pixmap != None)
495 	CacheFreePixmap(w, w->shadow.arm_pixmap);
496     if (w->shadow.alloced_shadow_pixels) {
497 	pixels[n] = w->shadow.light_pixel;
498 	n++;
499 	pixels[n] = w->shadow.dark_pixel;
500 	n++;
501     }
502     if (w->shadow.alloced_arm_pixel) {
503 	pixels[n] = w->shadow.arm_pixel;
504 	n++;
505     }
506     if (n != 0) {
507 	Colormap	cmap = w->core.colormap;
508 
509 	XFreeColors(disp, cmap, pixels, n, 0);
510     }
511 }
512 
SetValues(Widget gcurrent,Widget grequest,Widget gnew,ArgList args,Cardinal * num_args)513 static Boolean SetValues(Widget gcurrent,
514 			 Widget grequest,
515 			 Widget gnew,
516 			 ArgList args,
517 			 Cardinal *num_args)
518 {
519     Boolean		redisplay = False;
520     ShadowWidget	new = (ShadowWidget)gnew;
521     ShadowWidget	current = (ShadowWidget)gcurrent;
522     ShadowWidgetClass	class = (ShadowWidgetClass)XtClass(new);
523     Pixel		new_pix = get_pixel(new);
524     Pixel		current_pix = get_pixel(current);
525 
526     if (new_pix != current_pix ||
527 	(new->shadow.line_mode &&
528 	 new->shadow.shadow_width != current->shadow.shadow_width) ||
529 	new->shadow.alloc_shadow_colors !=
530 	current->shadow.alloc_shadow_colors ||
531 	new->shadow.alloc_arm_color != current->shadow.alloc_arm_color ||
532 	new->shadow.use_lines != current->shadow.use_lines ||
533 	new->shadow.alloc_arm_pixmap != current->shadow.alloc_arm_pixmap) {
534 	Pixel	pixels[3];
535 	int	n = 0;
536 
537 	/* initialize first, then free, except for pixels... */
538 	if (current->shadow.alloced_shadow_pixels) {
539 	    pixels[n++] = current->shadow.light_pixel;
540 	    pixels[n++] = current->shadow.dark_pixel;
541 	}
542 	if (current->shadow.alloced_arm_pixel)
543 	    pixels[n++] = current->shadow.arm_pixel;
544 
545 	if (n > 0)
546 	    XFreeColors(XtDisplay(current),
547 			current->core.colormap, pixels, n, 0);
548 
549 	Initialize(NULL, (Widget)new, NULL, NULL);
550 
551 	if (current->shadow.light_gc != 0)
552 	    XtReleaseGC((Widget)new, current->shadow.light_gc);
553 	if (current->shadow.dark_gc != 0)
554 	    XtReleaseGC((Widget)new, current->shadow.dark_gc);
555 	if (current->shadow.arm_gc != 0)
556 	    XtReleaseGC((Widget)new, current->shadow.arm_gc);
557 	if (current->shadow.light_pixmap != None)
558 	    CacheFreePixmap(new, current->shadow.light_pixmap);
559 	if (current->shadow.dark_pixmap != None)
560 	    CacheFreePixmap(new, current->shadow.dark_pixmap);
561 	if (current->shadow.arm_pixmap != None)
562 	    CacheFreePixmap(new, current->shadow.arm_pixmap);
563 
564 	redisplay = True;
565     }
566 
567     if (class->shadow_class.use_arm_for_background &&
568 	(redisplay ||
569 	 new->core.background_pixel != current->core.background_pixel)) {
570 	Display			*disp = XtDisplay(new);
571 	Window			win = XtWindow(new);
572 
573 	if (new->shadow.alloced_arm_pixel)
574 	    XSetWindowBackground(disp, win, new->shadow.arm_pixel);
575 	else if (new->shadow.arm_pixmap != None)
576 	    XSetWindowBackgroundPixmap(disp, win, new->shadow.arm_pixmap);
577 	else
578 	    XSetWindowBackground(disp, win, new->core.background_pixel);
579     }
580 
581     return redisplay;
582 }
583 
584 /*************************************************************************/
585 
ShadowDrawShadows(ShadowWidget w,Position x,Position y,Dimension width,Dimension height,Boolean swap)586 void ShadowDrawShadows(ShadowWidget w, Position x, Position y,
587 		       Dimension width, Dimension height, Boolean swap)
588 {
589     Display	*disp = XtDisplay(w);
590     Window	win = XtWindow(w);
591     short	sw = w->shadow.shadow_width;
592 
593     if (sw == 0 || !XtIsRealized((Widget)w)) return;
594 
595     if (w->shadow.line_mode) {
596 	if (swap)
597 	    XDrawRectangle(disp, win, w->shadow.dark_gc, x + sw/2, y + sw/2,
598 			   width - sw, height - sw);
599 	else
600 	    XDrawRectangle(disp, win, w->shadow.light_gc, x, y,
601 			   width - 1, height - 1);
602     } else {
603 	GC	light_gc, dark_gc;
604 	XPoint	points[6];
605 
606 	if (swap) {
607 	    light_gc = w->shadow.dark_gc;
608 	    dark_gc  = w->shadow.light_gc;
609 	} else {
610 	    light_gc = w->shadow.light_gc;
611 	    dark_gc  = w->shadow.dark_gc;
612 	}
613 
614 	points[0].x = x;
615 	points[0].y = y;
616 	points[1].x = x + width;
617 	points[1].y = y;
618 	points[2].x = x + width - sw;
619 	points[2].y = y + sw;
620 	points[3].x = x + sw;
621 	points[3].y = y + sw;
622 	points[4].x = x + sw;
623 	points[4].y = y + height - sw;
624 	points[5].x = x;
625 	points[5].y = y + height;
626 	XFillPolygon(disp, win, light_gc, points, 6,
627 		     (sw > 1) ? Nonconvex : Complex, CoordModeOrigin);
628 
629 	points[0].x = x + width;
630 	points[0].y = y + height;
631 	points[3].x = x + width - sw;
632 	points[3].y = y + height - sw;
633 	XFillPolygon(disp, win, dark_gc, points, 6,
634 		     (sw > 1) ? Nonconvex : Complex, CoordModeOrigin);
635     }
636 }
637 
638 /* the widget must be able to handle NULL events and regions */
639 
ShadowRedrawWidget(Widget w)640 void ShadowRedrawWidget(Widget w)
641 {
642     if (XtIsRealized(w)) {
643 	XtExposeProc	expose_proc = XtClass(w)->core_class.expose;
644 
645 	if (expose_proc)
646 	    expose_proc(w, NULL, NULL);
647     }
648 }
649