view x11window.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
line wrap: on
line source

/* $Id: x11window.c,v 1.1.1.1 1997/12/06 05:41:31 darius Exp $ */


/* x11window.c
 *
 * Kevin P. Smith  6/11/89
 * Much modified by Jerry Frain and Joe Young
 */

#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef RFCURSORS
#include <X11/Xmu/CurUtil.h>
#endif
#include <X11/cursorfont.h>
#include <assert.h>
#include <string.h>
#include "Wlib.h"
#include "defs.h"
#include "struct.h"
#include "data.h"
#include "proto.h"

#define INVALID_POSITION	-10000	/* gotta be a big negative */
/* XFIX speedup */
#define MAXCACHE	128

/* changes too good to risk leaving out, by Richard Caley (rjc@cstr.ed.ac.uk)*/
#define RJC
#define FOURPLANEFIX

/*
#define NORMAL_FONT	"-*-fixed-medium-r-*-*-10-*-*-*-*-*-*-*"
#define BOLD_FONT	"-*-fixed-medium-r-*-*-10-*-*-*-*-*-*-*"
#define ITALIC_FONT	"-*-fixed-medium-r-*-*-10-*-*-*-*-*-*-*"
*/

#define NORMAL_FONT	"6x10"
#define BOLD_FONT	"6x10"
#define BOLD_FONT2	"-*-clean-bold-r-normal--10-100-75-75-c-60-*"
#define ITALIC_FONT	"6x10"
#define ITALIC_FONT2	"-*-clean-bold-r-normal--10-100-75-75-c-60-*"
#define BIG_FONT	"-adobe-helvetica-bold-r-normal--34-*-*-*-*-*-*-*"
#define IND_FONT        "-*-clean-bold-r-normal--10-100-75-75-c-60-*"
/*#define BOLD_FONT2	"-schumacher-clean-bold-r-normal--10-100-75-75-c-60-iso8859-1"
#define ITALIC_FONT2	"-misc-fixed-medium-i-normal--10-100-75-75-c-60-iso8859-1"
#define BIG_FONT	"-adobe-helvetica-bold-r-normal--34-*-*-*-*-*-*-*"
*/

static char *_nfonts[] = {
    NORMAL_FONT,
    "-*-clean-medium-r-normal--10-100-75-75-c-60-*",
    "fixed",
    NULL,
};
static char *_bfonts[] = {
    BOLD_FONT,
    "-*-clean-bold-r-normal--10-100-75-75-c-60-*",
    "fixed",
    NULL,
};
static char *_ifonts[] = {
    ITALIC_FONT,
    "-*-clean-bold-r-normal--10-100-75-75-c-60-*",
    "fixed",
    NULL,
};
static char *_bgfonts[] = {
    BIG_FONT,
    "-*-lucidatypewriter-*-*-*-*-40-*-*-*-*-*-*-*",
    "fixed",
    NULL,
};

#define FONTS 4
#define BITGC 4

#define WHITE   0
#define BLACK   1
#define RED     2
#define GREEN   3
#define YELLOW  4
#define CYAN    5
#define GREY	6

static int zero = 0;
static int one = 1;
static int two = 2;
static int three = 3;

int     controlkey = 0;
#define	BillsScrewyAltMask	(Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
int     altkey = 0;
int     W_FastClear = 0;
#ifdef CONTINUOUS_MOUSE
int     buttonDown = 0;
#endif				/* CONTINUOUS_MOUSE */
Display *W_Display;
Window  W_Root;
Colormap W_Colormap;
int     W_Screen;
#ifdef FOURPLANEFIX
Visual *W_Visual;
#endif
W_Font  W_BigFont = (W_Font) & zero, W_RegularFont = (W_Font) & one;
W_Font  W_HighlightFont = (W_Font) & two, W_UnderlineFont = (W_Font) & three;
W_Color W_White = WHITE, W_Black = BLACK, W_Red = RED, W_Green = GREEN;
W_Color W_Yellow = YELLOW, W_Cyan = CYAN, W_Grey = GREY;
int     W_Textwidth, W_Textheight;
char   *getdefault();
char   *strdup();

int     W_in_message = 0;	/* jfy -- for Jerry's warp message hack */

#ifdef RJC
extern W_Window baseWin;
static XClassHint class_hint = {
    "netrek", "Netrek",
};

static XWMHints wm_hint = {
    InputHint | StateHint,
    True,
    WithdrawnState,
    None,
    None,
    0, 0,
    None,
    None,
};

static XSizeHints wm_size_hint;
#endif				/* RJC */

static W_Event W_myevent;
static int W_isEvent = 0;

struct fontInfo {
    XFontStruct *fontstruct;
    int     baseline;
};

struct colors {
    char   *name;
    GC      contexts[FONTS + 1];
    Pixmap  pixmap;
    long    pixelValue;
};

struct icon {
    Window  window;
    Pixmap  bitmap;
    int     width, height;
    Pixmap  pixmap;
};

#define WIN_GRAPH	1
#define WIN_TEXT	2
#define WIN_MENU	3
#define WIN_SCROLL	4

struct window {
    Window  window;
    int     type;
    char   *data;
    int     mapped;
    int     width, height;
    char   *name;
    Cursor  cursor;
#ifdef SHORT_PACKETS
    int     insensitive;
#endif
#if 0
    W_Callback handle_keydown;
    W_Callback handle_keyup;
    W_Callback handle_button;
    W_Callback handle_expose;
#endif				/* 0 */
};

struct stringList {
    char   *string;
    W_Color color;
    struct stringList *next;
};

struct menuItem {
    char   *string;
    W_Color color;
    W_Font  font;
};

struct colors colortable[] = {
    {"white"},
    {"black"},
    {"red"},
    {"green"},
    {"yellow"},
    {"cyan"},
    {"light grey"}
};

struct windowlist {
    struct window *window;
    struct windowlist *next;
};

#define HASHSIZE 29
#define hash(x) (((int) (x)) % HASHSIZE)

struct windowlist *hashtable[HASHSIZE];
struct fontInfo fonts[FONTS];

struct window *newWindow();
#ifndef NeXT
#ifndef __STDC__
char   *malloc();
#endif
#endif				/* NeXT */
short  *x11tox10bits();

struct window myroot;

#define NCOLORS (sizeof(colortable)/sizeof(colortable[0]))
#define W_Void2Window(win) ((win) ? (struct window *) (win) : &myroot)
#define W_Window2Void(window) ((W_Window) (window))
#define W_Void2Icon(bit) ((struct icon *) (bit))
#define W_Icon2Void(bit) ((W_Icon) (bit))
#define fontNum(font) (*((int *) font))
#define TILESIDE 16

#define WIN_EDGE 5		/* border on l/r edges of text windows */
#define MENU_PAD 4		/* border on t/b edges of text windows */
#define MENU_BAR 2		/* width of menu bar */

static unsigned char gray[] = {
    0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
    0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
    0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
    0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55
};

static unsigned char striped[] = {
    0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
    0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f,
    0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00,
    0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0
};

static unsigned char solid[] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

/* Prototypes */
/*static int _myerror P((Display *d , XErrorEvent *e ));*/
static void GetFonts P((void));
static XFontStruct *find_font P((char *oldf, char **fonts));
static void GetColors P((void));
static void FlushClearAreaCache P((Window win));
static int W_SpNextEvent P((W_Event * wevent));
static void FlushLineCache P((Window win, int color));
static void FlushPointCache P((Window win, int color));
static struct window *findWindow P((Window window));
static void addToHash P((struct window * win));
static void AddToScrolling P((struct window * win, W_Color color, char *str, int len));
static void redrawScrolling P((struct window * win));
static void resizeScrolling P((struct window * win, int width, int height));
static void redrawMenu P((struct window * win));
static void redrawMenuItem P((struct window * win, int n));
static void changeMenuItem P((struct window * win, int n, W_Color color, char *str, int len, W_Font font));
/*static void W_SetTransientForHint P((W_Window w , W_Window pw ));*/
static void checkGeometry P((char *name, int *x, int *y, int *width, int *height));
static void checkParent P((char *name, W_Window * parent));
static void checkCursor P((char *name, char *cursname, Cursor * cursor));
static void findMouse P((int *x, int *y));
#ifdef AUTOKEY
static void W_Flush P((void));
#endif				/* AUTOKEY */
static void deleteWindow P((struct window * window));

/* X debugging */
#if 0
static int
_myerror(d, e)
    Display *d;
    XErrorEvent *e;
{
    abort();
}
#endif				/* 0 */

void
W_Initialize(str)
    char   *str;
{
    int     i;

#ifdef DEBUG
    printf("Initializing...\n");
#endif
    for (i = 0; i < HASHSIZE; i++) {
	hashtable[i] = NULL;
    }
    if ((W_Display = XOpenDisplay(str)) == NULL) {
	fprintf(stderr, "Cannot open display \"%s\"\n", str ? str : "(null)");
	EXIT(1);
    }
#if 0
    /* tmp */
    XSynchronize(W_Display, True);
    XSetErrorHandler(_myerror);
#endif

    W_Root = DefaultRootWindow(W_Display);
#ifdef FOURPLANEFIX
    W_Visual = DefaultVisual(W_Display, DefaultScreen(W_Display));
#endif
    W_Screen = DefaultScreen(W_Display);
    W_Colormap = DefaultColormap(W_Display, W_Screen);
    myroot.window = W_Root;
    myroot.type = WIN_GRAPH;
    GetFonts();
    GetColors();
}

