/*
 * Window system protocol server.
 * Use select and a single proc and single stack
 * to avoid aggravating the X11 library, which is
 * subtle and quick to anger.
 */

#include <u.h>
#include <sys/select.h>
#include <errno.h>
#include "x11-inc.h"
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <memlayer.h>
#include <keyboard.h>
#include <mouse.h>
#include <cursor.h>
#include <drawfcall.h>
#include "x11-memdraw.h"
#include "devdraw.h"

#undef time

#define MouseMask (\
	ButtonPressMask|\
	ButtonReleaseMask|\
	PointerMotionMask|\
	Button1MotionMask|\
	Button2MotionMask|\
	Button3MotionMask)

#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask

typedef struct Kbdbuf Kbdbuf;
typedef struct Mousebuf Mousebuf;
typedef struct Fdbuf Fdbuf;
typedef struct Tagbuf Tagbuf;

struct Kbdbuf
{
	Rune r[32];
	int ri;
	int wi;
	int stall;
};

struct Mousebuf
{
	Mouse m[32];
	int resized[32];
	int ri;
	int wi;
	int stall;
};

struct Tagbuf
{
	int t[32];
	int ri;
	int wi;
};

struct Fdbuf
{
	uchar buf[2*MAXWMSG];
	uchar *rp;
	uchar *wp;
	uchar *ep;
};

Kbdbuf kbd;
Mousebuf mouse;
Fdbuf fdin;
Fdbuf fdout;
Tagbuf kbdtags;
Tagbuf mousetags;
Tagbuf resizetags;

void fdslide(Fdbuf*);
void runmsg(Wsysmsg*);
void replymsg(Wsysmsg*);
void runxevent(XEvent*);
void matchkbd(void);
void matchmouse(void);
void matchresized(void);
int fdnoblock(int);

int chatty;

void
usage(void)
{
	fprint(2, "usage: devdraw (don't run  directly)\n");
	exits("usage");
}

void
main(int argc, char **argv)
{
	int n, top, firstx;
	fd_set rd, wr, xx;
	Wsysmsg m;
	XEvent event;

	ARGBEGIN{
	case 'D':
		chatty++;
		break;
	default:
		usage();
	}ARGEND
	
	if(argc != 0)
		usage();

	fdin.rp = fdin.wp = fdin.buf;
	fdin.ep = fdin.buf+sizeof fdin.buf;
	
	fdout.rp = fdout.wp = fdout.buf;
	fdout.ep = fdout.buf+sizeof fdout.buf;

	fdnoblock(0);
	fdnoblock(1);

	firstx = 1;
	_x.fd = -1;
	for(;;){
		/* set up file descriptors */
		FD_ZERO(&rd);
		FD_ZERO(&wr);
		FD_ZERO(&xx);
		/*
		 * Don't read unless there's room *and* we haven't
		 * already filled the output buffer too much.
		 */
		if(fdout.wp < fdout.buf+MAXWMSG && fdin.wp < fdin.ep)
			FD_SET(0, &rd);
		if(fdout.wp > fdout.rp)
			FD_SET(1, &wr);
		FD_SET(0, &xx);
		FD_SET(1, &xx);
		top = 1;
		if(_x.fd >= 0){
			if(firstx){
				firstx = 0;
				XSelectInput(_x.display, _x.drawable, Mask);
			}
			FD_SET(_x.fd, &rd);
			FD_SET(_x.fd, &xx);
			XFlush(_x.display);
			top = _x.fd;
		}

		if(chatty)
			fprint(2, "select %d...\n", top+1);
		/* wait for something to happen */
		if(select(top+1, &rd, &wr, &xx, NULL) < 0){
			if(chatty)
				fprint(2, "select failure\n");
			exits(0);
		}
		if(chatty)
			fprint(2, "got select...\n");

		{
			/* read what we can */
			n = 1;
			while(fdin.wp < fdin.ep && (n = read(0, fdin.wp, fdin.ep-fdin.wp)) > 0)
				fdin.wp += n;
			if(n == 0){
				if(chatty)
					fprint(2, "eof\n");
				exits(0);
			}
			if(n < 0 && errno != EAGAIN)
				sysfatal("reading wsys msg: %r");

			/* pick off messages one by one */
			while((n = convM2W(fdin.rp, fdin.wp-fdin.rp, &m)) > 0){
				runmsg(&m);
				fdin.rp += n;
			}
			
			/* slide data to beginning of buf */
			fdslide(&fdin);
		}
		{
			/* write what we can */
			n = 1;
			while(fdout.rp < fdout.wp && (n = write(1, fdout.rp, fdout.wp-fdout.rp)) > 0)
				fdout.rp += n;
			if(n == 0)
				sysfatal("short write writing wsys");
			if(n < 0 && errno != EAGAIN)
				sysfatal("writing wsys msg: %r");

			/* slide data to beginning of buf */
			fdslide(&fdout);
		}
		{
			/*
			 * Read an X message if we can.
			 * (XPending actually calls select to make sure
			 * the display's fd is readable and then reads
			 * in any waiting data before declaring whether
			 * there are events on the queue.)
			 */
			while(XPending(_x.display)){
				XNextEvent(_x.display, &event);
				runxevent(&event);
			}
		}
	}
}

int
fdnoblock(int fd)
{
	return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
}

void
fdslide(Fdbuf *fb)
{
	int n;

	n = fb->wp - fb->rp;
	if(n > 0)
		memmove(fb->buf, fb->rp, n);
	fb->rp = fb->buf;
	fb->wp = fb->rp+n;
}

void
replyerror(Wsysmsg *m)
{
	char err[256];
	
	rerrstr(err, sizeof err);
	m->type = Rerror;
	m->error = err;
	replymsg(m);
}

/* 
 * Handle a single wsysmsg. 
 * Might queue for later (kbd, mouse read)
 */
void
runmsg(Wsysmsg *m)
{
	uchar buf[65536];
	int n;
	Memimage *i;
	
	switch(m->type){
	case Tinit:
		memimageinit();
		i = _xattach(m->label, m->winsize);
		_initdisplaymemimage(i);
		replymsg(m);
		break;

	case Trdmouse:
		mousetags.t[mousetags.wi++] = m->tag;
		if(mousetags.wi == nelem(mousetags.t))
			mousetags.wi = 0;
		if(mousetags.wi == mousetags.ri)
			sysfatal("too many queued mouse reads");
		mouse.stall = 0;
		matchmouse();
		break;

	case Trdkbd:
		kbdtags.t[kbdtags.wi++] = m->tag;
		if(kbdtags.wi == nelem(kbdtags.t))
			kbdtags.wi = 0;
		if(kbdtags.wi == kbdtags.ri)
			sysfatal("too many queued keyboard reads");
		kbd.stall = 0;
		matchkbd();
		break;

	case Tmoveto:
		_xmoveto(m->mouse.xy);
		replymsg(m);
		break;

	case Tcursor:
		if(m->arrowcursor)
			_xsetcursor(nil);
		else
			_xsetcursor(&m->cursor);
		replymsg(m);
		break;
			
	case Tbouncemouse:
		_xbouncemouse(&m->mouse);
		replymsg(m);
		break;

	case Tlabel:
		_xsetlabel(m->label);
		replymsg(m);
		break;

	case Trdsnarf:
		m->snarf = _xgetsnarf();
		replymsg(m);
		free(m->snarf);
		break;

	case Twrsnarf:
		_xputsnarf(m->snarf);
		replymsg(m);
		break;

	case Trddraw:
		n = m->count;
		if(n > sizeof buf)
			n = sizeof buf;
		n = _drawmsgread(buf, n);
		if(n < 0)
			replyerror(m);
		else{
			m->count = n;
			m->data = buf;
			replymsg(m);
		}
		break;

	case Twrdraw:
		if(_drawmsgwrite(m->data, m->count) < 0)
			replyerror(m);
		else
			replymsg(m);
		break;
	
	case Ttop:
		_xtopwindow();
		replymsg(m);
		break;
	
	case Tresize:
		_xresizewindow(m->rect);
		replymsg(m);
		break;
	}
}

/*
 * Reply to m.
 */
void
replymsg(Wsysmsg *m)
{
	int n;

	/* T -> R msg */
	if(m->type%2 == 0)
		m->type++;
		
	/* copy to output buffer */
	n = sizeW2M(m);
	if(fdout.wp+n > fdout.ep)
		sysfatal("out of space for reply message");
	convW2M(m, fdout.wp, n);
	fdout.wp += n;
}

/*
 * Match queued kbd reads with queued kbd characters.
 */
void
matchkbd(void)
{
	Wsysmsg m;
	
	if(kbd.stall)
		return;
	while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){
		m.type = Rrdkbd;
		m.tag = kbdtags.t[kbdtags.ri++];
		if(kbdtags.ri == nelem(kbdtags.t))
			kbdtags.ri = 0;
		m.rune = kbd.r[kbd.ri++];
		if(kbd.ri == nelem(kbd.r))
			kbd.ri = 0;
		replymsg(&m);
	}
}

/*
 * Match queued mouse reads with queued mouse events.
 */
void
matchmouse(void)
{
	Wsysmsg m;
	
	if(mouse.stall)
		return;
	while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){
		m.type = Rrdmouse;
		m.tag = mousetags.t[mousetags.ri++];
		if(mousetags.ri == nelem(mousetags.t))
			mousetags.ri = 0;
		m.mouse = mouse.m[mouse.ri];
		m.resized = mouse.resized[mouse.ri];
		mouse.ri++;
		if(mouse.ri == nelem(mouse.m))
			mouse.ri = 0;
		replymsg(&m);
	}
}

/*
 * Handle an incoming X event.
 */
void
runxevent(XEvent *xev)
{
	int c;
	static Mouse m;

	switch(xev->type){
	case Expose:
		_xexpose(xev);
		break;
	
	case DestroyNotify:
		if(_xdestroy(xev))
			exits(0);
		break;

	case ConfigureNotify:
		if(_xconfigure(xev)){
			mouse.resized[mouse.wi] = 1;
			_xreplacescreenimage();
			goto addmouse;
		}
		break;

	case ButtonPress:
	case ButtonRelease:
	case MotionNotify:
		if(mouse.stall)
			return;
		if(_xtoplan9mouse(xev, &m) < 0)
			return;
		mouse.resized[mouse.wi] = 0;
	addmouse:
		mouse.m[mouse.wi] = m;
		mouse.wi++;
		if(mouse.wi == nelem(mouse.m))
			mouse.wi = 0;
		if(mouse.wi == mouse.ri)
			mouse.stall = 1;
		matchmouse();
		break;
	
	case KeyPress:
		if(kbd.stall)
			return;
		if((c = _xtoplan9kbd(xev)) < 0)
			return;
		kbd.r[kbd.wi++] = c;
		if(kbd.wi == nelem(kbd.r))
			kbd.wi = 0;
		if(kbd.ri == kbd.wi)
			kbd.stall = 1;
		matchkbd();
		break;
	
	case SelectionRequest:
		_xselect(xev);
		break;
	}
}

