New directory
[bpt/emacs.git] / src / coding.c
index 78ba80c..b06bf79 100644 (file)
@@ -1,7 +1,7 @@
 /* Coding system handler (conversion, detection, and etc).
-   Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN.
+   Copyright (C) 1995,97,1998,2002,2003  Electrotechnical Laboratory, JAPAN.
    Licensed to the Free Software Foundation.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001,2002,2003  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -60,7 +60,7 @@ Boston, MA 02111-1307, USA.  */
   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
   section 4.
@@ -345,6 +345,7 @@ encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes)
 #include "ccl.h"
 #include "coding.h"
 #include "window.h"
+#include "intervals.h"
 
 #else  /* not emacs */
 
@@ -367,6 +368,8 @@ Lisp_Object Qtarget_idx;
 
 Lisp_Object Vselect_safe_coding_system_function;
 
+int coding_system_require_warning;
+
 /* Mnemonic string for each format of end-of-line.  */
 Lisp_Object eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac;
 /* Mnemonic string to indicate format of end-of-line is not yet
@@ -379,6 +382,16 @@ int system_eol_type;
 
 #ifdef emacs
 
+/* Information about which coding system is safe for which chars.
+   The value has the form (GENERIC-LIST . NON-GENERIC-ALIST).
+
+   GENERIC-LIST is a list of generic coding systems which can encode
+   any characters.
+
+   NON-GENERIC-ALIST is an alist of non generic coding systems vs the
+   corresponding char table that contains safe chars.  */
+Lisp_Object Vcoding_system_safe_chars;
+
 Lisp_Object Vcoding_system_list, Vcoding_system_alist;
 
 Lisp_Object Qcoding_system_p, Qcoding_system_error;
@@ -387,6 +400,8 @@ Lisp_Object Qcoding_system_p, Qcoding_system_error;
    end-of-line format.  */
 Lisp_Object Qemacs_mule, Qraw_text;
 
+Lisp_Object Qutf_8;
+
 /* Coding-systems are handed between Emacs Lisp programs and C internal
    routines by the following three variables.  */
 /* Coding-system for reading files and receiving data from process.  */
@@ -485,26 +500,27 @@ Lisp_Object Vcharset_revision_alist;
 /* Default coding systems used for process I/O.  */
 Lisp_Object Vdefault_process_coding_system;
 
+/* Char table for translating Quail and self-inserting input.  */
+Lisp_Object Vtranslation_table_for_input;
+
 /* Global flag to tell that we can't call post-read-conversion and
    pre-write-conversion functions.  Usually the value is zero, but it
    is set to 1 temporarily while such functions are running.  This is
    to avoid infinite recursive call.  */
 static int inhibit_pre_post_conversion;
 
-/* Char-table containing safe coding systems of each character.  */
-Lisp_Object Vchar_coding_system_table;
 Lisp_Object Qchar_coding_system;
 
-/* Return `safe-chars' property of coding system CODING.  Don't check
-   validity of CODING.  */
+/* Return `safe-chars' property of CODING_SYSTEM (symbol).  Don't check
+   its validity.  */
 
 Lisp_Object
-coding_safe_chars (coding)
-     struct coding_system *coding;
+coding_safe_chars (coding_system)
+     Lisp_Object coding_system;
 {
   Lisp_Object coding_spec, plist, safe_chars;
-  
-  coding_spec = Fget (coding->symbol, Qcoding_system);
+
+  coding_spec = Fget (coding_system, Qcoding_system);
   plist = XVECTOR (coding_spec)->contents[3];
   safe_chars = Fplist_get (XVECTOR (coding_spec)->contents[3], Qsafe_chars);
   return (CHAR_TABLE_P (safe_chars) ? safe_chars : Qt);
@@ -673,8 +689,16 @@ detect_coding_emacs_mule (src, src_end, multibytep)
 
 /* Record one COMPONENT (alternate character or composition rule).  */
 
-#define CODING_ADD_COMPOSITION_COMPONENT(coding, component)    \
-  (coding->cmp_data->data[coding->cmp_data->used++] = component)
+#define CODING_ADD_COMPOSITION_COMPONENT(coding, component)            \
+  do {                                                                 \
+    coding->cmp_data->data[coding->cmp_data->used++] = component;      \
+    if (coding->cmp_data->used - coding->cmp_data_start                        \
+       == COMPOSITION_DATA_MAX_BUNCH_LENGTH)                           \
+      {                                                                        \
+       CODING_ADD_COMPOSITION_END (coding, coding->produced_char);     \
+       coding->composing = COMPOSITION_NO;                             \
+      }                                                                        \
+  } while (0)
 
 
 /* Get one byte from a data pointed by SRC and increment SRC.  If SRC
@@ -691,7 +715,7 @@ detect_coding_emacs_mule (src, src_end, multibytep)
 #define DECODE_EMACS_MULE_COMPOSITION_CHAR(c, p)               \
   do {                                                         \
     int bytes;                                                 \
-                                                               \
+                                                               \
     c = SAFE_ONE_MORE_BYTE ();                                 \
     if (c < 0)                                                 \
       break;                                                   \
@@ -722,7 +746,10 @@ detect_coding_emacs_mule (src, src_end, multibytep)
              break;                                            \
            *p++ = c;                                           \
          }                                                     \
-       if (UNIBYTE_STR_AS_MULTIBYTE_P (p0, p - p0, bytes))     \
+       if (UNIBYTE_STR_AS_MULTIBYTE_P (p0, p - p0, bytes)      \
+           || (coding->flags /* We are recovering a file.  */  \
+               && p0[0] == LEADING_CODE_8_BIT_CONTROL          \
+               && ! CHAR_HEAD_P (p0[1])))                      \
          c = STRING_CHAR (p0, bytes);                          \
        else                                                    \
          c = -1;                                               \
@@ -811,6 +838,10 @@ decode_composition_emacs_mule (coding, src, src_end,
        return 0;
       for (ncomponent = 0; src < src_base + data_len; ncomponent++)
        {
+         /* If it is longer than this, it can't be valid.  */
+         if (ncomponent >= COMPOSITION_DATA_MAX_BUNCH_LENGTH)
+           return 0;
+
          if (ncomponent % 2 && with_rule)
            {
              ONE_MORE_BYTE (gref);
@@ -822,7 +853,10 @@ decode_composition_emacs_mule (coding, src, src_end,
          else
            {
              int bytes;
-             if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes))
+             if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes)
+                 || (coding->flags /* We are recovering a file.  */
+                     && src[0] == LEADING_CODE_8_BIT_CONTROL
+                     && ! CHAR_HEAD_P (src[1])))
                c = STRING_CHAR (src, bytes);
              else
                c = *src, bytes = 1;
@@ -889,7 +923,7 @@ decode_composition_emacs_mule (coding, src, src_end,
       CODING_ADD_COMPOSITION_START (coding, coding->produced_char, method);
       for (i = 0; i < ncomponent; i++)
        CODING_ADD_COMPOSITION_COMPONENT (coding, component[i]);
-      CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars);  
+      CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars);
       if (buf < bufp)
        {
          unsigned char *p = buf;
@@ -938,11 +972,6 @@ decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
              ONE_MORE_BYTE (c);
              if (c != '\n')
                {
-                 if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)
-                   {
-                     coding->result = CODING_FINISH_INCONSISTENT_EOL;
-                     goto label_end_of_loop;
-                   }
                  src--;
                  c = '\r';
                }
@@ -964,7 +993,7 @@ decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
          coding->produced_char++;
          continue;
        }
-      else if (*src == 0x80)
+      else if (*src == 0x80 && coding->cmp_data)
        {
          /* Start of composition data.  */
          int consumed  = decode_composition_emacs_mule (coding, src, src_end,
@@ -981,7 +1010,10 @@ decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
          p = tmp;
          src++;
        }
-      else if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes))
+      else if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes)
+              || (coding->flags /* We are recovering a file.  */
+                  && src[0] == LEADING_CODE_8_BIT_CONTROL
+                  && ! CHAR_HEAD_P (src[1])))
        {
          p = src;
          src += bytes;
@@ -1055,9 +1087,9 @@ decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
        coding->cmp_data_start = 0;                                     \
       }                                                                        \
   } while (0)
-  
 
-static void encode_eol P_ ((struct coding_system *, unsigned char *,
+
+static void encode_eol P_ ((struct coding_system *, const unsigned char *,
                            unsigned char *, int, int));
 
 static void
@@ -1112,7 +1144,22 @@ encode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes)
            EMIT_ONE_BYTE ('\r');
        }
       else if (SINGLE_BYTE_CHAR_P (c))
-       EMIT_ONE_BYTE (c);
+       {
+         if (coding->flags && ! ASCII_BYTE_P (c))
+           {
+             /* As we are auto saving, retain the multibyte form for
+                8-bit chars.  */
+             unsigned char buf[MAX_MULTIBYTE_LENGTH];
+             int bytes = CHAR_STRING (c, buf);
+
+             if (bytes == 1)
+               EMIT_ONE_BYTE (buf[0]);
+             else
+               EMIT_TWO_BYTES (buf[0], buf[1]);
+           }
+         else
+           EMIT_ONE_BYTE (c);
+       }
       else
        EMIT_BYTES (src_base, src);
       coding->consumed_char++;
@@ -1306,7 +1353,7 @@ enum iso_code_class_type iso_code_class[256];
 #define CHARSET_OK(idx, charset, c)                                    \
   (coding_system_table[idx]                                            \
    && (charset == CHARSET_ASCII                                                \
-       || (safe_chars = coding_safe_chars (coding_system_table[idx]),  \
+       || (safe_chars = coding_safe_chars (coding_system_table[idx]->symbol), \
           CODING_SAFE_CHAR_P (safe_chars, c)))                         \
    && (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding_system_table[idx],        \
                                              charset)                  \
@@ -1315,6 +1362,9 @@ enum iso_code_class_type iso_code_class[256];
 #define SHIFT_OUT_OK(idx) \
   (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding_system_table[idx], 1) >= 0)
 
+#define COMPOSITION_OK(idx)    \
+  (coding_system_table[idx]->composing != COMPOSITION_DISABLED)
+
 /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions".
    Check if a text is encoded in ISO2022.  If it is, return an
    integer in which appropriate flag bits any of:
@@ -1345,6 +1395,7 @@ detect_coding_iso2022 (src, src_end, multibytep)
   while (mask && src < src_end)
     {
       ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep);
+    retry:
       switch (c)
        {
        case ISO_CODE_ESC:
@@ -1391,7 +1442,30 @@ detect_coding_iso2022 (src, src_end, multibytep)
          else if (c >= '0' && c <= '4')
            {
              /* ESC <Fp> for start/end composition.  */
-             mask_found |= CODING_CATEGORY_MASK_ISO;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7))
+               mask_found |= CODING_CATEGORY_MASK_ISO_7;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_7;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7_TIGHT))
+               mask_found |= CODING_CATEGORY_MASK_ISO_7_TIGHT;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_7_TIGHT;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_1))
+               mask_found |= CODING_CATEGORY_MASK_ISO_8_1;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_8_1;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_2))
+               mask_found |= CODING_CATEGORY_MASK_ISO_8_2;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_8_2;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7_ELSE))
+               mask_found |= CODING_CATEGORY_MASK_ISO_7_ELSE;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_7_ELSE;
+             if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_ELSE))
+               mask_found |= CODING_CATEGORY_MASK_ISO_8_ELSE;
+             else
+               mask &= ~CODING_CATEGORY_MASK_ISO_8_ELSE;
              break;
            }
          else
@@ -1433,7 +1507,7 @@ detect_coding_iso2022 (src, src_end, multibytep)
              mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT;
            }
          break;
-         
+
        case ISO_CODE_SI:
          if (inhibit_iso_escape_detection)
            break;
@@ -1519,6 +1593,8 @@ detect_coding_iso2022 (src, src_end, multibytep)
                  && mask & CODING_CATEGORY_MASK_ISO_8_2)
                {
                  int i = 1;
+
+                 c = -1;
                  while (src < src_end)
                    {
                      ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep);
@@ -1531,6 +1607,9 @@ detect_coding_iso2022 (src, src_end, multibytep)
                    mask &= ~CODING_CATEGORY_MASK_ISO_8_2;
                  else
                    mask_found |= CODING_CATEGORY_MASK_ISO_8_2;
+                 if (c >= 0)
+                   /* This means that we have read one extra byte.  */
+                   goto retry;
                }
            }
          break;
@@ -1665,7 +1744,7 @@ coding_allocate_composition_data (coding, char_offset)
 
 #define DECODE_COMPOSITION_END(c1)                                     \
   do {                                                                 \
-    if (coding->composing == COMPOSITION_DISABLED)                     \
+    if (! COMPOSING_P (coding))                                                \
       {                                                                        \
        *dst++ = ISO_CODE_ESC;                                          \
        *dst++ = c1;                                                    \
@@ -1729,7 +1808,7 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
   Lisp_Object translation_table;
   Lisp_Object safe_chars;
 
-  safe_chars = coding_safe_chars (coding);
+  safe_chars = coding_safe_chars (coding->symbol);
 
   if (NILP (Venable_character_translation))
     translation_table = Qnil;
@@ -1820,11 +1899,6 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
              ONE_MORE_BYTE (c1);
              if (c1 != ISO_CODE_LF)
                {
-                 if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)
-                   {
-                     coding->result = CODING_FINISH_INCONSISTENT_EOL;
-                     goto label_end_of_loop;
-                   }
                  src--;
                  c1 = '\r';
                }
@@ -1989,6 +2063,78 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
                }
              continue;
 
+           case '%':
+             if (COMPOSING_P (coding))
+               DECODE_COMPOSITION_END ('1');
+             ONE_MORE_BYTE (c1);
+             if (c1 == '/')
+               {
+                 /* CTEXT extended segment:
+                    ESC % / [0-4] M L --ENCODING-NAME-- \002 --BYTES--
+                    We keep these bytes as is for the moment.
+                    They may be decoded by post-read-conversion.  */
+                 int dim, M, L;
+                 int size, required;
+                 int produced_chars;
+                 
+                 ONE_MORE_BYTE (dim);
+                 ONE_MORE_BYTE (M);
+                 ONE_MORE_BYTE (L);
+                 size = ((M - 128) * 128) + (L - 128);
+                 required = 8 + size * 2;
+                 if (dst + required > (dst_bytes ? dst_end : src))
+                   goto label_end_of_loop;
+                 *dst++ = ISO_CODE_ESC;
+                 *dst++ = '%';
+                 *dst++ = '/';
+                 *dst++ = dim;
+                 produced_chars = 4;
+                 dst += CHAR_STRING (M, dst), produced_chars++;
+                 dst += CHAR_STRING (L, dst), produced_chars++;
+                 while (size-- > 0)
+                   {
+                     ONE_MORE_BYTE (c1);
+                     dst += CHAR_STRING (c1, dst), produced_chars++;
+                   }
+                 coding->produced_char += produced_chars;
+               }
+             else if (c1 == 'G')
+               {
+                 unsigned char *d = dst;
+                 int produced_chars;
+
+                 /* XFree86 extension for embedding UTF-8 in CTEXT:
+                    ESC % G --UTF-8-BYTES-- ESC % @
+                    We keep these bytes as is for the moment.
+                    They may be decoded by post-read-conversion.  */
+                 if (d + 6 > (dst_bytes ? dst_end : src))
+                   goto label_end_of_loop;
+                 *d++ = ISO_CODE_ESC;
+                 *d++ = '%';
+                 *d++ = 'G';
+                 produced_chars = 3;
+                 while (d + 1 < (dst_bytes ? dst_end : src))
+                   {
+                     ONE_MORE_BYTE (c1);
+                     if (c1 == ISO_CODE_ESC
+                         && src + 1 < src_end
+                         && src[0] == '%'
+                         && src[1] == '@')
+                       break;
+                     d += CHAR_STRING (c1, d), produced_chars++;
+                   }
+                 if (d + 3 > (dst_bytes ? dst_end : src))
+                   goto label_end_of_loop;
+                 *d++ = ISO_CODE_ESC;
+                 *d++ = '%';
+                 *d++ = '@';
+                 dst = d;
+                 coding->produced_char += produced_chars + 3;
+               }
+             else
+               goto label_invalid_code;
+             continue;
+
            default:
              if (! (coding->flags & CODING_FLAG_ISO_DESIGNATION))
                goto label_invalid_code;
@@ -2254,11 +2400,11 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
 
 /* Instead of encoding character C, produce one or two `?'s.  */
 
-#define ENCODE_UNSAFE_CHARACTER(c)                                     \
-  do {                                                                 \
-    ENCODE_ISO_CHARACTER (CODING_INHIBIT_CHARACTER_SUBSTITUTION);      \
-    if (CHARSET_WIDTH (CHAR_CHARSET (c)) > 1)                          \
-      ENCODE_ISO_CHARACTER (CODING_INHIBIT_CHARACTER_SUBSTITUTION);    \
+#define ENCODE_UNSAFE_CHARACTER(c)                             \
+  do {                                                         \
+    ENCODE_ISO_CHARACTER (CODING_REPLACEMENT_CHARACTER);       \
+    if (CHARSET_WIDTH (CHAR_CHARSET (c)) > 1)                  \
+      ENCODE_ISO_CHARACTER (CODING_REPLACEMENT_CHARACTER);     \
   } while (0)
 
 
@@ -2439,7 +2585,7 @@ encode_designation_at_bol (coding, translation_table, src, src_end, dst)
       ONE_MORE_CHAR (c);
       if (c == '\n')
        break;
-      
+
       charset = CHAR_CHARSET (c);
       reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset);
       if (reg != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION && r[reg] < 0)
@@ -2487,7 +2633,10 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
   Lisp_Object translation_table;
   Lisp_Object safe_chars;
 
-  safe_chars = coding_safe_chars (coding);
+  if (coding->flags & CODING_FLAG_ISO_SAFE)
+    coding->mode |= CODING_MODE_INHIBIT_UNENCODABLE_CHAR;
+
+  safe_chars = coding_safe_chars (coding->symbol);
 
   if (NILP (Venable_character_translation))
     translation_table = Qnil;
@@ -2554,7 +2703,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
                    }
                  else
                    {
-                     if (coding->flags & CODING_FLAG_ISO_SAFE
+                     if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR
                          && ! CODING_SAFE_CHAR_P (safe_chars, c))
                        ENCODE_UNSAFE_CHARACTER (c);
                      else
@@ -2609,7 +2758,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
                *dst++ = ISO_CODE_CR;
              CODING_SPEC_ISO_BOL (coding) = 1;
            }
-         else 
+         else
            {
              if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL)
                ENCODE_RESET_PLANE_AND_REGISTER;
@@ -2623,7 +2772,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
          *dst++ = c;
          coding->errors++;
        }
-      else if (coding->flags & CODING_FLAG_ISO_SAFE
+      else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR
               && ! CODING_SAFE_CHAR_P (safe_chars, c))
        ENCODE_UNSAFE_CHARACTER (c);
       else
@@ -2681,7 +2830,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
 
 /* Macros to decode or encode a character of Big5 in BIG5.  B1 and B2
    are the 1st and 2nd position-codes of Big5 in BIG5 coding system.
-   C1 and C2 are the 1st and 2nd position-codes of of Emacs' internal
+   C1 and C2 are the 1st and 2nd position-codes of Emacs' internal
    format.  CHARSET is `charset_big5_1' or `charset_big5_2'.  */
 
 /* Number of Big5 characters which have the same code in 1st byte.  */
@@ -2850,7 +2999,7 @@ detect_coding_utf_16 (src, src_end, multibytep)
      int multibytep;
 {
   unsigned char c1, c2;
-  /* Dummy for TWO_MORE_BYTES.  */
+  /* Dummy for ONE_MORE_BYTE_CHECK_MULTIBYTE.  */
   struct coding_system dummy_coding;
   struct coding_system *coding = &dummy_coding;
 
@@ -2918,12 +3067,6 @@ decode_coding_sjis_big5 (coding, source, destination,
                      ONE_MORE_BYTE (c2);
                      if (c2 == '\n')
                        c1 = c2;
-                     else if (coding->mode
-                              & CODING_MODE_INHIBIT_INCONSISTENT_EOL)
-                       {
-                         coding->result = CODING_FINISH_INCONSISTENT_EOL;
-                         goto label_end_of_loop;
-                       }
                      else
                        /* To process C2 again, SRC is subtracted by 1.  */
                        src--;
@@ -3032,14 +3175,14 @@ encode_coding_sjis_big5 (coding, source, destination,
 
       src_base = src;
       ONE_MORE_CHAR (c);
-      
+
       /* Now encode the character C.  */
       if (SINGLE_BYTE_CHAR_P (c))
        {
          switch (c)
            {
            case '\r':
-             if (!coding->mode & CODING_MODE_SELECTIVE_DISPLAY)
+             if (!(coding->mode & CODING_MODE_SELECTIVE_DISPLAY))
                {
                  EMIT_ONE_BYTE (c);
                  break;
@@ -3072,6 +3215,12 @@ encode_coding_sjis_big5 (coding, source, destination,
                EMIT_ONE_BYTE (c1 | 0x80);
              else if (charset == charset_latin_jisx0201)
                EMIT_ONE_BYTE (c1);
+             else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR)
+               {
+                 EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER);
+                 if (CHARSET_WIDTH (charset) > 1)
+                   EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER);
+               }
              else
                /* There's no way other than producing the internal
                   codes as is.  */
@@ -3084,6 +3233,12 @@ encode_coding_sjis_big5 (coding, source, destination,
                  ENCODE_BIG5 (charset, c1, c2, c1, c2);
                  EMIT_TWO_BYTES (c1, c2);
                }
+             else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR)
+               {
+                 EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER);
+                 if (CHARSET_WIDTH (charset) > 1)
+                   EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER);
+               }
              else
                /* There's no way other than producing the internal
                   codes as is.  */
@@ -3169,11 +3324,6 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
              ONE_MORE_BYTE (c);
              if (c != '\n')
                {
-                 if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)
-                   {
-                     coding->result = CODING_FINISH_INCONSISTENT_EOL;
-                     goto label_end_of_loop;
-                   }
                  src--;
                  c = '\r';
                }
@@ -3232,12 +3382,13 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
 static void
 encode_eol (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
-  unsigned char *src = source;
+  const unsigned char *src = source;
   unsigned char *dst = destination;
-  unsigned char *src_end = src + src_bytes;
+  const unsigned char *src_end = src + src_bytes;
   unsigned char *dst_end = dst + dst_bytes;
   Lisp_Object translation_table;
   /* SRC_BASE remembers the start position in source in each loop.
@@ -3245,7 +3396,8 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
      analyze multi-byte codes (within macro ONE_MORE_CHAR), or when
      there's not enough destination area to produce encoded codes
      (within macro EMIT_BYTES).  */
-  unsigned char *src_base;
+  const unsigned char *src_base;
+  unsigned char *tmp;
   int c;
   int selective_display = coding->mode & CODING_MODE_SELECTIVE_DISPLAY;
 
@@ -3295,13 +3447,13 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
        }
       if (coding->eol_type == CODING_EOL_CR)
        {
-         for (src = destination; src < dst; src++)
-           if (*src == '\n') *src = '\r';
+         for (tmp = destination; tmp < dst; tmp++)
+           if (*tmp == '\n') *tmp = '\r';
        }
       else if (selective_display)
        {
-         for (src = destination; src < dst; src++)
-           if (*src == '\r') *src = '\n';
+         for (tmp = destination; tmp < dst; tmp++)
+           if (*tmp == '\r') *tmp = '\n';
        }
     }
   if (coding->src_multibyte)
@@ -3357,7 +3509,7 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
 
        If the value is nil, graphic register N is never used on
        encoding.
-   
+
    sub-element[N] where N is 4 through 11: to be set in `coding->flags'
        Each value takes t or nil.  See the section ISO2022 of
        `coding.h' for more information.
@@ -3481,7 +3633,7 @@ setup_coding_system (coding_system, coding)
     }
   else
     goto label_invalid_coding_system;
-  
+
   /* If the coding system has non-nil `composition' property, enable
      composition handling.  */
   val = Fplist_get (plist, Qcomposition);
@@ -3494,7 +3646,6 @@ setup_coding_system (coding_system, coding)
       coding->type = coding_type_emacs_mule;
       coding->common_flags
        |= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK;
-      coding->composing = COMPOSITION_NO;
       if (!NILP (coding->post_read_conversion))
        coding->common_flags |= CODING_REQUIRE_DECODING_MASK;
       if (!NILP (coding->pre_write_conversion))
@@ -3576,8 +3727,8 @@ setup_coding_system (coding_system, coding)
            = CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION;
        for (i = 0; i < 4; i++)
          {
-           if (INTEGERP (flags[i])
-               && (charset = XINT (flags[i]), CHARSET_VALID_P (charset))
+           if ((INTEGERP (flags[i])
+                && (charset = XINT (flags[i]), CHARSET_VALID_P (charset)))
                || (charset = get_charset_id (flags[i])) >= 0)
              {
                CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
@@ -3595,9 +3746,9 @@ setup_coding_system (coding_system, coding)
                tail = flags[i];
 
                coding->flags |= CODING_FLAG_ISO_DESIGNATION;
-               if (INTEGERP (XCAR (tail))
-                   && (charset = XINT (XCAR (tail)),
-                       CHARSET_VALID_P (charset))
+               if ((INTEGERP (XCAR (tail))
+                    && (charset = XINT (XCAR (tail)),
+                        CHARSET_VALID_P (charset)))
                    || (charset = get_charset_id (XCAR (tail))) >= 0)
                  {
                    CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset;
@@ -3608,9 +3759,9 @@ setup_coding_system (coding_system, coding)
                tail = XCDR (tail);
                while (CONSP (tail))
                  {
-                   if (INTEGERP (XCAR (tail))
-                       && (charset = XINT (XCAR (tail)),
-                           CHARSET_VALID_P (charset))
+                   if ((INTEGERP (XCAR (tail))
+                        && (charset = XINT (XCAR (tail)),
+                            CHARSET_VALID_P (charset)))
                        || (charset = get_charset_id (XCAR (tail))) >= 0)
                      CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
                        = i;
@@ -3621,7 +3772,7 @@ setup_coding_system (coding_system, coding)
              }
            else
              CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1;
-           
+
            CODING_SPEC_ISO_DESIGNATION (coding, i)
              = CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i);
          }
@@ -3994,7 +4145,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
                  | CODING_CATEGORY_MASK_UTF_16_LE);
 
          /* Or, if C is a special latin extra code,
-            or is an ISO2022 specific control code of C1 (SS2 or SS3), 
+            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)
@@ -4037,7 +4188,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
              if (!iso2022_examined_p
                  && (priorities[i] & try & CODING_CATEGORY_MASK_ISO))
                {
-                 mask |= detect_coding_iso2022 (src, src_end);
+                 mask |= detect_coding_iso2022 (src, src_end, multibytep);
                  iso2022_examined_p = 1;
                }
              else if (priorities[i] & try & CODING_CATEGORY_MASK_SJIS)
@@ -4090,7 +4241,7 @@ detect_coding_mask (source, src_bytes, priorities, skip, multibytep)
 void
 detect_coding (coding, src, src_bytes)
      struct coding_system *coding;
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes;
 {
   unsigned int idx;
@@ -4263,7 +4414,7 @@ detect_eol_type_in_2_octet_form (source, src_bytes, skip, big_endian_p)
 void
 detect_eol (coding, src, src_bytes)
      struct coding_system *coding;
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes;
 {
   Lisp_Object val;
@@ -4313,11 +4464,13 @@ detect_eol (coding, src, src_bytes)
     {
       int src_multibyte = coding->src_multibyte;
       int dst_multibyte = coding->dst_multibyte;
+      struct composition_data *cmp_data = coding->cmp_data;
 
       setup_coding_system (XVECTOR (val)->contents[eol_type], coding);
       coding->src_multibyte = src_multibyte;
       coding->dst_multibyte = dst_multibyte;
       coding->heading_ascii = skip;
+      coding->cmp_data = cmp_data;
     }
 }
 
@@ -4353,7 +4506,11 @@ encoding_buffer_size (coding, src_bytes)
   int magnification;
 
   if (coding->type == coding_type_ccl)
-    magnification = coding->spec.ccl.encoder.buf_magnification;
+    {
+      magnification = coding->spec.ccl.encoder.buf_magnification;
+      if (coding->eol_type == CODING_EOL_CRLF)
+       magnification *= 2;
+    }
   else if (CODING_REQUIRE_ENCODING (coding))
     magnification = 3;
   else
@@ -4438,7 +4595,10 @@ ccl_coding_driver (coding, source, destination, src_bytes, dst_bytes, encodep)
       if (ccl->eol_type ==CODING_EOL_UNDECIDED)
        ccl->eol_type = CODING_EOL_LF;
       ccl->cr_consumed = coding->spec.ccl.cr_carryover;
+      ccl->eight_bit_control = coding->dst_multibyte;
     }
+  else
+    ccl->eight_bit_control = 1;
   ccl->multibyte = coding->src_multibyte;
   if (coding->spec.ccl.eight_bit_carryover[0] != 0)
     {
@@ -4586,7 +4746,7 @@ decode_eol_post_ccl (coding, ptr, bytes)
        {
          /* If the last character is CR, we can't handle it here
             because LF will be in the not-yet-decoded source text.
-            Recorded that the CR is not yet processed.  */
+            Record that the CR is not yet processed.  */
          coding->spec.ccl.cr_carryover = 1;
          coding->produced--;
          coding->produced_char--;
@@ -4679,9 +4839,12 @@ decode_eol_post_ccl (coding, ptr, bytes)
 int
 decode_coding (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
+  int extra = 0;
+
   if (coding->type == coding_type_undecided)
     detect_coding (coding, source, src_bytes);
 
@@ -4724,18 +4887,24 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
     case coding_type_ccl:
       if (coding->spec.ccl.cr_carryover)
        {
-         /* Set the CR which is not processed by the previous call of
-            decode_eol_post_ccl in DESTINATION.  */
+         /* Put the CR which was not processed by the previous call
+            of decode_eol_post_ccl in DESTINATION.  It will be
+            decoded together with the following LF by the call to
+            decode_eol_post_ccl below.  */
          *destination = '\r';
          coding->produced++;
          coding->produced_char++;
          dst_bytes--;
+         extra = coding->spec.ccl.cr_carryover;
        }
-      ccl_coding_driver (coding, source,
-                        destination + coding->spec.ccl.cr_carryover,
+      ccl_coding_driver (coding, source, destination + extra,
                         src_bytes, dst_bytes, 0);
       if (coding->eol_type != CODING_EOL_LF)
-       decode_eol_post_ccl (coding, destination, coding->produced);
+       {
+         coding->produced += extra;
+         coding->produced_char += extra;
+         decode_eol_post_ccl (coding, destination, coding->produced);
+       }
       break;
 
     default:
@@ -4750,7 +4919,7 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
   if (coding->mode & CODING_MODE_LAST_BLOCK
       && coding->result == CODING_FINISH_INSUFFICIENT_SRC)
     {
-      unsigned char *src = source + coding->consumed;
+      const unsigned char *src = source + coding->consumed;
       unsigned char *dst = destination + coding->produced;
 
       src_bytes -= coding->consumed;
@@ -4784,7 +4953,8 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
 int
 encode_coding (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
-     unsigned char *source, *destination;
+     const unsigned char *source;
+     unsigned char *destination;
      int src_bytes, dst_bytes;
 {
   coding->produced = coding->produced_char = 0;
@@ -4826,8 +4996,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
   if (coding->mode & CODING_MODE_LAST_BLOCK
       && coding->result == CODING_FINISH_INSUFFICIENT_SRC)
     {
-      unsigned char *src = source + coding->consumed;
-      unsigned char *src_end = src + src_bytes;
+      const unsigned char *src = source + coding->consumed;
       unsigned char *dst = destination + coding->produced;
 
       if (coding->type == coding_type_iso2022)
@@ -4838,7 +5007,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
        {
          int len = src_bytes - coding->consumed;
 
-         BCOPY_SHORT (source + coding->consumed, dst, len);
+         BCOPY_SHORT (src, dst, len);
          if (coding->src_multibyte)
            len = str_as_unibyte (dst, len);
          dst += len;
@@ -5048,7 +5217,7 @@ shrink_encoding_region (beg, end, coding, str)
   if (coding->type == coding_type_ccl
       || coding->eol_type == CODING_EOL_CRLF
       || coding->eol_type == CODING_EOL_CR
-      || coding->cmp_data && coding->cmp_data->used > 0)
+      || (coding->cmp_data && coding->cmp_data->used > 0))
     {
       /* We can't skip any data.  */
       return;
@@ -5102,7 +5271,7 @@ shrink_encoding_region (beg, end, coding, str)
        break;
       if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL)
        {
-         unsigned char *bol = begp; 
+         unsigned char *bol = begp;
          while (begp < endp && *begp < 0x80)
            {
              begp++;
@@ -5152,10 +5321,11 @@ static int shrink_conversion_region_threshhold = 1024;
   } while (0)
 
 static Lisp_Object
-code_convert_region_unwind (dummy)
-     Lisp_Object dummy;
+code_convert_region_unwind (arg)
+     Lisp_Object arg;
 {
   inhibit_pre_post_conversion = 0;
+  Vlast_coding_system_used = arg;
   return Qnil;
 }
 
@@ -5211,7 +5381,7 @@ coding_save_composition (coding, from, to, obj)
              else if (VECTORP (val) || STRINGP (val))
                {
                  int len = (VECTORP (val)
-                            ? XVECTOR (val)->size : XSTRING (val)->size);
+                            ? XVECTOR (val)->size : SCHARS (val));
                  int i;
                  for (i = 0; i < len; i++)
                    {
@@ -5273,6 +5443,9 @@ coding_restore_composition (coding, obj)
              int len = data[0] - 4, j;
              Lisp_Object args[MAX_COMPOSITION_COMPONENTS * 2 - 1];
 
+             if (method == COMPOSITION_WITH_RULE_ALTCHARS
+                 && len % 2 == 0)
+               len --;
              for (j = 0; j < len; j++)
                args[j] = make_number (data[4 + j]);
              components = (method == COMPOSITION_WITH_ALTCHARS
@@ -5306,6 +5479,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
      struct coding_system *coding;
 {
   int len = to - from, len_byte = to_byte - from_byte;
+  int nchars_del = 0, nbytes_del = 0;
   int require, inserted, inserted_byte;
   int head_skip, tail_skip, total_skip = 0;
   Lisp_Object saved_coding_symbol;
@@ -5394,9 +5568,9 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
          new buffer.  */
       struct buffer *prev = current_buffer;
       Lisp_Object new;
-      int count = specpdl_ptr - specpdl;
 
-      record_unwind_protect (code_convert_region_unwind, Qnil);
+      record_unwind_protect (code_convert_region_unwind,
+                            Vlast_coding_system_used);
       /* We should not call any more pre-write/post-read-conversion
          functions while this pre-write-conversion is running.  */
       inhibit_pre_post_conversion = 1;
@@ -5429,7 +5603,15 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
     }
 
   if (replace)
-    deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
+    {
+      if (! EQ (current_buffer->undo_list, Qt))
+       deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
+      else
+       {
+         nchars_del = to - from;
+         nbytes_del = to_byte - from_byte;
+       }
+    }
 
   if (coding->composing != COMPOSITION_DISABLED)
     {
@@ -5518,7 +5700,11 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       if (encodep)
        result = encode_coding (coding, src, dst, len_byte, 0);
       else
-       result = decode_coding (coding, src, dst, len_byte, 0);
+       {
+         if (coding->composing != COMPOSITION_DISABLED)
+           coding->cmp_data->char_offset = from + inserted;
+         result = decode_coding (coding, src, dst, len_byte, 0);
+       }
 
       /* The buffer memory is now:
         +--------+-------converted-text----+--+------original-text----+---+
@@ -5601,7 +5787,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
            coding->symbol = XVECTOR (eol_type)->contents[CODING_EOL_LF];
          else
            coding->symbol = saved_coding_symbol;
-         
+
          continue;
        }
       if (len_byte <= 0)
@@ -5619,7 +5805,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
          if (multibyte_p)
            {
              unsigned char *start = dst;
-             
+
              inserted += len_byte;
              while (len_byte--)
                {
@@ -5662,9 +5848,19 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
                REQUIRE + LEN_BYTE = LEN_BYTE * (NEW / ORIG)
                REQUIRE = LEN_BYTE * (NEW - ORIG) / ORIG
             Here, we are sure that NEW >= ORIG.  */
-         float ratio = coding->produced - coding->consumed;
-         ratio /= coding->consumed;
-         require = len_byte * ratio;
+         float ratio;
+
+         if (coding->produced <= coding->consumed)
+           {
+             /* This happens because of CCL-based coding system with
+                eol-type CRLF.  */
+             require = 0;
+           }
+         else
+           {
+             ratio = (coding->produced - coding->consumed) / coding->consumed;
+             require = len_byte * ratio;
+           }
          first = 0;
        }
       if ((src - dst) < (require + 2000))
@@ -5702,7 +5898,7 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       inserted_byte = str_to_multibyte (GPT_ADDR, GAP_SIZE, inserted_byte);
     }
 
-  /* If we shrank the conversion area, adjust it now.  */ 
+  /* If we shrank the conversion area, adjust it now.  */
   if (total_skip > 0)
     {
       if (tail_skip > 0)
@@ -5717,7 +5913,11 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
     }
 
   prev_Z = Z;
-  adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte);
+  if (! EQ (current_buffer->undo_list, Qt))
+    adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte);
+  else
+    adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del,
+                                inserted, inserted_byte);
   inserted = Z - prev_Z;
 
   if (!encodep && coding->cmp_data && coding->cmp_data->used)
@@ -5728,20 +5928,25 @@ code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
       && ! encodep && ! NILP (coding->post_read_conversion))
     {
       Lisp_Object val;
-      int count = specpdl_ptr - specpdl;
+      Lisp_Object saved_coding_system;
 
       if (from != PT)
        TEMP_SET_PT_BOTH (from, from_byte);
       prev_Z = Z;
-      record_unwind_protect (code_convert_region_unwind, Qnil);
+      record_unwind_protect (code_convert_region_unwind,
+                            Vlast_coding_system_used);
+      saved_coding_system = Vlast_coding_system_used;
+      Vlast_coding_system_used = coding->symbol;
       /* We should not call any more pre-write/post-read-conversion
          functions while this post-read-conversion is running.  */
       inhibit_pre_post_conversion = 1;
       val = call1 (coding->post_read_conversion, make_number (inserted));
       inhibit_pre_post_conversion = 0;
+      coding->symbol = Vlast_coding_system_used;
+      Vlast_coding_system_used = saved_coding_system;
       /* Discard the unwind protect.  */
       specpdl_ptr--;
-      CHECK_NUMBER (val, 0);
+      CHECK_NUMBER (val);
       inserted += Z - prev_Z;
     }
 
@@ -5776,32 +5981,53 @@ run_pre_post_conversion_on_str (str, coding, encodep)
      struct coding_system *coding;
      int encodep;
 {
-  int count = specpdl_ptr - specpdl;
-  struct gcpro gcpro1;
+  int count = SPECPDL_INDEX ();
+  struct gcpro gcpro1, gcpro2;
   int multibyte = STRING_MULTIBYTE (str);
+  Lisp_Object buffer;
+  struct buffer *buf;
+  Lisp_Object old_deactivate_mark;
 
   record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
-  record_unwind_protect (code_convert_region_unwind, Qnil);
-  GCPRO1 (str);
-  temp_output_buffer_setup (" *code-converting-work*");
-  set_buffer_internal (XBUFFER (Vstandard_output));
+  record_unwind_protect (code_convert_region_unwind,
+                        Vlast_coding_system_used);
+  /* It is not crucial to specbind this.  */
+  old_deactivate_mark = Vdeactivate_mark;
+  GCPRO2 (str, old_deactivate_mark);
+
+  buffer = Fget_buffer_create (build_string (" *code-converting-work*"));
+  buf = XBUFFER (buffer);
+
+  delete_all_overlays (buf);
+  buf->directory = current_buffer->directory;
+  buf->read_only = Qnil;
+  buf->filename = Qnil;
+  buf->undo_list = Qt;
+  eassert (buf->overlays_before == NULL);
+  eassert (buf->overlays_after == NULL);
+
+  set_buffer_internal (buf);
   /* We must insert the contents of STR as is without
      unibyte<->multibyte conversion.  For that, we adjust the
      multibyteness of the working buffer to that of STR.  */
   Ferase_buffer ();
-  current_buffer->enable_multibyte_characters = multibyte ? Qt : Qnil;
+  buf->enable_multibyte_characters = multibyte ? Qt : Qnil;
+
   insert_from_string (str, 0, 0,
-                     XSTRING (str)->size, STRING_BYTES (XSTRING (str)), 0);
+                     SCHARS (str), SBYTES (str), 0);
   UNGCPRO;
   inhibit_pre_post_conversion = 1;
   if (encodep)
     call2 (coding->pre_write_conversion, make_number (BEG), make_number (Z));
   else
     {
+      Vlast_coding_system_used = coding->symbol;
       TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
       call1 (coding->post_read_conversion, make_number (Z - BEG));
+      coding->symbol = Vlast_coding_system_used;
     }
   inhibit_pre_post_conversion = 0;
+  Vdeactivate_mark = old_deactivate_mark;
   str = make_buffer_string (BEG, Z, 1);
   return unbind_to (count, str);
 }
@@ -5815,7 +6041,6 @@ decode_coding_string (str, coding, nocopy)
   int len;
   struct conversion_buffer buf;
   int from, to_byte;
-  struct gcpro gcpro1;
   Lisp_Object saved_coding_symbol;
   int result;
   int require_decoding;
@@ -5824,7 +6049,7 @@ decode_coding_string (str, coding, nocopy)
   int consumed, consumed_char, produced, produced_char;
 
   from = 0;
-  to_byte = STRING_BYTES (XSTRING (str));
+  to_byte = SBYTES (str);
 
   saved_coding_symbol = coding->symbol;
   coding->src_multibyte = STRING_MULTIBYTE (str);
@@ -5834,7 +6059,7 @@ decode_coding_string (str, coding, nocopy)
       /* See the comments in code_convert_region.  */
       if (coding->type == coding_type_undecided)
        {
-         detect_coding (coding, XSTRING (str)->data, to_byte);
+         detect_coding (coding, SDATA (str), to_byte);
          if (coding->type == coding_type_undecided)
            {
              coding->type = coding_type_emacs_mule;
@@ -5849,7 +6074,7 @@ decode_coding_string (str, coding, nocopy)
          && coding->type != coding_type_ccl)
        {
          saved_coding_symbol = coding->symbol;
-         detect_eol (coding, XSTRING (str)->data, to_byte);
+         detect_eol (coding, SDATA (str), to_byte);
          if (coding->eol_type == CODING_EOL_UNDECIDED)
            coding->eol_type = CODING_EOL_LF;
          /* We had better recover the original eol format if we
@@ -5868,7 +6093,7 @@ decode_coding_string (str, coding, nocopy)
     {
       /* Decoding routines expect the source text to be unibyte.  */
       str = Fstring_as_unibyte (str);
-      to_byte = STRING_BYTES (XSTRING (str));
+      to_byte = SBYTES (str);
       nocopy = 1;
       coding->src_multibyte = 0;
     }
@@ -5876,24 +6101,26 @@ decode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (require_decoding && coding->type != coding_type_ccl)
     {
-      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
+      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str),
                                0);
       if (from == to_byte)
        require_decoding = 0;
-      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
+      shrinked_bytes = from + (SBYTES (str) - to_byte);
     }
 
-  if (!require_decoding)
+  if (!require_decoding
+      && !(SYMBOLP (coding->post_read_conversion)
+          && !NILP (Ffboundp (coding->post_read_conversion))))
     {
-      coding->consumed = STRING_BYTES (XSTRING (str));
-      coding->consumed_char = XSTRING (str)->size;
+      coding->consumed = SBYTES (str);
+      coding->consumed_char = SCHARS (str);
       if (coding->dst_multibyte)
        {
          str = Fstring_as_multibyte (str);
          nocopy = 1;
        }
-      coding->produced = STRING_BYTES (XSTRING (str));
-      coding->produced_char = XSTRING (str)->size;
+      coding->produced = SBYTES (str);
+      coding->produced_char = SCHARS (str);
       return (nocopy ? str : Fcopy_sequence (str));
     }
 
@@ -5905,7 +6132,7 @@ decode_coding_string (str, coding, nocopy)
   consumed = consumed_char = produced = produced_char = 0;
   while (1)
     {
-      result = decode_coding (coding, XSTRING (str)->data + from + consumed,
+      result = decode_coding (coding, SDATA (str) + from + consumed,
                              buf.data + produced, to_byte - from - consumed,
                              buf.size - produced);
       consumed += coding->consumed;
@@ -5946,7 +6173,7 @@ decode_coding_string (str, coding, nocopy)
                }
              produced += num_eol;
              produced_char += num_eol;
-           } 
+           }
          /* Suppress eol-format conversion in the further conversion.  */
          coding->eol_type = CODING_EOL_LF;
 
@@ -5974,12 +6201,12 @@ decode_coding_string (str, coding, nocopy)
   else
     newstr = make_uninit_string (produced + shrinked_bytes);
   if (from > 0)
-    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
-  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+    STRING_COPYIN (newstr, 0, SDATA (str), from);
+  STRING_COPYIN (newstr, from, buf.data, produced);
   if (shrinked_bytes > from)
-    bcopy (XSTRING (str)->data + to_byte,
-          XSTRING (newstr)->data + from + produced,
-          shrinked_bytes - from);
+    STRING_COPYIN (newstr, from + produced,
+                  SDATA (str) + to_byte,
+                  shrinked_bytes - from);
   free_conversion_buffer (&buf);
 
   if (coding->cmp_data && coding->cmp_data->used)
@@ -6012,8 +6239,8 @@ encode_coding_string (str, coding, nocopy)
     str = run_pre_post_conversion_on_str (str, coding, 1);
 
   from = 0;
-  to = XSTRING (str)->size;
-  to_byte = STRING_BYTES (XSTRING (str));
+  to = SCHARS (str);
+  to_byte = SBYTES (str);
 
   /* Encoding routines determine the multibyteness of the source text
      by coding->src_multibyte.  */
@@ -6021,15 +6248,15 @@ encode_coding_string (str, coding, nocopy)
   coding->dst_multibyte = 0;
   if (! CODING_REQUIRE_ENCODING (coding))
     {
-      coding->consumed = STRING_BYTES (XSTRING (str));
-      coding->consumed_char = XSTRING (str)->size;
+      coding->consumed = SBYTES (str);
+      coding->consumed_char = SCHARS (str);
       if (STRING_MULTIBYTE (str))
        {
          str = Fstring_as_unibyte (str);
          nocopy = 1;
        }
-      coding->produced = STRING_BYTES (XSTRING (str));
-      coding->produced_char = XSTRING (str)->size;
+      coding->produced = SBYTES (str);
+      coding->produced_char = SCHARS (str);
       return (nocopy ? str : Fcopy_sequence (str));
     }
 
@@ -6039,11 +6266,11 @@ encode_coding_string (str, coding, nocopy)
   /* Try to skip the heading and tailing ASCIIs.  */
   if (coding->type != coding_type_ccl)
     {
-      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
+      SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str),
                                1);
       if (from == to_byte)
        return (nocopy ? str : Fcopy_sequence (str));
-      shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
+      shrinked_bytes = from + (SBYTES (str) - to_byte);
     }
 
   len = encoding_buffer_size (coding, to_byte - from);
@@ -6052,7 +6279,7 @@ encode_coding_string (str, coding, nocopy)
   consumed = consumed_char = produced = produced_char = 0;
   while (1)
     {
-      result = encode_coding (coding, XSTRING (str)->data + from + consumed,
+      result = encode_coding (coding, SDATA (str) + from + consumed,
                              buf.data + produced, to_byte - from - consumed,
                              buf.size - produced);
       consumed += coding->consumed;
@@ -6074,12 +6301,12 @@ encode_coding_string (str, coding, nocopy)
 
   newstr = make_uninit_string (produced + shrinked_bytes);
   if (from > 0)
-    bcopy (XSTRING (str)->data, XSTRING (newstr)->data, from);
-  bcopy (buf.data, XSTRING (newstr)->data + from, produced);
+    STRING_COPYIN (newstr, 0, SDATA (str), from);
+  STRING_COPYIN (newstr, from, buf.data, produced);
   if (shrinked_bytes > from)
-    bcopy (XSTRING (str)->data + to_byte,
-          XSTRING (newstr)->data + from + produced,
-          shrinked_bytes - from);
+    STRING_COPYIN (newstr, from + produced,
+                  SDATA (str) + to_byte,
+                  shrinked_bytes - from);
 
   free_conversion_buffer (&buf);
   coding_free_composition_data (coding);
@@ -6092,10 +6319,10 @@ encode_coding_string (str, coding, nocopy)
 /*** 8. Emacs Lisp library functions ***/
 
 DEFUN ("coding-system-p", Fcoding_system_p, Scoding_system_p, 1, 1, 0,
-  "Return t if OBJECT is nil or a coding-system.\n\
-See the documentation of `make-coding-system' for information\n\
-about coding-system objects.")
-  (obj)
+       doc: /* Return t if OBJECT is nil or a coding-system.
+See the documentation of `make-coding-system' for information
+about coding-system objects.  */)
+     (obj)
      Lisp_Object obj;
 {
   if (NILP (obj))
@@ -6110,8 +6337,8 @@ about coding-system objects.")
 
 DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system,
        Sread_non_nil_coding_system, 1, 1, 0,
-  "Read a coding system from the minibuffer, prompting with string PROMPT.")
-  (prompt)
+       doc: /* Read a coding system from the minibuffer, prompting with string PROMPT.  */)
+     (prompt)
      Lisp_Object prompt;
 {
   Lisp_Object val;
@@ -6120,35 +6347,35 @@ DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system,
       val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil,
                              Qt, Qnil, Qcoding_system_history, Qnil, Qnil);
     }
-  while (XSTRING (val)->size == 0);
+  while (SCHARS (val) == 0);
   return (Fintern (val, Qnil));
 }
 
 DEFUN ("read-coding-system", Fread_coding_system, Sread_coding_system, 1, 2, 0,
-  "Read a coding system from the minibuffer, prompting with string PROMPT.\n\
-If the user enters null input, return second argument DEFAULT-CODING-SYSTEM.")
-  (prompt, default_coding_system)
+       doc: /* Read a coding system from the minibuffer, prompting with string PROMPT.
+If the user enters null input, return second argument DEFAULT-CODING-SYSTEM.  */)
+     (prompt, default_coding_system)
      Lisp_Object prompt, default_coding_system;
 {
   Lisp_Object val;
   if (SYMBOLP (default_coding_system))
-    XSETSTRING (default_coding_system, XSYMBOL (default_coding_system)->name);
+    default_coding_system = SYMBOL_NAME (default_coding_system);
   val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil,
                          Qt, Qnil, Qcoding_system_history,
                          default_coding_system, Qnil);
-  return (XSTRING (val)->size == 0 ? Qnil : Fintern (val, Qnil));
+  return (SCHARS (val) == 0 ? Qnil : Fintern (val, Qnil));
 }
 
 DEFUN ("check-coding-system", Fcheck_coding_system, Scheck_coding_system,
        1, 1, 0,
-  "Check validity of CODING-SYSTEM.\n\
-If valid, return CODING-SYSTEM, else signal a `coding-system-error' error.\n\
-It is valid if it is a symbol with a non-nil `coding-system' property.\n\
-The value of property should be a vector of length 5.")
-  (coding_system)
+       doc: /* Check validity of CODING-SYSTEM.
+If valid, return CODING-SYSTEM, else signal a `coding-system-error' error.
+It is valid if it is a symbol with a non-nil `coding-system' property.
+The value of property should be a vector of length 5.  */)
+     (coding_system)
      Lisp_Object coding_system;
 {
-  CHECK_SYMBOL (coding_system, 0);
+  CHECK_SYMBOL (coding_system);
   if (!NILP (Fcoding_system_p (coding_system)))
     return coding_system;
   while (1)
@@ -6157,7 +6384,7 @@ The value of property should be a vector of length 5.")
 \f
 Lisp_Object
 detect_coding_system (src, src_bytes, highest, multibytep)
-     unsigned char *src;
+     const unsigned char *src;
      int src_bytes, highest;
      int multibytep;
 {
@@ -6216,28 +6443,31 @@ detect_coding_system (src, src_bytes, highest, multibytep)
        }
     }
   return (highest ? XCAR (val) : val);
-}  
+}
 
 DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region,
        2, 3, 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\
-\n\
-If only ASCII characters are found, it returns a list of single element\n\
-`undecided' or its subsidiary coding system according to a detected\n\
-end-of-line format.\n\
-\n\
-If optional argument HIGHEST is non-nil, return the coding system of\n\
-highest priority.")
-  (start, end, highest)
+       doc: /* Detect how the byte sequence in the region is encoded.
+Return a list of possible coding systems used on decoding a byte
+sequence containing the bytes in the region between START and END when
+the coding system `undecided' is specified.  The list is ordered by
+priority decided in the current language environment.
+
+If only ASCII characters are found, it returns a list of single element
+`undecided' or its subsidiary coding system according to a detected
+end-of-line format.
+
+If optional argument HIGHEST is non-nil, return the coding system of
+highest priority.  */)
+     (start, end, highest)
      Lisp_Object start, end, highest;
 {
   int from, to;
   int from_byte, to_byte;
   int include_anchor_byte = 0;
 
-  CHECK_NUMBER_COERCE_MARKER (start, 0);
-  CHECK_NUMBER_COERCE_MARKER (end, 1);
+  CHECK_NUMBER_COERCE_MARKER (start);
+  CHECK_NUMBER_COERCE_MARKER (end);
 
   validate_region (&start, &end);
   from = XINT (start), to = XINT (end);
@@ -6250,7 +6480,7 @@ highest priority.")
      the detecting source.  Then code detectors can handle the tailing
      byte sequence more accurately.
 
-     Fix me: This is not an perfect solution.  It is better that we
+     Fix me: This is not a perfect solution.  It is better that we
      add one more argument, say LAST_BLOCK, to all detect_coding_XXX.
   */
   if (to == Z || (to == GPT && GAP_SIZE > 0))
@@ -6264,51 +6494,37 @@ highest priority.")
 
 DEFUN ("detect-coding-string", Fdetect_coding_string, Sdetect_coding_string,
        1, 2, 0,
-  "Detect coding system of the text in STRING.\n\
-Return a list of possible coding systems ordered by priority.\n\
-\n\
-If only ASCII characters are found, it returns a list of single element\n\
-`undecided' or its subsidiary coding system according to a detected\n\
-end-of-line format.\n\
-\n\
-If optional argument HIGHEST is non-nil, return the coding system of\n\
-highest priority.")
-  (string, highest)
+       doc: /* Detect how the byte sequence in STRING is encoded.
+Return a list of possible coding systems used on decoding a byte
+sequence containing the bytes in STRING when the coding system
+`undecided' is specified.  The list is ordered by priority decided in
+the current language environment.
+
+If only ASCII characters are found, it returns a list of single element
+`undecided' or its subsidiary coding system according to a detected
+end-of-line format.
+
+If optional argument HIGHEST is non-nil, return the coding system of
+highest priority.  */)
+     (string, highest)
      Lisp_Object string, highest;
 {
-  CHECK_STRING (string, 0);
+  CHECK_STRING (string);
 
-  return detect_coding_system (XSTRING (string)->data,
+  return detect_coding_system (SDATA (string),
                               /* "+ 1" is to include the anchor byte
                                  `\0'.  With this, code detectors can
                                  handle the tailing bytes more
                                  accurately.  */
-                              STRING_BYTES (XSTRING (string)) + 1,
+                              SBYTES (string) + 1,
                               !NILP (highest),
                               STRING_MULTIBYTE (string));
 }
 
-/* Return an intersection of lists L1 and L2.  */
-
-static Lisp_Object
-intersection (l1, l2)
-     Lisp_Object l1, l2;
-{
-  Lisp_Object val;
-
-  for (val = Qnil; CONSP (l1); l1 = XCDR (l1))
-    {
-      if (!NILP (Fmemq (XCAR (l1), l2)))
-       val = Fcons (XCAR (l1), val);
-    }
-  return val;
-}
-
-
 /*  Subroutine for Fsafe_coding_systems_region_internal.
 
     Return a list of coding systems that safely encode the multibyte
-    text between P and PEND.  SAFE_CODINGS, if non-nil, is a list of
+    text between P and PEND.  SAFE_CODINGS, if non-nil, is an alist of
     possible coding systems.  If it is nil, it means that we have not
     yet found any coding systems.
 
@@ -6324,8 +6540,9 @@ find_safe_codings (p, pend, safe_codings, work_table, single_byte_char_found)
      Lisp_Object safe_codings, work_table;
      int *single_byte_char_found;
 {
-  int c, len, idx;
-  Lisp_Object val;
+  int c, len;
+  Lisp_Object val, ch;
+  Lisp_Object prev, tail;
 
   while (p < pend)
     {
@@ -6337,57 +6554,123 @@ find_safe_codings (p, pend, safe_codings, work_table, single_byte_char_found)
       if (SINGLE_BYTE_CHAR_P (c))
        *single_byte_char_found = 1;
       if (NILP (safe_codings))
+       /* Already all coding systems are excluded.  But, we can't
+          terminate the loop here because non-ASCII single-byte char
+          must be found.  */
        continue;
       /* Check the safe coding systems for C.  */
-      val = char_table_ref_and_index (work_table, c, &idx);
+      ch = make_number (c);
+      val = Faref (work_table, ch);
       if (EQ (val, Qt))
        /* This element was already checked.  Ignore it.  */
        continue;
       /* Remember that we checked this element.  */
-      CHAR_TABLE_SET (work_table, make_number (idx), Qt);
+      Faset (work_table, ch, Qt);
 
-      /* If there are some safe coding systems for C and we have
-        already found the other set of coding systems for the
-        different characters, get the intersection of them.  */
-      if (!EQ (safe_codings, Qt) && !NILP (val))
-       val = intersection (safe_codings, val);
-      safe_codings = val;
+      for (prev = tail = safe_codings; CONSP (tail); tail = XCDR (tail))
+       {
+         Lisp_Object elt, translation_table, hash_table, accept_latin_extra;
+         int encodable;
+
+         elt = XCAR (tail);
+         if (CONSP (XCDR (elt)))
+           {
+             /* This entry has this format now:
+                ( CODING SAFE-CHARS TRANSLATION-TABLE HASH-TABLE
+                         ACCEPT-LATIN-EXTRA ) */
+             val = XCDR (elt);
+             encodable = ! NILP (Faref (XCAR (val), ch));
+             if (! encodable)
+               {
+                 val = XCDR (val);
+                 translation_table = XCAR (val);
+                 hash_table = XCAR (XCDR (val));
+                 accept_latin_extra = XCAR (XCDR (XCDR (val)));
+               }
+           }
+         else
+           {
+             /* This entry has this format now: ( CODING . SAFE-CHARS) */
+             encodable = ! NILP (Faref (XCDR (elt), ch));
+             if (! encodable)
+               {
+                 /* Transform the format to:
+                    ( CODING SAFE-CHARS TRANSLATION-TABLE HASH-TABLE
+                      ACCEPT-LATIN-EXTRA )  */
+                 val = Fget (XCAR (elt), Qcoding_system);
+                 translation_table
+                   = Fplist_get (AREF (val, 3),
+                                 Qtranslation_table_for_encode);
+                 if (SYMBOLP (translation_table))
+                   translation_table = Fget (translation_table,
+                                             Qtranslation_table);
+                 hash_table
+                   = (CHAR_TABLE_P (translation_table)
+                      ? XCHAR_TABLE (translation_table)->extras[1]
+                      : Qnil);
+                 accept_latin_extra
+                   = ((EQ (AREF (val, 0), make_number (2))
+                       && VECTORP (AREF (val, 4)))
+                      ? AREF (AREF (val, 4), 16)
+                      : Qnil);
+                 XSETCAR (tail, list5 (XCAR (elt), XCDR (elt),
+                                       translation_table, hash_table,
+                                       accept_latin_extra));
+               }
+           }
+             
+         if (! encodable
+             && ((CHAR_TABLE_P (translation_table)
+                  && ! NILP (Faref (translation_table, ch)))
+                 || (HASH_TABLE_P (hash_table)
+                     && ! NILP (Fgethash (ch, hash_table, Qnil)))
+                 || (SINGLE_BYTE_CHAR_P (c)
+                     && ! NILP (accept_latin_extra)
+                     && VECTORP (Vlatin_extra_code_table)
+                     && ! NILP (AREF (Vlatin_extra_code_table, c)))))
+           encodable = 1;
+         if (encodable)
+           prev = tail;
+         else
+           {
+             /* Exclude this coding system from SAFE_CODINGS.  */
+             if (EQ (tail, safe_codings))
+               safe_codings = XCDR (safe_codings);
+             else
+               XSETCDR (prev, XCDR (tail));
+           }
+       }
     }
   return safe_codings;
 }
 
