/*****************************************************************************/ /* Copyright 1989, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Cambridge, Massachusetts **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** name of Evans & Sutherland not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/ /** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ /*********************************************************************** * * $Xorg: util.c,v 1.5 2001/02/09 02:05:37 xorgcvs Exp $ * * utility routines for twm * * 28-Oct-87 Thomas E. LaStrange File created * ***********************************************************************/ #include "twm.h" #include "util.h" #include "gram.h" #include "screen.h" #include #include #include #include #include static Pixmap CreateXLogoPixmap(), CreateResizePixmap(); static Pixmap CreateQuestionPixmap(), CreateMenuPixmap(); static Pixmap CreateDotPixmap(); int HotX, HotY; /*********************************************************************** * * Procedure: * MoveOutline - move a window outline * * Inputs: * root - the window we are outlining * x - upper left x coordinate * y - upper left y coordinate * width - the width of the rectangle * height - the height of the rectangle * bw - the border width of the frame * th - title height * *********************************************************************** */ /* ARGSUSED */ void MoveOutline(root, x, y, width, height, bw, th) Window root; int x, y, width, height, bw, th; { static int lastx = 0; static int lasty = 0; static int lastWidth = 0; static int lastHeight = 0; static int lastBW = 0; static int lastTH = 0; int xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb; int xthird, ythird; XSegment outline[18]; register XSegment *r; if (x == lastx && y == lasty && width == lastWidth && height == lastHeight && lastBW == bw && th == lastTH) return; r = outline; #define DRAWIT() \ if (lastWidth || lastHeight) \ { \ xl = lastx; \ xr = lastx + lastWidth - 1; \ yt = lasty; \ yb = lasty + lastHeight - 1; \ xinnerl = xl + lastBW; \ xinnerr = xr - lastBW; \ yinnert = yt + lastTH + lastBW; \ yinnerb = yb - lastBW; \ xthird = (xinnerr - xinnerl) / 3; \ ythird = (yinnerb - yinnert) / 3; \ \ r->x1 = xl; \ r->y1 = yt; \ r->x2 = xr; \ r->y2 = yt; \ r++; \ \ r->x1 = xl; \ r->y1 = yb; \ r->x2 = xr; \ r->y2 = yb; \ r++; \ \ r->x1 = xl; \ r->y1 = yt; \ r->x2 = xl; \ r->y2 = yb; \ r++; \ \ r->x1 = xr; \ r->y1 = yt; \ r->x2 = xr; \ r->y2 = yb; \ r++; \ \ r->x1 = xinnerl + xthird; \ r->y1 = yinnert; \ r->x2 = r->x1; \ r->y2 = yinnerb; \ r++; \ \ r->x1 = xinnerl + (2 * xthird); \ r->y1 = yinnert; \ r->x2 = r->x1; \ r->y2 = yinnerb; \ r++; \ \ r->x1 = xinnerl; \ r->y1 = yinnert + ythird; \ r->x2 = xinnerr; \ r->y2 = r->y1; \ r++; \ \ r->x1 = xinnerl; \ r->y1 = yinnert + (2 * ythird); \ r->x2 = xinnerr; \ r->y2 = r->y1; \ r++; \ \ if (lastTH != 0) { \ r->x1 = xl; \ r->y1 = yt + lastTH; \ r->x2 = xr; \ r->y2 = r->y1; \ r++; \ } \ } /* undraw the old one, if any */ DRAWIT (); lastx = x; lasty = y; lastWidth = width; lastHeight = height; lastBW = bw; lastTH = th; /* draw the new one, if any */ DRAWIT (); #undef DRAWIT if (r != outline) { XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline); } } /*********************************************************************** * * Procedure: * Zoom - zoom in or out of an icon * * Inputs: * wf - window to zoom from * wt - window to zoom to * *********************************************************************** */ void Zoom(wf, wt) Window wf, wt; { int fx, fy, tx, ty; /* from, to */ unsigned int fw, fh, tw, th; /* from, to */ long dx, dy, dw, dh; long z; int j; if (!Scr->DoZoom || Scr->ZoomCount < 1) return; if (wf == None || wt == None) return; XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth); XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth); dx = ((long) (tx - fx)); /* going from -> to */ dy = ((long) (ty - fy)); /* going from -> to */ dw = ((long) (tw - fw)); /* going from -> to */ dh = ((long) (th - fh)); /* going from -> to */ z = (long) (Scr->ZoomCount + 1); for (j = 0; j < 2; j++) { long i; XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh); for (i = 1; i < z; i++) { int x = fx + (int) ((dx * i) / z); int y = fy + (int) ((dy * i) / z); unsigned width = (unsigned) (((long) fw) + (dw * i) / z); unsigned height = (unsigned) (((long) fh) + (dh * i) / z); XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, x, y, width, height); } XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th); } } /*********************************************************************** * * Procedure: * ExpandFilename - expand the tilde character to HOME * if it is the first character of the filename * * Returned Value: * a pointer to the new name * * Inputs: * name - the filename to expand * *********************************************************************** */ char * ExpandFilename(name) char *name; { char *newname; if (name[0] != '~') return name; newname = (char *) malloc (HomeLen + strlen(name) + 2); if (!newname) { fprintf (stderr, "%s: unable to allocate %d bytes to expand filename %s/%s\n", ProgramName, HomeLen + strlen(name) + 2, Home, &name[1]); } else { (void) sprintf (newname, "%s/%s", Home, &name[1]); } return newname; } /*********************************************************************** * * Procedure: * GetUnknownIcon - read in the bitmap file for the unknown icon * * Inputs: * name - the filename to read * *********************************************************************** */ void GetUnknownIcon(name) char *name; { if ((Scr->UnknownPm = GetBitmap(name)) != None) { XGetGeometry(dpy, Scr->UnknownPm, &JunkRoot, &JunkX, &JunkY, (unsigned int *)&Scr->UnknownWidth, (unsigned int *)&Scr->UnknownHeight, &JunkBW, &JunkDepth); } } /*********************************************************************** * * Procedure: * FindBitmap - read in a bitmap file and return size * * Returned Value: * the pixmap associated with the bitmap * widthp - pointer to width of bitmap * heightp - pointer to height of bitmap * * Inputs: * name - the filename to read * *********************************************************************** */ Pixmap FindBitmap (name, widthp, heightp) char *name; unsigned int *widthp, *heightp; { char *bigname; Pixmap pm; if (!name) return None; /* * Names of the form :name refer to hardcoded images that are scaled to * look nice in title buttons. Eventually, it would be nice to put in a * menu symbol as well.... */ if (name[0] == ':') { int i; static struct { char *name; Pixmap (*proc)(); } pmtab[] = { { TBPM_DOT, CreateDotPixmap }, { TBPM_ICONIFY, CreateDotPixmap }, { TBPM_RESIZE, CreateResizePixmap }, { TBPM_XLOGO, CreateXLogoPixmap }, { TBPM_DELETE, CreateXLogoPixmap }, { TBPM_MENU, CreateMenuPixmap }, { TBPM_QUESTION, CreateQuestionPixmap }, }; for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) { if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0) return (*pmtab[i].proc) (widthp, heightp); } fprintf (stderr, "%s: no such built-in bitmap \"%s\"\n", ProgramName, name); return None; } /* * Generate a full pathname if any special prefix characters (such as ~) * are used. If the bigname is different from name, bigname will need to * be freed. */ bigname = ExpandFilename (name); if (!bigname) return None; /* * look along bitmapFilePath resource same as toolkit clients */ pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL, 0, (int *)widthp, (int *)heightp, &HotX, &HotY); if (pm == None && Scr->IconDirectory && bigname[0] != '/') { if (bigname != name) free (bigname); /* * Attempt to find icon in old IconDirectory (now obsolete) */ bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) + 2); if (!bigname) { fprintf (stderr, "%s: unable to allocate memory for \"%s/%s\"\n", ProgramName, Scr->IconDirectory, name); return None; } (void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name); if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm, &HotX, &HotY) != BitmapSuccess) { pm = None; } } if (bigname != name) free (bigname); if (pm == None) { fprintf (stderr, "%s: unable to find bitmap \"%s\"\n", ProgramName, name); } return pm; } Pixmap GetBitmap (name) char *name; { return FindBitmap (name, &JunkWidth, &JunkHeight); } InsertRGBColormap (a, maps, nmaps, replace) Atom a; XStandardColormap *maps; int nmaps; Bool replace; { StdCmap *sc = NULL; if (replace) { /* locate existing entry */ for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { if (sc->atom == a) break; } } if (!sc) { /* no existing, allocate new */ sc = (StdCmap *) malloc (sizeof (StdCmap)); if (!sc) { fprintf (stderr, "%s: unable to allocate %d bytes for StdCmap\n", ProgramName, sizeof (StdCmap)); return; } } if (replace) { /* just update contents */ if (sc->maps) XFree ((char *) maps); if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL; } else { /* else appending */ sc->next = NULL; sc->atom = a; if (Scr->StdCmapInfo.tail) { Scr->StdCmapInfo.tail->next = sc; } else { Scr->StdCmapInfo.head = sc; } Scr->StdCmapInfo.tail = sc; } sc->nmaps = nmaps; sc->maps = maps; return; } RemoveRGBColormap (a) Atom a; { StdCmap *sc, *prev; prev = NULL; for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { if (sc->atom == a) break; prev = sc; } if (sc) { /* found one */ if (sc->maps) XFree ((char *) sc->maps); if (prev) prev->next = sc->next; if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next; if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev; if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL; } return; } LocateStandardColormaps() { Atom *atoms; int natoms; int i; atoms = XListProperties (dpy, Scr->Root, &natoms); for (i = 0; i < natoms; i++) { XStandardColormap *maps = NULL; int nmaps; if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) { /* if got one, then append to current list */ InsertRGBColormap (atoms[i], maps, nmaps, False); } } if (atoms) XFree ((char *) atoms); return; } GetColor(kind, what, name) int kind; Pixel *what; char *name; { XColor color, junkcolor; Status stat = 0; Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; #ifndef TOM if (!Scr->FirstTime) return; #endif if (Scr->Monochrome != kind) return; if (!XAllocNamedColor (dpy, cmap, name, &color, &junkcolor)) { /* if we could not allocate the color, let's see if this is a * standard colormap */ XStandardColormap *stdcmap = NULL; /* parse the named color */ if (name[0] != '#') stat = XParseColor (dpy, cmap, name, &color); if (!stat) { fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); return; } /* * look through the list of standard colormaps (check cache first) */ if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps && (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap == cmap)) { stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]); } else { StdCmap *sc; for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) { int i; for (i = 0; i < sc->nmaps; i++) { if (sc->maps[i].colormap == cmap) { Scr->StdCmapInfo.mru = sc; Scr->StdCmapInfo.mruindex = i; stdcmap = &(sc->maps[i]); goto gotit; } } } } gotit: if (stdcmap) { color.pixel = (stdcmap->base_pixel + ((Pixel)(((float)color.red / 65535.0) * stdcmap->red_max + 0.5) * stdcmap->red_mult) + ((Pixel)(((float)color.green /65535.0) * stdcmap->green_max + 0.5) * stdcmap->green_mult) + ((Pixel)(((float)color.blue / 65535.0) * stdcmap->blue_max + 0.5) * stdcmap->blue_mult)); } else { fprintf (stderr, "%s: unable to allocate color \"%s\"\n", ProgramName, name); return; } } *what = color.pixel; } GetColorValue(kind, what, name) int kind; XColor *what; char *name; { XColor junkcolor; Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; #ifndef TOM if (!Scr->FirstTime) return; #endif if (Scr->Monochrome != kind) return; if (!XLookupColor (dpy, cmap, name, what, &junkcolor)) { fprintf (stderr, "%s: invalid color name \"%s\"\n", ProgramName, name); } else { what->pixel = AllPlanes; } } GetFont(font) MyFont *font; { char *deffontname = "fixed"; if (font->font != NULL) XFreeFont(dpy, font->font); if ((font->font = XLoadQueryFont(dpy, font->name)) == NULL) { if (Scr->DefaultFont.name) { deffontname = Scr->DefaultFont.name; } if ((font->font = XLoadQueryFont(dpy, deffontname)) == NULL) { fprintf (stderr, "%s: unable to open fonts \"%s\" or \"%s\"\n", ProgramName, font->name, deffontname); exit(1); } } font->height = font->font->ascent + font->font->descent; font->y = font->font->ascent; } /* * SetFocus - separate routine to set focus to make things more understandable * and easier to debug */ SetFocus (tmp_win, time) TwmWindow *tmp_win; Time time; { Window w = (tmp_win ? tmp_win->w : PointerRoot); #ifdef TRACE if (tmp_win) { printf ("Focusing on window \"%s\"\n", tmp_win->full_name); } else { printf ("Unfocusing; Scr->Focus was \"%s\"\n", Scr->Focus ? Scr->Focus->full_name : "(nil)"); } #endif XSetInputFocus (dpy, w, RevertToPointerRoot, time); } #ifdef NOPUTENV /* * define our own putenv() if the system doesn't have one. * putenv(s): place s (a string of the form "NAME=value") in * the environment; replacing any existing NAME. s is placed in * environment, so if you change s, the environment changes (like * putenv on a sun). Binding removed if you putenv something else * called NAME. */ int putenv(s) char *s; { char *v; int varlen, idx; extern char **environ; char **newenv; static int virgin = 1; /* true while "environ" is a virgin */ v = index(s, '='); if(v == 0) return 0; /* punt if it's not of the right form */ varlen = (v + 1) - s; for (idx = 0; environ[idx] != 0; idx++) { if (strncmp(environ[idx], s, varlen) == 0) { if(v[1] != 0) { /* true if there's a value */ environ[idx] = s; return 0; } else { do { environ[idx] = environ[idx+1]; } while(environ[++idx] != 0); return 0; } } } /* add to environment (unless no value; then just return) */ if(v[1] == 0) return 0; if(virgin) { register i; newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*))); if(newenv == 0) return -1; for(i = idx-1; i >= 0; --i) newenv[i] = environ[i]; virgin = 0; /* you're not a virgin anymore, sweety */ } else { newenv = (char **) realloc((char *) environ, (unsigned) ((idx + 2) * sizeof(char*))); if (newenv == 0) return -1; } environ = newenv; environ[idx] = s; environ[idx+1] = 0; return 0; } #endif /* NOPUTENV */ static Pixmap CreateXLogoPixmap (widthp, heightp) unsigned int *widthp, *heightp; { int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; if (h < 0) h = 0; *widthp = *heightp = (unsigned int) h; if (Scr->tbpm.xlogo == None) { GC gc, gcBack; Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1); gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); XSetForeground (dpy, gc, 0); XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h); XSetForeground (dpy, gc, 1); gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL); XSetForeground (dpy, gcBack, 0); /* * draw the logo large so that it gets as dense as possible; then white * out the edges so that they look crisp */ XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2); XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1); /* * done drawing */ XFreeGC (dpy, gc); XFreeGC (dpy, gcBack); } return Scr->tbpm.xlogo; } static Pixmap CreateResizePixmap (widthp, heightp) unsigned int *widthp, *heightp; { int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; if (h < 1) h = 1; *widthp = *heightp = (unsigned int) h; if (Scr->tbpm.resize == None) { XPoint points[3]; GC gc; int w; int lw; /* * create the pixmap */ Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1); gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL); XSetForeground (dpy, gc, 0); XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h); XSetForeground (dpy, gc, 1); lw = h / 16; if (lw == 1) lw = 0; XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter); /* * draw the resize button, */ w = (h * 2) / 3; points[0].x = w; points[0].y = 0; points[1].x = w; points[1].y = w; points[2].x = 0; points[2].y = w; XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); w = w / 2; points[0].x = w; points[0].y = 0; points[1].x = w; points[1].y = w; points[2].x = 0; points[2].y = w; XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin); /* * done drawing */ XFreeGC(dpy, gc); } return Scr->tbpm.resize; } static Pixmap CreateDotPixmap (widthp, heightp) unsigned int *widthp, *heightp; { int h = Scr->TBInfo.width - Scr->TBInfo.border * 2; h = h * 3 / 4; if (h < 1) h = 1; if (!(h & 1)) h--; *widthp = *heightp = (unsigned int) h; if (Scr->tbpm.delete == None) { GC gc; Pixmap pix; pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1); gc = XCreateGC (dpy, pix, 0L, NULL); XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound); XSetForeground (dpy, gc, 0L); XFillRectangle (dpy, pix, gc, 0, 0, h, h); XSetForeground (dpy, gc, 1L); XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2); XFreeGC (dpy, gc); } return Scr->tbpm.delete; } #define questionmark_width 8 #define questionmark_height 8 static char questionmark_bits[] = { 0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18}; static Pixmap CreateQuestionPixmap (widthp, heightp) unsigned int *widthp, *heightp; { *widthp = questionmark_width; *heightp = questionmark_height; if (Scr->tbpm.question == None) { Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root, questionmark_bits, questionmark_width, questionmark_height); } /* * this must succeed or else we are in deep trouble elsewhere */ return Scr->tbpm.question; } static Pixmap CreateMenuPixmap (widthp, heightp) int *widthp, *heightp; { return CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2, widthp,heightp); } Pixmap CreateMenuIcon (height, widthp, heightp) int height; int *widthp, *heightp; { int h, w; int ih, iw; int ix, iy; int mh, mw; int tw, th; int lw, lh; int lx, ly; int lines, dly; int off; int bw; h = height; w = h * 7 / 8; if (h < 1) h = 1; if (w < 1) w = 1; *widthp = w; *heightp = h; if (Scr->tbpm.menu == None) { Pixmap pix; GC gc; pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1); gc = XCreateGC (dpy, pix, 0L, NULL); XSetForeground (dpy, gc, 0L); XFillRectangle (dpy, pix, gc, 0, 0, w, h); XSetForeground (dpy, gc, 1L); ix = 1; iy = 1; ih = h - iy * 2; iw = w - ix * 2; off = ih / 8; mh = ih - off; mw = iw - off; bw = mh / 16; if (bw == 0 && mw > 2) bw = 1; tw = mw - bw * 2; th = mh - bw * 2; XFillRectangle (dpy, pix, gc, ix, iy, mw, mh); XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh); XSetForeground (dpy, gc, 0L); XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th); XSetForeground (dpy, gc, 1L); lw = tw / 2; if ((tw & 1) ^ (lw & 1)) lw++; lx = ix + bw + (tw - lw) / 2; lh = th / 2 - bw; if ((lh & 1) ^ ((th - bw) & 1)) lh++; ly = iy + bw + (th - bw - lh) / 2; lines = 3; if ((lh & 1) && lh < 6) { lines--; } dly = lh / (lines - 1); while (lines--) { XFillRectangle (dpy, pix, gc, lx, ly, lw, bw); ly += dly; } XFreeGC (dpy, gc); } return Scr->tbpm.menu; } void Bell(type,percent,win) int type; int percent; Window win; { #ifdef XKB XkbStdBell(dpy, win, percent, type); #else XBell(dpy, percent); #endif return; }