(cmpchar_component): New arg NOERROR. Check
[bpt/emacs.git] / src / charset.c
index 0017ac1..41b9018 100644 (file)
@@ -74,9 +74,14 @@ Lisp_Object Vcharset_symbol_table;
 /* A list of charset symbols ever defined.  */
 Lisp_Object Vcharset_list;
 
-/* Vector of character translation table ever defined.
-   ID of a character translation table is used to index this vector.  */
-Lisp_Object Vcharacter_translation_table_vector;
+/* Vector of translation table ever defined.
+   ID of a translation table is used to index this vector.  */
+Lisp_Object Vtranslation_table_vector;
+
+/* A char-table for characters which may invoke auto-filling.  */
+Lisp_Object Vauto_fill_chars;
+
+Lisp_Object Qauto_fill_chars;
 
 /* Tables used by macros BYTES_BY_CHAR_HEAD and WIDTH_BY_CHAR_HEAD.  */
 int bytes_by_char_head[256];
@@ -105,6 +110,9 @@ int nonascii_insert_offset;
    to multibyte codes, or nil.  */
 Lisp_Object Vnonascii_translation_table;
 
+/* List of all possible generic characters.  */
+Lisp_Object Vgeneric_character_list;
+
 #define min(X, Y) ((X) < (Y) ? (X) : (Y))
 #define max(X, Y) ((X) > (Y) ? (X) : (Y))
 \f
@@ -112,7 +120,7 @@ void
 invalid_character (c)
      int c;
 {
-  error ("Invalid character: %o, %d, 0x%x", c);
+  error ("Invalid character: 0%o, %d, 0x%x", c, c, c);
 }
 
 
@@ -168,53 +176,69 @@ non_ascii_char_to_string (c, workbuf, str)
 
 /* Return a non-ASCII character of which multi-byte form is at STR of
    length LEN.  If ACTUAL_LEN is not NULL, the actual length of the
-   character is set to the address ACTUAL_LEN.
+   multibyte form is set to the address ACTUAL_LEN.
+
+   If exclude_tail_garbage is nonzero, ACTUAL_LEN excludes gabage
+   bytes following the non-ASCII character.
 
    Use macro `STRING_CHAR (STR, LEN)' instead of calling this function
    directly if STR can hold an ASCII character.  */
 
 int
-string_to_non_ascii_char (str, len, actual_len)
+string_to_non_ascii_char (str, len, actual_len, exclude_tail_garbage)
      const unsigned char *str;
-     int len, *actual_len;
+     int len, *actual_len, exclude_tail_garbage;
 {
   int charset;
   unsigned char c1, c2;
-  register int c, bytes;
+  int c, bytes;
+  const unsigned char *begp = str;
 
-  c = *str;
+  c = *str++;
   bytes = 1;
 
   if (BASE_LEADING_CODE_P (c))
-    {
-      while (bytes < len && ! CHAR_HEAD_P (str[bytes])) bytes++;
+    do {
+      while (bytes < len && ! CHAR_HEAD_P (begp[bytes])) bytes++;
 
       if (c == LEADING_CODE_COMPOSITION)
        {
-         int cmpchar_id = str_cmpchar_id (str, bytes);
+         int cmpchar_id = str_cmpchar_id (begp, bytes);
 
          if (cmpchar_id >= 0)
-           c = MAKE_COMPOSITE_CHAR (cmpchar_id);
+           {
+             c = MAKE_COMPOSITE_CHAR (cmpchar_id);
+             str += cmpchar_table[cmpchar_id]->len - 1;
+           }
+         else
+           str += bytes - 1;
        }
       else
        {
+         const unsigned char *endp = begp + bytes;
          int charset = c, c1, c2 = 0;
 
-         str++;
-         if (c >= LEADING_CODE_PRIVATE_11)
-           charset = *str++;
-         if (BYTES_BY_CHAR_HEAD (c) <= bytes && CHARSET_DEFINED_P (charset))
+         if (str >= endp) break;
+         if (c >= LEADING_CODE_PRIVATE_11 && c <= LEADING_CODE_PRIVATE_22)
            {
-             c1 = *str++ & 0x7f;
-             if (CHARSET_DIMENSION (charset) == 2)
-               c2 = *str & 0x7F;
-             c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
+             charset = *str++;
+             if (str < endp)
+               c1 = *str++ & 0x7F;
+             else
+               c1 = charset, charset = c;
            }
+         else
+           c1 = *str++ & 0x7f;
+         if (CHARSET_DEFINED_P (charset)
+             && CHARSET_DIMENSION (charset) == 2
+             && str < endp)
+           c2 = *str++ & 0x7F;
+         c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
        }
-    }
+    } while (0);
 
   if (actual_len)
-    *actual_len = bytes;
+    *actual_len = exclude_tail_garbage ? str - begp : bytes;
   return c;
 }
 
