Patch 9.0.1598

6 views
Skip to first unread message

Bram Moolenaar

unread,
Jun 1, 2023, 3:27:31 PM6/1/23
to vim...@googlegroups.com

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 -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages