X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/4c0078d4ab7fa8c234fa8098ec3a9686199edbff..4c31be6153255dfe29a0231253263ea0d9011ac3:/src/undo.c diff --git a/src/undo.c b/src/undo.c index 7e999fe512..cfb67ba5bc 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. @@ -20,6 +20,7 @@ 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 (current_buffer, undo_list, + 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 (current_buffer, undo_list, + Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); } /* Record that a deletion is about to take place, @@ -166,8 +168,8 @@ 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 (current_buffer, undo_list, + Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); } /* Record the fact that MARKER is about to be adjusted by ADJUSTMENT. @@ -189,9 +191,9 @@ 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 (current_buffer, undo_list, + Fcons (Fcons (marker, make_number (adjustment)), + BVAR (current_buffer, undo_list))); } /* Record that a replacement is about to take place, @@ -224,9 +226,9 @@ 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 (current_buffer, undo_list, + 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 +266,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 (current_buffer, undo_list, + Fcons (entry, BVAR (current_buffer, undo_list))); current_buffer = obuf; } @@ -287,11 +290,11 @@ 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 (current_buffer, undo_list, pending_boundary); pending_boundary = Qnil; } else - BVAR (current_buffer, undo_list) = Fcons (Qnil, BVAR (current_buffer, undo_list)); + BSET (current_buffer, undo_list, Fcons (Qnil, BVAR (current_buffer, undo_list))); } last_boundary_position = PT; last_boundary_buffer = current_buffer; @@ -432,10 +435,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 (b, undo_list, 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 +507,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 +531,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 +551,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 +560,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 +611,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 +650,8 @@ 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 (current_buffer, undo_list, + Fcons (list3 (Qapply, Qcdr, Qnil), BVAR (current_buffer, undo_list))); UNGCPRO; return unbind_to (count, list);