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