# HG changeset patch # User Bram Moolenaar # Date 1546470054 -3600 # Node ID 6abee072b93c369c25429f2f90051349aaff9ab2 # Parent 24c31bd03f3aa60bc8e7a9af7c4f3cf53c18374f patch 8.1.0682: text properties not adjusted when backspacing replaced text commit https://github.com/vim/vim/commit/196d157f12cf0476d97f78834155fc67d6b161de Author: Bram Moolenaar Date: Wed Jan 2 23:47:18 2019 +0100 patch 8.1.0682: text properties not adjusted when backspacing replaced text Problem: Text properties are not adjusted when backspacing replaced text. Solution: Keep text properties on text restored in replace mode. diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -7962,6 +7962,17 @@ replace_do_bs(int limit_col) cc = replace_pop(); if (cc > 0) { +#ifdef FEAT_TEXT_PROP + size_t len_before; + + if (curbuf->b_has_textprop) + { + // Do not adjust text properties for individual delete and insert + // operations, do it afterwards on the resulting text. + len_before = STRLEN(ml_get_curline()); + ++text_prop_frozen; + } +#endif if (State & VREPLACE_FLAG) { /* Get the number of screen cells used by the character we are @@ -8012,8 +8023,19 @@ replace_do_bs(int limit_col) curwin->w_cursor.col -= ins_len; } - /* mark the buffer as changed and prepare for displaying */ + // mark the buffer as changed and prepare for displaying changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); + +#ifdef FEAT_TEXT_PROP + if (curbuf->b_has_textprop) + { + size_t len_now = STRLEN(ml_get_curline()); + + --text_prop_frozen; + adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col, + (int)(len_now - len_before)); + } +#endif } else if (cc == 0) (void)del_char_after_col(limit_col); diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -1658,6 +1658,10 @@ EXTERN int *eval_lavars_used INIT(= NULL EXTERN int ctrl_break_was_pressed INIT(= FALSE); #endif +#ifdef FEAT_TEXT_PROP +EXTERN int text_prop_frozen INIT(= 0); +#endif + /* * Optional Farsi support. Include it here, so EXTERN and INIT are defined. */ diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -145,6 +145,19 @@ func Test_prop_remove() bwipe! endfunc +func SetupOneLine() + call setline(1, 'xonex xtwoxx') + call AddPropTypes() + call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'}) + call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'}) + let expected = [ + \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, + \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, + \] + call assert_equal(expected, prop_list(1)) + return expected +endfunc + func Test_prop_add_remove_buf() new let bufnr = bufnr('') @@ -180,15 +193,7 @@ endfunc func Test_prop_backspace() new set bs=2 - call setline(1, 'xonex xtwoxx') - call AddPropTypes() - call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'}) - call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'}) - let expected = [ - \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, - \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, - \] - call assert_equal(expected, prop_list(1)) + let expected = SetupOneLine() " 'xonex xtwoxx' exe "normal 0li\\fxli\\" call assert_equal('one xtwoxx', getline(1)) @@ -201,6 +206,32 @@ func Test_prop_backspace() set bs& endfunc +func Test_prop_replace() + new + set bs=2 + let expected = SetupOneLine() " 'xonex xtwoxx' + + exe "normal 0Ryyy\" + call assert_equal('yyyex xtwoxx', getline(1)) + call assert_equal(expected, prop_list(1)) + + exe "normal ftRyy\" + call assert_equal('yyyex xywoxx', getline(1)) + call assert_equal(expected, prop_list(1)) + + exe "normal 0fwRyy\" + call assert_equal('yyyex xyyoxx', getline(1)) + call assert_equal(expected, prop_list(1)) + + exe "normal 0foRyy\\" + call assert_equal('yyyex xyyoxx', getline(1)) + call assert_equal(expected, prop_list(1)) + + call DeletePropTypes() + bwipe! + set bs& +endfunc + func Test_prop_clear() new call AddPropTypes() diff --git a/src/textprop.c b/src/textprop.c --- a/src/textprop.c +++ b/src/textprop.c @@ -920,41 +920,59 @@ clear_buf_prop_types(buf_T *buf) * Called is expected to check b_has_textprop and "bytes_added" being non-zero. */ void -adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added) +adjust_prop_columns( + linenr_T lnum, + colnr_T col, + int bytes_added) { int proplen; char_u *props; textprop_T tmp_prop; proptype_T *pt; int dirty = FALSE; - int i; + int ri, wi; + size_t textlen; + + if (text_prop_frozen > 0) + return; proplen = get_text_props(curbuf, lnum, &props, TRUE); if (proplen == 0) return; + textlen = curbuf->b_ml.ml_line_len - proplen * sizeof(textprop_T); - for (i = 0; i < proplen; ++i) + wi = 0; // write index + for (ri = 0; ri < proplen; ++ri) { - mch_memmove(&tmp_prop, props + i * sizeof(textprop_T), + mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T), sizeof(textprop_T)); pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type); - if (tmp_prop.tp_col >= col + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL) ? 2 : 1)) + 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 += bytes_added; dirty = TRUE; } - else if (tmp_prop.tp_col + tmp_prop.tp_len > col + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL) ? 0 : 1)) + else if (tmp_prop.tp_len > 0 + && tmp_prop.tp_col + tmp_prop.tp_len > col + + ((pt != NULL && (pt->pt_flags & PT_FLAG_INS_END_INCL)) + ? 0 : 1)) { tmp_prop.tp_len += bytes_added; dirty = TRUE; + if (tmp_prop.tp_len <= 0) + continue; // drop this text property } - if (dirty) - { - curbuf->b_ml.ml_flags |= ML_LINE_DIRTY; - mch_memmove(props + i * sizeof(textprop_T), &tmp_prop, + mch_memmove(props + wi * sizeof(textprop_T), &tmp_prop, sizeof(textprop_T)); - } + ++wi; + } + if (dirty) + { + curbuf->b_ml.ml_flags |= ML_LINE_DIRTY; + curbuf->b_ml.ml_line_len = textlen + wi * sizeof(textprop_T); } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -800,6 +800,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 682, +/**/ 681, /**/ 680,