ararus |
03-19-2008 02:12 PM |
OK, I wrote a quick hack to allow less to handle the mouse key sequences.
Code:
diff -u -X diff_ignore/less less-418.orig/cmd.h less-418/cmd.h
--- less-418.orig/cmd.h 2007-06-15 23:06:23.000000000 +0100
+++ less-418/cmd.h 2008-03-18 10:51:02.000000000 +0000
@@ -72,6 +72,8 @@
#define A_END_LIST 103
#define A_SPECIAL_KEY 104
+#define A_MOUSE 126
+
#define A_SKIP 127
#define A_EXTRA 0200
@@ -129,3 +131,17 @@
#define SK_BACKTAB 15
#define SK_CTL_BACKSPACE 16
#define SK_CONTROL_K 40
+
+#define M_BTN1 1
+#define M_BTN2 2
+#define M_BTN3 3
+#define M_BTN4 4
+#define M_BTN5 5
+#define M_BTN_FIRST M_BTN1
+#define M_BTN_LAST M_BTN5
+
+#define M_BTN_RELEASE 0x23
+
+#define MOD_NONE 1
+#define MOD_ALT 2
+#define MOD_CTRL 4
diff -u -X diff_ignore/less less-418.orig/command.c less-418/command.c
--- less-418.orig/command.c 2007-12-10 16:40:37.000000000 +0000
+++ less-418/command.c 2008-03-18 10:51:02.000000000 +0000
@@ -899,6 +899,7 @@
IFILE old_ifile;
IFILE new_ifile;
char *tagfile;
+ char btn[3];
search_type = SRCH_FORW;
wscroll = (sc_height + 1) / 2;
@@ -1021,6 +1022,7 @@
if (action != A_PREFIX)
cmd_reset();
+action:
switch (action)
{
case A_DIGIT:
@@ -1652,6 +1654,25 @@
screen_trashed = 1;
break;
+ case A_MOUSE:
+ cmd_reset();
+
+ if (decode_button(btn))
+ break;
+
+ btn[2] = 0;
+ extra = NULL;
+ action = bcmd_decode(&btn, &extra);
+
+ switch (action) {
+ case A_INVALID:
+ case A_NOACTION:
+ break;
+
+ default:
+ goto action;
+ }
+
case A_PREFIX:
/*
* The command is incomplete (more chars are needed).
diff -u -X diff_ignore/less less-418.orig/decode.c less-418/decode.c
--- less-418.orig/decode.c 2007-12-10 16:35:52.000000000 +0000
+++ less-418/decode.c 2008-03-18 10:51:02.000000000 +0000
@@ -66,6 +66,7 @@
CONTROL('D'),0, A_F_SCROLL,
'u',0, A_B_SCROLL,
CONTROL('U'),0, A_B_SCROLL,
+ ESC,'[','M',0, A_MOUSE,
' ',0, A_F_SCREEN,
'f',0, A_F_SCREEN,
CONTROL('F'),0, A_F_SCREEN,
@@ -201,6 +202,45 @@
SK(SK_UP_ARROW),0, EC_UP, /* UPARROW */
ESC,'j',0, EC_DOWN, /* ESC j */
SK(SK_DOWN_ARROW),0, EC_DOWN, /* DOWNARROW */
+ ESC,'[','M',0, A_MOUSE,
+};
+
+static unsigned char cmdbtntable[] =
+{
+ MOD_NONE,M_BTN4,0, A_B_SCROLL,
+ MOD_NONE,M_BTN5,0, A_F_SCROLL,
+ MOD_CTRL,M_BTN4,0, A_B_LINE,
+ MOD_CTRL,M_BTN5,0, A_F_LINE,
+ MOD_ALT,M_BTN4,0, A_B_SCREEN,
+ MOD_ALT,M_BTN5,0, A_F_SCREEN,
+ MOD_NONE,M_BTN1,0, A_AGAIN_SEARCH,
+ MOD_NONE,M_BTN3,0, A_REVERSE_SEARCH,
+ MOD_CTRL,M_BTN1,0, A_T_AGAIN_SEARCH,
+ MOD_CTRL,M_BTN3,0, A_T_REVERSE_SEARCH,
+ MOD_NONE,M_BTN2,0, A_NOACTION,
+ MOD_CTRL,M_BTN2,0, A_NOACTION,
+ MOD_ALT,M_BTN1,0, A_NOACTION,
+ MOD_ALT,M_BTN2,0, A_NOACTION,
+ MOD_ALT,M_BTN3,0, A_NOACTION,
+};
+
+static unsigned char editbtntable[] =
+{
+ MOD_NONE,M_BTN1,0, A_NOACTION,
+ MOD_NONE,M_BTN2,0, A_NOACTION,
+ MOD_NONE,M_BTN3,0, A_NOACTION,
+ MOD_NONE,M_BTN4,0, EC_UP,
+ MOD_NONE,M_BTN5,0, EC_DOWN,
+ MOD_CTRL,M_BTN1,0, A_NOACTION,
+ MOD_CTRL,M_BTN2,0, A_NOACTION,
+ MOD_CTRL,M_BTN3,0, A_NOACTION,
+ MOD_CTRL,M_BTN4,0, A_NOACTION,
+ MOD_CTRL,M_BTN5,0, A_NOACTION,
+ MOD_ALT,M_BTN1,0, A_NOACTION,
+ MOD_ALT,M_BTN2,0, A_NOACTION,
+ MOD_ALT,M_BTN3,0, A_NOACTION,
+ MOD_ALT,M_BTN4,0, A_NOACTION,
+ MOD_ALT,M_BTN5,0, A_NOACTION,
};
/*
@@ -218,6 +258,8 @@
*/
static struct tablelist *list_fcmd_tables = NULL;
static struct tablelist *list_ecmd_tables = NULL;
+static struct tablelist *list_cb_cmd_tables = NULL;
+static struct tablelist *list_eb_cmd_tables = NULL;
static struct tablelist *list_var_tables = NULL;
static struct tablelist *list_sysvar_tables = NULL;
@@ -294,6 +336,8 @@
*/
add_fcmd_table((char*)cmdtable, sizeof(cmdtable));
add_ecmd_table((char*)edittable, sizeof(edittable));
+ add_cb_cmd_table((char*)cmdbtntable, sizeof(cmdbtntable));
+ add_eb_cmd_table((char*)editbtntable, sizeof(editbtntable));
#if USERFILE
/*
* For backwards compatibility,
@@ -368,6 +412,27 @@
}
/*
+ * Add a mouse button command table.
+ */
+ public void
+add_cb_cmd_table(buf, len)
+ char *buf;
+ int len;
+{
+ if (add_cmd_table(&list_cb_cmd_tables, buf, len) < 0)
+ error("Warning: some edit commands disabled", NULL_PARG);
+}
+
+ public void
+add_eb_cmd_table(buf, len)
+ char *buf;
+ int len;
+{
+ if (add_cmd_table(&list_eb_cmd_tables, buf, len) < 0)
+ error("Warning: some edit commands disabled", NULL_PARG);
+}
+
+/*
* Add an environment variable table.
*/
static void
@@ -518,7 +583,29 @@
char *cmd;
char **sp;
{
- return (cmd_decode(list_ecmd_tables, cmd, sp));
+ char btn[3];
+ int action = cmd_decode(list_ecmd_tables, cmd, sp);
+
+ if (action == A_MOUSE) {
+ if (decode_button(btn)) {
+ return (A_NOACTION);
+ }
+
+ btn[2] = 0;
+ return (cmd_decode(list_eb_cmd_tables, btn, sp));
+ }
+ return (action);
+}
+
+/*
+ * Decode a command from the cmdbtntables list.
+ */
+ public int
+bcmd_decode(cmd,sp)
+ char *cmd;
+ char **sp;
+{
+ return (cmd_decode(list_cb_cmd_tables, cmd, sp));
}
/*
@@ -619,6 +706,16 @@
add_ecmd_table(p, n);
p += n;
break;
+ case CMD_BTN_SECTION:
+ n = gint(&p);
+ add_cb_cmd_table(p, n);
+ p += n;
+ break;
+ case EDIT_BTN_SECTION:
+ n = gint(&p);
+ add_eb_cmd_table(p, n);
+ p += n;
+ break;
case VAR_SECTION:
n = gint(&p);
add_var_table((sysvar) ?
@@ -837,3 +934,39 @@
return action;
}
+
+/*
+ * Read a character and decode into mod + button.
+ *
+ * Bits 0-1 = Button number (buttons 0-2, 3 is release).
+ * Bit 2 = Shift status (according to rxvtRef, but why?).
+ * Bit 3 = Alt/Meta status.
+ * Bit 4 = Control status.
+ * Bit 5 = Always set to make the character printable (i.e. >space).
+ * Bit 6 = Indicates a wheel event (bit 0 is up/down).
+ * Bit 7 = Unknown.
+ *
+ * Return 0 if OK, 1 if button should be ignored (button release).
+ */
+ public int
+decode_button(btn)
+ char btn[2];
+{
+ int b = getcc();
+
+ /* Discard x/y coordinates. */
+ getcc();
+ getcc();
+
+ /* Ignore release events. */
+ if ((b & 0x23) == M_BTN_RELEASE)
+ return (1);
+
+ btn[0] = (b & 0x1c) >> 2;
+ if (!btn[0]) btn[0] = 1;
+
+ btn[1] = (b & 3) | ((b & 0x40) >> 4);
+ if (btn[1] < 4) (btn[1])++;
+
+ return (0);
+}
diff -u -X diff_ignore/less less-418.orig/funcs.h less-418/funcs.h
--- less-418.orig/funcs.h 2008-01-01 00:51:17.000000000 +0000
+++ less-418/funcs.h 2008-03-18 10:51:02.000000000 +0000
@@ -86,8 +86,11 @@
public void init_cmds ();
public void add_fcmd_table ();
public void add_ecmd_table ();
+ public void add_cb_cmd_table ();
+ public void add_eb_cmd_table ();
public int fcmd_decode ();
public int ecmd_decode ();
+ public int bcmd_decode ();
public char * lgetenv ();
public int lesskey ();
public void add_hometable ();
@@ -270,3 +273,6 @@
public void open_getchr ();
public void close_getchr ();
public int getchr ();
+ public void xwin_mouse_on ();
+ public void xwin_mouse_off ();
+ public int decode_button(char btn[2]);
diff -u -X diff_ignore/less less-418.orig/less.h less-418/less.h
--- less-418.orig/less.h 2007-12-04 20:23:30.000000000 +0000
+++ less-418/less.h 2008-03-18 10:51:02.000000000 +0000
@@ -468,6 +468,7 @@
#define S_INTERRUPT 01
#define S_STOP 02
#define S_WINCH 04
+#define S_TERM 8
#define ABORT_SIGS() (sigs & (S_INTERRUPT|S_STOP))
#define QUIT_OK 0
diff -u -X diff_ignore/less less-418.orig/lesskey.c less-418/lesskey.c
--- less-418.orig/lesskey.c 2007-12-10 16:35:52.000000000 +0000
+++ less-418/lesskey.c 2008-03-18 10:51:02.000000000 +0000
@@ -185,6 +185,8 @@
struct table cmdtable;
struct table edittable;
+struct table cbtntable;
+struct table ebtntable;
struct table vartable;
struct table *currtable = &cmdtable;
@@ -201,6 +203,8 @@
};
char cmdsection[1] = { CMD_SECTION };
char editsection[1] = { EDIT_SECTION };
+char cbtnsection[1] = { CMD_BTN_SECTION };
+char ebtnsection[1] = { EDIT_BTN_SECTION };
char varsection[1] = { VAR_SECTION };
char endsection[1] = { END_SECTION };
@@ -344,6 +348,12 @@
edittable.names = editnames;
edittable.pbuffer = edittable.buffer;
+ cbtntable.names = cmdnames;
+ cbtntable.pbuffer = cbtntable.buffer;
+
+ ebtntable.names = editnames;
+ ebtntable.pbuffer = ebtntable.buffer;
+
vartable.names = NULL;
vartable.pbuffer = vartable.buffer;
}
@@ -556,6 +566,16 @@
currtable = &vartable;
return (1);
}
+ if (PREFIX(s, "#cmdbutton"))
+ {
+ currtable = &cbtntable;
+ return (1);
+ }
+ if (PREFIX(s, "#editbutton"))
+ {
+ currtable = &ebtntable;
+ return (1);
+ }
if (PREFIX(s, "#stop"))
{
add_cmd_char('\0');
@@ -699,6 +719,48 @@
}
void
+parse_btnline(p)
+ char *p;
+{
+ char buf[2];
+ int c;
+ int action;
+
+ buf[0] = MOD_NONE;
+ buf[1] = 0;
+
+ c = tolower(*p++);
+ if (c == 'c') {
+ buf[0] = MOD_CTRL;
+ c = *p++;
+ } else if (c == 'a') {
+ buf[0] = MOD_ALT;
+ c = *p++;
+ }
+
+ c -= '0';
+ if (c >= M_BTN_FIRST && c <= M_BTN_LAST) {
+ buf[1] = c;
+ } else {
+ error("bad button number");
+ return;
+ }
+
+ p = skipsp(p);
+ if (*p == '\0')
+ {
+ error("missing action");
+ return;
+ }
+
+ add_cmd_char(buf[0]);
+ add_cmd_char(buf[1]);
+ add_cmd_char('\0');
+ action = findaction(p);
+ add_cmd_char(action);
+}
+
+ void
parse_varline(p)
char *p;
{
@@ -755,10 +817,13 @@
if (*p == '\0')
return;
- if (currtable == &vartable)
+ if (currtable == &vartable) {
parse_varline(p);
- else
+ } else if (currtable == &cbtntable || currtable == &ebtntable) {
+ parse_btnline(p);
+ } else {
parse_cmdline(p);
+ }
}
int
@@ -859,6 +924,16 @@
fputint(out, edittable.pbuffer - edittable.buffer);
fputbytes(out, (char *)edittable.buffer, edittable.pbuffer-edittable.buffer);
+ /* Cmd button section */
+ fputbytes(out, cbtnsection, sizeof(cbtnsection));
+ fputint(out, cbtntable.pbuffer - cbtntable.buffer);
+ fputbytes(out, (char *)cbtntable.buffer, cbtntable.pbuffer-cbtntable.buffer);
+
+ /* Edit button section */
+ fputbytes(out, ebtnsection, sizeof(ebtnsection));
+ fputint(out, ebtntable.pbuffer - ebtntable.buffer);
+ fputbytes(out, (char *)ebtntable.buffer, ebtntable.pbuffer-ebtntable.buffer);
+
/* Environment variable section */
fputbytes(out, varsection, sizeof(varsection));
fputint(out, vartable.pbuffer - vartable.buffer);
diff -u -X diff_ignore/less less-418.orig/lesskey.h less-418/lesskey.h
--- less-418.orig/lesskey.h 2007-06-15 23:06:24.000000000 +0100
+++ less-418/lesskey.h 2008-03-18 10:51:02.000000000 +0000
@@ -29,6 +29,8 @@
#define CMD_SECTION 'c'
#define EDIT_SECTION 'e'
+#define CMD_BTN_SECTION 'b'
+#define EDIT_BTN_SECTION 'B'
#define VAR_SECTION 'v'
#define END_SECTION 'x'
diff -u -X diff_ignore/less less-418.orig/screen.c less-418/screen.c
--- less-418.orig/screen.c 2008-01-01 00:50:42.000000000 +0000
+++ less-418/screen.c 2008-03-18 10:51:02.000000000 +0000
@@ -210,6 +210,8 @@
static void tmodes();
#endif
+static int use_mouse; /* Enable XWin mouse button reporting */
+
/*
* These two variables are sometimes defined in,
* and needed by, the termcap library.
@@ -1559,6 +1561,12 @@
initcolor();
flush();
#endif
+
+ if (getenv("LESSUSEMOUSE")) {
+ use_mouse = 1;
+ xwin_mouse_on();
+ }
+
init_done = 1;
}
@@ -1586,6 +1594,7 @@
clreol();
#endif
#endif
+ xwin_mouse_off();
init_done = 0;
}
@@ -2498,3 +2507,22 @@
#endif
}
#endif
+
+#define XWIN_MOUSE_ON "\033[?1000h"
+#define XWIN_MOUSE_OFF "\033[?1000l"
+
+ public void
+xwin_mouse_on()
+{
+ if (use_mouse) {
+ tputs(XWIN_MOUSE_ON, 1, putchr);
+ }
+}
+
+ public void
+xwin_mouse_off()
+{
+ if (use_mouse) {
+ tputs(XWIN_MOUSE_OFF, 1, putchr);
+ }
+}
diff -u -X diff_ignore/less less-418.orig/signal.c less-418/signal.c
--- less-418.orig/signal.c 2007-12-10 16:35:52.000000000 +0000
+++ less-418/signal.c 2008-03-18 10:51:02.000000000 +0000
@@ -78,6 +78,22 @@
}
#endif
+#ifdef SIGTERM
+/*
+ * Term signal handler.
+ */
+ /* ARGSUSED*/
+ static RETSIGTYPE
+term(type)
+ int type;
+{
+ LSIGNAL(SIGTERM, term);
+ sigs |= S_TERM;
+ if (reading)
+ intread();
+}
+#endif
+
#ifdef SIGWINCH
/*
* "Window" change handler
@@ -161,6 +177,9 @@
#ifdef SIGQUIT
(void) LSIGNAL(SIGQUIT, SIG_IGN);
#endif
+#ifdef SIGTERM
+ (void) LSIGNAL(SIGTERM, term);
+#endif
} else
{
/*
@@ -271,4 +290,10 @@
}
}
+#ifdef S_TERM
+ if (tsignals & S_TERM)
+ {
+ quit(QUIT_OK);
+ }
+#endif
}
I used the current version, 418, it may work with other versions, but you might as well get the latest source.
Define the environment variable LESSUSEMOUSE to enable the mouse.
Default actions:
wheel up/down: scroll half a page
ctrl + wheel: scroll 1 line
alt + wheel: scroll full page (may not work)
button1/button3 will do a next/prev search.
NOTE: Alt+wheel works in rxvt, but not in xterm, but there may be an option to enable it. Don't know about other terminals. The window manager may also eat certain combinations, of course.
NOTE: You'll see I only used Control and Alt, you generally cannot bind Shift since mouse reporting is disabled while Shift is held down (to enable making selections).
You can change the bindings in your lesskey file, section #cmdbutton for command mode, #editbutton for edit mode (the prompt line), key names are the button number (4/5 for wheel), optionally prefixed with 'c' or 'a' (case insensitive) for ctrl/alt.
e.g.
Code:
#cmdbutton
4 back-line
5 forw-line
c4 back-scroll
c5 forw-scroll
will swap the behaviour of (plain) wheel and ctrl+wheel.
In edit mode, the wheel will scroll through the search history. None of the other buttons do anything by default, but you can bind them in the #editbutton section, as mentioned above. Using the mouse in edit mode doesn't seem that useful to me, but it has to interpret the escape sequences or the'll just be dumped into the input buffer.
|