/*
 * di_redraw.c
 */

#ifdef  X11_DISP

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "corewar.h"
#include "cwdisp.h"


gbut_info  di_but[DI_NBUT] = {
	{0,0,0,0,0, GBUT_DRAWABLE, ":0: :\n:",
		 di_draw_ctbut, gbut_true, (void *)"Step"},      /* DI_BSTOP */
	{0,0,0,0,0, GBUT_DRAWABLE, ":1:2:3:4:5:6:7:8:",
		 di_draw_sfbut, gbut_true, (void *)&di_slopos},  /* DI_BSLOW */
	{0,0,0,0,0, GBUT_DRAWABLE, ":9:",
		 di_draw_ctbut, gbut_true, (void *)"Go"},        /* DI_BGO   */
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":q:Q:",
		 di_draw_ctbut, gbut_true, (void *)"Quit"},      /* DI_BQUIT */
	{0,0,0,0,0, GBUT_DRAWABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Reset"},     /* DI_BRESTART */
	{0,0,0,0,0, 0, ":\n:",
		 di_draw_ctbut, gbut_true, (void *)"OK"},        /* DI_BWIN2OK */
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE|GBUT_TWITCHABLE, ":",
		 di_dis_cpdraw, di_dis_cpcheck, NULL},           /* DI_BCOREPIC */

	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"},
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"},
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"},
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"},
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"},
	{0,0,0,0,0, GBUT_DRAWABLE|GBUT_PRESSABLE, ":",
		 di_draw_ctbut, gbut_true, (void *)"Load"}};
	
static char  *backup_sfonts[] = {
	"-adobe-times-medium-r-normal--8-*",
	"-adobe-times-medium-r-normal--8-*",
	"-adobe-times-medium-r-normal--8-*",
	"-adobe-times-medium-r-normal--10-*",
	"-adobe-times-medium-r-normal--12-*",
	"-adobe-times-medium-r-normal--14-*",
	"-adobe-times-medium-r-normal--20-*",
	"-adobe-times-medium-r-normal--20-*",
	"-adobe-times-medium-r-normal--25-*"};
static char  *backup_ffonts[] = {
	"-adobe-courier-medium-r-normal--8-*",
	"-adobe-courier-medium-r-normal--8-*",
	"-adobe-courier-medium-r-normal--8-*",
	"-adobe-courier-medium-r-normal--10-*",
	"-adobe-courier-medium-r-normal--12-*",
	"-adobe-courier-medium-r-normal--14-*",
	"-adobe-courier-medium-r-normal--20-*",
	"-adobe-courier-medium-r-normal--20-*",
	"-adobe-courier-medium-r-normal--25-*"};
static char  *backup_bfonts[] = {
	"-adobe-times-medium-r-normal--8-*",
	"-adobe-times-medium-r-normal--8-*",
	"-adobe-times-medium-r-normal--14-*",
	"-adobe-times-medium-r-normal--20-*",
	"-adobe-times-medium-r-normal--25-*",
	"-adobe-times-medium-r-normal--34-*"};



static int  recalc_ov(Display *dpy, Window win, XWindowAttributes *xwa);
static void  recalc_co(Display *dpy, Window win, int remap);
static void  recalc_pls(Display *dpy, Window win, int remap);
static void  recalc_ti(Display *dpy, Window win, int remap);
static void  recalc_cy(Display *dpy, Window win, int remap);
static void  draw_bitmap(int oc, int ic, unsigned picsize, char *pics);
static void  recalc_but(Display *dpy, Window win, int remap);

unsigned long  di_colors[4+DI_MAXPLAYERS*2];
static int  cyth, butth, titth, emptyslot;
Pixmap  di_grey50pixmap, di_grey75pixmap;

