[comp.bugs.4bsd] VI Wrapmargin Bug Fix

jack@cadre.dsl.PITTSBURGH.EDU (Jack Nelson) (07/23/89)

7-21-89
I think I have fixed the wrapmargin bug in which a non interactive
text insertion into the margin area leads to junk being inserted and
no proper wrap onto the next line.  This bug has been noted before with
no posted fixes (to my knowledge), and probably exists on all VI versions
before recent SYSV where it is fixed (at least on SYSV/386, release 3.2.1,
which I have available to test.  I have tested it as much as I can
with the things I do with VI, but it is a complex program, so test it
yourself as well.

Repeat By: put the next two lines into a file "wmtest"
+---------+---------+---------+---------+---------+---------+---------+---------
this is a 123456 1234567 line on the second line
Now:
  $ vi +'set wm=30' wmtest
    yank the first two words 'this is ' into a buffer
    move to the end of the line and then do a 'p'
You should hear beeping, but note that the second word 'is ' doesn't
move onto the second line as it should, but the ' is '
is compressed into 's':

this is a 123456 1234567 line on the second linethiss

Also note that you are left in
insert mode.  If you just yank one word, then repeat the put at
the end of the line, the trailing space gets eaten, and repeat
puts of the same word just pile up at the end with no spaces
between them.

Explanation:

    The stuff to be wrapped (after the space between the two words)
    in the wrap margin is macpush()'d in vgetline() in ex_vops2.c.
    The idea is that it should be restored on the next line.
    When a space is encountered in the wrap margin area, the newline
    and non-space characters which follow the space are macpush()'d,
    then a jump is made to the 'vbackup:' code section where the
    insert mode is turned off.  When the newline is seen as the
    next character, vgetline() exits back to vappend(), then
    control returns to vappend() and 'vinsrch()' is again made the
    output routine to turn on insert mode for insertion on the new line.
	This works well with type-in of text, but not with a 'p' or '.'
    commands.  In the latter cases, 'vglobp' is not NULL, and also
    with macpush()'d text the 'vmacp' also is not NULL.
    The bug comes into play during the next
    call to getkey(), if there is macpush()'d text
    waiting.  Getkey() calls getbr(), which in the original code
    pulls in 'vglobp' text in precedence to the 'vmacp' text
    using non-pushed text, and signals completion when it is done
    so that the macpush()'d '\n' is never seen; unless the 
    newline "escape" is seen, vgetline() can't
    exit back to vappend(); since the insert mode is not then
    turned on again until vappend() re-calls vappend(),
    the "doomed" 'vglobp' characters are interpreted 
    as command-mode input with the expected chaos resulting, the
    exact nature of which depends on the characters themselves,
    which is why the bug is so multiform and destructive.

Fix: move the 'vmacp' code in ex_vgets.c to have higher precedence
    than the 'vglobp' code, by putting it above it in the subroutine.
    One could also skip the 'vglobp' code if 'vmacp' not NULL, but
    I think these are equivalent.

*** orgs/ex_vget.c	Tue Feb 17 01:07:33 1987
--- ex_vget.c	Sat Jul 22 00:55:44 1989
***************
*** 94,105 ****
  		return (c);
  	}
  #endif
- 	if (vglobp) {
- 		if (*vglobp)
- 			return (lastvgk = *vglobp++);
- 		lastvgk = 0;
- 		return (ESCAPE);
- 	}
  	if (vmacp) {
  		if (*vmacp)
  			return(*vmacp++);
--- 94,99 ----
***************
*** 109,114 ****
--- 103,114 ----
  			vundkind = VMANY;
  		inopen = 1;	/* restore old setting now that macro done */
  		vch_mac = VC_NOTINMAC;
+ 	}
+ 	if (vglobp) {
+ 		if (*vglobp)
+ 			return (lastvgk = *vglobp++);
+ 		lastvgk = 0;
+ 		return (ESCAPE);
  	}
  	flusho();
  again:


UUCP: { akgua | allegra | cmcl2 | idis | ihnp4 | mi-cec | pitt |
	psuvax1 | sun | sunrise | vax135 } ! cadre ! nelslab ! jack
ARPA: jack@cadre.dsl.pitt.edu
John P. Nelson, M.D., 3811 O'Hara St, Pittsburgh, PA 15213, t:412-624-1769
Dept. of Psychiatry, U. of Pittsburgh
-- 
John P. Nelson, M.D., 3811 O'Hara St, Pittsburgh, PA 15213, t:412-624-1769 Dept. of Psychiatry, U. of Pittsburgh
UUCP: { akgua | allegra | cmcl2 | idis | ihnp4 | mi-cec | pitt | psuvax1 | sun | sunrise | vax135 } ! cadre ! jack
ARPA: jack@cadre.dsl.pitt.edu