Subject: lib/18103: libedit doesn't get word boundaries right in vi mode
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dsl@l8s.co.uk>
List: netbsd-bugs
Date: 08/29/2002 14:18:25
>Number:         18103
>Category:       lib
>Synopsis:       libedit doesn't get word boundaries right in vi mode
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Aug 29 06:16:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     David Laight
>Release:        NetBSD 1.6F
>Organization:
no
>Environment:
System: NetBSD snowdrop 1.6F NetBSD 1.6F (GENERIC) #161: Tue Aug 27 10:39:43 BST 2002
dsl@snowdrop:/oldroot/usr/bsd-current/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
	libedit (used for command editing in sh) doesn't get the following
	right:
	1) c2w	- miscounts words
	2) E	- treated as e
	3) c2b	- count ignored
>How-To-Repeat:
	Play with sh after 'set -o vi'
>Fix:
	Apply following changes

Index: chared.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/chared.c,v
retrieving revision 1.15
diff -u -r1.15 chared.c
--- chared.c	2002/03/18 16:00:50	1.15
+++ chared.c	2002/08/29 13:09:46
@@ -221,7 +221,7 @@
 		 * vi historically deletes with cw only the word preserving the
 		 * trailing whitespace! This is not what 'w' does..
 		 */
-		if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+		if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
 			while ((p < high) && isspace((unsigned char) *p))
 				p++;
 	}
@@ -238,26 +238,19 @@
  *	Find the previous word vi style
  */
 protected char *
-cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
+cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
 {
 	int test;
 
+	p--;
 	while (n--) {
-		p--;
-		/*
-		 * vi historically deletes with cb only the word preserving the
-		 * leading whitespace! This is not what 'b' does..
-		 */
-		if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
-			while ((p > low) && isspace((unsigned char) *p))
-				p--;
+		while ((p > low) && isspace((unsigned char) *p))
+			p--;
 		test = (*wtest)((unsigned char) *p);
 		while ((p >= low) && (*wtest)((unsigned char) *p) == test)
 			p--;
-		p++;
-		while (isspace((unsigned char) *p))
-			p++;
 	}
+	p++;
 
 	/* p now points where we want it */
 	if (p < low)
@@ -378,21 +371,19 @@
  *	Go to the end of this word according to vi
  */
 protected char *
-cv__endword(char *p, char *high, int n)
+cv__endword(char *p, char *high, int n, int (*wtest)(int))
 {
+	int test;
+
 	p++;
 
 	while (n--) {
 		while ((p < high) && isspace((unsigned char) *p))
 			p++;
 
-		if (isalnum((unsigned char) *p))
-			while ((p < high) && isalnum((unsigned char) *p))
-				p++;
-		else
-			while ((p < high) && !(isspace((unsigned char) *p) ||
-			    isalnum((unsigned char) *p)))
-				p++;
+		test = (*wtest)((unsigned char) *p);
+		while ((p < high) && (*wtest)((unsigned char) *p) == test)
+			p++;
 	}
 	p--;
 	return (p);
Index: chared.h
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/chared.h,v
retrieving revision 1.8
diff -u -r1.8 chared.h
--- chared.h	2002/03/18 16:00:51	1.8
+++ chared.h	2002/08/29 13:09:47
@@ -138,11 +138,11 @@
 
 protected int	 cv__isword(int);
 protected void	 cv_delfini(EditLine *);
-protected char	*cv__endword(char *, char *, int);
+protected char	*cv__endword(char *, char *, int, int (*)(int));
 protected int	 ce__isword(int);
 protected void	 cv_undo(EditLine *, int, size_t, char *);
 protected char	*cv_next_word(EditLine*, char *, char *, int, int (*)(int));
-protected char	*cv_prev_word(EditLine*, char *, char *, int, int (*)(int));
+protected char	*cv_prev_word(char *, char *, int, int (*)(int));
 protected char	*c__next_word(char *, char *, int, int (*)(int));
 protected char	*c__prev_word(char *, char *, int, int (*)(int));
 protected void	 c_insert(EditLine *, int);
Index: vi.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/vi.c,v
retrieving revision 1.9
diff -u -r1.9 vi.c
--- vi.c	2002/03/18 16:01:01	1.9
+++ vi.c	2002/08/29 13:09:49
@@ -170,7 +170,7 @@
 	if (el->el_line.cursor == el->el_line.buffer)
 		return (CC_ERROR);
 
-	el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 	    el->el_line.buffer,
 	    el->el_state.argument,
 	    cv__isword);
@@ -185,7 +185,7 @@
 
 /* vi_prev_word():
  *	Vi move to the previous word
- *	[B]
+ *	[b]
  */
 protected el_action_t
 /*ARGSUSED*/
@@ -195,7 +195,7 @@
 	if (el->el_line.cursor == el->el_line.buffer)
 		return (CC_ERROR);
 
-	el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+	el->el_line.cursor = cv_prev_word(el->el_line.cursor,
 	    el->el_line.buffer,
 	    el->el_state.argument,
 	    ce__isword);
@@ -495,7 +495,7 @@
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv__endword(el->el_line.cursor,
-	    el->el_line.lastchar, el->el_state.argument);
+	    el->el_line.lastchar, el->el_state.argument, ce__isword);
 
 	if (el->el_chared.c_vcmd.action & DELETE) {
 		el->el_line.cursor++;
@@ -519,7 +519,7 @@
 		return (CC_ERROR);
 
 	el->el_line.cursor = cv__endword(el->el_line.cursor,
-	    el->el_line.lastchar, el->el_state.argument);
+	    el->el_line.lastchar, el->el_state.argument, cv__isword);
 
 	if (el->el_chared.c_vcmd.action & DELETE) {
 		el->el_line.cursor++;
>Release-Note:
>Audit-Trail:
>Unformatted: