Fix -Wimplicit warnings.
[bpt/emacs.git] / src / coding.c
index 2417c25..a98ca65 100644 (file)
@@ -640,10 +640,11 @@ detect_coding_emacs_mule (src, src_end)
 
 enum iso_code_class_type iso_code_class[256];
 
-#define CHARSET_OK(idx, charset)               \
-  (CODING_SPEC_ISO_REQUESTED_DESIGNATION       \
-   (coding_system_table[idx], charset)         \
-   != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)
+#define CHARSET_OK(idx, charset)                       \
+  (coding_system_table[idx]->safe_charsets[charset]    \
+   || (CODING_SPEC_ISO_REQUESTED_DESIGNATION           \
+       (coding_system_table[idx], charset)             \
+       != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION))
 
 #define SHIFT_OUT_OK(idx) \
   (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding_system_table[idx], 1) >= 0)
@@ -909,7 +910,8 @@ detect_coding_iso2022 (src, src_end)
                                     make_number (chars),                  \
                                     make_number (final_char));            \
     if (charset >= 0                                                      \
-       && CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) == reg) \
+       && (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) == reg \
+           || coding->safe_charsets[charset]))                            \
       {                                                                           \
        if (coding->spec.iso2022.last_invalid_designation_register == 0    \
            && reg == 0                                                    \
@@ -968,6 +970,7 @@ int check_composing_code (coding, src, src_end)
              c1 = *src++;
              if ((c1 < ' ' || c1 >= 0x80)
                  || (charset = iso_charset_table[dim][c >= ','][c1]) < 0
+                 || ! coding->safe_charsets[charset]
                  || (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset)
                      == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION))
                invalid_code_found = 1;
@@ -1007,6 +1010,7 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
     unification_table = Vstandard_character_unification_table_for_decode;
 
   coding->produced_char = 0;
+  coding->fake_multibyte = 0;
   while (src < src_end && (dst_bytes
                           ? (dst < adjusted_dst_end)
                           : (dst < src - 6)))
@@ -1046,21 +1050,12 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
        case ISO_0xA0_or_0xFF:
          if (charset1 < 0 || CHARSET_CHARS (charset1) == 94
              || coding->flags & CODING_FLAG_ISO_SEVEN_BITS)
-           {
-             /* Invalid code.  */
-             *dst++ = c1;
-             coding->produced_char++;
-             break;
-           }
+           goto label_invalid_code;
          /* This is a graphic character, we fall down ... */
 
        case ISO_graphic_plane_1:
          if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS)
-           {
-             /* Invalid code.  */
-             *dst++ = c1;
-             coding->produced_char++;
-           }
+           goto label_invalid_code;
          else
            DECODE_ISO_CHARACTER (charset1, c1);
          break;
@@ -1310,9 +1305,9 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
          break;
 
        label_invalid_code:
-         coding->produced_char += src - src_base;
          while (src_base < src)
            *dst++ = *src_base++;
+         coding->fake_multibyte = 1;
        }
       continue;
 
@@ -1323,19 +1318,26 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
       break;
     }
 
-  if (result == CODING_FINISH_NORMAL
-      && src < src_end)
-    result = CODING_FINISH_INSUFFICIENT_DST;
-
-  /* If this is the last block of the text to be decoded, we had
-     better just flush out all remaining codes in the text although
-     they are not valid characters.  */
-  if (coding->mode & CODING_MODE_LAST_BLOCK)
+  if (src < src_end)
     {
-      bcopy (src, dst, src_end - src);
-      dst += (src_end - src);
-      src = src_end;
+      if (result == CODING_FINISH_NORMAL)
+       result = CODING_FINISH_INSUFFICIENT_DST;
+      else if (result != CODING_FINISH_INCONSISTENT_EOL
+              && coding->mode & CODING_MODE_LAST_BLOCK)
+       {
+         /* This is the last block of the text to be decoded.  We had
+            better just flush out all remaining codes in the text
+            although they are not valid characters.  */
+         src_bytes = src_end - src;
+         if (dst_bytes && (dst_end - dst < src_bytes))
+           src_bytes = dst_end - dst;
+         bcopy (src, dst, src_bytes);
+         dst += src_bytes;
+         src += src_bytes;
+         coding->fake_multibyte = 1;
+       }
     }
+
   coding->consumed = coding->consumed_char = src - source;
   coding->produced = dst - destination;
   return result;
@@ -1413,16 +1415,22 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
     if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS)    \
       *dst++ = ISO_CODE_ESC, *dst++ = 'N';             \
     else                                               \
-      *dst++ = ISO_CODE_SS2;                           \
+      {                                                        \
+       *dst++ = ISO_CODE_SS2;                          \
+       coding->fake_multibyte = 1;                     \
+      }                                                        \
     CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 1;      \
   } while (0)
 
-#define ENCODE_SINGLE_SHIFT_3                          \
-  do {                                                 \
+#define ENCODE_SINGLE_SHIFT_3                          \
+  do {                                                 \
     if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS)    \
-      *dst++ = ISO_CODE_ESC, *dst++ = 'O';             \
-    else                                               \
-      *dst++ = ISO_CODE_SS3;                           \
+      *dst++ = ISO_CODE_ESC, *dst++ = 'O';             \
+    else                                               \
+      {                                                        \
+       *dst++ = ISO_CODE_SS3;                          \
+       coding->fake_multibyte = 1;                     \
+      }                                                        \
     CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 1;      \
   } while (0)
 
@@ -1551,12 +1559,22 @@ decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
     else                                                                 \
       charset_alt = charset;                                             \
     if (CHARSET_DIMENSION (charset_alt) == 1)                            \
-      ENCODE_ISO_CHARACTER_DIMENSION1 (charset_alt, c1);                 \
+      {                                                                          \
+       if (charset == CHARSET_ASCII                                      \
+           && coding->flags & CODING_FLAG_ISO_USE_ROMAN)                 \
+         charset_alt = charset_latin_jisx0201;                           \
+       ENCODE_ISO_CHARACTER_DIMENSION1 (charset_alt, c1);                \
+      }                                                                          \
     else                                                                 \
-      ENCODE_ISO_CHARACTER_DIMENSION2 (charset_alt, c1, c2);             \
+      {                                                                          \
+       if (charset == charset_jisx0208                                   \
+           && coding->flags & CODING_FLAG_ISO_USE_OLDJIS)                \
+         charset_alt = charset_jisx0208_1978;                            \
+       ENCODE_ISO_CHARACTER_DIMENSION2 (charset_alt, c1, c2);            \
+      }                                                                          \
     if (! COMPOSING_P (coding->composing))                               \
       coding->consumed_char++;                                           \
