update.
[chise/xemacs-chise.git-] / src / mule-charset.c
index 67f1049..6f89233 100644 (file)
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA.  */
 #include "lstream.h"
 #include "device.h"
 #include "faces.h"
 #include "lstream.h"
 #include "device.h"
 #include "faces.h"
+#include "mule-ccl.h"
 
 /* The various pre-defined charsets. */
 
 
 /* The various pre-defined charsets. */
 
@@ -56,6 +57,14 @@ Lisp_Object Vcharset_korean_ksc5601;
 Lisp_Object Vcharset_japanese_jisx0212;
 Lisp_Object Vcharset_chinese_cns11643_1;
 Lisp_Object Vcharset_chinese_cns11643_2;
 Lisp_Object Vcharset_japanese_jisx0212;
 Lisp_Object Vcharset_chinese_cns11643_1;
 Lisp_Object Vcharset_chinese_cns11643_2;
+#ifdef UTF2000
+Lisp_Object Vcharset_ucs_bmp;
+Lisp_Object Vcharset_latin_viscii;
+Lisp_Object Vcharset_latin_viscii_lower;
+Lisp_Object Vcharset_latin_viscii_upper;
+Lisp_Object Vcharset_ideograph_daikanwa;
+Lisp_Object Vcharset_ethiopic_ucs;
+#endif
 Lisp_Object Vcharset_chinese_big5_1;
 Lisp_Object Vcharset_chinese_big5_2;
 
 Lisp_Object Vcharset_chinese_big5_1;
 Lisp_Object Vcharset_chinese_big5_2;
 
@@ -74,11 +83,16 @@ static int composite_char_col_next;
 #endif /* ENABLE_COMPOSITE_CHARS */
 
 /* Table of charsets indexed by leading byte. */
 #endif /* ENABLE_COMPOSITE_CHARS */
 
 /* Table of charsets indexed by leading byte. */
-Lisp_Object charset_by_leading_byte[128];
+Lisp_Object charset_by_leading_byte[NUM_LEADING_BYTES];
 
 /* Table of charsets indexed by type/final-byte/direction. */
 
 /* Table of charsets indexed by type/final-byte/direction. */
+#ifdef UTF2000
+Lisp_Object charset_by_attributes[4][128];
+#else
 Lisp_Object charset_by_attributes[4][128][2];
 Lisp_Object charset_by_attributes[4][128][2];
+#endif
 
 
+#ifndef UTF2000
 /* Table of number of bytes in the string representation of a character
    indexed by the first byte of that representation.
 
 /* Table of number of bytes in the string representation of a character
    indexed by the first byte of that representation.
 
@@ -98,12 +112,619 @@ Bytecount rep_bytes_by_first_byte[0xA0] =
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   /* 0x80 - 0x8f are for Dimension-1 official charsets */
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   /* 0x80 - 0x8f are for Dimension-1 official charsets */
+#ifdef CHAR_IS_UCS4
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+#else
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+#endif
   /* 0x90 - 0x9d are for Dimension-2 official charsets */
   /* 0x9e is for Dimension-1 private charsets */
   /* 0x9f is for Dimension-2 private charsets */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
 };
   /* 0x90 - 0x9d are for Dimension-2 official charsets */
   /* 0x9e is for Dimension-1 private charsets */
   /* 0x9f is for Dimension-2 private charsets */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
 };
+#endif
+
+#ifdef UTF2000
+
+static Lisp_Object
+mark_char_byte_table (Lisp_Object obj, void (*markobj) (Lisp_Object))
+{
+  struct Lisp_Char_Byte_Table *cte = XCHAR_BYTE_TABLE (obj);
+  int i;
+
+  for (i = 0; i < 256; i++)
+    {
+      markobj (cte->property[i]);
+    }
+  return Qnil;
+}
+
+static int
+char_byte_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+{
+  struct Lisp_Char_Byte_Table *cte1 = XCHAR_BYTE_TABLE (obj1);
+  struct Lisp_Char_Byte_Table *cte2 = XCHAR_BYTE_TABLE (obj2);
+  int i;
+
+  for (i = 0; i < 256; i++)
+    if (CHAR_BYTE_TABLE_P (cte1->property[i]))
+      {
+       if (CHAR_BYTE_TABLE_P (cte2->property[i]))
+         {
+           if (!char_byte_table_equal (cte1->property[i],
+                                       cte2->property[i], depth + 1))
+             return 0;
+         }
+       else
+         return 0;
+      }
+    else
+      if (!internal_equal (cte1->property[i], cte2->property[i], depth + 1))
+       return 0;
+  return 1;
+}
+
+static unsigned long
+char_byte_table_hash (Lisp_Object obj, int depth)
+{
+  struct Lisp_Char_Byte_Table *cte = XCHAR_BYTE_TABLE (obj);
+
+  return internal_array_hash (cte->property, 256, depth);
+}
+
+static const struct lrecord_description char_byte_table_description[] = {
+  { XD_LISP_OBJECT, offsetof(struct Lisp_Char_Byte_Table, property), 256 },
+  { XD_END }
+};
+
+DEFINE_LRECORD_IMPLEMENTATION ("char-byte-table", char_byte_table,
+                               mark_char_byte_table,
+                              internal_object_printer,
+                              0, char_byte_table_equal,
+                              char_byte_table_hash,
+                              char_byte_table_description,
+                              struct Lisp_Char_Byte_Table);
+
+static Lisp_Object
+make_char_byte_table (Lisp_Object initval)
+{
+  Lisp_Object obj;
+  int i;
+  struct Lisp_Char_Byte_Table *cte =
+    alloc_lcrecord_type (struct Lisp_Char_Byte_Table,
+                        &lrecord_char_byte_table);
+
+  for (i = 0; i < 256; i++)
+    cte->property[i] = initval;
+
+  XSETCHAR_BYTE_TABLE (obj, cte);
+  return obj;
+}
+
+static Lisp_Object
+copy_char_byte_table (Lisp_Object entry)
+{
+  struct Lisp_Char_Byte_Table *cte = XCHAR_BYTE_TABLE (entry);
+  Lisp_Object obj;
+  int i;
+  struct Lisp_Char_Byte_Table *ctenew =
+    alloc_lcrecord_type (struct Lisp_Char_Byte_Table,
+                        &lrecord_char_byte_table);
+
+  for (i = 0; i < 256; i++)
+    {
+      Lisp_Object new = cte->property[i];
+      if (CHAR_BYTE_TABLE_P (new))
+       ctenew->property[i] = copy_char_byte_table (new);
+      else
+       ctenew->property[i] = new;
+    }
+
+  XSETCHAR_BYTE_TABLE (obj, ctenew);
+  return obj;
+}
+
+
+static Lisp_Object
+mark_char_code_table (Lisp_Object obj, void (*markobj) (Lisp_Object))
+{
+  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (obj);
+
+  return cte->table;
+}
+
+static int
+char_code_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);
+
+  return char_byte_table_equal (cte1->table, cte2->table, depth + 1);
+}
+
+static unsigned long
+char_code_table_hash (Lisp_Object obj, int depth)
+{
+  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (obj);
+
+  return char_code_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 },
+  { XD_END }
+};
+
+DEFINE_LRECORD_IMPLEMENTATION ("char-code-table", char_code_table,
+                               mark_char_code_table,
+                              internal_object_printer,
+                              0, char_code_table_equal,
+                              char_code_table_hash,
+                              char_code_table_description,
+                              struct Lisp_Char_Code_Table);
+
+static Lisp_Object
+make_char_code_table (Lisp_Object initval)
+{
+  Lisp_Object obj;
+  struct Lisp_Char_Code_Table *cte =
+    alloc_lcrecord_type (struct Lisp_Char_Code_Table,
+                        &lrecord_char_code_table);
+
+  cte->table = make_char_byte_table (initval);
+
+  XSETCHAR_CODE_TABLE (obj, cte);
+  return obj;
+}
+
+static Lisp_Object
+copy_char_code_table (Lisp_Object entry)
+{
+  struct Lisp_Char_Code_Table *cte = XCHAR_CODE_TABLE (entry);
+  Lisp_Object obj;
+  struct Lisp_Char_Code_Table *ctenew =
+    alloc_lcrecord_type (struct Lisp_Char_Code_Table,
+                        &lrecord_char_code_table);
+
+  ctenew->table = copy_char_byte_table (cte->table);
+  XSETCHAR_CODE_TABLE (obj, ctenew);
+  return obj;
+}
+
+
+Lisp_Object
+get_char_code_table (Emchar ch, Lisp_Object table)
+{
+  unsigned int code = ch;
+  struct Lisp_Char_Byte_Table* cpt
+    = XCHAR_BYTE_TABLE (XCHAR_CODE_TABLE (table)->table);
+  Lisp_Object ret = cpt->property [(unsigned char)(code >> 24)];
+
+  if (CHAR_BYTE_TABLE_P (ret))
+    cpt = XCHAR_BYTE_TABLE (ret);
+  else
+    return ret;
+
+  ret = cpt->property [(unsigned char) (code >> 16)];
+  if (CHAR_BYTE_TABLE_P (ret))
+    cpt = XCHAR_BYTE_TABLE (ret);
+  else
+    return ret;
+
+  ret = cpt->property [(unsigned char) (code >> 8)];
+  if (CHAR_BYTE_TABLE_P (ret))
+    cpt = XCHAR_BYTE_TABLE (ret);
+  else
+    return ret;
+  
+  return cpt->property [(unsigned char) code];
+}
+
+void
+put_char_code_table (Emchar ch, Lisp_Object value, Lisp_Object table)
+{
+  unsigned int code = ch;
+  struct Lisp_Char_Byte_Table* cpt1
+    = XCHAR_BYTE_TABLE (XCHAR_CODE_TABLE (table)->table);
+  Lisp_Object ret = cpt1->property[(unsigned char)(code >> 24)];
+
+  if (CHAR_BYTE_TABLE_P (ret))
+    {
+      struct Lisp_Char_Byte_Table* cpt2 = XCHAR_BYTE_TABLE (ret);
+      
+      ret = cpt2->property[(unsigned char)(code >> 16)];
+      if (CHAR_BYTE_TABLE_P (ret))
+       {
+         struct Lisp_Char_Byte_Table* cpt3 = XCHAR_BYTE_TABLE (ret);
+         
+         ret = cpt3->property[(unsigned char)(code >> 8)];
+         if (CHAR_BYTE_TABLE_P (ret))
+           {
+             struct Lisp_Char_Byte_Table* cpt4
+               = XCHAR_BYTE_TABLE (ret);
+             
+             cpt4->property[(unsigned char)code] = value;
+           }
+         else if (!EQ (ret, value))
+           {
+             Lisp_Object cpt4 = make_char_byte_table (ret);
+             
+             XCHAR_BYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
+             cpt3->property[(unsigned char)(code >> 8)] = cpt4;
+           }
+       }
+      else if (!EQ (ret, value))
+       {
+         Lisp_Object cpt3 = make_char_byte_table (ret);
+         Lisp_Object cpt4 = make_char_byte_table (ret);
+         
+         XCHAR_BYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
+         XCHAR_BYTE_TABLE(cpt3)->property[(unsigned char)(code >> 8)]
+           = cpt4;
+         cpt2->property[(unsigned char)(code >> 16)] = cpt3;
+       }
+    }
+  else if (!EQ (ret, value))
+    {
+      Lisp_Object cpt2 = make_char_byte_table (ret);
+      Lisp_Object cpt3 = make_char_byte_table (ret);
+      Lisp_Object cpt4 = make_char_byte_table (ret);
+      
+      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);
+    }
+  else if (!EQ (Fcdr (cell), value))
+    {
+      Fsetcdr (cell, value);
+    }
+  put_char_code_table (char_code, ret, Vcharacter_attribute_table);
+  return ret;
+}
+  
+DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
+Store CHARACTER's ATTRIBUTE with VALUE.
+*/
+       (character, attribute, value))
+{
+  Lisp_Object ccs;
+
+  CHECK_CHAR (character);
+  ccs = Ffind_charset (attribute);
+  if (!NILP (ccs))
+    {
+      Lisp_Object rest;
+      Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
+      Lisp_Object nv;
+      int i = -1;
+      int ccs_len;
+
+      /* 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))
+       signal_simple_error ("Invalid value for coded-charset",
+                            value);
+
+      attribute = ccs;
+      rest = Fget_char_attribute (character, attribute);
+      if (VECTORP (v))
+       {
+         if (!NILP (rest))
+           {
+             while (!NILP (rest))
+               {
+                 Lisp_Object ei = Fcar (rest);
+                 
+                 i = XINT (ei) - XCHARSET_BYTE_OFFSET (ccs);
+                 nv = XVECTOR_DATA(v)[i];
+                 if (!VECTORP (nv))
+                   break;
+                 v = nv;
+                 rest = Fcdr (rest);
+               }
+             if (i >= 0)
+               XVECTOR_DATA(v)[i] = Qnil;
+             v = XCHARSET_DECODING_TABLE (ccs);
+           }
+       }
+      else
+       {
+         XCHARSET_DECODING_TABLE (ccs) = v = make_vector (ccs_len, Qnil);
+       }
+
+      if (XCHARSET_GRAPHIC (ccs) == 1)
+       value = Fcopy_list (value);
+      rest = value;
+      i = -1;
+      while (CONSP (rest))
+       {
+         Lisp_Object ei = Fcar (rest);
+         
+         if (!INTP (ei))
+           signal_simple_error ("Invalid value for coded-charset", value);
+         i = XINT (ei);
+         if ((i < 0) || (255 < i))
+           signal_simple_error ("Invalid value for coded-charset", value);
+         if (XCHARSET_GRAPHIC (ccs) == 1)
+           {
+             i &= 0x7F;
+             Fsetcar (rest, make_int (i));
+           }
+         i -= XCHARSET_BYTE_OFFSET (ccs);
+         nv = XVECTOR_DATA(v)[i];
+         rest = Fcdr (rest);
+         if (CONSP (rest))
+           {
+             if (!VECTORP (nv))
+               {
+                 nv = (XVECTOR_DATA(v)[i] = make_vector (ccs_len, Qnil));
+               }
+             v = nv;
+           }
+         else
+           break;
+       }
+      XVECTOR_DATA(v)[i] = character;
+    }
+  else if (EQ (attribute, Q_decomposition))
+    {
+      Lisp_Object rest = value;
+      Lisp_Object table = Vcharacter_composition_table;
+
+      if (!CONSP (value))
+       signal_simple_error ("Invalid value for ->decomposition",
+                            value);
+
+      while (CONSP (rest))
+       {
+         Lisp_Object v = Fcar (rest);
+         Lisp_Object ntable;
+         Emchar c
+           = to_char_code (v, "Invalid value for ->decomposition", value);
+
+         rest = Fcdr (rest);
+         if (!CONSP (rest))
+           {
+             put_char_code_table (c, character, table);
+             break;
+           }
+         else
+           {
+             ntable = get_char_code_table (c, table);
+             if (!CHAR_CODE_TABLE_P (ntable))
+               {
+                 ntable = make_char_code_table (Qnil);
+                 put_char_code_table (c, ntable, table);
+               }
+             table = ntable;
+           }
+       }
+    }
+  else if (EQ (attribute, Q_ucs))
+    {
+      Lisp_Object ret;
+      Emchar c;
+
+      if (!INTP (value))
+       signal_simple_error ("Invalid value for ->ucs", value);
+
+      c = XINT (value);
+
+      ret = get_char_code_table (c, Vcharacter_variant_table);
+      if (NILP (Fmemq (character, ret)))
+       {
+         put_char_code_table (c, Fcons (character, ret),
+                              Vcharacter_variant_table);
+       }
+    }
+  return put_char_attribute (character, attribute, value);
+}
+
+Lisp_Object Qucs;
+
+EXFUN (Fmake_char, 3);
+
+DEFUN ("define-char", Fdefine_char, 1, 1, 0, /*
+Store character's ATTRIBUTES.
+*/
+       (attributes))
+{
+  Lisp_Object rest = attributes;
+  Lisp_Object code = Fcdr (Fassq (Qucs, attributes));
+  Lisp_Object character;
+
+  if (NILP (code))
+    {
+      while (CONSP (rest))
+       {
+         Lisp_Object cell = Fcar (rest);
+         Lisp_Object ccs;
+
+         if (!LISTP (cell))
+           signal_simple_error ("Invalid argument", attributes);
+         if (!NILP (ccs = Ffind_charset (Fcar (cell))))
+           {
+             cell = Fcdr (cell);
+             character = Fmake_char (ccs, Fcar (cell),
+                                     Fcar (Fcdr (cell)));
+             goto setup_attributes;
+           }
+         rest = Fcdr (rest);
+       }
+      return Qnil;
+    }
+  else if (!INTP (code))
+    signal_simple_error ("Invalid argument", attributes);
+  else
+    character = make_char (XINT (code));
+
+ setup_attributes:
+  rest = attributes;
+  while (CONSP (rest))
+    {
+      Lisp_Object cell = Fcar (rest);
+
+      if (!LISTP (cell))
+       signal_simple_error ("Invalid argument", attributes);
+      Fput_char_attribute (character, Fcar (cell), Fcdr (cell));
+      rest = Fcdr (rest);
+    }
+  return
+    get_char_code_table (XCHAR (character), Vcharacter_attribute_table);
+}
+
+Lisp_Object Vutf_2000_version;
+#endif
+
+#ifndef UTF2000
+int leading_code_private_11;
+#endif
 
 Lisp_Object Qcharsetp;
 
 
 Lisp_Object Qcharsetp;
 
@@ -111,7 +732,6 @@ Lisp_Object Qcharsetp;
 Lisp_Object Qregistry, Qfinal, Qgraphic;
 Lisp_Object Qdirection;
 Lisp_Object Qreverse_direction_charset;
 Lisp_Object Qregistry, Qfinal, Qgraphic;
 Lisp_Object Qdirection;
 Lisp_Object Qreverse_direction_charset;
-Lisp_Object Qccl_program;
 Lisp_Object Qleading_byte;
 Lisp_Object Qshort_name, Qlong_name;
 
 Lisp_Object Qleading_byte;
 Lisp_Object Qshort_name, Qlong_name;
 
@@ -136,6 +756,16 @@ Lisp_Object Qascii,
   Qjapanese_jisx0212,
   Qchinese_cns11643_1,
   Qchinese_cns11643_2,
   Qjapanese_jisx0212,
   Qchinese_cns11643_1,
   Qchinese_cns11643_2,
+#ifdef UTF2000
+  Qucs_bmp,
+  Qlatin_viscii,
+  Qlatin_viscii_lower,
+  Qlatin_viscii_upper,
+  Qvietnamese_viscii_lower,
+  Qvietnamese_viscii_upper,
+  Qideograph_daikanwa,
+  Qethiopic_ucs,
+#endif
   Qchinese_big5_1,
   Qchinese_big5_2,
   Qcomposite;
   Qchinese_big5_1,
   Qchinese_big5_2,
   Qcomposite;
@@ -144,8 +774,12 @@ Lisp_Object Ql2r, Qr2l;
 
 Lisp_Object Vcharset_hash_table;
 
 
 Lisp_Object Vcharset_hash_table;
 
-static Bufbyte next_allocated_1_byte_leading_byte;
-static Bufbyte next_allocated_2_byte_leading_byte;
+#ifdef UTF2000
+static Charset_ID next_allocated_leading_byte;
+#else
+static Charset_ID next_allocated_1_byte_leading_byte;
+static Charset_ID next_allocated_2_byte_leading_byte;
+#endif
 
 /* Composite characters are characters constructed by overstriking two
    or more regular characters.
 
 /* Composite characters are characters constructed by overstriking two
    or more regular characters.
@@ -190,11 +824,54 @@ Bytecount
 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
 {
   Bufbyte *p;
 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
 {
   Bufbyte *p;
-  Bufbyte lb;
+#ifndef UTF2000
+  Charset_ID lb;
   int c1, c2;
   Lisp_Object charset;
   int c1, c2;
   Lisp_Object charset;
+#endif
 
   p = str;
 
   p = str;
+#ifdef UTF2000
+  if ( c <= 0x7f )
+    {
+      *p++ = c;
+    }
+  else if ( c <= 0x7ff )
+    {
+      *p++ = (c >> 6) | 0xc0;
+      *p++ = (c & 0x3f) | 0x80;
+    }
+  else if ( c <= 0xffff )
+    {
+      *p++ =  (c >> 12) | 0xe0;
+      *p++ = ((c >>  6) & 0x3f) | 0x80;
+      *p++ =  (c        & 0x3f) | 0x80;
+    }
+  else if ( c <= 0x1fffff )
+    {
+      *p++ =  (c >> 18) | 0xf0;
+      *p++ = ((c >> 12) & 0x3f) | 0x80;
+      *p++ = ((c >>  6) & 0x3f) | 0x80;
+      *p++ =  (c        & 0x3f) | 0x80;
+    }
+  else if ( c <= 0x3ffffff )
+    {
+      *p++ =  (c >> 24) | 0xf8;
+      *p++ = ((c >> 18) & 0x3f) | 0x80;
+      *p++ = ((c >> 12) & 0x3f) | 0x80;
+      *p++ = ((c >>  6) & 0x3f) | 0x80;
+      *p++ =  (c        & 0x3f) | 0x80;
+    }
+  else
+    {
+      *p++ =  (c >> 30) | 0xfc;
+      *p++ = ((c >> 24) & 0x3f) | 0x80;
+      *p++ = ((c >> 18) & 0x3f) | 0x80;
+      *p++ = ((c >> 12) & 0x3f) | 0x80;
+      *p++ = ((c >>  6) & 0x3f) | 0x80;
+      *p++ =  (c        & 0x3f) | 0x80;
+    }
+#else
   BREAKUP_CHAR (c, charset, c1, c2);
   lb = CHAR_LEADING_BYTE (c);
   if (LEADING_BYTE_PRIVATE_P (lb))
   BREAKUP_CHAR (c, charset, c1, c2);
   lb = CHAR_LEADING_BYTE (c);
   if (LEADING_BYTE_PRIVATE_P (lb))
@@ -205,7 +882,7 @@ non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
   *p++ = c1 | 0x80;
   if (c2)
     *p++ = c2 | 0x80;
   *p++ = c1 | 0x80;
   if (c2)
     *p++ = c2 | 0x80;
-
+#endif
   return (p - str);
 }
 
   return (p - str);
 }
 
@@ -216,6 +893,49 @@ non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
 Emchar
 non_ascii_charptr_emchar (CONST Bufbyte *str)
 {
 Emchar
 non_ascii_charptr_emchar (CONST Bufbyte *str)
 {
+#ifdef UTF2000
+  Bufbyte b;
+  Emchar ch;
+  int len;
+
+  b = *str++;
+  if ( b >= 0xfc )
+    {
+      ch = (b & 0x01);
+      len = 5;
+    }
+  else if ( b >= 0xf8 )
+    {
+      ch = b & 0x03;
+      len = 4;
+    }
+  else if ( b >= 0xf0 )
+    {
+      ch = b & 0x07;
+      len = 3;
+    }
+  else if ( b >= 0xe0 )
+    {
+      ch = b & 0x0f;
+      len = 2;
+    }
+  else if ( b >= 0xc0 )
+    {
+      ch = b & 0x1f;
+      len = 1;
+    }
+  else
+    {
+      ch = b;
+      len = 0;
+    }
+  for( ; len > 0; len-- )
+    {
+      b = *str++;
+      ch = ( ch << 6 ) | ( b & 0x3f );
+    }
+  return ch;
+#else
   Bufbyte i0 = *str, i1, i2 = 0;
   Lisp_Object charset;
 
   Bufbyte i0 = *str, i1, i2 = 0;
   Lisp_Object charset;
 
@@ -232,11 +952,13 @@ non_ascii_charptr_emchar (CONST Bufbyte *str)
     i2 = *++str & 0x7F;
 
   return MAKE_CHAR (charset, i1, i2);
     i2 = *++str & 0x7F;
 
   return MAKE_CHAR (charset, i1, i2);
+#endif
 }
 
 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
    Do not call this directly.  Use the macro valid_char_p() instead. */
 
 }
 
 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
    Do not call this directly.  Use the macro valid_char_p() instead. */
 
+#ifndef UTF2000
 int
 non_ascii_valid_char_p (Emchar ch)
 {
 int
 non_ascii_valid_char_p (Emchar ch)
 {
@@ -307,6 +1029,7 @@ non_ascii_valid_char_p (Emchar ch)
       return (XCHARSET_CHARS (charset) == 96);
     }
 }
       return (XCHARSET_CHARS (charset) == 96);
     }
 }
+#endif
 
 \f
 /************************************************************************/
 
 \f
 /************************************************************************/
@@ -325,6 +1048,10 @@ non_ascii_charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *str)
   switch (REP_BYTES_BY_FIRST_BYTE (*strptr))
     {
       /* Notice fallthrough. */
   switch (REP_BYTES_BY_FIRST_BYTE (*strptr))
     {
       /* Notice fallthrough. */
+#ifdef UTF2000
+    case 6: *++strptr = *ptr++;
+    case 5: *++strptr = *ptr++;
+#endif
     case 4: *++strptr = *ptr++;
     case 3: *++strptr = *ptr++;
     case 2: *++strptr = *ptr;
     case 4: *++strptr = *ptr++;
     case 3: *++strptr = *ptr++;
     case 2: *++strptr = *ptr;
@@ -354,6 +1081,16 @@ Lstream_get_emchar_1 (Lstream *stream, int ch)
   switch (REP_BYTES_BY_FIRST_BYTE (ch))
     {
       /* Notice fallthrough. */
   switch (REP_BYTES_BY_FIRST_BYTE (ch))
     {
       /* Notice fallthrough. */
+#ifdef UTF2000
+    case 6:
+      ch = Lstream_getc (stream);
+      assert (ch >= 0);
+      *++strptr = (Bufbyte) ch;
+    case 5:
+      ch = Lstream_getc (stream);
+      assert (ch >= 0);
+      *++strptr = (Bufbyte) ch;
+#endif
     case 4:
       ch = Lstream_getc (stream);
       assert (ch >= 0);
     case 4:
       ch = Lstream_getc (stream);
       assert (ch >= 0);
@@ -404,6 +1141,9 @@ mark_charset (Lisp_Object obj, void (*markobj) (Lisp_Object))
   markobj (cs->doc_string);
   markobj (cs->registry);
   markobj (cs->ccl_program);
   markobj (cs->doc_string);
   markobj (cs->registry);
   markobj (cs->ccl_program);
+#ifdef UTF2000
+  markobj (cs->decoding_table);
+#endif
   return cs->name;
 }
 
   return cs->name;
 }
 
@@ -441,17 +1181,30 @@ print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
   write_c_string (buf, printcharfun);
 }
 
   write_c_string (buf, printcharfun);
 }
 
+static const struct lrecord_description charset_description[] = {
+  { XD_LISP_OBJECT, offsetof(struct Lisp_Charset, name), 7 },
+#ifdef UTF2000
+  { XD_LISP_OBJECT, offsetof(struct Lisp_Charset, decoding_table), 2 },
+#endif
+  { XD_END }
+};
+
 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
                                mark_charset, print_charset, 0, 0, 0,
 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
                                mark_charset, print_charset, 0, 0, 0,
+                              charset_description,
                               struct Lisp_Charset);
                               struct Lisp_Charset);
+
 /* Make a new charset. */
 
 static Lisp_Object
 /* Make a new charset. */
 
 static Lisp_Object
-make_charset (int id, Lisp_Object name, unsigned char rep_bytes,
+make_charset (Charset_ID id, Lisp_Object name,
              unsigned char type, unsigned char columns, unsigned char graphic,
              unsigned char type, unsigned char columns, unsigned char graphic,
-             Bufbyte final, unsigned char direction,  Lisp_Object short_name,
+             Bufbyte final, unsigned char direction, Lisp_Object short_name,
              Lisp_Object long_name, Lisp_Object doc,
              Lisp_Object long_name, Lisp_Object doc,
-             Lisp_Object reg)
+             Lisp_Object reg,
+             Lisp_Object decoding_table,
+             Emchar ucs_min, Emchar ucs_max,
+             Emchar code_offset, unsigned char byte_offset)
 {
   Lisp_Object obj;
   struct Lisp_Charset *cs =
 {
   Lisp_Object obj;
   struct Lisp_Charset *cs =
@@ -462,7 +1215,6 @@ make_charset (int id, Lisp_Object name, unsigned char rep_bytes,
   CHARSET_NAME         (cs) = name;
   CHARSET_SHORT_NAME   (cs) = short_name;
   CHARSET_LONG_NAME    (cs) = long_name;
   CHARSET_NAME         (cs) = name;
   CHARSET_SHORT_NAME   (cs) = short_name;
   CHARSET_LONG_NAME    (cs) = long_name;
-  CHARSET_REP_BYTES    (cs) = rep_bytes;
   CHARSET_DIRECTION    (cs) = direction;
   CHARSET_TYPE         (cs) = type;
   CHARSET_COLUMNS      (cs) = columns;
   CHARSET_DIRECTION    (cs) = direction;
   CHARSET_TYPE         (cs) = type;
   CHARSET_COLUMNS      (cs) = columns;
@@ -472,26 +1224,85 @@ make_charset (int id, Lisp_Object name, unsigned char rep_bytes,
   CHARSET_REGISTRY     (cs) = reg;
   CHARSET_CCL_PROGRAM  (cs) = Qnil;
   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
   CHARSET_REGISTRY     (cs) = reg;
   CHARSET_CCL_PROGRAM  (cs) = Qnil;
   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
+#ifdef UTF2000
+  CHARSET_DECODING_TABLE(cs) = Qnil;
+  CHARSET_UCS_MIN(cs) = ucs_min;
+  CHARSET_UCS_MAX(cs) = ucs_max;
+  CHARSET_CODE_OFFSET(cs) = code_offset;
+  CHARSET_BYTE_OFFSET(cs) = byte_offset;
+#endif
 
 
-  CHARSET_DIMENSION     (cs) = (CHARSET_TYPE (cs) == CHARSET_TYPE_94 ||
-                               CHARSET_TYPE (cs) == CHARSET_TYPE_96) ? 1 : 2;
-  CHARSET_CHARS         (cs) = (CHARSET_TYPE (cs) == CHARSET_TYPE_94 ||
-                               CHARSET_TYPE (cs) == CHARSET_TYPE_94X94) ? 94 : 96;
+  switch (CHARSET_TYPE (cs))
+    {
+    case CHARSET_TYPE_94:
+      CHARSET_DIMENSION (cs) = 1;
+      CHARSET_CHARS (cs) = 94;
+      break;
+    case CHARSET_TYPE_96:
+      CHARSET_DIMENSION (cs) = 1;
+      CHARSET_CHARS (cs) = 96;
+      break;
+    case CHARSET_TYPE_94X94:
+      CHARSET_DIMENSION (cs) = 2;
+      CHARSET_CHARS (cs) = 94;
+      break;
+    case CHARSET_TYPE_96X96:
+      CHARSET_DIMENSION (cs) = 2;
+      CHARSET_CHARS (cs) = 96;
+      break;
+#ifdef UTF2000
+    case CHARSET_TYPE_128:
+      CHARSET_DIMENSION (cs) = 1;
+      CHARSET_CHARS (cs) = 128;
+      break;
+    case CHARSET_TYPE_128X128:
+      CHARSET_DIMENSION (cs) = 2;
+      CHARSET_CHARS (cs) = 128;
+      break;
+    case CHARSET_TYPE_256:
+      CHARSET_DIMENSION (cs) = 1;
+      CHARSET_CHARS (cs) = 256;
+      break;
+    case CHARSET_TYPE_256X256:
+      CHARSET_DIMENSION (cs) = 2;
+      CHARSET_CHARS (cs) = 256;
+      break;
+#endif
+    }
 
 
+#ifndef UTF2000
+  if (id == LEADING_BYTE_ASCII)
+    CHARSET_REP_BYTES (cs) = 1;
+  else if (id < 0xA0)
+    CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
+  else
+    CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
+#endif
+  
   if (final)
     {
       /* some charsets do not have final characters.  This includes
         ASCII, Control-1, Composite, and the two faux private
         charsets. */
   if (final)
     {
       /* some charsets do not have final characters.  This includes
         ASCII, Control-1, Composite, and the two faux private
         charsets. */
+#if UTF2000
+      if (code_offset == 0)
+       {
+         assert (NILP (charset_by_attributes[type][final]));
+         charset_by_attributes[type][final] = obj;
+       }
+#else
       assert (NILP (charset_by_attributes[type][final][direction]));
       charset_by_attributes[type][final][direction] = obj;
       assert (NILP (charset_by_attributes[type][final][direction]));
       charset_by_attributes[type][final][direction] = obj;
+#endif
     }
 
     }
 
-  assert (NILP (charset_by_leading_byte[id - 128]));
-  charset_by_leading_byte[id - 128] = obj;
+  assert (NILP (charset_by_leading_byte[id - MIN_LEADING_BYTE]));
+  charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
+#ifndef UTF2000
   if (id < 0xA0)
     /* official leading byte */
   if (id < 0xA0)
     /* official leading byte */
-    rep_bytes_by_first_byte[id] = rep_bytes;
+    rep_bytes_by_first_byte[id] = CHARSET_REP_BYTES (cs);
+#endif
 
   /* Some charsets are "faux" and don't have names or really exist at
      all except in the leading-byte table. */
 
   /* Some charsets are "faux" and don't have names or really exist at
      all except in the leading-byte table. */
@@ -503,8 +1314,14 @@ make_charset (int id, Lisp_Object name, unsigned char rep_bytes,
 static int
 get_unallocated_leading_byte (int dimension)
 {
 static int
 get_unallocated_leading_byte (int dimension)
 {
-  int lb;
+  Charset_ID lb;
 
 
+#ifdef UTF2000
+  if (next_allocated_leading_byte > MAX_LEADING_BYTE_PRIVATE)
+    lb = 0;
+  else
+    lb = next_allocated_leading_byte++;
+#else
   if (dimension == 1)
     {
       if (next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
   if (dimension == 1)
     {
       if (next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
@@ -519,6 +1336,7 @@ get_unallocated_leading_byte (int dimension)
       else
        lb = next_allocated_2_byte_leading_byte++;
     }
       else
        lb = next_allocated_2_byte_leading_byte++;
     }
+#endif
 
   if (!lb)
     signal_simple_error
 
   if (!lb)
     signal_simple_error
@@ -528,6 +1346,214 @@ get_unallocated_leading_byte (int dimension)
   return lb;
 }
 
   return lb;
 }
 
+#ifdef UTF2000
+Lisp_Object
+range_charset_code_point (Lisp_Object charset, Emchar ch)
+{
+  int d;
+
+  if ((XCHARSET_UCS_MIN (charset) <= ch)
+      && (ch <= XCHARSET_UCS_MAX (charset)))
+    {
+      d = ch - XCHARSET_UCS_MIN (charset) + XCHARSET_CODE_OFFSET (charset);
+                      
+      if (XCHARSET_DIMENSION (charset) == 1)
+       return list1 (make_int (d + XCHARSET_BYTE_OFFSET (charset)));
+      else if (XCHARSET_DIMENSION (charset) == 2)
+       return list2 (make_int (d / XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)));
+      else if (XCHARSET_DIMENSION (charset) == 3)
+       return list3 (make_int (d / (XCHARSET_CHARS (charset)
+                                       * XCHARSET_CHARS (charset))
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d / XCHARSET_CHARS (charset)
+                               % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)));
+      else /* if (XCHARSET_DIMENSION (charset) == 4) */
+       return list4 (make_int (d / (XCHARSET_CHARS (charset)
+                                       * XCHARSET_CHARS (charset)
+                                       * XCHARSET_CHARS (charset))
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d / (XCHARSET_CHARS (charset)
+                                       * XCHARSET_CHARS (charset))
+                               % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d / XCHARSET_CHARS (charset)
+                               % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)),
+                     make_int (d % XCHARSET_CHARS (charset)
+                               + XCHARSET_BYTE_OFFSET (charset)));
+    }
+  else if (XCHARSET_CODE_OFFSET (charset) == 0)
+    {
+      if (XCHARSET_DIMENSION (charset) == 1)
+       {
+         if (XCHARSET_CHARS (charset) == 94)
+           {
+             if (((d = ch - (MIN_CHAR_94
+                             + (XCHARSET_FINAL (charset) - '0') * 94)) >= 0)
+                 && (d < 94))
+               return list1 (make_int (d + 33));
+           }
+         else if (XCHARSET_CHARS (charset) == 96)
+           {
+             if (((d = ch - (MIN_CHAR_96
+                             + (XCHARSET_FINAL (charset) - '0') * 96)) >= 0)
+                 && (d < 96))
+               return list1 (make_int (d + 32));
+           }
+         else
+           return Qnil;
+       }
+      else if (XCHARSET_DIMENSION (charset) == 2)
+       {
+         if (XCHARSET_CHARS (charset) == 94)
+           {
+             if (((d = ch - (MIN_CHAR_94x94
+                             + (XCHARSET_FINAL (charset) - '0') * 94 * 94))
+                  >= 0)
+                 && (d < 94 * 94))
+               return list2 (make_int ((d / 94) + 33),
+                             make_int (d % 94 + 33));
+           }
+         else if (XCHARSET_CHARS (charset) == 96)
+           {
+             if (((d = ch - (MIN_CHAR_96x96
+                             + (XCHARSET_FINAL (charset) - '0') * 96 * 96))
+                  >= 0)
+                 && (d < 96 * 96))
+               return list2 (make_int ((d / 96) + 32),
+                             make_int (d % 96 + 32));
+           }
+       }
+    }
+  return Qnil;
+}
+
+Lisp_Object
+split_builtin_char (Emchar c)
+{
+  if (c < MIN_CHAR_OBS_94x94)
+    {
+      if (c <= MAX_CHAR_BASIC_LATIN)
+       {
+         return list2 (Vcharset_ascii, make_int (c));
+       }
+      else if (c < 0xA0)
+       {
+         return list2 (Vcharset_control_1, make_int (c & 0x7F));
+       }
+      else if (c <= 0xff)
+       {
+         return list2 (Vcharset_latin_iso8859_1, make_int (c & 0x7F));
+       }
+      else if ((MIN_CHAR_GREEK <= c) && (c <= MAX_CHAR_GREEK))
+       {
+         return list2 (Vcharset_greek_iso8859_7,
+                       make_int (c - MIN_CHAR_GREEK + 0x20));
+       }
+      else if ((MIN_CHAR_CYRILLIC <= c) && (c <= MAX_CHAR_CYRILLIC))
+       {
+         return list2 (Vcharset_cyrillic_iso8859_5,
+                       make_int (c - MIN_CHAR_CYRILLIC + 0x20));
+       }
+      else if ((MIN_CHAR_HEBREW <= c) && (c <= MAX_CHAR_HEBREW))
+       {
+         return list2 (Vcharset_hebrew_iso8859_8,
+                       make_int (c - MIN_CHAR_HEBREW + 0x20));
+       }
+      else if ((MIN_CHAR_THAI <= c) && (c <= MAX_CHAR_THAI))
+       {
+         return list2 (Vcharset_thai_tis620,
+                       make_int (c - MIN_CHAR_THAI + 0x20));
+       }
+      else if ((MIN_CHAR_HALFWIDTH_KATAKANA <= c)
+              && (c <= MAX_CHAR_HALFWIDTH_KATAKANA))
+       {
+         return list2 (Vcharset_katakana_jisx0201,
+                       make_int (c - MIN_CHAR_HALFWIDTH_KATAKANA + 33));
+       }
+      else
+       {
+         return list3 (Vcharset_ucs_bmp,
+                       make_int (c >> 8), make_int (c & 0xff));
+       }
+    }
+  else if (c <= MAX_CHAR_OBS_94x94)
+    {
+      return list3 (CHARSET_BY_ATTRIBUTES
+                   (CHARSET_TYPE_94X94,
+                    ((c - MIN_CHAR_OBS_94x94) / (94 * 94)) + '@',
+                    CHARSET_LEFT_TO_RIGHT),
+                   make_int ((((c - MIN_CHAR_OBS_94x94) / 94) % 94) + 33),
+                   make_int (((c - MIN_CHAR_OBS_94x94) % 94) + 33));
+    }
+  else if (c <= MAX_CHAR_DAIKANWA)
+    {
+      return list3 (Vcharset_ideograph_daikanwa,
+                   make_int ((c - MIN_CHAR_DAIKANWA) >> 8),
+                   make_int ((c - MIN_CHAR_DAIKANWA) & 255));
+    }
+  else if (c <= MAX_CHAR_94)
+    {
+      return list2 (CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_94,
+                                          ((c - MIN_CHAR_94) / 94) + '0',
+                                          CHARSET_LEFT_TO_RIGHT),
+                   make_int (((c - MIN_CHAR_94) % 94) + 33));
+    }
+  else if (c <= MAX_CHAR_96)
+    {
+      return list2 (CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_96,
+                                          ((c - MIN_CHAR_96) / 96) + '0',
+                                          CHARSET_LEFT_TO_RIGHT),
+                   make_int (((c - MIN_CHAR_96) % 96) + 32));
+    }
+  else if (c <= MAX_CHAR_94x94)
+    {
+      return list3 (CHARSET_BY_ATTRIBUTES
+                   (CHARSET_TYPE_94X94,
+                    ((c - MIN_CHAR_94x94) / (94 * 94)) + '0',
+                    CHARSET_LEFT_TO_RIGHT),
+                   make_int ((((c - MIN_CHAR_94x94) / 94) % 94) + 33),
+                   make_int (((c - MIN_CHAR_94x94) % 94) + 33));
+    }
+  else if (c <= MAX_CHAR_96x96)
+    {
+      return list3 (CHARSET_BY_ATTRIBUTES
+                   (CHARSET_TYPE_96X96,
+                    ((c - MIN_CHAR_96x96) / (96 * 96)) + '0',
+                    CHARSET_LEFT_TO_RIGHT),
+                   make_int ((((c - MIN_CHAR_96x96) / 96) % 96) + 32),
+                   make_int (((c - MIN_CHAR_96x96) % 96) + 32));
+    }
+  else
+    {
+      return Qnil;
+    }
+}
+
+Lisp_Object
+charset_code_point (Lisp_Object charset, Emchar ch)
+{
+  Lisp_Object cdef = get_char_code_table (ch, Vcharacter_attribute_table);
+
+  if (!EQ (cdef, Qnil))
+    {
+      Lisp_Object field = Fassq (charset, cdef);
+
+      if (!EQ (field, Qnil))
+       return Fcdr (field);
+    }
+  return range_charset_code_point (charset, ch);
+}
+
+Lisp_Object Vdefault_coded_charset_priority_list;
+#endif
+
 \f
 /************************************************************************/
 /*                      Basic charset Lisp functions                    */
 \f
 /************************************************************************/
 /*                      Basic charset Lisp functions                    */
@@ -674,6 +1700,7 @@ character set.  Recognized properties are:
   Lisp_Object rest, keyword, value;
   Lisp_Object ccl_program = Qnil;
   Lisp_Object short_name = Qnil, long_name = Qnil;
   Lisp_Object rest, keyword, value;
   Lisp_Object ccl_program = Qnil;
   Lisp_Object short_name = Qnil, long_name = Qnil;
+  int byte_offset = -1;
 
   CHECK_SYMBOL (name);
   if (!NILP (doc_string))
 
   CHECK_SYMBOL (name);
   if (!NILP (doc_string))
@@ -725,7 +1752,11 @@ character set.  Recognized properties are:
        {
          CHECK_INT (value);
          graphic = XINT (value);
        {
          CHECK_INT (value);
          graphic = XINT (value);
+#ifdef UTF2000
+         if (graphic < 0 || graphic > 2)
+#else
          if (graphic < 0 || graphic > 1)
          if (graphic < 0 || graphic > 1)
+#endif
            signal_simple_error ("Invalid value for 'graphic", value);
        }
 
            signal_simple_error ("Invalid value for 'graphic", value);
        }
 
@@ -796,8 +1827,21 @@ character set.  Recognized properties are:
 
   if (columns == -1)
     columns = dimension;
 
   if (columns == -1)
     columns = dimension;
-  charset = make_charset (id, name, dimension + 2, type, columns, graphic,
-                         final, direction, short_name, long_name, doc_string, registry);
+
+  if (byte_offset < 0)
+    {
+      if (chars == 94)
+       byte_offset = 33;
+      else if (chars == 96)
+       byte_offset = 32;
+      else
+       byte_offset = 0;
+    }
+
+  charset = make_charset (id, name, type, columns, graphic,
+                         final, direction, short_name, long_name,
+                         doc_string, registry,
+                         Qnil, 0, 0, 0, byte_offset);
   if (!NILP (ccl_program))
     XCHARSET_CCL_PROGRAM (charset) = ccl_program;
   return charset;
   if (!NILP (ccl_program))
     XCHARSET_CCL_PROGRAM (charset) = ccl_program;
   return charset;
@@ -842,9 +1886,19 @@ NEW-NAME is the name of the new charset.  Return the new charset.
   long_name = CHARSET_LONG_NAME (cs);
   registry = CHARSET_REGISTRY (cs);
 
   long_name = CHARSET_LONG_NAME (cs);
   registry = CHARSET_REGISTRY (cs);
 
-  new_charset = make_charset (id, new_name, dimension + 2, type, columns,
+  new_charset = make_charset (id, new_name, type, columns,
                              graphic, final, direction, short_name, long_name,
                              graphic, final, direction, short_name, long_name,
-                             doc_string, registry);
+                             doc_string, registry,
+#ifdef UTF2000
+                             CHARSET_DECODING_TABLE(cs),
+                             CHARSET_UCS_MIN(cs),
+                             CHARSET_UCS_MAX(cs),
+                             CHARSET_CODE_OFFSET(cs),
+                             CHARSET_BYTE_OFFSET(cs)
+#else
+                             Qnil, 0, 0, 0, 0
+#endif
+);
 
   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
   XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
 
   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
   XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
@@ -852,6 +1906,16 @@ NEW-NAME is the name of the new charset.  Return the new charset.
   return new_charset;
 }
 
   return new_charset;
 }
 
