]> code.delx.au - gnu-emacs/blobdiff - src/chartab.c
(x_set_font): When ARG is a font-object, check if the
[gnu-emacs] / src / chartab.c
index 165fa0dd8952d2dc1c402f20457d36461a589b18..89f6379b416c1f9dbcb696f747e3e5b7a46f4ca2 100644 (file)
@@ -1,5 +1,5 @@
 /* chartab.c -- char-table support
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
 
@@ -159,14 +159,12 @@ copy_char_table (table)
   XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
   XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
   XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
-  XCHAR_TABLE (copy)->ascii = XCHAR_TABLE (table)->ascii;
   for (i = 0; i < chartab_size[0]; i++)
     XCHAR_TABLE (copy)->contents[i]
       = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
         ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
         : XCHAR_TABLE (table)->contents[i]);
-  if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy)->ascii))
-    XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
+  XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
   size -= VECSIZE (struct Lisp_Char_Table) - 1;
   for (i = 0; i < size; i++)
     XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
@@ -231,66 +229,60 @@ sub_char_table_ref_and_range (table, c, from, to, defalt)
   int depth = XINT (tbl->depth);
   int min_char = XINT (tbl->min_char);
   int max_char = min_char + chartab_chars[depth - 1] - 1;
-  int index = CHARTAB_IDX (c, depth, min_char);
+  int index = CHARTAB_IDX (c, depth, min_char), idx;
   Lisp_Object val;
 
   val = tbl->contents[index];
-  *from = min_char + index * chartab_chars[depth];
-  *to = *from + chartab_chars[depth] - 1;
   if (SUB_CHAR_TABLE_P (val))
     val = sub_char_table_ref_and_range (val, c, from, to, defalt);
   else if (NILP (val))
     val = defalt;
 
-  while (*from > min_char
-        && *from == min_char + index * chartab_chars[depth])
+  idx = index;
+  while (idx > 0 && *from < min_char + idx * chartab_chars[depth])
     {
       Lisp_Object this_val;
-      int this_from = *from - chartab_chars[depth];
-      int this_to = *from - 1;
 
-      index--;
-      this_val = tbl->contents[index];
+      c = min_char + idx * chartab_chars[depth] - 1;
+      idx--;
+      this_val = tbl->contents[idx];
       if (SUB_CHAR_TABLE_P (this_val))
-       this_val = sub_char_table_ref_and_range (this_val, this_to,
-                                                &this_from, &this_to,
-                                                defalt);
+       this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt);
       else if (NILP (this_val))
        this_val = defalt;
 
       if (! EQ (this_val, val))
-       break;
-      *from = this_from;
+       {
+         *from = c + 1;
+         break;
+       }
     }
-  index = CHARTAB_IDX (c, depth, min_char);
-  while (*to < max_char
-        && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
+  while ((c = min_char + (index + 1) * chartab_chars[depth]) < max_char
+        && *to >= c)
     {
       Lisp_Object this_val;
-      int this_from = *to + 1;
-      int this_to = this_from + chartab_chars[depth] - 1;
 
       index++;
       this_val = tbl->contents[index];
       if (SUB_CHAR_TABLE_P (this_val))
-       this_val = sub_char_table_ref_and_range (this_val, this_from,
-                                                &this_from, &this_to,
-                                                defalt);
+       this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt);
       else if (NILP (this_val))
        this_val = defalt;
       if (! EQ (this_val, val))
-       break;
-      *to = this_to;
+       {
+         *to = c - 1;
+         break;
+       }
     }
 
   return val;
 }
 
 
-/* Return the value for C in char-table TABLE.  Set *FROM and *TO to
-   the range of characters (containing C) that have the same value as
-   C.  It is not assured that the value of (*FROM - 1) and (*TO + 1)
-   is different from that of C.  */
+/* Return the value for C in char-table TABLE.  Shrink the range *FROM
+   and *TO to cover characters (containing C) that have the same value
+   as C.  It is not assured that the values of (*FROM - 1) and (*TO +
+   1) are different from that of C.  */
 
 Lisp_Object
 char_table_ref_and_range (table, c, from, to)
@@ -299,53 +291,56 @@ char_table_ref_and_range (table, c, from, to)
      int *from, *to;
 {
   struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
-  int index = CHARTAB_IDX (c, 0, 0);
+  int index = CHARTAB_IDX (c, 0, 0), idx;
   Lisp_Object val;
 
   val = tbl->contents[index];
-  *from = index * chartab_chars[0];
-  *to = *from + chartab_chars[0] - 1;
+  if (*from < 0)
+    *from = 0;
+  if (*to < 0)
+    *to = MAX_CHAR;
   if (SUB_CHAR_TABLE_P (val))
     val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
   else if (NILP (val))
     val = tbl->defalt;
 
-  while (*from > 0 && *from == index * chartab_chars[0])
+  idx = index;
+  while (*from < idx * chartab_chars[0])
     {
       Lisp_Object this_val;
-      int this_from = *from - chartab_chars[0];
-      int this_to = *from - 1;
 
-      index--;
-      this_val = tbl->contents[index];
+      c = idx * chartab_chars[0] - 1;
+      idx--;
+      this_val = tbl->contents[idx];
       if (SUB_CHAR_TABLE_P (this_val))
-       this_val = sub_char_table_ref_and_range (this_val, this_to,
-                                                &this_from, &this_to,
+       this_val = sub_char_table_ref_and_range (this_val, c, from, to,
                                                 tbl->defalt);
       else if (NILP (this_val))
        this_val = tbl->defalt;
 
       if (! EQ (this_val, val))
-       break;
-      *from = this_from;
+       {
+         *from = c + 1;
+         break;
+       }
     }
-  while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
+  while (*to >= (index + 1) * chartab_chars[0])
     {
       Lisp_Object this_val;
-      int this_from = *to + 1;
-      int this_to = this_from + chartab_chars[0] - 1;
 
       index++;
+      c = index * chartab_chars[0];
       this_val = tbl->contents[index];
       if (SUB_CHAR_TABLE_P (this_val))
-       this_val = sub_char_table_ref_and_range (this_val, this_from,
-                                                &this_from, &this_to,
+       this_val = sub_char_table_ref_and_range (this_val, c, from, to,
                                                 tbl->defalt);
       else if (NILP (this_val))
        this_val = tbl->defalt;
       if (! EQ (this_val, val))
-       break;
-      *to = this_to;
+       {
+         *to = c - 1;
+         break;
+       }
     }
 
   return val;
@@ -656,38 +651,42 @@ char_table_translate (table, ch)
 }
 
 static Lisp_Object
-optimize_sub_char_table (table)
-     Lisp_Object table;
+optimize_sub_char_table (table, test)
+     Lisp_Object table, test;
 {
   struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
   int depth = XINT (tbl->depth);
   Lisp_Object elt, this;
-  int i;
+  int i, optimizable;
 
   elt = XSUB_CHAR_TABLE (table)->contents[0];
   if (SUB_CHAR_TABLE_P (elt))
-    elt = XSUB_CHAR_TABLE (table)->contents[0] = optimize_sub_char_table (elt);
-  if (SUB_CHAR_TABLE_P (elt))
-    return table;
+    elt = XSUB_CHAR_TABLE (table)->contents[0]
+      = optimize_sub_char_table (elt, test);
+  optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1;
   for (i = 1; i < chartab_size[depth]; i++)
     {
       this = XSUB_CHAR_TABLE (table)->contents[i];
       if (SUB_CHAR_TABLE_P (this))
        this = XSUB_CHAR_TABLE (table)->contents[i]
-         = optimize_sub_char_table (this);
-      if (SUB_CHAR_TABLE_P (this)
-         || NILP (Fequal (this, elt)))
-       break;
+         = optimize_sub_char_table (this, test);
+      if (optimizable
+         && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
+             : EQ (test, Qeq) ? !EQ (this, elt)      /* Optimize `eq' case.  */
+             : NILP (call2 (test, this, elt))))
+       optimizable = 0;
     }
 
-  return (i < chartab_size[depth] ? table : elt);
+  return (optimizable ? elt : table);
 }
 
 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
-       1, 1, 0,
-       doc: /* Optimize CHAR-TABLE.  */)
-     (char_table)
-     Lisp_Object char_table;
+       1, 2, 0,
+       doc: /* Optimize CHAR-TABLE.
+TEST is the comparison function used to decide whether two entries are
+equivalent and can be merged.  It defaults to `equal'.  */)
+     (char_table, test)
+     Lisp_Object char_table, test;
 {
   Lisp_Object elt;
   int i;
@@ -698,8 +697,12 @@ DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
     {
       elt = XCHAR_TABLE (char_table)->contents[i];
       if (SUB_CHAR_TABLE_P (elt))
-       XCHAR_TABLE (char_table)->contents[i] = optimize_sub_char_table (elt);
+       XCHAR_TABLE (char_table)->contents[i]
+         = optimize_sub_char_table (elt, test);
     }
+  /* Reset the `ascii' cache, in case it got optimized away.  */
+  XCHAR_TABLE (char_table)->ascii = char_table_ascii (char_table);
+
   return Qnil;
 }
 
@@ -777,7 +780,7 @@ map_sub_char_table (c_function, function, table, arg, val, range,
        {
          if (NILP (this))
            this = default_val;
-         if (NILP (Fequal (val, this)))
+         if (!EQ (val, this))
            {
              int different_value = 1;
 
@@ -797,7 +800,7 @@ map_sub_char_table (c_function, function, table, arg, val, range,
                                                parent, arg, val, range,
                                                XCHAR_TABLE (parent)->defalt,
                                                XCHAR_TABLE (parent)->parent);
-                     if (! NILP (Fequal (val, this)))
+                     if (EQ (val, this))
                        different_value = 0;
                    }
                }
@@ -841,7 +844,6 @@ map_char_table (c_function, function, table, arg)
      Lisp_Object function, table, arg;
 {
   Lisp_Object range, val;
-  int c, i;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
   range = Fcons (make_number (0), make_number (MAX_CHAR));
@@ -975,6 +977,27 @@ map_sub_char_table_for_charset (c_function, function, table, arg, range,
 }
 
 
+/* Support function for `map-charset-chars'.  Map C_FUNCTION or
+   FUNCTION over TABLE, calling it for each character or a group of
+   succeeding characters that have non-nil value in TABLE.  TABLE is a
+   "mapping table" or a "deunifier table" of a certain charset.
+
+   If CHARSET is not NULL (this is the case that `map-charset-chars'
+   is called with non-nil FROM-CODE and TO-CODE), it is a charset who
+   owns TABLE, and the function is called only on a character in the
+   range FROM and TO.  FROM and TO are not character codes, but code
+   points of a character in CHARSET.
+
+   This function is called in these two cases:
+
+   (1) A charset has a mapping file name in :map property.
+
+   (2) A charset has an upper code space in :offset property and a
+   mapping file name in :unify-map property.  In this case, this
+   function is called only for characters in the Unicode code space.
+   Characters in upper code space are handled directly in
+   map_charset_chars.  */
+
 void
 map_char_table_for_charset (c_function, function, table, arg,
                            charset, from, to)