static void
GetFonts()
{
    Font    regular, italic, bold, big;
    int     i;
    XGCValues values;
    XFontStruct *fontinfo;
    char   *fontname;

    fontname = getdefault("font");
    if (fontname == NULL)
	fontname = NORMAL_FONT;
    fontinfo = XLoadQueryFont(W_Display, fontname);
    if (fontinfo == NULL) {
	fontinfo = find_font(fontname, _nfonts);
    }
    if (fontinfo == NULL) {
	printf("netrek: Can't find any fonts!\n");
	EXIT(1);
    }
    regular = fontinfo->fid;
    W_Textwidth = fontinfo->max_bounds.width;
    W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
    fonts[1].baseline = fontinfo->max_bounds.ascent;
    fonts[1].fontstruct = fontinfo;

    fontname = getdefault("boldfont");
    if (fontname == NULL) {
	if (DisplayCells(W_Display, W_Screen) <= 4)
	    fontname = BOLD_FONT2;
	else
	    fontname = BOLD_FONT;
    }
    fontinfo = XLoadQueryFont(W_Display, fontname);
    if (fontinfo == NULL) {
	fontinfo = find_font(fontname, _bfonts);
    }
    if (fontinfo == NULL) {
	bold = regular;
	fonts[2].baseline = fonts[1].baseline;
	fonts[2].fontstruct = fonts[1].fontstruct;
    } else {
	bold = fontinfo->fid;
	fonts[2].baseline = fontinfo->max_bounds.ascent;
	fonts[2].fontstruct = fontinfo;
	if (fontinfo->max_bounds.width > W_Textwidth)
	    W_Textwidth = fontinfo->max_bounds.width;
	if (fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent > W_Textheight)
	    W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
    }

    fontname = getdefault("italicfont");
    if (fontname == NULL) {
	if (DisplayCells(W_Display, W_Screen) <= 4)
	    fontname = ITALIC_FONT2;
	else
	    fontname = ITALIC_FONT;
    }
    fontinfo = XLoadQueryFont(W_Display, fontname);
    if (fontinfo == NULL) {
	fontinfo = find_font(fontname, _ifonts);
    }
    if (fontinfo == NULL) {
	italic = regular;
	fonts[3].baseline = fonts[1].baseline;
	fonts[3].fontstruct = fonts[1].fontstruct;
    } else {
	italic = fontinfo->fid;
	fonts[3].baseline = fontinfo->max_bounds.ascent;
	fonts[3].fontstruct = fontinfo;
	if (fontinfo->max_bounds.width > W_Textwidth)
	    W_Textwidth = fontinfo->max_bounds.width;
	if (fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent > W_Textheight)
	    W_Textheight = fontinfo->max_bounds.descent + fontinfo->max_bounds.ascent;
    }

    fontname = getdefault("bigfont");
    if (fontname == NULL)
	fontname = BIG_FONT;
    fontinfo = XLoadQueryFont(W_Display, fontname);
    if (fontinfo == NULL) {
	fontinfo = find_font(fontname, _bgfonts);
    }
    if (fontinfo == NULL) {
	big = regular;
	fonts[0].baseline = fonts[1].baseline;
	fonts[0].fontstruct = fonts[1].fontstruct;
    } else {
	big = fontinfo->fid;
	fonts[0].baseline = fontinfo->max_bounds.ascent;
	fonts[0].fontstruct = fontinfo;
    }
    for (i = 0; i < NCOLORS; i++) {
	values.font = big;
	colortable[i].contexts[0] = XCreateGC(W_Display, W_Root, GCFont, &values);
	XSetGraphicsExposures(W_Display, colortable[i].contexts[0], False);
	values.font = regular;
	colortable[i].contexts[1] = XCreateGC(W_Display, W_Root, GCFont, &values);
	XSetGraphicsExposures(W_Display, colortable[i].contexts[1], False);
	values.font = bold;
	colortable[i].contexts[2] = XCreateGC(W_Display, W_Root, GCFont, &values);
	XSetGraphicsExposures(W_Display, colortable[i].contexts[2], False);
	values.font = italic;
	colortable[i].contexts[3] = XCreateGC(W_Display, W_Root, GCFont, &values);
	XSetGraphicsExposures(W_Display, colortable[i].contexts[3], False);
	{
	    static char dl[] = {1, 4};
	    XSetLineAttributes(W_Display, colortable[i].contexts[3],
			       0, LineOnOffDash, CapButt, JoinMiter);
	    XSetDashes(W_Display, colortable[i].contexts[3], 0, dl, 2);
	}
	values.function = GXor;
	colortable[i].contexts[BITGC] = XCreateGC(W_Display, W_Root, GCFunction, &values);
	XSetGraphicsExposures(W_Display, colortable[i].contexts[BITGC], False);
    }
}

static XFontStruct *
find_font(oldf, fonts)
    char   *oldf, **fonts;
{
    XFontStruct *fi;
    char  **f;
    fprintf(stderr, "netrek: Can't find font %s.  Trying others...\n",
	    oldf);
    for (f = fonts; *f; f++) {
	if (strcmp(*f, oldf) != 0) {
	    if ((fi = XLoadQueryFont(W_Display, *f)))
		return fi;
	}
    }
    printf("Error - can't find any font!\n");
    return NULL;
}

#ifdef FOURPLANEFIX
static unsigned short extrared[8] = {0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xb0, 0xc0};
static unsigned short extragreen[8] = {0x40, 0x60, 0x80, 0xa0, 0xb0, 0xc0, 0x00, 0x20};
static unsigned short extrablue[8] = {0x80, 0xa0, 0xb0, 0xc0, 0x00, 0x20, 0x40, 0x60};
#endif

int
W_Mono()
{
    return forceMono;
}

static void
GetColors()
{
    int     i, j;
    XColor  foo;
    int     white, black;
    unsigned long pixel;
    unsigned long planes[3];
    char    defaultstring[100];
    char   *defaults;
#ifdef FOURPLANEFIX
    unsigned long extracolors[8];
    XColor  colordef;
#endif
    extern int forceMono;
    forceMono = booleanDefault("forcemono", forceMono);

    if ((DisplayCells(W_Display, W_Screen) <= 4) || forceMono) {
	forceMono = 1;
	white = WhitePixel(W_Display, W_Screen);
	black = BlackPixel(W_Display, W_Screen);
	for (i = 0; i < NCOLORS; i++) {
	    if (i != W_Black) {
		colortable[i].pixelValue = white;
	    } else {
		colortable[i].pixelValue = black;
	    }
	    if (i == W_Red) {
		colortable[i].pixmap = XCreatePixmapFromBitmapData
		    (W_Display,
		     W_Root, (char *) striped, TILESIDE, TILESIDE,
		     white, black,
		     DefaultDepth(W_Display, W_Screen));
	    } else if (i == W_Yellow) {
		colortable[i].pixmap = XCreatePixmapFromBitmapData
		    (W_Display,
		     W_Root, (char *) gray, TILESIDE, TILESIDE,
		     white, black,
		     DefaultDepth(W_Display, W_Screen));
	    } else {
		colortable[i].pixmap = XCreatePixmapFromBitmapData
		    (W_Display,
		     W_Root, (char *) solid, TILESIDE, TILESIDE,
		     colortable[i].pixelValue,
		     colortable[i].pixelValue,
		     DefaultDepth(W_Display, W_Screen));
	    }

	    /*
	       We assume white is 0 or 1, and black is 0 or 1. We adjust
	       graphics function based upon who is who.
	    */
	    if (white == 0) {	/* Black is 1 */
		XSetFunction(W_Display, colortable[i].contexts[BITGC], GXand);
	    }
	}
    } else if (DefaultVisual(W_Display, W_Screen)->class == TrueColor) {
/* Stuff added by sheldon@iastate.edu 5/28/93
 * This is supposed to detect a TrueColor display, and then do a lookup of
 * the colors in default colormap, instead of creating new colormap
 */
	for (i = 0; i < NCOLORS; i++) {
	    sprintf(defaultstring, "color.%s", colortable[i].name);

	    defaults = getdefault(defaultstring);
	    if (defaults == NULL)
		defaults = colortable[i].name;
	    XParseColor(W_Display, W_Colormap, defaults, &foo);
	    XAllocColor(W_Display, W_Colormap, &foo);
	    colortable[i].pixelValue = foo.pixel;
	    colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
	    W_Root, (char *) solid, TILESIDE, TILESIDE, foo.pixel, foo.pixel,
					 DefaultDepth(W_Display, W_Screen));
	}
    } else {
#ifdef FOURPLANEFIX
	if (!XAllocColorCells(W_Display, W_Colormap, False, planes, 3,
			      &pixel, 1)) {
	    /* couldn't allocate 3 planes, make a new colormap */
	    W_Colormap = XCreateColormap(W_Display, W_Root, W_Visual, AllocNone);
	    if (!XAllocColorCells(W_Display, W_Colormap, False, planes, 3,
				  &pixel, 1)) {
		fprintf(stderr, "Cannot create new colormap\n");
		EXIT(1);
	    }
	    /*
	       and fill it with at least 8 more colors so when mouse is
	       inside netrek windows, use might be able to see his other
	       windows
	    */
	    if (XAllocColorCells(W_Display, W_Colormap, False, NULL, 0,
				 extracolors, 8)) {
		colordef.flags = DoRed | DoGreen | DoBlue;
		for (i = 0; i < 8; i++) {
		    colordef.pixel = extracolors[i];
		    colordef.red = extrared[i] << 8;
		    colordef.green = extragreen[i] << 8;
		    colordef.blue = extrablue[i] << 8;
		    XStoreColor(W_Display, W_Colormap, &colordef);
		}
	    }
	}
#else
	XAllocColorCells(W_Display, W_Colormap, False, planes, 3, &pixel, 1);
#endif
	for (i = 0; i < NCOLORS; i++) {
	    /*
	       strcpy(defaultstring, "color.%s", colortable[i].name);
	    */
	    sprintf(defaultstring, "color.%s", colortable[i].name);

	    defaults = getdefault(defaultstring);
	    if (defaults == NULL)
		defaults = colortable[i].name;
	    XParseColor(W_Display, W_Colormap, defaults, &foo);
	    /*
	       Black must be the color with all the planes off. That is the
	       only restriction I concerned myself with in the following case
	       statement.
	    */
	    switch (i) {
	    case WHITE:
		foo.pixel = pixel | planes[0] | planes[1] | planes[2];
		break;
	    case BLACK:
		foo.pixel = pixel;
		break;
	    case RED:
		foo.pixel = pixel | planes[0];
		break;
	    case CYAN:
		foo.pixel = pixel | planes[1];
		break;
	    case YELLOW:
		foo.pixel = pixel | planes[2];
		break;
	    case GREY:
		foo.pixel = pixel | planes[0] | planes[1];
		break;
	    case GREEN:
		foo.pixel = pixel | planes[1] | planes[2];
		break;
	    }
	    XStoreColor(W_Display, W_Colormap, &foo);
	    colortable[i].pixelValue = foo.pixel;
	    colortable[i].pixmap = XCreatePixmapFromBitmapData(W_Display,
	    W_Root, (char *) solid, TILESIDE, TILESIDE, foo.pixel, foo.pixel,
					 DefaultDepth(W_Display, W_Screen));
	}
    }
    for (i = 0; i < NCOLORS; i++) {
	for (j = 0; j < FONTS + 1; j++) {
	    XSetForeground(W_Display, colortable[i].contexts[j],
			   colortable[i].pixelValue);
	    XSetBackground(W_Display, colortable[i].contexts[j],
			   colortable[W_Black].pixelValue);
	}
    }
}

