changeset 3806:38a133f54518

6459238 UNIX98/UNIX03: *vsc* vi 'C' and 'S' commands are failing in suite version 5.2.8 6481990 UNIX98/UNIX03: *vsc* vi '<count>r<return>' does not insert enough new lines 6491931 UNIX03/UNIX98: *vsc* vi insert mode alters auto-indent characters
author cf46844
date Mon, 12 Mar 2007 21:00:37 -0700
parents 8ef866880810
children c02340118a61
files usr/src/cmd/vi/port/ex_vis.h usr/src/cmd/vi/port/ex_vmain.c usr/src/cmd/vi/port/ex_vops.c usr/src/cmd/vi/port/ex_vops2.c
diffstat 4 files changed, 232 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/vi/port/ex_vis.h	Mon Mar 12 17:29:09 2007 -0700
+++ b/usr/src/cmd/vi/port/ex_vis.h	Mon Mar 12 21:00:37 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -300,7 +299,9 @@
 /*
  * Function types
  */
+int	any();
 int	beep();
+void	fixundo(void);
 int	qcount();
 int	vchange(unsigned char);
 int	vdelete(unsigned char);
--- a/usr/src/cmd/vi/port/ex_vmain.c	Mon Mar 12 17:29:09 2007 -0700
+++ b/usr/src/cmd/vi/port/ex_vmain.c	Mon Mar 12 21:00:37 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -58,6 +57,9 @@
 
 extern int windowchg;
 extern int sigok;
+#ifdef XPG6
+int redisplay;	/* XPG6 assertion 313 [count]r\n :  Also used in ex_vops2.c */
+#endif
 void redraw(), windowinit();
 
 #ifdef XPG4
@@ -149,6 +151,13 @@
 		} else if(windowchg)
 			redraw();
 
+#ifdef XPG6
+		if (redisplay) {
+			/* XPG6 assertion 313 & 254 : after [count]r\n */
+			fixdisplay();
+		}
+		redisplay = 0;
+#endif
 		/*
 		 * Gobble up counts and named buffer specifications.
 		 */
@@ -1355,7 +1364,17 @@
 	inglobal = oing;
 	if (FIXUNDO)
 		vundkind = VMANY;