@@ -273,7 +297,7 @@ split_non_ascii_string (str, len, charset, c1, c2)
   return 0;
 }
 
-/* Translate character C by character translation table TABLE.  If C
+/* Translate character C by translation table TABLE.  If C
    is negative, translate a character specified by CHARSET, C1, and C2
    (C1 and C2 are code points of the character).  If no translation is
    found in TABLE, return C.  */
@@ -316,19 +340,69 @@ int
 unibyte_char_to_multibyte (c)
      int c;
 {
-  if (c >= 0240 && c < 0400)
+  if (c < 0400)
     {
       int c_save = c;
 
       if (! NILP (Vnonascii_translation_table))
-       c = XINT (Faref (Vnonascii_translation_table, make_number (c)));
-      else if (nonascii_insert_offset > 0)
-       c += nonascii_insert_offset;
-      if (c >= 0240 && (c < 0400 || ! VALID_MULTIBYTE_CHAR_P (c)))
+       {
+         c = XINT (Faref (Vnonascii_translation_table, make_number (c)));
+         if (c >= 0400 && ! VALID_MULTIBYTE_CHAR_P (c))
+           c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
+       }
+      else if (c >= 0240 && nonascii_insert_offset > 0)
+       {
+         c += nonascii_insert_offset;
+         if (c < 0400 || ! VALID_MULTIBYTE_CHAR_P (c))
+           c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
+       }
+      else if (c >= 0240)
        c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
     }
   return c;
 }
+
+
+/* Convert the multibyte character C to unibyte 8-bit character based
+   on Vnonascii_translation_table or nonascii_insert_offset.  If
+   REV_TBL is non-nil, it should be a reverse table of
+   Vnonascii_translation_table, i.e. what given by:
+     Fchar_table_extra_slot (Vnonascii_translation_table, make_number (0))  */
+
+int
+multibyte_char_to_unibyte (c, rev_tbl)
+     int c;
+     Lisp_Object rev_tbl;
+{
+  if (!SINGLE_BYTE_CHAR_P (c))
+    {
+      int c_save = c;
+
+      if (! CHAR_TABLE_P (rev_tbl)
+         && CHAR_TABLE_P (Vnonascii_translation_table))
+       rev_tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
+                                         make_number (0));
+      if (CHAR_TABLE_P (rev_tbl))
+       {
+         Lisp_Object temp;
+         temp = Faref (rev_tbl, make_number (c));
+         if (INTEGERP (temp))
+           c = XINT (temp);
+         if (c >= 256)
+           c = (c_save & 0177) + 0200;
+       }
+      else
+       {
+         if (nonascii_insert_offset > 0)
+           c -= nonascii_insert_offset;
+         if (c < 128 || c >= 256)
+           c = (c_save & 0177) + 0200;
+       }
+    }
+
+  return c;
+}
+
 \f
 /* Update the table Vcharset_table with the given arguments (see the
    document of `define-charset' for the meaning of each argument).
@@ -379,6 +453,9 @@ update_charset_table (charset_id, dimension, chars, width, direction,
       leading_code_ext = charset;
     } 
 
+  if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes)
+    error ("Invalid dimension for the charset-ID %d", charset);
+
   CHARSET_TABLE_INFO (charset, CHARSET_ID_IDX) = charset_id;
   CHARSET_TABLE_INFO (charset, CHARSET_BYTES_IDX) = make_number (bytes);
   CHARSET_TABLE_INFO (charset, CHARSET_DIMENSION_IDX) = dimension;
@@ -428,8 +505,6 @@ update_charset_table (charset_id, dimension, chars, width, direction,
   if (charset != CHARSET_ASCII
       && charset < MIN_CHARSET_PRIVATE_DIMENSION1)
     {
-      /* Update tables bytes_by_char_head and width_by_char_head.  */
-      bytes_by_char_head[leading_code_base] = bytes;
       width_by_char_head[leading_code_base] = XINT (width);
 
       /* Update table emacs_code_class.  */