void
W_RenameWindow(window, str)
    W_Window window;
    char   *str;
{
    XStoreName(W_Display, ((struct window *) window)->window, str);
}

static  W_Window
w_MakeWindow(name, x, y, width, height, parent,
	     cursname, border, color, wsort)
    char   *name;
    int     x, y, width, height;
    W_Window parent;
    char   *cursname;
    int     border;
    W_Color color;
    int     wsort;		/* WIN_? */
{
    int     gx, gy;
    struct window *newwin;
    Window  wparent;
    Cursor  cursor;
    XSetWindowAttributes attrs;
    int     pwidth, pheight;	/* pixel width and height */


    checkGeometry(name, &gx, &gy, &width, &height);
    if (gx != INVALID_POSITION)
	x = gx;
    if (gy != INVALID_POSITION)
	y = gy;

    checkParent(name, &parent);
    wparent = W_Void2Window(parent)->window;

    checkCursor(name, cursname, &cursor);
    attrs.cursor = cursor;

    attrs.border_pixel = colortable[color].pixelValue;
    attrs.background_pixel = colortable[W_Black].pixelValue;

    if (wsort == WIN_TEXT || wsort == WIN_SCROLL || wsort == WIN_MENU) {
	pwidth = width * W_Textwidth + WIN_EDGE * 2;
	if (wsort == WIN_MENU)
	    pheight = height * (W_Textheight + MENU_PAD * 2 + MENU_BAR) - MENU_BAR;
	else
	    pheight = height * W_Textheight + MENU_PAD * 2;
    } else {
	pwidth = width;
	pheight = height;
    }

    switch (wsort) {
    case WIN_TEXT:
    case WIN_MENU:
	attrs.event_mask = KeyPressMask | ButtonPressMask | ExposureMask | ButtonReleaseMask;
	attrs.do_not_propagate_mask = ExposureMask | KeyPressMask | ButtonPressMask;
	break;
    case WIN_GRAPH:
	attrs.event_mask = KeyPressMask | ButtonPressMask | ExposureMask | LeaveWindowMask | ButtonReleaseMask | ButtonMotionMask;
	attrs.do_not_propagate_mask = ExposureMask;
	break;
    case WIN_SCROLL:
	attrs.event_mask = ResizeRedirectMask | ExposureMask | KeyPressMask | ButtonReleaseMask | ButtonPressMask;
	attrs.do_not_propagate_mask = ResizeRedirectMask | ExposureMask;
	break;
    default:
	fprintf(stderr, "x11window.c: w_MakeWindow: unknown wsort %d\n", wsort);
    }

#ifdef AUTOKEY
    if (attrs.event_mask & KeyPressMask)
	attrs.event_mask |= KeyReleaseMask;
#endif				/* AUTOKEY */

    if (strcmp(name, "netrek_icon") == 0)	/* icon should not select for
						   input */
	attrs.event_mask = ExposureMask;
    if (strcmp(name, "wait_icon") == 0)	/* same here [BDyess] */
	attrs.event_mask = ExposureMask;

    if (strcmp(name, "info") == 0)	/* make info window passthru [BDyess] */
	attrs.event_mask = ExposureMask;

    newwin = newWindow
	(XCreateWindow(W_Display, wparent, x, y, pwidth, pheight, border,
		       CopyFromParent, InputOutput, CopyFromParent,
		       CWBackPixel | CWBorderPixel | CWEventMask |
		       (cursor ? CWCursor : 0),
		       &attrs),
	 wsort);

    newwin->cursor = cursor;

    {
	char   *s;

	if (0 == strcmp(name, "wait"))
	    s = serverName;
	else if (0 == strcmp(name, "Motd"))
	    s = "Motd - [f] forward, [b] back, [tab] sysdefs, [space] unmap";
	else if (0 == strcmp(name, "netrek")) {
	    if (!title) {
		char    buf[80];
		sprintf(buf, "Netrek  @  %s", serverName);
		s = buf;
	    } else {
		/* but title on command line will override */
		/* from -h arg */
		s = title;
	    }
	} else
	    s = name;

	XStoreName(W_Display, newwin->window, s);
    }

    wm_size_hint.width = wm_size_hint.min_width =
	wm_size_hint.max_width = wm_size_hint.base_width = pwidth;
    wm_size_hint.min_height = wm_size_hint.height =
	wm_size_hint.max_height = wm_size_hint.base_height = pheight;
    wm_size_hint.flags = USSize | PMinSize | PMaxSize | PBaseSize;
    if (gx > INVALID_POSITION || gy > INVALID_POSITION) {
	wm_size_hint.flags |= USPosition;
	wm_size_hint.x = x;
	wm_size_hint.y = y;
    }
    XSetWMNormalHints(W_Display, newwin->window, &wm_size_hint);

    class_hint.res_name = name;
    class_hint.res_class = "Netrek";
    XSetClassHint(W_Display, newwin->window, &class_hint);

    XSetWMHints(W_Display, newwin->window, &wm_hint);

    if (((wparent == W_Root &&
	  baseWin != NULL &&
	  strcmp(name, "wait") != 0)
	 || wsort == WIN_MENU) &&
	strcmp(name, "MetaServer List") != 0 &&
	strcmp(name, "Motd") != 0) {
	XSetTransientForHint(W_Display, newwin->window,
			     W_Void2Window(baseWin)->window);
    }
    newwin->name = strdup(name);
    newwin->width = width;
    newwin->height = height;
    if (wsort == WIN_MENU) {
	int     i;
	struct menuItem *items;
	items = (struct menuItem *) malloc(height * sizeof(struct menuItem));
	for (i = 0; i < height; i++) {
	    items[i].string = NULL;
	    items[i].color = W_White;
	    items[i].font = W_RegularFont;
	}
	newwin->data = (char *) items;
    } else {
	newwin->data = 0;
    }

    if (wparent != W_Root)
	if (checkMapped(name))
	    W_MapWindow(W_Window2Void(newwin));

#ifdef DEBUG
    printf("New graphics window %d, child of %d\n", newwin, parent);
#endif

#ifdef FOURPLANEFIX
    XSetWindowColormap(W_Display, newwin->window, W_Colormap);
#endif

    return (W_Window2Void(newwin));
}




W_Window
W_MakeWindow(name, x, y, width, height, parent, cursname, border, color)
    char   *name;
    int     x, y, width, height;
    W_Window parent;
    char   *cursname;
    int     border;
    W_Color color;
{
    return w_MakeWindow(name, x, y, width, height, parent,
			cursname, border, color, WIN_GRAPH);
}

void
W_ChangeBorder(window, color)
    W_Window window;
    int     color;
{
#ifdef DEBUG
    printf("Changing border of %d\n", window);
#endif

    /* fix inexplicable color bug */
    if (DisplayCells(W_Display, W_Screen) <= 2)
	XSetWindowBorderPixmap(W_Display, W_Void2Window(window)->window,
			       colortable[color].pixmap);
    else
	XSetWindowBorder(W_Display, W_Void2Window(window)->window,
			 colortable[color].pixelValue);
}

void
W_MapWindow(window)
    W_Window window;
{
    struct window *win;

#ifdef DEBUG
    printf("Mapping %d\n", window);
#endif
    win = W_Void2Window(window);
    if (win->mapped)
	return;
    win->mapped = 1;
    XMapRaised(W_Display, win->window);
}

void
W_UnmapWindow(window)
    W_Window window;
{
    struct window *win;

#ifdef DEBUG
    printf("UnMapping %d\n", window);
#endif
    win = W_Void2Window(window);
    if (win->mapped == 0)
	return;
    win->mapped = 0;
    XUnmapWindow(W_Display, win->window);
}

int
W_IsMapped(window)
    W_Window window;
{
    struct window *win;

    win = W_Void2Window(window);
    if (win == NULL)
	return (0);
    return (win->mapped);
}

void
W_FillArea(window, x, y, width, height, color)
    W_Window window;
    int     x, y, width, height;
    W_Color color;
{
    struct window *win;

#ifdef DEBUG
    printf("Clearing (%d %d) x (%d %d) with %d on %d\n", x, y, width, height,
	   color, window);
#endif
    win = W_Void2Window(window);
    switch (win->type) {
    case WIN_GRAPH:
	XFillRectangle(W_Display, win->window, colortable[color].contexts[0],
		       x, y, width, height);
	break;
    default:
	XFillRectangle(W_Display, win->window, colortable[color].contexts[0],
		    WIN_EDGE + x * W_Textwidth, MENU_PAD + y * W_Textheight,
		       width * W_Textwidth, height * W_Textheight);
    }
}

/* XFIX */

static XRectangle _rcache[MAXCACHE];
static int _rcache_index;

static void
FlushClearAreaCache(win)
    Window  win;
{
    XFillRectangles(W_Display, win, colortable[backColor].contexts[0],
		    _rcache, _rcache_index);
    _rcache_index = 0;
}

/* local window only */
void
W_CacheClearArea(window, x, y, width, height)
    W_Window window;
    int     x, y, width, height;
{
    Window  win = W_Void2Window(window)->window;
    register XRectangle *r;

    if (_rcache_index == MAXCACHE)
	FlushClearAreaCache(win);

    r = &_rcache[_rcache_index++];
    r->x = (short) x;
    r->y = (short) y;
    r->width = (unsigned short) width;
    r->height = (unsigned short) height;
}

void
W_FlushClearAreaCache(window)
    W_Window window;
{
    Window  win = W_Void2Window(window)->window;

    if (_rcache_index)
	FlushClearAreaCache(win);
}

/* XFIX: clears now instead of filling. */
void
W_ClearArea(window, x, y, width, height)
    W_Window window;
    int     x, y, width, height;
{
    struct window *win;

#ifdef DEBUG
    printf("Clearing (%d %d) x (%d %d) with %d on %d\n", x, y, width, height,
	   color, window);
#endif
    win = W_Void2Window(window);
    switch (win->type) {
    case WIN_GRAPH:
	/* XFIX: changed */
	XClearArea(W_Display, win->window, x, y, width, height, False);
	break;
    default:
	/* XFIX: changed */
	XClearArea(W_Display, win->window, WIN_EDGE + x * W_Textwidth,
		   MENU_PAD + y * W_Textheight, width * W_Textwidth, height * W_Textheight, False);
	break;
    }
}

void
W_ClearWindow(window)
    W_Window window;
{
#ifdef DEBUG
    printf("Clearing %d\n", window);
#endif
    XClearWindow(W_Display, W_Void2Window(window)->window);
}

void
W_GetEvent(wevent)
    W_Event *wevent;
{
/* blocks until an event is received [BDyess] */
    XEvent  event;

    if (W_isEvent) {
	*wevent = W_myevent;
	W_isEvent = 0;
	return;
    }
    XNextEvent(W_Display, &event);
    XPutBackEvent(W_Display, &event);
    W_SpNextEvent(wevent);
}

int
W_EventsPending()
{
    if (W_isEvent)
	return (1);
    while (XPending(W_Display) || buttonDown) {
	if (W_SpNextEvent(&W_myevent)) {
	    W_isEvent = 1;
	    return (1);
	}
    }
    return (0);
}

void
W_NextEvent(wevent)
    W_Event *wevent;
{
    if (W_isEvent) {
	*wevent = W_myevent;
	W_isEvent = 0;
	return;
    }
    while (W_SpNextEvent(wevent) == 0);
}

static int
W_SpNextEvent(wevent)
    W_Event *wevent;
{
    XEvent  event;
    XKeyEvent *key;
    XButtonEvent *button;
    XExposeEvent *expose;
    XResizeRequestEvent *resize;
    char    ch;
    struct window *win;
#ifdef CONTINUOUS_MOUSE
    static W_Event buttonEvent;
    static int delay, cupd = -1;
#endif				/* CONTINUOUS_MOUSE */

#ifdef DEBUG
    printf("Getting an event...\n");
#endif
    key = (XKeyEvent *) & event;
    button = (XButtonEvent *) & event;
    expose = (XExposeEvent *) & event;
    resize = (XResizeRequestEvent *) & event;
    for (;;) {
	if (XPending(W_Display))
	    XNextEvent(W_Display, &event);
#ifdef CONTINUOUS_MOUSE
	else if (buttonDown) {
	    if (continuousMouse && allowContinuousMouse) {
		if (cupd != udcounter) {
		    cupd = udcounter;
		    if (delay == 0) {
			bcopy(&buttonEvent, wevent, sizeof(W_Event));
			delay = clickDelay;
		    } else {
			delay--;
			wevent->type = -1;
		    }
		} else
		    wevent->type = -1;
		exitInputLoop = 1;
	    } else {
		wevent->type = -1;
		buttonDown = 0;
	    }
	    return (1);
	}
#endif
	else
	    return (0);
	/*
	   printf("read an event %d\n", event.type);
	*/
	win = findWindow(key->window);
	if (win == NULL)
	    return (0);
	if ((event.type == KeyPress || event.type == ButtonPress) &&
	    win->type == WIN_MENU) {
	    if (key->y % (W_Textheight + MENU_PAD * 2 + MENU_BAR) >=
		W_Textheight + MENU_PAD * 2)
		return (0);
	    key->y = key->y / (W_Textheight + MENU_PAD * 2 + MENU_BAR);
	}
	switch ((int) event.type) {
	case LeaveNotify:	/* for message window -- jfy */
	    if (win == (struct window *) messagew) {
		W_in_message = 0;
	    }
	    return (0);
	    break;
	case KeyPress:
	    if (key->state & ControlMask) {
		controlkey = 1;
		key->state &= ~ControlMask;
	    } else
		controlkey = 0;
	    if (key->state & BillsScrewyAltMask) {
		altkey = 1;
		key->state &= ~BillsScrewyAltMask;
	    } else
		altkey = 0;
	    if (XLookupString(key, &ch, 1, NULL, NULL) > 0) {
		wevent->type = W_EV_KEY;
		wevent->Window = W_Window2Void(win);
		wevent->x = key->x;
		wevent->y = key->y;
		if (controlkey)
		    wevent->key = (int) ch + 128;
		else if (altkey)
		    wevent->key = (int) ch + 256;
		else
		    wevent->key = ch;
		return (1);
	    }
	    return (0);
	    break;
#ifdef AUTOKEY
	case KeyRelease:
	    if (XLookupString(key, &ch, 1, NULL, NULL) > 0) {
		wevent->type = W_EV_KEY_OFF;
		wevent->Window = W_Window2Void(win);
		wevent->x = key->x;
		wevent->y = key->y;
		wevent->key = ch;
		return (1);
	    }
	    return (0);
	    break;
#endif				/* AUTOKEY */
	case ButtonPress:
	    wevent->type = W_EV_BUTTON;
	    wevent->Window = W_Window2Void(win);
	    wevent->x = button->x;
	    wevent->y = button->y;
	    switch (button->button & 0xf) {
	    case Button3:
		wevent->key = W_RBUTTON;
		break;
	    case Button1:
		wevent->key = W_LBUTTON;
		break;
	    case Button2:
		wevent->key = W_MBUTTON;
		break;
	    }
	    if (key->state & ControlMask)
		wevent->key += 6;
	    if (key->state & ShiftMask)
		wevent->key += 3;
	    if (key->state & BillsScrewyAltMask)
		wevent->key += 12;	/* alt */
#ifdef CONTINUOUS_MOUSE
	    if (continuousMouse && allowContinuousMouse &&
		(wevent->Window == w || wevent->Window == mapw) &&
	    /*
	       buttonRepeatMask allows only certain buttons to repeat
	       [BDyess]
	    */
		(1 << (wevent->key) & buttonRepeatMask)) {
		buttonDown = 1;
		exitInputLoop = 1;
		delay = clickDelay;
		bcopy(wevent, &buttonEvent, sizeof(W_Event));
	    }
	    return (1);
	case ButtonRelease:
	    /* bcopy(&buttonEvent,wevent,sizeof(W_Event)); */
	    wevent->type = -1;
	    buttonDown = 0;
	    return (1);
	case MotionNotify:
	    /*
	       the !buttonDown ensures that if you press a button and then
	       press another, release just the second, and then move the
	       mouse that nothing happens.
	    */
	    if (!(continuousMouse && allowContinuousMouse) || !buttonDown) {
		wevent->type = -1;
		return (1);
	    }
	    wevent->type = W_EV_BUTTON;
	    wevent->Window = W_Window2Void(win);
	    wevent->x = button->x;
	    wevent->y = button->y;
	    wevent->key = buttonEvent.key;
	    bcopy(wevent, &buttonEvent, sizeof(W_Event));
	    if (cupd == udcounter)
		wevent->type = -1;
	    else
		cupd = udcounter;

	    return (1);
#else
	    return (1);
#endif				/* CONTINUOUS_MOUSE */
	case Expose:
	    if (expose->count != 0)
		return (0);
	    if (win->type == WIN_SCROLL) {
		redrawScrolling(win);
		return (0);
	    }
	    if (win->type == WIN_MENU) {
		redrawMenu(win);
		return (0);
	    }
	    wevent->type = W_EV_EXPOSE;
	    wevent->Window = W_Window2Void(win);
	    return (1);
	case ResizeRequest:
	    resizeScrolling(win, resize->width, resize->height);
	    break;
	default:
	    return (0);
	    break;
	}
    }
}

