1 /* This is the interface to the GPM mouse under Linux */
2 /* Copyright (c) 1992, 1998 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 <signal.h>
13 #include <slang.h>
14 
15 #include <gpm.h>
16 
17 #include "jdmacros.h"
18 
19 #include "buffer.h"
20 #include "sysdep.h"
21 #include "keymap.h"
22 #include "misc.h"
23 #include "paste.h"
24 #include "screen.h"
25 #include "ledit.h"
26 #include "ins.h"
27 #include "display.h"
28 #include "hooks.h"
29 #include "kanji.h"
30 
31 #define MOD_SHIFT 1
32 #define MOD_CTRL 4
33 
34 static int Mouse_Showing;
35 static int MouseX, MouseY;
36 static int Suspend_Mouse_Events;
37 
38 #if 0
39 /* This is needed to get the link to work with gpm. */
40 int wgetch (void)
41 {
42    return 0;
43 }
44 int *stdscr;
45 #endif
46 
draw_mouse(void)47 static void draw_mouse (void)
48 {
49    Gpm_Event event;
50 
51    if (MouseX < 1)
52      MouseX = 1;
53    else if (MouseX >= Jed_Num_Screen_Cols)
54      MouseX = Jed_Num_Screen_Cols;
55 
56    if (MouseY < 1)
57      MouseY = 1;
58    else if (MouseY >= Jed_Num_Screen_Rows)
59      MouseY = Jed_Num_Screen_Rows;
60 
61    event.x = MouseX;
62    event.y = MouseY;
63 
64    GPM_DRAWPOINTER(&event);
65    Mouse_Showing = 1;
66 }
67 
68 
mouse_handler_2(void)69 static int mouse_handler_2 (void)
70 {
71    int b = 0, nbuttons;
72    Gpm_Event event;
73    unsigned char buf[3];
74    JMouse_Type jm;
75 
76    if (Gpm_GetEvent (&event) <= 0) return -1;
77    if (Suspend_Mouse_Events)
78      {
79 	if (Suspend_Mouse_Events == -1)
80 	  Suspend_Mouse_Events = 0;
81 	return -1;
82      }
83 
84    MouseX += event.dx;
85    MouseY += event.dy;
86 
87    draw_mouse ();
88 
89    if (event.type & GPM_MOVE) return 0;
90 
91    nbuttons = 0;
92    if (event.buttons & GPM_B_LEFT)
93      {
94 	b = JMOUSE_BUTTON_1;
95 	nbuttons++;
96      }
97    if (event.buttons & GPM_B_MIDDLE)
98      {
99 	b = JMOUSE_BUTTON_2;
100 	nbuttons++;
101      }
102    if (event.buttons & GPM_B_RIGHT)
103      {
104 	b = JMOUSE_BUTTON_3;
105 	nbuttons++;
106      }
107 
108    if (nbuttons != 1) return 0;
109 
110    jm.button = b;
111 
112    if ((event.type & GPM_DOUBLE)
113        && (event.type & GPM_DOWN)) jm.type = JMOUSE_DOUBLE_CLICK;
114    else if ((event.type & GPM_TRIPLE)
115 	    && (event.type & GPM_DOWN)) jm.type = JMOUSE_TRIPLE_CLICK;
116    else if (event.type & GPM_DRAG) jm.type = JMOUSE_DRAG;
117    else if (event.type & GPM_DOWN) jm.type = JMOUSE_DOWN;
118    else if (event.type & GPM_UP) jm.type = JMOUSE_UP;
119    else return 0;
120 
121    if (event.modifiers & MOD_SHIFT)
122      {
123 	jm.state = JMOUSE_SHIFT;
124      }
125    else if (event.modifiers & MOD_CTRL)
126      {
127 	jm.state = JMOUSE_CTRL;
128      }
129    else jm.state = 0;
130 
131    jm.x = MouseX;
132    jm.y = MouseY;
133 
134    b = jed_mouse_add_event (&jm);
135    if (b == -1) return 0;
136 
137    buf[0] = 27; buf[1] = 0; buf[2] = (char) b;
138    ungetkey_string ((char *)buf, 3);
139    return 1;
140 }
141 
142 
143 static int Warp_Pending;
close_update(void)144 static void close_update (void)
145 {
146    if (Warp_Pending || Mouse_Showing)
147      {
148 	if (Warp_Pending)
149 	  {
150 	     MouseX = Screen_Col;
151 	     MouseY = Screen_Row;
152 	  }
153 	draw_mouse ();
154 	Warp_Pending = 0;
155      }
156    else Mouse_Showing = 0;
157 }
158 
warp_pointer(void)159 static void warp_pointer (void)
160 {
161    Warp_Pending = 1;
162 }
163 
164 static char *CutBuffer;
165 static int CutBuffer_Len;
166 
insert_cutbuffer(void)167 static int insert_cutbuffer (void)
168 {
169    CHECK_READ_ONLY
170    if (CutBuffer == NULL) return 0;
171    if (CutBuffer_Len) ins_chars ((unsigned char *) CutBuffer, CutBuffer_Len);
172    return CutBuffer_Len;
173 }
174 
region_to_cutbuffer(void)175 static void region_to_cutbuffer (void)
176 {
177    int nbytes;
178 
179    if (CutBuffer != NULL)
180      {
181 	SLfree (CutBuffer);
182      }
183 
184    CutBuffer = make_buffer_substring(&nbytes);
185    CutBuffer_Len = nbytes;
186 }
187 
close_mouse(void)188 static void close_mouse (void)
189 {
190    JMouse_Hide_Mouse_Hook = NULL;
191    X_Update_Close_Hook = NULL;
192 
193    if (JMouse_Event_Hook == NULL) return;
194    JMouse_Event_Hook = NULL;
195 
196    Gpm_Close ();
197 }
198 
disable_mouse(void)199 static void disable_mouse (void)
200 {
201    reset_tty ();		       /* closes mouse */
202    X_Open_Mouse_Hook = NULL;
203    X_Close_Mouse_Hook = NULL;
204    init_tty ();
205 }
206 
207 static SLang_Intrin_Fun_Type gpm_mouse_table[] =
208 {
209    MAKE_INTRINSIC("x_warp_pointer", warp_pointer, VOID_TYPE, 0),
210    MAKE_INTRINSIC("x_insert_cutbuffer", insert_cutbuffer, INT_TYPE, 0),
211    /* Prototype: Integer x_insert_cut_buffer ();
212     * Inserts cutbuffer into the current buffer and returns the number
213     * of characters inserted.
214     */
215    MAKE_INTRINSIC("x_copy_region_to_cutbuffer", region_to_cutbuffer, VOID_TYPE, 0),
216    /* Prototype: Void x_copy_region_to_cutbuffer();
217     */
218    MAKE_INTRINSIC("gpm_disable_mouse", disable_mouse, VOID_TYPE, 0),
219    SLANG_END_TABLE
220 };
221 
hide_mouse(int show)222 static void hide_mouse (int show)
223 {
224    Mouse_Showing = show;
225 }
226 
open_mouse(void)227 static int open_mouse (void)
228 {
229    static int not_first_time;
230    Gpm_Connect conn;
231    char *term;
232    SLSig_Fun_Type *sigtstp_fun;
233    int status;
234 
235    /* Unbelievable.  If we are running in an Xterm, gpm will turn on mouse
236     * reporting.  Nice huh? NOT!!!
237     */
238    term = getenv ("TERM");
239    if ((term != NULL)
240        && (!strncmp (term, "xterm", 5) && !strncmp(term, "kterm", 5)))
241      return -1;
242 
243    /* Another libgpm annoyance.  gpm installs a signal handler for SIGTSTP.
244     * I am going to un-install it.
245     */
246    sigtstp_fun = SLsignal (SIGTSTP, (SLSig_Fun_Type *)SIG_DFL);
247 
248    conn.eventMask = ~0;
249    conn.defaultMask = 0;
250    conn.maxMod = MOD_CTRL | MOD_SHIFT;
251    conn.minMod = 0;
252 
253    Mouse_Showing = 0;
254    Suspend_Mouse_Events = -1;
255    MouseX = Jed_Num_Screen_Cols / 2;
256    MouseY = Jed_Num_Screen_Rows / 2;
257 
258    status = Gpm_Open (&conn, 0);
259    /* Uninstall the gpm signal handler */
260    (void) SLsignal (SIGTSTP, sigtstp_fun);
261 
262    if (status == -1)
263      return -1;
264 
265    if (not_first_time == 0)
266      {
267 	if (-1 == SLadd_intrin_fun_table (gpm_mouse_table, "MOUSE"))
268 	  return -1;
269 
270 	not_first_time = 1;
271      }
272 
273    JMouse_Event_Hook = mouse_handler_2;
274    X_Update_Close_Hook = close_update;
275    JMouse_Hide_Mouse_Hook = hide_mouse;
276    return gpm_fd;
277 }
278 
279 
280 int (*X_Open_Mouse_Hook)(void) = open_mouse;
281 void (*X_Close_Mouse_Hook)(void) = close_mouse;
282 
283 
284