Date: Sun, 5 Jun 2005 16:40:05 GMT From: Eugene Grosbein <eugen@grosbein.pp.ru> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/48599: [PATCH] syscons cut-n-paste logic is broken Message-ID: <200506051640.j55Ge5WH083932@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/48599; it has been noted by GNATS. From: Eugene Grosbein <eugen@grosbein.pp.ru> To: bug-followup@freebsd.org Cc: Gleb Smirnoff <glebius@freebsd.org> Subject: Re: kern/48599: [PATCH] syscons cut-n-paste logic is broken Date: Mon, 6 Jun 2005 00:36:48 +0800 Hi! Here is a merge to RELENG_4 of sys/dev/syscons/scmouse.c rev. 1.20, 1.27-1.29 and corresponding revisions of sys/conf/options.i386, sys/i386/conf/LINT and share/man/man4/syscons.4. 1.20 is needed for 1.27 to apply cleanly. This patch fixes the problem and follows current codebase. --- sys/dev/syscons/scmouse.c.orig Mon Jun 6 00:10:21 2005 +++ sys/dev/syscons/scmouse.c Mon Jun 6 00:10:12 2005 @@ -280,6 +280,18 @@ #define IS_SPACE_CHAR(c) (((c) & 0xff) == ' ') +#ifdef SC_CUT_SPACES2TABS +#define IS_BLANK_CHAR(c) (((c) & 0xff) == ' ' || ((c) & 0xff) == '\t') +#else +#define IS_BLANK_CHAR(c) IS_SPACE_CHAR(c) +#endif /* SC_CUT_SPACES2TABS */ + +#ifdef SC_CUT_SEPCHARS +#define IS_SEP_CHAR(c) (index(SC_CUT_SEPCHARS, (c) & 0xff) != NULL) +#else +#define IS_SEP_CHAR(c) IS_SPACE_CHAR(c) +#endif /* SC_CUT_SEPCHARS */ + /* skip spaces to right */ static int skip_spc_right(scr_stat *scp, int p) @@ -312,6 +324,66 @@ return i; } +static void +mouse_do_cut(scr_stat *scp, int from, int to) +{ + int blank; + int i; + int leadspaces; + int p; + int s; + + for (p = from, i = blank = leadspaces = 0; p <= to; ++p) { + cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); + /* Be prepared that sc_vtb_getc() can return '\0' */ + if (cut_buffer[i] == '\0') + cut_buffer[i] = ' '; +#ifdef SC_CUT_SPACES2TABS + if (leadspaces != -1) { + if (IS_SPACE_CHAR(cut_buffer[i])) { + leadspaces++; + /* Check that we are at tabstop position */ + if ((p % scp->xsize) % 8 == 7) { + i -= leadspaces - 1; + cut_buffer[i] = '\t'; + leadspaces = 0; + } + } else { + leadspaces = -1; + } + } +#endif /* SC_CUT_SPACES2TABS */ + /* remember the position of the last non-space char */ + if (!IS_BLANK_CHAR(cut_buffer[i])) + blank = i + 1; /* the first space after the last non-space */ + ++i; + /* trim trailing blank when crossing lines */ + if ((p % scp->xsize) == (scp->xsize - 1)) { + cut_buffer[blank++] = '\r'; + i = blank; + leadspaces = 0; + } + } + cut_buffer[i] = '\0'; + + /* remove the current marking */ + s = spltty(); + if (scp->mouse_cut_start <= scp->mouse_cut_end) { + mark_for_update(scp, scp->mouse_cut_start); + mark_for_update(scp, scp->mouse_cut_end); + } else if (scp->mouse_cut_end >= 0) { + mark_for_update(scp, scp->mouse_cut_end); + mark_for_update(scp, scp->mouse_cut_start); + } + + /* mark the new region */ + scp->mouse_cut_start = from; + scp->mouse_cut_end = to; + mark_for_update(scp, from); + mark_for_update(scp, to); + splx(s); +} + /* copy marked region to the cut buffer */ static void mouse_cut(scr_stat *scp) @@ -320,7 +392,6 @@ int end; int from; int to; - int blank; int c; int p; int s; @@ -335,21 +406,7 @@ from = end = scp->mouse_pos; to = start - 1; } - for (p = from, i = blank = 0; p <= to; ++p) { - cut_buffer[i] = sc_vtb_getc(&scp->vtb, p); - /* remember the position of the last non-space char */ - if (!IS_SPACE_CHAR(cut_buffer[i++])) - blank = i; /* the first space after the last non-space */ - /* trim trailing blank when crossing lines */ - if ((p % scp->xsize) == (scp->xsize - 1)) { - cut_buffer[blank] = '\r'; - i = blank + 1; - } - } - cut_buffer[i] = '\0'; - - /* scan towards the end of the last line */ - --p; + p = to; for (i = p % scp->xsize; i < scp->xsize; ++i) { c = sc_vtb_getc(&scp->vtb, p); if (!IS_SPACE_CHAR(c)) @@ -357,47 +414,31 @@ ++p; } /* if there is nothing but blank chars, trim them, but mark towards eol */ - if (i >= scp->xsize) { + if (i == scp->xsize) { if (end >= start) to = end = p - 1; else to = start = p; - cut_buffer[blank++] = '\r'; - cut_buffer[blank] = '\0'; } - - /* remove the current marking */ + mouse_do_cut(scp, from, to); s = spltty(); - if (scp->mouse_cut_start <= scp->mouse_cut_end) { - mark_for_update(scp, scp->mouse_cut_start); - mark_for_update(scp, scp->mouse_cut_end); - } else if (scp->mouse_cut_end >= 0) { - mark_for_update(scp, scp->mouse_cut_end); - mark_for_update(scp, scp->mouse_cut_start); - } - - /* mark the new region */ scp->mouse_cut_start = start; scp->mouse_cut_end = end; - mark_for_update(scp, from); - mark_for_update(scp, to); splx(s); } /* a mouse button is pressed, start cut operation */ static void -mouse_cut_start(scr_stat *scp) +mouse_cut_start(scr_stat *scp) { int i; - int j; int s; if (scp->status & MOUSE_VISIBLE) { - i = scp->mouse_cut_start; - j = scp->mouse_cut_end; sc_remove_all_cutmarkings(scp->sc); - if (scp->mouse_pos == i && i == j) { + if (scp->mouse_pos == scp->mouse_cut_start == scp->mouse_cut_end) { cut_buffer[0] = '\0'; + return; } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { /* if the pointer is on trailing blank chars, mark towards eol */ i = skip_spc_left(scp, scp->mouse_pos) + 1; @@ -408,17 +449,15 @@ (scp->mouse_pos / scp->xsize + 1) * scp->xsize - 1; splx(s); cut_buffer[0] = '\r'; - cut_buffer[1] = '\0'; - scp->status |= MOUSE_CUTTING; } else { s = spltty(); scp->mouse_cut_start = scp->mouse_pos; scp->mouse_cut_end = scp->mouse_cut_start; splx(s); cut_buffer[0] = sc_vtb_getc(&scp->vtb, scp->mouse_cut_start); - cut_buffer[1] = '\0'; - scp->status |= MOUSE_CUTTING; } + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; mark_all(scp); /* this is probably overkill XXX */ } } @@ -440,43 +479,30 @@ int sol; int eol; int c; - int s; - int i; int j; + int len; /* * Because we don't have locale information in the kernel, * we only distinguish space char and non-space chars. Punctuation - * chars, symbols and other regular chars are all treated alike. + * chars, symbols and other regular chars are all treated alike + * unless user specified SC_CUT_SEPCHARS in his kernel config file. */ if (scp->status & MOUSE_VISIBLE) { - /* remove the current cut mark */ - s = spltty(); - if (scp->mouse_cut_start <= scp->mouse_cut_end) { - mark_for_update(scp, scp->mouse_cut_start); - mark_for_update(scp, scp->mouse_cut_end); - } else if (scp->mouse_cut_end >= 0) { - mark_for_update(scp, scp->mouse_cut_end); - mark_for_update(scp, scp->mouse_cut_start); - } - scp->mouse_cut_start = scp->xsize*scp->ysize; - scp->mouse_cut_end = -1; - splx(s); - sol = (scp->mouse_pos / scp->xsize) * scp->xsize; eol = sol + scp->xsize; c = sc_vtb_getc(&scp->vtb, scp->mouse_pos); - if (IS_SPACE_CHAR(c)) { + if (IS_SEP_CHAR(c)) { /* blank space */ for (j = scp->mouse_pos; j >= sol; --j) { c = sc_vtb_getc(&scp->vtb, j); - if (!IS_SPACE_CHAR(c)) + if (!IS_SEP_CHAR(c)) break; } start = ++j; for (j = scp->mouse_pos; j < eol; ++j) { c = sc_vtb_getc(&scp->vtb, j); - if (!IS_SPACE_CHAR(c)) + if (!IS_SEP_CHAR(c)) break; } end = j - 1; @@ -484,31 +510,23 @@ /* non-space word */ for (j = scp->mouse_pos; j >= sol; --j) { c = sc_vtb_getc(&scp->vtb, j); - if (IS_SPACE_CHAR(c)) + if (IS_SEP_CHAR(c)) break; } start = ++j; for (j = scp->mouse_pos; j < eol; ++j) { c = sc_vtb_getc(&scp->vtb, j); - if (IS_SPACE_CHAR(c)) + if (IS_SEP_CHAR(c)) break; } end = j - 1; } /* copy the found word */ - for (i = 0, j = start; j <= end; ++j) - cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); - cut_buffer[i] = '\0'; - scp->status |= MOUSE_CUTTING; - - /* mark the region */ - s = spltty(); - scp->mouse_cut_start = start; - scp->mouse_cut_end = end; - mark_for_update(scp, start); - mark_for_update(scp, end); - splx(s); + mouse_do_cut(scp, start, end); + len = strlen(cut_buffer); + if (cut_buffer[len - 1] == '\r') + cut_buffer[len - 1] = '\0'; } } @@ -516,34 +534,15 @@ static void mouse_cut_line(scr_stat *scp) { - int s; - int i; - int j; + int len; + int from; if (scp->status & MOUSE_VISIBLE) { - /* remove the current cut mark */ - s = spltty(); - if (scp->mouse_cut_start <= scp->mouse_cut_end) { - mark_for_update(scp, scp->mouse_cut_start); - mark_for_update(scp, scp->mouse_cut_end); - } else if (scp->mouse_cut_end >= 0) { - mark_for_update(scp, scp->mouse_cut_end); - mark_for_update(scp, scp->mouse_cut_start); - } - - /* mark the entire line */ - scp->mouse_cut_start = - (scp->mouse_pos / scp->xsize) * scp->xsize; - scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize - 1; - mark_for_update(scp, scp->mouse_cut_start); - mark_for_update(scp, scp->mouse_cut_end); - splx(s); - - /* copy the line into the cut buffer */ - for (i = 0, j = scp->mouse_cut_start; j <= scp->mouse_cut_end; ++j) - cut_buffer[i++] = sc_vtb_getc(&scp->vtb, j); - cut_buffer[i++] = '\r'; - cut_buffer[i] = '\0'; + from = (scp->mouse_pos / scp->xsize) * scp->xsize; + mouse_do_cut(scp, from, from + scp->xsize - 1); + len = strlen(cut_buffer); + if (cut_buffer[len - 1] == '\r') + cut_buffer[len - 1] = '\0'; scp->status |= MOUSE_CUTTING; } } --- sys/conf/options.i386.orig Fri Apr 2 00:40:28 2004 +++ sys/conf/options.i386 Sun Jun 5 23:14:08 2005 @@ -77,6 +77,8 @@ MAXCONS opt_syscons.h SC_ALT_MOUSE_IMAGE opt_syscons.h +SC_CUT_SPACES2TABS opt_syscons.h +SC_CUT_SEPCHARS opt_syscons.h SC_DEBUG_LEVEL opt_syscons.h SC_DFLT_FONT opt_syscons.h SC_DISABLE_DDBKEY opt_syscons.h --- sys/i386/conf/LINT.orig Mon Jan 17 16:37:27 2005 +++ sys/i386/conf/LINT Sun Jun 5 23:16:23 2005 @@ -1186,6 +1186,12 @@ options SC_KERNEL_CONS_ATTR="(FG_RED|BG_BLACK)" options SC_KERNEL_CONS_REV_ATTR="(FG_BLACK|BG_RED)" +# The following options will let you change the default behaviour of +# cut-n-paste feature +options SC_CUT_SPACES2TABS # convert leading spaces into tabs +options SC_CUT_SEPCHARS="\x20" # set of characters that delimit words + # (default is single space - "\x20") + # If you have a two button mouse, you may want to add the following option # to use the right button of the mouse to paste text. options SC_TWOBUTTON_MOUSE --- share/man/man4/syscons.4.orig Sat Apr 26 05:21:36 2003 +++ share/man/man4/syscons.4 Sun Jun 5 23:11:56 2005 @@ -261,6 +261,16 @@ .Dv SC_NO_FONT_LOADING option then you must also use this option if you wish to be able to use the mouse. +.It Dv SC_CUT_SEPCHARS=_characters_ +This options specifies characters that will be looked for when the +driver searches for words boundaries when doing cut operation. By +default its value is +.Dq \e\\&x20 +- a space character. +.It Dv SC_CUT_SPACES2TABS +This options instructs the driver to convert leading spaces into tabs +when copying data into cut buffer. This might be useful to preserve +identation when copying tab-idented text. .It Dv SC_DISABLE_DDBKEY This option disables the ``debug'' key combination (by default, it is .Dv Alt-Esc ,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200506051640.j55Ge5WH083932>