(add_emchar_rune): Use `ASCII_TO_CHARC', `CHAR_TO_CHARC' and
[chise/xemacs-chise.git-] / src / mule-charset.c
index 9a86e36..91376d7 100644 (file)
@@ -206,7 +206,7 @@ byte_table_hash (Lisp_Object obj, int depth)
 }
 
 static const struct lrecord_description byte_table_description[] = {
-  { XD_LISP_OBJECT, offsetof(Lisp_Byte_Table, property), 256 },
+  { XD_LISP_OBJECT_ARRAY, offsetof(Lisp_Byte_Table, property), 256 },
   { XD_END }
 };
 
@@ -219,12 +219,16 @@ DEFINE_LRECORD_IMPLEMENTATION ("byte-table", byte_table,
                               Lisp_Byte_Table);
 
 static Lisp_Object
-make_byte_table (Lisp_Object initval)
+make_byte_table (Lisp_Object initval, int older)
 {
   Lisp_Object obj;
   int i;
-  Lisp_Byte_Table *cte
-    = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
+  Lisp_Byte_Table *cte;
+
+  if (older)
+    cte = alloc_older_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
+  else
+    cte = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
 
   for (i = 0; i < 256; i++)
     cte->property[i] = initval;
@@ -257,78 +261,84 @@ copy_byte_table (Lisp_Object entry)
 
 
 static Lisp_Object
-mark_char_code_table (Lisp_Object obj)
+mark_char_id_table (Lisp_Object obj)
 {
-  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (obj);
+  Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
 
   return cte->table;
 }
 
 static int
-char_code_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+char_id_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 {
-  struct Lisp_Char_Code_Table *cte1 = XCHAR_CODE_TABLE (obj1);
-  struct Lisp_Char_Code_Table *cte2 = XCHAR_CODE_TABLE (obj2);
+  Lisp_Char_ID_Table *cte1 = XCHAR_ID_TABLE (obj1);
+  Lisp_Char_ID_Table *cte2 = XCHAR_ID_TABLE (obj2);
 
   return byte_table_equal (cte1->table, cte2->table, depth + 1);
 }
 
 static unsigned long
-char_code_table_hash (Lisp_Object obj, int depth)
+char_id_table_hash (Lisp_Object obj, int depth)
 {
-  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (obj);
+  Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
 
-  return char_code_table_hash (cte->table, depth + 1);
+  return char_id_table_hash (cte->table, depth + 1);
 }
 
-static const struct lrecord_description char_code_table_description[] = {
-  { XD_LISP_OBJECT, offsetof(struct Lisp_Char_Code_Table, table), 1 },
+static const struct lrecord_description char_id_table_description[] = {
+  { XD_LISP_OBJECT, offsetof(Lisp_Char_ID_Table, table) },
   { XD_END }
 };
 
-DEFINE_LRECORD_IMPLEMENTATION ("char-code-table", char_code_table,
-                               mark_char_code_table,
+DEFINE_LRECORD_IMPLEMENTATION ("char-id-table", char_id_table,
+                               mark_char_id_table,
                               internal_object_printer,
-                              0, char_code_table_equal,
-                              char_code_table_hash,
-                              char_code_table_description,
-                              struct Lisp_Char_Code_Table);
+                              0, char_id_table_equal,
+                              char_id_table_hash,
+                              char_id_table_description,
+                              Lisp_Char_ID_Table);
 
 static Lisp_Object
-make_char_code_table (Lisp_Object initval)
+make_char_id_table (Lisp_Object initval, int older)
 {
   Lisp_Object obj;
-  struct Lisp_Char_Code_Table *cte =
-    alloc_lcrecord_type (struct Lisp_Char_Code_Table,
-                        &lrecord_char_code_table);
+  Lisp_Char_ID_Table *cte;
+
+  if (older)
+    cte = alloc_older_lcrecord_type (Lisp_Char_ID_Table,
+                                    &lrecord_char_id_table);
+  else
+    cte = alloc_lcrecord_type (Lisp_Char_ID_Table, &lrecord_char_id_table);
 
-  cte->table = make_byte_table (initval);
+  cte->table = make_byte_table (initval, older);
 
-  XSETCHAR_CODE_TABLE (obj, cte);
+  XSETCHAR_ID_TABLE (obj, cte);
   return obj;
 }
 
+/* not used */
+#if 0
 static Lisp_Object
-copy_char_code_table (Lisp_Object entry)
+copy_char_id_table (Lisp_Object entry)
 {
-  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (entry);
+  Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (entry);
   Lisp_Object obj;
-  struct Lisp_Char_Code_Table *ctenew =
-    alloc_lcrecord_type (struct Lisp_Char_Code_Table,
-                        &lrecord_char_code_table);
+  Lisp_Char_ID_Table *ctenew
+    = alloc_lcrecord_type (Lisp_Char_ID_Table, &lrecord_char_id_table);
 
   ctenew->table = copy_byte_table (cte->table);
-  XSETCHAR_CODE_TABLE (obj, ctenew);
+  XSETCHAR_ID_TABLE (obj, ctenew);
   return obj;
 }
+#endif
 
 
 Lisp_Object
-get_char_code_table (Emchar ch, Lisp_Object table)
+get_char_id_table (Emchar ch, Lisp_Object table)
 {
   unsigned int code = ch;
   Lisp_Byte_Table* cpt
-    = XBYTE_TABLE (XCHAR_CODE_TABLE (table)->table);
+    = XBYTE_TABLE (XCHAR_ID_TABLE (table)->table);
   Lisp_Object ret = cpt->property [(unsigned char)(code >> 24)];
 
   if (BYTE_TABLE_P (ret))
@@ -351,13 +361,12 @@ get_char_code_table (Emchar ch, Lisp_Object table)
   return cpt->property [(unsigned char) code];
 }
 
-void put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table);
+void put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table);
 void
