+ XCHAR_BYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
+ XCHAR_BYTE_TABLE(cpt3)->property[(unsigned char)(code >> 8)] = cpt4;
+ XCHAR_BYTE_TABLE(cpt2)->property[(unsigned char)(code >> 16)] = cpt3;
+ cpt1->property[(unsigned char)(code >> 24)] = cpt2;
+ }
+}
+
+
+Lisp_Object Vcharacter_attribute_table;
+Lisp_Object Vcharacter_composition_table;
+Lisp_Object Vcharacter_variant_table;
+
+Lisp_Object Q_decomposition;
+Lisp_Object Q_ucs;
+Lisp_Object Qcompat;
+Lisp_Object QnoBreak;
+Lisp_Object Qfraction;
+Lisp_Object Qsuper;
+Lisp_Object Qsub;
+Lisp_Object Qcircle;
+Lisp_Object Qsquare;
+Lisp_Object Qwide;
+Lisp_Object Qnarrow;
+Lisp_Object Qfont;
+
+Emchar
+to_char_code (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
+{
+ if (INTP (v))
+ return XINT (v);
+ if (CHARP (v))
+ return XCHAR (v);
+ else if (EQ (v, Qcompat))
+ return -1;
+ else if (EQ (v, QnoBreak))
+ return -2;
+ else if (EQ (v, Qfraction))
+ return -3;
+ else if (EQ (v, Qsuper))
+ return -4;
+ else if (EQ (v, Qsub))
+ return -5;
+ else if (EQ (v, Qcircle))
+ return -6;
+ else if (EQ (v, Qsquare))
+ return -7;
+ else if (EQ (v, Qwide))
+ return -8;
+ else if (EQ (v, Qnarrow))
+ return -9;
+ else if (EQ (v, Qfont))
+ return -10;
+ else
+ signal_simple_error (err_msg, err_arg);
+}
+
+DEFUN ("get-composite-char", Fget_composite_char, 1, 1, 0, /*
+Return character corresponding with list.
+*/
+ (list))
+{
+ Lisp_Object table = Vcharacter_composition_table;
+ Lisp_Object rest = list;
+
+ while (CONSP (rest))
+ {
+ Lisp_Object v = Fcar (rest);
+ Lisp_Object ret;
+ Emchar c = to_char_code (v, "Invalid value for composition", list);
+
+ ret = get_char_code_table (c, table);
+
+ rest = Fcdr (rest);
+ if (NILP (rest))
+ {
+ if (!CHAR_CODE_TABLE_P (ret))
+ return ret;
+ else
+ return Qt;
+ }
+ else if (!CONSP (rest))
+ break;
+ else if (CHAR_CODE_TABLE_P (ret))
+ table = ret;
+ else
+ signal_simple_error ("Invalid table is found with", list);
+ }
+ signal_simple_error ("Invalid value for composition", list);
+}
+
+DEFUN ("char-variants", Fchar_variants, 1, 1, 0, /*
+Return variants of CHARACTER.
+*/
+ (character))
+{
+ CHECK_CHAR (character);
+ return Fcopy_list (get_char_code_table (XCHAR (character),
+ Vcharacter_variant_table));
+}
+
+DEFUN ("char-attribute-alist", Fchar_attribute_alist, 1, 1, 0, /*
+Return the alist of attributes of CHARACTER.
+*/
+ (character))
+{
+ CHECK_CHAR (character);
+ return Fcopy_alist (get_char_code_table (XCHAR (character),
+ Vcharacter_attribute_table));
+}
+
+DEFUN ("get-char-attribute", Fget_char_attribute, 2, 2, 0, /*
+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)
+{
+ Emchar char_code = XCHAR (character);
+ Lisp_Object ret
+ = get_char_code_table (char_code, Vcharacter_attribute_table);
+ Lisp_Object cell;
+
+ cell = Fassq (attribute, ret);
+
+ if (NILP (cell))
+ {
+ ret = Fcons (Fcons (attribute, value), ret);