-  } while (0)
+     } while (0)
 
 /* Produce designation and invocation codes at a place pointed by DST
    to use CHARSET.  The element `spec.iso2022' of *CODING is updated.
@@ -1663,6 +1681,7 @@ encode_invocation_designation (charset, coding, dst)
    If the current block ends before any end-of-line, we may fail to
    find all the necessary designations.  */
 
+void
 encode_designation_at_bol (coding, table, src, src_end, dstp)
      struct coding_system *coding;
      Lisp_Object table;
@@ -1736,6 +1755,7 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
     unification_table = Vstandard_character_unification_table_for_encode;
 
   coding->consumed_char = 0;
+  coding->fake_multibyte = 0;
   while (src < src_end && (dst_bytes
                           ? (dst < adjusted_dst_end)
                           : (dst < src - 19)))
@@ -1923,15 +1943,17 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
       break;
     }
 
-  if (result == CODING_FINISH_NORMAL
-      && src < src_end)
-    result = CODING_FINISH_INSUFFICIENT_DST;
-
-  /* If this is the last block of the text to be encoded, we must
-     reset graphic planes and registers to the initial state, and
-     flush out the carryover if any.  */
-  if (coding->mode & CODING_MODE_LAST_BLOCK)
-    ENCODE_RESET_PLANE_AND_REGISTER;
+  if (src < src_end)
+    {
+      if (result == CODING_FINISH_NORMAL)
+       result = CODING_FINISH_INSUFFICIENT_DST;
+      else
+       /* If this is the last block of the text to be encoded, we
+          must reset graphic planes and registers to the initial
+          state, and flush out the carryover if any.  */
+       if (coding->mode & CODING_MODE_LAST_BLOCK)
+         ENCODE_RESET_PLANE_AND_REGISTER;
+    }
 
   coding->consumed = src - source;
   coding->produced = coding->produced_char = dst - destination;
@@ -2044,7 +2066,10 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
        if (sjis_p && charset_alt == charset_katakana_jisx0201)           \
          *dst++ = c1;                                                    \
        else                                                              \
-         *dst++ = charset_alt, *dst++ = c1;                              \
+         {                                                               \
+           *dst++ = charset_alt, *dst++ = c1;                            \
+           coding->fake_multibyte = 1;                                   \
+         }                                                               \
       }                                                                          \
     else                                                                 \
       {                                                                          \
@@ -2052,21 +2077,25 @@ encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes)
        if (sjis_p && charset_alt == charset_jisx0208)                    \
          {                                                               \
            unsigned char s1, s2;                                         \
-                                                                         \
+                                                                         \
            ENCODE_SJIS (c1, c2, s1, s2);                                 \
            *dst++ = s1, *dst++ = s2;                                     \
+           coding->fake_multibyte = 1;                                   \
          }                                                               \
        else if (!sjis_p                                                  \
                 && (charset_alt == charset_big5_1                        \
                     || charset_alt == charset_big5_2))                   \
          {                                                               \
            unsigned char b1, b2;                                         \
-                                                                         \
+                                                                         \
            ENCODE_BIG5 (charset_alt, c1, c2, b1, b2);                    \
            *dst++ = b1, *dst++ = b2;                                     \
          }                                                               \
        else                                                              \
-         *dst++ = charset_alt, *dst++ = c1, *dst++ = c2;                 \
+         {                                                               \
+           *dst++ = charset_alt, *dst++ = c1, *dst++ = c2;               \
+           coding->fake_multibyte = 1;                                   \
+         }                                                               \
       }                                                                          \
     coding->consumed_char++;                                             \
   } while (0);
@@ -2145,6 +2174,7 @@ decode_coding_sjis_big5 (coding, source, destination,
     unification_table = Vstandard_character_unification_table_for_decode;
 
   coding->produced_char = 0;
+  coding->fake_multibyte = 0;
   while (src < src_end && (dst_bytes
                           ? (dst < adjusted_dst_end)
                           : (dst < src - 3)))
@@ -2193,46 +2223,85 @@ decode_coding_sjis_big5 (coding, source, destination,
        }
       else if (c1 < 0x80)
        DECODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2);
-      else if (c1 < 0xA0 || c1 >= 0xE0)
+      else if (c1 < 0xA0)
        {
-         /* SJIS -> JISX0208, BIG5 -> Big5 (only if 0xE0 <= c1 < 0xFF) */
+         /* SJIS -> JISX0208 */
          if (sjis_p)
            {
              ONE_MORE_BYTE (c2);
-             DECODE_SJIS (c1, c2, c3, c4);
-             DECODE_SJIS_BIG5_CHARACTER (charset_jisx0208, c3, c4);
+             if (c2 >= 0x40)
+               {
+                 DECODE_SJIS (c1, c2, c3, c4);
+                 DECODE_SJIS_BIG5_CHARACTER (charset_jisx0208, c3, c4);
+               }
+             else
+               goto label_invalid_code_2;
            }
-         else if (c1 >= 0xE0 && c1 < 0xFF)
+         else
+           goto label_invalid_code_1;
+       }
+      else if (c1 < 0xE0)
+       {
+         /* SJIS -> JISX0201-Kana, BIG5 -> Big5 */
+         if (sjis_p)
+           DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1,
+                                       /* dummy */ c2);
+         else
            {
              int charset;
 
              ONE_MORE_BYTE (c2);
-             DECODE_BIG5 (c1, c2, charset, c3, c4);
-             DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
-           }
-         else                  /* Invalid code */
-           {
-             *dst++ = c1;
-             coding->produced_char++;
+             if ((c2 >= 0x40 && c2 <= 0x7E) || (c2 >= 0xA1 && c2 <= 0xFE))
+               {
+                 DECODE_BIG5 (c1, c2, charset, c3, c4);
+                 DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
+               }
+             else
+               goto label_invalid_code_2;
            }
        }
