/***
****  QuBE --- X-Windows graphical display routines.  These need work.
***/

#include "qube.h"
#include "xgfx.h"
#include <stdarg.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <X11/Xmu/Drawing.h>
#include <X11/keysym.h>

#define STDEVENTS ExposureMask|KeyPressMask|ButtonPressMask|ButtonReleaseMask|FocusChangeMask| \
                  StructureNotifyMask|PointerMotionMask|EnterWindowMask|LeaveWindowMask

char Sans8N[] = { "6x9" };

int MouseX;
int MouseY;

static Display *display;
static int screennum;
static char *progname;
static GC gc;
static XGCValues gcvalues;
static unsigned long gcvaluemask;
static Cursor Arrow;
static int FontCount;
static XFontStruct *MainFont;
static int displaywidth, displayheight;
static Atom wm_delete_window, wm_protocols;
static XEvent report;
static Region region;
static XRectangle rectangle;
static Window qubewin;
static Colormap colormap;

static XColor colorarray[16];

static unsigned int Reds[16] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x7FFF, 0xAAAA,
				0x5555, 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
static unsigned int Grns[16] = { 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x3FFF, 0xAAAA,
				0x5555, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF };
static unsigned int Blus[16] = { 0x0000, 0x7FFF, 0x0000, 0x7FFF, 0x0000, 0x7FFF, 0x0000, 0xAAAA,
				0x5555, 0xFFFF, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000, 0xFFFF };

static int KeyBuffer[128];
static int KeyRead;
static int KeyWrite;

int InitScrn(int mode)
{
        XWindowAttributes windinfo;
        Screen *screenptr;
        char *displayname = NULL;
	int i;

	if (mode == M80x25x16) {
		XDestroyWindow(display, qubewin);
		XCloseDisplay(display);
		return;
	}

	if ((display = XOpenDisplay(displayname)) == NULL)
		Error("Unable to connect to X server.");

	screennum = DefaultScreen(display);
	screenptr = DefaultScreenOfDisplay(display);

	if (XGetWindowAttributes(display, RootWindow(display, screennum), &windinfo) == 0)
                Error("Could not obtain root window attributes.");
	displaywidth = windinfo.width;
	displayheight = windinfo.height;

	if ((MainFont = XLoadQueryFont(display, Sans8N)) == NULL)
		Error("Error loading font \"6x9\".");

	gc = XCreateGC(display, RootWindow(display, screennum), GCForeground|GCBackground, &gcvalues);
	XSetLineAttributes(display, gc, 1, LineSolid, CapRound, JoinRound);
	XSetFont(display, gc, MainFont->fid);
	XSetFunction(display, gc, GXxor);

	wm_protocols = XInternAtom(display, "WM_PROTOCOLS", 0);
	wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0);

	qubewin = XCreateSimpleWindow(display, RootWindow(display, screennum), 0, 0,
		640, 480, 1, BLACK, BLACK);

	region = XCreateRegion();

	Arrow = XCreateFontCursor(display, XC_left_ptr);

	XDefineCursor(display, qubewin, Arrow);
	XSelectInput(display, qubewin, STDEVENTS);
	XMapWindow(display, qubewin);

	colormap = XCreateColormap(display, qubewin, DefaultVisual(display, screennum), AllocAll);

	for (i = 0; i < 16; i++) {
		colorarray[i].red = Reds[i];
		colorarray[i].green = Grns[i];
		colorarray[i].blue = Blus[i];
		colorarray[i].flags = DoRed | DoGreen | DoBlue;
		colorarray[i].pixel = i;
	}

	XStoreColors(display, colormap, colorarray, 16);
	XSetWindowColormap(display, qubewin, colormap);
	XSync(display, 1);

	KeyRead = 0;
	KeyWrite = 0;

	XFlush(display);
}

int LineXOR(int x1, int y1, int x2, int y2, int color)
{
	XSetForeground(display, gc, color);
	XDrawLine(display, qubewin, gc, x1, y1, x2, y2);
}

int Gprintf(int x, int y, char *font, int color, char *format, ...)
{
	char string[1024];
	va_list arg_ptr;
	
	va_start(arg_ptr, format);
	XSetForeground(display, gc, color);
	vsprintf(string, format, arg_ptr);

	XSetFunction(display, gc, GXcopy);
        XDrawImageString(display, qubewin, gc, x, y, string, strlen(string));
	XSetFunction(display, gc, GXxor);
}

int BoxOutlnXOR(int x1, int y1, int x2, int y2, int color)
{
	XSetForeground(display, gc, color);
	XDrawRectangle(display, qubewin, gc, x1, y1, x2-x1+1, y2-y1+1);
}

int BoxFillXOR(int x1, int y1, int x2, int y2, int color)
{
	XSetForeground(display, gc, color);
	XFillRectangle(display, qubewin, gc, x1, y1, x2-x1+1, y2-y1+1);
}

int InitMouse(int width, int height, int xres, int yres)
{

}

void StdCursor(int cursor)
{

}

void KillMouse(void)
{

}

void MouseOn(void)
{

}

void MouseOff(void)
{

}

void ReadMouse(void)
{
	KeySym keysym;

	XNextEvent(display, &report);

	switch(report.type) {
	case Expose:
		KeyBuffer[KeyWrite] = 0x7F;
		KeyWrite = (KeyWrite + 1) & 0x7F;
		break;
	case KeyPress:
		XLookupString(&report, NULL, 0, &keysym, NULL);

		switch (keysym) {
		case XK_Left:	KeyBuffer[KeyWrite] = 0x4B; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_Right:	KeyBuffer[KeyWrite] = 0x4D; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_Up:	KeyBuffer[KeyWrite] = 0x48; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_Down:	KeyBuffer[KeyWrite] = 0x50; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_Escape:	KeyBuffer[KeyWrite] = 0x01; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_equal:
		case XK_plus:	KeyBuffer[KeyWrite] = 0x0D; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_underscore:
		case XK_minus:	KeyBuffer[KeyWrite] = 0x0C; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_N:
		case XK_n:	KeyBuffer[KeyWrite] = 0x31; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_P:
		case XK_p:	KeyBuffer[KeyWrite] = 0x19; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		case XK_G:
		case XK_g:	KeyBuffer[KeyWrite] = 0x22; KeyWrite = (KeyWrite + 1) & 0x7F; break;
		}
		break;
	case MotionNotify:
		MouseX = report.xmotion.x;
		MouseY = report.xmotion.y;
		break;
	default:
		break;
	}
}

int KeyStatus(void)
{
	return(KeyRead != KeyWrite);
}

int ReadKeyScan(void)
{
	int c = KeyBuffer[KeyRead];
	KeyRead = (KeyRead + 1) & 0x7F;
	return(c);
}