-
-/* Return a list of coding systems that safely encode the text between
-   START and END.  If the text contains only ASCII or is unibyte,
-   return t.  */
-
 DEFUN ("find-coding-systems-region-internal",
        Ffind_coding_systems_region_internal,
        Sfind_coding_systems_region_internal, 2, 2, 0,
-  "Internal use only.")
-  (start, end)
+       doc: /* Internal use only.  */)
+     (start, end)
      Lisp_Object start, end;
 {
   Lisp_Object work_table, safe_codings;
   int non_ascii_p = 0;
   int single_byte_char_found = 0;
-  unsigned char *p1, *p1end, *p2, *p2end, *p;
+  const unsigned char *p1, *p1end, *p2, *p2end, *p;
 
   if (STRINGP (start))
     {
       if (!STRING_MULTIBYTE (start))
        return Qt;
-      p1 = XSTRING (start)->data, p1end = p1 + STRING_BYTES (XSTRING (start));
+      p1 = SDATA (start), p1end = p1 + SBYTES (start);
       p2 = p2end = p1end;
-      if (XSTRING (start)->size != STRING_BYTES (XSTRING (start)))
+      if (SCHARS (start) != SBYTES (start))
        non_ascii_p = 1;
     }
   else
     {
       int from, to, stop;
 
-      CHECK_NUMBER_COERCE_MARKER (start, 0);
-      CHECK_NUMBER_COERCE_MARKER (end, 1);
+      CHECK_NUMBER_COERCE_MARKER (start);
+      CHECK_NUMBER_COERCE_MARKER (end);
       if (XINT (start) < BEG || XINT (end) > Z || XINT (start) > XINT (end))
        args_out_of_range (start, end);
       if (NILP (current_buffer->enable_multibyte_characters))
@@ -6412,36 +6695,182 @@ DEFUN ("find-coding-systems-region-internal",
       for (p = p1; p < p1end && ASCII_BYTE_P (*p); p++);
       if (p == p1end)
        {
-         for (p = p2; p < p2end && ASCII_BYTE_P (*p); p++);      
+         for (p = p2; p < p2end && ASCII_BYTE_P (*p); p++);
          if (p == p2end)
            return Qt;
        }
     }
 
   /* The text contains non-ASCII characters.  */
-  work_table = Fcopy_sequence (Vchar_coding_system_table);
-  safe_codings = find_safe_codings (p1, p1end, Qt, work_table,
+
+  work_table = Fmake_char_table (Qchar_coding_system, Qnil);
+  safe_codings = Fcopy_sequence (XCDR (Vcoding_system_safe_chars));
+
+  safe_codings = find_safe_codings (p1, p1end, safe_codings, work_table,
                                    &single_byte_char_found);
   if (p2 < p2end)
     safe_codings = find_safe_codings (p2, p2end, safe_codings, work_table,
                                      &single_byte_char_found);
+  if (EQ (safe_codings, XCDR (Vcoding_system_safe_chars)))
+    safe_codings = Qt;
+  else
+    {
+      /* Turn safe_codings to a list of coding systems... */
+      Lisp_Object val;
+
+      if (single_byte_char_found)
+       /* ... and append these for eight-bit chars.  */
+       val = Fcons (Qraw_text,
+                    Fcons (Qemacs_mule, Fcons (Qno_conversion, Qnil)));
+      else
+       /* ... and append generic coding systems.  */
+       val = Fcopy_sequence (XCAR (Vcoding_system_safe_chars));
+
+      for (; CONSP (safe_codings); safe_codings = XCDR (safe_codings))
+       val = Fcons (XCAR (XCAR (safe_codings)), val);
+      safe_codings = val;
+    }
+
+  return safe_codings;
+}
+
+
+/* Search from position POS for such characters that are unencodable
+   accoding to SAFE_CHARS, and return a list of their positions.  P
+   points where in the memory the character at POS exists.  Limit the
+   search at PEND or when Nth unencodable characters are found.
+
+   If SAFE_CHARS is a char table, an element for an unencodable
+   character is nil.
+
+   If SAFE_CHARS is nil, all non-ASCII characters are unencodable.
+
+   Otherwise, SAFE_CHARS is t, and only eight-bit-contrl and
+   eight-bit-graphic characters are unencodable.  */
 
-  if (EQ (safe_codings, Qt))
-    ; /* Nothing to be done.  */
-  else if (!single_byte_char_found)
+static Lisp_Object
+unencodable_char_position (safe_chars, pos, p, pend, n)
+     Lisp_Object safe_chars;
+     int pos;
+     unsigned char *p, *pend;
+     int n;
+{
+  Lisp_Object pos_list;
+
+  pos_list = Qnil;
+  while (p < pend)
     {
-      /* Append generic coding systems.  */
-      Lisp_Object args[2];
-      args[0] = safe_codings;
-      args[1] = Fchar_table_extra_slot (Vchar_coding_system_table,
-                                       make_number (0));
-      safe_codings = Fappend (2, args);
+      int len;
+      int c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, len);
+
+      if (c >= 128
+         && (CHAR_TABLE_P (safe_chars)
+             ? NILP (CHAR_TABLE_REF (safe_chars, c))
+             : (NILP (safe_chars) || c < 256)))
+       {
+         pos_list = Fcons (make_number (pos), pos_list);
+         if (--n <= 0)
+           break;
+       }
+      pos++;
+      p += len;
+    }
+  return Fnreverse (pos_list);
+}
+
+
+DEFUN ("unencodable-char-position", Funencodable_char_position,
+       Sunencodable_char_position, 3, 5, 0,
+       doc: /*
+Return position of first un-encodable character in a region.
+START and END specfiy the region and CODING-SYSTEM specifies the
+encoding to check.  Return nil if CODING-SYSTEM does encode the region.
+
+If optional 4th argument COUNT is non-nil, it specifies at most how
+many un-encodable characters to search.  In this case, the value is a
+list of positions.
+
+If optional 5th argument STRING is non-nil, it is a string to search
+for un-encodable characters.  In that case, START and END are indexes
+to the string.  */)
+     (start, end, coding_system, count, string)
+     Lisp_Object start, end, coding_system, count, string;
+{
+  int n;
+  Lisp_Object safe_chars;
+  struct coding_system coding;
+  Lisp_Object positions;
+  int from, to;
+  unsigned char *p, *pend;
+
+  if (NILP (string))
+    {
+      validate_region (&start, &end);
+      from = XINT (start);
+      to = XINT (end);
+      if (NILP (current_buffer->enable_multibyte_characters))
+       return Qnil;
+      p = CHAR_POS_ADDR (from);
+      if (to == GPT)
+       pend = GPT_ADDR;
+      else
+       pend = CHAR_POS_ADDR (to);
     }
   else
-    safe_codings = Fcons (Qraw_text,
-                         Fcons (Qemacs_mule,
-                                Fcons (Qno_conversion, safe_codings)));
-  return safe_codings;
+    {
+      CHECK_STRING (string);
+      CHECK_NATNUM (start);
+      CHECK_NATNUM (end);
+      from = XINT (start);
+      to = XINT (end);
+      if (from > to
+         || to > SCHARS (string))
+       args_out_of_range_3 (string, start, end);
+      if (! STRING_MULTIBYTE (string))
+       return Qnil;
+      p = SDATA (string) + string_char_to_byte (string, from);
+      pend = SDATA (string) + string_char_to_byte (string, to);
+    }
+
+  setup_coding_system (Fcheck_coding_system (coding_system), &coding);
+
+  if (NILP (count))
+    n = 1;
+  else
+    {
+      CHECK_NATNUM (count);
+      n = XINT (count);
+    }
+
+  if (coding.type == coding_type_no_conversion
+      || coding.type == coding_type_raw_text)
+    return Qnil;
+
+  if (coding.type == coding_type_undecided)
+    safe_chars = Qnil;
+  else
+    safe_chars = coding_safe_chars (coding_system);
+
+  if (STRINGP (string)
+      || from >= GPT || to <= GPT)
+    positions = unencodable_char_position (safe_chars, from, p, pend, n);
+  else
+    {
+      Lisp_Object args[2];
+
+      args[0] = unencodable_char_position (safe_chars, from, p, GPT_ADDR, n);
+      n -= XINT (Flength (args[0]));
+      if (n <= 0)
+       positions = args[0];
+      else
+       {
+         args[1] = unencodable_char_position (safe_chars, GPT, GAP_END_ADDR,
+                                              pend, n);
+         positions = Fappend (2, args);
+       }
+    }
+
+  return  (NILP (count) ? Fcar (positions) : positions);
 }
 
 
@@ -6453,9 +6882,9 @@ code_convert_region1 (start, end, coding_system, encodep)
   struct coding_system coding;
   int from, to;
 
-  CHECK_NUMBER_COERCE_MARKER (start, 0);
-  CHECK_NUMBER_COERCE_MARKER (end, 1);
-  CHECK_SYMBOL (coding_system, 2);
+  CHECK_NUMBER_COERCE_MARKER (start);
+  CHECK_NUMBER_COERCE_MARKER (end);
+  CHECK_SYMBOL (coding_system);
 
   validate_region (&start, &end);
   from = XFASTINT (start);
@@ -6465,7 +6894,7 @@ code_convert_region1 (start, end, coding_system, encodep)
     return make_number (to - from);
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
   coding.src_multibyte = coding.dst_multibyte
@@ -6478,14 +6907,14 @@ code_convert_region1 (start, end, coding_system, encodep)
 
 DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region,
        3, 3, "r\nzCoding system: ",
-  "Decode the current region from the specified coding system.\n\
-When called from a program, takes three arguments:\n\
-START, END, and CODING-SYSTEM.  START and END are buffer positions.\n\
-This function sets `last-coding-system-used' to the precise coding system\n\
-used (which may be different from CODING-SYSTEM if CODING-SYSTEM is\n\
-not fully specified.)\n\
-It returns the length of the decoded text.")
-  (start, end, coding_system)
+       doc: /* Decode the current region from the specified coding system.
+When called from a program, takes three arguments:
+START, END, and CODING-SYSTEM.  START and END are buffer positions.
+This function sets `last-coding-system-used' to the precise coding system
+used (which may be different from CODING-SYSTEM if CODING-SYSTEM is
+not fully specified.)
+It returns the length of the decoded text.  */)
+     (start, end, coding_system)
      Lisp_Object start, end, coding_system;
 {
   return code_convert_region1 (start, end, coding_system, 0);
@@ -6493,14 +6922,14 @@ It returns the length of the decoded text.")
 
 DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region,
        3, 3, "r\nzCoding system: ",
-  "Encode the current region into the specified coding system.\n\
-When called from a program, takes three arguments:\n\
-START, END, and CODING-SYSTEM.  START and END are buffer positions.\n\
-This function sets `last-coding-system-used' to the precise coding system\n\
-used (which may be different from CODING-SYSTEM if CODING-SYSTEM is\n\
-not fully specified.)\n\
-It returns the length of the encoded text.")
-  (start, end, coding_system)
+       doc: /* Encode the current region into the specified coding system.
+When called from a program, takes three arguments:
+START, END, and CODING-SYSTEM.  START and END are buffer positions.
+This function sets `last-coding-system-used' to the precise coding system
+used (which may be different from CODING-SYSTEM if CODING-SYSTEM is
+not fully specified.)
+It returns the length of the encoded text.  */)
+     (start, end, coding_system)
      Lisp_Object start, end, coding_system;
 {
   return code_convert_region1 (start, end, coding_system, 1);
@@ -6513,14 +6942,14 @@ code_convert_string1 (string, coding_system, nocopy, encodep)
 {
   struct coding_system coding;
 
-  CHECK_STRING (string, 0);
-  CHECK_SYMBOL (coding_system, 1);
+  CHECK_STRING (string);
+  CHECK_SYMBOL (coding_system);
 
   if (NILP (coding_system))
     return (NILP (nocopy) ? Fcopy_sequence (string) : string);
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
   string = (encodep
@@ -6533,13 +6962,13 @@ code_convert_string1 (string, coding_system, nocopy, encodep)
 
 DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string,
        2, 3, 0,
-  "Decode STRING which is encoded in CODING-SYSTEM, and return the result.\n\
-Optional arg NOCOPY non-nil means it is OK to return STRING itself\n\
-if the decoding operation is trivial.\n\
-This function sets `last-coding-system-used' to the precise coding system\n\
-used (which may be different from CODING-SYSTEM if CODING-SYSTEM is\n\
-not fully specified.)")
-  (string, coding_system, nocopy)
+       doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result.
+Optional arg NOCOPY non-nil means it is OK to return STRING itself
+if the decoding operation is trivial.
+This function sets `last-coding-system-used' to the precise coding system
+used (which may be different from CODING-SYSTEM if CODING-SYSTEM is
+not fully specified.)  */)
+     (string, coding_system, nocopy)
      Lisp_Object string, coding_system, nocopy;
 {
   return code_convert_string1 (string, coding_system, nocopy, 0);
@@ -6547,13 +6976,13 @@ not fully specified.)")
 
 DEFUN ("encode-coding-string", Fencode_coding_string, Sencode_coding_string,
        2, 3, 0,
-  "Encode STRING to CODING-SYSTEM, and return the result.\n\
-Optional arg NOCOPY non-nil means it is OK to return STRING itself\n\
-if the encoding operation is trivial.\n\
-This function sets `last-coding-system-used' to the precise coding system\n\
-used (which may be different from CODING-SYSTEM if CODING-SYSTEM is\n\
-not fully specified.)")
-  (string, coding_system, nocopy)
+       doc: /* Encode STRING to CODING-SYSTEM, and return the result.
+Optional arg NOCOPY non-nil means it is OK to return STRING itself
+if the encoding operation is trivial.
+This function sets `last-coding-system-used' to the precise coding system
+used (which may be different from CODING-SYSTEM if CODING-SYSTEM is
+not fully specified.)  */)
+     (string, coding_system, nocopy)
      Lisp_Object string, coding_system, nocopy;
 {
   return code_convert_string1 (string, coding_system, nocopy, 1);
@@ -6572,14 +7001,14 @@ code_convert_string_norecord (string, coding_system, encodep)
 {
   struct coding_system coding;
 
-  CHECK_STRING (string, 0);
-  CHECK_SYMBOL (coding_system, 1);
+  CHECK_STRING (string);
+  CHECK_SYMBOL (coding_system);
 
   if (NILP (coding_system))
     return string;
 
   if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0)
-    error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
+    error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system)));
 
   coding.composing = COMPOSITION_DISABLED;
   coding.mode |= CODING_MODE_LAST_BLOCK;
@@ -6589,15 +7018,15 @@ code_convert_string_norecord (string, coding_system, encodep)
 }
 \f
 DEFUN ("decode-sjis-char", Fdecode_sjis_char, Sdecode_sjis_char, 1, 1, 0,
-  "Decode a Japanese character which has CODE in shift_jis encoding.\n\
-Return the corresponding character.")
-  (code)
+       doc: /* Decode a Japanese character which has CODE in shift_jis encoding.
+Return the corresponding character.  */)
+     (code)
      Lisp_Object code;
 {
   unsigned char c1, c2, s1, s2;
   Lisp_Object val;
 
-  CHECK_NUMBER (code, 0);
+  CHECK_NUMBER (code);
   s1 = (XFASTINT (code)) >> 8, s2 = (XFASTINT (code)) & 0xFF;
   if (s1 == 0)
     {
@@ -6610,7 +7039,7 @@ Return the corresponding character.")
     }
   else
     {
-      if ((s1 < 0x80 || s1 > 0x9F && s1 < 0xE0 || s1 > 0xEF)
+      if ((s1 < 0x80 || (s1 > 0x9F && s1 < 0xE0) || s1 > 0xEF)
          || (s2 < 0x40 || s2 == 0x7F || s2 > 0xFC))
        error ("Invalid Shift JIS code: %x", XFASTINT (code));
       DECODE_SJIS (s1, s2, c1, c2);
@@ -6620,15 +7049,15 @@ Return the corresponding character.")
 }
 
 DEFUN ("encode-sjis-char", Fencode_sjis_char, Sencode_sjis_char, 1, 1, 0,
-  "Encode a Japanese character CHAR to shift_jis encoding.\n\
-Return the corresponding code in SJIS.")
-  (ch)
+       doc: /* Encode a Japanese character CHAR to shift_jis encoding.
+Return the corresponding code in SJIS.  */)
+     (ch)
      Lisp_Object ch;
 {
   int charset, c1, c2, s1, s2;
   Lisp_Object val;
 
-  CHECK_NUMBER (ch, 0);
+  CHECK_NUMBER (ch);
   SPLIT_CHAR (XFASTINT (ch), charset, c1, c2);
   if (charset == CHARSET_ASCII)
     {
@@ -6651,16 +7080,16 @@ Return the corresponding code in SJIS.")
 }
 
 DEFUN ("decode-big5-char", Fdecode_big5_char, Sdecode_big5_char, 1, 1, 0,
-  "Decode a Big5 character which has CODE in BIG5 coding system.\n\
-Return the corresponding character.")
-  (code)
+       doc: /* Decode a Big5 character which has CODE in BIG5 coding system.
+Return the corresponding character.  */)
+     (code)
      Lisp_Object code;
 {
   int charset;
   unsigned char b1, b2, c1, c2;
   Lisp_Object val;
 
-  CHECK_NUMBER (code, 0);
+  CHECK_NUMBER (code);
   b1 = (XFASTINT (code)) >> 8, b2 = (XFASTINT (code)) & 0xFF;
   if (b1 == 0)
     {
@@ -6680,15 +7109,15 @@ Return the corresponding character.")
 }
 
 DEFUN ("encode-big5-char", Fencode_big5_char, Sencode_big5_char, 1, 1, 0,
-  "Encode the Big5 character CHAR to BIG5 coding system.\n\
-Return the corresponding character code in Big5.")
-  (ch)
+       doc: /* Encode the Big5 character CHAR to BIG5 coding system.
+Return the corresponding character code in Big5.  */)
+     (ch)
      Lisp_Object ch;
 {
   int charset, c1, c2, b1, b2;
   Lisp_Object val;
 
-  CHECK_NUMBER (ch, 0);
+  CHECK_NUMBER (ch);
   SPLIT_CHAR (XFASTINT (ch), charset, c1, c2);
   if (charset == CHARSET_ASCII)
     {
@@ -6707,16 +7136,16 @@ Return the corresponding character code in Big5.")
   return val;
 }
 \f
-DEFUN ("set-terminal-coding-system-internal",
-       Fset_terminal_coding_system_internal,
-       Sset_terminal_coding_system_internal, 1, 1, 0, "")
-  (coding_system)
+DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_internal,
+       Sset_terminal_coding_system_internal, 1, 1, 0,
+       doc: /* Internal use only.  */)
+     (coding_system)
      Lisp_Object coding_system;
 {
-  CHECK_SYMBOL (coding_system, 0);
+  CHECK_SYMBOL (coding_system);
   setup_coding_system (Fcheck_coding_system (coding_system), &terminal_coding);
   /* We had better not send unsafe characters to terminal.  */
-  terminal_coding.flags |= CODING_FLAG_ISO_SAFE;
+  terminal_coding.mode |= CODING_MODE_INHIBIT_UNENCODABLE_CHAR;
   /* Character composition should be disabled.  */
   terminal_coding.composing = COMPOSITION_DISABLED;
   /* Error notification should be suppressed.  */
@@ -6726,13 +7155,13 @@ DEFUN ("set-terminal-coding-system-internal",
   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)
+DEFUN ("set-safe-terminal-coding-system-internal", Fset_safe_terminal_coding_system_internal,
+       Sset_safe_terminal_coding_system_internal, 1, 1, 0,
+       doc: /* Internal use only.  */)
+     (coding_system)
      Lisp_Object coding_system;
 {
-  CHECK_SYMBOL (coding_system, 0);
+  CHECK_SYMBOL (coding_system);
   setup_coding_system (Fcheck_coding_system (coding_system),
                       &safe_terminal_coding);
   /* Character composition should be disabled.  */
@@ -6744,31 +7173,31 @@ DEFUN ("set-safe-terminal-coding-system-internal",
   return Qnil;
 }
 
-DEFUN ("terminal-coding-system",
-       Fterminal_coding_system, Sterminal_coding_system, 0, 0, 0,
-  "Return coding system specified for terminal output.")
-  ()
+DEFUN ("terminal-coding-system", Fterminal_coding_system,
+       Sterminal_coding_system, 0, 0, 0,
+       doc: /* Return coding system specified for terminal output.  */)
+     ()
 {
   return terminal_coding.symbol;
 }
 
-DEFUN ("set-keyboard-coding-system-internal",
-       Fset_keyboard_coding_system_internal,
-       Sset_keyboard_coding_system_internal, 1, 1, 0, "")
-  (coding_system)
+DEFUN ("set-keyboard-coding-system-internal", Fset_keyboard_coding_system_internal,
+       Sset_keyboard_coding_system_internal, 1, 1, 0,
+       doc: /* Internal use only.  */)
+     (coding_system)
      Lisp_Object coding_system;
 {
-  CHECK_SYMBOL (coding_system, 0);
+  CHECK_SYMBOL (coding_system);
   setup_coding_system (Fcheck_coding_system (coding_system), &keyboard_coding);
   /* Character composition should be disabled.  */
   keyboard_coding.composing = COMPOSITION_DISABLED;
   return Qnil;
 }
 
-DEFUN ("keyboard-coding-system",
-       Fkeyboard_coding_system, Skeyboard_coding_system, 0, 0, 0,
-  "Return coding system specified for decoding keyboard input.")
-  ()
+DEFUN ("keyboard-coding-system", Fkeyboard_coding_system,
+       Skeyboard_coding_system, 0, 0, 0,
+       doc: /* Return coding system specified for decoding keyboard input.  */)
+     ()
 {
   return keyboard_coding.symbol;
 }
@@ -6776,37 +7205,37 @@ DEFUN ("keyboard-coding-system",
 \f
 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\
-  For process I/O, `call-process', `call-process-region', or `start-process'.\n\
-  For network I/O, `open-network-stream'.\n\
-\n\
-The remaining arguments should be the same arguments that were passed\n\
-to the primitive.  Depending on which primitive, one of those arguments\n\
-is selected as the TARGET.  For example, if OPERATION does file I/O,\n\
-whichever argument specifies the file name is TARGET.\n\
-\n\
-TARGET has a meaning which depends on OPERATION:\n\
-  For file I/O, TARGET is a file name.\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 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.\n\
-\n\
-usage: (find-operation-coding-system OPERATION ARGUMENTS ...)")
-  (nargs, args)
+       doc: /* Choose a coding system for an operation based on the target name.
+The value names a pair of coding systems: (DECODING-SYSTEM . ENCODING-SYSTEM).
+DECODING-SYSTEM is the coding system to use for decoding
+\(in case OPERATION does decoding), and ENCODING-SYSTEM is the coding system
+for encoding (in case OPERATION does encoding).
+
+The first argument OPERATION specifies an I/O primitive:
+  For file I/O, `insert-file-contents' or `write-region'.
+  For process I/O, `call-process', `call-process-region', or `start-process'.
+  For network I/O, `open-network-stream'.
+
+The remaining arguments should be the same arguments that were passed
+to the primitive.  Depending on which primitive, one of those arguments
+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 process I/O, TARGET is a process name.
+  For network I/O, TARGET is a service name or a port number
+
+This function looks up what specified for TARGET in,
+`file-coding-system-alist', `process-coding-system-alist',
+or `network-coding-system-alist' depending on OPERATION.
+They may specify a coding system, a cons of coding systems,
+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.
+
+usage: (find-operation-coding-system OPERATION ARGUMENTS ...)  */)
+     (nargs, args)
      int nargs;
      Lisp_Object *args;
 {
@@ -6821,7 +7250,14 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...)")
     error ("Invalid first argument");
   if (nargs < 1 + XINT (target_idx))
     error ("Too few arguments for operation: %s",
-          XSYMBOL (operation)->name->data);
+          SDATA (SYMBOL_NAME (operation)));
+  /* For write-region, if the 6th argument (i.e. VISIT, the 5th
+     argument to write-region) is string, it must be treated as a
+     target file name.  */
+  if (EQ (operation, Qwrite_region)
+      && nargs > 5
+      && STRINGP (args[5]))
+    target_idx = make_number (4);
   target = args[XINT (target_idx) + 1];
   if (!(STRINGP (target)
        || (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
@@ -6872,10 +7308,10 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS ...)")
 
 DEFUN ("update-coding-systems-internal",  Fupdate_coding_systems_internal,
        Supdate_coding_systems_internal, 0, 0, 0,
-  "Update internal database for ISO2022 and CCL based coding systems.\n\
-When values of any coding categories are changed, you must\n\
-call this function")
-  ()
+       doc: /* Update internal database for ISO2022 and CCL based coding systems.
+When values of any coding categories are changed, you must
+call this function.  */)
+     ()
 {
   int i;
 
@@ -6903,9 +7339,9 @@ call this function")
 
 DEFUN ("set-coding-priority-internal", Fset_coding_priority_internal,
        Sset_coding_priority_internal, 0, 0, 0,
-  "Update internal database for the current value of `coding-category-list'.\n\
-This function is internal use only.")
-  ()
+       doc: /* Update internal database for the current value of `coding-category-list'.
+This function is internal use only.  */)
+     ()
 {
   int i = 0, idx;
   Lisp_Object val;
@@ -6931,6 +7367,40 @@ This function is internal use only.")
   return Qnil;
 }
 
+DEFUN ("define-coding-system-internal", Fdefine_coding_system_internal,
+       Sdefine_coding_system_internal, 1, 1, 0,
+       doc: /* Register CODING-SYSTEM as a base coding system.
+This function is internal use only.  */)
+     (coding_system)
+     Lisp_Object coding_system;
+{
+  Lisp_Object safe_chars, slot;
+
+  if (NILP (Fcheck_coding_system (coding_system)))
+    Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil));
+  safe_chars = coding_safe_chars (coding_system);
+  if (! EQ (safe_chars, Qt) && ! CHAR_TABLE_P (safe_chars))
+    error ("No valid safe-chars property for %s",
+          SDATA (SYMBOL_NAME (coding_system)));
+  if (EQ (safe_chars, Qt))
+    {
+      if (NILP (Fmemq (coding_system, XCAR (Vcoding_system_safe_chars))))
+       XSETCAR (Vcoding_system_safe_chars,
+                Fcons (coding_system, XCAR (Vcoding_system_safe_chars)));
+    }
+  else
+    {
+      slot = Fassq (coding_system, XCDR (Vcoding_system_safe_chars));
+      if (NILP (slot))
+       XSETCDR (Vcoding_system_safe_chars,
+                nconc2 (XCDR (Vcoding_system_safe_chars),
+                        Fcons (Fcons (coding_system, safe_chars), Qnil)));
+      else
+       XSETCDR (slot, safe_chars);
+    }
+  return Qnil;
+}
+
 #endif /* emacs */
 
 \f
@@ -6941,7 +7411,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;
@@ -7084,9 +7554,12 @@ syms_of_coding ()
       }
   }
 
+  Vcoding_system_safe_chars = Fcons (Qnil, Qnil);
+  staticpro (&Vcoding_system_safe_chars);
+
   Qtranslation_table = intern ("translation-table");
   staticpro (&Qtranslation_table);
-  Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (1));
+  Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (2));
 
   Qtranslation_table_id = intern ("translation-table-id");
   staticpro (&Qtranslation_table_id);
@@ -7108,7 +7581,7 @@ syms_of_coding ()
      But don't staticpro it here--that is done in alloc.c.  */
   Qchar_table_extra_slots = intern ("char-table-extra-slots");
   Fput (Qsafe_chars, Qchar_table_extra_slots, make_number (0));
-  Fput (Qchar_coding_system, Qchar_table_extra_slots, make_number (1));
+  Fput (Qchar_coding_system, Qchar_table_extra_slots, make_number (0));
 
   Qvalid_codes = intern ("valid-codes");
   staticpro (&Qvalid_codes);
@@ -7119,6 +7592,9 @@ syms_of_coding ()
   Qraw_text = intern ("raw-text");
   staticpro (&Qraw_text);
 
+  Qutf_8 = intern ("utf-8");
+  staticpro (&Qutf_8);
+
   defsubr (&Scoding_system_p);
   defsubr (&Sread_coding_system);
   defsubr (&Sread_non_nil_coding_system);
@@ -7126,6 +7602,7 @@ syms_of_coding ()
   defsubr (&Sdetect_coding_region);
   defsubr (&Sdetect_coding_string);
   defsubr (&Sfind_coding_systems_region_internal);
+  defsubr (&Sunencodable_char_position);
   defsubr (&Sdecode_coding_region);
   defsubr (&Sencode_coding_region);
   defsubr (&Sdecode_coding_string);
@@ -7142,32 +7619,33 @@ syms_of_coding ()
   defsubr (&Sfind_operation_coding_system);
   defsubr (&Supdate_coding_systems_internal);
   defsubr (&Sset_coding_priority_internal);
+  defsubr (&Sdefine_coding_system_internal);
 
   DEFVAR_LISP ("coding-system-list", &Vcoding_system_list,
-    "List of coding systems.\n\
-\n\
-Do not alter the value of this variable manually.  This variable should be\n\
-updated by the functions `make-coding-system' and\n\
-`define-coding-system-alias'.");
+              doc: /* List of coding systems.
+
+Do not alter the value of this variable manually.  This variable should be
+updated by the functions `make-coding-system' and
+`define-coding-system-alias'.  */);
   Vcoding_system_list = Qnil;
 
   DEFVAR_LISP ("coding-system-alist", &Vcoding_system_alist,
-    "Alist of coding system names.\n\
-Each element is one element list of coding system name.\n\
-This variable is given to `completing-read' as TABLE argument.\n\
-\n\
-Do not alter the value of this variable manually.  This variable should be\n\
-updated by the functions `make-coding-system' and\n\
-`define-coding-system-alias'.");
+              doc: /* Alist of coding system names.
+Each element is one element list of coding system name.
+This variable is given to `completing-read' as TABLE argument.
+
+Do not alter the value of this variable manually.  This variable should be
+updated by the functions `make-coding-system' and
+`define-coding-system-alias'.  */);
   Vcoding_system_alist = Qnil;
 
   DEFVAR_LISP ("coding-category-list", &Vcoding_category_list,
-    "List of coding-categories (symbols) ordered by priority.\n\
-\n\
-On detecting a coding system, Emacs tries code detection algorithms\n\
-associated with each coding-category one by one in this order.  When\n\
-one algorithm agrees with a byte sequence of source text, the coding\n\
-system bound to the corresponding coding-category is selected.");
+              doc: /* List of coding-categories (symbols) ordered by priority.
+
+On detecting a coding system, Emacs tries code detection algorithms
+associated with each coding-category one by one in this order.  When
+one algorithm agrees with a byte sequence of source text, the coding
+system bound to the corresponding coding-category is selected.  */);
   {
     int i;
 
@@ -7179,194 +7657,206 @@ system bound to the corresponding coding-category is selected.");
   }
 
   DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read,