@@ -507,8 +582,8 @@ WIDTH (integer) is the number of columns a character in the charset\n\
 occupies on the screen: one of 0, 1, and 2.\n\
 \n\
 DIRECTION (integer) is the rendering direction of characters in the\n\
-charset when rendering.  If 0, render from right to left, else\n\
-render from left to right.\n\
+charset when rendering.  If 0, render from left to right, else\n\
+render from right to left.\n\
 \n\
 ISO-FINAL-CHAR (character) is the final character of the\n\
 corresponding ISO 2022 charset.\n\
@@ -570,6 +645,15 @@ DESCRIPTION (string) is the description string of the charset.")
   return Qnil;
 }
 
+DEFUN ("generic-character-list", Fgeneric_character_list,
+       Sgeneric_character_list, 0, 0, 0,
+  "Return a list of all possible generic characters.\n\
+It includes a generic character for a charset not yet defined.")
+  ()
+{
+  return Vgeneric_character_list;
+}
+
 DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,
        Sget_unused_iso_final_char, 2, 2, 0,
   "Return an unsed ISO's final char for a charset of DIMENISION and CHARS.\n\
@@ -630,13 +714,18 @@ CHARSET should be defined by `defined-charset' in advance.")
 /* Return number of different charsets in STR of length LEN.  In
    addition, for each found charset N, CHARSETS[N] is set 1.  The
    caller should allocate CHARSETS (MAX_CHARSET + 1 elements) in advance.
-   It may lookup a translation table TABLE if supplied.  */
+   It may lookup a translation table TABLE if supplied.
+
+   If CMPCHARP is nonzero and some composite character is found,
+   CHARSETS[128] is also set 1 and the returned number is incremented
+   by 1.  */
 
 int
-find_charset_in_str (str, len, charsets, table)
+find_charset_in_str (str, len, charsets, table, cmpcharp)
      unsigned char *str;
      int len, *charsets;
      Lisp_Object table;
+     int cmpcharp;
 {
   register int num = 0, c;
 
@@ -653,18 +742,18 @@ find_charset_in_str (str, len, charsets, table)
          int cmpchar_id = str_cmpchar_id (str, len);
          GLYPH *glyph;
 
-         if (cmpchar_id > 0)
+         if (cmpchar_id >= 0)
            {
-             struct cmpchar_info *cmpcharp = cmpchar_table[cmpchar_id];
+             struct cmpchar_info *cmp_p = cmpchar_table[cmpchar_id];
              int i;
 
-             for (i = 0; i < cmpcharp->glyph_len; i++)
+             for (i = 0; i < cmp_p->glyph_len; i++)
                {
-                 c = cmpcharp->glyph[i];
+                 c = cmp_p->glyph[i];
                  if (!NILP (table))
                    {
                      if ((c = translate_char (table, c, 0, 0, 0)) < 0)
-                       c = cmpcharp->glyph[i];
+                       c = cmp_p->glyph[i];
                    }
                  if ((charset = CHAR_CHARSET (c)) < 0)
                    charset = CHARSET_ASCII;
@@ -674,8 +763,13 @@ find_charset_in_str (str, len, charsets, table)
                      num += 1;
                    }
                }
-             str += cmpcharp->len;
-             len -= cmpcharp->len;
+             str += cmp_p->len;
+             len -= cmp_p->len;
+             if (cmpcharp && !charsets[CHARSET_COMPOSITION])
+               {
+                 charsets[CHARSET_COMPOSITION] = 1;
+                 num += 1;
+               }
              continue;
            }
 
@@ -709,6 +803,8 @@ DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region,
        2, 3, 0,
   "Return a list of charsets in the region between BEG and END.\n\
 BEG and END are buffer positions.\n\
+If the region contains any composite character,\n\
+`composition' is included in the returned list.\n\
 Optional arg TABLE if non-nil is a translation table to look up.")
   (beg, end, table)
      Lisp_Object beg, end, table;
@@ -721,6 +817,11 @@ Optional arg TABLE if non-nil is a translation table to look up.")
   from = XFASTINT (beg);
   stop = to = XFASTINT (end);
 
+  if (NILP (current_buffer->enable_multibyte_characters))
+    return (from == to
+           ? Qnil
+           : Fcons (Qascii, Qnil));
+
   if (from < GPT && GPT < to)
     {
       stop = GPT;
@@ -735,7 +836,7 @@ Optional arg TABLE if non-nil is a translation table to look up.")
   while (1)
     {
       find_charset_in_str (BYTE_POS_ADDR (from_byte), stop_byte - from_byte,
-                          charsets, table);
+                          charsets, table, 1);
       if (stop < to)
        {
          from = stop, from_byte = stop_byte;
@@ -755,6 +856,8 @@ Optional arg TABLE if non-nil is a translation table to look up.")
 DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string,
        1, 2, 0,
   "Return a list of charsets in STR.\n\
+If the string contains any composite characters,\n\
+`composition' is included in the returned list.\n\
 Optional arg TABLE if non-nil is a translation table to look up.")
   (str, table)
      Lisp_Object str, table;
@@ -766,11 +869,13 @@ Optional arg TABLE if non-nil is a translation table to look up.")
   CHECK_STRING (str, 0);
 
   if (! STRING_MULTIBYTE (str))
-    return Qnil;
+    return (XSTRING (str)->size == 0
+           ? Qnil
+           : Fcons (Qascii, Qnil));
 
   bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
   find_charset_in_str (XSTRING (str)->data, STRING_BYTES (XSTRING (str)),
-                      charsets, table);
+                      charsets, table, 1);
   val = Qnil;
   for (i = MAX_CHARSET; i >= 0; i--)
     if (charsets[i])
@@ -887,7 +992,7 @@ char_valid_p (c, genericp)
   if (SINGLE_BYTE_CHAR_P (c))
     return 1;
   SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
-  if (!CHARSET_VALID_P (charset))
+  if (!CHARSET_DEFINED_P (charset))
     return 0;
   return (c < MIN_CHAR_COMPOSITION
          ? ((c & CHAR_FIELD1_MASK) /* i.e. dimension of C is two.  */
@@ -913,7 +1018,7 @@ a valid generic character.")
 DEFUN ("unibyte-char-to-multibyte", Funibyte_char_to_multibyte,
        Sunibyte_char_to_multibyte, 1, 1, 0,
   "Convert the unibyte character CH to multibyte character.\n\
-The conversion is done based on `nonascii-translate-table' (which see)\n\
+The conversion is done based on `nonascii-translation-table' (which see)\n\
  or `nonascii-insert-offset' (which see).")
   (ch)
      Lisp_Object ch;
@@ -930,30 +1035,60 @@ The conversion is done based on `nonascii-translate-table' (which see)\n\
   return make_number (c);
 }
 
+DEFUN ("multibyte-char-to-unibyte", Fmultibyte_char_to_unibyte,
+       Smultibyte_char_to_unibyte, 1, 1, 0,
+  "Convert the multibyte character CH to unibyte character.\n\
+The conversion is done based on `nonascii-translation-table' (which see)\n\
+ or `nonascii-insert-offset' (which see).")
+  (ch)
+     Lisp_Object ch;
+{
+  int c;
+
+  CHECK_NUMBER (ch, 0);
+  c = XINT (ch);
+  if (c < 0)
+    error ("Invalid multibyte character: %d", c);
+  c = multibyte_char_to_unibyte (c, Qnil);
+  if (c < 0)
+    error ("Can't convert to unibyte character: %d", XINT (ch));
+  return make_number (c);
+}
+
 DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0,
-  "Return byte length of multi-byte form of CHAR.")
+  "Return 1 regardless of the argument CHAR.\n\
+This is now an obsolete function.  We keep it just for backward compatibility.")
   (ch)
      Lisp_Object ch;
 {
   Lisp_Object val;
-  int bytes;
 
   CHECK_NUMBER (ch, 0);
-  if (COMPOSITE_CHAR_P (XFASTINT (ch)))
+  return make_number (1);
+}
+
+/* Return how many bytes C will occupy in a multibyte buffer.
+   Don't call this function directly, instead use macro CHAR_BYTES.  */
+int
+char_bytes (c)
+     int c;
+{
+  int bytes;
+
+  if (COMPOSITE_CHAR_P (c))
     {
-      unsigned int id = COMPOSITE_CHAR_ID (XFASTINT (ch));
+      unsigned int id = COMPOSITE_CHAR_ID (c);
 
       bytes = (id < n_cmpchars ? cmpchar_table[id]->len : 1);
     }
   else
     {
-      int charset = CHAR_CHARSET (XFASTINT (ch));
+      int charset = CHAR_CHARSET (c);
 
       bytes = CHARSET_DEFINED_P (charset) ? CHARSET_BYTES (charset) : 1;
     }
 
-  XSETFASTINT (val, bytes);
-  return val;
+  return bytes;
 }
 
 /* Return the width of character of which multi-byte form starts with
@@ -1101,6 +1236,9 @@ DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0,
 {
   int from, to;
 
+  CHECK_NUMBER_COERCE_MARKER (beg, 0);
+  CHECK_NUMBER_COERCE_MARKER (end, 1);
+
   from = min (XFASTINT (beg), XFASTINT (end));
   to = max (XFASTINT (beg), XFASTINT (end));
 
@@ -1194,7 +1332,9 @@ DEFUN ("string", Fstring, Sstring, 1, MANY, 0,
       p += len;
     }
 
-  val = make_string_from_bytes (buf, n, p - buf);
+  /* Here, we can't use make_string_from_bytes because of byte
+     combining problem.  */
+  val = make_string (buf, p - buf);
   return val;
 }
 
@@ -1391,7 +1531,7 @@ str_cmpchar_id (str, len)
            /* Make `bufp' point normal multi-byte form temporally.  */
            *bufp -= 0x20;
            cmpcharp->glyph[i]
-             = FAST_MAKE_GLYPH (string_to_non_ascii_char (bufp, 4, 0), 0);
+             = FAST_MAKE_GLYPH (string_to_non_ascii_char (bufp, 4, 0, 0), 0);
            width = WIDTH_BY_CHAR_HEAD (*bufp);
            *bufp += 0x20;
            bufp += BYTES_BY_CHAR_HEAD (*bufp - 0x20);
@@ -1457,16 +1597,27 @@ str_cmpchar_id (str, len)
   return n_cmpchars++;
 }
 
-/* Return the Nth element of the composite character C.  */
+/* Return the Nth element of the composite character C.  If NOERROR is
+   nonzero, return 0 on error condition (C is an invalid composite
+   charcter, or N is out of range). */
 int
-cmpchar_component (c, n)
-     unsigned int c, n;
+cmpchar_component (c, n, noerror)
+     int c, n, noerror;
 {
   int id = COMPOSITE_CHAR_ID (c);
 
-  if (id >= n_cmpchars         /* C is not a valid composite character.  */
-      || n >= cmpchar_table[id]->glyph_len) /* No such component.  */
-    return -1;
+  if (id < 0 || id >= n_cmpchars)
+    {
+      /* C is not a valid composite character.  */
+      if (noerror) return 0;
+      error ("Invalid composite character: %d", c)  ;
+    }
+  if (n >= cmpchar_table[id]->glyph_len)
+    {
+      /* No such component.  */
+      if (noerror) return 0;
+      args_out_of_range (make_number (c), make_number (n));
+    }
   /* No face data is stored in glyph code.  */
   return ((int) (cmpchar_table[id]->glyph[n]));
 }
@@ -1482,30 +1633,28 @@ DEFUN ("cmpcharp", Fcmpcharp, Scmpcharp, 1, 1, 0,
 
 DEFUN ("composite-char-component", Fcmpchar_component, Scmpchar_component,
        2, 2, 0,
-  "Return the IDXth component character of composite character CHARACTER.")
-  (character, idx)
-     Lisp_Object character, idx;
+  "Return the Nth component character of composite character CHARACTER.")
+  (character, n)
+     Lisp_Object character, n;
 {
-  int c;
+  int id;
 
   CHECK_NUMBER (character, 0);
-  CHECK_NUMBER (idx, 1);
-
-  if ((c = cmpchar_component (XINT (character), XINT (idx))) < 0)
-    args_out_of_range (character, idx);
+  CHECK_NUMBER (n, 1);
 
-  return make_number (c);
+  return (make_number (cmpchar_component (XINT (character), XINT (n), 0)));
 }
 
 DEFUN ("composite-char-composition-rule", Fcmpchar_cmp_rule, Scmpchar_cmp_rule,
        2, 2, 0,
-  "Return the Nth composition rule embedded in composite character CHARACTER.\n\
+  "Return the Nth composition rule of composite character CHARACTER.\n\
 The returned rule is for composing the Nth component\n\
-on the (N-1)th component.  If N is 0, the returned value is always 255.")
+on the (N-1)th component.\n\
+If CHARACTER should be composed relatively or N is 0, return 255.")
   (character, n)
      Lisp_Object character, n;
 {
-  int id, i;
+  int id;
 
   CHECK_NUMBER (character, 0);
   CHECK_NUMBER (n, 1);
@@ -1513,11 +1662,12 @@ on the (N-1)th component.  If N is 0, the returned value is always 255.")
   id = COMPOSITE_CHAR_ID (XINT (character));
   if (id < 0 || id >= n_cmpchars)
     error ("Invalid composite character: %d", XINT (character));
-  i = XINT (n);
-  if (i > cmpchar_table[id]->glyph_len)
+  if (XINT (n) < 0 || XINT (n) >= cmpchar_table[id]->glyph_len)
     args_out_of_range (character, n);
 
-  return make_number (cmpchar_table[id]->cmp_rule[i]);
+  return make_number (cmpchar_table[id]->cmp_rule
+                     ? cmpchar_table[id]->cmp_rule[XINT (n)]
+                     : 255);
 }
 
 DEFUN ("composite-char-composition-rule-p", Fcmpchar_cmp_rule_p,
@@ -1586,6 +1736,8 @@ DEFUN ("compose-string", Fcompose_string, Scompose_string,
              LEADING_CODE_COMPOSITION, keep the remaining bytes
              unchanged.  */
          p++;
+         if (*p == 255)
+           error ("Can't compose a rule-based composition character");
          ptemp = p;
          while (! CHAR_HEAD_P (*p)) p++;
          if (i + (p - ptemp) >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
@@ -1618,8 +1770,9 @@ int
 charset_id_internal (charset_name)
      char *charset_name;
 {
-  Lisp_Object val = Fget (intern (charset_name), Qcharset);
+  Lisp_Object val;
 
+  val= Fget (intern (charset_name), Qcharset);
   if (!VECTORP (val))
     error ("Charset %s is not defined", charset_name);
 
@@ -1647,6 +1800,7 @@ init_charset_once ()
 
   staticpro (&Vcharset_table);
   staticpro (&Vcharset_symbol_table);
+  staticpro (&Vgeneric_character_list);
 
   /* This has to be done here, before we call Fmake_char_table.  */
   Qcharset_table = intern ("charset-table");
@@ -1675,13 +1829,21 @@ init_charset_once ()
 
   for (i = 0; i < 256; i++)
     BYTES_BY_CHAR_HEAD (i) = 1;
+  for (i = MIN_CHARSET_OFFICIAL_DIMENSION1;
+       i <= MAX_CHARSET_OFFICIAL_DIMENSION1; i++)
+    BYTES_BY_CHAR_HEAD (i) = 2;
+  for (i = MIN_CHARSET_OFFICIAL_DIMENSION2;
+       i <= MAX_CHARSET_OFFICIAL_DIMENSION2; i++)
+    BYTES_BY_CHAR_HEAD (i) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_11) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_12) = 3;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_21) = 4;
   BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_22) = 4;
-  /* The following doesn't reflect the actual bytes, but just to tell
+  /* The followings don't reflect the actual bytes, but just to tell
      that it is a start of a multibyte character.  */
   BYTES_BY_CHAR_HEAD (LEADING_CODE_COMPOSITION) = 2;
+  BYTES_BY_CHAR_HEAD (0x9E) = 2;
+  BYTES_BY_CHAR_HEAD (0x9F) = 2;
 
   for (i = 0; i < 128; i++)
     WIDTH_BY_CHAR_HEAD (i) = 1;
@@ -1691,6 +1853,25 @@ init_charset_once ()
   WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_12) = 2;
   WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_21) = 1;
   WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_22) = 2;
