(Fread_coding_system): Update decl.
[bpt/emacs.git] / src / coding.c
index bcc603a..4fae220 100644 (file)
@@ -1,7 +1,6 @@
 /* Coding system handler (conversion, detection, and etc).
-   Ver.1.0.
-   Copyright (C) 1995 Free Software Foundation, Inc.
-   Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
+   Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
+   Licensed to the Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -23,7 +22,7 @@ Boston, MA 02111-1307, USA.  */
 /*** TABLE OF CONTENTS ***
 
   1. Preamble
-  2. Emacs' internal format handlers
+  2. Emacs' internal format (emacs-mule) handlers
   3. ISO2022 handlers
   4. Shift-JIS and BIG5 handlers
   5. End-of-line handlers
@@ -38,47 +37,53 @@ Boston, MA 02111-1307, USA.  */
   Coding system is an encoding mechanism of one or more character
   sets.  Here's a list of coding systems which Emacs can handle.  When
   we say "decode", it means converting some other coding system to
-  Emacs' internal format, and when we say "encode", it means
-  converting Emacs' internal format to some other coding system.
+  Emacs' internal format (emacs-internal), and when we say "encode",
+  it means converting the coding system emacs-mule to some other
+  coding system.
 
-  0. Emacs' internal format
+  0. Emacs' internal format (emacs-mule)
 
   Emacs itself holds a multi-lingual character in a buffer and a string
-  in a special format.  Details are described in the section 2.
+  in a special format.  Details are described in section 2.
 
   1. ISO2022
 
   The most famous coding system for multiple character sets.  X's
-  Compound Text, various EUCs (Extended Unix Code), and such coding
-  systems used in Internet communication as ISO-2022-JP are all
-  variants of ISO2022.  Details are described in the section 3.
+  Compound Text, various EUCs (Extended Unix Code), and coding
+  systems used in Internet communication such as ISO-2022-JP are
+  all variants of ISO2022.  Details are described in section 3.
 
   2. SJIS (or Shift-JIS or MS-Kanji-Code)
    
   A coding system to encode character sets: ASCII, JISX0201, and
   JISX0208.  Widely used for PC's in Japan.  Details are described in
-  the section 4.
+  section 4.
 
   3. BIG5
 
   A coding system to encode character sets: ASCII and Big5.  Widely
   used by Chinese (mainly in Taiwan and Hong Kong).  Details are
-  described in the section 4.  In this file, when written as "BIG5"
-  (all uppercase), it means the coding system, and when written as
-  "Big5" (capitalized), it means the character set.
+  described in section 4.  In this file, when we write "BIG5"
+  (all uppercase), we mean the coding system, and when we write
+  "Big5" (capitalized), we mean the character set.
 
-  4. Else
+  4. Raw text
 
-  If a user want to read/write a text encoded in a coding system not
+  A coding system to for a text containing random 8-bit code.  Emacs
+  does no code conversion on such a text except for end-of-line
+  format.
+
+  5. Other
+
+  If a user wants to read/write a text encoded in a coding system not
   listed above, he can supply a decoder and an encoder for it in CCL
   (Code Conversion Language) programs.  Emacs executes the CCL program
   while reading/writing.
 
-  Emacs represent a coding-system by a Lisp symbol that has a property
+  Emacs represents a coding-system by a Lisp symbol that has a property
   `coding-system'.  But, before actually using the coding-system, the
   information about it is set in a structure of type `struct
-  coding_system' for rapid processing.  See the section 6 for more
-  detail.
+  coding_system' for rapid processing.  See section 6 for more details.
 
 */
 
@@ -86,14 +91,13 @@ Boston, MA 02111-1307, USA.  */
 
   How end-of-line of a text is encoded depends on a system.  For
   instance, Unix's format is just one byte of `line-feed' code,
-  whereas DOS's format is two bytes sequence of `carriage-return' and
+  whereas DOS's format is two-byte sequence of `carriage-return' and
   `line-feed' codes.  MacOS's format is one byte of `carriage-return'.
 
-  Since how characters in a text is encoded and how end-of-line is
-  encoded is independent, any coding system described above can take
+  Since text characters encoding and end-of-line encoding are
+  independent, any coding system described above can take
   any format of end-of-line.  So, Emacs has information of format of
-  end-of-line in each coding-system.  See the section 6 for more
-  detail.
+  end-of-line in each coding-system.  See section 6 for more details.
 
 */
 
@@ -106,7 +110,7 @@ Boston, MA 02111-1307, USA.  */
   template of these functions.  */
 #if 0
 int
-detect_coding_internal (src, src_end)
+detect_coding_emacs_mule (src, src_end)
      unsigned char *src, *src_end;
 {
   ...
@@ -116,11 +120,11 @@ detect_coding_internal (src, src_end)
 /*** GENERAL NOTES on `decode_coding_XXX ()' functions ***
 
   These functions decode SRC_BYTES length text at SOURCE encoded in
-  CODING to Emacs' internal format.  The resulting text goes to a
-  place pointed by DESTINATION, the length of which should not exceed
-  DST_BYTES.  The bytes actually processed is returned as *CONSUMED.
-  The return value is the length of the decoded text.  Below is a
-  template of these functions.  */
+  CODING to Emacs' internal format (emacs-mule).  The resulting text
+  goes to a place pointed to by DESTINATION, the length of which should
+  not exceed DST_BYTES.  The number of bytes actually processed is
+  returned as *CONSUMED.  The return value is the length of the decoded
+  text.  Below is a template of these functions.  */
 #if 0
 decode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
      struct coding_system *coding;
@@ -134,12 +138,12 @@ decode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
 
 /*** GENERAL NOTES on `encode_coding_XXX ()' functions ***
 
-  These functions encode SRC_BYTES length text at SOURCE of Emacs
-  internal format to CODING.  The resulting text goes to a place
-  pointed by DESTINATION, the length of which should not exceed
-  DST_BYTES.  The bytes actually processed is returned as *CONSUMED.
-  The return value is the length of the encoded text.  Below is a
-  template of these functions.  */
+  These functions encode SRC_BYTES length text at SOURCE of Emacs'
+  internal format (emacs-mule) to CODING.  The resulting text goes to
+  a place pointed to by DESTINATION, the length of which should not
+  exceed DST_BYTES.  The number of bytes actually processed is
+  returned as *CONSUMED.  The return value is the length of the
+  encoded text.  Below is a template of these functions.  */
 #if 0
 encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
      struct coding_system *coding;
@@ -200,7 +204,7 @@ encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
       *dst++ = (c);                                            \
   } while (0)
 
-/* Decode one DIMENSION1 character of which charset is CHARSET and
+/* Decode one DIMENSION1 character whose charset is CHARSET and whose
    position-code is C.  */
 
 #define DECODE_CHARACTER_DIMENSION1(charset, c)                                \
@@ -215,7 +219,7 @@ encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
     *dst++ = (c) | 0x80;                                               \
   } while (0)
 
-/* Decode one DIMENSION2 character of which charset is CHARSET and
+/* Decode one DIMENSION2 character whose charset is CHARSET and whose
    position-codes are C1 and C2.  */
 
 #define DECODE_CHARACTER_DIMENSION2(charset, c1, c2)   \
@@ -248,6 +252,8 @@ encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed)
 Lisp_Object Qcoding_system, Qeol_type;
 Lisp_Object Qbuffer_file_coding_system;
 Lisp_Object Qpost_read_conversion, Qpre_write_conversion;
+Lisp_Object Qno_conversion, Qundecided;
+Lisp_Object Qcoding_system_history;
 
 extern Lisp_Object Qinsert_file_contents, Qwrite_region;
 Lisp_Object Qcall_process, Qcall_process_region, Qprocess_argument;
@@ -260,9 +266,16 @@ int eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac;
    decided.  */
 int eol_mnemonic_undecided;
 
+/* Format of end-of-line decided by system.  This is CODING_EOL_LF on
+   Unix, CODING_EOL_CRLF on DOS/Windows, and CODING_EOL_CR on Mac.  */
+int system_eol_type;
+
 #ifdef emacs
 
-Lisp_Object Qcoding_system_vector, Qcoding_system_p, Qcoding_system_error;
+Lisp_Object Qcoding_system_spec, Qcoding_system_p, Qcoding_system_error;
+
+/* Coding system emacs-mule is for converting only end-of-line format.  */
+Lisp_Object Qemacs_mule;
 
 /* Coding-systems are handed between Emacs Lisp programs and C internal
    routines by the following three variables.  */
@@ -273,13 +286,26 @@ Lisp_Object Vcoding_system_for_write;
 /* Coding-system actually used in the latest I/O.  */
 Lisp_Object Vlast_coding_system_used;
 
-/* Coding-system of what terminal accept for displaying.  */
+/* A vector of length 256 which contains information about special
+   Latin codes (espepcially for dealing with Microsoft code).  */
+Lisp_Object Vlatin_extra_code_table;
+
+/* Flag to inhibit code conversion of end-of-line format.  */
+int inhibit_eol_conversion;
+
+/* Coding system to be used to encode text for terminal display.  */
 struct coding_system terminal_coding;
 
-/* Coding-system of what is sent from terminal keyboard.  */
+/* Coding system to be used to encode text for terminal display when
+   terminal coding system is nil.  */
+struct coding_system safe_terminal_coding;
+
+/* Coding system of what is sent from terminal keyboard.  */
 struct coding_system keyboard_coding;
 
-Lisp_Object Vcoding_system_alist;
+Lisp_Object Vfile_coding_system_alist;
+Lisp_Object Vprocess_coding_system_alist;
+Lisp_Object Vnetwork_coding_system_alist;
 
 #endif /* emacs */
 
@@ -293,52 +319,59 @@ Lisp_Object coding_category_table[CODING_CATEGORY_IDX_MAX];
 
 /* Table of names of symbol for each coding-category.  */
 char *coding_category_name[CODING_CATEGORY_IDX_MAX] = {
-  "coding-category-internal",
+  "coding-category-emacs-mule",
   "coding-category-sjis",
   "coding-category-iso-7",
   "coding-category-iso-8-1",
   "coding-category-iso-8-2",
-  "coding-category-iso-else",
+  "coding-category-iso-7-else",
+  "coding-category-iso-8-else",
   "coding-category-big5",
+  "coding-category-raw-text",
   "coding-category-binary"
 };
 
 /* Flag to tell if we look up unification table on character code
    conversion.  */
 Lisp_Object Venable_character_unification;
-/* Standard unification table to look up on reading (decoding).  */
-Lisp_Object Vstandard_character_unification_table_for_read;
-/* Standard unification table to look up on writing (encoding).  */
-Lisp_Object Vstandard_character_unification_table_for_write;
+/* Standard unification table to look up on decoding (reading).  */
+Lisp_Object Vstandard_character_unification_table_for_decode;
+/* Standard unification table to look up on encoding (writing).  */
+Lisp_Object Vstandard_character_unification_table_for_encode;
 
 Lisp_Object Qcharacter_unification_table;
+Lisp_Object Qcharacter_unification_table_for_decode;
+Lisp_Object Qcharacter_unification_table_for_encode;
 
 /* Alist of charsets vs revision number.  */
 Lisp_Object Vcharset_revision_alist;
 
+/* Default coding systems used for process I/O.  */
+Lisp_Object Vdefault_process_coding_system;
+
 \f