void  di_redraw(Display *dpy, Window win, XWindowAttributes *xwa,
								int x, int y, int w, int h)  {
	int  size_change = FALSE;

	if ((xwa->width < 150) || (xwa->height < 125))
		return;
	if ((di_winw != xwa->width) || (di_winh != xwa->height))  {
		/* Recalculate values. */
		int  remap;

		size_change = TRUE;
		remap = recalc_ov(dpy, win, xwa);
		recalc_co(dpy, win, remap);
		recalc_pls(dpy, win, remap);
		recalc_ti(dpy, win, remap);
		recalc_cy(dpy, win, remap);
		recalc_but(dpy, win, remap);
		if (remap)  {
			/* Redraw all the debugging windows. */
			win3  *w3p;
			int   winnum;
			XWindowAttributes  xwa;

			for (winnum = 0, w3p = di_win3list.next;
					 winnum < di_numwin3;
					 ++winnum, w3p = w3p->next)  {
				XGetWindowAttributes(dpy, w3p->win, &xwa);
				di_redraw3(dpy, w3p->win, xwa.x,xwa.y, xwa.width,xwa.height);
			}
		}
	}
	di_draw_ov(dpy, win, x, y, w, h);
	di_draw_co(dpy, win, x, y, w, h);
	di_draw_pls(dpy, win, -1);
	di_draw_cy(dpy, win);
	gbut_redraw(win, 0, 0, 1<<30,1<<30);
	if (size_change && (di_win2w != 0))  {
		di_killwin2(TRUE);
		di_mkwin2("Corewar");
	}
	XFlush(dpy);
}


