Update for font-backend changes.
[bpt/emacs.git] / src / chartab.c
CommitLineData
1ee5d538 1/* chartab.c -- char-table support
a9871c72 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
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
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
985773c9 10the Free Software Foundation; either version 3, or (at your option)
1ee5d538
KH
11any later version.
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
a9871c72
GM
19along with GNU Emacs; see the file COPYING. If not, write to the
20Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA. */
1ee5d538
KH
22
23#include <config.h>
b4a12c67
DL
24#include "lisp.h"
25#include "character.h"
26#include "charset.h"
27#include "ccl.h"
1ee5d538
KH
28
29/* 64/16/32/128 */
30
31/* Number of elements in Nth level char-table. */
32const int chartab_size[4] =
33 { (1 << CHARTAB_SIZE_BITS_0),
34 (1 << CHARTAB_SIZE_BITS_1),
35 (1 << CHARTAB_SIZE_BITS_2),
36 (1 << CHARTAB_SIZE_BITS_3) };
37
38/* Number of characters each element of Nth level char-table
39 covers. */
40const int chartab_chars[4] =
41 { (1 << (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
42 (1 << (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)),
43 (1 << CHARTAB_SIZE_BITS_3),
44 1 };
45
46/* Number of characters (in bits) each element of Nth level char-table
47 covers. */
48const int chartab_bits[4] =
49 { (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
50 (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3),
51 CHARTAB_SIZE_BITS_3,
52 0 };
53
54#define CHARTAB_IDX(c, depth, min_char) \
55 (((c) - (min_char)) >> chartab_bits[(depth)])
56
57
58DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0,
eaa3b0e0 59 doc: /* Return a newly created char-table, with purpose PURPOSE.
1ee5d538
KH
60Each element is initialized to INIT, which defaults to nil.
61
eaa3b0e0
KH
62PURPOSE should be a symbol. If it has a `char-table-extra-slots'
63property, the property's value should be an integer between 0 and 10
64that specifies how many extra slots the char-table has. Otherwise,
65the char-table has no extra slot. */)
1ee5d538
KH
66 (purpose, init)
67 register Lisp_Object purpose, init;
68{
69 Lisp_Object vector;
70 Lisp_Object n;
eaa3b0e0 71 int n_extras;
1ee5d538
KH
72 int size;
73
74 CHECK_SYMBOL (purpose);
eaa3b0e0
KH
75 n = Fget (purpose, Qchar_table_extra_slots);
76 if (NILP (n))
77 n_extras = 0;
78 else
1ee5d538 79 {
eaa3b0e0
KH
80 CHECK_NATNUM (n);
81 n_extras = XINT (n);
82 if (n_extras > 10)
83 args_out_of_range (n, Qnil);
1ee5d538
KH
84 }
85
86 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras;
87 vector = Fmake_vector (make_number (size), init);
985773c9 88 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
1ee5d538
KH
89 XCHAR_TABLE (vector)->parent = Qnil;
90 XCHAR_TABLE (vector)->purpose = purpose;
91 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
92 return vector;
93}
94
95static Lisp_Object
96make_sub_char_table (depth, min_char, defalt)
97 int depth, min_char;
98 Lisp_Object defalt;
99{
100 Lisp_Object table;
101 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
1ee5d538
KH
102
103 table = Fmake_vector (make_number (size), defalt);
985773c9 104 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE);
1ee5d538
KH
105 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
106 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
1ee5d538
KH
107
108 return table;
109}
110
111static Lisp_Object
112char_table_ascii (table)
113 Lisp_Object table;
114{
115 Lisp_Object sub;
116
117 sub = XCHAR_TABLE (table)->contents[0];
40033db7
KH
118 if (! SUB_CHAR_TABLE_P (sub))
119 return sub;
1ee5d538 120 sub = XSUB_CHAR_TABLE (sub)->contents[0];
40033db7
KH
121 if (! SUB_CHAR_TABLE_P (sub))
122 return sub;
1ee5d538
KH
123 return XSUB_CHAR_TABLE (sub)->contents[0];
124}
125
126Lisp_Object
127copy_sub_char_table (table)
128 Lisp_Object table;
129{
130 Lisp_Object copy;
131 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
132 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
133 Lisp_Object val;
134 int i;
135
136 copy = make_sub_char_table (depth, min_char, Qnil);
137 /* Recursively copy any sub char-tables. */
138 for (i = 0; i < chartab_size[depth]; i++)
139 {
140 val = XSUB_CHAR_TABLE (table)->contents[i];
141 if (SUB_CHAR_TABLE_P (val))
142 XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val);
143 else
144 XSUB_CHAR_TABLE (copy)->contents[i] = val;
145 }
146
147 return copy;
148}
149
150
151Lisp_Object
152copy_char_table (table)
153 Lisp_Object table;
154{
155 Lisp_Object copy;
156 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
157 int i;
158
159 copy = Fmake_vector (make_number (size), Qnil);
985773c9 160 XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE);
1ee5d538
KH
161 XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
162 XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
163 XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
164 XCHAR_TABLE (copy)->ascii = XCHAR_TABLE (table)->ascii;
165 for (i = 0; i < chartab_size[0]; i++)
166 XCHAR_TABLE (copy)->contents[i]
167 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
168 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
169 : XCHAR_TABLE (table)->contents[i]);
170 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy)->ascii))
171 XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
172 size -= VECSIZE (struct Lisp_Char_Table) - 1;
173 for (i = 0; i < size; i++)
174 XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
175
176 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
177 return copy;
178}
179
180Lisp_Object
181sub_char_table_ref (table, c)
182 Lisp_Object table;
183 int c;
184{
185 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
186 int depth = XINT (tbl->depth);
187 int min_char = XINT (tbl->min_char);
188 Lisp_Object val;
189
190 val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
191 if (SUB_CHAR_TABLE_P (val))
192 val = sub_char_table_ref (val, c);
193 return val;
194}
195
196Lisp_Object
197char_table_ref (table, c)
198 Lisp_Object table;
199 int c;
200{
201 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
202 Lisp_Object val;
203
204 if (ASCII_CHAR_P (c))
205 {
206 val = tbl->ascii;
207 if (SUB_CHAR_TABLE_P (val))
208 val = XSUB_CHAR_TABLE (val)->contents[c];
209 }
210 else
211 {
212 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
213 if (SUB_CHAR_TABLE_P (val))
214 val = sub_char_table_ref (val, c);
215 }
216 if (NILP (val))
217 {
218 val = tbl->defalt;
219 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
220 val = char_table_ref (tbl->parent, c);
221 }
222 return val;
8f924df7 223}
1ee5d538
KH
224
225static Lisp_Object
e15009d9 226sub_char_table_ref_and_range (table, c, from, to, defalt)
1ee5d538
KH
227 Lisp_Object table;
228 int c;
229 int *from, *to;
e15009d9 230 Lisp_Object defalt;
1ee5d538
KH
231{
232 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
233 int depth = XINT (tbl->depth);
234 int min_char = XINT (tbl->min_char);
e15009d9
KH
235 int max_char = min_char + chartab_chars[depth - 1] - 1;
236 int index = CHARTAB_IDX (c, depth, min_char);
1ee5d538 237 Lisp_Object val;
8f924df7 238
e15009d9
KH
239 val = tbl->contents[index];
240 *from = min_char + index * chartab_chars[depth];
241 *to = *from + chartab_chars[depth] - 1;
242 if (SUB_CHAR_TABLE_P (val))
243 val = sub_char_table_ref_and_range (val, c, from, to, defalt);
244 else if (NILP (val))
245 val = defalt;
246
247 while (*from > min_char
248 && *from == min_char + index * chartab_chars[depth])
1ee5d538 249 {
e15009d9
KH
250 Lisp_Object this_val;
251 int this_from = *from - chartab_chars[depth];
252 int this_to = *from - 1;
253
254 index--;
255 this_val = tbl->contents[index];
256 if (SUB_CHAR_TABLE_P (this_val))
257 this_val = sub_char_table_ref_and_range (this_val, this_to,
258 &this_from, &this_to,
259 defalt);
260 else if (NILP (this_val))
261 this_val = defalt;
262
263 if (! EQ (this_val, val))
264 break;
265 *from = this_from;
1ee5d538 266 }
e15009d9
KH
267 index = CHARTAB_IDX (c, depth, min_char);
268 while (*to < max_char
269 && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
1ee5d538 270 {
e15009d9
KH
271 Lisp_Object this_val;
272 int this_from = *to + 1;
273 int this_to = this_from + chartab_chars[depth] - 1;
274
275 index++;
276 this_val = tbl->contents[index];
277 if (SUB_CHAR_TABLE_P (this_val))
278 this_val = sub_char_table_ref_and_range (this_val, this_from,
279 &this_from, &this_to,
280 defalt);
281 else if (NILP (this_val))
282 this_val = defalt;
283 if (! EQ (this_val, val))
284 break;
285 *to = this_to;
1ee5d538 286 }
e15009d9 287
1ee5d538
KH
288 return val;
289}
290
291
e15009d9
KH
292/* Return the value for C in char-table TABLE. Set *FROM and *TO to
293 the range of characters (containing C) that have the same value as
294 C. It is not assured that the value of (*FROM - 1) and (*TO + 1)
295 is different from that of C. */
296
1ee5d538
KH
297Lisp_Object
298char_table_ref_and_range (table, c, from, to)
299 Lisp_Object table;
300 int c;
301 int *from, *to;
302{
303 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
e15009d9 304 int index = CHARTAB_IDX (c, 0, 0);
1ee5d538
KH
305 Lisp_Object val;
306
e15009d9
KH
307 val = tbl->contents[index];
308 *from = index * chartab_chars[0];
309 *to = *from + chartab_chars[0] - 1;
310 if (SUB_CHAR_TABLE_P (val))
311 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
312 else if (NILP (val))
313 val = tbl->defalt;
314
315 while (*from > 0 && *from == index * chartab_chars[0])
1ee5d538 316 {
e15009d9
KH
317 Lisp_Object this_val;
318 int this_from = *from - chartab_chars[0];
319 int this_to = *from - 1;
320
321 index--;
322 this_val = tbl->contents[index];
323 if (SUB_CHAR_TABLE_P (this_val))
324 this_val = sub_char_table_ref_and_range (this_val, this_to,
325 &this_from, &this_to,
326 tbl->defalt);
327 else if (NILP (this_val))
328 this_val = tbl->defalt;
329
330 if (! EQ (this_val, val))
331 break;
332 *from = this_from;
1ee5d538 333 }
e15009d9 334 while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
1ee5d538 335 {
e15009d9
KH
336 Lisp_Object this_val;
337 int this_from = *to + 1;
338 int this_to = this_from + chartab_chars[0] - 1;
339
340 index++;
341 this_val = tbl->contents[index];
342 if (SUB_CHAR_TABLE_P (this_val))
343 this_val = sub_char_table_ref_and_range (this_val, this_from,
344 &this_from, &this_to,
345 tbl->defalt);
346 else if (NILP (this_val))
347 this_val = tbl->defalt;
348 if (! EQ (this_val, val))
349 break;
350 *to = this_to;
1ee5d538
KH
351 }
352
1ee5d538 353 return val;
e15009d9 354}
1ee5d538
KH
355
356
357#define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
358 do { \
359 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
360 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
361 } while (0)
362
363#define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
364 do { \
365 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
366 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
367 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
368 } while (0)
369
370
371static void
372sub_char_table_set (table, c, val)
373 Lisp_Object table;
374 int c;
375 Lisp_Object val;
376{
377 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
378 int depth = XINT ((tbl)->depth);
379 int min_char = XINT ((tbl)->min_char);
380 int i = CHARTAB_IDX (c, depth, min_char);
381 Lisp_Object sub;
8f924df7 382
1ee5d538
KH
383 if (depth == 3)
384 tbl->contents[i] = val;
385 else
386 {
387 sub = tbl->contents[i];
388 if (! SUB_CHAR_TABLE_P (sub))
389 {
390 sub = make_sub_char_table (depth + 1,
391 min_char + i * chartab_chars[depth], sub);
392 tbl->contents[i] = sub;
393 }
394 sub_char_table_set (sub, c, val);
395 }
396}
397
398Lisp_Object
399char_table_set (table, c, val)
400 Lisp_Object table;
401 int c;
402 Lisp_Object val;
403{
404 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
405
406 if (ASCII_CHAR_P (c)
407 && SUB_CHAR_TABLE_P (tbl->ascii))
408 {
409 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
410 }
411 else
412 {
413 int i = CHARTAB_IDX (c, 0, 0);
414 Lisp_Object sub;
415
416 sub = tbl->contents[i];
417 if (! SUB_CHAR_TABLE_P (sub))
418 {
419 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
420 tbl->contents[i] = sub;
421 }
422 sub_char_table_set (sub, c, val);
423 if (ASCII_CHAR_P (c))
40033db7 424 tbl->ascii = char_table_ascii (table);
1ee5d538
KH
425 }
426 return val;
427}
428
429static void
430sub_char_table_set_range (table, depth, min_char, from, to, val)
431 Lisp_Object *table;
432 int depth;
433 int min_char;
434 int from, to;
435 Lisp_Object val;
436{
437 int max_char = min_char + chartab_chars[depth] - 1;
438
ed09a18b 439 if (depth == 3 || (from <= min_char && to >= max_char))
1ee5d538
KH
440 *table = val;
441 else
442 {
443 int i, j;
444
445 depth++;
446 if (! SUB_CHAR_TABLE_P (*table))
447 *table = make_sub_char_table (depth, min_char, *table);
448 if (from < min_char)
449 from = min_char;
450 if (to > max_char)
451 to = max_char;
22d49f94 452 i = CHARTAB_IDX (from, depth, min_char);
1ee5d538 453 j = CHARTAB_IDX (to, depth, min_char);
22d49f94
KH
454 min_char += chartab_chars[depth] * i;
455 for (; i <= j; i++, min_char += chartab_chars[depth])
1ee5d538 456 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
22d49f94 457 depth, min_char, from, to, val);
1ee5d538
KH
458 }
459}
460
461
462Lisp_Object
463char_table_set_range (table, from, to, val)
464 Lisp_Object table;
465 int from, to;
466 Lisp_Object val;
467{
468 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
469 Lisp_Object *contents = tbl->contents;
470 int i, min_char;
471
472 if (from == to)
473 char_table_set (table, from, val);
474 else
475 {
476 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
477 min_char <= to;
478 i++, min_char += chartab_chars[0])
479 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
480 if (ASCII_CHAR_P (from))
40033db7 481 tbl->ascii = char_table_ascii (table);
1ee5d538
KH
482 }
483 return val;
484}
485
486\f
487DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
488 1, 1, 0,
489 doc: /*
490Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
491 (char_table)
492 Lisp_Object char_table;
493{
494 CHECK_CHAR_TABLE (char_table);
495
496 return XCHAR_TABLE (char_table)->purpose;
497}
498
499DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
500 1, 1, 0,
501 doc: /* Return the parent char-table of CHAR-TABLE.
502The value is either nil or another char-table.
503If CHAR-TABLE holds nil for a given character,
504then the actual applicable value is inherited from the parent char-table
505\(or from its parents, if necessary). */)
506 (char_table)
507 Lisp_Object char_table;
508{
509 CHECK_CHAR_TABLE (char_table);
510
511 return XCHAR_TABLE (char_table)->parent;
512}
513
514DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
515 2, 2, 0,
516 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
6b61353c 517Return PARENT. PARENT must be either nil or another char-table. */)
1ee5d538
KH
518 (char_table, parent)
519 Lisp_Object char_table, parent;
520{
521 Lisp_Object temp;
522
523 CHECK_CHAR_TABLE (char_table);
524
525 if (!NILP (parent))
526 {
527 CHECK_CHAR_TABLE (parent);
528
529 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
530 if (EQ (temp, char_table))
531 error ("Attempt to make a chartable be its own parent");
532 }
533
534 XCHAR_TABLE (char_table)->parent = parent;
535
536 return parent;
537}
538
539DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
540 2, 2, 0,
541 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
542 (char_table, n)
543 Lisp_Object char_table, n;
544{
545 CHECK_CHAR_TABLE (char_table);
546 CHECK_NUMBER (n);
547 if (XINT (n) < 0
548 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
549 args_out_of_range (char_table, n);
550
551 return XCHAR_TABLE (char_table)->extras[XINT (n)];
552}
553
554DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
555 Sset_char_table_extra_slot,
556 3, 3, 0,
557 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
558 (char_table, n, value)
559 Lisp_Object char_table, n, value;
560{
561 CHECK_CHAR_TABLE (char_table);
562 CHECK_NUMBER (n);
563 if (XINT (n) < 0
564 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
565 args_out_of_range (char_table, n);
566
567 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
568}
569\f
570DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
571 2, 2, 0,
572 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
573RANGE should be nil (for the default value),
574a cons of character codes (for characters in the range), or a character code. */)
575 (char_table, range)
576 Lisp_Object char_table, range;
577{
578 Lisp_Object val;
579 CHECK_CHAR_TABLE (char_table);
580
581 if (EQ (range, Qnil))
582 val = XCHAR_TABLE (char_table)->defalt;
583 else if (INTEGERP (range))
584 val = CHAR_TABLE_REF (char_table, XINT (range));
585 else if (CONSP (range))
586 {
587 int from, to;
588
8f924df7
KH
589 CHECK_CHARACTER_CAR (range);
590 CHECK_CHARACTER_CDR (range);
1ee5d538
KH
591 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
592 &from, &to);
593 /* Not yet implemented. */
594 }
595 else
596 error ("Invalid RANGE argument to `char-table-range'");
597 return val;
598}
599
600DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
601 3, 3, 0,
6b61353c 602 doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.
1ee5d538 603RANGE should be t (for all characters), nil (for the default value),
6b61353c
KH
604a cons of character codes (for characters in the range),
605or a character code. Return VALUE. */)
1ee5d538
KH
606 (char_table, range, value)
607 Lisp_Object char_table, range, value;
608{
609 CHECK_CHAR_TABLE (char_table);
610 if (EQ (range, Qt))
611 {
612 int i;
613
c6bff69e 614 XCHAR_TABLE (char_table)->ascii = value;
1ee5d538 615 for (i = 0; i < chartab_size[0]; i++)
c6bff69e 616 XCHAR_TABLE (char_table)->contents[i] = value;
1ee5d538
KH
617 }
618 else if (EQ (range, Qnil))
619 XCHAR_TABLE (char_table)->defalt = value;
620 else if (INTEGERP (range))
621 char_table_set (char_table, XINT (range), value);
622 else if (CONSP (range))
623 {
8f924df7
KH
624 CHECK_CHARACTER_CAR (range);
625 CHECK_CHARACTER_CDR (range);
1ee5d538
KH
626 char_table_set_range (char_table,
627 XINT (XCAR (range)), XINT (XCDR (range)), value);
628 }
629 else
630 error ("Invalid RANGE argument to `set-char-table-range'");
631
632 return value;
633}
634
635DEFUN ("set-char-table-default", Fset_char_table_default,
636 Sset_char_table_default, 3, 3, 0,
637 doc: /*
f6e5cae0 638This function is obsolete and has no effect. */)
1ee5d538
KH
639 (char_table, ch, value)
640 Lisp_Object char_table, ch, value;
641{
642 return Qnil;
643}
644
645/* Look up the element in TABLE at index CH, and return it as an
05d6275c 646 integer. If the element is not a character, return CH itself. */
1ee5d538
KH
647
648int
649char_table_translate (table, ch)
650 Lisp_Object table;
651 int ch;
652{
653 Lisp_Object value;
654 value = Faref (table, make_number (ch));
05d6275c 655 if (! CHARACTERP (value))
1ee5d538
KH
656 return ch;
657 return XINT (value);
658}
659
660static Lisp_Object
661optimize_sub_char_table (table)
662 Lisp_Object table;
663{
664 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
665 int depth = XINT (tbl->depth);
666 Lisp_Object elt, this;
667 int i;
668
669 elt = XSUB_CHAR_TABLE (table)->contents[0];
670 if (SUB_CHAR_TABLE_P (elt))
671 elt = XSUB_CHAR_TABLE (table)->contents[0] = optimize_sub_char_table (elt);
672 if (SUB_CHAR_TABLE_P (elt))
673 return table;
674 for (i = 1; i < chartab_size[depth]; i++)
675 {
676 this = XSUB_CHAR_TABLE (table)->contents[i];
677 if (SUB_CHAR_TABLE_P (this))
678 this = XSUB_CHAR_TABLE (table)->contents[i]
679 = optimize_sub_char_table (this);
680 if (SUB_CHAR_TABLE_P (this)
681 || NILP (Fequal (this, elt)))
682 break;
683 }
684
685 return (i < chartab_size[depth] ? table : elt);
686}
687
688DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table,
689 1, 1, 0,
690 doc: /* Optimize CHAR-TABLE. */)
691 (char_table)
692 Lisp_Object char_table;
693{
694 Lisp_Object elt;
695 int i;
696
697 CHECK_CHAR_TABLE (char_table);
698
699 for (i = 0; i < chartab_size[0]; i++)
700 {
701 elt = XCHAR_TABLE (char_table)->contents[i];
702 if (SUB_CHAR_TABLE_P (elt))
703 XCHAR_TABLE (char_table)->contents[i] = optimize_sub_char_table (elt);
704 }
705 return Qnil;
706}
707
708\f
57d53d1b
KH
709/* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table),
710 calling it for each character or group of characters that share a
711 value. RANGE is a cons (FROM . TO) specifying the range of target
712 characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the
713 default value of the char-table, PARENT is the parent of the
714 char-table.
715
716 ARG is passed to C_FUNCTION when that is called.
717
718 It returns the value of last character covered by TABLE (not the
719 value inheritted from the parent), and by side-effect, the car part
720 of RANGE is updated to the minimum character C where C and all the
721 following characters in TABLE have the same value. */
722
1ee5d538 723static Lisp_Object
8f924df7
KH
724map_sub_char_table (c_function, function, table, arg, val, range,
725 default_val, parent)
1ee5d538 726 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
8f924df7 727 Lisp_Object function, table, arg, val, range, default_val, parent;
1ee5d538 728{
57d53d1b
KH
729 /* Pointer to the elements of TABLE. */
730 Lisp_Object *contents;
731 /* Depth of TABLE. */
732 int depth;
733 /* Minimum and maxinum characters covered by TABLE. */
734 int min_char, max_char;
735 /* Number of characters covered by one element of TABLE. */
736 int chars_in_block;
737 int from = XINT (XCAR (range)), to = XINT (XCDR (range));
1ee5d538
KH
738 int i, c;
739
57d53d1b
KH
740 if (SUB_CHAR_TABLE_P (table))
741 {
742 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
743
744 depth = XINT (tbl->depth);
745 contents = tbl->contents;
746 min_char = XINT (tbl->min_char);
747 max_char = min_char + chartab_chars[depth - 1] - 1;
748 }
749 else
750 {
751 depth = 0;
752 contents = XCHAR_TABLE (table)->contents;
753 min_char = 0;
754 max_char = MAX_CHAR;
755 }
756 chars_in_block = chartab_chars[depth];
757
758 if (to < max_char)
759 max_char = to;
760 /* Set I to the index of the first element to check. */
761 if (from <= min_char)
762 i = 0;
763 else
764 i = (from - min_char) / chars_in_block;
765 for (c = min_char + chars_in_block * i; c <= max_char;
766 i++, c += chars_in_block)
1ee5d538 767 {
57d53d1b
KH
768 Lisp_Object this = contents[i];
769 int nextc = c + chars_in_block;
1ee5d538 770
1ee5d538 771 if (SUB_CHAR_TABLE_P (this))
57d53d1b
KH
772 {
773 if (to >= nextc)
774 XSETCDR (range, make_number (nextc - 1));
775 val = map_sub_char_table (c_function, function, this, arg,
776 val, range, default_val, parent);
777 }
2f76e15e 778 else
1ee5d538 779 {
2f76e15e
KH
780 if (NILP (this))
781 this = default_val;
782 if (NILP (Fequal (val, this)))
1ee5d538 783 {
57d53d1b
KH
784 int different_value = 1;
785
786 if (NILP (val))
787 {
788 if (! NILP (parent))
789 {
790 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
791
792 /* This is to get a value of FROM in PARENT
793 without checking the parent of PARENT. */
794 XCHAR_TABLE (parent)->parent = Qnil;
795 val = CHAR_TABLE_REF (parent, from);
796 XCHAR_TABLE (parent)->parent = temp;
797 XSETCDR (range, make_number (c - 1));
798 val = map_sub_char_table (c_function, function,
799 parent, arg, val, range,
800 XCHAR_TABLE (parent)->defalt,
801 XCHAR_TABLE (parent)->parent);
802 if (! NILP (Fequal (val, this)))
803 different_value = 0;
804 }
805 }
806 if (! NILP (val) && different_value)
1ee5d538 807 {
8f924df7 808 XSETCDR (range, make_number (c - 1));
0a4bacdc 809 if (EQ (XCAR (range), XCDR (range)))
2f76e15e
KH
810 {
811 if (c_function)
812 (*c_function) (arg, XCAR (range), val);
813 else
814 call2 (function, XCAR (range), val);
815 }
1ee5d538 816 else
2f76e15e
KH
817 {
818 if (c_function)
819 (*c_function) (arg, range, val);
820 else
821 call2 (function, range, val);
822 }
1ee5d538 823 }
2f76e15e 824 val = this;
57d53d1b 825 from = c;
8f924df7 826 XSETCAR (range, make_number (c));
1ee5d538 827 }
1ee5d538 828 }
57d53d1b 829 XSETCDR (range, make_number (to));
1ee5d538
KH
830 }
831 return val;
832}
833
834
835/* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
836 character or group of characters that share a value.
837
8f924df7 838 ARG is passed to C_FUNCTION when that is called. */
1ee5d538
KH
839
840void
8f924df7 841map_char_table (c_function, function, table, arg)
1ee5d538 842 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
8f924df7 843 Lisp_Object function, table, arg;
1ee5d538
KH
844{
845 Lisp_Object range, val;
846 int c, i;
239191f2 847 struct gcpro gcpro1, gcpro2, gcpro3;
1ee5d538 848
57d53d1b 849 range = Fcons (make_number (0), make_number (MAX_CHAR));
239191f2 850 GCPRO3 (table, arg, range);
2f76e15e
KH
851 val = XCHAR_TABLE (table)->ascii;
852 if (SUB_CHAR_TABLE_P (val))
853 val = XSUB_CHAR_TABLE (val)->contents[0];
57d53d1b
KH
854 val = map_sub_char_table (c_function, function, table, arg, val, range,
855 XCHAR_TABLE (table)->defalt,
856 XCHAR_TABLE (table)->parent);
857 /* If VAL is nil and TABLE has a parent, we must consult the parent
858 recursively. */
859 while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent))
1ee5d538 860 {
57d53d1b
KH
861 Lisp_Object parent = XCHAR_TABLE (table)->parent;
862 Lisp_Object temp = XCHAR_TABLE (parent)->parent;
863 int from = XINT (XCAR (range));
864
865 /* This is to get a value of FROM in PARENT without checking the
866 parent of PARENT. */
867 XCHAR_TABLE (parent)->parent = Qnil;
868 val = CHAR_TABLE_REF (parent, from);
869 XCHAR_TABLE (parent)->parent = temp;
870 val = map_sub_char_table (c_function, function, parent, arg, val, range,
871 XCHAR_TABLE (parent)->defalt,
872 XCHAR_TABLE (parent)->parent);
873 table = parent;
1ee5d538 874 }
2f76e15e
KH
875
876 if (! NILP (val))
877 {
0a4bacdc
KH
878 if (EQ (XCAR (range), XCDR (range)))
879 {
880 if (c_function)
881 (*c_function) (arg, XCAR (range), val);
882 else
883 call2 (function, XCAR (range), val);
884 }
2f76e15e 885 else
0a4bacdc
KH
886 {
887 if (c_function)
888 (*c_function) (arg, range, val);
889 else
890 call2 (function, range, val);
891 }
2f76e15e 892 }
26132fb5
AS
893
894 UNGCPRO;
1ee5d538
KH
895}
896
897DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
898 2, 2, 0,
899 doc: /*
ed7219f8 900Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
1ee5d538 901FUNCTION is called with two arguments--a key and a value.
2f76e15e
KH
902The key is a character code or a cons of character codes specifying a
903range of characters that have the same value. */)
1ee5d538
KH
904 (function, char_table)
905 Lisp_Object function, char_table;
906{
907 CHECK_CHAR_TABLE (char_table);
908
8f924df7 909 map_char_table (NULL, function, char_table, char_table);
1ee5d538
KH
910 return Qnil;
911}
912
e15009d9
KH
913
914static void
915map_sub_char_table_for_charset (c_function, function, table, arg, range,
916 charset, from, to)
917 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
918 Lisp_Object function, table, arg, range;
919 struct charset *charset;
920 unsigned from, to;
921{
922 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
923 int depth = XINT (tbl->depth);
924 int c, i;
925
926 if (depth < 3)
927 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
928 i++, c += chartab_chars[depth])
929 {
930 Lisp_Object this;
931
932 this = tbl->contents[i];
933 if (SUB_CHAR_TABLE_P (this))
934 map_sub_char_table_for_charset (c_function, function, this, arg,
935 range, charset, from, to);
936 else
937 {
938 if (! NILP (XCAR (range)))
939 {
940 XSETCDR (range, make_number (c - 1));
941 if (c_function)
942 (*c_function) (arg, range);
943 else
944 call2 (function, range, arg);
945 }
946 XSETCAR (range, Qnil);
947 }
948 }
949 else
950 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
951 {
952 Lisp_Object this;
953 unsigned code;
954
955 this = tbl->contents[i];
956 if (NILP (this)
957 || (charset
958 && (code = ENCODE_CHAR (charset, c),
959 (code < from || code > to))))
960 {
961 if (! NILP (XCAR (range)))
962 {
963 XSETCDR (range, make_number (c - 1));
964 if (c_function)
bc85ac78 965 (*c_function) (arg, range);
e15009d9
KH
966 else
967 call2 (function, range, arg);
968 XSETCAR (range, Qnil);
969 }
970 }
971 else
972 {
973 if (NILP (XCAR (range)))
974 XSETCAR (range, make_number (c));
975 }
976 }
977}
978
979
980void
981map_char_table_for_charset (c_function, function, table, arg,
982 charset, from, to)
983 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
984 Lisp_Object function, table, arg;
985 struct charset *charset;
986 unsigned from, to;
987{
988 Lisp_Object range;
989 int c, i;
26132fb5 990 struct gcpro gcpro1;
e15009d9 991
8f924df7 992 range = Fcons (Qnil, Qnil);
26132fb5 993 GCPRO1 (range);
e15009d9
KH
994
995 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
996 {
997 Lisp_Object this;
998
999 this = XCHAR_TABLE (table)->contents[i];
1000 if (SUB_CHAR_TABLE_P (this))
1001 map_sub_char_table_for_charset (c_function, function, this, arg,
1002 range, charset, from, to);
1003 else
1004 {
1005 if (! NILP (XCAR (range)))
1006 {
1007 XSETCDR (range, make_number (c - 1));
1008 if (c_function)
1009 (*c_function) (arg, range);
1010 else
1011 call2 (function, range, arg);
1012 }
1013 XSETCAR (range, Qnil);
1014 }
1015 }
1016 if (! NILP (XCAR (range)))
1017 {
1018 XSETCDR (range, make_number (c - 1));
1019 if (c_function)
1020 (*c_function) (arg, range);
1021 else
1022 call2 (function, range, arg);
1023 }
26132fb5
AS
1024
1025 UNGCPRO;
e15009d9
KH
1026}
1027
1ee5d538
KH
1028\f
1029void
1030syms_of_chartab ()
1031{
1032 defsubr (&Smake_char_table);
1033 defsubr (&Schar_table_parent);
1034 defsubr (&Schar_table_subtype);
1035 defsubr (&Sset_char_table_parent);
1036 defsubr (&Schar_table_extra_slot);
1037 defsubr (&Sset_char_table_extra_slot);
1038 defsubr (&Schar_table_range);
1039 defsubr (&Sset_char_table_range);
1040 defsubr (&Sset_char_table_default);
1041 defsubr (&Soptimize_char_table);
1042 defsubr (&Smap_char_table);
1043}
fbaf0946
MB
1044
1045/* arch-tag: 18b5b560-7ab5-4108-b09e-d5dd65dc6fda
1046 (do not change this comment) */