-    "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 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'.");
+              doc: /* Specify the coding system for read operations.
+It is useful to bind this variable with `let', but do not set it globally.
+If the value is a coding system, it is used for decoding on read operation.
+If not, an appropriate element is used from one of the coding system alists:
+There are three such tables, `file-coding-system-alist',
+`process-coding-system-alist', and `network-coding-system-alist'.  */);
   Vcoding_system_for_read = Qnil;
 
   DEFVAR_LISP ("coding-system-for-write", &Vcoding_system_for_write,
-    "Specify the coding system for write operations.\n\
-Programs bind this variable with `let', but you should not set it globally.\n\
-If the value is a coding system, it is used for encoding of output,\n\
-when writing it to a file and when sending it to a file or subprocess.\n\
-\n\
-If this does not specify a coding system, an appropriate element\n\
-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'.\n\
-For output to files, if the above procedure does not specify a coding system,\n\
-the value of `buffer-file-coding-system' is used.");
+              doc: /* Specify the coding system for write operations.
+Programs bind this variable with `let', but you should not set it globally.
+If the value is a coding system, it is used for encoding of output,
+when writing it to a file and when sending it to a file or subprocess.
+
+If this does not specify a coding system, an appropriate element
+is used from one of the coding system alists:
+There are three such tables, `file-coding-system-alist',
+`process-coding-system-alist', and `network-coding-system-alist'.
+For output to files, if the above procedure does not specify a coding system,
+the value of `buffer-file-coding-system' is used.  */);
   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.");
+              doc: /* Coding system used in the latest file or process I/O.
+Also set by `encode-coding-region', `decode-coding-region',
+`encode-coding-string' and `decode-coding-string'.  */);
   Vlast_coding_system_used = Qnil;
 
   DEFVAR_BOOL ("inhibit-eol-conversion", &inhibit_eol_conversion,
-    "*Non-nil means always inhibit code conversion of end-of-line format.\n\
-See info node `Coding Systems' and info node `Text and Binary' concerning\n\
-such conversion.");
+              doc: /* *Non-nil means always inhibit code conversion of end-of-line format.
+See info node `Coding Systems' and info node `Text and Binary' concerning
+such conversion.  */);
   inhibit_eol_conversion = 0;
 
   DEFVAR_BOOL ("inherit-process-coding-system", &inherit_process_coding_system,
-    "Non-nil means process buffer inherits coding system of process output.\n\
-Bind it to t if the process output is to be treated as if it were a file\n\
-read from some filesystem.");
+              doc: /* Non-nil means process buffer inherits coding system of process output.
+Bind it to t if the process output is to be treated as if it were a file
+read from some filesystem.  */);
   inherit_process_coding_system = 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\
-See also the function `find-operation-coding-system'\n\
-and the variable `auto-coding-alist'.");
+              doc: /* Alist to decide a coding system to use for a file I/O operation.
+The format is ((PATTERN . VAL) ...),
+where PATTERN is a regular expression matching a file name,
+VAL is a coding system, a cons of coding systems, or a function symbol.
+If VAL is a coding system, it is used for both decoding and encoding
+the file contents.
+If VAL is a cons of coding systems, the car part is used for decoding,
+and the cdr part is used for encoding.
+If VAL is a function symbol, the function must return a coding system
+or a cons of coding systems which are used as above.  The function gets
+the arguments with which `find-operation-coding-system' was called.
+
+See also the function `find-operation-coding-system'
+and the variable `auto-coding-alist'.  */);
   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\
-See also the function `find-operation-coding-system'.");
+    doc: /* Alist to decide a coding system to use for a process I/O operation.
+The format is ((PATTERN . VAL) ...),
+where PATTERN is a regular expression matching a program name,
+VAL is a coding system, a cons of coding systems, or a function symbol.
+If VAL is a coding system, it is used for both decoding what received
+from the program and encoding what sent to the program.
+If VAL is a cons of coding systems, the car part is used for decoding,
+and the cdr part is used for encoding.
+If VAL is a function symbol, the function must return a coding system
+or a cons of coding systems which are used as above.
+
+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\
-See also the function `find-operation-coding-system'.");
+    doc: /* Alist to decide a coding system to use for a network I/O operation.
+The format is ((PATTERN . VAL) ...),
+where PATTERN is a regular expression matching a network service name
+or is a port number to connect to,
+VAL is a coding system, a cons of coding systems, or a function symbol.
+If VAL is a coding system, it is used for both decoding what received
+from the network stream and encoding what sent to the network stream.
+If VAL is a cons of coding systems, the car part is used for decoding,
+and the cdr part is used for encoding.
+If VAL is a function symbol, the function must return a coding system
+or a cons of coding systems which are used as above.
+
+See also the function `find-operation-coding-system'.  */);
   Vnetwork_coding_system_alist = Qnil;
 
   DEFVAR_LISP ("locale-coding-system", &Vlocale_coding_system,
-    "Coding system to use with system messages.  Also used for decoding\n\
-keyboard input on X Window system.");
+              doc: /* Coding system to use with system messages.
+Also used for decoding keyboard input on X Window system.  */);
   Vlocale_coding_system = Qnil;
 
   /* The eol mnemonics are reset in startup.el system-dependently.  */
   DEFVAR_LISP ("eol-mnemonic-unix", &eol_mnemonic_unix,
-    "*String displayed in mode line for UNIX-like (LF) end-of-line format.");
+              doc: /* *String displayed in mode line for UNIX-like (LF) end-of-line format.  */);
   eol_mnemonic_unix = build_string (":");
 
   DEFVAR_LISP ("eol-mnemonic-dos", &eol_mnemonic_dos,
-    "*String displayed in mode line for DOS-like (CRLF) end-of-line format.");
+              doc: /* *String displayed in mode line for DOS-like (CRLF) end-of-line format.  */);
   eol_mnemonic_dos = build_string ("\\");
 
   DEFVAR_LISP ("eol-mnemonic-mac", &eol_mnemonic_mac,
-    "*String displayed in mode line for MAC-like (CR) end-of-line format.");
+              doc: /* *String displayed in mode line for MAC-like (CR) end-of-line format.  */);
   eol_mnemonic_mac = build_string ("/");
 
   DEFVAR_LISP ("eol-mnemonic-undecided", &eol_mnemonic_undecided,
-    "*String displayed in mode line when end-of-line format is not yet determined.");
+              doc: /* *String displayed in mode line when end-of-line format is not yet determined.  */);
   eol_mnemonic_undecided = build_string (":");
 
   DEFVAR_LISP ("enable-character-translation", &Venable_character_translation,
-    "*Non-nil enables character translation while encoding and decoding.");
+              doc: /* *Non-nil enables character translation while encoding and decoding.  */);
   Venable_character_translation = Qt;
 
   DEFVAR_LISP ("standard-translation-table-for-decode",
-    &Vstandard_translation_table_for_decode,
-    "Table for translating characters while decoding.");
+              &Vstandard_translation_table_for_decode,
+              doc: /* Table for translating characters while decoding.  */);
   Vstandard_translation_table_for_decode = Qnil;
 
   DEFVAR_LISP ("standard-translation-table-for-encode",
-    &Vstandard_translation_table_for_encode,
-    "Table for translating characters while encoding.");
+              &Vstandard_translation_table_for_encode,
+              doc: /* Table for translating characters while encoding.  */);
   Vstandard_translation_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 identifying revision (cdr part of the element).");
+              doc: /* Alist of charsets vs revision numbers.
+While encoding, if a charset (car part of an element) is found,
+designate it with the escape sequence identifying 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.");
+              doc: /* Cons of coding systems used for process I/O by default.
+The car part is used for decoding a process output,
+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.");
+              doc: /* Table of extra Latin codes in the range 128..159 (inclusive).
+This is a vector of length 256.
+If Nth element is non-nil, the existence of code N in a file
+\(or output of subprocess) doesn't prevent it to be detected as
+a coding system of ISO 2022 variant which has a flag
+`accept-latin-extra-code' t (e.g. iso-latin-1) on reading a file
+or reading output of a subprocess.
+Only 128th through 159th elements has a meaning.  */);
   Vlatin_extra_code_table = Fmake_vector (make_number (256), Qnil);
 
   DEFVAR_LISP ("select-safe-coding-system-function",
               &Vselect_safe_coding_system_function,
-    "Function to call to select safe coding system for encoding a text.\n\
-\n\
-If set, this function is called to force a user to select a proper\n\
-coding system which can encode the text in the case that a default\n\
-coding system used in each operation can't encode the text.\n\
-\n\
-The default value is `select-safe-coding-system' (which see).");
+              doc: /* Function to call to select safe coding system for encoding a text.
+
+If set, this function is called to force a user to select a proper
+coding system which can encode the text in the case that a default
+coding system used in each operation can't encode the text.
+
+The default value is `select-safe-coding-system' (which see).  */);
   Vselect_safe_coding_system_function = Qnil;
 
-  DEFVAR_LISP ("char-coding-system-table", &Vchar_coding_system_table,
-    "Char-table containing safe coding systems of each characters.\n\
-Each element doesn't include such generic coding systems that can\n\
-encode any characters.   They are in the first extra slot.");
-  Vchar_coding_system_table = Fmake_char_table (Qchar_coding_system, Qnil);
+  DEFVAR_BOOL ("coding-system-require-warning",
+              &coding_system_require_warning,
+              doc: /* Internal use only.
+If non-nil, on writing a file, `select-safe-coding-system-function' is
+called even if `coding-system-for-write' is non-nil.  The command
+`universal-coding-system-argument' binds this variable to t temporarily.  */);
+  coding_system_require_warning = 0;
+
 
   DEFVAR_BOOL ("inhibit-iso-escape-detection",
               &inhibit_iso_escape_detection,
-    "If non-nil, Emacs ignores ISO2022's escape sequence on code detection.\n\
-\n\
-By default, on reading a file, Emacs tries to detect how the text is\n\
-encoded.  This code detection is sensitive to escape sequences.  If\n\
-the sequence is valid as ISO2022, the code is determined as one of\n\
-the ISO2022 encodings, and the file is decoded by the corresponding\n\
-coding system (e.g. `iso-2022-7bit').\n\
-\n\
-However, there may be a case that you want to read escape sequences in\n\
-a file as is.  In such a case, you can set this variable to non-nil.\n\
-Then, as the code detection ignores any escape sequences, no file is\n\
-detected as encoded in some ISO2022 encoding.  The result is that all\n\
-escape sequences become visible in a buffer.\n\
-\n\
-The default value is nil, and it is strongly recommended not to change\n\
-it.  That is because many Emacs Lisp source files that contain\n\
-non-ASCII characters are encoded by the coding system `iso-2022-7bit'\n\
-in Emacs's distribution, and they won't be decoded correctly on\n\
-reading if you suppress escape sequence detection.\n\
-\n\
-The other way to read escape sequences in a file without decoding is\n\
-to explicitly specify some coding system that doesn't use ISO2022's\n\
-escape sequence (e.g `latin-1') on reading by \\[universal-coding-system-argument].");
+              doc: /* If non-nil, Emacs ignores ISO2022's escape sequence on code detection.
+
+By default, on reading a file, Emacs tries to detect how the text is
+encoded.  This code detection is sensitive to escape sequences.  If
+the sequence is valid as ISO2022, the code is determined as one of
+the ISO2022 encodings, and the file is decoded by the corresponding
+coding system (e.g. `iso-2022-7bit').
+
+However, there may be a case that you want to read escape sequences in
+a file as is.  In such a case, you can set this variable to non-nil.
+Then, as the code detection ignores any escape sequences, no file is
+detected as encoded in some ISO2022 encoding.  The result is that all
+escape sequences become visible in a buffer.
+
+The default value is nil, and it is strongly recommended not to change
+it.  That is because many Emacs Lisp source files that contain
+non-ASCII characters are encoded by the coding system `iso-2022-7bit'
+in Emacs's distribution, and they won't be decoded correctly on
+reading if you suppress escape sequence detection.
+
+The other way to read escape sequences in a file without decoding is
+to explicitly specify some coding system that doesn't use ISO2022's
+escape sequence (e.g `latin-1') on reading by \\[universal-coding-system-argument].  */);
   inhibit_iso_escape_detection = 0;
+
+  DEFVAR_LISP ("translation-table-for-input", &Vtranslation_table_for_input,
+              doc: /* Char table for translating self-inserting characters.
+This is applied to the result of input methods, not their input.  See also
+`keyboard-translate-table'.  */);
+    Vtranslation_table_for_input = Qnil;
 }
 
 char *
@@ -7383,7 +7873,7 @@ emacs_strerror (error_number)
       Lisp_Object dec = code_convert_string_norecord (build_string (str),
                                                      Vlocale_coding_system,
                                                      0);
-      str = (char *) XSTRING (dec)->data;
+      str = (char *) SDATA (dec);
     }
 
   return str;