summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenichi Handa <handa@m17n.org>1998-06-12 01:38:07 +0000
committerKenichi Handa <handa@m17n.org>1998-06-12 01:38:07 +0000
commit0cd5f72036da2db2bc802e20ba0cb28ed889671a (patch)
tree3211a5befd000699ea9ed8a0eff5db90fbe78f0b
parent111a8483a9d6a769f31255149df4ef806f6ad84e (diff)
downloademacs-0cd5f72036da2db2bc802e20ba0cb28ed889671a.tar.gz
(set_auto_coding_unwind): New function.
(Finsert_file_contents): If the current buffer is empty, decide the coding system after the file is inserted in the buffer. If not, insert the head and tail of a file in a temporary buffer and call set-auto-coding-function. (e_write): If there are carryover bytes in encoding because of incomplete multibyte form, write them out as is.
-rw-r--r--src/fileio.c338
1 files changed, 189 insertions, 149 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 66ac9587342..742c7ad95fe 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3246,6 +3246,26 @@ Lisp_Object Qfind_buffer_file_type;
#define READ_BUF_SIZE (64 << 10)
#endif
+/* This function is called when a function bound to
+ Vset_auto_coding_function causes some error. At that time, a text
+ of a file has already been inserted in the current buffer, but,
+ markers has not yet been adjusted. Thus we must adjust markers
+ here. We are sure that the buffer was empty before the text of the
+ file was inserted. */
+
+static Lisp_Object
+set_auto_coding_unwind (multibyte)
+ Lisp_Object multibyte;
+{
+ int inserted = Z_BYTE - BEG_BYTE;
+
+ if (!NILP (multibyte))
+ inserted = multibyte_chars_in_text (GPT_ADDR - inserted, inserted);
+ adjust_after_insert (PT, PT_BYTE, Z, Z_BYTE, inserted);
+
+ return Qnil;
+}
+
DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
1, 5, 0,
"Insert contents of file FILENAME after point.\n\
@@ -3290,6 +3310,7 @@ actually used.")
unsigned char buffer[1 << 14];
int replace_handled = 0;
int set_coding_system = 0;
+ int coding_system_decided = 0;
if (current_buffer->base_buffer && ! NILP (visit))
error ("Cannot do file visiting in an indirect buffer");
@@ -3392,161 +3413,107 @@ actually used.")
}
}
- /* Decide the coding-system of the file. */
- {
- Lisp_Object val;
- val = Qnil;
-
- if (!NILP (Vcoding_system_for_read))
- val = Vcoding_system_for_read;
- else if (! NILP (replace))
- /* In REPLACE mode, we can use the same coding system
- that was used to visit the file. */
- val = current_buffer->buffer_file_coding_system;
- else if (! not_regular)
- {
- /* Don't try looking inside a file for a coding system specification
- if it is not seekable. */
- if (! NILP (Vset_auto_coding_function))
- {
- /* Find a coding system specified in the heading two lines
- or in the tailing several lines of the file. We assume
- that the 1K-byte and 3K-byte for heading and tailing
- respectively are sufficient fot this purpose. */
- int nread;
- int beginning_of_end, end_of_beginning;
-
- if (st.st_size <= (1024 * 4))
- {
- nread = read (fd, read_buf, 1024 * 4);
- end_of_beginning = nread;
- beginning_of_end = 0;
- }
- else
- {
- nread = read (fd, read_buf, 1024);
- end_of_beginning = nread;
- beginning_of_end = nread;
- if (nread >= 0)
- {
- if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
- nread += read (fd, read_buf + nread, 1024 * 3);
- }
- }
+ if (BEG < Z)
+ {
+ /* Decide the coding system to use for reading the file now
+ because we can't use an optimized method for handling
+ `coding:' tag if the current buffer is not empty. */
+ Lisp_Object val;
+ val = Qnil;
- if (nread < 0)
- error ("IO error reading %s: %s",
- XSTRING (orig_filename)->data, strerror (errno));
- else if (nread > 0)
- {
- int i;
- int possible_spec = 0;
- unsigned char *p, *p1;
- Lisp_Object tem;
- unsigned char *copy = (unsigned char *) alloca (nread + 1);
-
- /* Make a copy of the contents of read_buf in COPY,
- and convert it to lower case so we can compare
- more efficiently. */
- bcopy (read_buf, copy, nread);
- for (i = 0; i < nread; i++)
- copy[i] = DOWNCASE (copy[i]);
- /* Ensure various comparisons fail at end of data. */
- copy[nread] = 0;
-
- /* Now test quickly whether the file contains a -*- line. */
- p = copy;
- while (*p != '\n' && p - copy < end_of_beginning)
- p++;
- if (copy[0] == '#' && copy[1] == '!')
- while (*p != '\n' && p - copy < end_of_beginning)
- p++;
- p1 = copy;
- while (p - p1 >= 3)
- {
- if (p1[0] == '-' && p1[1] == '*' && p1[2] == '-')
- {
- while (p - p1 >= 7)
- {
- if (! bcmp ("coding:", p1, 7))
- {
- possible_spec = 1;
- goto win;
- }
- p1++;
- }
- break;
- }
- p1++;
- }
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if (! NILP (replace))
+ /* In REPLACE mode, we can use the same coding system
+ that was used to visit the file. */
+ val = current_buffer->buffer_file_coding_system;
+ else
+ {
+ /* Don't try looking inside a file for a coding system
+ specification if it is not seekable. */
+ if (! not_regular && ! NILP (Vset_auto_coding_function))
+ {
+ /* Find a coding system specified in the heading two
+ lines or in the tailing several lines of the file.
+ We assume that the 1K-byte and 3K-byte for heading
+ and tailing respectively are sufficient fot this
+ purpose. */
+ int how_many, nread;
+
+ if (st.st_size <= (1024 * 4))
+ nread = read (fd, read_buf, 1024 * 4);
+ else
+ {
+ nread = read (fd, read_buf, 1024);
+ if (nread >= 0)
+ {
+ if (lseek (fd, st.st_size - (1024 * 3), 0) < 0)
+ report_file_error ("Setting file position",
+ Fcons (orig_filename, Qnil));
+ nread += read (fd, read_buf + nread, 1024 * 3);
+ }
+ }
- /* Test quickly whether the file
- contains a local variables list. */
- p = &copy[nread - 1];
- p1 = &copy[beginning_of_end];
- while (p > p1)
- {
- if (p[0] == '\n' && p[1] == '\f')
- break;
- p--;
- }
- p1 = &copy[nread];
- while (p1 - p >= 16)
- {
- if (! bcmp ("local variables:", p, 16))
- {
- possible_spec = 1;
- break;
- }
- p++;
- }
- win:
+ if (nread < 0)
+ error ("IO error reading %s: %s",
+ XSTRING (orig_filename)->data, strerror (errno));
+ else if (nread > 0)
+ {
+ int count = specpdl_ptr - specpdl;
+ struct buffer *prev = current_buffer;
+
+ record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
+ temp_output_buffer_setup (" *code-converting-work*");
+ set_buffer_internal (XBUFFER (Vstandard_output));
+ current_buffer->enable_multibyte_characters = Qnil;
+ insert_1_both (read_buf, nread, nread, 0, 0, 0);
+ TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+ val = call1 (Vset_auto_coding_function, make_number (nread));
+ set_buffer_internal (prev);
+ /* Discard the unwind protect for recovering the
+ current buffer. */
+ specpdl_ptr--;
+
+ /* Rewind the file for the actual read done later. */
+ if (lseek (fd, 0, 0) < 0)
+ report_file_error ("Setting file position",
+ Fcons (orig_filename, Qnil));
+ }
+ }
- if (possible_spec)
- {
- /* Always make this a unibyte string
- because we have not yet decoded it. */
- tem = make_unibyte_string (read_buf, nread);
- val = call1 (Vset_auto_coding_function, tem);
- }
+ if (NILP (val))
+ {
+ /* If we have not yet decided a coding system, check
+ file-coding-system-alist. */
+ Lisp_Object args[6], coding_systems;
+
+ args[0] = Qinsert_file_contents, args[1] = orig_filename;
+ args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
+ coding_systems = Ffind_operation_coding_system (6, args);
+ if (CONSP (coding_systems))
+ val = XCONS (coding_systems)->car;
+ }
+ }
- /* Rewind the file for the actual read done later. */
- if (lseek (fd, 0, 0) < 0)
- report_file_error ("Setting file position",
- Fcons (orig_filename, Qnil));
- }
- }
- if (NILP (val))
- {
- Lisp_Object args[6], coding_systems;
+ setup_coding_system (Fcheck_coding_system (val), &coding);
- args[0] = Qinsert_file_contents, args[1] = orig_filename;
- args[2] = visit, args[3] = beg, args[4] = end, args[5] = replace;
- coding_systems = Ffind_operation_coding_system (6, args);
- if (CONSP (coding_systems))
- val = XCONS (coding_systems)->car;
- }
- }
+ if (NILP (Vcoding_system_for_read)
+ && NILP (current_buffer->enable_multibyte_characters))
+ {
+ /* We must suppress all text conversion except for end-of-line
+ conversion. */
+ int eol_type;
- if (NILP (Vcoding_system_for_read)
- && NILP (current_buffer->enable_multibyte_characters))
- {
- /* We must suppress all text conversion except for end-of-line
- conversion. */
- struct coding_system coding_temp;
+ eol_type = coding.eol_type;
+ setup_coding_system (Qraw_text, &coding);
+ coding.eol_type = eol_type;
+ }
- setup_coding_system (Fcheck_coding_system (val), &coding_temp);
- setup_coding_system (Qraw_text, &coding);
- coding.eol_type = coding_temp.eol_type;
- }
- else
- setup_coding_system (Fcheck_coding_system (val), &coding);
+ coding_system_decided = 1;
+ }
- /* Ensure we always set Vlast_coding_system_used. */
- set_coding_system = 1;
- }
+ /* Ensure we always set Vlast_coding_system_used. */
+ set_coding_system = 1;
/* If requested, replace the accessible part of the buffer
with the file contents. Avoid replacing text at the
@@ -3563,6 +3530,7 @@ actually used.")
But if we discover the need for conversion, we give up on this method
and let the following if-statement handle the replace job. */
if (!NILP (replace)
+ && BEGV < ZV
&& ! CODING_REQUIRE_DECODING (&coding)
&& (coding.eol_type == CODING_EOL_UNDECIDED
|| coding.eol_type == CODING_EOL_LF))
@@ -3741,7 +3709,7 @@ actually used.")
is needed, in a simple way that needs a lot of memory.
The preceding if-statement handles the case of no conversion
in a more optimized way. */
- if (!NILP (replace) && ! replace_handled)
+ if (!NILP (replace) && ! replace_handled && BEGV < ZV)
{
int same_at_start = BEGV_BYTE;
int same_at_end = ZV_BYTE;
@@ -3993,6 +3961,69 @@ actually used.")
if (inserted > 0)
{
+ if (! coding_system_decided)
+ {
+ /* The coding system is not yet decided. Decide it by an
+ optimized method for handling `coding:' tag. */
+ Lisp_Object val;
+ val = Qnil;
+
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else
+ {
+ if (! NILP (Vset_auto_coding_function))
+ {
+ /* Since we are sure that the current buffer was
+ empty before the insertion, we can toggle
+ enable-multibyte-characters directly here without
+ taking care of marker adjustment and byte
+ combining problem. */
+ Lisp_Object prev_multibyte;
+ int count = specpdl_ptr - specpdl;
+
+ prev_multibyte = current_buffer->enable_multibyte_characters;
+ current_buffer->enable_multibyte_characters = Qnil;
+ record_unwind_protect (set_auto_coding_unwind,
+ prev_multibyte);
+ val = call1 (Vset_auto_coding_function,
+ make_number (inserted));
+ /* Discard the unwind protect for recovering the
+ error of Vset_auto_coding_function. */
+ specpdl_ptr--;
+ current_buffer->enable_multibyte_characters = prev_multibyte;
+ TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
+ }
+
+ if (NILP (val))
+ {
+ /* If the coding system is not yet decided, check
+ file-coding-system-alist. */
+ Lisp_Object args[6], coding_systems;
+
+ args[0] = Qinsert_file_contents, args[1] = orig_filename;
+ args[2] = visit, args[3] = beg, args[4] = end, args[5] = Qnil;
+ coding_systems = Ffind_operation_coding_system (6, args);
+ if (CONSP (coding_systems))
+ val = XCONS (coding_systems)->car;
+ }
+ }
+
+ setup_coding_system (Fcheck_coding_system (val), &coding);
+
+ if (NILP (Vcoding_system_for_read)
+ && NILP (current_buffer->enable_multibyte_characters))
+ {
+ /* We must suppress all text conversion except for
+ end-of-line conversion. */
+ int eol_type;
+
+ eol_type = coding.eol_type;
+ setup_coding_system (Qraw_text, &coding);
+ coding.eol_type = eol_type;
+ }
+ }
+
if (CODING_MAY_REQUIRE_DECODING (&coding))
{
/* Here, we don't have to consider byte combining (see the
@@ -4763,13 +4794,22 @@ e_write (desc, addr, nbytes, coding)
now it is handled within encode_coding. */
while (1)
{
- encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
+ int result;
+
+ result = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE);
nbytes -= coding->consumed, addr += coding->consumed;
if (coding->produced > 0)
{
coding->produced -= write (desc, buf, coding->produced);
if (coding->produced) return -1;
}
+ if (result == CODING_FINISH_INSUFFICIENT_SRC)
+ {
+ /* The source text ends by an incomplete multibyte form.
+ There's no way other than write it out as is. */
+ nbytes -= write (desc, addr, nbytes);
+ if (nbytes) return -1;
+ }
if (nbytes <= 0)
break;
}