-/*** 2. Emacs internal format handlers ***/
+/*** 2. Emacs internal format (emacs-mule) handlers ***/
 
 /* Emacs' internal format for encoding multiple character sets is a
-   kind of multi-byte encoding, i.e. encoding a character by a sequence
-   of one-byte codes of variable length.  ASCII characters and control
-   characters (e.g. `tab', `newline') are represented by one-byte as
-   is.  It takes the range 0x00 through 0x7F.  The other characters
-   are represented by a sequence of `base leading-code', optional
-   `extended leading-code', and one or two `position-code's.  Length
-   of the sequence is decided by the base leading-code.  Leading-code
-   takes the range 0x80 through 0x9F, whereas extended leading-code
-   and position-code take the range 0xA0 through 0xFF.  See the
-   document of `charset.h' for more detail about leading-code and
-   position-code.
-
-   There's one exception in this rule.  Special leading-code
+   kind of multi-byte encoding, i.e. characters are encoded by
+   variable-length sequences of one-byte codes.  ASCII characters
+   and control characters (e.g. `tab', `newline') are represented by
+   one-byte sequences which are their ASCII codes, in the range 0x00
+   through 0x7F.  The other characters are represented by a sequence
+   of `base leading-code', optional `extended leading-code', and one
+   or two `position-code's.  The length of the sequence is determined
+   by the base leading-code.  Leading-code takes the range 0x80
+   through 0x9F, whereas extended leading-code and position-code take
+   the range 0xA0 through 0xFF.  See `charset.h' for more details
+   about leading-code and position-code.
+
+   There's one exception to this rule.  Special leading-code
    `leading-code-composition' denotes that the following several
    characters should be composed into one character.  Leading-codes of
    components (except for ASCII) are added 0x20.  An ASCII character
    component is represented by a 2-byte sequence of `0xA0' and
-   `ASCII-code + 0x80'.  See also the document in `charset.h' for the
-   detail of composite character.  Hence, we can summarize the code
+   `ASCII-code + 0x80'.  See also the comments in `charset.h' for the
+   details of composite character.  Hence, we can summarize the code
    range as follows:
 
    --- CODE RANGE of Emacs' internal format ---
@@ -364,10 +397,10 @@ enum emacs_code_class_type emacs_code_class[256];
 
 /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions".
    Check if a text is encoded in Emacs' internal format.  If it is,
-   return CODING_CATEGORY_MASK_INTERNAL, else return 0.  */
+   return CODING_CATEGORY_MASK_EMASC_MULE, else return 0.  */
 
 int
-detect_coding_internal (src, src_end)
+detect_coding_emacs_mule (src, src_end)
      unsigned char *src, *src_end;
 {
   unsigned char c;
@@ -423,28 +456,28 @@ detect_coding_internal (src, src_end)
          break;
        }
     }
-  return CODING_CATEGORY_MASK_INTERNAL;
+  return CODING_CATEGORY_MASK_EMACS_MULE;
 }
 
 \f
 /*** 3. ISO2022 handlers ***/
 
 /* The following note describes the coding system ISO2022 briefly.
-   Since the intension of this note is to help understanding of the
-   programs in this file, some parts are NOT ACCURATE or OVERLY
+   Since the intention of this note is to help in understanding of
+   the programs in this file, some parts are NOT ACCURATE or OVERLY
    SIMPLIFIED.  For the thorough understanding, please refer to the
    original document of ISO2022.
 
    ISO2022 provides many mechanisms to encode several character sets
-   in 7-bit and 8-bit environment.  If one choose 7-bite environment,
+   in 7-bit and 8-bit environment.  If one chooses 7-bite environment,
    all text is encoded by codes of less than 128.  This may make the
-   encoded text a little bit longer, but the text get more stability
-   to pass through several gateways (some of them split MSB off).
+   encoded text a little bit longer, but the text gets more stability
+   to pass through several gateways (some of them strip off the MSB).
 
-   There are two kind of character set: control character set and
+   There are two kinds of character set: control character set and
    graphic character set.  The former contains control characters such
    as `newline' and `escape' to provide control functions (control
-   functions are provided also by escape sequence).  The latter
+   functions are provided also by escape sequences).  The latter
    contains graphic characters such as ' A' and '-'.  Emacs recognizes
    two control character sets and many graphic character sets.
 
@@ -505,7 +538,7 @@ detect_coding_internal (src, src_end)
    function            control char    escape sequence description
    ----------------------------------------------------------------------
    SI  (shift-in)              0x0F    none            invoke G0 to GL
-   SI  (shift-out)             0x0E    none            invoke G1 to GL
+   SO  (shift-out)             0x0E    none            invoke G1 to GL
    LS2 (locking-shift-2)       none    ESC 'n'         invoke G2 into GL
    LS3 (locking-shift-3)       none    ESC 'o'         invoke G3 into GL
    SS2 (single-shift-2)                0x8E    ESC 'N'         invoke G2 into GL
@@ -548,7 +581,7 @@ detect_coding_internal (src, src_end)
    '(' can be omitted.  We call this as "short-form" here after.
 
    Now you may notice that there are a lot of ways for encoding the
-   same multilingual text in ISO2022.  Actually, there exist many
+   same multilingual text in ISO2022.  Actually, there exists many
    coding systems such as Compound Text (used in X's inter client
    communication, ISO-2022-JP (used in Japanese Internet), ISO-2022-KR
    (used in Korean Internet), EUC (Extended UNIX Code, used in Asian
@@ -580,7 +613,8 @@ enum iso_code_class_type iso_code_class[256];
        CODING_CATEGORY_MASK_ISO_7
        CODING_CATEGORY_MASK_ISO_8_1
        CODING_CATEGORY_MASK_ISO_8_2
-       CODING_CATEGORY_MASK_ISO_ELSE
+       CODING_CATEGORY_MASK_ISO_7_ELSE
+       CODING_CATEGORY_MASK_ISO_8_ELSE
    are set.  If a code which should never appear in ISO2022 is found,
    returns 0.  */
 
@@ -588,11 +622,25 @@ int
 detect_coding_iso2022 (src, src_end)
      unsigned char *src, *src_end;
 {
-  int mask = CODING_CATEGORY_MASK_ANY;
+  int mask = (CODING_CATEGORY_MASK_ISO_7
+             | CODING_CATEGORY_MASK_ISO_8_1
+             | CODING_CATEGORY_MASK_ISO_8_2
+             | CODING_CATEGORY_MASK_ISO_7_ELSE
+             | CODING_CATEGORY_MASK_ISO_8_ELSE
+             );
   int g1 = 0;                  /* 1 iff designating to G1.  */
   int c, i;
+  struct coding_system coding_iso_8_1, coding_iso_8_2;
 
-  while (src < src_end)
+  /* Coding systems of these categories may accept latin extra codes.  */
+  setup_coding_system
+    (XSYMBOL (coding_category_table[CODING_CATEGORY_IDX_ISO_8_1])->value,
+     &coding_iso_8_1);
+  setup_coding_system
+    (XSYMBOL (coding_category_table[CODING_CATEGORY_IDX_ISO_8_2])->value,
+     &coding_iso_8_2);
+
+  while (mask && src < src_end)
     {
       c = *src++;
       switch (c)
@@ -601,52 +649,101 @@ detect_coding_iso2022 (src, src_end)
          if (src >= src_end)
            break;
          c = *src++;
-         if (src < src_end
-             && ((c >= '(' && c <= '/')
-                 || c == '$' && ((*src >= '(' && *src <= '/')
-                                 || (*src >= '@' && *src <= 'B'))))
+         if ((c >= '(' && c <= '/'))
+           {
+             /* Designation sequence for a charset of dimension 1.  */
+             if (src >= src_end)
+               break;
+             c = *src++;
+             if (c < ' ' || c >= 0x80)
+               /* Invalid designation sequence.  */
+               return 0;
+           }
+         else if (c == '$')
            {
-             /* Valid designation sequence.  */
-             mask &= (CODING_CATEGORY_MASK_ISO_7
-                      | CODING_CATEGORY_MASK_ISO_8_1
-                      | CODING_CATEGORY_MASK_ISO_8_2
-                      | CODING_CATEGORY_MASK_ISO_ELSE);
-             if (c == ')' || (c == '$' && *src == ')'))
+             /* Designation sequence for a charset of dimension 2.  */
+             if (src >= src_end)
+               break;
+             c = *src++;
+             if (c >= '@' && c <= 'B')
+               /* Designation for JISX0208.1978, GB2312, or JISX0208.  */
+               ;
+             else if (c >= '(' && c <= '/')
                {
-                 g1 = 1;
-                 mask &= ~CODING_CATEGORY_MASK_ISO_7;
+                 if (src >= src_end)
+                   break;
+                 c = *src++;
+                 if (c < ' ' || c >= 0x80)
+                   /* Invalid designation sequence.  */
+                   return 0;
                }
-             src++;
-             break;
+             else
+               /* Invalid designation sequence.  */
+               return 0;
            }
          else if (c == 'N' || c == 'O' || c == 'n' || c == 'o')
-           return CODING_CATEGORY_MASK_ISO_ELSE;
+           /* Locking shift.  */
+           mask &= (CODING_CATEGORY_MASK_ISO_7_ELSE
+                    | CODING_CATEGORY_MASK_ISO_8_ELSE);
+         else if (c == '0' || c == '1' || c == '2')
+           /* Start/end composition.  */
+           ;
+         else
+           /* Invalid escape sequence.  */
+           return 0;
          break;
 
        case ISO_CODE_SO:
-         if (g1)
-           return CODING_CATEGORY_MASK_ISO_ELSE;
+         mask &= (CODING_CATEGORY_MASK_ISO_7_ELSE
+                  | CODING_CATEGORY_MASK_ISO_8_ELSE);
          break;
          
        case ISO_CODE_CSI:
        case ISO_CODE_SS2:
        case ISO_CODE_SS3:
-         mask &= ~CODING_CATEGORY_MASK_ISO_7;
+         {
+           int newmask = CODING_CATEGORY_MASK_ISO_8_ELSE;
+
+           if (VECTORP (Vlatin_extra_code_table)
+               && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c]))
+             {
+               if (coding_iso_8_1.flags & CODING_FLAG_ISO_LATIN_EXTRA)
+                 newmask |= CODING_CATEGORY_MASK_ISO_8_1;
+               if (coding_iso_8_2.flags & CODING_FLAG_ISO_LATIN_EXTRA)
+                 newmask |= CODING_CATEGORY_MASK_ISO_8_2;
+             }
+           mask &= newmask;
+         }
          break;
 
        default:
          if (c < 0x80)
            break;
          else if (c < 0xA0)
-           return 0;
+           {
+             if (VECTORP (Vlatin_extra_code_table)
+                 && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c]))
+               {
+                 int newmask = 0;
+
+                 if (coding_iso_8_1.flags & CODING_FLAG_ISO_LATIN_EXTRA)
+                   newmask |= CODING_CATEGORY_MASK_ISO_8_1;
+                 if (coding_iso_8_2.flags & CODING_FLAG_ISO_LATIN_EXTRA)
+                   newmask |= CODING_CATEGORY_MASK_ISO_8_2;
+                 mask &= newmask;
+               }
+             else
+               return 0;
+           }
          else
            {
-             int count = 1;
+             unsigned char *src_begin = src;
 
-             mask &= ~CODING_CATEGORY_MASK_ISO_7;
+             mask &= ~(CODING_CATEGORY_MASK_ISO_7
+                       | CODING_CATEGORY_MASK_ISO_7_ELSE);
              while (src < src_end && *src >= 0xA0)
-               count++, src++;
-             if (count & 1 && src < src_end)
+               src++;
+             if ((src - src_begin - 1) & 1 && src < src_end)
                mask &= ~CODING_CATEGORY_MASK_ISO_8_2;
            }
          break;
@@ -696,7 +793,9 @@ detect_coding_iso2022 (src, src_end)
 /* Set designation state into CODING.  */
 #define DECODE_DESIGNATION(reg, dimension, chars, final_char)          \
   do {                                                                 \
-    int charset = ISO_CHARSET_TABLE (dimension, chars, final_char);    \
+    int charset = ISO_CHARSET_TABLE (make_number (dimension),          \
+                                    make_number (chars),               \
+                                    make_number (final_char));         \
     if (charset >= 0)                                                  \
       {                                                                        \
         if (coding->direction == 1                                     \
@@ -728,10 +827,11 @@ decode_coding_iso2022 (coding, source, destination,
   /* Charsets invoked to graphic plane 0 and 1 respectively.  */
   int charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0);
   int charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1);
-  Lisp_Object unification_table = coding->character_unification_table;
+  Lisp_Object unification_table
+      = coding->character_unification_table_for_decode;
 
   if (!NILP (Venable_character_unification) && NILP (unification_table))
-    unification_table = Vstandard_character_unification_table_for_read;
+    unification_table = Vstandard_character_unification_table_for_decode;
 
   while (src < src_end && dst < adjusted_dst_end)
     {
@@ -999,10 +1099,10 @@ decode_coding_iso2022 (coding, source, destination,
   return dst - destination;
 }
 
-/* ISO2022 encoding staffs.  */
+/* ISO2022 encoding stuff.  */
 
 /*
-   It is not enough to say just "ISO2022" on encoding, but we have to
+   It is not enough to say just "ISO2022" on encoding, we have to
    specify more details.  In Emacs, each coding-system of ISO2022
    variant has the following specifications:
        1. Initial designation to G0 thru G3.
@@ -1017,7 +1117,7 @@ decode_coding_iso2022 (coding, source, destination,
        9. Use JISX0208-1983 in place of JISX0208-1978?
    These specifications are encoded in `coding->flags' as flag bits
    defined by macros CODING_FLAG_ISO_XXX.  See `coding.h' for more
-   detail.
+   details.
 */
 
 /* Produce codes (escape sequence) for designating CHARSET to graphic
@@ -1113,8 +1213,8 @@ decode_coding_iso2022 (coding, source, destination,
     CODING_SPEC_ISO_INVOCATION (coding, 0) = 3;        \
   } while (0)
 
-/* Produce codes for a DIMENSION1 character of which character set is
-   CHARSET and position-code is C1.  Designation and invocation
+/* Produce codes for a DIMENSION1 character whose character set is
+   CHARSET and whose position-code is C1.  Designation and invocation
    sequences are also produced in advance if necessary.  */
 
 
@@ -1139,6 +1239,16 @@ decode_coding_iso2022 (coding, source, destination,
        *dst++ = c1 | 0x80;                                             \
        break;                                                          \
       }                                                                        \
+    else if (coding->flags & CODING_FLAG_ISO_SAFE                      \
+            && !CODING_SPEC_ISO_EXPECTED_CHARSETS (coding)[charset])   \
+      {                                                                        \
+       /* We should not encode this character, instead produce one or  \
+          two `?'s.  */                                                \
+       *dst++ = CODING_INHIBIT_CHARACTER_SUBSTITUTION;                 \
+       if (CHARSET_WIDTH (charset) == 2)                               \
+         *dst++ = CODING_INHIBIT_CHARACTER_SUBSTITUTION;               \
+       break;                                                          \
+      }                                                                        \
     else                                                               \
       /* Since CHARSET is not yet invoked to any graphic planes, we    \
         must invoke it, or, at first, designate it to some graphic     \
@@ -1147,8 +1257,8 @@ decode_coding_iso2022 (coding, source, destination,
       dst = encode_invocation_designation (charset, coding, dst);      \
   } while (1)
 
-/* Produce codes for a DIMENSION2 character of which character set is
-   CHARSET and position-codes are C1 and C2.  Designation and
+/* Produce codes for a DIMENSION2 character whose character set is
+   CHARSET and whose position-codes are C1 and C2.  Designation and
    invocation codes are also produced in advance if necessary.  */
 
 #define ENCODE_ISO_CHARACTER_DIMENSION2(charset, c1, c2)               \
@@ -1172,6 +1282,16 @@ decode_coding_iso2022 (coding, source, destination,
        *dst++ = c1 | 0x80, *dst++= c2 | 0x80;                          \
        break;                                                          \
       }                                                                        \
+    else if (coding->flags & CODING_FLAG_ISO_SAFE                      \
+            && !CODING_SPEC_ISO_EXPECTED_CHARSETS (coding)[charset])   \
+      {                                                                        \
+       /* We should not encode this character, instead produce one or  \
+          two `?'s.  */                                                \
+       *dst++ = CODING_INHIBIT_CHARACTER_SUBSTITUTION;                 \
+       if (CHARSET_WIDTH (charset) == 2)                               \
+         *dst++ = CODING_INHIBIT_CHARACTER_SUBSTITUTION;               \
+       break;                                                          \
+      }                                                                        \
     else                                                               \
       /* Since CHARSET is not yet invoked to any graphic planes, we    \
         must invoke it, or, at first, designate it to some graphic     \
@@ -1185,7 +1305,7 @@ decode_coding_iso2022 (coding, source, destination,
     int c_alt, charset_alt;                                              \
     if (!NILP (unification_table)                                        \
        && ((c_alt = unify_char (unification_table, -1, charset, c1, c2)) \
-           < 0))                                                         \
+           >= 0))                                                        \
       SPLIT_CHAR (c_alt, charset_alt, c1, c2);                           \
     else                                                                 \
       charset_alt = charset;                                             \
@@ -1217,9 +1337,9 @@ encode_invocation_designation (charset, coding, dst)
       /* CHARSET is not yet designated to any graphic registers.  */
       /* At first check the requested designation.  */
       reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset);
-      if (reg < 0)
-       /* Since CHARSET requests no special designation, designate to
-          graphic register 0.  */
+      if (reg == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)
+       /* Since CHARSET requests no special designation, designate it
+          to graphic register 0.  */
        reg = 0;
 
       ENCODE_DESIGNATION (charset, reg, coding);
@@ -1328,7 +1448,7 @@ encode_designation_at_bol (coding, table, src, src_end, dstp)
        }
 
       reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset);
