diff options
-rw-r--r-- | src/evalfunc.c | 45 | ||||
-rw-r--r-- | src/screen.c | 8 | ||||
-rw-r--r-- | src/testdir/test_functions.vim | 25 | ||||
-rw-r--r-- | src/testdir/test_utf8.vim | 13 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 58 insertions, 35 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 8f20ebee17..62e9a40624 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -8934,7 +8934,6 @@ f_screenchar(typval_T *argvars, typval_T *rettv) { int row; int col; - int off; int c; if (in_vim9script() @@ -8948,11 +8947,9 @@ f_screenchar(typval_T *argvars, typval_T *rettv) c = -1; else { - off = LineOffset[row] + col; - if (enc_utf8 && ScreenLinesUC[off] != 0) - c = ScreenLinesUC[off]; - else - c = ScreenLines[off]; + char_u buf[MB_MAXBYTES + 1]; + screen_getbytes(row, col, buf, NULL); + c = (*mb_ptr2char)(buf); } rettv->vval.v_number = c; } @@ -8965,7 +8962,6 @@ f_screenchars(typval_T *argvars, typval_T *rettv) { int row; int col; - int off; int c; int i; @@ -8982,18 +8978,18 @@ f_screenchars(typval_T *argvars, typval_T *rettv) 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]; + 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 = ScreenLines[off]; + c = (*mb_ptr2char)(buf); 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]); + for (i = 0; i < Screen_mco && pcc[i] != 0; ++i) + list_append_number(rettv->vval.v_list, (varnumber_T)pcc[i]); } /* @@ -9024,11 +9020,7 @@ f_screenstring(typval_T *argvars, typval_T *rettv) { 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; @@ -9043,18 +9035,7 @@ f_screenstring(typval_T *argvars, typval_T *rettv) 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; + screen_getbytes(row, col, buf, NULL); rettv->vval.v_string = vim_strsave(buf); } @@ -9433,7 +9414,7 @@ f_searchpos(typval_T *argvars, typval_T *rettv) /* * Set the cursor or mark position. - * If 'charpos' is TRUE, then use the column number as a character offset. + * If "charpos" is TRUE, then use the column number as a character offset. * Otherwise use the column number as a byte offset. */ static void diff --git a/src/screen.c b/src/screen.c index e9bc79267b..7966f3b4d1 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1199,8 +1199,9 @@ screen_putchar(int c, int row, int col, int attr) } /* - * Get a single character directly from ScreenLines into "bytes[]". - * Also return its attribute in *attrp; + * 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,7 +1213,8 @@ screen_getbytes(int row, int col, char_u *bytes, int *attrp) return; off = LineOffset[row] + col; - *attrp = ScreenAttrs[off]; + if (attrp != NULL) + *attrp = ScreenAttrs[off]; bytes[0] = ScreenLines[off]; bytes[1] = NUL; diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 17a87d85e0..715da0b834 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3217,6 +3217,31 @@ func Test_screen_functions() 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() diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index 610566fd65..3bb7459797 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -135,6 +135,19 @@ func Test_screenchar_utf8() 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) diff --git a/src/version.c b/src/version.c index 11b962d7e0..320add580b 100644 --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1598, +/**/ 1597, /**/ 1596, |