Patch 7.4.1087
Problem: CTRL-A and CTRL-X do not work properly with blockwise visual
selection if there is a mix of Tab and spaces.
Solution: Add OP_NR_ADD and OP_NR_SUB. (Hirohito Higashi)
Files: src/testdir/test_increment.vim, src/normal.c, src/ops.c,
src/proto/ops.pro, src/vim.h
*** ../vim-7.4.1086/src/testdir/test_increment.vim 2016-01-10
20:07:57.981777388 +0100
--- src/testdir/test_increment.vim 2016-01-10 22:10:30.953675403 +0100
***************
*** 133,139 ****
exec "norm! vf-\<C-A>"
call assert_equal(["foobar-10"], getline(1, '$'))
" NOTE: I think this is correct behavior...
! "call assert_equal([0, 1, 1, 0], getpos('.'))
endfunc
" 5) g<Ctrl-A> on letter
--- 133,139 ----
exec "norm! vf-\<C-A>"
call assert_equal(["foobar-10"], getline(1, '$'))
" NOTE: I think this is correct behavior...
! call assert_equal([0, 1, 1, 0], getpos('.'))
endfunc
" 5) g<Ctrl-A> on letter
***************
*** 576,582 ****
endif
endfunc
! " 28) block-wise increment and dot-repeat
" Text:
" 1 23
" 4 56
--- 576,686 ----
endif
endfunc
! " Tab code and linewise-visual inc/dec
! func Test_visual_increment_28()
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! Vj\<C-A>"
! call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
!
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! ggVj\<C-X>"
! call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
! endfunc
!
! " Tab code and linewise-visual inc/dec with 'nrformats'+=alpha
! func Test_visual_increment_29()
! set nrformats+=alpha
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! Vj\<C-A>"
! call assert_equal(["y\<TAB>10", "\<TAB>0"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
!
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! ggVj\<C-X>"
! call assert_equal(["w\<TAB>10", "\<TAB>-2"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
! endfunc
!
! " Tab code and character-visual inc/dec
! func Test_visual_increment_30()
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! f1vjf1\<C-A>"
! call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
! call assert_equal([0, 1, 3, 0], getpos('.'))
!
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! ggf1vjf1\<C-X>"
! call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
! call assert_equal([0, 1, 3, 0], getpos('.'))
! endfunc
!
! " Tab code and blockwise-visual inc/dec
! func Test_visual_increment_31()
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! f1\<C-V>jl\<C-A>"
! call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
! call assert_equal([0, 1, 3, 0], getpos('.'))
!
! call setline(1, ["x\<TAB>10", "\<TAB>-1"])
! exec "norm! ggf1\<C-V>jl\<C-X>"
! call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
! call assert_equal([0, 1, 3, 0], getpos('.'))
! endfunc
!
! " Tab code and blockwise-visual decrement with 'linebreak' and 'showbreak'
! func Test_visual_increment_32()
! 28vnew dummy_31
! set linebreak showbreak=+
! call setline(1, ["x\<TAB>\<TAB>\<TAB>10", "\<TAB>\<TAB>\<TAB>\<TAB>-1"])
! exec "norm! ggf0\<C-V>jg_\<C-X>"
! call assert_equal(["x\<TAB>\<TAB>\<TAB>1-1", "\<TAB>\<TAB>\<TAB>\<TAB>-2"],
getline(1, '$'))
! call assert_equal([0, 1, 6, 0], getpos('.'))
! bwipe!
! endfunc
!
! " Tab code and blockwise-visual increment with $
! func Test_visual_increment_33()
! call setline(1, ["\<TAB>123", "456"])
! exec "norm! gg0\<C-V>j$\<C-A>"
! call assert_equal(["\<TAB>124", "457"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
! endfunc
!
! " Tab code and blockwise-visual increment and redo
! func Test_visual_increment_34()
! call setline(1, ["\<TAB>123", " 456789"])
! exec "norm! gg0\<C-V>j\<C-A>"
! call assert_equal(["\<TAB>123", " 457789"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
!
! exec "norm! .."
! call assert_equal(["\<TAB>123", " 459789"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
! endfunc
!
! " Tab code, spaces and character-visual increment and redo
! func Test_visual_increment_35()
! call setline(1, ["\<TAB>123", " 123", "\<TAB>123", "\<TAB>123"])
! exec "norm! ggvjf3\<C-A>..."
! call assert_equal(["\<TAB>127", " 127", "\<TAB>123", "\<TAB>123"],
getline(1, '$'))
! call assert_equal([0, 1, 2, 0], getpos('.'))
! endfunc
!
! " Tab code, spaces and blockwise-visual increment and redo
! func Test_visual_increment_36()
! call setline(1, [" 123", "\<TAB>456789"])
! exec "norm! G0\<C-V>kl\<C-A>"
! call assert_equal([" 123", "\<TAB>556789"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
!
! exec "norm! ..."
! call assert_equal([" 123", "\<TAB>856789"], getline(1, '$'))
! call assert_equal([0, 1, 1, 0], getpos('.'))
! endfunc
!
! " block-wise increment and dot-repeat
" Text:
" 1 23
" 4 56
***************
*** 587,593 ****
" 4 59
"
" Try with and without indent.
! func Test_visual_increment_28()
call setline(1, [" 1 23", " 4 56"])
exec "norm! ggf2\<C-V>jl\<C-A>.."
call assert_equal([" 1 26", " 4 59"], getline(1, 2))
--- 691,697 ----
" 4 59
"
" Try with and without indent.
! func Test_visual_increment_37()
call setline(1, [" 1 23", " 4 56"])
exec "norm! ggf2\<C-V>jl\<C-A>.."
call assert_equal([" 1 26", " 4 59"], getline(1, 2))
*** ../vim-7.4.1086/src/normal.c 2016-01-10 20:07:57.981777388 +0100
--- src/normal.c 2016-01-10 21:33:29.593904118 +0100
***************
*** 40,46 ****
static void find_end_of_word __ARGS((pos_T *));
static int get_mouse_class __ARGS((char_u *p));
#endif
- static void prep_redo_visual __ARGS((cmdarg_T *cap));
static void prep_redo_cmd __ARGS((cmdarg_T *cap));
static void prep_redo __ARGS((int regname, long, int, int, int, int, int));
static int checkclearop __ARGS((oparg_T *oap));
--- 40,45 ----
***************
*** 1392,1397 ****
--- 1391,1397 ----
static linenr_T redo_VIsual_line_count; /* number of lines */
static colnr_T redo_VIsual_vcol; /* number of cols or end column */
static long redo_VIsual_count; /* count for Visual
operator */
+ static int redo_VIsual_arg; /* extra argument */
#ifdef FEAT_VIRTUALEDIT
int include_line_break = FALSE;
#endif
***************
*** 1699,1704 ****
--- 1699,1705 ----
redo_VIsual_vcol = resel_VIsual_vcol;
redo_VIsual_line_count = resel_VIsual_line_count;
redo_VIsual_count = cap->count0;
+ redo_VIsual_arg = cap->arg;
}
}
***************
*** 2108,2113 ****
--- 2109,2132 ----
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break;
#endif
+ case OP_NR_ADD:
+ case OP_NR_SUB:
+ if (empty_region_error)
+ {
+ vim_beep(BO_OPER);
+ CancelRedo();
+ }
+ else
+ {
+ VIsual_active = TRUE;
+ #ifdef FEAT_LINEBREAK
+ curwin->w_p_lbr = lbr_saved;
+ #endif
+ op_addsub(oap, cap->count1, redo_VIsual_arg);
+ VIsual_active = FALSE;
+ }
+ check_cursor_col();
+ break;
default:
clearopbeep(oap);
}
***************
*** 3603,3645 ****
}
/*
- * Add commands to reselect Visual mode into the redo buffer.
- */
- static void
- prep_redo_visual(cap)
- cmdarg_T *cap;
- {
- ResetRedobuff();
- AppendCharToRedobuff(VIsual_mode);
- if (VIsual_mode == 'V' && curbuf->b_visual.vi_end.lnum
- != curbuf->b_visual.vi_start.lnum)
- {
- AppendNumberToRedobuff(curbuf->b_visual.vi_end.lnum
- - curbuf->b_visual.vi_start.lnum);
- AppendCharToRedobuff('j');
- }
- else if (VIsual_mode == 'v' || VIsual_mode == Ctrl_V)
- {
- /* block visual mode or char visual mmode*/
- if (curbuf->b_visual.vi_end.lnum != curbuf->b_visual.vi_start.lnum)
- {
- AppendNumberToRedobuff(curbuf->b_visual.vi_end.lnum -
- curbuf->b_visual.vi_start.lnum);
- AppendCharToRedobuff('j');
- }
- if (curbuf->b_visual.vi_curswant == MAXCOL)
- AppendCharToRedobuff('$');
- else if (curbuf->b_visual.vi_end.col > curbuf->b_visual.vi_start.col)
- {
- AppendNumberToRedobuff(curbuf->b_visual.vi_end.col
- - curbuf->b_visual.vi_start.col);
- AppendCharToRedobuff(' ');
- }
- }
- AppendNumberToRedobuff(cap->count1);
- }
-
- /*
* Prepare for redo of a normal command.
*/
static void
--- 3622,3627 ----
***************
*** 4243,4272 ****
nv_addsub(cap)
cmdarg_T *cap;
{
! int visual = VIsual_active;
!
! if (cap->oap->op_type == OP_NOP
! && do_addsub((int)cap->cmdchar, cap->count1, cap->arg) == OK)
{
! if (visual)
! {
! prep_redo_visual(cap);
! if (cap->arg)
! AppendCharToRedobuff('g');
! AppendCharToRedobuff(cap->cmdchar);
! }
! else
! prep_redo_cmd(cap);
}
else
! clearopbeep(cap->oap);
! if (visual)
! {
! VIsual_active = FALSE;
! redo_VIsual_busy = FALSE;
! may_clear_cmdline();
! redraw_later(INVERTED);
! }
}
/*
--- 4225,4240 ----
nv_addsub(cap)
cmdarg_T *cap;
{
! if (!VIsual_active && cap->oap->op_type == OP_NOP)
{
! cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
! op_addsub(cap->oap, cap->count1, cap->arg);
! cap->oap->op_type = OP_NOP;
}
+ else if (VIsual_active)
+ nv_operator(cap);
else
! clearop(cap->oap);
}
/*
***************
*** 7924,7929 ****
--- 7892,7898 ----
{
cap->arg = TRUE;
cap->cmdchar = cap->nchar;
+ cap->nchar = NUL;
nv_addsub(cap);
}
else
*** ../vim-7.4.1086/src/ops.c 2016-01-10 20:21:50.836727126 +0100
--- src/ops.c 2016-01-10 22:01:54.743302030 +0100
***************
*** 112,117 ****
--- 112,118 ----
static char_u *skip_comment __ARGS((char_u *line, int process, int
include_space, int *is_comment));
#endif
static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T,
int));
+ static int do_addsub __ARGS((int op_type, pos_T *pos, int length, linenr_T
Prenum1));
#if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL)
static void str_to_reg __ARGS((struct yankreg *y_ptr, int yank_type, char_u
*str, long len, long blocklen, int str_list));
#endif
***************
*** 158,163 ****
--- 159,166 ----
{'z', 'D', TRUE}, /* OP_FOLDDELREC */
{'g', 'w', TRUE}, /* OP_FORMAT2 */
{'g', '@', FALSE}, /* OP_FUNCTION */
+ {Ctrl_A, NUL, FALSE}, /* OP_NR_ADD */
+ {Ctrl_X, NUL, FALSE}, /* OP_NR_SUB */
};
/*
***************
*** 175,180 ****
--- 178,187 ----
return OP_REPLACE;
if (char1 == '~') /* when tilde is an operator */
return OP_TILDE;
+ if (char1 == 'g' && char2 == Ctrl_A) /* add */
+ return OP_NR_ADD;
+ if (char1 == 'g' && char2 == Ctrl_X) /* subtract */
+ return OP_NR_SUB;
for (i = 0; ; ++i)
if (opchars[i][0] == char1 && opchars[i][1] == char2)
break;
***************
*** 5340,5355 ****
}
/*
! * add or subtract 'Prenum1' from a number in a line
! * 'command' is CTRL-A for add, CTRL-X for subtract
*
! * return FAIL for failure, OK otherwise
*/
! int
! do_addsub(command, Prenum1, g_cmd)
! int command;
linenr_T Prenum1;
- int g_cmd; /* was g<c-a>/g<c-x> */
{
int col;
char_u *buf1;
--- 5347,5477 ----
}
/*
! * Handle the add/subtract operator.
! */
! void
! op_addsub(oap, Prenum1, g_cmd)
! oparg_T *oap;
! linenr_T Prenum1; /* Amount of add/subtract */
! int g_cmd; /* was g<c-a>/g<c-x> */
! {
! pos_T pos;
! struct block_def bd;
! int change_cnt = 0;
! linenr_T amount = Prenum1;
!
! if (!VIsual_active)
! {
! pos = curwin->w_cursor;
! if (u_save_cursor() == FAIL)
! return;
! change_cnt = do_addsub(oap->op_type, &pos, 0, amount);
! if (change_cnt)
! changed_lines(pos.lnum, 0, pos.lnum + 1, 0L);
! }
! else
! {
! int one_change;
! int length;
! pos_T startpos;
!
! if (u_save((linenr_T)(oap->start.lnum - 1),
! (linenr_T)(oap->end.lnum + 1)) == FAIL)
! return;
!
! pos = oap->start;
! for (; pos.lnum <= oap->end.lnum; ++pos.lnum)
! {
! if (oap->block_mode) /* Visual block mode */
! {
! block_prep(oap, &bd, pos.lnum, FALSE);
! pos.col = bd.textcol;
! length = bd.textlen;
! }
! else
! {
! if (oap->motion_type == MLINE)
! {
! curwin->w_cursor.col = 0;
! pos.col = 0;
! length = (colnr_T)STRLEN(ml_get(pos.lnum));
! }
! else if (oap->motion_type == MCHAR)
! {
! if (!oap->inclusive)
! dec(&(oap->end));
! length = (colnr_T)STRLEN(ml_get(pos.lnum));
! pos.col = 0;
! if (pos.lnum == oap->start.lnum)
! {
! pos.col += oap->start.col;
! length -= oap->start.col;
! }
! if (pos.lnum == oap->end.lnum)
! {
! length = (int)STRLEN(ml_get(oap->end.lnum));
! if (oap->end.col >= length)
! oap->end.col = length - 1;
! length = oap->end.col - pos.col + 1;
! }
! }
! }
! one_change = do_addsub(oap->op_type, &pos, length, amount);
! if (one_change)
! {
! /* Remember the start position of the first change. */
! if (change_cnt == 0)
! startpos = curbuf->b_op_start;
! ++change_cnt;
! }
!
! #ifdef FEAT_NETBEANS_INTG
! if (netbeans_active() && one_change)
! {
! char_u *ptr = ml_get_buf(curbuf, pos.lnum, FALSE);
!
! netbeans_removed(curbuf, pos.lnum, pos.col, (long)length);
! netbeans_inserted(curbuf, pos.lnum, pos.col,
! &ptr[pos.col], length);
! }
! #endif
! if (g_cmd && one_change)
! amount += Prenum1;
! }
! if (change_cnt)
! changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
!
! if (!change_cnt && oap->is_VIsual)
! /* No change: need to remove the Visual selection */
! redraw_curbuf_later(INVERTED);
!
! /* Set '[ mark if something changed. Keep the last end
! * position from do_addsub(). */
! if (change_cnt > 0)
! curbuf->b_op_start = startpos;
!
! if (change_cnt > p_report)
! {
! if (change_cnt == 1)
! MSG(_("1 line changed"));
! else
! smsg((char_u *)_("%ld lines changed"), change_cnt);
! }
! }
! }
!
! /*
! * Add or subtract 'Prenum1' from a number in a line
! * op_type is OP_NR_ADD or OP_NR_SUB
*
! * Returns TRUE if some character was changed.
*/
! static int
! do_addsub(op_type, pos, length, Prenum1)
! int op_type;
! pos_T *pos;
! int length;
linenr_T Prenum1;
{
int col;
char_u *buf1;
***************
*** 5357,5367 ****
int pre; /* 'X'/'x': hex; '0': octal; 'B'/'b':
bin */
static int hexupper = FALSE; /* 0xABC */
unsigned long n;
- unsigned long offset = 0; /* line offset for Ctrl_V mode */
long_u oldn;
char_u *ptr;
int c;
- int length = 0; /* character length of the
number */
int todel;
int dohex;
int dooct;
--- 5479,5487 ----
***************
*** 5372,5387 ****
int negative = FALSE;
int was_positive = TRUE;
int visual = VIsual_active;
- int i;
- int lnum = curwin->w_cursor.lnum;
- int lnume = curwin->w_cursor.lnum;
- int startcol = 0;
int did_change = FALSE;
pos_T t = curwin->w_cursor;
int maxlen = 0;
- int pos = 0;
- int bit = 0;
- int bits = sizeof(unsigned long) * 8;
pos_T startpos;
pos_T endpos;
--- 5492,5500 ----
***************
*** 5390,5439 ****
dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */
/*
* First check if we are on a hexadecimal number, after the "0x".
*/
! col = curwin->w_cursor.col;
! if (VIsual_active)
{
- if (lt(curwin->w_cursor, VIsual))
- {
- curwin->w_cursor = VIsual;
- VIsual = t;
- }
-
- ptr = ml_get(VIsual.lnum);
- if (VIsual_mode == 'V')
- {
- VIsual.col = 0;
- curwin->w_cursor.col = (colnr_T)STRLEN(ptr);
- }
- else if (VIsual_mode == Ctrl_V && VIsual.col > curwin->w_cursor.col)
- {
- t = VIsual;
- VIsual.col = curwin->w_cursor.col;
- curwin->w_cursor.col = t.col;
- }
-
- /* store visual area for 'gv' */
- curbuf->b_visual.vi_start = VIsual;
- curbuf->b_visual.vi_end = curwin->w_cursor;
- curbuf->b_visual.vi_mode = VIsual_mode;
- curbuf->b_visual.vi_curswant = curwin->w_curswant;
-
- if (VIsual_mode != 'v')
- startcol = VIsual.col < curwin->w_cursor.col ? VIsual.col
- : curwin->w_cursor.col;
- else
- startcol = VIsual.col;
- col = startcol;
- lnum = VIsual.lnum;
- lnume = curwin->w_cursor.lnum;
- }
- else
- {
- ptr = ml_get_curline();
-
if (dobin)
while (col > 0 && vim_isbdigit(ptr[col]))
--col;
--- 5503,5520 ----
dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */
+ curwin->w_cursor = *pos;
+ ptr = ml_get(pos->lnum);
+ col = pos->col;
+
+ if (*ptr == NUL)
+ goto theend;
+
/*
* First check if we are on a hexadecimal number, after the "0x".
*/
! if (!VIsual_active)
{
if (dobin)
while (col > 0 && vim_isbdigit(ptr[col]))
--col;
***************
*** 5453,5459 ****
/* In case of binary/hexadecimal pattern overlap match, rescan */
! col = curwin->w_cursor.col;
while (col > 0 && vim_isdigit(ptr[col]))
col--;
--- 5534,5540 ----
/* In case of binary/hexadecimal pattern overlap match, rescan */
! col = pos->col;
while (col > 0 && vim_isdigit(ptr[col]))
col--;
***************
*** 5480,5486 ****
/*
* Search forward and then backward to find the start of number.
*/
! col = curwin->w_cursor.col;
while (ptr[col] != NUL
&& !vim_isdigit(ptr[col])
--- 5561,5567 ----
/*
* Search forward and then backward to find the start of number.
*/
! col = pos->col;
while (ptr[col] != NUL
&& !vim_isdigit(ptr[col])
***************
*** 5494,5801 ****
}
}
! for (i = lnum; i <= lnume; i++)
{
! colnr_T stop = 0;
!
! t = curwin->w_cursor;
! curwin->w_cursor.lnum = i;
! ptr = ml_get_curline();
! if ((int)STRLEN(ptr) <= col)
! /* try again on next line */
! continue;
! if (visual)
{
! if (VIsual_mode == 'v'
! && i == lnume)
! stop = curwin->w_cursor.col;
! else if (VIsual_mode == Ctrl_V
! && curbuf->b_visual.vi_curswant != MAXCOL)
! stop = curwin->w_cursor.col;
! while (ptr[col] != NUL
! && !vim_isdigit(ptr[col])
! && !(doalp && ASCII_ISALPHA(ptr[col])))
! {
! if (col > 0 && col == stop)
! break;
! ++col;
! }
! if (col > startcol && ptr[col - 1] == '-')
! {
! negative = TRUE;
! was_positive = FALSE;
! }
! }
! /*
! * If a number was found, and saving for undo works, replace the number.
! */
! firstdigit = ptr[col];
! if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
! || u_save_cursor() != OK)
{
! if (lnum < lnume)
! {
! if (visual && VIsual_mode != Ctrl_V)
! col = 0;
! else
! col = startcol;
! /* Try again on next line */
! continue;
! }
! beep_flush();
! return FAIL;
}
! if (doalp && ASCII_ISALPHA(firstdigit))
{
! /* decrement or increment alphabetic character */
! if (command == Ctrl_X)
{
! if (CharOrd(firstdigit) < Prenum1)
! {
! if (isupper(firstdigit))
! firstdigit = 'A';
! else
! firstdigit = 'a';
! }
else
#ifdef EBCDIC
! firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
#else
! firstdigit -= Prenum1;
#endif
! }
! else
{
! if (26 - CharOrd(firstdigit) - 1 < Prenum1)
! {
! if (isupper(firstdigit))
! firstdigit = 'Z';
! else
! firstdigit = 'z';
! }
else
#ifdef EBCDIC
! firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
#else
! firstdigit += Prenum1;
#endif
- }
- curwin->w_cursor.col = col;
- if (!did_change)
- startpos = curwin->w_cursor;
- did_change = TRUE;
- (void)del_char(FALSE);
- ins_char(firstdigit);
- endpos = curwin->w_cursor;
- curwin->w_cursor.col = col;
}
else
{
! if (col > 0 && ptr[col - 1] == '-' && !visual)
! {
! /* negative number */
! --col;
! negative = TRUE;
! }
! /* get the number value (unsigned) */
! if (visual && VIsual_mode != 'V')
{
! if (VIsual_mode == 'v')
{
! if (i == lnum)
! maxlen = (lnum == lnume
! ? curwin->w_cursor.col - col + 1
! : (int)STRLEN(ptr) - col);
! else
! maxlen = (i == lnume ? curwin->w_cursor.col - col + 1
! : (int)STRLEN(ptr) - col);
}
- else if (VIsual_mode == Ctrl_V)
- maxlen = (curbuf->b_visual.vi_curswant == MAXCOL
- ? (int)STRLEN(ptr) - col
- : curwin->w_cursor.col - col + 1);
}
-
- vim_str2nr(ptr + col, &pre, &length,
- 0 + (dobin ? STR2NR_BIN : 0)
- + (dooct ? STR2NR_OCT : 0)
- + (dohex ? STR2NR_HEX : 0),
- NULL, &n, maxlen);
-
- /* ignore leading '-' for hex and octal and bin numbers */
- if (pre && negative)
- {
- ++col;
- --length;
- negative = FALSE;
- }
-
- /* add or subtract */
- subtract = FALSE;
- if (command == Ctrl_X)
- subtract ^= TRUE;
- if (negative)
- subtract ^= TRUE;
-
- oldn = n;
- if (subtract)
- n -= (unsigned long)Prenum1;
else
- n += (unsigned long)Prenum1;
-
- /* handle wraparound for decimal numbers */
- if (!pre)
{
! if (subtract)
{
! if (n > oldn)
! {
! n = 1 + (n ^ (unsigned long)-1);
! negative ^= TRUE;
! }
}
- else
- {
- /* add */
- if (n < oldn)
- {
- n = (n ^ (unsigned long)-1);
- negative ^= TRUE;
- }
- }
- if (n == 0)
- negative = FALSE;
- }
-
- if (visual && !was_positive && !negative && col > 0)
- {
- /* need to remove the '-' */
- col--;
- length++;
}
! /*
! * Delete the old number.
! */
! curwin->w_cursor.col = col;
! if (!did_change)
! startpos = curwin->w_cursor;
! did_change = TRUE;
! todel = length;
! c = gchar_cursor();
!
! /*
! * Don't include the '-' in the length, only the length of the
! * part after it is kept the same.
! */
! if (c == '-')
! --length;
! while (todel-- > 0)
! {
! if (c < 0x100 && isalpha(c))
! {
! if (isupper(c))
! hexupper = TRUE;
! else
! hexupper = FALSE;
! }
! /* del_char() will mark line needing displaying */
! (void)del_char(FALSE);
! c = gchar_cursor();
! }
!
! /*
! * Prepare the leading characters in buf1[].
! * When there are many leading zeros it could be very long.
! * Allocate a bit too much.
! */
! buf1 = alloc((unsigned)length + NUMBUFLEN);
! if (buf1 == NULL)
! return FAIL;
! ptr = buf1;
! if (negative && (!visual || (visual && was_positive)))
! {
! *ptr++ = '-';
! }
! if (pre)
! {
! *ptr++ = '0';
! --length;
! }
! if (pre == 'b' || pre == 'B' ||
! pre == 'x' || pre == 'X')
{
! *ptr++ = pre;
! --length;
}
!
! /*
! * Put the number characters in buf2[].
! */
! if (pre == 'b' || pre == 'B')
! {
! /* leading zeros */
! for (bit = bits; bit > 0; bit--)
! if ((n >> (bit - 1)) & 0x1) break;
!
! for (pos = 0; bit > 0; bit--)
! buf2[pos++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0';
!
! buf2[pos] = '\0';
! }
! else if (pre == 0)
! sprintf((char *)buf2, "%lu", n);
! else if (pre == '0')
! sprintf((char *)buf2, "%lo", n);
! else if (pre && hexupper)
! sprintf((char *)buf2, "%lX", n);
! else
! sprintf((char *)buf2, "%lx", n);
! length -= (int)STRLEN(buf2);
!
! /*
! * Adjust number of zeros to the new number of digits, so the
! * total length of the number remains the same.
! * Don't do this when
! * the result may look like an octal number.
! */
! if (firstdigit == '0' && !(dooct && pre == 0))
! while (length-- > 0)
! *ptr++ = '0';
! *ptr = NUL;
! STRCAT(buf1, buf2);
! ins_str(buf1); /* insert the new number */
! vim_free(buf1);
! endpos = curwin->w_cursor;
! if (lnum < lnume)
! curwin->w_cursor.col = t.col;
! else if (did_change && curwin->w_cursor.col)
! --curwin->w_cursor.col;
}
! if (g_cmd)
{
! offset = (unsigned long)Prenum1;
! g_cmd = 0;
}
! /* reset */
! subtract = FALSE;
! negative = FALSE;
! was_positive = TRUE;
! if (visual && VIsual_mode == Ctrl_V)
! col = startcol;
else
! col = 0;
! Prenum1 += offset;
! curwin->w_set_curswant = TRUE;
}
if (visual)
! /* cursor at the top of the selection */
! curwin->w_cursor = VIsual;
if (did_change)
{
/* set the '[ and '] marks */
--- 5575,5827 ----
}
}
! if (visual)
{
! while (ptr[col] != NUL && length > 0
! && !vim_isdigit(ptr[col])
! && !(doalp && ASCII_ISALPHA(ptr[col])))
{
! ++col;
! --length;
! }
! if (length == 0)
! goto theend;
! if (col > pos->col && ptr[col - 1] == '-')
{
! negative = TRUE;
! was_positive = FALSE;
}
+ }
! /*
! * If a number was found, and saving for undo works, replace the number.
! */
! firstdigit = ptr[col];
! if (!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
! {
! beep_flush();
! goto theend;
! }
!
! if (doalp && ASCII_ISALPHA(firstdigit))
! {
! /* decrement or increment alphabetic character */
! if (op_type == OP_NR_SUB)
{
! if (CharOrd(firstdigit) < Prenum1)
{
! if (isupper(firstdigit))
! firstdigit = 'A';
else
+ firstdigit = 'a';
+ }
+ else
#ifdef EBCDIC
! firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1);
#else
! firstdigit -= Prenum1;
#endif
! }
! else
! {
! if (26 - CharOrd(firstdigit) - 1 < Prenum1)
{
! if (isupper(firstdigit))
! firstdigit = 'Z';
else
+ firstdigit = 'z';
+ }
+ else
#ifdef EBCDIC
! firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1);
#else
! firstdigit += Prenum1;
#endif
}
+ curwin->w_cursor.col = col;
+ if (!did_change)
+ startpos = curwin->w_cursor;
+ did_change = TRUE;
+ (void)del_char(FALSE);
+ ins_char(firstdigit);
+ endpos = curwin->w_cursor;
+ curwin->w_cursor.col = col;
+ }
+ else
+ {
+ if (col > 0 && ptr[col - 1] == '-' && !visual)
+ {
+ /* negative number */
+ --col;
+ negative = TRUE;
+ }
+ /* get the number value (unsigned) */
+ if (visual && VIsual_mode != 'V')
+ maxlen = (curbuf->b_visual.vi_curswant == MAXCOL
+ ? (int)STRLEN(ptr) - col
+ : length);
+
+ vim_str2nr(ptr + col, &pre, &length,
+ 0 + (dobin ? STR2NR_BIN : 0)
+ + (dooct ? STR2NR_OCT : 0)
+ + (dohex ? STR2NR_HEX : 0),
+ NULL, &n, maxlen);
+
+ /* ignore leading '-' for hex and octal and bin numbers */
+ if (pre && negative)
+ {
+ ++col;
+ --length;
+ negative = FALSE;
+ }
+ /* add or subtract */
+ subtract = FALSE;
+ if (op_type == OP_NR_SUB)
+ subtract ^= TRUE;
+ if (negative)
+ subtract ^= TRUE;
+
+ oldn = n;
+ if (subtract)
+ n -= (unsigned long)Prenum1;
else
+ n += (unsigned long)Prenum1;
+ /* handle wraparound for decimal numbers */
+ if (!pre)
{
! if (subtract)
{
! if (n > oldn)
{
! n = 1 + (n ^ (unsigned long)-1);
! negative ^= TRUE;
}
}
else
{
! /* add */
! if (n < oldn)
{
! n = (n ^ (unsigned long)-1);
! negative ^= TRUE;
}
}
+ if (n == 0)
+ negative = FALSE;
+ }
+ if (visual && !was_positive && !negative && col > 0)
+ {
+ /* need to remove the '-' */
+ col--;
+ length++;
+ }
! /*
! * Delete the old number.
! */
! curwin->w_cursor.col = col;
! if (!did_change)
! startpos = curwin->w_cursor;
! did_change = TRUE;
! todel = length;
! c = gchar_cursor();
! /*
! * Don't include the '-' in the length, only the length of the
! * part after it is kept the same.
! */
! if (c == '-')
! --length;
! while (todel-- > 0)
! {
! if (c < 0x100 && isalpha(c))
{
! if (isupper(c))
! hexupper = TRUE;
! else
! hexupper = FALSE;
}
! /* del_char() will mark line needing displaying */
! (void)del_char(FALSE);
! c = gchar_cursor();
}
! /*
! * Prepare the leading characters in buf1[].
! * When there are many leading zeros it could be very long.
! * Allocate a bit too much.
! */
! buf1 = alloc((unsigned)length + NUMBUFLEN);
! if (buf1 == NULL)
! goto theend;
! ptr = buf1;
! if (negative && (!visual || (visual && was_positive)))
{
! *ptr++ = '-';
}
! if (pre)
! {
! *ptr++ = '0';
! --length;
! }
! if (pre == 'b' || pre == 'B' ||
! pre == 'x' || pre == 'X')
! {
! *ptr++ = pre;
! --length;
! }
!
! /*
! * Put the number characters in buf2[].
! */
! if (pre == 'b' || pre == 'B')
! {
! int i;
! int bit = 0;
! int bits = sizeof(unsigned long) * 8;
!
! /* leading zeros */
! for (bit = bits; bit > 0; bit--)
! if ((n >> (bit - 1)) & 0x1) break;
!
! for (i = 0; bit > 0; bit--)
! buf2[i++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0';
!
! buf2[i] = '\0';
! }
! else if (pre == 0)
! sprintf((char *)buf2, "%lu", n);
! else if (pre == '0')
! sprintf((char *)buf2, "%lo", n);
! else if (pre && hexupper)
! sprintf((char *)buf2, "%lX", n);
else
! sprintf((char *)buf2, "%lx", n);
! length -= (int)STRLEN(buf2);
!
! /*
! * Adjust number of zeros to the new number of digits, so the
! * total length of the number remains the same.
! * Don't do this when
! * the result may look like an octal number.
! */
! if (firstdigit == '0' && !(dooct && pre == 0))
! while (length-- > 0)
! *ptr++ = '0';
! *ptr = NUL;
! STRCAT(buf1, buf2);
! ins_str(buf1); /* insert the new number */
! vim_free(buf1);
! endpos = curwin->w_cursor;
! if (did_change && curwin->w_cursor.col)
! --curwin->w_cursor.col;
}
+
+ theend:
if (visual)
! curwin->w_cursor = t;
if (did_change)
{
/* set the '[ and '] marks */
***************
*** 5804,5810 ****
if (curbuf->b_op_end.col > 0)
--curbuf->b_op_end.col;
}
! return OK;
}
#ifdef FEAT_VIMINFO
--- 5830,5837 ----
if (curbuf->b_op_end.col > 0)
--curbuf->b_op_end.col;
}
!
! return did_change;
}
#ifdef FEAT_VIMINFO
*** ../vim-7.4.1086/src/proto/ops.pro 2016-01-03 22:47:52.987427330 +0100
--- src/proto/ops.pro 2016-01-10 21:19:34.307017845 +0100
***************
*** 43,49 ****
int fex_format __ARGS((linenr_T lnum, long count, int c));
void format_lines __ARGS((linenr_T line_count, int avoid_fex));
int paragraph_start __ARGS((linenr_T lnum));
! int do_addsub __ARGS((int command, linenr_T Prenum1, int g_cmd));
int read_viminfo_register __ARGS((vir_T *virp, int force));
void write_viminfo_registers __ARGS((FILE *fp));
void x11_export_final_selection __ARGS((void));
--- 43,49 ----
int fex_format __ARGS((linenr_T lnum, long count, int c));
void format_lines __ARGS((linenr_T line_count, int avoid_fex));
int paragraph_start __ARGS((linenr_T lnum));
! void op_addsub __ARGS((oparg_T *oap, linenr_T Prenum1, int g_cmd));
int read_viminfo_register __ARGS((vir_T *virp, int force));
void write_viminfo_registers __ARGS((FILE *fp));
void x11_export_final_selection __ARGS((void));
*** ../vim-7.4.1086/src/vim.h 2016-01-09 22:28:13.339790774 +0100
--- src/vim.h 2016-01-10 21:34:14.113418468 +0100
***************
*** 1457,1462 ****
--- 1457,1466 ----
#define OP_FOLDDELREC 25 /* "zD" delete folds recursively */
#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
#define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */
+ #define OP_NR_ADD 28 /* "<C-A>" Add to the number or alphabetic
+ character (OP_ADD conflicts with Perl) */
+ #define OP_NR_SUB 29 /* "<C-X>" Subtract from the number or
+ alphabetic character */
/*
* Motion types, used for operators and for yank/delete registers.
*** ../vim-7.4.1086/src/version.c 2016-01-10 20:54:11.827626122 +0100
--- src/version.c 2016-01-10 22:09:38.794243821 +0100
***************
*** 743,744 ****
--- 743,746 ----
{ /* Add new patch number below this line */
+ /**/
+ 1087,
/**/
--
The problem with political jokes is that they get elected.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
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/d/optout.