X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/60b5d3ca2bf381f450da02e3936f7b43b7ca2dab..22294a56e8115801f7b515f71ca87342d3e2e558:/src/undo.c diff --git a/src/undo.c b/src/undo.c index 7e999fe512..e878ef4dcf 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1,5 +1,5 @@ /* undo handling for GNU Emacs. - Copyright (C) 1990, 1993-1994, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1990, 1993-1994, 2000-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -18,8 +18,9 @@ along with GNU Emacs. If not, see . */ #include -#include + #include "lisp.h" +#include "character.h" #include "buffer.h" #include "commands.h" #include "window.h" @@ -103,8 +104,9 @@ record_point (ptrdiff_t pt) if (at_boundary && current_buffer == last_boundary_buffer && last_boundary_position != pt) - BVAR (current_buffer, undo_list) - = Fcons (make_number (last_boundary_position), BVAR (current_buffer, undo_list)); + bset_undo_list (current_buffer, + Fcons (make_number (last_boundary_position), + BVAR (current_buffer, undo_list))); } /* Record an insertion that just happened or is about to happen, @@ -140,8 +142,8 @@ record_insert (ptrdiff_t beg, ptrdiff_t length) XSETFASTINT (lbeg, beg); XSETINT (lend, beg + length); - BVAR (current_buffer, undo_list) = Fcons (Fcons (lbeg, lend), - BVAR (current_buffer, undo_list)); + bset_undo_list (current_buffer, + Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); } /* Record that a deletion is about to take place, @@ -166,8 +168,9 @@ record_delete (ptrdiff_t beg, Lisp_Object string) record_point (beg); } - BVAR (current_buffer, undo_list) - = Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list)); + bset_undo_list + (current_buffer, + Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); } /* Record the fact that MARKER is about to be adjusted by ADJUSTMENT. @@ -189,9 +192,10 @@ record_marker_adjustment (Lisp_Object marker, ptrdiff_t adjustment) Fundo_boundary (); last_undo_buffer = current_buffer; - BVAR (current_buffer, undo_list) - = Fcons (Fcons (marker, make_number (adjustment)), - BVAR (current_buffer, undo_list)); + bset_undo_list + (current_buffer, + Fcons (Fcons (marker, make_number (adjustment)), + BVAR (current_buffer, undo_list))); } /* Record that a replacement is about to take place, @@ -224,9 +228,10 @@ record_first_change (void) if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; - BVAR (current_buffer, undo_list) = - Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)), - BVAR (current_buffer, undo_list)); + bset_undo_list + (current_buffer, + Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)), + BVAR (current_buffer, undo_list))); } /* Record a change in property PROP (whose old value was VAL) @@ -264,7 +269,8 @@ record_property_change (ptrdiff_t beg, ptrdiff_t length, XSETINT (lbeg, beg); XSETINT (lend, beg + length); entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend)))); - BVAR (current_buffer, undo_list) = Fcons (entry, BVAR (current_buffer, undo_list)); + bset_undo_list (current_buffer, + Fcons (entry, BVAR (current_buffer, undo_list))); current_buffer = obuf; } @@ -287,11 +293,12 @@ but another undo command will undo to the previous boundary. */) /* If we have preallocated the cons cell to use here, use that one. */ XSETCDR (pending_boundary, BVAR (current_buffer, undo_list)); - BVAR (current_buffer, undo_list) = pending_boundary; + bset_undo_list (current_buffer, pending_boundary); pending_boundary = Qnil; } else - BVAR (current_buffer, undo_list) = Fcons (Qnil, BVAR (current_buffer, undo_list)); + bset_undo_list (current_buffer, + Fcons (Qnil, BVAR (current_buffer, undo_list))); } last_boundary_position = PT; last_boundary_buffer = current_buffer; @@ -317,7 +324,7 @@ truncate_undo_list (struct buffer *b) /* Make the buffer current to get its local values of variables such as undo_limit. Also so that Vundo_outer_limit_function can tell which buffer to operate on. */ - record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); + record_unwind_current_buffer (); set_buffer_internal (b); list = BVAR (b, undo_list); @@ -432,10 +439,17 @@ truncate_undo_list (struct buffer *b) XSETCDR (last_boundary, Qnil); /* There's nothing we decided to keep, so clear it out. */ else - BVAR (b, undo_list) = Qnil; + bset_undo_list (b, Qnil); unbind_to (count, Qnil); } + +static _Noreturn void +user_error (const char *msg) +{ + xsignal1 (Quser_error, build_string (msg)); +} + DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0, doc: /* Undo N records from the front of the list LIST. @@ -497,10 +511,23 @@ Return what remains of the list. */) cdr = XCDR (next); if (EQ (car, Qt)) { - /* Element (t high . low) records previous modtime. */ + /* Element (t . TIME) records previous modtime. + Preserve any flag of NONEXISTENT_MODTIME_NSECS or + UNKNOWN_MODTIME_NSECS. */ struct buffer *base_buffer = current_buffer; - time_t mod_time; - CONS_TO_INTEGER (cdr, time_t, mod_time); + EMACS_TIME mod_time; + + if (CONSP (cdr) + && CONSP (XCDR (cdr)) + && CONSP (XCDR (XCDR (cdr))) + && CONSP (XCDR (XCDR (XCDR (cdr)))) + && INTEGERP (XCAR (XCDR (XCDR (XCDR (cdr))))) + && XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) < 0) + mod_time = + (make_emacs_time + (0, XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000)); + else + mod_time = lisp_time_argument (cdr); if (current_buffer->base_buffer) base_buffer = current_buffer->base_buffer; @@ -508,7 +535,7 @@ Return what remains of the list. */) /* If this records an obsolete save (not matching the actual disk file) then don't mark unmodified. */ - if (mod_time != base_buffer->modtime) + if (EMACS_TIME_NE (mod_time, base_buffer->modtime)) continue; #ifdef CLASH_DETECTION Funlock_buffer (); @@ -528,7 +555,7 @@ Return what remains of the list. */) end = Fcdr (cdr); if (XINT (beg) < BEGV || XINT (end) > ZV) - error ("Changes to be undone are outside visible portion of buffer"); + user_error ("Changes to be undone are outside visible portion of buffer"); Fput_text_property (beg, end, prop, val, Qnil); } else if (INTEGERP (car) && INTEGERP (cdr)) @@ -537,7 +564,7 @@ Return what remains of the list. */) if (XINT (car) < BEGV || XINT (cdr) > ZV) - error ("Changes to be undone are outside visible portion of buffer"); + user_error ("Changes to be undone are outside visible portion of buffer"); /* Set point first thing, so that undoing this undo does not send point back to where it is now. */ Fgoto_char (car); @@ -588,14 +615,14 @@ Return what remains of the list. */) if (pos < 0) { if (-pos < BEGV || -pos > ZV) - error ("Changes to be undone are outside visible portion of buffer"); + user_error ("Changes to be undone are outside visible portion of buffer"); SET_PT (-pos); Finsert (1, &membuf); } else { if (pos < BEGV || pos > ZV) - error ("Changes to be undone are outside visible portion of buffer"); + user_error ("Changes to be undone are outside visible portion of buffer"); SET_PT (pos); /* Now that we record marker adjustments @@ -627,8 +654,9 @@ Return what remains of the list. */) will work right. */ if (did_apply && EQ (oldlist, BVAR (current_buffer, undo_list))) - BVAR (current_buffer, undo_list) - = Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list)); + bset_undo_list + (current_buffer, + Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list))); UNGCPRO; return unbind_to (count, list);