static int  recalc_ov(Display *dpy, Window win, XWindowAttributes *xwa)  {
	int  oldps = di_picsize, remap;

	if (di_color)  {
		static float  cmult[] = {0.0, 0.0, 0.0,
															 0.75, 0.75, 0.75,
															 1.0, 1.0, 1.0,
															 0.5, 0.5, 0.5,
															 1.0, 0.64286, 0.64286,
															 1.0, 0.28571, 0.28571,
															 0.39024, 1.0, 0.39024,
															 0.0, 0.84746, 0.0,
															 0.71910, 0.71910, 1.0,
															 0.43820, 0.43820, 1.0,
															 0.16667, 1.0, 1.0,
															 0.0, 0.71429, 0.71429,
															 1.0, 0.57627, 1.0,
															 1.0, 0.15254, 1.0,
															 0.84270, 0.84270, 0,
															 0.56180, 0.56180, 0};
		XColor  clr;
		int  i;

		for (i = 0;  i < 4 + DI_MAXPLAYERS*2;  ++i)  {
			clr.red   = MAX_CVAL * cmult[i*3 + 0];
			clr.green = MAX_CVAL * cmult[i*3 + 1];
			clr.blue  = MAX_CVAL * cmult[i*3 + 2];
			clr.flags = DoRed | DoGreen | DoBlue;
			XAllocColor(dpy, di_cmap, &clr);
			di_colors[i] = clr.pixel;
		}
	}
	di_width  = di_winw = xwa->width;
	di_height = di_winh = xwa->height;
	if (di_height > (int)((double)di_width / WHRATIO))
		di_height = (int)((double)di_width / WHRATIO);
	di_picsize = (di_height * 4) / (5 * 80);
	di_butbw = (di_picsize + 1) / 2;
	di_height = di_picsize * 100;  /* Actually * 80 * 4 / 4. */
	di_width = (int)(di_height * WHRATIO + 0.99999);
	remap = (oldps != di_picsize);
	/* Build the fonts. */
	if (remap)  {
		static int  need_free = FALSE;
		int  nfonts, asc, desc;
		XFontStruct  *flist;
		char  **fnames, fname[200];
		XCharStruct  size;
		static int  sfloaded = FALSE, bfloaded = FALSE, ffloaded = FALSE;

		if (need_free)  {
			if (sfloaded)
				XFreeFont(dpy, di_sfontstr);
			if (bfloaded)
				XFreeFont(dpy, di_bfontstr);
			if (ffloaded)
				XFreeFont(dpy, di_ffontstr);
		}
		need_free = TRUE;

		sprintf(fname, FONTNAME, di_height / 30);
		fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		if (nfonts < 1)  {  /* X11R4 compatibility.  NO scalable fonts! */
			XFreeFontInfo(fnames, flist, nfonts);
			if (di_picsize >= sizeof(backup_sfonts) / sizeof(*backup_sfonts))
				strcpy(fname, backup_sfonts[(sizeof(backup_sfonts) /
																		 sizeof(*backup_sfonts)) - 1]);
			else
				strcpy(fname, backup_sfonts[di_picsize]);
			fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		}
		if (nfonts < 1)  {
			GC  dummy_gc;
			XGCValues  vals;

			dummy_gc = XCreateGC(dpy, win, 0, &vals);
			XGetGCValues(dpy, dummy_gc, GCFont, &vals);
			XFreeGC(dpy, dummy_gc);
			di_sfont = vals.font;
			di_sfontstr = XQueryFont(dpy, XGContextFromGC(DefaultGC(dpy,
			              DefaultScreen(dpy))));
			sfloaded = FALSE;
		} else  {
			di_sfontstr = XLoadQueryFont(dpy, fnames[0]);
			di_sfont = di_sfontstr->fid;
			sfloaded = TRUE;
		}
		XFreeFontInfo(fnames, flist, nfonts);
		XTextExtents(di_sfontstr, "Cycles: 0", 9, &nfonts, &asc, &desc, &size);
		cyth = asc + desc;
		XTextExtents(di_sfontstr, "StopelwFasG", 11, &nfonts, &asc, &desc, &size);
		butth = asc + desc;

		sprintf(fname, FFONTNAME, di_height / 30);
		fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		if (nfonts < 1)  {  /* X11R4 compatibility.  NO scalable fonts! */
			XFreeFontInfo(fnames, flist, nfonts);
			if (di_picsize >= sizeof(backup_ffonts) / sizeof(*backup_ffonts))
				strcpy(fname, backup_ffonts[(sizeof(backup_ffonts) /
																		 sizeof(*backup_ffonts)) - 1]);
			else
				strcpy(fname, backup_ffonts[di_picsize]);
			fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		}
		if (nfonts < 1)  {
			di_ffont = di_sfont;
			di_ffontstr = di_sfontstr;
			ffloaded = FALSE;
		} else  {
			di_ffontstr = XLoadQueryFont(dpy, fnames[0]);
			di_ffont = di_ffontstr->fid;
			ffloaded = TRUE;
		}
		XFreeFontInfo(fnames, flist, nfonts);

		sprintf(fname, FONTNAME, di_height - (di_picsize * 85 + cyth + butth));
		fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		if (nfonts < 1)  {  /* X11R4 compatibility.  NO scalable fonts! */
			XFreeFontInfo(fnames, flist, nfonts);
			if (di_picsize >= sizeof(backup_bfonts) / sizeof(*backup_bfonts))
				strcpy(fname, backup_bfonts[(sizeof(backup_bfonts) /
																		 sizeof(*backup_bfonts)) - 1]);
			else
				strcpy(fname, backup_bfonts[di_picsize]);
			fnames = XListFontsWithInfo(dpy, fname, 1, &nfonts, &flist);
		}
		if (nfonts < 1)  {
			di_bfont = di_sfont;
			di_bfontstr = di_sfontstr;
			bfloaded = FALSE;
		} else  {
			di_bfontstr = XLoadQueryFont(dpy, fnames[0]);
			di_bfont = di_bfontstr->fid;
			bfloaded = TRUE;
		}
		XFreeFontInfo(fnames, flist, nfonts);
		XTextExtents(di_bfontstr, "The Core", 8, &nfonts, &asc, &desc, &size);
		titth = asc + desc;
		emptyslot = di_height - (titth + butth + cyth + di_picsize * 82);
	}
	return(remap);
}


