util.c revision 8ae3b938
1/*****************************************************************************/ 2/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ 3/** Salt Lake City, Utah **/ 4/** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ 5/** Cambridge, Massachusetts **/ 6/** **/ 7/** All Rights Reserved **/ 8/** **/ 9/** Permission to use, copy, modify, and distribute this software and **/ 10/** its documentation for any purpose and without fee is hereby **/ 11/** granted, provided that the above copyright notice appear in all **/ 12/** copies and that both that copyright notice and this permis- **/ 13/** sion notice appear in supporting documentation, and that the **/ 14/** names of Evans & Sutherland and M.I.T. not be used in advertising **/ 15/** in publicity pertaining to distribution of the software without **/ 16/** specific, written prior permission. **/ 17/** **/ 18/** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ 19/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ 20/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ 21/** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ 22/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ 23/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ 24/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ 25/** OR PERFORMANCE OF THIS SOFTWARE. **/ 26/*****************************************************************************/ 27/* 28 * [ ctwm ] 29 * 30 * Copyright 1992 Claude Lecommandeur. 31 * 32 * Permission to use, copy, modify and distribute this software [ctwm] and 33 * its documentation for any purpose is hereby granted without fee, provided 34 * that the above copyright notice appear in all copies and that both that 35 * copyright notice and this permission notice appear in supporting documen- 36 * tation, and that the name of Claude Lecommandeur not be used in adverti- 37 * sing or publicity pertaining to distribution of the software without 38 * specific, written prior permission. Claude Lecommandeur make no represen- 39 * tations about the suitability of this software for any purpose. It is 40 * provided "as is" without express or implied warranty. 41 * 42 * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO 44 * EVENT SHALL Claude Lecommandeur BE LIABLE FOR ANY SPECIAL, INDIRECT OR 45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 46 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 47 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 48 * PERFORMANCE OF THIS SOFTWARE. 49 * 50 * Author: Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ] 51 */ 52 53 54/*********************************************************************** 55 * 56 * $XConsortium: util.c,v 1.47 91/07/14 13:40:37 rws Exp $ 57 * 58 * utility routines for twm 59 * 60 * 28-Oct-87 Thomas E. LaStrange File created 61 * 62 * Do the necessary modification to be integrated in ctwm. 63 * Can no longer be used for the standard twm. 64 * 65 * 22-April-92 Claude Lecommandeur. 66 * 67 * Changed behavior of DontMoveOff/MoveOffResistance to allow 68 * moving a window off screen less than #MoveOffResistance pixels. 69 * New code will no longer "snap" windows to #MoveOffResistance 70 * pixels off screen and instead movements will just be stopped and 71 * then resume once movement of #MoveOffResistance have been attempted. 72 * 73 * 15-December-02 Bjorn Knutsson 74 * 75 ***********************************************************************/ 76 77#define LEVITTE_TEST 78 79#include "twm.h" 80#include "util.h" 81#include "events.h" 82#include "add_window.h" 83#include "gram.tab.h" 84#include "screen.h" 85#include "icons.h" 86#include "cursor.h" 87#include <stdio.h> 88 89/* 90 * Need this for the fixed-size uint_*'s used below. stdint.h would be 91 * the more appropriate include, but there exist systems that don't have 92 * it, but do have inttypes.h (FreeBSD 4, Solaris 7-9 I've heard of, 93 * probably more). 94 */ 95#include <inttypes.h> 96 97#ifdef VMS 98#include <decw$include/Xos.h> 99#include <decw$include/Xatom.h> 100#include <decw$include/Xutil.h> 101#include <X11Xmu/Drawing.h> 102#include <X11Xmu/CharSet.h> 103#include <X11Xmu/WinUtil.h> 104#ifdef HAVE_XWDFILE_H 105#include "XWDFile.h" /* We do some tricks, since the original 106 has bugs... /Richard Levitte */ 107#endif /* HAVE_XWDFILE_H */ 108#include <unixlib.h> 109#include <starlet.h> 110#include <ssdef.h> 111#include <psldef.h> 112#include <lib$routines.h> 113#ifdef __DECC 114#include <unistd.h> 115#endif /* __DECC */ 116#define USE_SIGNALS 117#ifndef F_OK 118# define F_OK 0 119#endif 120#ifndef X_OK 121# define X_OK 1 122#endif 123#ifndef W_OK 124# define W_OK 2 125#endif 126#ifndef R_OK 127# define R_OK 4 128#endif 129#else /* !VMS */ 130#include <X11/Xos.h> 131#include <X11/Xatom.h> 132#include <X11/Xmu/Drawing.h> 133#include <X11/Xmu/CharSet.h> 134#include <X11/Xmu/WinUtil.h> 135#include <X11/XWDFile.h> 136#endif /* VMS */ 137 138#if defined(USE_SIGNALS) && defined(__sgi) 139# define _BSD_SIGNALS 140#endif 141 142#include <signal.h> 143#ifndef VMS 144#include <sys/time.h> 145#endif 146 147#if defined (XPM) 148#ifdef VMS 149#include "xpm.h" 150#else 151# include <X11/xpm.h> 152#endif 153#endif 154 155#ifdef JPEG 156# include <setjmp.h> 157# include <jpeglib.h> 158# include <jerror.h> 159 static Image *LoadJpegImage (char *name); 160 static Image *GetJpegImage (char *name); 161 162 struct jpeg_error { 163 struct jpeg_error_mgr pub; 164 sigjmp_buf setjmp_buffer; 165 }; 166 167 typedef struct jpeg_error *jerr_ptr; 168#endif /* JPEG */ 169 170#ifdef IMCONV 171# include "im.h" 172# include "sdsc.h" 173#endif 174 175#define MAXANIMATIONSPEED 20 176 177extern Atom _XA_WM_WORKSPACESLIST; 178 179static Image *LoadBitmapImage (char *name, ColorPair cp); 180static Image *GetBitmapImage (char *name, ColorPair cp); 181#if !defined(VMS) || defined(HAVE_XWDFILE_H) 182static Image *LoadXwdImage (char *filename, ColorPair cp); 183static Image *GetXwdImage (char *name, ColorPair cp); 184#endif 185#ifdef XPM 186static Image *LoadXpmImage (char *name, ColorPair cp); 187static Image *GetXpmImage (char *name, ColorPair cp); 188static void xpmErrorMessage (int status, char *name, char *fullname); 189#endif 190#ifdef IMCONV 191static Image *GetImconvImage (char *filename, 192 unsigned int *widthp, unsigned int *heightp); 193#endif 194static Pixmap CreateXLogoPixmap(unsigned int *widthp, unsigned int *heightp); 195static Pixmap CreateResizePixmap(unsigned int *widthp, unsigned int *heightp); 196static Pixmap CreateQuestionPixmap(unsigned int *widthp, unsigned int *heightp); 197static Pixmap CreateMenuPixmap(unsigned int *widthp, unsigned int *heightp); 198static Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp); 199static Image *Create3DMenuImage (ColorPair cp); 200static Image *Create3DDotImage (ColorPair cp); 201static Image *Create3DResizeImage (ColorPair cp); 202static Image *Create3DZoomImage (ColorPair cp); 203static Image *Create3DBarImage (ColorPair cp); 204static Image *Create3DVertBarImage (ColorPair cp); 205static Image *Create3DResizeAnimation (Bool in, Bool left, Bool top, 206 ColorPair cp); 207static Image *Create3DCrossImage (ColorPair cp); 208static Image *Create3DIconifyImage (ColorPair cp); 209static Image *Create3DSunkenResizeImage (ColorPair cp); 210static Image *Create3DBoxImage (ColorPair cp); 211 212extern FILE *tracefile; 213 214void FreeImage (Image *image); 215 216void _swapshort (register char *bp, register unsigned n); 217void _swaplong (register char *bp, register unsigned n); 218 219static int reportfilenotfound = 1; 220static Colormap AlternateCmap = None; 221 222int HotX, HotY; 223 224int AnimationSpeed = 0; 225Bool AnimationActive = False; 226Bool MaybeAnimate = True; 227#ifdef USE_SIGNALS 228 Bool AnimationPending = False; 229#else 230 struct timeval AnimateTimeout; 231#endif /* USE_SIGNALS */ 232 233/*********************************************************************** 234 * 235 * Procedure: 236 * MoveOutline - move a window outline 237 * 238 * Inputs: 239 * root - the window we are outlining 240 * x - upper left x coordinate 241 * y - upper left y coordinate 242 * width - the width of the rectangle 243 * height - the height of the rectangle 244 * bw - the border width of the frame 245 * th - title height 246 * 247 *********************************************************************** 248 */ 249 250/* ARGSUSED */ 251void MoveOutline(Window root, 252 int x, int y, int width, int height, int bw, int th) 253{ 254 static int lastx = 0; 255 static int lasty = 0; 256 static int lastWidth = 0; 257 static int lastHeight = 0; 258 static int lastBW = 0; 259 static int lastTH = 0; 260 int xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb; 261 int xthird, ythird; 262 XSegment outline[18]; 263 register XSegment *r; 264 265 if (x == lastx && y == lasty && width == lastWidth && height == lastHeight 266 && lastBW == bw && th == lastTH) 267 return; 268 269 r = outline; 270 271#define DRAWIT() \ 272 if (lastWidth || lastHeight) \ 273 { \ 274 xl = lastx; \ 275 xr = lastx + lastWidth - 1; \ 276 yt = lasty; \ 277 yb = lasty + lastHeight - 1; \ 278 xinnerl = xl + lastBW; \ 279 xinnerr = xr - lastBW; \ 280 yinnert = yt + lastTH + lastBW; \ 281 yinnerb = yb - lastBW; \ 282 xthird = (xinnerr - xinnerl) / 3; \ 283 ythird = (yinnerb - yinnert) / 3; \ 284 \ 285 r->x1 = xl; \ 286 r->y1 = yt; \ 287 r->x2 = xr; \ 288 r->y2 = yt; \ 289 r++; \ 290 \ 291 r->x1 = xl; \ 292 r->y1 = yb; \ 293 r->x2 = xr; \ 294 r->y2 = yb; \ 295 r++; \ 296 \ 297 r->x1 = xl; \ 298 r->y1 = yt; \ 299 r->x2 = xl; \ 300 r->y2 = yb; \ 301 r++; \ 302 \ 303 r->x1 = xr; \ 304 r->y1 = yt; \ 305 r->x2 = xr; \ 306 r->y2 = yb; \ 307 r++; \ 308 \ 309 r->x1 = xinnerl + xthird; \ 310 r->y1 = yinnert; \ 311 r->x2 = r->x1; \ 312 r->y2 = yinnerb; \ 313 r++; \ 314 \ 315 r->x1 = xinnerl + (2 * xthird); \ 316 r->y1 = yinnert; \ 317 r->x2 = r->x1; \ 318 r->y2 = yinnerb; \ 319 r++; \ 320 \ 321 r->x1 = xinnerl; \ 322 r->y1 = yinnert + ythird; \ 323 r->x2 = xinnerr; \ 324 r->y2 = r->y1; \ 325 r++; \ 326 \ 327 r->x1 = xinnerl; \ 328 r->y1 = yinnert + (2 * ythird); \ 329 r->x2 = xinnerr; \ 330 r->y2 = r->y1; \ 331 r++; \ 332 \ 333 if (lastTH != 0) { \ 334 r->x1 = xl; \ 335 r->y1 = yt + lastTH; \ 336 r->x2 = xr; \ 337 r->y2 = r->y1; \ 338 r++; \ 339 } \ 340 } 341 342 /* undraw the old one, if any */ 343 DRAWIT (); 344 345 lastx = x; 346 lasty = y; 347 lastWidth = width; 348 lastHeight = height; 349 lastBW = bw; 350 lastTH = th; 351 352 /* draw the new one, if any */ 353 DRAWIT (); 354 355#undef DRAWIT 356 357 358 if (r != outline) 359 { 360 XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline); 361 } 362} 363 364/*********************************************************************** 365 * 366 * Procedure: 367 * Zoom - zoom in or out of an icon 368 * 369 * Inputs: 370 * wf - window to zoom from 371 * wt - window to zoom to 372 * 373 *********************************************************************** 374 */ 375 376void Zoom(Window wf, Window wt) 377{ 378 int fx, fy, tx, ty; /* from, to */ 379 unsigned int fw, fh, tw, th; /* from, to */ 380 long dx, dy, dw, dh; 381 long z; 382 int j; 383 384 if ((Scr->IconifyStyle != ICONIFY_NORMAL) || !Scr->DoZoom || Scr->ZoomCount < 1) return; 385 386 if (wf == None || wt == None) return; 387 388 XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth); 389 XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth); 390 391 dx = (long) tx - (long) fx; /* going from -> to */ 392 dy = (long) ty - (long) fy; /* going from -> to */ 393 dw = (long) tw - (long) fw; /* going from -> to */ 394 dh = (long) th - (long) fh; /* going from -> to */ 395 z = (long) (Scr->ZoomCount + 1); 396 397 for (j = 0; j < 2; j++) { 398 long i; 399 400 XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh); 401 for (i = 1; i < z; i++) { 402 int x = fx + (int) ((dx * i) / z); 403 int y = fy + (int) ((dy * i) / z); 404 unsigned width = (unsigned) (((long) fw) + (dw * i) / z); 405 unsigned height = (unsigned) (((long) fh) + (dh * i) / z); 406 407 XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, 408 x, y, width, height); 409 } 410 XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th); 411 } 412} 413 414 415char *ExpandFilePath (char *path) 416{ 417 char *ret, *colon, *p; 418 int len; 419 420 len = 0; 421 p = path; 422 while ((colon = strchr (p, ':'))) { 423 len += colon - p + 1; 424 if (*p == '~') len += HomeLen - 1; 425 p = colon + 1; 426 } 427 if (*p == '~') len += HomeLen - 1; 428 len += strlen (p); 429 ret = (char*) malloc (len + 1); 430 *ret = 0; 431 432 p = path; 433 while ((colon = strchr (p, ':'))) { 434 *colon = '\0'; 435 if (*p == '~') { 436 strcat (ret, Home); 437 strcat (ret, p + 1); 438 } else { 439 strcat (ret, p); 440 } 441 *colon = ':'; 442 strcat (ret, ":"); 443 p = colon + 1; 444 } 445 if (*p == '~') { 446 strcat (ret, Home); 447 strcat (ret, p + 1); 448 } else { 449 strcat (ret, p); 450 } 451 return ret; 452} 453 454/*********************************************************************** 455 * 456 * Procedure: 457 * ExpandFilename - expand the tilde character to HOME 458 * if it is the first character of the filename 459 * 460 * Returned Value: 461 * a pointer to the new name 462 * 463 * Inputs: 464 * name - the filename to expand 465 * 466 *********************************************************************** 467 */ 468 469char *ExpandFilename(char *name) 470{ 471 char *newname; 472 473 if (name[0] != '~') return name; 474 475#ifdef VMS 476 newname = (char *) malloc (HomeLen + strlen(name) + 1); 477 if (!newname) { 478 fprintf (stderr, 479 "%s: unable to allocate %d bytes to expand filename %s%s\n", 480 ProgramName, HomeLen + strlen(name) + 1, Home, &name[1]); 481 } else { 482 (void) sprintf (newname, "%s%s", Home, &name[1]); 483 } 484#else 485 newname = (char *) malloc (HomeLen + strlen(name) + 2); 486 if (!newname) { 487 fprintf (stderr, 488 "%s: unable to allocate %lu bytes to expand filename %s/%s\n", 489 ProgramName, (unsigned long) HomeLen + strlen(name) + 2, 490 Home, &name[1]); 491 } else { 492 (void) sprintf (newname, "%s/%s", Home, &name[1]); 493 } 494#endif 495 496 return newname; 497} 498 499char *ExpandPixmapPath (char *name) 500{ 501 char *ret, *colon; 502 503 ret = NULL; 504#ifdef VMS 505 if (name[0] == '~') { 506 ret = (char *) malloc (HomeLen + strlen (name) + 1); 507 sprintf (ret, "%s%s", Home, &name[1]); 508 } 509 if (name[0] == '/') { 510 ret = (char *) malloc (strlen (name)); 511 sprintf (ret, "%s", &name[1]); 512 } 513 else 514 if (Scr->PixmapDirectory) { 515 char *p = Scr->PixmapDirectory; 516 while (colon = strchr (p, ':')) { 517 *colon = '\0'; 518 ret = (char *) malloc (strlen (p) + strlen (name) + 1); 519 sprintf (ret, "%s%s", p, name); 520 *colon = ':'; 521 if (!access (ret, R_OK)) return (ret); 522 p = colon + 1; 523 } 524 ret = (char *) malloc (strlen (Scr->PixmapDirectory) + strlen (name) + 1); 525 sprintf (ret, "%s%s", Scr->PixmapDirectory, name); 526 } 527#else 528 if (name[0] == '~') { 529 ret = (char *) malloc (HomeLen + strlen (name) + 2); 530 sprintf (ret, "%s/%s", Home, &name[1]); 531 } 532 else 533 if (name[0] == '/') { 534 ret = (char *) malloc (strlen (name) + 1); 535 strcpy (ret, name); 536 } 537 else 538 if (Scr->PixmapDirectory) { 539 char *p = Scr->PixmapDirectory; 540 while ((colon = strchr (p, ':'))) { 541 *colon = '\0'; 542 ret = (char *) malloc (strlen (p) + strlen (name) + 2); 543 sprintf (ret, "%s/%s", p, name); 544 *colon = ':'; 545 if (!access (ret, R_OK)) return (ret); 546 p = colon + 1; 547 } 548 ret = (char *) malloc (strlen (p) + strlen (name) + 2); 549 sprintf (ret, "%s/%s", p, name); 550 } 551#endif 552 return (ret); 553} 554 555/*********************************************************************** 556 * 557 * Procedure: 558 * GetUnknownIcon - read in the bitmap file for the unknown icon 559 * 560 * Inputs: 561 * name - the filename to read 562 * 563 *********************************************************************** 564 */ 565 566void GetUnknownIcon(char *name) 567{ 568 Scr->UnknownImage = GetImage (name, Scr->IconC); 569} 570 571/*********************************************************************** 572 * 573 * Procedure: 574 * FindBitmap - read in a bitmap file and return size 575 * 576 * Returned Value: 577 * the pixmap associated with the bitmap 578 * widthp - pointer to width of bitmap 579 * heightp - pointer to height of bitmap 580 * 581 * Inputs: 582 * name - the filename to read 583 * 584 *********************************************************************** 585 */ 586 587Pixmap FindBitmap (char *name, unsigned int *widthp, unsigned int *heightp) 588{ 589 char *bigname; 590 Pixmap pm; 591 592 if (!name) return None; 593 594 /* 595 * Names of the form :name refer to hardcoded images that are scaled to 596 * look nice in title buttons. Eventually, it would be nice to put in a 597 * menu symbol as well.... 598 */ 599 if (name[0] == ':') { 600 int i; 601 static struct { 602 char *name; 603 Pixmap (*proc)(unsigned int *wp, unsigned int *hp); 604 } pmtab[] = { 605 { TBPM_DOT, CreateDotPixmap }, 606 { TBPM_ICONIFY, CreateDotPixmap }, 607 { TBPM_RESIZE, CreateResizePixmap }, 608 { TBPM_XLOGO, CreateXLogoPixmap }, 609 { TBPM_DELETE, CreateXLogoPixmap }, 610 { TBPM_MENU, CreateMenuPixmap }, 611 { TBPM_QUESTION, CreateQuestionPixmap }, 612 }; 613 614 for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) { 615 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) 616 return (*pmtab[i].proc) (widthp, heightp); 617 } 618 fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", 619 ProgramName, name); 620 return None; 621 } 622 623 /* 624 * Generate a full pathname if any special prefix characters (such as ~) 625 * are used. If the bigname is different from name, bigname will need to 626 * be freed. 627 */ 628 bigname = ExpandFilename (name); 629 if (!bigname) return None; 630 631 /* 632 * look along bitmapFilePath resource same as toolkit clients 633 */ 634 pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL, 635 0, (int *)widthp, (int *)heightp, &HotX, &HotY); 636 if (pm == None && Scr->IconDirectory && bigname[0] != '/') { 637 if (bigname != name) free (bigname); 638 /* 639 * Attempt to find icon in old IconDirectory (now obsolete) 640 */ 641#ifdef VMS 642 bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 1); 643 if (!bigname) { 644 fprintf (stderr, 645 "%s: unable to allocate memory for \"%s%s\"\n", 646 ProgramName, Scr->IconDirectory, name); 647 return None; 648 } 649 (void) sprintf (bigname, "%s%s", Scr->IconDirectory, name); 650#else 651 bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 2); 652 if (!bigname) { 653 fprintf (stderr, 654 "%s: unable to allocate memory for \"%s/%s\"\n", 655 ProgramName, Scr->IconDirectory, name); 656 return None; 657 } 658 (void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name); 659#endif 660 if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm, 661 &HotX, &HotY) != BitmapSuccess) { 662 pm = None; 663 } 664 } 665 if (bigname != name) free (bigname); 666 if ((pm == None) && reportfilenotfound) { 667 fprintf (stderr, "%s: unable to find bitmap \"%s\"\n", ProgramName, name); 668 } 669 670 return pm; 671} 672 673Pixmap GetBitmap (char *name) 674{ 675 return FindBitmap (name, &JunkWidth, &JunkHeight); 676} 677 678static Image *LoadBitmapImage (char *name, ColorPair cp) 679{ 680 Image *image; 681 Pixmap bm; 682 unsigned int width, height; 683 XGCValues gcvalues; 684 685 if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues); 686 bm = FindBitmap (name, &width, &height); 687 if (bm == None) return (None); 688 689 image = (Image*) malloc (sizeof (struct _Image)); 690 image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 691 gcvalues.background = cp.back; 692 gcvalues.foreground = cp.fore; 693 XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues); 694 XCopyPlane (dpy, bm, image->pixmap, Scr->rootGC, 0, 0, width, height, 695 0, 0, (unsigned long) 1); 696 XFreePixmap (dpy, bm); 697 image->mask = None; 698 image->width = width; 699 image->height = height; 700 image->next = None; 701 return (image); 702} 703 704static Image *GetBitmapImage (char *name, ColorPair cp) 705{ 706 Image *image, *r, *s; 707 char path [128], pref [128]; 708 char *perc; 709 int i; 710 711 if (! strchr (name, '%')) return (LoadBitmapImage (name, cp)); 712 s = image = None; 713 strcpy (pref, name); 714 perc = strchr (pref, '%'); 715 *perc = '\0'; 716 reportfilenotfound = 0; 717 for (i = 1;; i++) { 718 sprintf (path, "%s%d%s", pref, i, perc + 1); 719 r = LoadBitmapImage (path, cp); 720 if (r == None) break; 721 r->next = None; 722 if (image == None) s = image = r; 723 else { 724 s->next = r; 725 s = r; 726 } 727 } 728 reportfilenotfound = 1; 729 if (s != None) s->next = image; 730 if (image == None) { 731 fprintf (stderr, "Cannot open any %s bitmap file\n", name); 732 } 733 return (image); 734} 735 736#ifdef XPM 737static int reportxpmerror = 1; 738 739static Image *LoadXpmImage (char *name, ColorPair cp) 740{ 741 char *fullname; 742 Image *image; 743 int status; 744 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 745 XpmAttributes attributes; 746 static XpmColorSymbol overrides[] = { 747 {"Foreground", NULL, 0}, 748 {"Background", NULL, 0}, 749 {"HiShadow", NULL, 0}, 750 {"LoShadow", NULL, 0} 751 }; 752 753 fullname = ExpandPixmapPath (name); 754 if (! fullname) return (None); 755 756 image = (Image*) malloc (sizeof (struct _Image)); 757 if (image == None) return (None); 758 759 attributes.valuemask = 0; 760 attributes.valuemask |= XpmSize; 761 attributes.valuemask |= XpmReturnPixels; 762 attributes.valuemask |= XpmColormap; 763 attributes.valuemask |= XpmDepth; 764 attributes.valuemask |= XpmVisual; 765 attributes.valuemask |= XpmCloseness; 766 attributes.valuemask |= XpmColorSymbols; 767 768 attributes.numsymbols = 4; 769 attributes.colorsymbols = overrides; 770 overrides[0].pixel = cp.fore; 771 overrides[1].pixel = cp.back; 772 overrides[2].pixel = cp.shadd; 773 overrides[3].pixel = cp.shadc; 774 775 776 attributes.colormap = AlternateCmap ? AlternateCmap : stdcmap; 777 attributes.depth = Scr->d_depth; 778 attributes.visual = Scr->d_visual; 779 attributes.closeness = 65535; /* Never fail */ 780 status = XpmReadFileToPixmap(dpy, Scr->Root, fullname, 781 &(image->pixmap), &(image->mask), &attributes); 782 if (status != XpmSuccess) { 783 xpmErrorMessage (status, name, fullname); 784 free (image); 785 return (None); 786 } 787 free (fullname); 788 image->width = attributes.width; 789 image->height = attributes.height; 790 image->next = None; 791 return (image); 792} 793 794static Image *GetXpmImage (char *name, ColorPair cp) 795{ 796 char path [128], pref [128]; 797 Image *image, *r, *s; 798 char *perc; 799 int i; 800 801 if (! strchr (name, '%')) return (LoadXpmImage (name, cp)); 802 s = image = None; 803 strcpy (pref, name); 804 perc = strchr (pref, '%'); 805 *perc = '\0'; 806 reportfilenotfound = 0; 807 for (i = 1;; i++) { 808 sprintf (path, "%s%d%s", pref, i, perc + 1); 809 r = LoadXpmImage (path, cp); 810 if (r == None) break; 811 r->next = None; 812 if (image == None) s = image = r; 813 else { 814 s->next = r; 815 s = r; 816 } 817 } 818 reportfilenotfound = 1; 819 if (s != None) s->next = image; 820 if (image == None) { 821 fprintf (stderr, "Cannot open any %s XPM file\n", name); 822 } 823 return (image); 824} 825 826static void xpmErrorMessage (int status, char *name, char *fullname) 827{ 828 switch (status) { 829 case XpmSuccess: 830 break; 831 832 case XpmColorError: 833 if (reportxpmerror) 834 fprintf (stderr, 835 "Could not parse or alloc requested color : %s\n", 836 fullname); 837 return; 838 839 case XpmOpenFailed: 840 if (reportxpmerror && reportfilenotfound) 841 fprintf (stderr, "unable to locate XPM file : %s\n", fullname); 842 return; 843 844 case XpmFileInvalid: 845 fprintf (stderr, "invalid XPM file : %s\n", fullname); 846 return; 847 848 case XpmNoMemory: 849 if (reportxpmerror) 850 fprintf (stderr, "Not enough memory for XPM file : %s\n", fullname); 851 return; 852 853 case XpmColorFailed: 854 if (reportxpmerror) 855 fprintf (stderr, "Color not found in : %s\n", fullname); 856 return; 857 858 default : 859 fprintf (stderr, "Unknown error in : %s\n", fullname); 860 return; 861 } 862} 863 864#endif 865 866void MaskScreen (char *file) 867{ 868 unsigned long valuemask; 869 XSetWindowAttributes attributes; 870 XEvent event; 871 Cursor waitcursor; 872 int x, y; 873 ColorPair WelcomeCp; 874 XColor black; 875 876 NewFontCursor (&waitcursor, "watch"); 877 878 valuemask = (CWBackingStore | CWSaveUnder | CWBackPixel | 879 CWOverrideRedirect | CWEventMask | CWCursor); 880 attributes.backing_store = NotUseful; 881 attributes.save_under = False; 882 attributes.override_redirect = True; 883 attributes.event_mask = ExposureMask; 884 attributes.cursor = waitcursor; 885 attributes.background_pixel = Scr->Black; 886 Scr->WindowMask = XCreateWindow (dpy, Scr->Root, 0, 0, 887 (unsigned int) Scr->rootw, 888 (unsigned int) Scr->rooth, 889 (unsigned int) 0, 890 CopyFromParent, (unsigned int) CopyFromParent, 891 (Visual *) CopyFromParent, valuemask, 892 &attributes); 893 XMapWindow (dpy, Scr->WindowMask); 894 XMaskEvent (dpy, ExposureMask, &event); 895 896 if (Scr->Monochrome != COLOR) return; 897 898 WelcomeCp.fore = Scr->Black; 899 WelcomeCp.back = Scr->White; 900 Scr->WelcomeCmap = XCreateColormap (dpy, Scr->WindowMask, Scr->d_visual, AllocNone); 901 if (! Scr->WelcomeCmap) return; 902 XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap); 903 black.red = 0; 904 black.green = 0; 905 black.blue = 0; 906 XAllocColor (dpy, Scr->WelcomeCmap, &black); 907 908 reportfilenotfound = 0; 909 AlternateCmap = Scr->WelcomeCmap; 910 if (! file) { 911#ifdef CTWM_WELCOME_FILE 912 Scr->WelcomeImage = GetImage (CTWM_WELCOME_FILE, WelcomeCp); 913 if (Scr->WelcomeImage == None) 914#endif 915 Scr->WelcomeImage = GetImage ("xwd:welcome.xwd", WelcomeCp); 916#ifdef XPM 917 if (Scr->WelcomeImage == None) 918 Scr->WelcomeImage = GetImage ("xpm:welcome.xpm", WelcomeCp); 919#endif 920 } 921 else { 922 Scr->WelcomeImage = GetImage (file, WelcomeCp); 923 } 924 AlternateCmap = None; 925 reportfilenotfound = 1; 926 if (Scr->WelcomeImage == None) return; 927 928 if (captive) { 929 XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap); 930 XSetWMColormapWindows (dpy, Scr->Root, &(Scr->WindowMask), 1); 931 } 932 else XInstallColormap (dpy, Scr->WelcomeCmap); 933 934 Scr->WelcomeGC = XCreateGC (dpy, Scr->WindowMask, 0, NULL); 935 x = (Scr->rootw - Scr->WelcomeImage->width) / 2; 936 y = (Scr->rooth - Scr->WelcomeImage->height) / 2; 937 938 XSetWindowBackground (dpy, Scr->WindowMask, black.pixel); 939 XClearWindow (dpy, Scr->WindowMask); 940 XCopyArea (dpy, Scr->WelcomeImage->pixmap, Scr->WindowMask, Scr->WelcomeGC, 0, 0, 941 Scr->WelcomeImage->width, Scr->WelcomeImage->height, x, y); 942} 943 944void UnmaskScreen (void) 945{ 946#ifdef VMS 947 float timeout; 948#else 949 struct timeval timeout; 950#endif 951 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 952 Colormap cmap; 953 XColor colors [256], stdcolors [256]; 954 int i, j, usec; 955 956#ifdef VMS 957 timeout = 0.017; 958#else 959 usec = 10000; 960 timeout.tv_usec = usec % (unsigned long) 1000000; 961 timeout.tv_sec = usec / (unsigned long) 1000000; 962#endif 963 964 if (Scr->WelcomeImage) { 965 Pixel pixels [256]; 966 967 cmap = Scr->WelcomeCmap; 968 for (i = 0; i < 256; i++) { 969 pixels [i] = i; 970 colors [i].pixel = i; 971 } 972 XQueryColors (dpy, cmap, colors, 256); 973 XFreeColors (dpy, cmap, pixels, 256, 0L); 974 XFreeColors (dpy, cmap, pixels, 256, 0L); /* Ah Ah */ 975 976 for (i = 0; i < 256; i++) { 977 colors [i].pixel = i; 978 colors [i].flags = DoRed | DoGreen | DoBlue; 979 stdcolors [i].red = colors [i].red; 980 stdcolors [i].green = colors [i].green; 981 stdcolors [i].blue = colors [i].blue; 982 } 983 for (i = 0; i < 128; i++) { 984 for (j = 0; j < 256; j++) { 985 colors [j].red = stdcolors [j].red * ((127.0 - i) / 128.0); 986 colors [j].green = stdcolors [j].green * ((127.0 - i) / 128.0); 987 colors [j].blue = stdcolors [j].blue * ((127.0 - i) / 128.0); 988 } 989 XStoreColors (dpy, cmap, colors, 256); 990#ifdef VMS 991 lib$wait(&timeout); 992#else 993 select (0, (void *) 0, (void *) 0, (void *) 0, &timeout); 994#endif 995 } 996 XFreeColors (dpy, cmap, pixels, 256, 0L); 997 XFreeGC (dpy, Scr->WelcomeGC); 998 FreeImage (Scr->WelcomeImage); 999 } 1000 if (Scr->Monochrome != COLOR) goto fin; 1001 1002 cmap = XCreateColormap (dpy, Scr->Root, Scr->d_visual, AllocNone); 1003 if (! cmap) goto fin; 1004 for (i = 0; i < 256; i++) { 1005 colors [i].pixel = i; 1006 colors [i].red = 0; 1007 colors [i].green = 0; 1008 colors [i].blue = 0; 1009 colors [i].flags = DoRed | DoGreen | DoBlue; 1010 } 1011 XStoreColors (dpy, cmap, colors, 256); 1012 1013 if (captive) XSetWindowColormap (dpy, Scr->Root, cmap); 1014 else XInstallColormap (dpy, cmap); 1015 1016 XUnmapWindow (dpy, Scr->WindowMask); 1017 XClearWindow (dpy, Scr->Root); 1018 XSync (dpy, 0); 1019 PaintAllDecoration (); 1020 1021 for (i = 0; i < 256; i++) stdcolors [i].pixel = i; 1022 XQueryColors (dpy, stdcmap, stdcolors, 256); 1023 for (i = 0; i < 128; i++) { 1024 for (j = 0; j < 256; j++) { 1025 colors [j].pixel = j; 1026 colors [j].red = stdcolors [j].red * (i / 127.0); 1027 colors [j].green = stdcolors [j].green * (i / 127.0); 1028 colors [j].blue = stdcolors [j].blue * (i / 127.0); 1029 colors [j].flags = DoRed | DoGreen | DoBlue; 1030 } 1031 XStoreColors (dpy, cmap, colors, 256); 1032#ifdef VMS 1033 lib$wait(&timeout); 1034#else 1035 select (0, (void *) 0, (void *) 0, (void *) 0, &timeout); 1036#endif 1037 } 1038 1039 if (captive) XSetWindowColormap (dpy, Scr->Root, stdcmap); 1040 else XInstallColormap (dpy, stdcmap); 1041 1042 XFreeColormap (dpy, cmap); 1043 1044fin: 1045 if (Scr->WelcomeCmap) XFreeColormap (dpy, Scr->WelcomeCmap); 1046 XDestroyWindow (dpy, Scr->WindowMask); 1047 Scr->WindowMask = (Window) 0; 1048} 1049 1050#ifdef VMS 1051 1052/* use the VMS system services to request the timer to issue an AST */ 1053void AnimateHandler (void); 1054 1055unsigned int tv[2]; 1056int status; 1057static unsigned long timefi; 1058/* unsigned long timefe = 17; */ 1059unsigned long timefe; 1060 1061#define TIMID 12L 1062 1063void StartAnimation (void) 1064{ 1065 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1066 if (AnimationSpeed <= 0) return; 1067 if (AnimationActive) return; 1068 1069 if (!timefi) lib$get_ef(&timefi); 1070 if (!timefe) lib$get_ef(&timefe); 1071 1072 tv[1] = 0xFFFFFFFF; /* quadword negative for relative */ 1073 tv[0] = -(10000000 / AnimationSpeed); /* time. In units of 100ns. */ 1074 sys$clref(timefe); 1075 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID ); 1076 if (status != SS$_NORMAL) lib$signal(status); 1077 AnimationActive = True; 1078} 1079 1080void StopAnimation () { 1081 if (AnimationSpeed <= 0) return; 1082 if (! AnimationActive) return; 1083 AnimationActive = False; 1084 1085 status = sys$cantim(TIMID, PSL$C_USER); 1086 if (status != SS$_NORMAL) lib$signal(status); 1087} 1088 1089void SetAnimationSpeed (int speed) 1090{ 1091 AnimationSpeed = speed; 1092 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1093} 1094 1095void ModifyAnimationSpeed (int incr) 1096{ 1097 if ((AnimationSpeed + incr) < 0) return; 1098 if ((AnimationSpeed + incr) == 0) { 1099 if (AnimationActive) StopAnimation (); 1100 AnimationSpeed = 0; 1101 return; 1102 } 1103 AnimationSpeed += incr; 1104 1105 status = sys$cantim(TIMID, PSL$C_USER); 1106 if (status != SS$_NORMAL) lib$signal(status); 1107 1108 tv[1] = 0xFFFFFFFF; 1109 tv[0] = -(10000000 / AnimationSpeed); 1110 1111 sys$clref(timefe); 1112 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID); 1113 if (status != SS$_NORMAL) lib$signal(status); 1114 1115 AnimationActive = True; 1116} 1117 1118void AnimateHandler (void) { 1119 AnimationPending = True; 1120 1121 sys$setef(timefe); 1122 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID); 1123 if (status != SS$_NORMAL) lib$signal(status); 1124} 1125#else /* VMS */ 1126 1127#ifdef USE_SIGNALS 1128SIGNAL_T AnimateHandler (); 1129#endif 1130 1131#ifndef USE_SIGNALS 1132void TryToAnimate (void) 1133{ 1134 struct timeval tp; 1135 struct timezone tzp; 1136 static unsigned long lastsec; 1137 static long lastusec; 1138 unsigned long gap; 1139 1140 gettimeofday (&tp, &tzp); 1141 gap = ((tp.tv_sec - lastsec) * 1000000) + (tp.tv_usec - lastusec); 1142 if (tracefile) { 1143 fprintf (tracefile, "Time = %lu, %ld, %ld, %ld, %lu\n", lastsec, 1144 lastusec, (long)tp.tv_sec, (long)tp.tv_usec, gap); 1145 fflush (tracefile); 1146 } 1147 gap *= AnimationSpeed; 1148 if (gap < 1000000) return; 1149 if (tracefile) { 1150 fprintf (tracefile, "Animate\n"); 1151 fflush (tracefile); 1152 } 1153 Animate (); 1154 lastsec = tp.tv_sec; 1155 lastusec = tp.tv_usec; 1156} 1157#endif /* USE_SIGNALS */ 1158 1159void StartAnimation (void) 1160{ 1161#ifdef USE_SIGNALS 1162 struct itimerval tv; 1163#endif 1164 1165 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1166 if (AnimationSpeed <= 0) AnimationSpeed = 0; 1167 if (AnimationActive) return; 1168#ifdef USE_SIGNALS 1169 if (AnimationSpeed == 0) return; 1170 signal (SIGALRM, AnimateHandler); 1171 if (AnimationSpeed == 1) { 1172 tv.it_interval.tv_sec = 1; 1173 tv.it_interval.tv_usec = 0; 1174 tv.it_value.tv_sec = 1; 1175 tv.it_value.tv_usec = 0; 1176 } 1177 else { 1178 tv.it_interval.tv_sec = 0; 1179 tv.it_interval.tv_usec = 1000000 / AnimationSpeed; 1180 tv.it_value.tv_sec = 0; 1181 tv.it_value.tv_usec = 1000000 / AnimationSpeed; 1182 } 1183 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1184#else /* USE_SIGNALS */ 1185 switch (AnimationSpeed) { 1186 case 0 : 1187 return; 1188 case 1 : 1189 AnimateTimeout.tv_sec = 1; 1190 AnimateTimeout.tv_usec = 0; 1191 break; 1192 default : 1193 AnimateTimeout.tv_sec = 0; 1194 AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1195 } 1196#endif /* USE_SIGNALS */ 1197 AnimationActive = True; 1198} 1199 1200void StopAnimation (void) 1201{ 1202#ifdef USE_SIGNALS 1203 struct itimerval tv; 1204 1205 if (AnimationSpeed <= 0) return; 1206 if (! AnimationActive) return; 1207 signal (SIGALRM, SIG_IGN); 1208 1209 tv.it_value.tv_sec = 0; 1210 tv.it_value.tv_usec = 0; 1211 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1212#endif 1213 AnimationActive = False; 1214} 1215 1216void SetAnimationSpeed (int speed) 1217{ 1218 AnimationSpeed = speed; 1219 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1220} 1221 1222void ModifyAnimationSpeed (int incr) 1223{ 1224#ifdef USE_SIGNALS 1225 struct itimerval tv; 1226#endif 1227 1228 if ((AnimationSpeed + incr) < 0) return; 1229 if ((AnimationSpeed + incr) == 0) { 1230 if (AnimationActive) StopAnimation (); 1231 AnimationSpeed = 0; 1232 return; 1233 } 1234 AnimationSpeed += incr; 1235 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1236 1237#ifdef USE_SIGNALS 1238 signal (SIGALRM, AnimateHandler); 1239 if (AnimationSpeed == 1) { 1240 tv.it_interval.tv_sec = 1; 1241 tv.it_interval.tv_usec = 0; 1242 tv.it_value.tv_sec = 1; 1243 tv.it_value.tv_usec = 0; 1244 } 1245 else { 1246 tv.it_interval.tv_sec = 0; 1247 tv.it_interval.tv_usec = 1000000 / AnimationSpeed; 1248 tv.it_value.tv_sec = 0; 1249 tv.it_value.tv_usec = 1000000 / AnimationSpeed; 1250 } 1251 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1252#else /* USE_SIGNALS */ 1253 if (AnimationSpeed == 1) { 1254 AnimateTimeout.tv_sec = 1; 1255 AnimateTimeout.tv_usec = 0; 1256 } 1257 else { 1258 AnimateTimeout.tv_sec = 0; 1259 AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1260 } 1261#endif /* USE_SIGNALS */ 1262 AnimationActive = True; 1263} 1264 1265#ifdef USE_SIGNALS 1266SIGNAL_T AnimateHandler (int dummy) 1267{ 1268 signal (SIGALRM, AnimateHandler); 1269 AnimationPending = True; 1270} 1271#endif 1272#endif /* VMS */ 1273 1274void Animate (void) 1275{ 1276 TwmWindow *t; 1277 int scrnum; 1278 ScreenInfo *scr; 1279 int i; 1280 TBWindow *tbw; 1281 int nb; 1282 1283 if (AnimationSpeed == 0) return; 1284#ifdef USE_SIGNALS 1285 AnimationPending = False; 1286#endif 1287 1288 MaybeAnimate = False; 1289 for (scrnum = 0; scrnum < NumScreens; scrnum++) { 1290 if ((scr = ScreenList [scrnum]) == NULL) continue; 1291 1292 for (t = scr->FirstWindow; t != NULL; t = t->next) { 1293 if (! visible (t)) continue; 1294 if (t->icon_on && t->icon && t->icon->bm_w && t->icon->image && 1295 t->icon->image->next) { 1296 AnimateIcons (scr, t->icon); 1297 MaybeAnimate = True; 1298 } 1299 else 1300 if (t->mapped && t->titlebuttons) { 1301 nb = scr->TBInfo.nleft + scr->TBInfo.nright; 1302 for (i = 0, tbw = t->titlebuttons; i < nb; i++, tbw++) { 1303 if (tbw->image && tbw->image->next) { 1304 AnimateButton (tbw); 1305 MaybeAnimate = True; 1306 } 1307 } 1308 } 1309 } 1310 if (scr->Focus) { 1311 t = scr->Focus; 1312 if (t->mapped && t->titlehighlight && t->title_height && 1313 t->HiliteImage && t->HiliteImage->next) { 1314 AnimateHighlight (t); 1315 MaybeAnimate = True; 1316 } 1317 } 1318 } 1319 MaybeAnimate |= AnimateRoot (); 1320 XFlush (dpy); 1321 return; 1322} 1323 1324void InsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps, 1325 Bool replace) 1326{ 1327 StdCmap *sc = NULL; 1328 1329 if (replace) { /* locate existing entry */ 1330 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1331 if (sc->atom == a) break; 1332 } 1333 } 1334 1335 if (!sc) { /* no existing, allocate new */ 1336 sc = (StdCmap *) malloc (sizeof (StdCmap)); 1337 if (!sc) { 1338 fprintf (stderr, "%s: unable to allocate %lu bytes for StdCmap\n", 1339 ProgramName, (unsigned long) sizeof(StdCmap)); 1340 return; 1341 } 1342 } 1343 1344 if (replace) { /* just update contents */ 1345 if (sc->maps) XFree ((char *) maps); 1346 if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL; 1347 } else { /* else appending */ 1348 sc->next = NULL; 1349 sc->atom = a; 1350 if (Scr->StdCmapInfo.tail) { 1351 Scr->StdCmapInfo.tail->next = sc; 1352 } else { 1353 Scr->StdCmapInfo.head = sc; 1354 } 1355 Scr->StdCmapInfo.tail = sc; 1356 } 1357 sc->nmaps = nmaps; 1358 sc->maps = maps; 1359 1360 return; 1361} 1362 1363void RemoveRGBColormap (Atom a) 1364{ 1365 StdCmap *sc, *prev; 1366 1367 prev = NULL; 1368 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1369 if (sc->atom == a) break; 1370 prev = sc; 1371 } 1372 if (sc) { /* found one */ 1373 if (sc->maps) XFree ((char *) sc->maps); 1374 if (prev) prev->next = sc->next; 1375 if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next; 1376 if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev; 1377 if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL; 1378 } 1379 return; 1380} 1381 1382void LocateStandardColormaps(void) 1383{ 1384 Atom *atoms; 1385 int natoms; 1386 int i; 1387 1388 atoms = XListProperties (dpy, Scr->Root, &natoms); 1389 for (i = 0; i < natoms; i++) { 1390 XStandardColormap *maps = NULL; 1391 int nmaps; 1392 1393 if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) { 1394 /* if got one, then append to current list */ 1395 InsertRGBColormap (atoms[i], maps, nmaps, False); 1396 } 1397 } 1398 if (atoms) XFree ((char *) atoms); 1399 return; 1400} 1401 1402void GetColor(int kind, Pixel *what, char *name) 1403{ 1404 XColor color; 1405 Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 1406 1407#ifndef TOM 1408 if (!Scr->FirstTime) 1409 return; 1410#endif 1411 1412 if (Scr->Monochrome != kind) 1413 return; 1414 1415 if (! XParseColor (dpy, cmap, name, &color)) { 1416 fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1417 return; 1418 } 1419 if (! XAllocColor (dpy, cmap, &color)) 1420 { 1421 /* if we could not allocate the color, let's see if this is a 1422 * standard colormap 1423 */ 1424 XStandardColormap *stdcmap = NULL; 1425 1426 if (! XParseColor (dpy, cmap, name, &color)) { 1427 fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1428 return; 1429 } 1430 1431 /* 1432 * look through the list of standard colormaps (check cache first) 1433 */ 1434 if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps && 1435 (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap == 1436 cmap)) { 1437 stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]); 1438 } else { 1439 StdCmap *sc; 1440 1441 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1442 int i; 1443 1444 for (i = 0; i < sc->nmaps; i++) { 1445 if (sc->maps[i].colormap == cmap) { 1446 Scr->StdCmapInfo.mru = sc; 1447 Scr->StdCmapInfo.mruindex = i; 1448 stdcmap = &(sc->maps[i]); 1449 goto gotit; 1450 } 1451 } 1452 } 1453 } 1454 1455 gotit: 1456 if (stdcmap) { 1457 color.pixel = (stdcmap->base_pixel + 1458 ((Pixel)(((float)color.red / 65535.0) * 1459 stdcmap->red_max + 0.5) * 1460 stdcmap->red_mult) + 1461 ((Pixel)(((float)color.green /65535.0) * 1462 stdcmap->green_max + 0.5) * 1463 stdcmap->green_mult) + 1464 ((Pixel)(((float)color.blue / 65535.0) * 1465 stdcmap->blue_max + 0.5) * 1466 stdcmap->blue_mult)); 1467 } else { 1468 fprintf (stderr, "%s: unable to allocate color \"%s\"\n", 1469 ProgramName, name); 1470 return; 1471 } 1472 } 1473 1474 *what = color.pixel; 1475 return; 1476} 1477 1478void GetShadeColors (ColorPair *cp) 1479{ 1480 XColor xcol; 1481 Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 1482 int save; 1483 float clearfactor; 1484 float darkfactor; 1485 char clearcol [32], darkcol [32]; 1486 1487 clearfactor = (float) Scr->ClearShadowContrast / 100.0; 1488 darkfactor = (100.0 - (float) Scr->DarkShadowContrast) / 100.0; 1489 xcol.pixel = cp->back; 1490 XQueryColor (dpy, cmap, &xcol); 1491 1492 sprintf (clearcol, "#%04x%04x%04x", 1493 xcol.red + (unsigned short) ((65535 - xcol.red) * clearfactor), 1494 xcol.green + (unsigned short) ((65535 - xcol.green) * clearfactor), 1495 xcol.blue + (unsigned short) ((65535 - xcol.blue) * clearfactor)); 1496 sprintf (darkcol, "#%04x%04x%04x", 1497 (unsigned short) (xcol.red * darkfactor), 1498 (unsigned short) (xcol.green * darkfactor), 1499 (unsigned short) (xcol.blue * darkfactor)); 1500 1501 save = Scr->FirstTime; 1502 Scr->FirstTime = True; 1503 GetColor (Scr->Monochrome, &cp->shadc, clearcol); 1504 GetColor (Scr->Monochrome, &cp->shadd, darkcol); 1505 Scr->FirstTime = save; 1506} 1507 1508void GetFont(MyFont *font) 1509{ 1510 char *deffontname = "fixed,*"; 1511 char **missing_charset_list_return; 1512 int missing_charset_count_return; 1513 char *def_string_return; 1514 XFontSetExtents *font_extents; 1515 XFontStruct **xfonts; 1516 char **font_names; 1517 register int i; 1518 int ascent; 1519 int descent; 1520 int fnum; 1521 char *basename2; 1522 1523 if (font->font_set != NULL){ 1524 XFreeFontSet(dpy, font->font_set); 1525 } 1526 1527 basename2 = (char *)malloc(strlen(font->basename) + 3); 1528 if (basename2) sprintf(basename2, "%s,*", font->basename); 1529 else basename2 = font->basename; 1530 if( (font->font_set = XCreateFontSet(dpy, basename2, 1531 &missing_charset_list_return, 1532 &missing_charset_count_return, 1533 &def_string_return)) == NULL) { 1534 if (Scr->DefaultFont.basename) { 1535 deffontname = Scr->DefaultFont.basename; 1536 } 1537 if ((font->font_set = XCreateFontSet(dpy, deffontname, 1538 &missing_charset_list_return, 1539 &missing_charset_count_return, 1540 &def_string_return)) == NULL) 1541 { 1542 fprintf (stderr, "%s: unable to open fonts \"%s\" or \"%s\"\n", 1543 ProgramName, font->basename, deffontname); 1544 exit(1); 1545 } 1546 } 1547 if (basename2 != font->basename) free(basename2); 1548 font_extents = XExtentsOfFontSet(font->font_set); 1549 1550 fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names); 1551 for( i = 0, ascent = 0, descent = 0; i<fnum; i++){ 1552 ascent = MaxSize(ascent, (*xfonts)->ascent); 1553 descent = MaxSize(descent, (*xfonts)->descent); 1554 xfonts++; 1555 } 1556 1557 font->height = font_extents->max_logical_extent.height; 1558 font->y = ascent; 1559 font->ascent = ascent; 1560 font->descent = descent; 1561} 1562 1563 1564void SetFocusVisualAttributes (TwmWindow *tmp_win, Bool focus) 1565{ 1566 if (! tmp_win) return; 1567 1568 if (focus == tmp_win->hasfocusvisible) return; 1569 if (tmp_win->highlight) { 1570 if (Scr->use3Dborders) { 1571 PaintBorders (tmp_win, focus); 1572 } 1573 else { 1574 if (focus) { 1575 XSetWindowBorder (dpy, tmp_win->frame, tmp_win->borderC.back); 1576 if (tmp_win->title_w) 1577 XSetWindowBorder (dpy, tmp_win->title_w, tmp_win->borderC.back); 1578 } else { 1579 XSetWindowBorderPixmap (dpy, tmp_win->frame, tmp_win->gray); 1580 if (tmp_win->title_w) 1581 XSetWindowBorderPixmap (dpy, tmp_win->title_w, tmp_win->gray); 1582 } 1583 } 1584 } 1585 1586 if (focus) { 1587 Bool hil = False; 1588 1589 if (tmp_win->lolite_wl) XUnmapWindow (dpy, tmp_win->lolite_wl); 1590 if (tmp_win->lolite_wr) XUnmapWindow (dpy, tmp_win->lolite_wr); 1591 if (tmp_win->hilite_wl) { 1592 XMapWindow (dpy, tmp_win->hilite_wl); 1593 hil = True; 1594 } 1595 if (tmp_win->hilite_wr) { 1596 XMapWindow (dpy, tmp_win->hilite_wr); 1597 hil = True; 1598 } 1599 if (hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) { 1600 MaybeAnimate = True; 1601 } 1602 if (tmp_win->iconmanagerlist) 1603 ActiveIconManager (tmp_win->iconmanagerlist); 1604 } 1605 else { 1606 if (tmp_win->hilite_wl) XUnmapWindow (dpy, tmp_win->hilite_wl); 1607 if (tmp_win->hilite_wr) XUnmapWindow (dpy, tmp_win->hilite_wr); 1608 if (tmp_win->lolite_wl) XMapWindow (dpy, tmp_win->lolite_wl); 1609 if (tmp_win->lolite_wr) XMapWindow (dpy, tmp_win->lolite_wr); 1610 if (tmp_win->iconmanagerlist) 1611 NotActiveIconManager (tmp_win->iconmanagerlist); 1612 } 1613 if (Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) { 1614 ButtonState bs; 1615 1616 bs = focus ? on : off; 1617 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 1618 tmp_win->title_width - Scr->TBInfo.titlex - 1619 Scr->TBInfo.rightoff - Scr->TitlePadding, 1620 Scr->TitleHeight, Scr->TitleShadowDepth, 1621 tmp_win->title, bs, False, False); 1622 } 1623 tmp_win->hasfocusvisible = focus; 1624} 1625 1626static void move_to_head (TwmWindow *t) 1627{ 1628 if (t == NULL) return; 1629 if (Scr->FirstWindow == t) return; 1630 1631 if (t->prev) t->prev->next = t->next; 1632 if (t->next) t->next->prev = t->prev; 1633 1634 t->next = Scr->FirstWindow; 1635 if (Scr->FirstWindow != NULL) 1636 Scr->FirstWindow->prev = t; 1637 t->prev = NULL; 1638 Scr->FirstWindow = t; 1639} 1640 1641/* 1642 * SetFocus - separate routine to set focus to make things more understandable 1643 * and easier to debug 1644 */ 1645void SetFocus (TwmWindow *tmp_win, Time tim) 1646{ 1647 Window w = (tmp_win ? tmp_win->w : PointerRoot); 1648 int f_iconmgr = 0; 1649 1650 if (Scr->Focus && (Scr->Focus->iconmgr)) f_iconmgr = 1; 1651 if (Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) return; 1652 1653 XSetInputFocus (dpy, w, RevertToPointerRoot, tim); 1654 if (Scr->Focus == tmp_win) return; 1655 1656 if (Scr->Focus) { 1657 if (Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) { 1658 AutoSqueeze (Scr->Focus); 1659 } 1660 SetFocusVisualAttributes (Scr->Focus, False); 1661 } 1662 if (tmp_win) { 1663 if (tmp_win->AutoSqueeze && tmp_win->squeezed) { 1664 AutoSqueeze (tmp_win); 1665 } 1666 SetFocusVisualAttributes (tmp_win, True); 1667 } 1668 Scr->Focus = tmp_win; 1669 move_to_head (tmp_win); 1670} 1671 1672# 1673#ifdef NOPUTENV 1674/* 1675 * define our own putenv() if the system doesn't have one. 1676 * putenv(s): place s (a string of the form "NAME=value") in 1677 * the environment; replacing any existing NAME. s is placed in 1678 * environment, so if you change s, the environment changes (like 1679 * putenv on a sun). Binding removed if you putenv something else 1680 * called NAME. 1681 */ 1682int 1683putenv(s) 1684 char *s; 1685{ 1686 char *v; 1687 int varlen, idx; 1688 extern char **environ; 1689 char **newenv; 1690 static int virgin = 1; /* true while "environ" is a virgin */ 1691 1692 v = strchr(s, '='); 1693 if(v == 0) 1694 return 0; /* punt if it's not of the right form */ 1695 varlen = (v + 1) - s; 1696 1697 for (idx = 0; environ[idx] != 0; idx++) { 1698 if (strncmp(environ[idx], s, varlen) == 0) { 1699 if(v[1] != 0) { /* true if there's a value */ 1700 environ[idx] = s; 1701 return 0; 1702 } else { 1703 do { 1704 environ[idx] = environ[idx+1]; 1705 } while(environ[++idx] != 0); 1706 return 0; 1707 } 1708 } 1709 } 1710 1711 /* add to environment (unless no value; then just return) */ 1712 if(v[1] == 0) 1713 return 0; 1714 if(virgin) { 1715 register i; 1716 1717 newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*))); 1718 if(newenv == 0) 1719 return -1; 1720 for(i = idx-1; i >= 0; --i) 1721 newenv[i] = environ[i]; 1722 virgin = 0; /* you're not a virgin anymore, sweety */ 1723 } else { 1724 newenv = (char **) realloc((char *) environ, 1725 (unsigned) ((idx + 2) * sizeof(char*))); 1726 if (newenv == 0) 1727 return -1; 1728 } 1729 1730 environ = newenv; 1731 environ[idx] = s; 1732 environ[idx+1] = 0; 1733 1734 return 0; 1735} 1736#endif /* NOPUTENV */ 1737 1738 1739static Pixmap CreateXLogoPixmap (unsigned int *widthp, unsigned int *heightp) 1740{ 1741 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1742 if (h < 0) h = 0; 1743 1744 *widthp = *heightp = (unsigned int) h; 1745 if (Scr->tbpm.xlogo == None) { 1746 GC gc, gcBack; 1747 1748 Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1749 gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); 1750 XSetForeground (dpy, gc, 0); 1751 XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h); 1752 XSetForeground (dpy, gc, 1); 1753 gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); 1754 XSetForeground (dpy, gcBack, 0); 1755 1756 /* 1757 * draw the logo large so that it gets as dense as possible; then white 1758 * out the edges so that they look crisp 1759 */ 1760 XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2); 1761 XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1); 1762 1763 /* 1764 * done drawing 1765 */ 1766 XFreeGC (dpy, gc); 1767 XFreeGC (dpy, gcBack); 1768 } 1769 return Scr->tbpm.xlogo; 1770} 1771 1772 1773static Pixmap CreateResizePixmap (unsigned int *widthp, unsigned int *heightp) 1774{ 1775 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1776 if (h < 1) h = 1; 1777 1778 *widthp = *heightp = (unsigned int) h; 1779 if (Scr->tbpm.resize == None) { 1780 XPoint points[3]; 1781 GC gc; 1782 int w; 1783 int lw; 1784 1785 /* 1786 * create the pixmap 1787 */ 1788 Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1789 gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL); 1790 XSetForeground (dpy, gc, 0); 1791 XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h); 1792 XSetForeground (dpy, gc, 1); 1793 lw = h / 16; 1794 if (lw == 1) 1795 lw = 0; 1796 XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter); 1797 1798 /* 1799 * draw the resize button, 1800 */ 1801 w = (h * 2) / 3; 1802 points[0].x = w; 1803 points[0].y = 0; 1804 points[1].x = w; 1805 points[1].y = w; 1806 points[2].x = 0; 1807 points[2].y = w; 1808 XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 1809 w = w / 2; 1810 points[0].x = w; 1811 points[0].y = 0; 1812 points[1].x = w; 1813 points[1].y = w; 1814 points[2].x = 0; 1815 points[2].y = w; 1816 XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 1817 1818 /* 1819 * done drawing 1820 */ 1821 XFreeGC(dpy, gc); 1822 } 1823 return Scr->tbpm.resize; 1824} 1825 1826static Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp) 1827{ 1828 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1829 1830 h = h * 3 / 4; 1831 if (h < 1) h = 1; 1832 if (!(h & 1)) 1833 h--; 1834 *widthp = *heightp = (unsigned int) h; 1835 if (Scr->tbpm.delete == None) { 1836 GC gc; 1837 Pixmap pix; 1838 1839 pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1840 gc = XCreateGC (dpy, pix, 0L, NULL); 1841 XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound); 1842 XSetForeground (dpy, gc, 0L); 1843 XFillRectangle (dpy, pix, gc, 0, 0, h, h); 1844 XSetForeground (dpy, gc, 1L); 1845 XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2); 1846 XFreeGC (dpy, gc); 1847 } 1848 return Scr->tbpm.delete; 1849} 1850 1851static Image *Create3DCrossImage (ColorPair cp) 1852{ 1853 Image *image; 1854 int h; 1855 int point; 1856 int midpoint; 1857 1858 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1859 if (!(h & 1)) h--; 1860 point = 4; 1861 midpoint = h/2; 1862 1863 image = (Image*) malloc (sizeof (struct _Image)); 1864 if (! image) return (None); 1865 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1866 if (image->pixmap == None) return (None); 1867 1868 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1869 1870#ifdef LEVITTE_TEST 1871 FB (cp.shadc, cp.shadd); 1872 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point-1, point-1, point+1); 1873 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point, point, point+1); 1874 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point+1, midpoint-2, midpoint); 1875 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint+2, h-point-3, h-point-1); 1876 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point+1, h-point-3, h-point-2); 1877 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-2, midpoint-2, midpoint); 1878 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint-2, h-point-2, point-1); 1879 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-2, h-point-2, point); 1880#endif 1881 1882 FB (cp.shadd, cp.shadc); 1883#ifdef LEVITTE_TEST 1884 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point+1, h-point-1, h-point-2); 1885 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point, midpoint, midpoint-2); 1886 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, h-point-2); 1887 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, h-point-2, h-point-2, h-point); 1888 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, h-point-2, h-point-2, h-point-1); 1889#else 1890 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point-1, h-point-1); 1891 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point, h-point-1, h-point); 1892 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point-1, h-point, h-point-1); 1893#endif 1894 1895#ifdef LEVITTE_TEST 1896 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, point, h-point-1); 1897 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point, h-point-1, point); 1898#else 1899 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, h-point-1, point); 1900#endif 1901#ifdef LEVITTE_TEST 1902 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point-1, h-point-1, point+1); 1903 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point, midpoint, midpoint+2); 1904 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, point+1); 1905#else 1906 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-1, h-point-1, point-1); 1907 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point, h-point, point); 1908#endif 1909 1910 image->mask = None; 1911 image->width = h; 1912 image->height = h; 1913 image->next = None; 1914 1915 return (image); 1916} 1917 1918static Image *Create3DIconifyImage (ColorPair cp) 1919{ 1920 Image *image; 1921 int h; 1922 int point; 1923 1924 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1925 if (!(h & 1)) h--; 1926 point = ((h/2-2) * 2+1) / 3; 1927 1928 image = (Image*) malloc (sizeof (struct _Image)); 1929 if (! image) return (None); 1930 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1931 if (image->pixmap == None) return (None); 1932 1933 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1934 FB (cp.shadd, cp.shadc); 1935 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h/2, h-point); 1936 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point, point); 1937 1938 FB (cp.shadc, cp.shadd); 1939 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, point, h/2+1, h-point); 1940 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point+1, h/2+1, h-point-1); 1941 1942 image->mask = None; 1943 image->width = h; 1944 image->height = h; 1945 image->next = None; 1946 1947 return (image); 1948} 1949 1950static Image *Create3DSunkenResizeImage (ColorPair cp) 1951{ 1952 int h; 1953 Image *image; 1954 1955 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1956 if (!(h & 1)) h--; 1957 1958 image = (Image*) malloc (sizeof (struct _Image)); 1959 if (! image) return (None); 1960 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1961 if (image->pixmap == None) return (None); 1962 1963 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1964 Draw3DBorder (image->pixmap, 3, 3, h-6, h-6, 1, cp, on, True, False); 1965 Draw3DBorder (image->pixmap, 3, ((h-6)/3)+3, ((h-6)*2/3)+1, 1966 ((h-6)*2/3)+1, 1, cp, on, True, False); 1967 Draw3DBorder (image->pixmap, 3, ((h-6)*2/3)+3, ((h-6)/3)+1, 1968 ((h-6)/3)+1, 1, cp, on, True, False); 1969 1970 image->mask = None; 1971 image->width = h; 1972 image->height = h; 1973 image->next = None; 1974 1975 return (image); 1976} 1977 1978static Image *Create3DBoxImage (ColorPair cp) 1979{ 1980 int h; 1981 Image *image; 1982 1983 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1984 if (! (h & 1)) h--; 1985 1986 image = (Image*) malloc (sizeof (struct _Image)); 1987 if (! image) return (None); 1988 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1989 if (image->pixmap == None) return (None); 1990 1991 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1992 Draw3DBorder (image->pixmap, (h / 2) - 4, (h / 2) - 4, 9, 9, 1, cp, 1993 off, True, False); 1994 1995 image->mask = None; 1996 image->width = h; 1997 image->height = h; 1998 image->next = None; 1999 2000 return (image); 2001} 2002 2003static Image *Create3DDotImage (ColorPair cp) 2004{ 2005 Image *image; 2006 int h; 2007 static int idepth = 2; 2008 2009 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2010 if (!(h & 1)) h--; 2011 2012 image = (Image*) malloc (sizeof (struct _Image)); 2013 if (! image) return (None); 2014 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2015 if (image->pixmap == None) return (None); 2016 2017 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2018 Draw3DBorder (image->pixmap, (h / 2) - idepth, 2019 (h / 2) - idepth, 2020 2 * idepth + 1, 2021 2 * idepth + 1, 2022 idepth, cp, off, True, False); 2023 image->mask = None; 2024 image->width = h; 2025 image->height = h; 2026 image->next = None; 2027 return (image); 2028} 2029 2030static Image *Create3DBarImage (ColorPair cp) 2031{ 2032 Image *image; 2033 int h; 2034 static int idepth = 2; 2035 2036 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2037 if (!(h & 1)) h--; 2038 2039 image = (Image*) malloc (sizeof (struct _Image)); 2040 if (! image) return (None); 2041 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2042 if (image->pixmap == None) return (None); 2043 2044 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2045 Draw3DBorder (image->pixmap, 2046 Scr->TitleButtonShadowDepth + 2, 2047 (h / 2) - idepth, 2048 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2049 2 * idepth + 1, 2050 idepth, cp, off, True, False); 2051 image->mask = None; 2052 image->width = h; 2053 image->height = h; 2054 image->next = None; 2055 return (image); 2056} 2057 2058static Image *Create3DVertBarImage (ColorPair cp) 2059{ 2060 Image *image; 2061 int h; 2062 static int idepth = 2; 2063 2064 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2065 if (!(h & 1)) h--; 2066 2067 image = (Image*) malloc (sizeof (struct _Image)); 2068 if (! image) return (None); 2069 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2070 if (image->pixmap == None) return (None); 2071 2072 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2073 Draw3DBorder (image->pixmap, 2074 (h / 2) - idepth, 2075 Scr->TitleButtonShadowDepth + 2, 2076 2 * idepth + 1, 2077 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2078 idepth, cp, off, True, False); 2079 image->mask = None; 2080 image->width = h; 2081 image->height = h; 2082 image->next = None; 2083 return (image); 2084} 2085 2086static Image *Create3DMenuImage (ColorPair cp) 2087{ 2088 Image *image; 2089 int h, i; 2090 2091 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2092 if (!(h & 1)) h--; 2093 2094 image = (Image*) malloc (sizeof (struct _Image)); 2095 if (! image) return (None); 2096 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2097 if (image->pixmap == None) return (None); 2098 2099 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2100 for (i = 4; i < h - 7; i += 5) { 2101 Draw3DBorder (image->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False); 2102 } 2103 image->mask = None; 2104 image->width = h; 2105 image->height = h; 2106 image->next = None; 2107 return (image); 2108} 2109 2110static Image *Create3DResizeImage (ColorPair cp) 2111{ 2112 Image *image; 2113 int h; 2114 2115 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2116 if (!(h & 1)) h--; 2117 2118 image = (Image*) malloc (sizeof (struct _Image)); 2119 if (! image) return (None); 2120 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2121 if (image->pixmap == None) return (None); 2122 2123 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2124 Draw3DBorder (image->pixmap, 0, h / 4, ((3 * h) / 4) + 1, ((3 * h) / 4) + 1, 2, 2125 cp, off, True, False); 2126 Draw3DBorder (image->pixmap, 0, h / 2, (h / 2) + 1, (h / 2) + 1, 2, cp, off, True, False); 2127 image->mask = None; 2128 image->width = h; 2129 image->height = h; 2130 image->next = None; 2131 return (image); 2132} 2133 2134static Image *Create3DZoomImage (ColorPair cp) 2135{ 2136 Image *image; 2137 int h; 2138 static int idepth = 2; 2139 2140 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2141 if (!(h & 1)) h--; 2142 2143 image = (Image*) malloc (sizeof (struct _Image)); 2144 if (! image) return (None); 2145 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2146 if (image->pixmap == None) return (None); 2147 2148 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2149 Draw3DBorder (image->pixmap, Scr->TitleButtonShadowDepth + 2, 2150 Scr->TitleButtonShadowDepth + 2, 2151 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2152 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2153 idepth, cp, off, True, False); 2154 2155 image->mask = None; 2156 image->width = h; 2157 image->height = h; 2158 image->next = None; 2159 return (image); 2160} 2161 2162struct Colori { 2163 Pixel color; 2164 Pixmap pix; 2165 struct Colori *next; 2166}; 2167 2168Pixmap Create3DMenuIcon (unsigned int height, 2169 unsigned int *widthp, unsigned int *heightp, 2170 ColorPair cp) 2171{ 2172 unsigned int h, w; 2173 int i; 2174 struct Colori *col; 2175 static struct Colori *colori = NULL; 2176 2177 h = height; 2178 w = h * 7 / 8; 2179 if (h < 1) h = 1; 2180 if (w < 1) w = 1; 2181 *widthp = w; 2182 *heightp = h; 2183 2184 for (col = colori; col; col = col->next) { 2185 if (col->color == cp.back) break; 2186 } 2187 if (col != NULL) { 2188 return (col->pix); 2189 } 2190 col = (struct Colori*) malloc (sizeof (struct Colori)); 2191 col->color = cp.back; 2192 col->pix = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2193 col->next = colori; 2194 colori = col; 2195 2196 Draw3DBorder (col->pix, 0, 0, w, h, 1, cp, off, True, False); 2197 for (i = 3; i + 5 < h; i += 5) { 2198 Draw3DBorder (col->pix, 4, i, w - 8, 3, 1, Scr->MenuC, off, True, False); 2199 } 2200 return (colori->pix); 2201} 2202 2203#include "siconify.bm" 2204 2205Pixmap Create3DIconManagerIcon (ColorPair cp) 2206{ 2207 unsigned int w, h; 2208 struct Colori *col; 2209 static struct Colori *colori = NULL; 2210 2211 w = (unsigned int) siconify_width; 2212 h = (unsigned int) siconify_height; 2213 2214 for (col = colori; col; col = col->next) { 2215 if (col->color == cp.back) break; 2216 } 2217 if (col != NULL) { 2218 return (col->pix); 2219 } 2220 col = (struct Colori*) malloc (sizeof (struct Colori)); 2221 col->color = cp.back; 2222 col->pix = XCreatePixmap (dpy, Scr->Root, w, h, Scr->d_depth); 2223 Draw3DBorder (col->pix, 0, 0, w, h, 4, cp, off, True, False); 2224 col->next = colori; 2225 colori = col; 2226 2227 return (colori->pix); 2228} 2229 2230static Image *Create3DResizeAnimation (Bool in, Bool left, Bool top, 2231 ColorPair cp) 2232{ 2233 int h, i, j; 2234 Image *image, *im, *im1; 2235 2236 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2237 if (!(h & 1)) h--; 2238 2239 image = im1 = None; 2240 for (i = (in ? 0 : (h/4)-1); (i < h/4) && (i >= 0); i += (in ? 1 : -1)) { 2241 im = (Image*) malloc (sizeof (struct _Image)); 2242 if (! im) return (None); 2243 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2244 if (im->pixmap == None) { 2245 free (im); 2246 return (None); 2247 } 2248 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2249 for (j = i; j <= h; j += (h/4)){ 2250 Draw3DBorder (im->pixmap, (left ? 0 : j), (top ? 0 : j), 2251 h - j, h - j, 2, cp, off, True, False); 2252 } 2253 im->mask = None; 2254 im->width = h; 2255 im->height = h; 2256 im->next = None; 2257 if (image == None) { 2258 image = im1 = im; 2259 } 2260 else { 2261 im1->next = im; 2262 im1 = im; 2263 } 2264 } 2265 if (im1 != None) im1->next = image; 2266 return (image); 2267} 2268 2269static Image *Create3DResizeInTopAnimation (ColorPair cp) 2270{ 2271 return Create3DResizeAnimation (TRUE, FALSE, TRUE, cp); 2272} 2273 2274static Image *Create3DResizeOutTopAnimation (ColorPair cp) 2275{ 2276 return Create3DResizeAnimation (False, FALSE, TRUE, cp); 2277} 2278 2279static Image *Create3DResizeInBotAnimation (ColorPair cp) 2280{ 2281 return Create3DResizeAnimation (TRUE, TRUE, FALSE, cp); 2282} 2283 2284static Image *Create3DResizeOutBotAnimation (ColorPair cp) 2285{ 2286 return Create3DResizeAnimation (False, TRUE, FALSE, cp); 2287} 2288 2289static Image *Create3DMenuAnimation (Bool up, ColorPair cp) 2290{ 2291 int h, i, j; 2292 Image *image, *im, *im1; 2293 2294 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2295 if (!(h & 1)) h--; 2296 2297 image = im1 = None; 2298 for (j = (up ? 4 : 0); j != (up ? -1 : 5); j+= (up ? -1 : 1)) { 2299 im = (Image*) malloc (sizeof (struct _Image)); 2300 if (! im) return (None); 2301 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2302 if (im->pixmap == None) { 2303 free (im); 2304 return (None); 2305 } 2306 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2307 for (i = j; i < h - 3; i += 5) { 2308 Draw3DBorder (im->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False); 2309 } 2310 im->mask = None; 2311 im->width = h; 2312 im->height = h; 2313 im->next = None; 2314 if (image == None) { 2315 image = im1 = im; 2316 } 2317 else { 2318 im1->next = im; 2319 im1 = im; 2320 } 2321 } 2322 if (im1 != None) im1->next = image; 2323 return (image); 2324} 2325 2326static Image *Create3DMenuUpAnimation (ColorPair cp) 2327{ 2328 return Create3DMenuAnimation (TRUE, cp); 2329} 2330 2331static Image *Create3DMenuDownAnimation (ColorPair cp) 2332{ 2333 return Create3DMenuAnimation (False, cp); 2334} 2335 2336static Image *Create3DZoomAnimation (Bool in, Bool out, int n, ColorPair cp) 2337{ 2338 int h, i, j, k; 2339 Image *image, *im, *im1; 2340 2341 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2342 if (!(h & 1)) h--; 2343 2344 if (n == 0) n = (h/2) - 2; 2345 2346 image = im1 = None; 2347 for (j = (out ? -1 : 1) ; j < (in ? 2 : 0); j += 2){ 2348 for(k = (j > 0 ? 0 : n-1) ; (k >= 0) && (k < n); k += j){ 2349 im = (Image*) malloc (sizeof (struct _Image)); 2350 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2351 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2352 for (i = 2 + k; i < (h / 2); i += n) { 2353 Draw3DBorder (im->pixmap, i, i, h - (2 * i), h - (2 * i), 2, cp, off, True, False); 2354 } 2355 im->mask = None; 2356 im->width = h; 2357 im->height = h; 2358 im->next = None; 2359 if (image == None) { 2360 image = im1 = im; 2361 } 2362 else { 2363 im1->next = im; 2364 im1 = im; 2365 } 2366 } 2367 } 2368 if (im1 != None) im1->next = image; 2369 return (image); 2370} 2371 2372static Image *Create3DMazeInAnimation (ColorPair cp) 2373{ 2374 return Create3DZoomAnimation(TRUE, FALSE, 6, cp); 2375} 2376 2377static Image *Create3DMazeOutAnimation (ColorPair cp) 2378{ 2379 return Create3DZoomAnimation(FALSE, TRUE, 6, cp); 2380} 2381 2382static Image *Create3DZoomInAnimation (ColorPair cp) 2383{ 2384 return Create3DZoomAnimation(TRUE, FALSE, 0, cp); 2385} 2386 2387static Image *Create3DZoomOutAnimation (ColorPair cp) 2388{ 2389 return Create3DZoomAnimation(FALSE, TRUE, 0, cp); 2390} 2391 2392static Image *Create3DZoomInOutAnimation (ColorPair cp) 2393{ 2394 return Create3DZoomAnimation(TRUE, TRUE, 0, cp); 2395} 2396 2397#define questionmark_width 8 2398#define questionmark_height 8 2399static char questionmark_bits[] = { 2400 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18}; 2401 2402static Pixmap CreateQuestionPixmap (unsigned int *widthp, 2403 unsigned int *heightp) 2404{ 2405 *widthp = questionmark_width; 2406 *heightp = questionmark_height; 2407 if (Scr->tbpm.question == None) { 2408 Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root, 2409 questionmark_bits, 2410 questionmark_width, 2411 questionmark_height); 2412 } 2413 /* 2414 * this must succeed or else we are in deep trouble elsewhere 2415 */ 2416 return Scr->tbpm.question; 2417} 2418 2419 2420static Pixmap CreateMenuPixmap (unsigned int *widthp, unsigned int *heightp) 2421{ 2422 return (CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,widthp,heightp)); 2423} 2424 2425Pixmap CreateMenuIcon (int height, unsigned int *widthp, unsigned int *heightp) 2426{ 2427 int h, w; 2428 int ih, iw; 2429 int ix, iy; 2430 int mh, mw; 2431 int tw, th; 2432 int lw, lh; 2433 int lx, ly; 2434 int lines, dly; 2435 int offset; 2436 int bw; 2437 2438 h = height; 2439 w = h * 7 / 8; 2440 if (h < 1) 2441 h = 1; 2442 if (w < 1) 2443 w = 1; 2444 *widthp = w; 2445 *heightp = h; 2446 if (Scr->tbpm.menu == None) { 2447 Pixmap pix; 2448 GC gc; 2449 2450 pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1); 2451 gc = XCreateGC (dpy, pix, 0L, NULL); 2452 XSetForeground (dpy, gc, 0L); 2453 XFillRectangle (dpy, pix, gc, 0, 0, w, h); 2454 XSetForeground (dpy, gc, 1L); 2455 ix = 1; 2456 iy = 1; 2457 ih = h - iy * 2; 2458 iw = w - ix * 2; 2459 offset = ih / 8; 2460 mh = ih - offset; 2461 mw = iw - offset; 2462 bw = mh / 16; 2463 if (bw == 0 && mw > 2) 2464 bw = 1; 2465 tw = mw - bw * 2; 2466 th = mh - bw * 2; 2467 XFillRectangle (dpy, pix, gc, ix, iy, mw, mh); 2468 XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh); 2469 XSetForeground (dpy, gc, 0L); 2470 XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th); 2471 XSetForeground (dpy, gc, 1L); 2472 lw = tw / 2; 2473 if ((tw & 1) ^ (lw & 1)) 2474 lw++; 2475 lx = ix + bw + (tw - lw) / 2; 2476 2477 lh = th / 2 - bw; 2478 if ((lh & 1) ^ ((th - bw) & 1)) 2479 lh++; 2480 ly = iy + bw + (th - bw - lh) / 2; 2481 2482 lines = 3; 2483 if ((lh & 1) && lh < 6) 2484 { 2485 lines--; 2486 } 2487 dly = lh / (lines - 1); 2488 while (lines--) 2489 { 2490 XFillRectangle (dpy, pix, gc, lx, ly, lw, bw); 2491 ly += dly; 2492 } 2493 XFreeGC (dpy, gc); 2494 } 2495 return Scr->tbpm.menu; 2496} 2497 2498#define FBGC(gc, fix_fore, fix_back)\ 2499 Gcv.foreground = fix_fore;\ 2500 Gcv.background = fix_back;\ 2501 XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv) 2502 2503void Draw3DBorder (Window w, int x, int y, int width, int height, int bw, 2504 ColorPair cp, int state, int fill, int forcebw) 2505{ 2506 int i; 2507 XGCValues gcv; 2508 unsigned long gcm; 2509 2510 if ((width < 1) || (height < 1)) return; 2511 if (Scr->Monochrome != COLOR) { 2512 if (fill) { 2513 gcm = GCFillStyle; 2514 gcv.fill_style = FillOpaqueStippled; 2515 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2516 XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height); 2517 } 2518 gcm = 0; 2519 gcm |= GCLineStyle; 2520 gcv.line_style = (state == on) ? LineSolid : LineDoubleDash; 2521 gcm |= GCFillStyle; 2522 gcv.fill_style = FillSolid; 2523 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2524 for (i = 0; i < bw; i++) { 2525 XDrawLine (dpy, w, Scr->BorderGC, x, y + i, 2526 x + width - i - 1, y + i); 2527 XDrawLine (dpy, w, Scr->BorderGC, x + i, y, 2528 x + i, y + height - i - 1); 2529 } 2530 2531 gcm = 0; 2532 gcm |= GCLineStyle; 2533 gcv.line_style = (state == on) ? LineDoubleDash : LineSolid; 2534 gcm |= GCFillStyle; 2535 gcv.fill_style = FillSolid; 2536 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2537 for (i = 0; i < bw; i++) { 2538 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2539 x + width - i - 1, y + height - 1); 2540 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2541 x + width - 1, y + height - i - 1); 2542 } 2543 return; 2544 } 2545 2546 if (fill) { 2547 FBGC (Scr->BorderGC, cp.back, cp.fore); 2548 XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height); 2549 } 2550 if (Scr->BeNiceToColormap) { 2551 int dashoffset = 0; 2552 2553 gcm = 0; 2554 gcm |= GCLineStyle; 2555 gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash; 2556 gcm |= GCBackground; 2557 gcv.background = cp.back; 2558 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2559 2560 if (state == on) 2561 XSetForeground (dpy, Scr->BorderGC, Scr->Black); 2562 else 2563 XSetForeground (dpy, Scr->BorderGC, Scr->White); 2564 for (i = 0; i < bw; i++) { 2565 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + dashoffset, 2566 x + i, y + height - i - 1); 2567 XDrawLine (dpy, w, Scr->BorderGC, x + dashoffset, y + i, 2568 x + width - i - 1, y + i); 2569 dashoffset = 1 - dashoffset; 2570 } 2571 XSetForeground (dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black)); 2572 for (i = 0; i < bw; i++) { 2573 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2574 x + width - 1, y + height - i - 1); 2575 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2576 x + width - i - 1, y + height - 1); 2577 } 2578 return; 2579 } 2580 if (state == on) { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); } 2581 else { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); } 2582 for (i = 0; i < bw; i++) { 2583 XDrawLine (dpy, w, Scr->BorderGC, x, y + i, 2584 x + width - i - 1, y + i); 2585 XDrawLine (dpy, w, Scr->BorderGC, x + i, y, 2586 x + i, y + height - i - 1); 2587 } 2588 2589 if (state == on) { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); } 2590 else { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); } 2591 for (i = 0; i < bw; i++) { 2592 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2593 x + width - i - 1, y + height - 1); 2594 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2595 x + width - 1, y + height - i - 1); 2596 } 2597 return; 2598} 2599 2600void Draw3DCorner (Window w, 2601 int x, int y, int width, int height, int thick, int bw, 2602 ColorPair cp, int type) 2603{ 2604 XRectangle rects [2]; 2605 2606 switch (type) { 2607 case 0 : 2608 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2609 Draw3DBorder (w, x + thick - bw, y + thick - bw, 2610 width - thick + 2 * bw, height - thick + 2 * bw, 2611 bw, cp, on, True, False); 2612 break; 2613 case 1 : 2614 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2615 Draw3DBorder (w, x, y + thick - bw, 2616 width - thick + bw, height - thick, 2617 bw, cp, on, True, False); 2618 break; 2619 case 2 : 2620 rects [0].x = x + width - thick; 2621 rects [0].y = y; 2622 rects [0].width = thick; 2623 rects [0].height = height; 2624 rects [1].x = x; 2625 rects [1].y = y + width - thick; 2626 rects [1].width = width - thick; 2627 rects [1].height = thick; 2628 XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted); 2629 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2630 Draw3DBorder (w, x, y, 2631 width - thick + bw, height - thick + bw, 2632 bw, cp, on, True, False); 2633 XSetClipMask (dpy, Scr->BorderGC, None); 2634 break; 2635 case 3 : 2636 rects [0].x = x; 2637 rects [0].y = y; 2638 rects [0].width = thick; 2639 rects [0].height = height; 2640 rects [1].x = x + thick; 2641 rects [1].y = y + height - thick; 2642 rects [1].width = width - thick; 2643 rects [1].height = thick; 2644 XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted); 2645 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2646 Draw3DBorder (w, x + thick - bw, y, 2647 width - thick, height - thick + bw, 2648 bw, cp, on, True, False); 2649 XSetClipMask (dpy, Scr->BorderGC, None); 2650 break; 2651 } 2652 return; 2653} 2654 2655void PaintAllDecoration (void) 2656{ 2657 TwmWindow *tmp_win; 2658 virtualScreen *vs; 2659 2660 for (tmp_win = Scr->FirstWindow; tmp_win != NULL; tmp_win = tmp_win->next) { 2661 if (! visible (tmp_win)) continue; 2662 if (tmp_win->mapped == TRUE) { 2663 if (tmp_win->frame_bw3D) { 2664 if (tmp_win->highlight && tmp_win == Scr->Focus) 2665 PaintBorders (tmp_win, True); 2666 else 2667 PaintBorders (tmp_win, False); 2668 } 2669 if (tmp_win->title_w) PaintTitle (tmp_win); 2670 if (tmp_win->titlebuttons) PaintTitleButtons (tmp_win); 2671 } 2672 else 2673 if ((tmp_win->icon_on == TRUE) && 2674 !tmp_win->icon_not_ours && 2675 !Scr->NoIconTitlebar && 2676 tmp_win->icon && 2677 tmp_win->icon->w && 2678 ! LookInList (Scr->NoIconTitle, tmp_win->full_name, &tmp_win->class)) { 2679 PaintIcon (tmp_win); 2680 } 2681 } 2682 for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) { 2683 PaintWorkSpaceManager (vs); 2684 } 2685} 2686 2687void PaintBorders (TwmWindow *tmp_win, Bool focus) 2688{ 2689 ColorPair cp; 2690 2691 cp = (focus && tmp_win->highlight) ? tmp_win->borderC : tmp_win->border_tile; 2692 if (tmp_win->title_height == 0) { 2693 Draw3DBorder (tmp_win->frame, 2694 0, 2695 0, 2696 tmp_win->frame_width, 2697 tmp_win->frame_height, 2698 Scr->BorderShadowDepth, cp, off, True, False); 2699 Draw3DBorder (tmp_win->frame, 2700 tmp_win->frame_bw3D - Scr->BorderShadowDepth, 2701 tmp_win->frame_bw3D - Scr->BorderShadowDepth, 2702 tmp_win->frame_width - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth, 2703 tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth, 2704 Scr->BorderShadowDepth, cp, on, True, False); 2705 return; 2706 } 2707 Draw3DCorner (tmp_win->frame, 2708 tmp_win->title_x - tmp_win->frame_bw3D, 2709 0, 2710 Scr->TitleHeight + tmp_win->frame_bw3D, 2711 Scr->TitleHeight + tmp_win->frame_bw3D, 2712 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 0); 2713 Draw3DCorner (tmp_win->frame, 2714 tmp_win->title_x + tmp_win->title_width - Scr->TitleHeight, 2715 0, 2716 Scr->TitleHeight + tmp_win->frame_bw3D, 2717 Scr->TitleHeight + tmp_win->frame_bw3D, 2718 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 1); 2719 Draw3DCorner (tmp_win->frame, 2720 tmp_win->frame_width - (Scr->TitleHeight + tmp_win->frame_bw3D), 2721 tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D), 2722 Scr->TitleHeight + tmp_win->frame_bw3D, 2723 Scr->TitleHeight + tmp_win->frame_bw3D, 2724 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 2); 2725 Draw3DCorner (tmp_win->frame, 2726 0, 2727 tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D), 2728 Scr->TitleHeight + tmp_win->frame_bw3D, 2729 Scr->TitleHeight + tmp_win->frame_bw3D, 2730 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 3); 2731 2732 Draw3DBorder (tmp_win->frame, 2733 tmp_win->title_x + Scr->TitleHeight, 2734 0, 2735 tmp_win->title_width - 2 * Scr->TitleHeight, 2736 tmp_win->frame_bw3D, 2737 Scr->BorderShadowDepth, cp, off, True, False); 2738 Draw3DBorder (tmp_win->frame, 2739 tmp_win->frame_bw3D + Scr->TitleHeight, 2740 tmp_win->frame_height - tmp_win->frame_bw3D, 2741 tmp_win->frame_width - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2742 tmp_win->frame_bw3D, 2743 Scr->BorderShadowDepth, cp, off, True, False); 2744 Draw3DBorder (tmp_win->frame, 2745 0, 2746 Scr->TitleHeight + tmp_win->frame_bw3D, 2747 tmp_win->frame_bw3D, 2748 tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2749 Scr->BorderShadowDepth, cp, off, True, False); 2750 Draw3DBorder (tmp_win->frame, 2751 tmp_win->frame_width - tmp_win->frame_bw3D, 2752 Scr->TitleHeight + tmp_win->frame_bw3D, 2753 tmp_win->frame_bw3D, 2754 tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2755 Scr->BorderShadowDepth, cp, off, True, False); 2756 2757 if (tmp_win->squeeze_info && !tmp_win->squeezed) { 2758 Draw3DBorder (tmp_win->frame, 2759 0, 2760 Scr->TitleHeight, 2761 tmp_win->title_x, 2762 tmp_win->frame_bw3D, 2763 Scr->BorderShadowDepth, cp, off, True, False); 2764 Draw3DBorder (tmp_win->frame, 2765 tmp_win->title_x + tmp_win->title_width, 2766 Scr->TitleHeight, 2767 tmp_win->frame_width - tmp_win->title_x - tmp_win->title_width, 2768 tmp_win->frame_bw3D, 2769 Scr->BorderShadowDepth, cp, off, True, False); 2770 } 2771} 2772 2773void PaintTitle (TwmWindow *tmp_win) 2774{ 2775 int width, mwidth, len; 2776 XRectangle inc_rect; 2777 XRectangle logical_rect; 2778 2779 if (Scr->use3Dtitles) { 2780 if (Scr->SunkFocusWindowTitle && (Scr->Focus == tmp_win) && 2781 (tmp_win->title_height != 0)) 2782 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 2783 tmp_win->title_width - Scr->TBInfo.titlex - 2784 Scr->TBInfo.rightoff - Scr->TitlePadding, 2785 Scr->TitleHeight, Scr->TitleShadowDepth, 2786 tmp_win->title, on, True, False); 2787 else 2788 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 2789 tmp_win->title_width - Scr->TBInfo.titlex - 2790 Scr->TBInfo.rightoff - Scr->TitlePadding, 2791 Scr->TitleHeight, Scr->TitleShadowDepth, 2792 tmp_win->title, off, True, False); 2793 } 2794 FB(tmp_win->title.fore, tmp_win->title.back); 2795 if (Scr->use3Dtitles) { 2796 len = strlen(tmp_win->name); 2797 XmbTextExtents(Scr->TitleBarFont.font_set, 2798 tmp_win->name, strlen (tmp_win->name), 2799 &inc_rect, &logical_rect); 2800 width = logical_rect.width; 2801 mwidth = tmp_win->title_width - Scr->TBInfo.titlex - 2802 Scr->TBInfo.rightoff - Scr->TitlePadding - 2803 Scr->TitleShadowDepth - 4; 2804 while ((len > 0) && (width > mwidth)) { 2805 len--; 2806 XmbTextExtents(Scr->TitleBarFont.font_set, 2807 tmp_win->name, len, 2808 &inc_rect, &logical_rect); 2809 width = logical_rect.width; 2810 } 2811 if (Scr->Monochrome != COLOR) { 2812 XmbDrawImageString(dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2813 Scr->NormalGC, 2814 tmp_win->name_x, 2815 Scr->TitleBarFont.y + Scr->TitleShadowDepth, 2816 tmp_win->name, len); 2817 } 2818 else { 2819 XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2820 Scr->NormalGC, tmp_win->name_x, 2821 Scr->TitleBarFont.y + Scr->TitleShadowDepth, 2822 tmp_win->name, len); 2823 } 2824 } 2825 else 2826 XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2827 Scr->NormalGC, 2828 tmp_win->name_x, Scr->TitleBarFont.y, 2829 tmp_win->name, strlen(tmp_win->name)); 2830} 2831 2832void PaintIcon (TwmWindow *tmp_win) 2833{ 2834 int width, twidth, mwidth, len, x; 2835 Icon *icon; 2836 XRectangle inc_rect; 2837 XRectangle logical_rect; 2838 2839 if (!tmp_win || !tmp_win->icon) return; 2840 icon = tmp_win->icon; 2841 if (!icon->has_title) return; 2842 2843 x = 0; 2844 width = icon->w_width; 2845 if (Scr->ShrinkIconTitles && icon->title_shrunk) { 2846 x = GetIconOffset (icon); 2847 width = icon->width; 2848 } 2849 len = strlen (tmp_win->icon_name); 2850 XmbTextExtents(Scr->IconFont.font_set, 2851 tmp_win->icon_name, len, 2852 &inc_rect, &logical_rect); 2853 twidth = logical_rect.width; 2854 mwidth = width - 2 * Scr->IconManagerShadowDepth - 6; 2855 if (Scr->use3Diconmanagers) { 2856 Draw3DBorder (icon->w, x, icon->height, width, 2857 Scr->IconFont.height + 2 * Scr->IconManagerShadowDepth + 6, 2858 Scr->IconManagerShadowDepth, icon->iconc, off, False, False); 2859 } 2860 while ((len > 0) && (twidth > mwidth)) { 2861 len--; 2862 XmbTextExtents(Scr->IconFont.font_set, 2863 tmp_win->icon_name, len, 2864 &inc_rect, &logical_rect); 2865 twidth = logical_rect.width; 2866 } 2867 FB (icon->iconc.fore, icon->iconc.back); 2868 XmbDrawString(dpy, icon->w, Scr->IconFont.font_set, Scr->NormalGC, 2869 x + ((mwidth - twidth)/2) + Scr->IconManagerShadowDepth + 3, 2870 icon->y, tmp_win->icon_name, len); 2871} 2872 2873void PaintTitleButton (TwmWindow *tmp_win, TBWindow *tbw) 2874{ 2875 TitleButton *tb = tbw->info; 2876 2877 XCopyArea (dpy, tbw->image->pixmap, tbw->window, Scr->NormalGC, 2878 tb->srcx, tb->srcy, tb->width, tb->height, 2879 tb->dstx, tb->dsty); 2880 return; 2881} 2882 2883void PaintTitleButtons (TwmWindow *tmp_win) 2884{ 2885 int i; 2886 TBWindow *tbw = tmp_win->titlebuttons; 2887 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 2888 2889 if (tbw == NULL) 2890 return; 2891 2892 for (i = 0; i < nb; i++, tbw++) { 2893 PaintTitleButton (tmp_win, tbw); 2894 } 2895} 2896 2897void adoptWindow (void) 2898{ 2899 unsigned long data [2]; 2900 Window localroot, w; 2901 unsigned char *prop; 2902 unsigned long bytesafter; 2903 unsigned long len; 2904 Atom actual_type; 2905 int actual_format; 2906 XEvent event; 2907 Window root, parent, child, *children; 2908 unsigned int nchildren, key_buttons; 2909 int root_x, root_y, win_x, win_y; 2910 int ret; 2911 2912 localroot = w = RootWindow (dpy, Scr->screen); 2913 XGrabPointer (dpy, localroot, False, 2914 ButtonPressMask | ButtonReleaseMask, 2915 GrabModeAsync, GrabModeAsync, 2916 None, Scr->SelectCursor, CurrentTime); 2917 2918 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2919 child = event.xbutton.subwindow; 2920 while (1) { 2921 if (child == (Window) 0) break; 2922 2923 w = XmuClientWindow (dpy, child); 2924 ret = XGetWindowProperty (dpy, w, _XA_WM_WORKSPACESLIST, 0L, 512, 2925 False, XA_STRING, &actual_type, &actual_format, &len, 2926 &bytesafter, &prop); 2927 XFree ((char *)prop); /* Don't ever do anything with it */ 2928 if (ret != Success) 2929 break; 2930 if (len == 0) /* it is not a local root window */ 2931 break; /* it is not a local root window */ 2932 localroot = w; 2933 XQueryPointer (dpy, localroot, &root, &child, &root_x, &root_y, 2934 &win_x, &win_y, &key_buttons); 2935 } 2936 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2937 XUngrabPointer (dpy, CurrentTime); 2938 2939 if (localroot == Scr->Root) return; 2940 if (w == localroot) { /* try to not adopt an ancestor */ 2941 XQueryTree (dpy, Scr->Root, &root, &parent, &children, &nchildren); 2942 while (parent != (Window) 0) { 2943 XFree ((char *) children); 2944 if (w == parent) return; 2945 XQueryTree (dpy, parent, &root, &parent, &children, &nchildren); 2946 } 2947 XFree ((char *) children); 2948 if (w == root) return; 2949 } 2950 if (localroot == RootWindow (dpy, Scr->screen)) { 2951 XWithdrawWindow (dpy, w, Scr->screen); 2952 } 2953 else { 2954 XUnmapWindow (dpy, w); 2955 } 2956 XReparentWindow (dpy, w, Scr->Root, 0, 0); 2957 2958 data [0] = (unsigned long) NormalState; 2959 data [1] = (unsigned long) None; 2960 2961 XChangeProperty (dpy, w, _XA_WM_STATE, _XA_WM_STATE, 32, 2962 PropModeReplace, (unsigned char *) data, 2); 2963 XFlush (dpy); 2964 SimulateMapRequest (w); 2965 return; 2966} 2967 2968void DebugTrace (char *file) 2969{ 2970 if (!file) return; 2971 if (tracefile) { 2972 fprintf (stderr, "stop logging events\n"); 2973 if (tracefile != stderr) fclose (tracefile); 2974 tracefile = NULL; 2975 } 2976 else { 2977 if (strcmp (file, "stderr")) 2978 tracefile = fopen (file, "w"); 2979 else 2980 tracefile = stderr; 2981 fprintf (stderr, "logging events to : %s\n", file); 2982 } 2983} 2984 2985extern Cursor TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor, 2986 LeftCursor, RightCursor, TopCursor, BottomCursor; 2987 2988void SetBorderCursor (TwmWindow *tmp_win, int x, int y) 2989{ 2990 Cursor cursor; 2991 XSetWindowAttributes attr; 2992 int h, fw, fh, wd; 2993 2994 if (!tmp_win) 2995 return; 2996 2997 /* Use the max of these, but since one is always 0 we can add them. */ 2998 wd = tmp_win->frame_bw + tmp_win->frame_bw3D; 2999 h = Scr->TitleHeight + wd; 3000 fw = tmp_win->frame_width; 3001 fh = tmp_win->frame_height; 3002 3003#if defined DEBUG && DEBUG 3004 fprintf(stderr, "wd=%d h=%d, fw=%d fh=%d x=%d y=%d\n", 3005 wd, h, fw, fh, x, y); 3006#endif 3007 3008 /* 3009 * If not using 3D borders: 3010 * 3011 * The left border has negative x coordinates, 3012 * The top border (above the title) has negative y coordinates. 3013 * The title is TitleHeight high, the next wd pixels are border. 3014 * The bottom border has coordinates >= the frame height. 3015 * The right border has coordinates >= the frame width. 3016 * 3017 * If using 3D borders: all coordinates are >= 0, and all coordinates 3018 * are higher by the border width. 3019 * 3020 * Since we only get events when we're actually in the border, we simply 3021 * allow for both cases at the same time. 3022 */ 3023 3024 if ((x < -wd) || (y < -wd)) { 3025 cursor = Scr->FrameCursor; 3026 } else if (x < h) { 3027 if (y < h) 3028 cursor = TopLeftCursor; 3029 else if (y >= fh - h) 3030 cursor = BottomLeftCursor; 3031 else 3032 cursor = LeftCursor; 3033 } else if (x >= fw - h) { 3034 if (y < h) 3035 cursor = TopRightCursor; 3036 else if (y >= fh - h) 3037 cursor = BottomRightCursor; 3038 else 3039 cursor = RightCursor; 3040 } else if (y < h) { /* also include title bar in top border area */ 3041 cursor = TopCursor; 3042 } else if (y >= fh - h) { 3043 cursor = BottomCursor; 3044 } else { 3045 cursor = Scr->FrameCursor; 3046 } 3047 attr.cursor = cursor; 3048 XChangeWindowAttributes (dpy, tmp_win->frame, CWCursor, &attr); 3049 tmp_win->curcurs = cursor; 3050} 3051 3052Image *GetImage (char *name, ColorPair cp) 3053{ 3054 name_list **list; 3055 char fullname [256]; 3056 Image *image; 3057 3058 if (name == NULL) return (None); 3059 image = None; 3060 3061 list = &Scr->ImageCache; 3062#ifdef XPM 3063 if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) { 3064 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3065 3066 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3067 int startn = (name [0] == '@') ? 1 : 4; 3068 if ((image = GetXpmImage (name + startn, cp)) != None) { 3069 AddToList (list, fullname, (char*) image); 3070 } 3071 } 3072 } 3073 else 3074#endif 3075#ifdef JPEG 3076 if (strncmp (name, "jpeg:", 5) == 0) { 3077 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3078 if ((image = GetJpegImage (&name [5])) != None) { 3079 AddToList (list, name, (char*) image); 3080 } 3081 } 3082 } 3083 else 3084#endif 3085#ifdef IMCONV 3086 if (strncmp (name, "im:", 3) == 0) { 3087 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3088 if ((image = GetImconvImage (&name [3])) != None) { 3089 AddToList (list, name, (char*) image); 3090 } 3091 } 3092 } 3093 else 3094#endif 3095#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3096 if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) { 3097 int startn = (name [0] == '|') ? 0 : 4; 3098 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3099 if ((image = GetXwdImage (&name [startn], cp)) != None) { 3100 AddToList (list, name, (char*) image); 3101 } 3102 } 3103 } 3104 else 3105#endif 3106 if (strncmp (name, ":xpm:", 5) == 0) { 3107 int i; 3108 static struct { 3109 char *name; 3110 Image* (*proc)(ColorPair colorpair); 3111 } pmtab[] = { 3112 { TBPM_3DDOT, Create3DDotImage }, 3113 { TBPM_3DRESIZE, Create3DResizeImage }, 3114 { TBPM_3DMENU, Create3DMenuImage }, 3115 { TBPM_3DZOOM, Create3DZoomImage }, 3116 { TBPM_3DBAR, Create3DBarImage }, 3117 { TBPM_3DVBAR, Create3DVertBarImage }, 3118 { TBPM_3DCROSS, Create3DCrossImage }, 3119 { TBPM_3DICONIFY, Create3DIconifyImage }, 3120 { TBPM_3DSUNKEN_RESIZE, Create3DSunkenResizeImage }, 3121 { TBPM_3DBOX, Create3DBoxImage } 3122 }; 3123 3124 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3125 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3126 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3127 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3128 image = (*pmtab[i].proc) (cp); 3129 if (image == None) { 3130 fprintf (stderr, 3131 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3132 return (None); 3133 } 3134 break; 3135 } 3136 } 3137 if (image == None) { 3138 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3139 return (None); 3140 } 3141 AddToList (list, fullname, (char*) image); 3142 } 3143 } 3144 else 3145 if (strncmp (name, "%xpm:", 5) == 0) { 3146 int i; 3147 static struct { 3148 char *name; 3149 Image* (*proc)(ColorPair colorpair); 3150 } pmtab[] = { 3151 { "%xpm:menu-up", Create3DMenuUpAnimation }, 3152 { "%xpm:menu-down", Create3DMenuDownAnimation }, 3153 { "%xpm:resize", Create3DZoomOutAnimation }, /* compatibility */ 3154 { "%xpm:resize-out-top", Create3DResizeInTopAnimation }, 3155 { "%xpm:resize-in-top", Create3DResizeOutTopAnimation }, 3156 { "%xpm:resize-out-bot", Create3DResizeInBotAnimation }, 3157 { "%xpm:resize-in-bot", Create3DResizeOutBotAnimation }, 3158 { "%xpm:maze-out", Create3DMazeOutAnimation }, 3159 { "%xpm:maze-in", Create3DMazeInAnimation }, 3160 { "%xpm:zoom-out", Create3DZoomOutAnimation }, 3161 { "%xpm:zoom-in", Create3DZoomInAnimation }, 3162 { "%xpm:zoom-inout", Create3DZoomInOutAnimation } 3163 }; 3164 3165 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3166 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3167 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3168 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3169 image = (*pmtab[i].proc) (cp); 3170 if (image == None) { 3171 fprintf (stderr, 3172 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3173 return (None); 3174 } 3175 break; 3176 } 3177 } 3178 if (image == None) { 3179 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3180 return (None); 3181 } 3182 AddToList (list, fullname, (char*) image); 3183 } 3184 } 3185 else 3186 if (name [0] == ':') { 3187 int i; 3188 unsigned int width, height; 3189 Pixmap pm = 0; 3190 XGCValues gcvalues; 3191 static struct { 3192 char *name; 3193 Pixmap (*proc)(unsigned int *widthp, unsigned int *heightp); 3194 } pmtab[] = { 3195 { TBPM_DOT, CreateDotPixmap }, 3196 { TBPM_ICONIFY, CreateDotPixmap }, 3197 { TBPM_RESIZE, CreateResizePixmap }, 3198 { TBPM_XLOGO, CreateXLogoPixmap }, 3199 { TBPM_DELETE, CreateXLogoPixmap }, 3200 { TBPM_MENU, CreateMenuPixmap }, 3201 { TBPM_QUESTION, CreateQuestionPixmap }, 3202 }; 3203 3204 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3205 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3206 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3207 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3208 pm = (*pmtab[i].proc) (&width, &height); 3209 if (pm == None) { 3210 fprintf (stderr, 3211 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3212 return (None); 3213 } 3214 break; 3215 } 3216 } 3217 if (pm == None) { 3218 fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", ProgramName, name); 3219 return (None); 3220 } 3221 image = (Image*) malloc (sizeof (struct _Image)); 3222 image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 3223 if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues); 3224 gcvalues.background = cp.back; 3225 gcvalues.foreground = cp.fore; 3226 XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues); 3227 XCopyPlane (dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0, 3228 (unsigned long) 1); 3229 image->mask = None; 3230 image->width = width; 3231 image->height = height; 3232 image->next = None; 3233 AddToList (list, fullname, (char*) image); 3234 } 3235 } 3236 else { 3237 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3238 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3239 if ((image = GetBitmapImage (name, cp)) != None) { 3240 AddToList (list, fullname, (char*) image); 3241 } 3242 } 3243 } 3244 return (image); 3245} 3246 3247void FreeImage (Image *image) 3248{ 3249 Image *im, *im2; 3250 3251 im = image; 3252 while (im != None) { 3253 if (im->pixmap) XFreePixmap (dpy, im->pixmap); 3254 if (im->mask) XFreePixmap (dpy, im->mask); 3255 im2 = im->next; 3256 free (im); 3257 im = im2; 3258 } 3259} 3260 3261#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3262static void compress (XImage *image, XColor *colors, int *ncolors); 3263 3264static Image *LoadXwdImage (char *filename, ColorPair cp) 3265{ 3266 FILE *file; 3267 char *fullname; 3268 XColor colors [256]; 3269 XWDColor xwdcolors [256]; 3270 unsigned buffer_size; 3271 XImage *image; 3272 unsigned char *imagedata; 3273 Pixmap pixret; 3274 Visual *visual; 3275 char win_name [256]; 3276 int win_name_size; 3277 int ispipe; 3278 int i, len; 3279 int w, h, depth, ncolors; 3280 int scrn; 3281 Colormap cmap; 3282 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3283 GC gc; 3284 XGCValues gcvalues; 3285 XWDFileHeader header; 3286 Image *ret; 3287 Bool anim; 3288 unsigned long swaptest = 1; 3289 3290 ispipe = 0; 3291 anim = False; 3292#ifndef VMS 3293 if (filename [0] == '|') { 3294 file = (FILE*) popen (filename + 1, "r"); 3295 if (file == NULL) return (None); 3296 ispipe = 1; 3297 anim = AnimationActive; 3298 if (anim) StopAnimation (); 3299 goto file_opened; 3300 } 3301#endif 3302 fullname = ExpandPixmapPath (filename); 3303 if (! fullname) return (None); 3304 file = fopen (fullname, "r"); 3305 free (fullname); 3306 if (file == NULL) { 3307 if (reportfilenotfound) fprintf (stderr, "unable to locate %s\n", filename); 3308 return (None); 3309 } 3310file_opened: 3311 len = fread ((char *) &header, sizeof (header), 1, file); 3312 if (len != 1) { 3313 fprintf (stderr, "ctwm: cannot read %s\n", filename); 3314#ifdef USE_SIGNALS 3315 if (ispipe && anim) StartAnimation (); 3316#endif 3317 return (None); 3318 } 3319 if (*(char *) &swaptest) _swaplong ((char *) &header, sizeof (header)); 3320 if (header.file_version != XWD_FILE_VERSION) { 3321 fprintf(stderr,"ctwm: XWD file format version mismatch : %s\n", filename); 3322 return (None); 3323 } 3324 win_name_size = header.header_size - sizeof (header); 3325 len = fread (win_name, win_name_size, 1, file); 3326 if (len != 1) { 3327 fprintf (stderr, "file %s has not the correct format\n", filename); 3328#ifdef USE_SIGNALS 3329 if (ispipe && anim) StartAnimation (); 3330#endif 3331 return (None); 3332 } 3333 3334 if (header.pixmap_format == XYPixmap) { 3335 fprintf (stderr,"ctwm: XYPixmap XWD file not supported : %s\n", filename); 3336 return (None); 3337 } 3338 w = header.pixmap_width; 3339 h = header.pixmap_height; 3340 depth = header.pixmap_depth; 3341 ncolors = header.ncolors; 3342 len = fread ((char *) xwdcolors, sizeof (XWDColor), ncolors, file); 3343 if (len != ncolors) { 3344 fprintf (stderr, "file %s has not the correct format\n", filename); 3345#ifdef USE_SIGNALS 3346 if (ispipe && anim) StartAnimation (); 3347#endif 3348 return (None); 3349 } 3350 if (*(char *) &swaptest) { 3351 for (i = 0; i < ncolors; i++) { 3352 _swaplong ((char *) &xwdcolors [i].pixel, 4); 3353 _swapshort ((char *) &xwdcolors [i].red, 3 * 2); 3354 } 3355 } 3356 for (i = 0; i < ncolors; i++) { 3357 colors [i].pixel = xwdcolors [i].pixel; 3358 colors [i].red = xwdcolors [i].red; 3359 colors [i].green = xwdcolors [i].green; 3360 colors [i].blue = xwdcolors [i].blue; 3361 colors [i].flags = xwdcolors [i].flags; 3362 colors [i].pad = xwdcolors [i].pad; 3363 } 3364 3365 scrn = Scr->screen; 3366 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3367 visual = Scr->d_visual; 3368 gc = DefaultGC (dpy, scrn); 3369 3370 buffer_size = header.bytes_per_line * h; 3371 imagedata = (unsigned char*) malloc (buffer_size); 3372 if (! imagedata) { 3373 fprintf (stderr, "cannot allocate memory for image %s\n", filename); 3374#ifdef USE_SIGNALS 3375 if (ispipe && anim) StartAnimation (); 3376#endif 3377 return (None); 3378 } 3379 len = fread (imagedata, (int) buffer_size, 1, file); 3380 if (len != 1) { 3381 free (imagedata); 3382 fprintf (stderr, "file %s has not the correct format\n", filename); 3383#ifdef USE_SIGNALS 3384 if (ispipe && anim) StartAnimation (); 3385#endif 3386 return (None); 3387 } 3388#ifndef VMS 3389 if (ispipe) 3390 pclose (file); 3391 else 3392#endif 3393 fclose (file); 3394 3395 image = XCreateImage (dpy, visual, depth, header.pixmap_format, 3396 0, (char*) imagedata, w, h, 3397 header.bitmap_pad, header.bytes_per_line); 3398 if (image == None) { 3399 free (imagedata); 3400 fprintf (stderr, "cannot create image for %s\n", filename); 3401#ifdef USE_SIGNALS 3402 if (ispipe && anim) StartAnimation (); 3403#endif 3404 return (None); 3405 } 3406 if (header.pixmap_format == ZPixmap) { 3407 compress (image, colors, &ncolors); 3408 } 3409 if (header.pixmap_format != XYBitmap) { 3410 for (i = 0; i < ncolors; i++) { 3411 XAllocColor (dpy, cmap, &(colors [i])); 3412 } 3413 for (i = 0; i < buffer_size; i++) { 3414 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3415 } 3416 } 3417 if (w > Scr->rootw) w = Scr->rootw; 3418 if (h > Scr->rooth) h = Scr->rooth; 3419 3420 ret = (Image*) malloc (sizeof (struct _Image)); 3421 if (! ret) { 3422 fprintf (stderr, "unable to allocate memory for image : %s\n", filename); 3423 free (image); 3424 free (imagedata); 3425 for (i = 0; i < ncolors; i++) { 3426 XFreeColors (dpy, cmap, &(colors [i].pixel), 1, 0L); 3427 } 3428#ifdef USE_SIGNALS 3429 if (ispipe && anim) StartAnimation (); 3430#endif 3431 return (None); 3432 } 3433 if (header.pixmap_format == XYBitmap) { 3434 gcvalues.foreground = cp.fore; 3435 gcvalues.background = cp.back; 3436 XChangeGC (dpy, gc, GCForeground | GCBackground, &gcvalues); 3437 } 3438 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3439 int x, y; 3440 3441 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, 3442 Scr->rooth, Scr->d_depth); 3443 x = (Scr->rootw - w) / 2; 3444 y = (Scr->rooth - h) / 2; 3445 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3446 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3447 ret->width = Scr->rootw; 3448 ret->height = Scr->rooth; 3449 } 3450 else { 3451 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3452 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3453 ret->width = w; 3454 ret->height = h; 3455 } 3456 XDestroyImage (image); 3457 3458 ret->pixmap = pixret; 3459 ret->mask = None; 3460 ret->next = None; 3461#ifdef USE_SIGNALS 3462 if (ispipe && anim) StartAnimation (); 3463#endif 3464 return (ret); 3465} 3466 3467static Image *GetXwdImage (char *name, ColorPair cp) 3468{ 3469 Image *image, *r, *s; 3470 char path [128]; 3471 char pref [128], *perc; 3472 int i; 3473 3474 if (! strchr (name, '%')) return (LoadXwdImage (name, cp)); 3475 s = image = None; 3476 strcpy (pref, name); 3477 perc = strchr (pref, '%'); 3478 *perc = '\0'; 3479 reportfilenotfound = 0; 3480 for (i = 1;; i++) { 3481 sprintf (path, "%s%d%s", pref, i, perc + 1); 3482 r = LoadXwdImage (path, cp); 3483 if (r == None) break; 3484 r->next = None; 3485 if (image == None) s = image = r; 3486 else { 3487 s->next = r; 3488 s = r; 3489 } 3490 } 3491 reportfilenotfound = 1; 3492 if (s != None) s->next = image; 3493 if (image == None) { 3494 fprintf (stderr, "Cannot open any %s xwd file\n", name); 3495 } 3496 return (image); 3497} 3498 3499static void compress (XImage *image, XColor *colors, int *ncolors) 3500{ 3501 unsigned char ind [256]; 3502 unsigned int used [256]; 3503 int i, j, size, nused; 3504 unsigned char color; 3505 XColor newcolors [256]; 3506 unsigned char *imagedata; 3507 3508 for (i = 0; i < 256; i++) { 3509 used [i] = 0; 3510 ind [i] = 0; 3511 } 3512 nused = 0; 3513 size = image->bytes_per_line * image->height; 3514 imagedata = (unsigned char *) image->data; 3515 for (i = 0; i < size; i++) { 3516 if ((i % image->bytes_per_line) > image->width) continue; 3517 color = imagedata [i]; 3518 if (used [color] == 0) { 3519 for (j = 0; j < nused; j++) { 3520 if ((colors [color].red == newcolors [j].red) && 3521 (colors [color].green == newcolors [j].green) && 3522 (colors [color].blue == newcolors [j].blue)) break; 3523 } 3524 ind [color] = j; 3525 used [color] = 1; 3526 if (j == nused) { 3527 newcolors [j].red = colors [color].red; 3528 newcolors [j].green = colors [color].green; 3529 newcolors [j].blue = colors [color].blue; 3530 nused++; 3531 } 3532 } 3533 } 3534 for (i = 0; i < size; i++) { 3535 imagedata [i] = ind [imagedata [i]]; 3536 } 3537 for (i = 0; i < nused; i++) { 3538 colors [i] = newcolors [i]; 3539 } 3540 *ncolors = nused; 3541} 3542#endif 3543 3544#ifdef IMCONV 3545 3546static void free_images (); 3547 3548static Image *GetImconvImage (char *filename, 3549 unsigned int *widthp, unsigned int *heightp) 3550{ 3551 TagTable *toolInTable; 3552 ImVfb *sourceVfb; 3553 ImVfbPtr vptr; 3554 ImClt *clt; 3555 int i, j, ij, k, retval; 3556 3557 XColor colors [256]; 3558 unsigned buffer_size; 3559 XImage *image; 3560 unsigned char *imagedata; 3561 Pixmap pixret; 3562 Visual *visual; 3563 int w, h, depth, ncolors; 3564 int scrn; 3565 Colormap cmap; 3566 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3567 GC gc; 3568 unsigned char red, green, blue; 3569 int icol; 3570 char *fullname; 3571 3572 TagEntry *dataEntry; 3573 FILE *fp; 3574 char the_format[1024]; 3575 char *tmp_format; 3576 Image *ret; 3577 3578 if (*filename == NULL) return (None); 3579 fullname = ExpandPixmapPath (filename); 3580 if (! fullname) return (None); 3581 3582 fp = fopen (fullname, "r"); 3583 if (!fp) { 3584 if (reportfilenotfound) fprintf (stderr, "Cannot open the image %s\n", filename); 3585 free (fullname); 3586 return (None); 3587 } 3588 if ((toolInTable = TagTableAlloc ()) == TAGTABLENULL ) { 3589 fprintf (stderr, "TagTableAlloc failed\n"); 3590 free_images (toolInTable); 3591 free (fullname); 3592 return (None); 3593 } 3594 if ((tmp_format = ImFileQFFormat (fp, fullname)) == NULL) { 3595 fprintf (stderr, "Cannot determine image type of %s\n", filename); 3596 free_images (toolInTable); 3597 free (fullname); 3598 return (None); 3599 } 3600 strcpy (the_format, tmp_format); 3601 retval = ImFileFRead (fp, the_format, NULL, toolInTable); 3602 if(retval < 0) { 3603 fprintf(stderr, "Cannot read image file %s: ", fullname); 3604 switch(ImErrNo) { 3605 case IMESYS: 3606 fprintf (stderr, "System call error\n"); 3607 break; 3608 case IMEMALLOC: 3609 fprintf (stderr, "Cannot allocate memory\n"); 3610 break; 3611 case IMEFORMAT: 3612 fprintf (stderr, "Data in file is corrupt\n"); 3613 break; 3614 case IMENOREAD: 3615 fprintf (stderr, "Sorry, this format is write-only\n"); 3616 break; 3617 case IMEMAGIC: 3618 fprintf (stderr, "Bad magic number in image file\n"); 3619 break; 3620 case IMEDEPTH: 3621 fprintf (stderr, "Unknown image depth\n"); 3622 break; 3623 default: 3624 fprintf(stderr, "Unknown error\n"); 3625 break; 3626 } 3627 free_images (toolInTable); 3628 free (fullname); 3629 return (None); 3630 } 3631 3632 if (TagTableQNEntry (toolInTable, "image vfb") == 0) { 3633 fprintf (stderr, "Image file %s contains no images\n", fullname); 3634 free_images (toolInTable); 3635 free (fullname); 3636 return (None); 3637 } 3638 dataEntry = TagTableQDirect (toolInTable, "image vfb", 0); 3639 TagEntryQValue (dataEntry, &sourceVfb); 3640 fclose (fp); 3641 3642 w = ImVfbQWidth (sourceVfb); 3643 h = ImVfbQHeight (sourceVfb); 3644 depth = 8 * ImVfbQNBytes (sourceVfb); 3645 if (depth != 8) { 3646 fprintf (stderr, "I don't know yet how to deal with images not of 8 planes depth\n"); 3647 free_images (toolInTable); 3648 return (None); 3649 } 3650 3651 *width = w; 3652 *height = h; 3653 3654 scrn = Scr->screen; 3655 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3656 visual = Scr->d_visual; 3657 gc = DefaultGC (dpy, scrn); 3658 3659 buffer_size = w * h; 3660 imagedata = (unsigned char*) malloc (buffer_size); 3661 if (imagedata == (unsigned char*) 0) { 3662 fprintf (stderr, "Can't alloc enough space for background images\n"); 3663 free_images (toolInTable); 3664 return (None); 3665 } 3666 3667 clt = ImVfbQClt (sourceVfb); 3668 vptr = ImVfbQFirst (sourceVfb); 3669 ncolors = 0; 3670 for (i = 0; i < h - 1; i++) { 3671 for (j = 0; j < w; j++) { 3672 ij = (i * w) + j; 3673 red = ImCltQRed (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3674 green = ImCltQGreen (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3675 blue = ImCltQBlue (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3676 for (k = 0; k < ncolors; k++) { 3677 if ((colors [k].red == red) && 3678 (colors [k].green == green) && 3679 (colors [k].blue == blue)) { 3680 icol = k; 3681 break; 3682 } 3683 } 3684 if (k == ncolors) { 3685 icol = ncolors; 3686 ncolors++; 3687 } 3688 imagedata [ij] = icol; 3689 colors [icol].red = red; 3690 colors [icol].green = green; 3691 colors [icol].blue = blue; 3692 ImVfbSInc (sourceVfb, vptr); 3693 } 3694 } 3695 for (i = 0; i < ncolors; i++) { 3696 colors [i].red *= 256; 3697 colors [i].green *= 256; 3698 colors [i].blue *= 256; 3699 } 3700 for (i = 0; i < ncolors; i++) { 3701 if (! XAllocColor (dpy, cmap, &(colors [i]))) { 3702 fprintf (stderr, "can't alloc color for image %s\n", filename); 3703 } 3704 } 3705 for (i = 0; i < buffer_size; i++) { 3706 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3707 } 3708 3709 image = XCreateImage (dpy, visual, depth, ZPixmap, 0, (char*) imagedata, w, h, 8, 0); 3710 if (w > Scr->rootw) w = Scr->rootw; 3711 if (h > Scr->rooth) h = Scr->rooth; 3712 3713 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3714 int x, y; 3715 3716 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, depth); 3717 x = (Scr->rootw - w) / 2; 3718 y = (Scr->rooth - h) / 2; 3719 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3720 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3721 ret->width = Scr->rootw; 3722 ret->height = Scr->rooth; 3723 } 3724 else { 3725 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3726 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3727 ret->width = w; 3728 ret->height = h; 3729 } 3730 XFree (image); 3731 ret = (Image*) malloc (sizeof (struct _Image)); 3732 ret->pixmap = pixret; 3733 ret->mask = None; 3734 ret->next = None; 3735 return (ret); 3736 3737} 3738 3739static void free_images (table) 3740TagTable *table; 3741{ 3742 int i, n; 3743 ImVfb *v; 3744 ImClt *c; 3745 TagEntry *dataEntry; 3746 3747 n = TagTableQNEntry (table, "image vfb"); 3748 for (i = 0 ; i < n ; i++) { 3749 dataEntry = TagTableQDirect (table, "image vfb", i); 3750 TagEntryQValue (dataEntry, &v); 3751 ImVfbFree (v); 3752 } 3753 n = TagTableQNEntry (table, "image clt"); 3754 for (i = 0 ; i < n ; i++) { 3755 dataEntry = TagTableQDirect (table, "image clt", i ); 3756 TagEntryQValue (dataEntry, &c); 3757 ImCltFree (c); 3758 } 3759 TagTableFree (table); 3760} 3761 3762#endif 3763 3764void _swapshort (register char *bp, register unsigned n) 3765{ 3766 register char c; 3767 register char *ep = bp + n; 3768 3769 while (bp < ep) { 3770 c = *bp; 3771 *bp = *(bp + 1); 3772 bp++; 3773 *bp++ = c; 3774 } 3775} 3776 3777void _swaplong (register char *bp, register unsigned n) 3778{ 3779 register char c; 3780 register char *ep = bp + n; 3781 register char *sp; 3782 3783 while (bp < ep) { 3784 sp = bp + 3; 3785 c = *sp; 3786 *sp = *bp; 3787 *bp++ = c; 3788 sp = bp + 1; 3789 c = *sp; 3790 *sp = *bp; 3791 *bp++ = c; 3792 bp += 2; 3793 } 3794} 3795 3796/*********************************************************************** 3797 * 3798 * Procedure: 3799 * GetWMPropertyString - Get Window Manager text property and 3800 * convert it to a string. 3801 * 3802 * Returned Value: 3803 * (char *) - pointer to the malloc'd string or NULL 3804 * 3805 * Inputs: 3806 * w - the id of the window whose property is to be retrieved 3807 * prop - property atom (typically WM_NAME or WM_ICON_NAME) 3808 * 3809 *********************************************************************** 3810 */ 3811 3812unsigned char *GetWMPropertyString(Window w, Atom prop) 3813{ 3814 XTextProperty text_prop; 3815 char **text_list; 3816 int text_list_count; 3817 Atom XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False); 3818 unsigned char *stringptr; 3819 int status, len = -1; 3820 3821 (void)XGetTextProperty(dpy, w, &text_prop, prop); 3822 if (text_prop.value != NULL) { 3823 if (text_prop.encoding == XA_STRING 3824 || text_prop.encoding == XA_COMPOUND_TEXT) { 3825 /* property is encoded as compound text - convert to locale string */ 3826 status = XmbTextPropertyToTextList(dpy, &text_prop, 3827 &text_list, &text_list_count); 3828 if (text_list_count == 0) { 3829 stringptr = NULL; 3830 } else 3831 if (text_list == (char **)0) { 3832 stringptr = NULL; 3833 } else 3834 if (text_list [0] == (char *)0) { 3835 stringptr = NULL; 3836 } else 3837 if (status < 0 || text_list_count < 0) { 3838 switch (status) { 3839 case XConverterNotFound: 3840 fprintf (stderr, "%s: Converter not found; unable to convert property %s of window ID %lx.\n", 3841 ProgramName, XGetAtomName(dpy, prop), w); 3842 break; 3843 case XNoMemory: 3844 fprintf (stderr, "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n", 3845 ProgramName, XGetAtomName(dpy, prop), w); 3846 break; 3847 case XLocaleNotSupported: 3848 fprintf (stderr, "%s: Locale not supported; unable to convert property %s of window ID %lx.\n", 3849 ProgramName, XGetAtomName(dpy, prop), w); 3850 break; 3851 } 3852 stringptr = NULL; 3853 /* 3854 don't call XFreeStringList - text_list appears to have 3855 invalid address if status is bad 3856 XFreeStringList(text_list); 3857 */ 3858 } else { 3859 len = strlen(text_list[0]); 3860 stringptr = memcpy(malloc(len+1), text_list[0], len+1); 3861 XFreeStringList(text_list); 3862 } 3863 } else { 3864 /* property is encoded in a format we don't understand */ 3865 fprintf (stderr, "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n", 3866 ProgramName, XGetAtomName(dpy, prop), w); 3867 stringptr = NULL; 3868 } 3869 XFree (text_prop.value); 3870 } else { 3871 stringptr = NULL; 3872 } 3873 3874 return stringptr; 3875} 3876 3877void FreeWMPropertyString(char *prop) 3878{ 3879 if (prop && (char *)prop != NoName) { 3880 free(prop); 3881 } 3882} 3883 3884static void ConstrainLeftTop (int *value, int border) 3885{ 3886 if (*value < border) { 3887 if (Scr->MoveOffResistance < 0 || 3888 *value > border - Scr->MoveOffResistance) 3889 { 3890 *value = border; 3891 } else if (Scr->MoveOffResistance > 0 && 3892 *value <= border - Scr->MoveOffResistance) 3893 { 3894 *value = *value + Scr->MoveOffResistance; 3895 } 3896 } 3897} 3898 3899static void ConstrainRightBottom (int *value, int size1, int border, int size2) 3900{ 3901 if (*value + size1 > size2 - border) { 3902 if (Scr->MoveOffResistance < 0 || 3903 *value + size1 < size2 - border + Scr->MoveOffResistance) 3904 { 3905 *value = size2 - size1 - border; 3906 } else if (Scr->MoveOffResistance > 0 && 3907 *value + size1 >= size2 - border + Scr->MoveOffResistance) { 3908 *value = *value - Scr->MoveOffResistance; 3909 } 3910 } 3911} 3912 3913void ConstrainByBorders1 (int *left, int width, int *top, int height) 3914{ 3915 ConstrainRightBottom (left, width, Scr->BorderRight, Scr->rootw); 3916 ConstrainLeftTop (left, Scr->BorderLeft); 3917 ConstrainRightBottom (top, height, Scr->BorderBottom, Scr->rooth); 3918 ConstrainLeftTop (top, Scr->BorderTop); 3919} 3920 3921void ConstrainByBorders (TwmWindow *twmwin, 3922 int *left, int width, int *top, int height) 3923{ 3924 if (twmwin->winbox) { 3925 XWindowAttributes attr; 3926 XGetWindowAttributes (dpy, twmwin->winbox->window, &attr); 3927 ConstrainRightBottom (left, width, 0, attr.width); 3928 ConstrainLeftTop (left, 0); 3929 ConstrainRightBottom (top, height, 0, attr.height); 3930 ConstrainLeftTop (top, 0); 3931 } else { 3932 ConstrainByBorders1 (left, width, top, height); 3933 } 3934} 3935 3936#ifdef JPEG 3937 3938uint16_t *buffer_16bpp; 3939uint32_t *buffer_32bpp; 3940 3941static void convert_for_16 (int w, int x, int y, int r, int g, int b) { 3942 buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3); 3943} 3944 3945static void convert_for_32 (int w, int x, int y, int r, int g, int b) { 3946 buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF; 3947} 3948 3949static void jpeg_error_exit (j_common_ptr cinfo) { 3950 jerr_ptr errmgr = (jerr_ptr) cinfo->err; 3951 cinfo->err->output_message (cinfo); 3952 siglongjmp (errmgr->setjmp_buffer, 1); 3953 return; 3954} 3955 3956static Image *GetJpegImage (char *name) 3957{ 3958 Image *image, *r, *s; 3959 char path [128]; 3960 char pref [128], *perc; 3961 int i; 3962 3963 if (! strchr (name, '%')) return (LoadJpegImage (name)); 3964 s = image = None; 3965 strcpy (pref, name); 3966 perc = strchr (pref, '%'); 3967 *perc = '\0'; 3968 reportfilenotfound = 0; 3969 for (i = 1;; i++) { 3970 sprintf (path, "%s%d%s", pref, i, perc + 1); 3971 r = LoadJpegImage (path); 3972 if (r == None) break; 3973 r->next = None; 3974 if (image == None) s = image = r; 3975 else { 3976 s->next = r; 3977 s = r; 3978 } 3979 } 3980 reportfilenotfound = 1; 3981 if (s != None) s->next = image; 3982 if (image == None) { 3983 fprintf (stderr, "Cannot open any %s jpeg file\n", name); 3984 } 3985 return (image); 3986} 3987 3988static Image *LoadJpegImage (char *name) 3989{ 3990 char *fullname; 3991 XImage *ximage; 3992 FILE *infile; 3993 Image *image; 3994 Pixmap pixret; 3995 void (*store_data) (int w, int x, int y, int r, int g, int b); 3996 struct jpeg_decompress_struct cinfo; 3997 struct jpeg_error jerr; 3998 JSAMPARRAY buffer; 3999 int width, height; 4000 int row_stride; 4001 int g, i, a; 4002 int bpix; 4003 GC gc; 4004 4005 fullname = ExpandPixmapPath (name); 4006 if (! fullname) return (None); 4007 4008 image = (Image*) malloc (sizeof (struct _Image)); 4009 if (image == None) return (None); 4010 4011 if ((infile = fopen (fullname, "rb")) == NULL) { 4012 if (!reportfilenotfound) fprintf (stderr, "unable to locate %s\n", fullname); 4013 fflush (stdout); 4014 return None; 4015 } 4016 cinfo.err = jpeg_std_error (&jerr.pub); 4017 jerr.pub.error_exit = jpeg_error_exit; 4018 4019 if (sigsetjmp(jerr.setjmp_buffer, 1)) { 4020 jpeg_destroy_decompress (&cinfo); 4021 fclose (infile); 4022 return None; 4023 } 4024 jpeg_create_decompress (&cinfo); 4025 jpeg_stdio_src (&cinfo, infile); 4026 jpeg_read_header (&cinfo, FALSE); 4027 cinfo.do_fancy_upsampling = FALSE; 4028 cinfo.do_block_smoothing = FALSE; 4029 jpeg_start_decompress (&cinfo); 4030 width = cinfo.output_width; 4031 height = cinfo.output_height; 4032 4033 if (Scr->d_depth == 16) { 4034 store_data = &convert_for_16; 4035 buffer_16bpp = (unsigned short int *) malloc ((width) * (height) * 2); 4036 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4037 (char *) buffer_16bpp, width, height, 16, width * 2); 4038 } else { 4039 if (Scr->d_depth == 24) { 4040 store_data = &convert_for_32; 4041 buffer_32bpp = malloc (width * height * 4); 4042 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4043 (char *) buffer_32bpp, width, height, 32, width * 4); 4044 } else 4045 if (Scr->d_depth == 32) { 4046 store_data = &convert_for_32; 4047 buffer_32bpp = malloc (width * height * 4); 4048 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4049 (char *) buffer_32bpp, width, height, 32, width * 4); 4050 } else { 4051 fprintf (stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth); 4052 return None; 4053 } 4054 } 4055 if (ximage == None) { 4056 fprintf (stderr, "cannot create image for %s\n", name); 4057 } 4058 g = 0; 4059 row_stride = cinfo.output_width * cinfo.output_components; 4060 buffer = (*cinfo.mem->alloc_sarray) 4061 ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1); 4062 4063 bpix = cinfo.output_components; 4064 while (cinfo.output_scanline < cinfo.output_height) { 4065 jpeg_read_scanlines (&cinfo, buffer, 1); 4066 a = 0; 4067 for (i = 0; i < bpix * cinfo.output_width; i += bpix) { 4068 (*store_data) (width, a, g, buffer[0][i], buffer[0][i + 1], buffer[0][i + 2]); 4069 a++; 4070 } 4071 g++; 4072 } 4073 jpeg_finish_decompress (&cinfo); 4074 jpeg_destroy_decompress (&cinfo); 4075 fclose (infile); 4076 4077 gc = DefaultGC (dpy, Scr->screen); 4078 if ((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) { 4079 int x, y; 4080 4081 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth); 4082 x = (Scr->rootw - width) / 2; 4083 y = (Scr->rooth - height) / 2; 4084 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 4085 XPutImage (dpy, pixret, gc, ximage, 0, 0, x, y, width, height); 4086 image->width = Scr->rootw; 4087 image->height = Scr->rooth; 4088 } else { 4089 pixret = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 4090 XPutImage (dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height); 4091 image->width = width; 4092 image->height = height; 4093 } 4094 XDestroyImage (ximage); 4095 image->pixmap = pixret; 4096 image->mask = None; 4097 image->next = None; 4098 4099 return image; 4100} 4101 4102#endif /* JPEG */ 4103