0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.2.2324: not easy to get mark en cursor posotion by character count

Problem:    Not easy to get mark en cursor posotion by character count.
Solution:   Add functions that use character index. (Yegappan Lakshmanan,
            closes #7648)
This commit is contained in:
Bram Moolenaar
2021-01-10 20:22:54 +01:00
parent 31a11b942a
commit 6f02b00bb0
9 changed files with 668 additions and 190 deletions

View File

@@ -5053,6 +5053,61 @@ string2float(
}
#endif
/*
* Convert the specified byte index of line 'lnum' in buffer 'buf' to a
* character index. Works only for loaded buffers. Returns -1 on failure.
* The index of the first character is one.
*/
int
buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
{
char_u *str;
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return -1;
if (lnum > buf->b_ml.ml_line_count)
lnum = buf->b_ml.ml_line_count;
str = ml_get_buf(buf, lnum, FALSE);
if (str == NULL)
return -1;
if (*str == NUL)
return 1;
return mb_charlen_len(str, byteidx + 1);
}
/*
* Convert the specified character index of line 'lnum' in buffer 'buf' to a
* byte index. Works only for loaded buffers. Returns -1 on failure. The index
* of the first byte and the first character is one.
*/
int
buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
{
char_u *str;
char_u *t;
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return -1;
if (lnum > buf->b_ml.ml_line_count)
lnum = buf->b_ml.ml_line_count;
str = ml_get_buf(buf, lnum, FALSE);
if (str == NULL)
return -1;
// Convert the character offset to a byte offset
t = str;
while (*t != NUL && --charidx > 0)
t += mb_ptr2len(t);
return t - str + 1;
}
/*
* Translate a String variable into a position.
* Returns NULL when there is an error.
@@ -5061,7 +5116,8 @@ string2float(
var2fpos(
typval_T *varp,
int dollar_lnum, // TRUE when $ is last line
int *fnum) // set to fnum for '0, 'A, etc.
int *fnum, // set to fnum for '0, 'A, etc.
int charcol) // return character column
{
char_u *name;
static pos_T pos;
@@ -5083,7 +5139,10 @@ var2fpos(
pos.lnum = list_find_nr(l, 0L, &error);
if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count)
return NULL; // invalid line number
len = (long)STRLEN(ml_get(pos.lnum));
if (charcol)
len = (long)mb_charlen(ml_get(pos.lnum));
else
len = (long)STRLEN(ml_get(pos.lnum));
// Get the column number
// We accept "$" for the column number: last column.
@@ -5118,18 +5177,29 @@ var2fpos(
if (name == NULL)
return NULL;
if (name[0] == '.') // cursor
return &curwin->w_cursor;
{
pos = curwin->w_cursor;
if (charcol)
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
return &pos;
}
if (name[0] == 'v' && name[1] == NUL) // Visual start
{
if (VIsual_active)
return &VIsual;
return &curwin->w_cursor;
pos = VIsual;
else
pos = curwin->w_cursor;
if (charcol)
pos.col = buf_byteidx_to_charidx(curbuf, pos.lnum, pos.col) - 1;
return &pos;
}
if (name[0] == '\'') // mark
{
pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum);
if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
return NULL;
if (charcol)
pp->col = buf_byteidx_to_charidx(curbuf, pp->lnum, pp->col) - 1;
return pp;
}
@@ -5164,7 +5234,10 @@ var2fpos(
else
{
pos.lnum = curwin->w_cursor.lnum;
pos.col = (colnr_T)STRLEN(ml_get_curline());
if (charcol)
pos.col = (colnr_T)mb_charlen(ml_get_curline());
else
pos.col = (colnr_T)STRLEN(ml_get_curline());
}
return &pos;
}
@@ -5184,7 +5257,8 @@ list2fpos(
typval_T *arg,
pos_T *posp,
int *fnump,
colnr_T *curswantp)
colnr_T *curswantp,
int charcol)
{
list_T *l = arg->vval.v_list;
long i = 0;
@@ -5216,6 +5290,18 @@ list2fpos(
n = list_find_nr(l, i++, NULL); // col
if (n < 0)
return FAIL;
// If character position is specified, then convert to byte position
if (charcol)
{
buf_T *buf;
// Get the text for the specified line in a loaded buffer
buf = buflist_findnr(fnump == NULL ? curbuf->b_fnum : *fnump);
if (buf == NULL || buf->b_ml.ml_mfp == NULL)
return FAIL;
n = buf_charidx_to_byteidx(buf, posp->lnum, n);
}
posp->col = n;
n = list_find_nr(l, i, NULL); // off