mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-06 03:40:56 -08:00
Timestamp fixes for undo.
* doc/lispref/text.texi (Undo): Document (t . 0) and (t . -1) in buffer-undo-list. * etc/NEWS: Changes to visited-file-modtime, set-visited-file-modtime. * lisp/files.el (clear-visited-file-modtime): Move here from fileio.c. * src/atimer.c (schedule_atimer): * src/fileio.c (Ffile_newer_than_file_p): Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT. * src/buffer.c (buffer-undo-list): Document (t . 0) and (t . -1). * src/fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el. (syms_of_fileio): Remove Sclear_visited_file_name. (Fvisited_file_modtime): Return -1, not (-1 ...), when the visited file doesn't exist; this avoids an ambiguity with negative timestamps. (Fset_visited_file_modtime): Accept -1 and 0 as time-list arg. * src/systime.h (make_emacs_time, invalid_emacs_time): Don't assume struct timespec layout; POSIX doesn't guarantee it. (EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove. * src/undo.c (record_first_change): Push (visited-file-modtime) onto undo list rather than reimplementing it by hand, incorrectly. Fixes: debbugs:14824
This commit is contained in:
parent
56973319b5
commit
954b166e90
12 changed files with 86 additions and 53 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
2013-07-10 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
|
Timestamp fixes for undo (Bug#14824).
|
||||||
|
* text.texi (Undo): Document (t . 0) and (t . -1) in buffer-undo-list.
|
||||||
|
|
||||||
2013-07-06 Eli Zaretskii <eliz@gnu.org>
|
2013-07-06 Eli Zaretskii <eliz@gnu.org>
|
||||||
|
|
||||||
* nonascii.texi (Text Representations): Document that
|
* nonascii.texi (Text Representations): Document that
|
||||||
|
|
|
||||||
|
|
@ -1250,14 +1250,18 @@ reinsert it is @code{(abs @var{position})}. If @var{position} is
|
||||||
positive, point was at the beginning of the deleted text, otherwise it
|
positive, point was at the beginning of the deleted text, otherwise it
|
||||||
was at the end.
|
was at the end.
|
||||||
|
|
||||||
@item (t @var{sec-high} @var{sec-low} @var{microsec} @var{picosec})
|
@item (t . @var{time-flag})
|
||||||
This kind of element indicates that an unmodified buffer became
|
This kind of element indicates that an unmodified buffer became
|
||||||
modified. The list @code{(@var{sec-high} @var{sec-low} @var{microsec}
|
modified. A @var{time-flag} of the form
|
||||||
|
@code{(@var{sec-high} @var{sec-low} @var{microsec}
|
||||||
@var{picosec})} represents the visited file's modification time as of
|
@var{picosec})} represents the visited file's modification time as of
|
||||||
when it was previously visited or saved, using the same format as
|
when it was previously visited or saved, using the same format as
|
||||||
@code{current-time}; see @ref{Time of Day}. @code{primitive-undo} uses those
|
@code{current-time}; see @ref{Time of Day}.
|
||||||
|
A @var{time-flag} of 0 means the buffer does not correspond to any file;
|
||||||
|
@minus{}1 means the visited file previously did not exist.
|
||||||
|
@code{primitive-undo} uses these
|
||||||
values to determine whether to mark the buffer as unmodified once again;
|
values to determine whether to mark the buffer as unmodified once again;
|
||||||
it does so only if the file's modification time matches those numbers.
|
it does so only if the file's status matches that of @var{time-flag}.
|
||||||
|
|
||||||
@item (nil @var{property} @var{value} @var{beg} . @var{end})
|
@item (nil @var{property} @var{value} @var{beg} . @var{end})
|
||||||
This kind of element records a change in a text property.
|
This kind of element records a change in a text property.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2013-07-10 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
|
Timestamp fixes for undo (Bug#14824).
|
||||||
|
* NEWS: Changes to visited-file-modtime, set-visited-file-modtime.
|
||||||
|
|
||||||
2013-07-08 Jan Djärv <jan.h.d@swipnet.se>
|
2013-07-08 Jan Djärv <jan.h.d@swipnet.se>
|
||||||
|
|
||||||
* NEWS: NS can be build with ImageMagick.
|
* NEWS: NS can be build with ImageMagick.
|
||||||
|
|
|
||||||
6
etc/NEWS
6
etc/NEWS
|
|
@ -537,6 +537,9 @@ alist of extended attributes as returned by the new function
|
||||||
`file-extended-attributes'. The attributes can be applied to another
|
`file-extended-attributes'. The attributes can be applied to another
|
||||||
file using `set-file-extended-attributes'.
|
file using `set-file-extended-attributes'.
|
||||||
|
|
||||||
|
** `visited-file-modtime' now returns -1 for nonexistent files.
|
||||||
|
Formerly it returned a list (-1 LOW USEC PSEC), but this was ambiguous
|
||||||
|
in the presence of files with negative time stamps.
|
||||||
|
|
||||||
* Lisp Changes in Emacs 24.4
|
* Lisp Changes in Emacs 24.4
|
||||||
|
|
||||||
|
|
@ -613,6 +616,9 @@ Emacs uses `image-default-frame-delay'.
|
||||||
*** New functions `image-current-frame' and `image-show-frame' for getting
|
*** New functions `image-current-frame' and `image-show-frame' for getting
|
||||||
and setting the current frame of a multi-frame image.
|
and setting the current frame of a multi-frame image.
|
||||||
|
|
||||||
|
** The function `set-visited-file-modtime' now accepts a 0 or -1 argument
|
||||||
|
with the same interpretation as the returned value of `visited-file-modtime'.
|
||||||
|
|
||||||
** time-to-seconds is not obsolete any more.
|
** time-to-seconds is not obsolete any more.
|
||||||
** New function special-form-p.
|
** New function special-form-p.
|
||||||
** Docstrings can be made dynamic by adding a `dynamic-docstring-function'
|
** Docstrings can be made dynamic by adding a `dynamic-docstring-function'
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2013-07-10 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
|
Timestamp fixes for undo (Bug#14824).
|
||||||
|
* files.el (clear-visited-file-modtime): Move here from fileio.c.
|
||||||
|
|
||||||
2013-07-10 Leo Liu <sdl.web@gmail.com>
|
2013-07-10 Leo Liu <sdl.web@gmail.com>
|
||||||
|
|
||||||
* files.el (require-final-newline): Allow safe local value.
|
* files.el (require-final-newline): Allow safe local value.
|
||||||
|
|
|
||||||
|
|
@ -4918,6 +4918,11 @@ change the additional actions you can take on files."
|
||||||
(length autosaved-buffers)
|
(length autosaved-buffers)
|
||||||
(mapconcat 'identity autosaved-buffers ", "))))))))
|
(mapconcat 'identity autosaved-buffers ", "))))))))
|
||||||
|
|
||||||
|
(defun clear-visited-file-modtime ()
|
||||||
|
"Clear out records of last mod time of visited file.
|
||||||
|
Next attempt to save will certainly not complain of a discrepancy."
|
||||||
|
(set-visited-file-modtime 0))
|
||||||
|
|
||||||
(defun not-modified (&optional arg)
|
(defun not-modified (&optional arg)
|
||||||
"Mark current buffer as unmodified, not needing to be saved.
|
"Mark current buffer as unmodified, not needing to be saved.
|
||||||
With prefix ARG, mark buffer as modified, so \\[save-buffer] will save.
|
With prefix ARG, mark buffer as modified, so \\[save-buffer] will save.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,21 @@
|
||||||
|
2013-07-10 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
|
Timestamp fixes for undo (Bug#14824).
|
||||||
|
* atimer.c (schedule_atimer):
|
||||||
|
* fileio.c (Ffile_newer_than_file_p):
|
||||||
|
Minor cleanup: use EMACS_TIME_LT so that we can remove EMACS_TIME_GT.
|
||||||
|
* buffer.c (buffer-undo-list): Document (t . 0) and (t . -1).
|
||||||
|
* fileio.c (Fclear_visited_file_modtime): Move to lisp/files.el.
|
||||||
|
(syms_of_fileio): Remove Sclear_visited_file_name.
|
||||||
|
(Fvisited_file_modtime): Return -1, not (-1 ...), when the visited
|
||||||
|
file doesn't exist; this avoids an ambiguity with negative timestamps.
|
||||||
|
(Fset_visited_file_modtime): Accept -1 and 0 as time-list arg.
|
||||||
|
* systime.h (make_emacs_time, invalid_emacs_time):
|
||||||
|
Don't assume struct timespec layout; POSIX doesn't guarantee it.
|
||||||
|
(EMACS_TIME_NE, EMACS_TIME_GT, EMACS_TIME_GE): Remove.
|
||||||
|
* undo.c (record_first_change): Push (visited-file-modtime) onto
|
||||||
|
undo list rather than reimplementing it by hand, incorrectly.
|
||||||
|
|
||||||
2013-07-09 Ken Brown <kbrown@cornell.edu>
|
2013-07-09 Ken Brown <kbrown@cornell.edu>
|
||||||
|
|
||||||
* sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB.
|
* sheap.c (STATIC_HEAP_SIZE) [__x86_64__]: Increase to 18MB.
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ schedule_atimer (struct atimer *t)
|
||||||
struct atimer *a = atimers, *prev = NULL;
|
struct atimer *a = atimers, *prev = NULL;
|
||||||
|
|
||||||
/* Look for the first atimer that is ripe after T. */
|
/* Look for the first atimer that is ripe after T. */
|
||||||
while (a && EMACS_TIME_GT (t->expiration, a->expiration))
|
while (a && EMACS_TIME_LT (a->expiration, t->expiration))
|
||||||
prev = a, a = a->next;
|
prev = a, a = a->next;
|
||||||
|
|
||||||
/* Insert T in front of the atimer found, if any. */
|
/* Insert T in front of the atimer found, if any. */
|
||||||
|
|
|
||||||
|
|
@ -6095,6 +6095,11 @@ and is the visited file's modification time, as of that time. If the
|
||||||
modification time of the most recent save is different, this entry is
|
modification time of the most recent save is different, this entry is
|
||||||
obsolete.
|
obsolete.
|
||||||
|
|
||||||
|
An entry (t . 0) means means the buffer was previously unmodified but
|
||||||
|
its time stamp was unknown because it was not associated with a file.
|
||||||
|
An entry (t . -1) is similar, except that it means the buffer's visited
|
||||||
|
file did not exist.
|
||||||
|
|
||||||
An entry (nil PROPERTY VALUE BEG . END) indicates that a text property
|
An entry (nil PROPERTY VALUE BEG . END) indicates that a text property
|
||||||
was modified between BEG and END. PROPERTY is the property name,
|
was modified between BEG and END. PROPERTY is the property name,
|
||||||
and VALUE is the old value.
|
and VALUE is the old value.
|
||||||
|
|
|
||||||
46
src/fileio.c
46
src/fileio.c
|
|
@ -3345,7 +3345,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
|
||||||
if (stat (SSDATA (absname2), &st2) < 0)
|
if (stat (SSDATA (absname2), &st2) < 0)
|
||||||
return Qt;
|
return Qt;
|
||||||
|
|
||||||
return (EMACS_TIME_GT (get_stat_mtime (&st1), get_stat_mtime (&st2))
|
return (EMACS_TIME_LT (get_stat_mtime (&st2), get_stat_mtime (&st1))
|
||||||
? Qt : Qnil);
|
? Qt : Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5375,36 +5375,19 @@ See Info node `(elisp)Modification Time' for more details. */)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("clear-visited-file-modtime", Fclear_visited_file_modtime,
|
|
||||||
Sclear_visited_file_modtime, 0, 0, 0,
|
|
||||||
doc: /* Clear out records of last mod time of visited file.
|
|
||||||
Next attempt to save will certainly not complain of a discrepancy. */)
|
|
||||||
(void)
|
|
||||||
{
|
|
||||||
current_buffer->modtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS);
|
|
||||||
current_buffer->modtime_size = -1;
|
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
|
DEFUN ("visited-file-modtime", Fvisited_file_modtime,
|
||||||
Svisited_file_modtime, 0, 0, 0,
|
Svisited_file_modtime, 0, 0, 0,
|
||||||
doc: /* Return the current buffer's recorded visited file modification time.
|
doc: /* Return the current buffer's recorded visited file modification time.
|
||||||
The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
|
The value is a list of the form (HIGH LOW USEC PSEC), like the time values that
|
||||||
`file-attributes' returns. If the current buffer has no recorded file
|
`file-attributes' returns. If the current buffer has no recorded file
|
||||||
modification time, this function returns 0. If the visited file
|
modification time, this function returns 0. If the visited file
|
||||||
doesn't exist, HIGH will be -1.
|
doesn't exist, return -1.
|
||||||
See Info node `(elisp)Modification Time' for more details. */)
|
See Info node `(elisp)Modification Time' for more details. */)
|
||||||
(void)
|
(void)
|
||||||
{
|
{
|
||||||
if (EMACS_NSECS (current_buffer->modtime) < 0)
|
int ns = EMACS_NSECS (current_buffer->modtime);
|
||||||
{
|
if (ns < 0)
|
||||||
if (EMACS_NSECS (current_buffer->modtime) == NONEXISTENT_MODTIME_NSECS)
|
return make_number (UNKNOWN_MODTIME_NSECS - ns);
|
||||||
{
|
|
||||||
/* make_lisp_time won't work here if time_t is unsigned. */
|
|
||||||
return list4i (-1, 65535, 0, 0);
|
|
||||||
}
|
|
||||||
return make_number (0);
|
|
||||||
}
|
|
||||||
return make_lisp_time (current_buffer->modtime);
|
return make_lisp_time (current_buffer->modtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5415,12 +5398,22 @@ Useful if the buffer was not read from the file normally
|
||||||
or if the file itself has been changed for some known benign reason.
|
or if the file itself has been changed for some known benign reason.
|
||||||
An argument specifies the modification time value to use
|
An argument specifies the modification time value to use
|
||||||
\(instead of that of the visited file), in the form of a list
|
\(instead of that of the visited file), in the form of a list
|
||||||
\(HIGH LOW USEC PSEC) as returned by `current-time'. */)
|
\(HIGH LOW USEC PSEC) or an integer flag as returned by
|
||||||
(Lisp_Object time_list)
|
`visited-file-modtime'. */)
|
||||||
|
(Lisp_Object time_flag)
|
||||||
{
|
{
|
||||||
if (!NILP (time_list))
|
if (!NILP (time_flag))
|
||||||
{
|
{
|
||||||
current_buffer->modtime = lisp_time_argument (time_list);
|
EMACS_TIME mtime;
|
||||||
|
if (INTEGERP (time_flag))
|
||||||
|
{
|
||||||
|
CHECK_RANGED_INTEGER (time_flag, -1, 0);
|
||||||
|
mtime = make_emacs_time (0, UNKNOWN_MODTIME_NSECS - XINT (time_flag));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mtime = lisp_time_argument (time_flag);
|
||||||
|
|
||||||
|
current_buffer->modtime = mtime;
|
||||||
current_buffer->modtime_size = -1;
|
current_buffer->modtime_size = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -6121,7 +6114,6 @@ This includes interactive calls to `delete-file' and
|
||||||
defsubr (&Swrite_region);
|
defsubr (&Swrite_region);
|
||||||
defsubr (&Scar_less_than_car);
|
defsubr (&Scar_less_than_car);
|
||||||
defsubr (&Sverify_visited_file_modtime);
|
defsubr (&Sverify_visited_file_modtime);
|
||||||
defsubr (&Sclear_visited_file_modtime);
|
|
||||||
defsubr (&Svisited_file_modtime);
|
defsubr (&Svisited_file_modtime);
|
||||||
defsubr (&Sset_visited_file_modtime);
|
defsubr (&Sset_visited_file_modtime);
|
||||||
defsubr (&Sdo_auto_save);
|
defsubr (&Sdo_auto_save);
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,9 @@ SYSTIME_INLINE time_t *emacs_secs_addr (EMACS_TIME *t) { return &t->tv_sec; }
|
||||||
SYSTIME_INLINE EMACS_TIME
|
SYSTIME_INLINE EMACS_TIME
|
||||||
make_emacs_time (time_t s, int ns)
|
make_emacs_time (time_t s, int ns)
|
||||||
{
|
{
|
||||||
EMACS_TIME r = { s, ns };
|
EMACS_TIME r;
|
||||||
|
r.tv_sec = s;
|
||||||
|
r.tv_nsec = ns;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +77,9 @@ make_emacs_time (time_t s, int ns)
|
||||||
SYSTIME_INLINE EMACS_TIME
|
SYSTIME_INLINE EMACS_TIME
|
||||||
invalid_emacs_time (void)
|
invalid_emacs_time (void)
|
||||||
{
|
{
|
||||||
EMACS_TIME r = { 0, -1 };
|
EMACS_TIME r;
|
||||||
|
r.tv_sec = 0;
|
||||||
|
r.tv_nsec = -1;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,21 +170,6 @@ EMACS_TIME_EQ (EMACS_TIME t1, EMACS_TIME t2)
|
||||||
return timespec_cmp (t1, t2) == 0;
|
return timespec_cmp (t1, t2) == 0;
|
||||||
}
|
}
|
||||||
SYSTIME_INLINE int
|
SYSTIME_INLINE int
|
||||||
EMACS_TIME_NE (EMACS_TIME t1, EMACS_TIME t2)
|
|
||||||
{
|
|
||||||
return timespec_cmp (t1, t2) != 0;
|
|
||||||
}
|
|
||||||
SYSTIME_INLINE int
|
|
||||||
EMACS_TIME_GT (EMACS_TIME t1, EMACS_TIME t2)
|
|
||||||
{
|
|
||||||
return timespec_cmp (t1, t2) > 0;
|
|
||||||
}
|
|
||||||
SYSTIME_INLINE int
|
|
||||||
EMACS_TIME_GE (EMACS_TIME t1, EMACS_TIME t2)
|
|
||||||
{
|
|
||||||
return timespec_cmp (t1, t2) >= 0;
|
|
||||||
}
|
|
||||||
SYSTIME_INLINE int
|
|
||||||
EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2)
|
EMACS_TIME_LT (EMACS_TIME t1, EMACS_TIME t2)
|
||||||
{
|
{
|
||||||
return timespec_cmp (t1, t2) < 0;
|
return timespec_cmp (t1, t2) < 0;
|
||||||
|
|
|
||||||
|
|
@ -229,10 +229,9 @@ record_first_change (void)
|
||||||
if (base_buffer->base_buffer)
|
if (base_buffer->base_buffer)
|
||||||
base_buffer = base_buffer->base_buffer;
|
base_buffer = base_buffer->base_buffer;
|
||||||
|
|
||||||
bset_undo_list
|
bset_undo_list (current_buffer,
|
||||||
(current_buffer,
|
Fcons (Fcons (Qt, Fvisited_file_modtime ()),
|
||||||
Fcons (Fcons (Qt, make_lisp_time (base_buffer->modtime)),
|
BVAR (current_buffer, undo_list)));
|
||||||
BVAR (current_buffer, undo_list)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record a change in property PROP (whose old value was VAL)
|
/* Record a change in property PROP (whose old value was VAL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue