13e747e6dSmrg/*****************************************************************************/ 23e747e6dSmrg/* 33e747e6dSmrg 43e747e6dSmrgCopyright 1989, 1998 The Open Group 53e747e6dSmrg 63e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its 73e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that 83e747e6dSmrgthe above copyright notice appear in all copies and that both that 93e747e6dSmrgcopyright notice and this permission notice appear in supporting 103e747e6dSmrgdocumentation. 113e747e6dSmrg 123e747e6dSmrgThe above copyright notice and this permission notice shall be included in 133e747e6dSmrgall copies or substantial portions of the Software. 143e747e6dSmrg 153e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 183e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 193e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 203e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 213e747e6dSmrg 223e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be 233e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings 243e747e6dSmrgin this Software without prior written authorization from The Open Group. 253e747e6dSmrg 263e747e6dSmrg*/ 273e747e6dSmrg/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ 283e747e6dSmrg/** Salt Lake City, Utah **/ 293e747e6dSmrg/** Cambridge, Massachusetts **/ 303e747e6dSmrg/** **/ 313e747e6dSmrg/** All Rights Reserved **/ 323e747e6dSmrg/** **/ 333e747e6dSmrg/** Permission to use, copy, modify, and distribute this software and **/ 343e747e6dSmrg/** its documentation for any purpose and without fee is hereby **/ 353e747e6dSmrg/** granted, provided that the above copyright notice appear in all **/ 363e747e6dSmrg/** copies and that both that copyright notice and this permis- **/ 373e747e6dSmrg/** sion notice appear in supporting documentation, and that the **/ 383e747e6dSmrg/** name of Evans & Sutherland not be used in advertising **/ 393e747e6dSmrg/** in publicity pertaining to distribution of the software without **/ 403e747e6dSmrg/** specific, written prior permission. **/ 413e747e6dSmrg/** **/ 423e747e6dSmrg/** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/ 433e747e6dSmrg/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ 443e747e6dSmrg/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/ 453e747e6dSmrg/** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ 463e747e6dSmrg/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ 473e747e6dSmrg/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ 483e747e6dSmrg/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ 493e747e6dSmrg/** OR PERFORMANCE OF THIS SOFTWARE. **/ 503e747e6dSmrg/*****************************************************************************/ 513e747e6dSmrg 523e747e6dSmrg/*********************************************************************** 533e747e6dSmrg * 543e747e6dSmrg * utility routines for twm 553e747e6dSmrg * 56329eaa64Smrg * 28-Oct-87 Thomas E. LaStrange File created 573e747e6dSmrg * 583e747e6dSmrg ***********************************************************************/ 593e747e6dSmrg 603e747e6dSmrg#include "twm.h" 613e747e6dSmrg#include "util.h" 62b66deae1Smrg#include "parse.h" 633e747e6dSmrg#include "screen.h" 643e747e6dSmrg#include <X11/Xos.h> 653e747e6dSmrg#include <X11/Xatom.h> 663e747e6dSmrg#include <stdio.h> 673e747e6dSmrg#include <X11/Xmu/Drawing.h> 683e747e6dSmrg#include <X11/Xmu/CharSet.h> 693e747e6dSmrg 70329eaa64Smrgstatic Pixmap CreateXLogoPixmap(unsigned int *widthp, unsigned int *heightp); 71329eaa64Smrgstatic Pixmap CreateResizePixmap(unsigned int *widthp, unsigned int *heightp); 72329eaa64Smrgstatic Pixmap CreateDotPixmap(unsigned int *widthp, unsigned int *heightp); 73329eaa64Smrgstatic Pixmap CreateQuestionPixmap(unsigned int *widthp, unsigned int *heightp); 74329eaa64Smrgstatic Pixmap CreateMenuPixmap(unsigned int *widthp, unsigned int *heightp); 753e747e6dSmrg 763e747e6dSmrgint HotX, HotY; 773e747e6dSmrg 78ffd25bcaSmrg/** 793e747e6dSmrg * move a window outline 803e747e6dSmrg * 813e747e6dSmrg * \param root window we are outlining 823e747e6dSmrg * \param x,y upper left coordinate 833e747e6dSmrg * \param width,height size of the rectangle 843e747e6dSmrg * \param bw border width of the frame 853e747e6dSmrg * \param th title height 863e747e6dSmrg */ 87329eaa64Smrgvoid 88329eaa64SmrgMoveOutline(Window root, int x, int y, int width, int height, int bw, int th) 893e747e6dSmrg{ 90329eaa64Smrg static int lastx = 0; 91329eaa64Smrg static int lasty = 0; 92329eaa64Smrg static int lastWidth = 0; 93329eaa64Smrg static int lastHeight = 0; 94329eaa64Smrg static int lastBW = 0; 95329eaa64Smrg static int lastTH = 0; 96329eaa64Smrg int xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb; 97329eaa64Smrg int xthird, ythird; 98329eaa64Smrg XSegment outline[18]; 99b66deae1Smrg XSegment *r; 1003e747e6dSmrg 1013e747e6dSmrg if (x == lastx && y == lasty && width == lastWidth && height == lastHeight 102329eaa64Smrg && lastBW == bw && th == lastTH) 103329eaa64Smrg return; 104ffd25bcaSmrg 1053e747e6dSmrg r = outline; 1063e747e6dSmrg 1073e747e6dSmrg#define DRAWIT() \ 108329eaa64Smrg if (lastWidth || lastHeight) \ 109329eaa64Smrg { \ 110329eaa64Smrg xl = lastx; \ 111329eaa64Smrg xr = lastx + lastWidth - 1; \ 112329eaa64Smrg yt = lasty; \ 113329eaa64Smrg yb = lasty + lastHeight - 1; \ 114329eaa64Smrg xinnerl = xl + lastBW; \ 115329eaa64Smrg xinnerr = xr - lastBW; \ 116329eaa64Smrg yinnert = yt + lastTH + lastBW; \ 117329eaa64Smrg yinnerb = yb - lastBW; \ 118329eaa64Smrg xthird = (xinnerr - xinnerl) / 3; \ 119329eaa64Smrg ythird = (yinnerb - yinnert) / 3; \ 120329eaa64Smrg \ 121329eaa64Smrg r->x1 = (short)(xl); \ 122329eaa64Smrg r->y1 = (short)(yt); \ 123329eaa64Smrg r->x2 = (short)(xr); \ 124329eaa64Smrg r->y2 = (short)(yt); \ 125329eaa64Smrg r++; \ 126329eaa64Smrg \ 127329eaa64Smrg r->x1 = (short)(xl); \ 128329eaa64Smrg r->y1 = (short)(yb); \ 129329eaa64Smrg r->x2 = (short)(xr); \ 130329eaa64Smrg r->y2 = (short)(yb); \ 131329eaa64Smrg r++; \ 132329eaa64Smrg \ 133329eaa64Smrg r->x1 = (short)(xl); \ 134329eaa64Smrg r->y1 = (short)(yt); \ 135329eaa64Smrg r->x2 = (short)(xl); \ 136329eaa64Smrg r->y2 = (short)(yb); \ 137329eaa64Smrg r++; \ 138329eaa64Smrg \ 139329eaa64Smrg r->x1 = (short)(xr); \ 140329eaa64Smrg r->y1 = (short)(yt); \ 141329eaa64Smrg r->x2 = (short)(xr); \ 142329eaa64Smrg r->y2 = (short)(yb); \ 143329eaa64Smrg r++; \ 144329eaa64Smrg \ 145329eaa64Smrg r->x1 = (short)(xinnerl + xthird); \ 146329eaa64Smrg r->y1 = (short)(yinnert); \ 147329eaa64Smrg r->x2 = (short)(r->x1); \ 148329eaa64Smrg r->y2 = (short)(yinnerb); \ 149329eaa64Smrg r++; \ 150329eaa64Smrg \ 151329eaa64Smrg r->x1 = (short)(xinnerl + (2 * xthird)); \ 152329eaa64Smrg r->y1 = (short)(yinnert); \ 153329eaa64Smrg r->x2 = (short)(r->x1); \ 154329eaa64Smrg r->y2 = (short)(yinnerb); \ 155329eaa64Smrg r++; \ 156329eaa64Smrg \ 157329eaa64Smrg r->x1 = (short)(xinnerl); \ 158329eaa64Smrg r->y1 = (short)(yinnert + ythird); \ 159329eaa64Smrg r->x2 = (short)(xinnerr); \ 160329eaa64Smrg r->y2 = (short)(r->y1); \ 161329eaa64Smrg r++; \ 162329eaa64Smrg \ 163329eaa64Smrg r->x1 = (short)(xinnerl); \ 164329eaa64Smrg r->y1 = (short)(yinnert + (2 * ythird)); \ 165329eaa64Smrg r->x2 = (short)(xinnerr); \ 166329eaa64Smrg r->y2 = (short)(r->y1); \ 167329eaa64Smrg r++; \ 168329eaa64Smrg \ 169329eaa64Smrg if (lastTH != 0) { \ 170329eaa64Smrg r->x1 = (short)(xl); \ 171329eaa64Smrg r->y1 = (short)(yt + lastTH); \ 172329eaa64Smrg r->x2 = (short)(xr); \ 173329eaa64Smrg r->y2 = (short)(r->y1); \ 174329eaa64Smrg r++; \ 175329eaa64Smrg } \ 1763e747e6dSmrg } 1773e747e6dSmrg 1783e747e6dSmrg /* undraw the old one, if any */ 179329eaa64Smrg DRAWIT(); 1803e747e6dSmrg 1813e747e6dSmrg lastx = x; 1823e747e6dSmrg lasty = y; 1833e747e6dSmrg lastWidth = width; 1843e747e6dSmrg lastHeight = height; 1853e747e6dSmrg lastBW = bw; 1863e747e6dSmrg lastTH = th; 1873e747e6dSmrg 1883e747e6dSmrg /* draw the new one, if any */ 189329eaa64Smrg DRAWIT(); 1903e747e6dSmrg 1913e747e6dSmrg#undef DRAWIT 1923e747e6dSmrg 193329eaa64Smrg if (r != outline) { 194329eaa64Smrg XDrawSegments(dpy, root, Scr->DrawGC, outline, (int) (r - outline)); 1953e747e6dSmrg } 1963e747e6dSmrg} 1973e747e6dSmrg 1983e747e6dSmrg/** 1993e747e6dSmrg * zoom in or out of an icon 2003e747e6dSmrg * 2013e747e6dSmrg * \param wf window to zoom from 2023e747e6dSmrg * \param wt window to zoom to 2033e747e6dSmrg */ 2043e747e6dSmrgvoid 2053e747e6dSmrgZoom(Window wf, Window wt) 2063e747e6dSmrg{ 207329eaa64Smrg int fx, fy, tx, ty; /* from, to */ 208329eaa64Smrg unsigned int fw, fh, tw, th; /* from, to */ 2093e747e6dSmrg long dx, dy, dw, dh; 2103e747e6dSmrg long z; 2113e747e6dSmrg int j; 212b66deae1Smrg unsigned udummy = 0; 213b66deae1Smrg Window wdummy = None; 2143e747e6dSmrg 215329eaa64Smrg if (!Scr->DoZoom || Scr->ZoomCount < 1) 216329eaa64Smrg return; 2173e747e6dSmrg 218329eaa64Smrg if (wf == None || wt == None) 219329eaa64Smrg return; 2203e747e6dSmrg 221b66deae1Smrg XGetGeometry(dpy, wf, &wdummy, &fx, &fy, &fw, &fh, &udummy, &udummy); 222b66deae1Smrg XGetGeometry(dpy, wt, &wdummy, &tx, &ty, &tw, &th, &udummy, &udummy); 2233e747e6dSmrg 224329eaa64Smrg dx = ((long) (tx - fx)); /* going from -> to */ 225329eaa64Smrg dy = ((long) (ty - fy)); /* going from -> to */ 226329eaa64Smrg dw = ((long) (tw - fw)); /* going from -> to */ 227329eaa64Smrg dh = ((long) (th - fh)); /* going from -> to */ 2283e747e6dSmrg z = (long) (Scr->ZoomCount + 1); 2293e747e6dSmrg 2303e747e6dSmrg for (j = 0; j < 2; j++) { 231329eaa64Smrg long i; 232329eaa64Smrg 233329eaa64Smrg XDrawRectangle(dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh); 234329eaa64Smrg for (i = 1; i < z; i++) { 235329eaa64Smrg int x = fx + (int) ((dx * i) / z); 236329eaa64Smrg int y = fy + (int) ((dy * i) / z); 237329eaa64Smrg unsigned width = (unsigned) (((long) fw) + (dw * i) / z); 238329eaa64Smrg unsigned height = (unsigned) (((long) fh) + (dh * i) / z); 239329eaa64Smrg 240329eaa64Smrg XDrawRectangle(dpy, Scr->Root, Scr->DrawGC, x, y, width, height); 241329eaa64Smrg } 242329eaa64Smrg XDrawRectangle(dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th); 2433e747e6dSmrg } 2443e747e6dSmrg} 2453e747e6dSmrg 2463e747e6dSmrg/** 247ffd25bcaSmrg * expand the tilde character to HOME if it is the first 2483e747e6dSmrg * character of the filename 2493e747e6dSmrg * 250329eaa64Smrg * \return a pointer to the new name 2513e747e6dSmrg * 2523e747e6dSmrg * \param name the filename to expand 2533e747e6dSmrg */ 2543e747e6dSmrgchar * 255c9398294SchristosExpandFilename(const char *name) 2563e747e6dSmrg{ 2573e747e6dSmrg char *newname; 2583e747e6dSmrg 259329eaa64Smrg if (name[0] != '~') 260329eaa64Smrg return strdup(name); 2613e747e6dSmrg 262b66deae1Smrg newname = (char *) malloc((size_t) HomeLen + strlen(name) + 2); 2633e747e6dSmrg if (!newname) { 264329eaa64Smrg twmWarning("unable to allocate %lu bytes to expand filename %s/%s", 265329eaa64Smrg (unsigned long) HomeLen + (unsigned long) strlen(name) + 2, 266329eaa64Smrg Home, &name[1]); 267329eaa64Smrg } 268329eaa64Smrg else { 269329eaa64Smrg (void) sprintf(newname, "%s/%s", Home, &name[1]); 2703e747e6dSmrg } 2713e747e6dSmrg 2723e747e6dSmrg return newname; 2733e747e6dSmrg} 2743e747e6dSmrg 2753e747e6dSmrg/** 2763e747e6dSmrg * read in the bitmap file for the unknown icon 2773e747e6dSmrg * 2783e747e6dSmrg * \param name the filename to read 2793e747e6dSmrg */ 2803e747e6dSmrgvoid 281c2535118SmrgGetUnknownIcon(const char *name) 2823e747e6dSmrg{ 283b66deae1Smrg int dummy = 0; 284b66deae1Smrg unsigned udummy = 0; 285b66deae1Smrg Window wdummy = None; 286b66deae1Smrg 287329eaa64Smrg if ((Scr->UnknownPm = GetBitmap(name)) != None) { 288b66deae1Smrg XGetGeometry(dpy, Scr->UnknownPm, &wdummy, &dummy, &dummy, 289329eaa64Smrg (unsigned int *) &Scr->UnknownWidth, 290b66deae1Smrg (unsigned int *) &Scr->UnknownHeight, &udummy, &udummy); 2913e747e6dSmrg } 2923e747e6dSmrg} 2933e747e6dSmrg 2943e747e6dSmrg/** 295329eaa64Smrg * FindBitmap - read in a bitmap file and return size 2963e747e6dSmrg * 2973e747e6dSmrg * \return pixmap associated with bitmap 2983e747e6dSmrg * 2993e747e6dSmrg * \param name filename to read 3003e747e6dSmrg * \param[out] widthp pointer to width of bitmap 301329eaa64Smrg * \param[out] heightp pointer to height of bitmap 3023e747e6dSmrg */ 303ffd25bcaSmrgPixmap 304329eaa64SmrgFindBitmap(const char *name, unsigned *widthp, unsigned *heightp) 3053e747e6dSmrg{ 3063e747e6dSmrg char *bigname; 3073e747e6dSmrg Pixmap pm; 3083e747e6dSmrg 309329eaa64Smrg if (!name) 310329eaa64Smrg return None; 3113e747e6dSmrg 3123e747e6dSmrg /* 3133e747e6dSmrg * Names of the form :name refer to hardcoded images that are scaled to 3143e747e6dSmrg * look nice in title buttons. Eventually, it would be nice to put in a 3153e747e6dSmrg * menu symbol as well.... 3163e747e6dSmrg */ 3173e747e6dSmrg if (name[0] == ':') { 318329eaa64Smrg int i; 319329eaa64Smrg /* *INDENT-OFF* */ 320329eaa64Smrg static struct { 321329eaa64Smrg const char *name; 322329eaa64Smrg Pixmap (*proc)(unsigned int *, unsigned int *); 323329eaa64Smrg } pmtab[] = { 324329eaa64Smrg { TBPM_DOT, CreateDotPixmap }, 325329eaa64Smrg { TBPM_ICONIFY, CreateDotPixmap }, 326329eaa64Smrg { TBPM_RESIZE, CreateResizePixmap }, 327329eaa64Smrg { TBPM_XLOGO, CreateXLogoPixmap }, 328329eaa64Smrg { TBPM_DELETE, CreateXLogoPixmap }, 329329eaa64Smrg { TBPM_MENU, CreateMenuPixmap }, 330329eaa64Smrg { TBPM_QUESTION, CreateQuestionPixmap }, 331329eaa64Smrg }; 332329eaa64Smrg /* *INDENT-ON* */ 333329eaa64Smrg 334329eaa64Smrg for (i = 0; (size_t) i < (sizeof pmtab) / (sizeof pmtab[0]); i++) { 335329eaa64Smrg if (XmuCompareISOLatin1(pmtab[i].name, name) == 0) 336329eaa64Smrg return (*pmtab[i].proc) (widthp, heightp); 337329eaa64Smrg } 338329eaa64Smrg twmWarning("no such built-in bitmap \"%s\"", name); 339329eaa64Smrg return None; 3403e747e6dSmrg } 3413e747e6dSmrg 3423e747e6dSmrg /* 3433e747e6dSmrg * Generate a full pathname if any special prefix characters (such as ~) 3443e747e6dSmrg * are used. If the bigname is different from name, bigname will need to 3453e747e6dSmrg * be freed. 3463e747e6dSmrg */ 347329eaa64Smrg bigname = ExpandFilename(name); 348329eaa64Smrg if (!bigname) 349329eaa64Smrg return None; 3503e747e6dSmrg 3513e747e6dSmrg /* 3523e747e6dSmrg * look along bitmapFilePath resource same as toolkit clients 3533e747e6dSmrg */ 354329eaa64Smrg pm = XmuLocateBitmapFile(ScreenOfDisplay(dpy, Scr->screen), bigname, NULL, 355329eaa64Smrg 0, (int *) widthp, (int *) heightp, &HotX, &HotY); 3563e747e6dSmrg if (pm == None && Scr->IconDirectory && bigname[0] != '/') { 357329eaa64Smrg free(bigname); 358329eaa64Smrg /* 359329eaa64Smrg * Attempt to find icon in old IconDirectory (now obsolete) 360329eaa64Smrg */ 361b66deae1Smrg bigname = (char *) 362b66deae1Smrg malloc(strlen(name) + strlen(Scr->IconDirectory) + 2); 363329eaa64Smrg if (!bigname) { 364329eaa64Smrg twmWarning("unable to allocate memory for \"%s/%s\"", 365329eaa64Smrg Scr->IconDirectory, name); 366329eaa64Smrg return None; 367329eaa64Smrg } 368329eaa64Smrg (void) sprintf(bigname, "%s/%s", Scr->IconDirectory, name); 369329eaa64Smrg if (XReadBitmapFile(dpy, Scr->Root, bigname, widthp, heightp, &pm, 370329eaa64Smrg &HotX, &HotY) != BitmapSuccess) { 371329eaa64Smrg pm = None; 372329eaa64Smrg } 373329eaa64Smrg } 374329eaa64Smrg free(bigname); 3753e747e6dSmrg if (pm == None) { 376329eaa64Smrg twmWarning("unable to find bitmap \"%s\"", name); 3773e747e6dSmrg } 3783e747e6dSmrg 3793e747e6dSmrg return pm; 3803e747e6dSmrg} 3813e747e6dSmrg 382ffd25bcaSmrgPixmap 383329eaa64SmrgGetBitmap(const char *name) 3843e747e6dSmrg{ 385b66deae1Smrg unsigned udummy = 0; 386b66deae1Smrg 387b66deae1Smrg return FindBitmap(name, &udummy, &udummy); 3883e747e6dSmrg} 3893e747e6dSmrg 3903e747e6dSmrgvoid 391329eaa64SmrgInsertRGBColormap(Atom a, XStandardColormap *maps, int nmaps, Bool replace) 3923e747e6dSmrg{ 3933e747e6dSmrg StdCmap *sc = NULL; 3943e747e6dSmrg 395329eaa64Smrg if (replace) { /* locate existing entry */ 396329eaa64Smrg for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 397329eaa64Smrg if (sc->atom == a) 398329eaa64Smrg break; 399329eaa64Smrg } 400329eaa64Smrg } 401329eaa64Smrg 402329eaa64Smrg if (!sc) { /* no existing, allocate new */ 403b66deae1Smrg sc = (StdCmap *) malloc(sizeof(StdCmap)); 404329eaa64Smrg if (!sc) { 405329eaa64Smrg twmWarning("unable to allocate %lu bytes for StdCmap", 406329eaa64Smrg (unsigned long) sizeof(StdCmap)); 407329eaa64Smrg return; 408329eaa64Smrg } 409329eaa64Smrg replace = False; 410329eaa64Smrg } 411329eaa64Smrg 412329eaa64Smrg if (replace) { /* just update contents */ 413329eaa64Smrg if (sc->maps) 414329eaa64Smrg XFree(sc->maps); 415329eaa64Smrg if (sc == Scr->StdCmapInfo.mru) 416329eaa64Smrg Scr->StdCmapInfo.mru = NULL; 417329eaa64Smrg } 418329eaa64Smrg else { /* else appending */ 419329eaa64Smrg sc->next = NULL; 420329eaa64Smrg sc->atom = a; 421329eaa64Smrg if (Scr->StdCmapInfo.tail) { 422329eaa64Smrg Scr->StdCmapInfo.tail->next = sc; 423329eaa64Smrg } 424329eaa64Smrg else { 425329eaa64Smrg Scr->StdCmapInfo.head = sc; 426329eaa64Smrg } 427329eaa64Smrg Scr->StdCmapInfo.tail = sc; 4283e747e6dSmrg } 4293e747e6dSmrg sc->nmaps = nmaps; 4303e747e6dSmrg sc->maps = maps; 4313e747e6dSmrg 4323e747e6dSmrg return; 4333e747e6dSmrg} 4343e747e6dSmrg 4353e747e6dSmrgvoid 436329eaa64SmrgRemoveRGBColormap(Atom a) 4373e747e6dSmrg{ 4383e747e6dSmrg StdCmap *sc, *prev; 4393e747e6dSmrg 4403e747e6dSmrg prev = NULL; 441ffd25bcaSmrg for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 442329eaa64Smrg if (sc->atom == a) 443329eaa64Smrg break; 444329eaa64Smrg prev = sc; 4453e747e6dSmrg } 446329eaa64Smrg if (sc) { /* found one */ 447329eaa64Smrg if (sc->maps) 448329eaa64Smrg XFree(sc->maps); 449329eaa64Smrg if (prev) 450329eaa64Smrg prev->next = sc->next; 451329eaa64Smrg if (Scr->StdCmapInfo.head == sc) 452329eaa64Smrg Scr->StdCmapInfo.head = sc->next; 453329eaa64Smrg if (Scr->StdCmapInfo.tail == sc) 454329eaa64Smrg Scr->StdCmapInfo.tail = prev; 455329eaa64Smrg if (Scr->StdCmapInfo.mru == sc) 456329eaa64Smrg Scr->StdCmapInfo.mru = NULL; 4573e747e6dSmrg } 4583e747e6dSmrg return; 4593e747e6dSmrg} 4603e747e6dSmrg 4613e747e6dSmrgvoid 462c2535118SmrgLocateStandardColormaps(void) 4633e747e6dSmrg{ 4643e747e6dSmrg Atom *atoms; 4653e747e6dSmrg int natoms; 4663e747e6dSmrg int i; 4673e747e6dSmrg 468329eaa64Smrg atoms = XListProperties(dpy, Scr->Root, &natoms); 4693e747e6dSmrg for (i = 0; i < natoms; i++) { 470329eaa64Smrg XStandardColormap *maps = NULL; 471329eaa64Smrg int nmaps; 4723e747e6dSmrg 473329eaa64Smrg if (XGetRGBColormaps(dpy, Scr->Root, &maps, &nmaps, atoms[i])) { 474329eaa64Smrg /* if got one, then append to current list */ 475329eaa64Smrg InsertRGBColormap(atoms[i], maps, nmaps, False); 476329eaa64Smrg } 4773e747e6dSmrg } 478329eaa64Smrg if (atoms) 479329eaa64Smrg XFree(atoms); 4803e747e6dSmrg return; 4813e747e6dSmrg} 4823e747e6dSmrg 4833e747e6dSmrgvoid 484c2535118SmrgGetColor(int kind, Pixel *what, const char *name) 4853e747e6dSmrg{ 4863e747e6dSmrg XColor color, junkcolor; 4873e747e6dSmrg Status stat = 0; 4883e747e6dSmrg Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; 4893e747e6dSmrg 4903e747e6dSmrg if (!Scr->FirstTime) 491329eaa64Smrg return; 4923e747e6dSmrg 4933e747e6dSmrg if (Scr->Monochrome != kind) 494329eaa64Smrg return; 495329eaa64Smrg 496329eaa64Smrg if (!XAllocNamedColor(dpy, cmap, name, &color, &junkcolor)) { 497329eaa64Smrg /* if we could not allocate the color, let's see if this is a 498329eaa64Smrg * standard colormap 499329eaa64Smrg */ 500329eaa64Smrg XStandardColormap *stdcmap = NULL; 501329eaa64Smrg 502329eaa64Smrg /* parse the named color */ 503329eaa64Smrg if (name[0] != '#') 504329eaa64Smrg stat = XParseColor(dpy, cmap, name, &color); 505329eaa64Smrg if (!stat) { 506329eaa64Smrg twmWarning("invalid color name \"%s\"", name); 507329eaa64Smrg return; 508329eaa64Smrg } 509329eaa64Smrg 510329eaa64Smrg /* 511329eaa64Smrg * look through the list of standard colormaps (check cache first) 512329eaa64Smrg */ 513329eaa64Smrg if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps && 514329eaa64Smrg (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap == 515329eaa64Smrg cmap)) { 516329eaa64Smrg stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]); 517329eaa64Smrg } 518329eaa64Smrg else { 519329eaa64Smrg StdCmap *sc; 520329eaa64Smrg 521329eaa64Smrg for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { 522329eaa64Smrg int i; 523329eaa64Smrg 524329eaa64Smrg for (i = 0; i < sc->nmaps; i++) { 525329eaa64Smrg if (sc->maps[i].colormap == cmap) { 526329eaa64Smrg Scr->StdCmapInfo.mru = sc; 527329eaa64Smrg Scr->StdCmapInfo.mruindex = i; 528329eaa64Smrg stdcmap = &(sc->maps[i]); 529329eaa64Smrg goto gotit; 530329eaa64Smrg } 531329eaa64Smrg } 532329eaa64Smrg } 533329eaa64Smrg } 534329eaa64Smrg 535329eaa64Smrg gotit: 536329eaa64Smrg if (stdcmap) { 5373e747e6dSmrg color.pixel = (stdcmap->base_pixel + 538329eaa64Smrg ((Pixel) (((float) color.red / 65535.0) * 539329eaa64Smrg (double) stdcmap->red_max + 0.5) * 540329eaa64Smrg stdcmap->red_mult) + 541329eaa64Smrg ((Pixel) (((float) color.green / 65535.0) * 542329eaa64Smrg (double) stdcmap->green_max + 0.5) * 543329eaa64Smrg stdcmap->green_mult) + 544329eaa64Smrg ((Pixel) (((float) color.blue / 65535.0) * 545329eaa64Smrg (double) stdcmap->blue_max + 0.5) * 546329eaa64Smrg stdcmap->blue_mult)); 547329eaa64Smrg } 548329eaa64Smrg else { 549329eaa64Smrg twmWarning("unable to allocate color \"%s\"", name); 550329eaa64Smrg return; 551329eaa64Smrg } 5523e747e6dSmrg } 5533e747e6dSmrg 5543e747e6dSmrg *what = color.pixel; 5553e747e6dSmrg} 5563e747e6dSmrg 5573e747e6dSmrgvoid 558c2535118SmrgGetColorValue(int kind, XColor *what, const char *name) 5593e747e6dSmrg{ 5603e747e6dSmrg XColor junkcolor; 5613e747e6dSmrg Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; 5623e747e6dSmrg 5633e747e6dSmrg if (!Scr->FirstTime) 564329eaa64Smrg return; 5653e747e6dSmrg 5663e747e6dSmrg if (Scr->Monochrome != kind) 567329eaa64Smrg return; 5683e747e6dSmrg 569329eaa64Smrg if (!XLookupColor(dpy, cmap, name, what, &junkcolor)) { 570329eaa64Smrg twmWarning("invalid color name \"%s\"", name); 5713e747e6dSmrg } 572329eaa64Smrg else { 573329eaa64Smrg what->pixel = AllPlanes; 5743e747e6dSmrg } 5753e747e6dSmrg} 5763e747e6dSmrg 577329eaa64Smrgstatic Boolean 578329eaa64SmrgFindFontSet(MyFont *font, const char *fontname) 5793e747e6dSmrg{ 5803e747e6dSmrg char **missing_charset_list_return; 5813e747e6dSmrg int missing_charset_count_return; 5823e747e6dSmrg char *def_string_return; 5833e747e6dSmrg XFontSetExtents *font_extents; 5843e747e6dSmrg XFontStruct **xfonts; 5853e747e6dSmrg char **font_names; 5863e747e6dSmrg 5873e747e6dSmrg if (use_fontset) { 588329eaa64Smrg int ascent; 589329eaa64Smrg int descent; 590329eaa64Smrg int fnum; 591b66deae1Smrg int i; 592329eaa64Smrg 593329eaa64Smrg if (font->fontset != NULL) { 594329eaa64Smrg XFreeFontSet(dpy, font->fontset); 595329eaa64Smrg } 596329eaa64Smrg 597329eaa64Smrg if ((font->fontset = XCreateFontSet(dpy, fontname, 598329eaa64Smrg &missing_charset_list_return, 599329eaa64Smrg &missing_charset_count_return, 600329eaa64Smrg &def_string_return)) == NULL) { 601329eaa64Smrg return False; 602329eaa64Smrg } 603329eaa64Smrg if (missing_charset_count_return) { 604329eaa64Smrg twmVerbose("%d fonts are missing from fontset", 605329eaa64Smrg missing_charset_count_return); 606329eaa64Smrg for (i = 0; i < missing_charset_count_return; i++) { 607329eaa64Smrg twmVerbose("font for charset %s is lacking.", 608329eaa64Smrg missing_charset_list_return[i]); 609329eaa64Smrg } 610b66deae1Smrg XFreeStringList(missing_charset_list_return); 611329eaa64Smrg } 612329eaa64Smrg 613329eaa64Smrg font_extents = XExtentsOfFontSet(font->fontset); 614329eaa64Smrg fnum = XFontsOfFontSet(font->fontset, &xfonts, &font_names); 615329eaa64Smrg for (i = 0, ascent = 0, descent = 0; i < fnum; i++) { 616329eaa64Smrg if (ascent < (*xfonts)->ascent) 617329eaa64Smrg ascent = (*xfonts)->ascent; 618329eaa64Smrg if (descent < (*xfonts)->descent) 619329eaa64Smrg descent = (*xfonts)->descent; 620329eaa64Smrg xfonts++; 621329eaa64Smrg } 622329eaa64Smrg font->height = font_extents->max_logical_extent.height; 623329eaa64Smrg font->y = ascent; 624329eaa64Smrg font->ascent = ascent; 625329eaa64Smrg font->descent = descent; 626329eaa64Smrg twmMessage("created fontset with %d fonts (%d missing) for \"%s\"", 627329eaa64Smrg fnum, missing_charset_count_return, 628329eaa64Smrg fontname ? fontname : "NULL"); 629329eaa64Smrg return True; 6303e747e6dSmrg } 6313e747e6dSmrg 6323e747e6dSmrg if (font->font != NULL) 633329eaa64Smrg XFreeFont(dpy, font->font); 6343e747e6dSmrg 635329eaa64Smrg if ((font->font = XLoadQueryFont(dpy, fontname)) == NULL) { 636329eaa64Smrg return False; 6373e747e6dSmrg } 6383e747e6dSmrg font->height = font->font->ascent + font->font->descent; 6393e747e6dSmrg font->y = font->font->ascent; 6403e747e6dSmrg font->ascent = font->font->ascent; 6413e747e6dSmrg font->descent = font->font->descent; 642329eaa64Smrg return True; 643329eaa64Smrg} 644329eaa64Smrg 645329eaa64Smrg/* 646329eaa64Smrg * The following functions are sensible to 'use_fontset'. 647329eaa64Smrg * When 'use_fontset' is True, 648329eaa64Smrg * - XFontSet-related internationalized functions are used 649329eaa64Smrg * so as multibyte languages can be displayed. 650329eaa64Smrg * When 'use_fontset' is False, 651329eaa64Smrg * - XFontStruct-related conventional functions are used 652329eaa64Smrg * so as 8-bit characters can be displayed even when 653329eaa64Smrg * locale is not set properly. 654329eaa64Smrg */ 655329eaa64Smrgvoid 656329eaa64SmrgGetFont(MyFont *font) 657329eaa64Smrg{ 658329eaa64Smrg 659329eaa64Smrg if (!FindFontSet(font, font->name)) { 660329eaa64Smrg const char *what = "fonts"; 661329eaa64Smrg const char *deffontname = "fixed"; 662329eaa64Smrg 663329eaa64Smrg if (use_fontset) { 664329eaa64Smrg what = "fontsets"; 665329eaa64Smrg } 666329eaa64Smrg else if (Scr->DefaultFont.name) { 667329eaa64Smrg deffontname = Scr->DefaultFont.name; 668329eaa64Smrg } 669329eaa64Smrg if (!FindFontSet(font, deffontname)) { 670329eaa64Smrg twmError("unable to open %s \"%s\" or \"%s\"", 671329eaa64Smrg what, font->name, deffontname); 672329eaa64Smrg } 673329eaa64Smrg } 6743e747e6dSmrg} 6753e747e6dSmrg 676b66deae1Smrgvoid 677b66deae1SmrgDestroyFont(MyFont *font) 678b66deae1Smrg{ 679b66deae1Smrg if (!font) { 680b66deae1Smrg return; 681b66deae1Smrg } 682b66deae1Smrg 683b66deae1Smrg if (font->fontset) { 684b66deae1Smrg XFreeFontSet(dpy, font->fontset); 685b66deae1Smrg font->fontset = NULL; 686b66deae1Smrg } 687b66deae1Smrg 688b66deae1Smrg if (font->font) { 689b66deae1Smrg XFreeFont(dpy, font->font); 690b66deae1Smrg font->font = NULL; 691b66deae1Smrg } 692b66deae1Smrg} 693b66deae1Smrg 6943e747e6dSmrgint 695c2535118SmrgMyFont_TextWidth(MyFont *font, const char *string, int len) 6963e747e6dSmrg{ 6973e747e6dSmrg XRectangle ink_rect; 6983e747e6dSmrg XRectangle logical_rect; 6993e747e6dSmrg 7003e747e6dSmrg if (use_fontset) { 701329eaa64Smrg XmbTextExtents(font->fontset, string, len, &ink_rect, &logical_rect); 702329eaa64Smrg return logical_rect.width; 7033e747e6dSmrg } 7043e747e6dSmrg return XTextWidth(font->font, string, len); 7053e747e6dSmrg} 7063e747e6dSmrg 7073e747e6dSmrgvoid 708329eaa64SmrgMyFont_DrawImageString(Display *dpy2, Drawable d, MyFont *font, GC gc, 709c2535118Smrg int x, int y, const char *string, int len) 7103e747e6dSmrg{ 7113e747e6dSmrg if (use_fontset) { 712329eaa64Smrg XmbDrawImageString(dpy2, d, font->fontset, gc, x, y, string, len); 713329eaa64Smrg return; 7143e747e6dSmrg } 715329eaa64Smrg XDrawImageString(dpy2, d, gc, x, y, string, len); 7163e747e6dSmrg} 7173e747e6dSmrg 7183e747e6dSmrgvoid 719329eaa64SmrgMyFont_DrawString(Display *dpy2, Drawable d, MyFont *font, GC gc, 720c2535118Smrg int x, int y, const char *string, int len) 7213e747e6dSmrg{ 7223e747e6dSmrg if (use_fontset) { 723329eaa64Smrg XmbDrawString(dpy2, d, font->fontset, gc, x, y, string, len); 724329eaa64Smrg return; 7253e747e6dSmrg } 726329eaa64Smrg XDrawString(dpy2, d, gc, x, y, string, len); 7273e747e6dSmrg} 7283e747e6dSmrg 7293e747e6dSmrgvoid 730ffd25bcaSmrgMyFont_ChangeGC(unsigned long fix_fore, unsigned long fix_back, 7313e747e6dSmrg MyFont *fix_font) 7323e747e6dSmrg{ 7333e747e6dSmrg Gcv.foreground = fix_fore; 7343e747e6dSmrg Gcv.background = fix_back; 7353e747e6dSmrg if (use_fontset) { 736329eaa64Smrg XChangeGC(dpy, Scr->NormalGC, GCForeground | GCBackground, &Gcv); 737329eaa64Smrg return; 7383e747e6dSmrg } 7393e747e6dSmrg Gcv.font = fix_font->font->fid; 740329eaa64Smrg XChangeGC(dpy, Scr->NormalGC, GCFont | GCForeground | GCBackground, &Gcv); 7413e747e6dSmrg} 7423e747e6dSmrg 7433e747e6dSmrg/* 7443e747e6dSmrg * The following functions are internationalized substitutions 7453e747e6dSmrg * for XFetchName and XGetIconName using XGetWMName and 746ffd25bcaSmrg * XGetWMIconName. 7473e747e6dSmrg * 748ffd25bcaSmrg * Please note that the third arguments have to be freed using free(), 7493e747e6dSmrg * not XFree(). 7503e747e6dSmrg */ 7513e747e6dSmrgStatus 752329eaa64SmrgI18N_FetchName(Display *dpy2, Window w, char **winname) 7533e747e6dSmrg{ 754329eaa64Smrg int status; 7553e747e6dSmrg XTextProperty text_prop; 756329eaa64Smrg int rc = 0; 757329eaa64Smrg 758329eaa64Smrg *winname = NULL; 759329eaa64Smrg 760329eaa64Smrg status = XGetWMName(dpy2, w, &text_prop); 761329eaa64Smrg if (status && text_prop.value && text_prop.nitems) { 762329eaa64Smrg char **list = NULL; 763329eaa64Smrg int num; 764329eaa64Smrg 765329eaa64Smrg status = XmbTextPropertyToTextList(dpy2, &text_prop, &list, &num); 766329eaa64Smrg if (status >= Success && num && list && *list) { 767329eaa64Smrg XFree(text_prop.value); 768329eaa64Smrg *winname = strdup(*list); 769329eaa64Smrg XFreeStringList(list); 770329eaa64Smrg rc = 1; 771329eaa64Smrg } 772329eaa64Smrg else { 773329eaa64Smrg char *value = NULL; 774329eaa64Smrg 775329eaa64Smrg /* 776329eaa64Smrg * If the system's locale support is broken (e.g., missing useful 777329eaa64Smrg * parts), the preceding Xmb call may fail. 778329eaa64Smrg */ 779329eaa64Smrg if (XFetchName(dpy2, w, &value) && value != NULL) { 780329eaa64Smrg *winname = strdup(value); 781329eaa64Smrg XFree(value); 782329eaa64Smrg rc = 1; 783329eaa64Smrg } 784329eaa64Smrg } 7853e747e6dSmrg } 786329eaa64Smrg 787329eaa64Smrg return rc; 7883e747e6dSmrg} 7893e747e6dSmrg 7903e747e6dSmrgStatus 791329eaa64SmrgI18N_GetIconName(Display *dpy2, Window w, char **iconname) 7923e747e6dSmrg{ 793329eaa64Smrg int status; 7943e747e6dSmrg XTextProperty text_prop; 7953e747e6dSmrg char **list; 796329eaa64Smrg int num; 797329eaa64Smrg 798329eaa64Smrg status = XGetWMIconName(dpy2, w, &text_prop); 799329eaa64Smrg if (!status || !text_prop.value || !text_prop.nitems) 800329eaa64Smrg return 0; 801329eaa64Smrg status = XmbTextPropertyToTextList(dpy2, &text_prop, &list, &num); 802329eaa64Smrg if (status < Success || !num || !*list) 803329eaa64Smrg return 0; 8043e747e6dSmrg XFree(text_prop.value); 805329eaa64Smrg *iconname = (char *) strdup(*list); 8063e747e6dSmrg XFreeStringList(list); 8073e747e6dSmrg return 1; 8083e747e6dSmrg} 8093e747e6dSmrg 8103e747e6dSmrg/** 8113e747e6dSmrg * separate routine to set focus to make things more understandable 8123e747e6dSmrg * and easier to debug 8133e747e6dSmrg */ 8143e747e6dSmrgvoid 815329eaa64SmrgSetFocus(TwmWindow *tmp_win, Time time) 8163e747e6dSmrg{ 8173e747e6dSmrg Window w = (tmp_win ? tmp_win->w : PointerRoot); 8183e747e6dSmrg 8193e747e6dSmrg#ifdef TRACE 8203e747e6dSmrg if (tmp_win) { 821329eaa64Smrg twmMessage("Focusing on window \"%s\"", tmp_win->full_name); 822329eaa64Smrg } 823329eaa64Smrg else { 824329eaa64Smrg twmMessage("Unfocusing; Scr->Focus was \"%s\"", 825329eaa64Smrg Scr->Focus ? Scr->Focus->full_name : "(nil)"); 8263e747e6dSmrg } 8273e747e6dSmrg#endif 8283e747e6dSmrg 829329eaa64Smrg XSetInputFocus(dpy, w, RevertToPointerRoot, time); 8303e747e6dSmrg} 8313e747e6dSmrg 832ffd25bcaSmrgstatic Pixmap 833329eaa64SmrgCreateXLogoPixmap(unsigned *widthp, unsigned *heightp) 8343e747e6dSmrg{ 8353e747e6dSmrg int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 836329eaa64Smrg 837329eaa64Smrg if (h < 0) 838329eaa64Smrg h = 0; 8393e747e6dSmrg 8403e747e6dSmrg *widthp = *heightp = (unsigned int) h; 8413e747e6dSmrg if (Scr->tbpm.xlogo == None) { 842329eaa64Smrg GC gc, gcBack; 843329eaa64Smrg 844329eaa64Smrg Scr->tbpm.xlogo = 845329eaa64Smrg XCreatePixmap(dpy, Scr->Root, (unsigned) h, (unsigned) h, 1); 846329eaa64Smrg gc = XCreateGC(dpy, Scr->tbpm.xlogo, 0L, NULL); 847329eaa64Smrg XSetForeground(dpy, gc, 0); 848329eaa64Smrg XFillRectangle(dpy, Scr->tbpm.xlogo, gc, 0, 0, (unsigned) h, 849329eaa64Smrg (unsigned) h); 850329eaa64Smrg XSetForeground(dpy, gc, 1); 851329eaa64Smrg gcBack = XCreateGC(dpy, Scr->tbpm.xlogo, 0L, NULL); 852329eaa64Smrg XSetForeground(dpy, gcBack, 0); 853329eaa64Smrg 854329eaa64Smrg /* 855329eaa64Smrg * draw the logo large so that it gets as dense as possible; then white 856329eaa64Smrg * out the edges so that they look crisp 857329eaa64Smrg */ 858329eaa64Smrg XmuDrawLogo(dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, 859329eaa64Smrg (unsigned) (h + 2), (unsigned) (h + 2)); 860329eaa64Smrg XDrawRectangle(dpy, Scr->tbpm.xlogo, gcBack, 0, 0, (unsigned) (h - 1), 861329eaa64Smrg (unsigned) (h - 1)); 862329eaa64Smrg 863329eaa64Smrg /* 864329eaa64Smrg * done drawing 865329eaa64Smrg */ 866329eaa64Smrg XFreeGC(dpy, gc); 867329eaa64Smrg XFreeGC(dpy, gcBack); 8683e747e6dSmrg } 8693e747e6dSmrg return Scr->tbpm.xlogo; 8703e747e6dSmrg} 8713e747e6dSmrg 872ffd25bcaSmrgstatic Pixmap 873329eaa64SmrgCreateResizePixmap(unsigned *widthp, unsigned *heightp) 8743e747e6dSmrg{ 8753e747e6dSmrg int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 876329eaa64Smrg 877329eaa64Smrg if (h < 1) 878329eaa64Smrg h = 1; 8793e747e6dSmrg 8803e747e6dSmrg *widthp = *heightp = (unsigned int) h; 8813e747e6dSmrg if (Scr->tbpm.resize == None) { 882329eaa64Smrg XPoint points[3]; 883329eaa64Smrg GC gc; 884329eaa64Smrg int w; 885329eaa64Smrg int lw; 886329eaa64Smrg 887329eaa64Smrg /* 888329eaa64Smrg * create the pixmap 889329eaa64Smrg */ 890329eaa64Smrg Scr->tbpm.resize = 891329eaa64Smrg XCreatePixmap(dpy, Scr->Root, (unsigned) h, (unsigned) h, 1); 892329eaa64Smrg gc = XCreateGC(dpy, Scr->tbpm.resize, 0L, NULL); 893329eaa64Smrg XSetForeground(dpy, gc, 0); 894329eaa64Smrg XFillRectangle(dpy, Scr->tbpm.resize, gc, 0, 0, (unsigned) h, 895329eaa64Smrg (unsigned) h); 896329eaa64Smrg XSetForeground(dpy, gc, 1); 897329eaa64Smrg lw = h / 16; 898329eaa64Smrg if (lw == 1) 899329eaa64Smrg lw = 0; 900329eaa64Smrg XSetLineAttributes(dpy, gc, (unsigned) lw, LineSolid, CapButt, 901329eaa64Smrg JoinMiter); 902329eaa64Smrg 903329eaa64Smrg /* 904329eaa64Smrg * draw the resize button, 905329eaa64Smrg */ 906329eaa64Smrg w = (h * 2) / 3; 907329eaa64Smrg points[0].x = (short) w; 908329eaa64Smrg points[0].y = 0; 909329eaa64Smrg points[1].x = (short) w; 910329eaa64Smrg points[1].y = (short) w; 911329eaa64Smrg points[2].x = 0; 912329eaa64Smrg points[2].y = (short) w; 913329eaa64Smrg XDrawLines(dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 914329eaa64Smrg w = w / 2; 915329eaa64Smrg points[0].x = (short) w; 916329eaa64Smrg points[0].y = 0; 917329eaa64Smrg points[1].x = (short) w; 918329eaa64Smrg points[1].y = (short) w; 919329eaa64Smrg points[2].x = 0; 920329eaa64Smrg points[2].y = (short) w; 921329eaa64Smrg XDrawLines(dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); 922329eaa64Smrg 923329eaa64Smrg /* 924329eaa64Smrg * done drawing 925329eaa64Smrg */ 926329eaa64Smrg XFreeGC(dpy, gc); 9273e747e6dSmrg } 9283e747e6dSmrg return Scr->tbpm.resize; 9293e747e6dSmrg} 9303e747e6dSmrg 931ffd25bcaSmrgstatic Pixmap 932329eaa64SmrgCreateDotPixmap(unsigned *widthp, unsigned *heightp) 9333e747e6dSmrg{ 9343e747e6dSmrg int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; 9353e747e6dSmrg 9363e747e6dSmrg h = h * 3 / 4; 937329eaa64Smrg if (h < 1) 938329eaa64Smrg h = 1; 9393e747e6dSmrg if (!(h & 1)) 940329eaa64Smrg h--; 9413e747e6dSmrg *widthp = *heightp = (unsigned int) h; 942b66deae1Smrg if (Scr->tbpm.remove == None) { 943329eaa64Smrg GC gc; 944329eaa64Smrg Pixmap pix; 945329eaa64Smrg 946b66deae1Smrg pix = Scr->tbpm.remove = 947329eaa64Smrg XCreatePixmap(dpy, Scr->Root, (unsigned) h, (unsigned) h, 1); 948329eaa64Smrg gc = XCreateGC(dpy, pix, 0L, NULL); 949329eaa64Smrg XSetLineAttributes(dpy, gc, (unsigned) h, LineSolid, CapRound, 950329eaa64Smrg JoinRound); 951329eaa64Smrg XSetForeground(dpy, gc, 0L); 952329eaa64Smrg XFillRectangle(dpy, pix, gc, 0, 0, (unsigned) h, (unsigned) h); 953329eaa64Smrg XSetForeground(dpy, gc, 1L); 954329eaa64Smrg XDrawLine(dpy, pix, gc, h / 2, h / 2, h / 2, h / 2); 955329eaa64Smrg XFreeGC(dpy, gc); 9563e747e6dSmrg } 957b66deae1Smrg return Scr->tbpm.remove; 9583e747e6dSmrg} 9593e747e6dSmrg 9603e747e6dSmrg#define questionmark_width 8 9613e747e6dSmrg#define questionmark_height 8 9623e747e6dSmrgstatic char questionmark_bits[] = { 963329eaa64Smrg 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18 964329eaa64Smrg}; 9653e747e6dSmrg 966ffd25bcaSmrgstatic Pixmap 967329eaa64SmrgCreateQuestionPixmap(unsigned *widthp, unsigned *heightp) 9683e747e6dSmrg{ 9693e747e6dSmrg *widthp = questionmark_width; 9703e747e6dSmrg *heightp = questionmark_height; 9713e747e6dSmrg if (Scr->tbpm.question == None) { 972329eaa64Smrg Scr->tbpm.question = XCreateBitmapFromData(dpy, Scr->Root, 973329eaa64Smrg questionmark_bits, 974329eaa64Smrg questionmark_width, 975329eaa64Smrg questionmark_height); 9763e747e6dSmrg } 9773e747e6dSmrg /* 9783e747e6dSmrg * this must succeed or else we are in deep trouble elsewhere 9793e747e6dSmrg */ 9803e747e6dSmrg return Scr->tbpm.question; 9813e747e6dSmrg} 9823e747e6dSmrg 983ffd25bcaSmrgstatic Pixmap 984329eaa64SmrgCreateMenuPixmap(unsigned *widthp, unsigned *heightp) 9853e747e6dSmrg{ 986329eaa64Smrg return CreateMenuIcon(Scr->TBInfo.width - Scr->TBInfo.border * 2, 987329eaa64Smrg widthp, heightp); 9883e747e6dSmrg} 9893e747e6dSmrg 990ffd25bcaSmrgPixmap 991329eaa64SmrgCreateMenuIcon(int height, unsigned *widthp, unsigned *heightp) 9923e747e6dSmrg{ 9933e747e6dSmrg int h, w; 9943e747e6dSmrg 9953e747e6dSmrg h = height; 9963e747e6dSmrg w = h * 7 / 8; 9973e747e6dSmrg if (h < 1) 998329eaa64Smrg h = 1; 9993e747e6dSmrg if (w < 1) 1000329eaa64Smrg w = 1; 1001329eaa64Smrg *widthp = (unsigned) w; 1002329eaa64Smrg *heightp = (unsigned) h; 10033e747e6dSmrg if (Scr->tbpm.menu == None) { 1004329eaa64Smrg Pixmap pix; 1005329eaa64Smrg GC gc; 1006329eaa64Smrg int ih, iw; 1007329eaa64Smrg int ix, iy; 1008329eaa64Smrg int mh, mw; 1009329eaa64Smrg int tw, th; 1010329eaa64Smrg int lw, lh; 1011329eaa64Smrg int lx, ly; 1012329eaa64Smrg int lines, dly; 1013329eaa64Smrg int off; 1014329eaa64Smrg int bw; 1015329eaa64Smrg 1016329eaa64Smrg pix = Scr->tbpm.menu = 1017329eaa64Smrg XCreatePixmap(dpy, Scr->Root, (unsigned) w, (unsigned) h, 1); 1018329eaa64Smrg gc = XCreateGC(dpy, pix, 0L, NULL); 1019329eaa64Smrg XSetForeground(dpy, gc, 0L); 1020329eaa64Smrg XFillRectangle(dpy, pix, gc, 0, 0, (unsigned) w, (unsigned) h); 1021329eaa64Smrg XSetForeground(dpy, gc, 1L); 1022329eaa64Smrg ix = 1; 1023329eaa64Smrg iy = 1; 1024329eaa64Smrg ih = h - iy * 2; 1025329eaa64Smrg iw = w - ix * 2; 1026329eaa64Smrg off = ih / 8; 1027329eaa64Smrg mh = ih - off; 1028329eaa64Smrg mw = iw - off; 1029329eaa64Smrg bw = mh / 16; 1030329eaa64Smrg if (bw == 0 && mw > 2) 1031329eaa64Smrg bw = 1; 1032329eaa64Smrg tw = mw - bw * 2; 1033329eaa64Smrg th = mh - bw * 2; 1034329eaa64Smrg XFillRectangle(dpy, pix, gc, ix, iy, (unsigned) mw, (unsigned) mh); 1035329eaa64Smrg XFillRectangle(dpy, pix, gc, ix + iw - mw, iy + ih - mh, (unsigned) mw, 1036329eaa64Smrg (unsigned) mh); 1037329eaa64Smrg XSetForeground(dpy, gc, 0L); 1038329eaa64Smrg XFillRectangle(dpy, pix, gc, ix + bw, iy + bw, (unsigned) tw, 1039329eaa64Smrg (unsigned) th); 1040329eaa64Smrg XSetForeground(dpy, gc, 1L); 1041329eaa64Smrg lw = tw / 2; 1042329eaa64Smrg if ((tw & 1) ^ (lw & 1)) 1043329eaa64Smrg lw++; 1044329eaa64Smrg lx = ix + bw + (tw - lw) / 2; 1045329eaa64Smrg 1046329eaa64Smrg lh = th / 2 - bw; 1047329eaa64Smrg if ((lh & 1) ^ ((th - bw) & 1)) 1048329eaa64Smrg lh++; 1049329eaa64Smrg ly = iy + bw + (th - bw - lh) / 2; 1050329eaa64Smrg 1051329eaa64Smrg lines = 3; 1052329eaa64Smrg if ((lh & 1) && lh < 6) { 1053329eaa64Smrg lines--; 1054329eaa64Smrg } 1055329eaa64Smrg dly = lh / (lines - 1); 1056329eaa64Smrg while (lines--) { 1057329eaa64Smrg XFillRectangle(dpy, pix, gc, lx, ly, (unsigned) lw, (unsigned) bw); 1058329eaa64Smrg ly += dly; 1059329eaa64Smrg } 1060329eaa64Smrg XFreeGC(dpy, gc); 10613e747e6dSmrg } 10623e747e6dSmrg return Scr->tbpm.menu; 10633e747e6dSmrg} 10643e747e6dSmrg 10653e747e6dSmrgvoid 1066329eaa64SmrgBell(int type _X_UNUSED, int percent, Window win _X_UNUSED) 10673e747e6dSmrg{ 10683e747e6dSmrg#ifdef XKB 10693e747e6dSmrg XkbStdBell(dpy, win, percent, type); 10703e747e6dSmrg#else 10713e747e6dSmrg XBell(dpy, percent); 10723e747e6dSmrg#endif 10733e747e6dSmrg return; 10743e747e6dSmrg} 1075