void
W_MakeLine(window, x0, y0, x1, y1, color)
    W_Window window;
    int     x0, y0, x1, y1;
    W_Color color;
{
    Window  win;

#ifdef DEBUG
    printf("Line on %d\n", window);
#endif
    win = W_Void2Window(window)->window;
    XDrawLine(W_Display, win, colortable[color].contexts[0], x0, y0, x1, y1);
}

void
W_DrawPoint(window, x, y, color)
    W_Window window;
    int     x, y;
    W_Color color;
{
    Window  win;

#ifdef DEBUG
    printf("Point on %d\n", window);
#endif
    win = W_Void2Window(window)->window;
    XDrawPoint(W_Display, win, colortable[color].contexts[0], x, y);
}

/* XFIX */

static XSegment _lcache[NCOLORS][MAXCACHE];
static int _lcache_index[NCOLORS];

static void
FlushLineCache(win, color)
    Window  win;
    int     color;
{
    XDrawSegments(W_Display, win, colortable[color].contexts[0],
		  _lcache[color], _lcache_index[color]);
    _lcache_index[color] = 0;
}

/* for local window only */
void
W_CacheLine(window, x0, y0, x1, y1, color)
    W_Window window;
    int     x0, y0, x1, y1, color;
{
    Window  win = W_Void2Window(window)->window;
    register XSegment *s;

    if (_lcache_index[color] == MAXCACHE)
	FlushLineCache(win, color);

    s = &_lcache[color][_lcache_index[color]++];
    s->x1 = (short) x0;
    s->y1 = (short) y0;
    s->x2 = (short) x1;
    s->y2 = (short) y1;
}

void
W_FlushLineCaches(window)
    W_Window window;
{
    Window  win = W_Void2Window(window)->window;
    register i;
    for (i = 0; i < NCOLORS; i++) {
	if (_lcache_index[i])
	    FlushLineCache(win, i);
    }
}

static XPoint _pcache[NCOLORS][MAXCACHE];
static int _pcache_index[NCOLORS];

static void
FlushPointCache(win, color)
    Window  win;
    int     color;
{
    XDrawPoints(W_Display, win, colortable[color].contexts[0],
		_pcache[color], _pcache_index[color], CoordModeOrigin);
    _pcache_index[color] = 0;
}

void
W_CachePoint(window, x, y, color)
    W_Window window;
    int     x, y, color;
{
    Window  win = W_Void2Window(window)->window;
    register XPoint *p;

    if (_pcache_index[color] == MAXCACHE)
	FlushPointCache(win, color);

    p = &_pcache[color][_pcache_index[color]++];
    p->x = (short) x;
    p->y = (short) y;
}

void
W_FlushPointCaches(window)
    W_Window window;
{
    Window  win = W_Void2Window(window)->window;
    register i;
    for (i = 0; i < NCOLORS; i++) {
	if (_pcache_index[i])
	    FlushPointCache(win, i);
    }
}

void
W_MakeTractLine(window, x0, y0, x1, y1, color)
    W_Window window;
    int     x0, y0, x1, y1;
    W_Color color;
{
    Window  win;

#ifdef DEBUG
    printf("Line on %d\n", window);
#endif
    win = W_Void2Window(window)->window;
    XDrawLine(W_Display, win, colortable[color].contexts[3], x0, y0, x1, y1);
}

void
W_DrawSectorHighlight(window, x, y, w, h, color)
    W_Window window;
    int     x, y, w, h;
    W_Color color;
{
    Window  win;
#ifdef YUCK
    XRectangle r[2];

    r[0].x = (short) x;
    r[0].y = (short) y;
    r[0].width = (unsigned short) w;
    r[0].height = (unsigned short) h;
    r[1].x = (short) x + 2;
    r[1].y = (short) y + 2;
    r[1].width = (unsigned short) w - 4;
    r[1].height = (unsigned short) h - 4;

    win = W_Void2Window(window)->window;
    XDrawRectangles(W_Display, win, colortable[color].contexts[3],
		    r, 2);
#else
    XRectangle r[1];

    r[0].x = (short) x + 2;
    r[0].y = (short) y + 2;
    r[0].width = (unsigned short) w - 4;
    r[0].height = (unsigned short) h - 4;

    win = W_Void2Window(window)->window;
    XDrawRectangles(W_Display, win, colortable[color].contexts[3],
		    r, 1);
#endif
}

void
W_WriteTriangle(window, x, y, s, t, color)
    W_Window window;
    int     x, y, s;
    int     t;
    W_Color color;
{
    struct window *win = W_Void2Window(window);
    XPoint  points[3];

    if (t == 0) {
	points[0].x = x;
	points[0].y = y;
	points[1].x = x + s;
	points[1].y = y - s;
	points[2].x = x - s;
	points[2].y = y - s;
    } else {
	points[0].x = x;
	points[0].y = y;
	points[1].x = x + s;
	points[1].y = y + s;
	points[2].x = x - s;
	points[2].y = y + s;
    }


    XFillPolygon(W_Display, win->window, colortable[color].contexts[0],
		 points, 3, Convex, CoordModeOrigin);
}

void
W_WriteText(window, x, y, color, str, len, font)
    W_Window window;
    int     x, y, len;
    W_Color color;
    W_Font  font;
    char   *str;
{
    struct window *win;
    int     addr;

    if (!font)
	font = W_RegularFont;
#ifdef DEBUG
    printf("Text for %d @ (%d, %d) in %d: [%s]\n", window, x, y, color, str);
#endif
    win = W_Void2Window(window);
    switch (win->type) {
    case WIN_GRAPH:
	addr = fonts[fontNum(font)].baseline;
	XDrawImageString(W_Display, win->window,
	  colortable[color].contexts[fontNum(font)], x, y + addr, str, len);
	break;
    case WIN_SCROLL:
	if (y<0) {
	  XCopyArea(W_Display, win->window, win->window,

		    colortable[W_White].contexts[0], WIN_EDGE, MENU_PAD,
		    win->width * W_Textwidth, (win->height - 1) * W_Textheight,
		    WIN_EDGE, MENU_PAD+W_Textheight);
	  XClearArea(W_Display, win->window,
		     WIN_EDGE, MENU_PAD,
		     W_Textwidth * win->width, W_Textheight, False);
	  XDrawImageString(W_Display, win->window,
			   colortable[color].contexts[1],
			   WIN_EDGE, MENU_PAD + fonts[1].baseline,
			   str, len);
	} else {
	  XCopyArea(W_Display, win->window, win->window,
		    colortable[W_White].contexts[0], WIN_EDGE, MENU_PAD + W_Textheight,
		    win->width * W_Textwidth, (win->height - 1) * W_Textheight,
		    WIN_EDGE, MENU_PAD);
	  XClearArea(W_Display, win->window,
		     WIN_EDGE, MENU_PAD + W_Textheight * (win->height - 1),
		     W_Textwidth * win->width, W_Textheight, False);
	  XDrawImageString(W_Display, win->window,
			   colortable[color].contexts[1],
			   WIN_EDGE, MENU_PAD + W_Textheight * (win->height - 1) + fonts[1].baseline,
			   str, len);
	}
	AddToScrolling(win, color, str, len);
	break;
    case WIN_MENU:
	changeMenuItem(win, y, color, str, len, font);
	break;
    default:
	addr = fonts[fontNum(font)].baseline;
	XDrawImageString(W_Display, win->window,
			 colortable[color].contexts[fontNum(font)],
	     x * W_Textwidth + WIN_EDGE, MENU_PAD + y * W_Textheight + addr,
			 str, len);
	break;
    }
}

