summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-05-19 22:53:40 +0200
committerBram Moolenaar <Bram@vim.org>2019-05-19 22:53:40 +0200
commitf3333b02f34526da46cdae608f7e2d869bb8c654 (patch)
treebe05ce3393cee6644f8755f59dcdf4b3694dbc33
parent386b43e59498cc7b52a60f09f74bdb44df99386c (diff)
patch 8.1.1359: text property wrong after :substitute with backslashv8.1.1359
Problem: Text property wrong after :substitute with backslash. Solution: Adjust text property columns when removing backslashes. (closes #4397)
-rw-r--r--src/change.c2
-rw-r--r--src/edit.c2
-rw-r--r--src/ex_cmds.c20
-rw-r--r--src/misc1.c2
-rw-r--r--src/ops.c2
-rw-r--r--src/proto/textprop.pro2
-rw-r--r--src/testdir/test_textprop.vim19
-rw-r--r--src/textprop.c34
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h4
10 files changed, 72 insertions, 17 deletions
diff --git a/src/change.c b/src/change.c
index fa8c42538f..b43ba35745 100644
--- a/src/change.c
+++ b/src/change.c
@@ -684,7 +684,7 @@ inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED)
{
#ifdef FEAT_TEXT_PROP
if (curbuf->b_has_textprop && added != 0)
- adjust_prop_columns(lnum, col, added, FALSE);
+ adjust_prop_columns(lnum, col, added, 0);
#endif
changed_bytes(lnum, col);
diff --git a/src/edit.c b/src/edit.c
index be195fc1ae..8a008cbfd4 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -4104,7 +4104,7 @@ replace_do_bs(int limit_col)
--text_prop_frozen;
adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col,
- (int)(len_now - len_before), FALSE);
+ (int)(len_now - len_before), 0);
}
#endif
}
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index ff86d1cd47..df5dcd01ff 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -5189,7 +5189,7 @@ do_sub(exarg_T *eap)
int skip_match = FALSE;
linenr_T sub_firstlnum; /* nr of first sub line */
#ifdef FEAT_TEXT_PROP
- int save_for_undo = TRUE;
+ int apc_flags = APC_SAVE_FOR_UNDO | APC_SUBSTITUTE;
#endif
/*
@@ -5612,8 +5612,9 @@ do_sub(exarg_T *eap)
// undo first, unless done already.
if (adjust_prop_columns(lnum, regmatch.startpos[0].col,
sublen - 1 - (regmatch.endpos[0].col
- - regmatch.startpos[0].col), save_for_undo))
- save_for_undo = FALSE;
+ - regmatch.startpos[0].col),
+ apc_flags))
+ apc_flags &= ~APC_SAVE_FOR_UNDO;
}
#endif
}
@@ -5715,7 +5716,20 @@ do_sub(exarg_T *eap)
for (p1 = new_end; *p1; ++p1)
{
if (p1[0] == '\\' && p1[1] != NUL) /* remove backslash */
+ {
STRMOVE(p1, p1 + 1);
+#ifdef FEAT_TEXT_PROP
+ if (curbuf->b_has_textprop)
+ {
+ // When text properties are changed, need to save
+ // for undo first, unless done already.
+ if (adjust_prop_columns(lnum,
+ (colnr_T)(p1 - new_start), -1,
+ apc_flags))
+ apc_flags &= ~APC_SAVE_FOR_UNDO;
+ }
+#endif
+ }
else if (*p1 == CAR)
{
if (u_inssub(lnum) == OK) // prepare for undo
diff --git a/src/misc1.c b/src/misc1.c
index 1eac5189ae..e76e4a4a37 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -441,7 +441,7 @@ set_indent(
// the old indent, when decreasing indent it behaves like spaces
// were deleted at the new indent.
adjust_prop_columns(curwin->w_cursor.lnum,
- (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, FALSE);
+ (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, 0);
}
#endif
retval = TRUE;
diff --git a/src/ops.c b/src/ops.c
index a989ce2115..4d2692483b 100644
--- a/src/ops.c
+++ b/src/ops.c
@@ -1937,7 +1937,7 @@ op_delete(oparg_T *oap)
#ifdef FEAT_TEXT_PROP
if (curbuf->b_has_textprop && n != 0)
- adjust_prop_columns(lnum, bd.textcol, -n, FALSE);
+ adjust_prop_columns(lnum, bd.textcol, -n, 0);
#endif
}
diff --git a/src/proto/textprop.pro b/src/proto/textprop.pro
index 0114b4fadc..1301f31a51 100644
--- a/src/proto/textprop.pro
+++ b/src/proto/textprop.pro
@@ -13,7 +13,7 @@ void f_prop_type_get(typval_T *argvars, typval_T *rettv);
void f_prop_type_list(typval_T *argvars, typval_T *rettv);
void clear_global_prop_types(void);
void clear_buf_prop_types(buf_T *buf);
-int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int save_for_undo);
+int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int flags);
void adjust_props_for_split(linenr_T lnum_props, linenr_T lnum_top, int kept, int deleted);
void adjust_props_for_join(linenr_T lnum, textprop_T **prop_line, int *prop_length, long col, int removed);
void join_prop_lines(linenr_T lnum, char_u *newp, textprop_T **prop_lines, int *prop_lengths, int count);
diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim
index eb30c04c6c..08b93dfc94 100644
--- a/src/testdir/test_textprop.vim
+++ b/src/testdir/test_textprop.vim
@@ -620,6 +620,25 @@ func Test_prop_undo()
undo
let expected[0].col = 12
call assert_equal(expected, prop_list(1))
+ call prop_clear(1)
+
+ " substitute with backslash
+ call setline(1, 'the number 123 is highlighted.')
+ call prop_add(1, 12, {'length': 3, 'type': 'comment'})
+ let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
+ call assert_equal(expected, prop_list(1))
+ 1s/the/\The
+ call assert_equal(expected, prop_list(1))
+ 1s/^/\\
+ let expected[0].col += 1
+ call assert_equal(expected, prop_list(1))
+ 1s/^/\~
+ let expected[0].col += 1
+ call assert_equal(expected, prop_list(1))
+ 1s/123/12\\3
+ let expected[0].length += 1
+ call assert_equal(expected, prop_list(1))
+ call prop_clear(1)
bwipe!
call prop_type_delete('comment')
diff --git a/src/textprop.c b/src/textprop.c
index aa3e83b354..15ae4945b9 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -957,8 +957,9 @@ clear_buf_prop_types(buf_T *buf)
* shift by "bytes_added" (can be negative).
* Note that "col" is zero-based, while tp_col is one-based.
* Only for the current buffer.
- * When "save_for_undo" is TRUE then call u_savesub() before making changes to
- * the line.
+ * "flags" can have:
+ * APC_SAVE_FOR_UNDO: Call u_savesub() before making changes to the line.
+ * APC_SUBSTITUTE: Text is replaced, not inserted.
* Caller is expected to check b_has_textprop and "bytes_added" being non-zero.
* Returns TRUE when props were changed.
*/
@@ -967,7 +968,7 @@ adjust_prop_columns(
linenr_T lnum,
colnr_T col,
int bytes_added,
- int save_for_undo)
+ int flags)
{
int proplen;
char_u *props;
@@ -988,15 +989,30 @@ adjust_prop_columns(
wi = 0; // write index
for (ri = 0; ri < proplen; ++ri)
{
+ int start_incl;
+
mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T),
sizeof(textprop_T));
pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type);
+ start_incl = (flags & APC_SUBSTITUTE) ||
+ (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL));
if (bytes_added > 0
- ? (tmp_prop.tp_col >= col
- + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)
- ? 2 : 1))
- : (tmp_prop.tp_col > col + 1))
+ && (tmp_prop.tp_col >= col + (start_incl ? 2 : 1)))
+ {
+ if (tmp_prop.tp_col < col + (start_incl ? 2 : 1))
+ {
+ tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added;
+ tmp_prop.tp_col = col + 1;
+ }
+ else
+ tmp_prop.tp_col += bytes_added;
+ // Save for undo if requested and not done yet.
+ if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
+ u_savesub(lnum);
+ dirty = TRUE;
+ }
+ else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
{
if (tmp_prop.tp_col + bytes_added < col + 1)
{
@@ -1006,7 +1022,7 @@ adjust_prop_columns(
else
tmp_prop.tp_col += bytes_added;
// Save for undo if requested and not done yet.
- if (save_for_undo && !dirty)
+ if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
u_savesub(lnum);
dirty = TRUE;
if (tmp_prop.tp_len <= 0)
@@ -1024,7 +1040,7 @@ adjust_prop_columns(
else
tmp_prop.tp_len += bytes_added;
// Save for undo if requested and not done yet.
- if (save_for_undo && !dirty)
+ if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
u_savesub(lnum);
dirty = TRUE;
if (tmp_prop.tp_len <= 0)
diff --git a/src/version.c b/src/version.c
index 0cd0d7caf3..f9962a0cfd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1359,
+/**/
1358,
/**/
1357,
diff --git a/src/vim.h b/src/vim.h
index 05ad07ff6b..153a8c6ed9 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2571,4 +2571,8 @@ long elapsed(DWORD start_tick);
#define SAVE_RESTORE_ICON 2
#define SAVE_RESTORE_BOTH (SAVE_RESTORE_TITLE | SAVE_RESTORE_ICON)
+// Flags for adjust_prop_columns()
+#define APC_SAVE_FOR_UNDO 1 // call u_savesub() before making changes
+#define APC_SUBSTITUTE 2 // text is replaced, not inserted
+
#endif /* VIM__H */