less/less-409-mouse.patch

937 lines
21 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--- 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;
+}