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 | |
| 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')
| -rw-r--r-- | src/buffer.c | 8 | ||||
| -rw-r--r-- | src/insdel.c | 41 | ||||
| -rw-r--r-- | src/itree.c | 25 | ||||
| -rw-r--r-- | src/itree.h | 2 | ||||
| -rw-r--r-- | src/lisp.h | 2 |
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 | ||
| 3456 | void | 3456 | void |
| 3457 | adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) | 3457 | adjust_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 | ||
| 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); |
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); |
| 121 | extern struct itree_node *itree_remove (struct itree_tree *, | 121 | extern struct itree_node *itree_remove (struct itree_tree *, |
| 122 | struct itree_node *); | 122 | struct itree_node *); |
| 123 | extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); | 123 | extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t, bool); |
| 124 | extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); | 124 | extern 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); | |||
| 4690 | extern bool mouse_face_overlay_overlaps (Lisp_Object); | 4690 | extern bool mouse_face_overlay_overlaps (Lisp_Object); |
| 4691 | extern Lisp_Object disable_line_numbers_overlay_at_eob (void); | 4691 | extern Lisp_Object disable_line_numbers_overlay_at_eob (void); |
| 4692 | extern AVOID nsberror (Lisp_Object); | 4692 | extern AVOID nsberror (Lisp_Object); |
| 4693 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t); | 4693 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool); |
| 4694 | extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); | 4694 | extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); |
| 4695 | extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); | 4695 | extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); |
| 4696 | extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool, | 4696 | extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool, |