From 37ea8275f7faad1192ddaba9f4a0789580675e17 Mon Sep 17 00:00:00 2001 From: Barry O'Reilly Date: Mon, 24 Mar 2014 22:47:39 -0400 Subject: Undo in region after markers in undo history relocated * simple.el (primitive-undo): Only process marker adjustments validated against their corresponding (TEXT . POS). Issue warning for lone marker adjustments in undo history. (Bug#16818) (undo-make-selective-list): Add marker adjustments to selective undo list based on whether their corresponding (TEXT . POS) is in the region. Remove variable adjusted-markers, which was unused and only non nil during undo-make-selective-list. (undo-elt-in-region): Return nil when passed a marker adjustment and explain in function doc. Have (MARKER . ADJUSTMENT) undo records always be immediately after their corresponding (TEXT . POS) record in undo list. (Bug#16818) * lisp.h (record-delete): New arg record_markers. (record_marker_adjustment): No longer needed outside undo.c. * insdel.c (adjust_markers_for_delete): Move calculation of marker adjustments to undo.c's record_marker_adjustments. Note that fileio.c's decide_coding_unwind is another caller to adjust_markers_for_delete. Because it has undo list bound to t, it does not rely on adjust_markers_for_delete to record marker adjustments. (del_range_2): Swap call to record_delete and adjust_markers_for_delete so as undo marker adjustments are recorded before current deletion's adjustments, as before. (adjust_after_replace): (replace_range): Pass value for new record_markers arg to delete_record. * undo.c (record_marker_adjustment): Renamed to record_marker_adjustments and made static. (record_delete): Check record_markers arg and call record_marker_adjustments. (record_change): Pass value for new record_markers arg to delete_record. (record_point): at_boundary calculation no longer needs to account for marker adjustments. * undo-tests.el (undo-test-marker-adjustment-nominal): (undo-test-region-t-marker): New tests of marker adjustments. (undo-test-marker-adjustment-moved): (undo-test-region-mark-adjustment): New tests to demonstrate bug#16818, which fail without the fix. * markers.texi (Moving Marker Positions): The 2014-03-02 doc change mentioning undo's inability to handle relocated markers no longer applies. See bug#16818. * text.texi (Undo): Expand documentation of (TEXT . POS) and (MARKER . ADJUSTMENT) undo elements. --- src/insdel.c | 40 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) (limited to 'src/insdel.c') diff --git a/src/insdel.c b/src/insdel.c index 1c9bafd6004..eb1ad627f66 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -233,34 +233,9 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte, /* Here's the case where a marker is inside text being deleted. */ else if (charpos > from) { - if (! m->insertion_type) - { /* Normal markers will end up at the beginning of the - re-inserted text after undoing a deletion, and must be - adjusted to move them to the correct place. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, from - charpos); - } - else if (charpos < to) - { /* Before-insertion markers will automatically move forward - upon re-inserting the deleted text, so we have to arrange - for them to move backward to the correct position. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, to - charpos); - } m->charpos = from; m->bytepos = from_byte; } - /* Here's the case where a before-insertion marker is immediately - before the deleted region. */ - else if (charpos == from && m->insertion_type) - { - /* Undoing the change uses normal insertion, which will - incorrectly make MARKER move forward, so we arrange for it - to then move backward to the correct place at the beginning - of the deleted region. */ - XSETMISC (marker, m); - record_marker_adjustment (marker, to - from); - } } } @@ -1219,7 +1194,7 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte, from + len, from_byte + len_byte, 0); if (nchars_del > 0) - record_delete (from, prev_text); + record_delete (from, prev_text, false); record_insert (from, len); if (len > nchars_del) @@ -1384,7 +1359,7 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new, if (!NILP (deletion)) { record_insert (from + SCHARS (deletion), inschars); - record_delete (from, deletion); + record_delete (from, deletion, false); } GAP_SIZE -= outgoing_insbytes; @@ -1716,13 +1691,14 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte, else deletion = Qnil; - /* Relocate all markers pointing into the new, larger gap - to point at the end of the text before the gap. - Do this before recording the deletion, - so that undo handles this after reinserting the text. */ + /* Record marker adjustments, and text deletion into undo + history. */ + record_delete (from, deletion, true); + + /* Relocate all markers pointing into the new, larger gap to point + at the end of the text before the gap. */ adjust_markers_for_delete (from, from_byte, to, to_byte); - record_delete (from, deletion); MODIFF++; CHARS_MODIFF = MODIFF; -- cgit v1.2.1