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