+DEFUN ("define-charset-alias", Fdefine_charset_alias, 2, 2, 0, /*
+Define symbol ALIAS as an alias for CHARSET.
+*/
+       (alias, charset))
+{
+  CHECK_SYMBOL (alias);
+  charset = Fget_charset (charset);
+  return Fputhash (alias, charset, Vcharset_hash_table);
+}
+
 /* #### Reverse direction charsets not yet implemented.  */
 #if 0
 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
 /* #### Reverse direction charsets not yet implemented.  */
 #if 0
 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
@@ -1030,7 +2094,6 @@ invalidate_charset_font_caches (Lisp_Object charset)
     }
 }
 
     }
 }
 
-/* Japanese folks may want to (set-charset-registry 'ascii "jisx0201") */
 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
 Set the 'registry property of CHARSET to REGISTRY.
 */
 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
 Set the 'registry property of CHARSET to REGISTRY.
 */
@@ -1044,13 +2107,115 @@ Set the 'registry property of CHARSET to REGISTRY.
   return Qnil;
 }
 
   return Qnil;
 }
 
+#ifdef UTF2000
+DEFUN ("charset-mapping-table", Fcharset_mapping_table, 1, 1, 0, /*
+Return mapping-table of CHARSET.
+*/
+       (charset))
+{
+  return XCHARSET_DECODING_TABLE (Fget_charset (charset));
+}
+
+DEFUN ("set-charset-mapping-table", Fset_charset_mapping_table, 2, 2, 0, /*
+Set mapping-table of CHARSET to TABLE.
+*/
+       (charset, table))
+{
+  struct Lisp_Charset *cs;
+  Lisp_Object old_table;
+  size_t i;
+
+  charset = Fget_charset (charset);
+  cs = XCHARSET (charset);
+
+  if (EQ (table, Qnil))
+    {
+      CHARSET_DECODING_TABLE(cs) = table;
+      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;
+    }
+  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); */
+
+  switch (CHARSET_DIMENSION (cs))
+    {
+    case 1:
+      for (i = 0; i < XVECTOR_LENGTH (table); i++)
+       {
+         Lisp_Object c = XVECTOR_DATA(table)[i];
+
+         if (CHARP (c))
+           put_char_attribute
+             (c, charset,
+              list1 (make_int (i + CHARSET_BYTE_OFFSET (cs))));
+       }
+      break;
+    case 2:
+      for (i = 0; i < XVECTOR_LENGTH (table); i++)
+       {
+         Lisp_Object v = XVECTOR_DATA(table)[i];
+
+         if (VECTORP (v))
+           {
+             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 (c, charset,
+                                       list2
+                                       (make_int
+                                        (i + CHARSET_BYTE_OFFSET (cs)),
+                                        make_int
+                                        (j + CHARSET_BYTE_OFFSET (cs))));
+               }
+           }
+         else if (CHARP (v))
+           put_char_attribute (v, charset,
+                               list1
+                               (make_int (i + CHARSET_BYTE_OFFSET (cs))));
+       }
+      break;
+    }
+  return table;
+}
+#endif
+
 \f
 /************************************************************************/
 /*              Lisp primitives for working with characters             */
 /************************************************************************/
 
 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
 \f
 /************************************************************************/
 /*              Lisp primitives for working with characters             */
 /************************************************************************/
 
 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
