(Finsert_file_contents): Run format-decode and

after_insert_file_functions on entire buffer when REPLACE is
non-nil and inhibit modification_hooks and point_motion_hooks.
For consistency, run after_insert_file_functions iff something
got inserted.  Move signal_after_change and update_compositions
after code running after_insert_file_functions.  Make sure that
undo_list doesn't record intermediate steps of the decoding
process.
This commit is contained in:
Martin Rudalics
2007-08-07 12:23:20 +00:00
parent 3ceeb306d2
commit 6f2528d8d8
2 changed files with 126 additions and 48 deletions

View File

@@ -1,3 +1,14 @@
2007-08-07 Martin Rudalics <rudalics@gmx.at>
* fileio.c (Finsert_file_contents): Run format-decode and
after_insert_file_functions on entire buffer when REPLACE is
non-nil and inhibit modification_hooks and point_motion_hooks.
For consistency, run after_insert_file_functions iff something
got inserted. Move signal_after_change and update_compositions
after code running after_insert_file_functions. Make sure that
undo_list doesn't record intermediate steps of the decoding
process.
2007-08-07 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
* emacs.c (main)

View File

@@ -3690,27 +3690,25 @@ DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
1, 5, 0,
doc: /* Insert contents of file FILENAME after point.
Returns list of absolute file name and number of characters inserted.
If second argument VISIT is non-nil, the buffer's visited filename
and last save file modtime are set, and it is marked unmodified.
If visiting and the file does not exist, visiting is completed
before the error is signaled.
The optional third and fourth arguments BEG and END
specify what portion of the file to insert.
These arguments count bytes in the file, not characters in the buffer.
If VISIT is non-nil, BEG and END must be nil.
If second argument VISIT is non-nil, the buffer's visited filename and
last save file modtime are set, and it is marked unmodified. If
visiting and the file does not exist, visiting is completed before the
error is signaled.
If optional fifth argument REPLACE is non-nil,
it means replace the current buffer contents (in the accessible portion)
with the file contents. This is better than simply deleting and inserting
the whole thing because (1) it preserves some marker positions
and (2) it puts less data in the undo list.
When REPLACE is non-nil, the value is the number of characters actually read,
which is often less than the number of characters to be read.
The optional third and fourth arguments BEG and END specify what portion
of the file to insert. These arguments count bytes in the file, not
characters in the buffer. If VISIT is non-nil, BEG and END must be nil.
This does code conversion according to the value of
`coding-system-for-read' or `file-coding-system-alist',
and sets the variable `last-coding-system-used' to the coding system
actually used. */)
If optional fifth argument REPLACE is non-nil, replace the current
buffer contents (in the accessible portion) with the file contents.
This is better than simply deleting and inserting the whole thing
because (1) it preserves some marker positions and (2) it puts less data
in the undo list. When REPLACE is non-nil, the second return value is
the number of characters that replace previous buffer contents.
This function does code conversion according to the value of
`coding-system-for-read' or `file-coding-system-alist', and sets the
variable `last-coding-system-used' to the coding system actually used. */)
(filename, visit, beg, end, replace)
Lisp_Object filename, visit, beg, end, replace;
{
@@ -3720,8 +3718,8 @@ actually used. */)
register int how_much;
register int unprocessed;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object handler, val, insval, orig_filename;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
Lisp_Object handler, val, insval, orig_filename, old_undo;
Lisp_Object p;
int total = 0;
int not_regular = 0;
@@ -3744,8 +3742,9 @@ actually used. */)
val = Qnil;
p = Qnil;
orig_filename = Qnil;
old_undo = Qnil;
GCPRO4 (filename, val, p, orig_filename);
GCPRO5 (filename, val, p, orig_filename, old_undo);
CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
@@ -4704,24 +4703,105 @@ actually used. */)
/* Decode file format */
if (inserted > 0)
{
int empty_undo_list_p = 0;
/* Don't run point motion or modification hooks when decoding. */
int count = SPECPDL_INDEX ();
specbind (Qinhibit_point_motion_hooks, Qt);
specbind (Qinhibit_modification_hooks, Qt);
/* If we're anyway going to discard undo information, don't
record it in the first place. The buffer's undo list at this
point is either nil or t when visiting a file. */
if (!NILP (visit))
/* Save old undo list and don't record undo for decoding. */
old_undo = current_buffer->undo_list;
current_buffer->undo_list = Qt;
if (NILP (replace))
{
empty_undo_list_p = NILP (current_buffer->undo_list);
current_buffer->undo_list = Qt;
insval = call3 (Qformat_decode,
Qnil, make_number (inserted), visit);
CHECK_NUMBER (insval);
inserted = XFASTINT (insval);
}
else
{
/* If REPLACE is non-nil and we succeeded in not replacing the
beginning or end of the buffer text with the file's contents,
call format-decode with `point' positioned at the beginning of
the buffer and `inserted' equalling the number of characters
in the buffer. Otherwise, format-decode might fail to
correctly analyze the beginning or end of the buffer. Hence
we temporarily save `point' and `inserted' here and restore
`point' iff format-decode did not insert or delete any text.
Otherwise we leave `point' at point-min. */
int opoint = PT;
int opoint_byte = PT_BYTE;
int oinserted = ZV - BEGV;
TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
insval = call3 (Qformat_decode,
Qnil, make_number (oinserted), visit);
CHECK_NUMBER (insval);
if (insval = oinserted)
SET_PT_BOTH (opoint, opoint_byte);
inserted = XFASTINT (insval);
}
insval = call3 (Qformat_decode,
Qnil, make_number (inserted), visit);
CHECK_NUMBER (insval);
inserted = XFASTINT (insval);
/* For consistency with format-decode call these now iff inserted > 0
(martin 2007-06-28) */
p = Vafter_insert_file_functions;
while (CONSP (p))
{
if (NILP (replace))
{
insval = call1 (XCAR (p), make_number (inserted));
if (!NILP (insval))
{
CHECK_NUMBER (insval);
inserted = XFASTINT (insval);
}
}
else
{
/* For the rationale of this see the comment on format-decode above. */
int opoint = PT;
int opoint_byte = PT_BYTE;
int oinserted = ZV - BEGV;
if (!NILP (visit))
current_buffer->undo_list = empty_undo_list_p ? Qnil : Qt;
TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
insval = call1 (XCAR (p), make_number (oinserted));
if (!NILP (insval))
{
CHECK_NUMBER (insval);
if (insval = oinserted)
SET_PT_BOTH (opoint, opoint_byte);
inserted = XFASTINT (insval);
}
}
QUIT;
p = XCDR (p);
}
if (NILP (visit))
{
Lisp_Object lbeg, lend;
XSETINT (lbeg, PT);
XSETINT (lend, PT + inserted);
if (CONSP (old_undo))
{
Lisp_Object tem = XCAR (old_undo);
if (CONSP (tem) && INTEGERP (XCAR (tem)) &&
INTEGERP (XCDR (tem)) && (XCAR (tem)) == lbeg)
/* In the non-visiting case record only the final insertion. */
current_buffer->undo_list =
Fcons (Fcons (lbeg, lend), Fcdr (old_undo));
}
}
else if (old_undo == Qt)
/* If undo_list was Qt before, keep it that way. */
current_buffer->undo_list = Qt;
else
/* Otherwise start with an empty undo_list. */
current_buffer->undo_list = Qnil;
unbind_to (count, Qnil);
}
/* Call after-change hooks for the inserted text, aside from the case
@@ -4734,19 +4814,6 @@ actually used. */)
update_compositions (PT, PT, CHECK_BORDER);
}
p = Vafter_insert_file_functions;
while (CONSP (p))
{
insval = call1 (XCAR (p), make_number (inserted));
if (!NILP (insval))
{
CHECK_NUMBER (insval);
inserted = XFASTINT (insval);
}
QUIT;
p = XCDR (p);
}
if (!NILP (visit)
&& current_buffer->modtime == -1)
{