Sync up with XEmacs 21.4.17.
[chise/xemacs-chise.git.1] / src / chartab.c
index bf1c526..6eb6b32 100644 (file)
@@ -76,7 +76,6 @@ EXFUN (Fchar_refs_simplify_char_specs, 1);
 extern Lisp_Object Qideographic_structure;
 
 Lisp_Object Vnext_defined_char_id;
-EXFUN (Fdefine_char, 1);
 
 EXFUN (Fmap_char_attribute, 3);
 
@@ -1130,14 +1129,16 @@ make_char_id_table (Lisp_Object initval)
 }
 
 
-#if defined(HAVE_CHISE) && !defined(HAVE_LIBCHISE_LIBCHISE)
-Lisp_Object Qsystem_char_id;
-#endif
-
 Lisp_Object Qcomposition;
 Lisp_Object Q_decomposition;
-Lisp_Object Q_unified;
-Lisp_Object Q_unified_from;
+Lisp_Object Q_identical;
+Lisp_Object Q_identical_from;
+Lisp_Object Q_denotational;
+Lisp_Object Q_denotational_from;
+Lisp_Object Q_subsumptive;
+Lisp_Object Q_subsumptive_from;
+Lisp_Object Q_component;
+Lisp_Object Q_component_of;
 Lisp_Object Qto_ucs;
 Lisp_Object Q_ucs_unified;
 Lisp_Object Qcompat;
@@ -1223,7 +1224,8 @@ Return character corresponding with list.
       modifier = Fcar (rest);
       rest = Fcdr (rest);
       base = Fcdr (Fassq (modifier,
-                         Fget_char_attribute (base, Qcomposition, Qnil)));
+                         Fchar_feature (base, Qcomposition, Qnil,
+                                        Qnil, Qnil)));
     }
   return base;
 }
@@ -1233,14 +1235,16 @@ Return variants of CHARACTER.
 */
        (character))
 {
-  Lisp_Object ret;
-
   CHECK_CHAR (character);
-  ret = Fget_char_attribute (character, Q_ucs_unified, Qnil);
-  if (CONSP (ret))
-    return Fcopy_list (ret);
-  else
-    return Qnil;
+  return
+    nconc2
+    (Fcopy_list (Fget_char_attribute (character, Q_subsumptive, Qnil)),
+     (nconc2
+      (Fcopy_list (Fget_char_attribute (character, Q_denotational, Qnil)),
+       (nconc2
+       (Fcopy_list (Fget_char_attribute (character, Q_identical, Qnil)),
+        Fcopy_list (Fchar_feature (character, Q_ucs_unified, Qnil,
+                                   Qnil, Qnil)))))));
 }
 
 #endif
@@ -1388,7 +1392,7 @@ char_table_type_to_symbol (enum char_table_type type)
 {
   switch (type)
   {
-  default: abort();
+  default: ABORT();
   case CHAR_TABLE_TYPE_GENERIC:  return Qgeneric;
   case CHAR_TABLE_TYPE_SYNTAX:   return Qsyntax;
   case CHAR_TABLE_TYPE_DISPLAY:  return Qdisplay;
@@ -1846,7 +1850,7 @@ Reset CHAR-TABLE to its default state.
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 
   return Qnil;
@@ -2029,7 +2033,7 @@ XCHARSET_CELL_RANGE (Lisp_Object ccs)
       return (0 << 8) | 255;
 #endif
     default:
-      abort ();
+      ABORT ();
       return 0;
     }
 }
@@ -2091,7 +2095,7 @@ decode_char_table_range (Lisp_Object range, struct chartab_range *outrange)
        }
 #endif
       else