void
W_MaskText(window, x, y, color, str, len, font)
    W_Window window;
    int     x, y, len;
    W_Color color;
    W_Font  font;
    char   *str;
{
    struct window *win;
    int     addr;

    addr = fonts[fontNum(font)].baseline;
#ifdef DEBUG
    printf("TextMask for %d @ (%d, %d) in %d: [%s]\n", window, x, y, color, str);
#endif
    win = W_Void2Window(window);
    XDrawString(W_Display, win->window,
	  colortable[color].contexts[fontNum(font)], x, y + addr, str, len);
}

W_Icon
W_StoreBitmap(width, height, data, window)
    int     width, height;
    W_Window window;
    char   *data;
{
    struct icon *newicon;
    struct window *win;

#ifdef DEBUG
    printf("Storing bitmap for %d (%d x %d)\n", window, width, height);
    fflush(stdout);
#endif
    win = W_Void2Window(window);
    newicon = (struct icon *) malloc(sizeof(struct icon));
    newicon->width = width;
    newicon->height = height;
    newicon->bitmap = XCreateBitmapFromData(W_Display, win->window,
					    data, width, height);
    newicon->window = win->window;
    newicon->pixmap = 0;
    return (W_Icon2Void(newicon));
}

void
W_FreeBitmap(bit)
    W_Icon  bit;
{
    struct icon *icon;
    icon = W_Void2Icon(bit);
    XFreePixmap(W_Display, icon->bitmap);
    free(icon);
}

void
W_WriteBitmap(x, y, bit, color)
    int     x, y;
    W_Icon  bit;
    W_Color color;
{
    struct icon *icon;

    icon = W_Void2Icon(bit);
#ifdef DEBUG
    printf("Writing bitmap to %d\n", icon->window);
#endif

    XCopyPlane(W_Display, icon->bitmap, icon->window,
	 colortable[color].contexts[BITGC], 0, 0, icon->width, icon->height,
	       x, y, 1);

}

void
W_WriteWinBitmap(win, x, y, bit, color)
    W_Window win;
    int     x, y;
    W_Icon  bit;
    W_Color color;
{
    struct icon *icon;
    Window  original;

    icon = W_Void2Icon(bit);
    original = icon->window;
    icon->window = W_Void2Window(win)->window;
    W_WriteBitmap(x, y, bit, color);
    icon->window = original;
    return;
}

void
W_TileWindow(window, bit)
    W_Window window;
    W_Icon  bit;
{
    Window  win;
    struct icon *icon;

#ifdef DEBUG
    printf("Tiling window %d\n", window);
#endif
    icon = W_Void2Icon(bit);
    win = W_Void2Window(window)->window;

    if (icon->pixmap == 0) {
	icon->pixmap = XCreatePixmap(W_Display, W_Root,
	      icon->width, icon->height, DefaultDepth(W_Display, W_Screen));
	XCopyPlane(W_Display, icon->bitmap, icon->pixmap,
	   colortable[W_White].contexts[0], 0, 0, icon->width, icon->height,
		   0, 0, 1);
    }
    XSetWindowBackgroundPixmap(W_Display, win, icon->pixmap);
    XClearWindow(W_Display, win);

    /*
       if (icon->pixmap==0) { icon->pixmap=XMakePixmap(icon->bitmap,
       colortable[W_White].pixelValue, colortable[W_Black].pixelValue); }
       XChangeBackground(win, icon->pixmap); XClear(win);
    */
}

void
W_UnTileWindow(window)
    W_Window window;
{
    Window  win;

#ifdef DEBUG
    printf("Untiling window %d\n", window);
#endif
    win = W_Void2Window(window)->window;

    XSetWindowBackground(W_Display, win, colortable[W_Black].pixelValue);
    XClearWindow(W_Display, win);
}

W_Window
W_MakeTextWindow(name, x, y, width, height, parent, cursname, border)
    char   *name;
    int     x, y, width, height;
    W_Window parent;
    char   *cursname;
    int     border;
{
    return w_MakeWindow(name, x, y, width, height,
			parent, cursname, border, W_White, WIN_TEXT);
}

struct window *
newWindow(window, type)
    Window  window;
    int     type;
{
    struct window *newwin;

    newwin = (struct window *) malloc(sizeof(struct window));
    newwin->window = window;
    newwin->type = type;
    newwin->mapped = 0;
    newwin->insensitive = 0;
    addToHash(newwin);
    return (newwin);
}


static struct window *
findWindow(window)
    Window  window;
{
    struct windowlist *entry;

    entry = hashtable[hash(window)];
    while (entry != NULL) {
	if (entry->window->window == window)
	    return (entry->window);
	entry = entry->next;
    }
    return (NULL);
}

static void
addToHash(win)
    struct window *win;
{
    struct windowlist **new;

#ifdef DEBUG
    printf("Adding to %d\n", hash(win->window));
#endif
    new = &hashtable[hash(win->window)];
    while (*new != NULL) {
	new = &((*new)->next);
    }
    *new = (struct windowlist *) malloc(sizeof(struct windowlist));
    (*new)->next = NULL;
    (*new)->window = win;
}

W_Window
W_MakeScrollingWindow(name, x, y, width, height, parent, cursname, border)
    char   *name;
    int     x, y, width, height;
    W_Window parent;
    char   *cursname;
    int     border;
{
    return w_MakeWindow(name, x, y, width, height, parent, cursname,
			border, W_White, WIN_SCROLL);
}

/* Add a string to the string list of the scrolling window.
 */
static void
AddToScrolling(win, color, str, len)
    struct window *win;
    W_Color color;
    char   *str;
    int     len;
{
    struct stringList **strings;
    char   *newstring;
    int     count;

    strings = (struct stringList **) & (win->data);
    count = 0;
    while ((*strings) != NULL) {
	count++;
	strings = &((*strings)->next);
    }
    (*strings) = (struct stringList *) malloc(sizeof(struct stringList));
    (*strings)->next = NULL;
    (*strings)->color = color;
    newstring = (char *) malloc(len + 1);
    strncpy(newstring, str, len);
    newstring[len] = 0;
    (*strings)->string = newstring;
    if (count >= 100) {		/* Arbitrary large size. */
	struct stringList *temp;

	temp = (struct stringList *) win->data;
	free(temp->string);
	temp = temp->next;
	free((char *) win->data);
	win->data = (char *) temp;
    }
}

#ifdef SHORT_PACKETS
void
W_SetSensitive(w, v)
    W_Window w;
    int     v;
{
    struct window *win = W_Void2Window(w);

    win->insensitive = !v;

    if (win->type == WIN_SCROLL)
	redrawScrolling(win);
}
#endif

static void
redrawScrolling(win)
    struct window *win;
{
    int     count;
    struct stringList *list;
    int     y;

    XClearWindow(W_Display, win->window);
    count = 0;
    list = (struct stringList *) win->data;
    while (list != NULL) {
	list = list->next;
	count++;
    }
    list = (struct stringList *) win->data;
    while (count > win->height) {
	list = list->next;
	count--;
    }
    y = (win->height - count) * W_Textheight + fonts[1].baseline;
    if (count == 0)
	return;
    while (list != NULL) {
	XDrawImageString(W_Display, win->window,
			 colortable[list->color].contexts[1],
		WIN_EDGE, MENU_PAD + y, list->string, strlen(list->string));
	list = list->next;
	y = y + W_Textheight;
    }
}

static void
resizeScrolling(win, width, height)
    struct window *win;
    int     width, height;
{
    win->height = (height - MENU_PAD * 2) / W_Textheight;
    win->width = (width - WIN_EDGE * 2) / W_Textwidth;
    XResizeWindow(W_Display, win->window, win->width * W_Textwidth + WIN_EDGE * 2,
		  win->height * W_Textheight + MENU_PAD * 2);
}

W_Window
W_MakeMenu(name, x, y, width, height, parent, border)
    char   *name;
    int     x, y, width, height;
    W_Window parent;
    int     border;
{
    return w_MakeWindow(name, x, y, width, height, parent,
			"left_ptr", border, W_White, WIN_MENU);
}

static void
redrawMenu(win)
    struct window *win;
{
    int     count;

    for (count = 1; count < win->height; count++) {
	XFillRectangle(W_Display, win->window,
		       colortable[W_Grey].contexts[0],
	  0, count * (W_Textheight + MENU_PAD * 2) + (count - 1) * MENU_BAR,
		       win->width * W_Textwidth + WIN_EDGE * 2, MENU_BAR);
    }
    for (count = 0; count < win->height; count++) {
	redrawMenuItem(win, count);
    }
}

static void
redrawMenuItem(win, n)
    struct window *win;
    int     n;
{
    struct menuItem *items;
    int     addr;

    items = (struct menuItem *) win->data;

    XFillRectangle(W_Display, win->window,
		   colortable[W_Black].contexts[0],
	  WIN_EDGE, n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD,
		   win->width * W_Textwidth, W_Textheight);
    if (items[n].string) {
	addr = fonts[fontNum(items[n].font)].baseline;
	XDrawImageString(W_Display, win->window,
		colortable[items[n].color].contexts[fontNum(items[n].font)],
			 WIN_EDGE,
	     n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD + addr,
			 items[n].string, strlen(items[n].string));
    }
}

