/*****************************************************************************/ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ /** 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 **/ /** names of Evans & Sutherland and M.I.T. not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ /** M.I.T. 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. **/ /*****************************************************************************/ /*********************************************************************** * * $XConsortium: util.c,v 1.39 90/03/16 12:06:46 jim Exp $ * * utility routines for twm * * 28-Oct-87 Thomas E. LaStrange File created * ***********************************************************************/ #if !defined(lint) && !defined(SABER) static char RCSinfo[]= "$XConsortium: util.c,v 1.39 90/03/16 12:06:46 jim Exp $"; #endif #include #include "twm.h" #include "util.h" #include "gram.h" #include "screen.h" #include #include #include #include #ifdef XPM #include #endif 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 Window lastRoot; 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; if (root == None) root = lastRoot; lastRoot = root; 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; { Bool isXpm; Pixmap shape_mask; #ifdef SHAPE Pixmap SetIconMask(); Pixmap SetIconClip(); #endif if ((Scr->UnknownPm = FindPixmap(name, &JunkWidth, &JunkHeight, &isXpm, NULL, &shape_mask)) != None) { XGetGeometry(dpy, Scr->UnknownPm, &JunkRoot, &JunkX, &JunkY, (unsigned int *)&Scr->UnknownWidth, (unsigned int *)&Scr->UnknownHeight, &JunkBW, &JunkDepth); #ifdef SHAPE if (shape_mask) Scr->UnknownPmmsk = Scr->UnknownPmclp = shape_mask; else { Scr->UnknownPmmsk = SetIconMask(name); Scr->UnknownPmclp = SetIconClip(name); Scr->UnknownPmmsk = (Pixmap)LookInNameList(Scr->Iconsmask, name); } #endif } #ifdef SHAPE else { Scr->UnknownPmmsk = None; Scr->UnknownPmclp = None; } #endif } /*********************************************************************** * * Procedure: * FindPixmap - 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 * isXpm - pointer to an Boolean that says whether it's an Xpm * pixmap or not. Used ifdef XPM. * bg_color - pointer to a Pixel (unsigned long) which is the background * color of the pixmap (for an Xpm). Actually, it's just the * first color in the pixel list, so it's not neccessarily * the "real" background color. Can be passed as NULL. Used * ifdef XPM. * shape_mask - pointer to a Pixmap where will be returned the shape * mask of the Pixmap, if XpmReadFileToPixmap returns such. * * Inputs: * name - the filename to read * *********************************************************************** */ extern int FIXED_XmuCompareISOLatin1(); Pixmap FindPixmap (name, widthp, heightp, isXpm, bg_color, shape_mask) char *name; unsigned int *widthp, *heightp; Bool *isXpm; Pixel *bg_color; Pixmap *shape_mask; { char *bigname; Pixmap pm; #ifdef XPM int XPMret, ncolors; long *colors; XpmAttributes attribs; #endif /* XPM */ *isXpm = False; #ifdef XPM attribs.valuemask = 0; #endif 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 (FIXED_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 */ #ifdef XPM attribs.valuemask = XpmVisual | XpmColormap | XpmDepth; attribs.visual = Scr->d_visual; attribs.colormap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; attribs.depth = DefaultDepth(dpy, Scr->screen); attribs.colorTable = NULL; attribs.hints_cmt = attribs.colors_cmt = attribs.pixels_cmt = NULL; attribs.pixels = NULL; if (bg_color) { attribs.valuemask |= XpmReturnPixels; } pm = XcprLocatePixmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, BlackPixel(dpy, Scr->screen), WhitePixel(dpy, Scr->screen), Scr->d_depth, NULL, 0, widthp, heightp, &HotX, &HotY, isXpm, &attribs, shape_mask); if (bg_color && *isXpm) *bg_color = *attribs.pixels; #else pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL, 0, widthp, heightp, &HotX, &HotY); #endif /* XPM */ 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); #ifdef XPM attribs.valuemask = XpmVisual | XpmColormap | XpmDepth; attribs.visual = Scr->d_visual; attribs.colormap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; attribs.depth = DefaultDepth(dpy, Scr->screen); attribs.colorTable = NULL; attribs.hints_cmt = attribs.colors_cmt = attribs.pixels_cmt = NULL; attribs.pixels = NULL; XPMret = XpmReadFileToPixmap(dpy, RootWindow(dpy, Scr->screen), bigname, &pm, shape_mask, &attribs); switch (XPMret) { case XpmSuccess: case XpmColorError: *isXpm = True; break; case XpmNoMemory: printf("%s: XpmReadFileToPixmap out of memory (reading \"%s\")\n", ProgramName, bigname); break; case XpmColorFailed: printf("%s: Color parse/alloc failed in XpmReadFileToPixmap (reading \"%s\")\n", ProgramName, bigname); break; case XpmOpenFailed: case XpmFileInvalid: default: if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm, &HotX, &HotY) != BitmapSuccess) pm = None; if (shape_mask) *shape_mask = None; break; } /* switch */ #else if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm, &HotX, &HotY) != BitmapSuccess) pm = None; if (shape_mask) *shape_mask = None; #endif /* XPM */ } /* if */ if (bigname != name) free (bigname); if (pm == None) { #ifndef SHAPE fprintf (stderr, "%s: unable to find bitmap \"%s\"\n", ProgramName, name); #else int l = strlen(name); if (l <=4 || ((strncmp(&name[l-3],"clp",3) != 0) && (strncmp(&name[l-3],"msk",3) != 0)) ) { fprintf (stderr, "%s: unable to find bitmap \"%s\"\n", ProgramName, name); } #endif } #ifdef XPM XpmFreeAttributes(&attribs); #endif return pm; } Pixmap GetPixmap (name) char *name; { return FindPixmap (name, &JunkWidth, &JunkHeight, JunkIsXpm, NULL, NULL); } 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; } int 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; if (Scr->Monochrome != kind) return FALSE; /* * small hack to avoid extra roundtrip for color allocation */ if (!((name[0] == '#') ? ((stat = XParseColor (dpy, cmap, name, &color)) && XAllocColor (dpy, cmap, &color)) : 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 FALSE; } /* * 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)((color.red / 65535.0) * stdcmap->red_max + 0.5) * stdcmap->red_mult) + ((Pixel)((color.green /65535.0) * stdcmap->green_max + 0.5) * stdcmap->green_mult) + ((Pixel)((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 FALSE; } } *what = color.pixel; return TRUE; } 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) TwmWindow *tmp_win; { 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, CurrentTime); } #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; { extern char *index(); 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; { 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; }