diff --git a/src/conio/GNUmakefile b/src/conio/GNUmakefile
index 859355f795150862347dcd4d3e8599219351852c..278e38a351939ef22b86aa7237ad6c3ebdff4c4c 100644
--- a/src/conio/GNUmakefile
+++ b/src/conio/GNUmakefile
@@ -8,14 +8,17 @@ OBJS	+=	$(MTOBJODIR)$(DIRSEP)curs_cio$(OFILE)
 ifdef NO_X
  CFLAGS	+=	-DNO_X
 else
- OBJS	+=	$(MTOBJODIR)$(DIRSEP)console$(OFILE) \
+ OBJS	+=	$(MTOBJODIR)$(DIRSEP)x_events$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)x_cio$(OFILE)
+ NEED_BITMAP := 1
 endif
 
 ifdef WITH_SDL_AUDIO
  OBJS	+=	$(MTOBJODIR)$(DIRSEP)sdl_con$(OFILE)
+ NEED_BITMAP := 1
 else
  ifdef WITH_SDL
+  NEED_BITMAP := 1
   OBJS	+=	$(MTOBJODIR)$(DIRSEP)sdl_con$(OFILE)
   OBJS	+=      $(MTOBJODIR)$(DIRSEP)sdlfuncs$(OFILE)
   ifeq ($(os),darwin)
@@ -30,29 +33,17 @@ ifeq ($(os),netbsd)
  endif
 endif
 
-$(MTOBJODIR)$(DIRSEP)console$(OFILE).static:
-	$(QUIET)$(DELETE) $(MTOBJODIR)$(DIRSEP)console$(OFILE)*
-	$(QUIET)touch $(MTOBJODIR)$(DIRSEP)console$(OFILE).static
-
-$(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic:
-	$(QUIET)$(DELETE) $(MTOBJODIR)$(DIRSEP)console$(OFILE)*
-	$(QUIET)touch $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic
+ifdef NEED_BITMAP
+ OBJS	+=	$(MTOBJODIR)$(DIRSEP)bitmap_con$(OFILE)
+endif
 
 # CIOLIB Library Link Rule
-ifdef STATIC
-$(CIOLIB-MT_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).static $(MTOBJODIR) $(OBJS)
-else
-$(CIOLIB-MT_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic $(MTOBJODIR) $(OBJS)
-endif
+$(CIOLIB-MT_BUILD): $(MTOBJODIR) $(OBJS)
 	@echo Creating $@ ...
 	$(QUIET)$(AR) rc $@ $(OBJS)
 	$(QUIET)$(RANLIB) $@
 
-ifdef STATIC
-$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).static $(MTOBJODIR) $(OBJS)
-else
-$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR)$(DIRSEP)console$(OFILE).dynamic $(MTOBJODIR) $(OBJS)
-endif
+$(CIOLIB-MT_SHLIB_BUILD): $(MTOBJODIR) $(OBJS)
 	@echo Creating $@
 	$(QUIET)$(MKSHLIB) $(LDFLAGS) $(OBJS) $(SHLIBOPTS) -o $@
 
diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ad1682b0273d85c9a24fa5504ba39e7b861188f
--- /dev/null
+++ b/src/conio/bitmap_con.c
@@ -0,0 +1,717 @@
+/* $Id$ */
+
+#include <stdarg.h>
+#include <stdio.h>		/* NULL */
+#include <stdlib.h>
+#include <string.h>
+
+#include "threadwrap.h"
+#include "semwrap.h"
+#include "gen_defs.h"
+#include "genwrap.h"
+#include "dirwrap.h"
+#include "xpbeep.h"
+
+#if (defined CIOLIB_IMPORTS)
+ #undef CIOLIB_IMPORTS
+#endif
+#if (defined CIOLIB_EXPORTS)
+ #undef CIOLIB_EXPORTS
+#endif
+
+#include "ciolib.h"
+#include "keys.h"
+#include "vidmodes.h"
+#include "allfonts.h"
+
+static char *screen;
+int screenwidth;
+int screenheight;
+#define PIXEL_OFFSET(x,y)	( (y)*screenwidth+(x) )
+
+static int current_font=-99;
+struct video_stats vstat;
+
+struct bitmap_callbacks {
+	void	(*drawrect)		(int xpos, int ypos, int width, int height, unsigned char *data);
+};
+
+pthread_mutex_t		vstatlock;
+pthread_mutex_t		screenlock;
+static struct bitmap_callbacks callbacks;
+static unsigned char *font;
+
+struct rectangle {
+	int x;
+	int y;
+	int width;
+	int height;
+};
+
+static int update_rect(int sx, int sy, int width, int height, int force);
+
+/* Blinker Thread */
+static void blinker_thread(void *data)
+{
+	while(1) {
+		SLEEP(500);
+		pthread_mutex_lock(&vstatlock);
+		if(vstat.blink)
+			vstat.blink=FALSE;
+		else
+			vstat.blink=TRUE;
+		update_rect(0,0,0,0,FALSE);
+		pthread_mutex_unlock(&vstatlock);
+	}
+}
+
+int bitmap_init(void	(*drawrect_cb)		(int xpos, int ypos, int width, int height, unsigned char *data))
+{
+	pthread_mutex_init(&vstatlock, NULL);
+	pthread_mutex_init(&screenlock, NULL);
+	pthread_mutex_lock(&vstatlock);
+	vstat.vmem=NULL;
+	pthread_mutex_unlock(&vstatlock);
+
+	callbacks.drawrect=drawrect_cb;
+	_beginthread(blinker_thread,0,NULL);
+
+	return(0);
+}
+
+void send_rectangle(int xoffset, int yoffset, int width, int height, int force)
+{
+	unsigned char *rect;
+	int pixel=0;
+	int inpixel;
+	int x,y;
+
+	pthread_mutex_lock(&screenlock);
+	if(callbacks.drawrect) {
+		if(xoffset < 0 || xoffset >= screenwidth || yoffset < 0 || yoffset >= screenheight || width <= 0 || width > screenwidth || height <=0 || height >screenheight) {
+			pthread_mutex_unlock(&screenlock);
+			return;
+		}
+
+		rect=(unsigned char *)malloc(width*height*sizeof(unsigned char));
+		if(!rect) {
+			pthread_mutex_unlock(&screenlock);
+			return;
+		}
+
+		for(y=0; y<height; y++) {
+			inpixel=PIXEL_OFFSET(xoffset, yoffset+y);
+			for(x=0; x<width; x++) {
+				rect[pixel++]=vstat.palette[screen[inpixel++]];
+			}
+		}
+		callbacks.drawrect(xoffset,yoffset,width,height,rect);
+	}
+	pthread_mutex_unlock(&screenlock);
+}
+
+int bitmap_init_mode(int mode, int *width, int *height)
+{
+    int i;
+	char *newscreen;
+
+	pthread_mutex_lock(&vstatlock);
+
+	if(load_vmode(&vstat, mode)) {
+		pthread_mutex_unlock(&vstatlock);
+		return(-1);
+	}
+
+	/* Initialize video memory with black background, white foreground */
+	for (i = 0; i < vstat.cols*vstat.rows; ++i)
+	    vstat.vmem[i] = 0x0700;
+
+	pthread_mutex_lock(&screenlock);
+	screenwidth=vstat.charwidth*vstat.cols;
+	if(width)
+		*width=screenwidth;
+	screenheight=vstat.charheight*vstat.rows;
+	if(height)
+		*height=screenheight;
+	newscreen=realloc(screen, screenwidth*screenheight);
+	if(!newscreen) {
+		pthread_mutex_unlock(&screenlock);
+		pthread_mutex_unlock(&vstatlock);
+		return(-1);
+	}
+	screen=newscreen;
+	memset(screen,vstat.palette[0],screenwidth*screenheight);
+	pthread_mutex_unlock(&screenlock);
+	/* TODO: Re-enable this
+	send_rectangle(0,0,screenwidth,screenheight,TRUE);
+	*/
+	bitmap_loadfont(NULL);
+	/* TODO: Remove this next line */
+	update_rect(1,1,cio_textinfo.screenwidth,cio_textinfo.screenheight,TRUE);
+	pthread_mutex_unlock(&vstatlock);
+
+	cio_textinfo.attribute=7;
+	cio_textinfo.normattr=7;
+	cio_textinfo.currmode=mode;
+	cio_textinfo.screenheight=vstat.rows;
+	cio_textinfo.screenwidth=vstat.cols;
+	cio_textinfo.curx=1;
+	cio_textinfo.cury=1;
+	cio_textinfo.winleft=1;
+	cio_textinfo.wintop=1;
+	cio_textinfo.winright=cio_textinfo.screenwidth;
+	cio_textinfo.winbottom=cio_textinfo.screenheight;
+
+    return(0);
+}
+
+/********************************************************/
+/* High Level Stuff										*/
+/********************************************************/
+
+/* Called from main thread only (Passes Event) */
+int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill)
+{
+	int x,y;
+	unsigned char *out;
+	WORD	sch;
+
+	pthread_mutex_lock(&vstatlock);
+	if(		   sx < 1
+			|| sy < 1
+			|| ex < 1
+			|| ey < 1
+			|| sx > cio_textinfo.screenwidth
+			|| sy > cio_textinfo.screenheight
+			|| sx > ex
+			|| sy > ey
+			|| ex > cio_textinfo.screenwidth
+			|| ey > cio_textinfo.screenheight
+			|| fill==NULL) {
+		pthread_mutex_unlock(&vstatlock);
+		return(0);
+	}
+
+	out=fill;
+	for(y=sy-1;y<ey;y++) {
+		for(x=sx-1;x<ex;x++) {
+			sch=*(out++);
+			sch |= (*(out++))<<8;
+			vstat.vmem[y*cio_textinfo.screenwidth+x]=sch;
+		}
+	}
+	update_rect(sx,sy,ex-sx+1,ey-sy+1,FALSE);
+	pthread_mutex_unlock(&vstatlock);
+	return(1);
+}
+
+/* Called from main thread only */
+int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill)
+{
+	int x,y;
+	unsigned char *out;
+	WORD	sch;
+
+	pthread_mutex_lock(&vstatlock);
+
+	if(		   sx < 1
+			|| sy < 1
+			|| ex < 1
+			|| ey < 1
+			|| sx > cio_textinfo.screenwidth
+			|| sy > cio_textinfo.screenheight
+			|| sx > ex
+			|| sy > ey
+			|| ex > cio_textinfo.screenwidth
+			|| ey > cio_textinfo.screenheight
+			|| fill==NULL) {
+		pthread_mutex_unlock(&vstatlock);
+		return(0);
+	}
+
+	out=fill;
+	for(y=sy-1;y<ey;y++) {
+		for(x=sx-1;x<ex;x++) {
+			sch=vstat.vmem[y*cio_textinfo.screenwidth+x];
+			*(out++)=sch & 0xff;
+			*(out++)=sch >> 8;
+		}
+	}
+	pthread_mutex_unlock(&vstatlock);
+	return(1);
+}
+
+/* Called from main thread only */
+void bitmap_setcursortype(int type)
+{
+	pthread_mutex_lock(&vstatlock);
+	switch(type) {
+		case _NOCURSOR:
+			vstat.curs_start=0xff;
+			vstat.curs_end=0;
+			break;
+		case _SOLIDCURSOR:
+			vstat.curs_start=0;
+			vstat.curs_end=vstat.charheight-1;
+			break;
+		default:
+		    vstat.curs_start = vstat.default_curs_start;
+		    vstat.curs_end = vstat.default_curs_end;
+			break;
+	}
+	update_rect(cio_textinfo.curx+cio_textinfo.winleft-1,cio_textinfo.cury+cio_textinfo.wintop-1,1,1,TRUE);
+	pthread_mutex_unlock(&vstatlock);
+}
+
+int bitmap_setfont(int font, int force)
+{
+	int changemode=0;
+	int	newmode=-1;
+	struct text_info ti;
+	char	*old;
+	int		ow,oh;
+	int		row,col;
+	char	*new;
+	int		attr;
+	char	*pold;
+	char	*pnew;
+
+	if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2))
+		return(-1);
+
+	if(conio_fontdata[font].eight_by_sixteen!=NULL)
+		newmode=C80;
+	else if(conio_fontdata[font].eight_by_fourteen!=NULL)
+		newmode=C80X28;
+	else if(conio_fontdata[font].eight_by_eight!=NULL)
+		newmode=C80X50;
+
+	switch(vstat.charheight) {
+		case 8:
+			if(conio_fontdata[font].eight_by_eight==NULL) {
+				if(force)
+					return(-1);
+				else
+					changemode=1;
+			}
+			break;
+		case 14:
+			if(conio_fontdata[font].eight_by_fourteen==NULL) {
+				if(force)
+					return(-1);
+				else
+					changemode=1;
+			}
+			break;
+		case 16:
+			if(conio_fontdata[font].eight_by_sixteen==NULL) {
+				if(force)
+					return(-1);
+				else
+					changemode=1;
+			}
+			break;
+	}
+	if(changemode && newmode==-1)
+		return(-1);
+	current_font=font;
+	if(changemode) {
+		gettextinfo(&ti);
+		
+		attr=ti.attribute;
+		ow=ti.screenwidth;
+		oh=ti.screenheight;
+
+		old=malloc(ow*oh*2);
+		if(old) {
+			gettext(1,1,ow,oh,old);
+			textmode(newmode);
+			new=malloc(ti.screenwidth*ti.screenheight*2);
+			pold=old;
+			pnew=new;
+			for(row=0; row<ti.screenheight; row++) {
+				for(col=0; col<ti.screenwidth; col++) {
+					if(row < oh) {
+						if(col < ow) {
+							*(new++)=*(old++);
+							*(new++)=*(old++);
+						}
+						else {
+							*(new++)=' ';
+							*(new++)=attr;
+						}
+					}
+					else {
+						*(new++)=' ';
+						*(new++)=attr;
+					}
+				}
+				if(row < oh) {
+					for(;col<ow;col++) {
+						old++;
+						old++;
+					}
+				}
+			}
+			puttext(1,1,ti.screenwidth,ti.screenheight,new);
+			free(pnew);
+			free(pold);
+		}
+	}
+	return(0);
+}
+
+int bitmap_getfont(void)
+{
+	return(current_font);
+}
+
+/* Called from event thread only */
+int bitmap_loadfont(char *filename)
+{
+	static char current_filename[MAX_PATH];
+	unsigned int fontsize;
+	int fw;
+	int fh;
+	int	ch;
+	int x;
+	int y;
+	int charrow;
+	int charcol;
+	FILE	*fontfile;
+
+	if(current_font==-99 || current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) {
+		for(x=0; conio_fontdata[x].desc != NULL; x++) {
+			if(!strcmp(conio_fontdata[x].desc, "Codepage 437 English")) {
+				current_font=x;
+				break;
+			}
+		}
+		if(conio_fontdata[x].desc==NULL)
+			current_font=0;
+	}
+	if(current_font==-1)
+		filename=current_filename;
+	else if(conio_fontdata[current_font].desc==NULL)
+		return(-1);
+
+	pthread_mutex_lock(&vstatlock);
+	fh=vstat.charheight;
+	fw=vstat.charwidth/8+(vstat.charwidth%8?1:0);
+
+	fontsize=fw*fh*256*sizeof(unsigned char);
+
+	if(font)
+		free(font);
+	if((font=(unsigned char *)malloc(fontsize))==NULL) {
+		pthread_mutex_unlock(&vstatlock);
+		return(-1);
+	}
+
+	if(filename != NULL) {
+		if(flength(filename)!=fontsize) {
+			pthread_mutex_unlock(&vstatlock);
+			free(font);
+			return(-1);
+		}
+		if((fontfile=fopen(filename,"rb"))==NULL) {
+			pthread_mutex_unlock(&vstatlock);
+			free(font);
+			return(-1);
+		}
+		if(fread(font, 1, fontsize, fontfile)!=fontsize) {
+			pthread_mutex_unlock(&vstatlock);
+			free(font);
+			fclose(fontfile);
+			return(-1);
+		}
+		fclose(fontfile);
+		current_font=-1;
+		if(filename != current_filename)
+			SAFECOPY(current_filename,filename);
+	}
+	else {
+		switch(vstat.charwidth) {
+			case 8:
+				switch(vstat.charheight) {
+					case 8:
+						if(conio_fontdata[current_font].eight_by_eight==NULL) {
+							pthread_mutex_unlock(&vstatlock);
+							free(font);
+							return(-1);
+						}
+						memcpy(font, conio_fontdata[current_font].eight_by_eight, fontsize);
+						break;
+					case 14:
+						if(conio_fontdata[current_font].eight_by_fourteen==NULL) {
+							pthread_mutex_unlock(&vstatlock);
+							free(font);
+							return(-1);
+						}
+						memcpy(font, conio_fontdata[current_font].eight_by_fourteen, fontsize);
+						break;
+					case 16:
+						if(conio_fontdata[current_font].eight_by_sixteen==NULL) {
+							pthread_mutex_unlock(&vstatlock);
+							free(font);
+							return(-1);
+						}
+						memcpy(font, conio_fontdata[current_font].eight_by_sixteen, fontsize);
+						break;
+					default:
+						pthread_mutex_unlock(&vstatlock);
+						free(font);
+						return(-1);
+				}
+				break;
+			default:
+				pthread_mutex_unlock(&vstatlock);
+				free(font);
+				return(-1);
+		}
+	}
+
+	pthread_mutex_unlock(&vstatlock);
+    return(0);
+}
+
+/* Called from events thread only */
+static void bitmap_draw_cursor(void)
+{
+	int x;
+	int y;
+	int attr;
+	int pixel;
+	int xoffset,yoffset;
+	int start,end;
+	int width;
+
+	if(vstat.blink && !hold_update) {
+		pthread_mutex_lock(&vstatlock);
+		if(vstat.curs_start<=vstat.curs_end) {
+			xoffset=(cio_textinfo.curx+cio_textinfo.winleft-2)*vstat.charwidth;
+			yoffset=(cio_textinfo.cury+cio_textinfo.wintop-2)*vstat.charheight;
+			attr=cio_textinfo.attribute&0x0f;
+			start=vstat.curs_start;
+			end=vstat.curs_end;
+			width=vstat.charwidth;
+			pthread_mutex_unlock(&vstatlock);
+
+			pthread_mutex_lock(&screenlock);
+			for(y=start; y<=end; y++) {
+				pixel=PIXEL_OFFSET(xoffset, yoffset+y);
+				for(x=0; x<width; x++)
+					screen[pixel++]=attr;
+			}
+			pthread_mutex_unlock(&screenlock);
+			send_rectangle(xoffset, yoffset+vstat.curs_start, vstat.charwidth, vstat.curs_end-vstat.curs_start+1,FALSE);
+		}
+		else
+			pthread_mutex_unlock(&vstatlock);
+	}
+}
+
+/* Called from main thread only */
+void bitmap_gotoxy(int x, int y)
+{
+	static int lx=-1,ly=-1;
+
+	pthread_mutex_lock(&vstatlock);
+	if((x != cio_textinfo.curx) || (y != cio_textinfo.cury)) {
+		vstat.curs_col=x+cio_textinfo.winleft-1;
+		vstat.curs_row=y+cio_textinfo.wintop-1;
+		cio_textinfo.curx=x;
+		cio_textinfo.cury=y;
+	}
+	if(!hold_update) {
+		/* Erase old cursor */
+		if(lx != vstat.curs_col || ly != vstat.curs_row)
+			update_rect(lx,ly,1,1,TRUE);
+		/* Draw new cursor */
+		bitmap_draw_cursor();
+		lx=vstat.curs_col;
+		ly=vstat.curs_row;
+	}
+	pthread_mutex_unlock(&vstatlock);
+}
+
+static int bitmap_draw_one_char(unsigned int xpos, unsigned int ypos)
+{
+	int		fg;
+	int		bg;
+	int		xoffset=(xpos-1)*vstat.charwidth;
+	int		yoffset=(ypos-1)*vstat.charheight;
+	int		x;
+	int		y;
+	int		fontoffset;
+	WORD	sch;
+
+	if(!screen)
+		return;
+
+	if(!vstat.vmem)
+		return;
+
+	sch=vstat.vmem[(ypos-1)*cio_textinfo.screenwidth+(xpos-1)];
+	bg=(sch&0x7000)>>12;
+	fg=(sch&0x0f00)>>8;
+	fontoffset=(sch&0xff)*vstat.charheight;
+
+	pthread_mutex_lock(&screenlock);
+	for(y=0; y<vstat.charheight; y++) {
+		for(x=0; x<vstat.charwidth; x++) {
+			if(font[fontoffset] & (0x80 >> x))
+				screen[PIXEL_OFFSET(xoffset+x, yoffset+y)]=fg;
+			else
+				screen[PIXEL_OFFSET(xoffset+x, yoffset+y)]=bg;
+		}
+		fontoffset++;
+	}
+	pthread_mutex_unlock(&screenlock);
+
+	return(0);
+}
+
+static int update_rect(int sx, int sy, int width, int height, int force)
+{
+	int x,y;
+	unsigned int pos;
+	int	redraw_cursor=0;
+	int	lastcharupdated=0;
+	int fullredraw=0;
+	static unsigned short *last_vmem=NULL;
+	static struct video_stats vs;
+	struct rectangle this_rect;
+	int this_rect_used=0;
+	struct rectangle last_rect;
+	int last_rect_used=0;
+
+	if(sx==0 && sy==0 && width==0 && height==0)
+		fullredraw=1;
+
+	if(sx<=0)
+		sx=1;
+	if(sy<=0)
+		sy=1;
+	if(width<=0 || width>cio_textinfo.screenwidth)
+		width=cio_textinfo.screenwidth;
+	if(height<=0 || height>cio_textinfo.screenheight)
+		height=cio_textinfo.screenheight;
+
+	if(vs.cols!=vstat.cols || vs.rows != vstat.rows || last_vmem==NULL) {
+		unsigned short *p;
+
+		p=(unsigned short *)realloc(last_vmem, vstat.cols*vstat.rows*sizeof(unsigned short));
+		if(p==NULL)
+			return(-1);
+		last_vmem=p;
+		memset(last_vmem, 255, vstat.cols*vstat.rows*sizeof(unsigned short));
+		sx=1;
+		sy=1;
+		width=vstat.cols;
+		height=vstat.rows;
+		force=1;
+		vs.cols=vstat.cols;
+		vs.rows=vstat.rows;
+	}
+
+	/* Redraw all chars */
+	if(vstat.blink != vs.blink
+			|| vstat.curs_col!=vs.curs_col
+			|| vstat.curs_row!=vs.curs_row)
+		redraw_cursor=1;
+
+	for(y=0;y<height;y++) {
+		for(x=0;x<width;x++) {
+			pos=(sy+y-1)*vstat.cols+(sx+x-1);
+			if(force
+					|| (last_vmem[pos] != vstat.vmem[pos]) 					/* Different char */
+					|| (vstat.blink != vs.blink && vstat.vmem[pos]>>15) 	/* Blinking char */
+					|| (redraw_cursor && ((vs.curs_col==sx+x && vs.curs_row==sy+y) || (vstat.curs_col==sx+x && vstat.curs_row==sy+y)))	/* Cursor */
+					) {
+				last_vmem[pos] = vstat.vmem[pos];
+				bitmap_draw_one_char(sx+x,sy+y);
+
+				if(lastcharupdated) {
+					this_rect.width+=vstat.charwidth;
+					lastcharupdated++;
+				}
+				else {
+					if(this_rect_used) {
+						send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE);
+					}
+
+					this_rect.x=(sx+x-1)*vstat.charwidth;
+					this_rect.y=(sy+y-1)*vstat.charheight;
+					this_rect.width=vstat.charwidth;
+					this_rect.height=vstat.charheight;
+					this_rect_used=1;
+					lastcharupdated++;
+				}
+				if(!redraw_cursor && sx+x==vstat.curs_col && sy+y==vstat.curs_row)
+					redraw_cursor=1;
+			}
+			else {
+				if(this_rect_used) {
+					send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height,FALSE);
+					this_rect_used=0;
+				}
+				if(last_rect_used) {
+					send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE);
+					last_rect_used=0;
+				}
+
+				lastcharupdated=0;
+			}
+			pos++;
+		}
+		/* If ALL chars in the line were used, add to last_rect */
+		if(lastcharupdated==width) {
+			if(last_rect_used) {
+				last_rect.height += vstat.charheight;
+				this_rect_used=0;
+			}
+			else {
+				last_rect=this_rect;
+				last_rect_used=1;
+				this_rect_used=0;
+			}
+		}
+		/* Otherwise send any stale line buffers */
+		else
+		{
+			if(last_rect_used) {
+				send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE);
+				last_rect_used=0;
+			}
+			if(this_rect_used) {
+				send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height, FALSE);
+				this_rect_used=0;
+			}
+		}
+		lastcharupdated=0;
+	}
+
+	if(this_rect_used) {
+		send_rectangle(this_rect.x, this_rect.y, this_rect.width, this_rect.height, FALSE);
+	}
+	if(last_rect_used) {
+		send_rectangle(last_rect.x, last_rect.y, last_rect.width, last_rect.height, FALSE);
+	}
+
+	/* Did we redraw the cursor?  If so, update position */
+	if(redraw_cursor) {
+		vs.curs_col=vstat.curs_col;
+		vs.curs_row=vstat.curs_row;
+	}
+
+	/* On full redraws, save the last blink value */
+	if(fullredraw) {
+		vs.blink=vstat.blink;
+	}
+
+	if(redraw_cursor)
+		bitmap_draw_cursor();
+
+	return(0);
+}
diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h
new file mode 100644
index 0000000000000000000000000000000000000000..58859654c30d2ecb7d5df6f1152d1eaa3ee5b4be
--- /dev/null
+++ b/src/conio/bitmap_con.h
@@ -0,0 +1,23 @@
+#ifndef BITMAP_CON_H
+#define BITMAP_CON_H
+
+#include "vidmodes.h"
+#include "threadwrap.h"
+
+extern struct video_stats vstat;
+extern pthread_mutex_t vstatlock;
+extern sem_t	drawn_sem;
+
+int bitmap_gettext(int sx, int sy, int ex, int ey, void *fill);
+int bitmap_puttext(int sx, int sy, int ex, int ey, void *fill);
+void bitmap_gotoxy(int x, int y);
+void bitmap_setcursortype(int type);
+int bitmap_setfont(int font, int force);
+int bitmap_getfont(void);
+int bitmap_loadfont(char *filename);
+
+void send_rectangle(int xoffset, int yoffset, int width, int height, int force);
+int bitmap_init_mode(int mode, int *width, int *height);
+int bitmap_init(void	(*drawrect_cb)		(int xpos, int ypos, int width, int height, unsigned char *data));
+
+#endif
diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c
index 3c38ff3ace22b0aa131bba4dfc823107f4610503..a8d6f251eaacd00a67c6dda8aa38ddfcbe463ec0 100644
--- a/src/conio/ciolib.c
+++ b/src/conio/ciolib.c
@@ -63,6 +63,7 @@
  #undef getch
 #endif
 
