changeset 6826:bf3e6012dfbd v7.4.734

patch 7.4.734 Problem: ml_get error when using "p" in a Visual selection in the last line. Solution: Change the behavior at the last line. (Yukihiro Nakadaira)
author Bram Moolenaar <bram@vim.org>
date Tue, 09 Jun 2015 20:20:03 +0200
parents e274ed6dd308
children d8903a6829f5
files src/normal.c src/ops.c src/testdir/test94.in src/testdir/test94.ok src/version.c
diffstat 5 files changed, 195 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/normal.c
+++ b/src/normal.c
@@ -1547,8 +1547,10 @@ do_pending_operator(cap, old_col, gui_ya
 	    }
 
 	    /* In Select mode, a linewise selection is operated upon like a
-	     * characterwise selection. */
-	    if (VIsual_select && VIsual_mode == 'V')
+	     * characterwise selection.
+	     * Special case: gH<Del> deletes the last line. */
+	    if (VIsual_select && VIsual_mode == 'V'
+					    && cap->oap->op_type != OP_DELETE)
 	    {
 		if (lt(VIsual, curwin->w_cursor))
 		{
@@ -1770,24 +1772,16 @@ do_pending_operator(cap, old_col, gui_ya
 		    oap->inclusive = FALSE;
 		    /* Try to include the newline, unless it's an operator
 		     * that works on lines only. */
-		    if (*p_sel != 'o' && !op_on_lines(oap->op_type))
+		    if (*p_sel != 'o'
+			    && !op_on_lines(oap->op_type)
+			    && oap->end.lnum < curbuf->b_ml.ml_line_count)
 		    {
-			if (oap->end.lnum < curbuf->b_ml.ml_line_count)
-			{
-			    ++oap->end.lnum;
-			    oap->end.col = 0;
+			++oap->end.lnum;
+			oap->end.col = 0;
 #ifdef FEAT_VIRTUALEDIT
-			    oap->end.coladd = 0;
-#endif
-			    ++oap->line_count;
-			}
-			else
-			{
-			    /* Cannot move below the last line, make the op
-			     * inclusive to tell the operation to include the
-			     * line break. */
-			    oap->inclusive = TRUE;
-			}
+			oap->end.coladd = 0;
+#endif
+			++oap->line_count;
 		    }
 		}
 	    }
--- a/src/ops.c
+++ b/src/ops.c
@@ -1959,60 +1959,31 @@ op_delete(oap)
 		    curwin->w_cursor.coladd = 0;
 	    }
 #endif
-	    if (oap->op_type == OP_DELETE
-		    && oap->inclusive
-		    && oap->end.lnum == curbuf->b_ml.ml_line_count
-		    && n > (int)STRLEN(ml_get(oap->end.lnum)))
-	    {
-		/* Special case: gH<Del> deletes the last line. */
-		del_lines(1L, FALSE);
-	    }
-	    else
-	    {
-		(void)del_bytes((long)n, !virtual_op,
-				oap->op_type == OP_DELETE && !oap->is_VIsual);
-	    }
+	    (void)del_bytes((long)n, !virtual_op,
+			    oap->op_type == OP_DELETE && !oap->is_VIsual);
 	}
 	else				/* delete characters between lines */
 	{
 	    pos_T   curpos;
-	    int     delete_last_line;
 
 	    /* save deleted and changed lines for undo */
 	    if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
 		 (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
 		return FAIL;
 
-	    delete_last_line = (oap->end.lnum == curbuf->b_ml.ml_line_count);
 	    truncate_line(TRUE);	/* delete from cursor to end of line */
 
 	    curpos = curwin->w_cursor;	/* remember curwin->w_cursor */
 	    ++curwin->w_cursor.lnum;
 	    del_lines((long)(oap->line_count - 2), FALSE);
 
-	    if (delete_last_line)
-		oap->end.lnum = curbuf->b_ml.ml_line_count;
-
+	    /* delete from start of line until op_end */
 	    n = (oap->end.col + 1 - !oap->inclusive);
-	    if (oap->inclusive && delete_last_line
-		    && n > (int)STRLEN(ml_get(oap->end.lnum)))
-	    {
-		/* Special case: gH<Del> deletes the last line. */
-		del_lines(1L, FALSE);
-		curwin->w_cursor = curpos;	/* restore curwin->w_cursor */
-		if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
-		    curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
-	    }
-	    else
-	    {
-		/* delete from start of line until op_end */
-		curwin->w_cursor.col = 0;
-		(void)del_bytes((long)n, !virtual_op,
-				oap->op_type == OP_DELETE && !oap->is_VIsual);
-		curwin->w_cursor = curpos;	/* restore curwin->w_cursor */
-	    }
-	    if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
-		(void)do_join(2, FALSE, FALSE, FALSE, FALSE);
+	    curwin->w_cursor.col = 0;
+	    (void)del_bytes((long)n, !virtual_op,
+			    oap->op_type == OP_DELETE && !oap->is_VIsual);
+	    curwin->w_cursor = curpos;	/* restore curwin->w_cursor */
+	    (void)do_join(2, FALSE, FALSE, FALSE, FALSE);
 	}
     }
 
