/*
 * di_but.c
 */

#ifdef  X11_DISP

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


static void  button_gc(Display *dpy, int flags, GC *fg, GC *bg);


/* A button with text centered in it.  The packet is a pointer to the
 *   text.
 */
void  di_draw_ctbut(int butnum, gbut_info *info)  {
	Display *dpy = di_dpy;
	GC  fg_butgc, bg_butgc;
	char  *txtout = (char *)(info->packet);
	int  txtwidth, txtlen = strlen(txtout);

#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drawing %d\n", butnum);
#endif  DEBUG
	di_outline_box(dpy, info->win, info->x, info->y, info->w, info->h,
								 info->flags & GBUT_PRESSED);
	button_gc(dpy, info->flags, &fg_butgc, &bg_butgc);
	txtwidth = XTextWidth(di_sfontstr, txtout, strlen(txtout));
	XFillRectangle(dpy, info->win, bg_butgc,
								 info->x+di_butbw, info->y+di_butbw,
								 info->w-2*di_butbw, info->h-2*di_butbw);
	XDrawString(dpy, info->win, fg_butgc, info->x + (info->w - txtwidth) / 2,
							info->y + (info->h + di_sfontstr->ascent -
												 di_sfontstr->descent)/2,
							txtout, txtlen);
#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drew %d\n", butnum);
#endif  DEBUG
}


/* A button with an up arrow in it. */
void  di_draw_upbut(int butnum, gbut_info *info)  {
	Display *dpy = di_dpy;
	GC  fg_butgc, bg_butgc;
	XPoint  points[4];

#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drawing %d\n", butnum);
#endif  DEBUG
	di_outline_box(dpy, info->win, info->x, info->y, info->w, info->h,
								 info->flags & GBUT_PRESSED);
	button_gc(dpy, info->flags, &fg_butgc, &bg_butgc);
	XFillRectangle(dpy, info->win, bg_butgc,
								 info->x+di_butbw, info->y+di_butbw,
								 info->w-2*di_butbw, info->h-2*di_butbw);
	points[0].x = info->x + di_picsize;
	points[0].y = info->y + info->h/2;
	points[1].x = info->x + info->w/2;
	points[1].y = info->y + di_picsize;
	points[2].x = points[1].x + (points[1].x - points[0].x);
	points[2].y = points[0].y;
	points[3] = points[0];
	XFillPolygon(dpy, info->win, fg_butgc, points, 3, Convex, CoordModeOrigin);
	XDrawLines(dpy, info->win, fg_butgc, points, 4, CoordModeOrigin);
#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drew %d\n", butnum);
#endif  DEBUG
}


/* A button with a down arrow in it. */
void  di_draw_downbut(int butnum, gbut_info *info)  {
	Display *dpy = di_dpy;
	GC  fg_butgc, bg_butgc;
	XPoint  points[4];

#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drawing %d\n", butnum);
#endif  DEBUG
	di_outline_box(dpy, info->win, info->x, info->y, info->w, info->h,
								 info->flags & GBUT_PRESSED);
	button_gc(dpy, info->flags, &fg_butgc, &bg_butgc);
	XFillRectangle(dpy, info->win, bg_butgc,
								 info->x+di_butbw, info->y+di_butbw,
								 info->w-2*di_butbw, info->h-2*di_butbw);
	points[0].x = info->x + di_picsize;
	points[0].y = info->y + info->h/2;
	points[1].x = info->x + info->w/2;
	points[1].y = info->y + info->h - di_picsize - 1;
	points[2].x = points[1].x + (points[1].x - points[0].x);
	points[2].y = points[0].y;
	points[3] = points[0];
	XFillPolygon(dpy, info->win, fg_butgc, points, 3, Convex, CoordModeOrigin);
	XDrawLines(dpy, info->win, fg_butgc, points, 4, CoordModeOrigin);
#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drew %d\n", butnum);
#endif  DEBUG
}


/* The slow-fast positional button.  The bar is always three pixels wide;
 *   I don't like this, it's the only non-scaling aspect of the entire display.
 *   I want to think of a better looking bar.  Maybe diamond shaped?  Drawing
 *   speed isn't really an issue here since it's only redrawn when the user
 *   clicks on it.
 */