-      else
+      else                     /* C1 >= 0xE0 */
        {
-         /* SJIS -> JISX0201-Kana, BIG5 -> Big5 */
+         /* SJIS -> JISX0208, BIG5 -> Big5 */
          if (sjis_p)
-           DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1,
-                                       /* dummy */ c2);
+           {
+             ONE_MORE_BYTE (c2);
+             if (c2 >= 0x40)
+               {
+                 DECODE_SJIS (c1, c2, c3, c4);
+                 DECODE_SJIS_BIG5_CHARACTER (charset_jisx0208, c3, c4);
+               }
+             else
+               goto label_invalid_code_2;
+           }
          else
            {
              int charset;
 
              ONE_MORE_BYTE (c2);
-             DECODE_BIG5 (c1, c2, charset, c3, c4);
-             DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
+             if ((c2 >= 0x40 && c2 <= 0x7E) || (c2 >= 0xA1 && c2 <= 0xFE))
+               {
+                 DECODE_BIG5 (c1, c2, charset, c3, c4);
+                 DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4);
+               }
+             else
+               goto label_invalid_code_2;
            }
        }
       continue;
 
+    label_invalid_code_1:
+      *dst++ = c1;
+      coding->produced_char++;
+      coding->fake_multibyte = 1;
+      continue;
+
+    label_invalid_code_2:
+      *dst++ = c1; *dst++= c2;
+      coding->produced_char += 2;
+      coding->fake_multibyte = 1;
+      continue;
+
     label_end_of_loop:
       result = CODING_FINISH_INSUFFICIENT_SRC;
     label_end_of_loop_2:
@@ -2240,9 +2309,22 @@ decode_coding_sjis_big5 (coding, source, destination,
       break;
     }
 
-  if (result == CODING_FINISH_NORMAL
-      && src < src_end)
-    result = CODING_FINISH_INSUFFICIENT_DST;
+  if (src < src_end)
+    {
+      if (result == CODING_FINISH_NORMAL)
+       result = CODING_FINISH_INSUFFICIENT_DST;
+      else if (result != CODING_FINISH_INCONSISTENT_EOL
+              && coding->mode & CODING_MODE_LAST_BLOCK)
+       {
+         src_bytes = src_end - src;
+         if (dst_bytes && (dst_end - dst < src_bytes))
+           src_bytes = dst_end - dst;
+         bcopy (dst, src, src_bytes);
+         src += src_bytes;
+         dst += src_bytes;
+         coding->fake_multibyte = 1;
+       }
+    }
 
   coding->consumed = coding->consumed_char = src - source;
   coding->produced = dst - destination;
@@ -2281,6 +2363,7 @@ encode_coding_sjis_big5 (coding, source, destination,
     unification_table = Vstandard_character_unification_table_for_encode;
 
   coding->consumed_char = 0;
+  coding->fake_multibyte = 0;
   while (src < src_end && (dst_bytes
                           ? (dst < adjusted_dst_end)
                           : (dst < src - 1)))
@@ -2383,6 +2466,7 @@ encode_coding_sjis_big5 (coding, source, destination,
    This function is called only when `coding->eol_type' is
    CODING_EOL_CRLF or CODING_EOL_CR.  */
 
+int
 decode_eol (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
      unsigned char *source, *destination;
@@ -2392,8 +2476,11 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
   unsigned char *src_end = source + src_bytes;
   unsigned char *dst = destination;
   unsigned char *dst_end = destination + dst_bytes;
+  unsigned char c;
   int result = CODING_FINISH_NORMAL;
 
+  coding->fake_multibyte = 0;
+
   if (src_bytes <= 0)
     return result;
 
@@ -2411,7 +2498,8 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
                                 : (dst < src - 1)))
          {
            unsigned char *src_base = src;
-           unsigned char c = *src++;
+
+           c = *src++;
            if (c == '\r')
              {
                ONE_MORE_BYTE (c);
@@ -2423,6 +2511,8 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
                        goto label_end_of_loop_2;
                      }
                    *dst++ = '\r';
+                   if (BASE_LEADING_CODE_P (c))
+                     coding->fake_multibyte = 1;
                  }
                *dst++ = c;
              }
@@ -2433,7 +2523,11 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
                goto label_end_of_loop_2;
              }
            else
-             *dst++ = c;
+             {
+               *dst++ = c;
+               if (BASE_LEADING_CODE_P (c))
+                 coding->fake_multibyte = 1;
+             }
            continue;
 
          label_end_of_loop:
@@ -2451,7 +2545,13 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
     case CODING_EOL_CR:
       if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)
        {
-         while (src < src_end) if (*src++ == '\n') break;
+         while (src < src_end)
+           {
+             if ((c = *src++) == '\n')
+               break;
+             if (BASE_LEADING_CODE_P (c))
+               coding->fake_multibyte = 1;
+           }
          if (*--src == '\n')
            {
              src_bytes = src - source;
@@ -2483,6 +2583,7 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
        safe_bcopy (source, destination, src_bytes);
       src += src_bytes;
       dst += dst_bytes;
+      coding->fake_multibyte = 1;
       break;
     }
 
@@ -2496,6 +2597,7 @@ decode_eol (coding, source, destination, src_bytes, dst_bytes)
    `coding->mode & CODING_MODE_SELECTIVE_DISPLAY' is nonzero, code
    '\r' in source text also means end-of-line.  */
 
+int
 encode_eol (coding, source, destination, src_bytes, dst_bytes)
      struct coding_system *coding;
      unsigned char *source, *destination;
@@ -2505,6 +2607,8 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
   unsigned char *dst = destination;
   int result = CODING_FINISH_NORMAL;
 
+  coding->fake_multibyte = 0;
+
   if (coding->eol_type == CODING_EOL_CRLF)
     {
       unsigned char c;
@@ -2524,13 +2628,19 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
              || (c == '\r' && (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)))
            *dst++ = '\r', *dst++ = '\n';
          else
-           *dst++ = c;
+           {
+             *dst++ = c;
+             if (BASE_LEADING_CODE_P (c))
+               coding->fake_multibyte = 1;
+           }
        }
       if (src < src_end)
        result = CODING_FINISH_INSUFFICIENT_DST;
     }
   else
     {
+      unsigned char c;
+
       if (dst_bytes && src_bytes > dst_bytes)
        {
          src_bytes = dst_bytes;
@@ -2539,19 +2649,31 @@ encode_eol (coding, source, destination, src_bytes, dst_bytes)
       if (dst_bytes)
        bcopy (source, destination, src_bytes);
       else
-       safe_bcopy (source, destination, src_bytes);
+       {
+         safe_bcopy (source, destination, src_bytes);
+         dst_bytes = src_bytes;
+       }
       if (coding->eol_type == CODING_EOL_CRLF)
        {
          while (src_bytes--)
-           if (*dst++ == '\n') dst[-1] = '\r';
+           {
+             if ((c = *dst++) == '\n')
+               dst[-1] = '\r';
+             else if (BASE_LEADING_CODE_P (c))
+                 coding->fake_multibyte = 1;
+           }
        }
-      else if (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)
+      else
        {
-         while (src_bytes--)
-           if (*dst++ == '\r') dst[-1] = '\n';
+         if (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)
+           {
+             while (src_bytes--)
+               if (*dst++ == '\r') dst[-1] = '\n';
+           }
+         coding->fake_multibyte = 1;
        }
-      src += src_bytes;
-      dst += src_bytes;
+      src = source + dst_bytes;
+      dst = destination + dst_bytes;
     }
 
   coding->consumed = coding->consumed_char = src - source;
@@ -3448,6 +3570,7 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
     {
       coding->produced = coding->produced_char = 0;
       coding->consumed = coding->consumed_char = 0;
+      coding->fake_multibyte = 0;
       return CODING_FINISH_NORMAL;
     }
 
@@ -3504,6 +3627,7 @@ decode_coding (coding, source, destination, src_bytes, dst_bytes)
        bcopy (source, destination, coding->produced);
       else
        safe_bcopy (source, destination, coding->produced);
+      coding->fake_multibyte = 1;
       coding->consumed
        = coding->consumed_char = coding->produced_char = coding->produced;
       break;
@@ -3526,6 +3650,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
     {
       coding->produced = coding->produced_char = 0;
       coding->consumed = coding->consumed_char = 0;
+      coding->fake_multibyte = 0;
       return CODING_FINISH_NORMAL;
     }
 
@@ -3582,6 +3707,7 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
          while (p < pend)
            if (*p++ == '\015') p[-1] = '\n';
        }
+      coding->fake_multibyte = 1;
       coding->consumed
        = coding->consumed_char = coding->produced_char = coding->produced;
       break;
@@ -3590,10 +3716,11 @@ encode_coding (coding, source, destination, src_bytes, dst_bytes)
   return result;
 }
 
-/* Scan text in the region between *BEG and *END, skip characters
-   which we don't have to decode by coding system CODING at the head
-   and tail, then set *BEG and *END to the region of the text we
-   actually have to convert.
+/* Scan text in the region between *BEG and *END (byte positions),
+   skip characters which we don't have to decode by coding system
+   CODING at the head and tail, then set *BEG and *END to the region
+   of the text we actually have to convert.  The caller should move
+   the gap out of the region in advance.
 
    If STR is not NULL, *BEG and *END are indices into STR.  */
 
@@ -3603,7 +3730,7 @@ shrink_decoding_region (beg, end, coding, str)
      struct coding_system *coding;
      unsigned char *str;
 {
-  unsigned char *begp_orig, *begp, *endp_orig, *endp;
+  unsigned char *begp_orig, *begp, *endp_orig, *endp, c;
   int eol_conversion;
 
   if (coding->type == coding_type_ccl
@@ -3615,8 +3742,8 @@ shrink_decoding_region (beg, end, coding, str)
     }
   else if (coding->type == coding_type_no_conversion)
     {
-      /* We need no conversion.  */
-      *beg = *end;
+      /* We need no conversion, but don't have to skip any data here.
+         Decoding routine handles them effectively anyway.  */
       return;
     }
 
@@ -3632,8 +3759,7 @@ shrink_decoding_region (beg, end, coding, str)
     }
   else
     {
-      move_gap (*beg);
-      begp_orig = begp = GAP_END_ADDR;
+      begp_orig = begp = BYTE_POS_ADDR (*beg);
       endp_orig = endp = begp + *end - *beg;
     }
 
@@ -3646,8 +3772,9 @@ shrink_decoding_region (beg, end, coding, str)
       if (eol_conversion)
        {
          if (coding->heading_ascii < 0)
-           while (begp < endp && *begp != '\r') begp++;
-         while (begp < endp && *(endp - 1) != '\r') endp--;
+           while (begp < endp && *begp != '\r' && *begp < 0x80) begp++;
+         while (begp < endp && *(endp - 1) != '\r' && *(endp - 1) < 0x80)
+           endp--;
        }
       else
        begp = endp;
@@ -3659,14 +3786,14 @@ shrink_decoding_region (beg, end, coding, str)
       if (coding->heading_ascii < 0)
        {
          if (eol_conversion)
-           while (begp < endp && *begp < 0x80 && *begp != '\n') begp++;
+           while (begp < endp && *begp < 0x80 && *begp != '\r') begp++;
          else
            while (begp < endp && *begp < 0x80) begp++;
        }
       /* We can skip all ASCII characters at the tail except for the
         second byte of SJIS or BIG5 code.  */
       if (eol_conversion)
-       while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\n') endp--;
+       while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\r') endp--;
       else
        while (begp < endp && endp[-1] < 0x80) endp--;
       if (begp < endp && endp < endp_orig && endp[-1] >= 0x80)
@@ -3676,8 +3803,6 @@ shrink_decoding_region (beg, end, coding, str)
     default:           /* i.e. case coding_type_iso2022: */
       if (coding->heading_ascii < 0)
        {
-         unsigned char c;
-
          /* We can skip all ASCII characters at the head except for a
             few control codes.  */
          while (begp < endp && (c = *begp) < 0x80
@@ -3692,7 +3817,7 @@ shrink_decoding_region (beg, end, coding, str)
        case CODING_CATEGORY_IDX_ISO_8_2:
          /* We can skip all ASCII characters at the tail.  */
          if (eol_conversion)
-           while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\n') endp--;
+           while (begp < endp && (c = endp[-1]) < 0x80 && c != '\r') endp--;
          else
            while (begp < endp && endp[-1] < 0x80) endp--;
          break;
@@ -3702,10 +3827,12 @@ shrink_decoding_region (beg, end, coding, str)
          /* We can skip all charactes at the tail except for ESC and
              the following 2-byte at the tail.  */
          if (eol_conversion)
-           while (begp < endp && endp[-1] != ISO_CODE_ESC && endp[-1] != '\n')
+           while (begp < endp
+                  && (c = endp[-1]) < 0x80 && c != ISO_CODE_ESC && c != '\r')
              endp--;
          else
-           while (begp < endp && endp[-1] != ISO_CODE_ESC)
+           while (begp < endp
+                  && (c = endp[-1]) < 0x80 && c != ISO_CODE_ESC)
              endp--;
          if (begp < endp && endp[-1] == ISO_CODE_ESC)
            {
@@ -3752,8 +3879,7 @@ shrink_encoding_region (beg, end, coding, str)
     }
   else
     {
-      move_gap (*beg);
-      begp_orig = begp = GAP_END_ADDR;
+      begp_orig = begp = BYTE_POS_ADDR (*beg);
       endp_orig = endp = begp + *end - *beg;
     }
 
@@ -3811,47 +3937,63 @@ shrink_encoding_region (beg, end, coding, str)
 }
 
 /* Decode (if ENCODEP is zero) or encode (if ENCODEP is nonzero) the
-   text from FROM to TO by coding system CODING, and return number of
-   characters in the resulting text.
+   text from FROM to TO (byte positions are FROM_BYTE and TO_BYTE) by
+   coding system CODING, and return the status code of code conversion
+   (currently, this value has no meaning).
 
-   If ADJUST is nonzero, we do various things as if the original text
-   is deleted and a new text is inserted.  See the comments in
-   replace_range (insdel.c) to know what we are doing.
+   How many characters (and bytes) are converted to how many
+   characters (and bytes) are recorded in members of the structure
+   CODING.
 
-   ADJUST nonzero also means that post-read-conversion or
-   pre-write-conversion functions (if any) should be processed.  */
+   If REPLACE is nonzero, we do various things as if the original text
+   is deleted and a new text is inserted.  See the comments in
+   replace_range (insdel.c) to know what we are doing.  */
 
 int
-code_convert_region (from, to, coding, encodep, adjust)
-     int from, to, encodep, adjust;
+code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace)
+     int from, from_byte, to, to_byte, encodep, replace;
      struct coding_system *coding;
 {
-  int len = to - from, require, inserted, inserted_byte;
-  int from_byte, to_byte, len_byte;
-  int from_byte_orig, to_byte_orig;
+  int len = to - from, len_byte = to_byte - from_byte;
+  int require, inserted, inserted_byte;
+  int head_skip, tail_skip, total_skip;
   Lisp_Object saved_coding_symbol = Qnil;
+  int multibyte = !NILP (current_buffer->enable_multibyte_characters);
+  int first = 1;
+  int fake_multibyte = 0;
+  unsigned char *src, *dst;
+  Lisp_Object deletion = Qnil;
 
-  if (adjust)
+  if (replace)
     {
+      int saved_from = from;
+
       prepare_to_modify_buffer (from, to, &from);
-      to = from + len;
+      if (saved_from != from)
+       {
+         to = from + len;
+         if (multibyte)
+           from_byte = CHAR_TO_BYTE (from), to_byte = CHAR_TO_BYTE (to);
+         else
+           from_byte = from, to_byte = to;
+         len_byte = to_byte - from_byte;
+       }
     }
-  from_byte = CHAR_TO_BYTE (from); to_byte = CHAR_TO_BYTE (to);
-  len_byte = to_byte - from_byte;
 
   if (! encodep && CODING_REQUIRE_DETECTION (coding))
     {
-      /* We must detect encoding of text and eol.  Even if detection
-         routines can't decide the encoding, we should not let them
-         undecided because the deeper decoding routine (decode_coding)
-         tries to detect the encodings in vain in that case.  */
+      /* We must detect encoding of text and eol format.  */
 
       if (from < GPT && to > GPT)
        move_gap_both (from, from_byte);
       if (coding->type == coding_type_undecided)
        {
-         detect_coding (coding, BYTE_POS_ADDR (from), len);
+         detect_coding (coding, BYTE_POS_ADDR (from_byte), len_byte);
          if (coding->type == coding_type_undecided)
+           /* It seems that the text contains only ASCII, but we
+              should not left it undecided because the deeper
+              decoding routine (decode_coding) tries to detect the
+              encodings again in vain.  */
            coding->type = coding_type_emacs_mule;
        }
       if (coding->eol_type == CODING_EOL_UNDECIDED)
@@ -3866,22 +4008,45 @@ code_convert_region (from, to, coding, encodep, adjust)
        }
     }
 
+  coding->consumed_char = len, coding->consumed = len_byte;
+
   if (encodep
       ? ! CODING_REQUIRE_ENCODING (coding)
       : ! CODING_REQUIRE_DECODING (coding))
-    return len;
+    {
+      coding->produced = len_byte;
+      if (multibyte
+         && ! replace
+         /* See the comment of the member heading_ascii in coding.h.  */
+         && coding->heading_ascii < len_byte)
+       {
+         /* We still may have to combine byte at the head and the
+             tail of the text in the region.  */
+         if (from < GPT && GPT < to)
+           move_gap_both (to, to_byte);
+         len = multibyte_chars_in_text (BYTE_POS_ADDR (from_byte), len_byte);
+         adjust_after_insert (from, from_byte, to, to_byte, len);
+         coding->produced_char = len;
+       }
+      else
+       {
+         if (!replace)
+           adjust_after_insert (from, from_byte, to, to_byte, len_byte);
+         coding->produced_char = len_byte;
+       }
+      return 0;
+    }
 
   /* Now we convert the text.  */
 
   /* For encoding, we must process pre-write-conversion in advance.  */
   if (encodep
-      && adjust
       && ! NILP (coding->pre_write_conversion)
       && SYMBOLP (coding->pre_write_conversion)
       && ! NILP (Ffboundp (coding->pre_write_conversion)))
     {
-      /* The function in pre-write-conversion put a new text in a new
-         buffer.  */
+      /* The function in pre-write-conversion may put a new text in a
+         new buffer.  */
       struct buffer *prev = current_buffer, *new;
 
       call2 (coding->pre_write_conversion, from, to);
@@ -3890,80 +4055,100 @@ code_convert_region (from, to, coding, encodep, adjust)
          len = ZV - BEGV;
          new = current_buffer;
          set_buffer_internal_1 (prev);
-         del_range (from, to);
+         del_range_2 (from, from_byte, to, to_byte);
          insert_from_buffer (new, BEG, len, 0);
          to = from + len;
-         to_byte = CHAR_TO_BYTE (to);
+         to_byte = multibyte ? CHAR_TO_BYTE (to) : to;
          len_byte = to_byte - from_byte;
        }
     }
 
+  if (replace)
+    deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1);
+
   /* Try to skip the heading and tailing ASCIIs.  */
