Mercurial > ~darius > hgwebdir.cgi > paradise_client
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x11window.c Sat Dec 06 05:41:29 1997 +0000 @@ -0,0 +1,2532 @@ +/* $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