+
+  {
+    Lisp_Object val;
+
+    val = Qnil;
+    for (i = 0x81; i < 0x90; i++)
+      val = Fcons (make_number ((i - 0x70) << 7), val);
+    for (; i < 0x9A; i++)
+      val = Fcons (make_number ((i - 0x8F) << 14), val);
+    for (i = 0xA0; i < 0xF0; i++)
+      val = Fcons (make_number ((i - 0x70) << 7), val);
+    for (; i < 0xFF; i++)
+      val = Fcons (make_number ((i - 0xE0) << 14), val);
+    val = Fcons (make_number (GENERIC_COMPOSITION_CHAR), val);
+    Vgeneric_character_list = Fnreverse (val);
+  }
+
+  nonascii_insert_offset = 0;
+  Vnonascii_translation_table = Qnil;
 }
 
 #ifdef emacs
@@ -1721,7 +1902,12 @@ syms_of_charset ()
   staticpro (&Qcomposition);
   CHARSET_SYMBOL (CHARSET_COMPOSITION) = Qcomposition;
 
+  Qauto_fill_chars = intern ("auto-fill-chars");
+  staticpro (&Qauto_fill_chars);
+  Fput (Qauto_fill_chars, Qchar_table_extra_slots, make_number (0));
+
   defsubr (&Sdefine_charset);
+  defsubr (&Sgeneric_character_list);
   defsubr (&Sget_unused_iso_final_char);
   defsubr (&Sdeclare_equiv_charset);
   defsubr (&Sfind_charset_region);
@@ -1733,6 +1919,7 @@ syms_of_charset ()
   defsubr (&Siso_charset);
   defsubr (&Schar_valid_p);
   defsubr (&Sunibyte_char_to_multibyte);
+  defsubr (&Smultibyte_char_to_unibyte);
   defsubr (&Schar_bytes);
   defsubr (&Schar_width);
   defsubr (&Sstring_width);
@@ -1751,11 +1938,10 @@ syms_of_charset ()
     "List of charsets ever defined.");
   Vcharset_list = Fcons (Qascii, Qnil);
 
-  DEFVAR_LISP ("character-translation-table-vector",
-              &Vcharacter_translation_table_vector,
+  DEFVAR_LISP ("translation-table-vector",  &Vtranslation_table_vector,
     "Vector of cons cell of a symbol and translation table ever defined.\n\
 An ID of a translation table is an index of this vector.");
-  Vcharacter_translation_table_vector = Fmake_vector (make_number (16), Qnil);
+  Vtranslation_table_vector = Fmake_vector (make_number (16), Qnil);
 
   DEFVAR_INT ("leading-code-composition", &leading_code_composition,
     "Leading-code of composite characters.");
@@ -1785,23 +1971,30 @@ This serves to convert a Latin-1 or similar 8-bit character code\n\
 to the corresponding Emacs multibyte character code.\n\
 Typically the value should be (- (make-char CHARSET 0) 128),\n\
 for your choice of character set.\n\
-If `nonascii-translate-table' is non-nil, it overrides this variable.");
+If `nonascii-translation-table' is non-nil, it overrides this variable.");
   nonascii_insert_offset = 0;
 
   DEFVAR_LISP ("nonascii-translation-table", &Vnonascii_translation_table,
-    "Character translation table to convert non-ASCII unibyte codes to multibyte.\n\
+    "Translation table to convert non-ASCII unibyte codes to multibyte.\n\
 This is used for converting unibyte text to multibyte,\n\
 and for inserting character codes specified by number.\n\n\
 Conversion is performed only when multibyte characters are enabled,\n\
 and it serves to convert a Latin-1 or similar 8-bit character code\n\
 to the corresponding Emacs character code.\n\n\
-If this is nil, `nonascii-insert-offset' is used instead.
+If this is nil, `nonascii-insert-offset' is used instead.\n\
 See also the docstring of `make-translation-table'.");
   Vnonascii_translation_table = Qnil;
 
   DEFVAR_INT ("min-composite-char", &min_composite_char,
     "Minimum character code of a composite character.");
   min_composite_char = MIN_CHAR_COMPOSITION;
+
+  DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars,
+    "A char-table for characters which invoke auto-filling.\n\
+Such characters has value t in this table.");
+  Vauto_fill_chars = Fmake_char_table (Qauto_fill_chars, Qnil);
+  CHAR_TABLE_SET (Vauto_fill_chars, make_number (' '), Qt);
+  CHAR_TABLE_SET (Vauto_fill_chars, make_number ('\n'), Qt);
 }
 
 #endif /* emacs */