-  from_byte_orig = from_byte; to_byte_orig = to_byte;
-  if (encodep)
-    shrink_encoding_region (&from_byte, &to_byte, coding, NULL);
-  else
-    shrink_decoding_region (&from_byte, &to_byte, coding, NULL);
-  if (from_byte == to_byte)
-    return len;
-  /* Here, the excluded region by shrinking contains only ASCIIs.  */
-  from += (from_byte - from_byte_orig);
-  to += (to_byte - to_byte_orig);
-  len = to - from;
-  len_byte = to_byte - from_byte;
-
-  /* For converion, we must put the gap before the text to be decoded
-     in addition to make the gap larger for efficient decoding.  The
-     required gap size starts from 2000 which is the magic number used
-     in make_gap.  But, after one batch of conversion, it will be
-     incremented if we find that it is not enough .  */
+  {
+    int from_byte_orig = from_byte, to_byte_orig = to_byte;
+
+    if (from < GPT && GPT < to)
+      move_gap_both (from, from_byte);
+    if (encodep)
+      shrink_encoding_region (&from_byte, &to_byte, coding, NULL);
+    else
+      shrink_decoding_region (&from_byte, &to_byte, coding, NULL);
+    if (from_byte == to_byte)
+      {
+       coding->produced = len_byte;
+       coding->produced_char = multibyte ? len : len_byte;
+       if (!replace)
+         /* We must record and adjust for this new text now.  */
+         adjust_after_insert (from, from_byte_orig, to, to_byte_orig, len);
+       return 0;
+      }
+
+    head_skip = from_byte - from_byte_orig;
+    tail_skip = to_byte_orig - to_byte;
+    total_skip = head_skip + tail_skip;
+    from += head_skip;
+    to -= tail_skip;
+    len -= total_skip; len_byte -= total_skip;
+  }
+
+  /* For converion, we must put the gap before the text in addition to
+     making the gap larger for efficient decoding.  The required gap
+     size starts from 2000 which is the magic number used in make_gap.
+     But, after one batch of conversion, it will be incremented if we
+     find that it is not enough .  */
   require = 2000;
 
   if (GAP_SIZE  < require)
     make_gap (require - GAP_SIZE);
   move_gap_both (from, from_byte);
 
-  if (adjust)
-    adjust_before_replace (from, from_byte, to, to_byte);
-
   if (GPT - BEG < beg_unchanged)
     beg_unchanged = GPT - BEG;
   if (Z - GPT < end_unchanged)
     end_unchanged = Z - GPT;
 
   inserted = inserted_byte = 0;
+  src = GAP_END_ADDR, dst = GPT_ADDR;
+
+  GAP_SIZE += len_byte;
+  ZV -= len;
+  Z -= len;
+  ZV_BYTE -= len_byte;
+  Z_BYTE -= len_byte;
+
   for (;;)
     {
-      int result, diff_char, diff_byte;
+      int result;
 
       /* The buffer memory is changed from:
-        +--------+converted-text+------------+-----original-text-----+---+
-        |<-from->|<--inserted-->|<-GAP_SIZE->|<---------len--------->|---|  */
-
+        +--------+converted-text+---------+-------original-text------+---+
+        |<-from->|<--inserted-->|---------|<-----------len---------->|---|
+                 |<------------------- GAP_SIZE -------------------->|  */
       if (encodep)
-       result = encode_coding (coding, GAP_END_ADDR, GPT_ADDR, len_byte, 0);
+       result = encode_coding (coding, src, dst, len_byte, 0);
       else
-       result = decode_coding (coding, GAP_END_ADDR, GPT_ADDR, len_byte, 0);
+       result = decode_coding (coding, src, dst, len_byte, 0);
       /* to:
         +--------+-------converted-text--------+--+---original-text--+---+
-        |<-from->|<----(inserted+produced)---->|--|<-(len-consumed)->|---|  */
-
-      diff_char = coding->produced_char - coding->consumed_char;
-      diff_byte = coding->produced - coding->consumed;
-
-      GAP_SIZE -= diff_byte;
-      ZV += diff_char; ZV_BYTE += diff_byte;
-      Z += diff_char; Z_BYTE += diff_byte;
-      GPT += coding->produced_char; GPT_BYTE += coding->produced;
+        |<-from->|<--inserted-->|<--produced-->|--|<-(len-consumed)->|---|
+                 |<------------------- GAP_SIZE -------------------->|  */
+      if (coding->fake_multibyte)
+       fake_multibyte = 1;
 
+      if (!encodep && !multibyte)
+       coding->produced_char = coding->produced;
       inserted += coding->produced_char;
       inserted_byte += coding->produced;
-      len -= coding->consumed_char;
       len_byte -= coding->consumed;
+      src += coding->consumed;
+      dst += inserted_byte;
 
       if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL)
        {
-         unsigned char *p = GPT_ADDR - inserted_byte, *pend = GPT_ADDR;
+         unsigned char *pend = dst, *p = pend - inserted_byte;
 
          /* Encode LFs back to the original eol format (CR or CRLF).  */
          if (coding->eol_type == CODING_EOL_CR)
@@ -3972,24 +4157,39 @@ code_convert_region (from, to, coding, encodep, adjust)
            }
          else
            {
-             unsigned char *p2 = p;
              int count = 0;
 
-             while (p2 < pend) if (*p2++ == '\n') count++;
-             if (GAP_SIZE < count)
-               make_gap (count - GAP_SIZE);
-             p2 = GPT_ADDR + count;
-             while (p < pend)
+             while (p < pend) if (*p++ == '\n') count++;
+             if (src - dst < count)
                {
-                 *--p2 = *--pend;
-                 if (*pend == '\n') *--p2 = '\r';
+                 /* We don't have sufficient room for putting LFs
+                    back to CRLF.  We must record converted and
+                    not-yet-converted text back to the buffer
+                    content, enlarge the gap, then record them out of
+                    the buffer contents again.  */
+                 int add = len_byte + inserted_byte;
+
+                 GAP_SIZE -= add;
+                 ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add;
+                 GPT += inserted_byte; GPT_BYTE += inserted_byte;
+                 make_gap (count - GAP_SIZE);
+                 GAP_SIZE += add;
+                 ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add;
+                 GPT -= inserted_byte; GPT_BYTE -= inserted_byte;
+                 /* Don't forget to update SRC, DST, and PEND.  */
+                 src = GAP_END_ADDR - len_byte;
+                 dst = GPT_ADDR + inserted_byte;
+                 pend = dst;
                }
-             GPT += count; GAP_SIZE -= count; ZV += count; Z += count;
-             ZV_BYTE += count; Z_BYTE += count;
-             coding->produced += count;
-             coding->produced_char += count;
              inserted += count;
              inserted_byte += count;
+             coding->produced += count;
+             p = dst = pend + count;
+             while (count)
+               {
+                 *--p = *--pend;
+                 if (*p == '\n') count--, *--p = '\r';
+               }
            }
 
          /* Suppress eol-format conversion in the further conversion.  */
