937 lines
21 KiB
Diff
937 lines
21 KiB
Diff
--- Makefile.in
|
||
+++ Makefile.in
|
||
@@ -49,7 +49,8 @@
|
||
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
|
||
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
|
||
output.${O} position.${O} prompt.${O} search.${O} signal.${O} \
|
||
- tags.${O} ttyin.${O} version.${O} @REGEX_O@
|
||
+ tags.${O} ttyin.${O} version.${O} @REGEX_O@ \
|
||
+ selection.${O}
|
||
|
||
all: less lesskey lessecho
|
||
|
||
--- cmd.h
|
||
+++ cmd.h
|
||
@@ -66,6 +66,10 @@
|
||
#define A_NEXT_TAG 53
|
||
#define A_PREV_TAG 54
|
||
|
||
+#define A_MOUSE 60
|
||
+#define A_MOUSE_END_SEL_IN 61
|
||
+#define A_MOUSE_END_SEL_OUT 62
|
||
+
|
||
#define A_INVALID 100
|
||
#define A_NOACTION 101
|
||
#define A_UINVALID 102
|
||
@@ -129,3 +133,7 @@
|
||
#define SK_BACKTAB 15
|
||
#define SK_CTL_BACKSPACE 16
|
||
#define SK_CONTROL_K 40
|
||
+
|
||
+/* less input command mode */
|
||
+#define M_NORMAL 1
|
||
+#define M_MULTICHAR_COMMAND 2
|
||
--- command.c
|
||
+++ command.c
|
||
@@ -57,7 +57,7 @@
|
||
extern int forw_prompt;
|
||
|
||
static char ungot[UNGOT_SIZE];
|
||
-static char *ungotp = NULL;
|
||
+public char *ungotp = NULL;
|
||
#if SHELL_ESCAPE
|
||
static char *shellcmd = NULL; /* For holding last shell command for "!!" */
|
||
#endif
|
||
@@ -73,6 +73,10 @@
|
||
#if PIPEC
|
||
static char pipec;
|
||
#endif
|
||
+int mouse_x1, mouse_y1; /* mouse coordinates on left mouse button press */
|
||
+extern char *selection; /* buffer with selection */
|
||
+extern int selection_size; /* current selection size */
|
||
+extern int xselection; /* is xselection available */
|
||
|
||
static void multi_search();
|
||
|
||
@@ -858,13 +862,218 @@
|
||
}
|
||
|
||
/*
|
||
+ * process escape sequence with mouse button action
|
||
+ * Note: action on mouse wheel depends on current less input command mode
|
||
+ */
|
||
+ static void
|
||
+process_mouse_button(mode)
|
||
+ int mode; /* normal mode or multicharacter command mode */
|
||
+{
|
||
+ int button, mouse_x, mouse_y;
|
||
+ int counter;
|
||
+
|
||
+ button = getcc() - 32;
|
||
+ mouse_x = getcc() - 32;
|
||
+ mouse_y = getcc() - 32;
|
||
+
|
||
+ if (button & 64)
|
||
+ {
|
||
+ /* mouse wheel used */
|
||
+ if (button & 1)
|
||
+ {
|
||
+ /* mouse wheel down */
|
||
+ switch (mode)
|
||
+ {
|
||
+ case M_NORMAL:
|
||
+ /* forward N (default 3) line. */
|
||
+ if (number <= 0)
|
||
+ number = 3;
|
||
+ cmd_exec();
|
||
+ if (show_attn == OPT_ONPLUS && number > 1)
|
||
+ set_attnpos(bottompos);
|
||
+ forward(number, 0, 0);
|
||
+ break;
|
||
+ case M_MULTICHAR_COMMAND:
|
||
+ /* the same behaviour as for down arrow */
|
||
+ ungetcc('k');
|
||
+ ungetcc('\033');
|
||
+ break;
|
||
+ default:
|
||
+ error("Warnning: Internal error, bad mode for process_mouse_button()", NULL_PARG);
|
||
+ break;
|
||
+ }
|
||
+ } else
|
||
+ {
|
||
+ /* mouse wheel up */
|
||
+ switch (mode)
|
||
+ {
|
||
+ case M_NORMAL:
|
||
+ /* backward N (default 3) line. */
|
||
+ if (number <= 0)
|
||
+ number = 3;
|
||
+ cmd_exec();
|
||
+ backward(number, 0, 0);
|
||
+ break;
|
||
+ case M_MULTICHAR_COMMAND:
|
||
+ /* the same behaviour as for up arrow */
|
||
+ ungetcc('j');
|
||
+ ungetcc('\033');
|
||
+ break;
|
||
+ default:
|
||
+ error("Warnning: Internal error, bad mode for process_mouse_button()", NULL_PARG);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ } else
|
||
+ {
|
||
+ /* 1-3 mouse button used */
|
||
+ switch (button & 3)
|
||
+ {
|
||
+ case 0:
|
||
+ /*
|
||
+ * left button pressed
|
||
+ * xterm is waiting for mouse tracking information
|
||
+ */
|
||
+ printf("\033[1;%d;%d;1;%dT",
|
||
+ mouse_x, mouse_y, get_swindow() + 1);
|
||
+ fflush(stdout);
|
||
+ /* save coordinates of selection */
|
||
+ mouse_x1 = mouse_x;
|
||
+ mouse_y1 = mouse_y;
|
||
+ break;
|
||
+ case 1:
|
||
+ /*
|
||
+ * middle button pressed
|
||
+ * paste selection
|
||
+ */
|
||
+ if (xselection)
|
||
+ read_xselection();
|
||
+ for (counter = selection_size; --counter >= 0;)
|
||
+ ungetcc(selection[counter]);
|
||
+ break;
|
||
+ case 3:
|
||
+ /* any button released */
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ return;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * process escape sequence with mouse action (end of selection)
|
||
+ * left mouse button was released inside of given area
|
||
+ */
|
||
+ static void
|
||
+process_mouse_end_selection_in()
|
||
+{
|
||
+ int button, mouse_x, mouse_y;
|
||
+
|
||
+ mouse_x = getcc() - 32;
|
||
+ mouse_y = getcc() - 32;
|
||
+ create_selection(mouse_x1 - 1, mouse_y1 - 1,
|
||
+ mouse_x - 1, mouse_y - 1);
|
||
+ if (xselection)
|
||
+ write_xselection();
|
||
+ return;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * process escape sequence with mouse action (end of selection)
|
||
+ * left mouse button was released outside of given area
|
||
+ */
|
||
+ static void
|
||
+process_mouse_end_selection_out()
|
||
+{
|
||
+ int mouse_x, mouse_y;
|
||
+ int mouse_x2, mouse_y2;
|
||
+
|
||
+ mouse_x1 = getcc() - 32; /* startx */
|
||
+ mouse_y1 = getcc() - 32; /* starty */
|
||
+ mouse_x2 = getcc() - 32; /* endx - inside of given area */
|
||
+ mouse_y2 = getcc() - 32; /* endy - inside of given area */
|
||
+ mouse_x = getcc() - 32; /* current mouse x coordinate */
|
||
+ mouse_y = getcc() - 32; /* current mouse y coordinate */
|
||
+ create_selection(mouse_x1 - 1, mouse_y1 - 1,
|
||
+ mouse_x2 - 1, mouse_y2 - 1);
|
||
+ if (xselection)
|
||
+ write_xselection();
|
||
+ return;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * process possible escape sequention with mouse action
|
||
+ * in multicharacter command mode
|
||
+ */
|
||
+ static int
|
||
+save_mouse_action(int *c)
|
||
+{
|
||
+ unsigned char mouse_cbuf[CMDBUF_SIZE + 1]; /* buffer for current input */
|
||
+ char *mouse_extra = NULL;
|
||
+ int mouse_cbuf_pos; /* current position in mouse_cbuf */
|
||
+ int mouse_action; /* what action is in current input ? */
|
||
+
|
||
+ mouse_cbuf[0] = *c;
|
||
+ mouse_cbuf[1] = '\0';
|
||
+ mouse_cbuf_pos = 1;
|
||
+
|
||
+ while (((mouse_action = mcmd_decode(mouse_cbuf, &mouse_extra)) == A_PREFIX) &&
|
||
+ (mouse_cbuf_pos < CMDBUF_SIZE))
|
||
+ {
|
||
+ /*
|
||
+ * current input contains prefix for an action
|
||
+ * read next char
|
||
+ */
|
||
+ mouse_cbuf[mouse_cbuf_pos++] = getcc();
|
||
+ mouse_cbuf[mouse_cbuf_pos] = '\0';
|
||
+ mouse_extra = NULL;
|
||
+ }
|
||
+
|
||
+ switch (mouse_action)
|
||
+ {
|
||
+ case A_MOUSE:
|
||
+ /*
|
||
+ * a mouse button pressed or released
|
||
+ */
|
||
+ process_mouse_button(M_MULTICHAR_COMMAND);
|
||
+ *c = getcc();
|
||
+ return 1;
|
||
+ case A_MOUSE_END_SEL_IN:
|
||
+ /*
|
||
+ * end of mouse selection
|
||
+ * left mouse button was released inside of given area
|
||
+ */
|
||
+ process_mouse_end_selection_in();
|
||
+ *c = getcc();
|
||
+ return 1;
|
||
+ case A_MOUSE_END_SEL_OUT:
|
||
+ /*
|
||
+ * end of mouse selection
|
||
+ * left mouse button was released outside of given area
|
||
+ */
|
||
+ process_mouse_end_selection_out();
|
||
+ *c = getcc();
|
||
+ return 1;
|
||
+ default:
|
||
+ /*
|
||
+ * no mouse action
|
||
+ * unget all characters
|
||
+ */
|
||
+ while (--mouse_cbuf_pos > 0)
|
||
+ ungetcc(mouse_cbuf[mouse_cbuf_pos]);
|
||
+ *c = mouse_cbuf[0];
|
||
+ return 0;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/*
|
||
* Main command processor.
|
||
* Accept and execute commands until a quit command.
|
||
*/
|
||
public void
|
||
commands()
|
||
{
|
||
- register int c;
|
||
+ int c;
|
||
register int action;
|
||
register char *cbuf;
|
||
int newaction;
|
||
@@ -929,6 +1138,7 @@
|
||
* action to be performed.
|
||
*/
|
||
if (mca)
|
||
+ while (save_mouse_action(&c)); /* process all escape sequences with mouse actions */
|
||
switch (mca_char(c))
|
||
{
|
||
case MCA_MORE:
|
||
@@ -999,6 +1209,29 @@
|
||
|
||
switch (action)
|
||
{
|
||
+ case A_MOUSE:
|
||
+ /*
|
||
+ * a mouse button pressed or released
|
||
+ */
|
||
+ process_mouse_button(M_NORMAL);
|
||
+ break;
|
||
+
|
||
+ case A_MOUSE_END_SEL_IN:
|
||
+ /*
|
||
+ * end of mouse selection
|
||
+ * left mouse button was released inside of given area
|
||
+ */
|
||
+ process_mouse_end_selection_in();
|
||
+ break;
|
||
+
|
||
+ case A_MOUSE_END_SEL_OUT:
|
||
+ /*
|
||
+ * end of mouse selection
|
||
+ * left mouse button was released outside of given area
|
||
+ */
|
||
+ process_mouse_end_selection_out();
|
||
+ break;
|
||
+
|
||
case A_DIGIT:
|
||
/*
|
||
* First digit of a number.
|
||
--- decode.c
|
||
+++ decode.c
|
||
@@ -165,6 +165,13 @@
|
||
'Z','Z',0, A_QUIT
|
||
};
|
||
|
||
+static unsigned char mousetable[] =
|
||
+{
|
||
+ ESC,'[','M',0, A_MOUSE,
|
||
+ ESC,'[','t',0, A_MOUSE_END_SEL_IN,
|
||
+ ESC,'[','T',0, A_MOUSE_END_SEL_OUT
|
||
+};
|
||
+
|
||
static unsigned char edittable[] =
|
||
{
|
||
'\t',0, EC_F_COMPLETE, /* TAB */
|
||
@@ -217,6 +224,7 @@
|
||
* List of command tables and list of line-edit tables.
|
||
*/
|
||
static struct tablelist *list_fcmd_tables = NULL;
|
||
+static struct tablelist *list_mcmd_tables = NULL;
|
||
static struct tablelist *list_ecmd_tables = NULL;
|
||
static struct tablelist *list_var_tables = NULL;
|
||
static struct tablelist *list_sysvar_tables = NULL;
|
||
@@ -292,8 +300,10 @@
|
||
/*
|
||
* Add the default command tables.
|
||
*/
|
||
+ add_fcmd_table((char*)mousetable, sizeof(mousetable));
|
||
add_fcmd_table((char*)cmdtable, sizeof(cmdtable));
|
||
add_ecmd_table((char*)edittable, sizeof(edittable));
|
||
+ add_mcmd_table((char*)mousetable, sizeof(mousetable));
|
||
#if USERFILE
|
||
/*
|
||
* For backwards compatibility,
|
||
@@ -368,6 +378,18 @@
|
||
}
|
||
|
||
/*
|
||
+ * Add an mouse command table.
|
||
+ */
|
||
+ public void
|
||
+add_mcmd_table(buf, len)
|
||
+ char *buf;
|
||
+ int len;
|
||
+{
|
||
+ if (add_cmd_table(&list_mcmd_tables, buf, len) < 0)
|
||
+ error("Warning: some mouse commands disabled", NULL_PARG);
|
||
+}
|
||
+
|
||
+/*
|
||
* Add an environment variable table.
|
||
*/
|
||
static void
|
||
@@ -522,6 +544,17 @@
|
||
}
|
||
|
||
/*
|
||
+ * Decode a command from the mousetables list.
|
||
+ */
|
||
+ public int
|
||
+mcmd_decode(cmd, sp)
|
||
+ char *cmd;
|
||
+ char **sp;
|
||
+{
|
||
+ return (cmd_decode(list_mcmd_tables, cmd, sp));
|
||
+}
|
||
+
|
||
+/*
|
||
* Get the value of an environment variable.
|
||
* Looks first in the lesskey file, then in the real environment.
|
||
*/
|
||
--- defines.h.in
|
||
+++ defines.h.in
|
||
@@ -183,7 +183,7 @@
|
||
* Sizes of various buffers.
|
||
*/
|
||
#define CMDBUF_SIZE 512 /* Buffer for multichar commands */
|
||
-#define UNGOT_SIZE 100 /* Max chars to unget() */
|
||
+#define UNGOT_SIZE 10000 /* Max chars to unget() */
|
||
#define LINEBUF_SIZE 1024 /* Max size of line in input file */
|
||
#define OUTBUF_SIZE 1024 /* Output buffer */
|
||
#define PROMPT_SIZE 200 /* Max size of prompt string */
|
||
--- funcs.h
|
||
+++ funcs.h
|
||
@@ -83,8 +83,10 @@
|
||
public void init_cmds ();
|
||
public void add_fcmd_table ();
|
||
public void add_ecmd_table ();
|
||
+ public void add_mcmd_table ();
|
||
public int fcmd_decode ();
|
||
public int ecmd_decode ();
|
||
+ public int mcmd_decode ();
|
||
public char * lgetenv ();
|
||
public int lesskey ();
|
||
public void add_hometable ();
|
||
@@ -181,6 +183,7 @@
|
||
public void gomark ();
|
||
public POSITION markpos ();
|
||
public void unmark ();
|
||
+ public void opt_A ();
|
||
public void opt_o ();
|
||
public void opt__O ();
|
||
public void opt_l ();
|
||
@@ -266,3 +269,10 @@
|
||
public void open_getchr ();
|
||
public void close_getchr ();
|
||
public int getchr ();
|
||
+ public void clear_selection();
|
||
+ public int create_selection(int, int, int, int);
|
||
+ public int write_xselection();
|
||
+ public int read_xselection();
|
||
+ public int is_xselection_available();
|
||
+ public void init_mouse_support();
|
||
+ public void deinit_mouse_support();
|
||
--- less.hlp
|
||
+++ less.hlp
|
||
@@ -111,6 +111,8 @@
|
||
Display help (from command line).
|
||
-a ........ --search-skip-screen
|
||
Forward search skips current screen.
|
||
+ -A ........ --mouse-support
|
||
+ Use less mouse support (works only in xterm)
|
||
-b [_N] .... --buffers=[_N]
|
||
Number of buffers.
|
||
-B ........ --auto-buffers
|
||
--- less.nro
|
||
+++ less.nro
|
||
@@ -10,7 +10,7 @@
|
||
.br
|
||
.B "less \-\-version"
|
||
.br
|
||
-.B "less [\-[+]aBcCdeEfFgGiIJKLmMnNqQrRsSuUVwWX~]"
|
||
+.B "less [\-[+]aABcCdeEfFgGiIJKLmMnNqQrRsSuUVwWX~]"
|
||
.br
|
||
.B " [\-b \fIspace\fP] [\-h \fIlines\fP] [\-j \fIline\fP] [\-k \fIkeyfile\fP]"
|
||
.br
|
||
@@ -453,6 +453,22 @@
|
||
thus skipping all lines displayed on the screen.
|
||
By default, searches start at the second line on the screen
|
||
(or after the last found line; see the \-j option).
|
||
+.IP "-A or --mouse-support"
|
||
+Causes less to process mouse actions itself. Currently
|
||
+it works only in xterm. The inspiration comes from vim-6.0.
|
||
+.sp
|
||
+Cut&Paste function works only internally by default. To access
|
||
+X selection you must hold SHIFT key to process the mouse actions
|
||
+by xterm. Or you can install
|
||
+.I xselection
|
||
+utility by which less
|
||
+is able to access X selection itself.
|
||
+.sp
|
||
+Also scrolling by mouse wheel button is supported. You must map
|
||
+wheel mouse action on the 4th and 5th mouse button. This is done
|
||
+in XF86Config in Section "InputDevice" by option:
|
||
+.sp
|
||
+ Option "ZAxisMapping" "4 5"
|
||
.IP "\-b\fIn\fP or \-\-buffers=\fIn\fP"
|
||
Specifies the amount of buffer space
|
||
.I less
|
||
--- main.c
|
||
+++ main.c
|
||
@@ -32,6 +32,7 @@
|
||
public int quitting;
|
||
public int secure;
|
||
public int dohelp;
|
||
+public int xselection = 0; /* is xselection utility available ? */
|
||
public int less_is_more;
|
||
|
||
#if LOGFILE
|
||
--- optfunc.c
|
||
+++ optfunc.c
|
||
@@ -64,7 +64,31 @@
|
||
extern int so_fg_color, so_bg_color;
|
||
extern int bl_fg_color, bl_bg_color;
|
||
#endif
|
||
+extern int opt_mouse_support;
|
||
|
||
+/*
|
||
+ * Handler for the -A option.
|
||
+ */
|
||
+ /*ARGSUSED*/
|
||
+ public void
|
||
+opt_A(type, s)
|
||
+ int type;
|
||
+ char *s;
|
||
+{
|
||
+ switch (type)
|
||
+ {
|
||
+ case TOGGLE:
|
||
+ if (opt_mouse_support)
|
||
+ init_mouse_support();
|
||
+ else
|
||
+ deinit_mouse_support();
|
||
+ break;
|
||
+ case QUERY:
|
||
+ case INIT:
|
||
+ break;
|
||
+ }
|
||
+ return;
|
||
+}
|
||
|
||
#if LOGFILE
|
||
/*
|
||
--- opttbl.c
|
||
+++ opttbl.c
|
||
@@ -54,6 +54,7 @@
|
||
#if HILITE_SEARCH
|
||
public int hilite_search; /* Highlight matched search patterns? */
|
||
#endif
|
||
+public int opt_mouse_support; /* Less mouse support (works only with xterm) */
|
||
|
||
public int less_is_more = 0; /* Make compatible with POSIX more */
|
||
|
||
@@ -61,6 +62,7 @@
|
||
* Long option names.
|
||
*/
|
||
static struct optname a_optname = { "search-skip-screen", NULL };
|
||
+static struct optname A_optname = { "mouse-support", NULL };
|
||
static struct optname b_optname = { "buffers", NULL };
|
||
static struct optname B__optname = { "auto-buffers", NULL };
|
||
static struct optname c_optname = { "clear-screen", NULL };
|
||
@@ -137,7 +139,14 @@
|
||
NULL
|
||
}
|
||
},
|
||
-
|
||
+ { 'A', &A_optname,
|
||
+ BOOL, OPT_OFF, &opt_mouse_support, opt_A,
|
||
+ {
|
||
+ "Do not use less mouse support",
|
||
+ "Use less mouse support (works only in xterm)",
|
||
+ NULL
|
||
+ }
|
||
+ },
|
||
{ 'b', &b_optname,
|
||
NUMBER|INIT_HANDLER, 64, &bufspace, opt_b,
|
||
{
|
||
--- output.c
|
||
+++ output.c
|
||
@@ -40,6 +40,8 @@
|
||
extern int bl_fg_color, bl_bg_color;
|
||
#endif
|
||
|
||
+extern char *ungotp;
|
||
+
|
||
/*
|
||
* Display the line which is in the line buffer.
|
||
*/
|
||
@@ -505,7 +507,27 @@
|
||
#else
|
||
c = getchr();
|
||
if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
|
||
+ {
|
||
+ /*
|
||
+ * on the standard input can be a sequence (not only one char)
|
||
+ * we have read first char of the potential sequence and
|
||
+ * we want to unget it to internal less buffer but there
|
||
+ * can be older ungotten chracters
|
||
+ *
|
||
+ * we must not to put old ungotten chars inside this sequence
|
||
+ *
|
||
+ * 1. solution is to put this char at the begin of internal
|
||
+ * less buffer (LIFO) to use this character after all older
|
||
+ * ungotten chars. But the user can be mixed that the current
|
||
+ * command is done later
|
||
+ *
|
||
+ * 2. soluton is to discard all old ungotten chars
|
||
+ *
|
||
+ * I prefer the 2. solution
|
||
+ */
|
||
+ ungotp = NULL;
|
||
ungetcc(c);
|
||
+ }
|
||
#endif
|
||
}
|
||
|
||
--- screen.c
|
||
+++ screen.c
|
||
@@ -241,6 +241,9 @@
|
||
extern char *tgetstr();
|
||
extern char *tgoto();
|
||
|
||
+extern int xselection; /* is xselection available */
|
||
+extern int opt_mouse_support; /* is less mouse support enabled (option -A ) */
|
||
+int mouse_support = 0; /* is less mouse support initialized ? */
|
||
|
||
/*
|
||
* Change terminal to "raw mode", or restore to "normal" mode.
|
||
@@ -1527,6 +1530,42 @@
|
||
|
||
#endif
|
||
|
||
+public void
|
||
+init_mouse_support()
|
||
+{
|
||
+ if (mouse_support)
|
||
+ /* nothing to do (less mouse support is already inicialized */
|
||
+ return;
|
||
+
|
||
+ /* save old highlight mouse tracking */
|
||
+ printf("\033[?1001s");
|
||
+ /* enable mouse tracking */
|
||
+ printf("\033[?1001h");
|
||
+ fflush(stdout);
|
||
+ mouse_support = 1;
|
||
+
|
||
+ /* check if the xselection utility is available and is usable */
|
||
+ xselection = is_xselection_available();
|
||
+
|
||
+ return;
|
||
+}
|
||
+
|
||
+public void
|
||
+deinit_mouse_support()
|
||
+{
|
||
+ if (!mouse_support)
|
||
+ /* nothing to do (mouse support was not inicialized) */
|
||
+ return;
|
||
+
|
||
+ /* disable mouse tracking */
|
||
+ printf("\033[?1001l");
|
||
+ /* restore old highlight mouse tracking */
|
||
+ printf("\033[?1001r");
|
||
+ fflush(stdout);
|
||
+ mouse_support = 0;
|
||
+ return;
|
||
+}
|
||
+
|
||
/*
|
||
* Initialize terminal
|
||
*/
|
||
@@ -1538,6 +1577,8 @@
|
||
tputs(sc_init, sc_height, putchr);
|
||
if (!no_keypad)
|
||
tputs(sc_s_keypad, sc_height, putchr);
|
||
+ if (opt_mouse_support)
|
||
+ init_mouse_support();
|
||
if (top_scroll)
|
||
{
|
||
int i;
|
||
@@ -1575,6 +1616,7 @@
|
||
tputs(sc_e_keypad, sc_height, putchr);
|
||
if (!no_init)
|
||
tputs(sc_deinit, sc_height, putchr);
|
||
+ deinit_mouse_support();
|
||
#else
|
||
/* Restore system colors. */
|
||
SETCOLORS(sy_fg_color, sy_bg_color);
|
||
--- selection.c
|
||
+++ selection.c
|
||
@@ -0,0 +1,271 @@
|
||
+/*
|
||
+ * Copyright (C) 1984-2000 Mark Nudelman
|
||
+ *
|
||
+ * You may distribute under the terms of either the GNU General Public
|
||
+ * License or the Less License, as specified in the README file.
|
||
+ *
|
||
+ * For more information about less, or for information on how to
|
||
+ * contact the author, see the README file.
|
||
+ */
|
||
+/*
|
||
+ * Copyright (c) 1997-2000 Kazushi (Jam) Marukawa
|
||
+ * All rights of japanized routines are reserved.
|
||
+ *
|
||
+ * You may distribute under the terms of the Less License.
|
||
+ */
|
||
+
|
||
+
|
||
+/*
|
||
+ * User-level command processor.
|
||
+ */
|
||
+
|
||
+#include <stdio.h>
|
||
+#include "less.h"
|
||
+#include "position.h"
|
||
+#include "option.h"
|
||
+#include "cmd.h"
|
||
+
|
||
+#define IS_CONT(c) (((c) & 0xC0) == 0x80)
|
||
+#define SELECTION_SIZE_STEP 1000
|
||
+
|
||
+char *selection=NULL; /* buffer for less internal selection */
|
||
+int max_selection_size=0; /* current size of the buffer for less */
|
||
+ /* internal selection */
|
||
+int selection_size=0; /* current size of less internal selection */
|
||
+
|
||
+extern int utf_mode;
|
||
+
|
||
+/*
|
||
+ * clear less internal selection
|
||
+ */
|
||
+ public void
|
||
+clear_selection()
|
||
+{
|
||
+ if (selection)
|
||
+ {
|
||
+ free(selection);
|
||
+ selection=NULL;
|
||
+ max_selection_size=0;
|
||
+ selection_size=0;
|
||
+ }
|
||
+ return;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * expand the size of less internal selection buffer
|
||
+ */
|
||
+ static int
|
||
+expand_selection_buffer(size)
|
||
+ int size; /* new size will be: max_selection_size + size */
|
||
+{
|
||
+ char *new_selection;
|
||
+
|
||
+ if (!selection)
|
||
+ {
|
||
+ /* buffer for selection isn't allocated */
|
||
+ selection = (char*)malloc((size + 1) * sizeof(char));
|
||
+ if (!selection)
|
||
+ {
|
||
+ error("WARNING: Not enough memory for selection", NULL_PARG);
|
||
+ clear_selection();
|
||
+ return 0;
|
||
+ }
|
||
+ max_selection_size = size;
|
||
+ selection_size = 0;
|
||
+ *selection = '\0';
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ if (size > 0)
|
||
+ {
|
||
+ new_selection = (char*)malloc((max_selection_size + size + 1) * sizeof(char));
|
||
+ if (!new_selection)
|
||
+ {
|
||
+ error("WARNING: Not enough memory for selection", NULL_PARG);
|
||
+ clear_selection();
|
||
+ return 0;
|
||
+ }
|
||
+ memcpy(new_selection, selection, max_selection_size + 1);
|
||
+ free(selection);
|
||
+ selection = new_selection;
|
||
+ max_selection_size += size;
|
||
+ return 1;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+
|
||
+/*
|
||
+ * add a char into less internal selection
|
||
+ */
|
||
+ static int
|
||
+add_char_to_selection(c)
|
||
+ int c;
|
||
+{
|
||
+ if (selection_size >= max_selection_size)
|
||
+ if (!(expand_selection_buffer(SELECTION_SIZE_STEP)))
|
||
+ return 0;
|
||
+
|
||
+ /* finally add new char */
|
||
+ selection[selection_size++] = c;
|
||
+ selection[selection_size] = '\0';
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * add more chars into less internal selection
|
||
+ */
|
||
+ static int
|
||
+add_buf_to_selection(buf, size)
|
||
+ char *buf;
|
||
+ int size;
|
||
+{
|
||
+ if ((selection_size + size) > max_selection_size)
|
||
+ if (!(expand_selection_buffer(size)))
|
||
+ return 0;
|
||
+
|
||
+ /* finally add buf to selection */
|
||
+ memcpy(selection + selection_size, buf, size);
|
||
+ selection_size += size;
|
||
+ selection[selection_size] = '\0';
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+
|
||
+/*
|
||
+ * create less internal selection
|
||
+ * x1, y1, x2, y2 - are coordinates of begin and end of selection
|
||
+ */
|
||
+ public int
|
||
+create_selection(x1, y1, x2, y2)
|
||
+ int x1;
|
||
+ int y1;
|
||
+ int x2;
|
||
+ int y2;
|
||
+{
|
||
+ int x, y;
|
||
+ int c, csp, ap;
|
||
+ POSITION pos;
|
||
+
|
||
+ if ((x1 == x2) && (y1 == y2))
|
||
+ /* no new selection */
|
||
+ return 1;
|
||
+
|
||
+ if (((y1 == y2) && (x1 > x2)) || (y1 > y2))
|
||
+ {
|
||
+ /* we want to have x1,y1 as begin of selection */
|
||
+ x = x1; y = y1;
|
||
+ x1 = x2; y1 = y2;
|
||
+ x2 = x; y2 = y;
|
||
+ }
|
||
+
|
||
+ clear_selection();
|
||
+ for (y = y1; y <= y2; y++)
|
||
+ {
|
||
+ pos = position(y);
|
||
+ forw_line(pos);
|
||
+ for (x = (y == y1) ? x1 : 0;
|
||
+ (((c = gline(x, &csp, &ap)) != '\0') && !((y == y2) && (x >= x2)));
|
||
+ x++)
|
||
+ {
|
||
+ if (!add_char_to_selection(c))
|
||
+ /* something wrong */
|
||
+ return 0;
|
||
+ if ((utf_mode) && (IS_CONT(c)) && (y == y2))
|
||
+ /* it is multichar */
|
||
+ ++x2;
|
||
+ }
|
||
+ }
|
||
+ return 2;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * write less internal selection to xselection
|
||
+ * it use the xselection utility because less isn't linked against Xlib
|
||
+ */
|
||
+ public int
|
||
+write_xselection()
|
||
+{
|
||
+ FILE *xsel;
|
||
+
|
||
+ if ((xsel = popen("xselection PRIMARY -", "w")) == NULL)
|
||
+ /* can't open xselection */
|
||
+ return 0;
|
||
+
|
||
+ if (selection)
|
||
+ if (fwrite(selection, 1, selection_size, xsel) != selection_size)
|
||
+ {
|
||
+ error("WARNING: Can not write the whole selection to the xselection", NULL_PARG);
|
||
+ pclose(xsel);
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ if (pclose(xsel) != 0)
|
||
+ /* xselection didn't work correctly */
|
||
+ return 0;
|
||
+
|
||
+ /* everything OK */
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+
|
||
+/*
|
||
+ * read xselection to less internal selection
|
||
+ * it use the xselection utility because less isn't linked against Xlib
|
||
+ */
|
||
+ public int
|
||
+read_xselection()
|
||
+{
|
||
+ FILE *xsel;
|
||
+ char buf[SELECTION_SIZE_STEP];
|
||
+ int read;
|
||
+
|
||
+ if ((xsel = popen("xselection PRIMARY", "r")) == NULL)
|
||
+ /* can't open xselection */
|
||
+ return 0;
|
||
+
|
||
+ clear_selection();
|
||
+ while ((read = fread(buf, 1, SELECTION_SIZE_STEP, xsel)) != 0)
|
||
+ {
|
||
+ if (!add_buf_to_selection(buf, read))
|
||
+ {
|
||
+ /* something wrong */
|
||
+ pclose(xsel);
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (pclose(xsel) != 0)
|
||
+ {
|
||
+ /* xselection didn't work correctly */
|
||
+ clear_selection();
|
||
+ return 0;
|
||
+ }
|
||
+
|
||
+ /* everything OK */
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * test if xselection utility is available
|
||
+ */
|
||
+ public int
|
||
+is_xselection_available()
|
||
+{
|
||
+ FILE *xsel;
|
||
+ char buf[SELECTION_SIZE_STEP];
|
||
+ int read;
|
||
+
|
||
+ if ((xsel = popen("xselection -help 2>/dev/null", "r")) == NULL)
|
||
+ /* can't open xselection */
|
||
+ return 0;
|
||
+
|
||
+ while ((read = fread(buf, 1, SELECTION_SIZE_STEP, xsel)) != 0);
|
||
+
|
||
+ if (pclose(xsel) != 0)
|
||
+ /* xselection doesn't work correctly */
|
||
+ return 0;
|
||
+
|
||
+ /* everything OK */
|
||
+ return 1;
|
||
+}
|