-       abort ();
+       ABORT ();
     }
   else
     {
@@ -2154,9 +2158,11 @@ get_char_table (Emchar ch, Lisp_Char_Table *ct)
     if (NILP (ret))
       {
        if (EQ (CHAR_TABLE_NAME (ct), Qdowncase))
-         ret = Fget_char_attribute (make_char (ch), Q_lowercase, Qnil);
+         ret = Fchar_feature (make_char (ch), Q_lowercase, Qnil,
+                              Qnil, Qnil);
        else if (EQ (CHAR_TABLE_NAME (ct), Qflippedcase))
-         ret = Fget_char_attribute (make_char (ch), Q_uppercase, Qnil);
+         ret = Fchar_feature (make_char (ch), Q_uppercase, Qnil,
+                              Qnil, Qnil);
        if (CONSP (ret))
          {
            ret = XCAR (ret);
@@ -2323,7 +2329,7 @@ If there is more than one value, return MULTI (defaults to nil).
 #endif /* not MULE */
 
     default:
-      abort ();
+      ABORT ();
     }
 
   return Qnil; /* not reached */
@@ -2373,7 +2379,7 @@ check_valid_char_table_value (Lisp_Object value, enum char_table_type type,
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 
   return 0; /* not reached */
@@ -2449,7 +2455,6 @@ put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
   switch (range->type)
     {
     case CHARTAB_RANGE_ALL:
-      /* printf ("put-char-table: range = all\n"); */
       fill_char_table (ct, val);
       return; /* avoid the duplicate call to update_syntax_table() below,
                 since fill_char_table() also did that. */
@@ -2466,9 +2471,6 @@ put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
       {
        Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (range->charset);
 
-       /* printf ("put-char-table: range = charset: %d\n",
-          XCHARSET_LEADING_BYTE (range->charset));
-       */
        if ( CHAR_TABLEP (encoding_table) )
          {
            Lisp_Object mother = XCHARSET_MOTHER (range->charset);
@@ -2554,7 +2556,6 @@ put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
 
     case CHARTAB_RANGE_CHAR:
 #ifdef UTF2000
-      /* printf ("put-char-table: range = char: 0x%x\n", range->ch); */
       put_char_id_table_0 (ct, range->ch, val);
       break;
 #elif defined(MULE)
@@ -2824,7 +2825,7 @@ map_char_table_for_charset_fun (struct chartab_range *range,
       break;
 
     default:
-      abort ();
+      ABORT ();
     }
 
   return 0;
@@ -3035,7 +3036,7 @@ map_char_table (Lisp_Char_Table *ct,
       }
 
     default:
-      abort ();
+      ABORT ();
     }
 
   return 0;
@@ -3081,7 +3082,7 @@ slow_map_char_table_fun (struct chartab_range *range,
       ranjarg = make_char (range->ch);
       break;
     default:
-      abort ();
+      ABORT ();
     }
 
   closure->retval = call2 (closure->function, ranjarg, val);
@@ -3274,6 +3275,110 @@ Return DEFAULT-VALUE if the value is not exist.
   return default_value;
 }
 
+static Lisp_Object
+find_char_feature_in_family (Lisp_Object character,
+                            Lisp_Object con_feature,
+                            Lisp_Object feature,
+                            Lisp_Object feature_rel_max)
+{
+  Lisp_Object ancestors
+    = Fget_char_attribute (character, con_feature, Qnil);
+
+  while (!NILP (ancestors))
+    {
+      Lisp_Object ancestor = XCAR (ancestors);
+      Lisp_Object ret;
+
+      if (EQ (ancestor, character))
+       return Qunbound;
+
+      ret = Fchar_feature (ancestor, feature, Qunbound,
+                          Qnil, make_int (0));
+      if (!UNBOUNDP (ret))
+       return ret;
+
+      ancestors = XCDR (ancestors);
+
+      ret = Fget_char_attribute (ancestor, Q_subsumptive_from, Qnil);
+      if (!NILP (ret))
+       ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
+
+      ret = Fget_char_attribute (ancestor, Q_denotational_from, Qnil);
+      if (!NILP (ret))
+       ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
+    }
+  return Qunbound;
+}
+
+DEFUN ("char-feature", Fchar_feature, 2, 5, 0, /*
+Return the value of CHARACTER's FEATURE.
+Return DEFAULT-VALUE if the value is not exist.
+*/
+       (character, attribute, default_value,
+       feature_rel_max, char_rel_max))
+{
+  Lisp_Object ret
+    = Fget_char_attribute (character, attribute, Qunbound);
+
+  if (!UNBOUNDP (ret))
+    return ret;
+
+  if (NILP (feature_rel_max)
+      || (INTP (feature_rel_max) &&
+         XINT (feature_rel_max) > 0))
+    {
+      Lisp_String* name = symbol_name (XSYMBOL (attribute));
+      Bufbyte *name_str = string_data (name);
+
+      if (name_str[0] == '=' && name_str[1] == '>')
+       {
+         Bytecount length = string_length (name) - 1;
+         Lisp_Object map_to = make_uninit_string (length);
+
+         memcpy (XSTRING_DATA (map_to) + 1, name_str + 2, length - 1);
+         XSTRING_DATA(map_to)[0] = '=';
+         ret = Fchar_feature (character, Fintern (map_to, Qnil),
+                              Qunbound,
+                              NILP (feature_rel_max)
+                              ? feature_rel_max
+                              : make_int (XINT (feature_rel_max) - 1),
+                              char_rel_max);
+         if (!UNBOUNDP (ret))
+           return ret;
+       }
+    }
+
+  if ( !(EQ (attribute, Q_identical)) &&
+       !(EQ (attribute, Q_subsumptive_from)) &&
+       !(EQ (attribute, Q_denotational_from)) &&
+       ( (NILP (char_rel_max)
+         || (INTP (char_rel_max) &&
+             XINT (char_rel_max) > 0)) ) )
+    {
+      Lisp_String* name = symbol_name (XSYMBOL (attribute));
+      Bufbyte *name_str = string_data (name);
+
+      if ( (name_str[0] != '=') || (name_str[1] == '>') )
+       {
+         ret = find_char_feature_in_family (character, Q_identical,
+                                            attribute, feature_rel_max);
+         if (!UNBOUNDP (ret))
+           return ret;
+
+         ret = find_char_feature_in_family (character, Q_subsumptive_from,
+                                            attribute, feature_rel_max);
+         if (!UNBOUNDP (ret))
+           return ret;
+
+         ret = find_char_feature_in_family (character, Q_denotational_from,
+                                            attribute, feature_rel_max);
+         if (!UNBOUNDP (ret))
+           return ret;
+       }
+    }
+  return default_value;
+}
+
 void put_char_composition (Lisp_Object character, Lisp_Object value);
 void
 put_char_composition (Lisp_Object character, Lisp_Object value)
@@ -3302,7 +3407,8 @@ put_char_composition (Lisp_Object character, Lisp_Object value)
          if (CHARP (base))
            {
              Lisp_Object alist
-               = Fget_char_attribute (base, Qcomposition, Qnil);
+               = Fchar_feature (base, Qcomposition, Qnil,
+                                Qnil, Qnil);
              Lisp_Object ret = Fassq (modifier, alist);
 
              if (NILP (ret))
@@ -3320,9 +3426,10 @@ put_char_composition (Lisp_Object character, Lisp_Object value)
 
       if (INTP (v))
        {
-         Emchar c = XINT (v);
+         Emchar c = DECODE_CHAR (Vcharset_ucs, XINT (v), 0);
          Lisp_Object ret
-           = Fget_char_attribute (make_char (c), Q_ucs_unified, Qnil);
+           = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
+                            Qnil, Qnil);
 
          if (!CONSP (ret))
            {
@@ -3338,6 +3445,26 @@ put_char_composition (Lisp_Object character, Lisp_Object value)
     }
 }
 
+static Lisp_Object
+put_char_attribute (Lisp_Object character, Lisp_Object attribute,
+                   Lisp_Object value)
+{
+  Lisp_Object table = Fgethash (attribute,
+                               Vchar_attribute_hash_table,
+                               Qnil);
+
+  if (NILP (table))
+    {
+      table = make_char_id_table (Qunbound);
+      Fputhash (attribute, table, Vchar_attribute_hash_table);
+#ifdef HAVE_CHISE
+      XCHAR_TABLE_NAME (table) = attribute;
+#endif
+    }
+  put_char_id_table (XCHAR_TABLE(table), character, value);
+  return value;
+}
+
 DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
 Store CHARACTER's ATTRIBUTE with VALUE.
 */
@@ -3362,24 +3489,82 @@ Store CHARACTER's ATTRIBUTE with VALUE.
       if (!INTP (value))
        signal_simple_error ("Invalid value for =>ucs", value);
 
-      c = XINT (value);
+      c = DECODE_CHAR (Vcharset_ucs, XINT (value), 0);
 
-      ret = Fget_char_attribute (make_char (c), Q_ucs_unified, Qnil);
+      ret = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
+                          Qnil, Qnil);
       if (!CONSP (ret))
-       {
-         Fput_char_attribute (make_char (c), Q_ucs_unified,
-                              Fcons (character, Qnil));
-       }
+       put_char_attribute (make_char (c), Q_ucs_unified,
+                           list1 (character));
       else if (NILP (Fmemq (character, ret)))
-       {
-         Fput_char_attribute (make_char (c), Q_ucs_unified,
-                              Fcons (character, ret));
-       }
+       Fput_char_attribute (make_char (c), Q_ucs_unified,
+                            Fcons (character, ret));
     }
-  else if (EQ (attribute, Q_unified))
+  else if ( EQ (attribute, Q_subsumptive) ||
+           EQ (attribute, Q_subsumptive_from) ||
+           EQ (attribute, Q_denotational) ||
+           EQ (attribute, Q_denotational_from) ||
+           EQ (attribute, Q_identical) ||
+           EQ (attribute, Q_identical_from) ||
+           EQ (attribute, Q_component) ||
+           EQ (attribute, Q_component_of) ||
+           !NILP (Fstring_match
+                  (build_string ("^\\(<-\\|->\\)\\("
+                                 "fullwidth\\|halfwidth"
+                                 "\\|simplified\\|vulgar\\|wrong"
+                                 "\\|same\\|original\\|ancient"
+                                 "\\|Oracle-Bones\\)[^*]*$"),
+                   Fsymbol_name (attribute),
+                   Qnil, Qnil)) )
     {
       Lisp_Object rest = value;
       Lisp_Object ret;
+      Lisp_Object rev_feature = Qnil;
+      struct gcpro gcpro1;
+      GCPRO1 (rev_feature);
+
+      if (EQ (attribute, Q_identical))
+       rev_feature = Q_identical_from;
+      else if (EQ (attribute, Q_identical_from))
+       rev_feature = Q_identical;
+      else if (EQ (attribute, Q_subsumptive))
+       rev_feature = Q_subsumptive_from;
+      else if (EQ (attribute, Q_subsumptive_from))
+       rev_feature = Q_subsumptive;
+      else if (EQ (attribute, Q_denotational))
+       rev_feature = Q_denotational_from;
+      else if (EQ (attribute, Q_denotational_from))
+       rev_feature = Q_denotational;
+      else if (EQ (attribute, Q_component))
+       rev_feature = Q_component_of;
+      else if (EQ (attribute, Q_component_of))
+       rev_feature = Q_component;
+      else
+       {
+         Lisp_String* name = symbol_name (XSYMBOL (attribute));
+         Bufbyte *name_str = string_data (name);
+
+         if ( (name_str[0] == '<' && name_str[1] == '-') || 
+              (name_str[0] == '-' && name_str[1] == '>') )
+           {
+             Bytecount length = string_length (name);
+             Bufbyte *rev_name_str = alloca (length + 1);
+
+             memcpy (rev_name_str + 2, name_str + 2, length - 2);
+             if (name_str[0] == '<')
+               {
+                 rev_name_str[0] = '-';
+                 rev_name_str[1] = '>';
+               }
+             else
+               {
+                 rev_name_str[0] = '<';
+                 rev_name_str[1] = '-';
+               }
+             rev_name_str[length] = 0;
+             rev_feature = intern (rev_name_str);
+           }
+       }
 
       while (CONSP (rest))
        {
@@ -3388,34 +3573,28 @@ Store CHARACTER's ATTRIBUTE with VALUE.
          if (CONSP (ret))
            ret = Fdefine_char (ret);
          
-         if (!NILP (ret))
+         if ( !NILP (ret) && !EQ (ret, character) )
            {
-             Fput_char_attribute (ret, Q_unified_from, list1 (character));
+             Lisp_Object ffv;
+
+             ffv = Fget_char_attribute (ret, rev_feature, Qnil);
+             if (!CONSP (ffv))
+               put_char_attribute (ret, rev_feature, list1 (character));
+             else if (NILP (Fmemq (character, ffv)))
+               put_char_attribute
+                 (ret, rev_feature,
+                  nconc2 (Fcopy_sequence (ffv), list1 (character)));
              Fsetcar (rest, ret);
            }
          rest = XCDR (rest);
        }
+      UNGCPRO;
     }
-#if 0
+#if 1
   else if (EQ (attribute, Qideographic_structure))
     value = Fcopy_sequence (Fchar_refs_simplify_char_specs (value));
 #endif
-  {
-    Lisp_Object table = Fgethash (attribute,
-                                 Vchar_attribute_hash_table,
-                                 Qnil);
-
-    if (NILP (table))
-      {
-       table = make_char_id_table (Qunbound);
-       Fputhash (attribute, table, Vchar_attribute_hash_table);
-#ifdef HAVE_CHISE
-       XCHAR_TABLE_NAME (table) = attribute;
-#endif
-      }
-    put_char_id_table (XCHAR_TABLE(table), character, value);
-    return value;
-  }
+  return put_char_attribute (character, attribute, value);
 }
   
 DEFUN ("remove-char-attribute", Fremove_char_attribute, 2, 2, 0, /*
@@ -3457,11 +3636,11 @@ open_chise_data_source_maybe ()
 {
   if (default_chise_data_source == NULL)
     {
-      Lisp_Object db_dir = Vexec_directory;
+      Lisp_Object db_dir = Vdata_directory;
       int modemask = 0755;             /* rwxr-xr-x */
 
       if (NILP (db_dir))
-       db_dir = build_string ("../lib-src");
+       db_dir = build_string ("../etc");
       db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
 
       default_chise_data_source
@@ -3469,6 +3648,10 @@ open_chise_data_source_maybe ()
                         0 /* DB_HASH */, modemask);
       if (default_chise_data_source == NULL)
        return -1;
+#if 0
+      chise_ds_set_make_string_function (default_chise_data_source,
+                                        &make_string);
+#endif
     }
   return 0;
 }
