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) 27static DEF_BI_PPM(CreateXLogoPixmap); 28static DEF_BI_PPM(CreateResizePixmap); 29static DEF_BI_PPM(CreateQuestionPixmap); 30static DEF_BI_PPM(CreateMenuPixmap); 31static 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 */ 42Pixmap 43get_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 */ 93DEF_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 129DEF_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 188static char questionmark_bits[] = { 189 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18 190}; 191 192DEF_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 211DEF_BI_PPM(CreateMenuPixmap) 212{ 213 return (CreateMenuIcon(Scr->TBInfo.width - Scr->TBInfo.border * 2, widthp, 214 heightp)); 215} 216 217DEF_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) 258static DEF_BI_SPM(Create3DMenuImage); 259static DEF_BI_SPM(Create3DDotImage); 260static DEF_BI_SPM(Create3DResizeImage); 261static DEF_BI_SPM(Create3DZoomImage); 262static DEF_BI_SPM(Create3DBarImage); 263static DEF_BI_SPM(Create3DVertBarImage); 264static DEF_BI_SPM(Create3DCrossImage); 265static DEF_BI_SPM(Create3DIconifyImage); 266static DEF_BI_SPM(Create3DSunkenResizeImage); 267static 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 */ 278Image * 279get_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 323static 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 421static 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 461static 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 495static 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 526static 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 559static 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 593static 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 627static 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 657static 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 688static 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 */ 735static Image *Create3DResizeAnimation(bool in, bool left, bool top, 736 ColorPair cp); 737static Image *Create3DMenuAnimation(bool up, ColorPair cp); 738static Image *Create3DZoomAnimation(bool in, bool out, int n, ColorPair cp); 739 740/* Frontends */ 741/* Using: ResizeAnimation */ 742static DEF_BI_ASPM(Create3DResizeInTopAnimation); 743static DEF_BI_ASPM(Create3DResizeOutTopAnimation); 744static DEF_BI_ASPM(Create3DResizeInBotAnimation); 745static DEF_BI_ASPM(Create3DResizeOutBotAnimation); 746/* Using: MenuAnimation */ 747static DEF_BI_ASPM(Create3DMenuUpAnimation); 748static DEF_BI_ASPM(Create3DMenuDownAnimation); 749/* Using: ZoomAnimation */ 750static DEF_BI_ASPM(Create3DMazeOutAnimation); 751static DEF_BI_ASPM(Create3DMazeInAnimation); 752static DEF_BI_ASPM(Create3DZoomInAnimation); 753static DEF_BI_ASPM(Create3DZoomOutAnimation); 754static 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 */ 765Image * 766get_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 */ 813static Image * 814Create3DResizeAnimation(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 860static Image * 861Create3DMenuAnimation(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 905static Image * 906Create3DZoomAnimation(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 */ 954static DEF_BI_ASPM(Create3DResizeInTopAnimation) 955{ 956 return Create3DResizeAnimation(true, false, true, cp); 957} 958 959static DEF_BI_ASPM(Create3DResizeOutTopAnimation) 960{ 961 return Create3DResizeAnimation(false, false, true, cp); 962} 963 964static DEF_BI_ASPM(Create3DResizeInBotAnimation) 965{ 966 return Create3DResizeAnimation(true, true, false, cp); 967} 968 969static DEF_BI_ASPM(Create3DResizeOutBotAnimation) 970{ 971 return Create3DResizeAnimation(false, true, false, cp); 972} 973 974 975static DEF_BI_ASPM(Create3DMenuUpAnimation) 976{ 977 return Create3DMenuAnimation(true, cp); 978} 979 980static DEF_BI_ASPM(Create3DMenuDownAnimation) 981{ 982 return Create3DMenuAnimation(false, cp); 983} 984 985 986static DEF_BI_ASPM(Create3DMazeInAnimation) 987{ 988 return Create3DZoomAnimation(true, false, 6, cp); 989} 990 991static DEF_BI_ASPM(Create3DMazeOutAnimation) 992{ 993 return Create3DZoomAnimation(false, true, 6, cp); 994} 995 996static DEF_BI_ASPM(Create3DZoomInAnimation) 997{ 998 return Create3DZoomAnimation(true, false, 0, cp); 999} 1000 1001static DEF_BI_ASPM(Create3DZoomOutAnimation) 1002{ 1003 return Create3DZoomAnimation(false, true, 0, cp); 1004} 1005 1006static 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 1021Pixmap 1022mk_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 1047void 1048get_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