static void
changeMenuItem(win, n, color, str, len, font)
    struct window *win;
    int     n;
    W_Color color;
    char   *str;
    int     len;
    W_Font  font;
{
    struct menuItem *items;
    char   *news;

    items = (struct menuItem *) win->data;
    if (items[n].string) {
	free(items[n].string);
    }
    news = malloc(len + 1);
    strncpy(news, str, len);
    news[len] = 0;
    items[n].string = news;
    items[n].color = color;
    items[n].font = font;
    redrawMenuItem(win, n);
    XFlush(W_Display);
}

static  Cursor
make_cursor(bits, mask, width, height, xhot, yhot)
    char   *bits, *mask;
    int     width, height, xhot, yhot;
{
    Pixmap  cursbits;
    Pixmap  cursmask;
    XColor  whiteCol, blackCol;
    Cursor  curs;

    whiteCol.pixel = colortable[W_White].pixelValue;
    XQueryColor(W_Display, W_Colormap, &whiteCol);
    blackCol.pixel = colortable[W_Black].pixelValue;
    XQueryColor(W_Display, W_Colormap, &blackCol);

    cursbits = XCreateBitmapFromData(W_Display, DefaultRootWindow(W_Display),
				     bits, width, height);
    cursmask = XCreateBitmapFromData(W_Display, DefaultRootWindow(W_Display),
				     mask, width, height);

    curs = XCreatePixmapCursor(W_Display, cursbits, cursmask,
			       &whiteCol, &blackCol, xhot, yhot);

    XFreePixmap(W_Display, cursbits);
    XFreePixmap(W_Display, cursmask);
    return curs;
}

#ifdef TCURSORS
#if 1

void
W_DefineTCrossCursor(window)
    W_Window window;
{
    return;
}

void
W_DefineTextCursor(window)
    W_Window window;
{
    static Cursor new = 0;
    struct window *win = W_Void2Window(window);
    XColor  f, b;

    if (!new) {
	f.pixel = colortable[W_Yellow].pixelValue;
	b.pixel = colortable[W_Black].pixelValue;

	XQueryColor(W_Display, W_Colormap, &f);
	XQueryColor(W_Display, W_Colormap, &b);

	new = XCreateFontCursor(W_Display, XC_xterm);

	XRecolorCursor(W_Display, new, &f, &b);
    }
    XDefineCursor(W_Display, win->window, new);

    return;
}

void
W_RevertCursor(window)
    W_Window window;
{
    struct window *win = W_Void2Window(window);

    XDefineCursor(W_Display, win->window, win->cursor);

    return;
}

void
W_DefineCursor(window, width, height, bits, mask, xhot, yhot)
    W_Window window;
    int     width, height, xhot, yhot;
    char   *bits, *mask;
{
    return;
}

#else

#ifdef YUCK
void
W_DefineTCrossCursor(window)
    W_Window window;
{
    static
    Cursor  new;
    struct window *win = W_Void2Window(window);
    static
    XColor  f, b;

    if (new) {
	XDefineCursor(W_Display, win->window, new);
	return;
    }
    f.pixel = colortable[W_White].pixelValue;
    b.pixel = colortable[W_Black].pixelValue;

    XQueryColor(W_Display, W_Colormap, &f);
    XQueryColor(W_Display, W_Colormap, &b);

    new = XCreateFontCursor(W_Display, XC_tcross);
    XRecolorCursor(W_Display, new, &f, &b);
    XDefineCursor(W_Display, win->window, new);
}

#else
W_DefineTCrossCursor(window)
    W_Window window;
{
    W_DefineCursor(window, cross_width, cross_height,
		   cross_bits, crossmask_bits, cross_x_hot, cross_y_hot);
}

#endif

void
W_DefineTextCursor(window)
    W_Window window;
{
    static
    Cursor  new;
    struct window *win = W_Void2Window(window);
    XColor  f, b;

    if (new) {
	XDefineCursor(W_Display, win->window, new);
	return;
    }
    f.pixel = colortable[W_Yellow].pixelValue;
    b.pixel = colortable[W_Black].pixelValue;

    XQueryColor(W_Display, W_Colormap, &f);
    XQueryColor(W_Display, W_Colormap, &b);

    new = XCreateFontCursor(W_Display, XC_xterm);
    XRecolorCursor(W_Display, new, &f, &b);
    XDefineCursor(W_Display, win->window, new);
}

void
W_DefineCursor(window, width, height, bits, mask, xhot, yhot)
    W_Window window;
    int     width, height, xhot, yhot;
    char   *bits, *mask;
{
    static char *oldbits = NULL;
    static Cursor curs;
    struct window *win;

#ifdef DEBUG
    printf("Defining cursor for %d\n", window);
#endif
    win = W_Void2Window(window);
    if (!oldbits || oldbits != bits) {
	oldbits = bits;
	curs = make_cursor(bits, mask, width, height, xhot, yhot);
    }
    XDefineCursor(W_Display, win->window, curs);
}
#endif
#endif

void
W_Beep()
{
    XBell(W_Display, 0);
}

int
W_WindowWidth(window)
    W_Window window;
{
    return (W_Void2Window(window)->width);
}

int
W_WindowHeight(window)
    W_Window window;
{
    return (W_Void2Window(window)->height);
}

int
W_Socket()
{
    return (ConnectionNumber(W_Display));
}

void
W_DestroyWindow(window)
    W_Window window;
{
    struct window *win;

#ifdef DEBUG
    printf("Destroying %d\n", window);
#endif
    win = W_Void2Window(window);
    deleteWindow(win);
    XDestroyWindow(W_Display, win->window);
    free((char *) win);
}

static void
deleteWindow(window)
    struct window *window;
{
    struct windowlist **rm;
    struct windowlist *temp;

    rm = &hashtable[hash(window->window)];
    while (*rm != NULL && (*rm)->window != window) {
	rm = &((*rm)->next);
    }
    if (*rm == NULL) {
	printf("Attempt to delete non-existent window!\n");
	return;
    }
    temp = *rm;
    *rm = temp->next;
    free((char *) temp);
}

void
W_SetIconWindow(main, icon)
    W_Window main;
    W_Window icon;
{
    XWMHints hints;

    XSetIconName(W_Display, W_Void2Window(icon)->window, W_Void2Window(main)->name);

    hints.flags = IconWindowHint;
    hints.icon_window = W_Void2Window(icon)->window;
    XSetWMHints(W_Display, W_Void2Window(main)->window, &hints);
}

static void
checkGeometry(name, x, y, width, height)
    char   *name;
    int    *x, *y, *width, *height;
/* fixed so that it handles negative positions 12/21/93          */
/* note that this is NOT standard X syntax, but it was requested */
/* and it's how BRM-Hadley works.                       [BDyess] */
{
    char   *adefault;
    char    buf[100];
    char   *s;

#ifdef RJC
    *x = *y = INVALID_POSITION;
#endif				/* RJC */

    sprintf(buf, "%s.geometry", name);
    adefault = getdefault(buf);
    if (adefault == NULL)
	return;
    /* geometry should be of the form 502x885+1+1, 502x885, or +1+1 */
    s = adefault;
    if (*s != '+' && *s != '-') {
	while (*s != 'x' && *s != 0)
	    s++;
	*width = atoi(adefault);
	if (*s == 0)
	    return;
	s++;
	adefault = s;
	while (*s != '+' && *s != '-' && *s != 0)
	    s++;
	*height = atoi(adefault);
	if (*s == 0)
	    return;
    }
    adefault = s;
    s++;
    if (*s == '-')
	s++;			/* for the case where they have wxh+-x+y */
    while (*s != '+' && *s != '-' && *s != 0)
	s++;
    *x = atoi(adefault + 1);
    if (*adefault == '-')
	*x = -*x;
    if (*s == 0)
	return;
    *y = atoi(s + 1);
    if (*s == '-')
	*y = -*y;
    /* printf("width: %d, height: %d, x: %d, y: %d\n",*width, *height,*x,*y); */
    return;
}

static void
checkParent(name, parent)
    char   *name;
    W_Window *parent;
{
    char   *adefault;
    char    buf[100];
    int     i;
    struct windowlist *windows;

    sprintf(buf, "%s.parent", name);
    adefault = getdefault(buf);
    if (adefault == NULL)
	return;
    /* parent must be name of other window or "root" */
    if (strcmpi(adefault, "root") == 0) {
	*parent = W_Window2Void(&myroot);
	return;
    }
    for (i = 0; i < HASHSIZE; i++) {
	windows = hashtable[i];
	while (windows != NULL) {
	    if (strcmpi(adefault, windows->window->name) == 0) {
		*parent = W_Window2Void(windows->window);
		return;
	    }
	    windows = windows->next;
	}
    }
}

#ifdef YUCK
#define cross_width 15
#define cross_height 15
#define cross_x_hot 7
#define cross_y_hot 7
static unsigned char cross_bits[] = {
    0x00, 0x00, 0xc0, 0x01, 0xa0, 0x02, 0x00, 0x00, 0x80, 0x00, 0x04, 0x10, 0x82, 0x20, 0x56,
0x35, 0x82, 0x20, 0x04, 0x10, 0x80, 0x00, 0x00, 0x00, 0xa0, 0x02, 0xc0, 0x01, 0x00, 0x00};
static unsigned char crossmask_bits[] = {
    0xe0, 0x03, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xce, 0x39, 0xcf, 0x79, 0xff, 0x7f, 0xff,
0x7f, 0xff, 0x7f, 0xcf, 0x79, 0xce, 0x39, 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xe0, 0x03};
#else
#define cross_width 16
#define cross_height 16
#define cross_x_hot 7
#define cross_y_hot 7
static unsigned char cross_bits[] = {
    0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, 0x01, 0x80, 0x00,
    0x10, 0x04, 0x3f, 0x7e, 0x10, 0x04, 0x80, 0x00, 0xc0, 0x01, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00};
static unsigned char crossmask_bits[] = {
    0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xd0, 0x05,
    0xbf, 0x7e, 0x7f, 0x7f, 0xbf, 0x7e, 0xd0, 0x05, 0xe0, 0x03, 0xc0, 0x01,
0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00};
#endif

static void
checkCursor(name, cursname, cursor)
    char   *name;
    char   *cursname;
    Cursor *cursor;
{
    char    buf[100];
    unsigned cnum;
    char   *adefault;

    *cursor = 0;

    sprintf(buf, "%s.cursor", name);
    adefault = getdefault(buf);
    if (adefault == NULL)
	adefault = cursname;
    if (adefault == NULL)
	return;

#ifdef RFCURSORS
    cnum = XmuCursorNameToIndex(adefault);
    if (cnum != -1) {
	XColor  f, b;
	*cursor = XCreateFontCursor(W_Display, cnum);
	if (cnum == XC_xterm) {

	    f.pixel = colortable[W_Yellow].pixelValue;
	    b.pixel = colortable[W_Black].pixelValue;

	    XQueryColor(W_Display, W_Colormap, &f);
	    XQueryColor(W_Display, W_Colormap, &b);

	    XRecolorCursor(W_Display, *cursor, &f, &b);
	} else if (cnum == XC_pirate) {
	    f.pixel = colortable[W_Red].pixelValue;
	    b.pixel = colortable[W_Black].pixelValue;

	    XQueryColor(W_Display, W_Colormap, &f);
	    XQueryColor(W_Display, W_Colormap, &b);

	    XRecolorCursor(W_Display, *cursor, &f, &b);
	}
    } else
#endif
    if (0 == strcmp("bomb here", adefault)) {
	static Cursor bomb_here = 0;
	if (bomb_here == 0) {
	    bomb_here = make_cursor(cross_bits, crossmask_bits,
				    cross_width, cross_height,
				    cross_x_hot, cross_y_hot);
	}
	*cursor = bomb_here;
    }
}

int
checkMapped(name)
    char   *name;
{
    char    buf[100];

    sprintf(buf, "%s.mapped", name);
    return (booleanDefault(buf, 0));
}

void
W_WarpPointer(window, x, y)
    W_Window window;
    int     x, y;
{
    static int warped_from_x = 0, warped_from_y = 0;

    if (window == NULL) {
	if (W_in_message) {
	    XWarpPointer(W_Display, None, W_Root, 0, 0, 0, 0, warped_from_x, warped_from_y);
	    W_in_message = 0;
	}
    } else {
	findMouse(&warped_from_x, &warped_from_y);
	XWarpPointer(W_Display, None, W_Void2Window(window)->window, 0, 0, 0, 0, 0, 0);
	W_in_message = 1;
    }
}

static void
findMouse(x, y)
    int    *x, *y;
{
    Window  theRoot, theChild;
    int     wX, wY, rootX, rootY, status;
    unsigned int wButtons;

    status = XQueryPointer(W_Display, W_Root, &theRoot, &theChild, &rootX, &rootY, &wX, &wY, &wButtons);
    if (status == True) {
	*x = wX;
	*y = wY;
    } else {
	*x = 0;
	*y = 0;
    }
}

int
findMouseInWin(x, y, w)
    int    *x, *y;
    W_Window w;
{
    Window  theRoot, theChild;
    int     wX, wY, rootX, rootY, status;
    unsigned int wButtons;
    struct window *win = W_Void2Window(w);
    Window  thisWin = win->window;

    status = XQueryPointer(W_Display, thisWin, &theRoot, &theChild,
			   &rootX, &rootY, &wX, &wY, &wButtons);
    if (status == True) {
	/*
	   if it's in the window we specified then the values returned should
	   be within the with and height of the window
	*/
	if (wX <= win->width && wY <= win->height) {
	    *x = wX;
	    *y = wY;
	    return 1;
	}
    }
    *x = 0;
    *y = 0;
    return 0;
}

#ifdef AUTOKEY
static void
W_Flush()
{
    XFlush(W_Display);
}

W_AutoRepeatOff()
{
    XAutoRepeatOff(W_Display);
    W_Flush();
}

W_AutoRepeatOn()
{
    XAutoRepeatOn(W_Display);
    W_Flush();
}
#endif				/* AUTOKEY */

/* find the width of a font */
int
W_StringWidth(string, font)
    char    string[];
    W_Font  font;
{
    int     x, y;

    y = strlen(string);
    x = XTextWidth(fonts[fontNum(font)].fontstruct, string, y);
    return (x);			/* just a guess ?? old never returned! WHS
				   4/6/93 */
}

void
W_TranslatePoints(w, x, y)
    int    *x, *y;
    W_Window w;
{
    struct window *win;
    win = W_Void2Window(w);

    if (win->type == WIN_TEXT) {
	*y = (*y - MENU_PAD) / W_Textheight;
	*x = (*x - MENU_PAD) / W_Textwidth;
    }
    return;
}

#if 0
#define MAKE_WINDOW_GETTER(name, part) \
  W_Callback name(w) \
       W_Window w; \
 { \
     return W_Void2Window(w)->part; \
 }

#define MAKE_WINDOW_SETTER(name, port) \
   W_Callback name(w, c) \
      W_Window w; \
      W_Callback c; \
   { \
      W_Void2Window(w)->port = c; \
   }

MAKE_WINDOW_GETTER(W_GetWindowKeyDownHandler, handle_keydown);
MAKE_WINDOW_SETTER(W_SetWindowKeyDownHandler, handle_keydown);

MAKE_WINDOW_GETTER(W_GetWindowKeyUpHandler, handle_keyup);
MAKE_WINDOW_SETTER(W_SetWindowKeyUpHandler, handle_keyup);

MAKE_WINDOW_GETTER(W_GetWindowButtonHandler, handle_button);
MAKE_WINDOW_SETTER(W_SetWindowButtonHandler, handle_button);

MAKE_WINDOW_GETTER(W_GetWindowExposeHandler, handle_expose);
MAKE_WINDOW_SETTER(W_SetWindowExposeHandler, handle_expose);
#endif				/* 0 */

void
W_ResizeWindow(window, neww, newh)	/* TSH 2/93 */
    W_Window window;
    int     neww, newh;
{
    Window  win = W_Void2Window(window)->window;

    XResizeWindow(W_Display, win, (unsigned int) neww, (unsigned int) newh);
}

void
W_ResizeMenu(window, neww, newh)/* TSH 2/93 */
    W_Window window;
    int     neww, newh;
{
    W_ResizeWindow(window, neww * W_Textwidth + WIN_EDGE * 2,
	      newh * (W_Textheight + MENU_PAD * 2) + (newh - 1) * MENU_BAR);
}

void
W_ResizeText(window, neww, newh)/* TSH 2/93 */
    W_Window window;
    int     neww, newh;
{
    W_ResizeWindow(window, neww * W_Textwidth + WIN_EDGE * 2,
		   newh * W_Textheight + MENU_PAD * 2);
}

void
W_Deiconify(window)
    W_Window window;
{
    struct window *win;
    win = W_Void2Window(window);
    /* according to ICCCM 4.1.4, this is how you deiconify a window. */
    XMapWindow(W_Display, win->window);
}

W_Icon
W_MakeShieldBitmap(width, height, window)
    int     width, height;
    W_Window window;
{
    static GC pen = 0;
    struct window *win;
    struct icon *newicon;

    win = W_Void2Window(window);

    newicon = (struct icon *) malloc(sizeof(struct icon));
    newicon->width = width;
    newicon->height = height;
    newicon->bitmap = XCreatePixmap(W_Display, win->window, width, height, 1);
    newicon->window = win->window;
    newicon->pixmap = 0;

    pen = XCreateGC(W_Display, newicon->bitmap, 0L, 0);
    XSetForeground(W_Display, pen, 0L);
    XFillRectangle(W_Display, newicon->bitmap, pen, 0, 0, width, height);
    XSetForeground(W_Display, pen, 1L);
    XDrawArc(W_Display, newicon->bitmap, pen, 0, 0, width - 1, height - 1, 0, 360 * 64);
    XFreeGC(W_Display, pen);

    return W_Icon2Void(newicon);
}

#ifdef BEEPLITE
void 
W_OverlayBitmap(x, y, bit, color)
    int     x, y;
    W_Icon  bit;
    W_Color color;
{
    struct icon *icon = W_Void2Icon(bit);
#ifdef DEBUG
    printf("Overlaying bitmap to %d\n", icon->window);
#endif
    XCopyPlane(W_Display, icon->bitmap, icon->window,
	     colortable[color].contexts[0], 0, 0, icon->width, icon->height,
	       x, y, 1);
}
#endif