@@ -3544,8 +3727,13 @@ char_table_get_db (Lisp_Char_Table* cit, Emchar ch)
 
   if (!status)
     {
+#if 0
       val = Fread (make_string (chise_value_data (&value),
                                chise_value_size (&value) ));
+#else
+      val = read_from_c_string (chise_value_data (&value),
+                               chise_value_size (&value) );
+#endif
     }
   else
     val = Qunbound;
@@ -3565,10 +3753,10 @@ Lisp_Object
 char_attribute_system_db_file (Lisp_Object key_type, Lisp_Object attribute,
                               int writing_mode)
 {
-  Lisp_Object db_dir = Vexec_directory;
+  Lisp_Object db_dir = Vdata_directory;
 
   if (NILP (db_dir))
-    db_dir = build_string ("../lib-src");
+    db_dir = build_string ("../etc");
 
   db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
   if (writing_mode && NILP (Ffile_exists_p (db_dir)))
@@ -3651,7 +3839,18 @@ Save values of ATTRIBUTE into database file.
     {
       Lisp_Object (*filter)(Lisp_Object value);
 
-      if (EQ (attribute, Qideographic_structure))
+      if ( !NILP (Ffind_charset (attribute)) )
+       filter = NULL;
+      else if ( EQ (attribute, Qideographic_structure)
+          || EQ (attribute, Q_identical)
+          || EQ (attribute, Q_identical_from)
+          || !NILP (Fstring_match
+                    (build_string ("^\\(<-\\|->\\)\\(simplified"
+                                   "\\|same\\|vulgar\\|wrong"
+                                   "\\|original\\|ancient"
+                                   "\\|Oracle-Bones\\)[^*]*$"),
+                     Fsymbol_name (attribute),
+                     Qnil, Qnil)) )
        filter = &Fchar_refs_simplify_char_specs;
       else
        filter = NULL;
@@ -3948,33 +4147,46 @@ Store character's ATTRIBUTES.
 */
        (attributes))
 {
-  Lisp_Object rest = attributes;
+  Lisp_Object rest;
   Lisp_Object code = Fcdr (Fassq (Qmap_ucs, attributes));
   Lisp_Object character;
 
   if (NILP (code))
     code = Fcdr (Fassq (Qucs, attributes));
+
   if (NILP (code))
     {
+      rest = attributes;
       while (CONSP (rest))
        {
          Lisp_Object cell = Fcar (rest);
          Lisp_Object ccs;
 
-         if (!LISTP (cell))
+         if ( !LISTP (cell) )
            signal_simple_error ("Invalid argument", attributes);
-         if (!NILP (ccs = Ffind_charset (Fcar (cell)))
-             && ((XCHARSET_FINAL (ccs) != 0) ||
-                 (XCHARSET_MAX_CODE (ccs) > 0) ||
-                 (EQ (ccs, Vcharset_chinese_big5))) )
+
+         ccs = Ffind_charset (Fcar (cell));
+         if (!NILP (ccs))
            {
              cell = Fcdr (cell);
-             if (CONSP (cell))
-               character = Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
-             else
-               character = Fdecode_char (ccs, cell, Qnil, Qt);
-             if (!NILP (character))
-               goto setup_attributes;
+             if (INTP (cell))
+               {
+                 character = Fdecode_char (ccs, cell, Qt, Qt);
+                 if (!NILP (character))
+                   goto setup_attributes;
+               }
+             if ( (XCHARSET_FINAL (ccs) != 0) ||
+                  (XCHARSET_MAX_CODE (ccs) > 0) ||
+                  (EQ (ccs, Vcharset_chinese_big5)) )
+               {
+                 if (CONSP (cell))
+                   character
+                     = Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
+                 else
+                   character = Fdecode_char (ccs, cell, Qnil, Qt);
+                 if (!NILP (character))
+                   goto setup_attributes;
+               }
            }
          rest = Fcdr (rest);
        }
@@ -4144,7 +4356,7 @@ chartab_instantiate (Lisp_Object data)
                 Fput_char_table (make_char (i), val, chartab);
            }
          else
-           abort ();
+           ABORT ();
        }
       else
        Fput_char_table (range, val, chartab);
@@ -4402,14 +4614,16 @@ syms_of_chartab (void)
   INIT_LRECORD_IMPLEMENTATION (uint16_byte_table);
   INIT_LRECORD_IMPLEMENTATION (byte_table);
 
-#if defined(HAVE_CHISE) && !defined(HAVE_LIBCHISE_LIBCHISE)
-  defsymbol (&Qsystem_char_id,         "system-char-id");
-#endif
-
   defsymbol (&Qto_ucs,                 "=>ucs");
   defsymbol (&Q_ucs_unified,           "->ucs-unified");
-  defsymbol (&Q_unified,               "->unified");
-  defsymbol (&Q_unified_from,          "<-unified");
+  defsymbol (&Q_subsumptive,           "->subsumptive");
+  defsymbol (&Q_subsumptive_from,      "<-subsumptive");
+  defsymbol (&Q_denotational,          "->denotational");
+  defsymbol (&Q_denotational_from,     "<-denotational");
+  defsymbol (&Q_identical,             "->identical");
+  defsymbol (&Q_identical_from,                "<-identical");
+  defsymbol (&Q_component,             "->ideographic-component-forms");
+  defsymbol (&Q_component_of,          "<-ideographic-component-forms");
   defsymbol (&Qcomposition,            "composition");
   defsymbol (&Q_decomposition,         "->decomposition");
   defsymbol (&Qcompat,                 "compat");
@@ -4446,6 +4660,7 @@ syms_of_chartab (void)
 #endif
   DEFSUBR (Fload_char_attribute_table);
 #endif
+  DEFSUBR (Fchar_feature);
   DEFSUBR (Fchar_attribute_alist);
   DEFSUBR (Fget_char_attribute);
   DEFSUBR (Fput_char_attribute);