Merge from emacs--devo--0
[bpt/emacs.git] / src / coding.c
index 65d2a1e..d3a82ae 100644 (file)
@@ -1,7 +1,8 @@
 /* Coding system handler (conversion, detection, etc).
    Copyright (C) 2001, 2002, 2003, 2004, 2005,
-                 2006 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1997, 1998, 2002, 2003, 2004, 2005
+                 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+     2005, 2006, 2007
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
    Copyright (C) 2003
@@ -340,6 +341,12 @@ Lisp_Object eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac;
    decided.  */
 Lisp_Object eol_mnemonic_undecided;
 
+/* Format of end-of-line decided by system.  This is Qunix on
+   Unix and Mac, Qdos on DOS/Windows.
+   This has an effect only for external encoding (i.e. for output to
+   file and process), not for in-buffer or Lisp string encoding.  */
+static Lisp_Object system_eol_type;
+
 #ifdef emacs
 
 Lisp_Object Vcoding_system_list, Vcoding_system_alist;
@@ -871,7 +878,7 @@ static void coding_set_source P_ ((struct coding_system *));
 static void coding_set_destination P_ ((struct coding_system *));
 static void coding_alloc_by_realloc P_ ((struct coding_system *, EMACS_INT));
 static void coding_alloc_by_making_gap P_ ((struct coding_system *,
-                                           EMACS_INT));
+                                           EMACS_INT, EMACS_INT));
 static unsigned char *alloc_destination P_ ((struct coding_system *,
                                             EMACS_INT, unsigned char *));
 static void setup_iso_safe_charsets P_ ((Lisp_Object));
@@ -1027,18 +1034,20 @@ coding_alloc_by_realloc (coding, bytes)
 }
 
 static void
-coding_alloc_by_making_gap (coding, bytes)
+coding_alloc_by_making_gap (coding, offset, bytes)
      struct coding_system *coding;
-     EMACS_INT bytes;
+     EMACS_INT offset, bytes;
 {
   if (BUFFERP (coding->dst_object)
       && EQ (coding->src_object, coding->dst_object))
     {
-      EMACS_INT add = coding->src_bytes - coding->consumed;
+      EMACS_INT add = offset + (coding->src_bytes - coding->consumed);
 
+      GPT += offset, GPT_BYTE += offset;
       GAP_SIZE -= add; ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add;
       make_gap (bytes);
       GAP_SIZE += add; ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add;
+      GPT -= offset, GPT_BYTE -= offset;
     }
   else
     {
@@ -1061,7 +1070,7 @@ alloc_destination (coding, nbytes, dst)
   EMACS_INT offset = dst - coding->destination;
 
   if (BUFFERP (coding->dst_object))
-    coding_alloc_by_making_gap (coding, nbytes);
+    coding_alloc_by_making_gap (coding, offset, nbytes);
   else
     coding_alloc_by_realloc (coding, nbytes);
   record_conversion_result (coding, CODING_RESULT_SUCCESS);
@@ -2942,6 +2951,9 @@ decode_coding_iso_2022 (coding)
 
   CODING_GET_INFO (coding, attrs, charset_list);
   setup_iso_safe_charsets (attrs);
+  /* Charset list may have been changed.  */
+  charset_list = CODING_ATTR_CHARSET_LIST (attrs);
+  coding->safe_charsets = (char *) SDATA (CODING_ATTR_SAFE_CHARSETS(attrs));
 
   while (1)
     {
@@ -3800,7 +3812,7 @@ encode_coding_iso_2022 (coding)
 
   setup_iso_safe_charsets (attrs);
   /* Charset list may have been changed.  */
-  charset_list = CODING_ATTR_CHARSET_LIST (attrs);             \
+  charset_list = CODING_ATTR_CHARSET_LIST (attrs);
   coding->safe_charsets = (char *) SDATA (CODING_ATTR_SAFE_CHARSETS(attrs));
 
   ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs));
@@ -4725,6 +4737,7 @@ detect_coding_charset (coding, detect_info)
   int consumed_chars = 0;
   Lisp_Object attrs, valids;
   int found = 0;
+  int head_ascii = coding->head_ascii;
 
   detect_info->checked |= CATEGORY_MASK_CHARSET;
 
@@ -4733,21 +4746,68 @@ detect_coding_charset (coding, detect_info)
   valids = AREF (attrs, coding_attr_charset_valids);
 
   if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs)))
-    src += coding->head_ascii;
+    src += head_ascii;
 
   while (1)
     {
       int c;
+      Lisp_Object val;
+      struct charset *charset;
+      int dim, idx;
 
       src_base = src;
       ONE_MORE_BYTE (c);
       if (c < 0)
        continue;
-      if (NILP (AREF (valids, c)))
+      val = AREF (valids, c);
+      if (NILP (val))
        break;
       if (c >= 0x80)
        found = CATEGORY_MASK_CHARSET;
+      if (INTEGERP (val))
+       {
+         charset = CHARSET_FROM_ID (XFASTINT (val));
+         dim = CHARSET_DIMENSION (charset);
+         for (idx = 1; idx < dim; idx++)
+           {
+             if (src == src_end)
+               goto too_short;
+             ONE_MORE_BYTE (c);
+             if (c < charset->code_space[(dim - 1 - idx) * 2] 
+                 || c > charset->code_space[(dim - 1 - idx) * 2 + 1])
+               break;
+           }
+         if (idx < dim)
+           break;
+       }
+      else
+       {
+         idx = 1;
+         for (; CONSP (val); val = XCDR (val))
+           {
+             charset = CHARSET_FROM_ID (XFASTINT (XCAR (val)));
+             dim = CHARSET_DIMENSION (charset);
+             while (idx < dim)
+               {
+                 if (src == src_end)
+                   goto too_short;
+                 ONE_MORE_BYTE (c);
+                 if (c < charset->code_space[(dim - 1 - idx) * 4]
+                     || c > charset->code_space[(dim - 1 - idx) * 4 + 1])
+                   break;
+                 idx++;
+               }
+             if (idx == dim)
+               {
+                 val = Qnil;
+                 break;
+               }
+           }
+         if (CONSP (val))
+           break;
+       }
     }
+ too_short:
   detect_info->rejected |= CATEGORY_MASK_CHARSET;
   return 0;
 
@@ -4957,8 +5017,14 @@ setup_coding_system (coding_system, coding)
 
   coding->mode = 0;
   coding->head_ascii = -1;
-  coding->common_flags
-    = (VECTORP (eol_type) ? CODING_REQUIRE_DETECTION_MASK : 0);
+  if (VECTORP (eol_type))
+    coding->common_flags = (CODING_REQUIRE_DECODING_MASK
+                           | CODING_REQUIRE_DETECTION_MASK);
+  else if (! EQ (eol_type, Qunix))
+    coding->common_flags = (CODING_REQUIRE_DECODING_MASK
+                           | CODING_REQUIRE_ENCODING_MASK);
+  else
+    coding->common_flags = 0;
   if (! NILP (CODING_ATTR_POST_READ (attrs)))
     coding->common_flags |= CODING_REQUIRE_DECODING_MASK;
   if (! NILP (CODING_ATTR_PRE_WRITE (attrs)))
@@ -5174,7 +5240,9 @@ raw_text_coding_system (coding_system)
 
 /* If CODING_SYSTEM doesn't specify end-of-line format but PARENT
    does, return one of the subsidiary that has the same eol-spec as
-   PARENT.  Otherwise, return CODING_SYSTEM.  */
+   PARENT.  Otherwise, return CODING_SYSTEM.  If PARENT is nil,
+   inherit end-of-line format from the system's setting
+   (system_eol_type).  */
 
 Lisp_Object
 coding_inherit_eol_type (coding_system, parent)
@@ -5186,15 +5254,19 @@ coding_inherit_eol_type (coding_system, parent)
     coding_system = Qraw_text;
   spec = CODING_SYSTEM_SPEC (coding_system);
   eol_type = AREF (spec, 2);
-  if (VECTORP (eol_type)
-      && ! NILP (parent))
+  if (VECTORP (eol_type))
     {
-      Lisp_Object parent_spec;
       Lisp_Object parent_eol_type;
 
-      parent_spec
-       = CODING_SYSTEM_SPEC (buffer_defaults.buffer_file_coding_system);
-      parent_eol_type = AREF (parent_spec, 2);
+      if (! NILP (parent))
+       {
+         Lisp_Object parent_spec;
+
+         parent_spec = CODING_SYSTEM_SPEC (parent);
+         parent_eol_type = AREF (parent_spec, 2);
+       }
+      else
+       parent_eol_type = system_eol_type;
       if (EQ (parent_eol_type, Qunix))
        coding_system = AREF (eol_type, 0);
       else if (EQ (parent_eol_type, Qdos))
@@ -6689,7 +6761,9 @@ decode_coding_gap (coding, chars, bytes)
     detect_coding (coding);
 
   coding->mode |= CODING_MODE_LAST_BLOCK;
+  current_buffer->text->inhibit_shrinking = 1;
   decode_coding (coding);
+  current_buffer->text->inhibit_shrinking = 0;
 
   attrs = CODING_ID_ATTRS (coding->id);
   if (! NILP (CODING_ATTR_POST_READ (attrs)))
@@ -7157,8 +7231,7 @@ function `define-coding-system'.  */)
     }
   if (!NILP (Fcoding_system_p (coding_system)))
     return coding_system;
-  while (1)
-    Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
+  xsignal1 (Qcoding_system_error, coding_system);
 }
 
 \f
@@ -7226,7 +7299,7 @@ detect_coding_system (src, src_chars, src_bytes, highest, multibytep,
            break;
          if (c < 0x20
              && (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
-             && inhibit_iso_escape_detection)
+             && inhibit_iso_escape_detection)
            {
              coding.head_ascii = src - coding.source;
              if (detect_coding_iso_2022 (&coding, &detect_info))
@@ -7249,6 +7322,7 @@ detect_coding_system (src, src_chars, src_bytes, highest, multibytep,
            for (i = 0; i < coding_category_raw_text; i++)
              {
                category = coding_priorities[i];
+               this = coding_categories + category;
                if (detect_info.found & (1 << category))
                  break;
              }
@@ -7332,7 +7406,8 @@ detect_coding_system (src, src_chars, src_bytes, highest, multibytep,
                {
                  found |= 1 << category;
                  id = coding_categories[category].id;
-                 val = Fcons (make_number (id), val);
+                 if (id >= 0)
+                   val = Fcons (make_number (id), val);
                }
            }
          for (i = coding_category_raw_text - 1; i >= 0; i--)
@@ -7442,7 +7517,8 @@ DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region,
        doc: /* Detect coding system of the text in the region between START and END.
 Return a list of possible coding systems ordered by priority.
 
-If only ASCII characters are found, it returns a list of single element
+If only ASCII characters are found (except for such ISO-2022 control
+characters ISO-2022 as ESC), it returns a list of single element
 `undecided' or its subsidiary coding system according to a detected
 end-of-line format.
 
@@ -7478,7 +7554,8 @@ DEFUN ("detect-coding-string", Fdetect_coding_string, Sdetect_coding_string,
        doc: /* Detect coding system of the text in STRING.
 Return a list of possible coding systems ordered by priority.
 
-If only ASCII characters are found, it returns a list of single element
+If only ASCII characters are found (except for such ISO-2022 control
+characters ISO-2022 as ESC), it returns a list of single element
 `undecided' or its subsidiary coding system according to a detected
 end-of-line format.
 
@@ -8115,7 +8192,7 @@ Return the corresponding character.  */)
 
 
 DEFUN ("encode-sjis-char", Fencode_sjis_char, Sencode_sjis_char, 1, 1, 0,
-       doc: /* Encode a Japanese character CHAR to shift_jis encoding.
+       doc: /* Encode a Japanese character CH to shift_jis encoding.
 Return the corresponding code in SJIS.  */)
      (ch)
     Lisp_Object ch;
@@ -8183,7 +8260,7 @@ Return the corresponding character.  */)
 }
 
 DEFUN ("encode-big5-char", Fencode_big5_char, Sencode_big5_char, 1, 1, 0,
-       doc: /* Encode the Big5 character CHAR to BIG5 coding system.
+       doc: /* Encode the Big5 character CH to BIG5 coding system.
 Return the corresponding character code in Big5.  */)
      (ch)
      Lisp_Object ch;
@@ -8302,7 +8379,7 @@ is selected as the TARGET.  For example, if OPERATION does file I/O,
 whichever argument specifies the file name is TARGET.
 
 TARGET has a meaning which depends on OPERATION:
-  For file I/O, TARGET is a file name.
+  For file I/O, TARGET is a file name (except for the special case below).
   For process I/O, TARGET is a process name.
   For network I/O, TARGET is a service name or a port number
 
@@ -8314,6 +8391,13 @@ or a function symbol to call.
 In the last case, we call the function with one argument,
 which is a list of all the arguments given to this function.
 
+If OPERATION is `insert-file-contents', the argument corresponding to
+TARGET may be a cons (FILENAME . BUFFER).  In that case, FILENAME is a
+file name to look up, and BUFFER is a buffer that contains the file's
+contents (not yet decoded).  If `file-coding-system-alist' specifies a
+function to call for FILENAME, that function should examine the
+contents of BUFFER instead of reading the file.
+
 usage: (find-operation-coding-system OPERATION ARGUMENTS ...)  */)
      (nargs, args)
      int nargs;
@@ -8333,8 +8417,12 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...)  */)
           SDATA (SYMBOL_NAME (operation)));
   target = args[XINT (target_idx) + 1];
   if (!(STRINGP (target)
+       || (EQ (operation, Qinsert_file_contents) && CONSP (target)
+           && STRINGP (XCAR (target)) && BUFFERP (XCDR (target)))
        || (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
     error ("Invalid %dth argument", XINT (target_idx) + 1);
+  if (CONSP (target))
+    target = XCAR (target);
 
   chain = ((EQ (operation, Qinsert_file_contents)
            || EQ (operation, Qwrite_region))
@@ -8367,6 +8455,9 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...)  */)
            return Fcons (val, val);
          if (! NILP (Ffboundp (val)))
            {
+             /* We use call1 rather than safe_call1
+                so as to get bug reports about functions called here
+                which don't handle the current interface.  */
              val = call1 (val, Flist (nargs, args));
              if (CONSP (val))
                return val;
@@ -9739,6 +9830,12 @@ character.");
     for (i = 0; i < coding_category_max; i++)
       Fset (AREF (Vcoding_category_table, i), Qno_conversion);
   }
+#if defined (MSDOS) || defined (WINDOWSNT)
+  system_eol_type = Qdos;
+#else
+  system_eol_type = Qunix;
+#endif
+  staticpro (&system_eol_type);
 }
 
 char *