-      if (r[reg] < 0)
+      if (r[reg] == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)
        {
          found++;
          r[reg] = charset;
@@ -1365,10 +1485,11 @@ encode_coding_iso2022 (coding, source, destination,
      from DST_END to assure overflow checking is necessary only at the
      head of loop.  */
   unsigned char *adjusted_dst_end = dst_end - 19;
-  Lisp_Object unification_table = coding->character_unification_table;
+  Lisp_Object unification_table
+      = coding->character_unification_table_for_encode;
 
   if (!NILP (Venable_character_unification) && NILP (unification_table))
-    unification_table = Vstandard_character_unification_table_for_write;
+    unification_table = Vstandard_character_unification_table_for_encode;
 
   while (src < src_end && dst < adjusted_dst_end)
     {
@@ -1457,7 +1578,7 @@ encode_coding_iso2022 (coding, source, destination,
                   coding->spec.iso2022.current_designation,
                   sizeof coding->spec.iso2022.initial_designation);
          if (coding->eol_type == CODING_EOL_LF
-             || coding->eol_type == CODING_EOL_AUTOMATIC)
+             || coding->eol_type == CODING_EOL_UNDECIDED)
            *dst++ = ISO_CODE_LF;
          else if (coding->eol_type == CODING_EOL_CRLF)
            *dst++ = ISO_CODE_CR, *dst++ = ISO_CODE_LF;
@@ -1468,12 +1589,26 @@ encode_coding_iso2022 (coding, source, destination,
 
        case EMACS_leading_code_2:
          ONE_MORE_BYTE (c2);
-         ENCODE_ISO_CHARACTER (c1, c2, /* dummy */ c3);
+         if (c2 < 0xA0)
+           {
+             /* invalid sequence */
+             *dst++ = c1;
+             *dst++ = c2;
+           }
+         else
+           ENCODE_ISO_CHARACTER (c1, c2, /* dummy */ c3);
          break;
 
        case EMACS_leading_code_3:
          TWO_MORE_BYTES (c2, c3);
-         if (c1 < LEADING_CODE_PRIVATE_11)
+         if (c2 < 0xA0 || c3 < 0xA0)
+           {
+             /* invalid sequence */
+             *dst++ = c1;
+             *dst++ = c2;
+             *dst++ = c3;
+           }
+         else if (c1 < LEADING_CODE_PRIVATE_11)
            ENCODE_ISO_CHARACTER (c1, c2, c3);
          else
            ENCODE_ISO_CHARACTER (c2, c3, /* dummy */ c4);
@@ -1481,12 +1616,27 @@ encode_coding_iso2022 (coding, source, destination,
 
        case EMACS_leading_code_4:
          THREE_MORE_BYTES (c2, c3, c4);
-         ENCODE_ISO_CHARACTER (c2, c3, c4);
+         if (c2 < 0xA0 || c3 < 0xA0 || c4 < 0xA0)
+           {
+             /* invalid sequence */
+             *dst++ = c1;
+             *dst++ = c2;
+             *dst++ = c3;
+             *dst++ = c4;
+           }
+         else
+           ENCODE_ISO_CHARACTER (c2, c3, c4);
          break;
 
        case EMACS_leading_code_composition:
-         ONE_MORE_BYTE (c1);
-         if (c1 == 0xFF)
+         ONE_MORE_BYTE (c2);
+         if (c2 < 0xA0)
+           {
+             /* invalid sequence */
+             *dst++ = c1;
+             *dst++ = c2;
+           }
+         else if (c2 == 0xFF)
            {
              coding->composing = COMPOSING_WITH_RULE_HEAD;
              ENCODE_COMPOSITION_WITH_RULE_START;
@@ -1507,8 +1657,11 @@ encode_coding_iso2022 (coding, source, destination,
        }
       continue;
     label_end_of_loop:
-      coding->carryover_size = src - src_base;
+      /* We reach here because the source date ends not at character
+        boundary.  */
+      coding->carryover_size = src_end - src_base;
       bcopy (src_base, coding->carryover, coding->carryover_size);
+      src = src_end;
       break;
     }
 
@@ -1532,7 +1685,7 @@ encode_coding_iso2022 (coding, source, destination,
 \f
 /*** 4. SJIS and BIG5 handlers ***/
 
-/* Although SJIS and BIG5 are not ISO's coding system, They are used
+/* Although SJIS and BIG5 are not ISO's coding system, they are used
    quite widely.  So, for the moment, Emacs supports them in the bare
    C code.  But, in the future, they may be supported only by CCL.  */
 
@@ -1604,6 +1757,63 @@ encode_coding_iso2022 (coding, source, destination,
     b2 += b2 < 0x3F ? 0x40 : 0x62;                                     \
   } while (0)
 
+#define DECODE_SJIS_BIG5_CHARACTER(charset, c1, c2)                    \
+  do {                                                                 \
+    int c_alt, charset_alt = (charset);                                        \
+    if (!NILP (unification_table)                                      \
+       && ((c_alt = unify_char (unification_table,                     \
+                                -1, (charset), c1, c2)) >= 0))         \
+         SPLIT_CHAR (c_alt, charset_alt, c1, c2);                      \
+    if (charset_alt == CHARSET_ASCII || charset_alt < 0)               \
+      DECODE_CHARACTER_ASCII (c1);                                     \
+    else if (CHARSET_DIMENSION (charset_alt) == 1)                     \
+      DECODE_CHARACTER_DIMENSION1 (charset_alt, c1);                   \
+    else                                                               \
+      DECODE_CHARACTER_DIMENSION2 (charset_alt, c1, c2);               \
+  } while (0)
+
+#define ENCODE_SJIS_BIG5_CHARACTER(charset, c1, c2)                      \
+  do {                                                                   \
+    int c_alt, charset_alt;                                              \
+    if (!NILP (unification_table)                                        \
+        && ((c_alt = unify_char (unification_table, -1, charset, c1, c2)) \
+           >= 0))                                                        \
+      SPLIT_CHAR (c_alt, charset_alt, c1, c2);                           \
+    else                                                                 \
+      charset_alt = charset;                                             \
+    if (charset_alt == charset_ascii)                                    \
+      *dst++ = c1;                                                       \
+    else if (CHARSET_DIMENSION (charset_alt) == 1)                       \
+      {                                                                          \
+       if (sjis_p && charset_alt == charset_katakana_jisx0201)           \
+         *dst++ = c1;                                                    \
+       else                                                              \
+         *dst++ = charset_alt, *dst++ = c1;                              \
+      }                                                                          \
+    else                                                                 \
+      {                                                                          \
+       c1 &= 0x7F, c2 &= 0x7F;                                           \
+       if (sjis_p && charset_alt == charset_jisx0208)                    \
+         {                                                               \
+           unsigned char s1, s2;                                         \
+                                                                         \
+           ENCODE_SJIS (c1, c2, s1, s2);                                 \
+           *dst++ = s1, *dst++ = s2;                                     \
+         }                                                               \
+       else if (!sjis_p                                                  \
+                && (charset_alt == charset_big5_1                        \
+                    || charset_alt == charset_big5_2))                   \
+         {                                                               \
+           unsigned char b1, b2;                                         \
+                                                                         \
+           ENCODE_BIG5 (charset_alt, c1, c2, b1, b2);                    \
+           *dst++ = b1, *dst++ = b2;                                     \
+         }                                                               \
+       else                                                              \
+         *dst++ = charset_alt, *dst++ = c1, *dst++ = c2;                 \
+      }                                                                          \
+  } while (0);
+
 /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions".
    Check if a text is encoded in SJIS.  If it is, return
    CODING_CATEGORY_MASK_SJIS, else return 0.  */
@@ -1675,6 +1885,11 @@ decode_coding_sjis_big5 (coding, source, destination,
      from DST_END to assure overflow checking is necessary only at the
      head of loop.  */
   unsigned char *adjusted_dst_end = dst_end - 3;
+  Lisp_Object unification_table
+      = coding->character_unification_table_for_decode;
+
+  if (!NILP (Venable_character_unification) && NILP (unification_table))
+    unification_table = Vstandard_character_unification_table_for_decode;
 
   while (src < src_end && dst < adjusted_dst_end)
     {
@@ -1699,8 +1914,10 @@ decode_coding_sjis_big5 (coding, source, destination,
          else
            *dst++ = c1;
        }
-      else if (c1 < 0x80)
+      else if (c1 < 0x20)
        *dst++ = c1;
+      else if (c1 < 0x80)
+       DECODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2);
       else if (c1 < 0xA0 || c1 >= 0xE0)
        {
          /* SJIS -> JISX0208, BIG5 -> Big5 (only if 0xE0 <= c1 < 0xFF) */
@@ -1708,7 +1925,7 @@ decode_coding_sjis_big5 (coding, source, destination,
            {
              ONE_MORE_BYTE (c2);
              DECODE_SJIS (c1, c2, c3, c4);
-             DECODE_CHARACTER_DIMENSION2 (charset_jisx0208, c3, c4);
+             DECODE_SJIS_BIG5_CHARACTER (charset_jisx0208, c3, c4);
            }
          else if (c1 >= 0xE0 && c1 < 0xFF)
            {
@@ -1716,7 +1933,7 @@ decode_coding_sjis_big5 (coding, source, destination,
 
              ONE_MORE_BYTE (c2);
              DECODE_BIG5 (c1, c2, charset, c3, c4);
-             DECODE_CHARACTER_DIMENSION2 (charset, c3, c4);
+             DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
            }
          else                  /* Invalid code */
            *dst++ = c1;
@@ -1725,14 +1942,14 @@ decode_coding_sjis_big5 (coding, source, destination,
        {
          /* SJIS -> JISX0201-Kana, BIG5 -> Big5 */
          if (sjis_p)
-           DECODE_CHARACTER_DIMENSION1 (charset_katakana_jisx0201, c1);
+           DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1, /* dummy */ c2);
          else
            {
              int charset;
 
              ONE_MORE_BYTE (c2);
              DECODE_BIG5 (c1, c2, charset, c3, c4);
-             DECODE_CHARACTER_DIMENSION2 (charset, c3, c4);
+             DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
            }
        }
       continue;
@@ -1773,6 +1990,11 @@ encode_coding_sjis_big5 (coding, source, destination,
      from DST_END to assure overflow checking is necessary only at the
      head of loop.  */
   unsigned char *adjusted_dst_end = dst_end - 1;
+  Lisp_Object unification_table
+      = coding->character_unification_table_for_encode;
+
+  if (!NILP (Venable_character_unification) && NILP (unification_table))
+    unification_table = Vstandard_character_unification_table_for_encode;
 
   while (src < src_end && dst < adjusted_dst_end)
     {
@@ -1800,6 +2022,9 @@ encode_coding_sjis_big5 (coding, source, destination,
       switch (emacs_code_class[c1])
        {
        case EMACS_ascii_code:
+         ENCODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2);
+         break;
+
        case EMACS_control_code:
          *dst++ = c1;
          break;
@@ -1814,7 +2039,7 @@ encode_coding_sjis_big5 (coding, source, destination,
 
        case EMACS_linefeed_code:
          if (coding->eol_type == CODING_EOL_LF
-             || coding->eol_type == CODING_EOL_AUTOMATIC)
+             || coding->eol_type == CODING_EOL_UNDECIDED)
            *dst++ = '\n';
          else if (coding->eol_type == CODING_EOL_CRLF)
            *dst++ = '\r', *dst++ = '\n';
@@ -1824,36 +2049,17 @@ encode_coding_sjis_big5 (coding, source, destination,
 
        case EMACS_leading_code_2:
          ONE_MORE_BYTE (c2);
-         if (sjis_p && c1 == charset_katakana_jisx0201)
-           *dst++ = c2;
-         else
-           *dst++ = c1, *dst++ = c2;
+         ENCODE_SJIS_BIG5_CHARACTER (c1, c2, /* dummy */ c3);
          break;
 
        case EMACS_leading_code_3:
          TWO_MORE_BYTES (c2, c3);
-         c2 &= 0x7F, c3 &= 0x7F;
-         if (sjis_p && c1 == charset_jisx0208)
-           {
-             unsigned char s1, s2;
-
-             ENCODE_SJIS (c2, c3, s1, s2);
-             *dst++ = s1, *dst++ = s2;
-           }
-         else if (!sjis_p && (c1 == charset_big5_1 || c1 == charset_big5_2))
-           {
-             unsigned char b1, b2;
-
-             ENCODE_BIG5 (c1, c2, c3, b1, b2);
-             *dst++ = b1, *dst++ = b2;
-           }
-         else
-           *dst++ = c1, *dst++ = c2, *dst++ = c3;
+         ENCODE_SJIS_BIG5_CHARACTER (c1, c2, c3);
          break;
 
        case EMACS_leading_code_4:
          THREE_MORE_BYTES (c2, c3, c4);
-         *dst++ = c1, *dst++ = c2, *dst++ = c3, *dst++ = c4;
+         ENCODE_SJIS_BIG5_CHARACTER (c2, c3, c4);
          break;
 
        case EMACS_leading_code_composition:
@@ -1866,9 +2072,9 @@ encode_coding_sjis_big5 (coding, source, destination,
       continue;
 
     label_end_of_loop:
-      coding->carryover_size = src - src_base;
+      coding->carryover_size = src_end - src_base;
       bcopy (src_base, coding->carryover, coding->carryover_size);
-      src = src_base;
+      src = src_end;
       break;
     }
 
@@ -1970,7 +2176,7 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes, consumed)
   switch (coding->eol_type)
     {
     case CODING_EOL_LF:
-    case CODING_EOL_AUTOMATIC:
+    case CODING_EOL_UNDECIDED:
       produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes;
       bcopy (source, destination, produced);
       if (coding->selective)
@@ -2036,13 +2242,14 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes, consumed)
    `element[0]' contains information to be set in `coding->type'.  The
    value and its meaning is as follows:
 
-   0 -- coding_system_internal
-   1 -- coding_system_sjis
-   2 -- coding_system_iso2022
-   3 -- coding_system_big5
-   4 -- coding_system_ccl
-   nil -- coding_system_no_conversion
-   t -- coding_system_automatic
+   0 -- coding_type_emacs_mule
+   1 -- coding_type_sjis
+   2 -- coding_type_iso2022
+   3 -- coding_type_big5
+   4 -- coding_type_ccl encoder/decoder written in CCL
+   nil -- coding_type_no_conversion
+   t -- coding_type_undecided (automatic conversion on decoding,
+                              no-conversion on encoding)
 
    `element[4]' contains information to be set in `coding->flags' and
    `coding->spec'.  The meaning varies by `coding->type'.
@@ -2093,7 +2300,7 @@ setup_coding_system (coding_system, coding)
 {
   Lisp_Object type, eol_type;
 
-  /* At first, set several fields default values.  */
+  /* At first, set several fields to default values.  */
   coding->require_flushing = 0;
   coding->last_block = 0;
   coding->selective = 0;
@@ -2101,15 +2308,16 @@ setup_coding_system (coding_system, coding)
   coding->direction = 0;
   coding->carryover_size = 0;
   coding->post_read_conversion = coding->pre_write_conversion = Qnil;
-  /* We have not yet implemented a way to specify unification table in
-     a coding system.  */
-  coding->character_unification_table = Qnil;
+  coding->character_unification_table_for_decode = Qnil;
+  coding->character_unification_table_for_encode = Qnil;
 
   Vlast_coding_system_used = coding->symbol = coding_system;
   eol_type = Qnil;
   /* Get value of property `coding-system' until we get a vector.
      While doing that, also get values of properties
-     `post-read-conversion', `pre-write-conversion', and `eol-type'.  */
+     `post-read-conversion', `pre-write-conversion',
+     `character-unification-table-for-decode',
+     `character-unification-table-for-encode' and `eol-type'.  */
   while (!NILP (coding_system) && SYMBOLP (coding_system))
     {
       if (NILP (coding->post_read_conversion))
@@ -2118,16 +2326,44 @@ setup_coding_system (coding_system, coding)
       if (NILP (coding->pre_write_conversion)) 
        coding->pre_write_conversion = Fget (coding_system,
                                             Qpre_write_conversion);
-      if (NILP (eol_type))
+      if (!inhibit_eol_conversion && NILP (eol_type))
        eol_type = Fget (coding_system, Qeol_type);
+
+      if (NILP (coding->character_unification_table_for_decode))
+       coding->character_unification_table_for_decode
+         = Fget (coding_system, Qcharacter_unification_table_for_decode);
+
+      if (NILP (coding->character_unification_table_for_encode))
+       coding->character_unification_table_for_encode
+         = Fget (coding_system, Qcharacter_unification_table_for_encode);
+
       coding_system = Fget (coding_system, Qcoding_system);
     }
+
+  while (!NILP (coding->character_unification_table_for_decode)
+        && SYMBOLP (coding->character_unification_table_for_decode))
+       coding->character_unification_table_for_decode
+         = Fget (coding->character_unification_table_for_decode,
+                 Qcharacter_unification_table_for_decode);
+  if (!NILP (coding->character_unification_table_for_decode)
+      && !CHAR_TABLE_P (coding->character_unification_table_for_decode))
+      coding->character_unification_table_for_decode = Qnil;
+
+  while (!NILP (coding->character_unification_table_for_encode)
+        && SYMBOLP (coding->character_unification_table_for_encode))
+       coding->character_unification_table_for_encode
+         = Fget (coding->character_unification_table_for_encode,
+                 Qcharacter_unification_table_for_encode);
+  if (!NILP (coding->character_unification_table_for_encode)
+      && !CHAR_TABLE_P (coding->character_unification_table_for_encode))
+      coding->character_unification_table_for_encode = Qnil;
+
   if (!VECTORP (coding_system)
       || XVECTOR (coding_system)->size != 5)
     goto label_invalid_coding_system;
 
   if (VECTORP (eol_type))
-    coding->eol_type = CODING_EOL_AUTOMATIC;
+    coding->eol_type = CODING_EOL_UNDECIDED;
   else if (XFASTINT (eol_type) == 1)
     coding->eol_type = CODING_EOL_CRLF;
   else if (XFASTINT (eol_type) == 2)
@@ -2139,7 +2375,7 @@ setup_coding_system (coding_system, coding)
   switch (XFASTINT (type))
     {
     case 0:
-      coding->type = coding_type_internal;
+      coding->type = coding_type_emacs_mule;
       break;
 
     case 1:
@@ -2149,10 +2385,12 @@ setup_coding_system (coding_system, coding)
     case 2:
       coding->type = coding_type_iso2022;
       {
-       Lisp_Object val = XVECTOR (coding_system)->contents[4];
+       Lisp_Object val;
        Lisp_Object *flags;
        int i, charset, default_reg_bits = 0;
 
+       val = XVECTOR (coding_system)->contents[4];
+
        if (!VECTORP (val) || XVECTOR (val)->size != 32)
          goto label_invalid_coding_system;
 
@@ -2168,7 +2406,10 @@ setup_coding_system (coding_system, coding)
             | (NILP (flags[11]) ? 0 : CODING_FLAG_ISO_USE_OLDJIS)
             | (NILP (flags[12]) ? 0 : CODING_FLAG_ISO_NO_DIRECTION)
             | (NILP (flags[13]) ? 0 : CODING_FLAG_ISO_INIT_AT_BOL)
-            | (NILP (flags[14]) ? 0 : CODING_FLAG_ISO_DESIGNATE_AT_BOL));
+            | (NILP (flags[14]) ? 0 : CODING_FLAG_ISO_DESIGNATE_AT_BOL)
+            | (NILP (flags[15]) ? 0 : CODING_FLAG_ISO_SAFE)
+            | (NILP (flags[16]) ? 0 : CODING_FLAG_ISO_LATIN_EXTRA)
+            );
 
        /* Invoke graphic register 0 to plane 0.  */
        CODING_SPEC_ISO_INVOCATION (coding, 0) = 0;
@@ -2176,9 +2417,9 @@ setup_coding_system (coding_system, coding)
        CODING_SPEC_ISO_INVOCATION (coding, 1)
          = (coding->flags & CODING_FLAG_ISO_SEVEN_BITS ? -1 : 1);
        /* Not single shifting at first.  */
-       CODING_SPEC_ISO_SINGLE_SHIFTING(coding) = 0;
+       CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 0;
        /* Beginning of buffer should also be regarded as bol. */
-       CODING_SPEC_ISO_BOL(coding) = 1;
+       CODING_SPEC_ISO_BOL (coding) = 1;
 
        /* Checks FLAGS[REG] (REG = 0, 1, 2 3) and decide designations.
           FLAGS[REG] can be one of below:
@@ -2191,7 +2432,9 @@ setup_coding_system (coding_system, coding)
                  if an element is t, REG can be used by any charset,
                nil: REG is never used.  */
        for (charset = 0; charset <= MAX_CHARSET; charset++)
-         CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) = -1;
+         CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
+           = CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION;
+       bzero (CODING_SPEC_ISO_EXPECTED_CHARSETS (coding), MAX_CHARSET + 1);
        for (i = 0; i < 4; i++)
          {
            if (INTEGERP (flags[i])
@@ -2200,6 +2443,7 @@ setup_coding_system (coding_system, coding)
              {
                CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
                CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) = i;
+               CODING_SPEC_ISO_EXPECTED_CHARSETS (coding)[charset] = 1;
              }
            else if (EQ (flags[i], Qt))
              {
@@ -2217,6 +2461,7 @@ setup_coding_system (coding_system, coding)
                  {
                    CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
                    CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) =i;
+                   CODING_SPEC_ISO_EXPECTED_CHARSETS (coding)[charset] = 1;
                  }
                else
                  CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1;
@@ -2227,8 +2472,12 @@ setup_coding_system (coding_system, coding)
                        && (charset = XINT (XCONS (tail)->car),
                            CHARSET_VALID_P (charset))
                        || (charset = get_charset_id (XCONS (tail)->car)) >= 0)
-                     CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
-                       = i;
+                     {
+                       CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
+                         = i;
+                       CODING_SPEC_ISO_EXPECTED_CHARSETS (coding)[charset]
+                         = 1;
+                     }
                    else if (EQ (XCONS (tail)->car, Qt))
                      default_reg_bits |= 1 << i;
                    tail = XCONS (tail)->cdr;
@@ -2253,7 +2502,8 @@ setup_coding_system (coding_system, coding)
 
        for (charset = 0; charset <= MAX_CHARSET; charset++)
          if (CHARSET_VALID_P (charset)
-             && CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) < 0)
+             && (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
+                 == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION))
            {
              /* We have not yet decided where to designate CHARSET.  */
              int reg_bits = default_reg_bits;
@@ -2307,9 +2557,13 @@ setup_coding_system (coding_system, coding)
       coding->require_flushing = 1;
       break;
 
+    case 5:
+      coding->type = coding_type_raw_text;
+      break;
+
     default:
       if (EQ (type, Qt))
-       coding->type = coding_type_automatic;
+       coding->type = coding_type_undecided;
       else
        coding->type = coding_type_no_conversion;
       break;
@@ -2330,44 +2584,54 @@ setup_coding_system (coding_system, coding)
    because they use the same range of codes.  So, at first, coding
    systems are categorized into 7, those are:
 
-   o coding-category-internal
+   o coding-category-emacs-mule
 
        The category for a coding system which has the same code range
        as Emacs' internal format.  Assigned the coding-system (Lisp
-       symbol) `internal' by default.
+       symbol) `emacs-mule' by default.
 
    o coding-category-sjis
 
        The category for a coding system which has the same code range
        as SJIS.  Assigned the coding-system (Lisp
-       symbol) `shift-jis' by default.
+       symbol) `japanese-shift-jis' by default.
 
    o coding-category-iso-7
 
        The category for a coding system which has the same code range
-       as ISO2022 of 7-bit environment.  Assigned the coding-system
-       (Lisp symbol) `iso-2022-7' by default.
+       as ISO2022 of 7-bit environment.  This doesn't use any locking
+       shift and single shift functions.  Assigned the coding-system
+       (Lisp symbol) `iso-2022-7bit' by default.
 
    o coding-category-iso-8-1
 
        The category for a coding system which has the same code range
        as ISO2022 of 8-bit environment and graphic plane 1 used only
-       for DIMENSION1 charset.  Assigned the coding-system (Lisp
-       symbol) `iso-8859-1' by default.
+       for DIMENSION1 charset.  This doesn't use any locking shift
+       and single shift functions.  Assigned the coding-system (Lisp
+       symbol) `iso-latin-1' by default.
 
    o coding-category-iso-8-2
 
        The category for a coding system which has the same code range
        as ISO2022 of 8-bit environment and graphic plane 1 used only
-       for DIMENSION2 charset.  Assigned the coding-system (Lisp
-       symbol) `euc-japan' by default.
+       for DIMENSION2 charset.  This doesn't use any locking shift
+       and single shift functions.  Assigned the coding-system (Lisp
+       symbol) `japanese-iso-8bit' by default.
 
-   o coding-category-iso-else
+   o coding-category-iso-7-else
 
        The category for a coding system which has the same code range
-       as ISO2022 but not belongs to any of the above three
-       categories.  Assigned the coding-system (Lisp symbol)
-       `iso-2022-ss2-7' by default.
+       as ISO2022 of 7-bit environemnt but uses locking shift or
+       single shift functions.  Assigned the coding-system (Lisp
+       symbol) `iso-2022-7bit-lock' by default.
+
+   o coding-category-iso-8-else
+
+       The category for a coding system which has the same code range
+       as ISO2022 of 8-bit environemnt but uses locking shift or
+       single shift functions.  Assigned the coding-system (Lisp
+       symbol) `iso-2022-8bit-ss2' by default.
 
    o coding-category-big5
 
@@ -2429,31 +2693,46 @@ detect_coding_mask (src, src_bytes)
       /* C is an ISO2022 specific control code of C0.  */
       mask = detect_coding_iso2022 (src, src_end);
       src++;
-      if (mask == CODING_CATEGORY_MASK_ANY)
+      if (mask == 0)
        /* No valid ISO2022 code follows C.  Try again.  */
        goto label_loop_detect_coding;
+      mask |= CODING_CATEGORY_MASK_RAW_TEXT;
     }
-  else if (c == ISO_CODE_SS2 || c == ISO_CODE_SS3 || c == ISO_CODE_CSI)
-    /* C is an ISO2022 specific control code of C1,
-       or the first byte of SJIS's 2-byte character code,
-       or a leading code of Emacs.  */
-    mask = (detect_coding_iso2022 (src, src_end)
-           | detect_coding_sjis (src, src_end)
-           | detect_coding_internal (src, src_end));
-
   else if (c < 0xA0)
-    /* C is the first byte of SJIS character code,
-       or a leading-code of Emacs.  */
-    mask = (detect_coding_sjis (src, src_end)
-           | detect_coding_internal (src, src_end));
+    {
+      /* If C is a special latin extra code,
+        or is an ISO2022 specific control code of C1 (SS2 or SS3), 
+        or is an ISO2022 control-sequence-introducer (CSI),
+        we should also consider the possibility of ISO2022 codings.  */
+      if ((VECTORP (Vlatin_extra_code_table)
+          && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c]))
+         || (c == ISO_CODE_SS2 || c == ISO_CODE_SS3)
+         || (c == ISO_CODE_CSI
+             && (src < src_end
+                 && (*src == ']'
+                     || (src + 1 < src_end
+                         && src[1] == ']'
+                         && (*src == '0' || *src == '1' || *src == '2'))))))
+       mask = (detect_coding_iso2022 (src, src_end)
+               | detect_coding_sjis (src, src_end)
+               | detect_coding_emacs_mule (src, src_end)
+               | CODING_CATEGORY_MASK_RAW_TEXT);
 
+      else
+       /* C is the first byte of SJIS character code,
+          or a leading-code of Emacs' internal format (emacs-mule).  */
+       mask = (detect_coding_sjis (src, src_end)
+               | detect_coding_emacs_mule (src, src_end)
+               | CODING_CATEGORY_MASK_RAW_TEXT);
+    }
   else
     /* C is a character of ISO2022 in graphic plane right,
        or a SJIS's 1-byte character code (i.e. JISX0201),
        or the first byte of BIG5's 2-byte code.  */
     mask = (detect_coding_iso2022 (src, src_end)
            | detect_coding_sjis (src, src_end)
-           | detect_coding_big5 (src, src_end));
+           | detect_coding_big5 (src, src_end)
+           | CODING_CATEGORY_MASK_RAW_TEXT);
 
   return mask;
 }
@@ -2469,49 +2748,42 @@ detect_coding (coding, src, src_bytes)
 {
   int mask = detect_coding_mask (src, src_bytes);
   int idx;
+  Lisp_Object val = Vcoding_category_list;
 
   if (mask == CODING_CATEGORY_MASK_ANY)
     /* We found nothing other than ASCII.  There's nothing to do.  */
     return;
 
-  if (!mask)
-    /* The source text seems to be encoded in unknown coding system.
-       Emacs regards the category of such a kind of coding system as
-       `coding-category-binary'.  We assume that a user has assigned
-       an appropriate coding system for a `coding-category-binary'.  */
-    idx = CODING_CATEGORY_IDX_BINARY;
-  else
-    {
-      /* We found some plausible coding systems.  Let's use a coding
-        system of the highest priority.  */
-      Lisp_Object val = Vcoding_category_list;
+  /* We found some plausible coding systems.  Let's use a coding
+     system of the highest priority.  */
 
-      if (CONSP (val))
-       while (!NILP (val))
-         {
-           idx = XFASTINT (Fget (XCONS (val)->car, Qcoding_category_index));
-           if ((idx < CODING_CATEGORY_IDX_MAX) && (mask & (1 << idx)))
-             break;
-           val = XCONS (val)->cdr;
-         }
-      else
-       val = Qnil;
+  if (CONSP (val))
+    while (!NILP (val))
+      {
+       idx = XFASTINT (Fget (XCONS (val)->car, Qcoding_category_index));
+       if ((idx < CODING_CATEGORY_IDX_MAX) && (mask & (1 << idx)))
+         break;
+       val = XCONS (val)->cdr;
+      }
+  else
+    val = Qnil;
 
-      if (NILP (val))
-       {
-         /* For unknown reason, `Vcoding_category_list' contains none
-            of found categories.  Let's use any of them.  */
-         for (idx = 0; idx < CODING_CATEGORY_IDX_MAX; idx++)
-           if (mask & (1 << idx))
-             break;
-       }
+  if (NILP (val))
+    {
+      /* For unknown reason, `Vcoding_category_list' contains none of
+        found categories.  Let's use any of them.  */
+      for (idx = 0; idx < CODING_CATEGORY_IDX_MAX; idx++)
+       if (mask & (1 << idx))
+         break;
     }
   setup_coding_system (XSYMBOL (coding_category_table[idx])->value, coding);
 }
 
 /* Detect how end-of-line of a text of length SRC_BYTES pointed by SRC
    is encoded.  Return one of CODING_EOL_LF, CODING_EOL_CRLF,
-   CODING_EOL_CR, and CODING_EOL_AUTOMATIC.  */
+   CODING_EOL_CR, and CODING_EOL_UNDECIDED.  */
+
+#define MAX_EOL_CHECK_COUNT 3
 
 int
 detect_eol_type (src, src_bytes)
@@ -2520,21 +2792,34 @@ detect_eol_type (src, src_bytes)
 {
   unsigned char *src_end = src + src_bytes;
   unsigned char c;
+  int total = 0;               /* How many end-of-lines are found so far.  */
+  int eol_type = CODING_EOL_UNDECIDED;
+  int this_eol_type;
 
-  while (src < src_end)
+  while (src < src_end && total < MAX_EOL_CHECK_COUNT)
     {
       c = *src++;
-      if (c == '\n')
-       return CODING_EOL_LF;
-      else if (c == '\r')
+      if (c == '\n' || c == '\r')
        {
-         if (src < src_end && *src == '\n')
-           return CODING_EOL_CRLF;
+         total++;
+         if (c == '\n')
+           this_eol_type = CODING_EOL_LF;
+         else if (src >= src_end || *src != '\n')
+           this_eol_type = CODING_EOL_CR;
          else
-           return CODING_EOL_CR;
+           this_eol_type = CODING_EOL_CRLF, src++;
+
+         if (eol_type == CODING_EOL_UNDECIDED)
+           /* This is the first end-of-line.  */
+           eol_type = this_eol_type;
+         else if (eol_type != this_eol_type)
+           /* The found type is different from what found before.
+              Let's notice the caller about this inconsistency.  */
+           return CODING_EOL_INCONSISTENT;
        }
     }
-  return CODING_EOL_AUTOMATIC;
+
+  return eol_type;
 }
 
 /* Detect how end-of-line of a text of length SRC_BYTES pointed by SRC
@@ -2547,14 +2832,35 @@ detect_eol (coding, src, src_bytes)
      unsigned char *src;
      int src_bytes;
 {
-  Lisp_Object val;
+  Lisp_Object val, coding_system;
   int eol_type = detect_eol_type (src, src_bytes);
 
-  if (eol_type == CODING_EOL_AUTOMATIC)
+  if (eol_type == CODING_EOL_UNDECIDED)
     /*  We found no end-of-line in the source text.  */
     return;
 
-  val = Fget (coding->symbol, Qeol_type);
+  if (eol_type == CODING_EOL_INCONSISTENT)
+    {
+#if 0
+      /* This code is suppressed until we find a better way to
+        distinguish raw text file and binary file.  */
+
+      /* If we have already detected that the coding is raw-text, the
+        coding should actually be no-conversion.  */
+      if (coding->type == coding_type_raw_text)
+       {
+         setup_coding_system (Qno_conversion, coding);
+         return;
+       }
+      /* Else, let's decode only text code anyway.  */
+#endif /* 0 */
+      eol_type = CODING_EOL_LF;
+    }
+
+  coding_system = coding->symbol;
+  while (!NILP (coding_system)
+        && NILP (val = Fget (coding_system, Qeol_type)))
+    coding_system = Fget (coding_system, Qcoding_system);
   if (VECTORP (val) && XVECTOR (val)->size == 3)
     setup_coding_system (XVECTOR (val)->contents[eol_type], coding);
 }
@@ -2578,10 +2884,10 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes, consumed)
       return 0;
     }
 
-  if (coding->type == coding_type_automatic)
+  if (coding->type == coding_type_undecided)
     detect_coding (coding, source, src_bytes);
 
-  if (coding->eol_type == CODING_EOL_AUTOMATIC)
+  if (coding->eol_type == CODING_EOL_UNDECIDED)
     detect_eol (coding, source, src_bytes);
 
   coding->carryover_size = 0;
@@ -2594,10 +2900,11 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes, consumed)
       *consumed = produced;
       break;
 
-    case coding_type_internal:
-    case coding_type_automatic:
+    case coding_type_emacs_mule:
+    case coding_type_undecided:
+    case coding_type_raw_text:
       if (coding->eol_type == CODING_EOL_LF
-         ||  coding->eol_type == CODING_EOL_AUTOMATIC)
+         ||  coding->eol_type == CODING_EOL_UNDECIDED)
        goto label_no_conversion;
       produced = decode_eol (coding, source, destination,
                             src_bytes, dst_bytes, consumed);
@@ -2640,7 +2947,6 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes, consumed)
 {
   int produced;
 
-  coding->carryover_size = 0;
   switch (coding->type)
     {
     case coding_type_no_conversion:
@@ -2659,10 +2965,11 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes, consumed)
       *consumed = produced;
       break;
 
-    case coding_type_internal:
-    case coding_type_automatic:
+    case coding_type_emacs_mule:
+    case coding_type_undecided:
+    case coding_type_raw_text:
       if (coding->eol_type == CODING_EOL_LF
-         ||  coding->eol_type == CODING_EOL_AUTOMATIC)
+         ||  coding->eol_type == CODING_EOL_UNDECIDED)
        goto label_no_conversion;
       produced = encode_eol (coding, source, destination,
                             src_bytes, dst_bytes, consumed);
@@ -2767,9 +3074,9 @@ get_conversion_buffer (size)
 #ifdef emacs
 /*** 7. Emacs Lisp library functions ***/
 
-DEFUN ("coding-system-vector", Fcoding_system_vector, Scoding_system_vector,
+DEFUN ("coding-system-spec", Fcoding_system_spec, Scoding_system_spec,
        1, 1, 0,
-  "Return coding-vector of CODING-SYSTEM.\n\
+  "Return coding-spec of CODING-SYSTEM.\n\
 If CODING-SYSTEM is not a valid coding-system, return nil.")
   (obj)
      Lisp_Object obj;
@@ -2786,7 +3093,7 @@ See document of make-coding-system for coding-system object.")
   (obj)
      Lisp_Object obj;
 {
-  return ((NILP (obj) || !NILP (Fcoding_system_vector (obj))) ? Qt : Qnil);
+  return ((NILP (obj) || !NILP (Fcoding_system_spec (obj))) ? Qt : Qnil);
 }
 
 DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system,
@@ -2798,8 +3105,8 @@ DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system,
   Lisp_Object val;
   do
     {
-      val = Fcompleting_read (prompt, Vobarray, Qcoding_system_vector,
-                             Qt, Qnil, Qnil, Qnil);
+      val = Fcompleting_read (prompt, Vobarray, Qcoding_system_spec,
+                             Qt, Qnil, Qnil, Qnil, Qnil);
     }
   while (XSTRING (val)->size == 0);
   return (Fintern (val, Qnil));
@@ -2810,8 +3117,9 @@ DEFUN ("read-coding-system", Fread_coding_system, Sread_coding_system, 1, 1, 0,
   (prompt)
      Lisp_Object prompt;
 {
-  Lisp_Object val = Fcompleting_read (prompt, Vobarray, Qcoding_system_p,
-                                     Qt, Qnil, Qnil, Qnil);
+  Lisp_Object val;
+  val = Fcompleting_read (prompt, Vobarray, Qcoding_system_p,
+                         Qt, Qnil, Qcoding_system_history, Qnil, Qnil);
   return (XSTRING (val)->size == 0 ? Qnil : Fintern (val, Qnil));
 }
 
@@ -2828,15 +3136,15 @@ The value of property should be a vector of length 5.")
   if (!NILP (Fcoding_system_p (coding_system)))
     return coding_system;
   while (1)
-    Fsignal (Qcoding_system_error, coding_system);
+    Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
 }
 
 DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region,
        2, 2, 0,
-  "Detect coding-system of the text in the region between START and END.\n\
-Return a list of possible coding-systems ordered by priority.\n\
-If only ASCII characters are found, it returns `automatic-conversion'\n\
- or its subsidiary coding-system according to a detected end-of-line format.")
+  "Detect coding system of the text in the region between START and END.\n\
+Return a list of possible coding systems ordered by priority.\n\
+If only ASCII characters are found, it returns `undecided'\n\
+ or its subsidiary coding system according to a detected end-of-line format.")
   (b, e)
      Lisp_Object b, e;
 {
@@ -2853,10 +3161,12 @@ If only ASCII characters are found, it returns `automatic-conversion'\n\
 
   if (coding_mask == CODING_CATEGORY_MASK_ANY)
     {
-      val = intern ("automatic-conversion");
-      if (eol_type != CODING_EOL_AUTOMATIC)
+      val = Qundecided;
+      if (eol_type != CODING_EOL_UNDECIDED
+         && eol_type != CODING_EOL_INCONSISTENT)
        {
-         Lisp_Object val2 = Fget (val, Qeol_type);
+         Lisp_Object val2;
+         val2 = Fget (Qundecided, Qeol_type);
          if (VECTORP (val2))
            val = XVECTOR (val2)->contents[eol_type];
        }
@@ -2875,20 +3185,34 @@ If only ASCII characters are found, it returns `automatic-conversion'\n\
          int idx
            = XFASTINT (Fget (XCONS (val2)->car, Qcoding_category_index));
          if (coding_mask & (1 << idx))
-           val = Fcons (Fsymbol_value (XCONS (val2)->car), val);
+           {
+#if 0
+             /* This code is suppressed until we find a better way to
+                distinguish raw text file and binary file.  */
+
+             if (idx == CODING_CATEGORY_IDX_RAW_TEXT
+                 && eol_type == CODING_EOL_INCONSISTENT)
+               val = Fcons (Qno_conversion, val);
+             else
+#endif /* 0 */
+               val = Fcons (Fsymbol_value (XCONS (val2)->car), val);
+           }
        }
 
       /* Then, change the order of the list, while getting subsidiary
         coding-systems.  */
       val2 = val;
       val = Qnil;
+      if (eol_type == CODING_EOL_INCONSISTENT)
+       eol_type == CODING_EOL_UNDECIDED;
       for (; !NILP (val2); val2 = XCONS (val2)->cdr)
        {
-         if (eol_type == CODING_EOL_AUTOMATIC)
+         if (eol_type == CODING_EOL_UNDECIDED)
            val = Fcons (XCONS (val2)->car, val);
          else
            {
-             Lisp_Object val3 = Fget (XCONS (val2)->car, Qeol_type);
+             Lisp_Object val3;
+             val3 = Fget (XCONS (val2)->car, Qeol_type);
              if (VECTORP (val3))
                val = Fcons (XVECTOR (val3)->contents[eol_type], val);
              else
@@ -2914,7 +3238,7 @@ shrink_conversion_area (begp, endp, coding, encodep)
   register unsigned char *beg_addr = *begp, *end_addr = *endp;
 
   if (coding->eol_type != CODING_EOL_LF
-      && coding->eol_type != CODING_EOL_AUTOMATIC)
+      && coding->eol_type != CODING_EOL_UNDECIDED)
     /* Since we anyway have to convert end-of-line format, it is not
        worth skipping at most 100 bytes or so.  */
     return;
@@ -2924,8 +3248,9 @@ shrink_conversion_area (begp, endp, coding, encodep)
       switch (coding->type)
        {
        case coding_type_no_conversion:
-       case coding_type_internal:
-       case coding_type_automatic:
+       case coding_type_emacs_mule:
+       case coding_type_undecided:
+       case coding_type_raw_text:
          /* We need no conversion.  */
          *begp = *endp;
          return;
@@ -2962,7 +3287,8 @@ shrink_conversion_area (begp, endp, coding, encodep)
          /* We need no conversion.  */
          *begp = *endp;
          return;
-       case coding_type_internal:
+       case coding_type_emacs_mule:
+       case coding_type_raw_text:
          if (coding->eol_type == CODING_EOL_LF)
            {
              /* We need no conversion.  */
@@ -3332,19 +3658,29 @@ Return the corresponding character code in Big5.")
   return val;
 }
 
-DEFUN ("set-terminal-coding-system",
-       Fset_terminal_coding_system, Sset_terminal_coding_system, 1, 1,
-       "zCoding-system for terminal display: ",
-  "Set coding-system of your terminal to CODING-SYSTEM.\n\
-All outputs to terminal are encoded to this coding-system.")
+DEFUN ("set-terminal-coding-system-internal",
+       Fset_terminal_coding_system_internal,
+       Sset_terminal_coding_system_internal, 1, 1, 0, "")
   (coding_system)
      Lisp_Object coding_system;
 {
   CHECK_SYMBOL (coding_system, 0);
   setup_coding_system (Fcheck_coding_system (coding_system), &terminal_coding);
-  update_mode_lines++;
-  if (!NILP (Finteractive_p ()))
-    Fredraw_display ();
+  /* We had better not send unexpected characters to terminal.  */
+  terminal_coding.flags |= CODING_FLAG_ISO_SAFE;
+
+  return Qnil;
+}
+
+DEFUN ("set-safe-terminal-coding-system-internal",
+       Fset_safe_terminal_coding_system_internal,
+       Sset_safe_terminal_coding_system_internal, 1, 1, 0, "")
+  (coding_system)
+     Lisp_Object coding_system;
+{
+  CHECK_SYMBOL (coding_system, 0);
+  setup_coding_system (Fcheck_coding_system (coding_system),
+                      &safe_terminal_coding);
   return Qnil;
 }
 
@@ -3356,14 +3692,9 @@ DEFUN ("terminal-coding-system",
   return terminal_coding.symbol;
 }
 
-DEFUN ("set-keyboard-coding-system",
-       Fset_keyboard_coding_system, Sset_keyboard_coding_system, 1, 1, 0,
-  "Set coding-system of codes sent from terminal keyboard to CODING-SYSTEM.\n\
-In Encoded-kbd minor mode, user inputs are decoded\n\
-accoding to CODING-SYSTEM.\n\
-Do not call this function directly, but use the command\n\
-encoded-kbd-set-coding-system to activate Encoded-kbd mode\n\
-with a specific coding system.")
+DEFUN ("set-keyboard-coding-system-internal",
+       Fset_keyboard_coding_system_internal,
+       Sset_keyboard_coding_system_internal, 1, 1, 0, "")
   (coding_system)
      Lisp_Object coding_system;
 {
@@ -3381,13 +3712,13 @@ DEFUN ("keyboard-coding-system",
 }
 
 \f
-DEFUN ("find-coding-system", Ffind_coding_system, Sfind_coding_system,
-       1, MANY, 0,
-  "Choose a coding system for a file operation based on file name.\n\
-The value names a pair of coding systems: (ENCODING-SYSTEM DECODING-SYSTEM).\n\
-ENCODING-SYSTEM is the coding system to use for encoding\n\
-\(in case OPERATION does encoding), and DECODING-SYSTEM is the coding system\n\
-for decoding (in case OPERATION does decoding).\n\
+DEFUN ("find-operation-coding-system", Ffind_operation_coding_system,
+       Sfind_operation_coding_system,  1, MANY, 0,
+  "Choose a coding system for an operation based on the target name.\n\
+The value names a pair of coding systems: (DECODING-SYSTEM ENCODING-SYSTEM).\n\
+DECODING-SYSTEM is the coding system to use for decoding\n\
+\(in case OPERATION does decoding), and ENCODING-SYSTEM is the coding system\n\
+for encoding (in case OPERATION does encoding).\n\
 \n\
 The first argument OPERATION specifies an I/O primitive:\n\
   For file I/O, `insert-file-contents' or `write-region'.\n\
@@ -3404,11 +3735,13 @@ TARGET has a meaning which depends on OPERATION:\n\
   For process I/O, TARGET is a process name.\n\
   For network I/O, TARGET is a service name or a port number\n\
 \n\
-This function looks up what `coding-system-alist' specifies for\n\
-OPERATION and TARGET.  It may specify a cons cell which represents\n\
-a particular coding system or it may have a function to call.\n\
-In the latter case, we call the function with one argument,\n\
-which is a list of all the arguments given to `find-coding-system'.")
+This function looks up what specified for TARGET in,\n\
+`file-coding-system-alist', `process-coding-system-alist',\n\
+or `network-coding-system-alist' depending on OPERATION.\n\
+They may specify a coding system, a cons of coding systems,\n\
+or a function symbol to call.\n\
+In the last case, we call the function with one argument,\n\
+which is a list of all the arguments given to this function.")
   (nargs, args)
      int nargs;
      Lisp_Object *args;
@@ -3430,24 +3763,37 @@ which is a list of all the arguments given to `find-coding-system'.")
        || (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
     error ("Invalid %dth argument", XINT (target_idx) + 1);
 
-  chain = Fassq (operation, Vcoding_system_alist);
+  chain = ((EQ (operation, Qinsert_file_contents)
+           || EQ (operation, Qwrite_region))
+          ? Vfile_coding_system_alist
+          : (EQ (operation, Qopen_network_stream)
+             ? Vnetwork_coding_system_alist
+             : Vprocess_coding_system_alist));
   if (NILP (chain))
     return Qnil;
 
-  for (chain = XCONS (chain)->cdr; CONSP (chain); chain = XCONS (chain)->cdr)
+  for (; CONSP (chain); chain = XCONS (chain)->cdr)
     {
-      Lisp_Object elt = XCONS (chain)->car;
+      Lisp_Object elt;
+      elt = XCONS (chain)->car;
 
       if (CONSP (elt)
          && ((STRINGP (target)
               && STRINGP (XCONS (elt)->car)
               && fast_string_match (XCONS (elt)->car, target) >= 0)
              || (INTEGERP (target) && EQ (target, XCONS (elt)->car))))
-       return (val = XCONS (elt)->cdr, CONSP (val)
-               ? val
-               : ((SYMBOLP (val) && !NILP (Fboundp (val))
-                   ? call2 (val, Flist (nargs, args))
-                   : Qnil)));
+       {
+         val = XCONS (elt)->cdr;
+         if (CONSP (val))
+           return val;
+         if (! SYMBOLP (val))
+           return Qnil;
+         if (! NILP (Fcoding_system_p (val)))
+           return Fcons (val, val);
+         if (!NILP (Ffboundp (val)))
+           return call1 (val, Flist (nargs, args));
+         return Qnil;
+       }
     }
   return Qnil;
 }
@@ -3461,7 +3807,7 @@ init_coding_once ()
 {
   int i;
 
-  /* Emacs internal format specific initialize routine.  */ 
+  /* Emacs' internal format specific initialize routine.  */ 
   for (i = 0; i <= 0x20; i++)
     emacs_code_class[i] = EMACS_control_code;
   emacs_code_class[0x0A] = EMACS_linefeed_code;
@@ -3502,6 +3848,13 @@ init_coding_once ()
 
   setup_coding_system (Qnil, &keyboard_coding);
   setup_coding_system (Qnil, &terminal_coding);
+  setup_coding_system (Qnil, &safe_terminal_coding);
+
+#if defined (MSDOS) || defined (WINDOWSNT)
+  system_eol_type = CODING_EOL_CRLF;
+#else
+  system_eol_type = CODING_EOL_LF;
+#endif
 }
 
 #ifdef emacs
@@ -3511,23 +3864,33 @@ syms_of_coding ()
   Qtarget_idx = intern ("target-idx");
   staticpro (&Qtarget_idx);
 
+  Qcoding_system_history = intern ("coding-system-history");
+  staticpro (&Qcoding_system_history);
+  Fset (Qcoding_system_history, Qnil);
+
+  /* Target FILENAME is the first argument.  */
   Fput (Qinsert_file_contents, Qtarget_idx, make_number (0));
+  /* Target FILENAME is the third argument.  */
   Fput (Qwrite_region, Qtarget_idx, make_number (2));
 
   Qcall_process = intern ("call-process");
   staticpro (&Qcall_process);
+  /* Target PROGRAM is the first argument.  */
   Fput (Qcall_process, Qtarget_idx, make_number (0));
 
   Qcall_process_region = intern ("call-process-region");
   staticpro (&Qcall_process_region);
+  /* Target PROGRAM is the third argument.  */
   Fput (Qcall_process_region, Qtarget_idx, make_number (2));
 
   Qstart_process = intern ("start-process");
   staticpro (&Qstart_process);
+  /* Target PROGRAM is the third argument.  */
   Fput (Qstart_process, Qtarget_idx, make_number (2));
 
   Qopen_network_stream = intern ("open-network-stream");
   staticpro (&Qopen_network_stream);
+  /* Target SERVICE is the fourth argument.  */
   Fput (Qopen_network_stream, Qtarget_idx, make_number (3));
 
   Qcoding_system = intern ("coding-system");
@@ -3545,8 +3908,14 @@ syms_of_coding ()
   Qpre_write_conversion = intern ("pre-write-conversion");
   staticpro (&Qpre_write_conversion);
 
-  Qcoding_system_vector = intern ("coding-system-vector");
-  staticpro (&Qcoding_system_vector);
+  Qno_conversion = intern ("no-conversion");
+  staticpro (&Qno_conversion);
+
+  Qundecided = intern ("undecided");
+  staticpro (&Qundecided);
+
+  Qcoding_system_spec = intern ("coding-system-spec");
+  staticpro (&Qcoding_system_spec);
 
   Qcoding_system_p = intern ("coding-system-p");
   staticpro (&Qcoding_system_p);
@@ -3557,7 +3926,7 @@ syms_of_coding ()
   Fput (Qcoding_system_error, Qerror_conditions,
        Fcons (Qcoding_system_error, Fcons (Qerror, Qnil)));
   Fput (Qcoding_system_error, Qerror_message,
-       build_string ("Coding-system error"));
+       build_string ("Invalid coding system"));
 
   Qcoding_category_index = intern ("coding-category-index");
   staticpro (&Qcoding_category_index);
@@ -3578,7 +3947,18 @@ syms_of_coding ()
   Fput (Qcharacter_unification_table, Qchar_table_extra_slots,
        make_number (0));
 
-  defsubr (&Scoding_system_vector);
+  Qcharacter_unification_table_for_decode
+    = intern ("character-unification-table-for-decode");
+  staticpro (&Qcharacter_unification_table_for_decode);
+
+  Qcharacter_unification_table_for_encode
+    = intern ("character-unification-table-for-encode");
+  staticpro (&Qcharacter_unification_table_for_encode);
+
+  Qemacs_mule = intern ("emacs-mule");
+  staticpro (&Qemacs_mule);
+
+  defsubr (&Scoding_system_spec);
   defsubr (&Scoding_system_p);
   defsubr (&Sread_coding_system);
   defsubr (&Sread_non_nil_coding_system);
@@ -3592,11 +3972,12 @@ syms_of_coding ()
   defsubr (&Sencode_sjis_char);
   defsubr (&Sdecode_big5_char);
   defsubr (&Sencode_big5_char);
-  defsubr (&Sset_terminal_coding_system);
+  defsubr (&Sset_terminal_coding_system_internal);
+  defsubr (&Sset_safe_terminal_coding_system_internal);
   defsubr (&Sterminal_coding_system);
-  defsubr (&Sset_keyboard_coding_system);
+  defsubr (&Sset_keyboard_coding_system_internal);
   defsubr (&Skeyboard_coding_system);
-  defsubr (&Sfind_coding_system);
+  defsubr (&Sfind_operation_coding_system);
 
   DEFVAR_LISP ("coding-category-list", &Vcoding_category_list,
     "List of coding-categories (symbols) ordered by priority.");
@@ -3610,77 +3991,130 @@ syms_of_coding ()
   }
 
   DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read,
-    "A variable of internal use only.\n\
+    "Specify the coding system for read operations.\n\
+It is useful to bind this variable with `let', but do not set it globally.\n\
 If the value is a coding system, it is used for decoding on read operation.\n\
-If not, an appropriate element in `coding-system-alist' (which see) is used.");
+If not, an appropriate element is used from one of the coding system alists:\n\
+There are three such tables, `file-coding-system-alist',\n\
+`process-coding-system-alist', and `network-coding-system-alist'.");
   Vcoding_system_for_read = Qnil;
 
   DEFVAR_LISP ("coding-system-for-write", &Vcoding_system_for_write,
-    "A variable of internal use only.\n\
+    "Specify the coding system for write operations.\n\
+It is useful to bind this variable with `let', but do not set it globally.\n\
 If the value is a coding system, it is used for encoding on write operation.\n\
-If not, an appropriate element in `coding-system-alist' (which see) is used.");
+If not, an appropriate element is used from one of the coding system alists:\n\
+There are three such tables, `file-coding-system-alist',\n\
+`process-coding-system-alist', and `network-coding-system-alist'.");
   Vcoding_system_for_write = Qnil;
 
   DEFVAR_LISP ("last-coding-system-used", &Vlast_coding_system_used,
-    "Coding-system used in the latest file or process I/O.");
+    "Coding system used in the latest file or process I/O.");
   Vlast_coding_system_used = Qnil;
 
-  DEFVAR_LISP ("coding-system-alist", &Vcoding_system_alist,
-    "Nested alist to decide a coding system for a specific I/O operation.\n\
-The format is ((OPERATION . ((REGEXP . CODING-SYSTEMS) ...)) ...).\n\
+  DEFVAR_BOOL ("inhibit-eol-conversion", &inhibit_eol_conversion,
+    "*Non-nil inhibit code conversion of end-of-line format in any cases.");
+  inhibit_eol_conversion = 0;
+
+  DEFVAR_LISP ("file-coding-system-alist", &Vfile_coding_system_alist,
+    "Alist to decide a coding system to use for a file I/O operation.\n\
+The format is ((PATTERN . VAL) ...),\n\
+where PATTERN is a regular expression matching a file name,\n\
+VAL is a coding system, a cons of coding systems, or a function symbol.\n\
+If VAL is a coding system, it is used for both decoding and encoding\n\
+the file contents.\n\
+If VAL is a cons of coding systems, the car part is used for decoding,\n\
+and the cdr part is used for encoding.\n\
+If VAL is a function symbol, the function must return a coding system\n\
+or a cons of coding systems which are used as above.\n\
 \n\
-OPERATION is one of the following Emacs I/O primitives:\n\
-  For file I/O, insert-file-contents and write-region.\n\
-  For process I/O, call-process, call-process-region, and start-process.\n\
-  For network I/O, open-network-stream.\n\
-In addition, for process I/O, `process-argument' can be specified for\n\
-encoding arguments of the process.\n\
+See also the function `find-operation-coding-system'.");
+  Vfile_coding_system_alist = Qnil;
+
+  DEFVAR_LISP ("process-coding-system-alist", &Vprocess_coding_system_alist,
+    "Alist to decide a coding system to use for a process I/O operation.\n\
+The format is ((PATTERN . VAL) ...),\n\
+where PATTERN is a regular expression matching a program name,\n\
+VAL is a coding system, a cons of coding systems, or a function symbol.\n\
+If VAL is a coding system, it is used for both decoding what received\n\
+from the program and encoding what sent to the program.\n\
+If VAL is a cons of coding systems, the car part is used for decoding,\n\
+and the cdr part is used for encoding.\n\
+If VAL is a function symbol, the function must return a coding system\n\
+or a cons of coding systems which are used as above.\n\
 \n\
-REGEXP is a regular expression matching a target of OPERATION, where\n\
-target is a file name for file I/O operations, a process name for\n\
-process I/O operations, or a service name for network I/O\n\
-operations.  REGEXP might be a port number for network I/O operation.\n\
+See also the function `find-operation-coding-system'.");
+  Vprocess_coding_system_alist = Qnil;
+
+  DEFVAR_LISP ("network-coding-system-alist", &Vnetwork_coding_system_alist,
+    "Alist to decide a coding system to use for a network I/O operation.\n\
+The format is ((PATTERN . VAL) ...),\n\
+where PATTERN is a regular expression matching a network service name\n\
+or is a port number to connect to,\n\
+VAL is a coding system, a cons of coding systems, or a function symbol.\n\
+If VAL is a coding system, it is used for both decoding what received\n\
+from the network stream and encoding what sent to the network stream.\n\
+If VAL is a cons of coding systems, the car part is used for decoding,\n\
+and the cdr part is used for encoding.\n\
+If VAL is a function symbol, the function must return a coding system\n\
+or a cons of coding systems which are used as above.\n\
 \n\
-CODING-SYSTEMS is a cons of coding systems to encode and decode\n\
-character code on OPERATION, or a function symbol returning the cons.\n\
-See the documentation of `find-coding-system' for more detail.");
-  Vcoding_system_alist = Qnil;
+See also the function `find-operation-coding-system'.");
+  Vnetwork_coding_system_alist = Qnil;
 
   DEFVAR_INT ("eol-mnemonic-unix", &eol_mnemonic_unix,
     "Mnemonic character indicating UNIX-like end-of-line format (i.e. LF) .");
-  eol_mnemonic_unix = '.';
+  eol_mnemonic_unix = ':';
 
   DEFVAR_INT ("eol-mnemonic-dos", &eol_mnemonic_dos,
     "Mnemonic character indicating DOS-like end-of-line format (i.e. CRLF).");
-  eol_mnemonic_dos = ':';
+  eol_mnemonic_dos = '\\';
 
   DEFVAR_INT ("eol-mnemonic-mac", &eol_mnemonic_mac,
     "Mnemonic character indicating MAC-like end-of-line format (i.e. CR).");
-  eol_mnemonic_mac = '\'';
+  eol_mnemonic_mac = '/';
 
   DEFVAR_INT ("eol-mnemonic-undecided", &eol_mnemonic_undecided,
     "Mnemonic character indicating end-of-line format is not yet decided.");
-  eol_mnemonic_undecided = '-';
+  eol_mnemonic_undecided = ':';
 
   DEFVAR_LISP ("enable-character-unification", &Venable_character_unification,
     "Non-nil means ISO 2022 encoder/decoder do character unification.");
   Venable_character_unification = Qt;
 
-  DEFVAR_LISP ("standard-character-unification-table-for-read",
-    &Vstandard_character_unification_table_for_read,
+  DEFVAR_LISP ("standard-character-unification-table-for-decode",
+    &Vstandard_character_unification_table_for_decode,
     "Table for unifying characters when reading.");
-  Vstandard_character_unification_table_for_read = Qnil;
+  Vstandard_character_unification_table_for_decode = Qnil;
 
-  DEFVAR_LISP ("standard-character-unification-table-for-write",
-    &Vstandard_character_unification_table_for_write,
+  DEFVAR_LISP ("standard-character-unification-table-for-encode",
+    &Vstandard_character_unification_table_for_encode,
     "Table for unifying characters when writing.");
-  Vstandard_character_unification_table_for_write = Qnil;
+  Vstandard_character_unification_table_for_encode = Qnil;
 
   DEFVAR_LISP ("charset-revision-table", &Vcharset_revision_alist,
     "Alist of charsets vs revision numbers.\n\
 While encoding, if a charset (car part of an element) is found,\n\
 designate it with the escape sequence identifing revision (cdr part of the element).");
   Vcharset_revision_alist = Qnil;
+
+  DEFVAR_LISP ("default-process-coding-system",
+              &Vdefault_process_coding_system,
+    "Cons of coding systems used for process I/O by default.\n\
+The car part is used for decoding a process output,\n\
+the cdr part is used for encoding a text to be sent to a process.");
+  Vdefault_process_coding_system = Qnil;
+
+  DEFVAR_LISP ("latin-extra-code-table", &Vlatin_extra_code_table,
+    "Table of extra Latin codes in the range 128..159 (inclusive).\n\
+This is a vector of length 256.\n\
+If Nth element is non-nil, the existence of code N in a file\n\
+\(or output of subprocess) doesn't prevent it to be detected as\n\
+a coding system of ISO 2022 variant which has a flag\n\
+`accept-latin-extra-code' t (e.g. iso-latin-1) on reading a file\n\
+or reading output of a subprocess.\n\
+Only 128th through 159th elements has a meaning.");
+  Vlatin_extra_code_table = Fmake_vector (make_number (256), Qnil);
 }
 
 #endif /* emacs */