forked from aniani/vim
patch 8.1.0655: when appending a line text property flags are not added
Problem: When appending a line text property flags are not added. Solution: Add text properties to a newly added line.
This commit is contained in:
120
src/memline.c
120
src/memline.c
@@ -2568,6 +2568,66 @@ ml_line_alloced(void)
|
|||||||
return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
|
return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
static void
|
||||||
|
add_text_props_for_append(
|
||||||
|
buf_T *buf,
|
||||||
|
linenr_T lnum,
|
||||||
|
char_u **line,
|
||||||
|
int *len,
|
||||||
|
char_u **tofree)
|
||||||
|
{
|
||||||
|
int round;
|
||||||
|
int new_prop_count = 0;
|
||||||
|
int count;
|
||||||
|
int n;
|
||||||
|
char_u *props;
|
||||||
|
int new_len;
|
||||||
|
char_u *new_line;
|
||||||
|
textprop_T prop;
|
||||||
|
|
||||||
|
// Make two rounds:
|
||||||
|
// 1. calculate the extra space needed
|
||||||
|
// 2. allocate the space and fill it
|
||||||
|
for (round = 1; round <= 2; ++round)
|
||||||
|
{
|
||||||
|
if (round == 2)
|
||||||
|
{
|
||||||
|
if (new_prop_count == 0)
|
||||||
|
return; // nothing to do
|
||||||
|
new_len = *len + new_prop_count * sizeof(textprop_T);
|
||||||
|
new_line = alloc((unsigned)new_len);
|
||||||
|
if (new_line == NULL)
|
||||||
|
return;
|
||||||
|
mch_memmove(new_line, *line, *len);
|
||||||
|
new_prop_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the line above to find any props that continue in the next
|
||||||
|
// line.
|
||||||
|
count = get_text_props(buf, lnum, &props, FALSE);
|
||||||
|
for (n = 0; n < count; ++n)
|
||||||
|
{
|
||||||
|
mch_memmove(&prop, props + n * sizeof(textprop_T), sizeof(textprop_T));
|
||||||
|
if (prop.tp_flags & TP_FLAG_CONT_NEXT)
|
||||||
|
{
|
||||||
|
if (round == 2)
|
||||||
|
{
|
||||||
|
prop.tp_flags |= TP_FLAG_CONT_PREV;
|
||||||
|
prop.tp_col = 1;
|
||||||
|
prop.tp_len = *len;
|
||||||
|
mch_memmove(new_line + *len + new_prop_count * sizeof(textprop_T), &prop, sizeof(textprop_T));
|
||||||
|
}
|
||||||
|
++new_prop_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*line = new_line;
|
||||||
|
*tofree = new_line;
|
||||||
|
*len = new_len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append a line after lnum (may be 0 to insert a line in front of the file).
|
* Append a line after lnum (may be 0 to insert a line in front of the file).
|
||||||
* "line" does not need to be allocated, but can't be another line in a
|
* "line" does not need to be allocated, but can't be another line in a
|
||||||
@@ -2622,12 +2682,13 @@ ml_append_buf(
|
|||||||
ml_append_int(
|
ml_append_int(
|
||||||
buf_T *buf,
|
buf_T *buf,
|
||||||
linenr_T lnum, // append after this line (can be 0)
|
linenr_T lnum, // append after this line (can be 0)
|
||||||
char_u *line, // text of the new line
|
char_u *line_arg, // text of the new line
|
||||||
colnr_T len_arg, // length of line, including NUL, or 0
|
colnr_T len_arg, // length of line, including NUL, or 0
|
||||||
int newfile, // flag, see above
|
int newfile, // flag, see above
|
||||||
int mark) // mark the new line
|
int mark) // mark the new line
|
||||||
{
|
{
|
||||||
colnr_T len = len_arg; // length of line, including NUL, or 0
|
char_u *line = line_arg;
|
||||||
|
colnr_T len = len_arg;
|
||||||
int i;
|
int i;
|
||||||
int line_count; // number of indexes in current block
|
int line_count; // number of indexes in current block
|
||||||
int offset;
|
int offset;
|
||||||
@@ -2641,16 +2702,26 @@ ml_append_int(
|
|||||||
DATA_BL *dp;
|
DATA_BL *dp;
|
||||||
PTR_BL *pp;
|
PTR_BL *pp;
|
||||||
infoptr_T *ip;
|
infoptr_T *ip;
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
char_u *tofree = NULL;
|
||||||
|
#endif
|
||||||
|
int ret = FAIL;
|
||||||
|
|
||||||
/* lnum out of range */
|
|
||||||
if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
|
if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL)
|
||||||
return FAIL;
|
return FAIL; // lnum out of range
|
||||||
|
|
||||||
if (lowest_marked && lowest_marked > lnum)
|
if (lowest_marked && lowest_marked > lnum)
|
||||||
lowest_marked = lnum + 1;
|
lowest_marked = lnum + 1;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
len = (colnr_T)STRLEN(line) + 1; // space needed for the text
|
len = (colnr_T)STRLEN(line) + 1; // space needed for the text
|
||||||
|
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
if (curbuf->b_has_textprop && lnum > 0)
|
||||||
|
// Add text properties that continue from the previous line.
|
||||||
|
add_text_props_for_append(buf, lnum, &line, &len, &tofree);
|
||||||
|
#endif
|
||||||
|
|
||||||
space_needed = len + INDEX_SIZE; // space needed for text + index
|
space_needed = len + INDEX_SIZE; // space needed for text + index
|
||||||
|
|
||||||
mfp = buf->b_ml.ml_mfp;
|
mfp = buf->b_ml.ml_mfp;
|
||||||
@@ -2663,7 +2734,7 @@ ml_append_int(
|
|||||||
*/
|
*/
|
||||||
if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
|
if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum,
|
||||||
ML_INSERT)) == NULL)
|
ML_INSERT)) == NULL)
|
||||||
return FAIL;
|
goto theend;
|
||||||
|
|
||||||
buf->b_ml.ml_flags &= ~ML_EMPTY;
|
buf->b_ml.ml_flags &= ~ML_EMPTY;
|
||||||
|
|
||||||
@@ -2694,7 +2765,7 @@ ml_append_int(
|
|||||||
--(buf->b_ml.ml_locked_lineadd);
|
--(buf->b_ml.ml_locked_lineadd);
|
||||||
--(buf->b_ml.ml_locked_high);
|
--(buf->b_ml.ml_locked_high);
|
||||||
if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
|
if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
|
||||||
return FAIL;
|
goto theend;
|
||||||
|
|
||||||
db_idx = -1; /* careful, it is negative! */
|
db_idx = -1; /* careful, it is negative! */
|
||||||
/* get line count before the insertion */
|
/* get line count before the insertion */
|
||||||
@@ -2708,8 +2779,9 @@ ml_append_int(
|
|||||||
|
|
||||||
if ((int)dp->db_free >= space_needed) /* enough room in data block */
|
if ((int)dp->db_free >= space_needed) /* enough room in data block */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Insert new line in existing data block, or in data block allocated above.
|
* Insert the new line in an existing data block, or in the data block
|
||||||
|
* allocated above.
|
||||||
*/
|
*/
|
||||||
dp->db_txt_start -= len;
|
dp->db_txt_start -= len;
|
||||||
dp->db_free -= space_needed;
|
dp->db_free -= space_needed;
|
||||||
@@ -2756,15 +2828,6 @@ ml_append_int(
|
|||||||
}
|
}
|
||||||
else /* not enough space in data block */
|
else /* not enough space in data block */
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* If there is not enough room we have to create a new data block and copy some
|
|
||||||
* lines into it.
|
|
||||||
* Then we have to insert an entry in the pointer block.
|
|
||||||
* If this pointer block also is full, we go up another block, and so on, up
|
|
||||||
* to the root if necessary.
|
|
||||||
* The line counts in the pointer blocks have already been adjusted by
|
|
||||||
* ml_find_line().
|
|
||||||
*/
|
|
||||||
long line_count_left, line_count_right;
|
long line_count_left, line_count_right;
|
||||||
int page_count_left, page_count_right;
|
int page_count_left, page_count_right;
|
||||||
bhdr_T *hp_left;
|
bhdr_T *hp_left;
|
||||||
@@ -2783,6 +2846,14 @@ ml_append_int(
|
|||||||
PTR_BL *pp_new;
|
PTR_BL *pp_new;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* There is not enough room, we have to create a new data block and
|
||||||
|
* copy some lines into it.
|
||||||
|
* Then we have to insert an entry in the pointer block.
|
||||||
|
* If this pointer block also is full, we go up another block, and so
|
||||||
|
* on, up to the root if necessary.
|
||||||
|
* The line counts in the pointer blocks have already been adjusted by
|
||||||
|
* ml_find_line().
|
||||||
|
*
|
||||||
* We are going to allocate a new data block. Depending on the
|
* We are going to allocate a new data block. Depending on the
|
||||||
* situation it will be put to the left or right of the existing
|
* situation it will be put to the left or right of the existing
|
||||||
* block. If possible we put the new line in the left block and move
|
* block. If possible we put the new line in the left block and move
|
||||||
@@ -2826,7 +2897,7 @@ ml_append_int(
|
|||||||
/* correct line counts in pointer blocks */
|
/* correct line counts in pointer blocks */
|
||||||
--(buf->b_ml.ml_locked_lineadd);
|
--(buf->b_ml.ml_locked_lineadd);
|
||||||
--(buf->b_ml.ml_locked_high);
|
--(buf->b_ml.ml_locked_high);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
if (db_idx < 0) /* left block is new */
|
if (db_idx < 0) /* left block is new */
|
||||||
{
|
{
|
||||||
@@ -2951,13 +3022,13 @@ ml_append_int(
|
|||||||
ip = &(buf->b_ml.ml_stack[stack_idx]);
|
ip = &(buf->b_ml.ml_stack[stack_idx]);
|
||||||
pb_idx = ip->ip_index;
|
pb_idx = ip->ip_index;
|
||||||
if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
|
if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
|
||||||
return FAIL;
|
goto theend;
|
||||||
pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
|
pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */
|
||||||
if (pp->pb_id != PTR_ID)
|
if (pp->pb_id != PTR_ID)
|
||||||
{
|
{
|
||||||
IEMSG(_("E317: pointer block id wrong 3"));
|
IEMSG(_("E317: pointer block id wrong 3"));
|
||||||
mf_put(mfp, hp, FALSE, FALSE);
|
mf_put(mfp, hp, FALSE, FALSE);
|
||||||
return FAIL;
|
goto theend;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* TODO: If the pointer block is full and we are adding at the end
|
* TODO: If the pointer block is full and we are adding at the end
|
||||||
@@ -3014,7 +3085,7 @@ ml_append_int(
|
|||||||
{
|
{
|
||||||
hp_new = ml_new_ptr(mfp);
|
hp_new = ml_new_ptr(mfp);
|
||||||
if (hp_new == NULL) /* TODO: try to fix tree */
|
if (hp_new == NULL) /* TODO: try to fix tree */
|
||||||
return FAIL;
|
goto theend;
|
||||||
pp_new = (PTR_BL *)(hp_new->bh_data);
|
pp_new = (PTR_BL *)(hp_new->bh_data);
|
||||||
|
|
||||||
if (hp->bh_bnum != 1)
|
if (hp->bh_bnum != 1)
|
||||||
@@ -3119,8 +3190,13 @@ ml_append_int(
|
|||||||
if (buf->b_write_to_channel)
|
if (buf->b_write_to_channel)
|
||||||
channel_write_new_lines(buf);
|
channel_write_new_lines(buf);
|
||||||
#endif
|
#endif
|
||||||
|
ret = OK;
|
||||||
|
|
||||||
return OK;
|
theend:
|
||||||
|
#ifdef FEAT_TEXT_PROP
|
||||||
|
vim_free(tofree);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -257,6 +257,16 @@ func Test_prop_multiline()
|
|||||||
call assert_equal([expect_short], prop_list(4))
|
call assert_equal([expect_short], prop_list(4))
|
||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
|
" Test appending a line below the text prop start.
|
||||||
|
call Setup_three_line_prop()
|
||||||
|
let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0}
|
||||||
|
call assert_equal([expect2], prop_list(2))
|
||||||
|
call append(2, "new line")
|
||||||
|
call assert_equal([expect2], prop_list(2))
|
||||||
|
let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0}
|
||||||
|
call assert_equal([expect3], prop_list(3))
|
||||||
|
bwipe!
|
||||||
|
|
||||||
call prop_type_delete('comment')
|
call prop_type_delete('comment')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
@@ -17,14 +17,12 @@
|
|||||||
* 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
|
* - Perhaps we only need TP_FLAG_CONT_NEXT ?
|
||||||
* - Let props overrule syntax HL.
|
* - Adjust text property column and length when text is inserted/deleted
|
||||||
* - When deleting a line where a prop ended, adjust flag of previous line.
|
* - Add an arrray for global_proptypes, to quickly lookup a prop type by ID
|
||||||
* - When deleting a line where a prop started, adjust flag of next line.
|
* - Add an arrray for b_proptypes, to quickly lookup a prop type by ID
|
||||||
* - When inserting a line add props that continue from previous line.
|
* - Checking the text length to detect text properties is slow. Use a flag in
|
||||||
* - Adjust property column and length when text is inserted/deleted
|
* the index, like DB_MARKED?
|
||||||
* - 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
|
|
||||||
* - Also test line2byte() with many lines, so that ml_updatechunk() is taken
|
* - Also test line2byte() with many lines, so that ml_updatechunk() is taken
|
||||||
* into account.
|
* into account.
|
||||||
* - add mechanism to keep track of changed lines.
|
* - add mechanism to keep track of changed lines.
|
||||||
|
@@ -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 */
|
||||||
|
/**/
|
||||||
|
655,
|
||||||
/**/
|
/**/
|
||||||
654,
|
654,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user