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.

Raspunde prin e-mail lui