-Make a multi-byte character from CHARSET and octets ARG1 and ARG2.
+Make a character from CHARSET and octets ARG1 and ARG2.
+ARG2 is required only for characters from two-dimensional charsets.
+For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
+character s with caron.
 */
        (charset, arg1, arg2))
 {
 */
        (charset, arg1, arg2))
 {
@@ -1063,6 +2228,9 @@ Make a multi-byte character from CHARSET and octets ARG1 and ARG2.
 
   if      (EQ (charset, Vcharset_ascii))     lowlim =  0, highlim = 127;
   else if (EQ (charset, Vcharset_control_1)) lowlim =  0, highlim =  31;
 
   if      (EQ (charset, Vcharset_ascii))     lowlim =  0, highlim = 127;
   else if (EQ (charset, Vcharset_control_1)) lowlim =  0, highlim =  31;
+#ifdef UTF2000
+  else if (CHARSET_CHARS (cs) == 256)        lowlim =  0, highlim = 255;
+#endif
   else if (CHARSET_CHARS (cs) == 94)         lowlim = 33, highlim = 126;
   else /* CHARSET_CHARS (cs) == 96) */      lowlim = 32, highlim = 127;
 
   else if (CHARSET_CHARS (cs) == 94)         lowlim = 33, highlim = 126;
   else /* CHARSET_CHARS (cs) == 96) */      lowlim = 32, highlim = 127;
 
@@ -1071,7 +2239,13 @@ Make a multi-byte character from CHARSET and octets ARG1 and ARG2.
      the 8th bit off ARG1 and ARG2 becaue it allows programmers to
      write (make-char 'latin-iso8859-2 CODE) where code is the actual
      Latin 2 code of the character.  */
      the 8th bit off ARG1 and ARG2 becaue it allows programmers to
      write (make-char 'latin-iso8859-2 CODE) where code is the actual
      Latin 2 code of the character.  */
-  a1 = XINT (arg1) & 0x7f;
+#ifdef UTF2000
+  a1 = XINT (arg1);
+  if (highlim < 128)
+    a1 &= 0x7f;
+#else
+  a1 = XINT (arg1);
+#endif
   if (a1 < lowlim || a1 > highlim)
     args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
 
   if (a1 < lowlim || a1 > highlim)
     args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
 
@@ -1084,7 +2258,13 @@ Make a multi-byte character from CHARSET and octets ARG1 and ARG2.
     }
 
   CHECK_INT (arg2);
     }
 
   CHECK_INT (arg2);
+#ifdef UTF2000
+  a2 = XINT (arg2);
+  if (highlim < 128)
+    a2 &= 0x7f;
+#else
   a2 = XINT (arg2) & 0x7f;
   a2 = XINT (arg2) & 0x7f;
+#endif
   if (a2 < lowlim || a2 > highlim)
     args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
 
   if (a2 < lowlim || a2 > highlim)
     args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
 
@@ -1098,31 +2278,48 @@ Return the character set of char CH.
 {
   CHECK_CHAR_COERCE_INT (ch);
 
 {
   CHECK_CHAR_COERCE_INT (ch);
 
-  return XCHARSET_NAME (CHARSET_BY_LEADING_BYTE
-                       (CHAR_LEADING_BYTE (XCHAR (ch))));
+  return XCHARSET_NAME (CHAR_CHARSET (XCHAR (ch)));
 }
 
 }
 
-DEFUN ("char-octet", Fchar_octet, 1, 2, 0, /*
-Return the octet numbered N (should be 0 or 1) of char CH.
-N defaults to 0 if omitted.
+DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
+Return list of charset and one or two position-codes of CHAR.
 */
 */
-       (ch, n))
+       (character))
 {
 {
+#ifdef UTF2000
+  Lisp_Object ret;
   Lisp_Object charset;
   Lisp_Object charset;
-  int c1, c2, int_n;
 
 
-  CHECK_CHAR_COERCE_INT (ch);
-  if (NILP (n))
-    int_n = 0;
+  CHECK_CHAR_COERCE_INT (character);
+  ret = SPLIT_CHAR (XCHAR (character));
+  charset = Fcar (ret);
+  if (CHARSETP (charset))
+    return Fcons (XCHARSET_NAME (charset), Fcopy_list (Fcdr (ret)));
+  else
+    return ret;
+#else
+  /* This function can GC */
+  struct gcpro gcpro1, gcpro2;
+  Lisp_Object charset = Qnil;
+  Lisp_Object rc = Qnil;
+  int c1, c2;
+
+  GCPRO2 (charset, rc);
+  CHECK_CHAR_COERCE_INT (character);
+
+  BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
+
+  if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
+    {
+      rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
+    }
   else
     {
   else
     {
-      CHECK_INT (n);
-      int_n = XINT (n);
-      if (int_n != 0 && int_n != 1)
-       signal_simple_error ("Octet number must be 0 or 1", n);
+      rc = list2 (XCHARSET_NAME (charset), make_int (c1));
     }
     }
-  BREAKUP_CHAR (XCHAR (ch), charset, c1, c2);
-  return make_int (int_n == 0 ? c1 : c2);
+  UNGCPRO;
+  return rc;
+#endif
 }
 
 \f
 }
 
 \f
@@ -1215,6 +2412,7 @@ syms_of_mule_charset (void)
   DEFSUBR (Fmake_charset);
   DEFSUBR (Fmake_reverse_direction_charset);
   /*  DEFSUBR (Freverse_direction_charset); */
   DEFSUBR (Fmake_charset);
   DEFSUBR (Fmake_reverse_direction_charset);
   /*  DEFSUBR (Freverse_direction_charset); */
+  DEFSUBR (Fdefine_charset_alias);
   DEFSUBR (Fcharset_from_attributes);
   DEFSUBR (Fcharset_short_name);
   DEFSUBR (Fcharset_long_name);
   DEFSUBR (Fcharset_from_attributes);
   DEFSUBR (Fcharset_short_name);
   DEFSUBR (Fcharset_long_name);
@@ -1224,10 +2422,20 @@ syms_of_mule_charset (void)
   DEFSUBR (Fcharset_id);
   DEFSUBR (Fset_charset_ccl_program);
   DEFSUBR (Fset_charset_registry);
   DEFSUBR (Fcharset_id);
   DEFSUBR (Fset_charset_ccl_program);
   DEFSUBR (Fset_charset_registry);
+#ifdef UTF2000
+  DEFSUBR (Fchar_attribute_alist);
+  DEFSUBR (Fget_char_attribute);
+  DEFSUBR (Fput_char_attribute);
+  DEFSUBR (Fdefine_char);
+  DEFSUBR (Fchar_variants);
+  DEFSUBR (Fget_composite_char);
+  DEFSUBR (Fcharset_mapping_table);
+  DEFSUBR (Fset_charset_mapping_table);
+#endif
 
   DEFSUBR (Fmake_char);
   DEFSUBR (Fchar_charset);
 
   DEFSUBR (Fmake_char);
   DEFSUBR (Fchar_charset);
-  DEFSUBR (Fchar_octet);
+  DEFSUBR (Fsplit_char);
 
 #ifdef ENABLE_COMPOSITE_CHARS
   DEFSUBR (Fmake_composite_char);
 
 #ifdef ENABLE_COMPOSITE_CHARS
   DEFSUBR (Fmake_composite_char);
@@ -1240,7 +2448,6 @@ syms_of_mule_charset (void)
   defsymbol (&Qgraphic, "graphic");
   defsymbol (&Qdirection, "direction");
   defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
   defsymbol (&Qgraphic, "graphic");
   defsymbol (&Qdirection, "direction");
   defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
-  defsymbol (&Qccl_program, "ccl-program");
   defsymbol (&Qshort_name, "short-name");
   defsymbol (&Qlong_name, "long-name");
 
   defsymbol (&Qshort_name, "short-name");
   defsymbol (&Qlong_name, "long-name");
 
@@ -1270,6 +2477,29 @@ syms_of_mule_charset (void)
   defsymbol (&Qjapanese_jisx0212,      "japanese-jisx0212");
   defsymbol (&Qchinese_cns11643_1,     "chinese-cns11643-1");
   defsymbol (&Qchinese_cns11643_2,     "chinese-cns11643-2");
   defsymbol (&Qjapanese_jisx0212,      "japanese-jisx0212");
   defsymbol (&Qchinese_cns11643_1,     "chinese-cns11643-1");
   defsymbol (&Qchinese_cns11643_2,     "chinese-cns11643-2");
+#ifdef UTF2000
+  defsymbol (&Q_ucs,                   "->ucs");
+  defsymbol (&Q_decomposition,         "->decomposition");
+  defsymbol (&Qcompat,                 "compat");
+  defsymbol (&QnoBreak,                        "noBreak");
+  defsymbol (&Qfraction,               "fraction");
+  defsymbol (&Qsuper,                  "super");
+  defsymbol (&Qsub,                    "sub");
+  defsymbol (&Qcircle,                 "circle");
+  defsymbol (&Qsquare,                 "square");
+  defsymbol (&Qwide,                   "wide");
+  defsymbol (&Qnarrow,                 "narrow");
+  defsymbol (&Qfont,                   "font");
+  defsymbol (&Qucs,                    "ucs");
+  defsymbol (&Qucs_bmp,                        "ucs-bmp");
+  defsymbol (&Qlatin_viscii,           "latin-viscii");
+  defsymbol (&Qlatin_viscii_lower,     "latin-viscii-lower");
+  defsymbol (&Qlatin_viscii_upper,     "latin-viscii-upper");
+  defsymbol (&Qvietnamese_viscii_lower,        "vietnamese-viscii-lower");
+  defsymbol (&Qvietnamese_viscii_upper,        "vietnamese-viscii-upper");
+  defsymbol (&Qideograph_daikanwa,     "ideograph-daikanwa");
+  defsymbol (&Qethiopic_ucs,           "ethiopic-ucs");
+#endif
   defsymbol (&Qchinese_big5_1,         "chinese-big5-1");
   defsymbol (&Qchinese_big5_2,         "chinese-big5-2");
 
   defsymbol (&Qchinese_big5_1,         "chinese-big5-1");
   defsymbol (&Qchinese_big5_2,         "chinese-big5-2");
 
@@ -1279,20 +2509,64 @@ syms_of_mule_charset (void)
 void
 vars_of_mule_charset (void)
 {
 void
 vars_of_mule_charset (void)
 {
-  int i, j, k;
+  int i, j;
+#ifndef UTF2000
+  int k;
+#endif
 
   /* Table of charsets indexed by leading byte. */
   for (i = 0; i < countof (charset_by_leading_byte); i++)
     charset_by_leading_byte[i] = Qnil;
 
 
   /* Table of charsets indexed by leading byte. */
   for (i = 0; i < countof (charset_by_leading_byte); i++)
     charset_by_leading_byte[i] = Qnil;
 
+#ifdef UTF2000
+  /* Table of charsets indexed by type/final-byte. */
+  for (i = 0; i < countof (charset_by_attributes); i++)
+    for (j = 0; j < countof (charset_by_attributes[0]); j++)
+       charset_by_attributes[i][j] = Qnil;
+#else
   /* Table of charsets indexed by type/final-byte/direction. */
   for (i = 0; i < countof (charset_by_attributes); i++)
     for (j = 0; j < countof (charset_by_attributes[0]); j++)
       for (k = 0; k < countof (charset_by_attributes[0][0]); k++)
        charset_by_attributes[i][j][k] = Qnil;
   /* Table of charsets indexed by type/final-byte/direction. */
   for (i = 0; i < countof (charset_by_attributes); i++)
     for (j = 0; j < countof (charset_by_attributes[0]); j++)
       for (k = 0; k < countof (charset_by_attributes[0][0]); k++)
        charset_by_attributes[i][j][k] = Qnil;
+#endif
 
 
+#ifdef UTF2000
+  next_allocated_leading_byte = MIN_LEADING_BYTE_PRIVATE;
+#else
   next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
   next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
   next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
   next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
+#endif
+
+#ifndef UTF2000
+  leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
+  DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
+Leading-code of private TYPE9N charset of column-width 1.
+*/ );
+  leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
+#endif
+
+#ifdef UTF2000
+  Vutf_2000_version = build_string("0.12 (Kashiwara)");
+  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);
+
+  staticpro (&Vcharacter_composition_table);
+  Vcharacter_composition_table = make_char_code_table (Qnil);
+
+  staticpro (&Vcharacter_variant_table);
+  Vcharacter_variant_table = make_char_code_table (Qnil);
+
+  Vdefault_coded_charset_priority_list = Qnil;
+  DEFVAR_LISP ("default-coded-charset-priority-list",
+              &Vdefault_coded_charset_priority_list /*
+Default order of preferred coded-character-sets.
+*/ );
+#endif
 }
 
 void
 }
 
 void
