Patch 9.0.1598
Problem:    screenchar(), screenchars() and screenstring() do not work
            properly when 'encoding' is set to a double-byte encoding.
Solution:   Fix the way the bytes of the characters are obtained.
            (issue #12469)
Files:      src/evalfunc.c, src/screen.c, src/testdir/test_functions.vim,
            src/testdir/test_utf8.vim


*** ../vim-9.0.1597/src/evalfunc.c      2023-05-11 15:02:52.231456894 +0100
--- src/evalfunc.c      2023-06-01 20:21:12.233128848 +0100
***************
*** 8934,8940 ****
  {
      int               row;
      int               col;
-     int               off;
      int               c;
  
      if (in_vim9script()
--- 8934,8939 ----
***************
*** 8948,8958 ****
        c = -1;
      else
      {
!       off = LineOffset[row] + col;
!       if (enc_utf8 && ScreenLinesUC[off] != 0)
!           c = ScreenLinesUC[off];
!       else
!           c = ScreenLines[off];
      }
      rettv->vval.v_number = c;
  }
--- 8947,8955 ----
        c = -1;
      else
      {
!       char_u buf[MB_MAXBYTES + 1];
!       screen_getbytes(row, col, buf, NULL);
!       c = (*mb_ptr2char)(buf);
      }
      rettv->vval.v_number = c;
  }
***************
*** 8965,8971 ****
  {
      int               row;
      int               col;
-     int               off;
      int               c;
      int               i;
  
--- 8962,8967 ----
***************
*** 8982,8999 ****
      if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
        return;
  
!     off = LineOffset[row] + col;
!     if (enc_utf8 && ScreenLinesUC[off] != 0)
!       c = ScreenLinesUC[off];
      else
!       c = ScreenLines[off];
      list_append_number(rettv->vval.v_list, (varnumber_T)c);
  
      if (enc_utf8)
! 
!       for (i = 0; i < Screen_mco && ScreenLinesC[i][off] != 0; ++i)
!           list_append_number(rettv->vval.v_list,
!                                      (varnumber_T)ScreenLinesC[i][off]);
  }
  
  /*
--- 8978,8995 ----
      if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
        return;
  
!     char_u buf[MB_MAXBYTES + 1];
!     screen_getbytes(row, col, buf, NULL);
!     int pcc[MAX_MCO];
!     if (enc_utf8)
!       c = utfc_ptr2char(buf, pcc);
      else
!       c = (*mb_ptr2char)(buf);
      list_append_number(rettv->vval.v_list, (varnumber_T)c);
  
      if (enc_utf8)
!       for (i = 0; i < Screen_mco && pcc[i] != 0; ++i)
!           list_append_number(rettv->vval.v_list, (varnumber_T)pcc[i]);
  }
  
  /*
***************
*** 9024,9034 ****
  {
      int               row;
      int               col;
-     int               off;
-     int               c;
-     int               i;
      char_u    buf[MB_MAXBYTES + 1];
-     int               buflen = 0;
  
      rettv->vval.v_string = NULL;
      rettv->v_type = VAR_STRING;
--- 9020,9026 ----
***************
*** 9043,9060 ****
      if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
        return;
  
!     off = LineOffset[row] + col;
!     if (enc_utf8 && ScreenLinesUC[off] != 0)
!       c = ScreenLinesUC[off];
!     else
!       c = ScreenLines[off];
!     buflen += mb_char2bytes(c, buf);
! 
!     if (enc_utf8 && ScreenLinesUC[off] != 0)
!       for (i = 0; i < Screen_mco && ScreenLinesC[i][off] != 0; ++i)
!           buflen += mb_char2bytes(ScreenLinesC[i][off], buf + buflen);
! 
!     buf[buflen] = NUL;
      rettv->vval.v_string = vim_strsave(buf);
  }
  
--- 9035,9041 ----
      if (row < 0 || row >= screen_Rows || col < 0 || col >= screen_Columns)
        return;
  
!     screen_getbytes(row, col, buf, NULL);
      rettv->vval.v_string = vim_strsave(buf);
  }
  
***************
*** 9433,9439 ****
  
  /*
   * Set the cursor or mark position.
!  * If 'charpos' is TRUE, then use the column number as a character offset.
   * Otherwise use the column number as a byte offset.
   */
      static void
--- 9414,9420 ----
  
  /*
   * Set the cursor or mark position.
!  * If "charpos" is TRUE, then use the column number as a character offset.
   * Otherwise use the column number as a byte offset.
   */
      static void
*** ../vim-9.0.1597/src/screen.c        2023-05-20 14:06:56.673542805 +0100
--- src/screen.c        2023-06-01 20:26:30.112235831 +0100
***************
*** 1199,1206 ****
  }
  
  /*
!  * Get a single character directly from ScreenLines into "bytes[]".
!  * Also return its attribute in *attrp;
   */
      void
  screen_getbytes(int row, int col, char_u *bytes, int *attrp)
