Subject: bin/17546: vi bug fixes and extensions
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dsl@l8s.co.uk>
List: netbsd-bugs
Date: 07/10/2002 16:12:15
>Number: 17546
>Category: bin
>Synopsis: vi bug fixes and extensions
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Jul 10 08:17:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: David Laight
>Release: NetBSD 1.6B
>Organization:
none
>Environment:
System: NetBSD snowdrop 1.6B NetBSD 1.6B (GENERIC) #17: Wed Jul 10 12:43:27 BST 2002
dsl@snowdrop:/oldroot/usr/bsd-current/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
I've got rather annoyed with vi % treating <> as a bracket pair.
- Added an option 'matchchars' to set the pairs of characters
that % will search for.
I was also trying to edit a file with tab separated fields where
some of the column widths varied by more than a single tab.
Setting a very wide screen hits an arbitrary width limit of
500 screen columns (real screen are too close to that one).
- increased the limit to 4000.
It seemed better to allow explicit positioning of tabs.
- added options:
tabadd=col adds tab at column 'col'
taddel=col removes tab from column col
tablist=col_list adds at +ve numbers, removes from -ve.
changes made by tabadd and tabdel affect the 'tablist' string.
The errorbells and escapetime options were missorted.
- fixed list.
>How-To-Repeat:
>Fix:
Diffs below, changed files can be downloaded from:
http://www.btinternet.com/~david.laight/netbsd/vi
I think the catalog changes are ok - done by symmetry!
Index: catalog/dutch.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/dutch.base,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 dutch.base
--- dutch.base 2001/03/31 11:29:50 1.1.1.2
+++ dutch.base 2002/07/05 21:14:12
@@ -43,8 +43,7 @@
044 "De lisp optie is niet ondersteund"
045 "messages niet uitgeschakeld: %s"
046 "messages niet geactiveerd: %s"
-048 "De paragraph optie moet karakter paren bevatten"
-049 "De section optie moet karakter paren bevatten"
+047 "set: de %s optie moet karakter paren bevatten"
053 "De standaard buffer is leeg"
054 "Buffer %s is leeg"
055 "Bestanden met newlines in de naam kunnen niet hersteld worden"
Index: catalog/french.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/french.base,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 french.base
--- french.base 2001/03/31 11:29:50 1.1.1.1
+++ french.base 2002/07/05 21:14:18
@@ -43,8 +43,7 @@
044 "L'option lisp n'est pas impl‚ment‚e"
045 "Les messages ne sont pas d‚sactiv‚s : %s"
046 "Les messages ne sont pas activ‚s : %s"
-048 "L'option de paragraphe doit ˆtre en groupe de deux caractŠres"
-049 "L'option de section doit ˆtre en groupe de deux caractŠres"
+047 "D‚finition : l'option de %s doit ˆtre en groupe de deux caractŠres"
053 "Le tampon par d‚faut est vide"
054 "Le tampon %s est vide"
055 "Les fichiers dont le nom contient des caractŠres de saut de ligne sont irr‚cup‚rables"
Index: catalog/german.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/german.base,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 german.base
--- german.base 2001/03/31 11:29:50 1.1.1.2
+++ german.base 2002/07/05 21:14:24
@@ -43,8 +43,7 @@
044 "Die lisp Option ist nicht implementiert"
045 "Messages nicht abgeschalten: %s"
046 "Messages nicht eingeschalten: %s"
-048 "Die paragraph Option muss Gruppen zu zwei Zeichen enthalten"
-049 "Die section Option muss Gruppen zu zwei Zeichen enthalten"
+047 "set: Die %s Option muss Gruppen zu zwei Zeichen enthalten"
053 "Der Standardpuffer ist leer"
054 "Puffer %s ist leer"
055 "Dateien mit newlines im Namen sind nicht wiederherstellbar"
Index: catalog/ru_RU.KOI8-R.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/ru_RU.KOI8-R.base,v
retrieving revision 1.2
diff -u -r1.2 ru_RU.KOI8-R.base
--- ru_RU.KOI8-R.base 2001/03/31 11:37:44 1.2
+++ ru_RU.KOI8-R.base 2002/07/05 21:14:30
@@ -31,9 +31,7 @@
044 "oPCIQ lisp OTSUTSTWUET"
045 "sOOB]ENIQ NE WYKL@^ENY: %s"
046 "sOOB]ENIQ NE WKL@^ENY: %s"
-047 "oPCIQ modeline(s) NE MOVET BYTX PEREUSTANOWLENA"
-048 "oPCIQ paragraph DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
-049 "oPCIQ section DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
+047 "set: oPCIQ %s DOLVNA SOSTOQTX IZ GRUPP S DWUMQ SIMWOLAMI"
050 "oPCIQ shiftwidth NE MOVET BYTX USTANOWLENA NA 0"
051 "oPCIQ sourceany NE MOVET BYTX USTANOWLENA"
052 "tABULQCIQ NE MOVET BYTX USTANOWLENA NA 0"
Index: catalog/spanish.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/spanish.base,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 spanish.base
--- spanish.base 2001/03/31 11:29:49 1.1.1.1
+++ spanish.base 2002/07/05 21:14:36
@@ -43,8 +43,7 @@
044 "La opci¢n lisp no est implementada"
045 "mensajes no desconectados: %s"
046 "mensajes no conectados: %s"
-048 "La opci¢n de p rrafo debe estar en dos grupos de caracteres"
-049 "La opci¢n de secci¢n debe estar en dos grupos de caracteres"
+047 "determinar: La opci¢n de %s debe estar en dos grupos de caracteres"
053 "El buffer por omisi¢n est vac¡o"
054 "El buffer %s est vac¡o"
055 "Los archivos con nuevas l¡neas en el nombre son irrecuperables"
Index: catalog/swedish.base
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/catalog/swedish.base,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 swedish.base
--- swedish.base 2001/03/31 11:29:50 1.1.1.2
+++ swedish.base 2002/07/05 21:14:42
@@ -43,8 +43,7 @@
044 "Lisp flaggan är inte implementerad"
045 "meddelanden är inte avslagna: %s"
046 "meddelanden är inte påslagna: %s"
-048 "Paragraph flaggan måste ges i teckengrupper om två"
-049 "Section flaggan måste ges i teckengrupper om två"
+047 "set: %s flaggan måste ges i teckengrupper om två"
053 "Standardbufferten är tom"
054 "Buffer %s är tom"
055 "Filer med radmatning i namnet kan inte återskapas"
Index: options.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/common/options.c,v
retrieving revision 1.6
diff -u -r1.6 options.c
--- options.c 2002/04/09 01:47:31 1.6
+++ options.c 2002/07/06 09:09:54
@@ -49,6 +49,8 @@
*
* HPUX noted options and abbreviations are from "The Ultimate Guide to the
* VI and EX Text Editors", 1990.
+ *
+ * This list must be sorted...
*/
OPTLIST const optlist[] = {
/* O_ALTWERASE 4.4BSD */
@@ -75,10 +77,10 @@
{"directory", NULL, OPT_STR, 0},
/* O_EDCOMPATIBLE 4BSD */
{"edcompatible",NULL, OPT_0BOOL, 0},
-/* O_ESCAPETIME 4.4BSD */
- {"escapetime", NULL, OPT_NUM, 0},
/* O_ERRORBELLS 4BSD */
{"errorbells", NULL, OPT_0BOOL, 0},
+/* O_ESCAPETIME 4.4BSD */
+ {"escapetime", NULL, OPT_NUM, 0},
/* O_EXRC System V (undocumented) */
{"exrc", NULL, OPT_0BOOL, 0},
/* O_EXTENDED 4.4BSD */
@@ -119,6 +121,8 @@
{"lock", NULL, OPT_1BOOL, 0},
/* O_MAGIC 4BSD */
{"magic", NULL, OPT_1BOOL, 0},
+/* O_MATCHCHARS netbsd 1.6 */
+ {"matchchars", NULL, OPT_STR, OPT_PAIRS},
/* O_MATCHTIME 4.4BSD */
{"matchtime", NULL, OPT_NUM, 0},
/* O_MESG 4BSD */
@@ -145,7 +149,7 @@
/* O_OPTIMIZE 4BSD */
{"optimize", NULL, OPT_1BOOL, 0},
/* O_PARAGRAPHS 4BSD */
- {"paragraphs", f_paragraph, OPT_STR, 0},
+ {"paragraphs", NULL, OPT_STR, OPT_PAIRS},
/* O_PATH 4.4BSD */
{"path", NULL, OPT_STR, 0},
/* O_PRINT 4.4BSD */
@@ -169,7 +173,7 @@
/* O_SEARCHINCR 4.4BSD */
{"searchincr", NULL, OPT_0BOOL, 0},
/* O_SECTIONS 4BSD */
- {"sections", f_section, OPT_STR, 0},
+ {"sections", NULL, OPT_STR, OPT_PAIRS},
/* O_SECURE 4.4BSD */
{"secure", NULL, OPT_0BOOL, OPT_NOUNSET},
/* O_SHELL 4BSD */
@@ -195,8 +199,14 @@
* and we ignore the option.
*/
{"sourceany", NULL, OPT_0BOOL, OPT_NOSET},
+/* O_TABADD netbsd 1.6 */
+ {"tabadd", f_tabadd, OPT_NUM, OPT_NOZERO|OPT_NOSAVE},
+/* O_TABDEL netbsd 1.6 */
+ {"tabdel", f_tabdel, OPT_NUM, OPT_NOZERO|OPT_NOSAVE},
+/* O_TABLIST netbsd 1.6 */
+ {"tablist", f_tablist, OPT_STR, 0},
/* O_TABSTOP 4BSD */
- {"tabstop", f_reformat, OPT_NUM, OPT_NOZERO},
+ {"tabstop", f_tabstop, OPT_NUM, OPT_NOZERO},
/* O_TAGLENGTH 4BSD */
{"taglength", NULL, OPT_NUM, 0},
/* O_TAGS 4BSD */
@@ -376,6 +386,7 @@
OI(O_TABSTOP, "tabstop=8");
(void)snprintf(b1, sizeof(b1), "tags=%s", _PATH_TAGS);
OI(O_TAGS, b1);
+ OI(O_MATCHCHARS, "matchchars=()[]{}<>");
/*
* XXX
@@ -705,6 +716,14 @@
if (!disp)
disp = SELECT_DISPLAY;
F_SET(spo, OPT_SELECTED);
+ break;
+ }
+
+ /* Check for strings that must have even length */
+ if (F_ISSET(op, OPT_PAIRS) && strlen(sep) & 1) {
+ msgq_str(sp, M_ERR, name,
+ "047|set: the %s option must be in two character groups");
+ rval = 1;
break;
}
Index: common/options.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/common/options.h,v
retrieving revision 1.4
diff -u -r1.4 options.h
--- options.h 2001/03/31 11:37:46 1.4
+++ options.h 2002/07/05 21:14:55
@@ -30,6 +30,8 @@
(F_ISSET(&(sp)->opts[(o)], OPT_GLOBAL) ? \
(sp)->gp->opts[(sp)->opts[(o)].o_cur.val].fld : \
(sp)->opts[(o)].fld)
+/* if known to be local */
+#define OL_V(sp, o, fld) ((sp)->opts[(o)].fld)
/* Global option macros. */
#define OG_CLR(gp, o) ((gp)->opts[(o)].o_cur.val) = 0
@@ -59,6 +61,7 @@
#define O_SET(sp, o) o_set(sp, o, 0, NULL, 1)
#define O_STR(sp, o) O_V(sp, o, o_cur.str)
#define O_VAL(sp, o) O_V(sp, o, o_cur.val)
+#define OL_VAL(sp, o) OL_V(sp, o, o_cur.val)
#define O_ISSET(sp, o) O_VAL(sp, o)
union {
@@ -92,7 +95,8 @@
#define OPT_NOUNSET 0x020 /* Option may not be unset. */
#define OPT_NOZERO 0x040 /* Option may not be set to 0. */
#define OPT_EARLYSET 0x080 /* Subsys called after value is set. */
- u_int8_t flags;
+#define OPT_PAIRS 0x100 /* String with even length */
+ int flags;
};
/* Option argument to opts_dump(). */
Index: common/options_f.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/common/options_f.c,v
retrieving revision 1.4
diff -u -r1.4 options_f.c
--- options_f.c 2002/04/09 01:47:31 1.4
+++ options_f.c 2002/07/05 21:15:00
@@ -74,7 +74,7 @@
* number of lines/columns for the screen, but at least we don't drop
* core.
*/
-#define MAXIMUM_SCREEN_COLS 500
+#define MAXIMUM_SCREEN_COLS 4000
if (*valp > MAXIMUM_SCREEN_COLS) {
msgq(sp, M_ERR, "041|Screen columns too large, greater than %d",
MAXIMUM_SCREEN_COLS);
@@ -108,7 +108,7 @@
* number of lines/columns for the screen, but at least we don't drop
* core.
*/
-#define MAXIMUM_SCREEN_ROWS 500
+#define MAXIMUM_SCREEN_ROWS 4000
if (*valp > MAXIMUM_SCREEN_ROWS) {
msgq(sp, M_ERR, "043|Screen lines too large, greater than %d",
MAXIMUM_SCREEN_ROWS);
@@ -169,24 +169,6 @@
}
/*
- * PUBLIC: int f_paragraph __P((SCR *, OPTION *, char *, u_long *));
- */
-int
-f_paragraph(sp, op, str, valp)
- SCR *sp;
- OPTION *op;
- char *str;
- u_long *valp;
-{
- if (strlen(str) & 1) {
- msgq(sp, M_ERR,
- "048|The paragraph option must be in two character groups");
- return (1);
- }
- return (0);
-}
-
-/*
* PUBLIC: int f_print __P((SCR *, OPTION *, char *, u_long *));
*/
int
@@ -261,24 +243,6 @@
}
/*
- * PUBLIC: int f_section __P((SCR *, OPTION *, char *, u_long *));
- */
-int
-f_section(sp, op, str, valp)
- SCR *sp;
- OPTION *op;
- char *str;
- u_long *valp;
-{
- if (strlen(str) & 1) {
- msgq(sp, M_ERR,
- "049|The section option must be in two character groups");
- return (1);
- }
- return (0);
-}
-
-/*
* PUBLIC: int f_ttywerase __P((SCR *, OPTION *, char *, u_long *));
*/
int
@@ -370,4 +334,156 @@
(*valp = O_VAL(sp, O_LINES) - 1) == 0)
*valp = 1;
return (0);
+}
+
+/*
+ * PUBLIC: int f_tabstop __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_tabstop(SCR *sp, OPTION *op, char *str, ulong *valp)
+{
+ char *tl;
+
+ if (*valp > 2048)
+ /* sanity */
+ return 1;
+
+ /* Hack tabstop value in for tabadd code... */
+ O_VAL(sp, O_TABSTOP) = *valp;
+
+ /* get modified tab positions */
+ tl = O_STR(sp, O_TABLIST);
+ if (tl && (tl = strdup(tl))) {
+ /* and reapply */
+ f_tablist(sp, op, tl, 0);
+ free(tl);
+ }
+
+ return f_reformat(sp, op, str, valp);
+}
+
+/*
+ * PUBLIC: int f_tabadd __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_tabadd(SCR *sp, OPTION *op, char *str, ulong *valp)
+{
+ int col = *valp;
+ size_t tc, ts = O_VAL(sp, O_TABSTOP);
+ size_t *tt;
+ char *as, *ns;
+ int i;
+
+ if (!col)
+ return 0;
+ /* force redraw */
+ f_reformat(sp, op, str, valp);
+
+ if (col < 0)
+ col = -col;
+
+ /* Make table large enough to include this tabstop */
+ tt = sp->tab_table;
+ if (col >= sp->tab_table_len) {
+ REALLOC(sp, tt, size_t *, (col + 1) * sizeof *sp->tab_table);
+ /* fill in default tabs */
+ for (i = sp->tab_table_len; i <= col; i++)
+ tt[i] = COL_OFF(i, ts);
+ sp->tab_table_len = col + 1;
+ sp->tab_table = tt;
+ }
+ /* overwrite offsets going back to previous tab position */
+ i = *(long *)valp < 0 ? tt[col] : 0;
+ do {
+ tt[--col] = ++i;
+ } while (col && tt[col-1] != 1);
+
+ /* finally generate equivalent 'string' tablist value */
+ as = 0;
+ for (tc = 0, col = 0; col < sp->tab_table_len; col++, tc--) {
+ if (!tc)
+ tc = ts;
+ if (tt[col] != 1) {
+ /* there isn't a tab here... */
+ if (tc != 1)
+ /* and we dont expect one */
+ continue;
+ i = -(col + 1);
+ } else {
+ /* there is a tab here */
+ if (tc == 1)
+ /* we expected it */
+ continue;
+ i = col + 1;
+ }
+ if (as) {
+ asprintf( &ns, "%s,%d", as, i );
+ free(as);
+ } else
+ asprintf( &ns, "%d", i );
+ as = ns;
+ }
+
+ if (!as) {
+ free(tt);
+ sp->tab_table_len = 0;
+ sp->tab_table = 0;
+ }
+
+ o_set(sp, O_TABLIST, OS_STRDUP, as ? as : "", 0);
+ free(as);
+
+ return 0;
+}
+
+/*
+ * PUBLIC: int f_tabdel __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_tabdel(SCR *sp, OPTION *op, char *str, ulong *valp)
+{
+ ulong col = -*valp;
+
+ return f_tabadd(sp, op, str, &col);
+}
+
+/*
+ * PUBLIC: int f_tablist __P((SCR *, OPTION *, char *, u_long *));
+ */
+int
+f_tablist(SCR *sp, OPTION *op, char *str, ulong *valp)
+{
+ char *cp, *ncp;
+ ulong col;
+
+ /* validate that string is comma separated numbers */
+ if (*str) {
+ for (cp = str; ; cp = ncp + 1) {
+ strtol( cp, &ncp, 0 );
+ if (!*ncp)
+ break;
+ if (*ncp != ',')
+ return 1;
+ }
+ }
+
+ /* Remove all old info */
+ if (sp->tab_table) {
+ free( sp->tab_table );
+ sp->tab_table = 0;
+ sp->tab_table_len = 0;
+ }
+
+ if (!*str)
+ return 0;
+
+ /* now add in one by one */
+ for (cp = str; ; cp = ncp + 1) {
+ col = strtol( cp, &ncp, 0 );
+ f_tabadd(sp, op, 0, &col);
+ if (!*ncp)
+ break;
+ }
+
+ return 0;
}
Index: common/screen.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/common/screen.h,v
retrieving revision 1.3
diff -u -r1.3 screen.h
--- screen.h 2001/03/31 11:37:47 1.3
+++ screen.h 2002/07/05 21:15:05
@@ -136,6 +136,9 @@
OPTION opts[O_OPTIONCOUNT]; /* Ex/vi: Options. */
+ size_t tab_table_len; /* size of tab offset table */
+ size_t *tab_table; /* offsets of tabs */
+
/*
* Screen flags.
*
Index: common/util.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/common/util.c,v
retrieving revision 1.4
diff -u -r1.4 util.c
--- util.c 2002/04/09 01:47:32 1.4
+++ util.c 2002/07/05 21:15:10
@@ -196,6 +196,22 @@
return (NUM_ERR);
}
+
+/*
+ * PUBLIC: size_t tab_off( SCR *, size_t );
+ *
+ * Return number of characters to next tab stop.
+ */
+size_t
+tab_off( SCR *sp, size_t off )
+{
+ /* Has user been fiddling with the tabs? */
+ if (off < sp->tab_table_len)
+ return sp->tab_table[off];
+
+ return COL_OFF( off, OL_VAL( sp, O_TABSTOP ) );
+}
+
#ifdef DEBUG
#ifdef __STDC__
#include <stdarg.h>
Index: ex/ex_txt.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/ex/ex_txt.c,v
retrieving revision 1.6
diff -u -r1.6 ex_txt.c
--- ex_txt.c 2002/04/09 01:47:34 1.6
+++ ex_txt.c 2002/07/05 21:15:16
@@ -393,16 +393,16 @@
SCR *sp;
TEXT *tp;
{
- u_long sw, ts;
+ u_long sw;
size_t cno, off, scno, spaces, tabs;
+ size_t nco;
- ts = O_VAL(sp, O_TABSTOP);
sw = O_VAL(sp, O_SHIFTWIDTH);
/* Get the current screen column. */
for (off = scno = 0; off < tp->len; ++off)
if (tp->lb[off] == '\t')
- scno += COL_OFF(scno, ts);
+ scno += tab_off(sp, scno);
else
++scno;
@@ -421,8 +421,8 @@
*
* Count up spaces/tabs needed to get to the target.
*/
- for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
- cno += COL_OFF(cno, ts);
+ for (cno = 0, tabs = 0; (nco = cno + tab_off(sp, cno)) <= scno; ++tabs)
+ cno = nco;
spaces = scno - cno;
/* Make sure there's enough room. */
Index: ex/ex_shift.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/ex/ex_shift.c,v
retrieving revision 1.9
diff -u -r1.9 ex_shift.c
--- ex_shift.c 2002/04/09 01:47:34 1.9
+++ ex_shift.c 2002/07/05 21:15:21
@@ -73,6 +73,7 @@
{
recno_t from, to;
size_t blen, len, newcol, newidx, oldcol, oldidx, sw;
+ size_t col, nc;
int curset;
char *p, *bp, *tbp;
@@ -120,8 +121,7 @@
if (p[oldidx] == ' ')
++oldcol;
else if (p[oldidx] == '\t')
- oldcol += O_VAL(sp, O_TABSTOP) -
- oldcol % O_VAL(sp, O_TABSTOP);
+ oldcol += tab_off(sp, oldcol);
else
break;
@@ -144,13 +144,13 @@
* Build a new indent string and count the number of
* characters it uses.
*/
- for (tbp = bp, newidx = 0;
- newcol >= O_VAL(sp, O_TABSTOP); ++newidx) {
+ for (col = 0, tbp = bp;
+ (nc = col + tab_off(sp, col)) <= newcol; col = nc) {
*tbp++ = '\t';
- newcol -= O_VAL(sp, O_TABSTOP);
}
- for (; newcol > 0; --newcol, ++newidx)
+ for (; col < newcol; col++)
*tbp++ = ' ';
+ newidx = tbp - bp;
/* Add the original line. */
memcpy(tbp, p + oldidx, len - oldidx);
Index: include/com_extern.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/include/com_extern.h,v
retrieving revision 1.2
diff -u -r1.2 com_extern.h
--- com_extern.h 2001/03/31 11:37:51 1.2
+++ com_extern.h 2002/07/05 21:15:25
@@ -152,12 +152,14 @@
int f_lines __P((SCR *, OPTION *, char *, u_long *));
int f_lisp __P((SCR *, OPTION *, char *, u_long *));
int f_msgcat __P((SCR *, OPTION *, char *, u_long *));
-int f_paragraph __P((SCR *, OPTION *, char *, u_long *));
int f_print __P((SCR *, OPTION *, char *, u_long *));
int f_readonly __P((SCR *, OPTION *, char *, u_long *));
int f_recompile __P((SCR *, OPTION *, char *, u_long *));
int f_reformat __P((SCR *, OPTION *, char *, u_long *));
-int f_section __P((SCR *, OPTION *, char *, u_long *));
+int f_tabadd __P((SCR *, OPTION *, char *, u_long *));
+int f_tabdel __P((SCR *, OPTION *, char *, u_long *));
+int f_tablist __P((SCR *, OPTION *, char *, u_long *));
+int f_tabstop __P((SCR *, OPTION *, char *, u_long *));
int f_ttywerase __P((SCR *, OPTION *, char *, u_long *));
int f_w300 __P((SCR *, OPTION *, char *, u_long *));
int f_w1200 __P((SCR *, OPTION *, char *, u_long *));
@@ -194,3 +196,4 @@
enum nresult nget_uslong __P((u_long *, const char *, char **, int));
enum nresult nget_slong __P((long *, const char *, char **, int));
void TRACE __P((SCR *, const char *, ...));
+size_t tab_off(SCR *, size_t);
Index: include/options_def.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/include/options_def.h,v
retrieving revision 1.4
diff -u -r1.4 options_def.h
--- options_def.h 2001/03/31 11:37:51 1.4
+++ options_def.h 2002/07/05 21:15:39
@@ -1,5 +1,3 @@
-/* $NetBSD: options_def.h,v 1.4 2001/03/31 11:37:51 aymeric Exp $ */
-
#define O_ALTWERASE 0
#define O_AUTOINDENT 1
#define O_AUTOPRINT 2
@@ -29,54 +27,58 @@
#define O_LIST 26
#define O_LOCKFILES 27
#define O_MAGIC 28
-#define O_MATCHTIME 29
-#define O_MESG 30
-#define O_MODELINE 31
-#define O_MSGCAT 32
-#define O_NOPRINT 33
-#define O_NUMBER 34
-#define O_OCTAL 35
-#define O_OPEN 36
-#define O_OPTIMIZE 37
-#define O_PARAGRAPHS 38
-#define O_PATH 39
-#define O_PRINT 40
-#define O_PROMPT 41
-#define O_READONLY 42
-#define O_RECDIR 43
-#define O_REDRAW 44
-#define O_REMAP 45
-#define O_REPORT 46
-#define O_RULER 47
-#define O_SCROLL 48
-#define O_SEARCHINCR 49
-#define O_SECTIONS 50
-#define O_SECURE 51
-#define O_SHELL 52
-#define O_SHELLMETA 53
-#define O_SHIFTWIDTH 54
-#define O_SHOWMATCH 55
-#define O_SHOWMODE 56
-#define O_SIDESCROLL 57
-#define O_SLOWOPEN 58
-#define O_SOURCEANY 59
-#define O_TABSTOP 60
-#define O_TAGLENGTH 61
-#define O_TAGS 62
-#define O_TERM 63
-#define O_TERSE 64
-#define O_TILDEOP 65
-#define O_TIMEOUT 66
-#define O_TTYWERASE 67
-#define O_VERBOSE 68
-#define O_W1200 69
-#define O_W300 70
-#define O_W9600 71
-#define O_WARN 72
-#define O_WINDOW 73
-#define O_WINDOWNAME 74
-#define O_WRAPLEN 75
-#define O_WRAPMARGIN 76
-#define O_WRAPSCAN 77
-#define O_WRITEANY 78
-#define O_OPTIONCOUNT 79
+#define O_MATCHCHARS 29
+#define O_MATCHTIME 30
+#define O_MESG 31
+#define O_MODELINE 32
+#define O_MSGCAT 33
+#define O_NOPRINT 34
+#define O_NUMBER 35
+#define O_OCTAL 36
+#define O_OPEN 37
+#define O_OPTIMIZE 38
+#define O_PARAGRAPHS 39
+#define O_PATH 40
+#define O_PRINT 41
+#define O_PROMPT 42
+#define O_READONLY 43
+#define O_RECDIR 44
+#define O_REDRAW 45
+#define O_REMAP 46
+#define O_REPORT 47
+#define O_RULER 48
+#define O_SCROLL 49
+#define O_SEARCHINCR 50
+#define O_SECTIONS 51
+#define O_SECURE 52
+#define O_SHELL 53
+#define O_SHELLMETA 54
+#define O_SHIFTWIDTH 55
+#define O_SHOWMATCH 56
+#define O_SHOWMODE 57
+#define O_SIDESCROLL 58
+#define O_SLOWOPEN 59
+#define O_SOURCEANY 60
+#define O_TABADD 61
+#define O_TABDEL 62
+#define O_TABLIST 63
+#define O_TABSTOP 64
+#define O_TAGLENGTH 65
+#define O_TAGS 66
+#define O_TERM 67
+#define O_TERSE 68
+#define O_TILDEOP 69
+#define O_TIMEOUT 70
+#define O_TTYWERASE 71
+#define O_VERBOSE 72
+#define O_W1200 73
+#define O_W300 74
+#define O_W9600 75
+#define O_WARN 76
+#define O_WINDOW 77
+#define O_WINDOWNAME 78
+#define O_WRAPLEN 79
+#define O_WRAPMARGIN 80
+#define O_WRAPSCAN 81
+#define O_WRITEANY 82
+#define O_OPTIONCOUNT 83
Index: vi/v_match.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/vi/v_match.c,v
retrieving revision 1.8
diff -u -r1.8 v_match.c
--- v_match.c 2002/04/09 01:47:35 1.8
+++ v_match.c 2002/07/05 21:15:43
@@ -48,7 +48,17 @@
size_t cno, len, off;
int cnt, isempty, matchc, startc, (*gc)__P((SCR *, VCS *));
char *p;
+ char *match_chars;
+ static int match_lno, match_col, match_dir;
+
+ /* Historically vi would match (), {} and [] however
+ an update included <>. This is ok for editing HTML
+ but a pain in the butt for C source.
+ Making it an option lets the user decide what is 'right'.
+ Also fixed to do something sensible with "". */
+ match_chars = O_STR( sp, O_MATCHCHARS );
+
/*
* !!!
* Historic practice; ignore the count.
@@ -63,48 +73,33 @@
return (1);
}
for (off = vp->m_start.cno;; ++off) {
+ char *cp;
if (off >= len) {
nomatch: msgq(sp, M_BERR, "184|No match character on this line");
return (1);
}
- switch (startc = p[off]) {
- case '(':
- matchc = ')';
- gc = cs_next;
- break;
- case ')':
- matchc = '(';
- gc = cs_prev;
- break;
- case '[':
- matchc = ']';
- gc = cs_next;
- break;
- case ']':
- matchc = '[';
- gc = cs_prev;
- break;
- case '{':
- matchc = '}';
- gc = cs_next;
- break;
- case '}':
- matchc = '{';
- gc = cs_prev;
- break;
- case '<':
- matchc = '>';
- gc = cs_next;
- break;
- case '>':
- matchc = '<';
- gc = cs_prev;
- break;
- default:
- continue;
- }
+ startc = p[off];
+ cp = strchr( match_chars, startc );
+ if (!cp)
+ continue;
+ cnt = cp - match_chars;
break;
}
+ matchc = match_chars[ cnt ^ 1 ];
+
+ /* Alternate back-forward search if startc and matchc the same */
+ if (startc == matchc) {
+ /* are we continuing from where last match finished? */
+ if (match_lno == vp->m_start.lno && match_col ==vp->m_start.cno)
+ /* yes - continue in sequence */
+ match_dir++;
+ else
+ /* no - go forward, back, back, forward */
+ match_dir = 1;
+ if (match_dir & 2)
+ cnt++;
+ }
+ gc = cnt & 1 ? cs_prev : cs_next;
cs.cs_lno = vp->m_start.lno;
cs.cs_cno = off;
@@ -118,10 +113,10 @@
break;
continue;
}
+ if (cs.cs_ch == matchc && --cnt == 0)
+ break;
if (cs.cs_ch == startc)
++cnt;
- else if (cs.cs_ch == matchc && --cnt == 0)
- break;
}
if (cnt) {
msgq(sp, M_BERR, "185|Matching character not found");
@@ -147,6 +142,9 @@
vp->m_final = ISMOTION(vp) ? vp->m_start : vp->m_stop;
else
vp->m_final = vp->m_stop;
+
+ match_lno = vp->m_final.lno;
+ match_col = vp->m_final.cno;
/*
* !!!
Index: vi/v_txt.c
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/vi/v_txt.c,v
retrieving revision 1.9
diff -u -r1.9 v_txt.c
--- v_txt.c 2002/04/09 01:47:36 1.9
+++ v_txt.c 2002/07/05 21:16:00
@@ -1698,9 +1698,9 @@
TEXT *tp;
int *changedp;
{
- u_long ts;
int del;
size_t cno, len, new, old, scno, spaces, tab_after_sp, tabs;
+ size_t nco;
char *p;
*changedp = 0;
@@ -1726,15 +1726,16 @@
* in the line are resolved into the minimum number of characters.
* Historic practice.
*/
- ts = O_VAL(sp, O_TABSTOP);
/* Figure out the last <blank> screen column. */
for (p = tp->lb, scno = 0, len = tp->len,
- spaces = tab_after_sp = 0; len-- && isblank(*p); ++p)
+ nco = spaces = tab_after_sp = 0; len-- && isblank(*p); ++p)
if (*p == '\t') {
if (spaces)
tab_after_sp = 1;
- scno += COL_OFF(scno, ts);
+ scno += tab_off(sp, scno);
+ /* get spaces to next tab stop... */
+ nco = tab_off(sp, scno);
} else {
++spaces;
++scno;
@@ -1742,14 +1743,14 @@
/*
* If there are no spaces, or no tabs after spaces and less than
- * ts spaces, it's already minimal.
+ * nco spaces, it's already minimal.
*/
- if (!spaces || !tab_after_sp && spaces < ts)
+ if (!spaces || !tab_after_sp && spaces < nco)
return;
/* Count up spaces/tabs needed to get to the target. */
- for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
- cno += COL_OFF(cno, ts);
+ for (cno = 0, tabs = 0; (nco = cno + tab_off(sp, cno)) <= scno; ++tabs)
+ cno = nco;
spaces = scno - cno;
/*
@@ -1922,11 +1923,11 @@
int isindent;
{
CHAR_T ch;
- u_long sw, ts;
+ u_long sw;
size_t cno, current, spaces, target, tabs;
+ size_t nco;
int ai_reset;
- ts = O_VAL(sp, O_TABSTOP);
sw = O_VAL(sp, O_SHIFTWIDTH);
/*
@@ -1947,7 +1948,7 @@
*/
for (current = cno = 0; cno < tp->cno; ++cno)
current += tp->lb[cno] == '\t' ?
- COL_OFF(current, ts) : KEY_LEN(sp, tp->lb[cno]);
+ tab_off(sp, current) : KEY_LEN(sp, tp->lb[cno]);
target = current;
if (isindent)
@@ -1977,7 +1978,7 @@
--tp->cno, ++tp->owrite);
for (current = cno = 0; cno < tp->cno; ++cno)
current += tp->lb[cno] == '\t' ?
- COL_OFF(current, ts) : KEY_LEN(sp, tp->lb[cno]);
+ tab_off(sp, current) : KEY_LEN(sp, tp->lb[cno]);
/*
* If we didn't move up to or past the target, it's because there
@@ -1995,8 +1996,8 @@
spaces = tabs = 0;
else {
for (cno = current,
- tabs = 0; cno + COL_OFF(cno, ts) <= target; ++tabs)
- cno += COL_OFF(cno, ts);
+ tabs = 0; (nco = cno + tab_off(sp, cno)) <= target; ++tabs)
+ cno = nco;
spaces = target - cno;
}
Index: vi/vi.h
===================================================================
RCS file: /cvsroot/basesrc/usr.bin/vi/vi/vi.h,v
retrieving revision 1.3
diff -u -r1.3 vi.h
--- vi.h 2001/03/31 11:37:52 1.3
+++ vi.h 2002/07/05 21:16:07
@@ -351,7 +351,7 @@
* positions when <esc> is entered. I believe that nvi does tabs correctly,
* but there are some historical incompatibilities.
*/
-#define TAB_OFF(c) COL_OFF((c), O_VAL(sp, O_TABSTOP))
+#define TAB_OFF(c) tab_off(sp, c)
/* If more than one screen being shown. */
#define IS_SPLIT(sp) \
>Release-Note:
>Audit-Trail:
>Unformatted: