diff --git a/lisp/simple.el b/lisp/simple.el index 6313ce81ef9..66640916a25 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -3525,12 +3525,22 @@ Return what remains of the list." ;; If this records an obsolete save ;; (not matching the actual disk file) ;; then don't mark unmodified. - (when (or (equal time (visited-file-modtime)) - (and (consp time) - (equal (list (car time) (cdr time)) - (visited-file-modtime)))) - (unlock-buffer) - (set-buffer-modified-p nil))) + (let ((visited-file-time (visited-file-modtime))) + ;; Indirect buffers don't have a visited file, so their + ;; file-modtime can be bogus. In that case, use the + ;; modtime of the base buffer instead. + (if (and (numberp visited-file-time) + (= visited-file-time 0) + (buffer-base-buffer)) + (setq visited-file-time + (with-current-buffer (buffer-base-buffer) + (visited-file-modtime)))) + (when (or (equal time visited-file-time) + (and (consp time) + (equal (list (car time) (cdr time)) + visited-file-time))) + (unlock-buffer) + (set-buffer-modified-p nil)))) ;; Element (nil PROP VAL BEG . END) is property change. (`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare)) (when (or (> (point-min) beg) (< (point-max) end)) diff --git a/src/fileio.c b/src/fileio.c index 10d4b8bc15e..d07e62a1212 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5832,6 +5832,15 @@ See Info node `(elisp)Modification Time' for more details. */) return Qnil; } +Lisp_Object +buffer_visited_file_modtime (struct buffer *buf) +{ + int ns = buf->modtime.tv_nsec; + if (ns < 0) + return make_fixnum (UNKNOWN_MODTIME_NSECS - ns); + return make_lisp_time (buf->modtime); +} + DEFUN ("visited-file-modtime", Fvisited_file_modtime, Svisited_file_modtime, 0, 0, 0, doc: /* Return the current buffer's recorded visited file modification time. @@ -5841,10 +5850,7 @@ visited file doesn't exist. See Info node `(elisp)Modification Time' for more details. */) (void) { - int ns = current_buffer->modtime.tv_nsec; - if (ns < 0) - return make_fixnum (UNKNOWN_MODTIME_NSECS - ns); - return make_lisp_time (current_buffer->modtime); + return buffer_visited_file_modtime (current_buffer); } DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime, @@ -5871,6 +5877,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */) current_buffer->modtime = mtime; current_buffer->modtime_size = -1; } + else if (current_buffer->base_buffer) + error ("An indirect buffer does not have a visited file"); else { register Lisp_Object filename; diff --git a/src/lisp.h b/src/lisp.h index e4a49b8ef94..35cc7f5a098 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4733,6 +4733,7 @@ extern bool internal_delete_file (Lisp_Object); extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *); extern bool file_directory_p (Lisp_Object); extern bool file_accessible_directory_p (Lisp_Object); +extern Lisp_Object buffer_visited_file_modtime (struct buffer *); extern void init_fileio (void); extern void syms_of_fileio (void); diff --git a/src/undo.c b/src/undo.c index 36664d16424..f76977dbe50 100644 --- a/src/undo.c +++ b/src/undo.c @@ -218,7 +218,7 @@ record_first_change (void) base_buffer = base_buffer->base_buffer; bset_undo_list (current_buffer, - Fcons (Fcons (Qt, Fvisited_file_modtime ()), + Fcons (Fcons (Qt, buffer_visited_file_modtime (base_buffer)), BVAR (current_buffer, undo_list))); }