aboutsummaryrefslogtreecommitdiffstats
path: root/src/itree.c
diff options
context:
space:
mode:
authorStefan Monnier2022-11-03 22:44:55 -0400
committerStefan Monnier2022-11-03 22:44:55 -0400
commitff679e16f8bf8a9876fc1a980c372d4e55f3745d (patch)
tree187712c5c9957fde923430d14ec6fd59f5441be4 /src/itree.c
parent7d47651d0168c863ad9e9b07921a42dc18029276 (diff)
downloademacs-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.c25
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
1187void 1187void
1188itree_insert_gap (struct itree_tree *tree, 1188itree_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);