-put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table)
+put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table)
 {
   unsigned int code = ch;
-  Lisp_Byte_Table* cpt1
-    = XBYTE_TABLE (XCHAR_CODE_TABLE (table)->table);
+  Lisp_Byte_Table* cpt1 = XBYTE_TABLE (XCHAR_ID_TABLE (table)->table);
   Lisp_Object ret = cpt1->property[(unsigned char)(code >> 24)];
 
   if (BYTE_TABLE_P (ret))
@@ -378,17 +387,19 @@ put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table)
            }
          else if (!EQ (ret, value))
            {
-             Lisp_Object cpt4 = make_byte_table (ret);
-             
+             Lisp_Object cpt4
+               = make_byte_table (ret, OLDER_RECORD_P (table));
+
              XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
              cpt3->property[(unsigned char)(code >> 8)] = cpt4;
            }
        }
       else if (!EQ (ret, value))
        {
-         Lisp_Object cpt3 = make_byte_table (ret);
-         Lisp_Object cpt4 = make_byte_table (ret);
-         
+         int older = OLDER_RECORD_P (table);
+         Lisp_Object cpt3 = make_byte_table (ret, older);
+         Lisp_Object cpt4 = make_byte_table (ret, older);
+
          XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
          XBYTE_TABLE(cpt3)->property[(unsigned char)(code >> 8)]
            = cpt4;
@@ -397,10 +408,11 @@ put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table)
     }
   else if (!EQ (ret, value))
     {
-      Lisp_Object cpt2 = make_byte_table (ret);
-      Lisp_Object cpt3 = make_byte_table (ret);
-      Lisp_Object cpt4 = make_byte_table (ret);
-      
+      int older = OLDER_RECORD_P (table);
+      Lisp_Object cpt2 = make_byte_table (ret, older);
+      Lisp_Object cpt3 = make_byte_table (ret, older);
+      Lisp_Object cpt4 = make_byte_table (ret, older);
+
       XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
       XBYTE_TABLE(cpt3)->property[(unsigned char)(code >>  8)] = cpt4;
       XBYTE_TABLE(cpt2)->property[(unsigned char)(code >> 16)] = cpt3;
@@ -410,10 +422,22 @@ put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table)
 
 
 Lisp_Object Vcharacter_attribute_table;
+Lisp_Object Vcharacter_name_table;
+Lisp_Object Vcharacter_ideographic_radical_table;
+Lisp_Object Vcharacter_ideographic_strokes_table;
+Lisp_Object Vcharacter_total_strokes_table;
+Lisp_Object Vcharacter_morohashi_daikanwa_table;
+Lisp_Object Vcharacter_decomposition_table;
 Lisp_Object Vcharacter_composition_table;
 Lisp_Object Vcharacter_variant_table;
 
+Lisp_Object Qname;
+Lisp_Object Qideographic_radical, Qideographic_strokes;
+Lisp_Object Qtotal_strokes;
+Lisp_Object Qmorohashi_daikanwa;
+Lisp_Object Qideograph_daikanwa;
 Lisp_Object Q_decomposition;
+Lisp_Object Qucs;
 Lisp_Object Q_ucs;
 Lisp_Object Qcompat;
 Lisp_Object Qisolated;
@@ -432,9 +456,20 @@ Lisp_Object Qnarrow;
 Lisp_Object Qsmall;
 Lisp_Object Qfont;
 
-Emchar to_char_code (Lisp_Object v, char* err_msg, Lisp_Object err_arg);
+Emchar to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg);
+
+Lisp_Object put_char_ccs_code_point (Lisp_Object character,
+                                    Lisp_Object ccs, Lisp_Object value);
+Lisp_Object remove_char_ccs (Lisp_Object character, Lisp_Object ccs);
+
+Lisp_Object put_char_attribute (Lisp_Object character,
+                               Lisp_Object attribute, Lisp_Object value);
+Lisp_Object remove_char_attribute (Lisp_Object character,
+                                  Lisp_Object attribute);
+
+
 Emchar
-to_char_code (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
+to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
 {
   if (INTP (v))
     return XINT (v);
@@ -488,21 +523,21 @@ Return character corresponding with list.
     {
       Lisp_Object v = Fcar (rest);
       Lisp_Object ret;
-      Emchar c = to_char_code (v, "Invalid value for composition", list);
+      Emchar c = to_char_id (v, "Invalid value for composition", list);
 
-      ret = get_char_code_table (c, table);
+      ret = get_char_id_table (c, table);
 
       rest = Fcdr (rest);
       if (NILP (rest))
        {
-         if (!CHAR_CODE_TABLE_P (ret))
+         if (!CHAR_ID_TABLE_P (ret))
            return ret;
          else
            return Qt;
        }
       else if (!CONSP (rest))
        break;
-      else if (CHAR_CODE_TABLE_P (ret))
+      else if (CHAR_ID_TABLE_P (ret))
        table = ret;
       else
        signal_simple_error ("Invalid table is found with", list);
@@ -516,8 +551,8 @@ Return variants of CHARACTER.
        (character))
 {
   CHECK_CHAR (character);
-  return Fcopy_list (get_char_code_table (XCHAR (character),
-                                         Vcharacter_variant_table));
+  return Fcopy_list (get_char_id_table (XCHAR (character),
+                                       Vcharacter_variant_table));
 }
 
 DEFUN ("char-attribute-alist", Fchar_attribute_alist, 1, 1, 0, /*
@@ -525,9 +560,68 @@ Return the alist of attributes of CHARACTER.
 */
        (character))
 {
+  Lisp_Object alist, ret;
+  int i;
+
   CHECK_CHAR (character);
-  return Fcopy_alist (get_char_code_table (XCHAR (character),
-                                          Vcharacter_attribute_table));
+  alist = Fcopy_alist (get_char_id_table (XCHAR (character),
+                                         Vcharacter_attribute_table));
+
+  ret = get_char_id_table (XCHAR (character), Vcharacter_name_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Qname, ret), alist);
+
+  ret = get_char_id_table (XCHAR (character),
+                          Vcharacter_ideographic_radical_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Qideographic_radical, ret), alist);
+
+  ret = get_char_id_table (XCHAR (character),
+                          Vcharacter_ideographic_strokes_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Qideographic_strokes, ret), alist);
+
+  ret = get_char_id_table (XCHAR (character), Vcharacter_total_strokes_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Qtotal_strokes, ret), alist);
+
+  ret = get_char_id_table (XCHAR (character),
+                          Vcharacter_morohashi_daikanwa_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Qmorohashi_daikanwa, ret), alist);
+
+  ret = get_char_id_table (XCHAR (character),
+                          Vcharacter_decomposition_table);
+  if (!NILP (ret))
+    alist = Fcons (Fcons (Q_decomposition, ret), alist);
+
+  for (i = 0; i < countof (chlook->charset_by_leading_byte); i++)
+    {
+      Lisp_Object ccs = chlook->charset_by_leading_byte[i];
+
+      if (!NILP (ccs))
+       {
+#if 0
+         int code_point = charset_code_point (ccs, XCHAR (character));
+
+         if (code_point >= 0)
+           {
+             alist = Fcons (Fcons (ccs, make_int (code_point)), alist);
+           }
+#else
+         Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
+         Lisp_Object cpos;
+
+         if ( CHAR_ID_TABLE_P (encoding_table)
+              && INTP (cpos = get_char_id_table (XCHAR (character),
+                                                 encoding_table)) )
+           {
+             alist = Fcons (Fcons (ccs, cpos), alist);
+           }
+#endif
+       }
+    }
+  return alist;
 }
 
 DEFUN ("get-char-attribute", Fget_char_attribute, 2, 2, 0, /*
@@ -535,81 +629,59 @@ Return the value of CHARACTER's ATTRIBUTE.
 */
        (character, attribute))
 {
-  Lisp_Object ret;
   Lisp_Object ccs;
 
   CHECK_CHAR (character);
-  ret = get_char_code_table (XCHAR (character),
-                            Vcharacter_attribute_table);
-  if (EQ (ret, Qnil))
-    return Qnil;
-
   if (!NILP (ccs = Ffind_charset (attribute)))
-    attribute = ccs;
-
-  return Fcdr (Fassq (attribute, ret));
-}
-
-Lisp_Object put_char_attribute (Lisp_Object character,
-                               Lisp_Object attribute, Lisp_Object value);
-Lisp_Object
-put_char_attribute (Lisp_Object character, Lisp_Object attribute,
-                   Lisp_Object value)
-{
-  Emchar char_code = XCHAR (character);
-  Lisp_Object ret
-    = get_char_code_table (char_code, Vcharacter_attribute_table);
-  Lisp_Object cell;
-
-  cell = Fassq (attribute, ret);
+    {
+      Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
 
-  if (NILP (cell))
+      if (CHAR_ID_TABLE_P (encoding_table))
+       return get_char_id_table (XCHAR (character), encoding_table);
+      else
+       return Qnil;
+    }
+  else if (EQ (attribute, Qname))
     {
-      ret = Fcons (Fcons (attribute, value), ret);
+      return get_char_id_table (XCHAR (character), Vcharacter_name_table);
     }
-  else if (!EQ (Fcdr (cell), value))
+  else if (EQ (attribute, Qideographic_radical))
     {
-      Fsetcdr (cell, value);
+      return get_char_id_table (XCHAR (character),
+                               Vcharacter_ideographic_radical_table);
     }
-  put_char_code_table (char_code, ret, Vcharacter_attribute_table);
-  return ret;
-}
-
-Lisp_Object remove_char_attribute (Lisp_Object character,
-                                  Lisp_Object attribute);
-Lisp_Object
-remove_char_attribute (Lisp_Object character, Lisp_Object attribute)
-{
-  Emchar char_code = XCHAR (character);
-  Lisp_Object alist
-    = get_char_code_table (char_code, Vcharacter_attribute_table);
-
-  if (EQ (attribute, Fcar (Fcar (alist))))
+  else if (EQ (attribute, Qideographic_strokes))
     {
-      alist = Fcdr (alist);
+      return get_char_id_table (XCHAR (character),
+                               Vcharacter_ideographic_strokes_table);
+    }
+  else if (EQ (attribute, Qtotal_strokes))
+    {
+      return get_char_id_table (XCHAR (character),
+                               Vcharacter_total_strokes_table);
+    }
+  else if (EQ (attribute, Qmorohashi_daikanwa))
+    {
+      return get_char_id_table (XCHAR (character),
+                               Vcharacter_morohashi_daikanwa_table);
+    }
+  else if (EQ (attribute, Q_decomposition))
+    {
+      return get_char_id_table (XCHAR (character),
+                               Vcharacter_decomposition_table);
     }
   else
     {
-      Lisp_Object pr = alist;
-      Lisp_Object r = Fcdr (alist);
+      Lisp_Object ret
+       = get_char_id_table (XCHAR (character), Vcharacter_attribute_table);
 
-      while (!NILP (r))
-       {
-         if (EQ (attribute, Fcar (Fcar (r))))
-           {
-             XCDR (pr) = Fcdr (r);
-             break;
-           }
-         pr = r;
-         r = Fcdr (r);
-       }
+      if (EQ (ret, Qnil))
+       return Qnil;
+      else
+       return Fcdr (Fassq (attribute, ret));
     }
-  put_char_code_table (char_code, alist, Vcharacter_attribute_table);
-  return alist;
 }
 
-Lisp_Object Qucs;
-
 DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
 Store CHARACTER's ATTRIBUTE with VALUE.
 */
@@ -621,114 +693,46 @@ Store CHARACTER's ATTRIBUTE with VALUE.
   ccs = Ffind_charset (attribute);
   if (!NILP (ccs))
     {
-      if (!EQ (XCHARSET_NAME (ccs), Qucs)
-         || (XCHAR (character) != XINT (value)))
-       {
-         Lisp_Object cpos, rest;
-         Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
-         Lisp_Object nv;
-         int i = -1;
-         int ccs_len;
-         int dim;
-         int code_point;
-
-         /* ad-hoc method for `ascii' */
-         if ((XCHARSET_CHARS (ccs) == 94) &&
-             (XCHARSET_BYTE_OFFSET (ccs) != 33))
-           ccs_len = 128 - XCHARSET_BYTE_OFFSET (ccs);
-         else
-           ccs_len = XCHARSET_CHARS (ccs);
-
-         if (CONSP (value))
-           {
-             Lisp_Object ret = Fcar (value);
-
-             if (!INTP (ret))
-               signal_simple_error ("Invalid value for coded-charset", value);
-             code_point = XINT (ret);
-             if (XCHARSET_GRAPHIC (ccs) == 1)
-               code_point &= 0x7F;
-             rest = Fcdr (value);
-             while (!NILP (rest))
-               {
-                 int j;
-
-                 if (!CONSP (rest))
-                   signal_simple_error ("Invalid value for coded-charset",
-                                        value);
-                 ret = Fcar (rest);
-                 if (!INTP (ret))
-                   signal_simple_error ("Invalid value for coded-charset",
-                                        value);
-                 j = XINT (ret);
-                 if (XCHARSET_GRAPHIC (ccs) == 1)
-                   j &= 0x7F;
-                 code_point = (code_point << 8) | j;
-                 rest = Fcdr (rest);
-               }
-             value = make_int (code_point);
-           }
-         else if (INTP (value))
-           {
-             if (XCHARSET_GRAPHIC (ccs) == 1)
-               value = make_int (XINT (value) & 0x7F7F7F7F);
-           }
-         else
-           signal_simple_error ("Invalid value for coded-charset", value);
-
-         attribute = ccs;
-         cpos = Fget_char_attribute (character, attribute);
-         if (VECTORP (v))
-           {
-             if (!NILP (cpos))
-               {
-                 dim = XCHARSET_DIMENSION (ccs);
-                 code_point = XINT (cpos);
-                 while (dim > 0)
-                   {
-                     dim--;
-                     i = ((code_point >> (8 * dim)) & 255)
-                       - XCHARSET_BYTE_OFFSET (ccs);
-                     nv = XVECTOR_DATA(v)[i];
-                     if (!VECTORP (nv))
-                       break;
-                     v = nv;
-                   }
-                 if (i >= 0)
-                   XVECTOR_DATA(v)[i] = Qnil;
-                 v = XCHARSET_DECODING_TABLE (ccs);
-               }
-           }
-         else
-           {
-             XCHARSET_DECODING_TABLE (ccs) = v = make_vector (ccs_len, Qnil);
-           }
-
-         dim = XCHARSET_DIMENSION (ccs);
-         code_point = XINT (value);
-         i = -1;
-         while (dim > 0)
-           {
-             dim--;
-             i = ((code_point >> (8 * dim)) & 255)
-               - XCHARSET_BYTE_OFFSET (ccs);
-             nv = XVECTOR_DATA(v)[i];
-             if (dim > 0)
-               {
-                 if (!VECTORP (nv))
-                   nv = (XVECTOR_DATA(v)[i] = make_vector (ccs_len, Qnil));
-                 v = nv;
-               }
-             else
-               break;
-           }
-         XVECTOR_DATA(v)[i] = character;
-       }
-      else
-       attribute = ccs;
+      return put_char_ccs_code_point (character, ccs, value);
+    }
+  else if (EQ (attribute, Qname))
+    {
+      CHECK_STRING (value);
+      put_char_id_table (XCHAR (character), value, Vcharacter_name_table);
+      return value;
+    }
+  else if (EQ (attribute, Qideographic_radical))
+    {
+      CHECK_INT (value);
+      put_char_id_table (XCHAR (character), value,
+                        Vcharacter_ideographic_radical_table);
+      return value;
+    }
+  else if (EQ (attribute, Qideographic_strokes))
+    {
+      CHECK_INT (value);
+      put_char_id_table (XCHAR (character), value,
+                        Vcharacter_ideographic_strokes_table);
+      return value;
+    }
+  else if (EQ (attribute, Qtotal_strokes))
+    {
+      CHECK_INT (value);
+      put_char_id_table (XCHAR (character), value,
+                        Vcharacter_total_strokes_table);
+      return value;
+    }
+  else if (EQ (attribute, Qmorohashi_daikanwa))
+    {
+      CHECK_LIST (value);
+      put_char_id_table (XCHAR (character), value,
+                        Vcharacter_morohashi_daikanwa_table);
+      return value;
     }
   else if (EQ (attribute, Q_decomposition))
     {
+      Lisp_Object seq;
+
       if (!CONSP (value))
        signal_simple_error ("Invalid value for ->decomposition",
                             value);
@@ -737,28 +741,37 @@ Store CHARACTER's ATTRIBUTE with VALUE.
        {
          Lisp_Object rest = value;
          Lisp_Object table = Vcharacter_composition_table;
+         size_t len;
+         int i = 0;
+
+         GET_EXTERNAL_LIST_LENGTH (rest, len);
+         seq = make_older_vector (len, Qnil);
 
          while (CONSP (rest))
            {
              Lisp_Object v = Fcar (rest);
              Lisp_Object ntable;
              Emchar c
-               = to_char_code (v,
-                               "Invalid value for ->decomposition", value);
+               = to_char_id (v, "Invalid value for ->decomposition", value);
 
+             if (c < 0)
+               XVECTOR_DATA(seq)[i++] = v;
+             else
+               XVECTOR_DATA(seq)[i++] = make_char (c);
              rest = Fcdr (rest);
              if (!CONSP (rest))
                {
-                 put_char_code_table (c, character, table);
+                 put_char_id_table (c, character, table);
                  break;
                }
              else
                {
-                 ntable = get_char_code_table (c, table);
-                 if (!CHAR_CODE_TABLE_P (ntable))
+                 ntable = get_char_id_table (c, table);
+                 if (!CHAR_ID_TABLE_P (ntable))
                    {
-                     ntable = make_char_code_table (Qnil);
-                     put_char_code_table (c, ntable, table);
+                     ntable
+                       = make_char_id_table (Qnil, OLDER_RECORD_P (table));
+                     put_char_id_table (c, ntable, table);
                    }
                  table = ntable;
                }
@@ -772,15 +785,19 @@ Store CHARACTER's ATTRIBUTE with VALUE.
            {
              Emchar c = XINT (v);
              Lisp_Object ret
-               = get_char_code_table (c, Vcharacter_variant_table);
+               = get_char_id_table (c, Vcharacter_variant_table);
 
              if (NILP (Fmemq (v, ret)))
                {
-                 put_char_code_table (c, Fcons (character, ret),
-                                      Vcharacter_variant_table);
+                 put_char_id_table (c, Fcons (character, ret),
+                                    Vcharacter_variant_table);
                }
            }
+         seq = make_older_vector (1, v);
        }
+      put_char_id_table (XCHAR (character), seq,
+                        Vcharacter_decomposition_table);
+      return value;
     }
   else if (EQ (attribute, Q_ucs))
     {
@@ -792,11 +809,11 @@ Store CHARACTER's ATTRIBUTE with VALUE.
 
       c = XINT (value);
 
-      ret = get_char_code_table (c, Vcharacter_variant_table);
+      ret = get_char_id_table (c, Vcharacter_variant_table);
       if (NILP (Fmemq (character, ret)))
        {
-         put_char_code_table (c, Fcons (character, ret),
-                              Vcharacter_variant_table);
+         put_char_id_table (c, Fcons (character, ret),
+                            Vcharacter_variant_table);
        }
     }
   return put_char_attribute (character, attribute, value);
@@ -813,46 +830,262 @@ Remove CHARACTER's ATTRIBUTE.
   ccs = Ffind_charset (attribute);
   if (!NILP (ccs))
     {
-      Lisp_Object cpos;
-      Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
+      return remove_char_ccs (character, ccs);
+    }
+  return remove_char_attribute (character, attribute);
+}
+
+INLINE_HEADER int CHARSET_BYTE_SIZE (Lisp_Charset* cs);
+INLINE_HEADER int
+CHARSET_BYTE_SIZE (Lisp_Charset* cs)
+{
+  /* ad-hoc method for `ascii' */
+  if ((CHARSET_CHARS (cs) == 94) &&
+      (CHARSET_BYTE_OFFSET (cs) != 33))
+    return 128 - CHARSET_BYTE_OFFSET (cs);
+  else
+    return CHARSET_CHARS (cs);
+}
+
+#define XCHARSET_BYTE_SIZE(ccs)        CHARSET_BYTE_SIZE (XCHARSET (ccs))
+
+int decoding_table_check_elements (Lisp_Object v, int dim, int ccs_len);
+int
+decoding_table_check_elements (Lisp_Object v, int dim, int ccs_len)
+{
+  int i;
+
+  if (XVECTOR_LENGTH (v) > ccs_len)
+    return -1;
+
+  for (i = 0; i < XVECTOR_LENGTH (v); i++)
+    {
+      Lisp_Object c = XVECTOR_DATA(v)[i];
+
+      if (!NILP (c) && !CHARP (c))
+       {
+         if (VECTORP (c))
+           {
+             int ret = decoding_table_check_elements (c, dim - 1, ccs_len);
+             if (ret)
+               return ret;
+           }
+         else
+           return -2;
+       }
+    }
+  return 0;
+}
+
+INLINE_HEADER void
+decoding_table_remove_char (Lisp_Object v, int dim, int byte_offset,
+                           int code_point);
+INLINE_HEADER void
+decoding_table_remove_char (Lisp_Object v, int dim, int byte_offset,
+                           int code_point)
+{
+  int i = -1;
+
+  while (dim > 0)
+    {
       Lisp_Object nv;
-      int i = -1;
-      int ccs_len;
-      int dim;
+
+      dim--;
+      i = ((code_point >> (8 * dim)) & 255) - byte_offset;
+      nv = XVECTOR_DATA(v)[i];
+      if (!VECTORP (nv))
+       break;
+      v = nv;
+    }
+  if (i >= 0)
+    XVECTOR_DATA(v)[i] = Qnil;
+}
+
+INLINE_HEADER void
+decoding_table_put_char (Lisp_Object v, int dim, int byte_offset,
+                        int code_point, Lisp_Object character);
+INLINE_HEADER void
+decoding_table_put_char (Lisp_Object v, int dim, int byte_offset,
+                        int code_point, Lisp_Object character)
+{
+  int i = -1;
+  Lisp_Object nv;
+  int ccs_len = XVECTOR_LENGTH (v);
+
+  while (dim > 0)
+    {
+      dim--;
+      i = ((code_point >> (8 * dim)) & 255) - byte_offset;
+      nv = XVECTOR_DATA(v)[i];
+      if (dim > 0)
+       {
+         if (!VECTORP (nv))
+           nv = (XVECTOR_DATA(v)[i] = make_older_vector (ccs_len, Qnil));
+         v = nv;
+       }
+      else
+       break;
+    }
+  XVECTOR_DATA(v)[i] = character;
+}
+
+Lisp_Object
+put_char_ccs_code_point (Lisp_Object character,
+                        Lisp_Object ccs, Lisp_Object value)
+{
+  Lisp_Object encoding_table;
+
+  if (!EQ (XCHARSET_NAME (ccs), Qucs)
+      || (XCHAR (character) != XINT (value)))
+    {
+      Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
+      int dim = XCHARSET_DIMENSION (ccs);
+      int ccs_len = XCHARSET_BYTE_SIZE (ccs);
+      int byte_offset = XCHARSET_BYTE_OFFSET (ccs);
       int code_point;
-             
-      /* ad-hoc method for `ascii' */
-      if ((XCHARSET_CHARS (ccs) == 94) &&
-         (XCHARSET_BYTE_OFFSET (ccs) != 33))
-       ccs_len = 128 - XCHARSET_BYTE_OFFSET (ccs);
+
+      if (CONSP (value))
+       { /* obsolete representation: value must be a list of bytes */
+         Lisp_Object ret = Fcar (value);
+         Lisp_Object rest;
+
+         if (!INTP (ret))
+           signal_simple_error ("Invalid value for coded-charset", value);
+         code_point = XINT (ret);
+         if (XCHARSET_GRAPHIC (ccs) == 1)
+           code_point &= 0x7F;
+         rest = Fcdr (value);
+         while (!NILP (rest))
+           {
+             int j;
+
+             if (!CONSP (rest))
+               signal_simple_error ("Invalid value for coded-charset",
+                                    value);
+             ret = Fcar (rest);
+             if (!INTP (ret))
+               signal_simple_error ("Invalid value for coded-charset",
+                                    value);
+             j = XINT (ret);
+             if (XCHARSET_GRAPHIC (ccs) == 1)
+               j &= 0x7F;
+             code_point = (code_point << 8) | j;
+             rest = Fcdr (rest);
+           }
+         value = make_int (code_point);
+       }
+      else if (INTP (value))
+       {
+         code_point = XINT (value);
+         if (XCHARSET_GRAPHIC (ccs) == 1)
+           {
+             code_point &= 0x7F7F7F7F;
+             value = make_int (code_point);
+           }
+       }
       else
-       ccs_len = XCHARSET_CHARS (ccs);
+       signal_simple_error ("Invalid value for coded-charset", value);
 
-      attribute = ccs;
-      cpos = Fget_char_attribute (character, attribute);
       if (VECTORP (v))
        {
+         Lisp_Object cpos = Fget_char_attribute (character, ccs);
          if (!NILP (cpos))
            {
-             dim = XCHARSET_DIMENSION (ccs);
-             code_point = XINT (cpos);
-             while (dim > 0)
-               {
-                 dim--;
-                 i = ((code_point >> (8 * dim)) & 255)
-                   - XCHARSET_BYTE_OFFSET (ccs);
-                 nv = XVECTOR_DATA(v)[i];
-                 if (!VECTORP (nv))
-                   break;
-                 v = nv;
-               }
-             if (i >= 0)
-               XVECTOR_DATA(v)[i] = Qnil;
-             v = XCHARSET_DECODING_TABLE (ccs);
+             decoding_table_remove_char (v, dim, byte_offset, XINT (cpos));
            }
        }
+      else
+       {
+         XCHARSET_DECODING_TABLE (ccs)
+           = v = make_older_vector (ccs_len, Qnil);
+       }
+
+      decoding_table_put_char (v, dim, byte_offset, code_point, character);
     }
-  return remove_char_attribute (character, attribute);
+  if (NILP (encoding_table = XCHARSET_ENCODING_TABLE (ccs)))
+    {
+      XCHARSET_ENCODING_TABLE (ccs)
+       = encoding_table = make_char_id_table (Qnil, -1);
+    }
+  put_char_id_table (XCHAR (character), value, encoding_table);
+  return Qt;
+}
+
+Lisp_Object
+remove_char_ccs (Lisp_Object character, Lisp_Object ccs)
+{
+  Lisp_Object decoding_table = XCHARSET_DECODING_TABLE (ccs);
+  Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
+
+  if (VECTORP (decoding_table))
+    {
+      Lisp_Object cpos = Fget_char_attribute (character, ccs);
+
+      if (!NILP (cpos))
+       {
+         decoding_table_remove_char (decoding_table,
+                                     XCHARSET_DIMENSION (ccs),
+                                     XCHARSET_BYTE_OFFSET (ccs),
+                                     XINT (cpos));
+       }
+    }
+  if (CHAR_ID_TABLE_P (encoding_table))
+    {
+      put_char_id_table (XCHAR (character), Qnil, encoding_table);
+    }
+  return Qt;
+}
+
+Lisp_Object
+put_char_attribute (Lisp_Object character, Lisp_Object attribute,
+                   Lisp_Object value)
+{
+  Emchar char_id = XCHAR (character);
+  Lisp_Object ret = get_char_id_table (char_id, Vcharacter_attribute_table);
+  Lisp_Object cell;
+
+  cell = Fassq (attribute, ret);
+
+  if (NILP (cell))
+    {
+      ret = Fcons (Fcons (attribute, value), ret);
+    }
+  else if (!EQ (Fcdr (cell), value))
+    {
+      Fsetcdr (cell, value);
+    }
+  put_char_id_table (char_id, ret, Vcharacter_attribute_table);
+  return ret;
+}
+
+Lisp_Object
+remove_char_attribute (Lisp_Object character, Lisp_Object attribute)
+{
+  Emchar char_id = XCHAR (character);
+  Lisp_Object alist = get_char_id_table (char_id, Vcharacter_attribute_table);
+
+  if (EQ (attribute, Fcar (Fcar (alist))))
+    {
+      alist = Fcdr (alist);
+    }
+  else
+    {
+      Lisp_Object pr = alist;
+      Lisp_Object r = Fcdr (alist);
+
+      while (!NILP (r))
+       {
+         if (EQ (attribute, Fcar (Fcar (r))))
+           {
+             XCDR (pr) = Fcdr (r);
+             break;
+           }
+         pr = r;
+         r = Fcdr (r);
+       }
+    }
+  put_char_id_table (char_id, alist, Vcharacter_attribute_table);
+  return alist;
 }
 
 EXFUN (Fmake_char, 3);
@@ -866,6 +1099,7 @@ Store character's ATTRIBUTES.
   Lisp_Object rest = attributes;
   Lisp_Object code = Fcdr (Fassq (Qucs, attributes));
   Lisp_Object character;
+  Lisp_Object daikanwa = Qnil;
 
   if (NILP (code))
     {
@@ -909,14 +1143,34 @@ Store character's ATTRIBUTES.
   while (CONSP (rest))
     {
       Lisp_Object cell = Fcar (rest);
+      Lisp_Object key = Fcar (cell);
+      Lisp_Object value = Fcdr (cell);
 
       if (!LISTP (cell))
        signal_simple_error ("Invalid argument", attributes);
+
+      if (EQ (key, Qmorohashi_daikanwa))
+       {
+         size_t len;
+         GET_EXTERNAL_LIST_LENGTH (value, len);
+
+         if (len == 1)
+           {
+             if (NILP (daikanwa))
+               daikanwa = Fcdr (Fassq (Qideograph_daikanwa, rest));
+             if (EQ (Fcar (value), daikanwa))
+               goto ignored;
+           }
+       }
+      else if (EQ (key, Qideograph_daikanwa))
+       daikanwa = value;
+
       Fput_char_attribute (character, Fcar (cell), Fcdr (cell));
+    ignored:
       rest = Fcdr (rest);
     }
   return
-    get_char_code_table (XCHAR (character), Vcharacter_attribute_table);
+    get_char_id_table (XCHAR (character), Vcharacter_attribute_table);
 }
 
 Lisp_Object Vutf_2000_version;
@@ -965,7 +1219,6 @@ Lisp_Object Qascii,
   Qlatin_viscii_upper,
   Qvietnamese_viscii_lower,
   Qvietnamese_viscii_upper,
-  Qideograph_daikanwa,
   Qmojikyo,
   Qmojikyo_pj_1,
   Qmojikyo_pj_2,
@@ -1365,7 +1618,8 @@ mark_charset (Lisp_Object obj)
   mark_object (cs->registry);
   mark_object (cs->ccl_program);
 #ifdef UTF2000
-  mark_object (cs->decoding_table);
+  /* mark_object (cs->encoding_table); */
+  /* mark_object (cs->decoding_table); */
 #endif
   return cs->name;
 }
@@ -1412,6 +1666,7 @@ static const struct lrecord_description charset_description[] = {
   { XD_LISP_OBJECT, offsetof (Lisp_Charset, ccl_program) },
 #ifdef UTF2000
   { XD_LISP_OBJECT, offsetof (Lisp_Charset, decoding_table) },
+  { XD_LISP_OBJECT, offsetof (Lisp_Charset, encoding_table) },
 #endif
   { XD_END }
 };
@@ -1457,6 +1712,7 @@ make_charset (Charset_ID id, Lisp_Object name,
   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
 #ifdef UTF2000
   CHARSET_DECODING_TABLE(cs) = Qnil;
+  CHARSET_ENCODING_TABLE(cs) = Qnil;
   CHARSET_UCS_MIN(cs) = ucs_min;
   CHARSET_UCS_MAX(cs) = ucs_max;
   CHARSET_CODE_OFFSET(cs) = code_offset;
@@ -1924,7 +2180,7 @@ add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
     (struct charset_list_closure*) charset_list_closure;
   Lisp_Object *charset_list = chcl->charset_list;
 
-  *charset_list = Fcons (XCHARSET_NAME (value), *charset_list);
+  *charset_list = Fcons (key /* XCHARSET_NAME (value) */, *charset_list);
   return 0;
 }
 
@@ -2433,39 +2689,40 @@ Set mapping-table of CHARSET to TABLE.
        (charset, table))
 {
   struct Lisp_Charset *cs;
-  Lisp_Object old_table;
   size_t i;
+  int byte_offset;
 
   charset = Fget_charset (charset);
   cs = XCHARSET (charset);
 
-  if (EQ (table, Qnil))
+  if (NILP (table))
     {
-      CHARSET_DECODING_TABLE(cs) = table;
+      CHARSET_DECODING_TABLE(cs) = Qnil;
       return table;
     }
   else if (VECTORP (table))
     {
-      int ccs_len;
-
-      /* ad-hoc method for `ascii' */
-      if ((CHARSET_CHARS (cs) == 94) &&
-         (CHARSET_BYTE_OFFSET (cs) != 33))
-       ccs_len = 128 - CHARSET_BYTE_OFFSET (cs);
-      else
-       ccs_len = CHARSET_CHARS (cs);
-
-      if (XVECTOR_LENGTH (table) > ccs_len)
-       args_out_of_range (table, make_int (CHARSET_CHARS (cs)));
-      old_table = CHARSET_DECODING_TABLE(cs);
-      CHARSET_DECODING_TABLE(cs) = table;
+      int ccs_len = CHARSET_BYTE_SIZE (cs);
+      int ret = decoding_table_check_elements (table,
+                                              CHARSET_DIMENSION (cs),
+                                              ccs_len);
+      if (ret)
+       {
+         if (ret == -1)
+           signal_simple_error ("Too big table", table);
+         else if (ret == -2)
+           signal_simple_error ("Invalid element is found", table);
+         else
+           signal_simple_error ("Something wrong", table);
+       }
+      CHARSET_DECODING_TABLE(cs) = Qnil;
     }
   else
     signal_error (Qwrong_type_argument,
                  list2 (build_translated_string ("vector-or-nil-p"),
                         table));
-  /* signal_simple_error ("Wrong type argument: vector-or-nil-p", table); */
 
+  byte_offset = CHARSET_BYTE_OFFSET (cs);
   switch (CHARSET_DIMENSION (cs))
     {
     case 1:
@@ -2474,9 +2731,8 @@ Set mapping-table of CHARSET to TABLE.
          Lisp_Object c = XVECTOR_DATA(table)[i];
 
          if (CHARP (c))
-           put_char_attribute
-             (c, charset,
-              make_int (i + CHARSET_BYTE_OFFSET (cs)));
+           put_char_ccs_code_point (c, charset,
+                                    make_int (i + byte_offset));
        }
       break;
     case 2:
@@ -2488,25 +2744,21 @@ Set mapping-table of CHARSET to TABLE.
            {
              size_t j;
 
-             if (XVECTOR_LENGTH (v) > CHARSET_CHARS (cs))
-               {
-                 CHARSET_DECODING_TABLE(cs) = old_table;
-                 args_out_of_range (v, make_int (CHARSET_CHARS (cs)));
-               }
              for (j = 0; j < XVECTOR_LENGTH (v); j++)
                {
                  Lisp_Object c = XVECTOR_DATA(v)[j];
 
                  if (CHARP (c))
-                   put_char_attribute
+                   put_char_ccs_code_point
                      (c, charset,
-                      make_int ( ((i + CHARSET_BYTE_OFFSET (cs)) << 8)
-                                 | (j + CHARSET_BYTE_OFFSET (cs)) ));
+                      make_int ( ( (i + byte_offset) << 8 )
+                                 | (j + byte_offset)
+                                 ) );
                }
            }
          else if (CHARP (v))
-           put_char_attribute (v, charset,
-                               make_int (i + CHARSET_BYTE_OFFSET (cs)));
+           put_char_ccs_code_point (v, charset,
+                                    make_int (i + byte_offset));
        }
       break;
     }
@@ -2757,7 +3009,7 @@ syms_of_mule_charset (void)
 {
 #ifdef UTF2000
   INIT_LRECORD_IMPLEMENTATION (byte_table);
-  INIT_LRECORD_IMPLEMENTATION (char_code_table);
+  INIT_LRECORD_IMPLEMENTATION (char_id_table);
 #endif
   INIT_LRECORD_IMPLEMENTATION (charset);
 
@@ -2841,6 +3093,11 @@ syms_of_mule_charset (void)
   defsymbol (&Qchinese_cns11643_1,     "chinese-cns11643-1");
   defsymbol (&Qchinese_cns11643_2,     "chinese-cns11643-2");
 #ifdef UTF2000
+  defsymbol (&Qname,                   "name");
+  defsymbol (&Qideographic_radical,    "ideographic-radical");
+  defsymbol (&Qideographic_strokes,    "ideographic-strokes");
+  defsymbol (&Qtotal_strokes,          "total-strokes");
+  defsymbol (&Qmorohashi_daikanwa,     "morohashi-daikanwa");
   defsymbol (&Q_ucs,                   "->ucs");
   defsymbol (&Q_decomposition,         "->decomposition");
   defsymbol (&Qcompat,                 "compat");
@@ -2942,19 +3199,37 @@ Leading-code of private TYPE9N charset of column-width 1.
 #endif
 
 #ifdef UTF2000
-  Vutf_2000_version = build_string("0.15 (Sangō)");
+  Vutf_2000_version = build_string("0.16 (Ōji)");
   DEFVAR_LISP ("utf-2000-version", &Vutf_2000_version /*
 Version number of UTF-2000.
 */ );
 
   staticpro (&Vcharacter_attribute_table);
-  Vcharacter_attribute_table = make_char_code_table (Qnil);
+  Vcharacter_attribute_table = make_char_id_table (Qnil, 0);
+
+  staticpro (&Vcharacter_name_table);
+  Vcharacter_name_table = make_char_id_table (Qnil, 0);
+
+  /* staticpro (&Vcharacter_ideographic_radical_table); */
+  Vcharacter_ideographic_radical_table = make_char_id_table (Qnil, -1);
+
+  /* staticpro (&Vcharacter_ideographic_strokes_table); */
+  Vcharacter_ideographic_strokes_table = make_char_id_table (Qnil, -1);
+
+  /* staticpro (&Vcharacter_total_strokes_table); */
+  Vcharacter_total_strokes_table = make_char_id_table (Qnil, -1);
+
+  staticpro (&Vcharacter_morohashi_daikanwa_table);
+  Vcharacter_morohashi_daikanwa_table = make_char_id_table (Qnil, 0);
+
+  /* staticpro (&Vcharacter_decomposition_table); */
+  Vcharacter_decomposition_table = make_char_id_table (Qnil, -1);
 
-  staticpro (&Vcharacter_composition_table);
-  Vcharacter_composition_table = make_char_code_table (Qnil);
+  /* staticpro (&Vcharacter_composition_table); */
+  Vcharacter_composition_table = make_char_id_table (Qnil, -1);
 
   staticpro (&Vcharacter_variant_table);
-  Vcharacter_variant_table = make_char_code_table (Qnil);
+  Vcharacter_variant_table = make_char_id_table (Qnil, 0);
 
   Vdefault_coded_charset_priority_list = Qnil;
   DEFVAR_LISP ("default-coded-charset-priority-list",