1 /*
2 * Builtin bitmap image generation/lookup.
3 */
4
5 #include "ctwm.h"
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #include <X11/Xmu/Drawing.h>
11
12 #include "screen.h"
13 #include "drawing.h"
14 #include "icons_builtin.h"
15
16 #include "image.h"
17 #include "image_bitmap_builtin.h"
18
19
20 /*
21 * Firstly, the plain built-in titlebar symbols. These are the ones
22 * specified with names like ":resize". For various reasons, these
23 * currently return Pixmap's, unlike most of our other builtins that
24 * generate Image's. Possible cleanup candidate.
25 */
26 #define DEF_BI_PPM(nm) Pixmap nm(unsigned int *widthp, unsigned int *heightp)
27 static DEF_BI_PPM(CreateXLogoPixmap);
28 static DEF_BI_PPM(CreateResizePixmap);
29 static DEF_BI_PPM(CreateQuestionPixmap);
30 static DEF_BI_PPM(CreateMenuPixmap);
31 static DEF_BI_PPM(CreateDotPixmap);
32
33
34
35 /*
36 * Look up and return a ":something" (not a ":xpm:something").
37 *
38 * Names of the form :name refer to hardcoded images that are scaled to
39 * look nice in title buttons. Eventually, it would be nice to put in a
40 * menu symbol as well....
41 */
42 Pixmap
get_builtin_plain_pixmap(const char * name,unsigned int * widthp,unsigned int * heightp)43 get_builtin_plain_pixmap(const char *name, unsigned int *widthp,
44 unsigned int *heightp)
45 {
46 int i;
47 static struct {
48 char *name;
49 DEF_BI_PPM((*proc));
50 } pmtab[] = {
51 /* Lookup table for our various default pixmaps */
52 { TBPM_DOT, CreateDotPixmap },
53 { TBPM_ICONIFY, CreateDotPixmap },
54 { TBPM_RESIZE, CreateResizePixmap },
55 { TBPM_XLOGO, CreateXLogoPixmap },
56 { TBPM_DELETE, CreateXLogoPixmap },
57 { TBPM_MENU, CreateMenuPixmap },
58 { TBPM_QUESTION, CreateQuestionPixmap },
59 };
60
61 /* Seatbelts */
62 if(!name || name[0] != ':') {
63 return None;
64 }
65 if(!widthp || !heightp) {
66 return None;
67 }
68
69
70 /* Find it */
71 for(i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
72 if(strcasecmp(pmtab[i].name, name) == 0) {
73 Pixmap pm = (*pmtab[i].proc)(widthp, heightp);
74 if(pm == None) {
75 fprintf(stderr, "%s: unable to build bitmap \"%s\"\n",
76 ProgramName, name);
77 return None;
78 }
79 return pm;
80 }
81 }
82
83 /* Didn't find it */
84 fprintf(stderr, "%s: no such built-in bitmap \"%s\"\n",
85 ProgramName, name);
86 return None;
87 }
88
89
90 /*
91 * Individual generators for those plain pixmaps
92 */
DEF_BI_PPM(CreateXLogoPixmap)93 DEF_BI_PPM(CreateXLogoPixmap)
94 {
95 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
96 if(h < 0) {
97 h = 0;
98 }
99
100 *widthp = *heightp = (unsigned int) h;
101 if(Scr->tbpm.xlogo == None) {
102 GC gc, gcBack;
103
104 Scr->tbpm.xlogo = XCreatePixmap(dpy, Scr->Root, h, h, 1);
105 gc = XCreateGC(dpy, Scr->tbpm.xlogo, 0L, NULL);
106 XSetForeground(dpy, gc, 0);
107 XFillRectangle(dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
108 XSetForeground(dpy, gc, 1);
109 gcBack = XCreateGC(dpy, Scr->tbpm.xlogo, 0L, NULL);
110 XSetForeground(dpy, gcBack, 0);
111
112 /*
113 * draw the logo large so that it gets as dense as possible; then white
114 * out the edges so that they look crisp
115 */
116 XmuDrawLogo(dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
117 XDrawRectangle(dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
118
119 /*
120 * done drawing
121 */
122 XFreeGC(dpy, gc);
123 XFreeGC(dpy, gcBack);
124 }
125 return Scr->tbpm.xlogo;
126 }
127
128
DEF_BI_PPM(CreateResizePixmap)129 DEF_BI_PPM(CreateResizePixmap)
130 {
131 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
132 if(h < 1) {
133 h = 1;
134 }
135
136 *widthp = *heightp = (unsigned int) h;
137 if(Scr->tbpm.resize == None) {
138 XPoint points[3];
139 GC gc;
140 int w;
141 int lw;
142
143 /*
144 * create the pixmap
145 */
146 Scr->tbpm.resize = XCreatePixmap(dpy, Scr->Root, h, h, 1);
147 gc = XCreateGC(dpy, Scr->tbpm.resize, 0L, NULL);
148 XSetForeground(dpy, gc, 0);
149 XFillRectangle(dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
150 XSetForeground(dpy, gc, 1);
151 lw = h / 16;
152 if(lw == 1) {
153 lw = 0;
154 }
155 XSetLineAttributes(dpy, gc, lw, LineSolid, CapButt, JoinMiter);
156
157 /*
158 * draw the resize button,
159 */
160 w = (h * 2) / 3;
161 points[0].x = w;
162 points[0].y = 0;
163 points[1].x = w;
164 points[1].y = w;
165 points[2].x = 0;
166 points[2].y = w;
167 XDrawLines(dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
168 w = w / 2;
169 points[0].x = w;
170 points[0].y = 0;
171 points[1].x = w;
172 points[1].y = w;
173 points[2].x = 0;
174 points[2].y = w;
175 XDrawLines(dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
176
177 /*
178 * done drawing
179 */
180 XFreeGC(dpy, gc);
181 }
182 return Scr->tbpm.resize;
183 }
184
185
186 #define questionmark_width 8
187 #define questionmark_height 8
188 static char questionmark_bits[] = {
189 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18
190 };
191
DEF_BI_PPM(CreateQuestionPixmap)192 DEF_BI_PPM(CreateQuestionPixmap)
193 {
194 *widthp = questionmark_width;
195 *heightp = questionmark_height;
196 if(Scr->tbpm.question == None) {
197 Scr->tbpm.question = XCreateBitmapFromData(dpy, Scr->Root,
198 questionmark_bits,
199 questionmark_width,
200 questionmark_height);
201 }
202 /*
203 * this must succeed or else we are in deep trouble elsewhere
204 */
205 return Scr->tbpm.question;
206 }
207 #undef questionmark_height
208 #undef questionmark_width
209
210
DEF_BI_PPM(CreateMenuPixmap)211 DEF_BI_PPM(CreateMenuPixmap)
212 {
213 return (CreateMenuIcon(Scr->TBInfo.width - Scr->TBInfo.border * 2, widthp,
214 heightp));
215 }
216
DEF_BI_PPM(CreateDotPixmap)217 DEF_BI_PPM(CreateDotPixmap)
218 {
219 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
220
221 h = h * 3 / 4;
222 if(h < 1) {
223 h = 1;
224 }
225 if(!(h & 1)) {
226 h--;
227 }
228 *widthp = *heightp = (unsigned int) h;
229 if(Scr->tbpm.delete == None) {
230 GC gc;
231 Pixmap pix;
232
233 pix = Scr->tbpm.delete = XCreatePixmap(dpy, Scr->Root, h, h, 1);
234 gc = XCreateGC(dpy, pix, 0L, NULL);
235 XSetLineAttributes(dpy, gc, h, LineSolid, CapRound, JoinRound);
236 XSetForeground(dpy, gc, 0L);
237 XFillRectangle(dpy, pix, gc, 0, 0, h, h);
238 XSetForeground(dpy, gc, 1L);
239 XDrawLine(dpy, pix, gc, h / 2, h / 2, h / 2, h / 2);
240 XFreeGC(dpy, gc);
241 }
242 return Scr->tbpm.delete;
243 }
244
245 #undef DEF_BI_PPM
246
247
248
249 /*
250 * Next, the "3D/scalable" builtins. These are the ones specified with
251 * names like ":xpm:resize". I'm not entirely clear on how these differ
252 * from ":resize"; they both vary by UseThreeDTitles and look the same.
253 * But, whatever.
254 *
255 * These yield [ctwm struct] Image's rather than [X11 type] Pixmap's.
256 */
257 #define DEF_BI_SPM(nm) Image *nm(ColorPair cp)
258 static DEF_BI_SPM(Create3DMenuImage);
259 static DEF_BI_SPM(Create3DDotImage);
260 static DEF_BI_SPM(Create3DResizeImage);
261 static DEF_BI_SPM(Create3DZoomImage);
262 static DEF_BI_SPM(Create3DBarImage);
263 static DEF_BI_SPM(Create3DVertBarImage);
264 static DEF_BI_SPM(Create3DCrossImage);
265 static DEF_BI_SPM(Create3DIconifyImage);
266 static DEF_BI_SPM(Create3DSunkenResizeImage);
267 static DEF_BI_SPM(Create3DBoxImage);
268
269
270 /*
271 * Main lookup
272 *
273 * This is where we find ":xpm:something". Note that these are _not_
274 * XPM's, and have no relation to the configurable XPM support, which we
275 * get with images specified as "xpm:something" (no leading colon).
276 * That's not confusing at all.
277 */
278 Image *
get_builtin_scalable_pixmap(const char * name,ColorPair cp)279 get_builtin_scalable_pixmap(const char *name, ColorPair cp)
280 {
281 int i;
282 static struct {
283 char *name;
284 DEF_BI_SPM((*proc));
285 } pmtab[] = {
286 /* Lookup for ":xpm:" pixmaps */
287 { TBPM_3DDOT, Create3DDotImage },
288 { TBPM_3DRESIZE, Create3DResizeImage },
289 { TBPM_3DMENU, Create3DMenuImage },
290 { TBPM_3DZOOM, Create3DZoomImage },
291 { TBPM_3DBAR, Create3DBarImage },
292 { TBPM_3DVBAR, Create3DVertBarImage },
293 { TBPM_3DCROSS, Create3DCrossImage },
294 { TBPM_3DICONIFY, Create3DIconifyImage },
295 { TBPM_3DBOX, Create3DBoxImage },
296 { TBPM_3DSUNKEN_RESIZE, Create3DSunkenResizeImage },
297 };
298
299 /* Seatbelts */
300 if(!name || (strncmp(name, ":xpm:", 5) != 0)) {
301 return NULL;
302 }
303
304 for(i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
305 if(strcasecmp(pmtab[i].name, name) == 0) {
306 Image *image = (*pmtab[i].proc)(cp);
307 if(image == NULL) {
308 fprintf(stderr, "%s: unable to build pixmap \"%s\"\n",
309 ProgramName, name);
310 return NULL;
311 }
312 return image;
313 }
314 }
315
316 fprintf(stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name);
317 return NULL;
318 }
319
320
321
322 #define LEVITTE_TEST
DEF_BI_SPM(Create3DCrossImage)323 static DEF_BI_SPM(Create3DCrossImage)
324 {
325 Image *image;
326 int h;
327 int point;
328 int midpoint;
329
330 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
331 if(!(h & 1)) {
332 h--;
333 }
334 point = 4;
335 midpoint = h / 2;
336
337 image = AllocImage();
338 if(! image) {
339 return (None);
340 }
341 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
342 if(image->pixmap == None) {
343 free(image);
344 return (None);
345 }
346
347 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
348 off, true, false);
349
350 #ifdef LEVITTE_TEST
351 FB(cp.shadc, cp.shadd);
352 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 1, point - 1, point - 1,
353 point + 1);
354 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 1, point, point,
355 point + 1);
356 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point - 1, point + 1, midpoint - 2,
357 midpoint);
358 XDrawLine(dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint + 2,
359 h - point - 3, h - point - 1);
360 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, point + 1, h - point - 3,
361 h - point - 2);
362 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point - 1, h - point - 2,
363 midpoint - 2, midpoint);
364 XDrawLine(dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint - 2,
365 h - point - 2, point - 1);
366 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, h - point - 2,
367 h - point - 2, point);
368 #endif
369
370 FB(cp.shadd, cp.shadc);
371 #ifdef LEVITTE_TEST
372 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 2, point + 1,
373 h - point - 1, h - point - 2);
374 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 2, point, midpoint,
375 midpoint - 2);
376 XDrawLine(dpy, image->pixmap, Scr->NormalGC, midpoint + 2, midpoint, h - point,
377 h - point - 2);
378 XDrawLine(dpy, image->pixmap, Scr->NormalGC, h - point, h - point - 2,
379 h - point - 2, h - point);
380 XDrawLine(dpy, image->pixmap, Scr->NormalGC, h - point - 1, h - point - 2,
381 h - point - 2, h - point - 1);
382 #else
383 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, point, h - point - 1,
384 h - point - 1);
385 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point - 1, point, h - point - 1,
386 h - point);
387 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, point - 1, h - point,
388 h - point - 1);
389 #endif
390
391 #ifdef LEVITTE_TEST
392 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, h - point - 1, point,
393 h - point - 1);
394 XDrawLine(dpy, image->pixmap, Scr->NormalGC, h - point - 1, point,
395 h - point - 1, point);
396 #else
397 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, h - point - 1,
398 h - point - 1, point);
399 #endif
400 #ifdef LEVITTE_TEST
401 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 1, h - point - 1,
402 h - point - 1, point + 1);
403 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point + 1, h - point, midpoint,
404 midpoint + 2);
405 XDrawLine(dpy, image->pixmap, Scr->NormalGC, midpoint + 2, midpoint, h - point,
406 point + 1);
407 #else
408 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point - 1, h - point - 1,
409 h - point - 1, point - 1);
410 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, h - point, h - point,
411 point);
412 #endif
413
414 image->width = h;
415 image->height = h;
416
417 return (image);
418 }
419 #undef LEVITTE_TEST
420
DEF_BI_SPM(Create3DIconifyImage)421 static DEF_BI_SPM(Create3DIconifyImage)
422 {
423 Image *image;
424 int h;
425 int point;
426
427 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
428 if(!(h & 1)) {
429 h--;
430 }
431 point = ((h / 2 - 2) * 2 + 1) / 3;
432
433 image = AllocImage();
434 if(! image) {
435 return (None);
436 }
437 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
438 if(image->pixmap == None) {
439 free(image);
440 return (None);
441 }
442
443 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
444 off, true, false);
445 FB(cp.shadd, cp.shadc);
446 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, point, h / 2, h - point);
447 XDrawLine(dpy, image->pixmap, Scr->NormalGC, point, point, h - point, point);
448
449 FB(cp.shadc, cp.shadd);
450 XDrawLine(dpy, image->pixmap, Scr->NormalGC, h - point, point, h / 2 + 1,
451 h - point);
452 XDrawLine(dpy, image->pixmap, Scr->NormalGC, h - point - 1, point + 1,
453 h / 2 + 1, h - point - 1);
454
455 image->width = h;
456 image->height = h;
457
458 return (image);
459 }
460
DEF_BI_SPM(Create3DSunkenResizeImage)461 static DEF_BI_SPM(Create3DSunkenResizeImage)
462 {
463 int h;
464 Image *image;
465
466 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
467 if(!(h & 1)) {
468 h--;
469 }
470
471 image = AllocImage();
472 if(! image) {
473 return (None);
474 }
475 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
476 if(image->pixmap == None) {
477 free(image);
478 return (None);
479 }
480
481 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
482 off, true, false);
483 Draw3DBorder(image->pixmap, 3, 3, h - 6, h - 6, 1, cp, on, true, false);
484 Draw3DBorder(image->pixmap, 3, ((h - 6) / 3) + 3, ((h - 6) * 2 / 3) + 1,
485 ((h - 6) * 2 / 3) + 1, 1, cp, on, true, false);
486 Draw3DBorder(image->pixmap, 3, ((h - 6) * 2 / 3) + 3, ((h - 6) / 3) + 1,
487 ((h - 6) / 3) + 1, 1, cp, on, true, false);
488
489 image->width = h;
490 image->height = h;
491
492 return (image);
493 }
494
DEF_BI_SPM(Create3DBoxImage)495 static DEF_BI_SPM(Create3DBoxImage)
496 {
497 int h;
498 Image *image;
499
500 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
501 if(!(h & 1)) {
502 h--;
503 }
504
505 image = AllocImage();
506 if(! image) {
507 return (None);
508 }
509 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
510 if(image->pixmap == None) {
511 free(image);
512 return (None);
513 }
514
515 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
516 off, true, false);
517 Draw3DBorder(image->pixmap, (h / 2) - 4, (h / 2) - 4, 9, 9, 1, cp,
518 off, true, false);
519
520 image->width = h;
521 image->height = h;
522
523 return (image);
524 }
525
DEF_BI_SPM(Create3DDotImage)526 static DEF_BI_SPM(Create3DDotImage)
527 {
528 Image *image;
529 int h;
530 static int idepth = 2;
531
532 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
533 if(!(h & 1)) {
534 h--;
535 }
536
537 image = AllocImage();
538 if(! image) {
539 return (None);
540 }
541 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
542 if(image->pixmap == None) {
543 free(image);
544 return (None);
545 }
546
547 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
548 off, true, false);
549 Draw3DBorder(image->pixmap, (h / 2) - idepth,
550 (h / 2) - idepth,
551 2 * idepth + 1,
552 2 * idepth + 1,
553 idepth, cp, off, true, false);
554 image->width = h;
555 image->height = h;
556 return (image);
557 }
558
DEF_BI_SPM(Create3DBarImage)559 static DEF_BI_SPM(Create3DBarImage)
560 {
561 Image *image;
562 int h;
563 static int idepth = 2;
564
565 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
566 if(!(h & 1)) {
567 h--;
568 }
569
570 image = AllocImage();
571 if(! image) {
572 return (None);
573 }
574 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
575 if(image->pixmap == None) {
576 free(image);
577 return (None);
578 }
579
580 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
581 off, true, false);
582 Draw3DBorder(image->pixmap,
583 Scr->TitleButtonShadowDepth + 2,
584 (h / 2) - idepth,
585 h - 2 * (Scr->TitleButtonShadowDepth + 2),
586 2 * idepth + 1,
587 idepth, cp, off, true, false);
588 image->width = h;
589 image->height = h;
590 return (image);
591 }
592
DEF_BI_SPM(Create3DVertBarImage)593 static DEF_BI_SPM(Create3DVertBarImage)
594 {
595 Image *image;
596 int h;
597 static int idepth = 2;
598
599 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
600 if(!(h & 1)) {
601 h--;
602 }
603
604 image = AllocImage();
605 if(! image) {
606 return (None);
607 }
608 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
609 if(image->pixmap == None) {
610 free(image);
611 return (None);
612 }
613
614 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
615 off, true, false);
616 Draw3DBorder(image->pixmap,
617 (h / 2) - idepth,
618 Scr->TitleButtonShadowDepth + 2,
619 2 * idepth + 1,
620 h - 2 * (Scr->TitleButtonShadowDepth + 2),
621 idepth, cp, off, true, false);
622 image->width = h;
623 image->height = h;
624 return (image);
625 }
626
DEF_BI_SPM(Create3DMenuImage)627 static DEF_BI_SPM(Create3DMenuImage)
628 {
629 Image *image;
630 int h, i;
631
632 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
633 if(!(h & 1)) {
634 h--;
635 }
636
637 image = AllocImage();
638 if(! image) {
639 return (None);
640 }
641 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
642 if(image->pixmap == None) {
643 free(image);
644 return (None);
645 }
646
647 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
648 off, true, false);
649 for(i = 4; i < h - 7; i += 5) {
650 Draw3DBorder(image->pixmap, 4, i, h - 8, 4, 2, cp, off, true, false);
651 }
652 image->width = h;
653 image->height = h;
654 return (image);
655 }
656
DEF_BI_SPM(Create3DResizeImage)657 static DEF_BI_SPM(Create3DResizeImage)
658 {
659 Image *image;
660 int h;
661
662 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
663 if(!(h & 1)) {
664 h--;
665 }
666
667 image = AllocImage();
668 if(! image) {
669 return (None);
670 }
671 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
672 if(image->pixmap == None) {
673 free(image);
674 return (None);
675 }
676
677 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
678 off, true, false);
679 Draw3DBorder(image->pixmap, 0, h / 4, ((3 * h) / 4) + 1, ((3 * h) / 4) + 1,
680 2, cp, off, true, false);
681 Draw3DBorder(image->pixmap, 0, h / 2, (h / 2) + 1, (h / 2) + 1, 2, cp, off,
682 true, false);
683 image->width = h;
684 image->height = h;
685 return (image);
686 }
687
DEF_BI_SPM(Create3DZoomImage)688 static DEF_BI_SPM(Create3DZoomImage)
689 {
690 Image *image;
691 int h;
692 static int idepth = 2;
693
694 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
695 if(!(h & 1)) {
696 h--;
697 }
698
699 image = AllocImage();
700 if(! image) {
701 return (None);
702 }
703 image->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
704 if(image->pixmap == None) {
705 free(image);
706 return (None);
707 }
708
709 Draw3DBorder(image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
710 off, true, false);
711 Draw3DBorder(image->pixmap, Scr->TitleButtonShadowDepth + 2,
712 Scr->TitleButtonShadowDepth + 2,
713 h - 2 * (Scr->TitleButtonShadowDepth + 2),
714 h - 2 * (Scr->TitleButtonShadowDepth + 2),
715 idepth, cp, off, true, false);
716
717 image->width = h;
718 image->height = h;
719 return (image);
720 }
721
722 #undef DEF_BI_SPM
723
724
725
726 /*
727 * And the animated builtins. These are the ones specified with names
728 * like "%xpm:resize".
729 *
730 * These yield [ctwm struct] Image's.
731 */
732 #define DEF_BI_ASPM(nm) Image *nm(ColorPair cp)
733
734 /* Backend generators */
735 static Image *Create3DResizeAnimation(bool in, bool left, bool top,
736 ColorPair cp);
737 static Image *Create3DMenuAnimation(bool up, ColorPair cp);
738 static Image *Create3DZoomAnimation(bool in, bool out, int n, ColorPair cp);
739
740 /* Frontends */
741 /* Using: ResizeAnimation */
742 static DEF_BI_ASPM(Create3DResizeInTopAnimation);
743 static DEF_BI_ASPM(Create3DResizeOutTopAnimation);
744 static DEF_BI_ASPM(Create3DResizeInBotAnimation);
745 static DEF_BI_ASPM(Create3DResizeOutBotAnimation);
746 /* Using: MenuAnimation */
747 static DEF_BI_ASPM(Create3DMenuUpAnimation);
748 static DEF_BI_ASPM(Create3DMenuDownAnimation);
749 /* Using: ZoomAnimation */
750 static DEF_BI_ASPM(Create3DMazeOutAnimation);
751 static DEF_BI_ASPM(Create3DMazeInAnimation);
752 static DEF_BI_ASPM(Create3DZoomInAnimation);
753 static DEF_BI_ASPM(Create3DZoomOutAnimation);
754 static DEF_BI_ASPM(Create3DZoomInOutAnimation);
755
756
757 /*
758 * Entry for animated pixmaps
759 *
760 * This is where we find "%xpm:something". Note that as above, these are
761 * _not_ XPM's, and have no relation to the configurable XPM support,
762 * which we get with images specified as "xpm:something" (no leading
763 * colon). Still not confusing at _all_.
764 */
765 Image *
get_builtin_animated_pixmap(const char * name,ColorPair cp)766 get_builtin_animated_pixmap(const char *name, ColorPair cp)
767 {
768 int i;
769 static struct {
770 char *name;
771 DEF_BI_ASPM((*proc));
772 } pmtab[] = {
773 /* Lookup for "%xpm:" pixmaps */
774 { "%xpm:resize-out-top", Create3DResizeInTopAnimation },
775 { "%xpm:resize-in-top", Create3DResizeOutTopAnimation },
776 { "%xpm:resize-out-bot", Create3DResizeInBotAnimation },
777 { "%xpm:resize-in-bot", Create3DResizeOutBotAnimation },
778 { "%xpm:menu-up", Create3DMenuUpAnimation },
779 { "%xpm:menu-down", Create3DMenuDownAnimation },
780 { "%xpm:maze-out", Create3DMazeOutAnimation },
781 { "%xpm:maze-in", Create3DMazeInAnimation },
782 { "%xpm:resize", Create3DZoomOutAnimation }, // compat
783 { "%xpm:zoom-out", Create3DZoomOutAnimation },
784 { "%xpm:zoom-in", Create3DZoomInAnimation },
785 { "%xpm:zoom-inout", Create3DZoomInOutAnimation },
786 };
787
788 /* Seatbelts */
789 if(!name || (strncmp(name, "%xpm:", 5) != 0)) {
790 return NULL;
791 }
792
793 for(i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) {
794 if(strcasecmp(pmtab[i].name, name) == 0) {
795 Image *image = (*pmtab[i].proc)(cp);
796 if(image == NULL) {
797 fprintf(stderr, "%s: unable to build pixmap \"%s\"\n",
798 ProgramName, name);
799 return NULL;
800 }
801 return image;
802 }
803 }
804
805 fprintf(stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name);
806 return (None);
807 }
808
809
810 /*
811 * First a couple generator functions the actual functions use
812 */
813 static Image *
Create3DResizeAnimation(bool in,bool left,bool top,ColorPair cp)814 Create3DResizeAnimation(bool in, bool left, bool top,
815 ColorPair cp)
816 {
817 int h, i, j;
818 Image *image, *im, *im1;
819
820 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
821 if(!(h & 1)) {
822 h--;
823 }
824
825 image = im1 = NULL;
826 for(i = (in ? 0 : (h / 4) - 1); (i < h / 4) && (i >= 0); i += (in ? 1 : -1)) {
827 im = AllocImage();
828 if(! im) {
829 return NULL;
830 }
831 im->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
832 if(im->pixmap == None) {
833 free(im);
834 return NULL;
835 }
836 Draw3DBorder(im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
837 off, true, false);
838 for(j = i; j <= h; j += (h / 4)) {
839 Draw3DBorder(im->pixmap, (left ? 0 : j), (top ? 0 : j),
840 h - j, h - j, 2, cp, off, true, false);
841 }
842 im->mask = None;
843 im->width = h;
844 im->height = h;
845 im->next = NULL;
846 if(image == NULL) {
847 image = im1 = im;
848 }
849 else {
850 im1->next = im;
851 im1 = im;
852 }
853 }
854 if(im1 != None) {
855 im1->next = image;
856 }
857 return image;
858 }
859
860 static Image *
Create3DMenuAnimation(bool up,ColorPair cp)861 Create3DMenuAnimation(bool up, ColorPair cp)
862 {
863 int h, i, j;
864 Image *image, *im, *im1;
865
866 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
867 if(!(h & 1)) {
868 h--;
869 }
870
871 image = im1 = NULL;
872 for(j = (up ? 4 : 0); j != (up ? -1 : 5); j += (up ? -1 : 1)) {
873 im = AllocImage();
874 if(! im) {
875 return NULL;
876 }
877 im->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
878 if(im->pixmap == None) {
879 free(im);
880 return NULL;
881 }
882 Draw3DBorder(im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp,
883 off, true, false);
884 for(i = j; i < h - 3; i += 5) {
885 Draw3DBorder(im->pixmap, 4, i, h - 8, 4, 2, cp, off, true, false);
886 }
887 im->mask = None;
888 im->width = h;
889 im->height = h;
890 im->next = NULL;
891 if(image == NULL) {
892 image = im1 = im;
893 }
894 else {
895 im1->next = im;
896 im1 = im;
897 }
898 }
899 if(im1 != None) {
900 im1->next = image;
901 }
902 return image;
903 }
904
905 static Image *
Create3DZoomAnimation(bool in,bool out,int n,ColorPair cp)906 Create3DZoomAnimation(bool in, bool out, int n, ColorPair cp)
907 {
908 int h, i, j, k;
909 Image *image, *im, *im1;
910
911 h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
912 if(!(h & 1)) {
913 h--;
914 }
915
916 if(n == 0) {
917 n = (h / 2) - 2;
918 }
919
920 image = im1 = NULL;
921 for(j = (out ? -1 : 1) ; j < (in ? 2 : 0); j += 2) {
922 for(k = (j > 0 ? 0 : n - 1) ; (k >= 0) && (k < n); k += j) {
923 im = AllocImage();
924 im->pixmap = XCreatePixmap(dpy, Scr->Root, h, h, Scr->d_depth);
925 Draw3DBorder(im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth,
926 cp, off, true, false);
927 for(i = 2 + k; i < (h / 2); i += n) {
928 Draw3DBorder(im->pixmap, i, i, h - (2 * i), h - (2 * i), 2, cp,
929 off, true, false);
930 }
931 im->mask = None;
932 im->width = h;
933 im->height = h;
934 im->next = NULL;
935 if(image == NULL) {
936 image = im1 = im;
937 }
938 else {
939 im1->next = im;
940 im1 = im;
941 }
942 }
943 }
944 if(im1 != None) {
945 im1->next = image;
946 }
947 return image;
948 }
949
950
951 /*
952 * And the wrapper funcs for making the images
953 */
DEF_BI_ASPM(Create3DResizeInTopAnimation)954 static DEF_BI_ASPM(Create3DResizeInTopAnimation)
955 {
956 return Create3DResizeAnimation(true, false, true, cp);
957 }
958
DEF_BI_ASPM(Create3DResizeOutTopAnimation)959 static DEF_BI_ASPM(Create3DResizeOutTopAnimation)
960 {
961 return Create3DResizeAnimation(false, false, true, cp);
962 }
963
DEF_BI_ASPM(Create3DResizeInBotAnimation)964 static DEF_BI_ASPM(Create3DResizeInBotAnimation)
965 {
966 return Create3DResizeAnimation(true, true, false, cp);
967 }
968
DEF_BI_ASPM(Create3DResizeOutBotAnimation)969 static DEF_BI_ASPM(Create3DResizeOutBotAnimation)
970 {
971 return Create3DResizeAnimation(false, true, false, cp);
972 }
973
974
DEF_BI_ASPM(Create3DMenuUpAnimation)975 static DEF_BI_ASPM(Create3DMenuUpAnimation)
976 {
977 return Create3DMenuAnimation(true, cp);
978 }
979
DEF_BI_ASPM(Create3DMenuDownAnimation)980 static DEF_BI_ASPM(Create3DMenuDownAnimation)
981 {
982 return Create3DMenuAnimation(false, cp);
983 }
984
985
DEF_BI_ASPM(Create3DMazeInAnimation)986 static DEF_BI_ASPM(Create3DMazeInAnimation)
987 {
988 return Create3DZoomAnimation(true, false, 6, cp);
989 }
990
DEF_BI_ASPM(Create3DMazeOutAnimation)991 static DEF_BI_ASPM(Create3DMazeOutAnimation)
992 {
993 return Create3DZoomAnimation(false, true, 6, cp);
994 }
995
DEF_BI_ASPM(Create3DZoomInAnimation)996 static DEF_BI_ASPM(Create3DZoomInAnimation)
997 {
998 return Create3DZoomAnimation(true, false, 0, cp);
999 }
1000
DEF_BI_ASPM(Create3DZoomOutAnimation)1001 static DEF_BI_ASPM(Create3DZoomOutAnimation)
1002 {
1003 return Create3DZoomAnimation(false, true, 0, cp);
1004 }
1005
DEF_BI_ASPM(Create3DZoomInOutAnimation)1006 static DEF_BI_ASPM(Create3DZoomInOutAnimation)
1007 {
1008 return Create3DZoomAnimation(true, true, 0, cp);
1009 }
1010
1011 #undef DEF_BI_ASPM
1012
1013
1014 /*
1015 * Lastly, some gray/black pixmaps that are used in window border and
1016 * hilite bars.
1017 */
1018 #define BG_WIDTH 2
1019 #define BG_HEIGHT 2
1020
1021 Pixmap
mk_blackgray_pixmap(const char * which,Drawable dw,unsigned long fg,unsigned long bg)1022 mk_blackgray_pixmap(const char *which, Drawable dw,
1023 unsigned long fg, unsigned long bg)
1024 {
1025 unsigned char gray_bits[] = { 0x02, 0x01 };
1026 unsigned char black_bits[] = { 0xFF, 0xFF };
1027 char *bits;
1028
1029 /* Which are we asking for? */
1030 if(strcmp(which, "black") == 0) {
1031 bits = (char *)black_bits;
1032 }
1033 else if(strcmp(which, "gray") == 0) {
1034 bits = (char *)gray_bits;
1035 }
1036 else {
1037 fprintf(stderr, "%s(): Invalid which arg '%s'\n", __func__, which);
1038 return None;
1039 }
1040
1041 /* Make it */
1042 return XCreatePixmapFromBitmapData(dpy, dw,
1043 bits, BG_WIDTH, BG_HEIGHT,
1044 fg, bg, Scr->d_depth);
1045 }
1046
1047 void
get_blackgray_size(int * width,int * height)1048 get_blackgray_size(int *width, int *height)
1049 {
1050 if(width) {
1051 *width = BG_WIDTH;
1052 }
1053 if(height) {
1054 *height = BG_HEIGHT;
1055 }
1056 }
1057
1058 #undef BG_HEIGHT
1059 #undef BG_WIDTH
1060