@@ -1305,205 +2579,298 @@ complex_vars_of_mule_charset (void)
   /* Predefined character sets.  We store them into variables for
      ease of access. */
 
   /* Predefined character sets.  We store them into variables for
      ease of access. */
 
+#ifdef UTF2000
+  Vcharset_ucs_bmp =
+    make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp,
+                 CHARSET_TYPE_256X256, 1, 2, 0,
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("BMP"),
+                 build_string ("BMP"),
+                 build_string ("ISO/IEC 10646 Group 0 Plane 0 (BMP)"),
+                 build_string ("\\(ISO10646.*-1\\|UNICODE[23]?-0\\)"),
+                 Qnil, 0, 0xFFFF, 0, 0);
+#else
+# define MIN_CHAR_THAI 0
+# define MAX_CHAR_THAI 0
+# define MIN_CHAR_GREEK 0
+# define MAX_CHAR_GREEK 0
+# define MIN_CHAR_HEBREW 0
+# define MAX_CHAR_HEBREW 0
+# define MIN_CHAR_HALFWIDTH_KATAKANA 0
+# define MAX_CHAR_HALFWIDTH_KATAKANA 0
+# define MIN_CHAR_CYRILLIC 0
+# define MAX_CHAR_CYRILLIC 0
+#endif
   Vcharset_ascii =
   Vcharset_ascii =
-    make_charset (LEADING_BYTE_ASCII, Qascii, 1,
+    make_charset (LEADING_BYTE_ASCII, Qascii,
                  CHARSET_TYPE_94, 1, 0, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ASCII"),
                  build_string ("ASCII)"),
                  build_string ("ASCII (ISO646 IRV)"),
                  CHARSET_TYPE_94, 1, 0, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ASCII"),
                  build_string ("ASCII)"),
                  build_string ("ASCII (ISO646 IRV)"),
-                 build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"));
+                 build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
+                 Qnil, 0, 0x7F, 0, 0);
   Vcharset_control_1 =
   Vcharset_control_1 =
-    make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1, 2,
+    make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1,
                  CHARSET_TYPE_94, 1, 1, 0,
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("C1"),
                  build_string ("Control characters"),
                  build_string ("Control characters 128-191"),
                  CHARSET_TYPE_94, 1, 1, 0,
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("C1"),
                  build_string ("Control characters"),
                  build_string ("Control characters 128-191"),
-                 build_string (""));
+                 build_string (""),
+                 Qnil, 0x80, 0x9F, 0, 0);
   Vcharset_latin_iso8859_1 =
   Vcharset_latin_iso8859_1 =
-    make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1, 2,
+    make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1,
                  CHARSET_TYPE_96, 1, 1, 'A',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-1"),
                  build_string ("ISO8859-1 (Latin-1)"),
                  build_string ("ISO8859-1 (Latin-1)"),
                  CHARSET_TYPE_96, 1, 1, 'A',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-1"),
                  build_string ("ISO8859-1 (Latin-1)"),
                  build_string ("ISO8859-1 (Latin-1)"),
-                 build_string ("iso8859-1"));
+                 build_string ("iso8859-1"),
+                 Qnil, 0xA0, 0xFF, 0, 32);
   Vcharset_latin_iso8859_2 =
   Vcharset_latin_iso8859_2 =
-    make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2, 2,
+    make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2,
                  CHARSET_TYPE_96, 1, 1, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-2"),
                  build_string ("ISO8859-2 (Latin-2)"),
                  build_string ("ISO8859-2 (Latin-2)"),
                  CHARSET_TYPE_96, 1, 1, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-2"),
                  build_string ("ISO8859-2 (Latin-2)"),
                  build_string ("ISO8859-2 (Latin-2)"),
-                 build_string ("iso8859-2"));
+                 build_string ("iso8859-2"),
+                 Qnil, 0, 0, 0, 32);
   Vcharset_latin_iso8859_3 =
   Vcharset_latin_iso8859_3 =
-    make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3, 2,
+    make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3,
                  CHARSET_TYPE_96, 1, 1, 'C',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-3"),
                  build_string ("ISO8859-3 (Latin-3)"),
                  build_string ("ISO8859-3 (Latin-3)"),
                  CHARSET_TYPE_96, 1, 1, 'C',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-3"),
                  build_string ("ISO8859-3 (Latin-3)"),
                  build_string ("ISO8859-3 (Latin-3)"),
-                 build_string ("iso8859-3"));
+                 build_string ("iso8859-3"),
+                 Qnil, 0, 0, 0, 32);
   Vcharset_latin_iso8859_4 =
   Vcharset_latin_iso8859_4 =
-    make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4, 2,
+    make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4,
                  CHARSET_TYPE_96, 1, 1, 'D',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-4"),
                  build_string ("ISO8859-4 (Latin-4)"),
                  build_string ("ISO8859-4 (Latin-4)"),
                  CHARSET_TYPE_96, 1, 1, 'D',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-4"),
                  build_string ("ISO8859-4 (Latin-4)"),
                  build_string ("ISO8859-4 (Latin-4)"),
-                 build_string ("iso8859-4"));
+                 build_string ("iso8859-4"),
+                 Qnil, 0, 0, 0, 32);
   Vcharset_thai_tis620 =
   Vcharset_thai_tis620 =
-    make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620, 2,
+    make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620,
                  CHARSET_TYPE_96, 1, 1, 'T',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("TIS620"),
                  build_string ("TIS620 (Thai)"),
                  build_string ("TIS620.2529 (Thai)"),
                  CHARSET_TYPE_96, 1, 1, 'T',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("TIS620"),
                  build_string ("TIS620 (Thai)"),
                  build_string ("TIS620.2529 (Thai)"),
-                 build_string ("tis620"));
+                 build_string ("tis620"),
+                 Qnil, MIN_CHAR_THAI, MAX_CHAR_THAI, 0, 32);
   Vcharset_greek_iso8859_7 =
   Vcharset_greek_iso8859_7 =
-    make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7, 2,
+    make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7,
                  CHARSET_TYPE_96, 1, 1, 'F',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ISO8859-7"),
                  build_string ("ISO8859-7 (Greek)"),
                  build_string ("ISO8859-7 (Greek)"),
                  CHARSET_TYPE_96, 1, 1, 'F',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ISO8859-7"),
                  build_string ("ISO8859-7 (Greek)"),
                  build_string ("ISO8859-7 (Greek)"),
-                 build_string ("iso8859-7"));
+                 build_string ("iso8859-7"),
+                 Qnil, MIN_CHAR_GREEK, MAX_CHAR_GREEK, 0, 32);
   Vcharset_arabic_iso8859_6 =
   Vcharset_arabic_iso8859_6 =
-    make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6, 2,
+    make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6,
                  CHARSET_TYPE_96, 1, 1, 'G',
                  CHARSET_RIGHT_TO_LEFT,
                  build_string ("ISO8859-6"),
                  build_string ("ISO8859-6 (Arabic)"),
                  build_string ("ISO8859-6 (Arabic)"),
                  CHARSET_TYPE_96, 1, 1, 'G',
                  CHARSET_RIGHT_TO_LEFT,
                  build_string ("ISO8859-6"),
                  build_string ("ISO8859-6 (Arabic)"),
                  build_string ("ISO8859-6 (Arabic)"),
-                 build_string ("iso8859-6"));
+                 build_string ("iso8859-6"),
+                 Qnil, 0, 0, 0, 32);
   Vcharset_hebrew_iso8859_8 =
   Vcharset_hebrew_iso8859_8 =
-    make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8, 2,
+    make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8,
                  CHARSET_TYPE_96, 1, 1, 'H',
                  CHARSET_RIGHT_TO_LEFT,
                  build_string ("ISO8859-8"),
                  build_string ("ISO8859-8 (Hebrew)"),
                  build_string ("ISO8859-8 (Hebrew)"),
                  CHARSET_TYPE_96, 1, 1, 'H',
                  CHARSET_RIGHT_TO_LEFT,
                  build_string ("ISO8859-8"),
                  build_string ("ISO8859-8 (Hebrew)"),
                  build_string ("ISO8859-8 (Hebrew)"),
-                 build_string ("iso8859-8"));
+                 build_string ("iso8859-8"),
+                 Qnil, MIN_CHAR_HEBREW, MAX_CHAR_HEBREW, 0, 32);
   Vcharset_katakana_jisx0201 =
   Vcharset_katakana_jisx0201 =
-    make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201, 2,
+    make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201,
                  CHARSET_TYPE_94, 1, 1, 'I',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0201 Kana"),
                  build_string ("JISX0201.1976 (Japanese Kana)"),
                  build_string ("JISX0201.1976 Japanese Kana"),
                  CHARSET_TYPE_94, 1, 1, 'I',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0201 Kana"),
                  build_string ("JISX0201.1976 (Japanese Kana)"),
                  build_string ("JISX0201.1976 Japanese Kana"),
-                 build_string ("jisx0201.1976"));
+                 build_string ("jisx0201\\.1976"),
+                 Qnil,
+                 MIN_CHAR_HALFWIDTH_KATAKANA,
+                 MAX_CHAR_HALFWIDTH_KATAKANA, 0, 33);
   Vcharset_latin_jisx0201 =
   Vcharset_latin_jisx0201 =
-    make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201, 2,
+    make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201,
                  CHARSET_TYPE_94, 1, 0, 'J',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0201 Roman"),
                  build_string ("JISX0201.1976 (Japanese Roman)"),
                  build_string ("JISX0201.1976 Japanese Roman"),
                  CHARSET_TYPE_94, 1, 0, 'J',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0201 Roman"),
                  build_string ("JISX0201.1976 (Japanese Roman)"),
                  build_string ("JISX0201.1976 Japanese Roman"),
-                 build_string ("jisx0201.1976"));
+                 build_string ("jisx0201\\.1976"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_cyrillic_iso8859_5 =
   Vcharset_cyrillic_iso8859_5 =
-    make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5, 2,
+    make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5,
                  CHARSET_TYPE_96, 1, 1, 'L',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ISO8859-5"),
                  build_string ("ISO8859-5 (Cyrillic)"),
                  build_string ("ISO8859-5 (Cyrillic)"),
                  CHARSET_TYPE_96, 1, 1, 'L',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("ISO8859-5"),
                  build_string ("ISO8859-5 (Cyrillic)"),
                  build_string ("ISO8859-5 (Cyrillic)"),
-                 build_string ("iso8859-5"));
+                 build_string ("iso8859-5"),
+                 Qnil, MIN_CHAR_CYRILLIC, MAX_CHAR_CYRILLIC, 0, 32);
   Vcharset_latin_iso8859_9 =
   Vcharset_latin_iso8859_9 =