@@ -3997,6 +4197,8 @@ code_convert_region (from, to, coding, encodep, adjust)
 
          /* Restore the original symbol.  */
          coding->symbol = saved_coding_symbol;
+         
+         continue;
        }
       if (len_byte <= 0)
        break;
@@ -4004,50 +4206,97 @@ code_convert_region (from, to, coding, encodep, adjust)
        {
          /* The source text ends in invalid codes.  Let's just
             make them valid buffer contents, and finish conversion.  */
-         inserted += len;
+         inserted += len_byte;
          inserted_byte += len_byte;
+         while (len_byte--)
+           *src++ = *dst++;
+         fake_multibyte = 1;
          break;
        }
-      if (inserted == coding->produced_char)
-       /* We have just done the first batch of conversion.  Let's
-          reconsider the required gap size now.
-
-          We have converted CONSUMED bytes into PRODUCED bytes.  To
-          convert the remaining LEN bytes, we may need REQUIRE bytes
-          of gap, where:
-              REQUIRE + LEN = (LEN * PRODUCED / CONSUMED)
-              REQUIRE = LEN * (PRODUCED - CONSUMED) / CONSUMED
-                      = LEN * DIFF / CONSUMED
-          Here, we are sure that DIFF is positive.  */
-       require = len_byte * diff_byte / coding->consumed;
-      if (GAP_SIZE  < require)
-       make_gap (require - GAP_SIZE);
+      if (first)
+       {
+         /* We have just done the first batch of conversion which was
+            stoped because of insufficient gap.  Let's reconsider the
+            required gap size (i.e. SRT - DST) now.
+
+            We have converted ORIG bytes (== coding->consumed) into
+            NEW bytes (coding->produced).  To convert the remaining
+            LEN bytes, we may need REQUIRE bytes of gap, where:
+               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;
+         first = 0;
+       }
+      if ((src - dst) < (require + 2000))
+       {
+         /* See the comment above the previous call of make_gap.  */
+         int add = len_byte + inserted_byte;
+
+         GAP_SIZE -= add;
+         ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add;
+         GPT += inserted_byte; GPT_BYTE += inserted_byte;
+         make_gap (require + 2000);
+         GAP_SIZE += add;
+         ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add;
+         GPT -= inserted_byte; GPT_BYTE -= inserted_byte;
+         /* Don't forget to update SRC, DST.  */
+         src = GAP_END_ADDR - len_byte;
+         dst = GPT_ADDR + inserted_byte;
+       }
     }
-  if (GAP_SIZE > 0) *GPT_ADDR = 0; /* Put an anchor.  */
+  if (src - dst > 0) *dst = 0; /* Put an anchor.  */
 
-  if (adjust)
+  if (multibyte
+      && (fake_multibyte
+         || !encodep && (to - from) != (to_byte - from_byte)))
+    inserted = multibyte_chars_in_text (GPT_ADDR, inserted_byte);
+
+  /* If we have shrinked the conversion area, adjust it now.  */ 
+  if (total_skip > 0)
     {
-      adjust_after_replace (from, from_byte, to, to_byte,
-                           inserted, inserted_byte);
+      if (tail_skip > 0)
+       safe_bcopy (GAP_END_ADDR, GPT_ADDR + inserted_byte, tail_skip);
+      inserted += total_skip; inserted_byte += total_skip;
+      GAP_SIZE += total_skip;
+      GPT -= head_skip; GPT_BYTE -= head_skip;
+      ZV -= total_skip; ZV_BYTE -= total_skip;
+      Z -= total_skip; Z_BYTE -= total_skip;
+      from -= head_skip; from_byte -= head_skip;
+      to += tail_skip; to_byte += tail_skip;
+    }
 
-      if (! encodep && ! NILP (coding->post_read_conversion))
-       {
-         Lisp_Object val;
-         int orig_inserted = inserted, pos = PT;
+  adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte);
 
-         temp_set_point_both (current_buffer, from, from_byte);
-         val = call1 (coding->post_read_conversion, make_number (inserted));
-         if (! NILP (val))
-           {
-             CHECK_NUMBER (val, 0);
-             inserted = XFASTINT (val);
-           }
-         if (pos >= from + orig_inserted)
-           temp_set_point (current_buffer, pos + (inserted - orig_inserted));
+  if (! encodep && ! NILP (coding->post_read_conversion))
+    {
+      Lisp_Object val;
+      int orig_inserted = inserted, pos = PT;
+
+      if (from != pos)
+       temp_set_point_both (current_buffer, from, from_byte);
+      val = call1 (coding->post_read_conversion, make_number (inserted));
+      if (! NILP (val))
+       {
+         CHECK_NUMBER (val, 0);
+         inserted = XFASTINT (val);
        }
+      if (pos >= from + orig_inserted)
+       temp_set_point (current_buffer, pos + (inserted - orig_inserted));
     }
 
-  return ((from_byte - from_byte_orig) + inserted + (to_byte_orig - to_byte));
+  signal_after_change (from, to - from, inserted);
+
+  {
+    coding->consumed = to_byte - from_byte;
+    coding->consumed_char = to - from;
+    coding->produced = inserted_byte;
+    coding->produced_char = inserted;
+  }
+
+  return 0;
 }
 
 Lisp_Object
@@ -4058,7 +4307,8 @@ code_convert_string (str, coding, encodep, nocopy)
 {
   int len;
   char *buf;
-  int from = 0, to = XSTRING (str)->size, to_byte = XSTRING (str)->size_byte;
+  int from = 0, to = XSTRING (str)->size;
+  int to_byte = STRING_BYTES (XSTRING (str));
   struct gcpro gcpro1;
   Lisp_Object saved_coding_symbol = Qnil;
   int result;
@@ -4085,7 +4335,7 @@ code_convert_string (str, coding, encodep, nocopy)
          insert_from_string (str, 0, 0, to_byte, to_byte, 0);
          current_buffer->enable_multibyte_characters = Qt;
        }