static void  recalc_co(Display *dpy, Window win, int remap)  {
	int  i;

	di_co_xoff = di_winw / 2 - 50 * di_picsize;
	di_co_yoff = (di_winh - di_height) / 2 + titth + (emptyslot * 3) / 8;
	if (remap)  {
		static int  need_free = FALSE;
		static int  oc[MAXPICS] = {2,2, 2,3,4, 2,1,0, 2,3,4, 2,1,0, 2,3,4, 2,1,0},
		            ic[MAXPICS] = {2,2, 4,4,4, 0,0,0, 4,4,4, 0,0,0, 4,4,4, 0,0,0},
		            cof[MAXPICS] = {3,0, 4,4,4, 6,6,6, 8,8,8,
																	10,10,10, 12,12,12, 14,14,14},
                cob[MAXPICS] = {3,0, 3,5,4, 3,7,6, 3,9,8,
																	3,11,10, 3,13,12, 3,15,14};
		XGCValues  vals;
		char  *pics, *bigpics;
		int  bpsize = di_ffontstr->ascent + di_ffontstr->descent;

		if (need_free)  {
			for (i = 0;  i < MAXPICS;  ++i)  {
				XFreeGC(dpy, di_picgc[i]);
				XFreePixmap(dpy, di_pixmaps[i]);
				XFreePixmap(dpy, di_bigpixmaps[i]);
			}
		}
		need_free = TRUE;
		pics = (char *)tmalloc(di_picsize*2 * ((di_picsize*2 + 7) / 8) *
													 sizeof(char));
		bigpics = (char *)tmalloc(bpsize*2 * ((bpsize*2 + 7) / 8) *
															sizeof(char));
		vals.function = GXcopy;
		if (di_color)  {
			draw_bitmap(0, 4, di_picsize, pics);
			draw_bitmap(0, 4, bpsize, bigpics);
		}
		for (i = 0;  i < MAXPICS;  ++i)  {
			if (di_color)  {
				vals.foreground = di_colors[cof[i]];
				vals.background = di_colors[cob[i]];
			} else  {
				vals.foreground = di_stdfg;
				vals.background = di_stdbg;
				draw_bitmap(oc[i], ic[i], di_picsize, pics);
				draw_bitmap(oc[i], ic[i], bpsize, bigpics);
			}
			di_pixmaps[i] = XCreatePixmapFromBitmapData(dpy, win, pics,
																									di_picsize * 2,
																									di_picsize * 2,
																									vals.foreground,
																									vals.background,
																									di_depth);
			di_bigpixmaps[i] = XCreatePixmapFromBitmapData(dpy, win, bigpics,
																										 bpsize*2, bpsize*2,
																										 vals.foreground,
																										 vals.background,
																										 di_depth);
			vals.tile = di_pixmaps[i];
			if ((di_color && (vals.foreground == vals.background)) ||
					(!di_color && (oc[i] == 4) && (ic[i] == 4)))
				vals.fill_style = FillSolid;
			else if (!di_color && (oc[i] == 0) && (ic[i] == 0))  {
				vals.fill_style = FillSolid;
				vals.foreground = vals.background;
			} else
				vals.fill_style = FillTiled;
			di_picgc[i] = XCreateGC(dpy, win, GCFunction | GCForeground |
															GCBackground | GCFillStyle | GCTile, &vals);
		}
		free(pics);
		free(bigpics);
	}
	for (i = 0;  i < MAXPICS;  ++i)
		XSetTSOrigin(dpy, di_picgc[i], di_co_xoff, di_co_yoff);
}


static void  recalc_pls(Display *dpy, Window win, int remap)  {
	int  i, asc, desc;
	XCharStruct size;
	char  mtstr[40];

	sprintf(mtstr, "%d", maxthreads);
	XTextExtents(di_sfontstr, mtstr, strlen(mtstr), &i, &asc, &desc, &size);
	for (i = 0;  i < DI_MAXPLAYERS;  ++i)  {
		if (!(i & 1))
			di_plstat[i].nbox_x = (di_winw - di_width) / 2 + di_picsize;
		else
			di_plstat[i].nbox_x = (di_winw / 2) + (di_picsize * 51);
		di_plstat[i].nbox_y = (i / 2) * (di_picsize + (di_picsize * 76) / 3) +
			di_co_yoff + di_picsize;
		di_plstat[i].nbox_w = (di_winw / 2 - di_picsize * 51) -
			((di_winw - di_width) / 2 + di_picsize);
		di_plstat[i].nbox_h = (di_picsize * 76) / 3;
		di_plstat[i].score_y = di_plstat[i].nbox_y + di_plstat[i].nbox_h -
			desc - di_picsize - di_butbw;
		di_plstat[i].sbox_y = di_plstat[i].score_y - asc;
		di_plstat[i].sbox_w = size.width;
		di_plstat[i].sbox_h = asc + desc;
		if (!(i & 1))  {
			di_plstat[i].score_x = di_plstat[i].nbox_x + di_plstat[i].nbox_w -
				di_picsize - di_butbw;
			di_plstat[i].sbox_x = di_plstat[i].score_x - di_plstat[i].sbox_w;
		} else  {
			di_plstat[i].score_x = di_plstat[i].nbox_x + di_picsize + di_butbw;
			di_plstat[i].sbox_x = di_plstat[i].score_x;
		}
	}
	if (remap)  {
		static int  need_free = FALSE;
		XGCValues  vals;

		if (need_free)  {
			for (i = 0;  i < DI_MAXPLAYERS;  ++i)
				XFreeGC(dpy, di_plstat[i].sboxgc);
		}
		need_free = TRUE;
		vals.font = di_sfont;
		vals.function = GXcopy;
		for (i = 0;  i < DI_MAXPLAYERS;  ++i)  {
			if (di_color)  {
				vals.foreground = di_stdfg;
				vals.background = di_colors[i*2+4];
			} else  {
				if (!(i & 1))  {
					vals.foreground = di_stdbg;
					vals.background = di_stdfg;
				} else  {
					vals.foreground = di_stdfg;
					vals.background = di_stdbg;
				}
			}
			if (di_color)
				vals.foreground = vals.background;
			else  {
				if (!(i & 1))
					vals.foreground = di_stdfg;
				else
					vals.foreground = di_stdbg;
			}
			di_plstat[i].sboxgc = XCreateGC(dpy, win, (GCForeground | GCFunction),
																	 &vals);
		}
	}
	for (i = 0;  i < DI_MAXPLAYERS;  ++i)  {
	}
}


