Patch 8.2.2342
Problem:    "char" functions return the wront column in Insert mode when the
            cursor is beyond the end of the line.
Solution:   Compute the column correctly. (Yegappan Lakshmanan, closes #7669)
Files:      src/eval.c, src/evalfunc.c, src/testdir/test_cursor_func.vim


*** ../vim-8.2.2341/src/eval.c  2021-01-10 20:22:20.763926913 +0100
--- src/eval.c  2021-01-13 20:05:35.725553517 +0100
***************
*** 5056,5067 ****
  /*
   * Convert the specified byte index of line 'lnum' in buffer 'buf' to a
   * character index.  Works only for loaded buffers. Returns -1 on failure.
!  * The index of the first character is one.
   */
      int
  buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
  {
      char_u    *str;
  
      if (buf == NULL || buf->b_ml.ml_mfp == NULL)
        return -1;
--- 5056,5069 ----
  /*
   * Convert the specified byte index of line 'lnum' in buffer 'buf' to a
   * character index.  Works only for loaded buffers. Returns -1 on failure.
!  * The index of the first byte and the first character is zero.
   */
      int
  buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
  {
      char_u    *str;
+     char_u    *t;
+     int               count;
  
      if (buf == NULL || buf->b_ml.ml_mfp == NULL)
        return -1;
***************
*** 5074,5088 ****
        return -1;
  
      if (*str == NUL)
!       return 1;
  
!     return mb_charlen_len(str, byteidx + 1);
  }
  
  /*
   * Convert the specified character index of line 'lnum' in buffer 'buf' to a
!  * byte index.  Works only for loaded buffers. Returns -1 on failure. The 
index
!  * of the first byte and the first character is one.
   */
      int
  buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
--- 5076,5101 ----
        return -1;
  
      if (*str == NUL)
!       return 0;
! 
!     // count the number of characters
!     t = str;
!     for (count = 0; *t != NUL && t <= str + byteidx; count++)
!       t += mb_ptr2len(t);
! 
!     // In insert mode, when the cursor is at the end of a non-empty line,
!     // byteidx points to the NUL character immediately past the end of the
!     // string. In this case, add one to the character count.
!     if (*t == NUL && byteidx != 0 && t == str + byteidx)
!       count++;
  
!     return count - 1;
  }
  
  /*
   * Convert the specified character index of line 'lnum' in buffer 'buf' to a
!  * byte index.  Works only for loaded buffers. Returns -1 on failure.
!  * The index of the first byte and the first character is zero.
   */
      int
  buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
***************
*** 5105,5111 ****
      while (*t != NUL && --charidx > 0)
        t += mb_ptr2len(t);
  
!     return t - str + 1;
  }
  
  /*
--- 5118,5124 ----
      while (*t != NUL && --charidx > 0)
        t += mb_ptr2len(t);
  
!     return t - str;
  }
  
  /*
***************
*** 5180,5186 ****
      {
        pos = curwin->w_cursor;
        if (charcol)
!           pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
        return &pos;
      }
      if (name[0] == 'v' && name[1] == NUL)     // Visual start
--- 5193,5199 ----
      {
        pos = curwin->w_cursor;
        if (charcol)
!           pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col);
        return &pos;
      }
      if (name[0] == 'v' && name[1] == NUL)     // Visual start
***************
*** 5190,5196 ****
        else
            pos = curwin->w_cursor;
        if (charcol)
!           pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
        return &pos;
      }
      if (name[0] == '\'')                      // mark
--- 5203,5209 ----
        else
            pos = curwin->w_cursor;
        if (charcol)
!           pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col);
        return &pos;
      }
      if (name[0] == '\'')                      // mark
***************
*** 5199,5205 ****
        if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
            return NULL;
        if (charcol)
!           pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col) - 1;
        return pp;
      }
  
--- 5212,5218 ----
        if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
            return NULL;
        if (charcol)
!           pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col);
        return pp;
      }
  
***************
*** 5300,5306 ****
        if (buf == NULL || buf->b_ml.ml_mfp == NULL)
            return FAIL;
  
!       n = buf_charidx_to_byteidx(buf, posp->lnum, n);
      }
      posp->col = n;
  
--- 5313,5319 ----
        if (buf == NULL || buf->b_ml.ml_mfp == NULL)
            return FAIL;
  
!       n = buf_charidx_to_byteidx(buf, posp->lnum, n) + 1;
      }
      posp->col = n;
  
*** ../vim-8.2.2341/src/evalfunc.c      2021-01-13 19:48:41.628312470 +0100
--- src/evalfunc.c      2021-01-13 20:05:35.725553517 +0100
***************
*** 2748,2754 ****
            semsg(_(e_invarg2), tv_get_string(&argvars[0]));
        col = (long)tv_get_number_chk(&argvars[1], NULL);
        if (charcol)
!           col = buf_charidx_to_byteidx(curbuf, line, col);
        if (argvars[2].v_type != VAR_UNKNOWN)
            coladd = (long)tv_get_number_chk(&argvars[2], NULL);
      }
--- 2748,2754 ----
            semsg(_(e_invarg2), tv_get_string(&argvars[0]));
        col = (long)tv_get_number_chk(&argvars[1], NULL);
        if (charcol)
!           col = buf_charidx_to_byteidx(curbuf, line, col) + 1;
        if (argvars[2].v_type != VAR_UNKNOWN)
            coladd = (long)tv_get_number_chk(&argvars[2], NULL);
      }
***************
*** 4011,4018 ****
            if (fp != NULL && charcol)
            {
                pos = *fp;
!               pos.col = buf_byteidx_to_charidx(wp->w_buffer, pos.lnum,
!                                                               pos.col) - 1;
                fp = &pos;
            }
        }
--- 4011,4018 ----
            if (fp != NULL && charcol)
            {
                pos = *fp;
!               pos.col =
!                   buf_byteidx_to_charidx(wp->w_buffer, pos.lnum, pos.col);
                fp = &pos;
            }
        }
*** ../vim-8.2.2341/src/testdir/test_cursor_func.vim    2021-01-10 
20:22:20.767926906 +0100
--- src/testdir/test_cursor_func.vim    2021-01-13 20:05:35.725553517 +0100
***************
*** 123,133 ****
--- 123,140 ----
    bwipe!
  endfunc
  
+ " Save the visual start character position
  func SaveVisualStartCharPos()
    call add(g:VisualStartPos, getcharpos('v'))
    return ''
  endfunc
  
+ " Save the current cursor character position in insert mode
+ func SaveInsertCurrentCharPos()
+   call add(g:InsertCurrentPos, getcharpos('.'))
+   return ''
+ endfunc
+ 
  " Test for the getcharpos() function
  func Test_getcharpos()
    call assert_fails('call getcharpos({})', 'E731:')
***************
*** 156,171 ****
    vnoremap <expr> <F3> SaveVisualStartCharPos()
    let g:VisualStartPos = []
    exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
!   call assert_equal([[0, 2, 7, 0], [0, 2, 9, 0], [0, 2, 5, 0]], 
g:VisualStartPos)
    call assert_equal([0, 2, 9, 0], getcharpos('v'))
    let g:VisualStartPos = []
    exe "normal 3Gv$\<F3>o\<F3>"
!   call assert_equal([[0, 3, 1, 0], [0, 3, 1, 0]], g:VisualStartPos)
    let g:VisualStartPos = []
    exe "normal 1Gv$\<F3>o\<F3>"
    call assert_equal([[0, 1, 1, 0], [0, 1, 1, 0]], g:VisualStartPos)
    vunmap <F3>
  
    %bw!
  endfunc
  
--- 163,191 ----
    vnoremap <expr> <F3> SaveVisualStartCharPos()
    let g:VisualStartPos = []
    exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
!   call assert_equal([[0, 2, 7, 0], [0, 2, 10, 0], [0, 2, 5, 0]], 
g:VisualStartPos)
    call assert_equal([0, 2, 9, 0], getcharpos('v'))
    let g:VisualStartPos = []
    exe "normal 3Gv$\<F3>o\<F3>"
!   call assert_equal([[0, 3, 1, 0], [0, 3, 2, 0]], g:VisualStartPos)
    let g:VisualStartPos = []
    exe "normal 1Gv$\<F3>o\<F3>"
    call assert_equal([[0, 1, 1, 0], [0, 1, 1, 0]], g:VisualStartPos)
    vunmap <F3>
  
+   " Test for getting the position in insert mode with the cursor after the
+   " last character in a line
+   inoremap <expr> <F3> SaveInsertCurrentCharPos()
+   let g:InsertCurrentPos = []
+   exe "normal 1GA\<F3>"
+   exe "normal 2GA\<F3>"
+   exe "normal 3GA\<F3>"
+   exe "normal 4GA\<F3>"
+   exe "normal 2G6li\<F3>"
+   call assert_equal([[0, 1, 1, 0], [0, 2, 10, 0], [0, 3, 2, 0], [0, 4, 10, 0],
+                         \ [0, 2, 7, 0]], g:InsertCurrentPos)
+   iunmap <F3>
+ 
    %bw!
  endfunc
  
***************
*** 192,197 ****
--- 212,221 ----
    call setcharpos("'m", [0, 2, 9, 0])
    normal `m
    call assert_equal([2, 11], [line('.'), col('.')])
+   " unload the buffer and try to set the mark
+   let bnr = bufnr()
+   enew!
+   call assert_equal(-1, setcharpos("'m", [bnr, 2, 2, 0]))
  
    %bw!
    call assert_equal(-1, setcharpos('.', [10, 3, 1, 0]))
***************
*** 202,207 ****
--- 226,236 ----
    return ''
  endfunc
  
+ func SaveInsertCurrentCharCol()
+   call add(g:InsertCurrentCol, charcol('.'))
+   return ''
+ endfunc
+ 
  " Test for the charcol() function
  func Test_charcol()
    call assert_fails('call charcol({})', 'E731:')
***************
*** 239,257 ****
    vnoremap <expr> <F3> SaveVisualStartCharCol()
    let g:VisualStartCol = []
    exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
!   call assert_equal([7, 9, 5], g:VisualStartCol)
    call assert_equal(9, charcol('v'))
    let g:VisualStartCol = []
    exe "normal 3Gv$\<F3>o\<F3>"
!   call assert_equal([1, 1], g:VisualStartCol)
    let g:VisualStartCol = []
    exe "normal 1Gv$\<F3>o\<F3>"
    call assert_equal([1, 1], g:VisualStartCol)
    vunmap <F3>
  
    %bw!
  endfunc
  
  " Test for getcursorcharpos()
  func Test_getcursorcharpos()
    call assert_equal(getcursorcharpos(), getcursorcharpos(0))
--- 268,303 ----
    vnoremap <expr> <F3> SaveVisualStartCharCol()
    let g:VisualStartCol = []
    exe "normal 2G6lv$\<F3>ohh\<F3>o\<F3>"
!   call assert_equal([7, 10, 5], g:VisualStartCol)
    call assert_equal(9, charcol('v'))
    let g:VisualStartCol = []
    exe "normal 3Gv$\<F3>o\<F3>"
!   call assert_equal([1, 2], g:VisualStartCol)
    let g:VisualStartCol = []
    exe "normal 1Gv$\<F3>o\<F3>"
    call assert_equal([1, 1], g:VisualStartCol)
    vunmap <F3>
  
+   " Test for getting the column number in insert mode with the cursor after
+   " the last character in a line
+   inoremap <expr> <F3> SaveInsertCurrentCharCol()
+   let g:InsertCurrentCol = []
+   exe "normal 1GA\<F3>"
+   exe "normal 2GA\<F3>"
+   exe "normal 3GA\<F3>"
+   exe "normal 4GA\<F3>"
+   exe "normal 2G6li\<F3>"
+   call assert_equal([1, 10, 2, 10, 7], g:InsertCurrentCol)
+   iunmap <F3>
+ 
    %bw!
  endfunc
  
+ func SaveInsertCursorCharPos()
+   call add(g:InsertCursorPos, getcursorcharpos('.'))
+   return ''
+ endfunc
+ 
  " Test for getcursorcharpos()
  func Test_getcursorcharpos()
    call assert_equal(getcursorcharpos(), getcursorcharpos(0))
***************
*** 269,274 ****
--- 315,333 ----
    normal 4G9l
    call assert_equal([0, 4, 9, 0, 9], getcursorcharpos())
  
+   " Test for getting the cursor position in insert mode with the cursor after
+   " the last character in a line
+   inoremap <expr> <F3> SaveInsertCursorCharPos()
+   let g:InsertCursorPos = []
+   exe "normal 1GA\<F3>"
+   exe "normal 2GA\<F3>"
+   exe "normal 3GA\<F3>"
+   exe "normal 4GA\<F3>"
+   exe "normal 2G6li\<F3>"
+   call assert_equal([[0, 1, 1, 0, 1], [0, 2, 10, 0, 15], [0, 3, 2, 0, 2],
+                     \ [0, 4, 10, 0, 10], [0, 2, 7, 0, 12]], g:InsertCursorPos)
+   iunmap <F3>
+ 
    let winid = win_getid()
    normal 2G5l
    wincmd w
*** ../vim-8.2.2341/src/version.c       2021-01-13 19:48:41.628312470 +0100
--- src/version.c       2021-01-13 20:07:47.081188096 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2342,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
137. You decide to stay in college for an additional year or two,
     just so you can have the free Internet access.

 /// 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].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202101131909.10DJ9C6D1344444%40masaka.moolenaar.net.

Raspunde prin e-mail lui