--- a/src/testdir/test94.in
+++ b/src/testdir/test94.in
@@ -64,6 +64,116 @@ dV:
dv:
:set noma | let v:errmsg = ''
 d:
:set ma | put = v:errmsg =~# '^E21' ? 'ok' : 'failed'
 dv:dV::set noma | let v:errmsg = ''
 d::set ma | put = v:errmsg =~# '^E21' ? 'failed' : 'ok'
+:
+:$put =''
+:$put ='characterwise visual mode: replace last line'
+:$put ='a'
+:let @" = 'x'
+:let v:errmsg = ''
+v$p
+:$put ='---'
+:$put ='v:errmsg='.v:errmsg
+:
+:$put =''
+:$put ='characterwise visual mode: delete middle line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkv$d
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise visual mode: delete middle two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkvj$d
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise visual mode: delete last line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+v$d
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise visual mode: delete last two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kvj$d
+:$put ='---'
+:
+:" Select mode maps
+:snoremap <lt>End> <End>
+:snoremap <lt>Down> <Down>
+:snoremap <lt>Del> <Del>
+:
+:$put =''
+:$put ='characterwise select mode: delete middle line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkgh<End><Del>
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise select mode: delete middle two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkgh<Down><End><Del>
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise select mode: delete last line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+gh<End><Del>
+:$put ='---'
+:
+:$put =''
+:$put ='characterwise select mode: delete last two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kgh<Down><End><Del>
+:$put ='---'
+:
+:$put =''
+:$put ='linewise select mode: delete middle line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkgH<Del>
+:$put ='---'
+:
+:$put =''
+:$put ='linewise select mode: delete middle two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kkgH<Down><Del>
+:$put ='---'
+:
+:$put =''
+:$put ='linewise select mode: delete last line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+gH<Del>
+:$put ='---'
+:
+:$put =''
+:$put ='linewise select mode: delete last two line'
+:$put ='a'
+:$put ='b'
+:$put ='c'
+kgH<Down><Del>
+:$put ='---'
 :/^start:/+2,$w! test.out
 :q!
 ENDTEST
--- a/src/testdir/test94.ok
+++ b/src/testdir/test94.ok
@@ -18,3 +18,66 @@ LemonNewNewZ
 zzz
 ok
 ok
+
+characterwise visual mode: replace last line
+x
+---
+v:errmsg=
+
+characterwise visual mode: delete middle line
+b
+c
+---
+
+characterwise visual mode: delete middle two line
+c
+---
+
+characterwise visual mode: delete last line
+a
+b
+
+---
+
+characterwise visual mode: delete last two line
+a
+
+---
+
+characterwise select mode: delete middle line
+b
+c
+---
+
+characterwise select mode: delete middle two line
+c
+---
+
+characterwise select mode: delete last line
+a
+b
+
+---
+
+characterwise select mode: delete last two line
+a
+
+---
+
+linewise select mode: delete middle line
+b
+c
+---
+
+linewise select mode: delete middle two line
+c
+---
+
+linewise select mode: delete last line
+a
+b
+---
+
+linewise select mode: delete last two line
+a
+---
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    734,
+/**/
     733,
 /**/
     732,