static void  recalc_ti(Display *dpy, Window win, int remap)  {
	int  dummy, asc, desc;
	XCharStruct  size;

	XTextExtents(di_bfontstr, "The Core", 8, &dummy, &asc, &desc, &size);
	di_ti_x = (di_winw - size.width) / 2;
	di_ti_y = asc + (di_winh - di_height) / 2 + emptyslot / 8;
}


static void  recalc_cy(Display *dpy, Window win, int remap)  {
	char  cystr[80];
	int  maxlen, tlen, xr, i;
	XCharStruct  size;
	int  asc, desc, dummy;

	sprintf(cystr, "Cycles: %d", max_cycles);
	tlen = strlen(cystr);
	maxlen = tlen - 8;
	XTextExtents(di_sfontstr, cystr, tlen, &dummy, &asc, &desc, &size);
	di_cyby = di_co_yoff + di_picsize*80 + emptyslot/4;
	di_cyty = di_cyby + asc;
	di_cyh = asc + desc;
	xr = (di_winw + size.width) / 2;
	if (di_cyx != NULL)  {
		free(di_cyx);
		free(di_cyw);
	}
	di_cyx = (int *)tmalloc((maxlen + 1) * sizeof(int));
	di_cyw = (int *)tmalloc((maxlen + 1) * sizeof(int));
	for (i = 1;  i <= maxlen;  ++i)  {
		XTextExtents(di_sfontstr, cystr+tlen-i, i, &dummy, &asc, &desc, &size);
		di_cyx[i] = xr - size.width;
		di_cyw[i] = size.width;
	}
	if (remap)  {
		static int  need_redraw = FALSE;
		XGCValues  vals;

		if (need_redraw)  {
			XFreeGC(dpy, di_cytgc);
			XFreeGC(dpy, di_cybgc);
		}
		need_redraw = TRUE;
		vals.foreground = di_stdfg;
		vals.background = di_stdbg;
		vals.font = di_sfont;
		vals.function = GXcopy;
		di_cytgc = XCreateGC(dpy, win, (GCForeground | GCBackground | GCFont |
																		GCFunction),
												 &vals);
		vals.foreground = di_stdbg;
		vals.font = di_sfont;
		di_cybgc = XCreateGC(dpy, win, (GCForeground | GCFunction | GCFont),
												 &vals);
	}
}


