comparison src/textprop.c @ 16662:1fc9cd08cf3c v8.1.1333

patch 8.1.1333: text properties don't always move after changes commit https://github.com/vim/vim/commit/45dd07f10af9bea86f8df77e92788209e209fdab Author: Bram Moolenaar <Bram@vim.org> Date: Wed May 15 22:45:37 2019 +0200 patch 8.1.1333: text properties don't always move after changes Problem: Text properties don't always move after changes. Solution: Update properties before reporting changes to listeners. Move text property when splitting a line.
author Bram Moolenaar <Bram@vim.org>
date Wed, 15 May 2019 23:00:15 +0200
parents 08557bad0b9d
children 5733d8e33bce
comparison
equal deleted inserted replaced
16661:0e9c064b096c 16662:1fc9cd08cf3c
6 * Do ":help credits" in Vim to see a list of people who contributed. 6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code. 7 * See README.txt for an overview of the Vim source code.
8 */ 8 */
9 9
10 /* 10 /*
11 * Text properties implementation. 11 * Text properties implementation. See ":help text-properties".
12 *
13 * Text properties are attached to the text. They move with the text when
14 * text is inserted/deleted.
15 *
16 * Text properties have a user specified ID number, which can be unique.
17 * Text properties have a type, which can be used to specify highlighting.
18 * 12 *
19 * TODO: 13 * TODO:
20 * - When using 'cursorline' attributes should be merged. (#3912) 14 * - When using 'cursorline' attributes should be merged. (#3912)
21 * - Adjust text property column and length when text is inserted/deleted. 15 * - Adjust text property column and length when text is inserted/deleted.
16 * -> splitting a line can create a zero-length property. Don't highlight it
17 * and extend it when inserting text.
22 * -> a :substitute with a multi-line match 18 * -> a :substitute with a multi-line match
19 * -> join two lines, also with BS in Insert mode
23 * -> search for changed_bytes() from misc1.c 20 * -> search for changed_bytes() from misc1.c
24 * - Perhaps we only need TP_FLAG_CONT_NEXT and can drop TP_FLAG_CONT_PREV? 21 * - Perhaps we only need TP_FLAG_CONT_NEXT and can drop TP_FLAG_CONT_PREV?
25 * - Add an arrray for global_proptypes, to quickly lookup a prop type by ID 22 * - Add an arrray for global_proptypes, to quickly lookup a prop type by ID
26 * - Add an arrray for b_proptypes, to quickly lookup a prop type by ID 23 * - Add an arrray for b_proptypes, to quickly lookup a prop type by ID
27 * - Checking the text length to detect text properties is slow. Use a flag in 24 * - Checking the text length to detect text properties is slow. Use a flag in
28 * the index, like DB_MARKED? 25 * the index, like DB_MARKED?
29 * - Also test line2byte() with many lines, so that ml_updatechunk() is taken 26 * - Also test line2byte() with many lines, so that ml_updatechunk() is taken
30 * into account. 27 * into account.
31 * - Add mechanism to keep track of changed lines, so that plugin can update
32 * text properties in these.
33 * - Perhaps have a window-local option to disable highlighting from text 28 * - Perhaps have a window-local option to disable highlighting from text
34 * properties? 29 * properties?
35 */ 30 */
36 31
37 #include "vim.h" 32 #include "vim.h"
1031 } 1026 }
1032 } 1027 }
1033 1028
1034 /* 1029 /*
1035 * Adjust text properties for a line that was split in two. 1030 * Adjust text properties for a line that was split in two.
1036 * "lnum" is the newly inserted line. The text properties are now on the line 1031 * "lnum_props" is the line that has the properties from before the split.
1037 * below it. "kept" is the number of bytes kept in the first line, while 1032 * "lnum_top" is the top line.
1033 * "kept" is the number of bytes kept in the first line, while
1038 * "deleted" is the number of bytes deleted. 1034 * "deleted" is the number of bytes deleted.
1039 */ 1035 */
1040 void 1036 void
1041 adjust_props_for_split(linenr_T lnum, int kept, int deleted) 1037 adjust_props_for_split(
1038 linenr_T lnum_props,
1039 linenr_T lnum_top,
1040 int kept,
1041 int deleted)
1042 { 1042 {
1043 char_u *props; 1043 char_u *props;
1044 int count; 1044 int count;
1045 garray_T prevprop; 1045 garray_T prevprop;
1046 garray_T nextprop; 1046 garray_T nextprop;
1047 int i; 1047 int i;
1048 int skipped = kept + deleted; 1048 int skipped = kept + deleted;
1049 1049
1050 if (!curbuf->b_has_textprop) 1050 if (!curbuf->b_has_textprop)
1051 return; 1051 return;
1052 count = get_text_props(curbuf, lnum + 1, &props, FALSE); 1052
1053 // Get the text properties from "lnum_props".
1054 count = get_text_props(curbuf, lnum_props, &props, FALSE);
1053 ga_init2(&prevprop, sizeof(textprop_T), 10); 1055 ga_init2(&prevprop, sizeof(textprop_T), 10);
1054 ga_init2(&nextprop, sizeof(textprop_T), 10); 1056 ga_init2(&nextprop, sizeof(textprop_T), 10);
1055 1057
1056 // Get the text properties, which are at "lnum + 1".
1057 // Keep the relevant ones in the first line, reducing the length if needed. 1058 // Keep the relevant ones in the first line, reducing the length if needed.
1058 // Copy the ones that include the split to the second line. 1059 // Copy the ones that include the split to the second line.
1059 // Move the ones after the split to the second line. 1060 // Move the ones after the split to the second line.
1060 for (i = 0; i < count; ++i) 1061 for (i = 0; i < count; ++i)
1061 { 1062 {
1087 } 1088 }
1088 ++nextprop.ga_len; 1089 ++nextprop.ga_len;
1089 } 1090 }
1090 } 1091 }
1091 1092
1092 set_text_props(lnum, prevprop.ga_data, prevprop.ga_len * sizeof(textprop_T)); 1093 set_text_props(lnum_top, prevprop.ga_data,
1094 prevprop.ga_len * sizeof(textprop_T));
1093 ga_clear(&prevprop); 1095 ga_clear(&prevprop);
1094 1096 set_text_props(lnum_top + 1, nextprop.ga_data,
1095 set_text_props(lnum + 1, nextprop.ga_data, nextprop.ga_len * sizeof(textprop_T)); 1097 nextprop.ga_len * sizeof(textprop_T));
1096 ga_clear(&nextprop); 1098 ga_clear(&nextprop);
1097 } 1099 }
1098 1100
1099 #endif // FEAT_TEXT_PROP 1101 #endif // FEAT_TEXT_PROP