1 /* -*- mode: C; mode: fold; -*- */
2 /* Copyright (c) 1992, 1998, 2000, 2002, 2003, 2004, 2005, 2006 John E. Davis
3 * This file is part of JED editor library source.
4 *
5 * You may distribute this file under the terms the GNU General Public
6 * License. See the file COPYING for more information.
7 */
8 #include "config.h"
9 #include "jed-feat.h"
10
11 #include <stdio.h>
12 #include <dos.h>
13
14 #if JED_HAS_MULTICLICK
15 #include <sys/types.h>
16 #include <time.h>
17
18 static int JX_MultiClick_Time = 5; /* 5/10 of sec */
19 #endif
20
21 #ifdef __GO32__
22 # include <go32.h>
23 # include <sys/farptr.h>
24 #endif
25
26
27 static int Mouse_X, Mouse_Y;
28
generate_press(int x,int y,int type,int but)29 static void generate_press (int x, int y, int type, int but) /*{{{*/
30 {
31 char buf[3];
32 unsigned char b, s;
33 JMouse_Type jm;
34 int id;
35 #if JED_HAS_MULTICLICK
36 clock_t t;
37 static clock_t last_press_time;
38 static unsigned int clicks;
39 static unsigned int last_button;
40
41 t = clock ();
42
43 t = t / (CLOCKS_PER_SEC / 10); /* clocks per 1/10 sec */
44
45 if (type == JMOUSE_DOWN)
46 {
47 if (((int)last_button == but)
48 && (last_press_time + JX_MultiClick_Time > t))
49 {
50 clicks++;
51 if (clicks == 2)
52 type = JMOUSE_DOUBLE_CLICK;
53 else
54 type = JMOUSE_TRIPLE_CLICK;
55 }
56 else
57 {
58 clicks = 1;
59 last_button = but;
60 }
61 last_press_time = t;
62 }
63 else if ((clicks > 1) && ((int)last_button == but))
64 {
65 /* Last was a multi-click. Ignore this event. */
66 type = JMOUSE_IGNORE_EVENT;
67 }
68 #endif
69
70 Mouse_X = jm.x = x;
71 Mouse_Y = jm.y = y;
72
73 b = but & 0xF;
74 s = but >> 4;
75
76 if (b == 1) jm.button = JMOUSE_BUTTON_1; /* left */
77 else if (b == 2) jm.button = JMOUSE_BUTTON_3; /* right */
78 else jm.button = JMOUSE_BUTTON_2; /* middle */
79
80 if (s & 0x8) /* alt key--- use as middle */
81 {
82 jm.button = JMOUSE_BUTTON_2;
83 }
84
85 if (s & 0x3) jm.state = JMOUSE_SHIFT;
86 else if (s & 0x4) jm.state = JMOUSE_CTRL;
87 else jm.state = 0;
88
89 jm.type = type;
90
91 if (-1 == (id = jed_mouse_add_event (&jm)))
92 return;
93
94 buf[0] = 27; buf[1] = 0; buf[2] = (char) id;
95
96 ungetkey_string (buf, 3);
97 }
98
99 /*}}}*/
100
101 /* Mouse routines for the ibmpc */
102 static int Mouse_Hidden = 1;
103 static int Last_Mouse_Hidden = 1;
104
show_mouse(int show)105 static void show_mouse (int show) /*{{{*/
106 {
107 union REGS r;
108
109 if (show)
110 {
111 if (Mouse_Hidden == 0) return;
112 r.x.ax = 1;
113 }
114 else
115 {
116 if (Mouse_Hidden) return;
117 r.x.ax = 2;
118 }
119 int86 (0x33, &r, &r);
120 Mouse_Hidden = !show;
121 }
122
123 /*}}}*/
124
pc_close_mouse()125 static void pc_close_mouse () /*{{{*/
126 {
127 show_mouse (0);
128 }
129
130 /*}}}*/
131
pc_get_mouse_event(void)132 static int pc_get_mouse_event (void) /*{{{*/
133 {
134 union REGS r;
135 static int last_press;
136 short x, y;
137
138 /* return 0; */
139 if (last_press)
140 {
141 show_mouse (1);
142 r.x.ax = 6;
143 r.x.bx = (last_press & 0xF) - 1;
144 int86 (0x33, &r, &r);
145 if (r.x.bx)
146 {
147 /* truncate to short because DJGPP has junk in 32 bit registers*/
148 x = r.x.cx;
149 y = r.x.dx;
150 x = x / 8 + 1;
151 y = y / 8 + 1;
152 generate_press (x, y, JMOUSE_UP, last_press);
153 last_press = 0;
154 return 1;
155 }
156 }
157
158 r.x.ax = 3;
159 int86 (0x33, &r, &r);
160 x = r.x.cx;
161 y = r.x.dx;
162
163 #if 0
164 /* Check motion counters */
165 r.x.ax = 0xB;
166 int86 (0x33, &r, &r);
167 #endif
168 if (last_press)
169 {
170 #if 0
171 y += (short) (int) (r.x.dx);
172 #endif
173
174 x = x / 8 + 1;
175 y = y / 8 + 1;
176
177 if ((Mouse_X == x) && (Mouse_Y == y)) return 0;
178 generate_press (x, y, JMOUSE_DRAG, last_press);
179 return 1;
180 }
181
182 x = x / 8 + 1;
183 y = y / 8 + 1;
184
185 /* It looks like we are looking for a press. */
186 if ((Mouse_X != x) || (Mouse_Y != y))
187 {
188 /* mouse moved so show it. */
189 show_mouse (1);
190 }
191 Mouse_X = x;
192 Mouse_Y = y;
193 if (r.x.bx)
194 {
195 if (r.x.bx & 1) last_press = 1; /* left */
196 else if (r.x.bx & 2) last_press = 2; /* right */
197 else if (r.x.bx & 4) last_press = 3; /* middle */
198 else return 0;
199
200 /* Find shift key status */
201 #ifdef __GO32__
202 r.h.ah = 0x12;
203 int86 (0x16, &r, &r);
204 last_press |= (r.x.ax & 0xF) << 4;
205 #else
206 last_press |= (*(unsigned char far *) 0x417) << 4;
207 #endif
208 generate_press (x, y, JMOUSE_DOWN, last_press);
209 return 1;
210 }
211 return 0;
212 }
213
214 /*}}}*/
215
move_mouse(int x,int y)216 static void move_mouse (int x, int y) /*{{{*/
217 {
218 union REGS r;
219 r.x.ax = 4;
220 r.x.cx = 8 * (x - 1);
221 r.x.dx = 8 * (y - 1);
222 int86 (0x33, &r, &r);
223 }
224
225 /*}}}*/
226
pc_update_open_hook(void)227 static void pc_update_open_hook (void) /*{{{*/
228 {
229 Last_Mouse_Hidden = Mouse_Hidden;
230 if (Mouse_Hidden == 0) show_mouse (0);
231 }
232
233 /*}}}*/
234
235 static int Warp_Pending;
pc_update_close_hook(void)236 static void pc_update_close_hook (void) /*{{{*/
237 {
238 if (Last_Mouse_Hidden == 0) show_mouse (1);
239 if (Warp_Pending) move_mouse (Screen_Col, Screen_Row);
240 Warp_Pending = 0;
241 }
242
243 /*}}}*/
244
warp_pointer(void)245 static void warp_pointer (void) /*{{{*/
246 {
247 Warp_Pending = 1;
248 }
249
250 /*}}}*/
251
252 static char *CutBuffer;
253 static int CutBuffer_Len;
254
insert_cutbuffer(void)255 static int insert_cutbuffer (void) /*{{{*/
256 {
257 CHECK_READ_ONLY
258 if (CutBuffer == NULL) return 0;
259 if (CutBuffer_Len) jed_insert_nbytes ((unsigned char *) CutBuffer, CutBuffer_Len);
260 return CutBuffer_Len;
261 }
262
263 /*}}}*/
264
region_to_cutbuffer(void)265 static void region_to_cutbuffer (void) /*{{{*/
266 {
267 int nbytes;
268
269 if (CutBuffer != NULL)
270 {
271 SLfree (CutBuffer);
272 }
273
274 CutBuffer = make_buffer_substring(&nbytes);
275 CutBuffer_Len = nbytes;
276 }
277
278 /*}}}*/
279
280 static SLang_Intrin_Fun_Type gpm_mouse_table[] = /*{{{*/
281 {
282 MAKE_INTRINSIC("x_warp_pointer", warp_pointer, VOID_TYPE, 0),
283 MAKE_INTRINSIC("x_insert_cutbuffer", insert_cutbuffer, INT_TYPE, 0),
284 /* Prototype: Integer x_insert_cut_buffer ();
285 * Inserts cutbuffer into the current buffer and returns the number
286 * of characters inserted.
287 */
288 MAKE_INTRINSIC("x_copy_region_to_cutbuffer", region_to_cutbuffer, VOID_TYPE, 0),
289 /* Prototype: Void x_copy_region_to_cutbuffer();
290 */
291 SLANG_END_TABLE
292 };
293
294 /*}}}*/
295
296 void (*X_Close_Mouse_Hook)(void);
pc_open_mouse(void)297 static int pc_open_mouse (void) /*{{{*/
298 {
299 union REGS r;
300 int rows, cols, scanlines;
301 static int not_first_time;
302
303 X_Close_Mouse_Hook = NULL;
304 JMouse_Event_Hook = NULL;
305 JMouse_Hide_Mouse_Hook = NULL;
306 X_Update_Open_Hook = NULL;
307 X_Update_Close_Hook = NULL;
308 #ifndef __GO32__
309 if (getvect (0x33) == NULL) return -1;
310 #endif
311 /* Now see if the mouse is present */
312 r.x.ax = 0x21;
313 int86 (0x33, &r, &r);
314 if (r.x.ax == 0x21) return -1;
315
316 jed_get_screen_size (&rows, &cols);
317
318 #ifdef __GO32__
319 scanlines = _farpeekw (_go32_conventional_mem_selector (), 0x485);
320 #else
321 scanlines = *(int *) 0x485;
322 #endif
323 if (scanlines <= 0) scanlines = 8;
324
325 r.x.ax = 7;
326 r.x.cx = 0;
327 r.x.dx = 8 * cols - 1;
328 int86 (0x33, &r, &r);
329
330 r.x.ax = 8;
331 r.x.cx = 0;
332 r.x.dx = scanlines * rows - 1;
333 int86 (0x33, &r, &r);
334
335 move_mouse (cols / 2 + 1, rows / 2 + 1);
336
337 if (not_first_time == 0)
338 {
339 if (-1 == SLadd_intrin_fun_table (gpm_mouse_table, "MOUSE"))
340 return -1;
341
342 not_first_time = 1;
343 }
344
345 JMouse_Hide_Mouse_Hook = show_mouse;
346 X_Close_Mouse_Hook = pc_close_mouse;
347 JMouse_Event_Hook = pc_get_mouse_event;
348 X_Update_Open_Hook = pc_update_open_hook;
349 X_Update_Close_Hook = pc_update_close_hook;
350 return 1;
351 }
352
353 /*}}}*/
354
355 int (*X_Open_Mouse_Hook)(void) = pc_open_mouse;
356