util.c revision b427e94e
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 Scr->WelcomeImage = GetImage ("xwd:welcome.xwd", WelcomeCp); 912#ifdef XPM 913 if (Scr->WelcomeImage == None) 914 Scr->WelcomeImage = GetImage ("xpm:welcome.xpm", WelcomeCp); 915#endif 916 } 917 else { 918 Scr->WelcomeImage = GetImage (file, WelcomeCp); 919 } 920 AlternateCmap = None; 921 reportfilenotfound = 1; 922 if (Scr->WelcomeImage == None) return; 923 924 if (captive) { 925 XSetWindowColormap (dpy, Scr->WindowMask, Scr->WelcomeCmap); 926 XSetWMColormapWindows (dpy, Scr->Root, &(Scr->WindowMask), 1); 927 } 928 else XInstallColormap (dpy, Scr->WelcomeCmap); 929 930 Scr->WelcomeGC = XCreateGC (dpy, Scr->WindowMask, 0, NULL); 931 x = (Scr->rootw - Scr->WelcomeImage->width) / 2; 932 y = (Scr->rooth - Scr->WelcomeImage->height) / 2; 933 934 XSetWindowBackground (dpy, Scr->WindowMask, black.pixel); 935 XClearWindow (dpy, Scr->WindowMask); 936 XCopyArea (dpy, Scr->WelcomeImage->pixmap, Scr->WindowMask, Scr->WelcomeGC, 0, 0, 937 Scr->WelcomeImage->width, Scr->WelcomeImage->height, x, y); 938} 939 940void UnmaskScreen (void) 941{ 942#ifdef VMS 943 float timeout; 944#else 945 struct timeval timeout; 946#endif 947 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 948 Colormap cmap; 949 XColor colors [256], stdcolors [256]; 950 int i, j, usec; 951 952#ifdef VMS 953 timeout = 0.017; 954#else 955 usec = 10000; 956 timeout.tv_usec = usec % (unsigned long) 1000000; 957 timeout.tv_sec = usec / (unsigned long) 1000000; 958#endif 959 960 if (Scr->WelcomeImage) { 961 Pixel pixels [256]; 962 963 cmap = Scr->WelcomeCmap; 964 for (i = 0; i < 256; i++) { 965 pixels [i] = i; 966 colors [i].pixel = i; 967 } 968 XQueryColors (dpy, cmap, colors, 256); 969 XFreeColors (dpy, cmap, pixels, 256, 0L); 970 XFreeColors (dpy, cmap, pixels, 256, 0L); /* Ah Ah */ 971 972 for (i = 0; i < 256; i++) { 973 colors [i].pixel = i; 974 colors [i].flags = DoRed | DoGreen | DoBlue; 975 stdcolors [i].red = colors [i].red; 976 stdcolors [i].green = colors [i].green; 977 stdcolors [i].blue = colors [i].blue; 978 } 979 for (i = 0; i < 128; i++) { 980 for (j = 0; j < 256; j++) { 981 colors [j].red = stdcolors [j].red * ((127.0 - i) / 128.0); 982 colors [j].green = stdcolors [j].green * ((127.0 - i) / 128.0); 983 colors [j].blue = stdcolors [j].blue * ((127.0 - i) / 128.0); 984 } 985 XStoreColors (dpy, cmap, colors, 256); 986#ifdef VMS 987 lib$wait(&timeout); 988#else 989 select (0, (void *) 0, (void *) 0, (void *) 0, &timeout); 990#endif 991 } 992 XFreeColors (dpy, cmap, pixels, 256, 0L); 993 XFreeGC (dpy, Scr->WelcomeGC); 994 FreeImage (Scr->WelcomeImage); 995 } 996 if (Scr->Monochrome != COLOR) goto fin; 997 998 cmap = XCreateColormap (dpy, Scr->Root, Scr->d_visual, AllocNone); 999 if (! cmap) goto fin; 1000 for (i = 0; i < 256; i++) { 1001 colors [i].pixel = i; 1002 colors [i].red = 0; 1003 colors [i].green = 0; 1004 colors [i].blue = 0; 1005 colors [i].flags = DoRed | DoGreen | DoBlue; 1006 } 1007 XStoreColors (dpy, cmap, colors, 256); 1008 1009 if (captive) XSetWindowColormap (dpy, Scr->Root, cmap); 1010 else XInstallColormap (dpy, cmap); 1011 1012 XUnmapWindow (dpy, Scr->WindowMask); 1013 XClearWindow (dpy, Scr->Root); 1014 XSync (dpy, 0); 1015 PaintAllDecoration (); 1016 1017 for (i = 0; i < 256; i++) stdcolors [i].pixel = i; 1018 XQueryColors (dpy, stdcmap, stdcolors, 256); 1019 for (i = 0; i < 128; i++) { 1020 for (j = 0; j < 256; j++) { 1021 colors [j].pixel = j; 1022 colors [j].red = stdcolors [j].red * (i / 127.0); 1023 colors [j].green = stdcolors [j].green * (i / 127.0); 1024 colors [j].blue = stdcolors [j].blue * (i / 127.0); 1025 colors [j].flags = DoRed | DoGreen | DoBlue; 1026 } 1027 XStoreColors (dpy, cmap, colors, 256); 1028#ifdef VMS 1029 lib$wait(&timeout); 1030#else 1031 select (0, (void *) 0, (void *) 0, (void *) 0, &timeout); 1032#endif 1033 } 1034 1035 if (captive) XSetWindowColormap (dpy, Scr->Root, stdcmap); 1036 else XInstallColormap (dpy, stdcmap); 1037 1038 XFreeColormap (dpy, cmap); 1039 1040fin: 1041 if (Scr->WelcomeCmap) XFreeColormap (dpy, Scr->WelcomeCmap); 1042 XDestroyWindow (dpy, Scr->WindowMask); 1043 Scr->WindowMask = (Window) 0; 1044} 1045 1046#ifdef VMS 1047 1048/* use the VMS system services to request the timer to issue an AST */ 1049void AnimateHandler (void); 1050 1051unsigned int tv[2]; 1052int status; 1053static unsigned long timefi; 1054/* unsigned long timefe = 17; */ 1055unsigned long timefe; 1056 1057#define TIMID 12L 1058 1059void StartAnimation (void) 1060{ 1061 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1062 if (AnimationSpeed <= 0) return; 1063 if (AnimationActive) return; 1064 1065 if (!timefi) lib$get_ef(&timefi); 1066 if (!timefe) lib$get_ef(&timefe); 1067 1068 tv[1] = 0xFFFFFFFF; /* quadword negative for relative */ 1069 tv[0] = -(10000000 / AnimationSpeed); /* time. In units of 100ns. */ 1070 sys$clref(timefe); 1071 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID ); 1072 if (status != SS$_NORMAL) lib$signal(status); 1073 AnimationActive = True; 1074} 1075 1076void StopAnimation () { 1077 if (AnimationSpeed <= 0) return; 1078 if (! AnimationActive) return; 1079 AnimationActive = False; 1080 1081 status = sys$cantim(TIMID, PSL$C_USER); 1082 if (status != SS$_NORMAL) lib$signal(status); 1083} 1084 1085void SetAnimationSpeed (int speed) 1086{ 1087 AnimationSpeed = speed; 1088 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1089} 1090 1091void ModifyAnimationSpeed (int incr) 1092{ 1093 if ((AnimationSpeed + incr) < 0) return; 1094 if ((AnimationSpeed + incr) == 0) { 1095 if (AnimationActive) StopAnimation (); 1096 AnimationSpeed = 0; 1097 return; 1098 } 1099 AnimationSpeed += incr; 1100 1101 status = sys$cantim(TIMID, PSL$C_USER); 1102 if (status != SS$_NORMAL) lib$signal(status); 1103 1104 tv[1] = 0xFFFFFFFF; 1105 tv[0] = -(10000000 / AnimationSpeed); 1106 1107 sys$clref(timefe); 1108 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID); 1109 if (status != SS$_NORMAL) lib$signal(status); 1110 1111 AnimationActive = True; 1112} 1113 1114void AnimateHandler (void) { 1115 AnimationPending = True; 1116 1117 sys$setef(timefe); 1118 status = sys$setimr (timefi, &tv, AnimateHandler, TIMID); 1119 if (status != SS$_NORMAL) lib$signal(status); 1120} 1121#else /* VMS */ 1122 1123#ifdef USE_SIGNALS 1124SIGNAL_T AnimateHandler (); 1125#endif 1126 1127#ifndef USE_SIGNALS 1128void TryToAnimate (void) 1129{ 1130 struct timeval tp; 1131 struct timezone tzp; 1132 static unsigned long lastsec; 1133 static long lastusec; 1134 unsigned long gap; 1135 1136 gettimeofday (&tp, &tzp); 1137 gap = ((tp.tv_sec - lastsec) * 1000000) + (tp.tv_usec - lastusec); 1138 if (tracefile) { 1139 fprintf (tracefile, "Time = %lu, %ld, %ld, %ld, %lu\n", lastsec, 1140 lastusec, (long)tp.tv_sec, (long)tp.tv_usec, gap); 1141 fflush (tracefile); 1142 } 1143 gap *= AnimationSpeed; 1144 if (gap < 1000000) return; 1145 if (tracefile) { 1146 fprintf (tracefile, "Animate\n"); 1147 fflush (tracefile); 1148 } 1149 Animate (); 1150 lastsec = tp.tv_sec; 1151 lastusec = tp.tv_usec; 1152} 1153#endif /* USE_SIGNALS */ 1154 1155void StartAnimation (void) 1156{ 1157#ifdef USE_SIGNALS 1158 struct itimerval tv; 1159#endif 1160 1161 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1162 if (AnimationSpeed <= 0) AnimationSpeed = 0; 1163 if (AnimationActive) return; 1164#ifdef USE_SIGNALS 1165 if (AnimationSpeed == 0) return; 1166 signal (SIGALRM, AnimateHandler); 1167 if (AnimationSpeed == 1) { 1168 tv.it_interval.tv_sec = 1; 1169 tv.it_interval.tv_usec = 0; 1170 tv.it_value.tv_sec = 1; 1171 tv.it_value.tv_usec = 0; 1172 } 1173 else { 1174 tv.it_interval.tv_sec = 0; 1175 tv.it_interval.tv_usec = 1000000 / AnimationSpeed; 1176 tv.it_value.tv_sec = 0; 1177 tv.it_value.tv_usec = 1000000 / AnimationSpeed; 1178 } 1179 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1180#else /* USE_SIGNALS */ 1181 switch (AnimationSpeed) { 1182 case 0 : 1183 return; 1184 case 1 : 1185 AnimateTimeout.tv_sec = 1; 1186 AnimateTimeout.tv_usec = 0; 1187 break; 1188 default : 1189 AnimateTimeout.tv_sec = 0; 1190 AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1191 } 1192#endif /* USE_SIGNALS */ 1193 AnimationActive = True; 1194} 1195 1196void StopAnimation (void) 1197{ 1198#ifdef USE_SIGNALS 1199 struct itimerval tv; 1200 1201 if (AnimationSpeed <= 0) return; 1202 if (! AnimationActive) return; 1203 signal (SIGALRM, SIG_IGN); 1204 1205 tv.it_value.tv_sec = 0; 1206 tv.it_value.tv_usec = 0; 1207 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1208#endif 1209 AnimationActive = False; 1210} 1211 1212void SetAnimationSpeed (int speed) 1213{ 1214 AnimationSpeed = speed; 1215 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1216} 1217 1218void ModifyAnimationSpeed (int incr) 1219{ 1220#ifdef USE_SIGNALS 1221 struct itimerval tv; 1222#endif 1223 1224 if ((AnimationSpeed + incr) < 0) return; 1225 if ((AnimationSpeed + incr) == 0) { 1226 if (AnimationActive) StopAnimation (); 1227 AnimationSpeed = 0; 1228 return; 1229 } 1230 AnimationSpeed += incr; 1231 if (AnimationSpeed > MAXANIMATIONSPEED) AnimationSpeed = MAXANIMATIONSPEED; 1232 1233#ifdef USE_SIGNALS 1234 signal (SIGALRM, AnimateHandler); 1235 if (AnimationSpeed == 1) { 1236 tv.it_interval.tv_sec = 1; 1237 tv.it_interval.tv_usec = 0; 1238 tv.it_value.tv_sec = 1; 1239 tv.it_value.tv_usec = 0; 1240 } 1241 else { 1242 tv.it_interval.tv_sec = 0; 1243 tv.it_interval.tv_usec = 1000000 / AnimationSpeed; 1244 tv.it_value.tv_sec = 0; 1245 tv.it_value.tv_usec = 1000000 / AnimationSpeed; 1246 } 1247 setitimer (ITIMER_REAL, &tv, (struct itimerval*) NULL); 1248#else /* USE_SIGNALS */ 1249 if (AnimationSpeed == 1) { 1250 AnimateTimeout.tv_sec = 1; 1251 AnimateTimeout.tv_usec = 0; 1252 } 1253 else { 1254 AnimateTimeout.tv_sec = 0; 1255 AnimateTimeout.tv_usec = 1000000 / AnimationSpeed; 1256 } 1257#endif /* USE_SIGNALS */ 1258 AnimationActive = True; 1259} 1260 1261#ifdef USE_SIGNALS 1262SIGNAL_T AnimateHandler (int dummy) 1263{ 1264 signal (SIGALRM, AnimateHandler); 1265 AnimationPending = True; 1266} 1267#endif 1268#endif /* VMS */ 1269 1270void Animate (void) 1271{ 1272 TwmWindow *t; 1273 int scrnum; 1274 ScreenInfo *scr; 1275 int i; 1276 TBWindow *tbw; 1277 int nb; 1278 1279 if (AnimationSpeed == 0) return; 1280#ifdef USE_SIGNALS 1281 AnimationPending = False; 1282#endif 1283 1284 MaybeAnimate = False; 1285 for (scrnum = 0; scrnum < NumScreens; scrnum++) { 1286 if ((scr = ScreenList [scrnum]) == NULL) continue; 1287 1288 for (t = scr->FirstWindow; t != NULL; t = t->next) { 1289 if (! visible (t)) continue; 1290 if (t->icon_on && t->icon && t->icon->bm_w && t->icon->image && 1291 t->icon->image->next) { 1292 AnimateIcons (scr, t->icon); 1293 MaybeAnimate = True; 1294 } 1295 else 1296 if (t->mapped && t->titlebuttons) { 1297 nb = scr->TBInfo.nleft + scr->TBInfo.nright; 1298 for (i = 0, tbw = t->titlebuttons; i < nb; i++, tbw++) { 1299 if (tbw->image && tbw->image->next) { 1300 AnimateButton (tbw); 1301 MaybeAnimate = True; 1302 } 1303 } 1304 } 1305 } 1306 if (scr->Focus) { 1307 t = scr->Focus; 1308 if (t->mapped && t->titlehighlight && t->title_height && 1309 t->HiliteImage && t->HiliteImage->next) { 1310 AnimateHighlight (t); 1311 MaybeAnimate = True; 1312 } 1313 } 1314 } 1315 MaybeAnimate |= AnimateRoot (); 1316 XFlush (dpy); 1317 return; 1318} 1319 1320void InsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps, 1321 Bool replace) 1322{ 1323 StdCmap *sc = NULL; 1324 1325 if (replace) { /* locate existing entry */ 1326 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1327 if (sc->atom == a) break; 1328 } 1329 } 1330 1331 if (!sc) { /* no existing, allocate new */ 1332 sc = (StdCmap *) malloc (sizeof (StdCmap)); 1333 if (!sc) { 1334 fprintf (stderr, "%s: unable to allocate %lu bytes for StdCmap\n", 1335 ProgramName, (unsigned long) sizeof(StdCmap)); 1336 return; 1337 } 1338 } 1339 1340 if (replace) { /* just update contents */ 1341 if (sc->maps) XFree ((char *) maps); 1342 if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL; 1343 } else { /* else appending */ 1344 sc->next = NULL; 1345 sc->atom = a; 1346 if (Scr->StdCmapInfo.tail) { 1347 Scr->StdCmapInfo.tail->next = sc; 1348 } else { 1349 Scr->StdCmapInfo.head = sc; 1350 } 1351 Scr->StdCmapInfo.tail = sc; 1352 } 1353 sc->nmaps = nmaps; 1354 sc->maps = maps; 1355 1356 return; 1357} 1358 1359void RemoveRGBColormap (Atom a) 1360{ 1361 StdCmap *sc, *prev; 1362 1363 prev = NULL; 1364 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1365 if (sc->atom == a) break; 1366 prev = sc; 1367 } 1368 if (sc) { /* found one */ 1369 if (sc->maps) XFree ((char *) sc->maps); 1370 if (prev) prev->next = sc->next; 1371 if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next; 1372 if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev; 1373 if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL; 1374 } 1375 return; 1376} 1377 1378void LocateStandardColormaps(void) 1379{ 1380 Atom *atoms; 1381 int natoms; 1382 int i; 1383 1384 atoms = XListProperties (dpy, Scr->Root, &natoms); 1385 for (i = 0; i < natoms; i++) { 1386 XStandardColormap *maps = NULL; 1387 int nmaps; 1388 1389 if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) { 1390 /* if got one, then append to current list */ 1391 InsertRGBColormap (atoms[i], maps, nmaps, False); 1392 } 1393 } 1394 if (atoms) XFree ((char *) atoms); 1395 return; 1396} 1397 1398void GetColor(int kind, Pixel *what, char *name) 1399{ 1400 XColor color; 1401 Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 1402 1403#ifndef TOM 1404 if (!Scr->FirstTime) 1405 return; 1406#endif 1407 1408 if (Scr->Monochrome != kind) 1409 return; 1410 1411 if (! XParseColor (dpy, cmap, name, &color)) { 1412 fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1413 return; 1414 } 1415 if (! XAllocColor (dpy, cmap, &color)) 1416 { 1417 /* if we could not allocate the color, let's see if this is a 1418 * standard colormap 1419 */ 1420 XStandardColormap *stdcmap = NULL; 1421 1422 if (! XParseColor (dpy, cmap, name, &color)) { 1423 fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); 1424 return; 1425 } 1426 1427 /* 1428 * look through the list of standard colormaps (check cache first) 1429 */ 1430 if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps && 1431 (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap == 1432 cmap)) { 1433 stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]); 1434 } else { 1435 StdCmap *sc; 1436 1437 for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 1438 int i; 1439 1440 for (i = 0; i < sc->nmaps; i++) { 1441 if (sc->maps[i].colormap == cmap) { 1442 Scr->StdCmapInfo.mru = sc; 1443 Scr->StdCmapInfo.mruindex = i; 1444 stdcmap = &(sc->maps[i]); 1445 goto gotit; 1446 } 1447 } 1448 } 1449 } 1450 1451 gotit: 1452 if (stdcmap) { 1453 color.pixel = (stdcmap->base_pixel + 1454 ((Pixel)(((float)color.red / 65535.0) * 1455 stdcmap->red_max + 0.5) * 1456 stdcmap->red_mult) + 1457 ((Pixel)(((float)color.green /65535.0) * 1458 stdcmap->green_max + 0.5) * 1459 stdcmap->green_mult) + 1460 ((Pixel)(((float)color.blue / 65535.0) * 1461 stdcmap->blue_max + 0.5) * 1462 stdcmap->blue_mult)); 1463 } else { 1464 fprintf (stderr, "%s: unable to allocate color \"%s\"\n", 1465 ProgramName, name); 1466 return; 1467 } 1468 } 1469 1470 *what = color.pixel; 1471 return; 1472} 1473 1474void GetShadeColors (ColorPair *cp) 1475{ 1476 XColor xcol; 1477 Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c; 1478 int save; 1479 float clearfactor; 1480 float darkfactor; 1481 char clearcol [32], darkcol [32]; 1482 1483 clearfactor = (float) Scr->ClearShadowContrast / 100.0; 1484 darkfactor = (100.0 - (float) Scr->DarkShadowContrast) / 100.0; 1485 xcol.pixel = cp->back; 1486 XQueryColor (dpy, cmap, &xcol); 1487 1488 sprintf (clearcol, "#%04x%04x%04x", 1489 xcol.red + (unsigned short) ((65535 - xcol.red) * clearfactor), 1490 xcol.green + (unsigned short) ((65535 - xcol.green) * clearfactor), 1491 xcol.blue + (unsigned short) ((65535 - xcol.blue) * clearfactor)); 1492 sprintf (darkcol, "#%04x%04x%04x", 1493 (unsigned short) (xcol.red * darkfactor), 1494 (unsigned short) (xcol.green * darkfactor), 1495 (unsigned short) (xcol.blue * darkfactor)); 1496 1497 save = Scr->FirstTime; 1498 Scr->FirstTime = True; 1499 GetColor (Scr->Monochrome, &cp->shadc, clearcol); 1500 GetColor (Scr->Monochrome, &cp->shadd, darkcol); 1501 Scr->FirstTime = save; 1502} 1503 1504void GetFont(MyFont *font) 1505{ 1506 char *deffontname = "fixed,*"; 1507 char **missing_charset_list_return; 1508 int missing_charset_count_return; 1509 char *def_string_return; 1510 XFontSetExtents *font_extents; 1511 XFontStruct **xfonts; 1512 char **font_names; 1513 register int i; 1514 int ascent; 1515 int descent; 1516 int fnum; 1517 char *basename2; 1518 1519 if (font->font_set != NULL){ 1520 XFreeFontSet(dpy, font->font_set); 1521 } 1522 1523 basename2 = (char *)malloc(strlen(font->basename) + 3); 1524 if (basename2) sprintf(basename2, "%s,*", font->basename); 1525 else basename2 = font->basename; 1526 if( (font->font_set = XCreateFontSet(dpy, basename2, 1527 &missing_charset_list_return, 1528 &missing_charset_count_return, 1529 &def_string_return)) == NULL) { 1530 if (Scr->DefaultFont.basename) { 1531 deffontname = Scr->DefaultFont.basename; 1532 } 1533 if ((font->font_set = XCreateFontSet(dpy, deffontname, 1534 &missing_charset_list_return, 1535 &missing_charset_count_return, 1536 &def_string_return)) == NULL) 1537 { 1538 fprintf (stderr, "%s: unable to open fonts \"%s\" or \"%s\"\n", 1539 ProgramName, font->basename, deffontname); 1540 exit(1); 1541 } 1542 } 1543 if (basename2 != font->basename) free(basename2); 1544 font_extents = XExtentsOfFontSet(font->font_set); 1545 1546 fnum = XFontsOfFontSet(font->font_set, &xfonts, &font_names); 1547 for( i = 0, ascent = 0, descent = 0; i<fnum; i++){ 1548 ascent = MaxSize(ascent, (*xfonts)->ascent); 1549 descent = MaxSize(descent, (*xfonts)->descent); 1550 xfonts++; 1551 } 1552 1553 font->height = font_extents->max_logical_extent.height; 1554 font->y = ascent; 1555 font->ascent = ascent; 1556 font->descent = descent; 1557} 1558 1559 1560void SetFocusVisualAttributes (TwmWindow *tmp_win, Bool focus) 1561{ 1562 if (! tmp_win) return; 1563 1564 if (focus == tmp_win->hasfocusvisible) return; 1565 if (tmp_win->highlight) { 1566 if (Scr->use3Dborders) { 1567 PaintBorders (tmp_win, focus); 1568 } 1569 else { 1570 if (focus) { 1571 XSetWindowBorder (dpy, tmp_win->frame, tmp_win->borderC.back); 1572 if (tmp_win->title_w) 1573 XSetWindowBorder (dpy, tmp_win->title_w, tmp_win->borderC.back); 1574 } else { 1575 XSetWindowBorderPixmap (dpy, tmp_win->frame, tmp_win->gray); 1576 if (tmp_win->title_w) 1577 XSetWindowBorderPixmap (dpy, tmp_win->title_w, tmp_win->gray); 1578 } 1579 } 1580 } 1581 1582 if (focus) { 1583 Bool hil = False; 1584 1585 if (tmp_win->lolite_wl) XUnmapWindow (dpy, tmp_win->lolite_wl); 1586 if (tmp_win->lolite_wr) XUnmapWindow (dpy, tmp_win->lolite_wr); 1587 if (tmp_win->hilite_wl) { 1588 XMapWindow (dpy, tmp_win->hilite_wl); 1589 hil = True; 1590 } 1591 if (tmp_win->hilite_wr) { 1592 XMapWindow (dpy, tmp_win->hilite_wr); 1593 hil = True; 1594 } 1595 if (hil && tmp_win->HiliteImage && tmp_win->HiliteImage->next) { 1596 MaybeAnimate = True; 1597 } 1598 if (tmp_win->iconmanagerlist) 1599 ActiveIconManager (tmp_win->iconmanagerlist); 1600 } 1601 else { 1602 if (tmp_win->hilite_wl) XUnmapWindow (dpy, tmp_win->hilite_wl); 1603 if (tmp_win->hilite_wr) XUnmapWindow (dpy, tmp_win->hilite_wr); 1604 if (tmp_win->lolite_wl) XMapWindow (dpy, tmp_win->lolite_wl); 1605 if (tmp_win->lolite_wr) XMapWindow (dpy, tmp_win->lolite_wr); 1606 if (tmp_win->iconmanagerlist) 1607 NotActiveIconManager (tmp_win->iconmanagerlist); 1608 } 1609 if (Scr->use3Dtitles && Scr->SunkFocusWindowTitle && tmp_win->title_height) { 1610 ButtonState bs; 1611 1612 bs = focus ? on : off; 1613 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 1614 tmp_win->title_width - Scr->TBInfo.titlex - 1615 Scr->TBInfo.rightoff - Scr->TitlePadding, 1616 Scr->TitleHeight, Scr->TitleShadowDepth, 1617 tmp_win->title, bs, False, False); 1618 } 1619 tmp_win->hasfocusvisible = focus; 1620} 1621 1622static void move_to_head (TwmWindow *t) 1623{ 1624 if (t == NULL) return; 1625 if (Scr->FirstWindow == t) return; 1626 1627 if (t->prev) t->prev->next = t->next; 1628 if (t->next) t->next->prev = t->prev; 1629 1630 t->next = Scr->FirstWindow; 1631 if (Scr->FirstWindow != NULL) 1632 Scr->FirstWindow->prev = t; 1633 t->prev = NULL; 1634 Scr->FirstWindow = t; 1635} 1636 1637/* 1638 * SetFocus - separate routine to set focus to make things more understandable 1639 * and easier to debug 1640 */ 1641void SetFocus (TwmWindow *tmp_win, Time tim) 1642{ 1643 Window w = (tmp_win ? tmp_win->w : PointerRoot); 1644 int f_iconmgr = 0; 1645 1646 if (Scr->Focus && (Scr->Focus->iconmgr)) f_iconmgr = 1; 1647 if (Scr->SloppyFocus && (w == PointerRoot) && (!f_iconmgr)) return; 1648 1649 XSetInputFocus (dpy, w, RevertToPointerRoot, tim); 1650 if (Scr->Focus == tmp_win) return; 1651 1652 if (Scr->Focus) { 1653 if (Scr->Focus->AutoSqueeze && !Scr->Focus->squeezed) { 1654 AutoSqueeze (Scr->Focus); 1655 } 1656 SetFocusVisualAttributes (Scr->Focus, False); 1657 } 1658 if (tmp_win) { 1659 if (tmp_win->AutoSqueeze && tmp_win->squeezed) { 1660 AutoSqueeze (tmp_win); 1661 } 1662 SetFocusVisualAttributes (tmp_win, True); 1663 } 1664 Scr->Focus = tmp_win; 1665 move_to_head (tmp_win); 1666} 1667 1668# 1669#ifdef NOPUTENV 1670/* 1671 * define our own putenv() if the system doesn't have one. 1672 * putenv(s): place s (a string of the form "NAME=value") in 1673 * the environment; replacing any existing NAME. s is placed in 1674 * environment, so if you change s, the environment changes (like 1675 * putenv on a sun). Binding removed if you putenv something else 1676 * called NAME. 1677 */ 1678int 1679putenv(s) 1680 char *s; 1681{ 1682 char *v; 1683 int varlen, idx; 1684 extern char **environ; 1685 char **newenv; 1686 static int virgin = 1; /* true while "environ" is a virgin */ 1687 1688 v = strchr(s, '='); 1689 if(v == 0) 1690 return 0; /* punt if it's not of the right form */ 1691 varlen = (v + 1) - s; 1692 1693 for (idx = 0; environ[idx] != 0; idx++) { 1694 if (strncmp(environ[idx], s, varlen) == 0) { 1695 if(v[1] != 0) { /* true if there's a value */ 1696 environ[idx] = s; 1697 return 0; 1698 } else { 1699 do { 1700 environ[idx] = environ[idx+1]; 1701 } while(environ[++idx] != 0); 1702 return 0; 1703 } 1704 } 1705 } 1706 1707 /* add to environment (unless no value; then just return) */ 1708 if(v[1] == 0) 1709 return 0; 1710 if(virgin) { 1711 register i; 1712 1713 newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*))); 1714 if(newenv == 0) 1715 return -1; 1716 for(i = idx-1; i >= 0; --i) 1717 newenv[i] = environ[i]; 1718 virgin = 0; /* you're not a virgin anymore, sweety */ 1719 } else { 1720 newenv = (char **) realloc((char *) environ, 1721 (unsigned) ((idx + 2) * sizeof(char*))); 1722 if (newenv == 0) 1723 return -1; 1724 } 1725 1726 environ = newenv; 1727 environ[idx] = s; 1728 environ[idx+1] = 0; 1729 1730 return 0; 1731} 1732#endif /* NOPUTENV */ 1733 1734 1735static Pixmap CreateXLogoPixmap (unsigned int *widthp, unsigned int *heightp) 1736{ 1737 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1738 if (h < 0) h = 0; 1739 1740 *widthp = *heightp = (unsigned int) h; 1741 if (Scr->tbpm.xlogo == None) { 1742 GC gc, gcBack; 1743 1744 Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1745 gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); 1746 XSetForeground (dpy, gc, 0); 1747 XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h); 1748 XSetForeground (dpy, gc, 1); 1749 gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); 1750 XSetForeground (dpy, gcBack, 0); 1751 1752 /* 1753 * draw the logo large so that it gets as dense as possible; then white 1754 * out the edges so that they look crisp 1755 */ 1756 XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2); 1757 XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1); 1758 1759 /* 1760 * done drawing 1761 */ 1762 XFreeGC (dpy, gc); 1763 XFreeGC (dpy, gcBack); 1764 } 1765 return Scr->tbpm.xlogo; 1766} 1767 1768 1769static Pixmap CreateResizePixmap (unsigned int *widthp, unsigned int *heightp) 1770{ 1771 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1772 if (h < 1) h = 1; 1773 1774 *widthp = *heightp = (unsigned int) h; 1775 if (Scr->tbpm.resize == None) { 1776 XPoint points[3]; 1777 GC gc; 1778 int w; 1779 int lw; 1780 1781 /* 1782 * create the pixmap 1783 */ 1784 Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1785 gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL); 1786 XSetForeground (dpy, gc, 0); 1787 XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h); 1788 XSetForeground (dpy, gc, 1); 1789 lw = h / 16; 1790 if (lw == 1) 1791 lw = 0; 1792 XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter); 1793 1794 /* 1795 * draw the resize button, 1796 */ 1797 w = (h * 2) / 3; 1798 points[0].x = w; 1799 points[0].y = 0; 1800 points[1].x = w; 1801 points[1].y = w; 1802 points[2].x = 0; 1803 points[2].y = w; 1804 XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 1805 w = w / 2; 1806 points[0].x = w; 1807 points[0].y = 0; 1808 points[1].x = w; 1809 points[1].y = w; 1810 points[2].x = 0; 1811 points[2].y = w; 1812 XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 1813 1814 /* 1815 * done drawing 1816 */ 1817 XFreeGC(dpy, gc); 1818 } 1819 return Scr->tbpm.resize; 1820} 1821 1822static Pixmap CreateDotPixmap (unsigned int *widthp, unsigned int *heightp) 1823{ 1824 int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1825 1826 h = h * 3 / 4; 1827 if (h < 1) h = 1; 1828 if (!(h & 1)) 1829 h--; 1830 *widthp = *heightp = (unsigned int) h; 1831 if (Scr->tbpm.delete == None) { 1832 GC gc; 1833 Pixmap pix; 1834 1835 pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1); 1836 gc = XCreateGC (dpy, pix, 0L, NULL); 1837 XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound); 1838 XSetForeground (dpy, gc, 0L); 1839 XFillRectangle (dpy, pix, gc, 0, 0, h, h); 1840 XSetForeground (dpy, gc, 1L); 1841 XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2); 1842 XFreeGC (dpy, gc); 1843 } 1844 return Scr->tbpm.delete; 1845} 1846 1847static Image *Create3DCrossImage (ColorPair cp) 1848{ 1849 Image *image; 1850 int h; 1851 int point; 1852 int midpoint; 1853 1854 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1855 if (!(h & 1)) h--; 1856 point = 4; 1857 midpoint = h/2; 1858 1859 image = (Image*) malloc (sizeof (struct _Image)); 1860 if (! image) return (None); 1861 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1862 if (image->pixmap == None) return (None); 1863 1864 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1865 1866#ifdef LEVITTE_TEST 1867 FB (cp.shadc, cp.shadd); 1868 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point-1, point-1, point+1); 1869 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, point, point, point+1); 1870 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point+1, midpoint-2, midpoint); 1871 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint+2, h-point-3, h-point-1); 1872 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point+1, h-point-3, h-point-2); 1873 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, h-point-2, midpoint-2, midpoint); 1874 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint, midpoint-2, h-point-2, point-1); 1875 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-2, h-point-2, point); 1876#endif 1877 1878 FB (cp.shadd, cp.shadc); 1879#ifdef LEVITTE_TEST 1880 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point+1, h-point-1, h-point-2); 1881 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+2, point, midpoint, midpoint-2); 1882 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, h-point-2); 1883 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, h-point-2, h-point-2, h-point); 1884 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, h-point-2, h-point-2, h-point-1); 1885#else 1886 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point-1, h-point-1); 1887 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point-1, point, h-point-1, h-point); 1888 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point-1, h-point, h-point-1); 1889#endif 1890 1891#ifdef LEVITTE_TEST 1892 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, point, h-point-1); 1893 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point, h-point-1, point); 1894#else 1895 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, h-point-1, h-point-1, point); 1896#endif 1897#ifdef LEVITTE_TEST 1898 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point-1, h-point-1, point+1); 1899 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point+1, h-point, midpoint, midpoint+2); 1900 XDrawLine (dpy, image->pixmap, Scr->NormalGC, midpoint+2, midpoint, h-point, point+1); 1901#else 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, h-point, h-point, point); 1904#endif 1905 1906 image->mask = None; 1907 image->width = h; 1908 image->height = h; 1909 image->next = None; 1910 1911 return (image); 1912} 1913 1914static Image *Create3DIconifyImage (ColorPair cp) 1915{ 1916 Image *image; 1917 int h; 1918 int point; 1919 1920 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1921 if (!(h & 1)) h--; 1922 point = ((h/2-2) * 2+1) / 3; 1923 1924 image = (Image*) malloc (sizeof (struct _Image)); 1925 if (! image) return (None); 1926 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1927 if (image->pixmap == None) return (None); 1928 1929 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1930 FB (cp.shadd, cp.shadc); 1931 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h/2, h-point); 1932 XDrawLine (dpy, image->pixmap, Scr->NormalGC, point, point, h-point, point); 1933 1934 FB (cp.shadc, cp.shadd); 1935 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point, point, h/2+1, h-point); 1936 XDrawLine (dpy, image->pixmap, Scr->NormalGC, h-point-1, point+1, h/2+1, h-point-1); 1937 1938 image->mask = None; 1939 image->width = h; 1940 image->height = h; 1941 image->next = None; 1942 1943 return (image); 1944} 1945 1946static Image *Create3DSunkenResizeImage (ColorPair cp) 1947{ 1948 int h; 1949 Image *image; 1950 1951 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1952 if (!(h & 1)) h--; 1953 1954 image = (Image*) malloc (sizeof (struct _Image)); 1955 if (! image) return (None); 1956 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1957 if (image->pixmap == None) return (None); 1958 1959 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1960 Draw3DBorder (image->pixmap, 3, 3, h-6, h-6, 1, cp, on, True, False); 1961 Draw3DBorder (image->pixmap, 3, ((h-6)/3)+3, ((h-6)*2/3)+1, 1962 ((h-6)*2/3)+1, 1, cp, on, True, False); 1963 Draw3DBorder (image->pixmap, 3, ((h-6)*2/3)+3, ((h-6)/3)+1, 1964 ((h-6)/3)+1, 1, cp, on, True, False); 1965 1966 image->mask = None; 1967 image->width = h; 1968 image->height = h; 1969 image->next = None; 1970 1971 return (image); 1972} 1973 1974static Image *Create3DBoxImage (ColorPair cp) 1975{ 1976 int h; 1977 Image *image; 1978 1979 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 1980 if (! (h & 1)) h--; 1981 1982 image = (Image*) malloc (sizeof (struct _Image)); 1983 if (! image) return (None); 1984 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 1985 if (image->pixmap == None) return (None); 1986 1987 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 1988 Draw3DBorder (image->pixmap, (h / 2) - 4, (h / 2) - 4, 9, 9, 1, cp, 1989 off, True, False); 1990 1991 image->mask = None; 1992 image->width = h; 1993 image->height = h; 1994 image->next = None; 1995 1996 return (image); 1997} 1998 1999static Image *Create3DDotImage (ColorPair cp) 2000{ 2001 Image *image; 2002 int h; 2003 static int idepth = 2; 2004 2005 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2006 if (!(h & 1)) h--; 2007 2008 image = (Image*) malloc (sizeof (struct _Image)); 2009 if (! image) return (None); 2010 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2011 if (image->pixmap == None) return (None); 2012 2013 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2014 Draw3DBorder (image->pixmap, (h / 2) - idepth, 2015 (h / 2) - idepth, 2016 2 * idepth + 1, 2017 2 * idepth + 1, 2018 idepth, cp, off, True, False); 2019 image->mask = None; 2020 image->width = h; 2021 image->height = h; 2022 image->next = None; 2023 return (image); 2024} 2025 2026static Image *Create3DBarImage (ColorPair cp) 2027{ 2028 Image *image; 2029 int h; 2030 static int idepth = 2; 2031 2032 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2033 if (!(h & 1)) h--; 2034 2035 image = (Image*) malloc (sizeof (struct _Image)); 2036 if (! image) return (None); 2037 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2038 if (image->pixmap == None) return (None); 2039 2040 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2041 Draw3DBorder (image->pixmap, 2042 Scr->TitleButtonShadowDepth + 2, 2043 (h / 2) - idepth, 2044 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2045 2 * idepth + 1, 2046 idepth, cp, off, True, False); 2047 image->mask = None; 2048 image->width = h; 2049 image->height = h; 2050 image->next = None; 2051 return (image); 2052} 2053 2054static Image *Create3DVertBarImage (ColorPair cp) 2055{ 2056 Image *image; 2057 int h; 2058 static int idepth = 2; 2059 2060 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2061 if (!(h & 1)) h--; 2062 2063 image = (Image*) malloc (sizeof (struct _Image)); 2064 if (! image) return (None); 2065 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2066 if (image->pixmap == None) return (None); 2067 2068 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2069 Draw3DBorder (image->pixmap, 2070 (h / 2) - idepth, 2071 Scr->TitleButtonShadowDepth + 2, 2072 2 * idepth + 1, 2073 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2074 idepth, cp, off, True, False); 2075 image->mask = None; 2076 image->width = h; 2077 image->height = h; 2078 image->next = None; 2079 return (image); 2080} 2081 2082static Image *Create3DMenuImage (ColorPair cp) 2083{ 2084 Image *image; 2085 int h, i; 2086 2087 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2088 if (!(h & 1)) h--; 2089 2090 image = (Image*) malloc (sizeof (struct _Image)); 2091 if (! image) return (None); 2092 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2093 if (image->pixmap == None) return (None); 2094 2095 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2096 for (i = 4; i < h - 7; i += 5) { 2097 Draw3DBorder (image->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False); 2098 } 2099 image->mask = None; 2100 image->width = h; 2101 image->height = h; 2102 image->next = None; 2103 return (image); 2104} 2105 2106static Image *Create3DResizeImage (ColorPair cp) 2107{ 2108 Image *image; 2109 int h; 2110 2111 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2112 if (!(h & 1)) h--; 2113 2114 image = (Image*) malloc (sizeof (struct _Image)); 2115 if (! image) return (None); 2116 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2117 if (image->pixmap == None) return (None); 2118 2119 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2120 Draw3DBorder (image->pixmap, 0, h / 4, ((3 * h) / 4) + 1, ((3 * h) / 4) + 1, 2, 2121 cp, off, True, False); 2122 Draw3DBorder (image->pixmap, 0, h / 2, (h / 2) + 1, (h / 2) + 1, 2, cp, off, True, False); 2123 image->mask = None; 2124 image->width = h; 2125 image->height = h; 2126 image->next = None; 2127 return (image); 2128} 2129 2130static Image *Create3DZoomImage (ColorPair cp) 2131{ 2132 Image *image; 2133 int h; 2134 static int idepth = 2; 2135 2136 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2137 if (!(h & 1)) h--; 2138 2139 image = (Image*) malloc (sizeof (struct _Image)); 2140 if (! image) return (None); 2141 image->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2142 if (image->pixmap == None) return (None); 2143 2144 Draw3DBorder (image->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2145 Draw3DBorder (image->pixmap, Scr->TitleButtonShadowDepth + 2, 2146 Scr->TitleButtonShadowDepth + 2, 2147 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2148 h - 2 * (Scr->TitleButtonShadowDepth + 2), 2149 idepth, cp, off, True, False); 2150 2151 image->mask = None; 2152 image->width = h; 2153 image->height = h; 2154 image->next = None; 2155 return (image); 2156} 2157 2158struct Colori { 2159 Pixel color; 2160 Pixmap pix; 2161 struct Colori *next; 2162}; 2163 2164Pixmap Create3DMenuIcon (unsigned int height, 2165 unsigned int *widthp, unsigned int *heightp, 2166 ColorPair cp) 2167{ 2168 unsigned int h, w; 2169 int i; 2170 struct Colori *col; 2171 static struct Colori *colori = NULL; 2172 2173 h = height; 2174 w = h * 7 / 8; 2175 if (h < 1) h = 1; 2176 if (w < 1) w = 1; 2177 *widthp = w; 2178 *heightp = h; 2179 2180 for (col = colori; col; col = col->next) { 2181 if (col->color == cp.back) break; 2182 } 2183 if (col != NULL) { 2184 return (col->pix); 2185 } 2186 col = (struct Colori*) malloc (sizeof (struct Colori)); 2187 col->color = cp.back; 2188 col->pix = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2189 col->next = colori; 2190 colori = col; 2191 2192 Draw3DBorder (col->pix, 0, 0, w, h, 1, cp, off, True, False); 2193 for (i = 3; i + 5 < h; i += 5) { 2194 Draw3DBorder (col->pix, 4, i, w - 8, 3, 1, Scr->MenuC, off, True, False); 2195 } 2196 return (colori->pix); 2197} 2198 2199#include "siconify.bm" 2200 2201Pixmap Create3DIconManagerIcon (ColorPair cp) 2202{ 2203 unsigned int w, h; 2204 struct Colori *col; 2205 static struct Colori *colori = NULL; 2206 2207 w = (unsigned int) siconify_width; 2208 h = (unsigned int) siconify_height; 2209 2210 for (col = colori; col; col = col->next) { 2211 if (col->color == cp.back) break; 2212 } 2213 if (col != NULL) { 2214 return (col->pix); 2215 } 2216 col = (struct Colori*) malloc (sizeof (struct Colori)); 2217 col->color = cp.back; 2218 col->pix = XCreatePixmap (dpy, Scr->Root, w, h, Scr->d_depth); 2219 Draw3DBorder (col->pix, 0, 0, w, h, 4, cp, off, True, False); 2220 col->next = colori; 2221 colori = col; 2222 2223 return (colori->pix); 2224} 2225 2226static Image *Create3DResizeAnimation (Bool in, Bool left, Bool top, 2227 ColorPair cp) 2228{ 2229 int h, i, j; 2230 Image *image, *im, *im1; 2231 2232 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2233 if (!(h & 1)) h--; 2234 2235 image = im1 = None; 2236 for (i = (in ? 0 : (h/4)-1); (i < h/4) && (i >= 0); i += (in ? 1 : -1)) { 2237 im = (Image*) malloc (sizeof (struct _Image)); 2238 if (! im) return (None); 2239 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2240 if (im->pixmap == None) { 2241 free (im); 2242 return (None); 2243 } 2244 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2245 for (j = i; j <= h; j += (h/4)){ 2246 Draw3DBorder (im->pixmap, (left ? 0 : j), (top ? 0 : j), 2247 h - j, h - j, 2, cp, off, True, False); 2248 } 2249 im->mask = None; 2250 im->width = h; 2251 im->height = h; 2252 im->next = None; 2253 if (image == None) { 2254 image = im1 = im; 2255 } 2256 else { 2257 im1->next = im; 2258 im1 = im; 2259 } 2260 } 2261 if (im1 != None) im1->next = image; 2262 return (image); 2263} 2264 2265static Image *Create3DResizeInTopAnimation (ColorPair cp) 2266{ 2267 return Create3DResizeAnimation (TRUE, FALSE, TRUE, cp); 2268} 2269 2270static Image *Create3DResizeOutTopAnimation (ColorPair cp) 2271{ 2272 return Create3DResizeAnimation (False, FALSE, TRUE, cp); 2273} 2274 2275static Image *Create3DResizeInBotAnimation (ColorPair cp) 2276{ 2277 return Create3DResizeAnimation (TRUE, TRUE, FALSE, cp); 2278} 2279 2280static Image *Create3DResizeOutBotAnimation (ColorPair cp) 2281{ 2282 return Create3DResizeAnimation (False, TRUE, FALSE, cp); 2283} 2284 2285static Image *Create3DMenuAnimation (Bool up, ColorPair cp) 2286{ 2287 int h, i, j; 2288 Image *image, *im, *im1; 2289 2290 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2291 if (!(h & 1)) h--; 2292 2293 image = im1 = None; 2294 for (j = (up ? 4 : 0); j != (up ? -1 : 5); j+= (up ? -1 : 1)) { 2295 im = (Image*) malloc (sizeof (struct _Image)); 2296 if (! im) return (None); 2297 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2298 if (im->pixmap == None) { 2299 free (im); 2300 return (None); 2301 } 2302 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2303 for (i = j; i < h - 3; i += 5) { 2304 Draw3DBorder (im->pixmap, 4, i, h - 8, 4, 2, cp, off, True, False); 2305 } 2306 im->mask = None; 2307 im->width = h; 2308 im->height = h; 2309 im->next = None; 2310 if (image == None) { 2311 image = im1 = im; 2312 } 2313 else { 2314 im1->next = im; 2315 im1 = im; 2316 } 2317 } 2318 if (im1 != None) im1->next = image; 2319 return (image); 2320} 2321 2322static Image *Create3DMenuUpAnimation (ColorPair cp) 2323{ 2324 return Create3DMenuAnimation (TRUE, cp); 2325} 2326 2327static Image *Create3DMenuDownAnimation (ColorPair cp) 2328{ 2329 return Create3DMenuAnimation (False, cp); 2330} 2331 2332static Image *Create3DZoomAnimation (Bool in, Bool out, int n, ColorPair cp) 2333{ 2334 int h, i, j, k; 2335 Image *image, *im, *im1; 2336 2337 h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 2338 if (!(h & 1)) h--; 2339 2340 if (n == 0) n = (h/2) - 2; 2341 2342 image = im1 = None; 2343 for (j = (out ? -1 : 1) ; j < (in ? 2 : 0); j += 2){ 2344 for(k = (j > 0 ? 0 : n-1) ; (k >= 0) && (k < n); k += j){ 2345 im = (Image*) malloc (sizeof (struct _Image)); 2346 im->pixmap = XCreatePixmap (dpy, Scr->Root, h, h, Scr->d_depth); 2347 Draw3DBorder (im->pixmap, 0, 0, h, h, Scr->TitleButtonShadowDepth, cp, off, True, False); 2348 for (i = 2 + k; i < (h / 2); i += n) { 2349 Draw3DBorder (im->pixmap, i, i, h - (2 * i), h - (2 * i), 2, cp, off, True, False); 2350 } 2351 im->mask = None; 2352 im->width = h; 2353 im->height = h; 2354 im->next = None; 2355 if (image == None) { 2356 image = im1 = im; 2357 } 2358 else { 2359 im1->next = im; 2360 im1 = im; 2361 } 2362 } 2363 } 2364 if (im1 != None) im1->next = image; 2365 return (image); 2366} 2367 2368static Image *Create3DMazeInAnimation (ColorPair cp) 2369{ 2370 return Create3DZoomAnimation(TRUE, FALSE, 6, cp); 2371} 2372 2373static Image *Create3DMazeOutAnimation (ColorPair cp) 2374{ 2375 return Create3DZoomAnimation(FALSE, TRUE, 6, cp); 2376} 2377 2378static Image *Create3DZoomInAnimation (ColorPair cp) 2379{ 2380 return Create3DZoomAnimation(TRUE, FALSE, 0, cp); 2381} 2382 2383static Image *Create3DZoomOutAnimation (ColorPair cp) 2384{ 2385 return Create3DZoomAnimation(FALSE, TRUE, 0, cp); 2386} 2387 2388static Image *Create3DZoomInOutAnimation (ColorPair cp) 2389{ 2390 return Create3DZoomAnimation(TRUE, TRUE, 0, cp); 2391} 2392 2393#define questionmark_width 8 2394#define questionmark_height 8 2395static char questionmark_bits[] = { 2396 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18}; 2397 2398static Pixmap CreateQuestionPixmap (unsigned int *widthp, 2399 unsigned int *heightp) 2400{ 2401 *widthp = questionmark_width; 2402 *heightp = questionmark_height; 2403 if (Scr->tbpm.question == None) { 2404 Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root, 2405 questionmark_bits, 2406 questionmark_width, 2407 questionmark_height); 2408 } 2409 /* 2410 * this must succeed or else we are in deep trouble elsewhere 2411 */ 2412 return Scr->tbpm.question; 2413} 2414 2415 2416static Pixmap CreateMenuPixmap (unsigned int *widthp, unsigned int *heightp) 2417{ 2418 return (CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,widthp,heightp)); 2419} 2420 2421Pixmap CreateMenuIcon (int height, unsigned int *widthp, unsigned int *heightp) 2422{ 2423 int h, w; 2424 int ih, iw; 2425 int ix, iy; 2426 int mh, mw; 2427 int tw, th; 2428 int lw, lh; 2429 int lx, ly; 2430 int lines, dly; 2431 int offset; 2432 int bw; 2433 2434 h = height; 2435 w = h * 7 / 8; 2436 if (h < 1) 2437 h = 1; 2438 if (w < 1) 2439 w = 1; 2440 *widthp = w; 2441 *heightp = h; 2442 if (Scr->tbpm.menu == None) { 2443 Pixmap pix; 2444 GC gc; 2445 2446 pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1); 2447 gc = XCreateGC (dpy, pix, 0L, NULL); 2448 XSetForeground (dpy, gc, 0L); 2449 XFillRectangle (dpy, pix, gc, 0, 0, w, h); 2450 XSetForeground (dpy, gc, 1L); 2451 ix = 1; 2452 iy = 1; 2453 ih = h - iy * 2; 2454 iw = w - ix * 2; 2455 offset = ih / 8; 2456 mh = ih - offset; 2457 mw = iw - offset; 2458 bw = mh / 16; 2459 if (bw == 0 && mw > 2) 2460 bw = 1; 2461 tw = mw - bw * 2; 2462 th = mh - bw * 2; 2463 XFillRectangle (dpy, pix, gc, ix, iy, mw, mh); 2464 XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh); 2465 XSetForeground (dpy, gc, 0L); 2466 XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th); 2467 XSetForeground (dpy, gc, 1L); 2468 lw = tw / 2; 2469 if ((tw & 1) ^ (lw & 1)) 2470 lw++; 2471 lx = ix + bw + (tw - lw) / 2; 2472 2473 lh = th / 2 - bw; 2474 if ((lh & 1) ^ ((th - bw) & 1)) 2475 lh++; 2476 ly = iy + bw + (th - bw - lh) / 2; 2477 2478 lines = 3; 2479 if ((lh & 1) && lh < 6) 2480 { 2481 lines--; 2482 } 2483 dly = lh / (lines - 1); 2484 while (lines--) 2485 { 2486 XFillRectangle (dpy, pix, gc, lx, ly, lw, bw); 2487 ly += dly; 2488 } 2489 XFreeGC (dpy, gc); 2490 } 2491 return Scr->tbpm.menu; 2492} 2493 2494#define FBGC(gc, fix_fore, fix_back)\ 2495 Gcv.foreground = fix_fore;\ 2496 Gcv.background = fix_back;\ 2497 XChangeGC(dpy, gc, GCForeground|GCBackground,&Gcv) 2498 2499void Draw3DBorder (Window w, int x, int y, int width, int height, int bw, 2500 ColorPair cp, int state, int fill, int forcebw) 2501{ 2502 int i; 2503 XGCValues gcv; 2504 unsigned long gcm; 2505 2506 if ((width < 1) || (height < 1)) return; 2507 if (Scr->Monochrome != COLOR) { 2508 if (fill) { 2509 gcm = GCFillStyle; 2510 gcv.fill_style = FillOpaqueStippled; 2511 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2512 XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height); 2513 } 2514 gcm = 0; 2515 gcm |= GCLineStyle; 2516 gcv.line_style = (state == on) ? LineSolid : LineDoubleDash; 2517 gcm |= GCFillStyle; 2518 gcv.fill_style = FillSolid; 2519 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2520 for (i = 0; i < bw; i++) { 2521 XDrawLine (dpy, w, Scr->BorderGC, x, y + i, 2522 x + width - i - 1, y + i); 2523 XDrawLine (dpy, w, Scr->BorderGC, x + i, y, 2524 x + i, y + height - i - 1); 2525 } 2526 2527 gcm = 0; 2528 gcm |= GCLineStyle; 2529 gcv.line_style = (state == on) ? LineDoubleDash : LineSolid; 2530 gcm |= GCFillStyle; 2531 gcv.fill_style = FillSolid; 2532 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2533 for (i = 0; i < bw; i++) { 2534 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2535 x + width - i - 1, y + height - 1); 2536 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2537 x + width - 1, y + height - i - 1); 2538 } 2539 return; 2540 } 2541 2542 if (fill) { 2543 FBGC (Scr->BorderGC, cp.back, cp.fore); 2544 XFillRectangle (dpy, w, Scr->BorderGC, x, y, width, height); 2545 } 2546 if (Scr->BeNiceToColormap) { 2547 int dashoffset = 0; 2548 2549 gcm = 0; 2550 gcm |= GCLineStyle; 2551 gcv.line_style = (forcebw) ? LineSolid : LineDoubleDash; 2552 gcm |= GCBackground; 2553 gcv.background = cp.back; 2554 XChangeGC (dpy, Scr->BorderGC, gcm, &gcv); 2555 2556 if (state == on) 2557 XSetForeground (dpy, Scr->BorderGC, Scr->Black); 2558 else 2559 XSetForeground (dpy, Scr->BorderGC, Scr->White); 2560 for (i = 0; i < bw; i++) { 2561 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + dashoffset, 2562 x + i, y + height - i - 1); 2563 XDrawLine (dpy, w, Scr->BorderGC, x + dashoffset, y + i, 2564 x + width - i - 1, y + i); 2565 dashoffset = 1 - dashoffset; 2566 } 2567 XSetForeground (dpy, Scr->BorderGC, ((state == on) ? Scr->White : Scr->Black)); 2568 for (i = 0; i < bw; i++) { 2569 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2570 x + width - 1, y + height - i - 1); 2571 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2572 x + width - i - 1, y + height - 1); 2573 } 2574 return; 2575 } 2576 if (state == on) { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); } 2577 else { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); } 2578 for (i = 0; i < bw; i++) { 2579 XDrawLine (dpy, w, Scr->BorderGC, x, y + i, 2580 x + width - i - 1, y + i); 2581 XDrawLine (dpy, w, Scr->BorderGC, x + i, y, 2582 x + i, y + height - i - 1); 2583 } 2584 2585 if (state == on) { FBGC (Scr->BorderGC, cp.shadc, cp.shadd); } 2586 else { FBGC (Scr->BorderGC, cp.shadd, cp.shadc); } 2587 for (i = 0; i < bw; i++) { 2588 XDrawLine (dpy, w, Scr->BorderGC, x + width - i - 1, y + i, 2589 x + width - i - 1, y + height - 1); 2590 XDrawLine (dpy, w, Scr->BorderGC, x + i, y + height - i - 1, 2591 x + width - 1, y + height - i - 1); 2592 } 2593 return; 2594} 2595 2596void Draw3DCorner (Window w, 2597 int x, int y, int width, int height, int thick, int bw, 2598 ColorPair cp, int type) 2599{ 2600 XRectangle rects [2]; 2601 2602 switch (type) { 2603 case 0 : 2604 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2605 Draw3DBorder (w, x + thick - bw, y + thick - bw, 2606 width - thick + 2 * bw, height - thick + 2 * bw, 2607 bw, cp, on, True, False); 2608 break; 2609 case 1 : 2610 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2611 Draw3DBorder (w, x, y + thick - bw, 2612 width - thick + bw, height - thick, 2613 bw, cp, on, True, False); 2614 break; 2615 case 2 : 2616 rects [0].x = x + width - thick; 2617 rects [0].y = y; 2618 rects [0].width = thick; 2619 rects [0].height = height; 2620 rects [1].x = x; 2621 rects [1].y = y + width - thick; 2622 rects [1].width = width - thick; 2623 rects [1].height = thick; 2624 XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted); 2625 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2626 Draw3DBorder (w, x, y, 2627 width - thick + bw, height - thick + bw, 2628 bw, cp, on, True, False); 2629 XSetClipMask (dpy, Scr->BorderGC, None); 2630 break; 2631 case 3 : 2632 rects [0].x = x; 2633 rects [0].y = y; 2634 rects [0].width = thick; 2635 rects [0].height = height; 2636 rects [1].x = x + thick; 2637 rects [1].y = y + height - thick; 2638 rects [1].width = width - thick; 2639 rects [1].height = thick; 2640 XSetClipRectangles (dpy, Scr->BorderGC, 0, 0, rects, 2, Unsorted); 2641 Draw3DBorder (w, x, y, width, height, bw, cp, off, True, False); 2642 Draw3DBorder (w, x + thick - bw, y, 2643 width - thick, height - thick + bw, 2644 bw, cp, on, True, False); 2645 XSetClipMask (dpy, Scr->BorderGC, None); 2646 break; 2647 } 2648 return; 2649} 2650 2651void PaintAllDecoration (void) 2652{ 2653 TwmWindow *tmp_win; 2654 virtualScreen *vs; 2655 2656 for (tmp_win = Scr->FirstWindow; tmp_win != NULL; tmp_win = tmp_win->next) { 2657 if (! visible (tmp_win)) continue; 2658 if (tmp_win->mapped == TRUE) { 2659 if (tmp_win->frame_bw3D) { 2660 if (tmp_win->highlight && tmp_win == Scr->Focus) 2661 PaintBorders (tmp_win, True); 2662 else 2663 PaintBorders (tmp_win, False); 2664 } 2665 if (tmp_win->title_w) PaintTitle (tmp_win); 2666 if (tmp_win->titlebuttons) PaintTitleButtons (tmp_win); 2667 } 2668 else 2669 if ((tmp_win->icon_on == TRUE) && 2670 !tmp_win->icon_not_ours && 2671 !Scr->NoIconTitlebar && 2672 tmp_win->icon && 2673 tmp_win->icon->w && 2674 ! LookInList (Scr->NoIconTitle, tmp_win->full_name, &tmp_win->class)) { 2675 PaintIcon (tmp_win); 2676 } 2677 } 2678 for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) { 2679 PaintWorkSpaceManager (vs); 2680 } 2681} 2682 2683void PaintBorders (TwmWindow *tmp_win, Bool focus) 2684{ 2685 ColorPair cp; 2686 2687 cp = (focus && tmp_win->highlight) ? tmp_win->borderC : tmp_win->border_tile; 2688 if (tmp_win->title_height == 0) { 2689 Draw3DBorder (tmp_win->frame, 2690 0, 2691 0, 2692 tmp_win->frame_width, 2693 tmp_win->frame_height, 2694 Scr->BorderShadowDepth, cp, off, True, False); 2695 Draw3DBorder (tmp_win->frame, 2696 tmp_win->frame_bw3D - Scr->BorderShadowDepth, 2697 tmp_win->frame_bw3D - Scr->BorderShadowDepth, 2698 tmp_win->frame_width - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth, 2699 tmp_win->frame_height - 2 * tmp_win->frame_bw3D + 2 * Scr->BorderShadowDepth, 2700 Scr->BorderShadowDepth, cp, on, True, False); 2701 return; 2702 } 2703 Draw3DCorner (tmp_win->frame, 2704 tmp_win->title_x - tmp_win->frame_bw3D, 2705 0, 2706 Scr->TitleHeight + tmp_win->frame_bw3D, 2707 Scr->TitleHeight + tmp_win->frame_bw3D, 2708 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 0); 2709 Draw3DCorner (tmp_win->frame, 2710 tmp_win->title_x + tmp_win->title_width - Scr->TitleHeight, 2711 0, 2712 Scr->TitleHeight + tmp_win->frame_bw3D, 2713 Scr->TitleHeight + tmp_win->frame_bw3D, 2714 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 1); 2715 Draw3DCorner (tmp_win->frame, 2716 tmp_win->frame_width - (Scr->TitleHeight + tmp_win->frame_bw3D), 2717 tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D), 2718 Scr->TitleHeight + tmp_win->frame_bw3D, 2719 Scr->TitleHeight + tmp_win->frame_bw3D, 2720 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 2); 2721 Draw3DCorner (tmp_win->frame, 2722 0, 2723 tmp_win->frame_height - (Scr->TitleHeight + tmp_win->frame_bw3D), 2724 Scr->TitleHeight + tmp_win->frame_bw3D, 2725 Scr->TitleHeight + tmp_win->frame_bw3D, 2726 tmp_win->frame_bw3D, Scr->BorderShadowDepth, cp, 3); 2727 2728 Draw3DBorder (tmp_win->frame, 2729 tmp_win->title_x + Scr->TitleHeight, 2730 0, 2731 tmp_win->title_width - 2 * Scr->TitleHeight, 2732 tmp_win->frame_bw3D, 2733 Scr->BorderShadowDepth, cp, off, True, False); 2734 Draw3DBorder (tmp_win->frame, 2735 tmp_win->frame_bw3D + Scr->TitleHeight, 2736 tmp_win->frame_height - tmp_win->frame_bw3D, 2737 tmp_win->frame_width - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2738 tmp_win->frame_bw3D, 2739 Scr->BorderShadowDepth, cp, off, True, False); 2740 Draw3DBorder (tmp_win->frame, 2741 0, 2742 Scr->TitleHeight + tmp_win->frame_bw3D, 2743 tmp_win->frame_bw3D, 2744 tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2745 Scr->BorderShadowDepth, cp, off, True, False); 2746 Draw3DBorder (tmp_win->frame, 2747 tmp_win->frame_width - tmp_win->frame_bw3D, 2748 Scr->TitleHeight + tmp_win->frame_bw3D, 2749 tmp_win->frame_bw3D, 2750 tmp_win->frame_height - 2 * (Scr->TitleHeight + tmp_win->frame_bw3D), 2751 Scr->BorderShadowDepth, cp, off, True, False); 2752 2753 if (tmp_win->squeeze_info && !tmp_win->squeezed) { 2754 Draw3DBorder (tmp_win->frame, 2755 0, 2756 Scr->TitleHeight, 2757 tmp_win->title_x, 2758 tmp_win->frame_bw3D, 2759 Scr->BorderShadowDepth, cp, off, True, False); 2760 Draw3DBorder (tmp_win->frame, 2761 tmp_win->title_x + tmp_win->title_width, 2762 Scr->TitleHeight, 2763 tmp_win->frame_width - tmp_win->title_x - tmp_win->title_width, 2764 tmp_win->frame_bw3D, 2765 Scr->BorderShadowDepth, cp, off, True, False); 2766 } 2767} 2768 2769void PaintTitle (TwmWindow *tmp_win) 2770{ 2771 int width, mwidth, len; 2772 XRectangle inc_rect; 2773 XRectangle logical_rect; 2774 2775 if (Scr->use3Dtitles) { 2776 if (Scr->SunkFocusWindowTitle && (Scr->Focus == tmp_win) && 2777 (tmp_win->title_height != 0)) 2778 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 2779 tmp_win->title_width - Scr->TBInfo.titlex - 2780 Scr->TBInfo.rightoff - Scr->TitlePadding, 2781 Scr->TitleHeight, Scr->TitleShadowDepth, 2782 tmp_win->title, on, True, False); 2783 else 2784 Draw3DBorder (tmp_win->title_w, Scr->TBInfo.titlex, 0, 2785 tmp_win->title_width - Scr->TBInfo.titlex - 2786 Scr->TBInfo.rightoff - Scr->TitlePadding, 2787 Scr->TitleHeight, Scr->TitleShadowDepth, 2788 tmp_win->title, off, True, False); 2789 } 2790 FB(tmp_win->title.fore, tmp_win->title.back); 2791 if (Scr->use3Dtitles) { 2792 len = strlen(tmp_win->name); 2793 XmbTextExtents(Scr->TitleBarFont.font_set, 2794 tmp_win->name, strlen (tmp_win->name), 2795 &inc_rect, &logical_rect); 2796 width = logical_rect.width; 2797 mwidth = tmp_win->title_width - Scr->TBInfo.titlex - 2798 Scr->TBInfo.rightoff - Scr->TitlePadding - 2799 Scr->TitleShadowDepth - 4; 2800 while ((len > 0) && (width > mwidth)) { 2801 len--; 2802 XmbTextExtents(Scr->TitleBarFont.font_set, 2803 tmp_win->name, len, 2804 &inc_rect, &logical_rect); 2805 width = logical_rect.width; 2806 } 2807 if (Scr->Monochrome != COLOR) { 2808 XmbDrawImageString(dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2809 Scr->NormalGC, 2810 tmp_win->name_x, 2811 Scr->TitleBarFont.y + Scr->TitleShadowDepth, 2812 tmp_win->name, len); 2813 } 2814 else { 2815 XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2816 Scr->NormalGC, tmp_win->name_x, 2817 Scr->TitleBarFont.y + Scr->TitleShadowDepth, 2818 tmp_win->name, len); 2819 } 2820 } 2821 else 2822 XmbDrawString (dpy, tmp_win->title_w, Scr->TitleBarFont.font_set, 2823 Scr->NormalGC, 2824 tmp_win->name_x, Scr->TitleBarFont.y, 2825 tmp_win->name, strlen(tmp_win->name)); 2826} 2827 2828void PaintIcon (TwmWindow *tmp_win) 2829{ 2830 int width, twidth, mwidth, len, x; 2831 Icon *icon; 2832 XRectangle inc_rect; 2833 XRectangle logical_rect; 2834 2835 if (!tmp_win || !tmp_win->icon) return; 2836 icon = tmp_win->icon; 2837 if (!icon->has_title) return; 2838 2839 x = 0; 2840 width = icon->w_width; 2841 if (Scr->ShrinkIconTitles && icon->title_shrunk) { 2842 x = GetIconOffset (icon); 2843 width = icon->width; 2844 } 2845 len = strlen (tmp_win->icon_name); 2846 XmbTextExtents(Scr->IconFont.font_set, 2847 tmp_win->icon_name, len, 2848 &inc_rect, &logical_rect); 2849 twidth = logical_rect.width; 2850 mwidth = width - 2 * Scr->IconManagerShadowDepth - 6; 2851 if (Scr->use3Diconmanagers) { 2852 Draw3DBorder (icon->w, x, icon->height, width, 2853 Scr->IconFont.height + 2 * Scr->IconManagerShadowDepth + 6, 2854 Scr->IconManagerShadowDepth, icon->iconc, off, False, False); 2855 } 2856 while ((len > 0) && (twidth > mwidth)) { 2857 len--; 2858 XmbTextExtents(Scr->IconFont.font_set, 2859 tmp_win->icon_name, len, 2860 &inc_rect, &logical_rect); 2861 twidth = logical_rect.width; 2862 } 2863 FB (icon->iconc.fore, icon->iconc.back); 2864 XmbDrawString(dpy, icon->w, Scr->IconFont.font_set, Scr->NormalGC, 2865 x + ((mwidth - twidth)/2) + Scr->IconManagerShadowDepth + 3, 2866 icon->y, tmp_win->icon_name, len); 2867} 2868 2869void PaintTitleButton (TwmWindow *tmp_win, TBWindow *tbw) 2870{ 2871 TitleButton *tb = tbw->info; 2872 2873 XCopyArea (dpy, tbw->image->pixmap, tbw->window, Scr->NormalGC, 2874 tb->srcx, tb->srcy, tb->width, tb->height, 2875 tb->dstx, tb->dsty); 2876 return; 2877} 2878 2879void PaintTitleButtons (TwmWindow *tmp_win) 2880{ 2881 int i; 2882 TBWindow *tbw = tmp_win->titlebuttons; 2883 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 2884 2885 if (tbw == NULL) 2886 return; 2887 2888 for (i = 0; i < nb; i++, tbw++) { 2889 PaintTitleButton (tmp_win, tbw); 2890 } 2891} 2892 2893void adoptWindow (void) 2894{ 2895 unsigned long data [2]; 2896 Window localroot, w; 2897 unsigned char *prop; 2898 unsigned long bytesafter; 2899 unsigned long len; 2900 Atom actual_type; 2901 int actual_format; 2902 XEvent event; 2903 Window root, parent, child, *children; 2904 unsigned int nchildren, key_buttons; 2905 int root_x, root_y, win_x, win_y; 2906 int ret; 2907 2908 localroot = w = RootWindow (dpy, Scr->screen); 2909 XGrabPointer (dpy, localroot, False, 2910 ButtonPressMask | ButtonReleaseMask, 2911 GrabModeAsync, GrabModeAsync, 2912 None, Scr->SelectCursor, CurrentTime); 2913 2914 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2915 child = event.xbutton.subwindow; 2916 while (1) { 2917 if (child == (Window) 0) break; 2918 2919 w = XmuClientWindow (dpy, child); 2920 ret = XGetWindowProperty (dpy, w, _XA_WM_WORKSPACESLIST, 0L, 512, 2921 False, XA_STRING, &actual_type, &actual_format, &len, 2922 &bytesafter, &prop); 2923 XFree ((char *)prop); /* Don't ever do anything with it */ 2924 if (ret != Success) 2925 break; 2926 if (len == 0) /* it is not a local root window */ 2927 break; /* it is not a local root window */ 2928 localroot = w; 2929 XQueryPointer (dpy, localroot, &root, &child, &root_x, &root_y, 2930 &win_x, &win_y, &key_buttons); 2931 } 2932 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2933 XUngrabPointer (dpy, CurrentTime); 2934 2935 if (localroot == Scr->Root) return; 2936 if (w == localroot) { /* try to not adopt an ancestor */ 2937 XQueryTree (dpy, Scr->Root, &root, &parent, &children, &nchildren); 2938 while (parent != (Window) 0) { 2939 XFree ((char *) children); 2940 if (w == parent) return; 2941 XQueryTree (dpy, parent, &root, &parent, &children, &nchildren); 2942 } 2943 XFree ((char *) children); 2944 if (w == root) return; 2945 } 2946 if (localroot == RootWindow (dpy, Scr->screen)) { 2947 XWithdrawWindow (dpy, w, Scr->screen); 2948 } 2949 else { 2950 XUnmapWindow (dpy, w); 2951 } 2952 XReparentWindow (dpy, w, Scr->Root, 0, 0); 2953 2954 data [0] = (unsigned long) NormalState; 2955 data [1] = (unsigned long) None; 2956 2957 XChangeProperty (dpy, w, _XA_WM_STATE, _XA_WM_STATE, 32, 2958 PropModeReplace, (unsigned char *) data, 2); 2959 XFlush (dpy); 2960 SimulateMapRequest (w); 2961 return; 2962} 2963 2964void DebugTrace (char *file) 2965{ 2966 if (!file) return; 2967 if (tracefile) { 2968 fprintf (stderr, "stop logging events\n"); 2969 if (tracefile != stderr) fclose (tracefile); 2970 tracefile = NULL; 2971 } 2972 else { 2973 if (strcmp (file, "stderr")) 2974 tracefile = fopen (file, "w"); 2975 else 2976 tracefile = stderr; 2977 fprintf (stderr, "logging events to : %s\n", file); 2978 } 2979} 2980 2981extern Cursor TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor, 2982 LeftCursor, RightCursor, TopCursor, BottomCursor; 2983 2984void SetBorderCursor (TwmWindow *tmp_win, int x, int y) 2985{ 2986 Cursor cursor; 2987 XSetWindowAttributes attr; 2988 int h, fw, fh, wd; 2989 2990 if (!tmp_win) 2991 return; 2992 2993 /* Use the max of these, but since one is always 0 we can add them. */ 2994 wd = tmp_win->frame_bw + tmp_win->frame_bw3D; 2995 h = Scr->TitleHeight + wd; 2996 fw = tmp_win->frame_width; 2997 fh = tmp_win->frame_height; 2998 2999#if defined DEBUG && DEBUG 3000 fprintf(stderr, "wd=%d h=%d, fw=%d fh=%d x=%d y=%d\n", 3001 wd, h, fw, fh, x, y); 3002#endif 3003 3004 /* 3005 * If not using 3D borders: 3006 * 3007 * The left border has negative x coordinates, 3008 * The top border (above the title) has negative y coordinates. 3009 * The title is TitleHeight high, the next wd pixels are border. 3010 * The bottom border has coordinates >= the frame height. 3011 * The right border has coordinates >= the frame width. 3012 * 3013 * If using 3D borders: all coordinates are >= 0, and all coordinates 3014 * are higher by the border width. 3015 * 3016 * Since we only get events when we're actually in the border, we simply 3017 * allow for both cases at the same time. 3018 */ 3019 3020 if ((x < -wd) || (y < -wd)) { 3021 cursor = Scr->FrameCursor; 3022 } else if (x < h) { 3023 if (y < h) 3024 cursor = TopLeftCursor; 3025 else if (y >= fh - h) 3026 cursor = BottomLeftCursor; 3027 else 3028 cursor = LeftCursor; 3029 } else if (x >= fw - h) { 3030 if (y < h) 3031 cursor = TopRightCursor; 3032 else if (y >= fh - h) 3033 cursor = BottomRightCursor; 3034 else 3035 cursor = RightCursor; 3036 } else if (y < h) { /* also include title bar in top border area */ 3037 cursor = TopCursor; 3038 } else if (y >= fh - h) { 3039 cursor = BottomCursor; 3040 } else { 3041 cursor = Scr->FrameCursor; 3042 } 3043 attr.cursor = cursor; 3044 XChangeWindowAttributes (dpy, tmp_win->frame, CWCursor, &attr); 3045 tmp_win->curcurs = cursor; 3046} 3047 3048Image *GetImage (char *name, ColorPair cp) 3049{ 3050 name_list **list; 3051 char fullname [256]; 3052 Image *image; 3053 3054 if (name == NULL) return (None); 3055 image = None; 3056 3057 list = &Scr->ImageCache; 3058#ifdef XPM 3059 if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) { 3060 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3061 3062 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3063 int startn = (name [0] == '@') ? 1 : 4; 3064 if ((image = GetXpmImage (name + startn, cp)) != None) { 3065 AddToList (list, fullname, (char*) image); 3066 } 3067 } 3068 } 3069 else 3070#endif 3071#ifdef JPEG 3072 if (strncmp (name, "jpeg:", 5) == 0) { 3073 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3074 if ((image = GetJpegImage (&name [5])) != None) { 3075 AddToList (list, name, (char*) image); 3076 } 3077 } 3078 } 3079 else 3080#endif 3081#ifdef IMCONV 3082 if (strncmp (name, "im:", 3) == 0) { 3083 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3084 if ((image = GetImconvImage (&name [3])) != None) { 3085 AddToList (list, name, (char*) image); 3086 } 3087 } 3088 } 3089 else 3090#endif 3091#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3092 if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) { 3093 int startn = (name [0] == '|') ? 0 : 4; 3094 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3095 if ((image = GetXwdImage (&name [startn], cp)) != None) { 3096 AddToList (list, name, (char*) image); 3097 } 3098 } 3099 } 3100 else 3101#endif 3102 if (strncmp (name, ":xpm:", 5) == 0) { 3103 int i; 3104 static struct { 3105 char *name; 3106 Image* (*proc)(ColorPair colorpair); 3107 } pmtab[] = { 3108 { TBPM_3DDOT, Create3DDotImage }, 3109 { TBPM_3DRESIZE, Create3DResizeImage }, 3110 { TBPM_3DMENU, Create3DMenuImage }, 3111 { TBPM_3DZOOM, Create3DZoomImage }, 3112 { TBPM_3DBAR, Create3DBarImage }, 3113 { TBPM_3DVBAR, Create3DVertBarImage }, 3114 { TBPM_3DCROSS, Create3DCrossImage }, 3115 { TBPM_3DICONIFY, Create3DIconifyImage }, 3116 { TBPM_3DSUNKEN_RESIZE, Create3DSunkenResizeImage }, 3117 { TBPM_3DBOX, Create3DBoxImage } 3118 }; 3119 3120 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3121 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3122 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3123 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3124 image = (*pmtab[i].proc) (cp); 3125 if (image == None) { 3126 fprintf (stderr, 3127 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3128 return (None); 3129 } 3130 break; 3131 } 3132 } 3133 if (image == None) { 3134 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3135 return (None); 3136 } 3137 AddToList (list, fullname, (char*) image); 3138 } 3139 } 3140 else 3141 if (strncmp (name, "%xpm:", 5) == 0) { 3142 int i; 3143 static struct { 3144 char *name; 3145 Image* (*proc)(ColorPair colorpair); 3146 } pmtab[] = { 3147 { "%xpm:menu-up", Create3DMenuUpAnimation }, 3148 { "%xpm:menu-down", Create3DMenuDownAnimation }, 3149 { "%xpm:resize", Create3DZoomOutAnimation }, /* compatibility */ 3150 { "%xpm:resize-out-top", Create3DResizeInTopAnimation }, 3151 { "%xpm:resize-in-top", Create3DResizeOutTopAnimation }, 3152 { "%xpm:resize-out-bot", Create3DResizeInBotAnimation }, 3153 { "%xpm:resize-in-bot", Create3DResizeOutBotAnimation }, 3154 { "%xpm:maze-out", Create3DMazeOutAnimation }, 3155 { "%xpm:maze-in", Create3DMazeInAnimation }, 3156 { "%xpm:zoom-out", Create3DZoomOutAnimation }, 3157 { "%xpm:zoom-in", Create3DZoomInAnimation }, 3158 { "%xpm:zoom-inout", Create3DZoomInOutAnimation } 3159 }; 3160 3161 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3162 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3163 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3164 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3165 image = (*pmtab[i].proc) (cp); 3166 if (image == None) { 3167 fprintf (stderr, 3168 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3169 return (None); 3170 } 3171 break; 3172 } 3173 } 3174 if (image == None) { 3175 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3176 return (None); 3177 } 3178 AddToList (list, fullname, (char*) image); 3179 } 3180 } 3181 else 3182 if (name [0] == ':') { 3183 int i; 3184 unsigned int width, height; 3185 Pixmap pm = 0; 3186 XGCValues gcvalues; 3187 static struct { 3188 char *name; 3189 Pixmap (*proc)(unsigned int *widthp, unsigned int *heightp); 3190 } pmtab[] = { 3191 { TBPM_DOT, CreateDotPixmap }, 3192 { TBPM_ICONIFY, CreateDotPixmap }, 3193 { TBPM_RESIZE, CreateResizePixmap }, 3194 { TBPM_XLOGO, CreateXLogoPixmap }, 3195 { TBPM_DELETE, CreateXLogoPixmap }, 3196 { TBPM_MENU, CreateMenuPixmap }, 3197 { TBPM_QUESTION, CreateQuestionPixmap }, 3198 }; 3199 3200 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3201 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3202 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3203 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3204 pm = (*pmtab[i].proc) (&width, &height); 3205 if (pm == None) { 3206 fprintf (stderr, 3207 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3208 return (None); 3209 } 3210 break; 3211 } 3212 } 3213 if (pm == None) { 3214 fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", ProgramName, name); 3215 return (None); 3216 } 3217 image = (Image*) malloc (sizeof (struct _Image)); 3218 image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 3219 if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues); 3220 gcvalues.background = cp.back; 3221 gcvalues.foreground = cp.fore; 3222 XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues); 3223 XCopyPlane (dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0, 3224 (unsigned long) 1); 3225 image->mask = None; 3226 image->width = width; 3227 image->height = height; 3228 image->next = None; 3229 AddToList (list, fullname, (char*) image); 3230 } 3231 } 3232 else { 3233 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3234 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3235 if ((image = GetBitmapImage (name, cp)) != None) { 3236 AddToList (list, fullname, (char*) image); 3237 } 3238 } 3239 } 3240 return (image); 3241} 3242 3243void FreeImage (Image *image) 3244{ 3245 Image *im, *im2; 3246 3247 im = image; 3248 while (im != None) { 3249 if (im->pixmap) XFreePixmap (dpy, im->pixmap); 3250 if (im->mask) XFreePixmap (dpy, im->mask); 3251 im2 = im->next; 3252 free (im); 3253 im = im2; 3254 } 3255} 3256 3257#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3258static void compress (XImage *image, XColor *colors, int *ncolors); 3259 3260static Image *LoadXwdImage (char *filename, ColorPair cp) 3261{ 3262 FILE *file; 3263 char *fullname; 3264 XColor colors [256]; 3265 XWDColor xwdcolors [256]; 3266 unsigned buffer_size; 3267 XImage *image; 3268 unsigned char *imagedata; 3269 Pixmap pixret; 3270 Visual *visual; 3271 char win_name [256]; 3272 int win_name_size; 3273 int ispipe; 3274 int i, len; 3275 int w, h, depth, ncolors; 3276 int scrn; 3277 Colormap cmap; 3278 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3279 GC gc; 3280 XGCValues gcvalues; 3281 XWDFileHeader header; 3282 Image *ret; 3283 Bool anim; 3284 unsigned long swaptest = 1; 3285 3286 ispipe = 0; 3287 anim = False; 3288#ifndef VMS 3289 if (filename [0] == '|') { 3290 file = (FILE*) popen (filename + 1, "r"); 3291 if (file == NULL) return (None); 3292 ispipe = 1; 3293 anim = AnimationActive; 3294 if (anim) StopAnimation (); 3295 goto file_opened; 3296 } 3297#endif 3298 fullname = ExpandPixmapPath (filename); 3299 if (! fullname) return (None); 3300 file = fopen (fullname, "r"); 3301 free (fullname); 3302 if (file == NULL) { 3303 if (reportfilenotfound) fprintf (stderr, "unable to locate %s\n", filename); 3304 return (None); 3305 } 3306file_opened: 3307 len = fread ((char *) &header, sizeof (header), 1, file); 3308 if (len != 1) { 3309 fprintf (stderr, "ctwm: cannot read %s\n", filename); 3310#ifdef USE_SIGNALS 3311 if (ispipe && anim) StartAnimation (); 3312#endif 3313 return (None); 3314 } 3315 if (*(char *) &swaptest) _swaplong ((char *) &header, sizeof (header)); 3316 if (header.file_version != XWD_FILE_VERSION) { 3317 fprintf(stderr,"ctwm: XWD file format version mismatch : %s\n", filename); 3318 return (None); 3319 } 3320 win_name_size = header.header_size - sizeof (header); 3321 len = fread (win_name, win_name_size, 1, file); 3322 if (len != 1) { 3323 fprintf (stderr, "file %s has not the correct format\n", filename); 3324#ifdef USE_SIGNALS 3325 if (ispipe && anim) StartAnimation (); 3326#endif 3327 return (None); 3328 } 3329 3330 if (header.pixmap_format == XYPixmap) { 3331 fprintf (stderr,"ctwm: XYPixmap XWD file not supported : %s\n", filename); 3332 return (None); 3333 } 3334 w = header.pixmap_width; 3335 h = header.pixmap_height; 3336 depth = header.pixmap_depth; 3337 ncolors = header.ncolors; 3338 len = fread ((char *) xwdcolors, sizeof (XWDColor), ncolors, file); 3339 if (len != ncolors) { 3340 fprintf (stderr, "file %s has not the correct format\n", filename); 3341#ifdef USE_SIGNALS 3342 if (ispipe && anim) StartAnimation (); 3343#endif 3344 return (None); 3345 } 3346 if (*(char *) &swaptest) { 3347 for (i = 0; i < ncolors; i++) { 3348 _swaplong ((char *) &xwdcolors [i].pixel, 4); 3349 _swapshort ((char *) &xwdcolors [i].red, 3 * 2); 3350 } 3351 } 3352 for (i = 0; i < ncolors; i++) { 3353 colors [i].pixel = xwdcolors [i].pixel; 3354 colors [i].red = xwdcolors [i].red; 3355 colors [i].green = xwdcolors [i].green; 3356 colors [i].blue = xwdcolors [i].blue; 3357 colors [i].flags = xwdcolors [i].flags; 3358 colors [i].pad = xwdcolors [i].pad; 3359 } 3360 3361 scrn = Scr->screen; 3362 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3363 visual = Scr->d_visual; 3364 gc = DefaultGC (dpy, scrn); 3365 3366 buffer_size = header.bytes_per_line * h; 3367 imagedata = (unsigned char*) malloc (buffer_size); 3368 if (! imagedata) { 3369 fprintf (stderr, "cannot allocate memory for image %s\n", filename); 3370#ifdef USE_SIGNALS 3371 if (ispipe && anim) StartAnimation (); 3372#endif 3373 return (None); 3374 } 3375 len = fread (imagedata, (int) buffer_size, 1, file); 3376 if (len != 1) { 3377 free (imagedata); 3378 fprintf (stderr, "file %s has not the correct format\n", filename); 3379#ifdef USE_SIGNALS 3380 if (ispipe && anim) StartAnimation (); 3381#endif 3382 return (None); 3383 } 3384#ifndef VMS 3385 if (ispipe) 3386 pclose (file); 3387 else 3388#endif 3389 fclose (file); 3390 3391 image = XCreateImage (dpy, visual, depth, header.pixmap_format, 3392 0, (char*) imagedata, w, h, 3393 header.bitmap_pad, header.bytes_per_line); 3394 if (image == None) { 3395 free (imagedata); 3396 fprintf (stderr, "cannot create image for %s\n", filename); 3397#ifdef USE_SIGNALS 3398 if (ispipe && anim) StartAnimation (); 3399#endif 3400 return (None); 3401 } 3402 if (header.pixmap_format == ZPixmap) { 3403 compress (image, colors, &ncolors); 3404 } 3405 if (header.pixmap_format != XYBitmap) { 3406 for (i = 0; i < ncolors; i++) { 3407 XAllocColor (dpy, cmap, &(colors [i])); 3408 } 3409 for (i = 0; i < buffer_size; i++) { 3410 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3411 } 3412 } 3413 if (w > Scr->rootw) w = Scr->rootw; 3414 if (h > Scr->rooth) h = Scr->rooth; 3415 3416 ret = (Image*) malloc (sizeof (struct _Image)); 3417 if (! ret) { 3418 fprintf (stderr, "unable to allocate memory for image : %s\n", filename); 3419 free (image); 3420 free (imagedata); 3421 for (i = 0; i < ncolors; i++) { 3422 XFreeColors (dpy, cmap, &(colors [i].pixel), 1, 0L); 3423 } 3424#ifdef USE_SIGNALS 3425 if (ispipe && anim) StartAnimation (); 3426#endif 3427 return (None); 3428 } 3429 if (header.pixmap_format == XYBitmap) { 3430 gcvalues.foreground = cp.fore; 3431 gcvalues.background = cp.back; 3432 XChangeGC (dpy, gc, GCForeground | GCBackground, &gcvalues); 3433 } 3434 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3435 int x, y; 3436 3437 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, 3438 Scr->rooth, Scr->d_depth); 3439 x = (Scr->rootw - w) / 2; 3440 y = (Scr->rooth - h) / 2; 3441 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3442 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3443 ret->width = Scr->rootw; 3444 ret->height = Scr->rooth; 3445 } 3446 else { 3447 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3448 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3449 ret->width = w; 3450 ret->height = h; 3451 } 3452 XDestroyImage (image); 3453 3454 ret->pixmap = pixret; 3455 ret->mask = None; 3456 ret->next = None; 3457#ifdef USE_SIGNALS 3458 if (ispipe && anim) StartAnimation (); 3459#endif 3460 return (ret); 3461} 3462 3463static Image *GetXwdImage (char *name, ColorPair cp) 3464{ 3465 Image *image, *r, *s; 3466 char path [128]; 3467 char pref [128], *perc; 3468 int i; 3469 3470 if (! strchr (name, '%')) return (LoadXwdImage (name, cp)); 3471 s = image = None; 3472 strcpy (pref, name); 3473 perc = strchr (pref, '%'); 3474 *perc = '\0'; 3475 reportfilenotfound = 0; 3476 for (i = 1;; i++) { 3477 sprintf (path, "%s%d%s", pref, i, perc + 1); 3478 r = LoadXwdImage (path, cp); 3479 if (r == None) break; 3480 r->next = None; 3481 if (image == None) s = image = r; 3482 else { 3483 s->next = r; 3484 s = r; 3485 } 3486 } 3487 reportfilenotfound = 1; 3488 if (s != None) s->next = image; 3489 if (image == None) { 3490 fprintf (stderr, "Cannot open any %s xwd file\n", name); 3491 } 3492 return (image); 3493} 3494 3495static void compress (XImage *image, XColor *colors, int *ncolors) 3496{ 3497 unsigned char ind [256]; 3498 unsigned int used [256]; 3499 int i, j, size, nused; 3500 unsigned char color; 3501 XColor newcolors [256]; 3502 unsigned char *imagedata; 3503 3504 for (i = 0; i < 256; i++) { 3505 used [i] = 0; 3506 ind [i] = 0; 3507 } 3508 nused = 0; 3509 size = image->bytes_per_line * image->height; 3510 imagedata = (unsigned char *) image->data; 3511 for (i = 0; i < size; i++) { 3512 if ((i % image->bytes_per_line) > image->width) continue; 3513 color = imagedata [i]; 3514 if (used [color] == 0) { 3515 for (j = 0; j < nused; j++) { 3516 if ((colors [color].red == newcolors [j].red) && 3517 (colors [color].green == newcolors [j].green) && 3518 (colors [color].blue == newcolors [j].blue)) break; 3519 } 3520 ind [color] = j; 3521 used [color] = 1; 3522 if (j == nused) { 3523 newcolors [j].red = colors [color].red; 3524 newcolors [j].green = colors [color].green; 3525 newcolors [j].blue = colors [color].blue; 3526 nused++; 3527 } 3528 } 3529 } 3530 for (i = 0; i < size; i++) { 3531 imagedata [i] = ind [imagedata [i]]; 3532 } 3533 for (i = 0; i < nused; i++) { 3534 colors [i] = newcolors [i]; 3535 } 3536 *ncolors = nused; 3537} 3538#endif 3539 3540#ifdef IMCONV 3541 3542static void free_images (); 3543 3544static Image *GetImconvImage (char *filename, 3545 unsigned int *widthp, unsigned int *heightp) 3546{ 3547 TagTable *toolInTable; 3548 ImVfb *sourceVfb; 3549 ImVfbPtr vptr; 3550 ImClt *clt; 3551 int i, j, ij, k, retval; 3552 3553 XColor colors [256]; 3554 unsigned buffer_size; 3555 XImage *image; 3556 unsigned char *imagedata; 3557 Pixmap pixret; 3558 Visual *visual; 3559 int w, h, depth, ncolors; 3560 int scrn; 3561 Colormap cmap; 3562 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3563 GC gc; 3564 unsigned char red, green, blue; 3565 int icol; 3566 char *fullname; 3567 3568 TagEntry *dataEntry; 3569 FILE *fp; 3570 char the_format[1024]; 3571 char *tmp_format; 3572 Image *ret; 3573 3574 if (*filename == NULL) return (None); 3575 fullname = ExpandPixmapPath (filename); 3576 if (! fullname) return (None); 3577 3578 fp = fopen (fullname, "r"); 3579 if (!fp) { 3580 if (reportfilenotfound) fprintf (stderr, "Cannot open the image %s\n", filename); 3581 free (fullname); 3582 return (None); 3583 } 3584 if ((toolInTable = TagTableAlloc ()) == TAGTABLENULL ) { 3585 fprintf (stderr, "TagTableAlloc failed\n"); 3586 free_images (toolInTable); 3587 free (fullname); 3588 return (None); 3589 } 3590 if ((tmp_format = ImFileQFFormat (fp, fullname)) == NULL) { 3591 fprintf (stderr, "Cannot determine image type of %s\n", filename); 3592 free_images (toolInTable); 3593 free (fullname); 3594 return (None); 3595 } 3596 strcpy (the_format, tmp_format); 3597 retval = ImFileFRead (fp, the_format, NULL, toolInTable); 3598 if(retval < 0) { 3599 fprintf(stderr, "Cannot read image file %s: ", fullname); 3600 switch(ImErrNo) { 3601 case IMESYS: 3602 fprintf (stderr, "System call error\n"); 3603 break; 3604 case IMEMALLOC: 3605 fprintf (stderr, "Cannot allocate memory\n"); 3606 break; 3607 case IMEFORMAT: 3608 fprintf (stderr, "Data in file is corrupt\n"); 3609 break; 3610 case IMENOREAD: 3611 fprintf (stderr, "Sorry, this format is write-only\n"); 3612 break; 3613 case IMEMAGIC: 3614 fprintf (stderr, "Bad magic number in image file\n"); 3615 break; 3616 case IMEDEPTH: 3617 fprintf (stderr, "Unknown image depth\n"); 3618 break; 3619 default: 3620 fprintf(stderr, "Unknown error\n"); 3621 break; 3622 } 3623 free_images (toolInTable); 3624 free (fullname); 3625 return (None); 3626 } 3627 3628 if (TagTableQNEntry (toolInTable, "image vfb") == 0) { 3629 fprintf (stderr, "Image file %s contains no images\n", fullname); 3630 free_images (toolInTable); 3631 free (fullname); 3632 return (None); 3633 } 3634 dataEntry = TagTableQDirect (toolInTable, "image vfb", 0); 3635 TagEntryQValue (dataEntry, &sourceVfb); 3636 fclose (fp); 3637 3638 w = ImVfbQWidth (sourceVfb); 3639 h = ImVfbQHeight (sourceVfb); 3640 depth = 8 * ImVfbQNBytes (sourceVfb); 3641 if (depth != 8) { 3642 fprintf (stderr, "I don't know yet how to deal with images not of 8 planes depth\n"); 3643 free_images (toolInTable); 3644 return (None); 3645 } 3646 3647 *width = w; 3648 *height = h; 3649 3650 scrn = Scr->screen; 3651 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3652 visual = Scr->d_visual; 3653 gc = DefaultGC (dpy, scrn); 3654 3655 buffer_size = w * h; 3656 imagedata = (unsigned char*) malloc (buffer_size); 3657 if (imagedata == (unsigned char*) 0) { 3658 fprintf (stderr, "Can't alloc enough space for background images\n"); 3659 free_images (toolInTable); 3660 return (None); 3661 } 3662 3663 clt = ImVfbQClt (sourceVfb); 3664 vptr = ImVfbQFirst (sourceVfb); 3665 ncolors = 0; 3666 for (i = 0; i < h - 1; i++) { 3667 for (j = 0; j < w; j++) { 3668 ij = (i * w) + j; 3669 red = ImCltQRed (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3670 green = ImCltQGreen (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3671 blue = ImCltQBlue (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3672 for (k = 0; k < ncolors; k++) { 3673 if ((colors [k].red == red) && 3674 (colors [k].green == green) && 3675 (colors [k].blue == blue)) { 3676 icol = k; 3677 break; 3678 } 3679 } 3680 if (k == ncolors) { 3681 icol = ncolors; 3682 ncolors++; 3683 } 3684 imagedata [ij] = icol; 3685 colors [icol].red = red; 3686 colors [icol].green = green; 3687 colors [icol].blue = blue; 3688 ImVfbSInc (sourceVfb, vptr); 3689 } 3690 } 3691 for (i = 0; i < ncolors; i++) { 3692 colors [i].red *= 256; 3693 colors [i].green *= 256; 3694 colors [i].blue *= 256; 3695 } 3696 for (i = 0; i < ncolors; i++) { 3697 if (! XAllocColor (dpy, cmap, &(colors [i]))) { 3698 fprintf (stderr, "can't alloc color for image %s\n", filename); 3699 } 3700 } 3701 for (i = 0; i < buffer_size; i++) { 3702 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3703 } 3704 3705 image = XCreateImage (dpy, visual, depth, ZPixmap, 0, (char*) imagedata, w, h, 8, 0); 3706 if (w > Scr->rootw) w = Scr->rootw; 3707 if (h > Scr->rooth) h = Scr->rooth; 3708 3709 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3710 int x, y; 3711 3712 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, depth); 3713 x = (Scr->rootw - w) / 2; 3714 y = (Scr->rooth - h) / 2; 3715 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3716 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3717 ret->width = Scr->rootw; 3718 ret->height = Scr->rooth; 3719 } 3720 else { 3721 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3722 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3723 ret->width = w; 3724 ret->height = h; 3725 } 3726 XFree (image); 3727 ret = (Image*) malloc (sizeof (struct _Image)); 3728 ret->pixmap = pixret; 3729 ret->mask = None; 3730 ret->next = None; 3731 return (ret); 3732 3733} 3734 3735static void free_images (table) 3736TagTable *table; 3737{ 3738 int i, n; 3739 ImVfb *v; 3740 ImClt *c; 3741 TagEntry *dataEntry; 3742 3743 n = TagTableQNEntry (table, "image vfb"); 3744 for (i = 0 ; i < n ; i++) { 3745 dataEntry = TagTableQDirect (table, "image vfb", i); 3746 TagEntryQValue (dataEntry, &v); 3747 ImVfbFree (v); 3748 } 3749 n = TagTableQNEntry (table, "image clt"); 3750 for (i = 0 ; i < n ; i++) { 3751 dataEntry = TagTableQDirect (table, "image clt", i ); 3752 TagEntryQValue (dataEntry, &c); 3753 ImCltFree (c); 3754 } 3755 TagTableFree (table); 3756} 3757 3758#endif 3759 3760void _swapshort (register char *bp, register unsigned n) 3761{ 3762 register char c; 3763 register char *ep = bp + n; 3764 3765 while (bp < ep) { 3766 c = *bp; 3767 *bp = *(bp + 1); 3768 bp++; 3769 *bp++ = c; 3770 } 3771} 3772 3773void _swaplong (register char *bp, register unsigned n) 3774{ 3775 register char c; 3776 register char *ep = bp + n; 3777 register char *sp; 3778 3779 while (bp < ep) { 3780 sp = bp + 3; 3781 c = *sp; 3782 *sp = *bp; 3783 *bp++ = c; 3784 sp = bp + 1; 3785 c = *sp; 3786 *sp = *bp; 3787 *bp++ = c; 3788 bp += 2; 3789 } 3790} 3791 3792/*********************************************************************** 3793 * 3794 * Procedure: 3795 * GetWMPropertyString - Get Window Manager text property and 3796 * convert it to a string. 3797 * 3798 * Returned Value: 3799 * (char *) - pointer to the malloc'd string or NULL 3800 * 3801 * Inputs: 3802 * w - the id of the window whose property is to be retrieved 3803 * prop - property atom (typically WM_NAME or WM_ICON_NAME) 3804 * 3805 *********************************************************************** 3806 */ 3807 3808unsigned char *GetWMPropertyString(Window w, Atom prop) 3809{ 3810 XTextProperty text_prop; 3811 char **text_list; 3812 int text_list_count; 3813 Atom XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False); 3814 unsigned char *stringptr; 3815 int status, len = -1; 3816 3817 (void)XGetTextProperty(dpy, w, &text_prop, prop); 3818 if (text_prop.value != NULL) { 3819 if (text_prop.encoding == XA_STRING 3820 || text_prop.encoding == XA_COMPOUND_TEXT) { 3821 /* property is encoded as compound text - convert to locale string */ 3822 status = XmbTextPropertyToTextList(dpy, &text_prop, 3823 &text_list, &text_list_count); 3824 if (text_list_count == 0) { 3825 stringptr = NULL; 3826 } else 3827 if (text_list == (char **)0) { 3828 stringptr = NULL; 3829 } else 3830 if (text_list [0] == (char *)0) { 3831 stringptr = NULL; 3832 } else 3833 if (status < 0 || text_list_count < 0) { 3834 switch (status) { 3835 case XConverterNotFound: 3836 fprintf (stderr, "%s: Converter not found; unable to convert property %s of window ID %lx.\n", 3837 ProgramName, XGetAtomName(dpy, prop), w); 3838 break; 3839 case XNoMemory: 3840 fprintf (stderr, "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n", 3841 ProgramName, XGetAtomName(dpy, prop), w); 3842 break; 3843 case XLocaleNotSupported: 3844 fprintf (stderr, "%s: Locale not supported; unable to convert property %s of window ID %lx.\n", 3845 ProgramName, XGetAtomName(dpy, prop), w); 3846 break; 3847 } 3848 stringptr = NULL; 3849 /* 3850 don't call XFreeStringList - text_list appears to have 3851 invalid address if status is bad 3852 XFreeStringList(text_list); 3853 */ 3854 } else { 3855 len = strlen(text_list[0]); 3856 stringptr = memcpy(malloc(len+1), text_list[0], len+1); 3857 XFreeStringList(text_list); 3858 } 3859 } else { 3860 /* property is encoded in a format we don't understand */ 3861 fprintf (stderr, "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n", 3862 ProgramName, XGetAtomName(dpy, prop), w); 3863 stringptr = NULL; 3864 } 3865 XFree (text_prop.value); 3866 } else { 3867 stringptr = NULL; 3868 } 3869 3870 return stringptr; 3871} 3872 3873void FreeWMPropertyString(char *prop) 3874{ 3875 if (prop && (char *)prop != NoName) { 3876 free(prop); 3877 } 3878} 3879 3880static void ConstrainLeftTop (int *value, int border) 3881{ 3882 if (*value < border) { 3883 if (Scr->MoveOffResistance < 0 || 3884 *value > border - Scr->MoveOffResistance) 3885 { 3886 *value = border; 3887 } else if (Scr->MoveOffResistance > 0 && 3888 *value <= border - Scr->MoveOffResistance) 3889 { 3890 *value = *value + Scr->MoveOffResistance; 3891 } 3892 } 3893} 3894 3895static void ConstrainRightBottom (int *value, int size1, int border, int size2) 3896{ 3897 if (*value + size1 > size2 - border) { 3898 if (Scr->MoveOffResistance < 0 || 3899 *value + size1 < size2 - border + Scr->MoveOffResistance) 3900 { 3901 *value = size2 - size1 - border; 3902 } else if (Scr->MoveOffResistance > 0 && 3903 *value + size1 >= size2 - border + Scr->MoveOffResistance) { 3904 *value = *value - Scr->MoveOffResistance; 3905 } 3906 } 3907} 3908 3909void ConstrainByBorders1 (int *left, int width, int *top, int height) 3910{ 3911 ConstrainRightBottom (left, width, Scr->BorderRight, Scr->rootw); 3912 ConstrainLeftTop (left, Scr->BorderLeft); 3913 ConstrainRightBottom (top, height, Scr->BorderBottom, Scr->rooth); 3914 ConstrainLeftTop (top, Scr->BorderTop); 3915} 3916 3917void ConstrainByBorders (TwmWindow *twmwin, 3918 int *left, int width, int *top, int height) 3919{ 3920 if (twmwin->winbox) { 3921 XWindowAttributes attr; 3922 XGetWindowAttributes (dpy, twmwin->winbox->window, &attr); 3923 ConstrainRightBottom (left, width, 0, attr.width); 3924 ConstrainLeftTop (left, 0); 3925 ConstrainRightBottom (top, height, 0, attr.height); 3926 ConstrainLeftTop (top, 0); 3927 } else { 3928 ConstrainByBorders1 (left, width, top, height); 3929 } 3930} 3931 3932#ifdef JPEG 3933 3934uint16_t *buffer_16bpp; 3935uint32_t *buffer_32bpp; 3936 3937static void convert_for_16 (int w, int x, int y, int r, int g, int b) { 3938 buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3); 3939} 3940 3941static void convert_for_32 (int w, int x, int y, int r, int g, int b) { 3942 buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF; 3943} 3944 3945static void jpeg_error_exit (j_common_ptr cinfo) { 3946 jerr_ptr errmgr = (jerr_ptr) cinfo->err; 3947 cinfo->err->output_message (cinfo); 3948 siglongjmp (errmgr->setjmp_buffer, 1); 3949 return; 3950} 3951 3952static Image *GetJpegImage (char *name) 3953{ 3954 Image *image, *r, *s; 3955 char path [128]; 3956 char pref [128], *perc; 3957 int i; 3958 3959 if (! strchr (name, '%')) return (LoadJpegImage (name)); 3960 s = image = None; 3961 strcpy (pref, name); 3962 perc = strchr (pref, '%'); 3963 *perc = '\0'; 3964 reportfilenotfound = 0; 3965 for (i = 1;; i++) { 3966 sprintf (path, "%s%d%s", pref, i, perc + 1); 3967 r = LoadJpegImage (path); 3968 if (r == None) break; 3969 r->next = None; 3970 if (image == None) s = image = r; 3971 else { 3972 s->next = r; 3973 s = r; 3974 } 3975 } 3976 reportfilenotfound = 1; 3977 if (s != None) s->next = image; 3978 if (image == None) { 3979 fprintf (stderr, "Cannot open any %s jpeg file\n", name); 3980 } 3981 return (image); 3982} 3983 3984static Image *LoadJpegImage (char *name) 3985{ 3986 char *fullname; 3987 XImage *ximage; 3988 FILE *infile; 3989 Image *image; 3990 Pixmap pixret; 3991 void (*store_data) (int w, int x, int y, int r, int g, int b); 3992 struct jpeg_decompress_struct cinfo; 3993 struct jpeg_error jerr; 3994 JSAMPARRAY buffer; 3995 int width, height; 3996 int row_stride; 3997 int g, i, a; 3998 int bpix; 3999 GC gc; 4000 4001 fullname = ExpandPixmapPath (name); 4002 if (! fullname) return (None); 4003 4004 image = (Image*) malloc (sizeof (struct _Image)); 4005 if (image == None) return (None); 4006 4007 if ((infile = fopen (fullname, "rb")) == NULL) { 4008 if (!reportfilenotfound) fprintf (stderr, "unable to locate %s\n", fullname); 4009 fflush (stdout); 4010 return None; 4011 } 4012 cinfo.err = jpeg_std_error (&jerr.pub); 4013 jerr.pub.error_exit = jpeg_error_exit; 4014 4015 if (sigsetjmp(jerr.setjmp_buffer, 1)) { 4016 jpeg_destroy_decompress (&cinfo); 4017 fclose (infile); 4018 return None; 4019 } 4020 jpeg_create_decompress (&cinfo); 4021 jpeg_stdio_src (&cinfo, infile); 4022 jpeg_read_header (&cinfo, FALSE); 4023 cinfo.do_fancy_upsampling = FALSE; 4024 cinfo.do_block_smoothing = FALSE; 4025 jpeg_start_decompress (&cinfo); 4026 width = cinfo.output_width; 4027 height = cinfo.output_height; 4028 4029 if (Scr->d_depth == 16) { 4030 store_data = &convert_for_16; 4031 buffer_16bpp = (unsigned short int *) malloc ((width) * (height) * 2); 4032 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4033 (char *) buffer_16bpp, width, height, 16, width * 2); 4034 } else { 4035 if (Scr->d_depth == 24) { 4036 store_data = &convert_for_32; 4037 buffer_32bpp = malloc (width * height * 4); 4038 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4039 (char *) buffer_32bpp, width, height, 32, width * 4); 4040 } else 4041 if (Scr->d_depth == 32) { 4042 store_data = &convert_for_32; 4043 buffer_32bpp = malloc (width * height * 4); 4044 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4045 (char *) buffer_32bpp, width, height, 32, width * 4); 4046 } else { 4047 fprintf (stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth); 4048 return None; 4049 } 4050 } 4051 if (ximage == None) { 4052 fprintf (stderr, "cannot create image for %s\n", name); 4053 } 4054 g = 0; 4055 row_stride = cinfo.output_width * cinfo.output_components; 4056 buffer = (*cinfo.mem->alloc_sarray) 4057 ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1); 4058 4059 bpix = cinfo.output_components; 4060 while (cinfo.output_scanline < cinfo.output_height) { 4061 jpeg_read_scanlines (&cinfo, buffer, 1); 4062 a = 0; 4063 for (i = 0; i < bpix * cinfo.output_width; i += bpix) { 4064 (*store_data) (width, a, g, buffer[0][i], buffer[0][i + 1], buffer[0][i + 2]); 4065 a++; 4066 } 4067 g++; 4068 } 4069 jpeg_finish_decompress (&cinfo); 4070 jpeg_destroy_decompress (&cinfo); 4071 fclose (infile); 4072 4073 gc = DefaultGC (dpy, Scr->screen); 4074 if ((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) { 4075 int x, y; 4076 4077 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth); 4078 x = (Scr->rootw - width) / 2; 4079 y = (Scr->rooth - height) / 2; 4080 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 4081 XPutImage (dpy, pixret, gc, ximage, 0, 0, x, y, width, height); 4082 image->width = Scr->rootw; 4083 image->height = Scr->rooth; 4084 } else { 4085 pixret = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 4086 XPutImage (dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height); 4087 image->width = width; 4088 image->height = height; 4089 } 4090 XDestroyImage (ximage); 4091 image->pixmap = pixret; 4092 image->mask = None; 4093 image->next = None; 4094 4095 return image; 4096} 4097 4098#endif /* JPEG */ 4099