aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval/funcs.c19
-rw-r--r--src/nvim/grid.c9
-rw-r--r--test/old/testdir/test_functions.vim28
-rw-r--r--test/old/testdir/test_utf8.vim15
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