428 lines
11 KiB
C
428 lines
11 KiB
C
/*===========================================================================
|
|
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 falseT 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 falseT 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
|
|
*/
|
|
|
|
extern int LINES;
|
|
|
|
#define FLDLINE (LINES - FIELDS - 1 - 1) /* first input field line */
|
|
|
|
#include "global.h"
|
|
|
|
bool mouse = false; /* mouse interface */
|
|
|
|
#ifdef UNIXPC /* build command requires #ifdef instead of #if */
|
|
# include <sys/window.h>
|
|
bool unixpcmouse = false; /* running with a mouse on the Unix PC? */
|
|
static int uw_hs, uw_vs; /* character height and width */
|
|
#endif
|
|
|
|
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 = false; /* 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 = true;
|
|
mouse = true;
|
|
}
|
|
/* 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 = true;
|
|
}
|
|
#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 = true;
|
|
}
|
|
#endif
|
|
if(mouse == true) { loadmenu(mainmenu); }
|
|
}
|
|
|
|
/* load the correct mouse menu */
|
|
|
|
void mousemenu(void) {
|
|
if(mouse == true) {
|
|
if(input_mode == INPUT_CHANGE) {
|
|
loadmenu(changemenu);
|
|
} else {
|
|
loadmenu(mainmenu);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* download a menu */
|
|
|
|
static void loadmenu(MENU *menu) {
|
|
int i;
|
|
|
|
if(emacsviterm == true) {
|
|
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 == true) {
|
|
|
|
/* 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 == true) {
|
|
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 == true && 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 falseT 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 = getch()) != '[') || ((i = getch()) != '?')) {
|
|
myungetch(i);
|
|
return (NULL);
|
|
}
|
|
|
|
/* Grab the X position (in pixels) */
|
|
while(isdigit(i = getch())) {
|
|
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 = getch())) {
|
|
y = (y * 10) + (i - '0');
|
|
}
|
|
if(i != ';') {
|
|
myungetch(i);
|
|
return (NULL);
|
|
}
|
|
|
|
/* Get which button */
|
|
if((button = getch()) > '4') {
|
|
myungetch(button);
|
|
return (NULL);
|
|
}
|
|
if((i = getch()) != ';') {
|
|
myungetch(i);
|
|
return (NULL);
|
|
}
|
|
|
|
/* Get the reason for this mouse report */
|
|
if((reason = getch()) > '8') {
|
|
myungetch(reason);
|
|
return (NULL);
|
|
}
|
|
|
|
/* sequence should terminate with an 'M' */
|
|
if((i = getch()) != '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 == true && leading_char == ctrl('X')) {
|
|
|
|
switch(getch()) {
|
|
case ctrl('_'): /* click */
|
|
if((m.button = getch()) == '0') { /* if scrollbar */
|
|
m.percent = getpercent();
|
|
} else {
|
|
m.x1 = getcoordinate();
|
|
m.y1 = getcoordinate();
|
|
m.x2 = m.y2 = -1;
|
|
}
|
|
break;
|
|
|
|
case ctrl(']'): /* sweep */
|
|
m.button = getch();
|
|
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 = getch();
|
|
next = 0;
|
|
if(c == ctrl('A')) {
|
|
next = 95;
|
|
c = getch();
|
|
}
|
|
if(c < ' ') { return (0); }
|
|
return (next + c - ' ');
|
|
}
|
|
|
|
/* get a percentage */
|
|
|
|
static int getpercent(void) {
|
|
int c;
|
|
|
|
c = getch();
|
|
if(c < 16) { return (0); }
|
|
if(c > 120) { return (100); }
|
|
return (c - 16);
|
|
}
|
|
|
|
int process_mouse() {
|
|
int i;
|
|
MOUSE *p;
|
|
if((p = getmouseaction(DUMMYCHAR)) == NULL) {
|
|
return (false); /* unknown control sequence */
|
|
}
|
|
/* if the button number is a scrollbar tag */
|
|
if(p->button == '0') {
|
|
// scrollbar(p); // XXX
|
|
return (false);
|
|
}
|
|
/* ignore a sweep */
|
|
if(p->x2 >= 0) { return (false); }
|
|
/* if this is a line selection */
|
|
if(p->y1 > FLDLINE) {
|
|
|
|
/* find the selected line */
|
|
/* note: the selection is forced into range */
|
|
for(i = disprefs - 1; i > 0; --i) {
|
|
if(p->y1 >= displine[i]) { return (false); }
|
|
}
|
|
/* display it in the file with the editor */
|
|
editref(i);
|
|
} else { /* this is an input field selection */
|
|
field = p->y1 - FLDLINE;
|
|
/* force it into range */
|
|
if(field >= FIELDS) { field = FIELDS - 1; }
|
|
return (false);
|
|
}
|
|
|
|
return false;
|
|
}
|