util.c revision 645f5050
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; 2883 int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 2884 2885 for (i = 0, tbw = tmp_win->titlebuttons; i < nb; i++, tbw++) { 2886 if (tbw) PaintTitleButton (tmp_win, tbw); 2887 } 2888} 2889 2890void adoptWindow (void) 2891{ 2892 unsigned long data [2]; 2893 Window localroot, w; 2894 unsigned char *prop; 2895 unsigned long bytesafter; 2896 unsigned long len; 2897 Atom actual_type; 2898 int actual_format; 2899 XEvent event; 2900 Window root, parent, child, *children; 2901 unsigned int nchildren, key_buttons; 2902 int root_x, root_y, win_x, win_y; 2903 int ret; 2904 2905 localroot = w = RootWindow (dpy, Scr->screen); 2906 XGrabPointer (dpy, localroot, False, 2907 ButtonPressMask | ButtonReleaseMask, 2908 GrabModeAsync, GrabModeAsync, 2909 None, Scr->SelectCursor, CurrentTime); 2910 2911 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2912 child = event.xbutton.subwindow; 2913 while (1) { 2914 if (child == (Window) 0) break; 2915 2916 w = XmuClientWindow (dpy, child); 2917 ret = XGetWindowProperty (dpy, w, _XA_WM_WORKSPACESLIST, 0L, 512, 2918 False, XA_STRING, &actual_type, &actual_format, &len, 2919 &bytesafter, &prop); 2920 XFree ((char *)prop); /* Don't ever do anything with it */ 2921 if (ret != Success) 2922 break; 2923 if (len == 0) /* it is not a local root window */ 2924 break; /* it is not a local root window */ 2925 localroot = w; 2926 XQueryPointer (dpy, localroot, &root, &child, &root_x, &root_y, 2927 &win_x, &win_y, &key_buttons); 2928 } 2929 XMaskEvent (dpy, ButtonPressMask | ButtonReleaseMask, &event); 2930 XUngrabPointer (dpy, CurrentTime); 2931 2932 if (localroot == Scr->Root) return; 2933 if (w == localroot) { /* try to not adopt an ancestor */ 2934 XQueryTree (dpy, Scr->Root, &root, &parent, &children, &nchildren); 2935 while (parent != (Window) 0) { 2936 XFree ((char *) children); 2937 if (w == parent) return; 2938 XQueryTree (dpy, parent, &root, &parent, &children, &nchildren); 2939 } 2940 XFree ((char *) children); 2941 if (w == root) return; 2942 } 2943 if (localroot == RootWindow (dpy, Scr->screen)) { 2944 XWithdrawWindow (dpy, w, Scr->screen); 2945 } 2946 else { 2947 XUnmapWindow (dpy, w); 2948 } 2949 XReparentWindow (dpy, w, Scr->Root, 0, 0); 2950 2951 data [0] = (unsigned long) NormalState; 2952 data [1] = (unsigned long) None; 2953 2954 XChangeProperty (dpy, w, _XA_WM_STATE, _XA_WM_STATE, 32, 2955 PropModeReplace, (unsigned char *) data, 2); 2956 XFlush (dpy); 2957 SimulateMapRequest (w); 2958 return; 2959} 2960 2961void DebugTrace (char *file) 2962{ 2963 if (!file) return; 2964 if (tracefile) { 2965 fprintf (stderr, "stop logging events\n"); 2966 if (tracefile != stderr) fclose (tracefile); 2967 tracefile = NULL; 2968 } 2969 else { 2970 if (strcmp (file, "stderr")) 2971 tracefile = fopen (file, "w"); 2972 else 2973 tracefile = stderr; 2974 fprintf (stderr, "logging events to : %s\n", file); 2975 } 2976} 2977 2978extern Cursor TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor, 2979 LeftCursor, RightCursor, TopCursor, BottomCursor; 2980 2981void SetBorderCursor (TwmWindow *tmp_win, int x, int y) 2982{ 2983 Cursor cursor; 2984 XSetWindowAttributes attr; 2985 int h, fw, fh, wd; 2986 2987 if (!tmp_win) 2988 return; 2989 2990 /* Use the max of these, but since one is always 0 we can add them. */ 2991 wd = tmp_win->frame_bw + tmp_win->frame_bw3D; 2992 h = Scr->TitleHeight + wd; 2993 fw = tmp_win->frame_width; 2994 fh = tmp_win->frame_height; 2995 2996#if defined DEBUG && DEBUG 2997 fprintf(stderr, "wd=%d h=%d, fw=%d fh=%d x=%d y=%d\n", 2998 wd, h, fw, fh, x, y); 2999#endif 3000 3001 /* 3002 * If not using 3D borders: 3003 * 3004 * The left border has negative x coordinates, 3005 * The top border (above the title) has negative y coordinates. 3006 * The title is TitleHeight high, the next wd pixels are border. 3007 * The bottom border has coordinates >= the frame height. 3008 * The right border has coordinates >= the frame width. 3009 * 3010 * If using 3D borders: all coordinates are >= 0, and all coordinates 3011 * are higher by the border width. 3012 * 3013 * Since we only get events when we're actually in the border, we simply 3014 * allow for both cases at the same time. 3015 */ 3016 3017 if ((x < -wd) || (y < -wd)) { 3018 cursor = Scr->FrameCursor; 3019 } else if (x < h) { 3020 if (y < h) 3021 cursor = TopLeftCursor; 3022 else if (y >= fh - h) 3023 cursor = BottomLeftCursor; 3024 else 3025 cursor = LeftCursor; 3026 } else if (x >= fw - h) { 3027 if (y < h) 3028 cursor = TopRightCursor; 3029 else if (y >= fh - h) 3030 cursor = BottomRightCursor; 3031 else 3032 cursor = RightCursor; 3033 } else if (y < h) { /* also include title bar in top border area */ 3034 cursor = TopCursor; 3035 } else if (y >= fh - h) { 3036 cursor = BottomCursor; 3037 } else { 3038 cursor = Scr->FrameCursor; 3039 } 3040 attr.cursor = cursor; 3041 XChangeWindowAttributes (dpy, tmp_win->frame, CWCursor, &attr); 3042 tmp_win->curcurs = cursor; 3043} 3044 3045Image *GetImage (char *name, ColorPair cp) 3046{ 3047 name_list **list; 3048 char fullname [256]; 3049 Image *image; 3050 3051 if (name == NULL) return (None); 3052 image = None; 3053 3054 list = &Scr->ImageCache; 3055#ifdef XPM 3056 if ((name [0] == '@') || (strncmp (name, "xpm:", 4) == 0)) { 3057 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3058 3059 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3060 int startn = (name [0] == '@') ? 1 : 4; 3061 if ((image = GetXpmImage (name + startn, cp)) != None) { 3062 AddToList (list, fullname, (char*) image); 3063 } 3064 } 3065 } 3066 else 3067#endif 3068#ifdef JPEG 3069 if (strncmp (name, "jpeg:", 5) == 0) { 3070 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3071 if ((image = GetJpegImage (&name [5])) != None) { 3072 AddToList (list, name, (char*) image); 3073 } 3074 } 3075 } 3076 else 3077#endif 3078#ifdef IMCONV 3079 if (strncmp (name, "im:", 3) == 0) { 3080 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3081 if ((image = GetImconvImage (&name [3])) != None) { 3082 AddToList (list, name, (char*) image); 3083 } 3084 } 3085 } 3086 else 3087#endif 3088#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3089 if ((strncmp (name, "xwd:", 4) == 0) || (name [0] == '|')) { 3090 int startn = (name [0] == '|') ? 0 : 4; 3091 if ((image = (Image*) LookInNameList (*list, name)) == None) { 3092 if ((image = GetXwdImage (&name [startn], cp)) != None) { 3093 AddToList (list, name, (char*) image); 3094 } 3095 } 3096 } 3097 else 3098#endif 3099 if (strncmp (name, ":xpm:", 5) == 0) { 3100 int i; 3101 static struct { 3102 char *name; 3103 Image* (*proc)(ColorPair colorpair); 3104 } pmtab[] = { 3105 { TBPM_3DDOT, Create3DDotImage }, 3106 { TBPM_3DRESIZE, Create3DResizeImage }, 3107 { TBPM_3DMENU, Create3DMenuImage }, 3108 { TBPM_3DZOOM, Create3DZoomImage }, 3109 { TBPM_3DBAR, Create3DBarImage }, 3110 { TBPM_3DVBAR, Create3DVertBarImage }, 3111 { TBPM_3DCROSS, Create3DCrossImage }, 3112 { TBPM_3DICONIFY, Create3DIconifyImage }, 3113 { TBPM_3DSUNKEN_RESIZE, Create3DSunkenResizeImage }, 3114 { TBPM_3DBOX, Create3DBoxImage } 3115 }; 3116 3117 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3118 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3119 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3120 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3121 image = (*pmtab[i].proc) (cp); 3122 if (image == None) { 3123 fprintf (stderr, 3124 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3125 return (None); 3126 } 3127 break; 3128 } 3129 } 3130 if (image == None) { 3131 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3132 return (None); 3133 } 3134 AddToList (list, fullname, (char*) image); 3135 } 3136 } 3137 else 3138 if (strncmp (name, "%xpm:", 5) == 0) { 3139 int i; 3140 static struct { 3141 char *name; 3142 Image* (*proc)(ColorPair colorpair); 3143 } pmtab[] = { 3144 { "%xpm:menu-up", Create3DMenuUpAnimation }, 3145 { "%xpm:menu-down", Create3DMenuDownAnimation }, 3146 { "%xpm:resize", Create3DZoomOutAnimation }, /* compatibility */ 3147 { "%xpm:resize-out-top", Create3DResizeInTopAnimation }, 3148 { "%xpm:resize-in-top", Create3DResizeOutTopAnimation }, 3149 { "%xpm:resize-out-bot", Create3DResizeInBotAnimation }, 3150 { "%xpm:resize-in-bot", Create3DResizeOutBotAnimation }, 3151 { "%xpm:maze-out", Create3DMazeOutAnimation }, 3152 { "%xpm:maze-in", Create3DMazeInAnimation }, 3153 { "%xpm:zoom-out", Create3DZoomOutAnimation }, 3154 { "%xpm:zoom-in", Create3DZoomInAnimation }, 3155 { "%xpm:zoom-inout", Create3DZoomInOutAnimation } 3156 }; 3157 3158 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3159 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3160 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3161 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3162 image = (*pmtab[i].proc) (cp); 3163 if (image == None) { 3164 fprintf (stderr, 3165 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3166 return (None); 3167 } 3168 break; 3169 } 3170 } 3171 if (image == None) { 3172 fprintf (stderr, "%s: no such built-in pixmap \"%s\"\n", ProgramName, name); 3173 return (None); 3174 } 3175 AddToList (list, fullname, (char*) image); 3176 } 3177 } 3178 else 3179 if (name [0] == ':') { 3180 int i; 3181 unsigned int width, height; 3182 Pixmap pm = 0; 3183 XGCValues gcvalues; 3184 static struct { 3185 char *name; 3186 Pixmap (*proc)(unsigned int *widthp, unsigned int *heightp); 3187 } pmtab[] = { 3188 { TBPM_DOT, CreateDotPixmap }, 3189 { TBPM_ICONIFY, CreateDotPixmap }, 3190 { TBPM_RESIZE, CreateResizePixmap }, 3191 { TBPM_XLOGO, CreateXLogoPixmap }, 3192 { TBPM_DELETE, CreateXLogoPixmap }, 3193 { TBPM_MENU, CreateMenuPixmap }, 3194 { TBPM_QUESTION, CreateQuestionPixmap }, 3195 }; 3196 3197 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3198 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3199 for (i = 0; i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 3200 if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) { 3201 pm = (*pmtab[i].proc) (&width, &height); 3202 if (pm == None) { 3203 fprintf (stderr, 3204 "%s: unable to build pixmap \"%s\"\n", ProgramName, name); 3205 return (None); 3206 } 3207 break; 3208 } 3209 } 3210 if (pm == None) { 3211 fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", ProgramName, name); 3212 return (None); 3213 } 3214 image = (Image*) malloc (sizeof (struct _Image)); 3215 image->pixmap = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 3216 if (Scr->rootGC == (GC) 0) Scr->rootGC = XCreateGC (dpy, Scr->Root, 0, &gcvalues); 3217 gcvalues.background = cp.back; 3218 gcvalues.foreground = cp.fore; 3219 XChangeGC (dpy, Scr->rootGC, GCForeground | GCBackground, &gcvalues); 3220 XCopyPlane (dpy, pm, image->pixmap, Scr->rootGC, 0, 0, width, height, 0, 0, 3221 (unsigned long) 1); 3222 image->mask = None; 3223 image->width = width; 3224 image->height = height; 3225 image->next = None; 3226 AddToList (list, fullname, (char*) image); 3227 } 3228 } 3229 else { 3230 sprintf (fullname, "%s%dx%d", name, (int) cp.fore, (int) cp.back); 3231 if ((image = (Image*) LookInNameList (*list, fullname)) == None) { 3232 if ((image = GetBitmapImage (name, cp)) != None) { 3233 AddToList (list, fullname, (char*) image); 3234 } 3235 } 3236 } 3237 return (image); 3238} 3239 3240void FreeImage (Image *image) 3241{ 3242 Image *im, *im2; 3243 3244 im = image; 3245 while (im != None) { 3246 if (im->pixmap) XFreePixmap (dpy, im->pixmap); 3247 if (im->mask) XFreePixmap (dpy, im->mask); 3248 im2 = im->next; 3249 free (im); 3250 im = im2; 3251 } 3252} 3253 3254#if !defined(VMS) || defined(HAVE_XWDFILE_H) 3255static void compress (XImage *image, XColor *colors, int *ncolors); 3256 3257static Image *LoadXwdImage (char *filename, ColorPair cp) 3258{ 3259 FILE *file; 3260 char *fullname; 3261 XColor colors [256]; 3262 XWDColor xwdcolors [256]; 3263 unsigned buffer_size; 3264 XImage *image; 3265 unsigned char *imagedata; 3266 Pixmap pixret; 3267 Visual *visual; 3268 char win_name [256]; 3269 int win_name_size; 3270 int ispipe; 3271 int i, len; 3272 int w, h, depth, ncolors; 3273 int scrn; 3274 Colormap cmap; 3275 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3276 GC gc; 3277 XGCValues gcvalues; 3278 XWDFileHeader header; 3279 Image *ret; 3280 Bool anim; 3281 unsigned long swaptest = 1; 3282 3283 ispipe = 0; 3284 anim = False; 3285#ifndef VMS 3286 if (filename [0] == '|') { 3287 file = (FILE*) popen (filename + 1, "r"); 3288 if (file == NULL) return (None); 3289 ispipe = 1; 3290 anim = AnimationActive; 3291 if (anim) StopAnimation (); 3292 goto file_opened; 3293 } 3294#endif 3295 fullname = ExpandPixmapPath (filename); 3296 if (! fullname) return (None); 3297 file = fopen (fullname, "r"); 3298 free (fullname); 3299 if (file == NULL) { 3300 if (reportfilenotfound) fprintf (stderr, "unable to locate %s\n", filename); 3301 return (None); 3302 } 3303file_opened: 3304 len = fread ((char *) &header, sizeof (header), 1, file); 3305 if (len != 1) { 3306 fprintf (stderr, "ctwm: cannot read %s\n", filename); 3307#ifdef USE_SIGNALS 3308 if (ispipe && anim) StartAnimation (); 3309#endif 3310 return (None); 3311 } 3312 if (*(char *) &swaptest) _swaplong ((char *) &header, sizeof (header)); 3313 if (header.file_version != XWD_FILE_VERSION) { 3314 fprintf(stderr,"ctwm: XWD file format version mismatch : %s\n", filename); 3315 return (None); 3316 } 3317 win_name_size = header.header_size - sizeof (header); 3318 len = fread (win_name, win_name_size, 1, file); 3319 if (len != 1) { 3320 fprintf (stderr, "file %s has not the correct format\n", filename); 3321#ifdef USE_SIGNALS 3322 if (ispipe && anim) StartAnimation (); 3323#endif 3324 return (None); 3325 } 3326 3327 if (header.pixmap_format == XYPixmap) { 3328 fprintf (stderr,"ctwm: XYPixmap XWD file not supported : %s\n", filename); 3329 return (None); 3330 } 3331 w = header.pixmap_width; 3332 h = header.pixmap_height; 3333 depth = header.pixmap_depth; 3334 ncolors = header.ncolors; 3335 len = fread ((char *) xwdcolors, sizeof (XWDColor), ncolors, file); 3336 if (len != ncolors) { 3337 fprintf (stderr, "file %s has not the correct format\n", filename); 3338#ifdef USE_SIGNALS 3339 if (ispipe && anim) StartAnimation (); 3340#endif 3341 return (None); 3342 } 3343 if (*(char *) &swaptest) { 3344 for (i = 0; i < ncolors; i++) { 3345 _swaplong ((char *) &xwdcolors [i].pixel, 4); 3346 _swapshort ((char *) &xwdcolors [i].red, 3 * 2); 3347 } 3348 } 3349 for (i = 0; i < ncolors; i++) { 3350 colors [i].pixel = xwdcolors [i].pixel; 3351 colors [i].red = xwdcolors [i].red; 3352 colors [i].green = xwdcolors [i].green; 3353 colors [i].blue = xwdcolors [i].blue; 3354 colors [i].flags = xwdcolors [i].flags; 3355 colors [i].pad = xwdcolors [i].pad; 3356 } 3357 3358 scrn = Scr->screen; 3359 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3360 visual = Scr->d_visual; 3361 gc = DefaultGC (dpy, scrn); 3362 3363 buffer_size = header.bytes_per_line * h; 3364 imagedata = (unsigned char*) malloc (buffer_size); 3365 if (! imagedata) { 3366 fprintf (stderr, "cannot allocate memory for image %s\n", filename); 3367#ifdef USE_SIGNALS 3368 if (ispipe && anim) StartAnimation (); 3369#endif 3370 return (None); 3371 } 3372 len = fread (imagedata, (int) buffer_size, 1, file); 3373 if (len != 1) { 3374 free (imagedata); 3375 fprintf (stderr, "file %s has not the correct format\n", filename); 3376#ifdef USE_SIGNALS 3377 if (ispipe && anim) StartAnimation (); 3378#endif 3379 return (None); 3380 } 3381#ifndef VMS 3382 if (ispipe) 3383 pclose (file); 3384 else 3385#endif 3386 fclose (file); 3387 3388 image = XCreateImage (dpy, visual, depth, header.pixmap_format, 3389 0, (char*) imagedata, w, h, 3390 header.bitmap_pad, header.bytes_per_line); 3391 if (image == None) { 3392 free (imagedata); 3393 fprintf (stderr, "cannot create image for %s\n", filename); 3394#ifdef USE_SIGNALS 3395 if (ispipe && anim) StartAnimation (); 3396#endif 3397 return (None); 3398 } 3399 if (header.pixmap_format == ZPixmap) { 3400 compress (image, colors, &ncolors); 3401 } 3402 if (header.pixmap_format != XYBitmap) { 3403 for (i = 0; i < ncolors; i++) { 3404 XAllocColor (dpy, cmap, &(colors [i])); 3405 } 3406 for (i = 0; i < buffer_size; i++) { 3407 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3408 } 3409 } 3410 if (w > Scr->rootw) w = Scr->rootw; 3411 if (h > Scr->rooth) h = Scr->rooth; 3412 3413 ret = (Image*) malloc (sizeof (struct _Image)); 3414 if (! ret) { 3415 fprintf (stderr, "unable to allocate memory for image : %s\n", filename); 3416 free (image); 3417 free (imagedata); 3418 for (i = 0; i < ncolors; i++) { 3419 XFreeColors (dpy, cmap, &(colors [i].pixel), 1, 0L); 3420 } 3421#ifdef USE_SIGNALS 3422 if (ispipe && anim) StartAnimation (); 3423#endif 3424 return (None); 3425 } 3426 if (header.pixmap_format == XYBitmap) { 3427 gcvalues.foreground = cp.fore; 3428 gcvalues.background = cp.back; 3429 XChangeGC (dpy, gc, GCForeground | GCBackground, &gcvalues); 3430 } 3431 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3432 int x, y; 3433 3434 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, 3435 Scr->rooth, Scr->d_depth); 3436 x = (Scr->rootw - w) / 2; 3437 y = (Scr->rooth - h) / 2; 3438 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3439 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3440 ret->width = Scr->rootw; 3441 ret->height = Scr->rooth; 3442 } 3443 else { 3444 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3445 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3446 ret->width = w; 3447 ret->height = h; 3448 } 3449 XDestroyImage (image); 3450 3451 ret->pixmap = pixret; 3452 ret->mask = None; 3453 ret->next = None; 3454#ifdef USE_SIGNALS 3455 if (ispipe && anim) StartAnimation (); 3456#endif 3457 return (ret); 3458} 3459 3460static Image *GetXwdImage (char *name, ColorPair cp) 3461{ 3462 Image *image, *r, *s; 3463 char path [128]; 3464 char pref [128], *perc; 3465 int i; 3466 3467 if (! strchr (name, '%')) return (LoadXwdImage (name, cp)); 3468 s = image = None; 3469 strcpy (pref, name); 3470 perc = strchr (pref, '%'); 3471 *perc = '\0'; 3472 reportfilenotfound = 0; 3473 for (i = 1;; i++) { 3474 sprintf (path, "%s%d%s", pref, i, perc + 1); 3475 r = LoadXwdImage (path, cp); 3476 if (r == None) break; 3477 r->next = None; 3478 if (image == None) s = image = r; 3479 else { 3480 s->next = r; 3481 s = r; 3482 } 3483 } 3484 reportfilenotfound = 1; 3485 if (s != None) s->next = image; 3486 if (image == None) { 3487 fprintf (stderr, "Cannot open any %s xwd file\n", name); 3488 } 3489 return (image); 3490} 3491 3492static void compress (XImage *image, XColor *colors, int *ncolors) 3493{ 3494 unsigned char ind [256]; 3495 unsigned int used [256]; 3496 int i, j, size, nused; 3497 unsigned char color; 3498 XColor newcolors [256]; 3499 unsigned char *imagedata; 3500 3501 for (i = 0; i < 256; i++) { 3502 used [i] = 0; 3503 ind [i] = 0; 3504 } 3505 nused = 0; 3506 size = image->bytes_per_line * image->height; 3507 imagedata = (unsigned char *) image->data; 3508 for (i = 0; i < size; i++) { 3509 if ((i % image->bytes_per_line) > image->width) continue; 3510 color = imagedata [i]; 3511 if (used [color] == 0) { 3512 for (j = 0; j < nused; j++) { 3513 if ((colors [color].red == newcolors [j].red) && 3514 (colors [color].green == newcolors [j].green) && 3515 (colors [color].blue == newcolors [j].blue)) break; 3516 } 3517 ind [color] = j; 3518 used [color] = 1; 3519 if (j == nused) { 3520 newcolors [j].red = colors [color].red; 3521 newcolors [j].green = colors [color].green; 3522 newcolors [j].blue = colors [color].blue; 3523 nused++; 3524 } 3525 } 3526 } 3527 for (i = 0; i < size; i++) { 3528 imagedata [i] = ind [imagedata [i]]; 3529 } 3530 for (i = 0; i < nused; i++) { 3531 colors [i] = newcolors [i]; 3532 } 3533 *ncolors = nused; 3534} 3535#endif 3536 3537#ifdef IMCONV 3538 3539static void free_images (); 3540 3541static Image *GetImconvImage (char *filename, 3542 unsigned int *widthp, unsigned int *heightp) 3543{ 3544 TagTable *toolInTable; 3545 ImVfb *sourceVfb; 3546 ImVfbPtr vptr; 3547 ImClt *clt; 3548 int i, j, ij, k, retval; 3549 3550 XColor colors [256]; 3551 unsigned buffer_size; 3552 XImage *image; 3553 unsigned char *imagedata; 3554 Pixmap pixret; 3555 Visual *visual; 3556 int w, h, depth, ncolors; 3557 int scrn; 3558 Colormap cmap; 3559 Colormap stdcmap = Scr->RootColormaps.cwins[0]->colormap->c; 3560 GC gc; 3561 unsigned char red, green, blue; 3562 int icol; 3563 char *fullname; 3564 3565 TagEntry *dataEntry; 3566 FILE *fp; 3567 char the_format[1024]; 3568 char *tmp_format; 3569 Image *ret; 3570 3571 if (*filename == NULL) return (None); 3572 fullname = ExpandPixmapPath (filename); 3573 if (! fullname) return (None); 3574 3575 fp = fopen (fullname, "r"); 3576 if (!fp) { 3577 if (reportfilenotfound) fprintf (stderr, "Cannot open the image %s\n", filename); 3578 free (fullname); 3579 return (None); 3580 } 3581 if ((toolInTable = TagTableAlloc ()) == TAGTABLENULL ) { 3582 fprintf (stderr, "TagTableAlloc failed\n"); 3583 free_images (toolInTable); 3584 free (fullname); 3585 return (None); 3586 } 3587 if ((tmp_format = ImFileQFFormat (fp, fullname)) == NULL) { 3588 fprintf (stderr, "Cannot determine image type of %s\n", filename); 3589 free_images (toolInTable); 3590 free (fullname); 3591 return (None); 3592 } 3593 strcpy (the_format, tmp_format); 3594 retval = ImFileFRead (fp, the_format, NULL, toolInTable); 3595 if(retval < 0) { 3596 fprintf(stderr, "Cannot read image file %s: ", fullname); 3597 switch(ImErrNo) { 3598 case IMESYS: 3599 fprintf (stderr, "System call error\n"); 3600 break; 3601 case IMEMALLOC: 3602 fprintf (stderr, "Cannot allocate memory\n"); 3603 break; 3604 case IMEFORMAT: 3605 fprintf (stderr, "Data in file is corrupt\n"); 3606 break; 3607 case IMENOREAD: 3608 fprintf (stderr, "Sorry, this format is write-only\n"); 3609 break; 3610 case IMEMAGIC: 3611 fprintf (stderr, "Bad magic number in image file\n"); 3612 break; 3613 case IMEDEPTH: 3614 fprintf (stderr, "Unknown image depth\n"); 3615 break; 3616 default: 3617 fprintf(stderr, "Unknown error\n"); 3618 break; 3619 } 3620 free_images (toolInTable); 3621 free (fullname); 3622 return (None); 3623 } 3624 3625 if (TagTableQNEntry (toolInTable, "image vfb") == 0) { 3626 fprintf (stderr, "Image file %s contains no images\n", fullname); 3627 free_images (toolInTable); 3628 free (fullname); 3629 return (None); 3630 } 3631 dataEntry = TagTableQDirect (toolInTable, "image vfb", 0); 3632 TagEntryQValue (dataEntry, &sourceVfb); 3633 fclose (fp); 3634 3635 w = ImVfbQWidth (sourceVfb); 3636 h = ImVfbQHeight (sourceVfb); 3637 depth = 8 * ImVfbQNBytes (sourceVfb); 3638 if (depth != 8) { 3639 fprintf (stderr, "I don't know yet how to deal with images not of 8 planes depth\n"); 3640 free_images (toolInTable); 3641 return (None); 3642 } 3643 3644 *width = w; 3645 *height = h; 3646 3647 scrn = Scr->screen; 3648 cmap = AlternateCmap ? AlternateCmap : stdcmap; 3649 visual = Scr->d_visual; 3650 gc = DefaultGC (dpy, scrn); 3651 3652 buffer_size = w * h; 3653 imagedata = (unsigned char*) malloc (buffer_size); 3654 if (imagedata == (unsigned char*) 0) { 3655 fprintf (stderr, "Can't alloc enough space for background images\n"); 3656 free_images (toolInTable); 3657 return (None); 3658 } 3659 3660 clt = ImVfbQClt (sourceVfb); 3661 vptr = ImVfbQFirst (sourceVfb); 3662 ncolors = 0; 3663 for (i = 0; i < h - 1; i++) { 3664 for (j = 0; j < w; j++) { 3665 ij = (i * w) + j; 3666 red = ImCltQRed (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3667 green = ImCltQGreen (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3668 blue = ImCltQBlue (ImCltQPtr (clt, ImVfbQIndex (sourceVfb, vptr))); 3669 for (k = 0; k < ncolors; k++) { 3670 if ((colors [k].red == red) && 3671 (colors [k].green == green) && 3672 (colors [k].blue == blue)) { 3673 icol = k; 3674 break; 3675 } 3676 } 3677 if (k == ncolors) { 3678 icol = ncolors; 3679 ncolors++; 3680 } 3681 imagedata [ij] = icol; 3682 colors [icol].red = red; 3683 colors [icol].green = green; 3684 colors [icol].blue = blue; 3685 ImVfbSInc (sourceVfb, vptr); 3686 } 3687 } 3688 for (i = 0; i < ncolors; i++) { 3689 colors [i].red *= 256; 3690 colors [i].green *= 256; 3691 colors [i].blue *= 256; 3692 } 3693 for (i = 0; i < ncolors; i++) { 3694 if (! XAllocColor (dpy, cmap, &(colors [i]))) { 3695 fprintf (stderr, "can't alloc color for image %s\n", filename); 3696 } 3697 } 3698 for (i = 0; i < buffer_size; i++) { 3699 imagedata [i] = (unsigned char) colors [imagedata [i]].pixel; 3700 } 3701 3702 image = XCreateImage (dpy, visual, depth, ZPixmap, 0, (char*) imagedata, w, h, 8, 0); 3703 if (w > Scr->rootw) w = Scr->rootw; 3704 if (h > Scr->rooth) h = Scr->rooth; 3705 3706 if ((w > (Scr->rootw / 2)) || (h > (Scr->rooth / 2))) { 3707 int x, y; 3708 3709 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, depth); 3710 x = (Scr->rootw - w) / 2; 3711 y = (Scr->rooth - h) / 2; 3712 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 3713 XPutImage (dpy, pixret, gc, image, 0, 0, x, y, w, h); 3714 ret->width = Scr->rootw; 3715 ret->height = Scr->rooth; 3716 } 3717 else { 3718 pixret = XCreatePixmap (dpy, Scr->Root, w, h, depth); 3719 XPutImage (dpy, pixret, gc, image, 0, 0, 0, 0, w, h); 3720 ret->width = w; 3721 ret->height = h; 3722 } 3723 XFree (image); 3724 ret = (Image*) malloc (sizeof (struct _Image)); 3725 ret->pixmap = pixret; 3726 ret->mask = None; 3727 ret->next = None; 3728 return (ret); 3729 3730} 3731 3732static void free_images (table) 3733TagTable *table; 3734{ 3735 int i, n; 3736 ImVfb *v; 3737 ImClt *c; 3738 TagEntry *dataEntry; 3739 3740 n = TagTableQNEntry (table, "image vfb"); 3741 for (i = 0 ; i < n ; i++) { 3742 dataEntry = TagTableQDirect (table, "image vfb", i); 3743 TagEntryQValue (dataEntry, &v); 3744 ImVfbFree (v); 3745 } 3746 n = TagTableQNEntry (table, "image clt"); 3747 for (i = 0 ; i < n ; i++) { 3748 dataEntry = TagTableQDirect (table, "image clt", i ); 3749 TagEntryQValue (dataEntry, &c); 3750 ImCltFree (c); 3751 } 3752 TagTableFree (table); 3753} 3754 3755#endif 3756 3757void _swapshort (register char *bp, register unsigned n) 3758{ 3759 register char c; 3760 register char *ep = bp + n; 3761 3762 while (bp < ep) { 3763 c = *bp; 3764 *bp = *(bp + 1); 3765 bp++; 3766 *bp++ = c; 3767 } 3768} 3769 3770void _swaplong (register char *bp, register unsigned n) 3771{ 3772 register char c; 3773 register char *ep = bp + n; 3774 register char *sp; 3775 3776 while (bp < ep) { 3777 sp = bp + 3; 3778 c = *sp; 3779 *sp = *bp; 3780 *bp++ = c; 3781 sp = bp + 1; 3782 c = *sp; 3783 *sp = *bp; 3784 *bp++ = c; 3785 bp += 2; 3786 } 3787} 3788 3789/*********************************************************************** 3790 * 3791 * Procedure: 3792 * GetWMPropertyString - Get Window Manager text property and 3793 * convert it to a string. 3794 * 3795 * Returned Value: 3796 * (char *) - pointer to the malloc'd string or NULL 3797 * 3798 * Inputs: 3799 * w - the id of the window whose property is to be retrieved 3800 * prop - property atom (typically WM_NAME or WM_ICON_NAME) 3801 * 3802 *********************************************************************** 3803 */ 3804 3805unsigned char *GetWMPropertyString(Window w, Atom prop) 3806{ 3807 XTextProperty text_prop; 3808 char **text_list; 3809 int text_list_count; 3810 Atom XA_COMPOUND_TEXT = XInternAtom(dpy, "COMPOUND_TEXT", False); 3811 unsigned char *stringptr; 3812 int status, len = -1; 3813 3814 (void)XGetTextProperty(dpy, w, &text_prop, prop); 3815 if (text_prop.value != NULL) { 3816 if (text_prop.encoding == XA_STRING 3817 || text_prop.encoding == XA_COMPOUND_TEXT) { 3818 /* property is encoded as compound text - convert to locale string */ 3819 status = XmbTextPropertyToTextList(dpy, &text_prop, 3820 &text_list, &text_list_count); 3821 if (text_list_count == 0) { 3822 stringptr = NULL; 3823 } else 3824 if (text_list == (char **)0) { 3825 stringptr = NULL; 3826 } else 3827 if (text_list [0] == (char *)0) { 3828 stringptr = NULL; 3829 } else 3830 if (status < 0 || text_list_count < 0) { 3831 switch (status) { 3832 case XConverterNotFound: 3833 fprintf (stderr, "%s: Converter not found; unable to convert property %s of window ID %lx.\n", 3834 ProgramName, XGetAtomName(dpy, prop), w); 3835 break; 3836 case XNoMemory: 3837 fprintf (stderr, "%s: Insufficient memory; unable to convert property %s of window ID %lx.\n", 3838 ProgramName, XGetAtomName(dpy, prop), w); 3839 break; 3840 case XLocaleNotSupported: 3841 fprintf (stderr, "%s: Locale not supported; unable to convert property %s of window ID %lx.\n", 3842 ProgramName, XGetAtomName(dpy, prop), w); 3843 break; 3844 } 3845 stringptr = NULL; 3846 /* 3847 don't call XFreeStringList - text_list appears to have 3848 invalid address if status is bad 3849 XFreeStringList(text_list); 3850 */ 3851 } else { 3852 len = strlen(text_list[0]); 3853 stringptr = memcpy(malloc(len+1), text_list[0], len+1); 3854 XFreeStringList(text_list); 3855 } 3856 } else { 3857 /* property is encoded in a format we don't understand */ 3858 fprintf (stderr, "%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n", 3859 ProgramName, XGetAtomName(dpy, prop), w); 3860 stringptr = NULL; 3861 } 3862 XFree (text_prop.value); 3863 } else { 3864 stringptr = NULL; 3865 } 3866 3867 return stringptr; 3868} 3869 3870void FreeWMPropertyString(char *prop) 3871{ 3872 if (prop && (char *)prop != NoName) { 3873 free(prop); 3874 } 3875} 3876 3877static void ConstrainLeftTop (int *value, int border) 3878{ 3879 if (*value < border) { 3880 if (Scr->MoveOffResistance < 0 || 3881 *value > border - Scr->MoveOffResistance) 3882 { 3883 *value = border; 3884 } else if (Scr->MoveOffResistance > 0 && 3885 *value <= border - Scr->MoveOffResistance) 3886 { 3887 *value = *value + Scr->MoveOffResistance; 3888 } 3889 } 3890} 3891 3892static void ConstrainRightBottom (int *value, int size1, int border, int size2) 3893{ 3894 if (*value + size1 > size2 - border) { 3895 if (Scr->MoveOffResistance < 0 || 3896 *value + size1 < size2 - border + Scr->MoveOffResistance) 3897 { 3898 *value = size2 - size1 - border; 3899 } else if (Scr->MoveOffResistance > 0 && 3900 *value + size1 >= size2 - border + Scr->MoveOffResistance) { 3901 *value = *value - Scr->MoveOffResistance; 3902 } 3903 } 3904} 3905 3906void ConstrainByBorders1 (int *left, int width, int *top, int height) 3907{ 3908 ConstrainRightBottom (left, width, Scr->BorderRight, Scr->rootw); 3909 ConstrainLeftTop (left, Scr->BorderLeft); 3910 ConstrainRightBottom (top, height, Scr->BorderBottom, Scr->rooth); 3911 ConstrainLeftTop (top, Scr->BorderTop); 3912} 3913 3914void ConstrainByBorders (TwmWindow *twmwin, 3915 int *left, int width, int *top, int height) 3916{ 3917 if (twmwin->winbox) { 3918 XWindowAttributes attr; 3919 XGetWindowAttributes (dpy, twmwin->winbox->window, &attr); 3920 ConstrainRightBottom (left, width, 0, attr.width); 3921 ConstrainLeftTop (left, 0); 3922 ConstrainRightBottom (top, height, 0, attr.height); 3923 ConstrainLeftTop (top, 0); 3924 } else { 3925 ConstrainByBorders1 (left, width, top, height); 3926 } 3927} 3928 3929#ifdef JPEG 3930 3931uint16_t *buffer_16bpp; 3932uint32_t *buffer_32bpp; 3933 3934static void convert_for_16 (int w, int x, int y, int r, int g, int b) { 3935 buffer_16bpp [y * w + x] = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3); 3936} 3937 3938static void convert_for_32 (int w, int x, int y, int r, int g, int b) { 3939 buffer_32bpp [y * w + x] = ((r << 16) + (g << 8) + b) & 0xFFFFFFFF; 3940} 3941 3942static void jpeg_error_exit (j_common_ptr cinfo) { 3943 jerr_ptr errmgr = (jerr_ptr) cinfo->err; 3944 cinfo->err->output_message (cinfo); 3945 siglongjmp (errmgr->setjmp_buffer, 1); 3946 return; 3947} 3948 3949static Image *GetJpegImage (char *name) 3950{ 3951 Image *image, *r, *s; 3952 char path [128]; 3953 char pref [128], *perc; 3954 int i; 3955 3956 if (! strchr (name, '%')) return (LoadJpegImage (name)); 3957 s = image = None; 3958 strcpy (pref, name); 3959 perc = strchr (pref, '%'); 3960 *perc = '\0'; 3961 reportfilenotfound = 0; 3962 for (i = 1;; i++) { 3963 sprintf (path, "%s%d%s", pref, i, perc + 1); 3964 r = LoadJpegImage (path); 3965 if (r == None) break; 3966 r->next = None; 3967 if (image == None) s = image = r; 3968 else { 3969 s->next = r; 3970 s = r; 3971 } 3972 } 3973 reportfilenotfound = 1; 3974 if (s != None) s->next = image; 3975 if (image == None) { 3976 fprintf (stderr, "Cannot open any %s jpeg file\n", name); 3977 } 3978 return (image); 3979} 3980 3981static Image *LoadJpegImage (char *name) 3982{ 3983 char *fullname; 3984 XImage *ximage; 3985 FILE *infile; 3986 Image *image; 3987 Pixmap pixret; 3988 void (*store_data) (int w, int x, int y, int r, int g, int b); 3989 struct jpeg_decompress_struct cinfo; 3990 struct jpeg_error jerr; 3991 JSAMPARRAY buffer; 3992 int width, height; 3993 int row_stride; 3994 int g, i, a; 3995 int bpix; 3996 GC gc; 3997 3998 fullname = ExpandPixmapPath (name); 3999 if (! fullname) return (None); 4000 4001 image = (Image*) malloc (sizeof (struct _Image)); 4002 if (image == None) return (None); 4003 4004 if ((infile = fopen (fullname, "rb")) == NULL) { 4005 if (!reportfilenotfound) fprintf (stderr, "unable to locate %s\n", fullname); 4006 fflush (stdout); 4007 return None; 4008 } 4009 cinfo.err = jpeg_std_error (&jerr.pub); 4010 jerr.pub.error_exit = jpeg_error_exit; 4011 4012 if (sigsetjmp(jerr.setjmp_buffer, 1)) { 4013 jpeg_destroy_decompress (&cinfo); 4014 fclose (infile); 4015 return None; 4016 } 4017 jpeg_create_decompress (&cinfo); 4018 jpeg_stdio_src (&cinfo, infile); 4019 jpeg_read_header (&cinfo, FALSE); 4020 cinfo.do_fancy_upsampling = FALSE; 4021 cinfo.do_block_smoothing = FALSE; 4022 jpeg_start_decompress (&cinfo); 4023 width = cinfo.output_width; 4024 height = cinfo.output_height; 4025 4026 if (Scr->d_depth == 16) { 4027 store_data = &convert_for_16; 4028 buffer_16bpp = (unsigned short int *) malloc ((width) * (height) * 2); 4029 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4030 (char *) buffer_16bpp, width, height, 16, width * 2); 4031 } else { 4032 if (Scr->d_depth == 24) { 4033 store_data = &convert_for_32; 4034 buffer_32bpp = malloc (width * height * 4); 4035 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4036 (char *) buffer_32bpp, width, height, 32, width * 4); 4037 } else 4038 if (Scr->d_depth == 32) { 4039 store_data = &convert_for_32; 4040 buffer_32bpp = malloc (width * height * 4); 4041 ximage = XCreateImage (dpy, CopyFromParent, Scr->d_depth, ZPixmap, 0, 4042 (char *) buffer_32bpp, width, height, 32, width * 4); 4043 } else { 4044 fprintf (stderr, "Image %s unsupported depth : %d\n", name, Scr->d_depth); 4045 return None; 4046 } 4047 } 4048 if (ximage == None) { 4049 fprintf (stderr, "cannot create image for %s\n", name); 4050 } 4051 g = 0; 4052 row_stride = cinfo.output_width * cinfo.output_components; 4053 buffer = (*cinfo.mem->alloc_sarray) 4054 ((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1); 4055 4056 bpix = cinfo.output_components; 4057 while (cinfo.output_scanline < cinfo.output_height) { 4058 jpeg_read_scanlines (&cinfo, buffer, 1); 4059 a = 0; 4060 for (i = 0; i < bpix * cinfo.output_width; i += bpix) { 4061 (*store_data) (width, a, g, buffer[0][i], buffer[0][i + 1], buffer[0][i + 2]); 4062 a++; 4063 } 4064 g++; 4065 } 4066 jpeg_finish_decompress (&cinfo); 4067 jpeg_destroy_decompress (&cinfo); 4068 fclose (infile); 4069 4070 gc = DefaultGC (dpy, Scr->screen); 4071 if ((width > (Scr->rootw / 2)) || (height > (Scr->rooth / 2))) { 4072 int x, y; 4073 4074 pixret = XCreatePixmap (dpy, Scr->Root, Scr->rootw, Scr->rooth, Scr->d_depth); 4075 x = (Scr->rootw - width) / 2; 4076 y = (Scr->rooth - height) / 2; 4077 XFillRectangle (dpy, pixret, gc, 0, 0, Scr->rootw, Scr->rooth); 4078 XPutImage (dpy, pixret, gc, ximage, 0, 0, x, y, width, height); 4079 image->width = Scr->rootw; 4080 image->height = Scr->rooth; 4081 } else { 4082 pixret = XCreatePixmap (dpy, Scr->Root, width, height, Scr->d_depth); 4083 XPutImage (dpy, pixret, gc, ximage, 0, 0, 0, 0, width, height); 4084 image->width = width; 4085 image->height = height; 4086 } 4087 XDestroyImage (ximage); 4088 image->pixmap = pixret; 4089 image->mask = None; 4090 image->next = None; 4091 4092 return image; 4093} 4094 4095#endif /* JPEG */ 4096