1 /* Copyright (c) 1992, 1998 John E. Davis
2  * This file is part of JED editor library source.
3  *
4  * You may distribute this file under the terms the GNU General Public
5  * License.  See the file COPYING for more information.
6  */
7 #ifdef HAS_MOUSE
8 
9 #define INCL_ERRORS
10 #define INCL_SUB
11 #define INCL_DOSPROCESS
12 #define INCL_DOSSEMAPHORES
13 #include "config.h"
14 #include "jed-feat.h"
15 
16 #include <os2.h>
17 
18 #include <process.h>
19 
20 static void show_mouse (int show);
21 
22 static int Mouse_X, Mouse_Y;
23 
24 #if __os2_16__
25 typedef USHORT APIRET;
26 #define DosSetPriority DosSetPrty
27 #endif
28 
29 #define THREADSTACKSIZE      32768
30 static TID Os2_Mouse_ThreadID = (TID) 0;
31 
32 static int Mouse_Hidden = 1;
33 static int Last_Mouse_Hidden = 1;
34 
35 static HMOU Mouse_Handle = -1;
36 
37 #define	MOUSE_BN1 (MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_BN1_DOWN)
38 #define	MOUSE_BN2 (MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_BN2_DOWN)
39 #define	MOUSE_BN3 (MOUSE_MOTION_WITH_BN3_DOWN | MOUSE_BN3_DOWN)
40 
41 
42 #define	MOUSE_NOMOVE  (MOUSE_BN1_DOWN | MOUSE_BN2_DOWN | MOUSE_BN3_DOWN)
43 #define	MOUSE_DRAGGED (MOUSE_MOTION_WITH_BN1_DOWN | MOUSE_MOTION_WITH_BN2_DOWN | MOUSE_MOTION_WITH_BN3_DOWN)
44 #define	MOUSE_MOVED   (MOUSE_MOTION | MOUSE_DRAGGED)
45 
46 #define	MouseNoMove(event) (MOUSE_NOMOVE & event.fs)
47 #define	MouseMoved(event)  (MOUSE_MOVED & event.fs)
48 #define MouseDragged(event) (MOUSE_DRAGGED & event.fs)
49 #define	MouseButtonPressed(event,button) (event.fs & button)
50 #define	MouseButtons(event) (event.fs &	(MOUSE_BN1 | MOUSE_BN2 | MOUSE_BN3))
51 
52 static int buttonDown [3] = {0, 0, 0};
53 static int buttonMask [3];
54 USHORT noButtons;
55 
56 
os2_add_event(int x,int y,int type,int but)57 static void os2_add_event (int x, int y, int type, int but)
58 {
59    char buf[4];
60    int b, s, id;
61    JMouse_Type jm;
62 
63    Mouse_X = jm.x = x;
64    Mouse_Y = jm.y = y;
65 
66    b = but & 0xF;
67    s = but >> 4;
68 
69    if (b == 1) jm.button = JMOUSE_BUTTON_1;	       /* left */
70    else if (b == 2) jm.button = JMOUSE_BUTTON_3;    /* right */
71    else jm.button = JMOUSE_BUTTON_2;		       /* middle */
72 
73    if (s & 0x8) 		       /* alt key--- use as middle */
74      {
75 	jm.button = JMOUSE_BUTTON_2;
76      }
77 
78    if (s & 0x3)	jm.state = JMOUSE_SHIFT;
79    else if (s & 0x4) jm.state = JMOUSE_CTRL;
80    else jm.state = 0;
81 
82    jm.type = type;
83 
84    if (-1 == (id = jed_mouse_add_event (&jm)))
85      return;
86 
87    buf[0] = 27; buf[1] = 0; buf[2] = (char) id;
88 
89    ungetkey_string (buf, 3);
90 }
91 
92 
os2_mouse_handler(void * Args)93 static void os2_mouse_handler (void *Args)
94 {
95    MOUEVENTINFO event_info;
96    APIRET Error;
97    USHORT wait_flag;
98    int press, i;
99    short x, y;
100    KBDINFO kbd_info;
101 
102    (void) Args;
103    wait_flag = MOU_NOWAIT;
104 
105    DosSetPriority( PRTYS_THREAD, PRTYC_NOCHANGE, PRTYD_MINIMUM, 0 ) ;
106 
107    while (Mouse_Handle) {
108 
109       Error = MouReadEventQue (&event_info, &wait_flag, Mouse_Handle);
110       if ((Error != NO_ERROR) || !event_info.time) {
111 	DosSleep (5);
112         continue;
113       }
114 
115       x = event_info.col + 1;
116       y = event_info.row + 1;
117 
118       if (MouseMoved (event_info) && ((x != Mouse_X) || (y != Mouse_Y)))
119 	{
120 	   /* mouse moved so show it. */
121 	   show_mouse (1);
122 	}
123 
124       for(i = 0; i < noButtons; i++) {
125 	 if(MouseButtonPressed (event_info, buttonMask[i])) {
126 	    if (!buttonDown [i]) {
127 	       /* I don't think that we can find shift key status in OS/2, since we
128 		* are reading the keyboard in another thread */
129 	       kbd_info.cb = sizeof (kbd_info);
130 	       KbdGetStatus (&kbd_info, 0);
131 	       press = (i + 1) | ((kbd_info.fsState & 0xF) << 4);
132 	       os2_add_event (x, y, JMOUSE_DOWN, press);
133 	       buttonDown [i] = 1;
134 	       continue;
135 	    } else {         /* button already down */
136 	       if (MouseDragged (event_info))
137 		 {
138 		    if ((x == Mouse_X) && (y == Mouse_Y)) continue;
139 		    os2_add_event (x, y, JMOUSE_DRAG, i + 1);
140 		    continue;
141 		 }
142 	    }
143 
144 	 } else {
145 	    if (buttonDown [i]) {
146 	       os2_add_event (x, y, JMOUSE_UP, i + 1);
147 	       buttonDown [i] = 0;
148 	       continue;
149 	    }
150 	 }
151       }
152    }
153    Mouse_Handle = -1;
154    _endthread ();
155 }
156 
157 
158 
os2_get_mouse_event(void)159 static int os2_get_mouse_event (void)
160 {
161    return 0;
162 }
163 
164 /* Mouse routines for OS/2 */
165 
166 
show_mouse(int show)167 static void show_mouse (int show)
168 {
169    NOPTRRECT PtrRect;
170 
171    if (show)
172      {
173 	if (Mouse_Hidden == 0) return;
174 	MouDrawPtr (Mouse_Handle);
175      }
176    else
177      {
178 	if (Mouse_Hidden) return;
179 	PtrRect.row = 0;
180 	PtrRect.col = 0;
181 	PtrRect.cRow = Jed_Num_Screen_Rows - 1;
182 	PtrRect.cCol = Jed_Num_Screen_Cols - 1;
183 	MouRemovePtr (&PtrRect, Mouse_Handle);
184      }
185    Mouse_Hidden = !show;
186 }
187 
os2_close_mouse()188 static void os2_close_mouse ()
189 {
190    MouClose (Mouse_Handle);
191    Mouse_Handle = 0;
192 #if defined(__os2_16__)
193    while (!Mouse_Handle) DosSleep(0);
194 #else
195    DosWaitThread (&Os2_Mouse_ThreadID, DCWW_WAIT);
196 #endif
197    Os2_Mouse_ThreadID = 0;
198 }
199 
200 
201 
move_mouse(int x,int y)202 static void move_mouse (int x, int y)
203 {
204    PTRLOC ptr_loc;
205    ptr_loc.row = y - 1;
206    ptr_loc.col = x - 1;
207    MouSetPtrPos (&ptr_loc, Mouse_Handle);
208 }
209 
os2_update_open_hook(void)210 static void os2_update_open_hook (void)
211 {
212    Last_Mouse_Hidden = Mouse_Hidden;
213    if (Mouse_Hidden == 0) show_mouse (0);
214 }
215 
216 static int Warp_Pending;
os2_update_close_hook(void)217 static void os2_update_close_hook (void)
218 {
219    if (Last_Mouse_Hidden == 0) show_mouse (1);
220    if (Warp_Pending) move_mouse (Screen_Col - 1, Screen_Row - 1);
221    Warp_Pending = 0;
222 }
223 
warp_pointer(void)224 static void warp_pointer (void)
225 {
226    Warp_Pending = 1;
227 }
228 
229 static char *CutBuffer;
230 static int CutBuffer_Len;
231 
insert_cutbuffer(void)232 static int insert_cutbuffer (void)
233 {
234    CHECK_READ_ONLY
235    if (CutBuffer == NULL) return 0;
236    if (CutBuffer_Len) ins_chars ((unsigned char *) CutBuffer, CutBuffer_Len);
237    return CutBuffer_Len;
238 }
239 
region_to_cutbuffer(void)240 static void region_to_cutbuffer (void)
241 {
242    int nbytes;
243 
244    if (CutBuffer != NULL)
245      {
246 	SLfree (CutBuffer);
247      }
248 
249    CutBuffer = make_buffer_substring(&nbytes);
250    CutBuffer_Len = nbytes;
251 }
252 
253 static SLang_Intrin_Fun_Type os2_mouse_table[] =
254 {
255    MAKE_INTRINSIC("x_warp_pointer", warp_pointer, VOID_TYPE, 0),
256    MAKE_INTRINSIC("x_insert_cutbuffer", insert_cutbuffer, INT_TYPE, 0),
257    /* Prototype: Integer x_insert_cut_buffer ();
258     * Inserts cutbuffer into the current buffer and returns the number
259     * of characters inserted.
260     */
261    MAKE_INTRINSIC("x_copy_region_to_cutbuffer", region_to_cutbuffer, VOID_TYPE, 0),
262    /* Prototype: Void x_copy_region_to_cutbuffer();
263     */
264    SLANG_END_TABLE
265 };
266 
267 void (*X_Close_Mouse_Hook)(void);
268 
os2_open_mouse()269 static int os2_open_mouse ()
270 {
271    static int not_first_time = 0;
272    USHORT Error;
273 
274    X_Close_Mouse_Hook = NULL;
275    JMouse_Event_Hook = NULL;
276    JMouse_Hide_Mouse_Hook = NULL;
277    X_Update_Open_Hook = NULL;
278    X_Update_Close_Hook = NULL;
279 
280    /* Now open the device */
281 
282    Error = MouOpen (NULL, &Mouse_Handle);
283    if (Error)
284       return -1;
285 
286    Mouse_X = Jed_Num_Screen_Cols / 2 + 1;
287    Mouse_Y = Jed_Num_Screen_Rows / 2 + 1;
288 
289    MouDrawPtr (Mouse_Handle);
290    MouGetNumButtons (&noButtons, Mouse_Handle);
291    if (noButtons == 3)
292      buttonMask [2] = MOUSE_BN3;
293 
294    buttonMask [0] = MOUSE_BN1;
295    buttonMask [1] = MOUSE_BN2;
296 
297    MouFlushQue(Mouse_Handle);		/* flush mouse queue		*/
298 
299    move_mouse (Mouse_X, Mouse_Y);
300    if (not_first_time == 0)
301      {
302 	if (-1 == SLadd_intrin_fun_table (os2_mouse_table, "MOUSE"))
303 	  return -1;
304 
305 	not_first_time = 1;
306      }
307 
308 #if defined __BORLANDC__
309    Os2_Mouse_ThreadID = _beginthread (os2_mouse_handler, THREADSTACKSIZE, NULL);
310 #else
311    Os2_Mouse_ThreadID = _beginthread (os2_mouse_handler, NULL, THREADSTACKSIZE, NULL);
312 #endif
313 
314    JMouse_Hide_Mouse_Hook = show_mouse;
315    X_Close_Mouse_Hook = os2_close_mouse;
316 /* I am not sure if I should set this */
317    JMouse_Event_Hook = os2_get_mouse_event;
318    X_Update_Open_Hook = os2_update_open_hook;
319    X_Update_Close_Hook = os2_update_close_hook;
320    return 1;
321 }
322 
323 int (*X_Open_Mouse_Hook)(void) = os2_open_mouse;
324 
325 #endif
326