Change to the linux kernel coding style
[wmaker-crm.git] / src / texture.c
1 /*
2  *  Window Maker window manager
3  *
4  *  Copyright (c) 1997-2003 Alfredo K. Kojima
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  *  USA.
20  */
21
22 #include "wconfig.h"
23
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26
27 #ifdef TEXTURE_PLUGIN
28 # ifdef HAVE_DLFCN_H
29 #  include <dlfcn.h>
30 # endif
31 #endif
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include <wraster.h>
38
39 #include "WindowMaker.h"
40 #include "wcore.h"
41 #include "texture.h"
42 #include "funcs.h"
43
44 extern WPreferences wPreferences;
45
46 static void bevelImage(RImage * image, int relief);
47
48 WTexSolid *wTextureMakeSolid(WScreen * scr, XColor * color)
49 {
50         WTexSolid *texture;
51         int gcm;
52         XGCValues gcv;
53
54         texture = wmalloc(sizeof(WTexture));
55
56         texture->type = WTEX_SOLID;
57         texture->subtype = 0;
58
59         XAllocColor(dpy, scr->w_colormap, color);
60         texture->normal = *color;
61         if (color->red == 0 && color->blue == 0 && color->green == 0) {
62                 texture->light.red = 0xb6da;
63                 texture->light.green = 0xb6da;
64                 texture->light.blue = 0xb6da;
65                 texture->dim.red = 0x6185;
66                 texture->dim.green = 0x6185;
67                 texture->dim.blue = 0x6185;
68         } else {
69                 RColor rgb;
70                 RHSVColor hsv, hsv2;
71                 int v;
72
73                 rgb.red = color->red >> 8;
74                 rgb.green = color->green >> 8;
75                 rgb.blue = color->blue >> 8;
76                 RRGBtoHSV(&rgb, &hsv);
77                 RHSVtoRGB(&hsv, &rgb);
78                 hsv2 = hsv;
79
80                 v = hsv.value * 16 / 10;
81                 hsv.value = (v > 255 ? 255 : v);
82                 RHSVtoRGB(&hsv, &rgb);
83                 texture->light.red = rgb.red << 8;
84                 texture->light.green = rgb.green << 8;
85                 texture->light.blue = rgb.blue << 8;
86
87                 hsv2.value = hsv2.value / 2;
88                 RHSVtoRGB(&hsv2, &rgb);
89                 texture->dim.red = rgb.red << 8;
90                 texture->dim.green = rgb.green << 8;
91                 texture->dim.blue = rgb.blue << 8;
92         }
93         texture->dark.red = 0;
94         texture->dark.green = 0;
95         texture->dark.blue = 0;
96         XAllocColor(dpy, scr->w_colormap, &texture->light);
97         XAllocColor(dpy, scr->w_colormap, &texture->dim);
98         XAllocColor(dpy, scr->w_colormap, &texture->dark);
99
100         gcm = GCForeground | GCBackground | GCGraphicsExposures;
101         gcv.graphics_exposures = False;
102
103         gcv.background = gcv.foreground = texture->light.pixel;
104         texture->light_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
105
106         gcv.background = gcv.foreground = texture->dim.pixel;
107         texture->dim_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
108
109         gcv.background = gcv.foreground = texture->dark.pixel;
110         texture->dark_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
111
112         gcv.background = gcv.foreground = color->pixel;
113         texture->normal_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
114
115         return texture;
116 }
117
118 static int dummyErrorHandler(Display * foo, XErrorEvent * bar)
119 {
120 #ifdef DEBUG
121         wwarning("your server is buggy. Tell the author if some error related to color occurs");
122 #endif
123         return 0;
124 }
125
126 void wTextureDestroy(WScreen * scr, WTexture * texture)
127 {
128         int i;
129         int count = 0;
130         unsigned long colors[8];
131
132 #ifdef DEBUG
133         if (texture == NULL) {
134                 printf("BUG: trying to free NULL texture\n");
135                 return;
136         }
137 #endif
138
139         /*
140          * some stupid servers don't like white or black being freed...
141          */
142 #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
143         switch (texture->any.type) {
144         case WTEX_SOLID:
145                 XFreeGC(dpy, texture->solid.light_gc);
146                 XFreeGC(dpy, texture->solid.dark_gc);
147                 XFreeGC(dpy, texture->solid.dim_gc);
148                 if (CANFREE(texture->solid.light.pixel))
149                         colors[count++] = texture->solid.light.pixel;
150                 if (CANFREE(texture->solid.dim.pixel))
151                         colors[count++] = texture->solid.dim.pixel;
152                 if (CANFREE(texture->solid.dark.pixel))
153                         colors[count++] = texture->solid.dark.pixel;
154                 break;
155
156         case WTEX_PIXMAP:
157                 RReleaseImage(texture->pixmap.pixmap);
158                 break;
159
160         case WTEX_MHGRADIENT:
161         case WTEX_MVGRADIENT:
162         case WTEX_MDGRADIENT:
163                 for (i = 0; texture->mgradient.colors[i] != NULL; i++) {
164                         wfree(texture->mgradient.colors[i]);
165                 }
166                 wfree(texture->mgradient.colors);
167                 break;
168
169         case WTEX_THGRADIENT:
170         case WTEX_TVGRADIENT:
171         case WTEX_TDGRADIENT:
172                 RReleaseImage(texture->tgradient.pixmap);
173                 break;
174
175 #ifdef TEXTURE_PLUGIN
176         case WTEX_FUNCTION:
177 #ifdef HAVE_DLFCN_H
178                 if (texture->function.handle) {
179                         dlclose(texture->function.handle);
180                 }
181 #endif
182                 for (i = 0; i < texture->function.argc; i++) {
183                         wfree(texture->function.argv[i]);
184                 }
185                 wfree(texture->function.argv);
186                 break;
187 #endif                          /* TEXTURE_PLUGIN */
188         }
189         if (CANFREE(texture->any.color.pixel))
190                 colors[count++] = texture->any.color.pixel;
191         if (count > 0) {
192                 XErrorHandler oldhandler;
193
194                 /* ignore error from buggy servers that don't know how
195                  * to do reference counting for colors. */
196                 XSync(dpy, 0);
197                 oldhandler = XSetErrorHandler(dummyErrorHandler);
198                 XFreeColors(dpy, scr->w_colormap, colors, count, 0);
199                 XSync(dpy, 0);
200                 XSetErrorHandler(oldhandler);
201         }
202         XFreeGC(dpy, texture->any.gc);
203         wfree(texture);
204 #undef CANFREE
205 }
206
207 WTexGradient *wTextureMakeGradient(WScreen * scr, int style, RColor * from, RColor * to)
208 {
209         WTexGradient *texture;
210         XGCValues gcv;
211
212         texture = wmalloc(sizeof(WTexture));
213         memset(texture, 0, sizeof(WTexture));
214         texture->type = style;
215         texture->subtype = 0;
216
217         texture->color1 = *from;
218         texture->color2 = *to;
219
220         texture->normal.red = (from->red + to->red) << 7;
221         texture->normal.green = (from->green + to->green) << 7;
222         texture->normal.blue = (from->blue + to->blue) << 7;
223
224         XAllocColor(dpy, scr->w_colormap, &texture->normal);
225         gcv.background = gcv.foreground = texture->normal.pixel;
226         gcv.graphics_exposures = False;
227         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
228
229         return texture;
230 }
231
232 WTexIGradient *wTextureMakeIGradient(WScreen * scr, int thickness1, RColor colors1[2],
233                                      int thickness2, RColor colors2[2])
234 {
235         WTexIGradient *texture;
236         XGCValues gcv;
237         int i;
238
239         texture = wmalloc(sizeof(WTexture));
240         memset(texture, 0, sizeof(WTexture));
241         texture->type = WTEX_IGRADIENT;
242         for (i = 0; i < 2; i++) {
243                 texture->colors1[i] = colors1[i];
244                 texture->colors2[i] = colors2[i];
245         }
246         texture->thickness1 = thickness1;
247         texture->thickness2 = thickness2;
248         if (thickness1 >= thickness2) {
249                 texture->normal.red = (colors1[0].red + colors1[1].red) << 7;
250                 texture->normal.green = (colors1[0].green + colors1[1].green) << 7;
251                 texture->normal.blue = (colors1[0].blue + colors1[1].blue) << 7;
252         } else {
253                 texture->normal.red = (colors2[0].red + colors2[1].red) << 7;
254                 texture->normal.green = (colors2[0].green + colors2[1].green) << 7;
255                 texture->normal.blue = (colors2[0].blue + colors2[1].blue) << 7;
256         }
257         XAllocColor(dpy, scr->w_colormap, &texture->normal);
258         gcv.background = gcv.foreground = texture->normal.pixel;
259         gcv.graphics_exposures = False;
260         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
261
262         return texture;
263 }
264
265 WTexMGradient *wTextureMakeMGradient(WScreen * scr, int style, RColor ** colors)
266 {
267         WTexMGradient *texture;
268         XGCValues gcv;
269         int i;
270
271         texture = wmalloc(sizeof(WTexture));
272         memset(texture, 0, sizeof(WTexture));
273         texture->type = style;
274         texture->subtype = 0;
275
276         i = 0;
277         while (colors[i] != NULL)
278                 i++;
279         i--;
280         texture->normal.red = (colors[0]->red << 8);
281         texture->normal.green = (colors[0]->green << 8);
282         texture->normal.blue = (colors[0]->blue << 8);
283
284         texture->colors = colors;
285
286         XAllocColor(dpy, scr->w_colormap, &texture->normal);
287         gcv.background = gcv.foreground = texture->normal.pixel;
288         gcv.graphics_exposures = False;
289         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
290
291         return texture;
292 }
293
294 WTexPixmap *wTextureMakePixmap(WScreen * scr, int style, char *pixmap_file, XColor * color)
295 {
296         WTexPixmap *texture;
297         XGCValues gcv;
298         RImage *image;
299         char *file;
300
301         file = FindImage(wPreferences.pixmap_path, pixmap_file);
302         if (!file) {
303                 wwarning(_("image file \"%s\" used as texture could not be found."), pixmap_file);
304                 return NULL;
305         }
306         image = RLoadImage(scr->rcontext, file, 0);
307         if (!image) {
308                 wwarning(_("could not load texture pixmap \"%s\":%s"), file, RMessageForError(RErrorCode));
309                 wfree(file);
310                 return NULL;
311         }
312         wfree(file);
313
314         texture = wmalloc(sizeof(WTexture));
315         memset(texture, 0, sizeof(WTexture));
316         texture->type = WTEX_PIXMAP;
317         texture->subtype = style;
318
319         texture->normal = *color;
320
321         XAllocColor(dpy, scr->w_colormap, &texture->normal);
322         gcv.background = gcv.foreground = texture->normal.pixel;
323         gcv.graphics_exposures = False;
324         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
325
326         texture->pixmap = image;
327
328         return texture;
329 }
330
331 WTexTGradient *wTextureMakeTGradient(WScreen * scr, int style, RColor * from, RColor * to,
332                                      char *pixmap_file, int opacity)
333 {
334         WTexTGradient *texture;
335         XGCValues gcv;
336         RImage *image;
337         char *file;
338
339         file = FindImage(wPreferences.pixmap_path, pixmap_file);
340         if (!file) {
341                 wwarning(_("image file \"%s\" used as texture could not be found."), pixmap_file);
342                 return NULL;
343         }
344         image = RLoadImage(scr->rcontext, file, 0);
345         if (!image) {
346                 wwarning(_("could not load texture pixmap \"%s\":%s"), file, RMessageForError(RErrorCode));
347                 wfree(file);
348                 return NULL;
349         }
350         wfree(file);
351
352         texture = wmalloc(sizeof(WTexture));
353         memset(texture, 0, sizeof(WTexture));
354         texture->type = style;
355
356         texture->opacity = opacity;
357
358         texture->color1 = *from;
359         texture->color2 = *to;
360
361         texture->normal.red = (from->red + to->red) << 7;
362         texture->normal.green = (from->green + to->green) << 7;
363         texture->normal.blue = (from->blue + to->blue) << 7;
364
365         XAllocColor(dpy, scr->w_colormap, &texture->normal);
366         gcv.background = gcv.foreground = texture->normal.pixel;
367         gcv.graphics_exposures = False;
368         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
369
370         texture->pixmap = image;
371
372         return texture;
373 }
374
375 #ifdef TEXTURE_PLUGIN
376 WTexFunction *wTextureMakeFunction(WScreen * scr, char *lib, char *func, int argc, char **argv)
377 {
378         XColor fallbackColor;
379         XGCValues gcv;
380         WTexFunction *texture;
381
382         texture = wmalloc(sizeof(WTexture));
383         texture->type = WTEX_FUNCTION;
384         texture->handle = NULL;
385         texture->render = 0;
386         texture->argc = argc;
387         texture->argv = argv;
388
389         fallbackColor.red = 0x8000;
390         fallbackColor.green = 0x8000;
391         fallbackColor.blue = 0x8000;
392
393         gcv.background = gcv.foreground = fallbackColor.pixel;
394         gcv.graphics_exposures = False;
395         texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
396
397 # ifdef HAVE_DLFCN_H
398         /* open the library */
399         texture->handle = dlopen(lib, RTLD_LAZY);
400         if (!texture->handle) {
401                 wwarning(_("library \"%s\" cound not be opened."), lib);
402                 wfree(argv);
403                 wfree(texture);
404                 return NULL;
405         }
406
407         /* find the function */
408         texture->render = dlsym(texture->handle, func);
409         if (!texture->render) {
410                 wwarning(_("function \"%s\" not found in library \"%s\""), func, lib);
411                 wfree(argv);
412                 dlclose(texture->handle);
413                 wfree(texture);
414                 return NULL;
415         }
416 # else
417         wwarning(_("function textures not supported on this system, sorry."));
418 # endif
419
420         /* success! */
421         return texture;
422 }
423 #endif                          /* TEXTURE_PLUGIN */
424
425 RImage *wTextureRenderImage(WTexture * texture, int width, int height, int relief)
426 {
427         RImage *image = NULL;
428         RColor color1;
429         int d;
430         int subtype;
431
432         switch (texture->any.type) {
433         case WTEX_SOLID:
434                 image = RCreateImage(width, height, False);
435
436                 color1.red = texture->solid.normal.red >> 8;
437                 color1.green = texture->solid.normal.green >> 8;
438                 color1.blue = texture->solid.normal.blue >> 8;
439                 color1.alpha = 255;
440
441                 RClearImage(image, &color1);
442                 break;
443
444         case WTEX_PIXMAP:
445                 if (texture->pixmap.subtype == WTP_TILE) {
446                         image = RMakeTiledImage(texture->pixmap.pixmap, width, height);
447                 } else if (texture->pixmap.subtype == WTP_CENTER) {
448                         color1.red = texture->pixmap.normal.red >> 8;
449                         color1.green = texture->pixmap.normal.green >> 8;
450                         color1.blue = texture->pixmap.normal.blue >> 8;
451                         color1.alpha = 255;
452                         image = RMakeCenteredImage(texture->pixmap.pixmap, width, height, &color1);
453                 } else {
454                         image = RScaleImage(texture->pixmap.pixmap, width, height);
455                 }
456                 break;
457
458         case WTEX_IGRADIENT:
459                 image = RRenderInterwovenGradient(width, height,
460                                                   texture->igradient.colors1,
461                                                   texture->igradient.thickness1,
462                                                   texture->igradient.colors2, texture->igradient.thickness2);
463                 break;
464
465         case WTEX_HGRADIENT:
466                 subtype = RGRD_HORIZONTAL;
467                 goto render_gradient;
468
469         case WTEX_VGRADIENT:
470                 subtype = RGRD_VERTICAL;
471                 goto render_gradient;
472
473         case WTEX_DGRADIENT:
474                 subtype = RGRD_DIAGONAL;
475  render_gradient:
476
477                 image = RRenderGradient(width, height, &texture->gradient.color1,
478                                         &texture->gradient.color2, subtype);
479                 break;
480
481         case WTEX_MHGRADIENT:
482                 subtype = RGRD_HORIZONTAL;
483                 goto render_mgradient;
484
485         case WTEX_MVGRADIENT:
486                 subtype = RGRD_VERTICAL;
487                 goto render_mgradient;
488
489         case WTEX_MDGRADIENT:
490                 subtype = RGRD_DIAGONAL;
491  render_mgradient:
492                 image = RRenderMultiGradient(width, height, &(texture->mgradient.colors[1]), subtype);
493                 break;
494
495         case WTEX_THGRADIENT:
496                 subtype = RGRD_HORIZONTAL;
497                 goto render_tgradient;
498
499         case WTEX_TVGRADIENT:
500                 subtype = RGRD_VERTICAL;
501                 goto render_tgradient;
502
503         case WTEX_TDGRADIENT:
504                 subtype = RGRD_DIAGONAL;
505  render_tgradient:
506                 {
507                         RImage *grad;
508
509                         image = RMakeTiledImage(texture->tgradient.pixmap, width, height);
510                         if (!image)
511                                 break;
512
513                         grad = RRenderGradient(width, height, &texture->tgradient.color1,
514                                                &texture->tgradient.color2, subtype);
515                         if (!grad) {
516                                 RReleaseImage(image);
517                                 image = NULL;
518                                 break;
519                         }
520
521                         RCombineImagesWithOpaqueness(image, grad, texture->tgradient.opacity);
522                         RReleaseImage(grad);
523                 }
524                 break;
525
526 #ifdef TEXTURE_PLUGIN
527         case WTEX_FUNCTION:
528 #ifdef HAVE_DLFCN_H
529                 if (texture->function.render) {
530                         image = texture->function.render(texture->function.argc, texture->function.argv,
531                                                          width, height, relief);
532                 }
533 #endif
534                 if (!image) {
535                         RErrorCode = RERR_INTERNAL;
536                 }
537                 break;
538 #endif                          /* TEXTURE_PLUGIN */
539
540         default:
541                 puts("ERROR in wTextureRenderImage()");
542                 image = NULL;
543                 break;
544         }
545
546         if (!image) {
547                 RColor gray;
548
549                 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
550
551                 image = RCreateImage(width, height, False);
552                 if (image == NULL) {
553                         wwarning(_("could not allocate image buffer"));
554                         return NULL;
555                 }
556
557                 gray.red = 190;
558                 gray.green = 190;
559                 gray.blue = 190;
560                 gray.alpha = 255;
561                 RClearImage(image, &gray);
562         }
563
564         /* render bevel */
565
566         switch (relief) {
567         case WREL_ICON:
568                 d = RBEV_RAISED3;
569                 break;
570
571         case WREL_RAISED:
572                 d = RBEV_RAISED2;
573                 break;
574
575         case WREL_SUNKEN:
576                 d = RBEV_SUNKEN;
577                 break;
578
579         case WREL_FLAT:
580                 d = 0;
581                 break;
582
583         case WREL_MENUENTRY:
584                 d = -WREL_MENUENTRY;
585                 break;
586
587         default:
588                 d = 0;
589         }
590
591         if (d > 0) {
592                 RBevelImage(image, d);
593         } else if (d < 0) {
594                 bevelImage(image, -d);
595         }
596
597         return image;
598 }
599
600 static void bevelImage(RImage * image, int relief)
601 {
602         int width = image->width;
603         int height = image->height;
604         RColor color;
605
606         switch (relief) {
607         case WREL_MENUENTRY:
608                 color.red = color.green = color.blue = 80;
609                 color.alpha = 0;
610                  /**/ ROperateLine(image, RAddOperation, 1, 0, width - 2, 0, &color);
611                  /**/ ROperateLine(image, RAddOperation, 0, 0, 0, height - 1, &color);
612
613                 color.red = color.green = color.blue = 40;
614                 color.alpha = 0;
615                 ROperateLine(image, RSubtractOperation, width - 1, 0, width - 1, height - 1, &color);
616
617                  /**/ ROperateLine(image, RSubtractOperation, 1, height - 2, width - 2, height - 2, &color);
618
619                 color.red = color.green = color.blue = 0;
620                 color.alpha = 255;
621                 RDrawLine(image, 0, height - 1, width - 1, height - 1, &color);
622                  /**/ break;
623
624         }
625 }
626
627 void wDrawBevel(Drawable d, unsigned width, unsigned height, WTexSolid * texture, int relief)
628 {
629         GC light, dim, dark;
630         XSegment segs[4];
631
632         if (relief == WREL_FLAT)
633                 return;
634
635         light = texture->light_gc;
636         dim = texture->dim_gc;
637         dark = texture->dark_gc;
638         switch (relief) {
639         case WREL_FLAT:
640                 return;
641         case WREL_MENUENTRY:
642         case WREL_RAISED:
643         case WREL_ICON:
644                 segs[0].x1 = 1;
645                 segs[0].x2 = width - 2;
646                 segs[0].y2 = segs[0].y1 = height - 2;
647                 segs[1].x1 = width - 2;
648                 segs[1].y1 = 1;
649                 segs[1].x2 = width - 2;
650                 segs[1].y2 = height - 2;
651                 XDrawSegments(dpy, d, dim, segs, 2);
652                 segs[0].x1 = 0;
653                 segs[0].x2 = width - 1;
654                 segs[0].y2 = segs[0].y1 = height - 1;
655                 segs[1].x1 = segs[1].x2 = width - 1;
656                 segs[1].y1 = 0;
657                 segs[1].y2 = height - 1;
658                 XDrawSegments(dpy, d, dark, segs, 2);
659                 segs[0].x1 = segs[0].y1 = segs[0].y2 = 0;
660                 segs[0].x2 = width - 2;
661                 segs[1].x1 = segs[1].y1 = 0;
662                 segs[1].x2 = 0;
663                 segs[1].y2 = height - 2;
664                 XDrawSegments(dpy, d, light, segs, 2);
665                 if (relief == WREL_ICON) {
666                         segs[0].x1 = segs[0].y1 = segs[0].y2 = 1;
667                         segs[0].x2 = width - 2;
668                         segs[1].x1 = segs[1].y1 = 1;
669                         segs[1].x2 = 1;
670                         segs[1].y2 = height - 2;
671                         XDrawSegments(dpy, d, light, segs, 2);
672                 }
673                 break;
674 #ifdef unused
675         case WREL_SUNKEN:
676                 segs[0].x1 = 0;
677                 segs[0].x2 = width - 1;
678                 segs[0].y2 = segs[0].y1 = 0;
679                 segs[1].x1 = segs[1].x2 = 0;
680                 segs[1].y1 = 0;
681                 segs[1].y2 = height - 1;
682                 XDrawSegments(dpy, d, dark, segs, 2);
683
684                 segs[0].x1 = 0;
685                 segs[0].y1 = segs[0].y2 = height - 1;
686                 segs[0].x2 = width - 1;
687                 segs[1].x2 = segs[1].x1 = width - 1;
688                 segs[1].y1 = 1;
689                 segs[1].y2 = height - 1;
690                 XDrawSegments(dpy, d, light, segs, 2);
691                 break;
692 #endif
693         }
694 }