Switch from NO_RETURN to C11's _Noreturn.
[bpt/emacs.git] / src / undo.c
index 7e999fe..c4ef557 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <setjmp.h>
 #include "lisp.h"
+#include "character.h"
 #include "buffer.h"
 #include "commands.h"
 #include "window.h"
@@ -225,7 +226,7 @@ record_first_change (void)
     base_buffer = base_buffer->base_buffer;
 
   BVAR (current_buffer, undo_list) =
-    Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)),
+    Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)),
           BVAR (current_buffer, undo_list));
 }
 
@@ -436,6 +437,13 @@ truncate_undo_list (struct buffer *b)
 
   unbind_to (count, Qnil);
 }
+
+static _Noreturn void
+user_error (const char *msg)
+{
+  xsignal1 (Quser_error, build_string (msg));
+}
+
 \f
 DEFUN ("primitive-undo", Fprimitive_undo, Sprimitive_undo, 2, 2, 0,
        doc: /* Undo N records from the front of the list LIST.
@@ -497,10 +505,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)
+                   EMACS_SET_SECS_NSECS
+                     (mod_time, 0,
+                      XINT (XCAR (XCDR (XCDR (XCDR (cdr))))) / 1000);
+                 else
+                   mod_time = lisp_time_argument (cdr, 0);
 
                  if (current_buffer->base_buffer)
                    base_buffer = current_buffer->base_buffer;
@@ -508,7 +529,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 +549,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 +558,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 +609,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