]> code.delx.au - gnu-emacs/blob - src/chartab.c
Merge from origin/emacs-24
[gnu-emacs] / src / chartab.c
1 /* chartab.c -- char-table support
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H13PRO009
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22
23 #include "lisp.h"
24 #include "character.h"
25 #include "charset.h"
26 #include "ccl.h"
27
28 /* 64/16/32/128 */
29
30 /* Number of elements in Nth level char-table. */
31 const int chartab_size[4] =
32 { (1 << CHARTAB_SIZE_BITS_0),
33 (1 << CHARTAB_SIZE_BITS_1),
34 (1 << CHARTAB_SIZE_BITS_2),
35 (1 << CHARTAB_SIZE_BITS_3) };
36
37 /* Number of characters each element of Nth level char-table
38 covers. */
39 static const int chartab_chars[4] =
40 { (1 << (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
41 (1 << (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
42 (1 << CHARTAB_SIZE_BITS_3),
43 1 };
44
45 /* Number of characters (in bits) each element of Nth level char-table
46 covers. */
47 static const int chartab_bits[4] =
48 { (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
49 (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
50 CHARTAB_SIZE_BITS_3,
51 0 };
52
53 #define CHARTAB_IDX(c, depth, min_char) \
54 (((c) - (min_char)) >> chartab_bits[(depth)])
55
56 \f
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)
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 static void
88 CHECK_CHAR_TABLE (Lisp_Object x)
89 {
90 CHECK_TYPE (CHAR_TABLE_P (x), Qchar_table_p, x);
91 }
92
93 static void
94 set_char_table_ascii (Lisp_Object table, Lisp_Object val)
95 {
96 XCHAR_TABLE (table)->ascii = val;
97 }
98 static void
99 set_char_table_parent (Lisp_Object table, Lisp_Object val)
100 {
101 XCHAR_TABLE (table)->parent = val;
102 }
103 \f
104 DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
105 doc: /* Return a newly created char-table, with purpose PURPOSE.
106 Each element is initialized to INIT, which defaults to nil.
107
108 PURPOSE should be a symbol. If it has a `char-table-extra-slots'
109 property, the property's value should be an integer between 0 and 10
110 that specifies how many extra slots the char-table has. Otherwise,
111 the char-table has no extra slot. */)
112 (register Lisp_Object purpose, Lisp_Object init)
113 {
114 Lisp_Object vector;
115 Lisp_Object n;
116 int n_extras;
117 int size;
118
119 CHECK_SYMBOL (purpose);
120 n = Fget (purpose, Qchar_table_extra_slots);
121 if (NILP (n))
122 n_extras = 0;
123 else
124 {
125 CHECK_NATNUM (n);
126 if (XINT (n) > 10)
127 args_out_of_range (n, Qnil);
128 n_extras = XINT (n);
129 }
130
131 size = CHAR_TABLE_STANDARD_SLOTS + n_extras;
132 vector = Fmake_vector (make_number (size), init);
133 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
134 set_char_table_parent (vector, Qnil);
135 set_char_table_purpose (vector, purpose);
136 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
137 return vector;
138 }
139
140 static Lisp_Object
141 make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
142 {
143 int i;
144 Lisp_Object table = make_uninit_sub_char_table (depth, min_char);
145
146 for (i = 0; i < chartab_size[depth]; i++)
147 XSUB_CHAR_TABLE (table)->contents[i] = defalt;
148 return table;
149 }
150
151 static Lisp_Object
152 char_table_ascii (Lisp_Object table)
153 {
154 Lisp_Object sub, val;
155
156 sub = XCHAR_TABLE (table)->contents[0];
157 if (! SUB_CHAR_TABLE_P (sub))
158 return sub;
159 sub = XSUB_CHAR_TABLE (sub)->contents[0];
160 if (! SUB_CHAR_TABLE_P (sub))
161 return sub;
162 val = XSUB_CHAR_TABLE (sub)->contents[0];
163 if (UNIPROP_TABLE_P (table) && UNIPROP_COMPRESSED_FORM_P (val))
164 val = uniprop_table_uncompress (sub, 0);
165 return val;
166 }
167
168 static Lisp_Object
169 copy_sub_char_table (Lisp_Object table)
170 {
171 int depth = XSUB_CHAR_TABLE (table)->depth;
172 int min_char = XSUB_CHAR_TABLE (table)->min_char;
173 Lisp_Object copy = make_sub_char_table (depth, min_char, Qnil);
174 int i;
175
176 /* Recursively copy any sub char-tables. */
177 for (i = 0; i < chartab_size[depth]; i++)
178 {
179 Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[i];
180 set_sub_char_table_contents
181 (copy, i, SUB_CHAR_TABLE_P (val) ? copy_sub_char_table (val) : val);
182 }
183
184 return copy;
185 }
186
187
188 Lisp_Object
189 copy_char_table (Lisp_Object table)
190 {
191 Lisp_Object copy;
192 int size = XCHAR_TABLE (table)->header.size & PSEUDOVECTOR_SIZE_MASK;
193 int i;
194
195 copy = Fmake_vector (make_number (size), Qnil);
196 XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE);
197 set_char_table_defalt (copy, XCHAR_TABLE (table)->defalt);
198 set_char_table_parent (copy, XCHAR_TABLE (table)->parent);
199 set_char_table_purpose (copy, XCHAR_TABLE (table)->purpose);
200 for (i = 0; i < chartab_size[0]; i++)
201 set_char_table_contents
202 (copy, i,
203 (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
204 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
205 : XCHAR_TABLE (table)->contents[i]));
206 set_char_table_ascii (copy, char_table_ascii (copy));
207 size -= CHAR_TABLE_STANDARD_SLOTS;
208 for (i = 0; i < size; i++)
209 set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]);
210
211 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
212 return copy;
213 }
214
215 static Lisp_Object
216 sub_char_table_ref (Lisp_Object table, int c, bool is_uniprop)
217 {
218 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
219 Lisp_Object val;
220 int idx = CHARTAB_IDX (c, tbl->depth, tbl->min_char);
221
222 val = tbl->contents[idx];
223 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
224 val = uniprop_table_uncompress (table, idx);
225 if (SUB_CHAR_TABLE_P (val))
226 val = sub_char_table_ref (val, c, is_uniprop);
227 return val;
228 }
229
230 Lisp_Object
231 char_table_ref (Lisp_Object table, int c)
232 {
233 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
234 Lisp_Object val;
235
236 if (ASCII_CHAR_P (c))
237 {
238 val = tbl->ascii;
239 if (SUB_CHAR_TABLE_P (val))
240 val = XSUB_CHAR_TABLE (val)->contents[c];
241 }
242 else
243 {
244 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
245 if (SUB_CHAR_TABLE_P (val))
246 val = sub_char_table_ref (val, c, UNIPROP_TABLE_P (table));
247 }
248 if (NILP (val))
249 {
250 val = tbl->defalt;
251 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
252 val = char_table_ref (tbl->parent, c);
253 }
254 return val;
255 }
256
257 static Lisp_Object
258 sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to,
259 Lisp_Object defalt, bool is_uniprop)
260 {
261 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
262 int depth = tbl->depth, min_char = tbl->min_char;
263 int chartab_idx = CHARTAB_IDX (c, depth, min_char), idx;
264 Lisp_Object val;
265
266 val = tbl->contents[chartab_idx];
267 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
268 val = uniprop_table_uncompress (table, chartab_idx);
269 if (SUB_CHAR_TABLE_P (val))
270 val = sub_char_table_ref_and_range (val, c, from, to, defalt, is_uniprop);
271 else if (NILP (val))
272 val = defalt;
273
274 idx = chartab_idx;
275 while (idx > 0 && *from < min_char + idx * chartab_chars[depth])
276 {
277 Lisp_Object this_val;
278
279 c = min_char + idx * chartab_chars[depth] - 1;
280 idx--;
281 this_val = tbl->contents[idx];
282 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
283 this_val = uniprop_table_uncompress (table, idx);
284 if (SUB_CHAR_TABLE_P (this_val))
285 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt,
286 is_uniprop);
287 else if (NILP (this_val))
288 this_val = defalt;
289
290 if (! EQ (this_val, val))
291 {
292 *from = c + 1;
293 break;
294 }
295 }
296 while (((c = (chartab_idx + 1) * chartab_chars[depth])
297 < chartab_chars[depth - 1])
298 && (c += min_char) <= *to)
299 {
300 Lisp_Object this_val;
301
302 chartab_idx++;
303 this_val = tbl->contents[chartab_idx];
304 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
305 this_val = uniprop_table_uncompress (table, chartab_idx);
306 if (SUB_CHAR_TABLE_P (this_val))
307 this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt,
308 is_uniprop);
309 else if (NILP (this_val))
310 this_val = defalt;
311 if (! EQ (this_val, val))
312 {
313 *to = c - 1;
314 break;
315 }
316 }
317
318 return val;
319 }
320
321
322 /* Return the value for C in char-table TABLE. Shrink the range *FROM
323 and *TO to cover characters (containing C) that have the same value
324 as C. It is not assured that the values of (*FROM - 1) and (*TO +
325 1) are different from that of C. */
326
327 Lisp_Object
328 char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to)
329 {
330 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
331 int chartab_idx = CHARTAB_IDX (c, 0, 0), idx;
332 Lisp_Object val;
333 bool is_uniprop = UNIPROP_TABLE_P (table);
334
335 val = tbl->contents[chartab_idx];
336 if (*from < 0)
337 *from = 0;
338 if (*to < 0)
339 *to = MAX_CHAR;
340 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val))
341 val = uniprop_table_uncompress (table, chartab_idx);
342 if (SUB_CHAR_TABLE_P (val))
343 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt,
344 is_uniprop);
345 else if (NILP (val))
346 val = tbl->defalt;
347 idx = chartab_idx;
348 while (*from < idx * chartab_chars[0])
349 {
350 Lisp_Object this_val;
351
352 c = idx * chartab_chars[0] - 1;
353 idx--;
354 this_val = tbl->contents[idx];
355 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
356 this_val = uniprop_table_uncompress (table, idx);
357 if (SUB_CHAR_TABLE_P (this_val))
358 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
359 tbl->defalt, is_uniprop);
360 else if (NILP (this_val))
361 this_val = tbl->defalt;
362
363 if (! EQ (this_val, val))
364 {
365 *from = c + 1;
366 break;
367 }
368 }
369 while (*to >= (chartab_idx + 1) * chartab_chars[0])
370 {
371 Lisp_Object this_val;
372
373 chartab_idx++;
374 c = chartab_idx * chartab_chars[0];
375 this_val = tbl->contents[chartab_idx];
376 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val))
377 this_val = uniprop_table_uncompress (table, chartab_idx);
378 if (SUB_CHAR_TABLE_P (this_val))
379 this_val = sub_char_table_ref_and_range (this_val, c, from, to,
380 tbl->defalt, is_uniprop);
381 else if (NILP (this_val))
382 this_val = tbl->defalt;
383 if (! EQ (this_val, val))
384 {
385 *to = c - 1;
386 break;
387 }
388 }
389
390 return val;
391 }
392
393
394 static void
395 sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, bool is_uniprop)
396 {
397 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
398 int depth = tbl->depth, min_char = tbl->min_char;
399 int i = CHARTAB_IDX (c, depth, min_char);
400 Lisp_Object sub;
401
402 if (depth == 3)
403 set_sub_char_table_contents (table, i, val);
404 else
405 {
406 sub = tbl->contents[i];
407 if (! SUB_CHAR_TABLE_P (sub))
408 {
409 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub))
410 sub = uniprop_table_uncompress (table, i);
411 else
412 {
413 sub = make_sub_char_table (depth + 1,
414 min_char + i * chartab_chars[depth],
415 sub);
416 set_sub_char_table_contents (table, i, sub);
417 }
418 }
419 sub_char_table_set (sub, c, val, is_uniprop);
420 }
421 }
422
423 void
424 char_table_set (Lisp_Object table, int c, Lisp_Object val)
425 {
426 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
427
428 if (ASCII_CHAR_P (c)
429 && SUB_CHAR_TABLE_P (tbl->ascii))
430 set_sub_char_table_contents (tbl->ascii, c, val);
431 else
432 {
433 int i = CHARTAB_IDX (c, 0, 0);
434 Lisp_Object sub;
435
436 sub = tbl->contents[i];
437 if (! SUB_CHAR_TABLE_P (sub))
438 {
439 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
440 set_char_table_contents (table, i, sub);
441 }
442 sub_char_table_set (sub, c, val, UNIPROP_TABLE_P (table));
443 if (ASCII_CHAR_P (c))
444 set_char_table_ascii (table, char_table_ascii (table));
445 }
446 }
447
448 static void
449 sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val,
450 bool is_uniprop)
451 {
452 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
453 int depth = tbl->depth, min_char = tbl->min_char;
454 int chars_in_block = chartab_chars[depth];
455 int i, c, lim = chartab_size[depth];
456
457 if (from < min_char)
458 from = min_char;
459 i = CHARTAB_IDX (from, depth, min_char);
460 c = min_char + chars_in_block * i;
461 for (; i < lim; i++, c += chars_in_block)
462 {
463 if (c > to)
464 break;
465 if (from <= c && c + chars_in_block - 1 <= to)
466 set_sub_char_table_contents (table, i, val);
467 else
468 {
469 Lisp_Object sub = tbl->contents[i];
470 if (! SUB_CHAR_TABLE_P (sub))
471 {
472 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub))
473 sub = uniprop_table_uncompress (table, i);
474 else
475 {
476 sub = make_sub_char_table (depth + 1, c, sub);
477 set_sub_char_table_contents (table, i, sub);
478 }
479 }
480 sub_char_table_set_range (sub, from, to, val, is_uniprop);
481 }
482 }
483 }
484
485
486 void
487 char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val)
488 {
489 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
490
491 if (from == to)
492 char_table_set (table, from, val);
493 else
494 {
495 bool is_uniprop = UNIPROP_TABLE_P (table);
496 int lim = CHARTAB_IDX (to, 0, 0);
497 int i, c;
498
499 for (i = CHARTAB_IDX (from, 0, 0), c = 0; i <= lim;
500 i++, c += chartab_chars[0])
501 {
502 if (c > to)
503 break;
504 if (from <= c && c + chartab_chars[0] - 1 <= to)
505 set_char_table_contents (table, i, val);
506 else
507 {
508 Lisp_Object sub = tbl->contents[i];
509 if (! SUB_CHAR_TABLE_P (sub))
510 {
511 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
512 set_char_table_contents (table, i, sub);
513 }
514 sub_char_table_set_range (sub, from, to, val, is_uniprop);
515 }
516 }
517 if (ASCII_CHAR_P (from))
518 set_char_table_ascii (table, char_table_ascii (table));
519 }
520 }
521
522 \f
523 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
524 1, 1, 0,
525 doc: /*
526 Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
527 (Lisp_Object char_table)
528 {
529 CHECK_CHAR_TABLE (char_table);
530
531 return XCHAR_TABLE (char_table)->purpose;
532 }
533
534 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
535 1, 1, 0,
536 doc: /* Return the parent char-table of CHAR-TABLE.
537 The value is either nil or another char-table.
538 If CHAR-TABLE holds nil for a given character,
539 then the actual applicable value is inherited from the parent char-table
540 \(or from its parents, if necessary). */)
541 (Lisp_Object char_table)
542 {
543 CHECK_CHAR_TABLE (char_table);
544
545 return XCHAR_TABLE (char_table)->parent;
546 }
547
548 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
549 2, 2, 0,
550 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
551 Return PARENT. PARENT must be either nil or another char-table. */)
552 (Lisp_Object char_table, Lisp_Object parent)
553 {
554 Lisp_Object temp;
555
556 CHECK_CHAR_TABLE (char_table);
557
558 if (!NILP (parent))
559 {
560 CHECK_CHAR_TABLE (parent);
561
562 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
563 if (EQ (temp, char_table))
564 error ("Attempt to make a chartable be its own parent");
565 }
566
567 set_char_table_parent (char_table, parent);
568
569 return parent;
570 }
571
572 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
573 2, 2, 0,
574 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
575 (Lisp_Object char_table, Lisp_Object n)
576 {
577 CHECK_CHAR_TABLE (char_table);
578 CHECK_NUMBER (n);
579 if (XINT (n) < 0
580 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
581 args_out_of_range (char_table, n);
582
583 return XCHAR_TABLE (char_table)->extras[XINT (n)];
584 }
585
586 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
587 Sset_char_table_extra_slot,
588 3, 3, 0,
589 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
590 (Lisp_Object char_table, Lisp_Object n, Lisp_Object value)
591 {
592 CHECK_CHAR_TABLE (char_table);
593 CHECK_NUMBER (n);
594 if (XINT (n) < 0
595 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
596 args_out_of_range (char_table, n);
597
598 set_char_table_extras (char_table, XINT (n), value);
599 return value;
600 }
601 \f
602 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
603 2, 2, 0,
604 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
605 RANGE should be nil (for the default value),
606 a cons of character codes (for characters in the range), or a character code. */)
607 (Lisp_Object char_table, Lisp_Object range)
608 {
609 Lisp_Object val;
610 CHECK_CHAR_TABLE (char_table);
611
612 if (EQ (range, Qnil))
613 val = XCHAR_TABLE (char_table)->defalt;
614 else if (CHARACTERP (range))
615 val = CHAR_TABLE_REF (char_table, XFASTINT (range));
616 else if (CONSP (range))
617 {
618 int from, to;
619
620 CHECK_CHARACTER_CAR (range);
621 CHECK_CHARACTER_CDR (range);
622 from = XFASTINT (XCAR (range));
623 to = XFASTINT (XCDR (range));
624 val = char_table_ref_and_range (char_table, from, &from, &to);
625 /* Not yet implemented. */
626 }
627 else
628 error ("Invalid RANGE argument to `char-table-range'");
629 return val;
630 }
631
632 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
633 3, 3, 0,
634 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
635 RANGE should be t (for all characters), nil (for the default value),
636 a cons of character codes (for characters in the range),
637 or a character code. Return VALUE. */)
638 (Lisp_Object char_table, Lisp_Object range, Lisp_Object value)
639 {
640 CHECK_CHAR_TABLE (char_table);
641 if (EQ (range, Qt))
642 {
643 int i;
644
645 set_char_table_ascii (char_table, value);
646 for (i = 0; i < chartab_size[0]; i++)
647 set_char_table_contents (char_table, i, value);
648 }
649 else if (EQ (range, Qnil))
650 set_char_table_defalt (char_table, value);
651 else if (CHARACTERP (range))
652 char_table_set (char_table, XINT (range), value);
653 else if (CONSP (range))
654 {
655 CHECK_CHARACTER_CAR (range);
656 CHECK_CHARACTER_CDR (range);
657 char_table_set_range (char_table,
658 XINT (XCAR (range)), XINT (XCDR (range)), value);
659 }
660 else
661 error ("Invalid RANGE argument to `set-char-table-range'");
662
663 return value;
664 }
665
666 static Lisp_Object
667 optimize_sub_char_table (Lisp_Object table, Lisp_Object test)
668 {
669 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
670 int i, depth = tbl->depth;
671 Lisp_Object elt, this;
672 bool optimizable;
673
674 elt = XSUB_CHAR_TABLE (table)->contents[0];
675 if (SUB_CHAR_TABLE_P (elt))
676 {
677 elt = optimize_sub_char_table (elt, test);
678 set_sub_char_table_contents (table, 0, elt);
679 }
680 optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1;
681 for (i = 1; i < chartab_size[depth]; i++)
682 {
683 this = XSUB_CHAR_TABLE (table)->contents[i];
684 if (SUB_CHAR_TABLE_P (this))
685 {
686 this = optimize_sub_char_table (this, test);
687 set_sub_char_table_contents (table, i, this);
688 }
689 if (optimizable
690 && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */
691 : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */
692 : NILP (call2 (test, this, elt))))
693 optimizable = 0;
694 }
695
696 return (optimizable ? elt : table);
697 }
698
699 DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
700 1, 2, 0,
701 doc: /* Optimize CHAR-TABLE.
702 TEST is the comparison function used to decide whether two entries are
703 equivalent and can be merged. It defaults to `equal'. */)
704 (Lisp_Object char_table, Lisp_Object test)
705 {
706 Lisp_Object elt;
707 int i;
708
709 CHECK_CHAR_TABLE (char_table);
710
711 for (i = 0; i < chartab_size[0]; i++)
712 {
713 elt = XCHAR_TABLE (char_table)->contents[i];
714 if (SUB_CHAR_TABLE_P (elt))
715 set_char_table_contents
716 (char_table, i, optimize_sub_char_table (elt, test));
717 }
718 /* Reset the `ascii' cache, in case it got optimized away. */
719 set_char_table_ascii (char_table, char_table_ascii (char_table));
720
721 return Qnil;
722 }
723
724 \f
725 /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
726 calling it for each character or group of characters that share a
727 value. RANGE is a cons (FROM . TO) specifying the range of target
728 characters, VAL is a value of FROM in TABLE, TOP is the top
729 char-table.
730
731 ARG is passed to C_FUNCTION when that is called.
732
733 It returns the value of last character covered by TABLE (not the
734 value inherited from the parent), and by side-effect, the car part
735 of RANGE is updated to the minimum character C where C and all the
736 following characters in TABLE have the same value. */
737
738 static Lisp_Object
739 map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
740 Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val,
741 Lisp_Object range, Lisp_Object top)
742 {
743 /* Depth of TABLE. */
744 int depth;
745 /* Minimum and maximum characters covered by TABLE. */
746 int min_char, max_char;
747 /* Number of characters covered by one element of TABLE. */
748 int chars_in_block;
749 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
750 int i, c;
751 bool is_uniprop = UNIPROP_TABLE_P (top);
752 uniprop_decoder_t decoder = UNIPROP_GET_DECODER (top);
753
754 if (SUB_CHAR_TABLE_P (table))
755 {
756 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
757
758 depth = tbl->depth;
759 min_char = tbl->min_char;
760 max_char = min_char + chartab_chars[depth - 1] - 1;
761 }
762 else
763 {
764 depth = 0;
765 min_char = 0;
766 max_char = MAX_CHAR;
767 }
768 chars_in_block = chartab_chars[depth];
769
770 if (to < max_char)
771 max_char = to;
772 /* Set I to the index of the first element to check. */
773 if (from <= min_char)
774 i = 0;
775 else
776 i = (from - min_char) / chars_in_block;
777 for (c = min_char + chars_in_block * i; c <= max_char;
778 i++, c += chars_in_block)
779 {
780 Lisp_Object this = (SUB_CHAR_TABLE_P (table)
781 ? XSUB_CHAR_TABLE (table)->contents[i]
782 : XCHAR_TABLE (table)->contents[i]);
783 int nextc = c + chars_in_block;
784
785 if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this))
786 this = uniprop_table_uncompress (table, i);
787 if (SUB_CHAR_TABLE_P (this))
788 {
789 if (to >= nextc)
790 XSETCDR (range, make_number (nextc - 1));
791 val = map_sub_char_table (c_function, function, this, arg,
792 val, range, top);
793 }
794 else
795 {
796 if (NILP (this))
797 this = XCHAR_TABLE (top)->defalt;
798 if (!EQ (val, this))
799 {
800 bool different_value = 1;
801
802 if (NILP (val))
803 {
804 if (! NILP (XCHAR_TABLE (top)->parent))
805 {
806 Lisp_Object parent = XCHAR_TABLE (top)->parent;
807 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
808
809 /* This is to get a value of FROM in PARENT
810 without checking the parent of PARENT. */
811 set_char_table_parent (parent, Qnil);
812 val = CHAR_TABLE_REF (parent, from);
813 set_char_table_parent (parent, temp);
814 XSETCDR (range, make_number (c - 1));
815 val = map_sub_char_table (c_function, function,
816 parent, arg, val, range,
817 parent);
818 if (EQ (val, this))
819 different_value = 0;
820 }
821 }
822 if (! NILP (val) && different_value)
823 {
824 XSETCDR (range, make_number (c - 1));
825 if (EQ (XCAR (range), XCDR (range)))
826 {
827 if (c_function)
828 (*c_function) (arg, XCAR (range), val);
829 else
830 {
831 if (decoder)
832 val = decoder (top, val);
833 call2 (function, XCAR (range), val);
834 }
835 }
836 else
837 {
838 if (c_function)
839 (*c_function) (arg, range, val);
840 else
841 {
842 if (decoder)
843 val = decoder (top, val);
844 call2 (function, range, val);
845 }
846 }
847 }
848 val = this;
849 from = c;
850 XSETCAR (range, make_number (c));
851 }
852 }
853 XSETCDR (range, make_number (to));
854 }
855 return val;
856 }
857
858
859 /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
860 character or group of characters that share a value.
861
862 ARG is passed to C_FUNCTION when that is called. */
863
864 void
865 map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object),
866 Lisp_Object function, Lisp_Object table, Lisp_Object arg)
867 {
868 Lisp_Object range, val, parent;
869 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
870 uniprop_decoder_t decoder = UNIPROP_GET_DECODER (table);
871
872 range = Fcons (make_number (0), make_number (MAX_CHAR));
873 parent = XCHAR_TABLE (table)->parent;
874
875 GCPRO4 (table, arg, range, parent);
876 val = XCHAR_TABLE (table)->ascii;
877 if (SUB_CHAR_TABLE_P (val))
878 val = XSUB_CHAR_TABLE (val)->contents[0];
879 val = map_sub_char_table (c_function, function, table, arg, val, range,
880 table);
881
882 /* If VAL is nil and TABLE has a parent, we must consult the parent
883 recursively. */
884 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
885 {
886 Lisp_Object temp;
887 int from = XINT (XCAR (range));
888
889 parent = XCHAR_TABLE (table)->parent;
890 temp = XCHAR_TABLE (parent)->parent;
891 /* This is to get a value of FROM in PARENT without checking the
892 parent of PARENT. */
893 set_char_table_parent (parent, Qnil);
894 val = CHAR_TABLE_REF (parent, from);
895 set_char_table_parent (parent, temp);
896 val = map_sub_char_table (c_function, function, parent, arg, val, range,
897 parent);
898 table = parent;
899 }
900
901 if (! NILP (val))
902 {
903 if (EQ (XCAR (range), XCDR (range)))
904 {
905 if (c_function)
906 (*c_function) (arg, XCAR (range), val);
907 else
908 {
909 if (decoder)
910 val = decoder (table, val);
911 call2 (function, XCAR (range), val);
912 }
913 }
914 else
915 {
916 if (c_function)
917 (*c_function) (arg, range, val);
918 else
919 {
920 if (decoder)
921 val = decoder (table, val);
922 call2 (function, range, val);
923 }
924 }
925 }
926
927 UNGCPRO;
928 }
929
930 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
931 2, 2, 0,
932 doc: /* Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
933 FUNCTION is called with two arguments, KEY and VALUE.
934 KEY is a character code or a cons of character codes specifying a
935 range of characters that have the same value.
936 VALUE is what (char-table-range CHAR-TABLE KEY) returns. */)
937 (Lisp_Object function, Lisp_Object char_table)
938 {
939 CHECK_CHAR_TABLE (char_table);
940
941 map_char_table (NULL, function, char_table, char_table);
942 return Qnil;
943 }
944
945
946 static void
947 map_sub_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
948 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
949 Lisp_Object range, struct charset *charset,
950 unsigned from, unsigned to)
951 {
952 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
953 int i, c = tbl->min_char, depth = tbl->depth;
954
955 if (depth < 3)
956 for (i = 0; i < chartab_size[depth]; i++, c += chartab_chars[depth])
957 {
958 Lisp_Object this;
959
960 this = tbl->contents[i];
961 if (SUB_CHAR_TABLE_P (this))
962 map_sub_char_table_for_charset (c_function, function, this, arg,
963 range, charset, from, to);
964 else
965 {
966 if (! NILP (XCAR (range)))
967 {
968 XSETCDR (range, make_number (c - 1));
969 if (c_function)
970 (*c_function) (arg, range);
971 else
972 call2 (function, range, arg);
973 }
974 XSETCAR (range, Qnil);
975 }
976 }
977 else
978 for (i = 0; i < chartab_size[depth]; i++, c++)
979 {
980 Lisp_Object this;
981 unsigned code;
982
983 this = tbl->contents[i];
984 if (NILP (this)
985 || (charset
986 && (code = ENCODE_CHAR (charset, c),
987 (code < from || code > to))))
988 {
989 if (! NILP (XCAR (range)))
990 {
991 XSETCDR (range, make_number (c - 1));
992 if (c_function)
993 (*c_function) (arg, range);
994 else
995 call2 (function, range, arg);
996 XSETCAR (range, Qnil);
997 }
998 }
999 else
1000 {
1001 if (NILP (XCAR (range)))
1002 XSETCAR (range, make_number (c));
1003 }
1004 }
1005 }
1006
1007
1008 /* Support function for `map-charset-chars'. Map C_FUNCTION or
1009 FUNCTION over TABLE, calling it for each character or a group of
1010 succeeding characters that have non-nil value in TABLE. TABLE is a
1011 "mapping table" or a "deunifier table" of a certain charset.
1012
1013 If CHARSET is not NULL (this is the case that `map-charset-chars'
1014 is called with non-nil FROM-CODE and TO-CODE), it is a charset who
1015 owns TABLE, and the function is called only on a character in the
1016 range FROM and TO. FROM and TO are not character codes, but code
1017 points of a character in CHARSET.
1018
1019 This function is called in these two cases:
1020
1021 (1) A charset has a mapping file name in :map property.
1022
1023 (2) A charset has an upper code space in :offset property and a
1024 mapping file name in :unify-map property. In this case, this
1025 function is called only for characters in the Unicode code space.
1026 Characters in upper code space are handled directly in
1027 map_charset_chars. */
1028
1029 void
1030 map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object),
1031 Lisp_Object function, Lisp_Object table, Lisp_Object arg,
1032 struct charset *charset,
1033 unsigned from, unsigned to)
1034 {
1035 Lisp_Object range;
1036 int c, i;
1037 struct gcpro gcpro1;
1038
1039 range = Fcons (Qnil, Qnil);
1040 GCPRO1 (range);
1041
1042 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
1043 {
1044 Lisp_Object this;
1045
1046 this = XCHAR_TABLE (table)->contents[i];
1047 if (SUB_CHAR_TABLE_P (this))
1048 map_sub_char_table_for_charset (c_function, function, this, arg,
1049 range, charset, from, to);
1050 else
1051 {
1052 if (! NILP (XCAR (range)))
1053 {
1054 XSETCDR (range, make_number (c - 1));
1055 if (c_function)
1056 (*c_function) (arg, range);
1057 else
1058 call2 (function, range, arg);
1059 }
1060 XSETCAR (range, Qnil);
1061 }
1062 }
1063 if (! NILP (XCAR (range)))
1064 {
1065 XSETCDR (range, make_number (c - 1));
1066 if (c_function)
1067 (*c_function) (arg, range);
1068 else
1069 call2 (function, range, arg);
1070 }
1071
1072 UNGCPRO;
1073 }
1074
1075 \f
1076 /* Unicode character property tables.
1077
1078 This section provides a convenient and efficient way to get Unicode
1079 character properties of characters from C code (from Lisp, you must
1080 use get-char-code-property).
1081
1082 The typical usage is to get a char-table object for a specific
1083 property like this (use of the "bidi-class" property below is just
1084 an example):
1085
1086 Lisp_Object bidi_class_table = uniprop_table (intern ("bidi-class"));
1087
1088 (uniprop_table can return nil if it fails to find data for the
1089 named property, or if it fails to load the appropriate Lisp support
1090 file, so the return value should be tested to be non-nil, before it
1091 is used.)
1092
1093 To get a property value for character CH use CHAR_TABLE_REF:
1094
1095 Lisp_Object bidi_class = CHAR_TABLE_REF (bidi_class_table, CH);
1096
1097 In this case, what you actually get is an index number to the
1098 vector of property values (symbols nil, L, R, etc).
1099
1100 The full list of Unicode character properties supported by Emacs is
1101 documented in the ELisp manual, in the node "Character Properties".
1102
1103 A table for Unicode character property has these characteristics:
1104
1105 o The purpose is `char-code-property-table', which implies that the
1106 table has 5 extra slots.
1107
1108 o The second extra slot is a Lisp function, an index (integer) to
1109 the array uniprop_decoder[], or nil. If it is a Lisp function, we
1110 can't use such a table from C (at the moment). If it is nil, it
1111 means that we don't have to decode values.
1112
1113 o The third extra slot is a Lisp function, an index (integer) to
1114 the array uniprop_encoder[], or nil. If it is a Lisp function, we
1115 can't use such a table from C (at the moment). If it is nil, it
1116 means that we don't have to encode values. */
1117
1118
1119 /* Uncompress the IDXth element of sub-char-table TABLE. */
1120
1121 static Lisp_Object
1122 uniprop_table_uncompress (Lisp_Object table, int idx)
1123 {
1124 Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx];
1125 int min_char = XSUB_CHAR_TABLE (table)->min_char + chartab_chars[2] * idx;
1126 Lisp_Object sub = make_sub_char_table (3, min_char, Qnil);
1127 const unsigned char *p, *pend;
1128
1129 set_sub_char_table_contents (table, idx, sub);
1130 p = SDATA (val), pend = p + SBYTES (val);
1131 if (*p == 1)
1132 {
1133 /* SIMPLE TABLE */
1134 p++;
1135 idx = STRING_CHAR_ADVANCE (p);
1136 while (p < pend && idx < chartab_chars[2])
1137 {
1138 int v = STRING_CHAR_ADVANCE (p);
1139 set_sub_char_table_contents
1140 (sub, idx++, v > 0 ? make_number (v) : Qnil);
1141 }
1142 }
1143 else if (*p == 2)
1144 {
1145 /* RUN-LENGTH TABLE */
1146 p++;
1147 for (idx = 0; p < pend; )
1148 {
1149 int v = STRING_CHAR_ADVANCE (p);
1150 int count = 1;
1151 int len;
1152
1153 if (p < pend)
1154 {
1155 count = STRING_CHAR_AND_LENGTH (p, len);
1156 if (count < 128)
1157 count = 1;
1158 else
1159 {
1160 count -= 128;
1161 p += len;
1162 }
1163 }
1164 while (count-- > 0)
1165 set_sub_char_table_contents (sub, idx++, make_number (v));
1166 }
1167 }
1168 /* It seems that we don't need this function because C code won't need
1169 to get a property that is compressed in this form. */
1170 #if 0
1171 else if (*p == 0)
1172 {
1173 /* WORD-LIST TABLE */
1174 }
1175 #endif
1176 return sub;
1177 }
1178
1179
1180 /* Decode VALUE as an element of char-table TABLE. */
1181
1182 static Lisp_Object
1183 uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value)
1184 {
1185 if (VECTORP (XCHAR_TABLE (table)->extras[4]))
1186 {
1187 Lisp_Object valvec = XCHAR_TABLE (table)->extras[4];
1188
1189 if (XINT (value) >= 0 && XINT (value) < ASIZE (valvec))
1190 value = AREF (valvec, XINT (value));
1191 }
1192 return value;
1193 }
1194
1195 static uniprop_decoder_t uniprop_decoder [] =
1196 { uniprop_decode_value_run_length };
1197
1198 static const int uniprop_decoder_count = ARRAYELTS (uniprop_decoder);
1199
1200 /* Return the decoder of char-table TABLE or nil if none. */
1201
1202 static uniprop_decoder_t
1203 uniprop_get_decoder (Lisp_Object table)
1204 {
1205 EMACS_INT i;
1206
1207 if (! INTEGERP (XCHAR_TABLE (table)->extras[1]))
1208 return NULL;
1209 i = XINT (XCHAR_TABLE (table)->extras[1]);
1210 if (i < 0 || i >= uniprop_decoder_count)
1211 return NULL;
1212 return uniprop_decoder[i];
1213 }
1214
1215
1216 /* Encode VALUE as an element of char-table TABLE which contains
1217 characters as elements. */
1218
1219 static Lisp_Object
1220 uniprop_encode_value_character (Lisp_Object table, Lisp_Object value)
1221 {
1222 if (! NILP (value) && ! CHARACTERP (value))
1223 wrong_type_argument (Qintegerp, value);
1224 return value;
1225 }
1226
1227
1228 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1229 compression. */
1230
1231 static Lisp_Object
1232 uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value)
1233 {
1234 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1235 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1236
1237 for (i = 0; i < size; i++)
1238 if (EQ (value, value_table[i]))
1239 break;
1240 if (i == size)
1241 wrong_type_argument (build_string ("Unicode property value"), value);
1242 return make_number (i);
1243 }
1244
1245
1246 /* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH
1247 compression and contains numbers as elements. */
1248
1249 static Lisp_Object
1250 uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value)
1251 {
1252 Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents;
1253 int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]);
1254
1255 CHECK_NUMBER (value);
1256 for (i = 0; i < size; i++)
1257 if (EQ (value, value_table[i]))
1258 break;
1259 value = make_number (i);
1260 if (i == size)
1261 set_char_table_extras (table, 4, Fvconcat (2, ((Lisp_Object []) {
1262 XCHAR_TABLE (table)->extras[4], Fmake_vector (make_number (1), value) })));
1263 return make_number (i);
1264 }
1265
1266 static uniprop_encoder_t uniprop_encoder[] =
1267 { uniprop_encode_value_character,
1268 uniprop_encode_value_run_length,
1269 uniprop_encode_value_numeric };
1270
1271 static const int uniprop_encoder_count = ARRAYELTS (uniprop_encoder);
1272
1273 /* Return the encoder of char-table TABLE or nil if none. */
1274
1275 static uniprop_decoder_t
1276 uniprop_get_encoder (Lisp_Object table)
1277 {
1278 EMACS_INT i;
1279
1280 if (! INTEGERP (XCHAR_TABLE (table)->extras[2]))
1281 return NULL;
1282 i = XINT (XCHAR_TABLE (table)->extras[2]);
1283 if (i < 0 || i >= uniprop_encoder_count)
1284 return NULL;
1285 return uniprop_encoder[i];
1286 }
1287
1288 /* Return a char-table for Unicode character property PROP. This
1289 function may load a Lisp file and thus may cause
1290 garbage-collection. */
1291
1292 Lisp_Object
1293 uniprop_table (Lisp_Object prop)
1294 {
1295 Lisp_Object val, table, result;
1296
1297 val = Fassq (prop, Vchar_code_property_alist);
1298 if (! CONSP (val))
1299 return Qnil;
1300 table = XCDR (val);
1301 if (STRINGP (table))
1302 {
1303 struct gcpro gcpro1;
1304 GCPRO1 (val);
1305 AUTO_STRING (intl, "international/");
1306 result = Fload (concat2 (intl, table), Qt, Qt, Qt, Qt);
1307 UNGCPRO;
1308 if (NILP (result))
1309 return Qnil;
1310 table = XCDR (val);
1311 }
1312 if (! CHAR_TABLE_P (table)
1313 || ! UNIPROP_TABLE_P (table))
1314 return Qnil;
1315 val = XCHAR_TABLE (table)->extras[1];
1316 if (INTEGERP (val)
1317 ? (XINT (val) < 0 || XINT (val) >= uniprop_decoder_count)
1318 : ! NILP (val))
1319 return Qnil;
1320 /* Prepare ASCII values in advance for CHAR_TABLE_REF. */
1321 set_char_table_ascii (table, char_table_ascii (table));
1322 return table;
1323 }
1324
1325 DEFUN ("unicode-property-table-internal", Funicode_property_table_internal,
1326 Sunicode_property_table_internal, 1, 1, 0,
1327 doc: /* Return a char-table for Unicode character property PROP.
1328 Use `get-unicode-property-internal' and
1329 `put-unicode-property-internal' instead of `aref' and `aset' to get
1330 and put an element value. */)
1331 (Lisp_Object prop)
1332 {
1333 Lisp_Object table = uniprop_table (prop);
1334
1335 if (CHAR_TABLE_P (table))
1336 return table;
1337 return Fcdr (Fassq (prop, Vchar_code_property_alist));
1338 }
1339
1340 DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal,
1341 Sget_unicode_property_internal, 2, 2, 0,
1342 doc: /* Return an element of CHAR-TABLE for character CH.
1343 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1344 (Lisp_Object char_table, Lisp_Object ch)
1345 {
1346 Lisp_Object val;
1347 uniprop_decoder_t decoder;
1348
1349 CHECK_CHAR_TABLE (char_table);
1350 CHECK_CHARACTER (ch);
1351 if (! UNIPROP_TABLE_P (char_table))
1352 error ("Invalid Unicode property table");
1353 val = CHAR_TABLE_REF (char_table, XINT (ch));
1354 decoder = uniprop_get_decoder (char_table);
1355 return (decoder ? decoder (char_table, val) : val);
1356 }
1357
1358 DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal,
1359 Sput_unicode_property_internal, 3, 3, 0,
1360 doc: /* Set an element of CHAR-TABLE for character CH to VALUE.
1361 CHAR-TABLE must be what returned by `unicode-property-table-internal'. */)
1362 (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value)
1363 {
1364 uniprop_encoder_t encoder;
1365
1366 CHECK_CHAR_TABLE (char_table);
1367 CHECK_CHARACTER (ch);
1368 if (! UNIPROP_TABLE_P (char_table))
1369 error ("Invalid Unicode property table");
1370 encoder = uniprop_get_encoder (char_table);
1371 if (encoder)
1372 value = encoder (char_table, value);
1373 CHAR_TABLE_SET (char_table, XINT (ch), value);
1374 return Qnil;
1375 }
1376
1377 \f
1378 void
1379 syms_of_chartab (void)
1380 {
1381 DEFSYM (Qchar_code_property_table, "char-code-property-table");
1382
1383 defsubr (&Smake_char_table);
1384 defsubr (&Schar_table_parent);
1385 defsubr (&Schar_table_subtype);
1386 defsubr (&Sset_char_table_parent);
1387 defsubr (&Schar_table_extra_slot);
1388 defsubr (&Sset_char_table_extra_slot);
1389 defsubr (&Schar_table_range);
1390 defsubr (&Sset_char_table_range);
1391 defsubr (&Soptimize_char_table);
1392 defsubr (&Smap_char_table);
1393 defsubr (&Sunicode_property_table_internal);
1394 defsubr (&Sget_unicode_property_internal);
1395 defsubr (&Sput_unicode_property_internal);
1396
1397 /* Each element has the form (PROP . TABLE).
1398 PROP is a symbol representing a character property.
1399 TABLE is a char-table containing the property value for each character.
1400 TABLE may be a name of file to load to build a char-table.
1401 This variable should be modified only through
1402 `define-char-code-property'. */
1403
1404 DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist,
1405 doc: /* Alist of character property name vs char-table containing property values.
1406 Internal use only. */);
1407 Vchar_code_property_alist = Qnil;
1408 }