-	vmcurs = 0;
+	/*
+	 * XPG6 assertion 273: For the following commands, don't set vmcurs
+	 * to 0, so that undo positions the cursor column correctly when
+	 * we've moved off the initial line that was changed eg. when G has
+	 * moved us off the line, or when a multi-line change was done.
+	 */
+	if (lastcmd[0] != 'C' && lastcmd[0] != 'c' && lastcmd[0] != 'o' &&
+	    lastcmd[0] != 'R' && lastcmd[0] != 'S' && lastcmd[0] != 's' &&
+	    lastcmd[0] != 'i' && lastcmd[0] != 'a' && lastcmd[0] != 'A') {
+		vmcurs = 0;
+	}
 }
 
 /*
--- a/usr/src/cmd/vi/port/ex_vops.c	Mon Mar 12 17:29:09 2007 -0700
+++ b/usr/src/cmd/vi/port/ex_vops.c	Mon Mar 12 21:00:37 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,6 +35,8 @@
 #include "ex_tty.h"
 #include "ex_vis.h"
 
+void fixundo(void);
+
 /*
  * This file defines the operation sequences which interface the
  * logical changes to the file buffer with the internal and external
@@ -319,8 +320,18 @@
 void
 vnoapp(void)
 {
-
 	vUD1 = vUD2 = cursor;
+	/*
+	 * XPG6 assertion 273: Set vmcurs so that undo positions the
+	 * cursor column correctly when we've moved off the initial
+	 * line that was changed with the A, a, i, and R commands,
+	 * eg: when G has moved us off the line, or when a
+	 * multi-line change was done.
+	 */
+	if (lastcmd[0] == 'A' || lastcmd[0] == 'a' || lastcmd[0] == 'i' ||
+	    lastcmd[0] == 'R') {
+		vmcurs = cursor;
+	}
 }
 
 /*
@@ -588,6 +599,11 @@
 		 * after a S command.
 		 */
 		if (ind >= 0) {
+			/*
+			 * XPG6 assertion 273: Set vmcurs so that cursor
+			 * column will be set by undo.
+			 */
+			fixundo();
 			*genindent(ind) = 0;
 			vdoappend(genbuf);
 		} else {
@@ -620,10 +636,22 @@
 		if (c != 'd') {
 			if (ind >= 0) {
 				cursor = linebuf;
+				/*
+				 * XPG6 assertion 273: Set vmcurs so that
+				 * cursor column will be set by undo.  When
+				 * undo is preceded by 'S' or 'O' command,
+				 * white space isn't skipped in vnline(vmcurs).
+				 */
+				fixundo();
 				linebuf[0] = 0;
 				vfixcurs();
 			} else {
 				ind = 0;
+				/*
+				 * XPG6 assertion 273: Set vmcurs so that
+				 * cursor column will be set by undo.
+				 */
+				fixundo();
 				vcursat(cursor);
 			}
 			vappend('x', 1, ind);
@@ -670,6 +698,11 @@
 	cursor = cp;
 	setDEL();
 	CP(cursor, wcursor);
+	/*
+	 * XPG6 assertion 273: Set vmcurs so that cursor column will be
+	 * set by undo.
+	 */
+	fixundo();
 	if (state != HARDOPEN) {
 		/* place cursor at beginning of changing text */
 		vgotoCL(lcolumn(cp));
@@ -741,6 +774,12 @@
 	else
 		vsync1(LINE(vcline));
 	cursor = linebuf;
+	/*
+	 * XPG6 assertion 273: Set vmcurs so that cursor column will be
+	 * set by undo.  For undo preceded by 'o' command, white space
+	 * isn't skipped in vnline(vmcurs).
+	 */
+	fixundo();
 	linebuf[0] = 0;
 	vappend('o', cnt, ind);
 }
@@ -897,7 +936,8 @@
 	 *			necessitating some optimization.
 	 */
 	vreg = 0;
-	if (any(op, "cd")) {
+	/* XPG6 assertion 194 and 264: use numeric buffers for 'C' and 'S' */
+	if (any(op, (unsigned char *)"cdCS")) {
 		vremote(cnt, YANKreg, '1');
 /*
 		if (notp)
@@ -928,6 +968,7 @@
 	int i, c;
 	unsigned char *endcurs;
 	endcurs = cursor;
+	/* point endcurs to last char entered */
 	for(i = 1; i <= cnt; i++) {
 		if(!*endcurs) {
 			(void) beep();
@@ -950,6 +991,7 @@
 	else
 		vshowmode(gettext("REPLACE 1 CHAR"));
 	if (!vglobp) {
+		/* get a key using getkey() */
 		c = getesc();
 		if (c == 0) {
 			vshowmode("");
@@ -964,6 +1006,7 @@
 	wcursor = endcurs;
 	vUD1 = cursor; vUD2 = wcursor;
 	CP(cursor, wcursor);
+	/* before appending lines, set addr1 and undo information */
 	prepapp();
 	vappend('r', cnt, 0);
 	*lastcp++ = INS[0];
@@ -1024,3 +1067,16 @@
 		pkill[1] = wcursor;
 	}
 }
+
+/*
+ * XPG6 assertion 273 : If the command is C, c, o, R, S, or s, set vmcurs
+ * so that the cursor column will be set by undo.
+ */
+void
+fixundo(void)
+{
+	if (lastcmd[0] == 'C' || lastcmd[0] == 'c' || lastcmd[0] == 'o' ||
+	    lastcmd[0] == 'R' || lastcmd[0] == 'S' || lastcmd[0] == 's') {
+		vmcurs = cursor;
+	}
+}
--- a/usr/src/cmd/vi/port/ex_vops2.c	Mon Mar 12 17:29:09 2007 -0700
+++ b/usr/src/cmd/vi/port/ex_vops2.c	Mon Mar 12 21:00:37 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,10 +55,18 @@
 extern unsigned char	*vUA1, *vUA2;		/* extern; also in ex_vops.c */
 extern unsigned char	*vUD1, *vUD2;		/* extern; also in ex_vops.c */
 
+#ifdef XPG6
+/* XPG6 assertion 313 & 254 [count]r\n :  Also used in ex_vmain.c */
+extern int redisplay;
+#endif
+
 int vmaxrep(unsigned char, int);
 static void imultlinerep(int, line *, int, int);
 static void omultlinerep(int, line *, int);
-static void fixdisplay(void);
+#ifdef XPG6
+static void rmultlinerep(int, int);
+#endif
+void fixdisplay(void);
 
 /*
  * Obleeperate characters in hardcopy
@@ -92,6 +99,14 @@
 	if (wcursor < cursor)
 		cp = wcursor, wcursor = cursor, cursor = cp;
 	vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
+	/*
+	 * XPG6 assertion 273: Set vmcurs so that undo positions the
+	 * cursor column correctly when we've moved off the initial line
+	 * that was changed, as with the C, c, and s commands,
+	 * when G has moved us off the line, or when a
+	 * multi-line change was done.
+	 */
+	fixundo();
 	return (lcolumn(wcursor));
 }
 
@@ -207,6 +222,10 @@
 		(void) vmove();
 		*gcursor = i;
 	}
+	/*
+	 * If vrep() passed indent = 0, this is the 'r' command,
+	 * so don't autoindent until the last char.
+	 */
 	vaifirst = indent == 0;
 
 	/*
@@ -402,11 +421,23 @@
 			escape = 0;
 		else {
 			ixlatctl(1);
+			/*
+			 * When vgetline() returns, gcursor is
+			 * pointing to '\0' and vgetline() has
+			 * read an ESCAPE or NL.
+			 */
 			gcursor = vgetline(repcnt, gcursor, &escape, ch);
-
-			/* vgetline() only returns when it got ESCAPE or NL */
 			if (escape == '\n') {
 				gotNL = 1;
+#ifdef XPG6
+				if (ch == 'r') {
+					/*
+					 * XPG6 assertion 313 [count]r\n :
+					 * Arrange to set cursor correctly.
+					 */
+					endsrccol = gcursor - genbuf - 1;
+				}
+#endif /* XPG6 */
 			} else {
 				/*
 				 * Upon escape, gcursor is pointing to '\0'
@@ -442,7 +473,7 @@
 		/*
 		 * Smash the generated and preexisting indents together
 		 * and generate one cleanly made out of tabs and spaces
-		 * if we are using autoindent.
+		 * if we are using autoindent and this isn't 'r' command.
 		 */
 		if (!vaifirst && value(vi_AUTOINDENT)) {
 			i = fixindent(indent);
@@ -468,8 +499,18 @@
 		 * in linebuf.
 		 */
 		cnt = vmaxrep(ch, cnt);
+		/*
+		 * cursor points to linebuf
+		 * Copy remaining old text (cursor) in original
+		 * line to after new text (gcursor + 1) in genbuf.
+		 */
 		CP(gcursor + 1, cursor);
+		/*
+		 * For [count] r \n command, when replacing [count] chars
+		 * with '\n', this loop replaces [count] chars with "".
+		 */
 		do {
+			/* cp new text (genbuf) into linebuf (cursor) */
 			CP(cursor, genbuf);
 			if (cnt > 1) {
 				int oldhold = hold;
@@ -480,16 +521,19 @@
 				hold = oldhold;
 				Outchar = vputchar;
 			}
+			/* point cursor after new text in linebuf */
 			cursor += gcursor - genbuf;
 		} while (--cnt > 0);
 		endim();
 		vUA2 = cursor;
+		/* add the remaining old text after the cursor */
 		if (escape != '\n')
 			CP(cursor, gcursor + 1);
 
 		/*
 		 * If doomed characters remain, clobber them,
 		 * and reopen the line to get the display exact.
+		 * eg. c$ to change to end of line
 		 */
 		if (state != HARDOPEN) {
 			DEPTH(vcline) = 0;
@@ -514,7 +558,9 @@
 		}
 
 		/*
-		 * All done unless we are continuing on to another line.
+		 * Unless we are continuing on to another line
+		 * (got a NL), break out of the for loop (got
+		 * an ESCAPE).
 		 */
 		if (escape != '\n') {
 			vshowmode("");
@@ -529,6 +575,7 @@
 		 */
 		killU();
 		addtext(gobblebl ? " " : "\n");
+		/* save vutmp (for undo state) into temp file */
 		vsave();
 		cnt = 1;
 		if (value(vi_AUTOINDENT)) {
@@ -545,6 +592,11 @@
 				gcursor = genbuf;
 			CP(gcursor, linebuf);
 		} else {
+			/*
+			 * Put gcursor at start of genbuf to wipe
+			 * out previous line in preparation for
+			 * the next vgetline() loop.
+			 */
 			CP(genbuf, gcursor + 1);
 			gcursor = genbuf;
 		}
@@ -562,7 +614,8 @@
 
 		/*
 		 * Now do the append of the new line in the buffer,
-		 * and update the display.  If slowopen
+		 * and update the display, ie: append genbuf to
+		 * the file after dot.  If slowopen
 		 * we don't do very much.
 		 */
 		vdoappend(genbuf);
@@ -631,6 +684,7 @@
 			}
 		}
 		strcLIN(gcursor);
+		/* zero genbuf */
 		*gcursor = 0;
 		cursor = linebuf;
 		vgotoCL(nqcolumn(cursor - 1, genbuf));
@@ -640,6 +694,15 @@
 		imultlinerep(savecnt, startsrcline, startsrccol, endsrccol);
 	} else if (omultlinecnt) {
 		omultlinerep(savecnt, startsrcline, endsrccol);
+#ifdef XPG6
+	} else if (savecnt > 1 && ch == 'r' && gotNL) {
+		/*
+		 * XPG6 assertion 313 & 254 : Position cursor for [count]r\n
+		 * then insert [count -1] newlines.
+		 */
+		endsrccol = gcursor - genbuf - 1;
+		rmultlinerep(savecnt, endsrccol);
+#endif /* XPG6 */
 	}
 
 	/*
@@ -649,8 +712,32 @@
 	hold = oldhold;
 	if ((imultlinecnt && gotNL) || omultlinecnt) {
 		fixdisplay();
+#ifdef XPG6
+	} else if (savecnt > 1 && ch == 'r' && gotNL) {
+		fixdisplay();
+		/*
+		 * XPG6 assertion 313 & 254 [count]r\n : Set flag to call
+		 * fixdisplay() after operate() has finished.  To be sure that
+		 * the text (after the last \n followed by an indent) is always
+		 * displayed, fixdisplay() is called right before getting
+		 * the next command.
+		 */
+		redisplay = 1;
+#endif /* XPG6 */
 	} else if (cursor > linebuf) {
 		cursor = lastchr(linebuf, cursor);
+#ifdef XPG6
+		/*
+		 * XPG6 assertion 313 & 254 [count]r\n :
+		 * For 'r' command, when the replacement char causes new
+		 * lines to be created, point cursor to first non-blank.
+		 * The old code, ie: cursor = lastchr(linebuf, cursor);
+		 * set cursor to the blank before the first non-blank
+		 * for r\n
+		 */
+		if (ch == 'r' && gotNL && isblank((int)*cursor))
+			++cursor;
+#endif /* XPG6 */
 	}
 	if (state != HARDOPEN)
 		vsyncCL();
@@ -763,12 +850,55 @@
 	cursor = linebuf + endsrccol;
 }
 
+#ifdef XPG6
+/*
+ * XPG6 assertion 313 & 254 : To repeat '\n' for [count]r\n
+ * insert '\n' savecnt-1 more times before the already added '\n'.
+ */
+
+static void
+rmultlinerep(int savecnt, int endsrccol)
+{
+	int tmpcnt = 2;	/* 1st replacement counts as 1 repeat */
+
+	/* Save linebuf into temp file before moving off the line. */
+	vsave();
+	/*
+	 * At this point the temp file contains the line followed by '\n',
+	 * which is preceded by indentation if autoindent is set.
+	 * '\n' must be repeated [savecnt - 1] more times in the temp file.
+	 * dot is the current line containing the '\n'.  Decrement dot so that
+	 * vdoappend() will append each '\n' before the current '\n'.
+	 * This will allow only the last line to contain any autoindent
+	 * characters.
+	 */
+	--dot;
+	--vcline;
+
+	/*
+	 * Append after dot.
+	 */
+	while (tmpcnt <= savecnt) {
+		linebuf[0] = '\0';
+		/* append linebuf below current line in temp file */
+		vdoappend(linebuf);
+		vcline++;
+		++tmpcnt;
+	}
+	/* set the current line to the line after the last '\n' */
+	++dot;
+	++vcline;
+	/* point cursor after (linebuf + endsrccol) */
+	vcursaft(linebuf + endsrccol);
+}
+#endif /* XPG6 */
+
 /*
  * Similiar to a ctrl-l, however always vrepaint() in case the last line
  * of the repeat would exceed the bottom of the screen.
  */
 
-static void
+void
 fixdisplay(void)
 {
 	vclear();