diff options
| author | Stefan Monnier | 2022-11-03 22:44:55 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-11-03 22:44:55 -0400 |
| commit | ff679e16f8bf8a9876fc1a980c372d4e55f3745d (patch) | |
| tree | 187712c5c9957fde923430d14ec6fd59f5441be4 /src/itree.c | |
| parent | 7d47651d0168c863ad9e9b07921a42dc18029276 (diff) | |
| download | emacs-ff679e16f8bf8a9876fc1a980c372d4e55f3745d.tar.gz emacs-ff679e16f8bf8a9876fc1a980c372d4e55f3745d.zip | |
itree: Reproduce markers's behavior more faithfully (bug#58928)
The most obvious problem was the lack of support for
`insert-before-markers`, but the behavior was also different in a few
other cases.
* src/itree.h (itree_insert_gap):
* src/itree.c (itree_insert_gap): Add `before_markers` arg.
* src/lisp.h (adjust_overlays_for_insert):
* src/buffer.c (adjust_overlays_for_insert): Add `before_markers` arg.
* src/insdel.c (adjust_markers_for_replace, adjust_markers_for_insert)
(adjust_markers_for_delete): Adjust overlays directly from here.
(insert_1_both, insert_from_string_1, insert_from_gap)
(insert_from_buffer_1, adjust_after_replace, replace_range)
(replace_range_2, del_range_2): Don't adjust overlays explicitly here
any more.
* test/src/buffer-tests.el (test-overlay-insert-before-markers-empty)
(test-overlay-insert-before-markers-non-empty): New tests.
Diffstat (limited to 'src/itree.c')
| -rw-r--r-- | src/itree.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/src/itree.c b/src/itree.c index 3137cb6358f..611f6d46845 100644 --- a/src/itree.c +++ b/src/itree.c | |||
| @@ -1186,7 +1186,7 @@ itree_iterator_finish (struct itree_iterator *iter) | |||
| 1186 | 1186 | ||
| 1187 | void | 1187 | void |
| 1188 | itree_insert_gap (struct itree_tree *tree, | 1188 | itree_insert_gap (struct itree_tree *tree, |
| 1189 | ptrdiff_t pos, ptrdiff_t length) | 1189 | ptrdiff_t pos, ptrdiff_t length, bool before_markers) |
| 1190 | { | 1190 | { |
| 1191 | if (!tree || length <= 0 || tree->root == NULL) | 1191 | if (!tree || length <= 0 || tree->root == NULL) |
| 1192 | return; | 1192 | return; |
| @@ -1195,14 +1195,19 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1195 | /* FIXME: Don't allocate iterator/stack anew every time. */ | 1195 | /* FIXME: Don't allocate iterator/stack anew every time. */ |
| 1196 | 1196 | ||
| 1197 | /* Nodes with front_advance starting at pos may mess up the tree | 1197 | /* Nodes with front_advance starting at pos may mess up the tree |
| 1198 | order, so we need to remove them first. */ | 1198 | order, so we need to remove them first. This doesn't apply for |
| 1199 | `before_markers` since in that case, all positions move identically | ||
| 1200 | regardless of `front_advance` or `rear_advance`. */ | ||
| 1199 | struct interval_stack *saved = interval_stack_create (0); | 1201 | struct interval_stack *saved = interval_stack_create (0); |
| 1200 | struct itree_node *node = NULL; | 1202 | struct itree_node *node = NULL; |
| 1201 | ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER) | 1203 | if (!before_markers) |
| 1202 | { | 1204 | { |
| 1203 | if (node->begin == pos && node->front_advance | 1205 | ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER) |
| 1204 | && (node->begin != node->end || node->rear_advance)) | 1206 | { |
| 1205 | interval_stack_push (saved, node); | 1207 | if (node->begin == pos && node->front_advance |
| 1208 | && (node->begin != node->end || node->rear_advance)) | ||
| 1209 | interval_stack_push (saved, node); | ||
| 1210 | } | ||
| 1206 | } | 1211 | } |
| 1207 | for (size_t i = 0; i < saved->length; ++i) | 1212 | for (size_t i = 0; i < saved->length; ++i) |
| 1208 | itree_remove (tree, nav_nodeptr (saved->nodes[i])); | 1213 | itree_remove (tree, nav_nodeptr (saved->nodes[i])); |
| @@ -1235,10 +1240,12 @@ itree_insert_gap (struct itree_tree *tree, | |||
| 1235 | && pos <= node->left->limit + node->left->offset) | 1240 | && pos <= node->left->limit + node->left->offset) |
| 1236 | interval_stack_push (stack, node->left); | 1241 | interval_stack_push (stack, node->left); |
| 1237 | 1242 | ||
| 1238 | /* node->begin == pos implies no front-advance. */ | 1243 | if (before_markers |
| 1239 | if (node->begin > pos) | 1244 | ? node->begin >= pos |
| 1245 | : node->begin > pos) /* node->begin == pos => !front-advance */ | ||
| 1240 | node->begin += length; | 1246 | node->begin += length; |
| 1241 | if (node->end > pos || (node->end == pos && node->rear_advance)) | 1247 | if (node->end > pos |
| 1248 | || (node->end == pos && (before_markers || node->rear_advance))) | ||
| 1242 | { | 1249 | { |
| 1243 | node->end += length; | 1250 | node->end += length; |
| 1244 | eassert (node != NULL); | 1251 | eassert (node != NULL); |