gallium/draw: initial code to properly support llvm in the draw module
[mesa.git] / src / glut / dos / PC_HW / pc_mouse.c
1 /*
2 * PC/HW routine collection v1.3 for DOS/DJGPP
3 *
4 * Copyright (C) 2002 - Daniel Borca
5 * Email : dborca@yahoo.com
6 * Web : http://www.geocities.com/dborca
7 */
8
9
10 #include <dpmi.h>
11 #include <sys/exceptn.h>
12 #include <sys/segments.h>
13
14 #include "pc_hw.h"
15
16
17 #define PC_CUTE_WHEEL 1 /* CuteMouse WheelAPI */
18
19 #define MOUSE_STACK_SIZE 16384
20
21 #define CLEAR_MICKEYS() \
22 do { \
23 __asm __volatile ("movw $0xb, %%ax; int $0x33":::"%eax", "%ecx", "%edx"); \
24 ox = oy = 0; \
25 } while (0)
26
27 extern void mouse_wrap (void);
28 extern int mouse_wrap_end[];
29
30 static MFUNC mouse_func;
31 static long mouse_callback;
32 static __dpmi_regs mouse_regs;
33
34 static volatile struct {
35 volatile int x, y, z, b;
36 } pc_mouse;
37
38 static int minx = 0;
39 static int maxx = 319;
40 static int miny = 0;
41 static int maxy = 199;
42 static int minz = 0;
43 static int maxz = 255;
44
45 static int sx = 2;
46 static int sy = 2;
47
48 static int emulat3 = FALSE;
49
50 static int ox, oy;
51
52
53 static void
54 mouse (__dpmi_regs *r)
55 {
56 int nx = (signed short)r->x.si / sx;
57 int ny = (signed short)r->x.di / sy;
58 int dx = nx - ox;
59 int dy = ny - oy;
60 #if PC_CUTE_WHEEL
61 int dz = (signed char)r->h.bh;
62 #endif
63 ox = nx;
64 oy = ny;
65
66 pc_mouse.b = r->h.bl;
67 pc_mouse.x = MID(minx, pc_mouse.x + dx, maxx);
68 pc_mouse.y = MID(miny, pc_mouse.y + dy, maxy);
69 #if PC_CUTE_WHEEL
70 pc_mouse.z = MID(minz, pc_mouse.z + dz, maxz);
71 #endif
72
73 if (emulat3) {
74 if ((pc_mouse.b & 3) == 3) {
75 pc_mouse.b = 4;
76 }
77 }
78
79 if (mouse_func) {
80 mouse_func(pc_mouse.x, pc_mouse.y, pc_mouse.z, pc_mouse.b);
81 }
82 } ENDOFUNC(mouse)
83
84
85 void
86 pc_remove_mouse (void)
87 {
88 if (mouse_callback) {
89 pc_clexit(pc_remove_mouse);
90 __asm("\n\
91 movl %%edx, %%ecx \n\
92 shrl $16, %%ecx \n\
93 movw $0x0304, %%ax \n\
94 int $0x31 \n\
95 movw $0x000c, %%ax \n\
96 xorl %%ecx, %%ecx \n\
97 int $0x33 \n\
98 "::"d"(mouse_callback):"%eax", "%ecx");
99
100 mouse_callback = 0;
101
102 free((void *)(mouse_wrap_end[0] - MOUSE_STACK_SIZE));
103 }
104 }
105
106
107 int
108 pc_install_mouse (void)
109 {
110 int buttons;
111
112 /* fail if already call-backed */
113 if (mouse_callback) {
114 return 0;
115 }
116
117 /* reset mouse and get status */
118 __asm("\n\
119 xorl %%eax, %%eax \n\
120 int $0x33 \n\
121 andl %%ebx, %%eax \n\
122 movl %%eax, %0 \n\
123 ":"=g" (buttons)::"%eax", "%ebx");
124 if (!buttons) {
125 return 0;
126 }
127
128 /* lock wrapper */
129 LOCKDATA(mouse_func);
130 LOCKDATA(mouse_callback);
131 LOCKDATA(mouse_regs);
132 LOCKDATA(pc_mouse);
133 LOCKDATA(minx);
134 LOCKDATA(maxx);
135 LOCKDATA(miny);
136 LOCKDATA(maxy);
137 LOCKDATA(minz);
138 LOCKDATA(maxz);
139 LOCKDATA(sx);
140 LOCKDATA(sy);
141 LOCKDATA(emulat3);
142 LOCKDATA(ox);
143 LOCKDATA(oy);
144 LOCKFUNC(mouse);
145 LOCKFUNC(mouse_wrap);
146
147 mouse_wrap_end[1] = __djgpp_ds_alias;
148 /* grab a locked stack */
149 if ((mouse_wrap_end[0] = (int)pc_malloc(MOUSE_STACK_SIZE)) == NULL) {
150 return 0;
151 }
152
153 /* try to hook a call-back */
154 __asm("\n\
155 pushl %%ds \n\
156 pushl %%es \n\
157 movw $0x0303, %%ax \n\
158 pushl %%ds \n\
159 pushl %%cs \n\
160 popl %%ds \n\
161 popl %%es \n\
162 int $0x31 \n\
163 popl %%es \n\
164 popl %%ds \n\
165 jc 0f \n\
166 shll $16, %%ecx \n\
167 movw %%dx, %%cx \n\
168 movl %%ecx, %0 \n\
169 0: \n\
170 ":"=g"(mouse_callback)
171 :"S" (mouse_wrap), "D"(&mouse_regs)
172 :"%eax", "%ecx", "%edx");
173 if (!mouse_callback) {
174 free((void *)mouse_wrap_end[0]);
175 return 0;
176 }
177
178 /* adjust stack */
179 mouse_wrap_end[0] += MOUSE_STACK_SIZE;
180
181 /* install the handler */
182 mouse_regs.x.ax = 0x000c;
183 #if PC_CUTE_WHEEL
184 mouse_regs.x.cx = 0x7f | 0x80;
185 #else
186 mouse_regs.x.cx = 0x7f;
187 #endif
188 mouse_regs.x.dx = mouse_callback & 0xffff;
189 mouse_regs.x.es = mouse_callback >> 16;
190 __dpmi_int(0x33, &mouse_regs);
191
192 CLEAR_MICKEYS();
193
194 emulat3 = (buttons < 3);
195 pc_atexit(pc_remove_mouse);
196 return buttons;
197 }
198
199
200 MFUNC
201 pc_install_mouse_handler (MFUNC handler)
202 {
203 MFUNC old;
204
205 if (!mouse_callback && !pc_install_mouse()) {
206 return NULL;
207 }
208
209 old = mouse_func;
210 mouse_func = handler;
211 return old;
212 }
213
214
215 void
216 pc_mouse_area (int x1, int y1, int x2, int y2)
217 {
218 minx = x1;
219 maxx = x2;
220 miny = y1;
221 maxy = y2;
222 }
223
224
225 void
226 pc_mouse_speed (int xspeed, int yspeed)
227 {
228 DISABLE();
229
230 sx = MAX(1, xspeed);
231 sy = MAX(1, yspeed);
232
233 ENABLE();
234 }
235
236
237 int
238 pc_query_mouse (int *x, int *y, int *z)
239 {
240 *x = pc_mouse.x;
241 *y = pc_mouse.y;
242 *z = pc_mouse.z;
243 return pc_mouse.b;
244 }
245
246
247 void
248 pc_warp_mouse (int x, int y)
249 {
250 CLEAR_MICKEYS();
251
252 pc_mouse.x = MID(minx, x, maxx);
253 pc_mouse.y = MID(miny, y, maxy);
254
255 if (mouse_func) {
256 mouse_func(pc_mouse.x, pc_mouse.y, pc_mouse.z, pc_mouse.b);
257 }
258 }
259
260
261 /* Hack alert:
262 * `mouse_wrap_end' actually holds the
263 * address of stack in a safe data selector.
264 */
265 __asm("\n\
266 .text \n\
267 .p2align 5,,31 \n\
268 .global _mouse_wrap \n\
269 _mouse_wrap: \n\
270 cld \n\
271 lodsl \n\
272 movl %eax, %es:42(%edi) \n\
273 addw $4, %es:46(%edi) \n\
274 pushl %es \n\
275 movl %ss, %ebx \n\
276 movl %esp, %esi \n\
277 lss %cs:_mouse_wrap_end, %esp\n\
278 pushl %ss \n\
279 pushl %ss \n\
280 popl %es \n\
281 popl %ds \n\
282 movl ___djgpp_dos_sel, %fs \n\
283 pushl %fs \n\
284 popl %gs \n\
285 pushl %edi \n\
286 call _mouse \n\
287 popl %edi \n\
288 movl %ebx, %ss \n\
289 movl %esi, %esp \n\
290 popl %es \n\
291 iret \n\
292 .global _mouse_wrap_end \n\
293 _mouse_wrap_end:.long 0, 0");