diff --git a/src/conio/Common.gmake b/src/conio/Common.gmake
index f4b3a303e228b7835106b79c993293aeb91ef08e..373053b4a8d37dd04556948b776b0e9076662832 100644
--- a/src/conio/Common.gmake
+++ b/src/conio/Common.gmake
@@ -23,6 +23,8 @@ CIOLIB_LDFLAGS	+=	${PTHREAD_LDFLAGS}
 CIOLIB_CFLAGS	+=	$(PTHREAD_CFLAGS)
 CIOLIB_OBJS	+=	$(LIBODIR)/ansi_cio.o $(LIBODIR)/threadwrap.o
 CIOLIB_OBJS	+=	$(LIBODIR)/curs_cio.o $(LIBODIR)/ciolib.o
+CIOLIB_OBJS	+=	$(LIBODIR)/mouse.o $(LIBODIR)/semwrap.o
+CIOLIB_OBJS	+=	$(LIBODIR)/genwrap.o $(PTHREAD_OBJS)
 CIOLIB_CFLAGS	+=	-I$(UIFC_SRC)
 
 # Curses Stuff
diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c
index 02e6facebe1faecc4e6b463bab796c7d5e3ae691..9407887b899874be852b796631079423ef5f5236 100644
--- a/src/conio/ciolib.c
+++ b/src/conio/ciolib.c
@@ -68,7 +68,7 @@ int try_x_init(int mode)
 {
 	if(!console_init()) {
 		cio_api.mode=CIOLIB_MODE_X;
-		cio_api.mouse=0;
+		cio_api.mouse=1;
 		cio_api.puttext=x_puttext;
 		cio_api.gettext=x_gettext;
 		cio_api.textattr=x_textattr;
@@ -83,7 +83,6 @@ int try_x_init(int mode)
 		cio_api.getch=x_getch;
 		cio_api.getche=x_getche;
 		cio_api.textmode=x_textmode;
-		cio_api.getmouse=NULL;
 		cio_api.showmouse=NULL;
 		cio_api.hidemouse=NULL;
 		cio_api.settitle=x_settitle;
@@ -112,7 +111,6 @@ int try_curses_init(int mode)
 		cio_api.getch=curs_getch;
 		cio_api.getche=curs_getche;
 		cio_api.textmode=curs_textmode;
-		cio_api.getmouse=curs_getmouse;
 		cio_api.showmouse=curs_showmouse;
 		cio_api.hidemouse=curs_hidemouse;
 		cio_api.settitle=NULL;
@@ -142,7 +140,6 @@ int try_ansi_init(int mode)
 		cio_api.getch=ansi_getch;
 		cio_api.getche=ansi_getche;
 		cio_api.textmode=ansi_textmode;
-		cio_api.getmouse=NULL;
 		cio_api.showmouse=NULL;
 		cio_api.hidemouse=NULL;
 		cio_api.settitle=NULL;
@@ -175,7 +172,6 @@ int try_conio_init(int mode)
 		cio_api.getch=win32_getch;
 		cio_api.getche=win32_getche;
 		cio_api.textmode=win32_textmode;
-		cio_api.getmouse=win32_getmouse;
 		cio_api.showmouse=win32_showmouse;
 		cio_api.hidemouse=win32_hidemouse;
 		cio_api.settitle=win32_settitle;
@@ -232,6 +228,7 @@ int initciolib(int mode)
 	cio_textinfo.winright=cio_textinfo.screenwidth;
 	cio_textinfo.winbottom=cio_textinfo.screenheight;
 	cio_textinfo.normattr=7;
+	_beginthread(ciolib_mouse_thread,0,NULL);
 	return(0);
 }
 
@@ -240,6 +237,8 @@ int ciolib_kbhit(void)
 	CIOLIB_INIT();
 	if(ungotch)
 		return(1);
+	if(mouse_pending())
+		return(1);
 	return(cio_api.kbhit());
 }
 
@@ -754,14 +753,6 @@ void ciolib_setcursortype(int a)
 	cio_api.setcursortype(a);
 }
 
