mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.0636: line2byte() gives wrong values with text properties
Problem: line2byte() gives wrong values with text properties. (Bjorn Linse) Solution: Compute byte offsets differently when text properties were added. (closes #3718)
This commit is contained in:
parent
e38197d50f
commit
b413d2e6a8
@ -3179,14 +3179,14 @@ ml_replace_len(linenr_T lnum, char_u *line_arg, colnr_T len_arg, int copy)
|
|||||||
curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
|
curbuf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (has_any_text_properties(curbuf))
|
if (curbuf->b_has_textprop)
|
||||||
// Need to fetch the old line to copy over any text properties.
|
// Need to fetch the old line to copy over any text properties.
|
||||||
ml_get_buf(curbuf, lnum, TRUE);
|
ml_get_buf(curbuf, lnum, TRUE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
if (has_any_text_properties(curbuf))
|
if (curbuf->b_has_textprop)
|
||||||
{
|
{
|
||||||
size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
|
size_t oldtextlen = STRLEN(curbuf->b_ml.ml_line_ptr) + 1;
|
||||||
|
|
||||||
@ -5131,6 +5131,7 @@ ml_updatechunk(
|
|||||||
{
|
{
|
||||||
int count; /* number of entries in block */
|
int count; /* number of entries in block */
|
||||||
int idx;
|
int idx;
|
||||||
|
int end_idx;
|
||||||
int text_end;
|
int text_end;
|
||||||
int linecnt;
|
int linecnt;
|
||||||
|
|
||||||
@ -5154,23 +5155,39 @@ ml_updatechunk(
|
|||||||
(long)(buf->b_ml.ml_locked_low) + 1;
|
(long)(buf->b_ml.ml_locked_low) + 1;
|
||||||
idx = curline - buf->b_ml.ml_locked_low;
|
idx = curline - buf->b_ml.ml_locked_low;
|
||||||
curline = buf->b_ml.ml_locked_high + 1;
|
curline = buf->b_ml.ml_locked_high + 1;
|
||||||
if (idx == 0)/* first line in block, text at the end */
|
|
||||||
text_end = dp->db_txt_end;
|
// compute index of last line to use in this MEMLINE
|
||||||
else
|
|
||||||
text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
|
|
||||||
/* Compute index of last line to use in this MEMLINE */
|
|
||||||
rest = count - idx;
|
rest = count - idx;
|
||||||
if (linecnt + rest > MLCS_MINL)
|
if (linecnt + rest > MLCS_MINL)
|
||||||
{
|
{
|
||||||
idx += MLCS_MINL - linecnt - 1;
|
end_idx = idx + MLCS_MINL - linecnt - 1;
|
||||||
linecnt = MLCS_MINL;
|
linecnt = MLCS_MINL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
idx = count - 1;
|
end_idx = count - 1;
|
||||||
linecnt += rest;
|
linecnt += rest;
|
||||||
}
|
}
|
||||||
size += text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (buf->b_has_textprop)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// We cannot use the text pointers to get the text length,
|
||||||
|
// the text prop info would also be counted. Go over the
|
||||||
|
// lines.
|
||||||
|
for (i = end_idx; i < idx; ++i)
|
||||||
|
size += STRLEN((char_u *)dp + (dp->db_index[i] & DB_INDEX_MASK)) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (idx == 0)/* first line in block, text at the end */
|
||||||
|
text_end = dp->db_txt_end;
|
||||||
|
else
|
||||||
|
text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK);
|
||||||
|
size += text_end - ((dp->db_index[end_idx]) & DB_INDEX_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt;
|
buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt;
|
||||||
buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt;
|
buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt;
|
||||||
@ -5360,7 +5377,20 @@ ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp)
|
|||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (buf->b_has_textprop)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// cannot use the db_index pointer, need to get the actual text
|
||||||
|
// lengths.
|
||||||
|
len = 0;
|
||||||
|
for (i = start_idx; i <= idx; ++i)
|
||||||
|
len += STRLEN((char_u *)dp + ((dp->db_index[idx]) & DB_INDEX_MASK)) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK);
|
||||||
size += len;
|
size += len;
|
||||||
if (offset != 0 && size >= offset)
|
if (offset != 0 && size >= offset)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* textprop.c */
|
/* textprop.c */
|
||||||
void f_prop_add(typval_T *argvars, typval_T *rettv);
|
void f_prop_add(typval_T *argvars, typval_T *rettv);
|
||||||
int has_any_text_properties(buf_T *buf);
|
|
||||||
int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
|
int get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change);
|
||||||
proptype_T *text_prop_type_by_id(buf_T *buf, int id);
|
proptype_T *text_prop_type_by_id(buf_T *buf, int id);
|
||||||
void f_prop_clear(typval_T *argvars, typval_T *rettv);
|
void f_prop_clear(typval_T *argvars, typval_T *rettv);
|
||||||
|
@ -2411,7 +2411,8 @@ struct file_buffer
|
|||||||
dict_T *b_vars; /* internal variables, local to buffer */
|
dict_T *b_vars; /* internal variables, local to buffer */
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
hashtab_T *b_proptypes; /* text property types local to buffer */
|
int b_has_textprop; // TRUE when text props were added
|
||||||
|
hashtab_T *b_proptypes; // text property types local to buffer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
|
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
|
||||||
|
@ -226,5 +226,17 @@ func Test_prop_multiline()
|
|||||||
call prop_type_delete('comment')
|
call prop_type_delete('comment')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_prop_byteoff()
|
||||||
|
call prop_type_add('comment', {'highlight': 'Directory'})
|
||||||
|
new
|
||||||
|
call setline(1, ['line1', 'line2', ''])
|
||||||
|
call assert_equal(13, line2byte(3))
|
||||||
|
call prop_add(1, 1, {'end_col': 3, 'type': 'comment'})
|
||||||
|
call assert_equal(13, line2byte(3))
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
call prop_type_delete('comment')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
" TODO: screenshot test with highlighting
|
" TODO: screenshot test with highlighting
|
||||||
|
@ -17,12 +17,16 @@
|
|||||||
* Text properties have a type, which can be used to specify highlighting.
|
* Text properties have a type, which can be used to specify highlighting.
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
|
* - mismatch in column 1 being the first column
|
||||||
|
* - Let props overrule syntax HL.
|
||||||
* - When deleting a line where a prop ended, adjust flag of previous line.
|
* - When deleting a line where a prop ended, adjust flag of previous line.
|
||||||
* - When deleting a line where a prop started, adjust flag of next line.
|
* - When deleting a line where a prop started, adjust flag of next line.
|
||||||
* - When inserting a line add props that continue from previous line.
|
* - When inserting a line add props that continue from previous line.
|
||||||
* - Adjust property column and length when text is inserted/deleted
|
* - Adjust property column and length when text is inserted/deleted
|
||||||
* - Add an arrray for global_proptypes, to quickly lookup a proptype by ID
|
* - Add an arrray for global_proptypes, to quickly lookup a proptype by ID
|
||||||
* - Add an arrray for b_proptypes, to quickly lookup a proptype by ID
|
* - Add an arrray for b_proptypes, to quickly lookup a proptype by ID
|
||||||
|
* - Also test line2byte() with many lines, so that ml_updatechunk() is taken
|
||||||
|
* into account.
|
||||||
* - add mechanism to keep track of changed lines.
|
* - add mechanism to keep track of changed lines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -261,7 +265,7 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
length = end_col - col + 1;
|
length = end_col - col + 1;
|
||||||
else
|
else
|
||||||
length = textlen - col + 1;
|
length = textlen - col + 1;
|
||||||
if (length > textlen)
|
if (length > (long)textlen)
|
||||||
length = textlen; // can include the end-of-line
|
length = textlen; // can include the end-of-line
|
||||||
if (length < 1)
|
if (length < 1)
|
||||||
length = 1;
|
length = 1;
|
||||||
@ -308,19 +312,10 @@ f_prop_add(typval_T *argvars, typval_T *rettv UNUSED)
|
|||||||
buf->b_ml.ml_flags |= ML_LINE_DIRTY;
|
buf->b_ml.ml_flags |= ML_LINE_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf->b_has_textprop = TRUE; // this is never reset
|
||||||
redraw_buf_later(buf, NOT_VALID);
|
redraw_buf_later(buf, NOT_VALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return TRUE if any text properties are defined globally or for buffer
|
|
||||||
* "buf".
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
has_any_text_properties(buf_T *buf)
|
|
||||||
{
|
|
||||||
return buf->b_proptypes != NULL || global_proptypes != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the text properties for line "lnum" in buffer "buf".
|
* Fetch the text properties for line "lnum" in buffer "buf".
|
||||||
* Returns the number of text properties and, when non-zero, a pointer to the
|
* Returns the number of text properties and, when non-zero, a pointer to the
|
||||||
@ -334,8 +329,9 @@ get_text_props(buf_T *buf, linenr_T lnum, char_u **props, int will_change)
|
|||||||
size_t textlen;
|
size_t textlen;
|
||||||
size_t proplen;
|
size_t proplen;
|
||||||
|
|
||||||
// Be quick when no text property types are defined.
|
// Be quick when no text property types have been defined or the buffer,
|
||||||
if (!has_any_text_properties(buf))
|
// unless we are adding one.
|
||||||
|
if (!buf->b_has_textprop && !will_change)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Fetch the line to get the ml_line_len field updated.
|
// Fetch the line to get the ml_line_len field updated.
|
||||||
|
@ -799,6 +799,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
636,
|
||||||
/**/
|
/**/
|
||||||
635,
|
635,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user