static void  draw_bitmap(int oc, int ic, unsigned picsize, char *pics)  {
	unsigned  i, j, ti, tj, pin = ((picsize * 2) + 7) / 8;
	static unsigned  min[2][2] = {{1, 3}, {4, 2}};
	unsigned  inwidx, inwidy, inwidxs, inwidys;

	for (i = 0;  i < picsize*2*pin;  ++i)
		pics[i] = 0;
	for (j = 0;  j < picsize*2;  ++j)  {
		for (i = 0;  i < picsize*2;  ++i)  {
			if (oc >= min[i&1][j&1])  {
				pics[i/8 + j*pin] |= (1 << (i & 7));
			}
		}
	}
	inwidx = (picsize + 1) / 2;
	inwidy = picsize / 2;
	inwidxs = (picsize-inwidx)/2;
	inwidys = (picsize-inwidy)/2;
	for (j = inwidys;  j < inwidys+inwidy;  ++j)  {
		for (i = inwidxs;  i < inwidxs+inwidx;  ++i)  {
			ti = i;  tj = j;
			if (ic >= min[ti&1][tj&1])
				pics[ti/8 + tj*pin] |= (1 << (ti & 7));
			else
				pics[ti/8 + tj*pin] &= ~(1 << (ti & 7));
			ti = i + picsize;  tj = j;
			if (ic >= min[ti&1][tj&1])
				pics[ti/8 + tj*pin] |= (1 << (ti & 7));
			else
				pics[ti/8 + tj*pin] &= ~(1 << (ti & 7));
			ti = i + picsize;  tj = j + picsize;
			if (ic >= min[ti&1][tj&1])
				pics[ti/8 + tj*pin] |= (1 << (ti & 7));
			else
				pics[ti/8 + tj*pin] &= ~(1 << (ti & 7));
			ti = i;  tj = j + picsize;
			if (ic >= min[ti&1][tj&1])
				pics[ti/8 + tj*pin] |= (1 << (ti & 7));
			else
				pics[ti/8 + tj*pin] &= ~(1 << (ti & 7));
		}
	}
}