-      code_convert_region (BEGV, ZV, coding, encodep, 1);
+      code_convert_region (BEGV, BEGV_BYTE, ZV, ZV_BYTE, coding, encodep, 1);
       if (encodep)
        /* We must return the buffer contents as unibyte string.  */
        current_buffer->enable_multibyte_characters = Qnil;
@@ -4134,7 +4384,7 @@ code_convert_string (str, coding, encodep, nocopy)
     len = encoding_buffer_size (coding, to_byte - from);
   else
     len = decoding_buffer_size (coding, to_byte - from);
-  len += from + XSTRING (str)->size_byte - to_byte;
+  len += from + STRING_BYTES (XSTRING (str)) - to_byte;
   GCPRO1 (str);
   buf = get_conversion_buffer (len);
   UNGCPRO;
@@ -4145,7 +4395,7 @@ code_convert_string (str, coding, encodep, nocopy)
            ? encode_coding (coding, XSTRING (str)->data + from,
                             buf + from, to_byte - from, len)
            : decode_coding (coding, XSTRING (str)->data + from,
-                            buf + from, to - from, len));
+                            buf + from, to_byte - from, len));
   if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL)
     {
       /* We simple try to decode the whole string again but without
@@ -4156,14 +4406,14 @@ code_convert_string (str, coding, encodep, nocopy)
     }
 
   bcopy (XSTRING (str)->data + to_byte, buf + from + coding->produced,
-        XSTRING (str)->size_byte - to_byte);
+        STRING_BYTES (XSTRING (str)) - to_byte);
 
-  len = from + XSTRING (str)->size_byte - to_byte;
+  len = from + STRING_BYTES (XSTRING (str)) - to_byte;
   if (encodep)
     str = make_unibyte_string (buf, len + coding->produced);
   else
-    str = make_multibyte_string (buf, len + coding->produced_char,
-                                len + coding->produced);
+    str = make_string_from_bytes (buf, len + coding->produced_char,
+                                 len + coding->produced);
   return str;
 }
 
@@ -4340,21 +4590,17 @@ highest priority.")
   CHECK_STRING (string, 0);
 
   return detect_coding_system (XSTRING (string)->data,
-                              XSTRING (string)->size_byte,
+                              STRING_BYTES (XSTRING (string)),
                               !NILP (highest));
 }
 
-DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region,
-       3, 3, "r\nzCoding system: ",
-  "Decode the current region by 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\
-Return length of decoded text.")
-  (start, end, coding_system)
+Lisp_Object
+code_convert_region1 (start, end, coding_system, encodep)
      Lisp_Object start, end, coding_system;
+     int encodep;
 {
   struct coding_system coding;
-  int from, to;
+  int from, to, len;
 
   CHECK_NUMBER_COERCE_MARKER (start, 0);
   CHECK_NUMBER_COERCE_MARKER (end, 1);
@@ -4371,7 +4617,21 @@ Return length of decoded text.")
     error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data);
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
-  return code_convert_region (from, to, &coding, 0, 1);
+  code_convert_region (from, CHAR_TO_BYTE (from), to, CHAR_TO_BYTE (to),
+                      &coding, encodep, 1);
+  return make_number (coding.produced_char);
+}
+
+DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region,
+       3, 3, "r\nzCoding system: ",
+  "Decode the current region by 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\
+Return length of decoded text.")
+  (start, end, coding_system)
+     Lisp_Object start, end, coding_system;
+{
+  return code_convert_region1 (start, end, coding_system, 0);
 }
 
 DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region,
@@ -4383,25 +4643,27 @@ Return length of encoded text.")
   (start, end, coding_system)
      Lisp_Object start, end, coding_system;
 {
-  struct coding_system coding;
-  int from, to;
+  return code_convert_region1 (start, end, coding_system, 1);
+}
 
-  CHECK_NUMBER_COERCE_MARKER (start, 0);
-  CHECK_NUMBER_COERCE_MARKER (end, 1);
-  CHECK_SYMBOL (coding_system, 2);
+Lisp_Object
+code_convert_string1 (string, coding_system, nocopy, encodep)
+     Lisp_Object string, coding_system, nocopy;
+     int encodep;
+{
+  struct coding_system coding;
 
-  validate_region (&start, &end);
-  from = XFASTINT (start);
-  to = XFASTINT (end);
+  CHECK_STRING (string, 0);
+  CHECK_SYMBOL (coding_system, 1);
 
   if (NILP (coding_system))
-    return make_number (to - from);
+    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);
 
   coding.mode |= CODING_MODE_LAST_BLOCK;
-  return code_convert_region (from, to, &coding, 1, 1);
+  return code_convert_string (string, &coding, encodep, !NILP (nocopy));
 }
 
 DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string,
@@ -4412,19 +4674,7 @@ if the decoding operation is trivial.")
   (string, coding_system, nocopy)
      Lisp_Object string, coding_system, nocopy;
 {
-  struct coding_system coding;
-
-  CHECK_STRING (string, 0);
-  CHECK_SYMBOL (coding_system, 1);
-
-  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);
-
-  coding.mode |= CODING_MODE_LAST_BLOCK;
-  return code_convert_string (string, &coding, 0, !NILP (nocopy));
+  return code_convert_string1(string, coding_system, nocopy, 0);
 }
 
 DEFUN ("encode-coding-string", Fencode_coding_string, Sencode_coding_string,
@@ -4435,20 +4685,9 @@ if the encoding operation is trivial.")
   (string, coding_system, nocopy)
      Lisp_Object string, coding_system, nocopy;
 {
-  struct coding_system coding;
-
-  CHECK_STRING (string, 0);
-  CHECK_SYMBOL (coding_system, 1);
-
-  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);
-
-  coding.mode |= CODING_MODE_LAST_BLOCK;
-  return code_convert_string (string, &coding, 1, !NILP (nocopy));
+  return code_convert_string1(string, coding_system, nocopy, 1);
 }
+
 \f
 DEFUN ("decode-sjis-char", Fdecode_sjis_char, Sdecode_sjis_char, 1, 1, 0,
   "Decode a JISX0208 character of shift-jis encoding.\n\
@@ -4705,6 +4944,7 @@ call this function:\n\
 \f
 /*** 8. Post-amble ***/
 
+void
 init_coding_once ()
 {
   int i;
@@ -4763,6 +5003,7 @@ init_coding_once ()
 
 #ifdef emacs
 
+void
 syms_of_coding ()
 {
   Qtarget_idx = intern ("target-idx");