diff options
Diffstat (limited to 'src/mouse.c')
-rw-r--r-- | src/mouse.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/mouse.c b/src/mouse.c new file mode 100644 index 0000000..69b85c0 --- /dev/null +++ b/src/mouse.c @@ -0,0 +1,433 @@ +/*=========================================================================== + Copyright (c) 1998-2000, The Santa Cruz Operation + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + *Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + *Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + *Neither name of The Santa Cruz Operation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + =========================================================================*/ + +/* cscope - interactive C symbol cross-reference + * + * mouse functions + */ + +#include "global.h" + +BOOL mouse = NO; /* mouse interface */ + +#ifdef UNIXPC /* build command requires #ifdef instead of #if */ +#include <sys/window.h> +BOOL unixpcmouse = NO; /* running with a mouse on the Unix PC? */ +static int uw_hs, uw_vs; /* character height and width */ +#endif + +static char const rcsid[] = "$Id: mouse.c,v 1.4 2001/07/05 14:31:00 broeker Exp $"; + +typedef struct { /* menu */ + char *text; + char *value; +} MENU; + +static MENU mainmenu[] = { /* main menu */ + {"Send", "##\033s##\r"}, + {"Repeat", "\031"}, + {"Edit All", "\05"}, + {"Rebuild", "\022"}, + {"Shell", "!"}, + {"Redraw", "\f"}, + {"Help", "?"}, + {"Exit", "\04"}, + {NULL, NULL} +}; + +static MENU changemenu[] = { /* change mode menu */ + {"Mark Screen", "*"}, + {"Mark All", "a"}, + {"Change", "\04"}, + {"No Change", "\033"}, + {"Shell", "!"}, + {"Redraw", "\f"}, + {"Help", "?"}, + {NULL, NULL} +}; + +static MENU *loaded; /* menu loaded */ +static BOOL emacsviterm = NO; /* terminal type */ + +static void loadmenu(MENU *menu); +static int getcoordinate(void); +static int getpercent(void); + +/* see if there is a mouse interface */ + +void +mouseinit(void) +{ + char *term; + + /* see if this is emacsterm or viterm */ + term = mygetenv("TERM", ""); + if (strcmp(term, "emacsterm") == 0 || + strcmp(term, "viterm") == 0) { + emacsviterm = YES; + mouse = YES; + } + /* the MOUSE enviroment variable is for 5620 terminal programs that have + mouse support but the TERM environment variable is the same as a + terminal without a mouse, such as myx */ + else if (strcmp(mygetenv("MOUSE", ""), "myx") == 0) { + mouse = YES; + } +#if UNIXPC + else if (strcmp(term,"s4") == 0 || + strcmp(term,"s120") == 0 || + strcmp(term,"s90") == 0) { + int retval; + struct uwdata uwd; /* Window data structure */ + struct umdata umd; /* Mouse data structure */ + + /* Ask for character size info */ + + retval = ioctl(1,WIOCGETD,&uwd); + if(retval || uwd.uw_hs <= 0 || uwd.uw_vs <= 0) { + /************************************************** + * something wrong with the kernel, so fake it... + **************************************************/ + if(!strcmp(term,"s4")) { + uw_hs = 9; + uw_vs = 12; + } + else { + uw_hs = 6; + uw_vs = 10; + } + } + else { + /* Kernel is working and knows about this font */ + uw_hs = uwd.uw_hs; + uw_vs = uwd.uw_vs; + } + + /************************************************** + * Now turn on mouse reporting so we can actually + * make use of all this stuff. + **************************************************/ + if((retval = ioctl(1,WIOCGETMOUSE,&umd)) != -1) { + umd.um_flags= MSDOWN+MSUP; + ioctl(1,WIOCSETMOUSE,&umd); + } + unixpcmouse = YES; + } +#endif + if (mouse == YES) { + loadmenu(mainmenu); + } +} + +/* load the correct mouse menu */ + +void +mousemenu(void) +{ + if (mouse == YES) { + if (changing == YES) { + loadmenu(changemenu); + } + else { + loadmenu(mainmenu); + } + } +} + +/* download a menu */ + +static void +loadmenu(MENU *menu) +{ + int i; + + if (emacsviterm == YES) { + mousereinit(); + (void) printf("\033V1"); /* display the scrollbar */ + (void) printf("\033M0@%s@%s@", menu[0].text, menu[0].value); + for (i = 1; menu[i].text != NULL; ++i) { + (void) printf("\033M@%s@%s@", menu[i].text, menu[i].value); + } + } + else { /* myx */ + int len; + + mousecleanup(); + (void) printf("\033[6;1X\033[9;1X"); + for (i = 0; menu[i].text != NULL; ++i) { + len = strlen(menu[i].text); + (void) printf("\033[%d;%dx%s%s", len, + (int) (len + strlen(menu[i].value)), + menu[i].text, menu[i].value); + } + loaded = menu; + } + (void) fflush(stdout); +} + +/* reinitialize the mouse in case curses changed the attributes */ + +void +mousereinit(void) +{ + if (emacsviterm == YES) { + + /* enable the mouse click and sweep coordinate control sequence */ + /* and switch to menu 2 */ + (void) printf("\033{2\033#2"); + (void) fflush(stdout); + } +} + +/* restore the mouse attributes */ + +void +mousecleanup(void) +{ + int i; + + if (loaded != NULL) { /* only true for myx */ + + /* remove the mouse menu */ + (void) printf("\033[6;0X\033[9;0X"); + for (i = 0; loaded[i].text != NULL; ++i) { + (void) printf("\033[0;0x"); + } + loaded = NULL; + } +} + +/* draw the scrollbar */ + +void +drawscrollbar(int top, int bot) +{ + int p1, p2; + + if (emacsviterm == YES) { + if (bot > top) { + p1 = 16 + (top - 1) * 100 / totallines; + p2 = 16 + (bot - 1) * 100 / totallines; + if (p2 > 116) { + p2 = 116; + } + if (p1 < 16) { + p1 = 16; + } + /* don't send ^S or ^Q because it will hang a layer using cu(1) */ + if (p1 == ctrl('Q') || p1 == ctrl('S')) { + ++p1; + } + if (p2 == ctrl('Q') || p2 == ctrl('S')) { + ++p2; + } + } + else { + p1 = p2 = 16; + } + (void) printf("\033W%c%c", p1, p2); + } +} + +/* get the mouse information */ + +MOUSE * +getmouseaction(char leading_char) +{ + static MOUSE m; + +#if UNIXPC + + if(unixpcmouse == YES && leading_char == ESC) { + + /* Called if cscope received an ESC character. See if it is + * a mouse report and if so, decipher it. A mouse report + * looks like: "<ESC>[?xx;yy;b;rM" + */ + int x = 0, y = 0, button = 0, reason = 0; + int i; + + /* Get a mouse report. The form is: XX;YY;B;RM where + * XX is 1,2, or 3 decimal digits with the X pixel position. + * Similarly for YY. B is a single decimal digit with the + * button number (4 for one, 2 for two, and 1 for three). + * R is the reason for the mouse report. + * + * In general, the input is read until the mouse report has + * been completely read in or we have discovered that this + * escape sequence is NOT a mouse report. In the latter case + * return the last character read to the input stream with + * myungetch(). + */ + + /* Check for "[?" being next 2 chars */ + if(((i = mygetch()) != '[') || ((i = mygetch()) != '?')) { + myungetch(i); + return(NULL); + } + + /* Grab the X position (in pixels) */ + while(isdigit(i = mygetch())) { + x = (x*10) + (i - '0'); + } + if(i != ';') { + myungetch(i); + return(NULL); /* not a mouse report after all */ + } + + /* Grab the Y position (in pixels) */ + while(isdigit(i = mygetch())) { + y = (y*10) + (i - '0'); + } + if(i != ';') { + myungetch(i); + return(NULL); + } + + /* Get which button */ + if((button = mygetch()) > '4') { + myungetch(button); + return(NULL); + } + if((i = mygetch()) != ';') { + myungetch(i); + return(NULL); + } + + /* Get the reason for this mouse report */ + if((reason = mygetch()) > '8') { + myungetch(reason); + return(NULL); + } + + /* sequence should terminate with an 'M' */ + if((i = mygetch()) != 'M') { + myungetch(i); + return(NULL); + } + + + /* OK. We get a mouse report whenever a button is depressed + * or released. Let's ignore the report whenever the button + * is depressed until when I am ready to implement sweeping. + */ + if(reason != '2') { + return(NULL); /* '2' means button is released */ + } + + /************************************************************ + * Always indicate button 1 irregardless of which button was + * really pushed. + ************************************************************/ + m.button = 1; + + /************************************************************ + * Convert pixel coordinates to line and column coords. + * The height and width are obtained using an ioctl() call + * in mouseinit(). This assumes that variable width chars + * are not being used ('though it would probably work anyway). + ************************************************************/ + + m.x1 = x/uw_hs; /* pixel/horizontal_spacing */ + m.y1 = y/uw_vs; /* pixel/vertical_spacing */ + + /* "null" out the other fields */ + m.percent = m.x2 = m.y2 = -1; + } + else +#endif /* not UNIXPC */ + + if (mouse == YES && leading_char == ctrl('X')) { + + switch (mygetch()) { + case ctrl('_'): /* click */ + if ((m.button = mygetch()) == '0') { /* if scrollbar */ + m.percent = getpercent(); + } + else { + m.x1 = getcoordinate(); + m.y1 = getcoordinate(); + m.x2 = m.y2 = -1; + } + break; + + case ctrl(']'): /* sweep */ + m.button = mygetch(); + m.x1 = getcoordinate(); + m.y1 = getcoordinate(); + m.x2 = getcoordinate(); + m.y2 = getcoordinate(); + break; + default: + return(NULL); + } + } + else return(NULL); + + return(&m); +} + +/* get a row or column coordinate from a mouse button click or sweep */ + +static int +getcoordinate(void) +{ + int c, next; + + c = mygetch(); + next = 0; + if (c == ctrl('A')) { + next = 95; + c = mygetch(); + } + if (c < ' ') { + return (0); + } + return (next + c - ' '); +} + +/* get a percentage */ + +static int +getpercent(void) +{ + int c; + + c = mygetch(); + if (c < 16) { + return(0); + } + if (c > 120) { + return(100); + } + return(c - 16); +} |