--- 1199,1207 ----
  }
  
  /*
!  * Get a single character directly from ScreenLines into "bytes", which must
!  * have a size of "MB_MAXBYTES + 1".
!  * If "attrp" is not NULL, return the character's attribute in "*attrp".
   */
      void
  screen_getbytes(int row, int col, char_u *bytes, int *attrp)
***************
*** 1212,1218 ****
        return;
  
      off = LineOffset[row] + col;
!     *attrp = ScreenAttrs[off];
      bytes[0] = ScreenLines[off];
      bytes[1] = NUL;
  
--- 1213,1220 ----
        return;
  
      off = LineOffset[row] + col;
!     if (attrp != NULL)
!       *attrp = ScreenAttrs[off];
      bytes[0] = ScreenLines[off];
      bytes[1] = NUL;
  
*** ../vim-9.0.1597/src/testdir/test_functions.vim      2023-05-24 
21:02:20.489162125 +0100
--- src/testdir/test_functions.vim      2023-06-01 20:17:49.333389396 +0100
***************
*** 3217,3222 ****
--- 3217,3247 ----
    call assert_equal(-1, screenattr(-1, -1))
    call assert_equal(-1, screenchar(-1, -1))
    call assert_equal([], screenchars(-1, -1))
+ 
+   " Run this in a separate Vim instance to avoid messing up.
+   let after =<< trim [CODE]
+     scriptencoding utf-8
+     call setline(1, '口')
+     redraw
+     call assert_equal(0, screenattr(1, 1))
+     call assert_equal(char2nr('口'), screenchar(1, 1))
+     call assert_equal([char2nr('口')], screenchars(1, 1))
+     call assert_equal('口', screenstring(1, 1))
+     call writefile(v:errors, 'Xresult')
+     qall!
+   [CODE]
+ 
+   let encodings = ['utf-8', 'cp932', 'cp936', 'cp949', 'cp950']
+   if !has('win32')
+     let encodings += ['euc-jp']
+   endif
+   for enc in encodings
+     let msg = 'enc=' .. enc
+     if RunVim([], after, $'--clean --cmd "set encoding={enc}"')
+       call assert_equal([], readfile('Xresult'), msg)
+     endif
+     call delete('Xresult')
+   endfor
  endfunc
  
  " Test for getcurpos() and setpos()
*** ../vim-9.0.1597/src/testdir/test_utf8.vim   2023-05-08 15:31:34.251545087 
+0100
--- src/testdir/test_utf8.vim   2023-06-01 20:17:49.333389396 +0100
***************
*** 135,140 ****
--- 135,153 ----
    call assert_equal("B", screenstring(1, 2))
    call assert_equal("C\u0308", screenstring(1, 3))
  
+   " 1-cell, with 6 composing characters
+   set maxcombine=6
+   call setline(1, ["ABC" .. repeat("\u0308", 6)])
+   redraw
+   call assert_equal([0x0041], screenchars(1, 1))
+   call assert_equal([0x0042], 1->screenchars(2))
+   " This should not use uninitialized memory
+   call assert_equal([0x0043] + repeat([0x0308], 6), screenchars(1, 3))
+   call assert_equal("A", screenstring(1, 1))
+   call assert_equal("B", screenstring(1, 2))
+   call assert_equal("C" .. repeat("\u0308", 6), screenstring(1, 3))
+   set maxcombine&
+ 
    " 2-cells, with composing characters
    let text = "\u3042\u3044\u3046\u3099"
    call setline(1, text)
*** ../vim-9.0.1597/src/version.c       2023-06-01 19:26:23.435627545 +0100
--- src/version.c       2023-06-01 20:16:22.041494837 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1598,
  /**/

-- 
>From "know your smileys":
 C=}>;*{)) Drunk, devilish chef with a toupee in an updraft,
           a mustache, and a double chin

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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/20230601192724.921D71C1B27%40moolenaar.net.

Raspunde prin e-mail lui