(U-0002195D): Add `ideographic-structure'; add `sound@ja/on'; add
[chise/xemacs-chise.git.1] / src / rangetab.c
index 0edf541..50a8735 100644 (file)
@@ -41,20 +41,20 @@ Lisp_Object Qrange_table;
    is not hard but just requires moving that stuff out of that file. */
 
 static Lisp_Object
-mark_range_table (Lisp_Object obj, void (*markobj) (Lisp_Object))
+mark_range_table (Lisp_Object obj)
 {
-  struct Lisp_Range_Table *rt = XRANGE_TABLE (obj);
+  Lisp_Range_Table *rt = XRANGE_TABLE (obj);
   int i;
 
   for (i = 0; i < Dynarr_length (rt->entries); i++)
-    markobj (Dynarr_at (rt->entries, i).val);
+    mark_object (Dynarr_at (rt->entries, i).val);
   return Qnil;
 }
 
 static void
 print_range_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 {
-  struct Lisp_Range_Table *rt = XRANGE_TABLE (obj);
+  Lisp_Range_Table *rt = XRANGE_TABLE (obj);
   char buf[200];
   int i;
 
@@ -77,8 +77,8 @@ print_range_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
 static int
 range_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
 {
-  struct Lisp_Range_Table *rt1 = XRANGE_TABLE (obj1);
-  struct Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2);
+  Lisp_Range_Table *rt1 = XRANGE_TABLE (obj1);
+  Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2);
   int i;
 
   if (Dynarr_length (rt1->entries) != Dynarr_length (rt2->entries))
@@ -107,7 +107,7 @@ range_table_entry_hash (struct range_table_entry *rte, int depth)
 static unsigned long
 range_table_hash (Lisp_Object obj, int depth)
 {
-  struct Lisp_Range_Table *rt = XRANGE_TABLE (obj);
+  Lisp_Range_Table *rt = XRANGE_TABLE (obj);
   int i;
   int size = Dynarr_length (rt->entries);
   unsigned long hash = size;
@@ -132,10 +132,36 @@ range_table_hash (Lisp_Object obj, int depth)
   return hash;
 }
 
+static const struct lrecord_description rte_description_1[] = {
+  { XD_LISP_OBJECT, offsetof (range_table_entry, val) },
+  { XD_END }
+};
+
+static const struct struct_description rte_description = {
+  sizeof (range_table_entry),
+  rte_description_1
+};
+
+static const struct lrecord_description rted_description_1[] = {
+  XD_DYNARR_DESC (range_table_entry_dynarr, &rte_description),
+  { XD_END }
+};
+
+static const struct struct_description rted_description = {
+  sizeof (range_table_entry_dynarr),
+  rted_description_1
+};
+
+static const struct lrecord_description range_table_description[] = {
+  { XD_STRUCT_PTR,  offsetof (Lisp_Range_Table, entries),  1, &rted_description },
+  { XD_END }
+};
+
 DEFINE_LRECORD_IMPLEMENTATION ("range-table", range_table,
                                mark_range_table, print_range_table, 0,
                               range_table_equal, range_table_hash,
-                              struct Lisp_Range_Table);
+                              range_table_description,
+                              Lisp_Range_Table);
 \f
 /************************************************************************/
 /*                        Range table operations                        */
@@ -144,7 +170,7 @@ DEFINE_LRECORD_IMPLEMENTATION ("range-table", range_table,
 #ifdef ERROR_CHECK_TYPECHECK
 
 static void
-verify_range_table (struct Lisp_Range_Table *rt)
+verify_range_table (Lisp_Range_Table *rt)
 {
   int i;
 
@@ -207,26 +233,27 @@ You can manipulate it using `put-range-table', `get-range-table',
        ())
 {
   Lisp_Object obj;
-  struct Lisp_Range_Table *rt = alloc_lcrecord_type (struct Lisp_Range_Table,
-                                                    lrecord_range_table);
+  Lisp_Range_Table *rt = alloc_lcrecord_type (Lisp_Range_Table,
+                                             &lrecord_range_table);
   rt->entries = Dynarr_new (range_table_entry);
   XSETRANGE_TABLE (obj, rt);
   return obj;
 }
 
 DEFUN ("copy-range-table", Fcopy_range_table, 1, 1, 0, /*
-Make a new range table which contains the same values for the same
-ranges as the given table.  The values will not themselves be copied.
+Return a new range table which is a copy of RANGE-TABLE.
+It will contain the same values for the same ranges as RANGE-TABLE.
+The values will not themselves be copied.
 */
-       (old_table))
+       (range_table))
 {
-  struct Lisp_Range_Table *rt, *rtnew;
+  Lisp_Range_Table *rt, *rtnew;
   Lisp_Object obj;
 
-  CHECK_RANGE_TABLE (old_table);
-  rt = XRANGE_TABLE (old_table);
+  CHECK_RANGE_TABLE (range_table);
+  rt = XRANGE_TABLE (range_table);
 
-  rtnew = alloc_lcrecord_type (struct Lisp_Range_Table, lrecord_range_table);
+  rtnew = alloc_lcrecord_type (Lisp_Range_Table, &lrecord_range_table);
   rtnew->entries = Dynarr_new (range_table_entry);
 
   Dynarr_add_many (rtnew->entries, Dynarr_atp (rt->entries, 0),
@@ -236,15 +263,15 @@ ranges as the given table.  The values will not themselves be copied.
 }
 
 DEFUN ("get-range-table", Fget_range_table, 2, 3, 0, /*
-Find value for position POS in TABLE.
+Find value for position POS in RANGE-TABLE.
 If there is no corresponding value, return DEFAULT (defaults to nil).
 */
-       (pos, table, default_))
+       (pos, range_table, default_))
 {
-  struct Lisp_Range_Table *rt;
+  Lisp_Range_Table *rt;
 
-  CHECK_RANGE_TABLE (table);
-  rt = XRANGE_TABLE (table);
+  CHECK_RANGE_TABLE (range_table);
+  rt = XRANGE_TABLE (range_table);
 
   CHECK_INT_COERCE_CHAR (pos);
 
@@ -258,7 +285,7 @@ put_range_table (Lisp_Object table, EMACS_INT first,
 {
   int i;
   int insert_me_here = -1;
-  struct Lisp_Range_Table *rt = XRANGE_TABLE (table);
+  Lisp_Range_Table *rt = XRANGE_TABLE (table);
 
   /* Now insert in the proper place.  This gets tricky because
      we may be overlapping one or more existing ranges and need
@@ -377,13 +404,13 @@ put_range_table (Lisp_Object table, EMACS_INT first,
 }
 
 DEFUN ("put-range-table", Fput_range_table, 4, 4, 0, /*
-Set the value for range (START, END) to be VAL in TABLE.
+Set the value for range (START, END) to be VALUE in RANGE-TABLE.
 */
-       (start, end, val, table))
+       (start, end, value, range_table))
 {
   EMACS_INT first, last;
 
-  CHECK_RANGE_TABLE (table);
+  CHECK_RANGE_TABLE (range_table);
   CHECK_INT_COERCE_CHAR (start);
   first = XINT (start);
   CHECK_INT_COERCE_CHAR (end);
@@ -391,36 +418,73 @@ Set the value for range (START, END) to be VAL in TABLE.
   if (first > last)
     signal_simple_error_2 ("start must be <= end", start, end);
 
-  put_range_table (table, first, last, val);
-  verify_range_table (XRANGE_TABLE (table));
+  put_range_table (range_table, first, last, value);
+  verify_range_table (XRANGE_TABLE (range_table));
   return Qnil;
 }
 
 DEFUN ("remove-range-table", Fremove_range_table, 3, 3, 0, /*
-Remove the value for range (START, END) in TABLE.
+Remove the value for range (START, END) in RANGE-TABLE.
 */
-       (start, end, table))
+       (start, end, range_table))
 {
-  return Fput_range_table (start, end, Qunbound, table);
+  return Fput_range_table (start, end, Qunbound, range_table);
 }
 
 DEFUN ("clear-range-table", Fclear_range_table, 1, 1, 0, /*
-Flush TABLE.
+Flush RANGE-TABLE.
 */
-       (table))
+       (range_table))
 {
-  CHECK_RANGE_TABLE (table);
-  Dynarr_reset (XRANGE_TABLE (table)->entries);
+  CHECK_RANGE_TABLE (range_table);
+  Dynarr_reset (XRANGE_TABLE (range_table)->entries);
   return Qnil;
 }
 
 DEFUN ("map-range-table", Fmap_range_table, 2, 2, 0, /*
-Map FUNCTION over entries in TABLE, calling it with three args,
+Map FUNCTION over entries in RANGE-TABLE, calling it with three args,
 the beginning and end of the range and the corresponding value.
+
+Results are guaranteed to be correct (i.e. each entry processed
+exactly once) if FUNCTION modifies or deletes the current entry
+\(i.e. passes the current range to `put-range-table' or
+`remove-range-table'), but not otherwise.
 */
-       (function, table))
+       (function, range_table))
 {
-  error ("not yet implemented");
+  Lisp_Range_Table *rt;
+  int i;
+
+  CHECK_RANGE_TABLE (range_table);
+  CHECK_FUNCTION (function);
+
+  rt = XRANGE_TABLE (range_table);
+
+  /* Do not "optimize" by pulling out the length computation below!
+     FUNCTION may have changed the table. */
+  for (i = 0; i < Dynarr_length (rt->entries); i++)
+    {
+      struct range_table_entry *entry = Dynarr_atp (rt->entries, i);
+      EMACS_INT first, last;
+      Lisp_Object args[4];
+      int oldlen;
+
+    again:
+      first = entry->first;
+      last = entry->last;
+      oldlen = Dynarr_length (rt->entries);
+      args[0] = function;
+      args[1] = make_int (first);
+      args[2] = make_int (last);
+      args[3] = entry->val;
+      Ffuncall (countof (args), args);
+      /* Has FUNCTION removed the entry? */
+      if (oldlen > Dynarr_length (rt->entries)
+         && i < Dynarr_length (rt->entries)
+         && (first != entry->first || last != entry->last))
+       goto again;
+      }
+
   return Qnil;
 }
 
@@ -678,6 +742,8 @@ unified_range_table_get_range (void *unrangetab, int offset,
 void
 syms_of_rangetab (void)
 {
+  INIT_LRECORD_IMPLEMENTATION (range_table);
+
   defsymbol (&Qrange_tablep, "range-table-p");
   defsymbol (&Qrange_table, "range-table");