-    make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9, 2,
+    make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9,
                  CHARSET_TYPE_96, 1, 1, 'M',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-5"),
                  build_string ("ISO8859-9 (Latin-5)"),
                  build_string ("ISO8859-9 (Latin-5)"),
                  CHARSET_TYPE_96, 1, 1, 'M',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Latin-5"),
                  build_string ("ISO8859-9 (Latin-5)"),
                  build_string ("ISO8859-9 (Latin-5)"),
-                 build_string ("iso8859-9"));
+                 build_string ("iso8859-9"),
+                 Qnil, 0, 0, 0, 32);
   Vcharset_japanese_jisx0208_1978 =
   Vcharset_japanese_jisx0208_1978 =
-    make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978, Qjapanese_jisx0208_1978, 3,
+    make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978, Qjapanese_jisx0208_1978,
                  CHARSET_TYPE_94X94, 2, 0, '@',
                  CHARSET_LEFT_TO_RIGHT,
                  CHARSET_TYPE_94X94, 2, 0, '@',
                  CHARSET_LEFT_TO_RIGHT,
-                 build_string ("JISX0208.1978"),
-                 build_string ("JISX0208.1978 (Japanese)"),
+                 build_string ("JIS X0208:1978"),
+                 build_string ("JIS X0208:1978 (Japanese)"),
                  build_string
                  build_string
-                 ("JISX0208.1978 Japanese Kanji (so called \"old JIS\")"),
-                 build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"));
+                 ("JIS X0208:1978 Japanese Kanji (so called \"old JIS\")"),
+                 build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_chinese_gb2312 =
   Vcharset_chinese_gb2312 =
-    make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312, 3,
+    make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312,
                  CHARSET_TYPE_94X94, 2, 0, 'A',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("GB2312"),
                  build_string ("GB2312)"),
                  build_string ("GB2312 Chinese simplified"),
                  CHARSET_TYPE_94X94, 2, 0, 'A',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("GB2312"),
                  build_string ("GB2312)"),
                  build_string ("GB2312 Chinese simplified"),
-                 build_string ("gb2312"));
+                 build_string ("gb2312"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_japanese_jisx0208 =
   Vcharset_japanese_jisx0208 =
-    make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208, 3,
+    make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208,
                  CHARSET_TYPE_94X94, 2, 0, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0208"),
                  CHARSET_TYPE_94X94, 2, 0, 'B',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0208"),
-                 build_string ("JISX0208.1983/1990 (Japanese)"),
-                 build_string ("JISX0208.1983/1990 Japanese Kanji"),
-                 build_string ("jisx0208.19\\(83\\|90\\)"));
+                 build_string ("JIS X0208:1983 (Japanese)"),
+                 build_string ("JIS X0208:1983 Japanese Kanji"),
+                 build_string ("jisx0208\\.1983"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_korean_ksc5601 =
   Vcharset_korean_ksc5601 =
-    make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601, 3,
+    make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601,
                  CHARSET_TYPE_94X94, 2, 0, 'C',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("KSC5601"),
                  build_string ("KSC5601 (Korean"),
                  build_string ("KSC5601 Korean Hangul and Hanja"),
                  CHARSET_TYPE_94X94, 2, 0, 'C',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("KSC5601"),
                  build_string ("KSC5601 (Korean"),
                  build_string ("KSC5601 Korean Hangul and Hanja"),
-                 build_string ("ksc5601"));
+                 build_string ("ksc5601"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_japanese_jisx0212 =
   Vcharset_japanese_jisx0212 =
-    make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212, 3,
+    make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212,
                  CHARSET_TYPE_94X94, 2, 0, 'D',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0212"),
                  build_string ("JISX0212 (Japanese)"),
                  build_string ("JISX0212 Japanese Supplement"),
                  CHARSET_TYPE_94X94, 2, 0, 'D',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("JISX0212"),
                  build_string ("JISX0212 (Japanese)"),
                  build_string ("JISX0212 Japanese Supplement"),
-                 build_string ("jisx0212"));
+                 build_string ("jisx0212"),
+                 Qnil, 0, 0, 0, 33);
 
 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
   Vcharset_chinese_cns11643_1 =
 
 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
   Vcharset_chinese_cns11643_1 =
-    make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1, 3,
+    make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1,
                  CHARSET_TYPE_94X94, 2, 0, 'G',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("CNS11643-1"),
                  build_string ("CNS11643-1 (Chinese traditional)"),
                  build_string
                  ("CNS 11643 Plane 1 Chinese traditional"),
                  CHARSET_TYPE_94X94, 2, 0, 'G',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("CNS11643-1"),
                  build_string ("CNS11643-1 (Chinese traditional)"),
                  build_string
                  ("CNS 11643 Plane 1 Chinese traditional"),
-                 build_string (CHINESE_CNS_PLANE_RE("1")));
+                 build_string (CHINESE_CNS_PLANE_RE("1")),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_chinese_cns11643_2 =
   Vcharset_chinese_cns11643_2 =
-    make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2, 3,
+    make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2,
                  CHARSET_TYPE_94X94, 2, 0, 'H',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("CNS11643-2"),
                  build_string ("CNS11643-2 (Chinese traditional)"),
                  build_string
                  ("CNS 11643 Plane 2 Chinese traditional"),
                  CHARSET_TYPE_94X94, 2, 0, 'H',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("CNS11643-2"),
                  build_string ("CNS11643-2 (Chinese traditional)"),
                  build_string
                  ("CNS 11643 Plane 2 Chinese traditional"),
-                 build_string (CHINESE_CNS_PLANE_RE("2")));
+                 build_string (CHINESE_CNS_PLANE_RE("2")),
+                 Qnil, 0, 0, 0, 33);
+#ifdef UTF2000
+  Vcharset_latin_viscii_lower =
+    make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower,
+                 CHARSET_TYPE_96, 1, 1, '1',
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("VISCII lower"),
+                 build_string ("VISCII lower (Vietnamese)"),
+                 build_string ("VISCII lower (Vietnamese)"),
+                 build_string ("MULEVISCII-LOWER"),
+                 Qnil, 0, 0, 0, 32);
+  Vcharset_latin_viscii_upper =
+    make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper,
+                 CHARSET_TYPE_96, 1, 1, '2',
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("VISCII upper"),
+                 build_string ("VISCII upper (Vietnamese)"),
+                 build_string ("VISCII upper (Vietnamese)"),
+                 build_string ("MULEVISCII-UPPER"),
+                 Qnil, 0, 0, 0, 32);
+  Vcharset_latin_viscii =
+    make_charset (LEADING_BYTE_LATIN_VISCII, Qlatin_viscii,
+                 CHARSET_TYPE_256, 1, 2, 0,
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("VISCII"),
+                 build_string ("VISCII 1.1 (Vietnamese)"),
+                 build_string ("VISCII 1.1 (Vietnamese)"),
+                 build_string ("VISCII1\\.1"),
+                 Qnil, 0, 0, 0, 0);
+  Vcharset_ideograph_daikanwa =
+    make_charset (LEADING_BYTE_DAIKANWA, Qideograph_daikanwa,
+                 CHARSET_TYPE_256X256, 2, 2, 0,
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("Daikanwa"),
+                 build_string ("Morohashi's Daikanwa"),
+                 build_string ("Daikanwa dictionary by MOROHASHI Tetsuji"),
+                 build_string ("Daikanwa"),
+                 Qnil, MIN_CHAR_DAIKANWA, MAX_CHAR_DAIKANWA, 0, 0);
+  Vcharset_ethiopic_ucs =
+    make_charset (LEADING_BYTE_ETHIOPIC_UCS, Qethiopic_ucs,
+                 CHARSET_TYPE_256X256, 2, 2, 0,
+                 CHARSET_LEFT_TO_RIGHT,
+                 build_string ("Ethiopic (UCS)"),
+                 build_string ("Ethiopic (UCS)"),
+                 build_string ("Ethiopic of UCS"),
+                 build_string ("Ethiopic-Unicode"),
+                 Qnil, 0x1200, 0x137F, 0x1200, 0);
+#endif
   Vcharset_chinese_big5_1 =
   Vcharset_chinese_big5_1 =
-    make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1, 3,
+    make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1,
                  CHARSET_TYPE_94X94, 2, 0, '0',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Big5"),
                  build_string ("Big5 (Level-1)"),
                  build_string
                  ("Big5 Level-1 Chinese traditional"),
                  CHARSET_TYPE_94X94, 2, 0, '0',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Big5"),
                  build_string ("Big5 (Level-1)"),
                  build_string
                  ("Big5 Level-1 Chinese traditional"),
-                 build_string ("big5"));
+                 build_string ("big5"),
+                 Qnil, 0, 0, 0, 33);
   Vcharset_chinese_big5_2 =
   Vcharset_chinese_big5_2 =
-    make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2, 3,
+    make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2,
                  CHARSET_TYPE_94X94, 2, 0, '1',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Big5"),
                  build_string ("Big5 (Level-2)"),
                  build_string
                  ("Big5 Level-2 Chinese traditional"),
                  CHARSET_TYPE_94X94, 2, 0, '1',
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Big5"),
                  build_string ("Big5 (Level-2)"),
                  build_string
                  ("Big5 Level-2 Chinese traditional"),
-                 build_string ("big5"));
-
+                 build_string ("big5"),
+                 Qnil, 0, 0, 0, 33);
 
 #ifdef ENABLE_COMPOSITE_CHARS
   /* #### For simplicity, we put composite chars into a 96x96 charset.
      This is going to lead to problems because you can run out of
      room, esp. as we don't yet recycle numbers. */
   Vcharset_composite =
 
 #ifdef ENABLE_COMPOSITE_CHARS
   /* #### For simplicity, we put composite chars into a 96x96 charset.
      This is going to lead to problems because you can run out of
      room, esp. as we don't yet recycle numbers. */
   Vcharset_composite =
-    make_charset (LEADING_BYTE_COMPOSITE, Qcomposite, 3,
+    make_charset (LEADING_BYTE_COMPOSITE, Qcomposite,
                  CHARSET_TYPE_96X96, 2, 0, 0,
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Composite"),
                  CHARSET_TYPE_96X96, 2, 0, 0,
                  CHARSET_LEFT_TO_RIGHT,
                  build_string ("Composite"),