aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/buffer.c8
-rw-r--r--src/insdel.c41
-rw-r--r--src/itree.c25
-rw-r--r--src/itree.h2
-rw-r--r--src/lisp.h2
5 files changed, 32 insertions, 46 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 3b0e6f1f9a1..ee0b7e13508 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3454,20 +3454,20 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3454 3454
3455 3455
3456void 3456void
3457adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) 3457adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length, bool before_markers)
3458{ 3458{
3459 if (!current_buffer->indirections) 3459 if (!current_buffer->indirections)
3460 itree_insert_gap (current_buffer->overlays, pos, length); 3460 itree_insert_gap (current_buffer->overlays, pos, length, before_markers);
3461 else 3461 else
3462 { 3462 {
3463 struct buffer *base = current_buffer->base_buffer 3463 struct buffer *base = current_buffer->base_buffer
3464 ? current_buffer->base_buffer 3464 ? current_buffer->base_buffer
3465 : current_buffer; 3465 : current_buffer;
3466 Lisp_Object tail, other; 3466 Lisp_Object tail, other;
3467 itree_insert_gap (base->overlays, pos, length); 3467 itree_insert_gap (base->overlays, pos, length, before_markers);
3468 FOR_EACH_LIVE_BUFFER (tail, other) 3468 FOR_EACH_LIVE_BUFFER (tail, other)
3469 if (XBUFFER (other)->base_buffer == base) 3469 if (XBUFFER (other)->base_buffer == base)
3470 itree_insert_gap (XBUFFER (other)->overlays, pos, length); 3470 itree_insert_gap (XBUFFER (other)->overlays, pos, length, before_markers);
3471 } 3471 }
3472} 3472}
3473 3473
diff --git a/src/insdel.c b/src/insdel.c
index 6d56a76c77a..ef17f99d21f 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -268,6 +268,7 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte,
268 m->bytepos = from_byte; 268 m->bytepos = from_byte;
269 } 269 }
270 } 270 }
271 adjust_overlays_for_delete (from, to - from);
271} 272}
272 273
273 274
@@ -307,6 +308,7 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
307 m->charpos += nchars; 308 m->charpos += nchars;
308 } 309 }
309 } 310 }
311 adjust_overlays_for_insert (from, to - from, before_markers);
310} 312}
311 313
312/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters. 314/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
@@ -358,6 +360,9 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
358 } 360 }
359 361
360 check_markers (); 362 check_markers ();
363
364 adjust_overlays_for_insert (from + old_chars, new_chars, true);
365 adjust_overlays_for_delete (from, old_chars);
361} 366}
362 367
363/* Starting at POS (BYTEPOS), find the byte position corresponding to 368/* Starting at POS (BYTEPOS), find the byte position corresponding to
@@ -917,7 +922,6 @@ insert_1_both (const char *string,
917 if (Z - GPT < END_UNCHANGED) 922 if (Z - GPT < END_UNCHANGED)
918 END_UNCHANGED = Z - GPT; 923 END_UNCHANGED = Z - GPT;
919 924
920 adjust_overlays_for_insert (PT, nchars);
921 adjust_markers_for_insert (PT, PT_BYTE, 925 adjust_markers_for_insert (PT, PT_BYTE,
922 PT + nchars, PT_BYTE + nbytes, 926 PT + nchars, PT_BYTE + nbytes,
923 before_markers); 927 before_markers);
@@ -1043,7 +1047,6 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1043 if (Z - GPT < END_UNCHANGED) 1047 if (Z - GPT < END_UNCHANGED)
1044 END_UNCHANGED = Z - GPT; 1048 END_UNCHANGED = Z - GPT;
1045 1049
1046 adjust_overlays_for_insert (PT, nchars);
1047 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, 1050 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1048 PT_BYTE + outgoing_nbytes, 1051 PT_BYTE + outgoing_nbytes,
1049 before_markers); 1052 before_markers);
@@ -1115,9 +1118,8 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1115 1118
1116 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail); 1119 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail);
1117 1120
1118 adjust_overlays_for_insert (ins_charpos, nchars);
1119 adjust_markers_for_insert (ins_charpos, ins_bytepos, 1121 adjust_markers_for_insert (ins_charpos, ins_bytepos,
1120 ins_charpos + nchars, ins_bytepos + nbytes, 0); 1122 ins_charpos + nchars, ins_bytepos + nbytes, false);
1121 1123
1122 if (buffer_intervals (current_buffer)) 1124 if (buffer_intervals (current_buffer))
1123 { 1125 {
@@ -1257,10 +1259,9 @@ insert_from_buffer_1 (struct buffer *buf,
1257 if (Z - GPT < END_UNCHANGED) 1259 if (Z - GPT < END_UNCHANGED)
1258 END_UNCHANGED = Z - GPT; 1260 END_UNCHANGED = Z - GPT;
1259 1261
1260 adjust_overlays_for_insert (PT, nchars);
1261 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, 1262 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1262 PT_BYTE + outgoing_nbytes, 1263 PT_BYTE + outgoing_nbytes,
1263 0); 1264 false);
1264 1265
1265 offset_intervals (current_buffer, PT, nchars); 1266 offset_intervals (current_buffer, PT, nchars);
1266 1267
@@ -1316,17 +1317,12 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1316 len, len_byte); 1317 len, len_byte);
1317 else 1318 else
1318 adjust_markers_for_insert (from, from_byte, 1319 adjust_markers_for_insert (from, from_byte,
1319 from + len, from_byte + len_byte, 0); 1320 from + len, from_byte + len_byte, false);
1320 1321
1321 if (nchars_del > 0) 1322 if (nchars_del > 0)
1322 record_delete (from, prev_text, false); 1323 record_delete (from, prev_text, false);
1323 record_insert (from, len); 1324 record_insert (from, len);
1324 1325
1325 if (len > nchars_del)
1326 adjust_overlays_for_insert (from, len - nchars_del);
1327 else if (len < nchars_del)
1328 adjust_overlays_for_delete (from, nchars_del - len);
1329
1330 offset_intervals (current_buffer, from, len - nchars_del); 1326 offset_intervals (current_buffer, from, len - nchars_del);
1331 1327
1332 if (from < PT) 1328 if (from < PT)
@@ -1507,14 +1503,9 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1507 which make the original byte positions of the markers 1503 which make the original byte positions of the markers
1508 invalid. */ 1504 invalid. */
1509 adjust_markers_bytepos (from, from_byte, from + inschars, 1505 adjust_markers_bytepos (from, from_byte, from + inschars,
1510 from_byte + outgoing_insbytes, 1); 1506 from_byte + outgoing_insbytes, true);
1511 } 1507 }
1512 1508
1513 /* Adjust the overlay center as needed. This must be done after
1514 adjusting the markers that bound the overlays. */
1515 adjust_overlays_for_delete (from, nchars_del);
1516 adjust_overlays_for_insert (from, inschars);
1517
1518 offset_intervals (current_buffer, from, inschars - nchars_del); 1509 offset_intervals (current_buffer, from, inschars - nchars_del);
1519 1510
1520 /* Get the intervals for the part of the string we are inserting-- 1511 /* Get the intervals for the part of the string we are inserting--
@@ -1640,18 +1631,10 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1640 sequences which make the original byte positions of the 1631 sequences which make the original byte positions of the
1641 markers invalid. */ 1632 markers invalid. */
1642 adjust_markers_bytepos (from, from_byte, from + inschars, 1633 adjust_markers_bytepos (from, from_byte, from + inschars,
1643 from_byte + insbytes, 1); 1634 from_byte + insbytes, true);
1644 } 1635 }
1645 } 1636 }
1646 1637
1647 /* Adjust the overlay center as needed. This must be done after
1648 adjusting the markers that bound the overlays. */
1649 if (nchars_del != inschars)
1650 {
1651 adjust_overlays_for_insert (from, inschars);
1652 adjust_overlays_for_delete (from + inschars, nchars_del);
1653 }
1654
1655 offset_intervals (current_buffer, from, inschars - nchars_del); 1638 offset_intervals (current_buffer, from, inschars - nchars_del);
1656 1639
1657 /* Relocate point as if it were a marker. */ 1640 /* Relocate point as if it were a marker. */
@@ -1854,10 +1837,6 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1854 1837
1855 offset_intervals (current_buffer, from, - nchars_del); 1838 offset_intervals (current_buffer, from, - nchars_del);
1856 1839
1857 /* Adjust the overlay center as needed. This must be done after
1858 adjusting the markers that bound the overlays. */
1859 adjust_overlays_for_delete (from, nchars_del);
1860
1861 GAP_SIZE += nbytes_del; 1840 GAP_SIZE += nbytes_del;
1862 ZV_BYTE -= nbytes_del; 1841 ZV_BYTE -= nbytes_del;
1863 Z_BYTE -= nbytes_del; 1842 Z_BYTE -= nbytes_del;
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);
diff --git a/src/itree.h b/src/itree.h
index 49a0333f345..d05bc7789a3 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -120,7 +120,7 @@ extern void itree_insert (struct itree_tree *, struct itree_node *,
120 ptrdiff_t, ptrdiff_t); 120 ptrdiff_t, ptrdiff_t);
121extern struct itree_node *itree_remove (struct itree_tree *, 121extern struct itree_node *itree_remove (struct itree_tree *,
122 struct itree_node *); 122 struct itree_node *);
123extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); 123extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t, bool);
124extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); 124extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t);
125 125
126/* Iteration functions. Almost all code should use ITREE_FOREACH 126/* Iteration functions. Almost all code should use ITREE_FOREACH
diff --git a/src/lisp.h b/src/lisp.h
index eafa241adfe..e240f86902f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4690,7 +4690,7 @@ extern void syms_of_editfns (void);
4690extern bool mouse_face_overlay_overlaps (Lisp_Object); 4690extern bool mouse_face_overlay_overlaps (Lisp_Object);
4691extern Lisp_Object disable_line_numbers_overlay_at_eob (void); 4691extern Lisp_Object disable_line_numbers_overlay_at_eob (void);
4692extern AVOID nsberror (Lisp_Object); 4692extern AVOID nsberror (Lisp_Object);
4693extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t); 4693extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool);
4694extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); 4694extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);
4695extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); 4695extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t);
4696extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool, 4696extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool,