diff options
-rw-r--r-- | src/nvim/eval/funcs.c | 19 | ||||
-rw-r--r-- | src/nvim/grid.c | 9 | ||||
-rw-r--r-- | test/old/testdir/test_functions.vim | 28 | ||||
-rw-r--r-- | test/old/testdir/test_utf8.vim | 15 |
4 files changed, 61 insertions, 10 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 927c1b3d5c..b4f9e4e219 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -62,7 +62,7 @@ #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" -#include "nvim/grid_defs.h" +#include "nvim/grid.h" #include "nvim/hashtab.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" @@ -6745,7 +6745,9 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col]); + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); + c = utf_ptr2char(buf); } rettv->vval.v_number = c; } @@ -6763,10 +6765,13 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_list_alloc_ret(rettv, 0); return; } + + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); int pcc[MAX_MCO]; - int c = utfc_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col], pcc); + int c = utfc_ptr2char(buf, pcc); int composing_len = 0; - while (pcc[composing_len] != 0) { + while (composing_len < MAX_MCO && pcc[composing_len] != 0) { composing_len++; } tv_list_alloc_ret(rettv, composing_len + 1); @@ -6806,7 +6811,9 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr return; } - rettv->vval.v_string = xstrdup((char *)grid->chars[grid->line_offset[row] + (size_t)col]); + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); + rettv->vval.v_string = xstrdup(buf); } /// "search()" function @@ -7201,7 +7208,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// 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 set_position(typval_T *argvars, typval_T *rettv, bool charpos) { diff --git a/src/nvim/grid.c b/src/nvim/grid.c index 76dd2a073a..aa542c5a2f 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -138,8 +138,9 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr) grid_puts(grid, buf, row, col, attr); } -/// get a single character directly from grid.chars into "bytes[]". -/// Also return its attribute in *attrp; +/// Get a single character directly from grid.chars into "bytes", which must +/// have a size of "MB_MAXBYTES + 1". +/// If "attrp" is not NULL, return the character's attribute in "*attrp". void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp) { grid_adjust(&grid, &row, &col); @@ -150,7 +151,9 @@ void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp) } size_t off = grid->line_offset[row] + (size_t)col; - *attrp = grid->attrs[off]; + if (attrp != NULL) { + *attrp = grid->attrs[off]; + } schar_copy(bytes, grid->chars[off]); } diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 41a8610893..177fef9e99 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -2834,6 +2834,34 @@ 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 + if has('nvim') + let encodings = ['utf-8'] + 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/test/old/testdir/test_utf8.vim b/test/old/testdir/test_utf8.vim index 00b060a9e2..a5a9624ec3 100644 --- a/test/old/testdir/test_utf8.vim +++ b/test/old/testdir/test_utf8.vim @@ -88,7 +88,20 @@ func Test_screenchar_utf8() call assert_equal("B", screenstring(1, 2)) call assert_equal("C\u0308", screenstring(1, 3)) - " 2-cells, with composing characters + " 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) redraw |