diff options
| author | Kenichi Handa | 2011-07-07 07:43:48 +0900 |
|---|---|---|
| committer | Kenichi Handa | 2011-07-07 07:43:48 +0900 |
| commit | c805dec0b5fa81b5c9f2b724e2ec12a17d723aca (patch) | |
| tree | c29a8490c976fdf4dbf64ef1b13a57f7d1110cc1 /src | |
| parent | 5c62d133468c354b47a1643092add8292e084765 (diff) | |
| download | emacs-c805dec0b5fa81b5c9f2b724e2ec12a17d723aca.tar.gz emacs-c805dec0b5fa81b5c9f2b724e2ec12a17d723aca.zip | |
Add C interface for Unicode character property table.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 42 | ||||
| -rw-r--r-- | src/character.h | 39 | ||||
| -rw-r--r-- | src/chartab.c | 579 | ||||
| -rw-r--r-- | src/composite.c | 5 | ||||
| -rw-r--r-- | src/dispextern.h | 6 | ||||
| -rw-r--r-- | src/font.c | 5 |
6 files changed, 598 insertions, 78 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 78fca60ca28..1a56298ee20 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,45 @@ | |||
| 1 | 2011-07-06 Kenichi Handa <handa@m17n.org> | ||
| 2 | |||
| 3 | * character.h (unicode_category_t): New enum type. | ||
| 4 | |||
| 5 | * chartab.c (uniprop_decoder_t, uniprop_encoder_t): New types. | ||
| 6 | (Qchar_code_property_table): New variable. | ||
| 7 | (UNIPROP_TABLE_P, UNIPROP_GET_DECODER) | ||
| 8 | (UNIPROP_COMPRESSED_FORM_P): New macros. | ||
| 9 | (char_table_ascii): Uncompress the compressed values. | ||
| 10 | (sub_char_table_ref): New arg is_uniprop. Callers changed. | ||
| 11 | Uncompress the compressed values. | ||
| 12 | (sub_char_table_ref_and_range): Likewise. | ||
| 13 | (char_table_ref_and_range): Uncompress the compressed values. | ||
| 14 | (sub_char_table_set): New arg is_uniprop. Callers changed. | ||
| 15 | Uncompress the compressed values. | ||
| 16 | (sub_char_table_set_range): Args changed. Callers changed. | ||
| 17 | (char_table_set_range): Adjuted for the above change. | ||
| 18 | (map_sub_char_table): Delete args default_val and parent. Add arg | ||
| 19 | top. Give decoded values to a Lisp function. | ||
| 20 | (map_char_table): Adjusted for the above change. Give decoded | ||
| 21 | values to a Lisp function. Gcpro more variables. | ||
| 22 | (uniprop_table_uncompress) | ||
| 23 | (uniprop_decode_value_run_length): New functions. | ||
| 24 | (uniprop_decoder, uniprop_decoder_count): New variables. | ||
| 25 | (uniprop_get_decoder, uniprop_encode_value_character) | ||
| 26 | (uniprop_encode_value_run_length, uniprop_encode_value_numeric): | ||
| 27 | New functions. | ||
| 28 | (uniprop_encoder, uniprop_encoder_count): New variables. | ||
| 29 | (uniprop_get_encoder, uniprop_table) | ||
| 30 | (Funicode_property_table_internal, Fget_unicode_property_internal) | ||
| 31 | (Fput_unicode_property_internal): New functions. | ||
| 32 | (syms_of_chartab): DEFSYM Qchar_code_property_table, defsubr | ||
| 33 | Sunicode_property_table_internal, Sget_unicode_property_internal, | ||
| 34 | and Sput_unicode_property_internal. Defvar_lisp | ||
| 35 | char-code-property-alist. | ||
| 36 | |||
| 37 | * composite.c (CHAR_COMPOSABLE_P): Adjusted for the change of | ||
| 38 | Vunicode_category_table. | ||
| 39 | |||
| 40 | * font.c (font_range): Adjusted for the change of | ||
| 41 | Vunicode_category_table. | ||
| 42 | |||
| 1 | 2011-06-22 Paul Eggert <eggert@cs.ucla.edu> | 43 | 2011-06-22 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 44 | ||
| 3 | Fixes for GLYPH_DEBUG found by GCC 4.6.0 static checking. | 45 | Fixes for GLYPH_DEBUG found by GCC 4.6.0 static checking. |
diff --git a/src/character.h b/src/character.h index 9a45e7f0033..d8e77c50953 100644 --- a/src/character.h +++ b/src/character.h | |||
| @@ -597,6 +597,45 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 597 | : (c) <= 0xDFFF ? 2 \ | 597 | : (c) <= 0xDFFF ? 2 \ |
| 598 | : 0) | 598 | : 0) |
| 599 | 599 | ||
| 600 | /* Data type for Unicode general category. | ||
| 601 | |||
| 602 | The order of members must be in sync with the 8th element of the | ||
| 603 | member of unidata-prop-alist (in admin/unidata/unidata-getn.el) for | ||
| 604 | Unicode character property `general-category'. */ | ||
| 605 | |||
| 606 | typedef enum { | ||
| 607 | UNICODE_CATEGORY_UNKNOWN = 0, | ||
| 608 | UNICODE_CATEGORY_Lu, | ||
| 609 | UNICODE_CATEGORY_Ll, | ||
| 610 | UNICODE_CATEGORY_Lt, | ||
| 611 | UNICODE_CATEGORY_Lm, | ||
| 612 | UNICODE_CATEGORY_Lo, | ||
| 613 | UNICODE_CATEGORY_Mn, | ||
| 614 | UNICODE_CATEGORY_Mc, | ||
| 615 | UNICODE_CATEGORY_Me, | ||
| 616 | UNICODE_CATEGORY_Nd, | ||
| 617 | UNICODE_CATEGORY_Nl, | ||
| 618 | UNICODE_CATEGORY_No, | ||
| 619 | UNICODE_CATEGORY_Pc, | ||
| 620 | UNICODE_CATEGORY_Pd, | ||
| 621 | UNICODE_CATEGORY_Ps, | ||
| 622 | UNICODE_CATEGORY_Pe, | ||
| 623 | UNICODE_CATEGORY_Pi, | ||
| 624 | UNICODE_CATEGORY_Pf, | ||
| 625 | UNICODE_CATEGORY_Po, | ||
| 626 | UNICODE_CATEGORY_Sm, | ||
| 627 | UNICODE_CATEGORY_Sc, | ||
| 628 | UNICODE_CATEGORY_Sk, | ||
| 629 | UNICODE_CATEGORY_So, | ||
| 630 | UNICODE_CATEGORY_Zs, | ||
| 631 | UNICODE_CATEGORY_Zl, | ||
| 632 | UNICODE_CATEGORY_Zp, | ||
| 633 | UNICODE_CATEGORY_Cc, | ||
| 634 | UNICODE_CATEGORY_Cf, | ||
| 635 | UNICODE_CATEGORY_Cs, | ||
| 636 | UNICODE_CATEGORY_Co, | ||
| 637 | UNICODE_CATEGORY_Cn | ||
| 638 | } unicode_category_t; | ||
| 600 | 639 | ||
| 601 | extern int char_resolve_modifier_mask (int); | 640 | extern int char_resolve_modifier_mask (int); |
| 602 | extern int char_string (unsigned, unsigned char *); | 641 | extern int char_string (unsigned, unsigned char *); |
diff --git a/src/chartab.c b/src/chartab.c index ed5b238646e..4a9a76bdd60 100644 --- a/src/chartab.c +++ b/src/chartab.c | |||
| @@ -53,7 +53,38 @@ static const int chartab_bits[4] = | |||
| 53 | #define CHARTAB_IDX(c, depth, min_char) \ | 53 | #define CHARTAB_IDX(c, depth, min_char) \ |
| 54 | (((c) - (min_char)) >> chartab_bits[(depth)]) | 54 | (((c) - (min_char)) >> chartab_bits[(depth)]) |
| 55 | 55 | ||
| 56 | |||
| 57 | /* Preamble for uniprop (Unicode character property) tables. See the | ||
| 58 | comment of "Unicode character property tables". */ | ||
| 59 | |||
| 60 | /* Purpose of uniprop tables. */ | ||
| 61 | static Lisp_Object Qchar_code_property_table; | ||
| 62 | |||
| 63 | /* Types of decoder and encoder functions for uniprop values. */ | ||
| 64 | typedef Lisp_Object (*uniprop_decoder_t) (Lisp_Object, Lisp_Object); | ||
| 65 | typedef Lisp_Object (*uniprop_encoder_t) (Lisp_Object, Lisp_Object); | ||
| 66 | |||
| 67 | static Lisp_Object uniprop_table_uncompress (Lisp_Object, int); | ||
| 68 | static uniprop_decoder_t uniprop_get_decoder (Lisp_Object); | ||
| 69 | |||
| 70 | /* 1 iff TABLE is a uniprop table. */ | ||
| 71 | #define UNIPROP_TABLE_P(TABLE) \ | ||
| 72 | (EQ (XCHAR_TABLE (TABLE)->purpose, Qchar_code_property_table) \ | ||
| 73 | && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (TABLE)) == 5) | ||
| 74 | |||
| 75 | /* Return a decoder for values in the uniprop table TABLE. */ | ||
| 76 | #define UNIPROP_GET_DECODER(TABLE) \ | ||
| 77 | (UNIPROP_TABLE_P (TABLE) ? uniprop_get_decoder (TABLE) : NULL) | ||
| 56 | 78 | ||
| 79 | /* Nonzero iff OBJ is a string representing uniprop values of 128 | ||
| 80 | succeeding characters (the bottom level of a char-table) by a | ||
| 81 | compressed format. We are sure that no property value has a string | ||
| 82 | starting with '\001' nor '\002'. */ | ||
| 83 | #define UNIPROP_COMPRESSED_FORM_P(OBJ) \ | ||
| 84 | (STRINGP (OBJ) && SCHARS (OBJ) > 0 \ | ||
| 85 | && ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2)))) | ||
| 86 | |||
| 87 | |||
| 57 | DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, | 88 | DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, |
| 58 | doc: /* Return a newly created char-table, with purpose PURPOSE. | 89 | doc: /* Return a newly created char-table, with purpose PURPOSE. |
| 59 | Each element is initialized to INIT, which defaults to nil. | 90 | Each element is initialized to INIT, which defaults to nil. |
| @@ -107,7 +138,7 @@ make_sub_char_table (int depth, int min_char, Lisp_Object defalt) | |||
| 107 | static Lisp_Object | 138 | static Lisp_Object |
| 108 | char_table_ascii (Lisp_Object table) | 139 | char_table_ascii (Lisp_Object table) |
| 109 | { | 140 | { |
| 110 | Lisp_Object sub; | 141 | Lisp_Object sub, val; |
| 111 | 142 | ||
| 112 | sub = XCHAR_TABLE (table)->contents[0]; | 143 | sub = XCHAR_TABLE (table)->contents[0]; |
| 113 | if (! SUB_CHAR_TABLE_P (sub)) | 144 | if (! SUB_CHAR_TABLE_P (sub)) |
| @@ -115,7 +146,10 @@ char_table_ascii (Lisp_Object table) | |||
| 115 | sub = XSUB_CHAR_TABLE (sub)->contents[0]; | 146 | sub = XSUB_CHAR_TABLE (sub)->contents[0]; |
| 116 | if (! SUB_CHAR_TABLE_P (sub)) | 147 | if (! SUB_CHAR_TABLE_P (sub)) |
| 117 | return sub; | 148 | return sub; |
| 118 | return XSUB_CHAR_TABLE (sub)->contents[0]; | 149 | val = XSUB_CHAR_TABLE (sub)->contents[0]; |
| 150 | if (UNIPROP_TABLE_P (table) && UNIPROP_COMPRESSED_FORM_P (val)) | ||
| 151 | val = uniprop_table_uncompress (sub, 0); | ||
| 152 | return val; | ||
| 119 | } | 153 | } |
| 120 | 154 | ||
| 121 | static Lisp_Object | 155 | static Lisp_Object |
| @@ -169,16 +203,19 @@ copy_char_table (Lisp_Object table) | |||
| 169 | } | 203 | } |
| 170 | 204 | ||
| 171 | static Lisp_Object | 205 | static Lisp_Object |
| 172 | sub_char_table_ref (Lisp_Object table, int c) | 206 | sub_char_table_ref (Lisp_Object table, int c, int is_uniprop) |
| 173 | { | 207 | { |
| 174 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); | 208 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); |
| 175 | int depth = XINT (tbl->depth); | 209 | int depth = XINT (tbl->depth); |
| 176 | int min_char = XINT (tbl->min_char); | 210 | int min_char = XINT (tbl->min_char); |
| 177 | Lisp_Object val; | 211 | Lisp_Object val; |
| 212 | int idx = CHARTAB_IDX (c, depth, min_char); | ||
| 178 | 213 | ||
| 179 | val = tbl->contents[CHARTAB_IDX (c, depth, min_char)]; | 214 | val = tbl->contents[idx]; |
| 215 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) | ||
| 216 | val = uniprop_table_uncompress (table, idx); | ||
| 180 | if (SUB_CHAR_TABLE_P (val)) | 217 | if (SUB_CHAR_TABLE_P (val)) |
| 181 | val = sub_char_table_ref (val, c); | 218 | val = sub_char_table_ref (val, c, is_uniprop); |
| 182 | return val; | 219 | return val; |
| 183 | } | 220 | } |
| 184 | 221 | ||
| @@ -198,7 +235,7 @@ char_table_ref (Lisp_Object table, int c) | |||
| 198 | { | 235 | { |
| 199 | val = tbl->contents[CHARTAB_IDX (c, 0, 0)]; | 236 | val = tbl->contents[CHARTAB_IDX (c, 0, 0)]; |
| 200 | if (SUB_CHAR_TABLE_P (val)) | 237 | if (SUB_CHAR_TABLE_P (val)) |
| 201 | val = sub_char_table_ref (val, c); | 238 | val = sub_char_table_ref (val, c, UNIPROP_TABLE_P (table)); |
| 202 | } | 239 | } |
| 203 | if (NILP (val)) | 240 | if (NILP (val)) |
| 204 | { | 241 | { |
| @@ -210,7 +247,8 @@ char_table_ref (Lisp_Object table, int c) | |||
| 210 | } | 247 | } |
| 211 | 248 | ||
| 212 | static Lisp_Object | 249 | static Lisp_Object |
| 213 | sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt) | 250 | sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, |
| 251 | Lisp_Object defalt, int is_uniprop) | ||
| 214 | { | 252 | { |
| 215 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); | 253 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); |
| 216 | int depth = XINT (tbl->depth); | 254 | int depth = XINT (tbl->depth); |
| @@ -219,8 +257,10 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp | |||
| 219 | Lisp_Object val; | 257 | Lisp_Object val; |
| 220 | 258 | ||
| 221 | val = tbl->contents[chartab_idx]; | 259 | val = tbl->contents[chartab_idx]; |
| 260 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) | ||
| 261 | val = uniprop_table_uncompress (table, chartab_idx); | ||
| 222 | if (SUB_CHAR_TABLE_P (val)) | 262 | if (SUB_CHAR_TABLE_P (val)) |
| 223 | val = sub_char_table_ref_and_range (val, c, from, to, defalt); | 263 | val = sub_char_table_ref_and_range (val, c, from, to, defalt, is_uniprop); |
| 224 | else if (NILP (val)) | 264 | else if (NILP (val)) |
| 225 | val = defalt; | 265 | val = defalt; |
| 226 | 266 | ||
| @@ -232,8 +272,11 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp | |||
| 232 | c = min_char + idx * chartab_chars[depth] - 1; | 272 | c = min_char + idx * chartab_chars[depth] - 1; |
| 233 | idx--; | 273 | idx--; |
| 234 | this_val = tbl->contents[idx]; | 274 | this_val = tbl->contents[idx]; |
| 275 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) | ||
| 276 | this_val = uniprop_table_uncompress (table, idx); | ||
| 235 | if (SUB_CHAR_TABLE_P (this_val)) | 277 | if (SUB_CHAR_TABLE_P (this_val)) |
| 236 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); | 278 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt, |
| 279 | is_uniprop); | ||
| 237 | else if (NILP (this_val)) | 280 | else if (NILP (this_val)) |
| 238 | this_val = defalt; | 281 | this_val = defalt; |
| 239 | 282 | ||
| @@ -251,8 +294,11 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp | |||
| 251 | 294 | ||
| 252 | chartab_idx++; | 295 | chartab_idx++; |
| 253 | this_val = tbl->contents[chartab_idx]; | 296 | this_val = tbl->contents[chartab_idx]; |
| 297 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) | ||
| 298 | this_val = uniprop_table_uncompress (table, chartab_idx); | ||
| 254 | if (SUB_CHAR_TABLE_P (this_val)) | 299 | if (SUB_CHAR_TABLE_P (this_val)) |
| 255 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); | 300 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt, |
| 301 | is_uniprop); | ||
| 256 | else if (NILP (this_val)) | 302 | else if (NILP (this_val)) |
| 257 | this_val = defalt; | 303 | this_val = defalt; |
| 258 | if (! EQ (this_val, val)) | 304 | if (! EQ (this_val, val)) |
| @@ -277,17 +323,20 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) | |||
| 277 | struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); | 323 | struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); |
| 278 | int chartab_idx = CHARTAB_IDX (c, 0, 0), idx; | 324 | int chartab_idx = CHARTAB_IDX (c, 0, 0), idx; |
| 279 | Lisp_Object val; | 325 | Lisp_Object val; |
| 326 | int is_uniprop = UNIPROP_TABLE_P (table); | ||
| 280 | 327 | ||
| 281 | val = tbl->contents[chartab_idx]; | 328 | val = tbl->contents[chartab_idx]; |
| 282 | if (*from < 0) | 329 | if (*from < 0) |
| 283 | *from = 0; | 330 | *from = 0; |
| 284 | if (*to < 0) | 331 | if (*to < 0) |
| 285 | *to = MAX_CHAR; | 332 | *to = MAX_CHAR; |
| 333 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) | ||
| 334 | val = uniprop_table_uncompress (table, chartab_idx); | ||
| 286 | if (SUB_CHAR_TABLE_P (val)) | 335 | if (SUB_CHAR_TABLE_P (val)) |
| 287 | val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt); | 336 | val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt, |
| 337 | is_uniprop); | ||
| 288 | else if (NILP (val)) | 338 | else if (NILP (val)) |
| 289 | val = tbl->defalt; | 339 | val = tbl->defalt; |
| 290 | |||
| 291 | idx = chartab_idx; | 340 | idx = chartab_idx; |
| 292 | while (*from < idx * chartab_chars[0]) | 341 | while (*from < idx * chartab_chars[0]) |
| 293 | { | 342 | { |
| @@ -296,9 +345,11 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) | |||
| 296 | c = idx * chartab_chars[0] - 1; | 345 | c = idx * chartab_chars[0] - 1; |
| 297 | idx--; | 346 | idx--; |
| 298 | this_val = tbl->contents[idx]; | 347 | this_val = tbl->contents[idx]; |
| 348 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) | ||
| 349 | this_val = uniprop_table_uncompress (table, idx); | ||
| 299 | if (SUB_CHAR_TABLE_P (this_val)) | 350 | if (SUB_CHAR_TABLE_P (this_val)) |
| 300 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, | 351 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, |
| 301 | tbl->defalt); | 352 | tbl->defalt, is_uniprop); |
| 302 | else if (NILP (this_val)) | 353 | else if (NILP (this_val)) |
| 303 | this_val = tbl->defalt; | 354 | this_val = tbl->defalt; |
| 304 | 355 | ||
| @@ -315,9 +366,11 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) | |||
| 315 | chartab_idx++; | 366 | chartab_idx++; |
| 316 | c = chartab_idx * chartab_chars[0]; | 367 | c = chartab_idx * chartab_chars[0]; |
| 317 | this_val = tbl->contents[chartab_idx]; | 368 | this_val = tbl->contents[chartab_idx]; |
| 369 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) | ||
| 370 | this_val = uniprop_table_uncompress (table, chartab_idx); | ||
| 318 | if (SUB_CHAR_TABLE_P (this_val)) | 371 | if (SUB_CHAR_TABLE_P (this_val)) |
| 319 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, | 372 | this_val = sub_char_table_ref_and_range (this_val, c, from, to, |
| 320 | tbl->defalt); | 373 | tbl->defalt, is_uniprop); |
| 321 | else if (NILP (this_val)) | 374 | else if (NILP (this_val)) |
| 322 | this_val = tbl->defalt; | 375 | this_val = tbl->defalt; |
| 323 | if (! EQ (this_val, val)) | 376 | if (! EQ (this_val, val)) |
| @@ -332,7 +385,7 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) | |||
| 332 | 385 | ||
| 333 | 386 | ||
| 334 | static void | 387 | static void |
| 335 | sub_char_table_set (Lisp_Object table, int c, Lisp_Object val) | 388 | sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, int is_uniprop) |
| 336 | { | 389 | { |
| 337 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); | 390 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); |
| 338 | int depth = XINT ((tbl)->depth); | 391 | int depth = XINT ((tbl)->depth); |
| @@ -347,11 +400,17 @@ sub_char_table_set (Lisp_Object table, int c, Lisp_Object val) | |||
| 347 | sub = tbl->contents[i]; | 400 | sub = tbl->contents[i]; |
| 348 | if (! SUB_CHAR_TABLE_P (sub)) | 401 | if (! SUB_CHAR_TABLE_P (sub)) |
| 349 | { | 402 | { |
| 350 | sub = make_sub_char_table (depth + 1, | 403 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub)) |
| 351 | min_char + i * chartab_chars[depth], sub); | 404 | sub = uniprop_table_uncompress (table, i); |
| 352 | tbl->contents[i] = sub; | 405 | else |
| 406 | { | ||
| 407 | sub = make_sub_char_table (depth + 1, | ||
| 408 | min_char + i * chartab_chars[depth], | ||
| 409 | sub); | ||
| 410 | tbl->contents[i] = sub; | ||
| 411 | } | ||
| 353 | } | 412 | } |
| 354 | sub_char_table_set (sub, c, val); | 413 | sub_char_table_set (sub, c, val, is_uniprop); |
| 355 | } | 414 | } |
| 356 | } | 415 | } |
| 357 | 416 | ||
| @@ -376,7 +435,7 @@ char_table_set (Lisp_Object table, int c, Lisp_Object val) | |||
| 376 | sub = make_sub_char_table (1, i * chartab_chars[0], sub); | 435 | sub = make_sub_char_table (1, i * chartab_chars[0], sub); |
| 377 | tbl->contents[i] = sub; | 436 | tbl->contents[i] = sub; |
| 378 | } | 437 | } |
| 379 | sub_char_table_set (sub, c, val); | 438 | sub_char_table_set (sub, c, val, UNIPROP_TABLE_P (table)); |
| 380 | if (ASCII_CHAR_P (c)) | 439 | if (ASCII_CHAR_P (c)) |
| 381 | tbl->ascii = char_table_ascii (table); | 440 | tbl->ascii = char_table_ascii (table); |
| 382 | } | 441 | } |
| @@ -384,30 +443,40 @@ char_table_set (Lisp_Object table, int c, Lisp_Object val) | |||
| 384 | } | 443 | } |
| 385 | 444 | ||
| 386 | static void | 445 | static void |
| 387 | sub_char_table_set_range (Lisp_Object *table, int depth, int min_char, int from, int to, Lisp_Object val) | 446 | sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val, |
| 447 | int is_uniprop) | ||
| 388 | { | 448 | { |
| 389 | int max_char = min_char + chartab_chars[depth] - 1; | 449 | struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); |
| 390 | 450 | int depth = XINT ((tbl)->depth); | |
| 391 | if (depth == 3 || (from <= min_char && to >= max_char)) | 451 | int min_char = XINT ((tbl)->min_char); |
| 392 | *table = val; | 452 | int chars_in_block = chartab_chars[depth]; |
| 393 | else | 453 | int i, c, lim = chartab_size[depth]; |
| 454 | |||
| 455 | if (from < min_char) | ||
| 456 | from = min_char; | ||
| 457 | i = CHARTAB_IDX (from, depth, min_char); | ||
| 458 | c = min_char + chars_in_block * i; | ||
| 459 | for (; i <= lim; i++, c += chars_in_block) | ||
| 394 | { | 460 | { |
| 395 | int i; | 461 | if (c > to) |
| 396 | unsigned j; | 462 | break; |
| 397 | 463 | if (from <= c && c + chars_in_block - 1 <= to) | |
| 398 | depth++; | 464 | tbl->contents[i] = val; |
| 399 | if (! SUB_CHAR_TABLE_P (*table)) | 465 | else |
| 400 | *table = make_sub_char_table (depth, min_char, *table); | 466 | { |
| 401 | if (from < min_char) | 467 | Lisp_Object sub = tbl->contents[i]; |
| 402 | from = min_char; | 468 | if (! SUB_CHAR_TABLE_P (sub)) |
| 403 | if (to > max_char) | 469 | { |
| 404 | to = max_char; | 470 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub)) |
| 405 | i = CHARTAB_IDX (from, depth, min_char); | 471 | sub = uniprop_table_uncompress (table, i); |
| 406 | j = CHARTAB_IDX (to, depth, min_char); | 472 | else |
| 407 | min_char += chartab_chars[depth] * i; | 473 | { |
| 408 | for (j++; i < j; i++, min_char += chartab_chars[depth]) | 474 | sub = make_sub_char_table (depth + 1, c, sub); |
| 409 | sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i, | 475 | tbl->contents[i] = sub; |
| 410 | depth, min_char, from, to, val); | 476 | } |
| 477 | } | ||
| 478 | sub_char_table_set_range (sub, from, to, val, is_uniprop); | ||
| 479 | } | ||
| 411 | } | 480 | } |
| 412 | } | 481 | } |
| 413 | 482 | ||
| @@ -417,16 +486,33 @@ char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val) | |||
| 417 | { | 486 | { |
| 418 | struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); | 487 | struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); |
| 419 | Lisp_Object *contents = tbl->contents; | 488 | Lisp_Object *contents = tbl->contents; |
| 420 | int i; | ||
| 421 | 489 | ||
| 422 | if (from == to) | 490 | if (from == to) |
| 423 | char_table_set (table, from, val); | 491 | char_table_set (table, from, val); |
| 424 | else | 492 | else |
| 425 | { | 493 | { |
| 426 | unsigned lim = to / chartab_chars[0] + 1; | 494 | int is_uniprop = UNIPROP_TABLE_P (table); |
| 427 | for (i = CHARTAB_IDX (from, 0, 0); i < lim; i++) | 495 | int lim = CHARTAB_IDX (to, 0, 0); |
| 428 | sub_char_table_set_range (contents + i, 0, i * chartab_chars[0], | 496 | int i, c; |
| 429 | from, to, val); | 497 | |
| 498 | for (i = CHARTAB_IDX (from, 0, 0), c = 0; i <= lim; | ||
| 499 | i++, c += chartab_chars[0]) | ||
| 500 | { | ||
| 501 | if (c > to) | ||
| 502 | break; | ||
| 503 | if (from <= c && c + chartab_chars[0] - 1 <= to) | ||
| 504 | tbl->contents[i] = val; | ||
| 505 | else | ||
| 506 | { | ||
| 507 | Lisp_Object sub = tbl->contents[i]; | ||
| 508 | if (! SUB_CHAR_TABLE_P (sub)) | ||
| 509 | { | ||
| 510 | sub = make_sub_char_table (1, i * chartab_chars[0], sub); | ||
| 511 | tbl->contents[i] = sub; | ||
| 512 | } | ||
| 513 | sub_char_table_set_range (sub, from, to, val, is_uniprop); | ||
| 514 | } | ||
| 515 | } | ||
| 430 | if (ASCII_CHAR_P (from)) | 516 | if (ASCII_CHAR_P (from)) |
| 431 | tbl->ascii = char_table_ascii (table); | 517 | tbl->ascii = char_table_ascii (table); |
| 432 | } | 518 | } |
| @@ -504,6 +590,8 @@ DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot, | |||
| 504 | (Lisp_Object char_table, Lisp_Object n, Lisp_Object value) | 590 | (Lisp_Object char_table, Lisp_Object n, Lisp_Object value) |
| 505 | { | 591 | { |
| 506 | CHECK_CHAR_TABLE (char_table); | 592 | CHECK_CHAR_TABLE (char_table); |
| 593 | if (EQ (XCHAR_TABLE (char_table)->purpose, Qchar_code_property_table)) | ||
| 594 | error ("Can't change extra-slot of char-code-property-table"); | ||
| 507 | CHECK_NUMBER (n); | 595 | CHECK_NUMBER (n); |
| 508 | if (XINT (n) < 0 | 596 | if (XINT (n) < 0 |
| 509 | || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table))) | 597 | || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table))) |
| @@ -532,8 +620,9 @@ a cons of character codes (for characters in the range), or a character code. * | |||
| 532 | 620 | ||
| 533 | CHECK_CHARACTER_CAR (range); | 621 | CHECK_CHARACTER_CAR (range); |
| 534 | CHECK_CHARACTER_CDR (range); | 622 | CHECK_CHARACTER_CDR (range); |
| 535 | val = char_table_ref_and_range (char_table, XFASTINT (XCAR (range)), | 623 | from = XFASTINT (XCAR (range)); |
| 536 | &from, &to); | 624 | to = XFASTINT (XCDR (range)); |
| 625 | val = char_table_ref_and_range (char_table, from, &from, &to); | ||
| 537 | /* Not yet implemented. */ | 626 | /* Not yet implemented. */ |
| 538 | } | 627 | } |
| 539 | else | 628 | else |
| @@ -655,8 +744,7 @@ equivalent and can be merged. It defaults to `equal'. */) | |||
| 655 | /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table), | 744 | /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table), |
| 656 | calling it for each character or group of characters that share a | 745 | calling it for each character or group of characters that share a |
| 657 | value. RANGE is a cons (FROM . TO) specifying the range of target | 746 | value. RANGE is a cons (FROM . TO) specifying the range of target |
| 658 | characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the | 747 | characters, VAL is a value of FROM in TABLE, TOP is the top |
| 659 | default value of the char-table, PARENT is the parent of the | ||
| 660 | char-table. | 748 | char-table. |
| 661 | 749 | ||
| 662 | ARG is passed to C_FUNCTION when that is called. | 750 | ARG is passed to C_FUNCTION when that is called. |
| @@ -669,7 +757,7 @@ equivalent and can be merged. It defaults to `equal'. */) | |||
| 669 | static Lisp_Object | 757 | static Lisp_Object |
| 670 | map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | 758 | map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), |
| 671 | Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val, | 759 | Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val, |
| 672 | Lisp_Object range, Lisp_Object default_val, Lisp_Object parent) | 760 | Lisp_Object range, Lisp_Object top) |
| 673 | { | 761 | { |
| 674 | /* Pointer to the elements of TABLE. */ | 762 | /* Pointer to the elements of TABLE. */ |
| 675 | Lisp_Object *contents; | 763 | Lisp_Object *contents; |
| @@ -681,6 +769,8 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | |||
| 681 | int chars_in_block; | 769 | int chars_in_block; |
| 682 | int from = XINT (XCAR (range)), to = XINT (XCDR (range)); | 770 | int from = XINT (XCAR (range)), to = XINT (XCDR (range)); |
| 683 | int i, c; | 771 | int i, c; |
| 772 | int is_uniprop = UNIPROP_TABLE_P (top); | ||
| 773 | uniprop_decoder_t decoder = UNIPROP_GET_DECODER (top); | ||
| 684 | 774 | ||
| 685 | if (SUB_CHAR_TABLE_P (table)) | 775 | if (SUB_CHAR_TABLE_P (table)) |
| 686 | { | 776 | { |
| @@ -710,28 +800,33 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | |||
| 710 | for (c = min_char + chars_in_block * i; c <= max_char; | 800 | for (c = min_char + chars_in_block * i; c <= max_char; |
| 711 | i++, c += chars_in_block) | 801 | i++, c += chars_in_block) |
| 712 | { | 802 | { |
| 713 | Lisp_Object this = contents[i]; | 803 | Lisp_Object this = (SUB_CHAR_TABLE_P (table) |
| 804 | ? XSUB_CHAR_TABLE (table)->contents[i] | ||
| 805 | : XCHAR_TABLE (table)->contents[i]); | ||
| 714 | int nextc = c + chars_in_block; | 806 | int nextc = c + chars_in_block; |
| 715 | 807 | ||
| 808 | if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this)) | ||
| 809 | this = uniprop_table_uncompress (table, i); | ||
| 716 | if (SUB_CHAR_TABLE_P (this)) | 810 | if (SUB_CHAR_TABLE_P (this)) |
| 717 | { | 811 | { |
| 718 | if (to >= nextc) | 812 | if (to >= nextc) |
| 719 | XSETCDR (range, make_number (nextc - 1)); | 813 | XSETCDR (range, make_number (nextc - 1)); |
| 720 | val = map_sub_char_table (c_function, function, this, arg, | 814 | val = map_sub_char_table (c_function, function, this, arg, |
| 721 | val, range, default_val, parent); | 815 | val, range, top); |
| 722 | } | 816 | } |
| 723 | else | 817 | else |
| 724 | { | 818 | { |
| 725 | if (NILP (this)) | 819 | if (NILP (this)) |
| 726 | this = default_val; | 820 | this = XCHAR_TABLE (top)->defalt; |
| 727 | if (!EQ (val, this)) | 821 | if (!EQ (val, this)) |
| 728 | { | 822 | { |
| 729 | int different_value = 1; | 823 | int different_value = 1; |
| 730 | 824 | ||
| 731 | if (NILP (val)) | 825 | if (NILP (val)) |
| 732 | { | 826 | { |
| 733 | if (! NILP (parent)) | 827 | if (! NILP (XCHAR_TABLE (top)->parent)) |
| 734 | { | 828 | { |
| 829 | Lisp_Object parent = XCHAR_TABLE (top)->parent; | ||
| 735 | Lisp_Object temp = XCHAR_TABLE (parent)->parent; | 830 | Lisp_Object temp = XCHAR_TABLE (parent)->parent; |
| 736 | 831 | ||
| 737 | /* This is to get a value of FROM in PARENT | 832 | /* This is to get a value of FROM in PARENT |
| @@ -742,8 +837,7 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | |||
| 742 | XSETCDR (range, make_number (c - 1)); | 837 | XSETCDR (range, make_number (c - 1)); |
| 743 | val = map_sub_char_table (c_function, function, | 838 | val = map_sub_char_table (c_function, function, |
| 744 | parent, arg, val, range, | 839 | parent, arg, val, range, |
| 745 | XCHAR_TABLE (parent)->defalt, | 840 | parent); |
| 746 | XCHAR_TABLE (parent)->parent); | ||
| 747 | if (EQ (val, this)) | 841 | if (EQ (val, this)) |
| 748 | different_value = 0; | 842 | different_value = 0; |
| 749 | } | 843 | } |
| @@ -756,14 +850,22 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | |||
| 756 | if (c_function) | 850 | if (c_function) |
| 757 | (*c_function) (arg, XCAR (range), val); | 851 | (*c_function) (arg, XCAR (range), val); |
| 758 | else | 852 | else |
| 759 | call2 (function, XCAR (range), val); | 853 | { |
| 854 | if (decoder) | ||
| 855 | val = decoder (top, val); | ||
| 856 | call2 (function, XCAR (range), val); | ||
| 857 | } | ||
| 760 | } | 858 | } |
| 761 | else | 859 | else |
| 762 | { | 860 | { |
| 763 | if (c_function) | 861 | if (c_function) |
| 764 | (*c_function) (arg, range, val); | 862 | (*c_function) (arg, range, val); |
| 765 | else | 863 | else |
| 766 | call2 (function, range, val); | 864 | { |
| 865 | if (decoder) | ||
| 866 | val = decoder (top, val); | ||
| 867 | call2 (function, range, val); | ||
| 868 | } | ||
| 767 | } | 869 | } |
| 768 | } | 870 | } |
| 769 | val = this; | 871 | val = this; |
| @@ -783,35 +885,39 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), | |||
| 783 | ARG is passed to C_FUNCTION when that is called. */ | 885 | ARG is passed to C_FUNCTION when that is called. */ |
| 784 | 886 | ||
| 785 | void | 887 | void |
| 786 | map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object function, Lisp_Object table, Lisp_Object arg) | 888 | map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), |
| 889 | Lisp_Object function, Lisp_Object table, Lisp_Object arg) | ||
| 787 | { | 890 | { |
| 788 | Lisp_Object range, val; | 891 | Lisp_Object range, val, parent; |
| 789 | struct gcpro gcpro1, gcpro2, gcpro3; | 892 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 893 | uniprop_decoder_t decoder = UNIPROP_GET_DECODER (table); | ||
| 790 | 894 | ||
| 791 | range = Fcons (make_number (0), make_number (MAX_CHAR)); | 895 | range = Fcons (make_number (0), make_number (MAX_CHAR)); |
| 792 | GCPRO3 (table, arg, range); | 896 | parent = XCHAR_TABLE (table)->parent; |
| 897 | |||
| 898 | GCPRO4 (table, arg, range, parent); | ||
| 793 | val = XCHAR_TABLE (table)->ascii; | 899 | val = XCHAR_TABLE (table)->ascii; |
| 794 | if (SUB_CHAR_TABLE_P (val)) | 900 | if (SUB_CHAR_TABLE_P (val)) |
| 795 | val = XSUB_CHAR_TABLE (val)->contents[0]; | 901 | val = XSUB_CHAR_TABLE (val)->contents[0]; |
| 796 | val = map_sub_char_table (c_function, function, table, arg, val, range, | 902 | val = map_sub_char_table (c_function, function, table, arg, val, range, |
| 797 | XCHAR_TABLE (table)->defalt, | 903 | table); |
| 798 | XCHAR_TABLE (table)->parent); | 904 | |
| 799 | /* If VAL is nil and TABLE has a parent, we must consult the parent | 905 | /* If VAL is nil and TABLE has a parent, we must consult the parent |
| 800 | recursively. */ | 906 | recursively. */ |
| 801 | while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent)) | 907 | while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent)) |
| 802 | { | 908 | { |
| 803 | Lisp_Object parent = XCHAR_TABLE (table)->parent; | 909 | Lisp_Object temp; |
| 804 | Lisp_Object temp = XCHAR_TABLE (parent)->parent; | ||
| 805 | int from = XINT (XCAR (range)); | 910 | int from = XINT (XCAR (range)); |
| 806 | 911 | ||
| 912 | parent = XCHAR_TABLE (table)->parent; | ||
| 913 | temp = XCHAR_TABLE (parent)->parent; | ||
| 807 | /* This is to get a value of FROM in PARENT without checking the | 914 | /* This is to get a value of FROM in PARENT without checking the |
| 808 | parent of PARENT. */ | 915 | parent of PARENT. */ |
| 809 | XCHAR_TABLE (parent)->parent = Qnil; | 916 | XCHAR_TABLE (parent)->parent = Qnil; |
| 810 | val = CHAR_TABLE_REF (parent, from); | 917 | val = CHAR_TABLE_REF (parent, from); |
| 811 | XCHAR_TABLE (parent)->parent = temp; | 918 | XCHAR_TABLE (parent)->parent = temp; |
| 812 | val = map_sub_char_table (c_function, function, parent, arg, val, range, | 919 | val = map_sub_char_table (c_function, function, parent, arg, val, range, |
| 813 | XCHAR_TABLE (parent)->defalt, | 920 | parent); |
| 814 | XCHAR_TABLE (parent)->parent); | ||
| 815 | table = parent; | 921 | table = parent; |
| 816 | } | 922 | } |
| 817 | 923 | ||
| @@ -822,14 +928,22 @@ map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp | |||
| 822 | if (c_function) | 928 | if (c_function) |
| 823 | (*c_function) (arg, XCAR (range), val); | 929 | (*c_function) (arg, XCAR (range), val); |
| 824 | else | 930 | else |
| 825 | call2 (function, XCAR (range), val); | 931 | { |
| 932 | if (decoder) | ||
| 933 | val = decoder (table, val); | ||
| 934 | call2 (function, XCAR (range), val); | ||
| 935 | } | ||
| 826 | } | 936 | } |
| 827 | else | 937 | else |
| 828 | { | 938 | { |
| 829 | if (c_function) | 939 | if (c_function) |
| 830 | (*c_function) (arg, range, val); | 940 | (*c_function) (arg, range, val); |
| 831 | else | 941 | else |
| 832 | call2 (function, range, val); | 942 | { |
| 943 | if (decoder) | ||
| 944 | val = decoder (table, val); | ||
| 945 | call2 (function, range, val); | ||
| 946 | } | ||
| 833 | } | 947 | } |
| 834 | } | 948 | } |
| 835 | 949 | ||
| @@ -984,9 +1098,315 @@ map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), | |||
| 984 | } | 1098 | } |
| 985 | 1099 | ||
| 986 | 1100 | ||
| 1101 | /* Unicode character property tables. | ||
| 1102 | |||
| 1103 | This section provides a convenient and efficient way to get a | ||
| 1104 | Unicode character property from C code (from Lisp, you must use | ||
| 1105 | get-char-code-property). | ||
| 1106 | |||
| 1107 | The typical usage is to get a char-table for a specific property at | ||
| 1108 | a proper initialization time as this: | ||
| 1109 | |||
| 1110 | Lisp_Object bidi_class_table = uniprop_table (intern ("bidi-class")); | ||
| 1111 | |||
| 1112 | and get a property value for character CH as this: | ||
| 1113 | |||
| 1114 | Lisp_Object bidi_class = CHAR_TABLE_REF (CH, bidi_class_table); | ||
| 1115 | |||
| 1116 | In this case, what you actually get is an index number to the | ||
| 1117 | vector of property values (symbols nil, L, R, etc). | ||
| 1118 | |||
| 1119 | A table for Unicode character property has these characteristics: | ||
| 1120 | |||
| 1121 | o The purpose is `char-code-property-table', which implies that the | ||
| 1122 | table has 5 extra slots. | ||
| 1123 | |||
| 1124 | o The second extra slot is a Lisp function, an index (integer) to | ||
| 1125 | the array uniprop_decoder[], or nil. If it is a Lisp function, we | ||
| 1126 | can't use such a table from C (at the moment). If it is nil, it | ||
| 1127 | means that we don't have to decode values. | ||
| 1128 | |||
| 1129 | o The third extra slot is a Lisp function, an index (integer) to | ||
| 1130 | the array uniprop_enncoder[], or nil. If it is a Lisp function, we | ||
| 1131 | can't use such a table from C (at the moment). If it is nil, it | ||
| 1132 | means that we don't have to encode values. */ | ||
| 1133 | |||
| 1134 | |||
| 1135 | /* Uncompress the IDXth element of sub-char-table TABLE. */ | ||
| 1136 | |||
| 1137 | static Lisp_Object | ||
| 1138 | uniprop_table_uncompress (Lisp_Object table, int idx) | ||
| 1139 | { | ||
| 1140 | Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx]; | ||
| 1141 | int min_char = (XINT (XSUB_CHAR_TABLE (table)->min_char) | ||
| 1142 | + chartab_chars[2] * idx); | ||
| 1143 | Lisp_Object sub = make_sub_char_table (3, min_char, Qnil); | ||
| 1144 | struct Lisp_Sub_Char_Table *subtbl = XSUB_CHAR_TABLE (sub); | ||
| 1145 | const unsigned char *p, *pend; | ||
| 1146 | int i; | ||
| 1147 | |||
| 1148 | XSUB_CHAR_TABLE (table)->contents[idx] = sub; | ||
| 1149 | p = SDATA (val), pend = p + SBYTES (val); | ||
| 1150 | if (*p == 1) | ||
| 1151 | { | ||
| 1152 | /* SIMPLE TABLE */ | ||
| 1153 | p++; | ||
| 1154 | idx = STRING_CHAR_ADVANCE (p); | ||
| 1155 | while (p < pend && idx < chartab_chars[2]) | ||
| 1156 | { | ||
| 1157 | int v = STRING_CHAR_ADVANCE (p); | ||
| 1158 | subtbl->contents[idx++] = v > 0 ? make_number (v) : Qnil; | ||
| 1159 | } | ||
| 1160 | } | ||
| 1161 | else if (*p == 2) | ||
| 1162 | { | ||
| 1163 | /* RUN-LENGTH TABLE */ | ||
| 1164 | p++; | ||
| 1165 | for (idx = 0; p < pend; ) | ||
| 1166 | { | ||
| 1167 | int v = STRING_CHAR_ADVANCE (p); | ||
| 1168 | int count = 1; | ||
| 1169 | int len; | ||
| 1170 | |||
| 1171 | if (p < pend) | ||
| 1172 | { | ||
| 1173 | count = STRING_CHAR_AND_LENGTH (p, len); | ||
| 1174 | if (count < 128) | ||
| 1175 | count = 1; | ||
| 1176 | else | ||
| 1177 | { | ||
| 1178 | count -= 128; | ||
| 1179 | p += len; | ||
| 1180 | } | ||
| 1181 | } | ||
| 1182 | while (count-- > 0) | ||
| 1183 | subtbl->contents[idx++] = make_number (v); | ||
| 1184 | } | ||
| 1185 | } | ||
| 1186 | /* It seems that we don't need this function because C code won't need | ||
| 1187 | to get a property that is compressed in this form. */ | ||
| 1188 | #if 0 | ||
| 1189 | else if (*p == 0) | ||
| 1190 | { | ||
| 1191 | /* WORD-LIST TABLE */ | ||
| 1192 | } | ||
| 1193 | #endif | ||
| 1194 | return sub; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | |||
| 1198 | /* Decode VALUE as an elemnet of char-table TABLE. */ | ||
| 1199 | |||
| 1200 | static Lisp_Object | ||
| 1201 | uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value) | ||
| 1202 | { | ||
| 1203 | if (VECTORP (XCHAR_TABLE (table)->extras[4])) | ||
| 1204 | { | ||
| 1205 | Lisp_Object valvec = XCHAR_TABLE (table)->extras[4]; | ||
| 1206 | |||
| 1207 | if (XINT (value) >= 0 && XINT (value) < ASIZE (valvec)) | ||
| 1208 | value = AREF (valvec, XINT (value)); | ||
| 1209 | } | ||
| 1210 | return value; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | static uniprop_decoder_t uniprop_decoder [] = | ||
| 1214 | { uniprop_decode_value_run_length }; | ||
| 1215 | |||
| 1216 | static int uniprop_decoder_count | ||
| 1217 | = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]); | ||
| 1218 | |||
| 1219 | |||
| 1220 | /* Return the decoder of char-table TABLE or nil if none. */ | ||
| 1221 | |||
| 1222 | static uniprop_decoder_t | ||
| 1223 | uniprop_get_decoder (Lisp_Object table) | ||
| 1224 | { | ||
| 1225 | int i; | ||
| 1226 | |||
| 1227 | if (! INTEGERP (XCHAR_TABLE (table)->extras[1])) | ||
| 1228 | return NULL; | ||
| 1229 | i = XINT (XCHAR_TABLE (table)->extras[1]); | ||
| 1230 | if (i < 0 || i >= uniprop_decoder_count) | ||
| 1231 | return NULL; | ||
| 1232 | return uniprop_decoder[i]; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | |||
| 1236 | /* Encode VALUE as an element of char-table TABLE which contains | ||
| 1237 | characters as elements. */ | ||
| 1238 | |||
| 1239 | static Lisp_Object | ||
| 1240 | uniprop_encode_value_character (Lisp_Object table, Lisp_Object value) | ||
| 1241 | { | ||
| 1242 | if (! NILP (value) && ! CHARACTERP (value)) | ||
| 1243 | wrong_type_argument (Qintegerp, value); | ||
| 1244 | return value; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | |||
| 1248 | /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH | ||
| 1249 | compression. */ | ||
| 1250 | |||
| 1251 | static Lisp_Object | ||
| 1252 | uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value) | ||
| 1253 | { | ||
| 1254 | Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents; | ||
| 1255 | int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]); | ||
| 1256 | |||
| 1257 | for (i = 0; i < size; i++) | ||
| 1258 | if (EQ (value, value_table[i])) | ||
| 1259 | break; | ||
| 1260 | if (i == size) | ||
| 1261 | wrong_type_argument (build_string ("Unicode property value"), value); | ||
| 1262 | return make_number (i); | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | |||
| 1266 | /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH | ||
| 1267 | compression and contains numbers as elements . */ | ||
| 1268 | |||
| 1269 | static Lisp_Object | ||
| 1270 | uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value) | ||
| 1271 | { | ||
| 1272 | Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents; | ||
| 1273 | int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]); | ||
| 1274 | |||
| 1275 | CHECK_NUMBER (value); | ||
| 1276 | for (i = 0; i < size; i++) | ||
| 1277 | if (EQ (value, value_table[i])) | ||
| 1278 | break; | ||
| 1279 | value = make_number (i); | ||
| 1280 | if (i == size) | ||
| 1281 | { | ||
| 1282 | Lisp_Object args[2]; | ||
| 1283 | |||
| 1284 | args[0] = XCHAR_TABLE (table)->extras[4]; | ||
| 1285 | args[1] = Fmake_vector (make_number (1), value); | ||
| 1286 | XCHAR_TABLE (table)->extras[4] = Fvconcat (2, args); | ||
| 1287 | } | ||
| 1288 | return make_number (i); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | static uniprop_encoder_t uniprop_encoder[] = | ||
| 1292 | { uniprop_encode_value_character, | ||
| 1293 | uniprop_encode_value_run_length, | ||
| 1294 | uniprop_encode_value_numeric }; | ||
| 1295 | |||
| 1296 | static int uniprop_encoder_count | ||
| 1297 | = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]); | ||
| 1298 | |||
| 1299 | |||
| 1300 | /* Return the encoder of char-table TABLE or nil if none. */ | ||
| 1301 | |||
| 1302 | static uniprop_decoder_t | ||
| 1303 | uniprop_get_encoder (Lisp_Object table) | ||
| 1304 | { | ||
| 1305 | int i; | ||
| 1306 | |||
| 1307 | if (! INTEGERP (XCHAR_TABLE (table)->extras[2])) | ||
| 1308 | return NULL; | ||
| 1309 | i = XINT (XCHAR_TABLE (table)->extras[2]); | ||
| 1310 | if (i < 0 || i >= uniprop_encoder_count) | ||
| 1311 | return NULL; | ||
| 1312 | return uniprop_encoder[i]; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | /* Return a char-table for Unicode character property PROP. This | ||
| 1316 | function may load a Lisp file and thus may cause | ||
| 1317 | garbage-collection. */ | ||
| 1318 | |||
| 1319 | Lisp_Object | ||
| 1320 | uniprop_table (Lisp_Object prop) | ||
| 1321 | { | ||
| 1322 | Lisp_Object val, table, result; | ||
| 1323 | |||
| 1324 | val = Fassq (prop, Vchar_code_property_alist); | ||
| 1325 | if (! CONSP (val)) | ||
| 1326 | return Qnil; | ||
| 1327 | table = XCDR (val); | ||
| 1328 | if (STRINGP (table)) | ||
| 1329 | { | ||
| 1330 | struct gcpro gcpro1; | ||
| 1331 | GCPRO1 (val); | ||
| 1332 | result = Fload (concat2 (build_string ("international/"), table), | ||
| 1333 | Qt, Qt, Qt, Qt); | ||
| 1334 | UNGCPRO; | ||
| 1335 | if (NILP (result)) | ||
| 1336 | return Qnil; | ||
| 1337 | table = XCDR (val); | ||
| 1338 | } | ||
| 1339 | if (! CHAR_TABLE_P (table) | ||
| 1340 | || ! UNIPROP_TABLE_P (table)) | ||
| 1341 | return Qnil; | ||
| 1342 | val = XCHAR_TABLE (table)->extras[1]; | ||
| 1343 | if (INTEGERP (val) | ||
| 1344 | ? (XINT (val) < 0 || XINT (val) >= uniprop_decoder_count) | ||
| 1345 | : ! NILP (val)) | ||
| 1346 | return Qnil; | ||
| 1347 | /* Prepare ASCII values in advance for CHAR_TABLE_REF. */ | ||
| 1348 | XCHAR_TABLE (table)->ascii = char_table_ascii (table); | ||
| 1349 | return table; | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | DEFUN ("unicode-property-table-internal", Funicode_property_table_internal, | ||
| 1353 | Sunicode_property_table_internal, 1, 1, 0, | ||
| 1354 | doc: /* Return a char-table for Unicode character property PROP. | ||
| 1355 | Use `get-unicode-property-internal' and | ||
| 1356 | `put-unicode-property-internal' instead of `aref' and `aset' to get | ||
| 1357 | and put an element value. */) | ||
| 1358 | (Lisp_Object prop) | ||
| 1359 | { | ||
| 1360 | Lisp_Object table = uniprop_table (prop); | ||
| 1361 | |||
| 1362 | if (CHAR_TABLE_P (table)) | ||
| 1363 | return table; | ||
| 1364 | return Fcdr (Fassq (prop, Vchar_code_property_alist)); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal, | ||
| 1368 | Sget_unicode_property_internal, 2, 2, 0, | ||
| 1369 | doc: /* Return an element of CHAR-TABLE for character CH. | ||
| 1370 | CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) | ||
| 1371 | (Lisp_Object char_table, Lisp_Object ch) | ||
| 1372 | { | ||
| 1373 | Lisp_Object val; | ||
| 1374 | uniprop_decoder_t decoder; | ||
| 1375 | |||
| 1376 | CHECK_CHAR_TABLE (char_table); | ||
| 1377 | CHECK_CHARACTER (ch); | ||
| 1378 | if (! UNIPROP_TABLE_P (char_table)) | ||
| 1379 | error ("Invalid Unicode property table"); | ||
| 1380 | val = CHAR_TABLE_REF (char_table, XINT (ch)); | ||
| 1381 | decoder = uniprop_get_decoder (char_table); | ||
| 1382 | return (decoder ? decoder (char_table, val) : val); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal, | ||
| 1386 | Sput_unicode_property_internal, 3, 3, 0, | ||
| 1387 | doc: /* Set an element of CHAR-TABLE for character CH to VALUE. | ||
| 1388 | CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) | ||
| 1389 | (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value) | ||
| 1390 | { | ||
| 1391 | uniprop_encoder_t encoder; | ||
| 1392 | |||
| 1393 | CHECK_CHAR_TABLE (char_table); | ||
| 1394 | CHECK_CHARACTER (ch); | ||
| 1395 | if (! UNIPROP_TABLE_P (char_table)) | ||
| 1396 | error ("Invalid Unicode property table"); | ||
| 1397 | encoder = uniprop_get_encoder (char_table); | ||
| 1398 | if (encoder) | ||
| 1399 | value = encoder (char_table, value); | ||
| 1400 | CHAR_TABLE_SET (char_table, XINT (ch), value); | ||
| 1401 | return Qnil; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | |||
| 987 | void | 1405 | void |
| 988 | syms_of_chartab (void) | 1406 | syms_of_chartab (void) |
| 989 | { | 1407 | { |
| 1408 | DEFSYM (Qchar_code_property_table, "char-code-property-table"); | ||
| 1409 | |||
| 990 | defsubr (&Smake_char_table); | 1410 | defsubr (&Smake_char_table); |
| 991 | defsubr (&Schar_table_parent); | 1411 | defsubr (&Schar_table_parent); |
| 992 | defsubr (&Schar_table_subtype); | 1412 | defsubr (&Schar_table_subtype); |
| @@ -998,4 +1418,19 @@ syms_of_chartab (void) | |||
| 998 | defsubr (&Sset_char_table_default); | 1418 | defsubr (&Sset_char_table_default); |
| 999 | defsubr (&Soptimize_char_table); | 1419 | defsubr (&Soptimize_char_table); |
| 1000 | defsubr (&Smap_char_table); | 1420 | defsubr (&Smap_char_table); |
| 1421 | defsubr (&Sunicode_property_table_internal); | ||
| 1422 | defsubr (&Sget_unicode_property_internal); | ||
| 1423 | defsubr (&Sput_unicode_property_internal); | ||
| 1424 | |||
| 1425 | /* Each element has the form (PROP . TABLE). | ||
| 1426 | PROP is a symbol representing a character property. | ||
| 1427 | TABLE is a char-table containing the property value for each character. | ||
| 1428 | TABLE may be a name of file to load to build a char-table. | ||
| 1429 | This variable should be modified only through | ||
| 1430 | `define-char-code-property'. */ | ||
| 1431 | |||
| 1432 | DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist, | ||
| 1433 | doc: /* Alist of character property name vs char-table containing property values. | ||
| 1434 | Internal use only. */); | ||
| 1435 | Vchar_code_property_alist = Qnil; | ||
| 1001 | } | 1436 | } |
diff --git a/src/composite.c b/src/composite.c index 796c5a58de6..7123b505e68 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -976,9 +976,8 @@ static int _work_char; | |||
| 976 | ((C) > ' ' \ | 976 | ((C) > ' ' \ |
| 977 | && ((C) == 0x200C || (C) == 0x200D \ | 977 | && ((C) == 0x200C || (C) == 0x200D \ |
| 978 | || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ | 978 | || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ |
| 979 | (SYMBOLP (_work_val) \ | 979 | (INTEGERP (_work_val) \ |
| 980 | && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \ | 980 | && (XINT (_work_val) <= UNICODE_CATEGORY_So))))) |
| 981 | && _work_char != 'Z')))) | ||
| 982 | 981 | ||
| 983 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and | 982 | /* Update cmp_it->stop_pos to the next position after CHARPOS (and |
| 984 | BYTEPOS) where character composition may happen. If BYTEPOS is | 983 | BYTEPOS) where character composition may happen. If BYTEPOS is |
diff --git a/src/dispextern.h b/src/dispextern.h index 57fa09d3bfc..c0a67690a5c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1773,7 +1773,11 @@ extern int face_change_count; | |||
| 1773 | /* Data type for describing the bidirectional character types. The | 1773 | /* Data type for describing the bidirectional character types. The |
| 1774 | first 7 must be at the beginning, because they are the only values | 1774 | first 7 must be at the beginning, because they are the only values |
| 1775 | valid in the `bidi_type' member of `struct glyph'; we only reserve | 1775 | valid in the `bidi_type' member of `struct glyph'; we only reserve |
| 1776 | 3 bits for it, so we cannot use there values larger than 7. */ | 1776 | 3 bits for it, so we cannot use there values larger than 7. |
| 1777 | |||
| 1778 | The order of members must be in sync with the 8th element of the | ||
| 1779 | member of unidata-prop-alist (in admin/unidata/unidata-getn.el) for | ||
| 1780 | Unicode character property `bidi-class'. */ | ||
| 1777 | typedef enum { | 1781 | typedef enum { |
| 1778 | UNKNOWN_BT = 0, | 1782 | UNKNOWN_BT = 0, |
| 1779 | STRONG_L, /* strong left-to-right */ | 1783 | STRONG_L, /* strong left-to-right */ |
diff --git a/src/font.c b/src/font.c index 14390335f3c..5aff20b1346 100644 --- a/src/font.c +++ b/src/font.c | |||
| @@ -3739,8 +3739,9 @@ font_range (EMACS_INT pos, EMACS_INT *limit, struct window *w, struct face *face | |||
| 3739 | else | 3739 | else |
| 3740 | FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte); | 3740 | FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte); |
| 3741 | category = CHAR_TABLE_REF (Vunicode_category_table, c); | 3741 | category = CHAR_TABLE_REF (Vunicode_category_table, c); |
| 3742 | if (EQ (category, QCf) | 3742 | if (INTEGERP (category) |
| 3743 | || CHAR_VARIATION_SELECTOR_P (c)) | 3743 | && (XINT (category) == UNICODE_CATEGORY_Cf |
| 3744 | || CHAR_VARIATION_SELECTOR_P (c))) | ||
| 3744 | continue; | 3745 | continue; |
| 3745 | if (NILP (font_object)) | 3746 | if (NILP (font_object)) |
| 3746 | { | 3747 | { |