1 /**
2  ** dosinput.c ---- polled mode mouse and keyboard interface for DOS
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu]
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  **/
18 
19 #include <stdlib.h>
20 
21 #if defined(__TURBOC__) || defined(__WATCOMC__) /* GS - Watcom C++ 11.0 */
22 #include <conio.h>
23 #endif
24 
25 #ifdef   __DJGPP__
26 #include <pc.h>
27 #endif
28 
29 #include "libgrx.h"
30 #include "grxkeys.h"
31 #include "allocate.h"
32 #include "arith.h"
33 #include "int86.h"
34 #include "memcopy.h"
35 #include "memfill.h"
36 #include "mouse/input.h"
37 
38 static int  kbd_enabled = TRUE;
39 static int  mou_enabled = TRUE;
40 static int  mou_buttons = 0;
41 static long evt_lasttime;
42 
uninit(void)43 static void uninit(void)
44 {
45 	if(MOUINFO->msstatus > 1) MOUINFO->msstatus = 1;
46 }
47 
GrMouseDetect(void)48 int GrMouseDetect(void)
49 {
50 	Int86Regs r;
51 	if(MOUINFO->msstatus == 0) {
52 	    MOUINFO->msstatus = (-1);           /* assume missing */
53 	    sttzero(&r);
54 	    int33(&r);
55 	    if(IREG_AX(r) != 0) {
56 		atexit(uninit);
57 		MOUINFO->msstatus = 1;          /* present, but not initted */
58 	    }
59 	}
60 	return((MOUINFO->msstatus > 0) ? TRUE : FALSE);
61 }
62 
GrMouseInitN(int queue_size)63 void GrMouseInitN(int queue_size)
64 {
65 	uninit();
66 	queue_size = umax(4,umin(256,queue_size));
67 	init_queue(queue_size);
68 	if(GrMouseDetect()) {
69 	    GrMouseSetSpeed(1,1);
70 	    GrMouseSetAccel(100,1);
71 	    GrMouseSetLimits(0,0,SCRN->gc_xmax,SCRN->gc_ymax);
72 	    GrMouseWarp((SCRN->gc_xmax >> 1),(SCRN->gc_ymax >> 1));
73 	    _GrInitMouseCursor();
74 	    MOUINFO->msstatus = 2;
75 	    mou_buttons = 0;
76 	}
77 	GrMouseEventEnable(TRUE,TRUE);
78 	real_time(evt_lasttime);
79 	MOUINFO->uninit = uninit;
80 }
81 
GrMouseSetSpeed(int spmult,int spdiv)82 void GrMouseSetSpeed(int spmult,int spdiv)
83 {
84 	MOUINFO->spmult = umin(16,umax(1,spmult));
85 	MOUINFO->spdiv  = umin(16,umax(1,spdiv));
86 }
87 
GrMouseSetAccel(int thresh,int accel)88 void GrMouseSetAccel(int thresh,int accel)
89 {
90 	MOUINFO->thresh = umin(64,umax(1,thresh));
91 	MOUINFO->accel  = umin(16,umax(1,accel));
92 }
93 
GrMouseSetLimits(int x1,int y1,int x2,int y2)94 void GrMouseSetLimits(int x1,int y1,int x2,int y2)
95 {
96 	isort(x1,x2);
97 	isort(y1,y2);
98 	MOUINFO->xmin = imax(0,imin(x1,SCRN->gc_xmax));
99 	MOUINFO->ymin = imax(0,imin(y1,SCRN->gc_ymax));
100 	MOUINFO->xmax = imax(0,imin(x2,SCRN->gc_xmax));
101 	MOUINFO->ymax = imax(0,imin(y2,SCRN->gc_ymax));
102 }
103 
GrMouseWarp(int x,int y)104 void GrMouseWarp(int x,int y)
105 {
106 	MOUINFO->xpos = imax(MOUINFO->xmin,imin(MOUINFO->xmax,x));
107 	MOUINFO->ypos = imax(MOUINFO->ymin,imin(MOUINFO->ymax,y));
108 	GrMouseUpdateCursor();
109 }
110 
GrMouseEventEnable(int enable_kb,int enable_ms)111 void GrMouseEventEnable(int enable_kb,int enable_ms)
112 {
113 	kbd_enabled = enable_kb;
114 	mou_enabled = enable_ms;
115 }
116 
_GrUpdateInputs(void)117 void _GrUpdateInputs(void)
118 {
119 	for( ; ; ) {
120 	    Int86Regs r;
121 	    GrMouseEvent ev;
122 	    int gotevt = FALSE;
123 	    if(mou_enabled && (MOUINFO->msstatus == 2)) {
124 		int mick,btn;
125 		sttzero(&r);
126 		IREG_AX(r) = 11;                /* read mickey counters */
127 		int33(&r);
128 		if((mick = (short)IREG_CX(r)) != 0) {
129 		    update_coord(x,mick);
130 		}
131 		if((mick = (short)IREG_DX(r)) != 0) {
132 		    update_coord(y,mick);
133 		}
134 		IREG_AX(r) = 3;                 /* read button state */
135 		int33(&r);
136 		btn = IREG_BX(r);
137 		if(btn != mou_buttons) {
138 		    fill_mouse_ev(
139 			ev,
140 			mou_buttons,btn,
141 			GR_M_LEFT,
142 			GR_M_MIDDLE,
143 			GR_M_RIGHT,
144 			GR_M_P4,
145 			GR_M_P5,
146 			GrKeyStat()
147 		    );
148 		    real_dtime(ev.dtime,evt_lasttime);
149 		    enqueue_event(ev);
150 		    MOUINFO->moved = FALSE;
151 		    mou_buttons = btn;
152 		    gotevt = TRUE;
153 		}
154 	    }
155 	    if(kbd_enabled && GrKeyPressed()) {
156 		fill_keybd_ev(ev,GrKeyRead(),GrKeyStat());
157 		real_dtime(ev.dtime,evt_lasttime);
158 		enqueue_event(ev);
159 		MOUINFO->moved = FALSE;
160 		gotevt = TRUE;
161 	    }
162 	    if(!gotevt) break;
163 	}
164 }
165 
GrMouseGetEventT(int flags,GrMouseEvent * ev,long tout)166 void GrMouseGetEventT(int flags,GrMouseEvent *ev,long tout)
167 {
168 	int  msdraw;
169 	long prevtime;
170 	if(MOUINFO->msstatus == 0) GrMouseInit();
171 	msdraw = !MOUINFO->displayed && !(flags & GR_M_NOPAINT);
172 	if(msdraw) GrMouseDisplayCursor();
173 	real_time(prevtime);
174 	for( ; ; ) {
175 	    _GrUpdateInputs();
176 	    GrMouseUpdateCursor();
177 	    while(MOUINFO->qlength > 0) {
178 		dequeue_event((*ev));
179 		if(ev->flags & flags) {
180 		    if(msdraw) GrMouseEraseCursor();
181 		    return;
182 		}
183 	    }
184 	    if((flags & GR_M_POLL) ||
185 	       (tout == 0L) ||
186 	       (MOUINFO->moved && (flags & GR_M_MOTION))) {
187 		fill_mouse_ev(
188 		    (*ev),
189 		    mou_buttons,mou_buttons,
190 		    GR_M_LEFT,
191 		    GR_M_MIDDLE,
192 		    GR_M_RIGHT,
193 		    GR_M_P4,
194 		    GR_M_P5,
195 		    GrKeyStat()
196 		);
197 		if ( ev->flags ) /* something happend */
198 		  real_dtime(ev->dtime,evt_lasttime);
199 		else
200 		  ev->dtime = -1; /* special time if nothing happend */
201 		MOUINFO->moved = FALSE;
202 		if(msdraw) GrMouseEraseCursor();
203 		return;
204 	    }
205 	    if(tout > 0L) {
206 		long dtime;
207 		real_dtime(dtime,prevtime);
208 		if((tout -= dtime) < 0L) tout = 0L;
209 	    }
210 	}
211 }
212 
213