You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

428 lines
11KB

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