# HG changeset patch # User Kenichi Handa # Date 1182767121 0 # Node ID d563fa5ce20080d3b74ea239d472232965de8d59 # Parent 77d6accc7a63c103ff956b5be72a0f7d5745624c (map_sub_char_table): Make it work for the top-level char-table. Fix handling of parent char-table. (map_char_table): Adjusted for the above change. diff -r 77d6accc7a63 -r d563fa5ce200 src/chartab.c --- a/src/chartab.c Sun Jun 24 20:49:39 2007 +0000 +++ b/src/chartab.c Mon Jun 25 10:25:21 2007 +0000 @@ -705,34 +705,104 @@ } +/* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table), + calling it for each character or group of characters that share a + value. RANGE is a cons (FROM . TO) specifying the range of target + characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the + default value of the char-table, PARENT is the parent of the + char-table. + + ARG is passed to C_FUNCTION when that is called. + + It returns the value of last character covered by TABLE (not the + value inheritted from the parent), and by side-effect, the car part + of RANGE is updated to the minimum character C where C and all the + following characters in TABLE have the same value. */ + static Lisp_Object map_sub_char_table (c_function, function, table, arg, val, range, default_val, parent) void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); Lisp_Object function, table, arg, val, range, default_val, parent; { - struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); - int depth = XINT (tbl->depth); + /* Pointer to the elements of TABLE. */ + Lisp_Object *contents; + /* Depth of TABLE. */ + int depth; + /* Minimum and maxinum characters covered by TABLE. */ + int min_char, max_char; + /* Number of characters covered by one element of TABLE. */ + int chars_in_block; + int from = XINT (XCAR (range)), to = XINT (XCDR (range)); int i, c; - for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; - i++, c += chartab_chars[depth]) + if (SUB_CHAR_TABLE_P (table)) { - Lisp_Object this; + struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); + + depth = XINT (tbl->depth); + contents = tbl->contents; + min_char = XINT (tbl->min_char); + max_char = min_char + chartab_chars[depth - 1] - 1; + } + else + { + depth = 0; + contents = XCHAR_TABLE (table)->contents; + min_char = 0; + max_char = MAX_CHAR; + } + chars_in_block = chartab_chars[depth]; - this = tbl->contents[i]; + if (to < max_char) + max_char = to; + /* Set I to the index of the first element to check. */ + if (from <= min_char) + i = 0; + else + i = (from - min_char) / chars_in_block; + for (c = min_char + chars_in_block * i; c <= max_char; + i++, c += chars_in_block) + { + Lisp_Object this = contents[i]; + int nextc = c + chars_in_block; + if (SUB_CHAR_TABLE_P (this)) - val = map_sub_char_table (c_function, function, this, arg, val, range, - default_val, parent); + { + if (to >= nextc) + XSETCDR (range, make_number (nextc - 1)); + val = map_sub_char_table (c_function, function, this, arg, + val, range, default_val, parent); + } else { if (NILP (this)) this = default_val; - if (NILP (this) && ! NILP (parent)) - this = CHAR_TABLE_REF (parent, c); if (NILP (Fequal (val, this))) { - if (! NILP (val)) + int different_value = 1; + + if (NILP (val)) + { + if (! NILP (parent)) + { + Lisp_Object temp = XCHAR_TABLE (parent)->parent; + + /* This is to get a value of FROM in PARENT + without checking the parent of PARENT. */ + XCHAR_TABLE (parent)->parent = Qnil; + val = CHAR_TABLE_REF (parent, from); + XCHAR_TABLE (parent)->parent = temp; + XSETCDR (range, make_number (c - 1)); + val = map_sub_char_table (c_function, function, + parent, arg, val, range, + XCHAR_TABLE (parent)->defalt, + XCHAR_TABLE (parent)->parent); + if (! NILP (Fequal (val, this))) + different_value = 0; + } + } + if (! NILP (val) && different_value) { XSETCDR (range, make_number (c - 1)); if (depth == 3 @@ -752,9 +822,11 @@ } } val = this; + from = c; XSETCAR (range, make_number (c)); } } + XSETCDR (range, make_number (to)); } return val; } @@ -774,46 +846,35 @@ int c, i; struct gcpro gcpro1, gcpro2, gcpro3; - range = Fcons (make_number (0), Qnil); + range = Fcons (make_number (0), make_number (MAX_CHAR)); GCPRO3 (table, arg, range); val = XCHAR_TABLE (table)->ascii; if (SUB_CHAR_TABLE_P (val)) val = XSUB_CHAR_TABLE (val)->contents[0]; - - for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0]) + val = map_sub_char_table (c_function, function, table, arg, val, range, + XCHAR_TABLE (table)->defalt, + XCHAR_TABLE (table)->parent); + /* If VAL is nil and TABLE has a parent, we must consult the parent + recursively. */ + while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent)) { - Lisp_Object this; + Lisp_Object parent = XCHAR_TABLE (table)->parent; + Lisp_Object temp = XCHAR_TABLE (parent)->parent; + int from = XINT (XCAR (range)); - this = XCHAR_TABLE (table)->contents[i]; - if (SUB_CHAR_TABLE_P (this)) - val = map_sub_char_table (c_function, function, this, arg, val, range, - XCHAR_TABLE (table)->defalt, - XCHAR_TABLE (table)->parent); - else - { - if (NILP (this)) - this = XCHAR_TABLE (table)->defalt; - if (NILP (this) && ! NILP (XCHAR_TABLE (table)->parent)) - this = CHAR_TABLE_REF (XCHAR_TABLE (table)->parent, c); - if (NILP (Fequal (val, this))) - { - if (! NILP (val)) - { - XSETCDR (range, make_number (c - 1)); - if (c_function) - (*c_function) (arg, range, val); - else - call2 (function, range, val); - } - val = this; - XSETCAR (range, make_number (c)); - } - } + /* This is to get a value of FROM in PARENT without checking the + parent of PARENT. */ + XCHAR_TABLE (parent)->parent = Qnil; + val = CHAR_TABLE_REF (parent, from); + XCHAR_TABLE (parent)->parent = temp; + val = map_sub_char_table (c_function, function, parent, arg, val, range, + XCHAR_TABLE (parent)->defalt, + XCHAR_TABLE (parent)->parent); + table = parent; } if (! NILP (val)) { - XSETCDR (range, make_number (c - 1)); if (c_function) (*c_function) (arg, range, val); else