util.c revision c2535118
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
265c2535118Smrg    newname = 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
284c2535118SmrgGetUnknownIcon(const 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
303c2535118SmrgFindBitmap (const 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 {
318c2535118Smrg	    const 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	 */
357c2535118Smrg	bigname = malloc (strlen(name) + strlen(Scr->IconDirectory) + 2);
3583e747e6dSmrg	if (!bigname) {
3593e747e6dSmrg	    fprintf (stderr,
3603e747e6dSmrg		     "%s:  unable to allocate memory for \"%s/%s\"\n",
3613e747e6dSmrg		     ProgramName, Scr->IconDirectory, name);
3623e747e6dSmrg	    return None;
3633e747e6dSmrg	}
3643e747e6dSmrg	(void) sprintf (bigname, "%s/%s", Scr->IconDirectory, name);
3653e747e6dSmrg	if (XReadBitmapFile (dpy, Scr->Root, bigname, widthp, heightp, &pm,
3663e747e6dSmrg			     &HotX, &HotY) != BitmapSuccess) {
3673e747e6dSmrg	    pm = None;
3683e747e6dSmrg	}
3693e747e6dSmrg    }
3703e747e6dSmrg    if (bigname != name) free (bigname);
3713e747e6dSmrg    if (pm == None) {
372ffd25bcaSmrg	fprintf (stderr, "%s:  unable to find bitmap \"%s\"\n",
3733e747e6dSmrg		 ProgramName, name);
3743e747e6dSmrg    }
3753e747e6dSmrg
3763e747e6dSmrg    return pm;
3773e747e6dSmrg}
3783e747e6dSmrg
379ffd25bcaSmrgPixmap
380c2535118SmrgGetBitmap (const char *name)
3813e747e6dSmrg{
3823e747e6dSmrg    return FindBitmap (name, &JunkWidth, &JunkHeight);
3833e747e6dSmrg}
3843e747e6dSmrg
3853e747e6dSmrgvoid
3863e747e6dSmrgInsertRGBColormap (Atom a, XStandardColormap *maps, int nmaps, Bool replace)
3873e747e6dSmrg{
3883e747e6dSmrg    StdCmap *sc = NULL;
3893e747e6dSmrg
3903e747e6dSmrg    if (replace) {			/* locate existing entry */
3913e747e6dSmrg	for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
3923e747e6dSmrg	    if (sc->atom == a) break;
3933e747e6dSmrg	}
3943e747e6dSmrg    }
3953e747e6dSmrg
3963e747e6dSmrg    if (!sc) {				/* no existing, allocate new */
397c2535118Smrg	sc = malloc (sizeof (StdCmap));
3983e747e6dSmrg	if (!sc) {
3993e747e6dSmrg	    fprintf (stderr, "%s:  unable to allocate %ld bytes for StdCmap\n",
4003e747e6dSmrg		     ProgramName, (unsigned long)sizeof (StdCmap));
4013e747e6dSmrg	    return;
4023e747e6dSmrg	}
4033e747e6dSmrg    }
4043e747e6dSmrg
4053e747e6dSmrg    if (replace) {			/* just update contents */
406c2535118Smrg	if (sc->maps) XFree (maps);
4073e747e6dSmrg	if (sc == Scr->StdCmapInfo.mru) Scr->StdCmapInfo.mru = NULL;
4083e747e6dSmrg    } else {				/* else appending */
4093e747e6dSmrg	sc->next = NULL;
4103e747e6dSmrg	sc->atom = a;
4113e747e6dSmrg	if (Scr->StdCmapInfo.tail) {
4123e747e6dSmrg	    Scr->StdCmapInfo.tail->next = sc;
4133e747e6dSmrg	} else {
4143e747e6dSmrg	    Scr->StdCmapInfo.head = sc;
4153e747e6dSmrg	}
4163e747e6dSmrg	Scr->StdCmapInfo.tail = sc;
4173e747e6dSmrg    }
4183e747e6dSmrg    sc->nmaps = nmaps;
4193e747e6dSmrg    sc->maps = maps;
4203e747e6dSmrg
4213e747e6dSmrg    return;
4223e747e6dSmrg}
4233e747e6dSmrg
4243e747e6dSmrgvoid
4253e747e6dSmrgRemoveRGBColormap (Atom a)
4263e747e6dSmrg{
4273e747e6dSmrg    StdCmap *sc, *prev;
4283e747e6dSmrg
4293e747e6dSmrg    prev = NULL;
430ffd25bcaSmrg    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
4313e747e6dSmrg	if (sc->atom == a) break;
4323e747e6dSmrg	prev = sc;
4333e747e6dSmrg    }
4343e747e6dSmrg    if (sc) {				/* found one */
435c2535118Smrg	if (sc->maps) XFree (sc->maps);
4363e747e6dSmrg	if (prev) prev->next = sc->next;
4373e747e6dSmrg	if (Scr->StdCmapInfo.head == sc) Scr->StdCmapInfo.head = sc->next;
4383e747e6dSmrg	if (Scr->StdCmapInfo.tail == sc) Scr->StdCmapInfo.tail = prev;
4393e747e6dSmrg	if (Scr->StdCmapInfo.mru == sc) Scr->StdCmapInfo.mru = NULL;
4403e747e6dSmrg    }
4413e747e6dSmrg    return;
4423e747e6dSmrg}
4433e747e6dSmrg
4443e747e6dSmrgvoid
445c2535118SmrgLocateStandardColormaps(void)
4463e747e6dSmrg{
4473e747e6dSmrg    Atom *atoms;
4483e747e6dSmrg    int natoms;
4493e747e6dSmrg    int i;
4503e747e6dSmrg
4513e747e6dSmrg    atoms = XListProperties (dpy, Scr->Root, &natoms);
4523e747e6dSmrg    for (i = 0; i < natoms; i++) {
4533e747e6dSmrg	XStandardColormap *maps = NULL;
4543e747e6dSmrg	int nmaps;
4553e747e6dSmrg
4563e747e6dSmrg	if (XGetRGBColormaps (dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
4573e747e6dSmrg	    /* if got one, then append to current list */
4583e747e6dSmrg	    InsertRGBColormap (atoms[i], maps, nmaps, False);
4593e747e6dSmrg	}
4603e747e6dSmrg    }
461c2535118Smrg    if (atoms) XFree (atoms);
4623e747e6dSmrg    return;
4633e747e6dSmrg}
4643e747e6dSmrg
4653e747e6dSmrgvoid
466c2535118SmrgGetColor(int kind, Pixel *what, const char *name)
4673e747e6dSmrg{
4683e747e6dSmrg    XColor color, junkcolor;
4693e747e6dSmrg    Status stat = 0;
4703e747e6dSmrg    Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
4713e747e6dSmrg
4723e747e6dSmrg#ifndef TOM
4733e747e6dSmrg    if (!Scr->FirstTime)
4743e747e6dSmrg	return;
4753e747e6dSmrg#endif
4763e747e6dSmrg
4773e747e6dSmrg    if (Scr->Monochrome != kind)
4783e747e6dSmrg	return;
4793e747e6dSmrg
4803e747e6dSmrg    if (!XAllocNamedColor (dpy, cmap, name, &color, &junkcolor))
4813e747e6dSmrg    {
4823e747e6dSmrg	/* if we could not allocate the color, let's see if this is a
4833e747e6dSmrg	 * standard colormap
4843e747e6dSmrg	 */
4853e747e6dSmrg	XStandardColormap *stdcmap = NULL;
4863e747e6dSmrg
4873e747e6dSmrg	/* parse the named color */
4883e747e6dSmrg	if (name[0] != '#')
4893e747e6dSmrg	    stat = XParseColor (dpy, cmap, name, &color);
4903e747e6dSmrg	if (!stat)
4913e747e6dSmrg	{
492ffd25bcaSmrg	    fprintf (stderr, "%s:  invalid color name \"%s\"\n",
4933e747e6dSmrg		     ProgramName, name);
4943e747e6dSmrg	    return;
4953e747e6dSmrg	}
4963e747e6dSmrg
4973e747e6dSmrg	/*
4983e747e6dSmrg	 * look through the list of standard colormaps (check cache first)
4993e747e6dSmrg	 */
5003e747e6dSmrg	if (Scr->StdCmapInfo.mru && Scr->StdCmapInfo.mru->maps &&
5013e747e6dSmrg	    (Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex].colormap ==
5023e747e6dSmrg	     cmap)) {
5033e747e6dSmrg	    stdcmap = &(Scr->StdCmapInfo.mru->maps[Scr->StdCmapInfo.mruindex]);
5043e747e6dSmrg	} else {
5053e747e6dSmrg	    StdCmap *sc;
5063e747e6dSmrg
5073e747e6dSmrg	    for (sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
5083e747e6dSmrg		int i;
5093e747e6dSmrg
5103e747e6dSmrg		for (i = 0; i < sc->nmaps; i++) {
5113e747e6dSmrg		    if (sc->maps[i].colormap == cmap) {
5123e747e6dSmrg			Scr->StdCmapInfo.mru = sc;
5133e747e6dSmrg			Scr->StdCmapInfo.mruindex = i;
5143e747e6dSmrg			stdcmap = &(sc->maps[i]);
5153e747e6dSmrg			goto gotit;
5163e747e6dSmrg		    }
5173e747e6dSmrg		}
5183e747e6dSmrg	    }
5193e747e6dSmrg	}
5203e747e6dSmrg
5213e747e6dSmrg      gotit:
5223e747e6dSmrg	if (stdcmap) {
5233e747e6dSmrg            color.pixel = (stdcmap->base_pixel +
5243e747e6dSmrg			   ((Pixel)(((float)color.red / 65535.0) *
5253e747e6dSmrg				    stdcmap->red_max + 0.5) *
5263e747e6dSmrg			    stdcmap->red_mult) +
5273e747e6dSmrg			   ((Pixel)(((float)color.green /65535.0) *
5283e747e6dSmrg				    stdcmap->green_max + 0.5) *
5293e747e6dSmrg			    stdcmap->green_mult) +
5303e747e6dSmrg			   ((Pixel)(((float)color.blue  / 65535.0) *
5313e747e6dSmrg				    stdcmap->blue_max + 0.5) *
5323e747e6dSmrg			    stdcmap->blue_mult));
5333e747e6dSmrg        } else {
534ffd25bcaSmrg	    fprintf (stderr, "%s:  unable to allocate color \"%s\"\n",
5353e747e6dSmrg		     ProgramName, name);
5363e747e6dSmrg	    return;
5373e747e6dSmrg	}
5383e747e6dSmrg    }
5393e747e6dSmrg
5403e747e6dSmrg    *what = color.pixel;
5413e747e6dSmrg}
5423e747e6dSmrg
5433e747e6dSmrgvoid
544c2535118SmrgGetColorValue(int kind, XColor *what, const char *name)
5453e747e6dSmrg{
5463e747e6dSmrg    XColor junkcolor;
5473e747e6dSmrg    Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c;
5483e747e6dSmrg
5493e747e6dSmrg#ifndef TOM
5503e747e6dSmrg    if (!Scr->FirstTime)
5513e747e6dSmrg	return;
5523e747e6dSmrg#endif
5533e747e6dSmrg
5543e747e6dSmrg    if (Scr->Monochrome != kind)
5553e747e6dSmrg	return;
5563e747e6dSmrg
5573e747e6dSmrg    if (!XLookupColor (dpy, cmap, name, what, &junkcolor))
5583e747e6dSmrg    {
559ffd25bcaSmrg	fprintf (stderr, "%s:  invalid color name \"%s\"\n",
5603e747e6dSmrg		 ProgramName, name);
5613e747e6dSmrg    }
5623e747e6dSmrg    else
5633e747e6dSmrg    {
5643e747e6dSmrg	what->pixel = AllPlanes;
5653e747e6dSmrg    }
5663e747e6dSmrg}
5673e747e6dSmrg
568ffd25bcaSmrg/*
5693e747e6dSmrg * The following functions are sensible to 'use_fontset'.
5703e747e6dSmrg * When 'use_fontset' is True,
5713e747e6dSmrg *  - XFontSet-related internationalized functions are used
5723e747e6dSmrg *     so as multibyte languages can be displayed.
5733e747e6dSmrg * When 'use_fontset' is False,
5743e747e6dSmrg *  - XFontStruct-related conventional functions are used
5753e747e6dSmrg *     so as 8-bit characters can be displayed even when
5763e747e6dSmrg *     locale is not set properly.
5773e747e6dSmrg */
5783e747e6dSmrgvoid
5793e747e6dSmrgGetFont(MyFont *font)
5803e747e6dSmrg{
581c2535118Smrg    const char *deffontname = "fixed";
5823e747e6dSmrg    char **missing_charset_list_return;
5833e747e6dSmrg    int missing_charset_count_return;
5843e747e6dSmrg    char *def_string_return;
5853e747e6dSmrg    XFontSetExtents *font_extents;
5863e747e6dSmrg    XFontStruct **xfonts;
5873e747e6dSmrg    char **font_names;
5883e747e6dSmrg    register int i;
5893e747e6dSmrg    int ascent;
5903e747e6dSmrg    int descent;
5913e747e6dSmrg    int fnum;
5923e747e6dSmrg    char *basename2;
5933e747e6dSmrg
5943e747e6dSmrg    if (use_fontset) {
5953e747e6dSmrg	if (font->fontset != NULL){
5963e747e6dSmrg	    XFreeFontSet(dpy, font->fontset);
5973e747e6dSmrg	}
5983e747e6dSmrg
599c2535118Smrg	basename2 = malloc(strlen(font->name) + 3);
6003e747e6dSmrg	if (basename2) sprintf(basename2, "%s,*", font->name);
6013e747e6dSmrg	else basename2 = font->name;
6023e747e6dSmrg	if( (font->fontset = XCreateFontSet(dpy, basename2,
6033e747e6dSmrg					    &missing_charset_list_return,
6043e747e6dSmrg					    &missing_charset_count_return,
6053e747e6dSmrg					    &def_string_return)) == NULL) {
6063e747e6dSmrg	    fprintf (stderr, "%s:  unable to open fontset \"%s\"\n",
6073e747e6dSmrg			 ProgramName, font->name);
6083e747e6dSmrg	    exit(1);
6093e747e6dSmrg	}
6103e747e6dSmrg	if (basename2 != font->name) free(basename2);
6113e747e6dSmrg	for(i=0; i<missing_charset_count_return; i++){
6123e747e6dSmrg	    printf("%s: warning: font for charset %s is lacking.\n",
6133e747e6dSmrg		   ProgramName, missing_charset_list_return[i]);
6143e747e6dSmrg	}
6153e747e6dSmrg
6163e747e6dSmrg	font_extents = XExtentsOfFontSet(font->fontset);
6173e747e6dSmrg	fnum = XFontsOfFontSet(font->fontset, &xfonts, &font_names);
6183e747e6dSmrg	for( i = 0, ascent = 0, descent = 0; i<fnum; i++){
6193e747e6dSmrg	    if (ascent < (*xfonts)->ascent) ascent = (*xfonts)->ascent;
6203e747e6dSmrg	    if (descent < (*xfonts)->descent) descent = (*xfonts)->descent;
6213e747e6dSmrg	    xfonts++;
6223e747e6dSmrg	}
6233e747e6dSmrg	font->height = font_extents->max_logical_extent.height;
6243e747e6dSmrg	font->y = ascent;
6253e747e6dSmrg	font->ascent = ascent;
6263e747e6dSmrg	font->descent = descent;
6273e747e6dSmrg	return;
6283e747e6dSmrg    }
6293e747e6dSmrg
6303e747e6dSmrg    if (font->font != NULL)
6313e747e6dSmrg	XFreeFont(dpy, font->font);
6323e747e6dSmrg
6333e747e6dSmrg    if ((font->font = XLoadQueryFont(dpy, font->name)) == NULL)
6343e747e6dSmrg    {
6353e747e6dSmrg	if (Scr->DefaultFont.name) {
6363e747e6dSmrg	    deffontname = Scr->DefaultFont.name;
6373e747e6dSmrg	}
6383e747e6dSmrg	if ((font->font = XLoadQueryFont(dpy, deffontname)) == NULL)
6393e747e6dSmrg	{
6403e747e6dSmrg	    fprintf (stderr, "%s:  unable to open fonts \"%s\" or \"%s\"\n",
6413e747e6dSmrg		     ProgramName, font->name, deffontname);
6423e747e6dSmrg	    exit(1);
6433e747e6dSmrg	}
6443e747e6dSmrg
6453e747e6dSmrg    }
6463e747e6dSmrg    font->height = font->font->ascent + font->font->descent;
6473e747e6dSmrg    font->y = font->font->ascent;
6483e747e6dSmrg    font->ascent = font->font->ascent;
6493e747e6dSmrg    font->descent = font->font->descent;
6503e747e6dSmrg}
6513e747e6dSmrg
6523e747e6dSmrgint
653c2535118SmrgMyFont_TextWidth(MyFont *font, const char *string, int len)
6543e747e6dSmrg{
6553e747e6dSmrg    XRectangle ink_rect;
6563e747e6dSmrg    XRectangle logical_rect;
6573e747e6dSmrg
6583e747e6dSmrg    if (use_fontset) {
6593e747e6dSmrg	XmbTextExtents(font->fontset, string, len,
6603e747e6dSmrg		       &ink_rect, &logical_rect);
6613e747e6dSmrg	return logical_rect.width;
6623e747e6dSmrg    }
6633e747e6dSmrg    return XTextWidth(font->font, string, len);
6643e747e6dSmrg}
6653e747e6dSmrg
6663e747e6dSmrgvoid
667ffd25bcaSmrgMyFont_DrawImageString(Display *dpy, Drawable d, MyFont *font, GC gc,
668c2535118Smrg                       int x, int y, const char *string, int len)
6693e747e6dSmrg{
6703e747e6dSmrg    if (use_fontset) {
6713e747e6dSmrg	XmbDrawImageString(dpy, d, font->fontset, gc, x, y, string, len);
6723e747e6dSmrg	return;
6733e747e6dSmrg    }
6743e747e6dSmrg    XDrawImageString (dpy, d, gc, x, y, string, len);
6753e747e6dSmrg}
6763e747e6dSmrg
6773e747e6dSmrgvoid
678ffd25bcaSmrgMyFont_DrawString(Display *dpy, Drawable d, MyFont *font, GC gc,
679c2535118Smrg                  int x, int y, const char *string, int len)
6803e747e6dSmrg{
6813e747e6dSmrg    if (use_fontset) {
6823e747e6dSmrg	XmbDrawString(dpy, d, font->fontset, gc, x, y, string, len);
6833e747e6dSmrg	return;
6843e747e6dSmrg    }
6853e747e6dSmrg    XDrawString (dpy, d, gc, x, y, string, len);
6863e747e6dSmrg}
6873e747e6dSmrg
6883e747e6dSmrgvoid
689ffd25bcaSmrgMyFont_ChangeGC(unsigned long fix_fore, unsigned long fix_back,
6903e747e6dSmrg                MyFont *fix_font)
6913e747e6dSmrg{
6923e747e6dSmrg    Gcv.foreground = fix_fore;
6933e747e6dSmrg    Gcv.background = fix_back;
6943e747e6dSmrg    if (use_fontset) {
6953e747e6dSmrg	XChangeGC(dpy, Scr->NormalGC, GCForeground|GCBackground, &Gcv);
6963e747e6dSmrg	return;
6973e747e6dSmrg    }
6983e747e6dSmrg    Gcv.font = fix_font->font->fid;
6993e747e6dSmrg    XChangeGC(dpy, Scr->NormalGC, GCFont|GCForeground|GCBackground,&Gcv);
7003e747e6dSmrg}
7013e747e6dSmrg
7023e747e6dSmrg/*
7033e747e6dSmrg * The following functions are internationalized substitutions
7043e747e6dSmrg * for XFetchName and XGetIconName using XGetWMName and
705ffd25bcaSmrg * XGetWMIconName.
7063e747e6dSmrg *
707ffd25bcaSmrg * Please note that the third arguments have to be freed using free(),
7083e747e6dSmrg * not XFree().
7093e747e6dSmrg */
7103e747e6dSmrgStatus
7113e747e6dSmrgI18N_FetchName(Display *dpy, Window w, char **winname)
7123e747e6dSmrg{
7133e747e6dSmrg    int    status;
7143e747e6dSmrg    XTextProperty text_prop;
7153e747e6dSmrg    char **list;
7163e747e6dSmrg    int    num;
717ffd25bcaSmrg
7183e747e6dSmrg    status = XGetWMName(dpy, w, &text_prop);
7193e747e6dSmrg    if (!status || !text_prop.value || !text_prop.nitems) {
7203e747e6dSmrg      *winname = NULL;
7213e747e6dSmrg      return 0;
7223e747e6dSmrg    }
7233e747e6dSmrg    status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
7243e747e6dSmrg    if (status < Success || !num || !*list) {
725ffd25bcaSmrg      *winname = NULL;
7263e747e6dSmrg      return 0;
7273e747e6dSmrg    }
7283e747e6dSmrg    XFree(text_prop.value);
7293e747e6dSmrg    *winname = (char *)strdup(*list);
7303e747e6dSmrg    XFreeStringList(list);
7313e747e6dSmrg    return 1;
7323e747e6dSmrg}
7333e747e6dSmrg
7343e747e6dSmrgStatus
7353e747e6dSmrgI18N_GetIconName(Display *dpy, Window w, char **iconname)
7363e747e6dSmrg{
7373e747e6dSmrg    int    status;
7383e747e6dSmrg    XTextProperty text_prop;
7393e747e6dSmrg    char **list;
7403e747e6dSmrg    int    num;
741ffd25bcaSmrg
7423e747e6dSmrg    status = XGetWMIconName(dpy, w, &text_prop);
7433e747e6dSmrg    if (!status || !text_prop.value || !text_prop.nitems) return 0;
7443e747e6dSmrg    status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
7453e747e6dSmrg    if (status < Success || !num || !*list) return 0;
7463e747e6dSmrg    XFree(text_prop.value);
7473e747e6dSmrg    *iconname = (char *)strdup(*list);
7483e747e6dSmrg    XFreeStringList(list);
7493e747e6dSmrg    return 1;
7503e747e6dSmrg}
7513e747e6dSmrg
7523e747e6dSmrg/**
7533e747e6dSmrg * separate routine to set focus to make things more understandable
7543e747e6dSmrg * and easier to debug
7553e747e6dSmrg */
7563e747e6dSmrgvoid
7573e747e6dSmrgSetFocus (TwmWindow *tmp_win, Time time)
7583e747e6dSmrg{
7593e747e6dSmrg    Window w = (tmp_win ? tmp_win->w : PointerRoot);
7603e747e6dSmrg
7613e747e6dSmrg#ifdef TRACE
7623e747e6dSmrg    if (tmp_win) {
7633e747e6dSmrg	printf ("Focusing on window \"%s\"\n", tmp_win->full_name);
7643e747e6dSmrg    } else {
7653e747e6dSmrg	printf ("Unfocusing; Scr->Focus was \"%s\"\n",
7663e747e6dSmrg		Scr->Focus ? Scr->Focus->full_name : "(nil)");
7673e747e6dSmrg    }
7683e747e6dSmrg#endif
7693e747e6dSmrg
7703e747e6dSmrg    XSetInputFocus (dpy, w, RevertToPointerRoot, time);
7713e747e6dSmrg}
7723e747e6dSmrg
773ffd25bcaSmrgstatic Pixmap
7743e747e6dSmrgCreateXLogoPixmap (unsigned *widthp, unsigned *heightp)
7753e747e6dSmrg{
7763e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
7773e747e6dSmrg    if (h < 0) h = 0;
7783e747e6dSmrg
7793e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
7803e747e6dSmrg    if (Scr->tbpm.xlogo == None) {
7813e747e6dSmrg	GC gc, gcBack;
7823e747e6dSmrg
7833e747e6dSmrg	Scr->tbpm.xlogo = XCreatePixmap (dpy, Scr->Root, h, h, 1);
7843e747e6dSmrg	gc = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
7853e747e6dSmrg	XSetForeground (dpy, gc, 0);
7863e747e6dSmrg	XFillRectangle (dpy, Scr->tbpm.xlogo, gc, 0, 0, h, h);
7873e747e6dSmrg	XSetForeground (dpy, gc, 1);
7883e747e6dSmrg	gcBack = XCreateGC (dpy, Scr->tbpm.xlogo, 0L, NULL);
7893e747e6dSmrg	XSetForeground (dpy, gcBack, 0);
7903e747e6dSmrg
7913e747e6dSmrg	/*
7923e747e6dSmrg	 * draw the logo large so that it gets as dense as possible; then white
7933e747e6dSmrg	 * out the edges so that they look crisp
7943e747e6dSmrg	 */
7953e747e6dSmrg	XmuDrawLogo (dpy, Scr->tbpm.xlogo, gc, gcBack, -1, -1, h + 2, h + 2);
7963e747e6dSmrg	XDrawRectangle (dpy, Scr->tbpm.xlogo, gcBack, 0, 0, h - 1, h - 1);
7973e747e6dSmrg
7983e747e6dSmrg	/*
7993e747e6dSmrg	 * done drawing
8003e747e6dSmrg	 */
8013e747e6dSmrg	XFreeGC (dpy, gc);
8023e747e6dSmrg	XFreeGC (dpy, gcBack);
8033e747e6dSmrg    }
8043e747e6dSmrg    return Scr->tbpm.xlogo;
8053e747e6dSmrg}
8063e747e6dSmrg
8073e747e6dSmrg
808ffd25bcaSmrgstatic Pixmap
8093e747e6dSmrgCreateResizePixmap (unsigned *widthp, unsigned *heightp)
8103e747e6dSmrg{
8113e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
8123e747e6dSmrg    if (h < 1) h = 1;
8133e747e6dSmrg
8143e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
8153e747e6dSmrg    if (Scr->tbpm.resize == None) {
8163e747e6dSmrg	XPoint	points[3];
8173e747e6dSmrg	GC gc;
8183e747e6dSmrg	int w;
8193e747e6dSmrg	int lw;
8203e747e6dSmrg
8213e747e6dSmrg	/*
8223e747e6dSmrg	 * create the pixmap
8233e747e6dSmrg	 */
8243e747e6dSmrg	Scr->tbpm.resize = XCreatePixmap (dpy, Scr->Root, h, h, 1);
8253e747e6dSmrg	gc = XCreateGC (dpy, Scr->tbpm.resize, 0L, NULL);
8263e747e6dSmrg	XSetForeground (dpy, gc, 0);
8273e747e6dSmrg	XFillRectangle (dpy, Scr->tbpm.resize, gc, 0, 0, h, h);
8283e747e6dSmrg	XSetForeground (dpy, gc, 1);
8293e747e6dSmrg	lw = h / 16;
8303e747e6dSmrg	if (lw == 1)
8313e747e6dSmrg	    lw = 0;
8323e747e6dSmrg	XSetLineAttributes (dpy, gc, lw, LineSolid, CapButt, JoinMiter);
8333e747e6dSmrg
8343e747e6dSmrg	/*
835ffd25bcaSmrg	 * draw the resize button,
8363e747e6dSmrg	 */
8373e747e6dSmrg	w = (h * 2) / 3;
8383e747e6dSmrg	points[0].x = w;
8393e747e6dSmrg	points[0].y = 0;
8403e747e6dSmrg	points[1].x = w;
8413e747e6dSmrg	points[1].y = w;
8423e747e6dSmrg	points[2].x = 0;
8433e747e6dSmrg	points[2].y = w;
8443e747e6dSmrg	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
8453e747e6dSmrg	w = w / 2;
8463e747e6dSmrg	points[0].x = w;
8473e747e6dSmrg	points[0].y = 0;
8483e747e6dSmrg	points[1].x = w;
8493e747e6dSmrg	points[1].y = w;
8503e747e6dSmrg	points[2].x = 0;
8513e747e6dSmrg	points[2].y = w;
8523e747e6dSmrg	XDrawLines (dpy, Scr->tbpm.resize, gc, points, 3, CoordModeOrigin);
8533e747e6dSmrg
8543e747e6dSmrg	/*
8553e747e6dSmrg	 * done drawing
8563e747e6dSmrg	 */
8573e747e6dSmrg	XFreeGC(dpy, gc);
8583e747e6dSmrg    }
8593e747e6dSmrg    return Scr->tbpm.resize;
8603e747e6dSmrg}
8613e747e6dSmrg
8623e747e6dSmrg
863ffd25bcaSmrgstatic Pixmap
8643e747e6dSmrgCreateDotPixmap (unsigned *widthp, unsigned *heightp)
8653e747e6dSmrg{
8663e747e6dSmrg    int h = Scr->TBInfo.width - Scr->TBInfo.border * 2;
8673e747e6dSmrg
8683e747e6dSmrg    h = h * 3 / 4;
8693e747e6dSmrg    if (h < 1) h = 1;
8703e747e6dSmrg    if (!(h & 1))
8713e747e6dSmrg	h--;
8723e747e6dSmrg    *widthp = *heightp = (unsigned int) h;
8733e747e6dSmrg    if (Scr->tbpm.delete == None) {
8743e747e6dSmrg	GC  gc;
8753e747e6dSmrg	Pixmap pix;
8763e747e6dSmrg
8773e747e6dSmrg	pix = Scr->tbpm.delete = XCreatePixmap (dpy, Scr->Root, h, h, 1);
8783e747e6dSmrg	gc = XCreateGC (dpy, pix, 0L, NULL);
8793e747e6dSmrg	XSetLineAttributes (dpy, gc, h, LineSolid, CapRound, JoinRound);
8803e747e6dSmrg	XSetForeground (dpy, gc, 0L);
8813e747e6dSmrg	XFillRectangle (dpy, pix, gc, 0, 0, h, h);
8823e747e6dSmrg	XSetForeground (dpy, gc, 1L);
8833e747e6dSmrg	XDrawLine (dpy, pix, gc, h/2, h/2, h/2, h/2);
8843e747e6dSmrg	XFreeGC (dpy, gc);
8853e747e6dSmrg    }
8863e747e6dSmrg    return Scr->tbpm.delete;
8873e747e6dSmrg}
8883e747e6dSmrg
8893e747e6dSmrg#define questionmark_width 8
8903e747e6dSmrg#define questionmark_height 8
8913e747e6dSmrgstatic char questionmark_bits[] = {
8923e747e6dSmrg   0x38, 0x7c, 0x64, 0x30, 0x18, 0x00, 0x18, 0x18};
8933e747e6dSmrg
894ffd25bcaSmrgstatic Pixmap
8953e747e6dSmrgCreateQuestionPixmap (unsigned *widthp, unsigned *heightp)
8963e747e6dSmrg{
8973e747e6dSmrg    *widthp = questionmark_width;
8983e747e6dSmrg    *heightp = questionmark_height;
8993e747e6dSmrg    if (Scr->tbpm.question == None) {
9003e747e6dSmrg	Scr->tbpm.question = XCreateBitmapFromData (dpy, Scr->Root,
9013e747e6dSmrg						    questionmark_bits,
9023e747e6dSmrg						    questionmark_width,
9033e747e6dSmrg						    questionmark_height);
9043e747e6dSmrg    }
9053e747e6dSmrg    /*
9063e747e6dSmrg     * this must succeed or else we are in deep trouble elsewhere
9073e747e6dSmrg     */
9083e747e6dSmrg    return Scr->tbpm.question;
9093e747e6dSmrg}
9103e747e6dSmrg
9113e747e6dSmrg
912ffd25bcaSmrgstatic Pixmap
9133e747e6dSmrgCreateMenuPixmap (unsigned *widthp, unsigned *heightp)
9143e747e6dSmrg{
9153e747e6dSmrg    return CreateMenuIcon (Scr->TBInfo.width - Scr->TBInfo.border * 2,
9163e747e6dSmrg			   widthp,heightp);
9173e747e6dSmrg}
9183e747e6dSmrg
919ffd25bcaSmrgPixmap
9203e747e6dSmrgCreateMenuIcon (int height, unsigned *widthp, unsigned *heightp)
9213e747e6dSmrg{
9223e747e6dSmrg    int h, w;
9233e747e6dSmrg    int ih, iw;
9243e747e6dSmrg    int	ix, iy;
9253e747e6dSmrg    int	mh, mw;
9263e747e6dSmrg    int	tw, th;
9273e747e6dSmrg    int	lw, lh;
9283e747e6dSmrg    int	lx, ly;
9293e747e6dSmrg    int	lines, dly;
9303e747e6dSmrg    int off;
9313e747e6dSmrg    int	bw;
9323e747e6dSmrg
9333e747e6dSmrg    h = height;
9343e747e6dSmrg    w = h * 7 / 8;
9353e747e6dSmrg    if (h < 1)
9363e747e6dSmrg	h = 1;
9373e747e6dSmrg    if (w < 1)
9383e747e6dSmrg	w = 1;
9393e747e6dSmrg    *widthp = w;
9403e747e6dSmrg    *heightp = h;
9413e747e6dSmrg    if (Scr->tbpm.menu == None) {
9423e747e6dSmrg	Pixmap  pix;
9433e747e6dSmrg	GC	gc;
9443e747e6dSmrg
9453e747e6dSmrg	pix = Scr->tbpm.menu = XCreatePixmap (dpy, Scr->Root, w, h, 1);
9463e747e6dSmrg	gc = XCreateGC (dpy, pix, 0L, NULL);
9473e747e6dSmrg	XSetForeground (dpy, gc, 0L);
9483e747e6dSmrg	XFillRectangle (dpy, pix, gc, 0, 0, w, h);
9493e747e6dSmrg	XSetForeground (dpy, gc, 1L);
9503e747e6dSmrg	ix = 1;
9513e747e6dSmrg	iy = 1;
9523e747e6dSmrg	ih = h - iy * 2;
9533e747e6dSmrg	iw = w - ix * 2;
9543e747e6dSmrg	off = ih / 8;
9553e747e6dSmrg	mh = ih - off;
9563e747e6dSmrg	mw = iw - off;
9573e747e6dSmrg	bw = mh / 16;
9583e747e6dSmrg	if (bw == 0 && mw > 2)
9593e747e6dSmrg	    bw = 1;
9603e747e6dSmrg	tw = mw - bw * 2;
9613e747e6dSmrg	th = mh - bw * 2;
9623e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix, iy, mw, mh);
9633e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix + iw - mw, iy + ih - mh, mw, mh);
9643e747e6dSmrg	XSetForeground (dpy, gc, 0L);
9653e747e6dSmrg	XFillRectangle (dpy, pix, gc, ix+bw, iy+bw, tw, th);
9663e747e6dSmrg	XSetForeground (dpy, gc, 1L);
9673e747e6dSmrg	lw = tw / 2;
9683e747e6dSmrg	if ((tw & 1) ^ (lw & 1))
9693e747e6dSmrg	    lw++;
9703e747e6dSmrg	lx = ix + bw + (tw - lw) / 2;
9713e747e6dSmrg
9723e747e6dSmrg	lh = th / 2 - bw;
9733e747e6dSmrg	if ((lh & 1) ^ ((th - bw) & 1))
9743e747e6dSmrg	    lh++;
9753e747e6dSmrg	ly = iy + bw + (th - bw - lh) / 2;
9763e747e6dSmrg
9773e747e6dSmrg	lines = 3;
9783e747e6dSmrg	if ((lh & 1) && lh < 6)
9793e747e6dSmrg	{
9803e747e6dSmrg	    lines--;
9813e747e6dSmrg	}
9823e747e6dSmrg	dly = lh / (lines - 1);
9833e747e6dSmrg	while (lines--)
9843e747e6dSmrg	{
9853e747e6dSmrg	    XFillRectangle (dpy, pix, gc, lx, ly, lw, bw);
9863e747e6dSmrg	    ly += dly;
9873e747e6dSmrg	}
9883e747e6dSmrg	XFreeGC (dpy, gc);
9893e747e6dSmrg    }
9903e747e6dSmrg    return Scr->tbpm.menu;
9913e747e6dSmrg}
9923e747e6dSmrg
9933e747e6dSmrgvoid
9943e747e6dSmrgBell(int type, int percent, Window win)
9953e747e6dSmrg{
9963e747e6dSmrg#ifdef XKB
9973e747e6dSmrg    XkbStdBell(dpy, win, percent, type);
9983e747e6dSmrg#else
9993e747e6dSmrg    XBell(dpy, percent);
10003e747e6dSmrg#endif
10013e747e6dSmrg    return;
10023e747e6dSmrg}
1003