+#include "bitmap_con.h"
 #include "ansi_cio.h"
 
 CIOLIBEXPORT cioapi_t	cio_api;
@@ -120,11 +121,15 @@ int try_sdl_init(int mode)
 {
 	if(!sdl_initciolib(mode)) {
 		cio_api.mouse=1;
-		cio_api.puttext=sdl_puttext;
-		cio_api.gettext=sdl_gettext;
+		cio_api.puttext=bitmap_puttext;
+		cio_api.gettext=bitmap_gettext;
+		cio_api.gotoxy=bitmap_gotoxy;
+		cio_api.setcursortype=bitmap_setcursortype;
+		cio_api.setfont=bitmap_setfont;
+		cio_api.getfont=bitmap_getfont;
+		cio_api.loadfont=bitmap_loadfont;
+
 		cio_api.kbhit=sdl_kbhit;
-		cio_api.gotoxy=sdl_gotoxy;
-		cio_api.setcursortype=sdl_setcursortype;
 		cio_api.getch=sdl_getch;
 		cio_api.textmode=sdl_textmode;
 		cio_api.showmouse=sdl_showmouse;
@@ -139,9 +144,6 @@ int try_sdl_init(int mode)
 		cio_api.copytext=sdl_copytext;
 		cio_api.getcliptext=sdl_getcliptext;
 #endif
-		cio_api.setfont=sdl_setfont;
-		cio_api.getfont=sdl_getfont;
-		cio_api.loadfont=sdl_loadfont;
 		cio_api.get_window_info=sdl_get_window_info;
 		return(1);
 	}
@@ -153,16 +155,16 @@ int try_sdl_init(int mode)
  #ifndef NO_X
 int try_x_init(int mode)
 {
-	if(!console_init()) {
+	if(!x_init()) {
 		cio_api.mode=CIOLIB_MODE_X;
 		cio_api.mouse=1;
-		cio_api.puttext=x_puttext;
-		cio_api.gettext=x_gettext;
-		cio_api.gotoxy=x_gotoxy;
-		cio_api.setcursortype=x_setcursortype;
-		cio_api.setfont=x_setfont;
-		cio_api.getfont=x_getfont;
-		cio_api.loadfont=x_loadfont;
+		cio_api.puttext=bitmap_puttext;
+		cio_api.gettext=bitmap_gettext;
+		cio_api.gotoxy=bitmap_gotoxy;
+		cio_api.setcursortype=bitmap_setcursortype;
+		cio_api.setfont=bitmap_setfont;
+		cio_api.getfont=bitmap_getfont;
+		cio_api.loadfont=bitmap_loadfont;
 		cio_api.beep=x_beep;
 
 		cio_api.kbhit=x_kbhit;
@@ -594,8 +596,8 @@ CIOLIBEXPORT void CIOLIBCALL ciolib_gettextinfo(struct text_info *info)
                                			 BW40, BW80, C40, C80, or C4350 */
 		info->screenheight=cio_textinfo.screenheight;   /* text screen's height */
 		info->screenwidth=cio_textinfo.screenwidth;    /* text screen's width */
-		info->curx=cio_textinfo.curx-cio_textinfo.winleft+1;           /* x-coordinate in current window */
-		info->cury=cio_textinfo.cury-cio_textinfo.wintop+1;           /* y-coordinate in current window */
+		info->curx=cio_textinfo.curx;           /* x-coordinate in current window */
+		info->cury=cio_textinfo.cury;           /* y-coordinate in current window */
 	}
 }
 
@@ -774,7 +776,7 @@ CIOLIBEXPORT void CIOLIBCALL ciolib_clrscr(void)
 		cio_api.clrscr();
 		return;
 	}
-	
+
 	width=cio_textinfo.winright-cio_textinfo.winleft+1;
 	height=cio_textinfo.winbottom-cio_textinfo.wintop+1;
 	buf=(unsigned char *)alloca(width*height*2);
diff --git a/src/conio/console.c b/src/conio/console.c
deleted file mode 100644
index bf40528f970d6fda278c3d976835978a6b204ca2..0000000000000000000000000000000000000000
--- a/src/conio/console.c
+++ /dev/null
@@ -1,1939 +0,0 @@
-/*
- * Copyright (c) 1992, 1993, 1996
- *      Berkeley Software Design, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Berkeley Software
- *      Design, Inc.
- *
- * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * July 22, 1999
- *
- * To All Licensees, Distributors of Any Version of BSD:
- *
- * As you know, certain of the Berkeley Software Distribution ("BSD") source
- * code files require that further distributions of products containing all or
- * portions of the software, acknowledge within their advertising materials
- * that such products contain software developed by UC Berkeley and its
- * contributors.
- * 
- * Specifically, the provision reads:
- * 
- * "     * 3. All advertising materials mentioning features or use of this software
- *       *    must display the following acknowledgement:
- *       *    This product includes software developed by the University of
- *       *    California, Berkeley and its contributors."
- * 
- * Effective immediately, licensees and distributors are no longer required to
- * include the acknowledgement within advertising materials.  Accordingly, the
- * foregoing paragraph of those BSD Unix files containing it is hereby deleted
- * in its entirety.
- * 
- * William Hoskins
- * Director, Office of Technology Licensing
- * University of California, Berkeley
- *
- *
- */ 
-
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.html									*
- *																			*
- * Anonymous FTP access to the most recent released source is available at	*
- * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
- *																			*
- * Anonymous CVS access to the development source and modification history	*
- * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
- *     (just hit return, no password is necessary)							*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
- *																			*
- * For Synchronet coding style and modification guidelines, see				*
- * http://www.synchro.net/source.html										*
- *																			*
- * You are encouraged to submit any modifications (preferably in Unix diff	*
- * format) via e-mail to mods@synchro.net									*
- *																			*
- * Note: If this box doesn't appear square, then you need to fix your tabs.	*
- ****************************************************************************/
-
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#ifndef STATIC_LINK
-#include <dlfcn.h>
-#endif
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>	/* malloc */
-#include <unistd.h>	/* sysconf() */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-
-#define CONSOLE_CLIPBOARD	XA_PRIMARY
-
-#include <threadwrap.h>
-#include <genwrap.h>
-#include <dirwrap.h>
-
-#include "console.h"
-#include "vidmodes.h"
-#include "allfonts.h"
-
-#include "keys.h"
-#include "mouse.h"
-
-#define CONSOLE_MAX_ROWS	61
-#define CONSOLE_MAX_COLS	81
-
-/* Console definition variables */
-int console_new_mode=NO_NEW_MODE;
-int CurrMode;
-sem_t	console_mode_changed;
-sem_t	copybuf_set;
-sem_t	pastebuf_set;
-sem_t	pastebuf_request;
-sem_t	font_set;
-sem_t	x11_loadfont;
-sem_t	x11_fontloaded;
-int		x_load_font_ret;
-char	font_filename[MAX_PATH];
-int		new_font=-1;
-int		font_force;
-int		setfont_return;
-pthread_mutex_t	copybuf_mutex;
-pthread_mutex_t	lines_mutex;
-char *copybuf=NULL;
-char *pastebuf=NULL;
-sem_t	x11_beep;
-sem_t	x11_title;
-sem_t	x11_name;
-int InitCS;
-int InitCE;
-int FW, FH;
-int FontScale=1;
-#define MAX_SCALE	2
-WORD DpyCols=80;		/* Initialize this so init_mode() is happy */
-BYTE DpyRows;
-BYTE *palette;
-BYTE CursStart;
-BYTE CursEnd;
-WORD *vmem=NULL;
-static int show = 1;
-BYTE CursRow=0;
-BYTE CursCol=0;
-static int x_current_font=-99;
-typedef struct TextLine {
-    WORD	*data;
-    u_char	max_length;	/* Not used, but here for future use */
-	u_char	*exposed;
-} TextLine;
-TextLine *lines = NULL;
-unsigned int	x_pending_mousekeys=0;
-
-/* X Variables */
-Display *dpy=NULL;
-Window win;
-XImage *xi = 0;
-Pixmap pfnt=0;
-Visual *visual;
-unsigned int depth;
-unsigned long black;
-unsigned long white;
-GC gc;
-GC cgc;
-int xfd;
-char window_title[81];
-char window_name[81];
-
-int x11_window_xpos=-1;
-int x11_window_ypos=-1;
-int x11_window_width=-1;
-int x11_window_height=-1;
-
-/* X functions */
-struct x11 {
-	int		(*XChangeGC)	(Display*, GC, unsigned long, XGCValues*);
-	int		(*XCopyPlane)	(Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
-	int		(*XFillRectangle)	(Display*, Drawable, GC, int, int, unsigned int, unsigned int);
-	int		(*XFlush)		(Display*);
-	int		(*XBell)		(Display*, int);
-	int		(*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
-	int		(*XNextEvent)	(Display*, XEvent *);
-	XSizeHints*	(*XAllocSizeHints)(void);
-	void		(*XSetWMNormalHints)	(Display*, Window, XSizeHints*);
-	int		(*XResizeWindow)(Display*, Window, unsigned int, unsigned int);
-	int		(*XMapWindow)	(Display*, Window);
-	int		(*XFree)		(void *data);
-	int		(*XFreePixmap)	(Display*, Pixmap);
-	Pixmap	(*XCreateBitmapFromData)	(Display*, Drawable, _Xconst char*, unsigned int, unsigned int);
-	Status	(*XAllocColor)	(Display*, Colormap, XColor*);
-	Display*(*XOpenDisplay)	(_Xconst char*);
-	Window	(*XCreateSimpleWindow)	(Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
-	GC		(*XCreateGC)	(Display*, Drawable, unsigned long, XGCValues*);
-	int		(*XSelectInput)	(Display*, Window, long);
-	int		(*XStoreName)	(Display*, Window, _Xconst char*);
-	Window	(*XGetSelectionOwner)	(Display*, Atom);
-	int		(*XConvertSelection)	(Display*, Atom, Atom, Atom, Window, Time);
-	int		(*XGetWindowProperty)	(Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **);
-	int		(*XChangeProperty)		(Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int);
-	Status	(*XSendEvent)	(Display*, Window, Bool, long, XEvent*);
-	int		(*XSetSelectionOwner)	(Display*, Atom, Window, Time);	
-	int		(*XSetIconName)	(Display*, Window, _Xconst char *);
-};
-struct x11 x11;
-
-/* X pixel values for the RGB triples */
-DWORD pixels[16];
-
-static	fd_set	fdset;		/* File Descriptors to select on */
-
-/* Keyboard stuff */
-WORD	keybuf[0x25];
-#define	K_NEXT		keybuf[0x21] /* *(WORD *)0x41a */
-#define	K_FREE		keybuf[0x22] /* *(WORD *)0x41c */
-#define	K_BUFSTARTP	keybuf[0x23] /* *(WORD *)0x480 */
-#define	K_BUFENDP	keybuf[0x24] /* *(WORD *)0x482 */
-#define	K_BUFSTART	(&keybuf[K_BUFSTARTP]) /* ((WORD *)(0x400 + K_BUFSTARTP)) */
-#define	K_BUFEND	(&keybuf[K_BUFENDP]) /* ((WORD *)(0x400 + keybuf[3])) */
-#define	K_BUF(i)	keybuf[i] /* *((WORD *)((u_char *)0x400 + (i))) */
-
-BYTE	K1_STATUS;
-#define	K1_RSHIFT	0x01
-#define	K1_LSHIFT	0x02
-#define	K1_SHIFT	0x03
-#define	K1_CTRL		0x04
-#define	K1_ALT		0x08
-#define	K1_SLOCK	0x10		/* Active */
-#define	K1_NLOCK	0x20		/* Active */
-#define	K1_CLOCK	0x40		/* Active */
-#define	K1_INSERT	0x80		/* Active */
-
-BYTE	K2_STATUS;
-#define	K2_LCTRL	0x01
-#define	K2_LALT		0x02
-#define	K2_SYSREQ	0x04
-#define	K2_PAUSE	0x08
-#define	K2_SLOCK	0x10		/* Actually held down */
-#define	K2_NLOCK	0x20		/* Actually held down */
-#define	K2_CLOCK	0x40		/* Actually held down */
-#define	K2_INSERT	0x80		/* Actually held down */
-
-BYTE	K3_STATUS;
-#define	K3_E1		0x01		/* Last code read was e1 */
-#define	K3_E2		0x02		/* Last code read was e2 */
-#define	K3_RCTRL	0x04
-#define	K3_RALT		0x08
-#define	K3_ENHANCED	0x10
-#define	K3_FORCENLOCK	0x20
-#define	K3_TWOBYTE	0x40		/* last code was first of 2 */
-#define	K3_READID	0x80		/* read ID in progress */
-
-BYTE	K4_STATUS;
-#define	K4_SLOCK_LED	0x01
-#define	K4_NLOCK_LED	0x02
-#define	K4_CLOCK_LED	0x04
-#define	K4_ACK		0x10		/* ACK recieved from keyboard */
-#define	K4_RESEND	0x20		/* RESEND recieved from keyboard */
-#define	K4_LED		0x40		/* LED update in progress */
-#define	K4_ERROR	0x80
-
-int flipdelete = 0;		/* Flip meaning of delete and backspace */
-static WORD break_code = 0x00;
-
-static WORD Ascii2Scan[] = {
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
- 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
- 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
- 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
- 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
- 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
- 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
- 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
- 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
- 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
- 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
- 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
- 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
-};
-
-struct {
-    WORD	base;
-    WORD	shift;
-    WORD	ctrl;
-    WORD	alt;
-} ScanCodes[] = {
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key  0 */
-    {	0x011b, 0x011b, 0x011b, 0xffff }, /* key  1 - Escape key */
-    {	0x0231, 0x0221, 0xffff, 0x7800 }, /* key  2 - '1' */
-    {	0x0332, 0x0340, 0x0300, 0x7900 }, /* key  3 - '2' - special handling */
-    {	0x0433, 0x0423, 0xffff, 0x7a00 }, /* key  4 - '3' */
-    {	0x0534, 0x0524, 0xffff, 0x7b00 }, /* key  5 - '4' */
-    {	0x0635, 0x0625, 0xffff, 0x7c00 }, /* key  6 - '5' */
-    {	0x0736, 0x075e, 0x071e, 0x7d00 }, /* key  7 - '6' */
-    {	0x0837, 0x0826, 0xffff, 0x7e00 }, /* key  8 - '7' */
-    {	0x0938, 0x092a, 0xffff, 0x7f00 }, /* key  9 - '8' */
-    {	0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
-    {	0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
-    {	0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
-    {	0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
-    {	0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
-    {	0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
-    {	0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
-    {	0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
-    {	0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
-    {	0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
-    {	0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
-    {	0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
-    {	0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
-    {	0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
-    {	0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
-    {	0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
-    {	0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
-    {	0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
-    {	0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
-    {	0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
-    {	0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
-    {	0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
-    {	0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
-    {	0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
-    {	0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
-    {	0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
-    {	0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
-    {	0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
-    {	0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
-    {	0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
-    {	0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
-    {	0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
-    {	0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
-    {	0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
-    {	0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
-    {	0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
-    {	0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
-    {	0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
-    {	0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
-    {	0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
-    {	0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
-    {	0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
-    {	0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
-    {	0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock -  */
-    {	0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
-    {	0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
-    {	0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
-    {	0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
-    {	0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
-    {	0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
-    {	0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
-    {	0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
-    {	0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
-    {	0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock -  */
-    {	0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
-    {	0x4800, 0x4838, 0x8d00, 0x9800 }, /* key 72 - cursor up */
-    {	0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
-    {	0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
-    {	0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
-    {	0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
-    {	0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
-    {	0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
-    {	0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
-    {	0x5000, 0x5032, 0x9100, 0xa000 }, /* key 80 - cursor down */
-    {	0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
-    {	0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
-    {	0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
-    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
-    {	0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
-    {	0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
-};
-
-#define	HWM	16
-void resize_window(void);
-int KbdEmpty(void);
-int load_font(char *filename, int width, int height, int scale, int *newmode);
-
-void tty_pause()
-{
-	usleep(1000);
-}
-
-volatile int	poll_cnt = 0;
-
-void
-wakeup_poll(void)
-{
-    if (poll_cnt <= 0)
-	poll_cnt = HWM;
-}
-
-void
-reset_poll(void)
-{
-    poll_cnt = HWM;
-}
-
-void
-sleep_poll(void)
-{
-	if (--poll_cnt <= 0) {
-		poll_cnt = 0;
-		while (KbdEmpty() && poll_cnt <= 0) {
-			if (KbdEmpty() && poll_cnt <= 0)
-			tty_pause();
-		}
-	}
-}
-
-static void
-setgc(WORD attr)
-{
-	XGCValues v;
-
-	v.background = pixels[(attr >> 12) & 0x07];
-	if ((!show) && (attr & 0x8000))
-		v.foreground = v.background;
-	else
-		v.foreground = pixels[(attr >> 8) & 0x0f];
-
-	x11.XChangeGC(dpy, gc, GCForeground|GCBackground, &v);
-}
-
-static void
-video_update_text()
-{
-    static int or = -1;
-    static int oc = -1;
-	static int os = -1;
-
-    static char buf[256];
-    int r, c;
-    int attr;
-    XGCValues v;
-	WORD *vmemc;
-	int cursrow;
-	int curscol;
-	int flush=0;
-
-	cursrow=CursRow;
-	curscol=CursCol;
-	wakeup_poll();	/* Wake up anyone waiting on kbd poll */
-
-    vmemc = (WORD *)alloca(DpyCols*(DpyRows+1)*sizeof(WORD));
-	pthread_mutex_lock(&lines_mutex);
-	memcpy(vmemc, vmem, DpyCols*(DpyRows+1)*sizeof(WORD));
-	for (r = 0; r < (DpyRows+1); ++r) {
-		for (c = 0; c < DpyCols; ++c) {
-			if ((lines[r].data[c] != vmemc[r * DpyCols + c]) 
-					|| (lines[r].data[c] & 0x8000 && show != os)
-					|| (lines[r].exposed[c])
-					|| (((r == or && c==oc) || (r == cursrow && c==curscol)) && (or != cursrow || oc !=curscol))) {
-				setgc(vmemc[r * DpyCols + c]  & 0xff00);
-				x11.XCopyPlane(dpy,pfnt,win,gc,0,FH*(vmemc[r * DpyCols + c]&0xff),FW,FH,c*FW+2,r*FH+2,1);
-				lines[r].exposed[c]=0;
-				lines[r].data[c]=vmemc[r * DpyCols + c];
-				flush=1;
-			}
-		}
-
-		reset_poll();
-	}
-	pthread_mutex_unlock(&lines_mutex);
-
-	if (CursStart <= CursEnd && CursEnd <= FH &&
-	    (show != os) && cursrow < (DpyRows+1) &&curscol < DpyCols) {
-
-	    attr = vmemc[cursrow * DpyCols +curscol] & 0xff00;
-	    v.foreground = pixels[(attr >> 8) & 0x0f] ^
-			pixels[(attr >> 12) & 0x07];
-	    if (v.foreground) {
-			v.function = GXxor;
-	    } else {
-			v.foreground = pixels[7];
-			v.function = GXcopy;
-	    }
-	    x11.XChangeGC(dpy, cgc, GCForeground | GCFunction, &v);
-	    x11.XFillRectangle(dpy, win, cgc,
-			   2 +curscol * FW,
-			   2 + cursrow * FH + CursStart * FontScale,
-			   FW, (CursEnd + 1)*FontScale - (CursStart*FontScale));
-		flush=1;
-	}
-
-	or =cursrow;
-	oc =curscol;
-	os =show;
-	if(flush)
-		x11.XFlush(dpy);
-}
-
-void
-video_update()
-{
-	static clock_t	lastupd=-1;
-	static int clock_started=0;
-	clock_t upd;
-
-	upd=msclock();
-	if(!clock_started) {
-		lastupd=upd;
-		clock_started=1;
-	}
-	if(upd-lastupd>(MSCLOCKS_PER_SEC/2)) {
-		show ^= 1;
-		lastupd=upd;
-	}
-
-	/* quick and dirty */
-	video_update_text();
-}
-
-/* Get memory for the text line buffer. */
-void
-get_lines()
-{
-	int i;
-	TextLine *newlines;
-
-	if (lines == NULL) {
-		pthread_mutex_lock(&lines_mutex);
-		lines = (TextLine *)malloc(sizeof(TextLine) * (CONSOLE_MAX_ROWS+1));
-		if (lines == NULL) {
-			fprintf(stderr, "Could not allocate data structure for text lines\n");
-			exit(1);
-		}
-		for (i = 0; i < (CONSOLE_MAX_ROWS+1); ++i) {
-			lines[i].max_length = DpyCols;
-			lines[i].data = (WORD *)malloc(CONSOLE_MAX_COLS * sizeof(WORD));
-			if (lines[i].data == NULL) {
-				fprintf(stderr, "Could not allocate data structure for text lines\n");
-				exit(1);
-			}
-			lines[i].exposed = (u_char *)malloc(CONSOLE_MAX_COLS * sizeof(u_char));
-			if (lines[i].exposed == NULL) {
-				fprintf(stderr, "Could not allocate data structure for text lines\n");
-				exit(1);
-			}
-			memset(lines[i].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char));
-		}
-		pthread_mutex_unlock(&lines_mutex);
-	}
-}
-
-void
-KbdWrite(WORD code)
-{
-	int kf;
-
-	kf = K_FREE + 2;
-	if (kf == K_BUFENDP)
-		kf = K_BUFSTARTP;
-
-	if (kf == K_NEXT) {
-		if(code==CIO_KEY_MOUSE)
-			x_pending_mousekeys++;
-		else {
-			x11.XBell(dpy, 0);
-			return;
-		}
-	}
-	K_BUF(K_FREE) = code;
-	K_FREE = kf;
-}
-
-void tty_beep(void)
-{
-	sem_post(&x11_beep);
-}
-
-void expose_chars(int x, int y, int width, int height)
-{
-	int sx,sy,ex,ey;
-	int r,c;
-
-	sx=x;
-	sx-=2;
-	if(sx<0)
-		sx=0;
-	sy=y;
-	sy-=2;
-	if(sy<0)
-		sy=0;
-	ex=sx+width+FW-1;
-	ey=sy+height+FH-1;
-	sx/=FW;
-	ex/=FW;
-	if(ex>=DpyCols)
-		ex=DpyCols-1;
-	sy/=FH;
-	ey/=FH;
-	if(ey>DpyRows)
-		ey=DpyRows;
-
-	for(r=sy;r<=ey;r++) {
-		pthread_mutex_lock(&lines_mutex);
-		for(c=sx;c<=ex;c++) {
-			lines[r].exposed[c]=1;
-		}
-		pthread_mutex_unlock(&lines_mutex);
-	}
-}
-
-static int
-video_event(XEvent *ev)
-{
-	switch (ev->type) {
-		case ConfigureNotify: {
-				int newFSH=1;
-				int newFSW=1;
-				int	oldFS;
-				int r;
-
-				oldFS=FontScale;
-				x11_window_xpos=ev->xconfigure.x-ev->xconfigure.border_width;
-				x11_window_ypos=ev->xconfigure.y-ev->xconfigure.border_width;
-				x11_window_width=ev->xconfigure.width+ev->xconfigure.border_width*2;
-				x11_window_height=ev->xconfigure.height+ev->xconfigure.border_width*2;
-				if((ev->xconfigure.width == FW * DpyCols + 4)
-						&& (ev->xconfigure.height == FH * (DpyRows+1) + 4))
-					break;
-
-				FW=FW/FontScale;
-				FH=FH/FontScale;
-				newFSH=(ev->xconfigure.width+(FW*DpyCols)/2)/(FW*DpyCols);
-				newFSW=(ev->xconfigure.height+(FH*(DpyRows+1))/2)/(FH*(DpyRows+1));
-				if(newFSW<1)
-					newFSW=1;
-				if(newFSW>MAX_SCALE)
-					newFSW=MAX_SCALE;
-				if(newFSH<1)
-					newFSH=1;
-				if(newFSH>MAX_SCALE)
-					newFSH=MAX_SCALE;
-				if(newFSH<newFSW)
-					FontScale=newFSH;
-				else
-					FontScale=newFSW;
-				load_font(NULL,FW,FH,FontScale,NULL);
-				resize_window();
-				break;
-		}
-		case SelectionClear: {
-				XSelectionClearEvent *req;
-
-				req=&(ev->xselectionclear);
-				pthread_mutex_lock(&copybuf_mutex);
-				if(req->selection==CONSOLE_CLIPBOARD && copybuf!=NULL) {
-					free(copybuf);
-					copybuf=NULL;
-				}
-				pthread_mutex_unlock(&copybuf_mutex);
-				break;
-		}
-		case SelectionNotify: {
-				int format;
-				unsigned long len, bytes_left, dummy;
-				Atom type;
-
-				if(ev->xselection.requestor!=win)
-					break;
-				x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf));
-				if(bytes_left > 0 && format==8)
-					x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf);
-				else
-					pastebuf=NULL;
-
-				/* Set paste buffer */
-				sem_post(&pastebuf_set);
-				sem_wait(&pastebuf_request);
-				x11.XFree(pastebuf);
-				pastebuf=NULL;
-				break;
-		}
-		case SelectionRequest: {
-				XSelectionRequestEvent *req;
-				XEvent respond;
-
-				req=&(ev->xselectionrequest);
-				pthread_mutex_lock(&copybuf_mutex);
-				if(copybuf==NULL) {
-					respond.xselection.property=None;
-				}
-				else {
-					if(req->target==XA_STRING) {
-						x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf));
-						respond.xselection.property=req->property;
-					}
-					else
-						respond.xselection.property=None;
-				}
-				respond.xselection.type=SelectionNotify;
-				respond.xselection.display=req->display;
-				respond.xselection.requestor=req->requestor;
-				respond.xselection.selection=req->selection;
-				respond.xselection.target=req->target;
-				respond.xselection.time=req->time;
-				x11.XSendEvent(dpy,req->requestor,0,0,&respond);
-				pthread_mutex_unlock(&copybuf_mutex);
-				break;
-		}
-		case MotionNotify: {
-				XMotionEvent *me = (XMotionEvent *)ev;
-				me->x -= 2;
-				me->y -= 2;
-				me->x/=FW;
-				me->y/=FH;
-				me->x++;
-				me->y++;
-				if(me->x<1)
-					me->x=1;
-				if(me->y<1)
-					me->y=1;
-				if(me->x>DpyCols)
-					me->x=DpyCols;
-				if(me->y>DpyRows+1)
-					me->y=DpyRows+1;
-				ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y);
-				break;
-	    	}
-		case ButtonRelease: {
-				XButtonEvent *be = (XButtonEvent *)ev;
-				be->x -= 2;
-				be->y -= 2;
-				be->x/=FW;
-				be->y/=FH;
-				be->x++;
-				be->y++;
-				if(be->x<1)
-					be->x=1;
-				if(be->y<1)
-					be->y=1;
-				if(be->x>DpyCols)
-					be->x=DpyCols;
-				if(be->y>DpyRows+1)
-					be->y=DpyRows+1;
-				if (be->button <= 3) {
-					ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y);
-				}
-				break;
-	    	}
-		case ButtonPress: {
-				XButtonEvent *be = (XButtonEvent *)ev;
-				be->x -= 2;
-				be->y -= 2;
-				be->x/=FW;
-				be->y/=FH;
-				be->x++;
-				be->y++;
-				if(be->x<1)
-					be->x=1;
-				if(be->y<1)
-					be->y=1;
-				if(be->x>DpyCols)
-					be->x=DpyCols;
-				if(be->y>DpyRows+1)
-					be->y=DpyRows+1;
-				if (be->button <= 3) {
-					ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y);
-				}
-				break;
-	    	}
-        case NoExpose:
-                break;
-        case GraphicsExpose: {
-			expose_chars(ev->xgraphicsexpose.x,ev->xgraphicsexpose.y
-					,ev->xgraphicsexpose.width,ev->xgraphicsexpose.height);
-			break;
-	    }
-        case Expose: {
-			expose_chars(ev->xexpose.x,ev->xexpose.y,ev->xexpose.width,ev->xexpose.height);
-			break;
-	    }
-	case KeyRelease: {
-		static char buf[128];
-		KeySym ks;
-
-		break_code |= 0x80;
-
-    	    	if (!(ev->xkey.state & ShiftMask)) {
-		    K1_STATUS &= ~K1_LSHIFT;
-		    K1_STATUS &= ~K1_RSHIFT;
-		}
-    	    	if (!(ev->xkey.state & ControlMask)) {
-			K1_STATUS &= ~K1_CTRL;
-			K2_STATUS &= ~K2_LCTRL;
-			K3_STATUS &= ~K3_RCTRL;
-		}
-    	    	if (!(ev->xkey.state & Mod1Mask)) {
-                        K1_STATUS &= ~K1_ALT;
-                        K2_STATUS &= ~K2_LALT;
-                        K3_STATUS &= ~K3_RALT;
-		}
-    	    	if (!(ev->xkey.state & LockMask)) {
-                        K2_STATUS &= ~K2_CLOCK;
-		}
-
-		x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
-		switch (ks) {
-		case XK_Shift_L:
-			K1_STATUS &= ~K1_LSHIFT;
-			break;
-		case XK_Shift_R:
-			K1_STATUS &= ~K1_RSHIFT;
-			break;
-		case XK_Control_L:
-			K1_STATUS &= ~K1_CTRL;
-			K2_STATUS &= ~K2_LCTRL;
-			break;
-		case XK_Control_R:
-			K1_STATUS &= ~K1_CTRL;
-			K3_STATUS &= ~K3_RCTRL;
-			break;
-		case XK_Alt_L:
-			K1_STATUS &= ~K1_ALT;
-			K2_STATUS &= ~K2_LALT;
-			break;
-		case XK_Alt_R:
-			K1_STATUS &= ~K1_ALT;
-			K3_STATUS &= ~K3_RALT;
-			break;
-		case XK_Scroll_Lock:
-			K2_STATUS &= ~K2_SLOCK;
-			break;
-		case XK_Num_Lock:
-			K2_STATUS &= ~K2_NLOCK;
-			break;
-		case XK_Caps_Lock:
-			K2_STATUS &= ~K2_CLOCK;
-			break;
-		case XK_Insert:
-			K2_STATUS &= ~K2_INSERT;
-			break;
-		}
-		return(1);
-	    }
-	case KeyPress: {
-		static char buf[128];
-		KeySym ks;
-		int n;
-		int nlock = 0;
-		WORD scan = 0xffff;
-
-		if (!(ev->xkey.state & ShiftMask)) {
-		    K1_STATUS &= ~K1_LSHIFT;
-		    K1_STATUS &= ~K1_RSHIFT;
-		}
-		if (!(ev->xkey.state & ControlMask)) {
-			K1_STATUS &= ~K1_CTRL;
-			K2_STATUS &= ~K2_LCTRL;
-			K3_STATUS &= ~K3_RCTRL;
-		}
-		if (!(ev->xkey.state & Mod1Mask)) {
-                        K1_STATUS &= ~K1_ALT;
-                        K2_STATUS &= ~K2_LALT;
-                        K3_STATUS &= ~K3_RALT;
-		}
-		if (!(ev->xkey.state & LockMask)) {
-                        K2_STATUS &= ~K2_CLOCK;
-		}
-
-		n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
-
-		switch (ks) {
-		case XK_Shift_L:
-			K1_STATUS |= K1_LSHIFT;
-			break;
-		case XK_Shift_R:
-			K1_STATUS |= K1_RSHIFT;
-			break;
-		case XK_Control_L:
-			K1_STATUS |= K1_CTRL;
-			K2_STATUS |= K2_LCTRL;
-			break;
-		case XK_Control_R:
-			K1_STATUS |= K1_CTRL;
-			K3_STATUS |= K3_RCTRL;
-			break;
-		case XK_Alt_L:
-			K1_STATUS |= K1_ALT;
-			K2_STATUS |= K2_LALT;
-			break;
-		case XK_Alt_R:
-			K1_STATUS |= K1_ALT;
-			K3_STATUS |= K3_RALT;
-			break;
-		case XK_Scroll_Lock:
-			K1_STATUS ^= K1_SLOCK;
-			K2_STATUS |= K2_SLOCK;
-			break;
-		case XK_Num_Lock:
-			K1_STATUS ^= K1_NLOCK;
-			K2_STATUS |= K2_NLOCK;
-			break;
-		case XK_Caps_Lock:
-			K1_STATUS ^= K1_CLOCK;
-			K2_STATUS |= K2_CLOCK;
-			break;
-		case XK_Insert:
-		case XK_KP_Insert:
-			K1_STATUS ^= K1_INSERT;
-			K2_STATUS |= K2_INSERT;
-			scan = 82;
-			goto docode;
-
-		case XK_Escape:
-			scan = 1;
-			goto docode;
-
-		case XK_Tab:
-		case XK_ISO_Left_Tab:
-			scan = 15;
-			goto docode;
-			
-    	    	case XK_Return:
-		case XK_KP_Enter:
-			scan = 28;
-		    	goto docode;
-
-    	    	case XK_Print:
-			scan = 55;
-			goto docode;
-
-		case XK_F1:
-		case XK_F2:
-		case XK_F3:
-		case XK_F4:
-		case XK_F5:
-		case XK_F6:
-		case XK_F7:
-		case XK_F8:
-		case XK_F9:
-		case XK_F10:
-			scan = ks - XK_F1 + 59;
-			goto docode;
-
-    	    	case XK_KP_7:
-			nlock = 1;
-		case XK_Home:
-		case XK_KP_Home:
-			scan = 71;
-			goto docode;
-    	    	case XK_KP_8:
-			nlock = 1;
-		case XK_Up:
-		case XK_KP_Up:
-			scan = 72;
-			goto docode;
-    	    	case XK_KP_9:
-			nlock = 1;
-		case XK_Prior:
-		case XK_KP_Prior:
-			scan = 73;
-			goto docode;
-    	    	case XK_KP_Subtract:
-			scan = 74;
-			goto docode;
-    	    	case XK_KP_4:
-			nlock = 1;
-		case XK_Left:
-		case XK_KP_Left:
-			scan = 75;
-			goto docode;
-    	    	case XK_KP_5:
-			nlock = 1;
-		case XK_Begin:
-		case XK_KP_Begin:
-			scan = 76;
-			goto docode;
-    	    	case XK_KP_6:
-			nlock = 1;
-		case XK_Right:
-		case XK_KP_Right:
-			scan = 77;
-			goto docode;
-    	    	case XK_KP_Add:
-			scan = 78;
-			goto docode;
-    	    	case XK_KP_1:
-			nlock = 1;
-		case XK_End:
-		case XK_KP_End:
-			scan = 79;
-			goto docode;
-    	    	case XK_KP_2:
-			nlock = 1;
-		case XK_Down:
-		case XK_KP_Down:
-			scan = 80;
-			goto docode;
-    	    	case XK_KP_3:
-			nlock = 1;
-		case XK_Next:
-		case XK_KP_Next:
-			scan = 81;
-			goto docode;
-    	    	case XK_KP_0:
-			nlock = 1;
-    	    	/* case XK_Insert: This is above */
-			scan = 82;
-			goto docode;
-
-    	    	case XK_KP_Decimal:
-			nlock = 1;
-			scan = 83;
-			goto docode;
-
-    	    	case XK_Delete:
-    	    	case XK_KP_Delete:
-			scan = flipdelete ? 14 : 83;
-			goto docode;
-
-		case XK_BackSpace:
-			scan = flipdelete ? 83 : 14;
-			goto docode;
-
-    	    	case XK_F11:
-			scan = 87;
-			goto docode;
-    	    	case XK_F12:
-			scan = 88;
-			goto docode;
-
-
-		case XK_KP_Divide:
-			scan = Ascii2Scan['/'];
-			goto docode;
-
-		case XK_KP_Multiply:
-			scan = Ascii2Scan['*'];
-			goto docode;
-
-		default:
-			if (ks < ' ' || ks > '~')
-				break;
-			scan = Ascii2Scan[ks]; 
-    	    	docode:
-			if (nlock)
-			    scan |= 0x100;
-
-    	    	    	if ((scan & ~0x100) > 88) {
-			    scan = 0xffff;
-			    break;
-    	    	    	}
-
-    	    	    	if ((K1_STATUS & K1_SHIFT) || (scan & 0x100)) {
-			    scan = ScanCodes[scan & 0xff].shift;
-			} else if (K1_STATUS & K1_CTRL) {
-			    scan = ScanCodes[scan & 0xff].ctrl;
-			} else if (K1_STATUS & K1_ALT) {
-			    scan = ScanCodes[scan & 0xff].alt;
-			}  else
-			    scan = ScanCodes[scan & 0xff].base;
-
-			break;
-		}
-		if (scan != 0xffff) {
-			break_code = scan >> 8;
-			KbdWrite(scan);
-		}
-		return(1);
-	    }
-
-	default:
-		break;
-	}
-    	return(0);
-}
-
-void
-mouse_event(void *crap)
-{
-	while(1) {
-		if(mouse_wait())
-			KbdWrite(CIO_KEY_MOUSE);
-	}
-}
-
-void
-video_async_event(void *crap)
-{
-	int x;
-	fd_set fdset;
-	XEvent ev;  
-	static struct timeval tv;
-
-	for (;;) {
-		video_update();
-
-		tv.tv_sec=0;
-		tv.tv_usec=54925;
-		/*
-		* Handle any events just sitting around...
-		*/
-		while (QLength(dpy) > 0) {
-			x11.XNextEvent(dpy, &ev);
-			video_event(&ev);
-		}
-
-		FD_ZERO(&fdset);
-		FD_SET(xfd, &fdset);
-
-		x = select(xfd+1, &fdset, 0, 0, &tv);
-
-		switch (x) {
-			case -1:
-				/*
-				* Errno might be wrong, so we just select again.
-				* This could cause a problem is something really
-				* was wrong with select....
-				*/
-
-				/* perror("select"); */
-				break;
-			case 0:
-				if(console_new_mode!=NO_NEW_MODE)
-					init_mode(console_new_mode);
-				if(x_current_font!=new_font) {
-					int oldfont=x_current_font;
-					int newmode=0;
-
-					x_current_font=new_font;
-					if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,&newmode)) {
-						if(font_force && newmode) {
-							init_mode(newmode);
-							sem_wait(&console_mode_changed);
-							if(load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL)) {
-								setfont_return=-1;
-								x_current_font=oldfont;
-								new_font=oldfont;
-								load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL);
-							}
-							else
-								setfont_return=0;
-						}
-						else {
-							setfont_return=-1;
-							x_current_font=oldfont;
-							new_font=oldfont;
-							load_font(NULL,FW/FontScale,FH/FontScale,FontScale,NULL);
-						}
-					}
-					else
-						setfont_return=0;
-					resize_window();
-					sem_post(&font_set);
-				}
-				while(!sem_trywait(&x11_beep))
-					x11.XBell(dpy, 0);
-				if(!sem_trywait(&x11_name))
-					x11.XSetIconName(dpy, win, window_name);
-				if(!sem_trywait(&x11_loadfont)) {
-					int oldfont=x_current_font;
-					x_load_font_ret=load_font(font_filename,FW/FontScale,FH/FontScale,FontScale,NULL);
-					if(x_load_font_ret)
-						x_current_font=oldfont;
-					new_font=x_current_font;
-					resize_window();
-					sem_post(&x11_fontloaded);
-				}
-				if(!sem_trywait(&x11_title))
-					x11.XStoreName(dpy, win, window_title);
-				if(!sem_trywait(&copybuf_set)) {
-					/* Copybuf has been set and isn't NULL */
-					x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime);
-				}
-				if(!sem_trywait(&pastebuf_request)) {
-					Window sowner=None;
-
-					sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD);
-					if(sowner==win) {
-						/* Get your own primary selection */
-						if(copybuf==NULL)
-							pastebuf=NULL;
-						else
-							pastebuf=(unsigned char *)malloc(strlen(copybuf)+1);
-						if(pastebuf!=NULL)
-							strcpy(pastebuf,copybuf);
-						/* Set paste buffer */
-						sem_post(&pastebuf_set);
-						sem_wait(&pastebuf_request);
-						if(pastebuf!=NULL)
-							free(pastebuf);
-						pastebuf=NULL;
-					}
-					else if(sowner!=None) {
-						x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, None, win, CurrentTime);
-					}
-					else {
-						/* Set paste buffer */
-						pastebuf=NULL;
-						sem_post(&pastebuf_set);
-						sem_wait(&pastebuf_request);
-					}
-				}
-				break;
-			default:
-				if (FD_ISSET(xfd, &fdset)) {
-					do {
-						x11.XNextEvent(dpy, &ev);
-						video_event(&ev);
-					} while (QLength(dpy));
-				}
-		}
-	}
-}
-
-/* Resize the window, using information from 'vga_status[]'. This function is
-   called after a mode change. */
-void
-resize_window()
-{
-    XSizeHints *sh;
-	int r;
-
-    sh = x11.XAllocSizeHints();
-    if (sh == NULL) {
-		fprintf(stderr, "Could not get XSizeHints structure");
-		exit(1);
-	}
-
-	sh->base_width = FW * DpyCols + 4;
-	sh->base_height = FH * (DpyRows+1) + 4;
-
-    sh->min_width = (FW/FontScale) * DpyCols + 4;
-	sh->max_width = (FW/FontScale) * MAX_SCALE * DpyCols + 4;
-    sh->min_height = (FH/FontScale) * (DpyRows+1) +4;
-	sh->max_height = (FH/FontScale) * MAX_SCALE * (DpyRows+1) +4;
-    sh->flags = USSize | PMinSize | PMaxSize | PSize;
-
-    x11.XSetWMNormalHints(dpy, win, sh);
-    x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height);
-    x11.XMapWindow(dpy, win);
-
-    x11.XFree(sh);
-
-	if(lines != NULL) {
-		pthread_mutex_lock(&lines_mutex);
-		for (r = 0; r < (CONSOLE_MAX_ROWS+1); ++r) {
-			memset(lines[r].exposed,1,CONSOLE_MAX_COLS * sizeof(u_char));
-		}
-		pthread_mutex_unlock(&lines_mutex);
-	}
-
-    return;
-}
-
-/* Scales a bitmap up to 2x it's current size */
-char *
-scale_bitmap(char *bitmap, int width, int height, int *multiplier)
-{
-	char 	*ret;
-	char	*outbyte;
-	int		pos;
-	int		origbmpsize;
-	int		origbytesperline=1;
-	int		scaledbmpsize;
-	int		scaledbytesperline=1;
-
-	while(origbytesperline*8<width)
-		origbytesperline++;
-
-	if(*multiplier>MAX_SCALE)
-		*multiplier=MAX_SCALE;
-	if(*multiplier < 1)
-		*multiplier=1;
-	while(scaledbytesperline * 8<width*(*multiplier))
-		scaledbytesperline++;
-
-	origbmpsize=origbytesperline*height;
-	scaledbmpsize=scaledbytesperline*height*(*multiplier);
-
-	ret=(char *)malloc(scaledbmpsize);
-	if(ret==NULL)
-		return(NULL);
-	outbyte=ret;
-	for(pos=0;pos<origbmpsize;pos++) {
-		switch(*multiplier) {
-			case 1:
-				*(outbyte++)=bitmap[pos];
-				break;
-			case 2:
-				*outbyte=
-						 ((bitmap[pos]&0x08)<<4)
-						|((bitmap[pos]&0x08)<<3)
-						|((bitmap[pos]&0x04)<<3)
-						|((bitmap[pos]&0x04)<<2)
-						|((bitmap[pos]&0x02)<<2)
-						|((bitmap[pos]&0x02)<<1)
-						|((bitmap[pos]&0x01)<<1)
-						|((bitmap[pos]&0x01));
-				outbyte++;
-				*outbyte=
-						 ((bitmap[pos]&0x80))
-						|((bitmap[pos]&0x80)>>1)
-						|((bitmap[pos]&0x40)>>1)
-						|((bitmap[pos]&0x40)>>2)
-						|((bitmap[pos]&0x20)>>2)
-						|((bitmap[pos]&0x20)>>3)
-						|((bitmap[pos]&0x10)>>3)
-						|((bitmap[pos]&0x10)>>4);
-				outbyte++;
-				*outbyte=
-						 ((bitmap[pos]&0x08)<<4)
-						|((bitmap[pos]&0x08)<<3)
-						|((bitmap[pos]&0x04)<<3)
-						|((bitmap[pos]&0x04)<<2)
-						|((bitmap[pos]&0x02)<<2)
-						|((bitmap[pos]&0x02)<<1)
-						|((bitmap[pos]&0x01)<<1)
-						|((bitmap[pos]&0x01));
-				outbyte++;
-				*outbyte=
-						 ((bitmap[pos]&0x80))
-						|((bitmap[pos]&0x80)>>1)
-						|((bitmap[pos]&0x40)>>1)
-						|((bitmap[pos]&0x40)>>2)
-						|((bitmap[pos]&0x20)>>2)
-						|((bitmap[pos]&0x20)>>3)
-						|((bitmap[pos]&0x10)>>3)
-						|((bitmap[pos]&0x10)>>4);
-				outbyte++;
-				break;
-		}
-	}
-	return(ret);
-}
-
-/* No longer uses X fonts - pass NULL to use VGA 8x16 font */
-int
-load_font(char *filename, int width, int height, int scale, int *newmode)
-{
-    XGCValues gcv;
-	char *font;
-	char *scaledfont;
-	char fontdata[256*16];
-	int	i,j;
-	static char current_filename[MAX_PATH];
-	FILE	*fontfile;
-
-	if(height > 16)
-		return(-1);
-
-	if(x_current_font==-99 || x_current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) {
-		for(i=0; conio_fontdata[i].desc != NULL; i++) {
-			if(!strcmp(conio_fontdata[i].desc, "Codepage 437 English")) {
-				x_current_font=i;
-				break;
-			}
-		}
-		if(conio_fontdata[i].desc==NULL)
-			x_current_font=0;
-		new_font=x_current_font;
-	}
-	if(x_current_font==-1)
-		filename=current_filename;
-	else if(conio_fontdata[x_current_font].desc==NULL)
-		return(-1);
-
-	if(filename != NULL) {
-		int fl=flength(filename);
-
-		if(newmode != NULL) {
-			switch(fl/256) {
-				case 8:
-					*newmode=C80X50;
-					break;
-				case 14:
-					*newmode=C80X28;
-					break;
-				case 16:
-					*newmode=C80;
-					break;
-			}
-		}
-		if(fl!=height*256)
-			return(-1);
-		if((fontfile=fopen(filename,"rb"))==NULL)
-			return(-1);
-		if(fread(fontdata, 1, height*256, fontfile)!=height*256) {
-			fclose(fontfile);
-			return(-1);
-		}
-		fclose(fontfile);
-		x_current_font=new_font=-1;
-		if(filename != current_filename)
-			SAFECOPY(current_filename,filename);
-	}
-	else {
-		if(newmode != NULL) {
-			if(conio_fontdata[x_current_font].eight_by_sixteen!=NULL)
-				*newmode=C80;
-			else if(conio_fontdata[x_current_font].eight_by_fourteen!=NULL)
-				*newmode=C80X28;
-			else if(conio_fontdata[x_current_font].eight_by_eight!=NULL)
-				*newmode=C80X50;
-		}
-		switch(width) {
-			case 8:
-				switch(height) {
-					case 8:
-						font=conio_fontdata[x_current_font].eight_by_eight;
-						break;
-					case 14:
-						font=conio_fontdata[x_current_font].eight_by_fourteen;
-						break;
-					case 16:
-						font=conio_fontdata[x_current_font].eight_by_sixteen;
-						break;
-					default:
-						return(1);
-				}
-				break;
-			default:
-				return(1);
-		}
-		if(font==NULL)
-			return(1);
-		memcpy(fontdata, font, height*256);
-	}
-	FW = width;
-    FH = height;
-	/* Swap bit order... leftmost bit is most significant, X11 wants it the
-	 * other way. */
-	for(i=0; i<256; i++) {
-		for(j=0; j<height; j++) {
-			fontdata[i*height+j]=		((fontdata[i*height+j] & 0x80) >> 7)
-						| ((fontdata[i*height+j] & 0x40) >> 5)
-						| ((fontdata[i*height+j] & 0x20) >> 3)
-						| ((fontdata[i*height+j] & 0x10) >> 1)
-						| ((fontdata[i*height+j] & 0x08) << 1)
-						| ((fontdata[i*height+j] & 0x04) << 3)
-						| ((fontdata[i*height+j] & 0x02) << 5)
-						| ((fontdata[i*height+j] & 0x01) << 7);
-		}
-	}
-	if(pfnt!=0)
-		x11.XFreePixmap(dpy,pfnt);
-	scaledfont=scale_bitmap(fontdata, FW, FH*256, &FontScale);
-	if(scaledfont==NULL)
-		pfnt=x11.XCreateBitmapFromData(dpy, win, fontdata, FW, FH*256);
-	else {
-		FW*=scale;
-		FH*=scale;
-		pfnt=x11.XCreateBitmapFromData(dpy, win, scaledfont, FW, FH*256);
-		free(scaledfont);
-	}
-
-    return(0);
-}
-
-/* Calculate 'pixels[]' from the current DAC table and palette.
-
-   To do: do not use 'pixels[]', use an array of 'XColor's which we can
-   allocate and free on demand. Install a private colormap if necessary. */
-void
-update_pixels()
-{
-    int i;
-	Colormap cm;
-
-    /* We support only 16 colors for now. */
-    for (i = 0; i < 16; i++) {
-		XColor color;
-
-	    color.red   = dac_default[palette[i]].red << 8;
-	    color.green = dac_default[palette[i]].green << 8;
-	    color.blue  = dac_default[palette[i]].blue << 8;
-		if (x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) {
-		    pixels[i] = color.pixel;
-		} else if (i < 7)
-		    pixels[i] = BlackPixel(dpy, DefaultScreen(dpy));
-		else
-		    pixels[i] = WhitePixel(dpy, DefaultScreen(dpy));
-	}
-}
-
-int
-init_mode(int mode)
-{
-    struct video_params vmode;
-    int idx;			/* Index into vmode */
-    int i;
-    WORD oldcols = DpyCols;
-
-    idx = find_vmode(mode);
-    if (idx == -1) {
-		console_new_mode=NO_NEW_MODE;
-		sem_post(&console_mode_changed);
-		return(-1);
-	}
-    vmode = vparams[idx];
-
-    DpyCols = vmode.cols;
-    CursStart = vmode.curs_start;
-    CursEnd = vmode.curs_end;
-    DpyRows = vmode.rows-1;
-    InitCS = CursStart;
-	InitCE = CursEnd;
-
-    vmem = (WORD *)realloc(vmem,vmode.cols*vmode.rows*sizeof(WORD));
-	/* Deal with 40 col doubling */
-	if(oldcols != DpyCols) {
-		if(oldcols == 40)
-			FontScale /= 2;
-		if(DpyCols == 40)
-			FontScale *= 2;
-	}
-
-	if(FontScale > MAX_SCALE)
-		FontScale = MAX_SCALE;
-
-	if(FontScale < 1)
-		FontScale = 1;
-
-    /* Point 'palette[]' to the Attribute Controller space. We will only use
-       the first 16 slots. */
-	palette = palettes[vmode.palette];
-
-    /* Load 'pixels[]' from default DAC values. */
-    update_pixels();
-
-    /* Update font. */
-    if(load_font(NULL,vmode.charwidth,vmode.charheight,FontScale,NULL)) {
-		sem_post(&console_mode_changed);
-		return(-1);
-	}
-
-    /* Resize window if necessary. */
-    resize_window();
-
-	get_lines();
-
-	/* Initialize video memory with black background, white foreground */
-	for (i = 0; i < DpyCols*DpyRows; ++i)
-	    vmem[i] = 0x0700;
-
-	CurrMode=mode;
-	console_new_mode=NO_NEW_MODE;
-
-	cio_textinfo.attribute=7;
-	cio_textinfo.normattr=7;
-	cio_textinfo.currmode=mode;
-	cio_textinfo.screenheight=DpyRows+1;
-	cio_textinfo.screenwidth=DpyCols;
-	cio_textinfo.curx=1;
-	cio_textinfo.cury=1;
-	cio_textinfo.winleft=1;
-	cio_textinfo.wintop=1;
-	cio_textinfo.winright=cio_textinfo.screenwidth;
-	cio_textinfo.winbottom=cio_textinfo.screenheight;
-
-	sem_post(&console_mode_changed);
-    return(0);
-}
-
-/* Get a connection to the X server and create the window. */
-int
-init_window()
-{
-    XGCValues gcv;
-    int i;
-
-	dpy = x11.XOpenDisplay(NULL);
-    if (dpy == NULL) {
-		return(-1);
-	}
-    xfd = ConnectionNumber(dpy);
-
-    /* Create window, but defer setting a size and GC. */
-    win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
-			      1, 1, 2, black, black);
-
-    gcv.foreground = white;
-    gcv.background = black;
-    gc = x11.XCreateGC(dpy, win, GCForeground | GCBackground, &gcv);
-
-    gcv.foreground = 1;
-    gcv.background = 0;
-    gcv.function = GXxor;
-    cgc = x11.XCreateGC(dpy, win, GCForeground|GCBackground|GCFunction, &gcv);
-
-    x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
-		     ExposureMask | ButtonPressMask
-		     | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
-
-	SAFECOPY(window_title,"SyncConsole");
-    x11.XStoreName(dpy, win, window_title);
-
-    /* Get the default visual and depth for later use. */
-    depth = DefaultDepth(dpy, DefaultScreen(dpy));
-    visual = DefaultVisual(dpy, DefaultScreen(dpy));
-
-	return(0);
-}
-
-int
-kbd_init()
-{
-	K_BUFSTARTP = 0x0000;	/* Start of keyboard buffer */
-	K_BUFENDP = 0x20;	/* End of keyboard buffer */
-	K_NEXT = K_FREE = K_BUFSTARTP;
-	
-	return(0);
-}
-
-int
-console_init()
-{
-    int fd;
-    int i;
-	void *dl;
-
-	if(dpy!=NULL)
-		return(0);
-
-#ifdef STATIC_LINK
-	x11.XChangeGC=XChangeGC;
-	x11.XCopyPlane=XCopyPlane;
-	x11.XFillRectangle=XFillRectangle;
-	x11.XFlush=XFlush;
-	x11.XBell=XBell;
-	x11.XLookupString=XLookupString;
-	x11.XNextEvent=XNextEvent;
-	x11.XAllocSizeHints=XAllocSizeHints;
-	x11.XSetWMNormalHints=XSetWMNormalHints;
-	x11.XResizeWindow=XResizeWindow;
-	x11.XMapWindow=XMapWindow;
-	x11.XFree=XFree;
-	x11.XFreePixmap=XFreePixmap;
-	x11.XCreateBitmapFromData=XCreateBitmapFromData;
-	x11.XAllocColor=XAllocColor;
-	x11.XOpenDisplay=XOpenDisplay;
-	x11.XCreateSimpleWindow=XCreateSimpleWindow;
-	x11.XCreateGC=XCreateGC;
-	x11.XSelectInput=XSelectInput;
-	x11.XStoreName=XStoreName;
-	x11.XGetSelectionOwner=XGetSelectionOwner;
-	x11.XConvertSelection=XConvertSelection;
-	x11.XGetWindowProperty=XGetWindowProperty;
-	x11.XChangeProperty=XChangeProperty;
-	x11.XSendEvent=XSendEvent;
-	x11.XSetSelectionOwner=XSetSelectionOwner;
-	x11.XSetIconName=XSetIconName;
-#else
-#if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
-	if((dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL))==NULL)
-#else
-	if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL)
-#endif
-		return(-1);
-	if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XBell=dlsym(dl,"XBell"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XFree=dlsym(dl,"XFree"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-	if((x11.XSetIconName=dlsym(dl,"XSetIconName"))==NULL) {
-		dlclose(dl);
-		return(-1);
-	}
-#endif
-
-	sem_init(&console_mode_changed,0,0);
-	sem_init(&copybuf_set,0,0);
-	sem_init(&pastebuf_request,0,0);
-	sem_init(&pastebuf_set,0,0);
-	sem_init(&x11_beep,0,0);
-	sem_init(&x11_title,0,0);
-	sem_init(&x11_name,0,0);
-	sem_init(&font_set,0,0);
-	sem_init(&x11_loadfont,0,0);
-	sem_init(&x11_fontloaded,0,0);
-
-	pthread_mutex_init(&copybuf_mutex, NULL);
-	pthread_mutex_init(&lines_mutex, NULL);
-
-   	if(kbd_init()) {
-		return(-1);
-	}
-
-    if(video_init()) {
-		return(-1);
-	}
-
-	_beginthread(video_async_event,1<<16,NULL);
-	_beginthread(mouse_event,1<<16,NULL);
-
-	return(0);
-}
-
-int
-video_init()
-{
-    /* If we are running under X, get a connection to the X server and create
-       an empty window of size (1, 1). It makes a couple of init functions a
-       lot easier. */
-    if(init_window())
-		return(-1);
-
-    /* Initialize mode 3 (text, 80x25, 16 colors) */
-    if(init_mode(3)) {
-		return(-1);
-	}
-	sem_wait(&console_mode_changed);
-
-    return(0);
-}
-
-WORD
-KbdPeek()
-{
-	return(K_BUF(K_NEXT));
-}
-
-WORD
-KbdRead()
-{
-	int kf = K_NEXT;
-	WORD	ret;
-
-	K_NEXT = K_NEXT + 2;
-	if (K_NEXT == K_BUFENDP)
-		K_NEXT = K_BUFSTARTP;
-
-	ret=K_BUF(kf);
-	if(x_pending_mousekeys) {
-		KbdWrite(CIO_KEY_MOUSE);
-		x_pending_mousekeys--;
-	}
-	return(ret);
-}
-
-int
-KbdEmpty(void)
-{
-	return(K_NEXT == K_FREE);
-}
-
-int x_nextchar = 0;
-
-int
-tty_read(int flag)
-{
-	int r;
-
-	if ((r = x_nextchar) != 0) {
-		x_nextchar = 0;
-		return(r & 0xff);
-	}
-
-	if (KbdEmpty()) {
-		if (flag & TTYF_BLOCK) {
-			while (KbdEmpty())
-			tty_pause();
-		} else {
-			return(-1);
-		}
-    }
-
-   	r = KbdRead();
-   	if ((r & 0xff) == 0 || (r & 0xff) == 0xff)
-		x_nextchar = r >> 8;
-   	r &= 0xff;
-   	return(r & 0xff);
-}
-
-int
-tty_peek(int flag)
-{
-	int c;
-
-	if (c == x_nextchar)
-	    return(x_nextchar & 0xff);
-
-	if (KbdEmpty()) {
-		if (flag & TTYF_POLL) {
-			sleep_poll();
-			if (KbdEmpty())
-				return(0);
-		} else if (flag & TTYF_BLOCK) {
-			while (KbdEmpty())
-				tty_pause();
-		} else
-			return(0);
-	}
-	c = KbdPeek();
-	return(0xff);
-}
-
-int
-tty_kbhit(void)
-{
-	if(x_nextchar || !KbdEmpty())
-		return(1);
-	return(0);
-}
-
-void x_win_title(const char *title)
-{
-	SAFECOPY(window_title,title);
-	sem_post(&x11_title);
-}
-
-void x_win_name(const char *name)
-{
-	SAFECOPY(window_name,name);
-	sem_post(&x11_name);
-}
-
-int x_load_font(const char *filename)
-{
-	SAFECOPY(font_filename, filename);
-	sem_post(&x11_loadfont);
-	sem_wait(&x11_fontloaded);
-	return(x_load_font_ret);
-}
diff --git a/src/conio/console.h b/src/conio/console.h
deleted file mode 100644
index c87b9dbd100548b4ec8f9bb73acb77772eed7d90..0000000000000000000000000000000000000000
--- a/src/conio/console.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* $Id$ */
-
-/****************************************************************************
- * @format.tab-size 4		(Plain Text/Source Code File Header)			*
- * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
- *																			*
- * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
- *																			*
- * This library is free software; you can redistribute it and/or			*
- * modify it under the terms of the GNU Lesser General Public License		*
- * as published by the Free Software Foundation; either version 2			*
- * of the License, or (at your option) any later version.					*
- * See the GNU Lesser General Public License for more details: lgpl.txt or	*
- * http://www.fsf.org/copyleft/lesser.html									*
- *																			*
- * Anonymous FTP access to the most recent released source is available at	*
- * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
- *																			*
- * Anonymous CVS access to the development source and modification history	*
- * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
- *     (just hit return, no password is necessary)							*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
- *																			*
- * For Synchronet coding style and modification guidelines, see				*
- * http://www.synchro.net/source.html										*
- *																			*
- * You are encouraged to submit any modifications (preferably in Unix diff	*
- * format) via e-mail to mods@synchro.net									*
- *																			*
- * Note: If this box doesn't appear square, then you need to fix your tabs.	*
- ****************************************************************************/
-
-
-#ifndef _CONSOLE_H_
-#define _CONSOLE_H_
-
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/user.h>
-
-#include <gen_defs.h>
-#include <semwrap.h>
-
-#include "vidmodes.h"
-
-extern sem_t	console_mode_changed;
-extern sem_t	copybuf_set;
-extern sem_t	pastebuf_request;
-extern sem_t	pastebuf_set;
-extern sem_t	font_set;
-extern int		new_font;
-extern int		font_force;
-extern int		setfont_return;
-extern pthread_mutex_t	copybuf_mutex;
-extern char *copybuf;
-extern char *pastebuf;
-
-extern int CurrMode;
-
-extern int InitCS;
-extern int InitCE;
-
-extern WORD *vmem;
-
-extern BYTE CursRow;
-extern BYTE CursCol;
-extern BYTE CursStart;
-extern BYTE CursEnd;
-
-extern WORD DpyCols;
-extern BYTE DpyRows;
-
-extern int FH,FW;
-
-extern int x_nextchar;
-
-extern int console_new_mode;
-
-extern int x11_window_xpos;
-extern int x11_window_ypos;
-extern int x11_window_width;
-extern int x11_window_height;
-
-int init_window();
-int video_init();
-int init_mode(int mode);
-int tty_read(int flag);
-int tty_peek(int flag);
-int tty_kbhit(void);
-void tty_beep(void);
-void x_win_title(const char *title);
-int console_init(void);
-int x_load_font(const char *filename);
-
-#define	TTYF_BLOCK	0x00000008
-#define	TTYF_POLL	0x00000010
-#define NO_NEW_MODE -999
-
-#endif
diff --git a/src/conio/sdl_con.c b/src/conio/sdl_con.c
index 9c2c318ba56d498f526ff912f3b7f04d11a50e00..e446c1d8344266f1f8eecd6aec831735d6ca41da 100644
--- a/src/conio/sdl_con.c
+++ b/src/conio/sdl_con.c
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 #if (defined(__MACH__) && defined(__APPLE__))
 #include <Carbon/Carbon.h>
 #endif
@@ -16,6 +14,7 @@
 #include "genwrap.h"
 #include "dirwrap.h"
 #include "xpbeep.h"
+#include "threadwrap.h"
 
 #if (defined CIOLIB_IMPORTS)
  #undef CIOLIB_IMPORTS
@@ -28,50 +27,45 @@
 #include "keys.h"
 #include "vidmodes.h"
 #include "allfonts.h"
+#include "bitmap_con.h"
 
 #include "SDL.h"
 #include "SDL_thread.h"
 
 #include "sdlfuncs.h"
 
-/********************************************************/
-/* Low Level Stuff										*/
-/* This should all be called from the same thread!		*/
-/********************************************************/
+int bitmap_width,bitmap_height;
+
+/* 256 bytes so I can cheat */
+unsigned char		sdl_keybuf[256];		/* Keyboard buffer */
+unsigned char		sdl_key=0;				/* Index into keybuf for next key in buffer */
+unsigned char		sdl_keynext=0;			/* Index into keybuf for next free position */
 
-SDL_Surface	*win=NULL;
-SDL_mutex *sdl_keylock;
-SDL_mutex *sdl_updlock;
-SDL_mutex *sdl_vstatlock;
-SDL_mutex *sdl_ufunc_lock;
-SDL_sem *sdl_key_pending;
-SDL_sem *sdl_init_complete;
-SDL_sem *sdl_ufunc_ret;
-int sdl_ufunc_retval;
-int	sdl_init_good=0;
-int sdl_updated;
 int sdl_exitcode=0;
 
-SDL_Surface *sdl_font=NULL;
-SDL_Surface	*sdl_cursor=NULL;
+SDL_Surface	*win=NULL;
 SDL_Surface	*sdl_icon=NULL;
+SDL_Surface	*new_rect=NULL;
 
-static int lastcursor_x=0;
-static int lastcursor_y=0;
-static int sdl_current_font=-99;
-static int lastfg=-1;
-static int lastbg=-1;
-static unsigned int sdl_pending_mousekeys=0;
-static SDL_Thread *blinker_thread;
+/* *nix copy/paste stuff */
+SDL_sem	*sdl_pastebuf_set;
+SDL_sem	*sdl_pastebuf_copied;
+SDL_mutex	*sdl_copybuf_mutex;
 static SDL_Thread *mouse_thread;
+char *sdl_copybuf=NULL;
+char *sdl_pastebuf=NULL;
+
+SDL_mutex *sdl_ufunc_lock;
+SDL_sem *sdl_ufunc_ret;
+int sdl_ufunc_retval;
 
-struct video_stats vstat;
 int fullscreen=0;
 
-/* 256 bytes so I can cheat */
-unsigned char		sdl_keybuf[256];		/* Keyboard buffer */
-unsigned char		sdl_key=0;				/* Index into keybuf for next key in buffer */
-unsigned char		sdl_keynext=0;			/* Index into keybuf for next free position */
+SDL_sem *sdl_init_complete;
+int	sdl_init_good=0;
+SDL_mutex *sdl_keylock;
+SDL_sem *sdl_key_pending;
+static unsigned int sdl_pending_mousekeys=0;
 
 struct sdl_keyvals {
 	int	keysym
@@ -81,13 +75,12 @@ struct sdl_keyvals {
 		,alt;
 };
 
-struct sdl_drawchar {
-	int  x
-		,y
-		,ch
-		,fg
-		,bg
-		,blink;
+struct update_rect {
+	int		x;
+	int		y;
+	int		width;
+	int		height;
+	unsigned char *data;
 };
 
 enum {
@@ -101,7 +94,6 @@ enum {
 	,SDL_USEREVENT_INIT
 	,SDL_USEREVENT_COPY
 	,SDL_USEREVENT_PASTE
-	,SDL_USEREVENT_LOADFONT
 	,SDL_USEREVENT_QUIT
 };
 
@@ -199,12 +191,6 @@ const struct sdl_keyvals sdl_keyval[] =
 	{SDLK_BACKQUOTE, '`', '~', 0, 0x2900},
 	{0, 0, 0, 0, 0}	/** END **/
 };
-/* *nix copy/paste stuff */
-SDL_sem	*sdl_pastebuf_set;
-SDL_sem	*sdl_pastebuf_copied;
-SDL_mutex	*sdl_copybuf_mutex;
-char *sdl_copybuf=NULL;
-char *sdl_pastebuf=NULL;
 
 #if !defined(NO_X) && defined(__unix__)
 #include "SDL_syswm.h"
@@ -231,7 +217,6 @@ struct x11 {
 struct x11 sdl_x11;
 #endif
 
-/* Called from all threads */
 void sdl_user_func(int func, ...)
 {
 	unsigned int	*i;
@@ -246,13 +231,8 @@ void sdl_user_func(int func, ...)
 	va_start(argptr, func);
 	switch(func) {
 		case SDL_USEREVENT_UPDATERECT:
-			/* Only send event if the last event wasn't already handled */
-			sdl.mutexP(sdl_updlock);
-			if(sdl_updated) {
-				if(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)==1);
-					sdl_updated=0;
-			}
-			sdl.mutexV(sdl_updlock);
+			ev.user.data1=va_arg(argptr, struct update_rect *);
+			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
 			break;
 		case SDL_USEREVENT_SETNAME:
 			if((ev.user.data1=strdup(va_arg(argptr, char *)))==NULL) {
@@ -319,17 +299,6 @@ int sdl_user_func_ret(int func, ...)
 	ev.user.code=func;
 	va_start(argptr, func);
 	switch(func) {
-		case SDL_USEREVENT_LOADFONT:
-			p=va_arg(argptr, char *);
-			if(p!=NULL) {
-				if((ev.user.data1=strdup(p))==NULL) {
-					va_end(argptr);
-					return(-1);
-				}
-			}
-			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
-			passed=TRUE;
-			break;
 		case SDL_USEREVENT_QUIT:
 			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
 			passed=TRUE;
@@ -450,22 +419,21 @@ char *sdl_getcliptext(void)
 	return(ret);
 }
 
-/* Blinker Thread */
-int sdl_blinker_thread(void *data)
+void sdl_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data)
 {
-	while(1) {
-		SLEEP(500);
-		sdl.mutexP(sdl_vstatlock);
-		if(vstat.blink)
-			vstat.blink=FALSE;
-		else
-			vstat.blink=TRUE;
-		sdl.mutexV(sdl_vstatlock);
-		sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0);
+	struct update_rect *rect;
+
+	rect=(struct update_rect *)malloc(sizeof(struct update_rect));
+	if(sdl_init_good) {
+		rect->x=xoffset;
+		rect->y=yoffset;
+		rect->width=width;
+		rect->height=height;
+		rect->data=data;
+		sdl_user_func(SDL_USEREVENT_UPDATERECT, rect);
 	}
 }
 
-/* Called from main thread only (Passes Event) */
 int sdl_init_mode(int mode)
 {
     struct video_params vmode;
@@ -473,10 +441,7 @@ int sdl_init_mode(int mode)
     int i;
     int oldcols=vstat.cols;
 
-	sdl.mutexP(sdl_vstatlock);
-
-	if(load_vmode(&vstat, mode))
-		return(-1);
+	bitmap_init_mode(mode, &bitmap_width, &bitmap_height);
 
 	/* Deal with 40 col doubling */
 	if(oldcols != vstat.cols) {
@@ -491,49 +456,9 @@ int sdl_init_mode(int mode)
 
 	sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols*vstat.scaling, vstat.charheight*vstat.rows*vstat.scaling);
 
-	/* Initialize video memory with black background, white foreground */
-	for (i = 0; i < vstat.cols*vstat.rows; ++i)
-	    vstat.vmem[i] = 0x0700;
-	vstat.currattr=7;
-
-	cio_textinfo.attribute=7;
-	cio_textinfo.normattr=7;
-	cio_textinfo.currmode=mode;
-	cio_textinfo.screenheight=vstat.rows;
-	cio_textinfo.screenwidth=vstat.cols;
-	cio_textinfo.curx=1;
-	cio_textinfo.cury=1;
-	cio_textinfo.winleft=1;
-	cio_textinfo.wintop=1;
-	cio_textinfo.winright=cio_textinfo.screenwidth;
-	cio_textinfo.winbottom=cio_textinfo.screenheight;
-
-	vstat.mode=mode;
-	sdl.mutexV(sdl_vstatlock);
-
-	sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0);
-
     return(0);
 }
 
-/* Called from main thread only (Passes Event) */
-int sdl_draw_char(unsigned short vch, int xpos, int ypos, int update)
-{
-	sdl.mutexP(sdl_vstatlock);
-	vstat.vmem[ypos*vstat.cols+xpos]=vch;
-	sdl.mutexV(sdl_vstatlock);
-
-	if(update) {
-#if 0	/* Currently, an update always updates the whole screen... so don't hold the mutex */
-		sdl_user_func(SDL_USEREVENT_UPDATERECT,xpos*vstat.charwidth*vstat.scaling,ypos*vstat.charheight*vstat.scaling,vstat.charwidth*vstat.scaling,vstat.charheight*vstat.scaling);
-#else
-		sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0);
-#endif
-	}
-
-	return(0);
-}
-
 /* Called from main thread only (Passes Event) */
 int sdl_init(int mode)
 {
@@ -544,15 +469,8 @@ int sdl_init(int mode)
 	if(init_sdl_video())
 		return(-1);
 
-	sdl.mutexP(sdl_vstatlock);
-	vstat.vmem=NULL;
-	vstat.scaling=1;
-	vstat.cols=80;		/* Initialize this so sdl_init_mode() is happy */
-	sdl.mutexV(sdl_vstatlock);
+	bitmap_init(sdl_drawrect);
 
-	sdl.mutexP(sdl_updlock);
-	sdl_updated=1;
-	sdl.mutexV(sdl_updlock);
 	if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
 		fullscreen=1;
 	sdl_init_mode(3);
@@ -609,83 +527,6 @@ int sdl_init(int mode)
 	return(-1);
 }
 
-/********************************************************/
-/* High Level Stuff										*/
-/********************************************************/
-
-/* Called from main thread only (Passes Event) */
-int sdl_puttext(int sx, int sy, int ex, int ey, void *fill)
-{
-	int x,y;
-	unsigned char *out;
-	WORD	sch;
-	struct text_info	ti;
-
-	gettextinfo(&ti);
-
-	if(		   sx < 1
-			|| sy < 1
-			|| ex < 1
-			|| ey < 1
-			|| sx > ti.screenwidth
-			|| sy > ti.screenheight
-			|| sx > ex
-			|| sy > ey
-			|| ex > ti.screenwidth
-			|| ey > ti.screenheight
-			|| fill==NULL)
-		return(0);
-
-	out=fill;
-	sdl.mutexP(sdl_vstatlock);
-	for(y=sy-1;y<ey;y++) {
-		for(x=sx-1;x<ex;x++) {
-			sch=*(out++);
-			sch |= (*(out++))<<8;
-			vstat.vmem[y*vstat.cols+x]=sch;
-		}
-	}
-	sdl.mutexV(sdl_vstatlock);
-	sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0);
-	return(1);
-}
-
-/* Called from main thread only */
-int sdl_gettext(int sx, int sy, int ex, int ey, void *fill)
-{
-	int x,y;
-	unsigned char *out;
-	WORD	sch;
-	struct text_info	ti;
-
-	gettextinfo(&ti);
-
-	if(		   sx < 1
-			|| sy < 1
-			|| ex < 1
-			|| ey < 1
-			|| sx > ti.screenwidth
-			|| sy > ti.screenheight
-			|| sx > ex
-			|| sy > ey
-			|| ex > ti.screenwidth
-			|| ey > ti.screenheight
-			|| fill==NULL)
-		return(0);
-
-	out=fill;
-	sdl.mutexP(sdl_vstatlock);
-	for(y=sy-1;y<ey;y++) {
-		for(x=sx-1;x<ex;x++) {
-			sch=vstat.vmem[y*vstat.cols+x];
-			*(out++)=sch & 0xff;
-			*(out++)=sch >> 8;
-		}
-	}
-	sdl.mutexV(sdl_vstatlock);
-	return(1);
-}
-
 /* Called from main thread only */
 int sdl_kbhit(void)
 {
@@ -697,41 +538,6 @@ int sdl_kbhit(void)
 	return(ret);
 }
 
-/* Called from main thread only */
-void sdl_gotoxy(int x, int y)
-{
-	sdl.mutexP(sdl_vstatlock);
-	if((x-1 != vstat.curs_col) || (y-1 !=vstat.curs_row)) {
-		vstat.curs_row=y-1;
-		vstat.curs_col=x-1;
-		sdl_user_func(SDL_USEREVENT_UPDATERECT,0,0,0,0);
-	}
-	cio_textinfo.curx=x;
-	cio_textinfo.cury=y;
-	sdl.mutexV(sdl_vstatlock);
-}
-
-/* Called from main thread only */
-void sdl_setcursortype(int type)
-{
-	sdl.mutexP(sdl_vstatlock);
-	switch(type) {
-		case _NOCURSOR:
-			vstat.curs_start=0xff;
-			vstat.curs_end=0;
-			break;
-		case _SOLIDCURSOR:
-			vstat.curs_start=0;
-			vstat.curs_end=vstat.charheight-1;
-			break;
-		default:
-		    vstat.curs_start = vstat.default_curs_start;
-		    vstat.curs_end = vstat.default_curs_end;
-			break;
-	}
-	sdl.mutexV(sdl_vstatlock);
-}
-
 /* Called from main thread only */
 int sdl_getch(void)
 {
@@ -790,68 +596,6 @@ int sdl_hidemouse(void)
 	return(0);
 }
 
-int sdl_loadfont(char *filename)
-{
-	int retval;
-
-	retval=sdl_user_func_ret(SDL_USEREVENT_LOADFONT,filename);
-	return(retval);
-}
-
-int sdl_setfont(int font, int force)
-{
-	int changemode=0;
-	int	newmode=-1;
-
-	if(font < 0 || font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2))
-		return(-1);
-
-	if(conio_fontdata[font].eight_by_sixteen!=NULL)
-		newmode=C80;
-	else if(conio_fontdata[font].eight_by_fourteen!=NULL)
-		newmode=C80X28;
-	else if(conio_fontdata[font].eight_by_eight!=NULL)
-		newmode=C80X50;
-
-	switch(vstat.charheight) {
-		case 8:
-			if(conio_fontdata[font].eight_by_eight==NULL) {
-				if(force)
-					return(-1);
-				else
-					changemode=1;
-			}
-			break;
-		case 14:
-			if(conio_fontdata[font].eight_by_fourteen==NULL) {
-				if(force)
-					return(-1);
-				else
-					changemode=1;
-			}
-			break;
-		case 16:
-			if(conio_fontdata[font].eight_by_sixteen==NULL) {
-				if(force)
-					return(-1);
-				else
-					changemode=1;
-			}
-			break;
-	}
-	if(changemode && newmode==-1)
-		return(-1);
-	sdl_current_font=font;
-	if(changemode)
-		sdl_init_mode(3);
-	return(sdl_user_func_ret(SDL_USEREVENT_LOADFONT,NULL));
-}
-
-int sdl_getfont(void)
-{
-	return(sdl_current_font);
-}
-
 int sdl_get_window_info(int *width, int *height, int *xpos, int *ypos)
 {
 	if(width)
@@ -872,9 +616,7 @@ void sdl_add_key(unsigned int keyval)
 	if(keyval==0xa600) {
 		fullscreen=!fullscreen;
 		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
-		sdl.mutexP(sdl_vstatlock);
 		sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols, vstat.charheight*vstat.rows);
-		sdl.mutexV(sdl_vstatlock);
 		return;
 	}
 	if(keyval <= 0xffff) {
@@ -902,330 +644,22 @@ void sdl_add_key(unsigned int keyval)
 	}
 }
 
-/* Called from event thread only */
-int sdl_load_font(char *filename)
-{
-	static char current_filename[MAX_PATH];
-	unsigned char *font;
-	unsigned int fontsize;
-	int fw;
-	int fh;
-	int	ch;
-	int x;
-	int y;
-	int charrow;
-	int charcol;
-	SDL_Rect r;
-	FILE	*fontfile;
-
-	if(sdl_current_font==-99 || sdl_current_font>(sizeof(conio_fontdata)/sizeof(struct conio_font_data_struct)-2)) {
-		for(x=0; conio_fontdata[x].desc != NULL; x++) {
-			if(!strcmp(conio_fontdata[x].desc, "Codepage 437 English")) {
-				sdl_current_font=x;
-				break;
-			}
-		}
-		if(conio_fontdata[x].desc==NULL)
-			sdl_current_font=0;
-	}
-	if(sdl_current_font==-1)
-		filename=current_filename;
-	else if(conio_fontdata[sdl_current_font].desc==NULL)
-		return(-1);
-
-	sdl.mutexP(sdl_vstatlock);
-	fh=vstat.charheight;
-	fw=vstat.charwidth/8+(vstat.charwidth%8?1:0);
-
-	fontsize=fw*fh*256*sizeof(unsigned char);
-
-	if((font=(unsigned char *)malloc(fontsize))==NULL) {
-		sdl.mutexV(sdl_vstatlock);
-		return(-1);
-	}
-
-	if(filename != NULL) {
-		if(flength(filename)!=fontsize) {
-			sdl.mutexV(sdl_vstatlock);
-			free(font);
-			return(-1);
-		}
-		if((fontfile=fopen(filename,"rb"))==NULL) {
-			sdl.mutexV(sdl_vstatlock);
-			free(font);
-			return(-1);
-		}
-		if(fread(font, 1, fontsize, fontfile)!=fontsize) {
-			sdl.mutexV(sdl_vstatlock);
-			free(font);
-			fclose(fontfile);
-			return(-1);
-		}
-		fclose(fontfile);
-		sdl_current_font=-1;
-		if(filename != current_filename)
-			SAFECOPY(current_filename,filename);
-	}
-	else {
-		switch(vstat.charwidth) {
-			case 8:
-				switch(vstat.charheight) {
-					case 8:
-						if(conio_fontdata[sdl_current_font].eight_by_eight==NULL) {
-							sdl.mutexV(sdl_vstatlock);
-							free(font);
-							return(-1);
-						}
-						memcpy(font, conio_fontdata[sdl_current_font].eight_by_eight, fontsize);
-						break;
-					case 14:
-						if(conio_fontdata[sdl_current_font].eight_by_fourteen==NULL) {
-							sdl.mutexV(sdl_vstatlock);
-							free(font);
-							return(-1);
-						}
-						memcpy(font, conio_fontdata[sdl_current_font].eight_by_fourteen, fontsize);
-						break;
-					case 16:
-						if(conio_fontdata[sdl_current_font].eight_by_sixteen==NULL) {
-							sdl.mutexV(sdl_vstatlock);
-							free(font);
-							return(-1);
-						}
-						memcpy(font, conio_fontdata[sdl_current_font].eight_by_sixteen, fontsize);
-						break;
-					default:
-						sdl.mutexV(sdl_vstatlock);
-						free(font);
-						return(-1);
-				}
-				break;
-			default:
-				sdl.mutexV(sdl_vstatlock);
-				free(font);
-				return(-1);
-		}
-	}
-
-	if(sdl_font!=NULL)
-		sdl.FreeSurface(sdl_font);
-	sdl_font=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*256*vstat.scaling, 8, 0, 0, 0, 0);
-	if(sdl_font == NULL) {
-		sdl.mutexV(sdl_vstatlock);
-		free(font);
-    	return(-1);
-	}
-	else {
-		for(ch=0; ch<256; ch++) {
-			for(charrow=0; charrow<vstat.charheight; charrow++) {
-				for(charcol=0; charcol<vstat.charwidth; charcol++) {
-					if(font[(ch*vstat.charheight+charrow)*fw+(charcol/8)] & (0x80 >> (charcol%8))) {
-						r.x=charcol*vstat.scaling;
-						r.y=(ch*vstat.charheight+charrow)*vstat.scaling;
-						r.w=vstat.scaling;
-						r.h=vstat.scaling;
-						sdl.FillRect(sdl_font, &r, 1);
-					}
-				}
-			}
-		}
-	}
-	sdl.mutexV(sdl_vstatlock);
-	free(font);
-	lastfg=-1;
-	lastbg=-1;
-    return(0);
-}
-
 /* Called from events thread only */
-int sdl_setup_colours(SDL_Surface *surf, int xor)
+int sdl_setup_colours(SDL_Surface *surf)
 {
 	int i;
 	int ret=0;
-	SDL_Color	co[16];
+	SDL_Color	co[sizeof(dac_default)/sizeof(struct dac_colors)];
 
-	sdl.mutexP(sdl_vstatlock);
-	for(i=0; i<16; i++) {
-		co[i^xor].r=dac_default[vstat.palette[i]].red;
-		co[i^xor].g=dac_default[vstat.palette[i]].green;
-		co[i^xor].b=dac_default[vstat.palette[i]].blue;
+	for(i=0; i<(sizeof(dac_default)/sizeof(struct dac_colors)); i++) {
+		co[i].r=dac_default[vstat.palette[i]].red;
+		co[i].g=dac_default[vstat.palette[i]].green;
+		co[i].b=dac_default[vstat.palette[i]].blue;
 	}
-	sdl.mutexV(sdl_vstatlock);
-	sdl.SetColors(surf, co, 0, 16);
+	sdl.SetColors(surf, co, 0, sizeof(dac_default)/sizeof(struct dac_colors));
 	return(ret);
 }
 
-/* Called from events thread only */
-void sdl_draw_cursor(void)
-{
-	SDL_Rect	src;
-	SDL_Rect	dst;
-	int	x;
-	int	y;
-
-	sdl.mutexP(sdl_vstatlock);
-	if(vstat.blink && vstat.curs_start<=vstat.curs_end) {
-		dst.x=0;
-		dst.y=0;
-		src.x=vstat.curs_col*vstat.charwidth*vstat.scaling;
-		src.y=(vstat.curs_row*vstat.charheight+vstat.curs_start)*vstat.scaling;
-		src.w=dst.w=vstat.charwidth*vstat.scaling;
-		src.h=dst.h=(vstat.curs_end-vstat.curs_start+1)*vstat.scaling;
-		sdl_setup_colours(sdl_cursor, 0);
-		sdl.BlitSurface(win, &src, sdl_cursor, &dst);
-		sdl_setup_colours(sdl_cursor, vstat.currattr&0x07);
-		sdl.BlitSurface(sdl_cursor, &dst, win, &src);
-		lastcursor_x=vstat.curs_col;
-		lastcursor_y=vstat.curs_row;
-	}
-	sdl.mutexV(sdl_vstatlock);
-}
-
-/* Called from event thread */
-/* ONLY Called from sdl_full_screen_redraw() which holds the mutex... */
-int sdl_draw_one_char(unsigned short sch, unsigned int x, unsigned int y, struct video_stats *vs)
-{
-	SDL_Color	co;
-	SDL_Rect	src;
-	SDL_Rect	dst;
-	unsigned char	ch;
-
-	ch=(sch >> 8) & 0x0f;
-	if(lastfg!=ch) {
-		co.r=dac_default[vs->palette[ch]].red;
-		co.g=dac_default[vs->palette[ch]].green;
-		co.b=dac_default[vs->palette[ch]].blue;
-		sdl.SetColors(sdl_font, &co, 1, 1);
-		lastfg=ch;
-	}
-	ch=(sch >> 12) & 0x07;
-	if(lastbg!=ch) {
-		co.r=dac_default[vs->palette[ch]].red;
-		co.g=dac_default[vs->palette[ch]].green;
-		co.b=dac_default[vs->palette[ch]].blue;
-		sdl.SetColors(sdl_font, &co, 0, 1);
-		lastbg=ch;
-	}
-	dst.x=x*vs->charwidth*vs->scaling;
-	dst.y=y*vs->charheight*vs->scaling;
-	dst.w=vs->charwidth*vs->scaling;
-	dst.h=vs->charheight*vs->scaling;
-	src.x=0;
-	src.w=vs->charwidth*vs->scaling;
-	src.h=vs->charheight*vs->scaling;
-	src.y=vs->charheight*vs->scaling;
-	ch=sch & 0xff;
-	if((sch >>15) && !(vs->blink))
-		src.y *= ' ';
-	else
-		src.y *= ch;
-	if(sdl_font != NULL)
-		sdl.BlitSurface(sdl_font, &src, win, &dst);
-	return(0);
-}
-
-
-/* Called from event thread only, */
-int sdl_full_screen_redraw(int force)
-{
-	static int last_blink;
-	int x;
-	int y;
-	unsigned int pos;
-	unsigned short *p;
-	unsigned short *newvmem;
-	static unsigned short *vmemcopies[2]={ NULL, NULL };
-	static SDL_Rect	*rects=NULL;
-	static int this_new=0;
-	static unsigned short *last_vmem=NULL;
-	int rcount=0;
-	static struct video_stats vs;
-	int	redraw_cursor=0;
-	int	lastlineupdated=0;
-	int	lastcharupdated=0;
-
-	sdl.mutexP(sdl_vstatlock);
-	if(vs.cols!=vstat.cols || vs.rows != vstat.rows || vmemcopies[0]==NULL || vmemcopies[1]==NULL || rects==NULL) {
-		FREE_AND_NULL(vmemcopies[0]);
-		if((vmemcopies[0]=(unsigned short *)malloc(vstat.cols*vstat.rows*sizeof(unsigned short)))==NULL) {
-			sdl.mutexV(sdl_vstatlock);
-			return(-1);
-		}
-		FREE_AND_NULL(vmemcopies[1]);
-		if((vmemcopies[1]=(unsigned short *)malloc(vstat.cols*vstat.rows*sizeof(unsigned short)))==NULL) {
-			sdl.mutexV(sdl_vstatlock);
-			return(-1);
-		}
-		FREE_AND_NULL(rects);
-		if((rects=(SDL_Rect *)malloc(sizeof(SDL_Rect)*vstat.cols*vstat.rows))==NULL) {
-			sdl.mutexV(sdl_vstatlock);
-			return(-1);
-		}
-	}
-	this_new = (this_new+1) % 2;
-	newvmem=vmemcopies[this_new];
-	memcpy(&vs, &vstat, sizeof(vs));
-	memcpy(newvmem, vs.vmem, vs.cols*vs.rows*sizeof(unsigned short));
-	sdl.mutexV(sdl_vstatlock);
-	sdl.mutexP(sdl_updlock);
-	sdl_updated=1;
-	sdl.mutexV(sdl_updlock);
-	/* Redraw all chars */
-	pos=0;
-	if(last_vmem==NULL)
-		force=1;
-	if(last_blink != vs.blink
-			|| lastcursor_x!=vs.curs_col
-			|| lastcursor_y!=vs.curs_row)
-		redraw_cursor=1;
-	for(y=0;y<vs.rows;y++) {
-		for(x=0;x<vs.cols;x++) {
-			if(force
-					|| (last_vmem[pos] != newvmem[pos]) 
-					|| (last_blink != vs.blink && newvmem[pos]>>15) 
-					|| (redraw_cursor && ((lastcursor_x==x && lastcursor_y==y) || (vs.curs_col==x && vs.curs_row==y)))
-					) {
-				sdl_draw_one_char(newvmem[pos],x,y,&vs);
-				if(lastcharupdated) {
-					rects[rcount-1].w+=vs.charwidth*vs.scaling;
-					lastcharupdated++;
-				}
-				else {
-					rects[rcount].x=x*vs.charwidth*vs.scaling;
-					rects[rcount].y=y*vs.charheight*vs.scaling;
-					rects[rcount].w=vs.charwidth*vs.scaling;
-					rects[rcount++].h=vs.charheight*vs.scaling;
-					lastcharupdated++;
-				}
-				if(!redraw_cursor && x==vs.curs_col && y==vs.curs_row)
-					redraw_cursor=1;
-			}
-			else
-				lastcharupdated=0;
-			pos++;
-		}
-		if(lastcharupdated==vs.cols) {
-			if(lastlineupdated) {
-				rcount--;
-				rects[rcount-1].h+=vs.charheight*vs.scaling;
-			}
-			else
-				lastlineupdated=1;
-		}
-		else
-			lastlineupdated=0;
-		lastcharupdated=0;
-	}
-	last_blink=vs.blink;
-	last_vmem=newvmem;
-
-	if(redraw_cursor)
-		sdl_draw_cursor();
-	if(rcount)
-		sdl.UpdateRects(win,rcount,rects);
-	return(0);
-}
-
 unsigned int cp437_convert(unsigned int unicode)
 {
 	if(unicode <= 0x80)
@@ -1608,28 +1042,20 @@ int sdl_video_event_thread(void *data)
 					case SDL_MOUSEMOTION:
 						if(!ciolib_mouse_initialized)
 							break;
-						sdl.mutexP(sdl_vstatlock);
 						ciomouse_gotevent(CIOLIB_MOUSE_MOVE,ev.motion.x/(vstat.charwidth*vstat.scaling)+1,ev.motion.y/(vstat.charheight*vstat.scaling)+1);
-						sdl.mutexV(sdl_vstatlock);
 						break;
 					case SDL_MOUSEBUTTONDOWN:
 						if(!ciolib_mouse_initialized)
 							break;
 						switch(ev.button.button) {
 							case SDL_BUTTON_LEFT:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 							case SDL_BUTTON_MIDDLE:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 							case SDL_BUTTON_RIGHT:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 						}
 						break;
@@ -1638,19 +1064,13 @@ int sdl_video_event_thread(void *data)
 							break;
 						switch(ev.button.button) {
 							case SDL_BUTTON_LEFT:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 							case SDL_BUTTON_MIDDLE:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 							case SDL_BUTTON_RIGHT:
-								sdl.mutexP(sdl_vstatlock);
 								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 						}
 						break;
@@ -1659,7 +1079,7 @@ int sdl_video_event_thread(void *data)
 						return(sdl_exitcode);
 					case SDL_VIDEORESIZE:
 						if(ev.resize.w > 0 && ev.resize.h > 0) {
-							sdl.mutexP(sdl_vstatlock);
+							pthread_mutex_lock(&vstatlock);
 							vstat.scaling=(int)(ev.resize.w/(vstat.charwidth*vstat.cols));
 							if(vstat.scaling < 1)
 								vstat.scaling=1;
@@ -1686,25 +1106,27 @@ int sdl_video_event_thread(void *data)
 										sdl_using_quartz=TRUE;
 								}
 	#endif
-
-								if(sdl_cursor!=NULL)
-									sdl.FreeSurface(sdl_cursor);
-								sdl_cursor=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*vstat.scaling, 8, 0, 0, 0, 0);
-						    	/* Update font. */
-						    	sdl_load_font(NULL);
-						    	sdl_setup_colours(win,0);
-								sdl_full_screen_redraw(TRUE);
+								if(new_rect)
+									sdl.FreeSurface(new_rect);
+								new_rect=sdl.CreateRGBSurface(SDL_SWSURFACE
+										, vstat.charwidth*vstat.cols*vstat.scaling
+										, vstat.charheight*vstat.rows*vstat.scaling
+										, 8, 0, 0, 0, 0);
+								pthread_mutex_unlock(&vstatlock);
+						    	sdl_setup_colours(win);
+						    	sdl_setup_colours(new_rect);
+								send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
 							}
 							else if(sdl_init_good) {
+								pthread_mutex_unlock(&vstatlock);
 								ev.type=SDL_QUIT;
 								sdl_exitcode=1;
 								sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
 							}
-							sdl.mutexV(sdl_vstatlock);
 						}
 						break;
 					case SDL_VIDEOEXPOSE:
-						sdl_full_screen_redraw(TRUE);
+						send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
 						break;
 					case SDL_USEREVENT: {
 						/* Tell SDL to do various stuff... */
@@ -1713,15 +1135,36 @@ int sdl_video_event_thread(void *data)
 								sdl_ufunc_retval=0;
 								sdl.SemPost(sdl_ufunc_ret);
 								return(0);
-							case SDL_USEREVENT_LOADFONT:
-								sdl_ufunc_retval=sdl_load_font((char *)ev.user.data1);
-								FREE_AND_NULL(ev.user.data1);
-								sdl.SemPost(sdl_ufunc_ret);
-								sdl_full_screen_redraw(TRUE);
-								break;
 							case SDL_USEREVENT_UPDATERECT:
-								sdl_full_screen_redraw(FALSE);
-								break;
+								{
+									struct update_rect *rect=(struct update_rect *)ev.user.data1;
+									SDL_Rect r;
+									SDL_Rect dst;
+									int x,y;
+
+									for(y=0; y<rect->height; y++) {
+										for(x=0; x<rect->width; x++) {
+											r.x=x*vstat.scaling;
+											r.y=y*vstat.scaling;
+											r.w=vstat.scaling;
+											r.h=vstat.scaling;
+											sdl.FillRect(new_rect, &r, rect->data[y*rect->width+x]);
+										}
+									}
+									r.x=0;
+									r.y=0;
+									r.w=rect->width*vstat.scaling;
+									r.h=rect->height*vstat.scaling;
+									dst.x=rect->x*vstat.scaling;
+									dst.y=rect->y*vstat.scaling;
+									dst.w=rect->width*vstat.scaling;
+									dst.h=rect->height*vstat.scaling;
+									sdl.BlitSurface(new_rect, &r, win, &dst);
+									sdl.UpdateRects(win,1,&dst);
+									free(rect->data);
+									free(rect);
+									break;
+								}
 							case SDL_USEREVENT_SETNAME:
 								sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1);
 								free(ev.user.data1);
@@ -1747,7 +1190,7 @@ int sdl_video_event_thread(void *data)
 								free(ev.user.data1);
 								break;
 							case SDL_USEREVENT_SETVIDMODE:
-								sdl.mutexP(sdl_vstatlock);
+								pthread_mutex_lock(&vstatlock);
 								if(fullscreen)
 									win=sdl.SetVideoMode(
 										 vstat.charwidth*vstat.cols*vstat.scaling
@@ -1773,22 +1216,25 @@ int sdl_video_event_thread(void *data)
 									vstat.scaling=(int)(win->w/(vstat.charwidth*vstat.cols));
 									if(vstat.scaling < 1)
 										vstat.scaling=1;
-									sdl_setup_colours(win,0);
-									if(sdl_cursor!=NULL)
-										sdl.FreeSurface(sdl_cursor);
-									sdl_cursor=sdl.CreateRGBSurface(SDL_SWSURFACE, vstat.charwidth*vstat.scaling, vstat.charheight*vstat.scaling, 8, 0, 0, 0, 0);
-									/* Update font. */
-									sdl_load_font(NULL);
-									sdl_full_screen_redraw(TRUE);
+									if(new_rect)
+										sdl.FreeSurface(new_rect);
+									new_rect=sdl.CreateRGBSurface(SDL_SWSURFACE
+											, vstat.charwidth*vstat.cols*vstat.scaling
+											, vstat.charheight*vstat.rows*vstat.scaling
+											, 8, 0, 0, 0, 0);
+									pthread_mutex_unlock(&vstatlock);
+						    		sdl_setup_colours(win);
+						    		sdl_setup_colours(new_rect);
+									send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
 								}
 								else if(sdl_init_good) {
+									pthread_mutex_unlock(&vstatlock);
 									ev.type=SDL_QUIT;
 									sdl_exitcode=1;
 									sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
 								}
 								free(ev.user.data1);
 								free(ev.user.data2);
-								sdl.mutexV(sdl_vstatlock);
 								break;
 							case SDL_USEREVENT_HIDEMOUSE:
 								sdl.ShowCursor(SDL_DISABLE);
@@ -1802,7 +1248,6 @@ int sdl_video_event_thread(void *data)
 										if(win != NULL) {
 											sdl.EnableUNICODE(1);
 											sdl.EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-											blinker_thread=sdl.CreateThread(sdl_blinker_thread, NULL);
 											mouse_thread=sdl.CreateThread(sdl_mouse_thread, NULL);
 											sdl_init_good=1;
 										}
@@ -2005,9 +1450,7 @@ int sdl_initciolib(int mode)
 	sdl_key_pending=sdl.SDL_CreateSemaphore(0);
 	sdl_init_complete=sdl.SDL_CreateSemaphore(0);
 	sdl_ufunc_ret=sdl.SDL_CreateSemaphore(0);
-	sdl_updlock=sdl.SDL_CreateMutex();
 	sdl_keylock=sdl.SDL_CreateMutex();
-	sdl_vstatlock=sdl.SDL_CreateMutex();
 	sdl_ufunc_lock=sdl.SDL_CreateMutex();
 #if !defined(NO_X) && defined(__unix__)
 	sdl_pastebuf_set=sdl.SDL_CreateSemaphore(0);
diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c
index 368d02f82b4e0c1060905b8326de77b2e2f072dd..b10bed931bb36cf8d0a79fff0af2385bdb2fe697 100644
--- a/src/conio/x_cio.c
+++ b/src/conio/x_cio.c
@@ -35,6 +35,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#ifndef STATIC_LINK
+#include <dlfcn.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
 
 #include <threadwrap.h>
 
@@ -47,145 +52,75 @@
 
 #include "ciolib.h"
 #include "x_cio.h"
-#include "console.h"
-WORD	x_curr_attr=0x0700;
-
-int x_puttext(int sx, int sy, int ex, int ey, void *fill)
-{
-	int x,y;
-	unsigned char *out;
-	WORD	sch;
-	struct text_info	ti;
-
-	gettextinfo(&ti);
-
-	if(		   sx < 1
-			|| sy < 1
-			|| ex < 1
-			|| ey < 1
-			|| sx > ti.screenwidth
-			|| sy > ti.screenheight
-			|| sx > ex
-			|| sy > ey
-			|| ex > ti.screenwidth
-			|| ey > ti.screenheight
-			|| fill==NULL)
-		return(0);
-
-	out=fill;
-	for(y=sy-1;y<ey;y++) {
-		for(x=sx-1;x<ex;x++) {
-			sch=*(out++);
-			sch |= (*(out++))<<8;
-			vmem[y*DpyCols+x]=sch;
-		}
-	}
-	return(1);
-}
-
-int x_gettext(int sx, int sy, int ex, int ey, void *fill)
-{
-	int x,y;
-	unsigned char *out;
-	WORD	sch;
-	struct text_info	ti;
-
-	gettextinfo(&ti);
-
-	if(		   sx < 1
-			|| sy < 1
-			|| ex < 1
-			|| ey < 1
-			|| sx > ti.screenwidth
-			|| sy > ti.screenheight
-			|| sx > ex
-			|| sy > ey
-			|| ex > ti.screenwidth
-			|| ey > ti.screenheight
-			|| fill==NULL)
-		return(0);
-
-	out=fill;
-	for(y=sy-1;y<ey;y++) {
-		for(x=sx-1;x<ex;x++) {
-			sch=vmem[y*DpyCols+x];
-			*(out++)=sch & 0xff;
-			*(out++)=sch >> 8;
-		}
-	}
-	return(1);
-}
+#include "x_events.h"
 
 int x_kbhit(void)
 {
-	return(tty_kbhit());
-}
+	fd_set	rfd;
+	struct timeval tv;
 
-void x_gotoxy(int x, int y)
-{
-	CursRow=cio_textinfo.wintop+y-2;
-	CursCol=cio_textinfo.winleft+x-2;
-	cio_textinfo.curx=x;
-	cio_textinfo.cury=y;
-}
-
-void x_setcursortype(int type)
-{
-	switch(type) {
-		case _NOCURSOR:
-			CursStart=0xff;
-			CursEnd=0;
-			break;
-		case _SOLIDCURSOR:
-			CursStart=0;
-			CursEnd=FH-1;
-			break;
-		default:
-		    CursStart = InitCS;
-		    CursEnd = InitCE;
-			break;
-	}
+	memset(&tv, 0, sizeof(tv));
+	FD_ZERO(&rfd);
+	FD_SET(key_pipe[0], &rfd);
+	return(select(key_pipe[0]+1, &rfd, NULL, NULL, &tv)==1);
 }
 
 int x_getch(void)
 {
-	return(tty_read(TTYF_BLOCK));
+	unsigned char ch;
+
+	while(read(key_pipe[0], &ch, 1)!=1);
+	return(ch);
 }
 
 int x_beep(void)
 {
-	tty_beep();
+	struct x11_local_event ev;
+
+	ev.type=X11_LOCAL_BEEP;
+	while(write(local_pipe[1], &ev, sizeof(ev))==-1);
 	return(0);
 }
 
 void x_textmode(int mode)
 {
-	console_new_mode=mode;
-	sem_wait(&console_mode_changed);
+	struct x11_local_event ev;
+
+	ev.type=X11_LOCAL_SETMODE;
+	ev.data.mode = mode;
+	while(write(local_pipe[1], &ev, sizeof(ev))==-1);
+	sem_wait(&mode_set);
 }
 
 void x_setname(const char *name)
 {
-	x_win_name(name);
+	struct x11_local_event ev;
+
+	ev.type=X11_LOCAL_SETNAME;
+	SAFECOPY(ev.data.name, name);
+	while(write(local_pipe[1], &ev, sizeof(ev))==-1);
 }
 
 void x_settitle(const char *title)
 {
-	x_win_title(title);
+	struct x11_local_event ev;
+
+	ev.type=X11_LOCAL_SETTITLE;
+	SAFECOPY(ev.data.title, title);
+	while(write(local_pipe[1], &ev, sizeof(ev))==-1);
 }
 
 void x_copytext(const char *text, size_t buflen)
 {
+	struct x11_local_event ev;
+
 	pthread_mutex_lock(&copybuf_mutex);
-	if(copybuf!=NULL) {
-		free(copybuf);
-		copybuf=NULL;
-	}
+	FREE_AND_NULL(copybuf);
 
-	copybuf=(char *)malloc(buflen+1);
-	if(copybuf!=NULL) {
-		strcpy(copybuf, text);
-		sem_post(&copybuf_set);
+	copybuf=strdup(text);
+	if(copybuf) {
+		ev.type=X11_LOCAL_COPY;
+		while(write(local_pipe[1], &ev, sizeof(ev))==-1);
 	}
 	pthread_mutex_unlock(&copybuf_mutex);
 	return;
@@ -194,38 +129,17 @@ void x_copytext(const char *text, size_t buflen)
 char *x_getcliptext(void)
 {
 	char *ret=NULL;
+	struct x11_local_event ev;
 
-	sem_post(&pastebuf_request);
+	ev.type=X11_LOCAL_PASTE;
+	while(write(local_pipe[1], &ev, sizeof(ev))==-1);
 	sem_wait(&pastebuf_set);
-	if(pastebuf!=NULL) {
-		ret=(char *)malloc(strlen(pastebuf)+1);
-		if(ret!=NULL)
-			strcpy(ret,pastebuf);
-	}
-	sem_post(&pastebuf_request);
+	if(pastebuf!=NULL)
+		ret=strdup(pastebuf);
+	sem_post(&pastebuf_used);
 	return(ret);
 }
 
-int x_setfont(int font, int force)
-{
-	if(font==getfont())
-		return(0);
-	font_force=force;
-	new_font=font;
-	sem_wait(&font_set);
-	return(setfont_return);
-}
-
-int x_getfont(void)
-{
-	return(new_font);
-}
-
-int x_loadfont(char *filename)
-{
-	return(x_load_font(filename));
-}
-
 int x_get_window_info(int *width, int *height, int *xpos, int *ypos)
 {
 	if(width)
@@ -239,3 +153,279 @@ int x_get_window_info(int *width, int *height, int *xpos, int *ypos)
 	
 	return(0);
 }
+
+int x_init(void)
+{
+    int fd;
+    int i;
+	void *dl;
+
+	/* Ensure we haven't already initialized */
+	if(initialized)
+		return(0);
+
+	/* Set up the pipe for local events */
+	if(pipe(local_pipe))
+		return(-1);
+
+	/* And the keyboard pipe */
+	if(pipe(key_pipe))
+		return(-1);
+
+	/* Load X11 functions */
+#ifdef STATIC_LINK
+	x11.XChangeGC=XChangeGC;
+	x11.XCopyPlane=XCopyPlane;
+	x11.XFillRectangle=XFillRectangle;
+	x11.XDrawPoint=XDrawPoint;
+	x11.XFlush=XFlush;
+	x11.XSync=XSync;
+	x11.XBell=XBell;
+	x11.XLookupString=XLookupString;
+	x11.XNextEvent=XNextEvent;
+	x11.XAllocSizeHints=XAllocSizeHints;
+	x11.XSetWMNormalHints=XSetWMNormalHints;
+	x11.XResizeWindow=XResizeWindow;
+	x11.XMapWindow=XMapWindow;
+	x11.XFree=XFree;
+	x11.XFreePixmap=XFreePixmap;
+	x11.XCreatePixmap=XCreatePixmap;
+	x11.XCopyArea=XCopyArea;
+	x11.XCreateBitmapFromData=XCreateBitmapFromData;
+	x11.XAllocColor=XAllocColor;
+	x11.XOpenDisplay=XOpenDisplay;
+	x11.XCreateSimpleWindow=XCreateSimpleWindow;
+	x11.XCreateGC=XCreateGC;
+	x11.XSelectInput=XSelectInput;
+	x11.XStoreName=XStoreName;
+	x11.XGetSelectionOwner=XGetSelectionOwner;
+	x11.XConvertSelection=XConvertSelection;
+	x11.XGetWindowProperty=XGetWindowProperty;
+	x11.XChangeProperty=XChangeProperty;
+	x11.XSendEvent=XSendEvent;
+	x11.XPutImage=XPutImage;
+#ifndef XPutPixel
+	x11.XPutPixel=XPutPixel;
+#endif
+#ifndef XDestroyImage
+	x11.XDestroyImage=XDestroyImage;
+#endif
+	x11.XCreateImage=XCreateImage;
+	x11.XSetSelectionOwner=XSetSelectionOwner;
+	x11.XSetIconName=XSetIconName;
+	x11.XSynchronize=XSynchronize;
+	x11.XGetWindowAttributes=XGetWindowAttributes;
+#else
+#if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
+	if((dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL))==NULL)
+#else
+	if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL)
+#endif
+		return(-1);
+	if((x11.XChangeGC=dlsym(dl,"XChangeGC"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCopyPlane=dlsym(dl,"XCopyPlane"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XFillRectangle=dlsym(dl,"XFillRectangle"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XDrawPoint=dlsym(dl,"XDrawPoint"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XFlush=dlsym(dl,"XFlush"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSync=dlsym(dl,"XSync"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XBell=dlsym(dl,"XBell"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XLookupString=dlsym(dl,"XLookupString"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XNextEvent=dlsym(dl,"XNextEvent"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XAllocSizeHints=dlsym(dl,"XAllocSizeHints"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSetWMNormalHints=dlsym(dl,"XSetWMNormalHints"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XResizeWindow=dlsym(dl,"XResizeWindow"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XMapWindow=dlsym(dl,"XMapWindow"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XFree=dlsym(dl,"XFree"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XFreePixmap=dlsym(dl,"XFreePixmap"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCreatePixmap=dlsym(dl,"XCreatePixmap"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCopyArea=dlsym(dl,"XCopyArea"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCreateBitmapFromData=dlsym(dl,"XCreateBitmapFromData"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XAllocColor=dlsym(dl,"XAllocColor"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XOpenDisplay=dlsym(dl,"XOpenDisplay"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCreateSimpleWindow=dlsym(dl,"XCreateSimpleWindow"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XCreateGC=dlsym(dl,"XCreateGC"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSelectInput=dlsym(dl,"XSelectInput"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XStoreName=dlsym(dl,"XStoreName"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XPutImage=dlsym(dl,"XPutImage"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+#ifndef XDestroyImage
+	if((x11.XDestroyImage=dlsym(dl,"XDestroyImage"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+#endif
+#ifndef XPutPixel
+	if((x11.XPutPixel=dlsym(dl,"XPutPixel"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+#endif
+	if((x11.XCreateImage=dlsym(dl,"XCreateImage"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSetIconName=dlsym(dl,"XSetIconName"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XSynchronize=dlsym(dl,"XSynchronize"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+	if((x11.XGetWindowAttributes=dlsym(dl,"XGetWindowAttributes"))==NULL) {
+		dlclose(dl);
+		return(-1);
+	}
+#endif
+
+	if(sem_init(&pastebuf_set, 0, 0))
+		return(-1);
+	if(sem_init(&pastebuf_used, 0, 0)) {
+		sem_destroy(&pastebuf_set);
+		return(-1);
+	}
+	if(sem_init(&init_complete, 0, 0)) {
+		sem_destroy(&pastebuf_set);
+		sem_destroy(&pastebuf_used);
+		return(-1);
+	}
+	if(sem_init(&mode_set, 0, 0)) {
+		sem_destroy(&pastebuf_set);
+		sem_destroy(&pastebuf_used);
+		sem_destroy(&init_complete);
+		return(-1);
+	}
+
+	if(pthread_mutex_init(&copybuf_mutex, 0)) {
+		sem_destroy(&pastebuf_set);
+		sem_destroy(&pastebuf_used);
+		sem_destroy(&init_complete);
+		sem_destroy(&mode_set);
+		return(-1);
+	}
+
+	_beginthread(x11_event_thread,1<<16,NULL);
+	sem_wait(&init_complete);
+	if(!initialized) {
+		sem_destroy(&pastebuf_set);
+		sem_destroy(&pastebuf_used);
+		sem_destroy(&init_complete);
+		sem_destroy(&mode_set);
+		pthread_mutex_destroy(&copybuf_mutex);
+		return(-1);
+	}
+	return(0);
+}
+
+void x11_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data)
+{
+	struct x11_local_event ev;
+
+	ev.type=X11_LOCAL_DRAWRECT;
+	if(initialized) {
+		ev.data.rect.x=xoffset;
+		ev.data.rect.y=yoffset;
+		ev.data.rect.width=width;
+		ev.data.rect.height=height;
+		ev.data.rect.data=data;
+		while(write(local_pipe[1], &ev, sizeof(ev))==-1);
+	}
+}
diff --git a/src/conio/x_cio.h b/src/conio/x_cio.h
index 8d623455e9bb78d000a7b24e77e3c8e8d004b3ef..f46602ab9a62eec680a75365e86943051916f020 100644
--- a/src/conio/x_cio.h
+++ b/src/conio/x_cio.h
@@ -40,18 +40,25 @@
 #endif
 
 #include "ciolib.h"
-#include "console.h"
+#include "x_events.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 int x_puttext(int sx, int sy, int ex, int ey, void *fill);
 int x_gettext(int sx, int sy, int ex, int ey, void *fill);
+void x_textattr(int attr);
 int x_kbhit(void);
+void x_delay(long msec);
+int x_wherey(void);
+int x_wherex(void);
+int x_putch(int ch);
 void x_gotoxy(int x, int y);
 void x_initciolib(long inmode);
+void x_gettextinfo(struct text_info *info);
 void x_setcursortype(int type);
 int x_getch(void);
+int x_getche(void);
 int x_beep(void);
 void x_textmode(int mode);
 void x_setname(const char *name);
@@ -62,6 +69,7 @@ int x_setfont(int font, int force);
 int x_getfont(void);
 int x_loadfont(char *filename);
 int x_get_window_info(int *width, int *height, int *xpos, int *ypos);
+void x11_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/conio/x_events.c b/src/conio/x_events.c
new file mode 100644
index 0000000000000000000000000000000000000000..54803a9df94c698a27ce2c1326d385b42f0e7163
--- /dev/null
+++ b/src/conio/x_events.c
@@ -0,0 +1,870 @@
+/*
+ * This file contains ONLY the functions that are called from the
+ * event thread.
+ */
+ 
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+#include <threadwrap.h>
+#include <genwrap.h>
+#include <dirwrap.h>
+
+#include "vidmodes.h"
+#include "allfonts.h"
+
+#include "keys.h"
+#include "mouse.h"
+#include "bitmap_con.h"
+#include "link_list.h"
+#include "x_events.h"
+#include "x_cio.h"
+
+/*
+ * Exported variables 
+ */
+
+int local_pipe[2];			/* Used for passing local events */
+int key_pipe[2];			/* Used for passing keyboard events */
+
+struct x11 x11;
+
+char 	*copybuf;
+pthread_mutex_t	copybuf_mutex;
+char 	*pastebuf;
+sem_t	pastebuf_set;
+sem_t	pastebuf_used;
+sem_t	init_complete;
+sem_t	mode_set;
+int x11_window_xpos;
+int x11_window_ypos;
+int x11_window_width;
+int x11_window_height;
+int initialized=0;
+/*
+ * Local variables
+ */
+
+/* Sets the atom to be used for copy/paste operations */
+#define CONSOLE_CLIPBOARD	XA_PRIMARY
+
+static Display *dpy=NULL;
+static Window win;
+static Visual visual;
+static unsigned int depth=0;
+static int xfd;
+static unsigned long black;
+static unsigned long white;
+static int bitmap_width;
+static int bitmap_height;
+
+/* Array of Graphics Contexts */
+static GC gca[sizeof(dac_default)/sizeof(struct dac_colors)];
+
+/* Array of pixel values to match all possible colours */
+static unsigned long pixel[sizeof(dac_default)/sizeof(struct dac_colors)];
+
+static WORD Ascii2Scan[] = {
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x000e, 0x000f, 0xffff, 0xffff, 0xffff, 0x001c, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0039, 0x0102, 0x0128, 0x0104, 0x0105, 0x0106, 0x0108, 0x0028,
+ 0x010a, 0x010b, 0x0109, 0x010d, 0x0033, 0x000c, 0x0034, 0x0035,
+ 0x000b, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
+ 0x0009, 0x000a, 0x0127, 0x0027, 0x0133, 0x000d, 0x0134, 0x0135,
+ 0x0103, 0x011e, 0x0130, 0x012e, 0x0120, 0x0112, 0x0121, 0x0122,
+ 0x0123, 0x0117, 0x0124, 0x0125, 0x0126, 0x0132, 0x0131, 0x0118,
+ 0x0119, 0x0110, 0x0113, 0x011f, 0x0114, 0x0116, 0x012f, 0x0111,
+ 0x012d, 0x0115, 0x012c, 0x001a, 0x002b, 0x001b, 0x0107, 0x010c,
+ 0x0029, 0x001e, 0x0030, 0x002e, 0x0020, 0x0012, 0x0021, 0x0022,
+ 0x0023, 0x0017, 0x0024, 0x0025, 0x0026, 0x0032, 0x0031, 0x0018,
+ 0x0019, 0x0010, 0x0013, 0x001f, 0x0014, 0x0016, 0x002f, 0x0011,
+ 0x002d, 0x0015, 0x002c, 0x011a, 0x012b, 0x011b, 0x0129, 0xffff,
+};
+
+static struct {
+    WORD	base;
+    WORD	shift;
+    WORD	ctrl;
+    WORD	alt;
+} ScanCodes[] = {
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key  0 */
+    {	0x011b, 0x011b, 0x011b, 0xffff }, /* key  1 - Escape key */
+    {	0x0231, 0x0221, 0xffff, 0x7800 }, /* key  2 - '1' */
+    {	0x0332, 0x0340, 0x0300, 0x7900 }, /* key  3 - '2' - special handling */
+    {	0x0433, 0x0423, 0xffff, 0x7a00 }, /* key  4 - '3' */
+    {	0x0534, 0x0524, 0xffff, 0x7b00 }, /* key  5 - '4' */
+    {	0x0635, 0x0625, 0xffff, 0x7c00 }, /* key  6 - '5' */
+    {	0x0736, 0x075e, 0x071e, 0x7d00 }, /* key  7 - '6' */
+    {	0x0837, 0x0826, 0xffff, 0x7e00 }, /* key  8 - '7' */
+    {	0x0938, 0x092a, 0xffff, 0x7f00 }, /* key  9 - '8' */
+    {	0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
+    {	0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
+    {	0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
+    {	0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
+    {	0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
+    {	0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
+    {	0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
+    {	0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
+    {	0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
+    {	0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
+    {	0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
+    {	0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
+    {	0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
+    {	0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
+    {	0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
+    {	0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
+    {	0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
+    {	0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
+    {	0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - control */
+    {	0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
+    {	0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
+    {	0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
+    {	0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
+    {	0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
+    {	0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
+    {	0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
+    {	0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
+    {	0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
+    {	0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
+    {	0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
+    {	0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
+    {	0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
+    {	0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
+    {	0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
+    {	0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
+    {	0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
+    {	0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
+    {	0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
+    {	0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
+    {	0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
+    {	0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
+    {	0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
+    {	0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - Alt - */
+    {	0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock -  */
+    {	0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
+    {	0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
+    {	0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
+    {	0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
+    {	0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
+    {	0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
+    {	0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
+    {	0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
+    {	0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
+    {	0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock -  */
+    {	0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
+    {	0x4800, 0x4838, 0x8d00, 0x9800 }, /* key 72 - cursor up */
+    {	0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
+    {	0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
+    {	0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
+    {	0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
+    {	0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
+    {	0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
+    {	0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
+    {	0x5000, 0x5032, 0x9100, 0xa000 }, /* key 80 - cursor down */
+    {	0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
+    {	0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
+    {	0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
+    {	0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
+    {	0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
+    {	0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
+};
+
+/* Get a connection to the X server and create the window. */
+static int init_window()
+{
+    XGCValues gcv;
+	XColor color;
+    int i;
+	XWindowAttributes	attr;
+
+	dpy = x11.XOpenDisplay(NULL);
+    if (dpy == NULL) {
+		return(-1);
+	}
+    xfd = ConnectionNumber(dpy);
+
+	/* Allocate black and white */
+	black=BlackPixel(dpy, DefaultScreen(dpy));
+	white=WhitePixel(dpy, DefaultScreen(dpy));
+
+    /* Create window, but defer setting a size and GC. */
+    win = x11.XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
+			      1, 1, 2, black, black);
+
+	gcv.function = GXcopy;
+    gcv.foreground = white;
+    gcv.background = black;
+	gcv.graphics_exposures = False;
+
+	/* Get the pixel and GC values */
+	for(i=0; i<sizeof(dac_default)/sizeof(struct dac_colors); i++) {
+		color.red=dac_default[i].red << 8;
+		color.green=dac_default[i].green << 8;
+		color.blue=dac_default[i].blue << 8;
+		if(x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color))
+			pixel[i]=color.pixel;
+		gcv.foreground=color.pixel;
+		gca[i]=x11.XCreateGC(dpy, win, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv);
+	}
+
+    x11.XSelectInput(dpy, win, KeyReleaseMask | KeyPressMask |
+		     ExposureMask | ButtonPressMask
+		     | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
+//	x11.XFlush(dpy);
+	x11.XGetWindowAttributes(dpy,win,&attr);
+	memcpy(&visual,attr.visual,sizeof(visual));
+
+    x11.XStoreName(dpy, win, "SyncConsole");
+	depth = DefaultDepth(dpy, DefaultScreen(dpy));
+
+	return(0);
+}
+
+/* Resize the window. This function is called after a mode change. */
+static void resize_window()
+{
+    XSizeHints *sh;
+
+    sh = x11.XAllocSizeHints();
+    if (sh == NULL) {
+		fprintf(stderr, "Could not get XSizeHints structure");
+		exit(1);
+	}
+
+	sh->base_width = bitmap_width*vstat.scaling;
+	sh->base_height = bitmap_height*vstat.scaling;
+
+    sh->min_width = bitmap_width;
+    sh->min_height = bitmap_height;
+    sh->flags = USSize | PMinSize | PSize;
+
+    x11.XSetWMNormalHints(dpy, win, sh);
+    x11.XResizeWindow(dpy, win, sh->base_width, sh->base_height);
+    x11.XMapWindow(dpy, win);
+
+    x11.XFree(sh);
+
+	send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
+
+    return;
+}
+
+static int init_mode(int mode)
+{
+    int i;
+
+	bitmap_init_mode(mode, &bitmap_width, &bitmap_height);
+
+    /* Resize window if necessary. */
+    resize_window();
+
+	sem_post(&mode_set);
+    return(0);
+}
+
+static int video_init()
+{
+    /* If we are running under X, get a connection to the X server and create
+       an empty window of size (1, 1). It makes a couple of init functions a
+       lot easier. */
+    if(init_window())
+		return(-1);
+
+	vstat.scaling=1;
+	bitmap_init(x11_drawrect);
+
+    /* Initialize mode 3 (text, 80x25, 16 colors) */
+    if(init_mode(3)) {
+		return(-1);
+	}
+
+	sem_wait(&mode_set);
+
+    return(0);
+}
+
+static void local_draw_rect(struct update_rect *rect)
+{
+	int x,y,xscale,yscale;
+	int rectw, recth, rectc,x2,y2;
+	XImage *xim;
+
+#if 0
+	/* Draw solid colour rectangles... */
+	for(y=0; y<rect->height; y++) {
+		for(x=0; x<rect->width; x++) {
+			rectc=rect->data[y*rect->width+x];
+
+			/* Already displayed? */
+			if(rectc == 255)
+				continue;
+
+			rectw=1;
+			recth=1;
+
+			/* Grow as wide as we can */
+			while(x+rectw < rect->width && rect->data[y*rect->width+x+rectw]==rectc)
+				rectw++;
+			
+			/* Now grow as tall as we can */
+			while(y+recth < rect->height && memcmp(rect->data+(y*rect->width+x), rect->data+((y+recth)*rect->width+x), rectw)==0)
+				recth++;
+
+			/* Mark pixels as drawn */
+			for(y2=0; y2<recth; y2++)
+				memset(rect->data+((y+y2)*rect->width+x),255,rectw);
+
+			/* Draw it */
+			x11.XFillRectangle(dpy, win, gca[rectc], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling, rectw*vstat.scaling, recth*vstat.scaling);
+		}
+	}
+#endif
+
+#if 1	/* Other Methods */
+#if 1	/* XImage */
+	xim=x11.XCreateImage(dpy,&visual,depth,ZPixmap,0,NULL,rect->width,rect->height,32,0);
+	xim->data=(char *)malloc(xim->bytes_per_line*rect->height);
+	for(y=0;y<rect->height;y++) {
+		for(x=0; x<rect->width; x++) {
+			for(yscale=0; yscale<vstat.scaling; yscale++) {
+				for(xscale=0; xscale<vstat.scaling; xscale++) {
+#ifdef XPutPixel
+					XPutPixel(xim,x*vstat.scaling+xscale,y*vstat.scaling+yscale,pixel[rect->data[y*rect->width+x]]);
+#else
+					x11.XPutPixel(xim,x*vstat.scaling+xscale,y*vstat.scaling+yscale,pixel[rect->data[y*rect->width+x]]);
+#endif
+				}
+			}
+		}
+	}
+
+	x11.XPutImage(dpy,win,gca[0],xim,0,0,(rect->x),(rect->y),rect->width,rect->height);
+#ifdef XDestroyImage
+	XDestroyImage(xim);
+#else
+	x11.XDestroyImage(xim);
+#endif
+
+#else	/* XFillRectangle */
+	for(y=0;y<rect->height;y++) {
+		for(x=0; x<rect->width; x++) {
+			x11.XFillRectangle(dpy, win, gca[rect->data[y*rect->width+x]], (rect->x+x)*vstat.scaling, (rect->y+y)*vstat.scaling, vstat.scaling, vstat.scaling);
+		}
+	}
+#endif
+#endif
+	x11.XFlush(dpy);
+	free(rect->data);
+}
+
+static int x11_event(XEvent *ev)
+{
+	switch (ev->type) {
+		/* Graphics related events */
+		case ConfigureNotify:
+			{
+				int newFSH=1;
+				int newFSW=1;
+				int r;
+
+				x11_window_xpos=ev->xconfigure.x;
+				x11_window_ypos=ev->xconfigure.y;
+				x11_window_width=ev->xconfigure.width;
+				x11_window_height=ev->xconfigure.height;
+				if((ev->xconfigure.width == vstat.charwidth * vstat.cols * vstat.scaling)
+						&& (ev->xconfigure.height == vstat.charheight * vstat.rows * vstat.scaling))
+					break;
+
+				newFSH=ev->xconfigure.width/bitmap_width;
+				newFSW=ev->xconfigure.height/bitmap_height;
+				if(newFSW<1)
+					newFSW=1;
+				if(newFSH<1)
+					newFSH=1;
+				if(newFSH<newFSW)
+					vstat.scaling=newFSH;
+				else
+					vstat.scaling=newFSW;
+				if(vstat.scaling > 16)
+					vstat.scaling=16;
+				resize_window();
+			}
+			break;
+        case NoExpose:
+                break;
+        case GraphicsExpose:
+			send_rectangle(ev->xgraphicsexpose.x/vstat.scaling,ev->xgraphicsexpose.y/vstat.scaling
+					,ev->xgraphicsexpose.width/vstat.scaling,ev->xgraphicsexpose.height/vstat.scaling,TRUE);
+			break;
+        case Expose:
+			send_rectangle(ev->xexpose.x/vstat.scaling,ev->xexpose.y/vstat.scaling,ev->xexpose.width/vstat.scaling,ev->xexpose.height/vstat.scaling,TRUE);
+			break;
+
+		/* Copy/Paste events */
+		case SelectionClear:
+			{
+				XSelectionClearEvent *req;
+
+				req=&(ev->xselectionclear);
+				pthread_mutex_lock(&copybuf_mutex);
+				if(req->selection==CONSOLE_CLIPBOARD)
+					FREE_AND_NULL(copybuf);
+				pthread_mutex_unlock(&copybuf_mutex);
+			}
+			break;
+		case SelectionNotify:
+			{
+				int format;
+				unsigned long len, bytes_left, dummy;
+				Atom type;
+
+				if(ev->xselection.selection != CONSOLE_CLIPBOARD)
+					break;
+				if(ev->xselection.requestor!=win)
+					break;
+				x11.XGetWindowProperty(dpy, win, ev->xselection.property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&pastebuf));
+				if(bytes_left > 0 && format==8)
+					x11.XGetWindowProperty(dpy, win, ev->xselection.property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&pastebuf);
+				else
+					pastebuf=NULL;
+
+				/* Set paste buffer */
+				sem_post(&pastebuf_set);
+				sem_wait(&pastebuf_used);
+				x11.XFree(pastebuf);
+				pastebuf=NULL;
+			}
+			break;
+		case SelectionRequest:
+			{
+				XSelectionRequestEvent *req;
+				XEvent respond;
+
+				req=&(ev->xselectionrequest);
+				pthread_mutex_lock(&copybuf_mutex);
+				if(copybuf==NULL) {
+					respond.xselection.property=None;
+				}
+				else {
+					if(req->target==XA_STRING) {
+						x11.XChangeProperty(dpy, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)copybuf, strlen(copybuf));
+						respond.xselection.property=req->property;
+					}
+					else
+						respond.xselection.property=None;
+				}
+				respond.xselection.type=SelectionNotify;
+				respond.xselection.display=req->display;
+				respond.xselection.requestor=req->requestor;
+				respond.xselection.selection=req->selection;
+				respond.xselection.target=req->target;
+				respond.xselection.time=req->time;
+				x11.XSendEvent(dpy,req->requestor,0,0,&respond);
+				pthread_mutex_unlock(&copybuf_mutex);
+			}
+			break;
+
+		/* Mouse Events */
+		case MotionNotify:
+			{
+				XMotionEvent *me = (XMotionEvent *)ev;
+
+				me->x/=vstat.scaling;
+				me->x/=vstat.charwidth;
+				me->y/=vstat.scaling;
+				me->y/=vstat.charheight;
+				me->x++;
+				me->y++;
+				if(me->x<1)
+					me->x=1;
+				if(me->y<1)
+					me->y=1;
+				if(me->x>vstat.cols)
+					me->x=vstat.cols;
+				if(me->y>vstat.rows+1)
+					me->y=vstat.rows+1;
+				ciomouse_gotevent(CIOLIB_MOUSE_MOVE,me->x,me->y);
+	    	}
+			break;
+		case ButtonRelease:
+			{
+				XButtonEvent *be = (XButtonEvent *)ev;
+
+				be->x/=vstat.scaling;
+				be->x/=vstat.charwidth;
+				be->y/=vstat.scaling;
+				be->y/=vstat.charheight;
+				be->x++;
+				be->y++;
+				if(be->x<1)
+					be->x=1;
+				if(be->y<1)
+					be->y=1;
+				if(be->x>vstat.cols)
+					be->x=vstat.cols;
+				if(be->y>vstat.rows+1)
+					be->y=vstat.rows+1;
+				if (be->button <= 3) {
+					ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(be->button),be->x,be->y);
+				}
+	    	}
+			break;
+		case ButtonPress:
+			{
+				XButtonEvent *be = (XButtonEvent *)ev;
+
+				be->x/=vstat.scaling;
+				be->x/=vstat.charwidth;
+				be->y/=vstat.scaling;
+				be->y/=vstat.charheight;
+				be->x++;
+				be->y++;
+				if(be->x<1)
+					be->x=1;
+				if(be->y<1)
+					be->y=1;
+				if(be->x>vstat.cols)
+					be->x=vstat.cols;
+				if(be->y>vstat.rows+1)
+					be->y=vstat.rows+1;
+				if (be->button <= 3) {
+					ciomouse_gotevent(CIOLIB_BUTTON_PRESS(be->button),be->x,be->y);
+				}
+	    	}
+			break;
+
+		/* Keyboard Events */
+		case KeyPress:
+			{
+				static char buf[128];
+				KeySym ks;
+				int n;
+				int nlock = 0;
+				WORD scan = 0xffff;
+
+				n = x11.XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &ks, 0);
+
+				switch (ks) {
+				
+					case XK_Escape:
+						scan = 1;
+						goto docode;
+
+					case XK_Tab:
+					case XK_ISO_Left_Tab:
+						scan = 15;
+						goto docode;
+			
+					case XK_Return:
+					case XK_KP_Enter:
+						scan = 28;
+						goto docode;
+
+					case XK_Print:
+						scan = 55;
+						goto docode;
+
+					case XK_F1:
+					case XK_F2:
+					case XK_F3:
+					case XK_F4:
+					case XK_F5:
+					case XK_F6:
+					case XK_F7:
+					case XK_F8:
+					case XK_F9:
+					case XK_F10:
+						scan = ks - XK_F1 + 59;
+						goto docode;
+
+					case XK_KP_7:
+						nlock = 1;
+					case XK_Home:
+					case XK_KP_Home:
+						scan = 71;
+						goto docode;
+
+					case XK_KP_8:
+						nlock = 1;
+					case XK_Up:
+					case XK_KP_Up:
+						scan = 72;
+						goto docode;
+
+					case XK_KP_9:
+						nlock = 1;
+					case XK_Prior:
+					case XK_KP_Prior:
+						scan = 73;
+						goto docode;
+
+					case XK_KP_Subtract:
+						scan = 74;
+						goto docode;
+
+					case XK_KP_4:
+						nlock = 1;
+					case XK_Left:
+					case XK_KP_Left:
+						scan = 75;
+						goto docode;
+
+					case XK_KP_5:
+						nlock = 1;
+					case XK_Begin:
+					case XK_KP_Begin:
+						scan = 76;
+						goto docode;
+
+					case XK_KP_6:
+						nlock = 1;
+					case XK_Right:
+					case XK_KP_Right:
+						scan = 77;
+						goto docode;
+
+					case XK_KP_Add:
+						scan = 78;
+						goto docode;
+
+					case XK_KP_1:
+						nlock = 1;
+					case XK_End:
+					case XK_KP_End:
+						scan = 79;
+						goto docode;
+
+					case XK_KP_2:
+						nlock = 1;
+					case XK_Down:
+					case XK_KP_Down:
+						scan = 80;
+						goto docode;
+
+					case XK_KP_3:
+						nlock = 1;
+					case XK_Next:
+					case XK_KP_Next:
+						scan = 81;
+						goto docode;
+
+					case XK_KP_0:
+						nlock = 1;
+					case XK_Insert:
+					case XK_KP_Insert:
+						scan = 82;
+						goto docode;
+
+					case XK_KP_Decimal:
+						nlock = 1;
+						scan = 83;
+						goto docode;
+
+					case XK_Delete:
+					case XK_KP_Delete:
+						/* scan = flipdelete ? 14 : 83; */
+						scan = 83;
+						goto docode;
+
+					case XK_BackSpace:
+						/* scan = flipdelete ? 83 : 14; */
+						scan = 14;
+						goto docode;
+
+					case XK_F11:
+						scan = 87;
+						goto docode;
+					case XK_F12:
+						scan = 88;
+						goto docode;
+
+
+					case XK_KP_Divide:
+						scan = Ascii2Scan['/'];
+						goto docode;
+
+					case XK_KP_Multiply:
+						scan = Ascii2Scan['*'];
+						goto docode;
+
+					default:
+						if (ks < ' ' || ks > '~')
+							break;
+						scan = Ascii2Scan[ks]; 
+						docode:
+						if (nlock)
+							scan |= 0x100;
+
+						if ((scan & ~0x100) > 88) {
+							scan = 0xffff;
+							break;
+						}
+
+						if ((ev->xkey.state & ShiftMask) || (scan & 0x100)) {
+							scan = ScanCodes[scan & 0xff].shift;
+						} else if (ev->xkey.state & ControlMask) {
+							scan = ScanCodes[scan & 0xff].ctrl;
+						} else if (ev->xkey.state & Mod1Mask) {
+							scan = ScanCodes[scan & 0xff].alt;
+						}  else
+							scan = ScanCodes[scan & 0xff].base;
+
+						break;
+				}
+				if (scan != 0xffff) {
+					unsigned char ch;
+					ch=scan & 0xff;
+					write(key_pipe[1], &ch, 1);
+					if(!ch) {
+						ch=scan >> 8;
+						write(key_pipe[1], &ch, 1);
+					}
+				}
+				return(1);
+			}
+		default:
+			break;
+	}
+	return(0);
+}
+
+void x11_event_thread(void *args)
+{
+	int x;
+	int high_fd;
+	fd_set fdset;
+	XEvent ev;
+	static struct timeval tv;
+
+	if(video_init()) {
+		sem_post(&init_complete);
+		return;
+	}
+	initialized=1;
+	sem_post(&init_complete);
+
+	if(local_pipe[0] > xfd)
+		high_fd=local_pipe[0];
+	else
+		high_fd=xfd;
+
+	for (;;) {
+		tv.tv_sec=0;
+		tv.tv_usec=54925; /* was 54925 (was also 10) */ 
+
+		/*
+		 * Handle any events just sitting around...
+		 */
+		while (QLength(dpy) > 0) {
+			x11.XNextEvent(dpy, &ev);
+			x11_event(&ev);
+		}
+
+		FD_ZERO(&fdset);
+		FD_SET(xfd, &fdset);
+		FD_SET(local_pipe[0], &fdset);
+
+		x = select(high_fd+1, &fdset, 0, 0, &tv);
+
+		switch (x) {
+			case -1:
+				/*
+				* Errno might be wrong, so we just select again.
+				* This could cause a problem is something really
+				* was wrong with select....
+				*/
+
+				/* perror("select"); */
+				break;
+			case 0:
+				/* Timeout */
+				break;
+			default:
+				if (FD_ISSET(xfd, &fdset)) {
+					x11.XNextEvent(dpy, &ev);
+					x11_event(&ev);
+				}
+				while(FD_ISSET(local_pipe[0], &fdset)) {
+					struct x11_local_event lev;
+
+					read(local_pipe[0], &lev, sizeof(lev));
+					switch(lev.type) {
+						case X11_LOCAL_SETMODE:
+							init_mode(lev.data.mode);
+							break;
+						case X11_LOCAL_SETNAME:
+							x11.XSetIconName(dpy, win, lev.data.name);
+							x11.XFlush(dpy);
+							break;
+						case X11_LOCAL_SETTITLE:
+							x11.XStoreName(dpy, win, lev.data.title);
+							x11.XFlush(dpy);
+							break;
+						case X11_LOCAL_COPY:
+							x11.XSetSelectionOwner(dpy, CONSOLE_CLIPBOARD, win, CurrentTime);
+							break;
+						case X11_LOCAL_PASTE: 
+							{
+								Window sowner=None;
+
+								sowner=x11.XGetSelectionOwner(dpy, CONSOLE_CLIPBOARD);
+								if(sowner==win) {
+									/* Get your own primary selection */
+									if(copybuf==NULL)
+										pastebuf=NULL;
+									else
+										pastebuf=strdup(copybuf);
+									/* Set paste buffer */
+									sem_post(&pastebuf_set);
+									sem_wait(&pastebuf_used);
+									FREE_AND_NULL(pastebuf);
+								}
+								else if(sowner!=None) {
+									x11.XConvertSelection(dpy, CONSOLE_CLIPBOARD, XA_STRING, None, win, CurrentTime);
+								}
+								else {
+									/* Set paste buffer */
+									pastebuf=NULL;
+									sem_post(&pastebuf_set);
+									sem_wait(&pastebuf_used);
+								}
+							}
+							break;
+						case X11_LOCAL_DRAWRECT:
+							local_draw_rect(&lev.data.rect);
+							break;
+						case X11_LOCAL_BEEP:
+							x11.XBell(dpy, 100);
+							break;
+					}
+					tv.tv_sec=0;
+					tv.tv_usec=0;
+
+					FD_ZERO(&fdset);
+					FD_SET(local_pipe[0], &fdset);
+
+					if(select(local_pipe[0]+1, &fdset, 0, 0, &tv)!=1)
+						FD_ZERO(&fdset);
+				}
+		}
+	}
+}
diff --git a/src/conio/x_events.h b/src/conio/x_events.h
new file mode 100644
index 0000000000000000000000000000000000000000..75feac3b3cd7d1a88d8a2f9e428d392ecdf0ce63
--- /dev/null
+++ b/src/conio/x_events.h
@@ -0,0 +1,104 @@
+#ifndef _X_EVENTS_H_
+#define _X_EVENTS_H_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+
+struct update_rect {
+	int	x;
+	int	y;
+	int	width;
+	int	height;
+	unsigned char *data;
+};
+
+enum x11_local_events {
+	 X11_LOCAL_SETMODE
+	,X11_LOCAL_SETNAME
+	,X11_LOCAL_SETTITLE
+	,X11_LOCAL_COPY
+	,X11_LOCAL_PASTE
+	,X11_LOCAL_DRAWRECT
+	,X11_LOCAL_BEEP
+};
+
+struct x11_local_event {
+	enum x11_local_events	type;
+	union {
+		int		mode;
+		char	name[81];
+		char	title[81];
+		struct	update_rect rect; 
+	} data;
+};
+
+/* X functions */
+struct x11 {
+	int		(*XChangeGC)	(Display*, GC, unsigned long, XGCValues*);
+	int		(*XCopyPlane)	(Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int, unsigned long);
+	int		(*XFillRectangle)	(Display*, Drawable, GC, int, int, unsigned int, unsigned int);
+	int		(*XDrawPoint)	(Display*, Drawable, GC, int, int);
+	int		(*XFlush)		(Display*);
+	int		(*XSync)		(Display*, Bool);
+	int		(*XBell)		(Display*, int);
+	int		(*XLookupString)(XKeyEvent*, char*, int, KeySym*, XComposeStatus*);
+	int		(*XNextEvent)	(Display*, XEvent *);
+	XSizeHints*	(*XAllocSizeHints)(void);
+	void		(*XSetWMNormalHints)	(Display*, Window, XSizeHints*);
+	int		(*XResizeWindow)(Display*, Window, unsigned int, unsigned int);
+	int		(*XMapWindow)	(Display*, Window);
+	int		(*XFree)		(void *data);
+	int		(*XFreePixmap)	(Display*, Pixmap);
+	Pixmap	(*XCreatePixmap)(Display*, Drawable, unsigned int, unsigned int, unsigned int);
+	void	(*XCopyArea)	(Display*, Drawable, Drawable, GC, int, int, unsigned int, unsigned int, int, int);
+	Pixmap	(*XCreateBitmapFromData)	(Display*, Drawable, _Xconst char*, unsigned int, unsigned int);
+	Status	(*XAllocColor)	(Display*, Colormap, XColor*);
+	Display*(*XOpenDisplay)	(_Xconst char*);
+	Window	(*XCreateSimpleWindow)	(Display*, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned long);
+	GC		(*XCreateGC)	(Display*, Drawable, unsigned long, XGCValues*);
+	int		(*XSelectInput)	(Display*, Window, long);
+	int		(*XStoreName)	(Display*, Window, _Xconst char*);
+	Window	(*XGetSelectionOwner)	(Display*, Atom);
+	int		(*XConvertSelection)	(Display*, Atom, Atom, Atom, Window, Time);
+	int		(*XGetWindowProperty)	(Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **);
+	int		(*XChangeProperty)		(Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int);
+	Status	(*XSendEvent)	(Display*, Window, Bool, long, XEvent*);
+	XImage*	(*XCreateImage)	(Display *, Visual *, unsigned int, int, int, char *,unsigned int, unsigned int, int, int);
+#ifndef XPutPixel
+	void	(*XPutPixel)	(XImage*,int,int,unsigned long);
+#endif
+	void	(*XPutImage)	(Display*, Drawable, GC, XImage *, int,int,int,int,unsigned int,unsigned int);
+#ifndef XDestroyImage
+	void	(*XDestroyImage)(XImage*);
+#endif
+	int		(*XSetSelectionOwner)	(Display*, Atom, Window, Time);	
+	int		(*XSetIconName)	(Display*, Window, _Xconst char *);
+	int		(*XSynchronize)	(Display*, Bool);
+	Status	(*XGetWindowAttributes)	(Display*,Window,XWindowAttributes*);
+};
+
+
+
+extern int local_pipe[2];			/* Used for passing local events */
+extern int key_pipe[2];			/* Used for passing keyboard events */
+
+extern struct x11 x11;
+
+extern char 	*copybuf;
+extern pthread_mutex_t	copybuf_mutex;
+extern char 	*pastebuf;
+extern sem_t	pastebuf_set;
+extern sem_t	pastebuf_used;
+extern sem_t	init_complete;
+extern sem_t	mode_set;
+extern int x11_window_xpos;
+extern int x11_window_ypos;
+extern int x11_window_width;
+extern int x11_window_height;
+extern int initialized;
+
+void x11_event_thread(void *args);
+
+#endif