mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.0.1598: screenchar() and others are wrong with DBCS 'encoding' (#23872)
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 vim/vim#12469)
47eec6716b
This commit is contained in:
parent
7ade44fefe
commit
a0375b68c1
@ -62,7 +62,7 @@
|
|||||||
#include "nvim/getchar.h"
|
#include "nvim/getchar.h"
|
||||||
#include "nvim/gettext.h"
|
#include "nvim/gettext.h"
|
||||||
#include "nvim/globals.h"
|
#include "nvim/globals.h"
|
||||||
#include "nvim/grid_defs.h"
|
#include "nvim/grid.h"
|
||||||
#include "nvim/hashtab.h"
|
#include "nvim/hashtab.h"
|
||||||
#include "nvim/highlight_defs.h"
|
#include "nvim/highlight_defs.h"
|
||||||
#include "nvim/highlight_group.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) {
|
if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) {
|
||||||
c = -1;
|
c = -1;
|
||||||
} else {
|
} 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;
|
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);
|
tv_list_alloc_ret(rettv, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char buf[MB_MAXBYTES + 1];
|
||||||
|
grid_getbytes(grid, row, col, buf, NULL);
|
||||||
int pcc[MAX_MCO];
|
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;
|
int composing_len = 0;
|
||||||
while (pcc[composing_len] != 0) {
|
while (composing_len < MAX_MCO && pcc[composing_len] != 0) {
|
||||||
composing_len++;
|
composing_len++;
|
||||||
}
|
}
|
||||||
tv_list_alloc_ret(rettv, composing_len + 1);
|
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;
|
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
|
/// "search()" function
|
||||||
@ -7201,7 +7208,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the cursor or mark position.
|
/// 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.
|
/// Otherwise use the column number as a byte offset.
|
||||||
static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
|
static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
|
||||||
{
|
{
|
||||||
|
@ -138,8 +138,9 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
|
|||||||
grid_puts(grid, buf, row, col, attr);
|
grid_puts(grid, buf, row, col, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a single character directly from grid.chars into "bytes[]".
|
/// Get a single character directly from grid.chars into "bytes", which must
|
||||||
/// Also return its attribute in *attrp;
|
/// 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)
|
void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp)
|
||||||
{
|
{
|
||||||
grid_adjust(&grid, &row, &col);
|
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;
|
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]);
|
schar_copy(bytes, grid->chars[off]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2834,6 +2834,34 @@ func Test_screen_functions()
|
|||||||
call assert_equal(-1, screenattr(-1, -1))
|
call assert_equal(-1, screenattr(-1, -1))
|
||||||
call assert_equal(-1, screenchar(-1, -1))
|
call assert_equal(-1, screenchar(-1, -1))
|
||||||
call assert_equal([], screenchars(-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
|
endfunc
|
||||||
|
|
||||||
" Test for getcurpos() and setpos()
|
" Test for getcurpos() and setpos()
|
||||||
|
@ -88,7 +88,20 @@ func Test_screenchar_utf8()
|
|||||||
call assert_equal("B", screenstring(1, 2))
|
call assert_equal("B", screenstring(1, 2))
|
||||||
call assert_equal("C\u0308", screenstring(1, 3))
|
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"
|
let text = "\u3042\u3044\u3046\u3099"
|
||||||
call setline(1, text)
|
call setline(1, text)
|
||||||
redraw
|
redraw
|
||||||
|
Loading…
Reference in New Issue
Block a user