-int ciolib_getmouse(struct cio_mouse_event *mevent) {
-	CIOLIB_INIT();
-
-	if(cio_api.getmouse!=NULL)
-		return(cio_api.getmouse(mevent));
-	return(-1);
-}
-
 int ciolib_showmouse(void) {
 	CIOLIB_INIT();
 
diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h
index 3af19e08e4edd7bb09c33398c1a3503e88437e0d..f639724d13cddd5e926721401b50643fe2515c7a 100644
--- a/src/conio/ciolib.h
+++ b/src/conio/ciolib.h
@@ -3,6 +3,8 @@
 #ifndef _CIOLIB_H_
 #define _CIOLIB_H_
 
+#include <mouse.h>
+
 enum {
 	 CIOLIB_MODE_AUTO
 	,CIOLIB_MODE_CURSES
@@ -81,12 +83,6 @@ struct text_info {
 	unsigned char cury;           /* y-coordinate in current window */
 };
 
-struct cio_mouse_event {
-	int	x;
-	int	y;
-	int	button;
-};
-
 typedef struct {
 	int		mode;
 	int		mouse;
@@ -123,7 +119,7 @@ typedef struct {
 	int		(*cputs)		(char *);
 	void	(*textbackground)	(int);
 	void	(*textcolor)	(int);
-	int		(*getmouse)		(struct cio_mouse_event *mevent);
+	int		(*getmouse)		(struct mouse_event *mevent);
 	int		(*hidemouse)	(void);
 	int		(*showmouse)	(void);
 	void	(*settitle)		(const char *);
diff --git a/src/conio/console.c b/src/conio/console.c
index 19ec879bc3eaf2135bc2b7d31c427ad5cd3d8e96..293155d603ea9711b18b52ad8501ccfa0a0a9d0b 100644
--- a/src/conio/console.c
+++ b/src/conio/console.c
@@ -47,6 +47,9 @@
 #include "console.h"
 #include "vparams.h"
 
+#include "keys.h"
+#include "mouse.h"
+
 /* Console definition variables */
 BYTE VideoMode;
 int FW, FH, FD;
@@ -561,58 +564,67 @@ static int
 video_event(XEvent *ev)
 {
 	switch (ev->type) {
-	case MotionNotify: {
-		XMotionEvent *me = (XMotionEvent *)ev;
-		me->x -= 2;
-		me->y -= 2;
-
-		mouse_status.x = (me->x < mouse_status.range.x)
-				    ? mouse_status.range.x
-				    : (me->x > mouse_status.range.w)
-				    ? mouse_status.range.w : me->x;
-		mouse_status.y = (me->y < mouse_status.range.y)
-				    ? mouse_status.range.y
-				    : (me->y > mouse_status.range.h)
-				    ? mouse_status.range.h : me->y;
-		break;
-	    }
-	case ButtonRelease: {
-		XButtonEvent *be = (XButtonEvent *)ev;
-		be->x -= 2;
-		be->y -= 2;
-
-		if (be->button < 3)
-		    mouse_status.ups[be->button]++;
-
-		mouse_status.x = (be->x < mouse_status.range.x)
-				    ? mouse_status.range.x
-				    : (be->x > mouse_status.range.w)
-				    ? mouse_status.range.w : be->x;
-		mouse_status.y = (be->y < mouse_status.range.y)
-				    ? mouse_status.range.y
-				    : (be->y > mouse_status.range.h)
-				    ? mouse_status.range.h : be->y;
-		break;
-	    }
-	case ButtonPress: {
-		XButtonEvent *be = (XButtonEvent *)ev;
-		be->x -= 2;
-		be->y -= 2;
-
-		if (be->button < 3)
-		    mouse_status.downs[be->button]++;
-
-		mouse_status.x = (be->x < mouse_status.range.x)
-				    ? mouse_status.range.x
-				    : (be->x > mouse_status.range.w)
-				    ? mouse_status.range.w : be->x;
-		mouse_status.y = (be->y < mouse_status.range.y)
-				    ? mouse_status.range.y
-				    : (be->y > mouse_status.range.h)
-				    ? mouse_status.range.h : be->y;
-
-		break;
-	    }
+		case MotionNotify: {
+				XMotionEvent *me = (XMotionEvent *)ev;
+				me->x -= 2;
+				me->y -= 8;
+				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 -= 8;
+				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 -= 8;
+				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:
@@ -1334,20 +1346,26 @@ tty_read(int flag)
 		return(r & 0xff);
 	}
 
-	if (KbdEmpty()) {
+	if (KbdEmpty() && !mouse_pending()) {
 		if (flag & TTYF_BLOCK) {
-			while (KbdEmpty())
+			while (KbdEmpty() && !mouse_pending())
 			tty_pause();
 		} else {
 			return(-1);
 		}
     }
 
-    r = KbdRead();
-    if ((r & 0xff) == 0)
-		x_nextchar = r >> 8;
-    r &= 0xff;
-    return(r & 0xff);
+	if(mouse_pending()) {
+		x_nextchar=CIO_KEY_MOUSE>>8;
+		return(CIO_KEY_MOUSE&0xff);
+	}
+	else {
+    	r = KbdRead();
+    	if ((r & 0xff) == 0)
+			x_nextchar = r >> 8;
+    	r &= 0xff;
+    	return(r & 0xff);
+	}
 }
 
 int
diff --git a/src/conio/curs_cio.c b/src/conio/curs_cio.c
index bc78666c00147d5ea21017e9922f94a108f79b22..04a41410a3836f03bc0ff4fe89d0e012e8cbe892 100644
--- a/src/conio/curs_cio.c
+++ b/src/conio/curs_cio.c
@@ -8,6 +8,7 @@
 #include "ciolib.h"
 #include "curs_cio.h"
 #include "keys.h"
+#include "mouse.h"
 
 static unsigned char curs_nextgetch=0;
 const int curs_tabs[10]={9,17,25,33,41,49,57,65,73,80};
@@ -401,6 +402,8 @@ int curs_kbhit(void)
 
 	if(curs_nextgetch)
 		return(1);
+	if(mouse_pending())
+		return(1);
 	timeout.tv_sec=0;
 	timeout.tv_usec=0;
 	FD_ZERO(&rfds);
@@ -639,6 +642,7 @@ int curs_initciolib(long inmode)
 	keypad(stdscr, TRUE);
 	scrollok(stdscr,FALSE);
 	raw();
+	halfdelay(1);
 	atexit(call_endwin);
 
 	/* Set up color pairs */
@@ -649,8 +653,10 @@ int curs_initciolib(long inmode)
 	}
 	mode = inmode;
 	#ifdef NCURSES_VERSION_MAJOR
-		if(mousemask(BUTTON1_CLICKED|BUTTON3_CLICKED,NULL)==BUTTON1_CLICKED|BUTTON3_CLICKED)
+		if(mousemask(BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION,NULL)==BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION) {
+			mouseinterval(0);
 			cio_api.mouse=1;
+		}
 		else
 			mousemask(0,NULL);
 	#endif
@@ -761,190 +767,220 @@ int curs_putch(int c)
 int curs_getch(void)
 {
 	int ch;
+	MEVENT mevnt;
 
 	if(curs_nextgetch) {
 		ch=curs_nextgetch;
 		curs_nextgetch=0;
 	}
 	else {
-		while((ch=getch())==ERR) {
-			delay(1);
+		while((ch=getch())==ERR && !mouse_pending());
+		if(mouse_pending()) {
+			curs_nextgetch=CIO_KEY_MOUSE>>8;
+			ch=CIO_KEY_MOUSE & 0xff;
 		}
-		if(ch > 255) {
-			switch(ch) {
-				case KEY_DOWN:            /* Down-arrow */
-					curs_nextgetch=0x50;
-					ch=0;
-					break;
-
-				case KEY_UP:		/* Up-arrow */
-					curs_nextgetch=0x48;
-					ch=0;
-					break;
-
-				case KEY_LEFT:		/* Left-arrow */
-					curs_nextgetch=0x4b;
-					ch=0;
-					break;
-
-				case KEY_RIGHT:            /* Right-arrow */
-					curs_nextgetch=0x4d;
-					ch=0;
-					break;
-
-				case KEY_HOME:            /* Home key (upward+left arrow) */
-					curs_nextgetch=0x47;
-					ch=0;
-					break;
-
-				case KEY_BACKSPACE:            /* Backspace (unreliable) */
-					ch=8;
-					break;
-
-				case KEY_F(1):			/* Function Key */
-					curs_nextgetch=0x3b;
-					ch=0;
-					break;
-
-				case KEY_F(2):			/* Function Key */
-					curs_nextgetch=0x3c;
-					ch=0;
-					break;
-
-				case KEY_F(3):			/* Function Key */
-					curs_nextgetch=0x3d;
-					ch=0;
-					break;
-
-				case KEY_F(4):			/* Function Key */
-					curs_nextgetch=0x3e;
-					ch=0;
-					break;
-
-				case KEY_F(5):			/* Function Key */
-					curs_nextgetch=0x3f;
-					ch=0;
-					break;
-
-				case KEY_F(6):			/* Function Key */
-					curs_nextgetch=0x40;
-					ch=0;
-					break;
-
-				case KEY_F(7):			/* Function Key */
-					curs_nextgetch=0x41;
-					ch=0;
-					break;
-
-				case KEY_F(8):			/* Function Key */
-					curs_nextgetch=0x42;
-					ch=0;
-					break;
-
-				case KEY_F(9):			/* Function Key */
-					curs_nextgetch=0x43;
-					ch=0;
-					break;
-
-				case KEY_F(10):			/* Function Key */
-					curs_nextgetch=0x44;
-					ch=0;
-					break;
-
-				case KEY_F(11):			/* Function Key */
-					curs_nextgetch=0x57;
-					ch=0;
-					break;
-
-				case KEY_F(12):			/* Function Key */
-					curs_nextgetch=0x58;
-					ch=0;
-					break;
-
-				case KEY_DC:            /* Delete character */
-					curs_nextgetch=0x53;
-					ch=0;
-					break;
-
-				case KEY_IC:            /* Insert char or enter insert mode */
-					curs_nextgetch=0x52;
-					ch=0;
-					break;
-
-				case KEY_EIC:            /* Exit insert char mode */
-					curs_nextgetch=0x52;
-					ch=0;
-					break;
-
-				case KEY_NPAGE:            /* Next page */
-					curs_nextgetch=0x51;
-					ch=0;
-					break;
-
-				case KEY_PPAGE:            /* Previous page */
-					curs_nextgetch=0x49;
-					ch=0;
-					break;
-
-				case KEY_ENTER:            /* Enter or send (unreliable) */
-					curs_nextgetch=0x0d;
-					ch=0;
-					break;
-
-				case KEY_A1:		/* Upper left of keypad */
-					curs_nextgetch=0x47;
-					ch=0;
-					break;
-
-				case KEY_A3:		/* Upper right of keypad */
-					curs_nextgetch=0x49;
-					ch=0;
-					break;
-
-				case KEY_B2:		/* Center of keypad */
-					curs_nextgetch=0x4c;
-					ch=0;
-					break;
-
-				case KEY_C1:		/* Lower left of keypad */
-					curs_nextgetch=0x4f;
-					ch=0;
-					break;
-
-				case KEY_C3:		/* Lower right of keypad */
-					curs_nextgetch=0x51;
-					ch=0;
-					break;
-
-				case KEY_BEG:		/* Beg (beginning) */
-					curs_nextgetch=0x47;
-					ch=0;
-					break;
-
-				case KEY_CANCEL:		/* Cancel */
-					curs_nextgetch=0x03;
-					ch=0;
-					break;
-
-				case KEY_END:		/* End */
-					curs_nextgetch=0x4f;
-					ch=0;
-					break;
-
-				case KEY_SELECT:		/* Select  - Is "End" in X */
-					curs_nextgetch=0x4f;
-					ch=0;
-					break;
-
-				case KEY_MOUSE:			/* Mouse stuff */
-					ch=CIO_KEY_MOUSE>>8;
-					curs_nextgetch=CIO_KEY_MOUSE&0xff;
-					break;
-
-				default:
-					curs_nextgetch=0xff;
-					ch=0;
-					break;
+		else {
+			if(ch > 255) {
+				switch(ch) {
+					case KEY_DOWN:            /* Down-arrow */
+						curs_nextgetch=0x50;
+						ch=0;
+						break;
+
+					case KEY_UP:		/* Up-arrow */
+						curs_nextgetch=0x48;
+						ch=0;
+						break;
+
+					case KEY_LEFT:		/* Left-arrow */
+						curs_nextgetch=0x4b;
+						ch=0;
+						break;
+
+					case KEY_RIGHT:            /* Right-arrow */
+						curs_nextgetch=0x4d;
+						ch=0;
+						break;
+
+					case KEY_HOME:            /* Home key (upward+left arrow) */
+						curs_nextgetch=0x47;
+						ch=0;
+						break;
+
+					case KEY_BACKSPACE:            /* Backspace (unreliable) */
+						ch=8;
+						break;
+
+					case KEY_F(1):			/* Function Key */
+						curs_nextgetch=0x3b;
+						ch=0;
+						break;
+
+					case KEY_F(2):			/* Function Key */
+						curs_nextgetch=0x3c;
+						ch=0;
+						break;
+
+					case KEY_F(3):			/* Function Key */
+						curs_nextgetch=0x3d;
+						ch=0;
+						break;
+
+					case KEY_F(4):			/* Function Key */
+						curs_nextgetch=0x3e;
+						ch=0;
+						break;
+
+					case KEY_F(5):			/* Function Key */
+						curs_nextgetch=0x3f;
+						ch=0;
+						break;
+
+					case KEY_F(6):			/* Function Key */
+						curs_nextgetch=0x40;
+						ch=0;
+						break;
+
+					case KEY_F(7):			/* Function Key */
+						curs_nextgetch=0x41;
+						ch=0;
+						break;
+
+					case KEY_F(8):			/* Function Key */
+						curs_nextgetch=0x42;
+						ch=0;
+						break;
+
+					case KEY_F(9):			/* Function Key */
+						curs_nextgetch=0x43;
+						ch=0;
+						break;
+
+					case KEY_F(10):			/* Function Key */
+						curs_nextgetch=0x44;
+						ch=0;
+						break;
+
+					case KEY_F(11):			/* Function Key */
+						curs_nextgetch=0x57;
+						ch=0;
+						break;
+
+					case KEY_F(12):			/* Function Key */
+						curs_nextgetch=0x58;
+						ch=0;
+						break;
+
+					case KEY_DC:            /* Delete character */
+						curs_nextgetch=0x53;
+						ch=0;
+						break;
+
+					case KEY_IC:            /* Insert char or enter insert mode */
+						curs_nextgetch=0x52;
+						ch=0;
+						break;
+
+					case KEY_EIC:            /* Exit insert char mode */
+						curs_nextgetch=0x52;
+						ch=0;
+						break;
+
+					case KEY_NPAGE:            /* Next page */
+						curs_nextgetch=0x51;
+						ch=0;
+						break;
+
+					case KEY_PPAGE:            /* Previous page */
+						curs_nextgetch=0x49;
+						ch=0;
+						break;
+
+					case KEY_ENTER:            /* Enter or send (unreliable) */
+						curs_nextgetch=0x0d;
+						ch=0;
+						break;
+
+					case KEY_A1:		/* Upper left of keypad */
+						curs_nextgetch=0x47;
+						ch=0;
+						break;
+
+					case KEY_A3:		/* Upper right of keypad */
+						curs_nextgetch=0x49;
+						ch=0;
+						break;
+
+					case KEY_B2:		/* Center of keypad */
+						curs_nextgetch=0x4c;
+						ch=0;
+						break;
+
+					case KEY_C1:		/* Lower left of keypad */
+						curs_nextgetch=0x4f;
+						ch=0;
+						break;
+
+					case KEY_C3:		/* Lower right of keypad */
+						curs_nextgetch=0x51;
+						ch=0;
+						break;
+
+					case KEY_BEG:		/* Beg (beginning) */
+						curs_nextgetch=0x47;
+						ch=0;
+						break;
+
+					case KEY_CANCEL:		/* Cancel */
+						curs_nextgetch=0x03;
+						ch=0;
+						break;
+
+					case KEY_END:		/* End */
+						curs_nextgetch=0x4f;
+						ch=0;
+						break;
+
+					case KEY_SELECT:		/* Select  - Is "End" in X */
+						curs_nextgetch=0x4f;
+						ch=0;
+						break;
+
+					case KEY_MOUSE:			/* Mouse stuff */
+						if(getmouse(&mevnt)==OK) {
+							int evnt=0;
+							switch(mevnt.bstate) {
+								case BUTTON1_PRESSED:
+									evnt=CIOLIB_BUTTON_1_PRESS;
+									break;
+								case BUTTON1_RELEASED:
+									evnt=CIOLIB_BUTTON_1_RELEASE;
+									break;
+								case BUTTON2_PRESSED:
+									evnt=CIOLIB_BUTTON_2_PRESS;
+									break;
+								case BUTTON2_RELEASED:
+									evnt=CIOLIB_BUTTON_2_RELEASE;
+									break;
+								case BUTTON3_PRESSED:
+									evnt=CIOLIB_BUTTON_3_PRESS;
+									break;
+								case BUTTON3_RELEASED:
+									evnt=CIOLIB_BUTTON_3_RELEASE;
+									break;
+								case REPORT_MOUSE_POSITION:
+									evnt=CIOLIB_MOUSE_MOVE;
+									break;
+							}
+							ciomouse_gotevent(evnt, mevnt.x+1, mevnt.y+1);
+						}
+						break;
+
+					default:
+						curs_nextgetch=0xff;
+						ch=0;
+						break;
+				}
 			}
 		}
 	}
@@ -980,34 +1016,8 @@ int curs_hidemouse(void)
 int curs_showmouse(void)
 {
 	#ifdef NCURSES_VERSION_MAJOR
-		if(mousemask(BUTTON1_CLICKED|BUTTON3_CLICKED,NULL)==BUTTON1_CLICKED|BUTTON3_CLICKED)
+		if(mousemask(BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION,NULL)==BUTTON1_PRESSED|BUTTON1_RELEASED|BUTTON2_PRESSED|BUTTON2_RELEASED|BUTTON3_PRESSED|BUTTON3_RELEASED|REPORT_MOUSE_POSITION)
 			return(0);
 	#endif
 	return(-1);
 }
-
-/* cio_get_mouse() */
-int curs_getmouse(struct cio_mouse_event *mevent)
-{
-	#ifdef NCURSES_VERSION_MAJOR
-		MEVENT	mevnt;
-
-		if(getmouse(&mevnt)==OK) {
-			mevent->x=mevnt.x;
-			mevent->y=mevnt.y;
-			switch(mevnt.bstate) {
-				case BUTTON1_CLICKED:
-					mevent->button=1;
-					break;
-				case BUTTON3_CLICKED:
-					mevent->button=2;
-					break;
-			}
-		}
-		else
-			return(-1);
-		return(0);
-	#else
-		return(-1);
-	#endif
-}
diff --git a/src/conio/curs_cio.h b/src/conio/curs_cio.h
index b2126f62d1d5ebe5b7acc8289941937ed8edaafc..6420def416fe924756358896477f070735677486 100644
--- a/src/conio/curs_cio.h
+++ b/src/conio/curs_cio.h
@@ -27,7 +27,6 @@ void curs_setcursortype(int type);
 int curs_getch(void);
 int curs_getche(void);
 void curs_textmode(int mode);
-int curs_getmouse(struct cio_mouse_event *mevent);
 int curs_showmouse(void);
 int curs_hidemouse(void);
 #ifdef __cplusplus
diff --git a/src/conio/mouse.c b/src/conio/mouse.c
index 324567151aca01a850dcf5dbb94e13f3c17ea92f..4f8ad0e7f6ffb7607f04cd1399a05c6fae265e2c 100644
--- a/src/conio/mouse.c
+++ b/src/conio/mouse.c
@@ -1,5 +1,6 @@
 #include <genwrap.h>
 #include <semwrap.h>
+#include <threadwrap.h>
 
 #include "mouse.h"
 
@@ -13,10 +14,11 @@ enum {
 	,MOUSE_TRIPLECLICKED
 	,MOUSE_QUADPRESSED
 	,MOUSE_QUADCLICKED
+	,MOUSE_DRAGSTARTED
 };
 
-static pthread_mutex_t in_mutex;
-static pthread_mutex_t out_mutex;
+pthread_mutex_t in_mutex;
+pthread_mutex_t out_mutex;
 sem_t in_sem;
 
 struct in_mouse_event {
@@ -38,25 +40,15 @@ struct out_mouse_event {
 	void *nextevent;
 };
 
-struct curr_event {
-	int	event;		/* Current event (if successfull)
-				 * ie: If you're already clicked, and not moved, a double-click
-				 * is the "Current Event" */
-	int	sx;		/* Current event start x */
-	int	sy;		/* Current event start y */
-	clock_t	ts;		/* msclock() time this event will finish
-				 * ie: When double-click is current, release+timeout or
-				 * press+timeout */
-}
-
 struct mouse_state {
 	int	buttonstate;			/* Current state of all buttons - bitmap */
 	int	knownbuttonstatemask;	/* Mask of buttons that have done something since
 								 * We started watching... the rest are actually in
 								 * an unknown state */
-	int	button_states[3];				/* Expanded state of each button */
-	int	button_x[3];					/* Start X/Y position of the current state */
-	int	button_y[3];					
+	int	button_state[3];		/* Expanded state of each button */
+	int	button_x[3];			/* Start X/Y position of the current state */
+	int	button_y[3];
+	clock_t	timeout[3];	/* Button event timeouts (timespecs ie: time of expiry) */
 	int	curx;					/* Current X position */
 	int	cury;					/* Current Y position */
 	int	events;					/* Currently enabled events */
@@ -68,14 +60,11 @@ struct mouse_state {
 };
 
 struct mouse_state state;
+int mouse_events=0;
 
 void init_mouse(void)
 {
-	state.buttonstate=0;
-	state.knownbuttonstatemask=0;
-	state.curx=0;
-	state.cury=0;
-	state.events=0;
+	memset(&state,0,sizeof(state));
 	state.click_timeout=200;
 	state.multi_timeout=300;
 	state.events_in=(struct in_mouse_event *)NULL;
@@ -87,32 +76,27 @@ void init_mouse(void)
 
 int ciomouse_setevents(int events)
 {
-	state.events=events;
-	return state.events;
+	mouse_events=events;
+	return mouse_events;
 }
 
 int ciomouse_addevents(int events)
 {
-	state.events |= events;
-	return state.events;
+	mouse_events |= events;
+	return mouse_events;
 }
 
 int ciomouse_delevents(int events)
 {
-	state.events &= ~events;
-	return state.events;
+	mouse_events &= ~events;
+	return mouse_events;
 }
 
-static void ciomouse_gotevent(int event, int x, int y)
+void ciomouse_gotevent(int event, int x, int y)
 {
 	struct in_mouse_event *ime;
 	struct in_mouse_event **lastevent;
 
-	/* If you're not handling any mouse events, it doesn't matter what happens */
-	/* though this COULD be used to build up correct current mouse state data */
-	if(!state.events)
-		return;
-
 	ime=(struct in_mouse_event *)malloc(sizeof(struct in_mouse_event));
 	ime->ts=msclock();
 	ime->event=event;
@@ -122,61 +106,263 @@ static void ciomouse_gotevent(int event, int x, int y)
 
 	pthread_mutex_lock(&in_mutex);
 
-	for(lastevent=&state.events_in;*lastevent != NULL;lastevnet=&(lastevent->nextevent));
+	for(lastevent=&state.events_in;*lastevent != NULL;lastevent=&(*lastevent)->nextevent);
 	*lastevent=ime;
 
 	pthread_mutex_unlock(&in_mutex);
 	sem_post(&in_sem);
 }
 
-static void add_outevent(int event, int bstate, int kbsm, sx, sy, ex, ey)
+void add_outevent(int event, int x, int y)
 {
 	struct out_mouse_event *ome;
 	struct out_mouse_event **lastevent;
+	int	but=0;
 
-	ome=(struct out_mouse_event *)malloc(sizeof(out_mouse_ecent));
+	if(!(mouse_events & 1<<event))
+		return;
+	ome=(struct out_mouse_event *)malloc(sizeof(struct out_mouse_event));
 
+	but=CIOLIB_BUTTON_NUMBER(event);
 	ome->event=event;
-	ome->bstate=bstate;
-	ome->kbsm=kbsm;
-	ome->startx=sx;
-	ome->starty=sy;
-	ome->endx=ex;
-	ome->endy=ey;
+	ome->bstate=state.buttonstate;
+	ome->kbsm=state.knownbuttonstatemask;
+	ome->startx=but?state.button_x[but-1]:state.curx;
+	ome->starty=but?state.button_y[but-1]:state.cury;
+	ome->endx=x;
+	ome->endy=y;
 	ome->nextevent=(struct out_mouse_event *)NULL;
 
 	pthread_mutex_lock(&out_mutex);
 
-	for(lastevent=&state.events_out;*lastevent != NULL;lastevent=&(lastevent->nextevent));
+	for(lastevent=&state.events_out;*lastevent != NULL;lastevent=&(*lastevent)->nextevent);
 	*lastevent=ome;
 
-	pthread_mutex_unlock(&in_mutex);
+	pthread_mutex_unlock(&out_mutex);
 }
 
-static void ciolib_mouse_thread(void *data)
+void ciolib_mouse_thread(void *data)
 {
-	int	use_timeout=0;
 	struct timespec timeout;
-	init_mouse();
 	struct in_mouse_event *old_in_event;
+	int	timedout;
+	int timeout_button=0;
+	int but;
+	int delay;
+	clock_t	ttime=0;
 
+	init_mouse();
 	while(1) {
-		if(use_timeout)
-			sem_timedwait(&in_sem,&timeout);
+		timedout=0;
+		if(timeout_button) {
+			delay=state.timeout[timeout_button-1]-msclock();
+			if(delay<=0) {
+				timedout=1;
+			}
+			else {
+				timedout=sem_trywait_block(&in_sem,delay);
+			}
+		}
 		else
 			sem_wait(&in_sem);
+		if(timedout) {
+			state.timeout[timeout_button-1]=0;
+			switch(state.button_state[timeout_button-1]) {
+				case MOUSE_SINGLEPRESSED:
+					/* Press event */
+					add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_CLICKED:
+					/* Click Event */
+					add_outevent(CIOLIB_BUTTON_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_DOUBLEPRESSED:
+					/* Click event, then press event */
+					add_outevent(CIOLIB_BUTTON_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_DOUBLECLICKED:
+					/* Double-click event */
+					add_outevent(CIOLIB_BUTTON_DBL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_TRIPLEPRESSED:
+					/* Double-click event, then press event */
+					add_outevent(CIOLIB_BUTTON_DBL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_TRIPLECLICKED:
+					/* Triple-click event */
+					add_outevent(CIOLIB_BUTTON_TRPL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_QUADPRESSED:
+					/* Triple-click evetn then press event */
+					add_outevent(CIOLIB_BUTTON_TRPL_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					add_outevent(CIOLIB_BUTTON_PRESS(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					break;
+				case MOUSE_QUADCLICKED:
+					add_outevent(CIOLIB_BUTTON_QUAD_CLICK(timeout_button),state.button_x[timeout_button-1],state.button_y[timeout_button-1]);
+					/* Quad click event (This doesn't need a timeout does it? */
+					break;
+			}
+			state.button_state[timeout_button-1]=MOUSE_NOSTATE;
+		}
+		else {
+			but=CIOLIB_BUTTON_NUMBER(state.events_in->event);
+			switch(CIOLIB_BUTTON_BASE(state.events_in->event)) {
+				case CIOLIB_MOUSE_MOVE:
+					add_outevent(CIOLIB_MOUSE_MOVE,state.events_in->x,state.events_in->y);
+					for(but=1;but<=3;but++) {
+						switch(state.button_state[but-1]) {
+							case MOUSE_NOSTATE:
+								if(state.buttonstate & CIOLIB_BUTTON(but)) {
+									add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]);
+									add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+									state.button_state[but-1]=MOUSE_DRAGSTARTED;
+								}
+								break;
+							case MOUSE_SINGLEPRESSED:
+								add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+								state.button_state[but-1]=MOUSE_DRAGSTARTED;
+								break;
+							case MOUSE_CLICKED:
+								add_outevent(CIOLIB_BUTTON_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								state.button_state[but-1]=MOUSE_NOSTATE;
+								break;
+							case MOUSE_DOUBLEPRESSED:
+								add_outevent(CIOLIB_BUTTON_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+								state.button_state[but-1]=MOUSE_DRAGSTARTED;
+								break;
+							case MOUSE_DOUBLECLICKED:
+								add_outevent(CIOLIB_BUTTON_DBL_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								state.button_state[but-1]=MOUSE_NOSTATE;
+								break;
+							case MOUSE_TRIPLEPRESSED:
+								add_outevent(CIOLIB_BUTTON_DBL_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+								state.button_state[but-1]=MOUSE_DRAGSTARTED;
+								break;
+							case MOUSE_TRIPLECLICKED:
+								add_outevent(CIOLIB_BUTTON_TRPL_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								state.button_state[but-1]=MOUSE_NOSTATE;
+								break;
+							case MOUSE_QUADPRESSED:
+								add_outevent(CIOLIB_BUTTON_TRPL_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_START(but),state.button_x[but-1],state.button_y[but-1]);
+								add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+								state.button_state[but-1]=MOUSE_DRAGSTARTED;
+								break;
+							case MOUSE_DRAGSTARTED:
+								add_outevent(CIOLIB_BUTTON_DRAG_MOVE(but),state.events_in->x,state.events_in->y);
+								break;
+						}
+					}
+					break;
+				case CIOLIB_BUTTON_1_PRESS:
+					state.buttonstate|=1<<(but-1);
+					state.knownbuttonstatemask|=1<<(but-1);
+					switch(state.button_state[but-1]) {
+						case MOUSE_NOSTATE:
+							state.button_state[but-1]=MOUSE_SINGLEPRESSED;
+							state.button_x[but-1]=state.events_in->x;
+							state.button_y[but-1]=state.events_in->y;
+							state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_CLICKED:
+							state.button_state[but-1]=MOUSE_DOUBLEPRESSED;
+							state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_DOUBLECLICKED:
+							state.button_state[but-1]=MOUSE_TRIPLEPRESSED;
+							state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_TRIPLECLICKED:
+							state.button_state[but-1]=MOUSE_QUADPRESSED;
+							state.timeout[but-1]=msclock()+(state.click_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+					}
+					break;
+				case CIOLIB_BUTTON_1_RELEASE:
+					state.buttonstate&= ~(1<<(but-1));
+					state.knownbuttonstatemask|=1<<(but-1);
+					switch(state.button_state[but-1]) {
+						case MOUSE_NOSTATE:
+							state.button_x[but-1]=state.events_in->x;
+							state.button_y[but-1]=state.events_in->y;
+							add_outevent(CIOLIB_BUTTON_RELEASE(but),state.button_x[but-1],state.button_y[but-1]);
+							break;
+						case MOUSE_SINGLEPRESSED:
+							state.button_state[but-1]=MOUSE_CLICKED;
+							state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_DOUBLEPRESSED:
+							state.button_state[but-1]=MOUSE_DOUBLECLICKED;
+							state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_TRIPLEPRESSED:
+							state.button_state[but-1]=MOUSE_TRIPLECLICKED;
+							state.timeout[but-1]=msclock()+(state.multi_timeout*MSCLOCKS_PER_SEC)/1000;
+							break;
+						case MOUSE_QUADPRESSED:
+							state.button_state[but-1]=MOUSE_NOSTATE;
+							add_outevent(CIOLIB_BUTTON_QUAD_CLICK(but),state.button_x[but-1],state.button_y[but-1]);
+							state.timeout[but-1]=0;
+							break;
+						case MOUSE_DRAGSTARTED:
+							add_outevent(CIOLIB_BUTTON_DRAG_END(but),state.events_in->x,state.events_in->y);
+							state.button_state[but-1]=0;
+					}
+			}
+			state.curx=state.events_in->x;
+			state.cury=state.events_in->y;
 
-		/* Check for a timeout rather than a sem_post() */
-		
-		if(!validate_pending(state.events_in->event)) {
-			add_eventsfor(state.events_in->event);
+			pthread_mutex_lock(&in_mutex);
+			old_in_event=state.events_in;
+			state.events_in=state.events_in->nextevent;
+			free(old_in_event);
+			pthread_mutex_unlock(&in_mutex);
 		}
-		use_timeout=get_timeout(&timeout);
 
-		pthread_mutex_lock(&in_mutex);
-		old_in_event=state.events_in;
-		state.events_in=state.events_in->nextevent;
-		free(old_in_event);
-		pthread_mutes_unlock(&in_mutex);
+		ttime=-1;
+		timeout_button=0;
+		for(but=1;but<=3;but++) {
+			if(state.button_state[but-1]!=MOUSE_NOSTATE && state.button_state[but-1]!=MOUSE_DRAGSTARTED && state.timeout[but-1]<ttime) {
+				ttime=state.timeout[but-1];
+				timeout_button=but;
+			}
+		}
+	}
+}
+
+int mouse_pending(void)
+{
+	return(state.events_out!=NULL);
+}
+
+int ciolib_getmouse(struct mouse_event *mevent)
+{
+	int retval=0;
+	struct out_mouse_event *old_out_event;
+
+	pthread_mutex_lock(&out_mutex);
+
+	if(state.events_out!=NULL) {
+		mevent->event=state.events_out->event;
+		mevent->bstate=state.events_out->bstate;
+		mevent->kbsm=state.events_out->kbsm;
+		mevent->startx=state.events_out->startx;
+		mevent->starty=state.events_out->starty;
+		mevent->endx=state.events_out->endx;
+		mevent->endy=state.events_out->endy;
+		old_out_event=state.events_out;
+		state.events_out=state.events_out->nextevent;
+		free(old_out_event);
 	}
+	else
+		retval=-1;
+	pthread_mutex_unlock(&out_mutex);
+	return(retval);
 }
diff --git a/src/conio/mouse.h b/src/conio/mouse.h
index 6fcf4cb7c83c452e88642a8236e1bfc2a3218348..ef9f7086b7c008c7088d54942cb85dc5dc987b4e 100644
--- a/src/conio/mouse.h
+++ b/src/conio/mouse.h
@@ -53,13 +53,27 @@ enum {
 #define CIOLIB_BUTTON_CLICK(x)		((x-1)*9+3)
 #define CIOLIB_BUTTON_DBL_CLICK(x)	((x-1)*9+4)
 #define CIOLIB_BUTTON_TRPL_CLICK(x)	((x-1)*9+5)
-#define CIOLIB_BUTTON_QUAD_CLOCK(x)	((x-1)*9+6)
+#define CIOLIB_BUTTON_QUAD_CLICK(x)	((x-1)*9+6)
 #define CIOLIB_BUTTON_DRAG_START(x)	((x-1)*9+7)
 #define CIOLIB_BUTTON_DRAG_MOVE(x)	((x-1)*9+8)
 #define CIOLIB_BUTTON_DRAG_END(x)	((x-1)*9+9)
 
-#define CIOLIB_BUTTON_NUMBER(x)		((x-1)/9+1)
+#define CIOLIB_BUTTON_NUMBER(x)		((x+8)/9)
 
-#define CIOLIB_BUTTON_BASE(x)		(x-9*CIOLIB_BUTTON_NUMBER(x))
+#define CIOLIB_BUTTON_BASE(x)		(x!=CIOLIB_MOUSE_MOVE?x-9*(CIOLIB_BUTTON_NUMBER(x)-1):CIOLIB_MOUSE_MOVE)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void ciomouse_gotevent(int event, int x, int y);
+int mouse_pending(void);
+int ciolib_getmouse(struct mouse_event *mevent);
+void ciolib_mouse_thread(void *data);
+int ciomouse_setevents(int events);
+int ciomouse_addevents(int events);
+int ciomouse_delevents(int events);
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/src/conio/win32cio.c b/src/conio/win32cio.c
index e1ac43d80913a81907b7d2667db63f5433cd45fc..e1bcb024efb0f07fc883a3c147db9004cdff01e7 100644
--- a/src/conio/win32cio.c
+++ b/src/conio/win32cio.c
@@ -84,6 +84,7 @@ unsigned char WintoDOSAttr(WORD newattr)
 
 int win32_kbhit(void)
 {
+	static DWORD last_state=0;
 	INPUT_RECORD input;
 	DWORD num=0;
 
@@ -97,11 +98,32 @@ int win32_kbhit(void)
 			return(1);
 		if(domouse) {
 			if(input.EventType==MOUSE_EVENT) {
-				if(!input.Event.MouseEvent.dwEventFlags
-					&& (!input.Event.MouseEvent.dwButtonState
-						|| input.Event.MouseEvent.dwButtonState==FROM_LEFT_1ST_BUTTON_PRESSED
-						|| input.Event.MouseEvent.dwButtonState==RIGHTMOST_BUTTON_PRESSED))
-					return(1);
+				if(input.Event.MouseEvent.dwEventFlags==MOUSE_MOVED) {
+					ciomouse_gotevent(CIOLIB_MOUSE_MOVE,dwMousePosition.X+1,dwMousePosition.Y+1);
+				}
+				if(!input.Event.MouseEvent.dwEventFlags) {
+					switch(input.Event.MouseEvent.dwButtonState ^ last_state) {
+						case FROM_LEFT_1ST_BUTTON_PRESSED:
+							if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
+								ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+							else
+								ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+							break;
+						case FROM_LEFT_2ND_BUTTON_PRESSED:
+							if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
+								ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+							else
+								ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+							break;
+						case RIGHTMOST_BUTTON_PRESSED:
+							if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED)
+								ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+							else
+								ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+							break;
+					}
+					last_state=input.Event.MouseEvent.dwButtonState;
+				}
 			}
 		}
 		if(ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &num)
@@ -109,6 +131,8 @@ int win32_kbhit(void)
 			continue;
 		}
 	}
+	if(mouse_pending())
+		return(1);
 	return(0);
 }
 
@@ -125,6 +149,8 @@ int win32_getch(void)
 			lastch>>=8;
 			return(ch);
 		}
+		if(mousepending())
+			lastch=CIO_KEY_MOUSE;
 		if(!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &input, 1, &num)
 			|| !num || (input.EventType!=KEY_EVENT && input.EventType!=MOUSE_EVENT))
 			continue;
@@ -155,34 +181,32 @@ int win32_getch(void)
 				break;
 			case MOUSE_EVENT:
 				if(domouse) {
-					if(input.Event.MouseEvent.dwEventFlags!=0)
-						continue;
-					if(input.Event.MouseEvent.dwButtonState==0) {
-						if(cio_last_button_press.button
-								&& cio_last_button_press.x==input.Event.MouseEvent.dwMousePosition.X
-								&& cio_last_button_press.y==input.Event.MouseEvent.dwMousePosition.Y) {
-							memcpy(&last_mouse_click,&cio_last_button_press,sizeof(last_mouse_click));
-							memset(&cio_last_button_press,0,sizeof(cio_last_button_press));
-							lastch=CIO_KEY_MOUSE;
-							break;
+					if(input.EventType==MOUSE_EVENT) {
+						if(input.Event.MouseEvent.dwEventFlags==MOUSE_MOVED) {
+							ciomouse_gotevent(CIOLIB_MOUSE_MOVE,dwMousePosition.X+1,dwMousePosition.Y+1);
 						}
-						else {
-							memset(&cio_last_button_press,0,sizeof(cio_last_button_press));
-						}
-					}
-					else {
-						memset(&cio_last_button_press,0,sizeof(cio_last_button_press));
-						switch(input.Event.MouseEvent.dwButtonState) {
-							case FROM_LEFT_1ST_BUTTON_PRESSED:
-								cio_last_button_press.x=input.Event.MouseEvent.dwMousePosition.X;
-								cio_last_button_press.y=input.Event.MouseEvent.dwMousePosition.Y;
-								cio_last_button_press.button=1;
-								break;
-							case RIGHTMOST_BUTTON_PRESSED:
-								cio_last_button_press.x=input.Event.MouseEvent.dwMousePosition.X;
-								cio_last_button_press.y=input.Event.MouseEvent.dwMousePosition.Y;
-								cio_last_button_press.button=2;
-								break;
+						if(!input.Event.MouseEvent.dwEventFlags) {
+							switch(input.Event.MouseEvent.dwButtonState ^ last_state) {
+								case FROM_LEFT_1ST_BUTTON_PRESSED:
+									if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED)
+										ciomouse_gotevent(CIOLIB_BUTTON_1_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+									else
+										ciomouse_gotevent(CIOLIB_BUTTON_1_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+									break;
+								case FROM_LEFT_2ND_BUTTON_PRESSED:
+									if(input.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED)
+										ciomouse_gotevent(CIOLIB_BUTTON_2_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+									else
+										ciomouse_gotevent(CIOLIB_BUTTON_2_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+									break;
+								case RIGHTMOST_BUTTON_PRESSED:
+									if(input.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED)
+										ciomouse_gotevent(CIOLIB_BUTTON_3_PRESS,dwMousePosition.X+1,dwMousePosition.Y+1);
+									else
+										ciomouse_gotevent(CIOLIB_BUTTON_3_RELEASE,dwMousePosition.X+1,dwMousePosition.Y+1);
+									break;
+							}
+							last_state=input.Event.MouseEvent.dwButtonState;
 						}
 					}
 				}