static void  recalc_but(Display *dpy, Window win, int remap)  {
	int  i;
	XCharStruct  size1[DI_NBUT], size2[DI_NBUT];
	int  asc, desc, width, widest = -1;
	static char  *btext[] = {"Stop", "Step", "Go", "OK"};
	unsigned  butbw = (di_picsize + 1) / 2;
	static Pixmap  grey_pixmap;

	for (i = 0;  i < sizeof(btext) / sizeof(char *);  ++i)  {
		width = XTextWidth(di_sfontstr, btext[i], strlen(btext[i]));
		if (width > widest)
			widest = width;
	}
	di_but[DI_BSTOP].win = win;
	di_but[DI_BSTOP].w = widest + 2*di_picsize;
	di_but[DI_BSTOP].h = di_sfontstr->ascent + di_sfontstr->descent +
		2*di_picsize;
	di_but[DI_BSTOP].x = (di_winw - di_picsize * 50) / 2;
	di_but[DI_BSTOP].y = (di_winh + di_height) / 2 - (emptyslot / 8) -
		di_but[DI_BSTOP].h;

	di_but[DI_BGO].win = win;
	di_but[DI_BGO].w = di_but[DI_BSTOP].w;
	di_but[DI_BGO].h = di_but[DI_BSTOP].h;
	di_but[DI_BGO].x = (di_winw + di_picsize * 50) / 2 -
		di_but[DI_BGO].w;
	di_but[DI_BGO].y = di_but[DI_BSTOP].y;

	di_but[DI_BSLOW].win = win;
	di_but[DI_BSLOW].w = di_but[DI_BGO].x - (di_but[DI_BSTOP].x +
		di_but[DI_BSTOP].w);
	di_but[DI_BSLOW].h = di_but[DI_BSTOP].h;
	di_but[DI_BSLOW].x = di_but[DI_BSTOP].x + di_but[DI_BSTOP].w;
	di_but[DI_BSLOW].y = di_but[DI_BSTOP].y;

	di_but[DI_BQUIT].win = win;
	di_but[DI_BQUIT].x = di_plstat[0].nbox_x;
	di_but[DI_BQUIT].y = di_but[DI_BSTOP].y;
	di_but[DI_BQUIT].w = di_plstat[0].nbox_w;
	di_but[DI_BQUIT].h = di_but[DI_BSTOP].h;

	di_but[DI_BRESTART].win = win;
	di_but[DI_BRESTART].x = di_plstat[1].nbox_x;
	di_but[DI_BRESTART].y = di_but[DI_BSTOP].y;
	di_but[DI_BRESTART].w = di_plstat[1].nbox_w;
	di_but[DI_BRESTART].h = di_but[DI_BSTOP].h;

	di_but[DI_BWIN2OK].win = di_win2;
	di_but[DI_BWIN2OK].w = 
		XTextWidth(di_sfontstr, "OK", 2) + di_picsize * 2;
	di_but[DI_BWIN2OK].h = di_but[DI_BSTOP].h;

	di_but[DI_BCOREPIC].win = win;
	di_but[DI_BCOREPIC].x = di_co_xoff;
	di_but[DI_BCOREPIC].y = di_co_yoff;
	di_but[DI_BCOREPIC].w = di_picsize * 100;
	di_but[DI_BCOREPIC].h = di_picsize * 80;
/*
	di_but[DI_BWIN3OK].win = di_win3;
	di_but[DI_BWIN3OK].w = di_but[DI_BWIN2OK].w;
	di_but[DI_BWIN3OK].h = di_but[DI_BWIN2OK].h;
*/
	widest = XTextWidth(di_sfontstr, "Unload", 6);
	width = XTextWidth(di_sfontstr, "Load", 4);
	if (width > widest)
		widest = width;
	for (i = 0;  i < DI_MAXPLAYERS;  ++i)  {
		di_but[DI_BPLAY(i)].win = win;
		di_but[DI_BPLAY(i)].w = widest + di_picsize * 2;
		di_but[DI_BPLAY(i)].h = di_but[DI_BSTOP].h;
		di_but[DI_BPLAY(i)].x = di_plstat[i].nbox_x +
			(di_plstat[i].nbox_w - di_but[DI_BPLAY(i)].w) / 2;
		di_but[DI_BPLAY(i)].y = di_plstat[i].nbox_y +
			(di_plstat[i].nbox_h - di_but[DI_BPLAY(i)].h) / 2;
	}

	if (di_state == DS_RUNSLOW)
		if (di_slopos >= di_but[DI_BSLOW].w)
			di_slopos = di_but[DI_BSLOW].w - 1;

	if (remap)  {
		static int  need_free = FALSE;
		XGCValues  vals;

		if (need_free)  {
			XFreeGC(dpy, di_butgc);
		} else  {  /* Create the border GCs...they never need a recalc. */
			static char  grey50_bits[] = {1, 2}, grey75_bits[] = {1, 4};

			vals.function = GXcopy;
			vals.foreground = di_stdfg;
			vals.background = di_stdbg;
			vals.line_width = 1;
			vals.line_style = LineSolid;
			di_grey50pixmap = XCreatePixmapFromBitmapData(dpy, win, grey50_bits,
																										2, 2, di_stdfg, di_stdbg,
																										di_depth);
			di_grey75pixmap = XCreatePixmapFromBitmapData(dpy, win, grey75_bits,
																										4, 2, di_stdfg, di_stdbg,
																										di_depth);
			vals.tile = di_grey50pixmap;
			if (di_color)  {
				vals.foreground = di_colors[2];
				vals.fill_style = FillSolid;
				vals.background = di_colors[2];
			} else
				vals.fill_style = FillTiled;
			di_butlgc = XCreateGC(dpy, win, GCFunction | GCForeground |
														GCBackground | GCFillStyle | GCTile |
														GCLineStyle | GCLineWidth, &vals);
			if (di_color)
				vals.foreground = vals.background = di_colors[0];
			vals.fill_style = FillSolid;
			di_butdgc = XCreateGC(dpy, win, GCFunction | GCForeground |
														GCLineStyle | GCLineWidth |
														GCBackground | GCFillStyle, &vals);
		}
		need_free = TRUE;
		vals.function = GXcopy;
		vals.foreground = di_stdfg;
		vals.background = di_stdbg;
		vals.fill_style = FillSolid;
		vals.line_width = 1;
		vals.line_style = LineSolid;
		vals.tile = di_grey50pixmap;
		vals.font = di_sfont;
		di_butgc = XCreateGC(dpy, win, (GCFunction | GCForeground | GCBackground |
																		GCLineStyle | GCLineWidth |
																		GCFillStyle | GCFont | GCTile), &vals);
	}

	for (i = 0;  i < DI_NBUT;  ++i)  {
		gbut_create(i, di_but+i);
	}
}

#endif  /* X11_DISP */
