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