/* */
This source file includes following definitions.
- mouseinit
- mousemenu
- loadmenu
- mousereinit
- mousecleanup
- drawscrollbar
- getmouseaction
- getcoordinate
- getpercent
1 /*===========================================================================
2 Copyright (c) 1998-2000, The Santa Cruz Operation
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 *Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 *Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 *Neither name of The Santa Cruz Operation nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
20 IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 DAMAGE.
31 =========================================================================*/
32
33 /** @file
34 * mouse functions
35 *
36 * cscope - interactive C symbol cross-reference
37 */
38
39 #include "global-cscope.h"
40
41 BOOL mouse = NO; /**< mouse interface */
42
43 #ifdef UNIXPC /* build command requires #ifdef instead of #if */
44 #include <sys/window.h>
45 BOOL unixpcmouse = NO; /**< running with a mouse on the @NAME{Unix} @NAME{PC}? */
46 static int uw_hs, uw_vs; /**< character height and width */
47 #endif
48
49 static char const rcsid[] = "$Id: mouse.c,v 1.2 2012/10/13 07:02:07 shigio Exp $";
50
51 typedef struct { /* menu */
52 char *text;
53 char *value;
54 } MENU;
55
56 static MENU mainmenu[] = { /**< main menu */
57 {"Send", "##\033s##\r"},
58 {"Repeat", "\031"},
59 {"Edit All", "\05"},
60 {"Rebuild", "\022"},
61 {"Shell", "!"},
62 {"Redraw", "\f"},
63 {"Help", "?"},
64 {"Exit", "\04"},
65 {NULL, NULL}
66 };
67
68 static MENU changemenu[] = { /**< change mode menu */
69 {"Mark Screen", "*"},
70 {"Mark All", "a"},
71 {"Change", "\04"},
72 {"No Change", "\033"},
73 {"Shell", "!"},
74 {"Redraw", "\f"},
75 {"Help", "?"},
76 {NULL, NULL}
77 };
78
79 static MENU *loaded; /**< menu loaded */
80 static BOOL emacsviterm = NO; /**< terminal type */
81
82 static void loadmenu(MENU *menu);
83 static int getcoordinate(void);
84 static int getpercent(void);
85
86 /** see if there is a mouse interface */
87
88 void
89 mouseinit(void)
90 {
91 char *term;
92
93 /* see if this is emacsterm or viterm */
94 term = mygetenv("TERM", "");
95 if (strcmp(term, "emacsterm") == 0 ||
96 strcmp(term, "viterm") == 0) {
97 emacsviterm = YES;
98 mouse = YES;
99 }
100 /* the MOUSE enviroment variable is for 5620 terminal programs that have
101 mouse support but the TERM environment variable is the same as a
102 terminal without a mouse, such as myx */
103 else if (strcmp(mygetenv("MOUSE", ""), "myx") == 0) {
104 mouse = YES;
105 }
106 #if UNIXPC
107 else if (strcmp(term,"s4") == 0 ||
108 strcmp(term,"s120") == 0 ||
109 strcmp(term,"s90") == 0) {
110 int retval;
111 struct uwdata uwd; /* Window data structure */
112 struct umdata umd; /* Mouse data structure */
113
114 /* Ask for character size info */
115
116 retval = ioctl(1,WIOCGETD,&uwd);
117 if(retval || uwd.uw_hs <= 0 || uwd.uw_vs <= 0) {
118 /**************************************************
119 * something wrong with the kernel, so fake it...
120 **************************************************/
121 if(!strcmp(term,"s4")) {
122 uw_hs = 9;
123 uw_vs = 12;
124 }
125 else {
126 uw_hs = 6;
127 uw_vs = 10;
128 }
129 }
130 else {
131 /* Kernel is working and knows about this font */
132 uw_hs = uwd.uw_hs;
133 uw_vs = uwd.uw_vs;
134 }
135
136 /**************************************************
137 * Now turn on mouse reporting so we can actually
138 * make use of all this stuff.
139 **************************************************/
140 if((retval = ioctl(1,WIOCGETMOUSE,&umd)) != -1) {
141 umd.um_flags= MSDOWN+MSUP;
142 ioctl(1,WIOCSETMOUSE,&umd);
143 }
144 unixpcmouse = YES;
145 }
146 #endif
147 if (mouse == YES) {
148 loadmenu(mainmenu);
149 }
150 }
151
152 /** load the correct mouse menu */
153
154 void
155 mousemenu(void)
156 {
157 if (mouse == YES) {
158 if (changing == YES) {
159 loadmenu(changemenu);
160 }
161 else {
162 loadmenu(mainmenu);
163 }
164 }
165 }
166
167 /** download a menu */
168
169 static void
170 loadmenu(MENU *menu)
171 {
172 int i;
173
174 if (emacsviterm == YES) {
175 mousereinit();
176 (void) printf("\033V1"); /* display the scrollbar */
177 (void) printf("\033M0@%s@%s@", menu[0].text, menu[0].value);
178 for (i = 1; menu[i].text != NULL; ++i) {
179 (void) printf("\033M@%s@%s@", menu[i].text, menu[i].value);
180 }
181 }
182 else { /* myx */
183 int len;
184
185 mousecleanup();
186 (void) printf("\033[6;1X\033[9;1X");
187 for (i = 0; menu[i].text != NULL; ++i) {
188 len = strlen(menu[i].text);
189 (void) printf("\033[%d;%dx%s%s", len,
190 (int) (len + strlen(menu[i].value)),
191 menu[i].text, menu[i].value);
192 }
193 loaded = menu;
194 }
195 (void) fflush(stdout);
196 }
197
198 /** reinitialize the mouse in case @NAME{curses} changed the attributes */
199
200 void
201 mousereinit(void)
202 {
203 if (emacsviterm == YES) {
204
205 /* enable the mouse click and sweep coordinate control sequence */
206 /* and switch to menu 2 */
207 (void) printf("\033{2\033#2");
208 (void) fflush(stdout);
209 }
210 }
211
212 /** restore the mouse attributes */
213
214 void
215 mousecleanup(void)
216 {
217 int i;
218
219 if (loaded != NULL) { /* only true for myx */
220
221 /* remove the mouse menu */
222 (void) printf("\033[6;0X\033[9;0X");
223 for (i = 0; loaded[i].text != NULL; ++i) {
224 (void) printf("\033[0;0x");
225 }
226 loaded = NULL;
227 }
228 }
229
230 /** draw the scrollbar */
231
232 void
233 drawscrollbar(int top, int bot)
234 {
235 int p1, p2;
236
237 if (emacsviterm == YES) {
238 if (bot > top) {
239 p1 = 16 + (top - 1) * 100 / totallines;
240 p2 = 16 + (bot - 1) * 100 / totallines;
241 if (p2 > 116) {
242 p2 = 116;
243 }
244 if (p1 < 16) {
245 p1 = 16;
246 }
247 /* don't send ^S or ^Q because it will hang a layer using cu(1) */
248 if (p1 == ctrl('Q') || p1 == ctrl('S')) {
249 ++p1;
250 }
251 if (p2 == ctrl('Q') || p2 == ctrl('S')) {
252 ++p2;
253 }
254 }
255 else {
256 p1 = p2 = 16;
257 }
258 (void) printf("\033W%c%c", p1, p2);
259 }
260 }
261
262 /** get the mouse information */
263
264 MOUSE *
265 getmouseaction(char leading_char)
266 {
267 static MOUSE m;
268
269 #if UNIXPC
270
271 if(unixpcmouse == YES && leading_char == ESC) {
272
273 /* Called if cscope received an ESC character. See if it is
274 * a mouse report and if so, decipher it. A mouse report
275 * looks like: "<ESC>[?xx;yy;b;rM"
276 */
277 int x = 0, y = 0, button = 0, reason = 0;
278 int i;
279
280 /* Get a mouse report. The form is: XX;YY;B;RM where
281 * XX is 1,2, or 3 decimal digits with the X pixel position.
282 * Similarly for YY. B is a single decimal digit with the
283 * button number (4 for one, 2 for two, and 1 for three).
284 * R is the reason for the mouse report.
285 *
286 * In general, the input is read until the mouse report has
287 * been completely read in or we have discovered that this
288 * escape sequence is NOT a mouse report. In the latter case
289 * return the last character read to the input stream with
290 * myungetch().
291 */
292
293 /* Check for "[?" being next 2 chars */
294 if(((i = mygetch()) != '[') || ((i = mygetch()) != '?')) {
295 myungetch(i);
296 return(NULL);
297 }
298
299 /* Grab the X position (in pixels) */
300 while(isdigit(i = mygetch())) {
301 x = (x*10) + (i - '0');
302 }
303 if(i != ';') {
304 myungetch(i);
305 return(NULL); /* not a mouse report after all */
306 }
307
308 /* Grab the Y position (in pixels) */
309 while(isdigit(i = mygetch())) {
310 y = (y*10) + (i - '0');
311 }
312 if(i != ';') {
313 myungetch(i);
314 return(NULL);
315 }
316
317 /* Get which button */
318 if((button = mygetch()) > '4') {
319 myungetch(button);
320 return(NULL);
321 }
322 if((i = mygetch()) != ';') {
323 myungetch(i);
324 return(NULL);
325 }
326
327 /* Get the reason for this mouse report */
328 if((reason = mygetch()) > '8') {
329 myungetch(reason);
330 return(NULL);
331 }
332
333 /* sequence should terminate with an 'M' */
334 if((i = mygetch()) != 'M') {
335 myungetch(i);
336 return(NULL);
337 }
338
339
340 /* OK. We get a mouse report whenever a button is depressed
341 * or released. Let's ignore the report whenever the button
342 * is depressed until when I am ready to implement sweeping.
343 */
344 if(reason != '2') {
345 return(NULL); /* '2' means button is released */
346 }
347
348 /************************************************************
349 * Always indicate button 1 irregardless of which button was
350 * really pushed.
351 ************************************************************/
352 m.button = 1;
353
354 /************************************************************
355 * Convert pixel coordinates to line and column coords.
356 * The height and width are obtained using an ioctl() call
357 * in mouseinit(). This assumes that variable width chars
358 * are not being used ('though it would probably work anyway).
359 ************************************************************/
360
361 m.x1 = x/uw_hs; /* pixel/horizontal_spacing */
362 m.y1 = y/uw_vs; /* pixel/vertical_spacing */
363
364 /* "null" out the other fields */
365 m.percent = m.x2 = m.y2 = -1;
366 }
367 else
368 #endif /* not UNIXPC */
369
370 if (mouse == YES && leading_char == ctrl('X')) {
371
372 switch (mygetch()) {
373 case ctrl('_'): /* click */
374 if ((m.button = mygetch()) == '0') { /* if scrollbar */
375 m.percent = getpercent();
376 }
377 else {
378 m.x1 = getcoordinate();
379 m.y1 = getcoordinate();
380 m.x2 = m.y2 = -1;
381 }
382 break;
383
384 case ctrl(']'): /* sweep */
385 m.button = mygetch();
386 m.x1 = getcoordinate();
387 m.y1 = getcoordinate();
388 m.x2 = getcoordinate();
389 m.y2 = getcoordinate();
390 break;
391 default:
392 return(NULL);
393 }
394 }
395 else return(NULL);
396
397 return(&m);
398 }
399
400 /** get a row or column coordinate from a mouse button click or sweep */
401
402 static int
403 getcoordinate(void)
404 {
405 int c, next;
406
407 c = mygetch();
408 next = 0;
409 if (c == ctrl('A')) {
410 next = 95;
411 c = mygetch();
412 }
413 if (c < ' ') {
414 return (0);
415 }
416 return (next + c - ' ');
417 }
418
419 /** get a percentage */
420
421 static int
422 getpercent(void)
423 {
424 int c;
425
426 c = mygetch();
427 if (c < 16) {
428 return(0);
429 }
430 if (c > 120) {
431 return(100);
432 }
433 return(c - 16);
434 }
/* */