*** empty log message ***
[bpt/emacs.git] / src / chartab.c
CommitLineData
1ee5d538
KH
1/* chartab.c -- char-table support
2 Copyright (C) 2001, 2002
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
10the Free Software Foundation; either version 2, or (at your option)
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
19along with GNU Emacs; see the file COPYING. If not, write to
20the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21Boston, MA 02111-1307, USA. */
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);
88 XCHAR_TABLE (vector)->parent = Qnil;
89 XCHAR_TABLE (vector)->purpose = purpose;
90 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector));
91 return vector;
92}
93
94static Lisp_Object
95make_sub_char_table (depth, min_char, defalt)
96 int depth, min_char;
97 Lisp_Object defalt;
98{
99 Lisp_Object table;
100 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth];
1ee5d538
KH
101
102 table = Fmake_vector (make_number (size), defalt);
103 XSUB_CHAR_TABLE (table)->depth = make_number (depth);
104 XSUB_CHAR_TABLE (table)->min_char = make_number (min_char);
105 XSETSUB_CHAR_TABLE (table, XSUB_CHAR_TABLE (table));
106
107 return table;
108}
109
110static Lisp_Object
111char_table_ascii (table)
112 Lisp_Object table;
113{
114 Lisp_Object sub;
115
116 sub = XCHAR_TABLE (table)->contents[0];
40033db7
KH
117 if (! SUB_CHAR_TABLE_P (sub))
118 return sub;
1ee5d538 119 sub = XSUB_CHAR_TABLE (sub)->contents[0];
40033db7
KH
120 if (! SUB_CHAR_TABLE_P (sub))
121 return sub;
1ee5d538
KH
122 return XSUB_CHAR_TABLE (sub)->contents[0];
123}
124
125Lisp_Object
126copy_sub_char_table (table)
127 Lisp_Object table;
128{
129 Lisp_Object copy;
130 int depth = XINT (XSUB_CHAR_TABLE (table)->depth);
131 int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char);
132 Lisp_Object val;
133 int i;
134
135 copy = make_sub_char_table (depth, min_char, Qnil);
136 /* Recursively copy any sub char-tables. */
137 for (i = 0; i < chartab_size[depth]; i++)
138 {
139 val = XSUB_CHAR_TABLE (table)->contents[i];
140 if (SUB_CHAR_TABLE_P (val))
141 XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val);
142 else
143 XSUB_CHAR_TABLE (copy)->contents[i] = val;
144 }
145
146 return copy;
147}
148
149
150Lisp_Object
151copy_char_table (table)
152 Lisp_Object table;
153{
154 Lisp_Object copy;
155 int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK;
156 int i;
157
158 copy = Fmake_vector (make_number (size), Qnil);
159 XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt;
160 XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent;
161 XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose;
162 XCHAR_TABLE (copy)->ascii = XCHAR_TABLE (table)->ascii;
163 for (i = 0; i < chartab_size[0]; i++)
164 XCHAR_TABLE (copy)->contents[i]
165 = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i])
166 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
167 : XCHAR_TABLE (table)->contents[i]);
168 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (copy)->ascii))
169 XCHAR_TABLE (copy)->ascii = char_table_ascii (copy);
170 size -= VECSIZE (struct Lisp_Char_Table) - 1;
171 for (i = 0; i < size; i++)
172 XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i];
173
174 XSETCHAR_TABLE (copy, XCHAR_TABLE (copy));
175 return copy;
176}
177
178Lisp_Object
179sub_char_table_ref (table, c)
180 Lisp_Object table;
181 int c;
182{
183 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
184 int depth = XINT (tbl->depth);
185 int min_char = XINT (tbl->min_char);
186 Lisp_Object val;
187
188 val = tbl->contents[CHARTAB_IDX (c, depth, min_char)];
189 if (SUB_CHAR_TABLE_P (val))
190 val = sub_char_table_ref (val, c);
191 return val;
192}
193
194Lisp_Object
195char_table_ref (table, c)
196 Lisp_Object table;
197 int c;
198{
199 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
200 Lisp_Object val;
201
202 if (ASCII_CHAR_P (c))
203 {
204 val = tbl->ascii;
205 if (SUB_CHAR_TABLE_P (val))
206 val = XSUB_CHAR_TABLE (val)->contents[c];
207 }
208 else
209 {
210 val = tbl->contents[CHARTAB_IDX (c, 0, 0)];
211 if (SUB_CHAR_TABLE_P (val))
212 val = sub_char_table_ref (val, c);
213 }
214 if (NILP (val))
215 {
216 val = tbl->defalt;
217 if (NILP (val) && CHAR_TABLE_P (tbl->parent))
218 val = char_table_ref (tbl->parent, c);
219 }
220 return val;
221}
222
223static Lisp_Object
e15009d9 224sub_char_table_ref_and_range (table, c, from, to, defalt)
1ee5d538
KH
225 Lisp_Object table;
226 int c;
227 int *from, *to;
e15009d9 228 Lisp_Object defalt;
1ee5d538
KH
229{
230 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
231 int depth = XINT (tbl->depth);
232 int min_char = XINT (tbl->min_char);
e15009d9
KH
233 int max_char = min_char + chartab_chars[depth - 1] - 1;
234 int index = CHARTAB_IDX (c, depth, min_char);
1ee5d538
KH
235 Lisp_Object val;
236
e15009d9
KH
237 val = tbl->contents[index];
238 *from = min_char + index * chartab_chars[depth];
239 *to = *from + chartab_chars[depth] - 1;
240 if (SUB_CHAR_TABLE_P (val))
241 val = sub_char_table_ref_and_range (val, c, from, to, defalt);
242 else if (NILP (val))
243 val = defalt;
244
245 while (*from > min_char
246 && *from == min_char + index * chartab_chars[depth])
1ee5d538 247 {
e15009d9
KH
248 Lisp_Object this_val;
249 int this_from = *from - chartab_chars[depth];
250 int this_to = *from - 1;
251
252 index--;
253 this_val = tbl->contents[index];
254 if (SUB_CHAR_TABLE_P (this_val))
255 this_val = sub_char_table_ref_and_range (this_val, this_to,
256 &this_from, &this_to,
257 defalt);
258 else if (NILP (this_val))
259 this_val = defalt;
260
261 if (! EQ (this_val, val))
262 break;
263 *from = this_from;
1ee5d538 264 }
e15009d9
KH
265 index = CHARTAB_IDX (c, depth, min_char);
266 while (*to < max_char
267 && *to == min_char + (index + 1) * chartab_chars[depth] - 1)
1ee5d538 268 {
e15009d9
KH
269 Lisp_Object this_val;
270 int this_from = *to + 1;
271 int this_to = this_from + chartab_chars[depth] - 1;
272
273 index++;
274 this_val = tbl->contents[index];
275 if (SUB_CHAR_TABLE_P (this_val))
276 this_val = sub_char_table_ref_and_range (this_val, this_from,
277 &this_from, &this_to,
278 defalt);
279 else if (NILP (this_val))
280 this_val = defalt;
281 if (! EQ (this_val, val))
282 break;
283 *to = this_to;
1ee5d538 284 }
e15009d9 285
1ee5d538
KH
286 return val;
287}
288
289
e15009d9
KH
290/* Return the value for C in char-table TABLE. Set *FROM and *TO to
291 the range of characters (containing C) that have the same value as
292 C. It is not assured that the value of (*FROM - 1) and (*TO + 1)
293 is different from that of C. */
294
1ee5d538
KH
295Lisp_Object
296char_table_ref_and_range (table, c, from, to)
297 Lisp_Object table;
298 int c;
299 int *from, *to;
300{
301 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
e15009d9 302 int index = CHARTAB_IDX (c, 0, 0);
1ee5d538
KH
303 Lisp_Object val;
304
e15009d9
KH
305 val = tbl->contents[index];
306 *from = index * chartab_chars[0];
307 *to = *from + chartab_chars[0] - 1;
308 if (SUB_CHAR_TABLE_P (val))
309 val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt);
310 else if (NILP (val))
311 val = tbl->defalt;
312
313 while (*from > 0 && *from == index * chartab_chars[0])
1ee5d538 314 {
e15009d9
KH
315 Lisp_Object this_val;
316 int this_from = *from - chartab_chars[0];
317 int this_to = *from - 1;
318
319 index--;
320 this_val = tbl->contents[index];
321 if (SUB_CHAR_TABLE_P (this_val))
322 this_val = sub_char_table_ref_and_range (this_val, this_to,
323 &this_from, &this_to,
324 tbl->defalt);
325 else if (NILP (this_val))
326 this_val = tbl->defalt;
327
328 if (! EQ (this_val, val))
329 break;
330 *from = this_from;
1ee5d538 331 }
e15009d9 332 while (*to < MAX_CHAR && *to == (index + 1) * chartab_chars[0] - 1)
1ee5d538 333 {
e15009d9
KH
334 Lisp_Object this_val;
335 int this_from = *to + 1;
336 int this_to = this_from + chartab_chars[0] - 1;
337
338 index++;
339 this_val = tbl->contents[index];
340 if (SUB_CHAR_TABLE_P (this_val))
341 this_val = sub_char_table_ref_and_range (this_val, this_from,
342 &this_from, &this_to,
343 tbl->defalt);
344 else if (NILP (this_val))
345 this_val = tbl->defalt;
346 if (! EQ (this_val, val))
347 break;
348 *to = this_to;
1ee5d538
KH
349 }
350
1ee5d538 351 return val;
e15009d9 352}
1ee5d538
KH
353
354
355#define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \
356 do { \
357 int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \
358 for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \
359 } while (0)
360
361#define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \
362 do { \
363 (SUBTABLE) = (TABLE)->contents[(IDX)]; \
364 if (!SUB_CHAR_TABLE_P (SUBTABLE)) \
365 (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \
366 } while (0)
367
368
369static void
370sub_char_table_set (table, c, val)
371 Lisp_Object table;
372 int c;
373 Lisp_Object val;
374{
375 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
376 int depth = XINT ((tbl)->depth);
377 int min_char = XINT ((tbl)->min_char);
378 int i = CHARTAB_IDX (c, depth, min_char);
379 Lisp_Object sub;
380
381 if (depth == 3)
382 tbl->contents[i] = val;
383 else
384 {
385 sub = tbl->contents[i];
386 if (! SUB_CHAR_TABLE_P (sub))
387 {
388 sub = make_sub_char_table (depth + 1,
389 min_char + i * chartab_chars[depth], sub);
390 tbl->contents[i] = sub;
391 }
392 sub_char_table_set (sub, c, val);
393 }
394}
395
396Lisp_Object
397char_table_set (table, c, val)
398 Lisp_Object table;
399 int c;
400 Lisp_Object val;
401{
402 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
403
404 if (ASCII_CHAR_P (c)
405 && SUB_CHAR_TABLE_P (tbl->ascii))
406 {
407 XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val;
408 }
409 else
410 {
411 int i = CHARTAB_IDX (c, 0, 0);
412 Lisp_Object sub;
413
414 sub = tbl->contents[i];
415 if (! SUB_CHAR_TABLE_P (sub))
416 {
417 sub = make_sub_char_table (1, i * chartab_chars[0], sub);
418 tbl->contents[i] = sub;
419 }
420 sub_char_table_set (sub, c, val);
421 if (ASCII_CHAR_P (c))
40033db7 422 tbl->ascii = char_table_ascii (table);
1ee5d538
KH
423 }
424 return val;
425}
426
427static void
428sub_char_table_set_range (table, depth, min_char, from, to, val)
429 Lisp_Object *table;
430 int depth;
431 int min_char;
432 int from, to;
433 Lisp_Object val;
434{
435 int max_char = min_char + chartab_chars[depth] - 1;
436
ed09a18b 437 if (depth == 3 || (from <= min_char && to >= max_char))
1ee5d538
KH
438 *table = val;
439 else
440 {
441 int i, j;
442
443 depth++;
444 if (! SUB_CHAR_TABLE_P (*table))
445 *table = make_sub_char_table (depth, min_char, *table);
446 if (from < min_char)
447 from = min_char;
448 if (to > max_char)
449 to = max_char;
22d49f94 450 i = CHARTAB_IDX (from, depth, min_char);
1ee5d538 451 j = CHARTAB_IDX (to, depth, min_char);
22d49f94
KH
452 min_char += chartab_chars[depth] * i;
453 for (; i <= j; i++, min_char += chartab_chars[depth])
1ee5d538 454 sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i,
22d49f94 455 depth, min_char, from, to, val);
1ee5d538
KH
456 }
457}
458
459
460Lisp_Object
461char_table_set_range (table, from, to, val)
462 Lisp_Object table;
463 int from, to;
464 Lisp_Object val;
465{
466 struct Lisp_Char_Table *tbl = XCHAR_TABLE (table);
467 Lisp_Object *contents = tbl->contents;
468 int i, min_char;
469
470 if (from == to)
471 char_table_set (table, from, val);
472 else
473 {
474 for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0];
475 min_char <= to;
476 i++, min_char += chartab_chars[0])
477 sub_char_table_set_range (contents + i, 0, min_char, from, to, val);
478 if (ASCII_CHAR_P (from))
40033db7 479 tbl->ascii = char_table_ascii (table);
1ee5d538
KH
480 }
481 return val;
482}
483
484\f
485DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
486 1, 1, 0,
487 doc: /*
488Return the subtype of char-table CHAR-TABLE. The value is a symbol. */)
489 (char_table)
490 Lisp_Object char_table;
491{
492 CHECK_CHAR_TABLE (char_table);
493
494 return XCHAR_TABLE (char_table)->purpose;
495}
496
497DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
498 1, 1, 0,
499 doc: /* Return the parent char-table of CHAR-TABLE.
500The value is either nil or another char-table.
501If CHAR-TABLE holds nil for a given character,
502then the actual applicable value is inherited from the parent char-table
503\(or from its parents, if necessary). */)
504 (char_table)
505 Lisp_Object char_table;
506{
507 CHECK_CHAR_TABLE (char_table);
508
509 return XCHAR_TABLE (char_table)->parent;
510}
511
512DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
513 2, 2, 0,
514 doc: /* Set the parent char-table of CHAR-TABLE to PARENT.
515PARENT must be either nil or another char-table. */)
516 (char_table, parent)
517 Lisp_Object char_table, parent;
518{
519 Lisp_Object temp;
520
521 CHECK_CHAR_TABLE (char_table);
522
523 if (!NILP (parent))
524 {
525 CHECK_CHAR_TABLE (parent);
526
527 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
528 if (EQ (temp, char_table))
529 error ("Attempt to make a chartable be its own parent");
530 }
531
532 XCHAR_TABLE (char_table)->parent = parent;
533
534 return parent;
535}
536
537DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
538 2, 2, 0,
539 doc: /* Return the value of CHAR-TABLE's extra-slot number N. */)
540 (char_table, n)
541 Lisp_Object char_table, n;
542{
543 CHECK_CHAR_TABLE (char_table);
544 CHECK_NUMBER (n);
545 if (XINT (n) < 0
546 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
547 args_out_of_range (char_table, n);
548
549 return XCHAR_TABLE (char_table)->extras[XINT (n)];
550}
551
552DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
553 Sset_char_table_extra_slot,
554 3, 3, 0,
555 doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */)
556 (char_table, n, value)
557 Lisp_Object char_table, n, value;
558{
559 CHECK_CHAR_TABLE (char_table);
560 CHECK_NUMBER (n);
561 if (XINT (n) < 0
562 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
563 args_out_of_range (char_table, n);
564
565 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
566}
567\f
568DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
569 2, 2, 0,
570 doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
571RANGE should be nil (for the default value),
572a cons of character codes (for characters in the range), or a character code. */)
573 (char_table, range)
574 Lisp_Object char_table, range;
575{
576 Lisp_Object val;
577 CHECK_CHAR_TABLE (char_table);
578
579 if (EQ (range, Qnil))
580 val = XCHAR_TABLE (char_table)->defalt;
581 else if (INTEGERP (range))
582 val = CHAR_TABLE_REF (char_table, XINT (range));
583 else if (CONSP (range))
584 {
585 int from, to;
586
587 CHECK_CHARACTER (XCAR (range));
588 CHECK_CHARACTER (XCDR (range));
589 val = char_table_ref_and_range (char_table, XINT (XCAR (range)),
590 &from, &to);
591 /* Not yet implemented. */
592 }
593 else
594 error ("Invalid RANGE argument to `char-table-range'");
595 return val;
596}
597
598DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
599 3, 3, 0,
600 doc: /*
601Set the value in CHAR-TABLE for characters specified by RANGE to VALUE.
602RANGE should be t (for all characters), nil (for the default value),
603a cons of character codes (for characters in the range), or a character code. */)
604 (char_table, range, value)
605 Lisp_Object char_table, range, value;
606{
607 CHECK_CHAR_TABLE (char_table);
608 if (EQ (range, Qt))
609 {
610 int i;
611
612 XCHAR_TABLE (char_table)->ascii = Qnil;
613 for (i = 0; i < chartab_size[0]; i++)
614 XCHAR_TABLE (char_table)->contents[i] = Qnil;
615 XCHAR_TABLE (char_table)->defalt = value;
616 }
617 else if (EQ (range, Qnil))
618 XCHAR_TABLE (char_table)->defalt = value;
619 else if (INTEGERP (range))
620 char_table_set (char_table, XINT (range), value);
621 else if (CONSP (range))
622 {
623 CHECK_CHARACTER (XCAR (range));
624 CHECK_CHARACTER (XCDR (range));
625 char_table_set_range (char_table,
626 XINT (XCAR (range)), XINT (XCDR (range)), value);
627 }
628 else
629 error ("Invalid RANGE argument to `set-char-table-range'");
630
631 return value;
632}
633
634DEFUN ("set-char-table-default", Fset_char_table_default,
635 Sset_char_table_default, 3, 3, 0,
636 doc: /*
f6e5cae0 637This function is obsolete and has no effect. */)
1ee5d538
KH
638 (char_table, ch, value)
639 Lisp_Object char_table, ch, value;
640{
641 return Qnil;
642}
643
644/* Look up the element in TABLE at index CH, and return it as an
645 integer. If the element is nil, return CH itself. (Actually we do
646 that for any non-integer.) */
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));
f6e5cae0 655 if (! INTEGERP (value)) /* fixme: use CHARACTERP? */
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
709static Lisp_Object
2f76e15e 710map_sub_char_table (c_function, function, table, arg, val, range, default_val)
1ee5d538 711 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
2f76e15e 712 Lisp_Object function, table, arg, val, range, default_val;
1ee5d538
KH
713{
714 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
715 int depth = XINT (tbl->depth);
716 int i, c;
717
718 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
719 i++, c += chartab_chars[depth])
720 {
721 Lisp_Object this;
722
723 this = tbl->contents[i];
724 if (SUB_CHAR_TABLE_P (this))
2f76e15e
KH
725 val = map_sub_char_table (c_function, function, this, arg, val, range,
726 default_val);
727 else
1ee5d538 728 {
2f76e15e
KH
729 if (NILP (this))
730 this = default_val;
731 if (NILP (Fequal (val, this)))
1ee5d538 732 {
2f76e15e 733 if (! NILP (val))
1ee5d538 734 {
2f76e15e
KH
735 XCDR (range) = make_number (c - 1);
736 if (depth == 3
737 && EQ (XCAR (range), XCDR (range)))
738 {
739 if (c_function)
740 (*c_function) (arg, XCAR (range), val);
741 else
742 call2 (function, XCAR (range), val);
743 }
1ee5d538 744 else
2f76e15e
KH
745 {
746 if (c_function)
747 (*c_function) (arg, range, val);
748 else
749 call2 (function, range, val);
750 }
1ee5d538 751 }
2f76e15e
KH
752 val = this;
753 XCAR (range) = make_number (c);
1ee5d538 754 }
1ee5d538
KH
755 }
756 }
757 return val;
758}
759
760
761/* Map C_FUNCTION or FUNCTION over TABLE, calling it for each
762 character or group of characters that share a value.
763
764 ARG is passed to C_FUNCTION when that is called.
765
766 DEPTH and INDICES are ignored. They are removed in the new
767 feature. */
768
769void
770map_char_table (c_function, function, table, arg, depth, indices)
771 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
772 Lisp_Object function, table, arg, *indices;
773 int depth;
774{
775 Lisp_Object range, val;
776 int c, i;
777
778 range = Fcons (make_number (0), Qnil);
2f76e15e
KH
779 val = XCHAR_TABLE (table)->ascii;
780 if (SUB_CHAR_TABLE_P (val))
781 val = XSUB_CHAR_TABLE (val)->contents[0];
1ee5d538
KH
782
783 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
784 {
785 Lisp_Object this;
786
787 this = XCHAR_TABLE (table)->contents[i];
788 if (SUB_CHAR_TABLE_P (this))
2f76e15e
KH
789 val = map_sub_char_table (c_function, function, this, arg, val, range,
790 XCHAR_TABLE (table)->defalt);
791 else
1ee5d538 792 {
2f76e15e
KH
793 if (NILP (this))
794 this = XCHAR_TABLE (table)->defalt;
795 if (NILP (Fequal (val, this)))
1ee5d538 796 {
2f76e15e
KH
797 if (! NILP (val))
798 {
799 XCDR (range) = make_number (c - 1);
800 if (c_function)
801 (*c_function) (arg, range, val);
802 else
803 call2 (function, range, val);
804 }
805 val = this;
806 XCAR (range) = make_number (c);
1ee5d538 807 }
1ee5d538
KH
808 }
809 }
2f76e15e
KH
810
811 if (! NILP (val))
812 {
813 XCDR (range) = make_number (c - 1);
814 if (c_function)
815 (*c_function) (arg, range, val);
816 else
817 call2 (function, range, val);
818 }
1ee5d538
KH
819}
820
821DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
822 2, 2, 0,
823 doc: /*
ed7219f8 824Call FUNCTION for each character in CHAR-TABLE that has non-nil value.
1ee5d538 825FUNCTION is called with two arguments--a key and a value.
2f76e15e
KH
826The key is a character code or a cons of character codes specifying a
827range of characters that have the same value. */)
1ee5d538
KH
828 (function, char_table)
829 Lisp_Object function, char_table;
830{
831 CHECK_CHAR_TABLE (char_table);
832
833 map_char_table (NULL, function, char_table, char_table, 0, NULL);
834 return Qnil;
835}
836
e15009d9
KH
837
838static void
839map_sub_char_table_for_charset (c_function, function, table, arg, range,
840 charset, from, to)
841 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
842 Lisp_Object function, table, arg, range;
843 struct charset *charset;
844 unsigned from, to;
845{
846 struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table);
847 int depth = XINT (tbl->depth);
848 int c, i;
849
850 if (depth < 3)
851 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth];
852 i++, c += chartab_chars[depth])
853 {
854 Lisp_Object this;
855
856 this = tbl->contents[i];
857 if (SUB_CHAR_TABLE_P (this))
858 map_sub_char_table_for_charset (c_function, function, this, arg,
859 range, charset, from, to);
860 else
861 {
862 if (! NILP (XCAR (range)))
863 {
864 XSETCDR (range, make_number (c - 1));
865 if (c_function)
866 (*c_function) (arg, range);
867 else
868 call2 (function, range, arg);
869 }
870 XSETCAR (range, Qnil);
871 }
872 }
873 else
874 for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++)
875 {
876 Lisp_Object this;
877 unsigned code;
878
879 this = tbl->contents[i];
880 if (NILP (this)
881 || (charset
882 && (code = ENCODE_CHAR (charset, c),
883 (code < from || code > to))))
884 {
885 if (! NILP (XCAR (range)))
886 {
887 XSETCDR (range, make_number (c - 1));
888 if (c_function)
889 (*c_function) (range, arg);
890 else
891 call2 (function, range, arg);
892 XSETCAR (range, Qnil);
893 }
894 }
895 else
896 {
897 if (NILP (XCAR (range)))
898 XSETCAR (range, make_number (c));
899 }
900 }
901}
902
903
904void
905map_char_table_for_charset (c_function, function, table, arg,
906 charset, from, to)
907 void (*c_function) P_ ((Lisp_Object, Lisp_Object));
908 Lisp_Object function, table, arg;
909 struct charset *charset;
910 unsigned from, to;
911{
912 Lisp_Object range;
913 int c, i;
914
915 if (NILP (char_table_ref (table, 0)))
916 range = Fcons (Qnil, Qnil);
917 else
918 range = Fcons (make_number (0), make_number (0));
919
920 for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0])
921 {
922 Lisp_Object this;
923
924 this = XCHAR_TABLE (table)->contents[i];
925 if (SUB_CHAR_TABLE_P (this))
926 map_sub_char_table_for_charset (c_function, function, this, arg,
927 range, charset, from, to);
928 else
929 {
930 if (! NILP (XCAR (range)))
931 {
932 XSETCDR (range, make_number (c - 1));
933 if (c_function)
934 (*c_function) (arg, range);
935 else
936 call2 (function, range, arg);
937 }
938 XSETCAR (range, Qnil);
939 }
940 }
941 if (! NILP (XCAR (range)))
942 {
943 XSETCDR (range, make_number (c - 1));
944 if (c_function)
945 (*c_function) (arg, range);
946 else
947 call2 (function, range, arg);
948 }
949}
950
951
1ee5d538
KH
952\f
953#if 0
954Lisp_Object
955make_class_table (purpose)
956 Lisp_Object purpose;
957{
958 Lisp_Object table;
959 Lisp_Object args[4];
960
961 args[0] = purpose;
962 args[1] = Qnil;
963 args[2] = QCextra_slots;
964 args[3] = Fmake_vector (make_number (2), Qnil);
965 ASET (args[3], 0, Fmakehash (Qequal));
966 table = Fmake_char_table (4, args);
967 return table;
968}
969
970Lisp_Object
971modify_class_entry (c, val, table, set)
972 int c;
973 Lisp_Object val, table, set;
974{
975 Lisp_Object classes, hash, canon;
976 int i, ival;
977
978 hash = XCHAR_TABLE (table)->extras[0];
979 classes = CHAR_TABLE_REF (table, c);
980
981 if (! BOOL_VECTOR_P (classes))
982 classes = (NILP (set)
983 ? Qnil
984 : Fmake_bool_vector (make_number ((ival / 8) * 8 + 8), Qnil));
985 else if (ival < XBOOL_VECTOR (classes)->size)
986 {
987 Lisp_Object old;
988 old = classes;
989 classes = Fmake_bool_vector (make_number ((ival / 8) * 8 + 8), Qnil);
990 for (i = 0; i < XBOOL_VECTOR (classes)->size; i++)
991 Faset (classes, make_number (i), Faref (old, make_number (i)));
992 Faset (classes, val, set);
993 }
994 else if (NILP (Faref (classes, val)) != NILP (set))
995 {
996 classes = Fcopy_sequence (classes);
997 Faset (classes, val, set);
998 }
999 else
1000 classes = Qnil;
1001
1002 if (!NILP (classes))
1003 {
1004 canon = Fgethash (classes, hash, Qnil);
1005 if (NILP (canon))
1006 {
1007 canon = classes;
1008 Fputhash (canon, canon, hash);
1009 }
1010 char_table_set (table, c, canon);
1011 }
1012
1013 return val;
1014}
1015#endif
1016
1017\f
1018void
1019syms_of_chartab ()
1020{
1021 defsubr (&Smake_char_table);
1022 defsubr (&Schar_table_parent);
1023 defsubr (&Schar_table_subtype);
1024 defsubr (&Sset_char_table_parent);
1025 defsubr (&Schar_table_extra_slot);
1026 defsubr (&Sset_char_table_extra_slot);
1027 defsubr (&Schar_table_range);
1028 defsubr (&Sset_char_table_range);
1029 defsubr (&Sset_char_table_default);
1030 defsubr (&Soptimize_char_table);
1031 defsubr (&Smap_char_table);
1032}