On 08/08/2013 23:51, tooth pik wrote:
On Thu, Aug 08, 2013 at 04:14:08PM -0400, Manuel Ortega wrote:
There is a horrendous bug wrt the 'g~' operator.  I've found it on OSX
10.8.4.  Doesn't matter whether it's MacVim 7.4b or Vim 7.4b.18.

To reproduce:  Make a new file with three lines:

-----------------
a

b
-----------------

(The middle line is empty, and there's no trailing whitespace after a or
b).  Now from the terminal do vim -N -u NONE -U NONE thefile.

With the cursor on the first column of the first line, do: g~ap

Observe that the first line is now "A", and the third line starts with "b".

Now do :redraw!, and observe that the third line suddenly is "B".

That's not how 'ap' is supposed to work, AFAIK.

It gets much worse, though!  Now hit 'u' to undo the surprising
capitalization.  Observe that "A" returns to "a", but that "B" does NOT
return to 'b'.

So not only is the motion 'ap' messed up, but the undo history is botched
and the original state is unrecoverable with 'u', *and* the change made to
'b' is for some reason not even shown on the screen right away.  Triple
threat.

I can confirm the same weirdness happens with version 7.4b.19 in
opensuse linux.

Ditto Win7 x64, but it does not happen with -u NONE -U NONE. A little experimentation shows it is encoding related, start gvim with:

gvim -u NONE -U NONE -c "set encoding=utf-8"

and the observed behaviour happens again. So the difference is between single and multi-byte buffer encodings. Ah, an off by one in the other direction ;-)

The bug is in swapchars() - mb_ptr2len() returns 0 for a NUL resulting in todo being increased by 1 causing a swap of one more byte than it should. Fixed with this patch:

diff --git a/src/ops.c b/src/ops.c
--- a/src/ops.c
+++ b/src/ops.c
@@ -2429,8 +2429,12 @@ swapchars(op_type, pos, length)
     {
 # ifdef FEAT_MBYTE
        if (has_mbyte)
+        {
            /* we're counting bytes, not characters */
-           todo -= (*mb_ptr2len)(ml_get_pos(pos)) - 1;
+            int len = (*mb_ptr2len)(ml_get_pos(pos));
+            if (len)
+                todo -= len - 1;
+        }
 # endif
        did_change |= swapchar(op_type, pos);
        if (inc(pos) == -1)    /* at end of file */

Mike
--
Errors have been made. Others will be blamed.

--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- You received this message because you are subscribed to the Google Groups "vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Raspunde prin e-mail lui