void  di_draw_sfbut(int butnum, gbut_info *info)  {
	Display *dpy = di_dpy;
	GC  fg_butgc, bg_butgc;
	int  txtwidth, barloc = *(int *)(info->packet);
	int  ytext;
	XPoint  points[4];

#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drawing %d\n", butnum);
#endif  DEBUG
	di_outline_box(dpy, info->win, info->x, info->y, info->w, info->h,
								 info->flags & GBUT_PRESSED);
	button_gc(dpy, info->flags, &fg_butgc, &bg_butgc);
	XFillRectangle(dpy, info->win, bg_butgc,
								 info->x+di_butbw, info->y+di_butbw,
								 info->w-2*di_butbw, info->h-2*di_butbw);
	points[0].x = info->x + info->w - di_butbw - 1;
	points[0].y = info->y + di_butbw;
	points[1].x = info->x + di_butbw;
	points[1].y = info->y + info->h - di_butbw - 1;
	points[2].x = points[0].x;
	points[2].y = points[1].y;
	points[3] = points[0];
	XFillPolygon(dpy, info->win, fg_butgc, points, 3, Convex, CoordModeOrigin);
	XDrawLines(dpy, info->win, fg_butgc, points, 4, CoordModeOrigin);
	ytext = info->y + (info->h + di_sfontstr->ascent -
										 di_sfontstr->descent) / 2;
	XDrawString(dpy, info->win, fg_butgc, info->x + di_butbw * 2, ytext,
							"Slow", 4);
	txtwidth = XTextWidth(di_sfontstr, "Fast", 4);
	XDrawString(dpy, info->win, bg_butgc,
							info->x + info->w - txtwidth - di_butbw * 2, ytext, "Fast", 4);
	if (di_state == DS_RUNSLOW)  {
		int  x, y1, y2;

		x = di_but[butnum].x + di_slopos + 1;
		y1 = di_but[butnum].y + di_butbw;
		y2 = di_but[butnum].y + di_but[butnum].h - di_butbw;
		XDrawLine(dpy, info->win, bg_butgc, x-1, y1, x-1, y2);
		XDrawLine(dpy, info->win, bg_butgc, x+1, y1, x+1, y2);
		XDrawLine(dpy, info->win, fg_butgc, x, y1, x, y2);
	}
#ifdef  DEBUG
	XSync(dpy, False);
	fprintf(stderr, "Drew %d\n", butnum);
#endif  DEBUG
}


/* Figure out what to use as foreground and background for the GCs. */
static void  button_gc(Display *dpy, int flags, GC *fg, GC *bg)  {
	if (flags & GBUT_PRESSED)  {
		*bg = di_butgc;
		*fg = di_cybgc;
	} else  {
		*bg = di_cybgc;
		*fg = di_butgc;
	}
	if (flags & GBUT_PRESSABLE)
		XSetFillStyle(dpy, di_butgc, FillSolid);
	else
		XSetFillStyle(dpy, di_butgc, FillTiled);
}


void  di_outline_box(Display *dpy, Window win,
										 int x, int y, int w, int h, int bstate)  {
	XPoint  points[7];
	GC  topgc, bottomgc;

	points[0].x = x + w - 1;
	points[0].y = y;
	points[1].x = x;
	points[1].y = y;
	points[2].x = x;
	points[2].y = y + h - 1;
	points[3].x = x + di_butbw - 1;
	points[3].y = y + h - di_butbw;
	points[4].x = points[3].x;
	points[4].y = y + di_butbw - 1;
	points[5].x = x + w - di_butbw;
	points[5].y = points[4].y;
	points[6] = points[0];
	if (bstate == 0)  {
		topgc = di_butlgc;
		bottomgc = di_butdgc;
	} else  {
		topgc = di_butdgc;
		bottomgc = di_butlgc;
	}
	XFillPolygon(dpy, win, topgc, points, 6, Nonconvex, CoordModeOrigin);
	XDrawLines(dpy, win, topgc, points, 7, CoordModeOrigin);
	points[1].x = points[0].x;
	points[1].y = points[2].y;
	points[4].x = points[5].x;
	points[4].y = points[3].y;
	XFillPolygon(dpy, win, bottomgc, points, 6, Nonconvex, CoordModeOrigin);
	XDrawLines(dpy, win, bottomgc, points, 7, CoordModeOrigin);
}


void  di_draw_sbar(int butnum, gbut_info *info)  {
	Display  *dpy = di_dpy;
	int  sbh, sbindex;
	GC  gc;

	di_outline_box(dpy, info->win, info->x, info->y, info->w, info->h, 1);
	sbh = info->h - info->w;
	sbindex = (sbh * ((win3 *)info->packet)->startaddr + coresize/2) / coresize;
	di_outline_box(dpy, info->win,
								 info->x + di_butbw, info->y + di_butbw + sbindex, 
								 info->w - di_butbw*2, info->w - di_butbw*2,
								 info->flags & GBUT_PRESSED);
	gc = di_picgc[DI_EMPTY];
	if (!di_color)
		XSetTile(dpy, gc, di_grey75pixmap);
	if (sbindex > 0)
		XFillRectangle(dpy, info->win, gc,
									 info->x + di_butbw, info->y + di_butbw,
									 info->w-di_butbw*2, sbindex);
	if (sbindex < sbh)
		XFillRectangle(dpy, info->win, gc,
									 info->x + di_butbw, info->y + info->w + sbindex - di_butbw,
									 info->w-di_butbw*2, sbh-sbindex);
	if (!di_color)
		XSetTile(dpy, gc, di_grey50pixmap);
	if (info->flags & GBUT_PRESSED)
		gc = di_cytgc;
	else
		gc = di_cybgc;
	XFillRectangle(dpy, info->win, gc,
								 info->x + di_butbw*2, sbindex+info->y+di_butbw*2,
								 info->w - di_butbw*4, info->w - di_butbw*4);
}

#endif  /* X11_DISP */
