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