changeset 88746:388c82972bb9

(sub_char_table_ref_and_range): New arg defalt. Fix the previous change. (char_table_ref_and_range): Adjusted for the above change. (map_sub_char_table_for_charset): New function. (map_char_table_for_charset): New function.
author Kenichi Handa <handa@m17n.org>
date Wed, 12 Jun 2002 00:14:15 +0000
parents f247f70ed2c3
children f35665df510f
files src/chartab.c
diffstat 1 files changed, 212 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/src/chartab.c	Wed Jun 12 00:13:57 2002 +0000
+++ b/src/chartab.c	Wed Jun 12 00:14:15 2002 +0000
@@ -219,35 +219,77 @@
 }  
 
 static Lisp_Object
-sub_char_table_ref_and_range (table, c, from, to)
+sub_char_table_ref_and_range (table, c, from, to, defalt)
      Lisp_Object table;
      int c;
      int *from, *to;
+     Lisp_Object defalt;
 {
   struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
   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);
   Lisp_Object val;
   
-  val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
-  if (depth == 3)
-    {
-      *from = *to = c;
-    }
-  else if (SUB_CHAR_TABLE_P (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])
     {
-      val = sub_char_table_ref_and_range (val, c, from, to);
+      Lisp_Object this_val;
+      int this_from = *from - chartab_chars[depth];
+      int this_to = *from - 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_to,
+						 &this_from, &this_to,
+						 defalt);
+      else if (NILP (this_val))
+	this_val = defalt;
+
+      if (! EQ (this_val, val))
+	break;
+      *from = this_from;
     }
-  else
+  index = CHARTAB_IDX (c, depth, min_char);
+  while (*to < max_char
+	 && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
     {
-      *from = (CHARTAB_IDX (c, depth, min_char) * chartab_chars[depth]
-	       + min_char);
-      *to = *from + chartab_chars[depth] - 1;
+      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);
+      else if (NILP (this_val))
+	this_val = defalt;
+      if (! EQ (this_val, val))
+	break;
+      *to = this_to;
     }
+
   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.  */
+
 Lisp_Object
 char_table_ref_and_range (table, c, from, to)
      Lisp_Object table;
@@ -255,44 +297,57 @@
      int *from, *to;
 {
   struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
+  int index = CHARTAB_IDX (c, 0, 0);
   Lisp_Object val;
 
-  if (ASCII_CHAR_P (c))
+  val = tbl->contents[index];
+  *from = index * chartab_chars[0];
+  *to = *from + chartab_chars[0] - 1;
+  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])
     {
-      val = tbl->ascii;
-      if (SUB_CHAR_TABLE_P (val))
-	{
-	  val = XSUB_CHAR_TABLE (val)->contents[c];
-	  *from = *to = c;
-	}
-      else
-	{
-	  *from = 0, *to = 127;
-	}
+      Lisp_Object this_val;
+      int this_from = *from - chartab_chars[0];
+      int this_to = *from - 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_to,
+						 &this_from, &this_to,
+						 tbl->defalt);
+      else if (NILP (this_val))
+	this_val = tbl->defalt;
+
+      if (! EQ (this_val, val))
+	break;
+      *from = this_from;
     }
-  else
+  while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
     {
-      val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
-      if (SUB_CHAR_TABLE_P (val))
-	{
-	  val = sub_char_table_ref_and_range (val, c, from, to);
-	}
-      else
-	{
-	  *from = CHARTAB_IDX (c, 0, 0) * chartab_chars[0];
-	  *to = *from + chartab_chars[0] - 1;
-	}
+      Lisp_Object this_val;
+      int this_from = *to + 1;
+      int this_to = this_from + chartab_chars[0] - 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,
+						 tbl->defalt);
+      else if (NILP (this_val))
+	this_val = tbl->defalt;
+      if (! EQ (this_val, val))
+	break;
+      *to = this_to;
     }
 
-  if (NILP (val))
-    {
-      val = tbl->defalt;
-      *from = 0, *to = MAX_CHAR;
-      if (NILP (val) && CHAR_TABLE_P (tbl->parent))
-	val = char_table_ref_and_range (tbl->parent, c, from, to);
-    }
   return val;
-}  
+}
 
 
 #define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL)				\
@@ -755,6 +810,121 @@
   return Qnil;
 }
 
+
+static void
+map_sub_char_table_for_charset (c_function, function, table, arg, range,
+				charset, from, to)
+     void (*c_function) P_ ((Lisp_Object, Lisp_Object));
+     Lisp_Object function, table, arg, range;
+     struct charset *charset;
+     unsigned from, to;
+{
+  struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
+  int depth = XINT (tbl->depth);
+  int c, i;
+
+  if (depth < 3)
+    for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
+	 i++, c += chartab_chars[depth])
+      {
+	Lisp_Object this;
+
+	this = tbl->contents[i];
+	if (SUB_CHAR_TABLE_P (this))
+	  map_sub_char_table_for_charset (c_function, function, this, arg,
+					  range, charset, from, to);
+	else
+	  {
+	    if (! NILP (XCAR (range)))
+	      {
+		XSETCDR (range, make_number (c - 1));
+		if (c_function)
+		  (*c_function) (arg, range);
+		else
+		  call2 (function, range, arg);
+	      }
+	    XSETCAR (range, Qnil);
+	  }
+      }
+  else
+    for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
+      {
+	Lisp_Object this;
+	unsigned code;
+
+	this = tbl->contents[i];
+	if (NILP (this)
+	    || (charset
+		&& (code = ENCODE_CHAR (charset, c),
+		    (code < from || code > to))))
+	  {
+	    if (! NILP (XCAR (range)))
+	      {
+		XSETCDR (range, make_number (c - 1));
+		if (c_function)
+		  (*c_function) (range, arg);
+		else
+		  call2 (function, range, arg);
+		XSETCAR (range, Qnil);
+	      }
+	  }
+	else
+	  {
+	    if (NILP (XCAR (range)))
+	      XSETCAR (range, make_number (c));
+	  }
+      }
+}
+
+
+void
+map_char_table_for_charset (c_function, function, table, arg,
+			    charset, from, to)
+     void (*c_function) P_ ((Lisp_Object, Lisp_Object));
+     Lisp_Object function, table, arg;
+     struct charset *charset;
+     unsigned from, to;
+{
+  Lisp_Object range;
+  int c, i;
+
+  if (NILP (char_table_ref (table, 0)))
+    range = Fcons (Qnil, Qnil);
+  else
+    range = Fcons (make_number (0), make_number (0));
+
+  for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
+    {
+      Lisp_Object this;
+
+      this = XCHAR_TABLE (table)->contents[i];
+      if (SUB_CHAR_TABLE_P (this))
+	map_sub_char_table_for_charset (c_function, function, this, arg,
+					range, charset, from, to);
+      else
+	{
+	  if (! NILP (XCAR (range)))
+	    {
+	      XSETCDR (range, make_number (c - 1));
+	      if (c_function)
+		(*c_function) (arg, range);
+	      else
+		call2 (function, range, arg);
+	    }
+	  XSETCAR (range, Qnil);
+	}
+    }
+  if (! NILP (XCAR (range)))
+    {
+      XSETCDR (range, make_number (c - 1));
+      if (c_function)
+	(*c_function) (arg, range);
+      else
+	call2 (function, range, arg);
+    }
+}
+
+
 
 #if 0
 Lisp_Object