util.c revision ffd25bca
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 *
553e747e6dSmrg * utility routines for twm
563e747e6dSmrg *
573e747e6dSmrg * 28-Oct-87 Thomas E. LaStrange	File created
583e747e6dSmrg *
593e747e6dSmrg ***********************************************************************/
603e747e6dSmrg
613e747e6dSmrg#include "twm.h"
623e747e6dSmrg#include "util.h"
633e747e6dSmrg#include "gram.h"
643e747e6dSmrg#include "screen.h"
653e747e6dSmrg#include <X11/Xos.h>
663e747e6dSmrg#include <X11/Xatom.h>
673e747e6dSmrg#include <stdio.h>
683e747e6dSmrg#include <X11/Xmu/Drawing.h>
693e747e6dSmrg#include <X11/Xmu/CharSet.h>
703e747e6dSmrg
71ffd25bcaSmrgstatic Pixmap CreateXLogoPixmap ( unsigned int *widthp,
723e747e6dSmrg				  unsigned int *heightp );
73ffd25bcaSmrgstatic Pixmap CreateResizePixmap ( unsigned int *widthp,
743e747e6dSmrg				   unsigned int *heightp );
75ffd25bcaSmrgstatic Pixmap CreateDotPixmap ( unsigned int *widthp,
763e747e6dSmrg				unsigned int *heightp );
77ffd25bcaSmrgstatic Pixmap CreateQuestionPixmap ( unsigned int *widthp,
783e747e6dSmrg				     unsigned int *heightp );
79ffd25bcaSmrgstatic Pixmap CreateMenuPixmap ( unsigned int *widthp,
803e747e6dSmrg				 unsigned int *heightp );
813e747e6dSmrg
823e747e6dSmrgint HotX, HotY;
833e747e6dSmrg
84ffd25bcaSmrg/**
853e747e6dSmrg * move a window outline
863e747e6dSmrg *
873e747e6dSmrg *  \param root         window we are outlining
883e747e6dSmrg *  \param x,y          upper left coordinate
893e747e6dSmrg *  \param width,height size of the rectangle
903e747e6dSmrg *  \param bw           border width of the frame
913e747e6dSmrg *  \param th           title height
923e747e6dSmrg */
933e747e6dSmrgvoid MoveOutline(Window root, int x, int y, int width, int height, int bw, int th)
943e747e6dSmrg{
953e747e6dSmrg    static int	lastx = 0;
963e747e6dSmrg    static int	lasty = 0;
973e747e6dSmrg    static int	lastWidth = 0;
983e747e6dSmrg    static int	lastHeight = 0;
993e747e6dSmrg    static int	lastBW = 0;
1003e747e6dSmrg    static int	lastTH = 0;
1013e747e6dSmrg    int		xl, xr, yt, yb, xinnerl, xinnerr, yinnert, yinnerb;
1023e747e6dSmrg    int		xthird, ythird;
1033e747e6dSmrg    XSegment	outline[18];
1043e747e6dSmrg    register XSegment	*r;
1053e747e6dSmrg
1063e747e6dSmrg    if (x == lastx && y == lasty && width == lastWidth && height == lastHeight
1073e747e6dSmrg	&& lastBW == bw && th == lastTH)
1083e747e6dSmrg	return;
109ffd25bcaSmrg
1103e747e6dSmrg    r = outline;
1113e747e6dSmrg
1123e747e6dSmrg#define DRAWIT() \
1133e747e6dSmrg    if (lastWidth || lastHeight)			\
1143e747e6dSmrg    {							\
1153e747e6dSmrg	xl = lastx;					\
1163e747e6dSmrg	xr = lastx + lastWidth - 1;			\
1173e747e6dSmrg	yt = lasty;					\
1183e747e6dSmrg	yb = lasty + lastHeight - 1;			\
1193e747e6dSmrg	xinnerl = xl + lastBW;				\
1203e747e6dSmrg	xinnerr = xr - lastBW;				\
1213e747e6dSmrg	yinnert = yt + lastTH + lastBW;			\
1223e747e6dSmrg	yinnerb = yb - lastBW;				\
1233e747e6dSmrg	xthird = (xinnerr - xinnerl) / 3;		\
1243e747e6dSmrg	ythird = (yinnerb - yinnert) / 3;		\
1253e747e6dSmrg							\
1263e747e6dSmrg	r->x1 = xl;					\
1273e747e6dSmrg	r->y1 = yt;					\
1283e747e6dSmrg	r->x2 = xr;					\
1293e747e6dSmrg	r->y2 = yt;					\
1303e747e6dSmrg	r++;						\
1313e747e6dSmrg							\
1323e747e6dSmrg	r->x1 = xl;					\
1333e747e6dSmrg	r->y1 = yb;					\
1343e747e6dSmrg	r->x2 = xr;					\
1353e747e6dSmrg	r->y2 = yb;					\
1363e747e6dSmrg	r++;						\
1373e747e6dSmrg							\
1383e747e6dSmrg	r->x1 = xl;					\
1393e747e6dSmrg	r->y1 = yt;					\
1403e747e6dSmrg	r->x2 = xl;					\
1413e747e6dSmrg	r->y2 = yb;					\
1423e747e6dSmrg	r++;						\
1433e747e6dSmrg							\
1443e747e6dSmrg	r->x1 = xr;					\
1453e747e6dSmrg	r->y1 = yt;					\
1463e747e6dSmrg	r->x2 = xr;					\
1473e747e6dSmrg	r->y2 = yb;					\
1483e747e6dSmrg	r++;						\
1493e747e6dSmrg							\
1503e747e6dSmrg	r->x1 = xinnerl + xthird;			\
1513e747e6dSmrg	r->y1 = yinnert;				\
1523e747e6dSmrg	r->x2 = r->x1;					\
1533e747e6dSmrg	r->y2 = yinnerb;				\
1543e747e6dSmrg	r++;						\
1553e747e6dSmrg							\
1563e747e6dSmrg	r->x1 = xinnerl + (2 * xthird);			\
1573e747e6dSmrg	r->y1 = yinnert;				\
1583e747e6dSmrg	r->x2 = r->x1;					\
1593e747e6dSmrg	r->y2 = yinnerb;				\
1603e747e6dSmrg	r++;						\
1613e747e6dSmrg							\
1623e747e6dSmrg	r->x1 = xinnerl;				\
1633e747e6dSmrg	r->y1 = yinnert + ythird;			\
1643e747e6dSmrg	r->x2 = xinnerr;				\
1653e747e6dSmrg	r->y2 = r->y1;					\
1663e747e6dSmrg	r++;						\
1673e747e6dSmrg							\
1683e747e6dSmrg	r->x1 = xinnerl;				\
1693e747e6dSmrg	r->y1 = yinnert + (2 * ythird);			\
1703e747e6dSmrg	r->x2 = xinnerr;				\
1713e747e6dSmrg	r->y2 = r->y1;					\
1723e747e6dSmrg	r++;						\
1733e747e6dSmrg							\
1743e747e6dSmrg	if (lastTH != 0) {				\
1753e747e6dSmrg	    r->x1 = xl;					\
1763e747e6dSmrg	    r->y1 = yt + lastTH;			\
1773e747e6dSmrg	    r->x2 = xr;					\
1783e747e6dSmrg	    r->y2 = r->y1;				\
1793e747e6dSmrg	    r++;					\
1803e747e6dSmrg	}						\
1813e747e6dSmrg    }
1823e747e6dSmrg
1833e747e6dSmrg    /* undraw the old one, if any */
1843e747e6dSmrg    DRAWIT ();
1853e747e6dSmrg
1863e747e6dSmrg    lastx = x;
1873e747e6dSmrg    lasty = y;
1883e747e6dSmrg    lastWidth = width;
1893e747e6dSmrg    lastHeight = height;
1903e747e6dSmrg    lastBW = bw;
1913e747e6dSmrg    lastTH = th;
1923e747e6dSmrg
1933e747e6dSmrg    /* draw the new one, if any */
1943e747e6dSmrg    DRAWIT ();
1953e747e6dSmrg
1963e747e6dSmrg#undef DRAWIT
1973e747e6dSmrg
1983e747e6dSmrg
1993e747e6dSmrg    if (r != outline)
2003e747e6dSmrg    {
2013e747e6dSmrg	XDrawSegments(dpy, root, Scr->DrawGC, outline, r - outline);
2023e747e6dSmrg    }
2033e747e6dSmrg}
2043e747e6dSmrg
2053e747e6dSmrg/**
2063e747e6dSmrg * zoom in or out of an icon
2073e747e6dSmrg *
2083e747e6dSmrg *  \param wf window to zoom from
2093e747e6dSmrg *  \param wt window to zoom to
2103e747e6dSmrg */
2113e747e6dSmrgvoid
2123e747e6dSmrgZoom(Window wf, Window wt)
2133e747e6dSmrg{
2143e747e6dSmrg    int fx, fy, tx, ty;			/* from, to */
2153e747e6dSmrg    unsigned int fw, fh, tw, th;	/* from, to */
2163e747e6dSmrg    long dx, dy, dw, dh;
2173e747e6dSmrg    long z;
2183e747e6dSmrg    int j;
2193e747e6dSmrg
2203e747e6dSmrg    if (!Scr->DoZoom || Scr->ZoomCount < 1) return;
2213e747e6dSmrg
2223e747e6dSmrg    if (wf == None || wt == None) return;
2233e747e6dSmrg
2243e747e6dSmrg    XGetGeometry (dpy, wf, &JunkRoot, &fx, &fy, &fw, &fh, &JunkBW, &JunkDepth);
2253e747e6dSmrg    XGetGeometry (dpy, wt, &JunkRoot, &tx, &ty, &tw, &th, &JunkBW, &JunkDepth);
2263e747e6dSmrg
2273e747e6dSmrg    dx = ((long) (tx - fx));	/* going from -> to */
2283e747e6dSmrg    dy = ((long) (ty - fy));	/* going from -> to */
2293e747e6dSmrg    dw = ((long) (tw - fw));	/* going from -> to */
2303e747e6dSmrg    dh = ((long) (th - fh));	/* going from -> to */
2313e747e6dSmrg    z = (long) (Scr->ZoomCount + 1);
2323e747e6dSmrg
2333e747e6dSmrg    for (j = 0; j < 2; j++) {
2343e747e6dSmrg	long i;
2353e747e6dSmrg
2363e747e6dSmrg	XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, fx, fy, fw, fh);
2373e747e6dSmrg	for (i = 1; i < z; i++) {
2383e747e6dSmrg	    int x = fx + (int) ((dx * i) / z);
2393e747e6dSmrg	    int y = fy + (int) ((dy * i) / z);
2403e747e6dSmrg	    unsigned width = (unsigned) (((long) fw) + (dw * i) / z);
2413e747e6dSmrg	    unsigned height = (unsigned) (((long) fh) + (dh * i) / z);
242ffd25bcaSmrg
2433e747e6dSmrg	    XDrawRectangle (dpy, Scr->Root, Scr->DrawGC,
2443e747e6dSmrg			    x, y, width, height);
2453e747e6dSmrg	}
2463e747e6dSmrg	XDrawRectangle (dpy, Scr->Root, Scr->DrawGC, tx, ty, tw, th);
2473e747e6dSmrg    }
2483e747e6dSmrg}
2493e747e6dSmrg
2503e747e6dSmrg/**
251ffd25bcaSmrg * expand the tilde character to HOME if it is the first
2523e747e6dSmrg * character of the filename
2533e747e6dSmrg *
2543e747e6dSmrg *	\return a pointer to the new name
2553e747e6dSmrg *
2563e747e6dSmrg *  \param name  the filename to expand
2573e747e6dSmrg */
2583e747e6dSmrgchar *
2593e747e6dSmrgExpandFilename(char *name)
2603e747e6dSmrg{
2613e747e6dSmrg    char *newname;
2623e747e6dSmrg
2633e747e6dSmrg    if (name[0] != '~') return name;
2643e747e6dSmrg
2653e747e6dSmrg    newname = (char *) malloc (HomeLen + strlen(name) + 2);
2663e747e6dSmrg    if (!newname) {
267ffd25bcaSmrg	fprintf (stderr,
2683e747e6dSmrg		 "%s:  unable to allocate %ld bytes to expand filename %s/%s\n",
2693e747e6dSmrg		 ProgramName, HomeLen + (unsigned long)strlen(name) + 2,
2703e747e6dSmrg		 Home, &name[1]);
2713e747e6dSmrg    } else {
2723e747e6dSmrg	(void) sprintf (newname, "%s/%s", Home, &name[1]);
2733e747e6dSmrg    }
2743e747e6dSmrg
2753e747e6dSmrg    return newname;
2763e747e6dSmrg}
2773e747e6dSmrg
2783e747e6dSmrg/**
2793e747e6dSmrg * read in the bitmap file for the unknown icon
2803e747e6dSmrg *
2813e747e6dSmrg * \param name  the filename to read
2823e747e6dSmrg */
2833e747e6dSmrgvoid
2843e747e6dSmrgGetUnknownIcon(char *name)
2853e747e6dSmrg{
2863e747e6dSmrg    if ((Scr->UnknownPm = GetBitmap(name)) != None)
2873e747e6dSmrg    {
2883e747e6dSmrg	XGetGeometry(dpy, Scr->UnknownPm, &JunkRoot, &JunkX, &JunkY,
2893e747e6dSmrg	    (unsigned int *)&Scr->UnknownWidth, (unsigned int *)&Scr->UnknownHeight, &JunkBW, &JunkDepth);
2903e747e6dSmrg    }
2913e747e6dSmrg}
2923e747e6dSmrg
2933e747e6dSmrg/**
2943e747e6dSmrg *	FindBitmap - read in a bitmap file and return size
2953e747e6dSmrg *
2963e747e6dSmrg *  \return pixmap associated with bitmap
2973e747e6dSmrg *
2983e747e6dSmrg *  \param name          filename to read
2993e747e6dSmrg *  \param[out] widthp   pointer to width of bitmap
3003e747e6dSmrg *  \param[out] heightp	 pointer to height of bitmap
3013e747e6dSmrg */
302ffd25bcaSmrgPixmap
3033e747e6dSmrgFindBitmap (char *name, unsigned *widthp, unsigned *heightp)
3043e747e6dSmrg{
3053e747e6dSmrg    char *bigname;
3063e747e6dSmrg    Pixmap pm;
3073e747e6dSmrg
3083e747e6dSmrg    if (!name) return None;
3093e747e6dSmrg
3103e747e6dSmrg    /*
3113e747e6dSmrg     * Names of the form :name refer to hardcoded images that are scaled to
3123e747e6dSmrg     * look nice in title buttons.  Eventually, it would be nice to put in a
3133e747e6dSmrg     * menu symbol as well....
3143e747e6dSmrg     */
3153e747e6dSmrg    if (name[0] == ':') {
3163e747e6dSmrg	int i;
3173e747e6dSmrg	static struct {
3183e747e6dSmrg	    char *name;
3193e747e6dSmrg	    Pixmap (*proc)(unsigned int *, unsigned int *);
3203e747e6dSmrg	} pmtab[] = {
3213e747e6dSmrg	    { TBPM_DOT,		CreateDotPixmap },
3223e747e6dSmrg	    { TBPM_ICONIFY,	CreateDotPixmap },
3233e747e6dSmrg	    { TBPM_RESIZE,	CreateResizePixmap },
3243e747e6dSmrg	    { TBPM_XLOGO,	CreateXLogoPixmap },
3253e747e6dSmrg	    { TBPM_DELETE,	CreateXLogoPixmap },
3263e747e6dSmrg	    { TBPM_MENU,	CreateMenuPixmap },
3273e747e6dSmrg	    { TBPM_QUESTION,	CreateQuestionPixmap },
3283e747e6dSmrg	};
329ffd25bcaSmrg
3303e747e6dSmrg	for (i = 0; i < (sizeof pmtab)/(sizeof pmtab[0]); i++) {
3313e747e6dSmrg	    if (XmuCompareISOLatin1 (pmtab[i].name, name) == 0)
3323e747e6dSmrg	      return (*pmtab[i].proc) (widthp, heightp);
3333e747e6dSmrg	}
3343e747e6dSmrg	fprintf (stderr, "%s:  no such built-in bitmap \"%s\"\n",
3353e747e6dSmrg		 ProgramName, name);
3363e747e6dSmrg	return None;
3373e747e6dSmrg    }
3383e747e6dSmrg
3393e747e6dSmrg    /*
3403e747e6dSmrg     * Generate a full pathname if any special prefix characters (such as ~)
3413e747e6dSmrg     * are used.  If the bigname is different from name, bigname will need to
3423e747e6dSmrg     * be freed.
3433e747e6dSmrg     */
3443e747e6dSmrg    bigname = ExpandFilename (name);
3453e747e6dSmrg    if (!bigname) return None;
3463e747e6dSmrg
3473e747e6dSmrg    /*
3483e747e6dSmrg     * look along bitmapFilePath resource same as toolkit clients
3493e747e6dSmrg     */
3503e747e6dSmrg    pm = XmuLocateBitmapFile (ScreenOfDisplay(dpy, Scr->screen), bigname, NULL,
3513e747e6dSmrg			      0, (int *)widthp, (int *)heightp, &HotX, &HotY);
3523e747e6dSmrg    if (pm == None && Scr->IconDirectory && bigname[0] != '/') {
3533e747e6dSmrg	if (bigname != name) free (bigname);
3543e747e6dSmrg	/*
3553e747e6dSmrg	 * Attempt to find icon in old IconDirectory (now obsolete)
3563e747e6dSmrg	 */
3573e747e6dSmrg	bigname = (char *) malloc (strlen(name) + strlen(Scr->IconDirectory) +
3583e747e6dSmrg				   2);
3593e747e6dSmrg	if (!bigname) {
3603e747e6dSmrg	    fprintf (stderr,
3613e747e6dSmrg		     "%s:  unable to allocate memory for \"%s/%s\"\n",
3623e747e6dSmrg		     ProgramName, Scr->IconDirectory, name);
3633e747e6dSmrg	    return None;
3643e747e6dSmrg	}
3653e747e6dSmrg	(void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
3663e747e6dSmrg	if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
3673e747e6dSmrg			     &HotX, &HotY) != BitmapSuccess) {
3683e747e6dSmrg	    pm = None;
3693e747e6dSmrg	}
3703e747e6dSmrg    }
3713e747e6dSmrg    if (bigname != name) free (bigname);
3723e747e6dSmrg    if (pm == None) {
373ffd25bcaSmrg	fprintf (stderr, "%s:  unable to find bitmap \"%s\"\n",
3743e747e6dSmrg		 ProgramName, name);
3753e747e6dSmrg    }
3763e747e6dSmrg
3773e747e6dSmrg    return pm;
3783e747e6dSmrg}
3793e747e6dSmrg
380ffd25bcaSmrgPixmap
3813e747e6dSmrgGetBitmap (char *name)
3823e747e6dSmrg{
3833e747e6dSmrg    return FindBitmap (name, &JunkWidth, &JunkHeight);
3843e747e6dSmrg}
3853e747e6dSmrg
3863e747e6dSmrgvoid
3873e747e6dSmrgInsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps, Bool replace)
3883e747e6dSmrg{
3893e747e6dSmrg    StdCmap *sc = NULL;
3903e747e6dSmrg
3913e747e6dSmrg    if (replace) {			/* locate existing entry */
3923e747e6dSmrg	for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
3933e747e6dSmrg	    if (sc->atom == a) break;
3943e747e6dSmrg	}
3953e747e6dSmrg    }
3963e747e6dSmrg
3973e747e6dSmrg    if (!sc) {				/* no existing, allocate new */
3983e747e6dSmrg	sc = (StdCmap *) malloc (sizeof (StdCmap));
3993e747e6dSmrg	if (!sc) {
4003e747e6dSmrg	    fprintf (stderr, "%s:  unable to allocate %ld bytes for StdCmap\n",
4013e747e6dSmrg		     ProgramName, (unsigned long)sizeof (StdCmap));
4023e747e6dSmrg	    return;
4033e747e6dSmrg	}
4043e747e6dSmrg    }
4053e747e6dSmrg
4063e747e6dSmrg    if (replace) {			/* just update contents */
4073e747e6dSmrg	if (sc->maps) XFree ((char *) maps);
4083e747e6dSmrg	if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
4093e747e6dSmrg    } else {				/* else appending */
4103e747e6dSmrg	sc->next = NULL;
4113e747e6dSmrg	sc->atom = a;
4123e747e6dSmrg	if (Scr->StdCmapInfo.tail) {
4133e747e6dSmrg	    Scr->StdCmapInfo.tail->next = sc;
4143e747e6dSmrg	} else {
4153e747e6dSmrg	    Scr->StdCmapInfo.head = sc;
4163e747e6dSmrg	}
4173e747e6dSmrg	Scr->StdCmapInfo.tail = sc;
4183e747e6dSmrg    }
4193e747e6dSmrg    sc->nmaps = nmaps;
4203e747e6dSmrg    sc->maps = maps;
4213e747e6dSmrg
4223e747e6dSmrg    return;
4233e747e6dSmrg}
4243e747e6dSmrg
4253e747e6dSmrgvoid
4263e747e6dSmrgRemoveRGBColormap (Atom a)
4273e747e6dSmrg{
4283e747e6dSmrg    StdCmap *sc, *prev;
4293e747e6dSmrg
4303e747e6dSmrg    prev = NULL;
431ffd25bcaSmrg    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
4323e747e6dSmrg	if (sc->atom == a) break;
4333e747e6dSmrg	prev = sc;
4343e747e6dSmrg    }
4353e747e6dSmrg    if (sc) {				/* found one */
4363e747e6dSmrg	if (sc->maps) XFree ((char *) sc->maps);
4373e747e6dSmrg	if (prev) prev->next = sc->next;
4383e747e6dSmrg	if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
4393e747e6dSmrg	if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
4403e747e6dSmrg	if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
4413e747e6dSmrg    }
4423e747e6dSmrg    return;
4433e747e6dSmrg}
4443e747e6dSmrg
4453e747e6dSmrgvoid
4463e747e6dSmrgLocateStandardColormaps()
4473e747e6dSmrg{
4483e747e6dSmrg    Atom *atoms;
4493e747e6dSmrg    int natoms;
4503e747e6dSmrg    int i;
4513e747e6dSmrg
4523e747e6dSmrg    atoms = XListProperties (dpy, Scr->Root, &natoms);
4533e747e6dSmrg    for (i = 0; i < natoms; i++) {
4543e747e6dSmrg	XStandardColormap *maps = NULL;
4553e747e6dSmrg	int nmaps;
4563e747e6dSmrg
4573e747e6dSmrg	if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
4583e747e6dSmrg	    /* if got one, then append to current list */
4593e747e6dSmrg	    InsertRGBColormap (atoms[i], maps, nmaps, False);
4603e747e6dSmrg	}
4613e747e6dSmrg    }
4623e747e6dSmrg    if (atoms) XFree ((char *) atoms);
4633e747e6dSmrg    return;
4643e747e6dSmrg}
4653e747e6dSmrg
4663e747e6dSmrgvoid
4673e747e6dSmrgGetColor(int kind, Pixel *what, char *name)
4683e747e6dSmrg{
4693e747e6dSmrg    XColor color, junkcolor;
4703e747e6dSmrg    Status stat = 0;
4713e747e6dSmrg    Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
4723e747e6dSmrg
4733e747e6dSmrg#ifndef TOM
4743e747e6dSmrg    if (!Scr->FirstTime)
4753e747e6dSmrg	return;
4763e747e6dSmrg#endif
4773e747e6dSmrg
4783e747e6dSmrg    if (Scr->Monochrome != kind)
4793e747e6dSmrg	return;
4803e747e6dSmrg
4813e747e6dSmrg    if (!XAllocNamedColor (dpy, cmap, name, &color, &junkcolor))
4823e747e6dSmrg    {
4833e747e6dSmrg	/* if we could not allocate the color, let's see if this is a
4843e747e6dSmrg	 * standard colormap
4853e747e6dSmrg	 */
4863e747e6dSmrg	XStandardColormap *stdcmap = NULL;
4873e747e6dSmrg
4883e747e6dSmrg	/* parse the named color */
4893e747e6dSmrg	if (name[0] != '#')
4903e747e6dSmrg	    stat = XParseColor (dpy, cmap, name, &color);
4913e747e6dSmrg	if (!stat)
4923e747e6dSmrg	{
493ffd25bcaSmrg	    fprintf (stderr, "%s:  invalid color name \"%s\"\n",
4943e747e6dSmrg		     ProgramName, name);
4953e747e6dSmrg	    return;
4963e747e6dSmrg	}
4973e747e6dSmrg
4983e747e6dSmrg	/*
4993e747e6dSmrg	 * look through the list of standard colormaps (check cache first)
5003e747e6dSmrg	 */
5013e747e6dSmrg	if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
5023e747e6dSmrg	    (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
5033e747e6dSmrg	     cmap)) {
5043e747e6dSmrg	    stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
5053e747e6dSmrg	} else {
5063e747e6dSmrg	    StdCmap *sc;
5073e747e6dSmrg
5083e747e6dSmrg	    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
5093e747e6dSmrg		int i;
5103e747e6dSmrg
5113e747e6dSmrg		for (i = 0; i < sc->nmaps; i++) {
5123e747e6dSmrg		    if (sc->maps[i].colormap == cmap) {
5133e747e6dSmrg			Scr->StdCmapInfo.mru = sc;
5143e747e6dSmrg			Scr->StdCmapInfo.mruindex = i;
5153e747e6dSmrg			stdcmap = &(sc->maps[i]);
5163e747e6dSmrg			goto gotit;
5173e747e6dSmrg		    }
5183e747e6dSmrg		}
5193e747e6dSmrg	    }
5203e747e6dSmrg	}
5213e747e6dSmrg
5223e747e6dSmrg      gotit:
5233e747e6dSmrg	if (stdcmap) {
5243e747e6dSmrg            color.pixel = (stdcmap->base_pixel +
5253e747e6dSmrg			   ((Pixel)(((float)color.red / 65535.0) *
5263e747e6dSmrg				    stdcmap->red_max + 0.5) *
5273e747e6dSmrg			    stdcmap->red_mult) +
5283e747e6dSmrg			   ((Pixel)(((float)color.green /65535.0) *
5293e747e6dSmrg				    stdcmap->green_max + 0.5) *
5303e747e6dSmrg			    stdcmap->green_mult) +
5313e747e6dSmrg			   ((Pixel)(((float)color.blue  / 65535.0) *
5323e747e6dSmrg				    stdcmap->blue_max + 0.5) *
5333e747e6dSmrg			    stdcmap->blue_mult));
5343e747e6dSmrg        } else {
535ffd25bcaSmrg	    fprintf (stderr, "%s:  unable to allocate color \"%s\"\n",
5363e747e6dSmrg		     ProgramName, name);
5373e747e6dSmrg	    return;
5383e747e6dSmrg	}
5393e747e6dSmrg    }
5403e747e6dSmrg
5413e747e6dSmrg    *what = color.pixel;
5423e747e6dSmrg}
5433e747e6dSmrg
5443e747e6dSmrgvoid
5453e747e6dSmrgGetColorValue(int kind, XColor *what, char *name)
5463e747e6dSmrg{
5473e747e6dSmrg    XColor junkcolor;
5483e747e6dSmrg    Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
5493e747e6dSmrg
5503e747e6dSmrg#ifndef TOM
5513e747e6dSmrg    if (!Scr->FirstTime)
5523e747e6dSmrg	return;
5533e747e6dSmrg#endif
5543e747e6dSmrg
5553e747e6dSmrg    if (Scr->Monochrome != kind)
5563e747e6dSmrg	return;
5573e747e6dSmrg
5583e747e6dSmrg    if (!XLookupColor (dpy, cmap, name, what, &junkcolor))
5593e747e6dSmrg    {
560ffd25bcaSmrg	fprintf (stderr, "%s:  invalid color name \"%s\"\n",
5613e747e6dSmrg		 ProgramName, name);
5623e747e6dSmrg    }
5633e747e6dSmrg    else
5643e747e6dSmrg    {
5653e747e6dSmrg	what->pixel = AllPlanes;
5663e747e6dSmrg    }
5673e747e6dSmrg}
5683e747e6dSmrg
569ffd25bcaSmrg/*
5703e747e6dSmrg * The following functions are sensible to 'use_fontset'.
5713e747e6dSmrg * When 'use_fontset' is True,
5723e747e6dSmrg *  - XFontSet-related internationalized functions are used
5733e747e6dSmrg *     so as multibyte languages can be displayed.
5743e747e6dSmrg * When 'use_fontset' is False,
5753e747e6dSmrg *  - XFontStruct-related conventional functions are used
5763e747e6dSmrg *     so as 8-bit characters can be displayed even when
5773e747e6dSmrg *     locale is not set properly.
5783e747e6dSmrg */
5793e747e6dSmrgvoid
5803e747e6dSmrgGetFont(MyFont *font)
5813e747e6dSmrg{
5823e747e6dSmrg    char *deffontname = "fixed";
5833e747e6dSmrg    char **missing_charset_list_return;
5843e747e6dSmrg    int missing_charset_count_return;
5853e747e6dSmrg    char *def_string_return;
5863e747e6dSmrg    XFontSetExtents *font_extents;
5873e747e6dSmrg    XFontStruct **xfonts;
5883e747e6dSmrg    char **font_names;
5893e747e6dSmrg    register int i;
5903e747e6dSmrg    int ascent;
5913e747e6dSmrg    int descent;
5923e747e6dSmrg    int fnum;
5933e747e6dSmrg    char *basename2;
5943e747e6dSmrg
5953e747e6dSmrg    if (use_fontset) {
5963e747e6dSmrg	if (font->fontset != NULL){
5973e747e6dSmrg	    XFreeFontSet(dpy, font->fontset);
5983e747e6dSmrg	}
5993e747e6dSmrg
6003e747e6dSmrg	basename2 = (char *)malloc(strlen(font->name) + 3);
6013e747e6dSmrg	if (basename2) sprintf(basename2, "%s,*", font->name);
6023e747e6dSmrg	else basename2 = font->name;
6033e747e6dSmrg	if( (font->fontset = XCreateFontSet(dpy, basename2,
6043e747e6dSmrg					    &missing_charset_list_return,
6053e747e6dSmrg					    &missing_charset_count_return,
6063e747e6dSmrg					    &def_string_return)) == NULL) {
6073e747e6dSmrg	    fprintf (stderr, "%s:  unable to open fontset \"%s\"\n",
6083e747e6dSmrg			 ProgramName, font->name);
6093e747e6dSmrg	    exit(1);
6103e747e6dSmrg	}
6113e747e6dSmrg	if (basename2 != font->name) free(basename2);
6123e747e6dSmrg	for(i=0; i<missing_charset_count_return; i++){
6133e747e6dSmrg	    printf("%s: warning: font for charset %s is lacking.\n",
6143e747e6dSmrg		   ProgramName, missing_charset_list_return[i]);
6153e747e6dSmrg	}
6163e747e6dSmrg
6173e747e6dSmrg	font_extents = XExtentsOfFontSet(font->fontset);
6183e747e6dSmrg	fnum = XFontsOfFontSet(font->fontset, &xfonts, &font_names);
6193e747e6dSmrg	for( i = 0, ascent = 0, descent = 0; i<fnum; i++){
6203e747e6dSmrg	    if (ascent < (*xfonts)->ascent) ascent = (*xfonts)->ascent;
6213e747e6dSmrg	    if (descent < (*xfonts)->descent) descent = (*xfonts)->descent;
6223e747e6dSmrg	    xfonts++;
6233e747e6dSmrg	}
6243e747e6dSmrg	font->height = font_extents->max_logical_extent.height;
6253e747e6dSmrg	font->y = ascent;
6263e747e6dSmrg	font->ascent = ascent;
6273e747e6dSmrg	font->descent = descent;
6283e747e6dSmrg	return;
6293e747e6dSmrg    }
6303e747e6dSmrg
6313e747e6dSmrg    if (font->font != NULL)
6323e747e6dSmrg	XFreeFont(dpy, font->font);
6333e747e6dSmrg
6343e747e6dSmrg    if ((font->font = XLoadQueryFont(dpy, font->name)) == NULL)
6353e747e6dSmrg    {
6363e747e6dSmrg	if (Scr->DefaultFont.name) {
6373e747e6dSmrg	    deffontname = Scr->DefaultFont.name;
6383e747e6dSmrg	}
6393e747e6dSmrg	if ((font->font = XLoadQueryFont(dpy, deffontname)) == NULL)
6403e747e6dSmrg	{
6413e747e6dSmrg	    fprintf (stderr, "%s:  unable to open fonts \"%s\" or \"%s\"\n",
6423e747e6dSmrg		     ProgramName, font->name, deffontname);
6433e747e6dSmrg	    exit(1);
6443e747e6dSmrg	}
6453e747e6dSmrg
6463e747e6dSmrg    }
6473e747e6dSmrg    font->height = font->font->ascent + font->font->descent;
6483e747e6dSmrg    font->y = font->font->ascent;
6493e747e6dSmrg    font->ascent = font->font->ascent;
6503e747e6dSmrg    font->descent = font->font->descent;
6513e747e6dSmrg}
6523e747e6dSmrg
6533e747e6dSmrgint
6543e747e6dSmrgMyFont_TextWidth(MyFont *font, char *string, int len)
6553e747e6dSmrg{
6563e747e6dSmrg    XRectangle ink_rect;
6573e747e6dSmrg    XRectangle logical_rect;
6583e747e6dSmrg
6593e747e6dSmrg    if (use_fontset) {
6603e747e6dSmrg	XmbTextExtents(font->fontset, string, len,
6613e747e6dSmrg		       &ink_rect, &logical_rect);
6623e747e6dSmrg	return logical_rect.width;
6633e747e6dSmrg    }
6643e747e6dSmrg    return XTextWidth(font->font, string, len);
6653e747e6dSmrg}
6663e747e6dSmrg
6673e747e6dSmrgvoid
668ffd25bcaSmrgMyFont_DrawImageString(Display *dpy, Drawable d, MyFont *font, GC gc,
6693e747e6dSmrg                       int x, int y, char *string, int len)
6703e747e6dSmrg{
6713e747e6dSmrg    if (use_fontset) {
6723e747e6dSmrg	XmbDrawImageString(dpy, d, font->fontset, gc, x, y, string, len);
6733e747e6dSmrg	return;
6743e747e6dSmrg    }
6753e747e6dSmrg    XDrawImageString (dpy, d, gc, x, y, string, len);
6763e747e6dSmrg}
6773e747e6dSmrg
6783e747e6dSmrgvoid
679ffd25bcaSmrgMyFont_DrawString(Display *dpy, Drawable d, MyFont *font, GC gc,
6803e747e6dSmrg                  int x, int y, char *string, int len)
6813e747e6dSmrg{
6823e747e6dSmrg    if (use_fontset) {
6833e747e6dSmrg	XmbDrawString(dpy, d, font->fontset, gc, x, y, string, len);
6843e747e6dSmrg	return;
6853e747e6dSmrg    }
6863e747e6dSmrg    XDrawString (dpy, d, gc, x, y, string, len);
6873e747e6dSmrg}
6883e747e6dSmrg
6893e747e6dSmrgvoid
690ffd25bcaSmrgMyFont_ChangeGC(unsigned long fix_fore, unsigned long fix_back,
6913e747e6dSmrg                MyFont *fix_font)
6923e747e6dSmrg{
6933e747e6dSmrg    Gcv.foreground = fix_fore;
6943e747e6dSmrg    Gcv.background = fix_back;
6953e747e6dSmrg    if (use_fontset) {
6963e747e6dSmrg	XChangeGC(dpy, Scr->NormalGC, GCForeground|GCBackground, &Gcv);
6973e747e6dSmrg	return;
6983e747e6dSmrg    }
6993e747e6dSmrg    Gcv.font = fix_font->font->fid;
7003e747e6dSmrg    XChangeGC(dpy, Scr->NormalGC, GCFont|GCForeground|GCBackground,&Gcv);
7013e747e6dSmrg}
7023e747e6dSmrg
7033e747e6dSmrg/*
7043e747e6dSmrg * The following functions are internationalized substitutions
7053e747e6dSmrg * for XFetchName and XGetIconName using XGetWMName and
706ffd25bcaSmrg * XGetWMIconName.
7073e747e6dSmrg *
708ffd25bcaSmrg * Please note that the third arguments have to be freed using free(),
7093e747e6dSmrg * not XFree().
7103e747e6dSmrg */
7113e747e6dSmrgStatus
7123e747e6dSmrgI18N_FetchName(Display *dpy, Window w, char **winname)
7133e747e6dSmrg{
7143e747e6dSmrg    int    status;
7153e747e6dSmrg    XTextProperty text_prop;
7163e747e6dSmrg    char **list;
7173e747e6dSmrg    int    num;
718ffd25bcaSmrg
7193e747e6dSmrg    status = XGetWMName(dpy, w, &text_prop);
7203e747e6dSmrg    if (!status || !text_prop.value || !text_prop.nitems) {
7213e747e6dSmrg      *winname = NULL;
7223e747e6dSmrg      return 0;
7233e747e6dSmrg    }
7243e747e6dSmrg    status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
7253e747e6dSmrg    if (status < Success || !num || !*list) {
726ffd25bcaSmrg      *winname = NULL;
7273e747e6dSmrg      return 0;
7283e747e6dSmrg    }
7293e747e6dSmrg    XFree(text_prop.value);
7303e747e6dSmrg    *winname = (char *)strdup(*list);
7313e747e6dSmrg    XFreeStringList(list);
7323e747e6dSmrg    return 1;
7333e747e6dSmrg}
7343e747e6dSmrg
7353e747e6dSmrgStatus
7363e747e6dSmrgI18N_GetIconName(Display *dpy, Window w, char **iconname)
7373e747e6dSmrg{
7383e747e6dSmrg    int    status;
7393e747e6dSmrg    XTextProperty text_prop;
7403e747e6dSmrg    char **list;
7413e747e6dSmrg    int    num;
742ffd25bcaSmrg
7433e747e6dSmrg    status = XGetWMIconName(dpy, w, &text_prop);
7443e747e6dSmrg    if (!status || !text_prop.value || !text_prop.nitems) return 0;
7453e747e6dSmrg    status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
7463e747e6dSmrg    if (status < Success || !num || !*list) return 0;
7473e747e6dSmrg    XFree(text_prop.value);
7483e747e6dSmrg    *iconname = (char *)strdup(*list);
7493e747e6dSmrg    XFreeStringList(list);
7503e747e6dSmrg    return 1;
7513e747e6dSmrg}
7523e747e6dSmrg
7533e747e6dSmrg/**
7543e747e6dSmrg * separate routine to set focus to make things more understandable
7553e747e6dSmrg * and easier to debug
7563e747e6dSmrg */
7573e747e6dSmrgvoid
7583e747e6dSmrgSetFocus (TwmWindow *tmp_win, Time time)
7593e747e6dSmrg{
7603e747e6dSmrg    Window w = (tmp_win ? tmp_win->w : PointerRoot);
7613e747e6dSmrg
7623e747e6dSmrg#ifdef TRACE
7633e747e6dSmrg    if (tmp_win) {
7643e747e6dSmrg	printf ("Focusing on window \"%s\"\n", tmp_win->full_name);
7653e747e6dSmrg    } else {
7663e747e6dSmrg	printf ("Unfocusing; Scr->Focus was \"%s\"\n",
7673e747e6dSmrg		Scr->Focus ? Scr->Focus->full_name : "(nil)");
7683e747e6dSmrg    }
7693e747e6dSmrg#endif
7703e747e6dSmrg
7713e747e6dSmrg    XSetInputFocus (dpy, w, RevertToPointerRoot, time);
7723e747e6dSmrg}
7733e747e6dSmrg
774ffd25bcaSmrgstatic Pixmap
7753e747e6dSmrgCreateXLogoPixmap (unsigned *widthp, unsigned *heightp)
7763e747e6dSmrg{
7773e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
7783e747e6dSmrg    if (h < 0) h = 0;
7793e747e6dSmrg
7803e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
7813e747e6dSmrg    if (Scr->tbpm.xlogo == None) {
7823e747e6dSmrg	GC gc, gcBack;
7833e747e6dSmrg
7843e747e6dSmrg	Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1);
7853e747e6dSmrg	gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
7863e747e6dSmrg	XSetForeground (dpy, gc, 0);
7873e747e6dSmrg	XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
7883e747e6dSmrg	XSetForeground (dpy, gc, 1);
7893e747e6dSmrg	gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
7903e747e6dSmrg	XSetForeground (dpy, gcBack, 0);
7913e747e6dSmrg
7923e747e6dSmrg	/*
7933e747e6dSmrg	 * draw the logo large so that it gets as dense as possible; then white
7943e747e6dSmrg	 * out the edges so that they look crisp
7953e747e6dSmrg	 */
7963e747e6dSmrg	XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
7973e747e6dSmrg	XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
7983e747e6dSmrg
7993e747e6dSmrg	/*
8003e747e6dSmrg	 * done drawing
8013e747e6dSmrg	 */
8023e747e6dSmrg	XFreeGC (dpy, gc);
8033e747e6dSmrg	XFreeGC (dpy, gcBack);
8043e747e6dSmrg    }
8053e747e6dSmrg    return Scr->tbpm.xlogo;
8063e747e6dSmrg}
8073e747e6dSmrg
8083e747e6dSmrg
809ffd25bcaSmrgstatic Pixmap
8103e747e6dSmrgCreateResizePixmap (unsigned *widthp, unsigned *heightp)
8113e747e6dSmrg{
8123e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
8133e747e6dSmrg    if (h < 1) h = 1;
8143e747e6dSmrg
8153e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
8163e747e6dSmrg    if (Scr->tbpm.resize == None) {
8173e747e6dSmrg	XPoint	points[3];
8183e747e6dSmrg	GC gc;
8193e747e6dSmrg	int w;
8203e747e6dSmrg	int lw;
8213e747e6dSmrg
8223e747e6dSmrg	/*
8233e747e6dSmrg	 * create the pixmap
8243e747e6dSmrg	 */
8253e747e6dSmrg	Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1);
8263e747e6dSmrg	gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL);
8273e747e6dSmrg	XSetForeground (dpy, gc, 0);
8283e747e6dSmrg	XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
8293e747e6dSmrg	XSetForeground (dpy, gc, 1);
8303e747e6dSmrg	lw = h / 16;
8313e747e6dSmrg	if (lw == 1)
8323e747e6dSmrg	    lw = 0;
8333e747e6dSmrg	XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter);
8343e747e6dSmrg
8353e747e6dSmrg	/*
836ffd25bcaSmrg	 * draw the resize button,
8373e747e6dSmrg	 */
8383e747e6dSmrg	w = (h * 2) / 3;
8393e747e6dSmrg	points[0].x = w;
8403e747e6dSmrg	points[0].y = 0;
8413e747e6dSmrg	points[1].x = w;
8423e747e6dSmrg	points[1].y = w;
8433e747e6dSmrg	points[2].x = 0;
8443e747e6dSmrg	points[2].y = w;
8453e747e6dSmrg	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
8463e747e6dSmrg	w = w / 2;
8473e747e6dSmrg	points[0].x = w;
8483e747e6dSmrg	points[0].y = 0;
8493e747e6dSmrg	points[1].x = w;
8503e747e6dSmrg	points[1].y = w;
8513e747e6dSmrg	points[2].x = 0;
8523e747e6dSmrg	points[2].y = w;
8533e747e6dSmrg	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
8543e747e6dSmrg
8553e747e6dSmrg	/*
8563e747e6dSmrg	 * done drawing
8573e747e6dSmrg	 */
8583e747e6dSmrg	XFreeGC(dpy, gc);
8593e747e6dSmrg    }
8603e747e6dSmrg    return Scr->tbpm.resize;
8613e747e6dSmrg}
8623e747e6dSmrg
8633e747e6dSmrg
864ffd25bcaSmrgstatic Pixmap
8653e747e6dSmrgCreateDotPixmap (unsigned *widthp, unsigned *heightp)
8663e747e6dSmrg{
8673e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
8683e747e6dSmrg
8693e747e6dSmrg    h = h * 3 / 4;
8703e747e6dSmrg    if (h < 1) h = 1;
8713e747e6dSmrg    if (!(h & 1))
8723e747e6dSmrg	h--;
8733e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
8743e747e6dSmrg    if (Scr->tbpm.delete == None) {
8753e747e6dSmrg	GC  gc;
8763e747e6dSmrg	Pixmap pix;
8773e747e6dSmrg
8783e747e6dSmrg	pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1);
8793e747e6dSmrg	gc = XCreateGC (dpy, pix, 0L, NULL);
8803e747e6dSmrg	XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound);
8813e747e6dSmrg	XSetForeground (dpy, gc, 0L);
8823e747e6dSmrg	XFillRectangle (dpy, pix, gc, 0, 0, h, h);
8833e747e6dSmrg	XSetForeground (dpy, gc, 1L);
8843e747e6dSmrg	XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2);
8853e747e6dSmrg	XFreeGC (dpy, gc);
8863e747e6dSmrg    }
8873e747e6dSmrg    return Scr->tbpm.delete;
8883e747e6dSmrg}
8893e747e6dSmrg
8903e747e6dSmrg#define questionmark_width 8
8913e747e6dSmrg#define questionmark_height 8
8923e747e6dSmrgstatic char questionmark_bits[] = {
8933e747e6dSmrg   0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
8943e747e6dSmrg
895ffd25bcaSmrgstatic Pixmap
8963e747e6dSmrgCreateQuestionPixmap (unsigned *widthp, unsigned *heightp)
8973e747e6dSmrg{
8983e747e6dSmrg    *widthp = questionmark_width;
8993e747e6dSmrg    *heightp = questionmark_height;
9003e747e6dSmrg    if (Scr->tbpm.question == None) {
9013e747e6dSmrg	Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root,
9023e747e6dSmrg						    questionmark_bits,
9033e747e6dSmrg						    questionmark_width,
9043e747e6dSmrg						    questionmark_height);
9053e747e6dSmrg    }
9063e747e6dSmrg    /*
9073e747e6dSmrg     * this must succeed or else we are in deep trouble elsewhere
9083e747e6dSmrg     */
9093e747e6dSmrg    return Scr->tbpm.question;
9103e747e6dSmrg}
9113e747e6dSmrg
9123e747e6dSmrg
913ffd25bcaSmrgstatic Pixmap
9143e747e6dSmrgCreateMenuPixmap (unsigned *widthp, unsigned *heightp)
9153e747e6dSmrg{
9163e747e6dSmrg    return CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,
9173e747e6dSmrg			   widthp,heightp);
9183e747e6dSmrg}
9193e747e6dSmrg
920ffd25bcaSmrgPixmap
9213e747e6dSmrgCreateMenuIcon (int height, unsigned *widthp, unsigned *heightp)
9223e747e6dSmrg{
9233e747e6dSmrg    int h, w;
9243e747e6dSmrg    int ih, iw;
9253e747e6dSmrg    int	ix, iy;
9263e747e6dSmrg    int	mh, mw;
9273e747e6dSmrg    int	tw, th;
9283e747e6dSmrg    int	lw, lh;
9293e747e6dSmrg    int	lx, ly;
9303e747e6dSmrg    int	lines, dly;
9313e747e6dSmrg    int off;
9323e747e6dSmrg    int	bw;
9333e747e6dSmrg
9343e747e6dSmrg    h = height;
9353e747e6dSmrg    w = h * 7 / 8;
9363e747e6dSmrg    if (h < 1)
9373e747e6dSmrg	h = 1;
9383e747e6dSmrg    if (w < 1)
9393e747e6dSmrg	w = 1;
9403e747e6dSmrg    *widthp = w;
9413e747e6dSmrg    *heightp = h;
9423e747e6dSmrg    if (Scr->tbpm.menu == None) {
9433e747e6dSmrg	Pixmap  pix;
9443e747e6dSmrg	GC	gc;
9453e747e6dSmrg
9463e747e6dSmrg	pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1);
9473e747e6dSmrg	gc = XCreateGC (dpy, pix, 0L, NULL);
9483e747e6dSmrg	XSetForeground (dpy, gc, 0L);
9493e747e6dSmrg	XFillRectangle (dpy, pix, gc, 0, 0, w, h);
9503e747e6dSmrg	XSetForeground (dpy, gc, 1L);
9513e747e6dSmrg	ix = 1;
9523e747e6dSmrg	iy = 1;
9533e747e6dSmrg	ih = h - iy * 2;
9543e747e6dSmrg	iw = w - ix * 2;
9553e747e6dSmrg	off = ih / 8;
9563e747e6dSmrg	mh = ih - off;
9573e747e6dSmrg	mw = iw - off;
9583e747e6dSmrg	bw = mh / 16;
9593e747e6dSmrg	if (bw == 0 && mw > 2)
9603e747e6dSmrg	    bw = 1;
9613e747e6dSmrg	tw = mw - bw * 2;
9623e747e6dSmrg	th = mh - bw * 2;
9633e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix, iy, mw, mh);
9643e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
9653e747e6dSmrg	XSetForeground (dpy, gc, 0L);
9663e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th);
9673e747e6dSmrg	XSetForeground (dpy, gc, 1L);
9683e747e6dSmrg	lw = tw / 2;
9693e747e6dSmrg	if ((tw & 1) ^ (lw & 1))
9703e747e6dSmrg	    lw++;
9713e747e6dSmrg	lx = ix + bw + (tw - lw) / 2;
9723e747e6dSmrg
9733e747e6dSmrg	lh = th / 2 - bw;
9743e747e6dSmrg	if ((lh & 1) ^ ((th - bw) & 1))
9753e747e6dSmrg	    lh++;
9763e747e6dSmrg	ly = iy + bw + (th - bw - lh) / 2;
9773e747e6dSmrg
9783e747e6dSmrg	lines = 3;
9793e747e6dSmrg	if ((lh & 1) && lh < 6)
9803e747e6dSmrg	{
9813e747e6dSmrg	    lines--;
9823e747e6dSmrg	}
9833e747e6dSmrg	dly = lh / (lines - 1);
9843e747e6dSmrg	while (lines--)
9853e747e6dSmrg	{
9863e747e6dSmrg	    XFillRectangle (dpy, pix, gc, lx, ly, lw, bw);
9873e747e6dSmrg	    ly += dly;
9883e747e6dSmrg	}
9893e747e6dSmrg	XFreeGC (dpy, gc);
9903e747e6dSmrg    }
9913e747e6dSmrg    return Scr->tbpm.menu;
9923e747e6dSmrg}
9933e747e6dSmrg
9943e747e6dSmrgvoid
9953e747e6dSmrgBell(int type, int percent, Window win)
9963e747e6dSmrg{
9973e747e6dSmrg#ifdef XKB
9983e747e6dSmrg    XkbStdBell(dpy, win, percent, type);
9993e747e6dSmrg#else
10003e747e6dSmrg    XBell(dpy, percent);
10013e747e6dSmrg#endif
10023e747e6dSmrg    return;
10033e747e6dSmrg}
1004