1 /* XEmacs routines to deal with char tables.
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1995, 1997, 1999 Electrotechnical Laboratory, JAPAN.
6 Licensed to the Free Software Foundation.
7 Copyright (C) 1999,2000,2001,2002,2003,2004,2005 MORIOKA Tomohiko
9 This file is part of XEmacs.
11 XEmacs is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 XEmacs is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with XEmacs; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. */
26 /* Synched up with: Mule 2.3. Not synched with FSF.
28 This file was written independently of the FSF implementation,
29 and is not compatible. */
33 Ben Wing: wrote, for 19.13 (Mule). Some category table stuff
34 loosely based on the original Mule.
35 Jareth Hein: fixed a couple of bugs in the implementation, and
36 added regex support for categories with check_category_at
37 MORIOKA Tomohiko: Rewritten for XEmacs CHISE
50 Lisp_Object Qchar_tablep, Qchar_table;
52 Lisp_Object Vall_syntax_tables;
55 Lisp_Object Qcategory_table_p;
56 Lisp_Object Qcategory_designator_p;
57 Lisp_Object Qcategory_table_value_p;
59 Lisp_Object Vstandard_category_table;
61 /* Variables to determine word boundary. */
62 Lisp_Object Vword_combining_categories, Vword_separating_categories;
67 Lisp_Object Vchise_db_directory;
68 Lisp_Object Vchise_system_db_directory;
70 CHISE_DS *default_chise_data_source = NULL;
75 EXFUN (Fchar_refs_simplify_char_specs, 1);
76 extern Lisp_Object Qideographic_structure;
78 Lisp_Object Vnext_defined_char_id;
80 EXFUN (Fmap_char_attribute, 3);
83 EXFUN (Fmount_char_attribute_table, 1);
87 EXFUN (Fload_char_attribute_table, 1);
89 Lisp_Object Vchar_db_stingy_mode;
92 #define BT_UINT8_MIN 0
93 #define BT_UINT8_MAX (UCHAR_MAX - 4)
94 #define BT_UINT8_t (UCHAR_MAX - 3)
95 #define BT_UINT8_nil (UCHAR_MAX - 2)
96 #define BT_UINT8_unbound (UCHAR_MAX - 1)
97 #define BT_UINT8_unloaded UCHAR_MAX
99 INLINE_HEADER int INT_UINT8_P (Lisp_Object obj);
100 INLINE_HEADER int UINT8_VALUE_P (Lisp_Object obj);
101 INLINE_HEADER unsigned char UINT8_ENCODE (Lisp_Object obj);
102 INLINE_HEADER Lisp_Object UINT8_DECODE (unsigned char n);
103 INLINE_HEADER unsigned short UINT8_TO_UINT16 (unsigned char n);
106 INT_UINT8_P (Lisp_Object obj)
110 int num = XINT (obj);
112 return (BT_UINT8_MIN <= num) && (num <= BT_UINT8_MAX);
119 UINT8_VALUE_P (Lisp_Object obj)
121 return EQ (obj, Qunloaded) || EQ (obj, Qunbound)
122 || EQ (obj, Qnil) || EQ (obj, Qt) || INT_UINT8_P (obj);
125 INLINE_HEADER unsigned char
126 UINT8_ENCODE (Lisp_Object obj)
128 if (EQ (obj, Qunloaded))
129 return BT_UINT8_unloaded;
130 else if (EQ (obj, Qunbound))
131 return BT_UINT8_unbound;
132 else if (EQ (obj, Qnil))
134 else if (EQ (obj, Qt))
140 INLINE_HEADER Lisp_Object
141 UINT8_DECODE (unsigned char n)
143 if (n == BT_UINT8_unloaded)
145 else if (n == BT_UINT8_unbound)
147 else if (n == BT_UINT8_nil)
149 else if (n == BT_UINT8_t)
156 mark_uint8_byte_table (Lisp_Object obj)
162 print_uint8_byte_table (Lisp_Object obj,
163 Lisp_Object printcharfun, int escapeflag)
165 Lisp_Uint8_Byte_Table *bte = XUINT8_BYTE_TABLE (obj);
167 struct gcpro gcpro1, gcpro2;
168 GCPRO2 (obj, printcharfun);
170 write_c_string ("\n#<uint8-byte-table", printcharfun);
171 for (i = 0; i < 256; i++)
173 unsigned char n = bte->property[i];
175 write_c_string ("\n ", printcharfun);
176 write_c_string (" ", printcharfun);
177 if (n == BT_UINT8_unbound)
178 write_c_string ("void", printcharfun);
179 else if (n == BT_UINT8_nil)
180 write_c_string ("nil", printcharfun);
181 else if (n == BT_UINT8_t)
182 write_c_string ("t", printcharfun);
187 sprintf (buf, "%hd", n);
188 write_c_string (buf, printcharfun);
192 write_c_string (">", printcharfun);
196 uint8_byte_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
198 Lisp_Uint8_Byte_Table *te1 = XUINT8_BYTE_TABLE (obj1);
199 Lisp_Uint8_Byte_Table *te2 = XUINT8_BYTE_TABLE (obj2);
202 for (i = 0; i < 256; i++)
203 if (te1->property[i] != te2->property[i])
209 uint8_byte_table_hash (Lisp_Object obj, int depth)
211 Lisp_Uint8_Byte_Table *te = XUINT8_BYTE_TABLE (obj);
215 for (i = 0; i < 256; i++)
216 hash = HASH2 (hash, te->property[i]);
220 static const struct lrecord_description uint8_byte_table_description[] = {
224 DEFINE_LRECORD_IMPLEMENTATION ("uint8-byte-table", uint8_byte_table,
225 mark_uint8_byte_table,
226 print_uint8_byte_table,
227 0, uint8_byte_table_equal,
228 uint8_byte_table_hash,
229 uint8_byte_table_description,
230 Lisp_Uint8_Byte_Table);
233 make_uint8_byte_table (unsigned char initval)
237 Lisp_Uint8_Byte_Table *cte;
239 cte = alloc_lcrecord_type (Lisp_Uint8_Byte_Table,
240 &lrecord_uint8_byte_table);
242 for (i = 0; i < 256; i++)
243 cte->property[i] = initval;
245 XSETUINT8_BYTE_TABLE (obj, cte);
250 copy_uint8_byte_table (Lisp_Object entry)
252 Lisp_Uint8_Byte_Table *cte = XUINT8_BYTE_TABLE (entry);
255 Lisp_Uint8_Byte_Table *ctenew
256 = alloc_lcrecord_type (Lisp_Uint8_Byte_Table,
257 &lrecord_uint8_byte_table);
259 for (i = 0; i < 256; i++)
261 ctenew->property[i] = cte->property[i];
264 XSETUINT8_BYTE_TABLE (obj, ctenew);
269 uint8_byte_table_same_value_p (Lisp_Object obj)
271 Lisp_Uint8_Byte_Table *bte = XUINT8_BYTE_TABLE (obj);
272 unsigned char v0 = bte->property[0];
275 for (i = 1; i < 256; i++)
277 if (bte->property[i] != v0)
284 map_over_uint8_byte_table (Lisp_Uint8_Byte_Table *ct, Lisp_Char_Table* root,
285 Emchar ofs, int place,
286 int (*fn) (struct chartab_range *range,
287 Lisp_Object val, void *arg),
290 struct chartab_range rainj;
292 int unit = 1 << (8 * place);
296 rainj.type = CHARTAB_RANGE_CHAR;
298 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
300 if (ct->property[i] == BT_UINT8_unloaded)
304 for (; c < c1 && retval == 0; c++)
306 Lisp_Object ret = get_char_id_table (root, c);
311 retval = (fn) (&rainj, ret, arg);
315 ct->property[i] = BT_UINT8_unbound;
319 else if (ct->property[i] != BT_UINT8_unbound)
322 for (; c < c1 && retval == 0; c++)
325 retval = (fn) (&rainj, UINT8_DECODE (ct->property[i]), arg);
336 save_uint8_byte_table (Lisp_Uint8_Byte_Table *ct, Lisp_Char_Table* root,
338 CHISE_Feature feature,
342 Emchar ofs, int place,
343 Lisp_Object (*filter)(Lisp_Object value))
345 struct chartab_range rainj;
347 int unit = 1 << (8 * place);
351 rainj.type = CHARTAB_RANGE_CHAR;
353 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
355 if (ct->property[i] == BT_UINT8_unloaded)
359 else if (ct->property[i] != BT_UINT8_unbound)
362 for (; c < c1 && retval == 0; c++)
365 chise_char_set_feature_value
368 (Fprin1_to_string (UINT8_DECODE (ct->property[i]),
371 Fput_database (Fprin1_to_string (make_char (c), Qnil),
372 Fprin1_to_string (UINT8_DECODE (ct->property[i]),
384 #define BT_UINT16_MIN 0
385 #define BT_UINT16_MAX (USHRT_MAX - 4)
386 #define BT_UINT16_t (USHRT_MAX - 3)
387 #define BT_UINT16_nil (USHRT_MAX - 2)
388 #define BT_UINT16_unbound (USHRT_MAX - 1)
389 #define BT_UINT16_unloaded USHRT_MAX
391 INLINE_HEADER int INT_UINT16_P (Lisp_Object obj);
392 INLINE_HEADER int UINT16_VALUE_P (Lisp_Object obj);
393 INLINE_HEADER unsigned short UINT16_ENCODE (Lisp_Object obj);
394 INLINE_HEADER Lisp_Object UINT16_DECODE (unsigned short us);
397 INT_UINT16_P (Lisp_Object obj)
401 int num = XINT (obj);
403 return (BT_UINT16_MIN <= num) && (num <= BT_UINT16_MAX);
410 UINT16_VALUE_P (Lisp_Object obj)
412 return EQ (obj, Qunloaded) || EQ (obj, Qunbound)
413 || EQ (obj, Qnil) || EQ (obj, Qt) || INT_UINT16_P (obj);
416 INLINE_HEADER unsigned short
417 UINT16_ENCODE (Lisp_Object obj)
419 if (EQ (obj, Qunloaded))
420 return BT_UINT16_unloaded;
421 else if (EQ (obj, Qunbound))
422 return BT_UINT16_unbound;
423 else if (EQ (obj, Qnil))
424 return BT_UINT16_nil;
425 else if (EQ (obj, Qt))
431 INLINE_HEADER Lisp_Object
432 UINT16_DECODE (unsigned short n)
434 if (n == BT_UINT16_unloaded)
436 else if (n == BT_UINT16_unbound)
438 else if (n == BT_UINT16_nil)
440 else if (n == BT_UINT16_t)
446 INLINE_HEADER unsigned short
447 UINT8_TO_UINT16 (unsigned char n)
449 if (n == BT_UINT8_unloaded)
450 return BT_UINT16_unloaded;
451 else if (n == BT_UINT8_unbound)
452 return BT_UINT16_unbound;
453 else if (n == BT_UINT8_nil)
454 return BT_UINT16_nil;
455 else if (n == BT_UINT8_t)
462 mark_uint16_byte_table (Lisp_Object obj)
468 print_uint16_byte_table (Lisp_Object obj,
469 Lisp_Object printcharfun, int escapeflag)
471 Lisp_Uint16_Byte_Table *bte = XUINT16_BYTE_TABLE (obj);
473 struct gcpro gcpro1, gcpro2;
474 GCPRO2 (obj, printcharfun);
476 write_c_string ("\n#<uint16-byte-table", printcharfun);
477 for (i = 0; i < 256; i++)
479 unsigned short n = bte->property[i];
481 write_c_string ("\n ", printcharfun);
482 write_c_string (" ", printcharfun);
483 if (n == BT_UINT16_unbound)
484 write_c_string ("void", printcharfun);
485 else if (n == BT_UINT16_nil)
486 write_c_string ("nil", printcharfun);
487 else if (n == BT_UINT16_t)
488 write_c_string ("t", printcharfun);
493 sprintf (buf, "%hd", n);
494 write_c_string (buf, printcharfun);
498 write_c_string (">", printcharfun);
502 uint16_byte_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
504 Lisp_Uint16_Byte_Table *te1 = XUINT16_BYTE_TABLE (obj1);
505 Lisp_Uint16_Byte_Table *te2 = XUINT16_BYTE_TABLE (obj2);
508 for (i = 0; i < 256; i++)
509 if (te1->property[i] != te2->property[i])
515 uint16_byte_table_hash (Lisp_Object obj, int depth)
517 Lisp_Uint16_Byte_Table *te = XUINT16_BYTE_TABLE (obj);
521 for (i = 0; i < 256; i++)
522 hash = HASH2 (hash, te->property[i]);
526 static const struct lrecord_description uint16_byte_table_description[] = {
530 DEFINE_LRECORD_IMPLEMENTATION ("uint16-byte-table", uint16_byte_table,
531 mark_uint16_byte_table,
532 print_uint16_byte_table,
533 0, uint16_byte_table_equal,
534 uint16_byte_table_hash,
535 uint16_byte_table_description,
536 Lisp_Uint16_Byte_Table);
539 make_uint16_byte_table (unsigned short initval)
543 Lisp_Uint16_Byte_Table *cte;
545 cte = alloc_lcrecord_type (Lisp_Uint16_Byte_Table,
546 &lrecord_uint16_byte_table);
548 for (i = 0; i < 256; i++)
549 cte->property[i] = initval;
551 XSETUINT16_BYTE_TABLE (obj, cte);
556 copy_uint16_byte_table (Lisp_Object entry)
558 Lisp_Uint16_Byte_Table *cte = XUINT16_BYTE_TABLE (entry);
561 Lisp_Uint16_Byte_Table *ctenew
562 = alloc_lcrecord_type (Lisp_Uint16_Byte_Table,
563 &lrecord_uint16_byte_table);
565 for (i = 0; i < 256; i++)
567 ctenew->property[i] = cte->property[i];
570 XSETUINT16_BYTE_TABLE (obj, ctenew);
575 expand_uint8_byte_table_to_uint16 (Lisp_Object table)
579 Lisp_Uint8_Byte_Table* bte = XUINT8_BYTE_TABLE(table);
580 Lisp_Uint16_Byte_Table* cte;
582 cte = alloc_lcrecord_type (Lisp_Uint16_Byte_Table,
583 &lrecord_uint16_byte_table);
584 for (i = 0; i < 256; i++)
586 cte->property[i] = UINT8_TO_UINT16 (bte->property[i]);
588 XSETUINT16_BYTE_TABLE (obj, cte);
593 uint16_byte_table_same_value_p (Lisp_Object obj)
595 Lisp_Uint16_Byte_Table *bte = XUINT16_BYTE_TABLE (obj);
596 unsigned short v0 = bte->property[0];
599 for (i = 1; i < 256; i++)
601 if (bte->property[i] != v0)
608 map_over_uint16_byte_table (Lisp_Uint16_Byte_Table *ct, Lisp_Char_Table* root,
609 Emchar ofs, int place,
610 int (*fn) (struct chartab_range *range,
611 Lisp_Object val, void *arg),
614 struct chartab_range rainj;
616 int unit = 1 << (8 * place);
620 rainj.type = CHARTAB_RANGE_CHAR;
622 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
624 if (ct->property[i] == BT_UINT16_unloaded)
628 for (; c < c1 && retval == 0; c++)
630 Lisp_Object ret = get_char_id_table (root, c);
635 retval = (fn) (&rainj, ret, arg);
639 ct->property[i] = BT_UINT16_unbound;
643 else if (ct->property[i] != BT_UINT16_unbound)
646 for (; c < c1 && retval == 0; c++)
649 retval = (fn) (&rainj, UINT16_DECODE (ct->property[i]), arg);
660 save_uint16_byte_table (Lisp_Uint16_Byte_Table *ct, Lisp_Char_Table* root,
662 CHISE_Feature feature,
666 Emchar ofs, int place,
667 Lisp_Object (*filter)(Lisp_Object value))
669 struct chartab_range rainj;
671 int unit = 1 << (8 * place);
675 rainj.type = CHARTAB_RANGE_CHAR;
677 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
679 if (ct->property[i] == BT_UINT16_unloaded)
683 else if (ct->property[i] != BT_UINT16_unbound)
686 for (; c < c1 && retval == 0; c++)
689 chise_char_set_feature_value
692 (Fprin1_to_string (UINT16_DECODE (ct->property[i]),
695 Fput_database (Fprin1_to_string (make_char (c), Qnil),
696 Fprin1_to_string (UINT16_DECODE (ct->property[i]),
710 mark_byte_table (Lisp_Object obj)
712 Lisp_Byte_Table *cte = XBYTE_TABLE (obj);
715 for (i = 0; i < 256; i++)
717 mark_object (cte->property[i]);
723 print_byte_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
725 Lisp_Byte_Table *bte = XBYTE_TABLE (obj);
727 struct gcpro gcpro1, gcpro2;
728 GCPRO2 (obj, printcharfun);
730 write_c_string ("\n#<byte-table", printcharfun);
731 for (i = 0; i < 256; i++)
733 Lisp_Object elt = bte->property[i];
735 write_c_string ("\n ", printcharfun);
736 write_c_string (" ", printcharfun);
737 if (EQ (elt, Qunbound))
738 write_c_string ("void", printcharfun);
740 print_internal (elt, printcharfun, escapeflag);
743 write_c_string (">", printcharfun);
747 byte_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
749 Lisp_Byte_Table *cte1 = XBYTE_TABLE (obj1);
750 Lisp_Byte_Table *cte2 = XBYTE_TABLE (obj2);
753 for (i = 0; i < 256; i++)
754 if (BYTE_TABLE_P (cte1->property[i]))
756 if (BYTE_TABLE_P (cte2->property[i]))
758 if (!byte_table_equal (cte1->property[i],
759 cte2->property[i], depth + 1))
766 if (!internal_equal (cte1->property[i], cte2->property[i], depth + 1))
772 byte_table_hash (Lisp_Object obj, int depth)
774 Lisp_Byte_Table *cte = XBYTE_TABLE (obj);
776 return internal_array_hash (cte->property, 256, depth);
779 static const struct lrecord_description byte_table_description[] = {
780 { XD_LISP_OBJECT_ARRAY, offsetof(Lisp_Byte_Table, property), 256 },
784 DEFINE_LRECORD_IMPLEMENTATION ("byte-table", byte_table,
789 byte_table_description,
793 make_byte_table (Lisp_Object initval)
797 Lisp_Byte_Table *cte;
799 cte = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
801 for (i = 0; i < 256; i++)
802 cte->property[i] = initval;
804 XSETBYTE_TABLE (obj, cte);
809 copy_byte_table (Lisp_Object entry)
811 Lisp_Byte_Table *cte = XBYTE_TABLE (entry);
814 Lisp_Byte_Table *ctnew
815 = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
817 for (i = 0; i < 256; i++)
819 if (UINT8_BYTE_TABLE_P (cte->property[i]))
821 ctnew->property[i] = copy_uint8_byte_table (cte->property[i]);
823 else if (UINT16_BYTE_TABLE_P (cte->property[i]))
825 ctnew->property[i] = copy_uint16_byte_table (cte->property[i]);
827 else if (BYTE_TABLE_P (cte->property[i]))
829 ctnew->property[i] = copy_byte_table (cte->property[i]);
832 ctnew->property[i] = cte->property[i];
835 XSETBYTE_TABLE (obj, ctnew);
840 byte_table_same_value_p (Lisp_Object obj)
842 Lisp_Byte_Table *bte = XBYTE_TABLE (obj);
843 Lisp_Object v0 = bte->property[0];
846 for (i = 1; i < 256; i++)
848 if (!internal_equal (bte->property[i], v0, 0))
855 map_over_byte_table (Lisp_Byte_Table *ct, Lisp_Char_Table* root,
856 Emchar ofs, int place,
857 int (*fn) (struct chartab_range *range,
858 Lisp_Object val, void *arg),
863 int unit = 1 << (8 * place);
866 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
869 if (UINT8_BYTE_TABLE_P (v))
872 = map_over_uint8_byte_table (XUINT8_BYTE_TABLE(v), root,
873 c, place - 1, fn, arg);
876 else if (UINT16_BYTE_TABLE_P (v))
879 = map_over_uint16_byte_table (XUINT16_BYTE_TABLE(v), root,
880 c, place - 1, fn, arg);
883 else if (BYTE_TABLE_P (v))
885 retval = map_over_byte_table (XBYTE_TABLE(v), root,
886 c, place - 1, fn, arg);
889 else if (EQ (v, Qunloaded))
892 struct chartab_range rainj;
893 Emchar c1 = c + unit;
895 rainj.type = CHARTAB_RANGE_CHAR;
897 for (; c < c1 && retval == 0; c++)
899 Lisp_Object ret = get_char_id_table (root, c);
904 retval = (fn) (&rainj, ret, arg);
908 ct->property[i] = Qunbound;
912 else if (!UNBOUNDP (v))
914 struct chartab_range rainj;
915 Emchar c1 = c + unit;
917 rainj.type = CHARTAB_RANGE_CHAR;
919 for (; c < c1 && retval == 0; c++)
922 retval = (fn) (&rainj, v, arg);
933 save_byte_table (Lisp_Byte_Table *ct, Lisp_Char_Table* root,
935 CHISE_Feature feature,
939 Emchar ofs, int place,
940 Lisp_Object (*filter)(Lisp_Object value))
944 int unit = 1 << (8 * place);
947 for (i = 0, retval = 0; i < 256 && retval == 0; i++)
950 if (UINT8_BYTE_TABLE_P (v))
952 save_uint8_byte_table (XUINT8_BYTE_TABLE(v), root,
958 c, place - 1, filter);
961 else if (UINT16_BYTE_TABLE_P (v))
963 save_uint16_byte_table (XUINT16_BYTE_TABLE(v), root,
969 c, place - 1, filter);
972 else if (BYTE_TABLE_P (v))
974 save_byte_table (XBYTE_TABLE(v), root,
980 c, place - 1, filter);
983 else if (EQ (v, Qunloaded))
987 else if (!UNBOUNDP (v))
989 struct chartab_range rainj;
990 Emchar c1 = c + unit;
995 rainj.type = CHARTAB_RANGE_CHAR;
997 for (; c < c1 && retval == 0; c++)
1000 chise_char_set_feature_value
1001 (c, feature, XSTRING_DATA (Fprin1_to_string (v, Qnil)));
1003 Fput_database (Fprin1_to_string (make_char (c), Qnil),
1004 Fprin1_to_string (v, Qnil),
1016 get_byte_table (Lisp_Object table, unsigned char idx)
1018 if (UINT8_BYTE_TABLE_P (table))
1019 return UINT8_DECODE (XUINT8_BYTE_TABLE(table)->property[idx]);
1020 else if (UINT16_BYTE_TABLE_P (table))
1021 return UINT16_DECODE (XUINT16_BYTE_TABLE(table)->property[idx]);
1022 else if (BYTE_TABLE_P (table))
1023 return XBYTE_TABLE(table)->property[idx];
1029 put_byte_table (Lisp_Object table, unsigned char idx, Lisp_Object value)
1031 if (UINT8_BYTE_TABLE_P (table))
1033 if (UINT8_VALUE_P (value))
1035 XUINT8_BYTE_TABLE(table)->property[idx] = UINT8_ENCODE (value);
1036 if (!UINT8_BYTE_TABLE_P (value) &&
1037 !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
1038 && uint8_byte_table_same_value_p (table))
1043 else if (UINT16_VALUE_P (value))
1045 Lisp_Object new = expand_uint8_byte_table_to_uint16 (table);
1047 XUINT16_BYTE_TABLE(new)->property[idx] = UINT16_ENCODE (value);
1052 Lisp_Object new = make_byte_table (Qnil);
1055 for (i = 0; i < 256; i++)
1057 XBYTE_TABLE(new)->property[i]
1058 = UINT8_DECODE (XUINT8_BYTE_TABLE(table)->property[i]);
1060 XBYTE_TABLE(new)->property[idx] = value;
1064 else if (UINT16_BYTE_TABLE_P (table))
1066 if (UINT16_VALUE_P (value))
1068 XUINT16_BYTE_TABLE(table)->property[idx] = UINT16_ENCODE (value);
1069 if (!UINT8_BYTE_TABLE_P (value) &&
1070 !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
1071 && uint16_byte_table_same_value_p (table))
1078 Lisp_Object new = make_byte_table (Qnil);
1081 for (i = 0; i < 256; i++)
1083 XBYTE_TABLE(new)->property[i]
1084 = UINT16_DECODE (XUINT16_BYTE_TABLE(table)->property[i]);
1086 XBYTE_TABLE(new)->property[idx] = value;
1090 else if (BYTE_TABLE_P (table))
1092 XBYTE_TABLE(table)->property[idx] = value;
1093 if (!UINT8_BYTE_TABLE_P (value) &&
1094 !UINT16_BYTE_TABLE_P (value) && !BYTE_TABLE_P (value)
1095 && byte_table_same_value_p (table))
1100 else if (!internal_equal (table, value, 0))
1102 if (UINT8_VALUE_P (table) && UINT8_VALUE_P (value))
1104 table = make_uint8_byte_table (UINT8_ENCODE (table));
1105 XUINT8_BYTE_TABLE(table)->property[idx] = UINT8_ENCODE (value);
1107 else if (UINT16_VALUE_P (table) && UINT16_VALUE_P (value))
1109 table = make_uint16_byte_table (UINT16_ENCODE (table));
1110 XUINT16_BYTE_TABLE(table)->property[idx] = UINT16_ENCODE (value);
1114 table = make_byte_table (table);
1115 XBYTE_TABLE(table)->property[idx] = value;
1123 make_char_id_table (Lisp_Object initval)
1126 obj = Fmake_char_table (Qgeneric);
1127 fill_char_table (XCHAR_TABLE (obj), initval);
1132 Lisp_Object Qcomposition;
1133 Lisp_Object Qmap_decomposition;
1134 Lisp_Object Qto_decomposition_at_superscript;
1135 Lisp_Object Q_canonical;
1136 Lisp_Object Q_superscript_of;
1137 Lisp_Object Q_compat_of;
1138 Lisp_Object Q_decomposition;
1139 Lisp_Object Q_identical;
1140 Lisp_Object Q_identical_from;
1141 Lisp_Object Q_denotational;
1142 Lisp_Object Q_denotational_from;
1143 Lisp_Object Q_subsumptive;
1144 Lisp_Object Q_subsumptive_from;
1145 Lisp_Object Q_component;
1146 Lisp_Object Q_component_of;
1147 Lisp_Object Qto_ucs;
1148 Lisp_Object Q_ucs_unified;
1149 Lisp_Object Qcompat;
1150 Lisp_Object Qisolated;
1151 Lisp_Object Qinitial;
1152 Lisp_Object Qmedial;
1154 Lisp_Object Qvertical;
1155 Lisp_Object QnoBreak;
1156 Lisp_Object Qfraction;
1159 Lisp_Object Qcircle;
1160 Lisp_Object Qsquare;
1162 Lisp_Object Qnarrow;
1166 Emchar to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg);
1169 to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
1175 else if (EQ (v, Qcompat))
1177 else if (EQ (v, Qisolated))
1179 else if (EQ (v, Qinitial))
1181 else if (EQ (v, Qmedial))
1183 else if (EQ (v, Qfinal))
1185 else if (EQ (v, Qvertical))
1187 else if (EQ (v, QnoBreak))
1189 else if (EQ (v, Qfraction))
1191 else if (EQ (v, Qsuper))
1193 else if (EQ (v, Qsub))
1195 else if (EQ (v, Qcircle))
1197 else if (EQ (v, Qsquare))
1199 else if (EQ (v, Qwide))
1201 else if (EQ (v, Qnarrow))
1203 else if (EQ (v, Qsmall))
1205 else if (EQ (v, Qfont))
1208 signal_simple_error (err_msg, err_arg);
1211 DEFUN ("get-composite-char", Fget_composite_char, 1, 1, 0, /*
1212 Return character corresponding with list.
1216 Lisp_Object base, modifier;
1220 signal_simple_error ("Invalid value for composition", list);
1223 while (!NILP (rest))
1228 signal_simple_error ("Invalid value for composition", list);
1229 modifier = Fcar (rest);
1231 base = Fcdr (Fassq (modifier,
1232 Fchar_feature (base, Qcomposition, Qnil,
1238 DEFUN ("char-variants", Fchar_variants, 1, 1, 0, /*
1239 Return variants of CHARACTER.
1243 CHECK_CHAR (character);
1246 (Fcopy_list (Fget_char_attribute (character, Q_subsumptive, Qnil)),
1248 (Fcopy_list (Fget_char_attribute (character, Q_denotational, Qnil)),
1250 (Fcopy_list (Fget_char_attribute (character, Q_identical, Qnil)),
1251 Fcopy_list (Fchar_feature (character, Q_ucs_unified, Qnil,
1258 /* A char table maps from ranges of characters to values.
1260 Implementing a general data structure that maps from arbitrary
1261 ranges of numbers to values is tricky to do efficiently. As it
1262 happens, it should suffice (and is usually more convenient, anyway)
1263 when dealing with characters to restrict the sorts of ranges that
1264 can be assigned values, as follows:
1267 2) All characters in a charset.
1268 3) All characters in a particular row of a charset, where a "row"
1269 means all characters with the same first byte.
1270 4) A particular character in a charset.
1272 We use char tables to generalize the 256-element vectors now
1273 littering the Emacs code.
1275 Possible uses (all should be converted at some point):
1281 5) keyboard-translate-table?
1284 abstract type to generalize the Emacs vectors and Mule
1285 vectors-of-vectors goo.
1288 /************************************************************************/
1289 /* Char Table object */
1290 /************************************************************************/
1292 #if defined(MULE)&&!defined(UTF2000)
1295 mark_char_table_entry (Lisp_Object obj)
1297 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
1300 for (i = 0; i < 96; i++)
1302 mark_object (cte->level2[i]);
1308 char_table_entry_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1310 Lisp_Char_Table_Entry *cte1 = XCHAR_TABLE_ENTRY (obj1);
1311 Lisp_Char_Table_Entry *cte2 = XCHAR_TABLE_ENTRY (obj2);
1314 for (i = 0; i < 96; i++)
1315 if (!internal_equal (cte1->level2[i], cte2->level2[i], depth + 1))
1321 static unsigned long
1322 char_table_entry_hash (Lisp_Object obj, int depth)
1324 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
1326 return internal_array_hash (cte->level2, 96, depth);
1329 static const struct lrecord_description char_table_entry_description[] = {
1330 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table_Entry, level2), 96 },
1334 DEFINE_LRECORD_IMPLEMENTATION ("char-table-entry", char_table_entry,
1335 mark_char_table_entry, internal_object_printer,
1336 0, char_table_entry_equal,
1337 char_table_entry_hash,
1338 char_table_entry_description,
1339 Lisp_Char_Table_Entry);
1343 mark_char_table (Lisp_Object obj)
1345 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1348 mark_object (ct->table);
1349 mark_object (ct->name);
1350 #ifndef HAVE_LIBCHISE
1351 mark_object (ct->db);
1356 for (i = 0; i < NUM_ASCII_CHARS; i++)
1357 mark_object (ct->ascii[i]);
1359 for (i = 0; i < NUM_LEADING_BYTES; i++)
1360 mark_object (ct->level1[i]);
1364 return ct->default_value;
1366 return ct->mirror_table;
1370 /* WARNING: All functions of this nature need to be written extremely
1371 carefully to avoid crashes during GC. Cf. prune_specifiers()
1372 and prune_weak_hash_tables(). */
1375 prune_syntax_tables (void)
1377 Lisp_Object rest, prev = Qnil;
1379 for (rest = Vall_syntax_tables;
1381 rest = XCHAR_TABLE (rest)->next_table)
1383 if (! marked_p (rest))
1385 /* This table is garbage. Remove it from the list. */
1387 Vall_syntax_tables = XCHAR_TABLE (rest)->next_table;
1389 XCHAR_TABLE (prev)->next_table =
1390 XCHAR_TABLE (rest)->next_table;
1396 char_table_type_to_symbol (enum char_table_type type)
1401 case CHAR_TABLE_TYPE_GENERIC: return Qgeneric;
1402 case CHAR_TABLE_TYPE_SYNTAX: return Qsyntax;
1403 case CHAR_TABLE_TYPE_DISPLAY: return Qdisplay;
1404 case CHAR_TABLE_TYPE_CHAR: return Qchar;
1406 case CHAR_TABLE_TYPE_CATEGORY: return Qcategory;
1411 static enum char_table_type
1412 symbol_to_char_table_type (Lisp_Object symbol)
1414 CHECK_SYMBOL (symbol);
1416 if (EQ (symbol, Qgeneric)) return CHAR_TABLE_TYPE_GENERIC;
1417 if (EQ (symbol, Qsyntax)) return CHAR_TABLE_TYPE_SYNTAX;
1418 if (EQ (symbol, Qdisplay)) return CHAR_TABLE_TYPE_DISPLAY;
1419 if (EQ (symbol, Qchar)) return CHAR_TABLE_TYPE_CHAR;
1421 if (EQ (symbol, Qcategory)) return CHAR_TABLE_TYPE_CATEGORY;
1424 signal_simple_error ("Unrecognized char table type", symbol);
1425 return CHAR_TABLE_TYPE_GENERIC; /* not reached */
1430 print_chartab_range (Emchar first, Emchar last, Lisp_Object val,
1431 Lisp_Object printcharfun)
1435 write_c_string (" (", printcharfun);
1436 print_internal (make_char (first), printcharfun, 0);
1437 write_c_string (" ", printcharfun);
1438 print_internal (make_char (last), printcharfun, 0);
1439 write_c_string (") ", printcharfun);
1443 write_c_string (" ", printcharfun);
1444 print_internal (make_char (first), printcharfun, 0);
1445 write_c_string (" ", printcharfun);
1447 print_internal (val, printcharfun, 1);
1451 #if defined(MULE)&&!defined(UTF2000)
1454 print_chartab_charset_row (Lisp_Object charset,
1456 Lisp_Char_Table_Entry *cte,
1457 Lisp_Object printcharfun)
1460 Lisp_Object cat = Qunbound;
1463 for (i = 32; i < 128; i++)
1465 Lisp_Object pam = cte->level2[i - 32];
1477 print_chartab_range (MAKE_CHAR (charset, first, 0),
1478 MAKE_CHAR (charset, i - 1, 0),
1481 print_chartab_range (MAKE_CHAR (charset, row, first),
1482 MAKE_CHAR (charset, row, i - 1),
1492 print_chartab_range (MAKE_CHAR (charset, first, 0),
1493 MAKE_CHAR (charset, i - 1, 0),
1496 print_chartab_range (MAKE_CHAR (charset, row, first),
1497 MAKE_CHAR (charset, row, i - 1),
1503 print_chartab_two_byte_charset (Lisp_Object charset,
1504 Lisp_Char_Table_Entry *cte,
1505 Lisp_Object printcharfun)
1509 for (i = 32; i < 128; i++)
1511 Lisp_Object jen = cte->level2[i - 32];
1513 if (!CHAR_TABLE_ENTRYP (jen))
1517 write_c_string (" [", printcharfun);
1518 print_internal (XCHARSET_NAME (charset), printcharfun, 0);
1519 sprintf (buf, " %d] ", i);
1520 write_c_string (buf, printcharfun);
1521 print_internal (jen, printcharfun, 0);
1524 print_chartab_charset_row (charset, i, XCHAR_TABLE_ENTRY (jen),
1532 print_char_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1534 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1537 struct gcpro gcpro1, gcpro2;
1538 GCPRO2 (obj, printcharfun);
1540 write_c_string ("#s(char-table ", printcharfun);
1541 write_c_string (" ", printcharfun);
1542 write_c_string (string_data
1544 (XSYMBOL (char_table_type_to_symbol (ct->type)))),
1546 write_c_string ("\n ", printcharfun);
1547 print_internal (ct->default_value, printcharfun, escapeflag);
1548 for (i = 0; i < 256; i++)
1550 Lisp_Object elt = get_byte_table (ct->table, i);
1551 if (i != 0) write_c_string ("\n ", printcharfun);
1552 if (EQ (elt, Qunbound))
1553 write_c_string ("void", printcharfun);
1555 print_internal (elt, printcharfun, escapeflag);
1558 #else /* non UTF2000 */
1561 sprintf (buf, "#s(char-table type %s data (",
1562 string_data (symbol_name (XSYMBOL
1563 (char_table_type_to_symbol (ct->type)))));
1564 write_c_string (buf, printcharfun);
1566 /* Now write out the ASCII/Control-1 stuff. */
1570 Lisp_Object val = Qunbound;
1572 for (i = 0; i < NUM_ASCII_CHARS; i++)
1581 if (!EQ (ct->ascii[i], val))
1583 print_chartab_range (first, i - 1, val, printcharfun);
1590 print_chartab_range (first, i - 1, val, printcharfun);
1597 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
1600 Lisp_Object ann = ct->level1[i - MIN_LEADING_BYTE];
1601 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (i);
1603 if (!CHARSETP (charset) || i == LEADING_BYTE_ASCII
1604 || i == LEADING_BYTE_CONTROL_1)
1606 if (!CHAR_TABLE_ENTRYP (ann))
1608 write_c_string (" ", printcharfun);
1609 print_internal (XCHARSET_NAME (charset),
1611 write_c_string (" ", printcharfun);
1612 print_internal (ann, printcharfun, 0);
1616 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (ann);
1617 if (XCHARSET_DIMENSION (charset) == 1)
1618 print_chartab_charset_row (charset, -1, cte, printcharfun);
1620 print_chartab_two_byte_charset (charset, cte, printcharfun);
1625 #endif /* non UTF2000 */
1627 write_c_string ("))", printcharfun);
1631 char_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1633 Lisp_Char_Table *ct1 = XCHAR_TABLE (obj1);
1634 Lisp_Char_Table *ct2 = XCHAR_TABLE (obj2);
1637 if (CHAR_TABLE_TYPE (ct1) != CHAR_TABLE_TYPE (ct2))
1641 for (i = 0; i < 256; i++)
1643 if (!internal_equal (get_byte_table (ct1->table, i),
1644 get_byte_table (ct2->table, i), 0))
1648 for (i = 0; i < NUM_ASCII_CHARS; i++)
1649 if (!internal_equal (ct1->ascii[i], ct2->ascii[i], depth + 1))
1653 for (i = 0; i < NUM_LEADING_BYTES; i++)
1654 if (!internal_equal (ct1->level1[i], ct2->level1[i], depth + 1))
1657 #endif /* non UTF2000 */
1662 static unsigned long
1663 char_table_hash (Lisp_Object obj, int depth)
1665 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1667 return byte_table_hash (ct->table, depth + 1);
1669 unsigned long hashval = internal_array_hash (ct->ascii, NUM_ASCII_CHARS,
1672 hashval = HASH2 (hashval,
1673 internal_array_hash (ct->level1, NUM_LEADING_BYTES, depth));
1679 static const struct lrecord_description char_table_description[] = {
1681 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, table) },
1682 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, default_value) },
1683 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, name) },
1684 #ifndef HAVE_LIBCHISE
1685 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, db) },
1688 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table, ascii), NUM_ASCII_CHARS },
1690 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table, level1), NUM_LEADING_BYTES },
1694 { XD_LISP_OBJECT, offsetof (Lisp_Char_Table, mirror_table) },
1696 { XD_LO_LINK, offsetof (Lisp_Char_Table, next_table) },
1700 DEFINE_LRECORD_IMPLEMENTATION ("char-table", char_table,
1701 mark_char_table, print_char_table, 0,
1702 char_table_equal, char_table_hash,
1703 char_table_description,
1706 DEFUN ("char-table-p", Fchar_table_p, 1, 1, 0, /*
1707 Return non-nil if OBJECT is a char table.
1709 A char table is a table that maps characters (or ranges of characters)
1710 to values. Char tables are specialized for characters, only allowing
1711 particular sorts of ranges to be assigned values. Although this
1712 loses in generality, it makes for extremely fast (constant-time)
1713 lookups, and thus is feasible for applications that do an extremely
1714 large number of lookups (e.g. scanning a buffer for a character in
1715 a particular syntax, where a lookup in the syntax table must occur
1716 once per character).
1718 When Mule support exists, the types of ranges that can be assigned
1722 -- an entire charset
1723 -- a single row in a two-octet charset
1724 -- a single character
1726 When Mule support is not present, the types of ranges that can be
1730 -- a single character
1732 To create a char table, use `make-char-table'.
1733 To modify a char table, use `put-char-table' or `remove-char-table'.
1734 To retrieve the value for a particular character, use `get-char-table'.
1735 See also `map-char-table', `clear-char-table', `copy-char-table',
1736 `valid-char-table-type-p', `char-table-type-list',
1737 `valid-char-table-value-p', and `check-char-table-value'.
1741 return CHAR_TABLEP (object) ? Qt : Qnil;
1744 DEFUN ("char-table-type-list", Fchar_table_type_list, 0, 0, 0, /*
1745 Return a list of the recognized char table types.
1746 See `valid-char-table-type-p'.
1751 return list5 (Qchar, Qcategory, Qdisplay, Qgeneric, Qsyntax);
1753 return list4 (Qchar, Qdisplay, Qgeneric, Qsyntax);
1757 DEFUN ("valid-char-table-type-p", Fvalid_char_table_type_p, 1, 1, 0, /*
1758 Return t if TYPE if a recognized char table type.
1760 Each char table type is used for a different purpose and allows different
1761 sorts of values. The different char table types are
1764 Used for category tables, which specify the regexp categories
1765 that a character is in. The valid values are nil or a
1766 bit vector of 95 elements. Higher-level Lisp functions are
1767 provided for working with category tables. Currently categories
1768 and category tables only exist when Mule support is present.
1770 A generalized char table, for mapping from one character to
1771 another. Used for case tables, syntax matching tables,
1772 `keyboard-translate-table', etc. The valid values are characters.
1774 An even more generalized char table, for mapping from a
1775 character to anything.
1777 Used for display tables, which specify how a particular character
1778 is to appear when displayed. #### Not yet implemented.
1780 Used for syntax tables, which specify the syntax of a particular
1781 character. Higher-level Lisp functions are provided for
1782 working with syntax tables. The valid values are integers.
1787 return (EQ (type, Qchar) ||
1789 EQ (type, Qcategory) ||
1791 EQ (type, Qdisplay) ||
1792 EQ (type, Qgeneric) ||
1793 EQ (type, Qsyntax)) ? Qt : Qnil;
1796 DEFUN ("char-table-type", Fchar_table_type, 1, 1, 0, /*
1797 Return the type of CHAR-TABLE.
1798 See `valid-char-table-type-p'.
1802 CHECK_CHAR_TABLE (char_table);
1803 return char_table_type_to_symbol (XCHAR_TABLE (char_table)->type);
1807 fill_char_table (Lisp_Char_Table *ct, Lisp_Object value)
1810 ct->table = Qunbound;
1811 ct->default_value = value;
1816 for (i = 0; i < NUM_ASCII_CHARS; i++)
1817 ct->ascii[i] = value;
1819 for (i = 0; i < NUM_LEADING_BYTES; i++)
1820 ct->level1[i] = value;
1825 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
1826 update_syntax_table (ct);
1830 DEFUN ("reset-char-table", Freset_char_table, 1, 1, 0, /*
1831 Reset CHAR-TABLE to its default state.
1835 Lisp_Char_Table *ct;
1837 CHECK_CHAR_TABLE (char_table);
1838 ct = XCHAR_TABLE (char_table);
1842 case CHAR_TABLE_TYPE_CHAR:
1843 fill_char_table (ct, make_char (0));
1845 case CHAR_TABLE_TYPE_DISPLAY:
1846 case CHAR_TABLE_TYPE_GENERIC:
1848 case CHAR_TABLE_TYPE_CATEGORY:
1850 fill_char_table (ct, Qnil);
1853 case CHAR_TABLE_TYPE_SYNTAX:
1854 fill_char_table (ct, make_int (Sinherit));
1864 DEFUN ("make-char-table", Fmake_char_table, 1, 1, 0, /*
1865 Return a new, empty char table of type TYPE.
1866 Currently recognized types are 'char, 'category, 'display, 'generic,
1867 and 'syntax. See `valid-char-table-type-p'.
1871 Lisp_Char_Table *ct;
1873 enum char_table_type ty = symbol_to_char_table_type (type);
1875 ct = alloc_lcrecord_type (Lisp_Char_Table, &lrecord_char_table);
1878 if (ty == CHAR_TABLE_TYPE_SYNTAX)
1880 ct->mirror_table = Fmake_char_table (Qgeneric);
1881 fill_char_table (XCHAR_TABLE (ct->mirror_table),
1885 ct->mirror_table = Qnil;
1888 #ifndef HAVE_LIBCHISE
1892 ct->next_table = Qnil;
1893 XSETCHAR_TABLE (obj, ct);
1894 if (ty == CHAR_TABLE_TYPE_SYNTAX)
1896 ct->next_table = Vall_syntax_tables;
1897 Vall_syntax_tables = obj;
1899 Freset_char_table (obj);
1903 #if defined(MULE)&&!defined(UTF2000)
1906 make_char_table_entry (Lisp_Object initval)
1910 Lisp_Char_Table_Entry *cte =
1911 alloc_lcrecord_type (Lisp_Char_Table_Entry, &lrecord_char_table_entry);
1913 for (i = 0; i < 96; i++)
1914 cte->level2[i] = initval;
1916 XSETCHAR_TABLE_ENTRY (obj, cte);
1921 copy_char_table_entry (Lisp_Object entry)
1923 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (entry);
1926 Lisp_Char_Table_Entry *ctenew =
1927 alloc_lcrecord_type (Lisp_Char_Table_Entry, &lrecord_char_table_entry);
1929 for (i = 0; i < 96; i++)
1931 Lisp_Object new = cte->level2[i];
1932 if (CHAR_TABLE_ENTRYP (new))
1933 ctenew->level2[i] = copy_char_table_entry (new);
1935 ctenew->level2[i] = new;
1938 XSETCHAR_TABLE_ENTRY (obj, ctenew);
1944 DEFUN ("copy-char-table", Fcopy_char_table, 1, 1, 0, /*
1945 Return a new char table which is a copy of CHAR-TABLE.
1946 It will contain the same values for the same characters and ranges
1947 as CHAR-TABLE. The values will not themselves be copied.
1951 Lisp_Char_Table *ct, *ctnew;
1957 CHECK_CHAR_TABLE (char_table);
1958 ct = XCHAR_TABLE (char_table);
1959 ctnew = alloc_lcrecord_type (Lisp_Char_Table, &lrecord_char_table);
1960 ctnew->type = ct->type;
1962 ctnew->default_value = ct->default_value;
1963 /* [tomo:2002-01-21] Perhaps this code seems wrong */
1964 ctnew->name = ct->name;
1965 #ifndef HAVE_LIBCHISE
1969 if (UINT8_BYTE_TABLE_P (ct->table))
1971 ctnew->table = copy_uint8_byte_table (ct->table);
1973 else if (UINT16_BYTE_TABLE_P (ct->table))
1975 ctnew->table = copy_uint16_byte_table (ct->table);
1977 else if (BYTE_TABLE_P (ct->table))
1979 ctnew->table = copy_byte_table (ct->table);
1981 else if (!UNBOUNDP (ct->table))
1982 ctnew->table = ct->table;
1983 #else /* non UTF2000 */
1985 for (i = 0; i < NUM_ASCII_CHARS; i++)
1987 Lisp_Object new = ct->ascii[i];
1989 assert (! (CHAR_TABLE_ENTRYP (new)));
1991 ctnew->ascii[i] = new;
1996 for (i = 0; i < NUM_LEADING_BYTES; i++)
1998 Lisp_Object new = ct->level1[i];
1999 if (CHAR_TABLE_ENTRYP (new))
2000 ctnew->level1[i] = copy_char_table_entry (new);
2002 ctnew->level1[i] = new;
2006 #endif /* non UTF2000 */
2009 if (CHAR_TABLEP (ct->mirror_table))
2010 ctnew->mirror_table = Fcopy_char_table (ct->mirror_table);
2012 ctnew->mirror_table = ct->mirror_table;
2014 ctnew->next_table = Qnil;
2015 XSETCHAR_TABLE (obj, ctnew);
2016 if (ctnew->type == CHAR_TABLE_TYPE_SYNTAX)
2018 ctnew->next_table = Vall_syntax_tables;
2019 Vall_syntax_tables = obj;
2024 INLINE_HEADER int XCHARSET_CELL_RANGE (Lisp_Object ccs);
2026 XCHARSET_CELL_RANGE (Lisp_Object ccs)
2028 switch (XCHARSET_CHARS (ccs))
2031 return (33 << 8) | 126;
2033 return (32 << 8) | 127;
2036 return (0 << 8) | 127;
2038 return (0 << 8) | 255;
2050 decode_char_table_range (Lisp_Object range, struct chartab_range *outrange)
2053 outrange->type = CHARTAB_RANGE_ALL;
2055 else if (EQ (range, Qnil))
2056 outrange->type = CHARTAB_RANGE_DEFAULT;
2058 else if (CHAR_OR_CHAR_INTP (range))
2060 outrange->type = CHARTAB_RANGE_CHAR;
2061 outrange->ch = XCHAR_OR_CHAR_INT (range);
2065 signal_simple_error ("Range must be t or a character", range);
2067 else if (VECTORP (range))
2069 Lisp_Vector *vec = XVECTOR (range);
2070 Lisp_Object *elts = vector_data (vec);
2071 int cell_min, cell_max;
2073 outrange->type = CHARTAB_RANGE_ROW;
2074 outrange->charset = Fget_charset (elts[0]);
2075 CHECK_INT (elts[1]);
2076 outrange->row = XINT (elts[1]);
2077 if (XCHARSET_DIMENSION (outrange->charset) < 2)
2078 signal_simple_error ("Charset in row vector must be multi-byte",
2082 int ret = XCHARSET_CELL_RANGE (outrange->charset);
2084 cell_min = ret >> 8;
2085 cell_max = ret & 0xFF;
2087 if (XCHARSET_DIMENSION (outrange->charset) == 2)
2088 check_int_range (outrange->row, cell_min, cell_max);
2090 else if (XCHARSET_DIMENSION (outrange->charset) == 3)
2092 check_int_range (outrange->row >> 8 , cell_min, cell_max);
2093 check_int_range (outrange->row & 0xFF, cell_min, cell_max);
2095 else if (XCHARSET_DIMENSION (outrange->charset) == 4)
2097 check_int_range ( outrange->row >> 16 , cell_min, cell_max);
2098 check_int_range ((outrange->row >> 8) & 0xFF, cell_min, cell_max);
2099 check_int_range ( outrange->row & 0xFF, cell_min, cell_max);
2107 if (!CHARSETP (range) && !SYMBOLP (range))
2109 ("Char table range must be t, charset, char, or vector", range);
2110 outrange->type = CHARTAB_RANGE_CHARSET;
2111 outrange->charset = Fget_charset (range);
2116 #if defined(MULE)&&!defined(UTF2000)
2118 /* called from CHAR_TABLE_VALUE(). */
2120 get_non_ascii_char_table_value (Lisp_Char_Table *ct, Charset_ID leading_byte,
2125 Lisp_Object charset;
2127 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (leading_byte);
2132 BREAKUP_CHAR (c, charset, byte1, byte2);
2134 BREAKUP_CHAR_1_UNSAFE (c, charset, byte1, byte2);
2136 val = ct->level1[leading_byte - MIN_LEADING_BYTE];
2137 if (CHAR_TABLE_ENTRYP (val))
2139 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2140 val = cte->level2[byte1 - 32];
2141 if (CHAR_TABLE_ENTRYP (val))
2143 cte = XCHAR_TABLE_ENTRY (val);
2144 assert (byte2 >= 32);
2145 val = cte->level2[byte2 - 32];
2146 assert (!CHAR_TABLE_ENTRYP (val));
2156 get_char_table (Emchar ch, Lisp_Char_Table *ct)
2160 Lisp_Object ret = get_char_id_table (ct, ch);
2165 if (EQ (CHAR_TABLE_NAME (ct), Qdowncase))
2166 ret = Fchar_feature (make_char (ch), Q_lowercase, Qnil,
2168 else if (EQ (CHAR_TABLE_NAME (ct), Qflippedcase))
2169 ret = Fchar_feature (make_char (ch), Q_uppercase, Qnil,
2175 ret = Ffind_char (ret);
2183 Lisp_Object charset;
2187 BREAKUP_CHAR (ch, charset, byte1, byte2);
2189 if (EQ (charset, Vcharset_ascii))
2190 val = ct->ascii[byte1];
2191 else if (EQ (charset, Vcharset_control_1))
2192 val = ct->ascii[byte1 + 128];
2195 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
2196 val = ct->level1[lb];
2197 if (CHAR_TABLE_ENTRYP (val))
2199 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2200 val = cte->level2[byte1 - 32];
2201 if (CHAR_TABLE_ENTRYP (val))
2203 cte = XCHAR_TABLE_ENTRY (val);
2204 assert (byte2 >= 32);
2205 val = cte->level2[byte2 - 32];
2206 assert (!CHAR_TABLE_ENTRYP (val));
2213 #else /* not MULE */
2214 return ct->ascii[(unsigned char)ch];
2215 #endif /* not MULE */
2219 DEFUN ("get-char-table", Fget_char_table, 2, 2, 0, /*
2220 Find value for CHARACTER in CHAR-TABLE.
2222 (character, char_table))
2224 CHECK_CHAR_TABLE (char_table);
2225 CHECK_CHAR_COERCE_INT (character);
2227 return get_char_table (XCHAR (character), XCHAR_TABLE (char_table));
2230 DEFUN ("get-range-char-table", Fget_range_char_table, 2, 3, 0, /*
2231 Find value for a range in CHAR-TABLE.
2232 If there is more than one value, return MULTI (defaults to nil).
2234 (range, char_table, multi))
2236 Lisp_Char_Table *ct;
2237 struct chartab_range rainj;
2239 if (CHAR_OR_CHAR_INTP (range))
2240 return Fget_char_table (range, char_table);
2241 CHECK_CHAR_TABLE (char_table);
2242 ct = XCHAR_TABLE (char_table);
2244 decode_char_table_range (range, &rainj);
2247 case CHARTAB_RANGE_ALL:
2250 if (UINT8_BYTE_TABLE_P (ct->table))
2252 else if (UINT16_BYTE_TABLE_P (ct->table))
2254 else if (BYTE_TABLE_P (ct->table))
2258 #else /* non UTF2000 */
2260 Lisp_Object first = ct->ascii[0];
2262 for (i = 1; i < NUM_ASCII_CHARS; i++)
2263 if (!EQ (first, ct->ascii[i]))
2267 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
2270 if (!CHARSETP (CHARSET_BY_LEADING_BYTE (i))
2271 || i == LEADING_BYTE_ASCII
2272 || i == LEADING_BYTE_CONTROL_1)
2274 if (!EQ (first, ct->level1[i - MIN_LEADING_BYTE]))
2280 #endif /* non UTF2000 */
2284 case CHARTAB_RANGE_CHARSET:
2288 if (EQ (rainj.charset, Vcharset_ascii))
2291 Lisp_Object first = ct->ascii[0];
2293 for (i = 1; i < 128; i++)
2294 if (!EQ (first, ct->ascii[i]))
2299 if (EQ (rainj.charset, Vcharset_control_1))
2302 Lisp_Object first = ct->ascii[128];
2304 for (i = 129; i < 160; i++)
2305 if (!EQ (first, ct->ascii[i]))
2311 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
2313 if (CHAR_TABLE_ENTRYP (val))
2319 case CHARTAB_RANGE_ROW:
2324 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
2326 if (!CHAR_TABLE_ENTRYP (val))
2328 val = XCHAR_TABLE_ENTRY (val)->level2[rainj.row - 32];
2329 if (CHAR_TABLE_ENTRYP (val))
2333 #endif /* not UTF2000 */
2334 #endif /* not MULE */
2337 case CHARTAB_RANGE_DEFAULT:
2338 return ct->default_value;
2339 #endif /* not UTF2000 */
2345 return Qnil; /* not reached */
2349 check_valid_char_table_value (Lisp_Object value, enum char_table_type type,
2350 Error_behavior errb)
2354 case CHAR_TABLE_TYPE_SYNTAX:
2355 if (!ERRB_EQ (errb, ERROR_ME))
2356 return INTP (value) || (CONSP (value) && INTP (XCAR (value))
2357 && CHAR_OR_CHAR_INTP (XCDR (value)));
2360 Lisp_Object cdr = XCDR (value);
2361 CHECK_INT (XCAR (value));
2362 CHECK_CHAR_COERCE_INT (cdr);
2369 case CHAR_TABLE_TYPE_CATEGORY:
2370 if (!ERRB_EQ (errb, ERROR_ME))
2371 return CATEGORY_TABLE_VALUEP (value);
2372 CHECK_CATEGORY_TABLE_VALUE (value);
2376 case CHAR_TABLE_TYPE_GENERIC:
2379 case CHAR_TABLE_TYPE_DISPLAY:
2381 maybe_signal_simple_error ("Display char tables not yet implemented",
2382 value, Qchar_table, errb);
2385 case CHAR_TABLE_TYPE_CHAR:
2386 if (!ERRB_EQ (errb, ERROR_ME))
2387 return CHAR_OR_CHAR_INTP (value);
2388 CHECK_CHAR_COERCE_INT (value);
2395 return 0; /* not reached */
2399 canonicalize_char_table_value (Lisp_Object value, enum char_table_type type)
2403 case CHAR_TABLE_TYPE_SYNTAX:
2406 Lisp_Object car = XCAR (value);
2407 Lisp_Object cdr = XCDR (value);
2408 CHECK_CHAR_COERCE_INT (cdr);
2409 return Fcons (car, cdr);
2412 case CHAR_TABLE_TYPE_CHAR:
2413 CHECK_CHAR_COERCE_INT (value);
2421 DEFUN ("valid-char-table-value-p", Fvalid_char_table_value_p, 2, 2, 0, /*
2422 Return non-nil if VALUE is a valid value for CHAR-TABLE-TYPE.
2424 (value, char_table_type))
2426 enum char_table_type type = symbol_to_char_table_type (char_table_type);
2428 return check_valid_char_table_value (value, type, ERROR_ME_NOT) ? Qt : Qnil;
2431 DEFUN ("check-valid-char-table-value", Fcheck_valid_char_table_value, 2, 2, 0, /*
2432 Signal an error if VALUE is not a valid value for CHAR-TABLE-TYPE.
2434 (value, char_table_type))
2436 enum char_table_type type = symbol_to_char_table_type (char_table_type);
2438 check_valid_char_table_value (value, type, ERROR_ME);
2443 Lisp_Char_Table* char_attribute_table_to_put;
2444 Lisp_Object Qput_char_table_map_function;
2445 Lisp_Object value_to_put;
2447 DEFUN ("put-char-table-map-function",
2448 Fput_char_table_map_function, 2, 2, 0, /*
2449 For internal use. Don't use it.
2453 put_char_id_table_0 (char_attribute_table_to_put,
2454 XCHAR (c), value_to_put);
2459 /* Assign VAL to all characters in RANGE in char table CT. */
2462 put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
2465 switch (range->type)
2467 case CHARTAB_RANGE_ALL:
2468 fill_char_table (ct, val);
2469 return; /* avoid the duplicate call to update_syntax_table() below,
2470 since fill_char_table() also did that. */
2473 case CHARTAB_RANGE_DEFAULT:
2474 ct->default_value = val;
2479 case CHARTAB_RANGE_CHARSET:
2482 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (range->charset);
2484 if ( CHAR_TABLEP (encoding_table) )
2486 Lisp_Object mother = XCHARSET_MOTHER (range->charset);
2488 char_attribute_table_to_put = ct;
2490 Fmap_char_attribute (Qput_char_table_map_function,
2491 XCHAR_TABLE_NAME (encoding_table),
2493 if ( CHARSETP (mother) )
2495 struct chartab_range r;
2497 r.type = CHARTAB_RANGE_CHARSET;
2499 put_char_table (ct, &r, val);
2507 for (c = 0; c < 1 << 24; c++)
2509 if ( charset_code_point (range->charset, c) >= 0 )
2510 put_char_id_table_0 (ct, c, val);
2516 if (EQ (range->charset, Vcharset_ascii))
2519 for (i = 0; i < 128; i++)
2522 else if (EQ (range->charset, Vcharset_control_1))
2525 for (i = 128; i < 160; i++)
2530 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
2531 ct->level1[lb] = val;
2536 case CHARTAB_RANGE_ROW:
2539 int cell_min, cell_max, i;
2541 i = XCHARSET_CELL_RANGE (range->charset);
2543 cell_max = i & 0xFF;
2544 for (i = cell_min; i <= cell_max; i++)
2547 = DECODE_CHAR (range->charset, (range->row << 8) | i, 0);
2549 if ( charset_code_point (range->charset, ch, 0) >= 0 )
2550 put_char_id_table_0 (ct, ch, val);
2555 Lisp_Char_Table_Entry *cte;
2556 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
2557 /* make sure that there is a separate entry for the row. */
2558 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
2559 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
2560 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
2561 cte->level2[range->row - 32] = val;
2563 #endif /* not UTF2000 */
2567 case CHARTAB_RANGE_CHAR:
2569 put_char_id_table_0 (ct, range->ch, val);
2573 Lisp_Object charset;
2576 BREAKUP_CHAR (range->ch, charset, byte1, byte2);
2577 if (EQ (charset, Vcharset_ascii))
2578 ct->ascii[byte1] = val;
2579 else if (EQ (charset, Vcharset_control_1))
2580 ct->ascii[byte1 + 128] = val;
2583 Lisp_Char_Table_Entry *cte;
2584 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
2585 /* make sure that there is a separate entry for the row. */
2586 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
2587 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
2588 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
2589 /* now CTE is a char table entry for the charset;
2590 each entry is for a single row (or character of
2591 a one-octet charset). */
2592 if (XCHARSET_DIMENSION (charset) == 1)
2593 cte->level2[byte1 - 32] = val;
2596 /* assigning to one character in a two-octet charset. */
2597 /* make sure that the charset row contains a separate
2598 entry for each character. */
2599 if (!CHAR_TABLE_ENTRYP (cte->level2[byte1 - 32]))
2600 cte->level2[byte1 - 32] =
2601 make_char_table_entry (cte->level2[byte1 - 32]);
2602 cte = XCHAR_TABLE_ENTRY (cte->level2[byte1 - 32]);
2603 cte->level2[byte2 - 32] = val;
2607 #else /* not MULE */
2608 ct->ascii[(unsigned char) (range->ch)] = val;
2610 #endif /* not MULE */
2614 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
2615 update_syntax_table (ct);
2619 DEFUN ("put-char-table", Fput_char_table, 3, 3, 0, /*
2620 Set the value for chars in RANGE to be VALUE in CHAR-TABLE.
2622 RANGE specifies one or more characters to be affected and should be
2623 one of the following:
2625 -- t (all characters are affected)
2626 -- A charset (only allowed when Mule support is present)
2627 -- A vector of two elements: a two-octet charset and a row number
2628 (only allowed when Mule support is present)
2629 -- A single character
2631 VALUE must be a value appropriate for the type of CHAR-TABLE.
2632 See `valid-char-table-type-p'.
2634 (range, value, char_table))
2636 Lisp_Char_Table *ct;
2637 struct chartab_range rainj;
2639 CHECK_CHAR_TABLE (char_table);
2640 ct = XCHAR_TABLE (char_table);
2641 check_valid_char_table_value (value, ct->type, ERROR_ME);
2642 decode_char_table_range (range, &rainj);
2643 value = canonicalize_char_table_value (value, ct->type);
2644 put_char_table (ct, &rainj, value);
2649 /* Map FN over the ASCII chars in CT. */
2652 map_over_charset_ascii (Lisp_Char_Table *ct,
2653 int (*fn) (struct chartab_range *range,
2654 Lisp_Object val, void *arg),
2657 struct chartab_range rainj;
2666 rainj.type = CHARTAB_RANGE_CHAR;
2668 for (i = start, retval = 0; i < stop && retval == 0; i++)
2670 rainj.ch = (Emchar) i;
2671 retval = (fn) (&rainj, ct->ascii[i], arg);
2679 /* Map FN over the Control-1 chars in CT. */
2682 map_over_charset_control_1 (Lisp_Char_Table *ct,
2683 int (*fn) (struct chartab_range *range,
2684 Lisp_Object val, void *arg),
2687 struct chartab_range rainj;
2690 int stop = start + 32;
2692 rainj.type = CHARTAB_RANGE_CHAR;
2694 for (i = start, retval = 0; i < stop && retval == 0; i++)
2696 rainj.ch = (Emchar) (i);
2697 retval = (fn) (&rainj, ct->ascii[i], arg);
2703 /* Map FN over the row ROW of two-byte charset CHARSET.
2704 There must be a separate value for that row in the char table.
2705 CTE specifies the char table entry for CHARSET. */
2708 map_over_charset_row (Lisp_Char_Table_Entry *cte,
2709 Lisp_Object charset, int row,
2710 int (*fn) (struct chartab_range *range,
2711 Lisp_Object val, void *arg),
2714 Lisp_Object val = cte->level2[row - 32];
2716 if (!CHAR_TABLE_ENTRYP (val))
2718 struct chartab_range rainj;
2720 rainj.type = CHARTAB_RANGE_ROW;
2721 rainj.charset = charset;
2723 return (fn) (&rainj, val, arg);
2727 struct chartab_range rainj;
2729 int charset94_p = (XCHARSET_CHARS (charset) == 94);
2730 int start = charset94_p ? 33 : 32;
2731 int stop = charset94_p ? 127 : 128;
2733 cte = XCHAR_TABLE_ENTRY (val);
2735 rainj.type = CHARTAB_RANGE_CHAR;
2737 for (i = start, retval = 0; i < stop && retval == 0; i++)
2739 rainj.ch = MAKE_CHAR (charset, row, i);
2740 retval = (fn) (&rainj, cte->level2[i - 32], arg);
2748 map_over_other_charset (Lisp_Char_Table *ct, Charset_ID lb,
2749 int (*fn) (struct chartab_range *range,
2750 Lisp_Object val, void *arg),
2753 Lisp_Object val = ct->level1[lb - MIN_LEADING_BYTE];
2754 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (lb);
2756 if (!CHARSETP (charset)
2757 || lb == LEADING_BYTE_ASCII
2758 || lb == LEADING_BYTE_CONTROL_1)
2761 if (!CHAR_TABLE_ENTRYP (val))
2763 struct chartab_range rainj;
2765 rainj.type = CHARTAB_RANGE_CHARSET;
2766 rainj.charset = charset;
2767 return (fn) (&rainj, val, arg);
2771 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2772 int charset94_p = (XCHARSET_CHARS (charset) == 94);
2773 int start = charset94_p ? 33 : 32;
2774 int stop = charset94_p ? 127 : 128;
2777 if (XCHARSET_DIMENSION (charset) == 1)
2779 struct chartab_range rainj;
2780 rainj.type = CHARTAB_RANGE_CHAR;
2782 for (i = start, retval = 0; i < stop && retval == 0; i++)
2784 rainj.ch = MAKE_CHAR (charset, i, 0);
2785 retval = (fn) (&rainj, cte->level2[i - 32], arg);
2790 for (i = start, retval = 0; i < stop && retval == 0; i++)
2791 retval = map_over_charset_row (cte, charset, i, fn, arg);
2799 #endif /* not UTF2000 */
2802 struct map_char_table_for_charset_arg
2804 int (*fn) (struct chartab_range *range, Lisp_Object val, void *arg);
2805 Lisp_Char_Table *ct;
2810 map_char_table_for_charset_fun (struct chartab_range *range,
2811 Lisp_Object val, void *arg)
2813 struct map_char_table_for_charset_arg *closure =
2814 (struct map_char_table_for_charset_arg *) arg;
2817 switch (range->type)
2819 case CHARTAB_RANGE_ALL:
2822 case CHARTAB_RANGE_DEFAULT:
2825 case CHARTAB_RANGE_CHARSET:
2828 case CHARTAB_RANGE_ROW:
2831 case CHARTAB_RANGE_CHAR:
2832 ret = get_char_table (range->ch, closure->ct);
2833 if (!UNBOUNDP (ret))
2834 return (closure->fn) (range, ret, closure->arg);
2846 /* Map FN (with client data ARG) over range RANGE in char table CT.
2847 Mapping stops the first time FN returns non-zero, and that value
2848 becomes the return value of map_char_table(). */
2851 map_char_table (Lisp_Char_Table *ct,
2852 struct chartab_range *range,
2853 int (*fn) (struct chartab_range *range,
2854 Lisp_Object val, void *arg),
2857 switch (range->type)
2859 case CHARTAB_RANGE_ALL:
2861 if (!UNBOUNDP (ct->default_value))
2863 struct chartab_range rainj;
2866 rainj.type = CHARTAB_RANGE_DEFAULT;
2867 retval = (fn) (&rainj, ct->default_value, arg);
2871 if (UINT8_BYTE_TABLE_P (ct->table))
2872 return map_over_uint8_byte_table (XUINT8_BYTE_TABLE(ct->table), ct,
2874 else if (UINT16_BYTE_TABLE_P (ct->table))
2875 return map_over_uint16_byte_table (XUINT16_BYTE_TABLE(ct->table), ct,
2877 else if (BYTE_TABLE_P (ct->table))
2878 return map_over_byte_table (XBYTE_TABLE(ct->table), ct,
2880 else if (EQ (ct->table, Qunloaded))
2883 struct chartab_range rainj;
2886 Emchar c1 = c + unit;
2889 rainj.type = CHARTAB_RANGE_CHAR;
2891 for (retval = 0; c < c1 && retval == 0; c++)
2893 Lisp_Object ret = get_char_id_table (ct, c);
2895 if (!UNBOUNDP (ret))
2898 retval = (fn) (&rainj, ct->table, arg);
2903 ct->table = Qunbound;
2906 else if (!UNBOUNDP (ct->table))
2907 return (fn) (range, ct->table, arg);
2913 retval = map_over_charset_ascii (ct, fn, arg);
2917 retval = map_over_charset_control_1 (ct, fn, arg);
2922 Charset_ID start = MIN_LEADING_BYTE;
2923 Charset_ID stop = start + NUM_LEADING_BYTES;
2925 for (i = start, retval = 0; i < stop && retval == 0; i++)
2927 retval = map_over_other_charset (ct, i, fn, arg);
2936 case CHARTAB_RANGE_DEFAULT:
2937 if (!UNBOUNDP (ct->default_value))
2938 return (fn) (range, ct->default_value, arg);
2943 case CHARTAB_RANGE_CHARSET:
2946 Lisp_Object encoding_table
2947 = XCHARSET_ENCODING_TABLE (range->charset);
2949 if (!NILP (encoding_table))
2951 struct chartab_range rainj;
2952 struct map_char_table_for_charset_arg mcarg;
2955 if (XCHAR_TABLE_UNLOADED(encoding_table))
2956 Fload_char_attribute_table (XCHAR_TABLE_NAME (encoding_table));
2961 rainj.type = CHARTAB_RANGE_ALL;
2962 return map_char_table (XCHAR_TABLE(encoding_table),
2964 &map_char_table_for_charset_fun,
2970 return map_over_other_charset (ct,
2971 XCHARSET_LEADING_BYTE (range->charset),
2975 case CHARTAB_RANGE_ROW:
2978 int cell_min, cell_max, i;
2980 struct chartab_range rainj;
2982 i = XCHARSET_CELL_RANGE (range->charset);
2984 cell_max = i & 0xFF;
2985 rainj.type = CHARTAB_RANGE_CHAR;
2986 for (retval =0, i = cell_min; i <= cell_max && retval == 0; i++)
2989 = DECODE_CHAR (range->charset, (range->row << 8) | i, 0);
2991 if ( charset_code_point (range->charset, ch, 0) >= 0 )
2994 = get_byte_table (get_byte_table
2998 (unsigned char)(ch >> 24)),
2999 (unsigned char) (ch >> 16)),
3000 (unsigned char) (ch >> 8)),
3001 (unsigned char) ch);
3004 val = ct->default_value;
3006 retval = (fn) (&rainj, val, arg);
3013 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (range->charset)
3014 - MIN_LEADING_BYTE];
3015 if (!CHAR_TABLE_ENTRYP (val))
3017 struct chartab_range rainj;
3019 rainj.type = CHARTAB_RANGE_ROW;
3020 rainj.charset = range->charset;
3021 rainj.row = range->row;
3022 return (fn) (&rainj, val, arg);
3025 return map_over_charset_row (XCHAR_TABLE_ENTRY (val),
3026 range->charset, range->row,
3029 #endif /* not UTF2000 */
3032 case CHARTAB_RANGE_CHAR:
3034 Emchar ch = range->ch;
3035 Lisp_Object val = CHAR_TABLE_VALUE_UNSAFE (ct, ch);
3037 if (!UNBOUNDP (val))
3039 struct chartab_range rainj;
3041 rainj.type = CHARTAB_RANGE_CHAR;
3043 return (fn) (&rainj, val, arg);
3055 struct slow_map_char_table_arg
3057 Lisp_Object function;
3062 slow_map_char_table_fun (struct chartab_range *range,
3063 Lisp_Object val, void *arg)
3065 Lisp_Object ranjarg = Qnil;
3066 struct slow_map_char_table_arg *closure =
3067 (struct slow_map_char_table_arg *) arg;
3069 switch (range->type)
3071 case CHARTAB_RANGE_ALL:
3076 case CHARTAB_RANGE_DEFAULT:
3082 case CHARTAB_RANGE_CHARSET:
3083 ranjarg = XCHARSET_NAME (range->charset);
3086 case CHARTAB_RANGE_ROW:
3087 ranjarg = vector2 (XCHARSET_NAME (range->charset),
3088 make_int (range->row));
3091 case CHARTAB_RANGE_CHAR:
3092 ranjarg = make_char (range->ch);
3098 closure->retval = call2 (closure->function, ranjarg, val);
3099 return !NILP (closure->retval);
3102 DEFUN ("map-char-table", Fmap_char_table, 2, 3, 0, /*
3103 Map FUNCTION over entries in CHAR-TABLE, calling it with two args,
3104 each key and value in the table.
3106 RANGE specifies a subrange to map over and is in the same format as
3107 the RANGE argument to `put-range-table'. If omitted or t, it defaults to
3110 (function, char_table, range))
3112 Lisp_Char_Table *ct;
3113 struct slow_map_char_table_arg slarg;
3114 struct gcpro gcpro1, gcpro2;
3115 struct chartab_range rainj;
3117 CHECK_CHAR_TABLE (char_table);
3118 ct = XCHAR_TABLE (char_table);
3121 decode_char_table_range (range, &rainj);
3122 slarg.function = function;
3123 slarg.retval = Qnil;
3124 GCPRO2 (slarg.function, slarg.retval);
3125 map_char_table (ct, &rainj, slow_map_char_table_fun, &slarg);
3128 return slarg.retval;
3132 /************************************************************************/
3133 /* Character Attributes */
3134 /************************************************************************/
3138 Lisp_Object Vchar_attribute_hash_table;
3140 /* We store the char-attributes in hash tables with the names as the
3141 key and the actual char-id-table object as the value. Occasionally
3142 we need to use them in a list format. These routines provide us
3144 struct char_attribute_list_closure
3146 Lisp_Object *char_attribute_list;
3150 add_char_attribute_to_list_mapper (Lisp_Object key, Lisp_Object value,
3151 void *char_attribute_list_closure)
3153 /* This function can GC */
3154 struct char_attribute_list_closure *calcl
3155 = (struct char_attribute_list_closure*) char_attribute_list_closure;
3156 Lisp_Object *char_attribute_list = calcl->char_attribute_list;
3158 *char_attribute_list = Fcons (key, *char_attribute_list);
3162 #ifdef HAVE_LIBCHISE
3164 char_attribute_list_reset_map_func (CHISE_DS *ds, unsigned char *name)
3166 Fmount_char_attribute_table (intern (name));
3170 DEFUN ("char-attribute-list", Fchar_attribute_list, 0, 1, 0, /*
3171 Return the list of all existing character attributes except coded-charsets.
3175 DEFUN ("char-attribute-list", Fchar_attribute_list, 0, 0, 0, /*
3176 Return the list of all existing character attributes except coded-charsets.
3181 Lisp_Object char_attribute_list = Qnil;
3182 struct gcpro gcpro1;
3183 struct char_attribute_list_closure char_attribute_list_closure;
3185 #ifdef HAVE_LIBCHISE
3188 open_chise_data_source_maybe ();
3189 chise_ds_foreach_char_feature_name
3190 (default_chise_data_source, &char_attribute_list_reset_map_func);
3193 GCPRO1 (char_attribute_list);
3194 char_attribute_list_closure.char_attribute_list = &char_attribute_list;
3195 elisp_maphash (add_char_attribute_to_list_mapper,
3196 Vchar_attribute_hash_table,
3197 &char_attribute_list_closure);
3199 return char_attribute_list;
3202 DEFUN ("find-char-attribute-table", Ffind_char_attribute_table, 1, 1, 0, /*
3203 Return char-id-table corresponding to ATTRIBUTE.
3207 return Fgethash (attribute, Vchar_attribute_hash_table, Qnil);
3211 /* We store the char-id-tables in hash tables with the attributes as
3212 the key and the actual char-id-table object as the value. Each
3213 char-id-table stores values of an attribute corresponding with
3214 characters. Occasionally we need to get attributes of a character
3215 in a association-list format. These routines provide us with
3217 struct char_attribute_alist_closure
3220 Lisp_Object *char_attribute_alist;
3224 add_char_attribute_alist_mapper (Lisp_Object key, Lisp_Object value,
3225 void *char_attribute_alist_closure)
3227 /* This function can GC */
3228 struct char_attribute_alist_closure *caacl =
3229 (struct char_attribute_alist_closure*) char_attribute_alist_closure;
3231 = get_char_id_table (XCHAR_TABLE(value), caacl->char_id);
3232 if (!UNBOUNDP (ret))
3234 Lisp_Object *char_attribute_alist = caacl->char_attribute_alist;
3235 *char_attribute_alist
3236 = Fcons (Fcons (key, ret), *char_attribute_alist);
3241 DEFUN ("char-attribute-alist", Fchar_attribute_alist, 1, 1, 0, /*
3242 Return the alist of attributes of CHARACTER.
3246 struct gcpro gcpro1;
3247 struct char_attribute_alist_closure char_attribute_alist_closure;
3248 Lisp_Object alist = Qnil;
3250 CHECK_CHAR (character);
3253 char_attribute_alist_closure.char_id = XCHAR (character);
3254 char_attribute_alist_closure.char_attribute_alist = &alist;
3255 elisp_maphash (add_char_attribute_alist_mapper,
3256 Vchar_attribute_hash_table,
3257 &char_attribute_alist_closure);
3263 DEFUN ("get-char-attribute", Fget_char_attribute, 2, 3, 0, /*
3264 Return the value of CHARACTER's ATTRIBUTE.
3265 Return DEFAULT-VALUE if the value is not exist.
3267 (character, attribute, default_value))
3271 CHECK_CHAR (character);
3273 if (CHARSETP (attribute))
3274 attribute = XCHARSET_NAME (attribute);
3276 table = Fgethash (attribute, Vchar_attribute_hash_table,
3278 if (!UNBOUNDP (table))
3280 Lisp_Object ret = get_char_id_table (XCHAR_TABLE(table),
3282 if (!UNBOUNDP (ret))
3285 return default_value;
3289 find_char_feature_in_family (Lisp_Object character,
3290 Lisp_Object con_feature,
3291 Lisp_Object feature,
3292 Lisp_Object feature_rel_max)
3294 Lisp_Object ancestors
3295 = Fget_char_attribute (character, con_feature, Qnil);
3297 while (!NILP (ancestors))
3299 Lisp_Object ancestor = XCAR (ancestors);
3302 if (EQ (ancestor, character))
3305 ret = Fchar_feature (ancestor, feature, Qunbound,
3306 Qnil, make_int (0));
3307 if (!UNBOUNDP (ret))
3310 ancestors = XCDR (ancestors);
3312 ret = Fget_char_attribute (ancestor, Q_subsumptive_from, Qnil);
3314 ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
3316 ret = Fget_char_attribute (ancestor, Q_denotational_from, Qnil);
3318 ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
3323 DEFUN ("char-feature", Fchar_feature, 2, 5, 0, /*
3324 Return the value of CHARACTER's FEATURE.
3325 Return DEFAULT-VALUE if the value is not exist.
3327 (character, attribute, default_value,
3328 feature_rel_max, char_rel_max))
3331 = Fget_char_attribute (character, attribute, Qunbound);
3333 if (!UNBOUNDP (ret))
3336 if (NILP (feature_rel_max)
3337 || (INTP (feature_rel_max) &&
3338 XINT (feature_rel_max) > 0))
3340 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3341 Bufbyte *name_str = string_data (name);
3343 if (name_str[0] == '=' && name_str[1] == '>')
3345 Bytecount length = string_length (name) - 1;
3346 Lisp_Object map_to = make_uninit_string (length);
3348 memcpy (XSTRING_DATA (map_to) + 1, name_str + 2, length - 1);
3349 XSTRING_DATA(map_to)[0] = '=';
3350 ret = Fchar_feature (character, Fintern (map_to, Qnil),
3352 NILP (feature_rel_max)
3354 : make_int (XINT (feature_rel_max) - 1),
3356 if (!UNBOUNDP (ret))
3361 if ( !(EQ (attribute, Q_identical)) &&
3362 !(EQ (attribute, Q_subsumptive_from)) &&
3363 !(EQ (attribute, Q_denotational_from)) &&
3364 ( (NILP (char_rel_max)
3365 || (INTP (char_rel_max) &&
3366 XINT (char_rel_max) > 0)) ) )
3368 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3369 Bufbyte *name_str = string_data (name);
3371 if ( (name_str[0] != '=') || (name_str[1] == '>') )
3373 ret = find_char_feature_in_family (character, Q_identical,
3374 attribute, feature_rel_max);
3375 if (!UNBOUNDP (ret))
3378 ret = find_char_feature_in_family (character, Q_subsumptive_from,
3379 attribute, feature_rel_max);
3380 if (!UNBOUNDP (ret))
3383 ret = find_char_feature_in_family (character, Q_denotational_from,
3384 attribute, feature_rel_max);
3385 if (!UNBOUNDP (ret))
3389 return default_value;
3393 put_char_composition (Lisp_Object character, Lisp_Object value);
3395 put_char_composition (Lisp_Object character, Lisp_Object value)
3398 signal_simple_error ("Invalid value for =decomposition",
3401 if (CONSP (XCDR (value)))
3403 if (NILP (Fcdr (XCDR (value))))
3405 Lisp_Object base = XCAR (value);
3406 Lisp_Object modifier = XCAR (XCDR (value));
3410 base = make_char (XINT (base));
3411 Fsetcar (value, base);
3413 if (INTP (modifier))
3415 modifier = make_char (XINT (modifier));
3416 Fsetcar (XCDR (value), modifier);
3421 = Fchar_feature (base, Qcomposition, Qnil,
3423 Lisp_Object ret = Fassq (modifier, alist);
3426 Fput_char_attribute (base, Qcomposition,
3427 Fcons (Fcons (modifier, character),
3430 Fsetcdr (ret, character);
3432 else if (EQ (base, Qsuper))
3433 return Q_superscript_of;
3434 else if (EQ (base, Qcompat))
3437 else if (EQ (XCAR (value), Qsuper))
3438 return Qto_decomposition_at_superscript;
3441 Fintern (concat2 (build_string ("=>decomposition@"),
3442 symbol_name (XSYMBOL (XCAR (value)))),
3449 Lisp_Object v = Fcar (value);
3453 Emchar c = DECODE_CHAR (Vcharset_ucs, XINT (v), 0);
3455 = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
3460 Fput_char_attribute (make_char (c), Q_ucs_unified,
3461 Fcons (character, Qnil));
3463 else if (NILP (Fmemq (character, ret)))
3465 Fput_char_attribute (make_char (c), Q_ucs_unified,
3466 Fcons (character, ret));
3471 return Qmap_decomposition;
3475 put_char_attribute (Lisp_Object character, Lisp_Object attribute,
3478 Lisp_Object table = Fgethash (attribute,
3479 Vchar_attribute_hash_table,
3484 table = make_char_id_table (Qunbound);
3485 Fputhash (attribute, table, Vchar_attribute_hash_table);
3487 XCHAR_TABLE_NAME (table) = attribute;
3490 put_char_id_table (XCHAR_TABLE(table), character, value);
3494 DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
3495 Store CHARACTER's ATTRIBUTE with VALUE.
3497 (character, attribute, value))
3499 Lisp_Object ccs = Ffind_charset (attribute);
3501 CHECK_CHAR (character);
3505 value = put_char_ccs_code_point (character, ccs, value);
3506 attribute = XCHARSET_NAME (ccs);
3508 else if ( EQ (attribute, Qmap_decomposition) ||
3509 EQ (attribute, Q_decomposition) )
3511 attribute = put_char_composition (character, value);
3512 if ( !EQ (attribute, Qmap_decomposition) &&
3513 SYMBOLP (XCAR (value)) )
3514 value = XCDR (value);
3516 else if (EQ (attribute, Qto_ucs))
3522 signal_simple_error ("Invalid value for =>ucs", value);
3524 c = DECODE_CHAR (Vcharset_ucs, XINT (value), 0);
3526 ret = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
3529 put_char_attribute (make_char (c), Q_ucs_unified,
3531 else if (NILP (Fmemq (character, ret)))
3532 Fput_char_attribute (make_char (c), Q_ucs_unified,
3533 Fcons (character, ret));
3535 if ( EQ (attribute, Q_subsumptive) ||
3536 EQ (attribute, Q_subsumptive_from) ||
3537 EQ (attribute, Q_denotational) ||
3538 EQ (attribute, Q_denotational_from) ||
3539 EQ (attribute, Q_identical) ||
3540 EQ (attribute, Q_identical_from) ||
3541 EQ (attribute, Q_canonical) ||
3542 EQ (attribute, Q_superscript_of) ||
3543 EQ (attribute, Q_compat_of) ||
3544 EQ (attribute, Q_component) ||
3545 EQ (attribute, Q_component_of) ||
3546 !NILP (Fstring_match
3547 (build_string ("^\\(<-\\|->\\)\\("
3549 "\\|superscript\\|compat"
3550 "\\|fullwidth\\|halfwidth"
3551 "\\|simplified\\|vulgar\\|wrong"
3552 "\\|same\\|original\\|ancient"
3553 "\\|Oracle-Bones\\)[^*]*$"),
3554 Fsymbol_name (attribute),
3557 Lisp_Object rest = value;
3559 Lisp_Object rev_feature = Qnil;
3560 struct gcpro gcpro1;
3561 GCPRO1 (rev_feature);
3563 if (EQ (attribute, Q_identical))
3564 rev_feature = Q_identical_from;
3565 else if (EQ (attribute, Q_identical_from))
3566 rev_feature = Q_identical;
3567 else if (EQ (attribute, Q_subsumptive))
3568 rev_feature = Q_subsumptive_from;
3569 else if (EQ (attribute, Q_subsumptive_from))
3570 rev_feature = Q_subsumptive;
3571 else if (EQ (attribute, Q_denotational))
3572 rev_feature = Q_denotational_from;
3573 else if (EQ (attribute, Q_denotational_from))
3574 rev_feature = Q_denotational;
3575 else if (EQ (attribute, Q_component))
3576 rev_feature = Q_component_of;
3577 else if (EQ (attribute, Q_component_of))
3578 rev_feature = Q_component;
3581 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3582 Bufbyte *name_str = string_data (name);
3584 if ( (name_str[0] == '<' && name_str[1] == '-') ||
3585 (name_str[0] == '-' && name_str[1] == '>') )
3587 Bytecount length = string_length (name);
3588 Bufbyte *rev_name_str = alloca (length + 1);
3590 memcpy (rev_name_str + 2, name_str + 2, length - 2);
3591 if (name_str[0] == '<')
3593 rev_name_str[0] = '-';
3594 rev_name_str[1] = '>';
3598 rev_name_str[0] = '<';
3599 rev_name_str[1] = '-';
3601 rev_name_str[length] = 0;
3602 rev_feature = intern (rev_name_str);
3606 while (CONSP (rest))
3611 ret = Fdefine_char (ret);
3612 else if (INTP (ret))
3614 int code_point = XINT (ret);
3615 Emchar cid = DECODE_CHAR (Vcharset_ucs, code_point, 0);
3618 ret = make_char (cid);
3620 ret = make_char (code_point);
3623 if ( !NILP (ret) && !EQ (ret, character) )
3627 ffv = Fget_char_attribute (ret, rev_feature, Qnil);
3629 put_char_attribute (ret, rev_feature, list1 (character));
3630 else if (NILP (Fmemq (character, ffv)))
3633 nconc2 (Fcopy_sequence (ffv), list1 (character)));
3634 Fsetcar (rest, ret);
3641 else if ( EQ (attribute, Qideographic_structure) ||
3642 !NILP (Fstring_match
3643 (build_string ("^=>decomposition\\(\\|@[^*]+\\)$"),
3644 Fsymbol_name (attribute),
3646 value = Fcopy_sequence (Fchar_refs_simplify_char_specs (value));
3648 return put_char_attribute (character, attribute, value);
3651 DEFUN ("remove-char-attribute", Fremove_char_attribute, 2, 2, 0, /*
3652 Remove CHARACTER's ATTRIBUTE.
3654 (character, attribute))
3658 CHECK_CHAR (character);
3659 ccs = Ffind_charset (attribute);
3662 return remove_char_ccs (character, ccs);
3666 Lisp_Object table = Fgethash (attribute,
3667 Vchar_attribute_hash_table,
3669 if (!UNBOUNDP (table))
3671 put_char_id_table (XCHAR_TABLE(table), character, Qunbound);
3680 int char_table_open_db_maybe (Lisp_Char_Table* cit);
3681 void char_table_close_db_maybe (Lisp_Char_Table* cit);
3682 Lisp_Object char_table_get_db (Lisp_Char_Table* cit, Emchar ch);
3684 #ifdef HAVE_LIBCHISE
3686 open_chise_data_source_maybe ()
3688 if (default_chise_data_source == NULL)
3690 Lisp_Object db_dir = Vdata_directory;
3691 int modemask = 0755; /* rwxr-xr-x */
3694 db_dir = build_string ("../etc");
3695 db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
3697 default_chise_data_source
3698 = CHISE_DS_open (CHISE_DS_Berkeley_DB, XSTRING_DATA (db_dir),
3699 0 /* DB_HASH */, modemask);
3700 if (default_chise_data_source == NULL)
3703 chise_ds_set_make_string_function (default_chise_data_source,
3709 #endif /* HAVE_LIBCHISE */
3711 DEFUN ("close-char-data-source", Fclose_char_data_source, 0, 0, 0, /*
3712 Close data-source of CHISE.
3716 #ifdef HAVE_LIBCHISE
3717 int status = CHISE_DS_close (default_chise_data_source);
3719 default_chise_data_source = NULL;
3722 #endif /* HAVE_LIBCHISE */
3727 char_table_open_db_maybe (Lisp_Char_Table* cit)
3729 Lisp_Object attribute = CHAR_TABLE_NAME (cit);
3731 if (!NILP (attribute))
3733 #ifdef HAVE_LIBCHISE
3734 if ( open_chise_data_source_maybe () )
3736 #else /* HAVE_LIBCHISE */
3737 if (NILP (Fdatabase_live_p (cit->db)))
3740 = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
3742 cit->db = Fopen_database (db_file, Qnil, Qnil,
3743 build_string ("r"), Qnil);
3747 #endif /* not HAVE_LIBCHISE */
3755 char_table_close_db_maybe (Lisp_Char_Table* cit)
3757 #ifndef HAVE_LIBCHISE
3758 if (!NILP (cit->db))
3760 if (!NILP (Fdatabase_live_p (cit->db)))
3761 Fclose_database (cit->db);
3764 #endif /* not HAVE_LIBCHISE */
3768 char_table_get_db (Lisp_Char_Table* cit, Emchar ch)
3771 #ifdef HAVE_LIBCHISE
3774 = chise_ds_load_char_feature_value (default_chise_data_source, ch,
3775 XSTRING_DATA(Fsymbol_name
3782 val = Fread (make_string (chise_value_data (&value),
3783 chise_value_size (&value) ));
3785 val = read_from_c_string (chise_value_data (&value),
3786 chise_value_size (&value) );
3791 #else /* HAVE_LIBCHISE */
3792 val = Fget_database (Fprin1_to_string (make_char (ch), Qnil),
3794 if (!UNBOUNDP (val))
3798 #endif /* not HAVE_LIBCHISE */
3802 #ifndef HAVE_LIBCHISE
3804 char_attribute_system_db_file (Lisp_Object key_type, Lisp_Object attribute,
3807 Lisp_Object db_dir = Vdata_directory;
3810 db_dir = build_string ("../etc");
3812 db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
3813 if (writing_mode && NILP (Ffile_exists_p (db_dir)))
3814 Fmake_directory_internal (db_dir);
3816 db_dir = Fexpand_file_name (Fsymbol_name (key_type), db_dir);
3817 if (writing_mode && NILP (Ffile_exists_p (db_dir)))
3818 Fmake_directory_internal (db_dir);
3821 Lisp_Object attribute_name = Fsymbol_name (attribute);
3822 Lisp_Object dest = Qnil, ret;
3824 struct gcpro gcpro1, gcpro2;
3825 int len = XSTRING_CHAR_LENGTH (attribute_name);
3829 for (i = 0; i < len; i++)
3831 Emchar c = string_char (XSTRING (attribute_name), i);
3833 if ( (c == '/') || (c == '%') )
3837 sprintf (str, "%%%02X", c);
3838 dest = concat3 (dest,
3839 Fsubstring (attribute_name,
3840 make_int (base), make_int (i)),
3841 build_string (str));
3845 ret = Fsubstring (attribute_name, make_int (base), make_int (len));
3846 dest = concat2 (dest, ret);
3848 return Fexpand_file_name (dest, db_dir);
3851 #endif /* not HAVE_LIBCHISE */
3853 DEFUN ("save-char-attribute-table", Fsave_char_attribute_table, 1, 1, 0, /*
3854 Save values of ATTRIBUTE into database file.
3858 Lisp_Object table = Fgethash (attribute,
3859 Vchar_attribute_hash_table, Qunbound);
3860 Lisp_Char_Table *ct;
3861 #ifdef HAVE_LIBCHISE
3862 CHISE_Feature feature;
3863 #else /* HAVE_LIBCHISE */
3864 Lisp_Object db_file;
3866 #endif /* not HAVE_LIBCHISE */
3868 if (CHAR_TABLEP (table))
3869 ct = XCHAR_TABLE (table);
3873 #ifdef HAVE_LIBCHISE
3874 if ( open_chise_data_source_maybe () )
3877 = chise_ds_get_feature (default_chise_data_source,
3878 XSTRING_DATA (Fsymbol_name (attribute)));
3879 #else /* HAVE_LIBCHISE */
3880 db_file = char_attribute_system_db_file (Qsystem_char_id, attribute, 1);
3881 db = Fopen_database (db_file, Qnil, Qnil, build_string ("w+"), Qnil);
3882 #endif /* not HAVE_LIBCHISE */
3884 #ifdef HAVE_LIBCHISE
3886 #else /* HAVE_LIBCHISE */
3888 #endif /* not HAVE_LIBCHISE */
3891 Lisp_Object (*filter)(Lisp_Object value);
3893 if ( !NILP (Ffind_charset (attribute)) )
3895 else if ( EQ (attribute, Qideographic_structure) ||
3896 EQ (attribute, Q_identical) ||
3897 EQ (attribute, Q_identical_from) ||
3898 EQ (attribute, Q_canonical) ||
3899 EQ (attribute, Q_superscript_of) ||
3900 EQ (attribute, Q_compat_of) ||
3901 !NILP (Fstring_match
3902 (build_string ("^\\(<-\\|->\\)\\(simplified"
3903 "\\|same\\|vulgar\\|wrong"
3904 "\\|original\\|ancient"
3905 "\\|Oracle-Bones\\)[^*]*$"),
3906 Fsymbol_name (attribute),
3908 filter = &Fchar_refs_simplify_char_specs;
3912 if (UINT8_BYTE_TABLE_P (ct->table))
3913 save_uint8_byte_table (XUINT8_BYTE_TABLE(ct->table), ct,
3914 #ifdef HAVE_LIBCHISE
3916 #else /* HAVE_LIBCHISE */
3918 #endif /* not HAVE_LIBCHISE */
3920 else if (UINT16_BYTE_TABLE_P (ct->table))
3921 save_uint16_byte_table (XUINT16_BYTE_TABLE(ct->table), ct,
3922 #ifdef HAVE_LIBCHISE
3924 #else /* HAVE_LIBCHISE */
3926 #endif /* not HAVE_LIBCHISE */
3928 else if (BYTE_TABLE_P (ct->table))
3929 save_byte_table (XBYTE_TABLE(ct->table), ct,
3930 #ifdef HAVE_LIBCHISE
3932 #else /* HAVE_LIBCHISE */
3934 #endif /* not HAVE_LIBCHISE */
3936 #ifdef HAVE_LIBCHISE
3937 chise_feature_sync (feature);
3938 #else /* HAVE_LIBCHISE */
3939 Fclose_database (db);
3940 #endif /* not HAVE_LIBCHISE */
3947 DEFUN ("mount-char-attribute-table", Fmount_char_attribute_table, 1, 1, 0, /*
3948 Mount database file on char-attribute-table ATTRIBUTE.
3952 Lisp_Object table = Fgethash (attribute,
3953 Vchar_attribute_hash_table, Qunbound);
3955 if (UNBOUNDP (table))
3957 Lisp_Char_Table *ct;
3959 table = make_char_id_table (Qunbound);
3960 Fputhash (attribute, table, Vchar_attribute_hash_table);
3961 XCHAR_TABLE_NAME(table) = attribute;
3962 ct = XCHAR_TABLE (table);
3963 ct->table = Qunloaded;
3964 XCHAR_TABLE_UNLOADED(table) = 1;
3965 #ifndef HAVE_LIBCHISE
3967 #endif /* not HAVE_LIBCHISE */
3973 DEFUN ("close-char-attribute-table", Fclose_char_attribute_table, 1, 1, 0, /*
3974 Close database of ATTRIBUTE.
3978 Lisp_Object table = Fgethash (attribute,
3979 Vchar_attribute_hash_table, Qunbound);
3980 Lisp_Char_Table *ct;
3982 if (CHAR_TABLEP (table))
3983 ct = XCHAR_TABLE (table);
3986 char_table_close_db_maybe (ct);
3990 DEFUN ("reset-char-attribute-table", Freset_char_attribute_table, 1, 1, 0, /*
3991 Reset values of ATTRIBUTE with database file.
3995 #ifdef HAVE_LIBCHISE
3996 CHISE_Feature feature
3997 = chise_ds_get_feature (default_chise_data_source,
3998 XSTRING_DATA (Fsymbol_name
4001 if (feature == NULL)
4004 if (chise_feature_setup_db (feature, 0) == 0)
4006 Lisp_Object table = Fgethash (attribute,
4007 Vchar_attribute_hash_table, Qunbound);
4008 Lisp_Char_Table *ct;
4010 chise_feature_sync (feature);
4011 if (UNBOUNDP (table))
4013 table = make_char_id_table (Qunbound);
4014 Fputhash (attribute, table, Vchar_attribute_hash_table);
4015 XCHAR_TABLE_NAME(table) = attribute;
4017 ct = XCHAR_TABLE (table);
4018 ct->table = Qunloaded;
4019 char_table_close_db_maybe (ct);
4020 XCHAR_TABLE_UNLOADED(table) = 1;
4024 Lisp_Object table = Fgethash (attribute,
4025 Vchar_attribute_hash_table, Qunbound);
4026 Lisp_Char_Table *ct;
4028 = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
4030 if (!NILP (Ffile_exists_p (db_file)))
4032 if (UNBOUNDP (table))
4034 table = make_char_id_table (Qunbound);
4035 Fputhash (attribute, table, Vchar_attribute_hash_table);
4036 XCHAR_TABLE_NAME(table) = attribute;
4038 ct = XCHAR_TABLE (table);
4039 ct->table = Qunloaded;
4040 char_table_close_db_maybe (ct);
4041 XCHAR_TABLE_UNLOADED(table) = 1;
4049 load_char_attribute_maybe (Lisp_Char_Table* cit, Emchar ch)
4051 Lisp_Object attribute = CHAR_TABLE_NAME (cit);
4053 if (!NILP (attribute))
4057 if (char_table_open_db_maybe (cit))
4060 val = char_table_get_db (cit, ch);
4062 if (!NILP (Vchar_db_stingy_mode))
4063 char_table_close_db_maybe (cit);
4070 Lisp_Char_Table* char_attribute_table_to_load;
4072 #ifdef HAVE_LIBCHISE
4074 load_char_attribute_table_map_func (CHISE_Char_ID cid,
4075 CHISE_Feature feature,
4076 CHISE_Value *value);
4078 load_char_attribute_table_map_func (CHISE_Char_ID cid,
4079 CHISE_Feature feature,
4083 Lisp_Object ret = get_char_id_table_0 (char_attribute_table_to_load, code);
4085 if (EQ (ret, Qunloaded))
4086 put_char_id_table_0 (char_attribute_table_to_load, code,
4087 Fread (make_string ((Bufbyte *) value->data,
4091 #else /* HAVE_LIBCHISE */
4092 Lisp_Object Qload_char_attribute_table_map_function;
4094 DEFUN ("load-char-attribute-table-map-function",
4095 Fload_char_attribute_table_map_function, 2, 2, 0, /*
4096 For internal use. Don't use it.
4100 Lisp_Object c = Fread (key);
4101 Emchar code = XCHAR (c);
4102 Lisp_Object ret = get_char_id_table_0 (char_attribute_table_to_load, code);
4104 if (EQ (ret, Qunloaded))
4105 put_char_id_table_0 (char_attribute_table_to_load, code, Fread (value));
4108 #endif /* not HAVE_LIBCHISE */
4110 DEFUN ("load-char-attribute-table", Fload_char_attribute_table, 1, 1, 0, /*
4111 Load values of ATTRIBUTE into database file.
4115 Lisp_Object table = Fgethash (attribute,
4116 Vchar_attribute_hash_table,
4118 if (CHAR_TABLEP (table))
4120 Lisp_Char_Table *cit = XCHAR_TABLE (table);
4122 if (char_table_open_db_maybe (cit))
4125 char_attribute_table_to_load = XCHAR_TABLE (table);
4127 struct gcpro gcpro1;
4130 #ifdef HAVE_LIBCHISE
4131 chise_feature_foreach_char_with_value
4132 (chise_ds_get_feature (default_chise_data_source,
4133 XSTRING_DATA (Fsymbol_name (cit->name))),
4134 &load_char_attribute_table_map_func);
4135 #else /* HAVE_LIBCHISE */
4136 Fmap_database (Qload_char_attribute_table_map_function, cit->db);
4137 #endif /* not HAVE_LIBCHISE */
4140 char_table_close_db_maybe (cit);
4141 XCHAR_TABLE_UNLOADED(table) = 0;
4146 #endif /* HAVE_CHISE */
4148 DEFUN ("map-char-attribute", Fmap_char_attribute, 2, 3, 0, /*
4149 Map FUNCTION over entries in ATTRIBUTE, calling it with two args,
4150 each key and value in the table.
4152 RANGE specifies a subrange to map over and is in the same format as
4153 the RANGE argument to `put-range-table'. If omitted or t, it defaults to
4156 (function, attribute, range))
4159 Lisp_Char_Table *ct;
4160 struct slow_map_char_table_arg slarg;
4161 struct gcpro gcpro1, gcpro2;
4162 struct chartab_range rainj;
4164 if (!NILP (ccs = Ffind_charset (attribute)))
4166 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
4168 if (CHAR_TABLEP (encoding_table))
4169 ct = XCHAR_TABLE (encoding_table);
4175 Lisp_Object table = Fgethash (attribute,
4176 Vchar_attribute_hash_table,
4178 if (CHAR_TABLEP (table))
4179 ct = XCHAR_TABLE (table);
4185 decode_char_table_range (range, &rainj);
4187 if (CHAR_TABLE_UNLOADED(ct))
4188 Fload_char_attribute_table (attribute);
4190 slarg.function = function;
4191 slarg.retval = Qnil;
4192 GCPRO2 (slarg.function, slarg.retval);
4193 map_char_table (ct, &rainj, slow_map_char_table_fun, &slarg);
4196 return slarg.retval;
4199 DEFUN ("define-char", Fdefine_char, 1, 1, 0, /*
4200 Store character's ATTRIBUTES.
4205 Lisp_Object code = Fcdr (Fassq (Qmap_ucs, attributes));
4206 Lisp_Object character;
4209 code = Fcdr (Fassq (Qucs, attributes));
4214 while (CONSP (rest))
4216 Lisp_Object cell = Fcar (rest);
4219 if ( !LISTP (cell) )
4220 signal_simple_error ("Invalid argument", attributes);
4222 ccs = Ffind_charset (Fcar (cell));
4228 character = Fdecode_char (ccs, cell, Qt, Qt);
4229 if (!NILP (character))
4230 goto setup_attributes;
4232 if ( (XCHARSET_FINAL (ccs) != 0) ||
4233 (XCHARSET_MAX_CODE (ccs) > 0) ||
4234 (EQ (ccs, Vcharset_chinese_big5)) )
4238 = Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
4240 character = Fdecode_char (ccs, cell, Qnil, Qt);
4241 if (!NILP (character))
4242 goto setup_attributes;
4249 int cid = XINT (Vnext_defined_char_id);
4251 if (cid <= 0xE00000)
4253 character = make_char (cid);
4254 Vnext_defined_char_id = make_int (cid + 1);
4255 goto setup_attributes;
4259 if ( (!NILP (code = Fcdr (Fassq (Qto_ucs, attributes)))) )
4262 signal_simple_error ("Invalid argument", attributes);
4264 character = make_char (XINT (code) + 0x100000);
4265 goto setup_attributes;
4270 else if (!INTP (code))
4271 signal_simple_error ("Invalid argument", attributes);
4273 character = make_char (XINT (code));
4277 while (CONSP (rest))
4279 Lisp_Object cell = Fcar (rest);
4282 signal_simple_error ("Invalid argument", attributes);
4284 Fput_char_attribute (character, Fcar (cell), Fcdr (cell));
4290 DEFUN ("find-char", Ffind_char, 1, 1, 0, /*
4291 Retrieve the character of the given ATTRIBUTES.
4295 Lisp_Object rest = attributes;
4298 while (CONSP (rest))
4300 Lisp_Object cell = Fcar (rest);
4304 signal_simple_error ("Invalid argument", attributes);
4305 if (!NILP (ccs = Ffind_charset (Fcar (cell))))
4309 return Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
4311 return Fdecode_char (ccs, cell, Qnil, Qnil);
4315 if ( (!NILP (code = Fcdr (Fassq (Qto_ucs, attributes)))) )
4318 signal_simple_error ("Invalid argument", attributes);
4320 return make_char (XINT (code) + 0x100000);
4328 /************************************************************************/
4329 /* Char table read syntax */
4330 /************************************************************************/
4333 chartab_type_validate (Lisp_Object keyword, Lisp_Object value,
4334 Error_behavior errb)
4336 /* #### should deal with ERRB */
4337 symbol_to_char_table_type (value);
4342 chartab_data_validate (Lisp_Object keyword, Lisp_Object value,
4343 Error_behavior errb)
4347 /* #### should deal with ERRB */
4348 EXTERNAL_LIST_LOOP (rest, value)
4350 Lisp_Object range = XCAR (rest);
4351 struct chartab_range dummy;
4355 signal_simple_error ("Invalid list format", value);
4358 if (!CONSP (XCDR (range))
4359 || !NILP (XCDR (XCDR (range))))
4360 signal_simple_error ("Invalid range format", range);
4361 decode_char_table_range (XCAR (range), &dummy);
4362 decode_char_table_range (XCAR (XCDR (range)), &dummy);
4365 decode_char_table_range (range, &dummy);
4372 chartab_instantiate (Lisp_Object data)
4374 Lisp_Object chartab;
4375 Lisp_Object type = Qgeneric;
4376 Lisp_Object dataval = Qnil;
4378 while (!NILP (data))
4380 Lisp_Object keyw = Fcar (data);
4386 if (EQ (keyw, Qtype))
4388 else if (EQ (keyw, Qdata))
4392 chartab = Fmake_char_table (type);
4395 while (!NILP (data))
4397 Lisp_Object range = Fcar (data);
4398 Lisp_Object val = Fcar (Fcdr (data));
4400 data = Fcdr (Fcdr (data));
4403 if (CHAR_OR_CHAR_INTP (XCAR (range)))
4405 Emchar first = XCHAR_OR_CHAR_INT (Fcar (range));
4406 Emchar last = XCHAR_OR_CHAR_INT (Fcar (Fcdr (range)));
4409 for (i = first; i <= last; i++)
4410 Fput_char_table (make_char (i), val, chartab);
4416 Fput_char_table (range, val, chartab);
4425 /************************************************************************/
4426 /* Category Tables, specifically */
4427 /************************************************************************/
4429 DEFUN ("category-table-p", Fcategory_table_p, 1, 1, 0, /*
4430 Return t if OBJECT is a category table.
4431 A category table is a type of char table used for keeping track of
4432 categories. Categories are used for classifying characters for use
4433 in regexps -- you can refer to a category rather than having to use
4434 a complicated [] expression (and category lookups are significantly
4437 There are 95 different categories available, one for each printable
4438 character (including space) in the ASCII charset. Each category
4439 is designated by one such character, called a "category designator".
4440 They are specified in a regexp using the syntax "\\cX", where X is
4441 a category designator.
4443 A category table specifies, for each character, the categories that
4444 the character is in. Note that a character can be in more than one
4445 category. More specifically, a category table maps from a character
4446 to either the value nil (meaning the character is in no categories)
4447 or a 95-element bit vector, specifying for each of the 95 categories
4448 whether the character is in that category.
4450 Special Lisp functions are provided that abstract this, so you do not
4451 have to directly manipulate bit vectors.
4455 return (CHAR_TABLEP (object) &&
4456 XCHAR_TABLE_TYPE (object) == CHAR_TABLE_TYPE_CATEGORY) ?
4461 check_category_table (Lisp_Object object, Lisp_Object default_)
4465 while (NILP (Fcategory_table_p (object)))
4466 object = wrong_type_argument (Qcategory_table_p, object);
4471 check_category_char (Emchar ch, Lisp_Object table,
4472 unsigned int designator, unsigned int not_p)
4474 REGISTER Lisp_Object temp;
4475 Lisp_Char_Table *ctbl;
4476 #ifdef ERROR_CHECK_TYPECHECK
4477 if (NILP (Fcategory_table_p (table)))
4478 signal_simple_error ("Expected category table", table);
4480 ctbl = XCHAR_TABLE (table);
4481 temp = get_char_table (ch, ctbl);
4486 return bit_vector_bit (XBIT_VECTOR (temp), designator) ? !not_p : not_p;
4489 DEFUN ("check-category-at", Fcheck_category_at, 2, 4, 0, /*
4490 Return t if category of the character at POSITION includes DESIGNATOR.
4491 Optional third arg BUFFER specifies which buffer to use, and defaults
4492 to the current buffer.
4493 Optional fourth arg CATEGORY-TABLE specifies the category table to
4494 use, and defaults to BUFFER's category table.
4496 (position, designator, buffer, category_table))
4501 struct buffer *buf = decode_buffer (buffer, 0);
4503 CHECK_INT (position);
4504 CHECK_CATEGORY_DESIGNATOR (designator);
4505 des = XCHAR (designator);
4506 ctbl = check_category_table (category_table, Vstandard_category_table);
4507 ch = BUF_FETCH_CHAR (buf, XINT (position));
4508 return check_category_char (ch, ctbl, des, 0) ? Qt : Qnil;
4511 DEFUN ("char-in-category-p", Fchar_in_category_p, 2, 3, 0, /*
4512 Return t if category of CHARACTER includes DESIGNATOR, else nil.
4513 Optional third arg CATEGORY-TABLE specifies the category table to use,
4514 and defaults to the standard category table.
4516 (character, designator, category_table))
4522 CHECK_CATEGORY_DESIGNATOR (designator);
4523 des = XCHAR (designator);
4524 CHECK_CHAR (character);
4525 ch = XCHAR (character);
4526 ctbl = check_category_table (category_table, Vstandard_category_table);
4527 return check_category_char (ch, ctbl, des, 0) ? Qt : Qnil;
4530 DEFUN ("category-table", Fcategory_table, 0, 1, 0, /*
4531 Return BUFFER's current category table.
4532 BUFFER defaults to the current buffer.
4536 return decode_buffer (buffer, 0)->category_table;
4539 DEFUN ("standard-category-table", Fstandard_category_table, 0, 0, 0, /*
4540 Return the standard category table.
4541 This is the one used for new buffers.
4545 return Vstandard_category_table;
4548 DEFUN ("copy-category-table", Fcopy_category_table, 0, 1, 0, /*
4549 Return a new category table which is a copy of CATEGORY-TABLE.
4550 CATEGORY-TABLE defaults to the standard category table.
4554 if (NILP (Vstandard_category_table))
4555 return Fmake_char_table (Qcategory);
4558 check_category_table (category_table, Vstandard_category_table);
4559 return Fcopy_char_table (category_table);
4562 DEFUN ("set-category-table", Fset_category_table, 1, 2, 0, /*
4563 Select CATEGORY-TABLE as the new category table for BUFFER.
4564 BUFFER defaults to the current buffer if omitted.
4566 (category_table, buffer))
4568 struct buffer *buf = decode_buffer (buffer, 0);
4569 category_table = check_category_table (category_table, Qnil);
4570 buf->category_table = category_table;
4571 /* Indicate that this buffer now has a specified category table. */
4572 buf->local_var_flags |= XINT (buffer_local_flags.category_table);
4573 return category_table;
4576 DEFUN ("category-designator-p", Fcategory_designator_p, 1, 1, 0, /*
4577 Return t if OBJECT is a category designator (a char in the range ' ' to '~').
4581 return CATEGORY_DESIGNATORP (object) ? Qt : Qnil;
4584 DEFUN ("category-table-value-p", Fcategory_table_value_p, 1, 1, 0, /*
4585 Return t if OBJECT is a category table value.
4586 Valid values are nil or a bit vector of size 95.
4590 return CATEGORY_TABLE_VALUEP (object) ? Qt : Qnil;
4594 #define CATEGORYP(x) \
4595 (CHARP (x) && XCHAR (x) >= 0x20 && XCHAR (x) <= 0x7E)
4597 #define CATEGORY_SET(c) \
4598 (get_char_table(c, XCHAR_TABLE(current_buffer->category_table)))
4600 /* Return 1 if CATEGORY_SET contains CATEGORY, else return 0.
4601 The faster version of `!NILP (Faref (category_set, category))'. */
4602 #define CATEGORY_MEMBER(category, category_set) \
4603 (bit_vector_bit(XBIT_VECTOR (category_set), category - 32))
4605 /* Return 1 if there is a word boundary between two word-constituent
4606 characters C1 and C2 if they appear in this order, else return 0.
4607 Use the macro WORD_BOUNDARY_P instead of calling this function
4610 int word_boundary_p (Emchar c1, Emchar c2);
4612 word_boundary_p (Emchar c1, Emchar c2)
4614 Lisp_Object category_set1, category_set2;
4619 if (COMPOSITE_CHAR_P (c1))
4620 c1 = cmpchar_component (c1, 0, 1);
4621 if (COMPOSITE_CHAR_P (c2))
4622 c2 = cmpchar_component (c2, 0, 1);
4626 if (EQ (CHAR_CHARSET (c1), CHAR_CHARSET (c2)))
4629 tail = Vword_separating_categories;
4635 tail = Vword_combining_categories;
4640 category_set1 = CATEGORY_SET (c1);
4641 if (NILP (category_set1))
4642 return default_result;
4643 category_set2 = CATEGORY_SET (c2);
4644 if (NILP (category_set2))
4645 return default_result;
4647 for (; CONSP (tail); tail = XCONS (tail)->cdr)
4649 Lisp_Object elt = XCONS(tail)->car;
4652 && CATEGORYP (XCONS (elt)->car)
4653 && CATEGORYP (XCONS (elt)->cdr)
4654 && CATEGORY_MEMBER (XCHAR (XCONS (elt)->car), category_set1)
4655 && CATEGORY_MEMBER (XCHAR (XCONS (elt)->cdr), category_set2))
4656 return !default_result;
4658 return default_result;
4664 syms_of_chartab (void)
4667 INIT_LRECORD_IMPLEMENTATION (uint8_byte_table);
4668 INIT_LRECORD_IMPLEMENTATION (uint16_byte_table);
4669 INIT_LRECORD_IMPLEMENTATION (byte_table);
4671 defsymbol (&Qto_ucs, "=>ucs");
4672 defsymbol (&Q_ucs_unified, "->ucs-unified");
4673 defsymbol (&Q_subsumptive, "->subsumptive");
4674 defsymbol (&Q_subsumptive_from, "<-subsumptive");
4675 defsymbol (&Q_denotational, "->denotational");
4676 defsymbol (&Q_denotational_from, "<-denotational");
4677 defsymbol (&Q_identical, "->identical");
4678 defsymbol (&Q_identical_from, "<-identical");
4679 defsymbol (&Q_component, "->ideographic-component-forms");
4680 defsymbol (&Q_component_of, "<-ideographic-component-forms");
4681 defsymbol (&Qcomposition, "composition");
4682 defsymbol (&Qmap_decomposition, "=decomposition");
4683 defsymbol (&Qto_decomposition_at_superscript,
4684 "=>decomposition@superscript");
4685 defsymbol (&Q_canonical, "->canonical");
4686 defsymbol (&Q_superscript_of, "<-superscript");
4687 defsymbol (&Q_compat_of, "<-compat");
4688 defsymbol (&Q_decomposition, "->decomposition");
4689 defsymbol (&Qcompat, "compat");
4690 defsymbol (&Qisolated, "isolated");
4691 defsymbol (&Qinitial, "initial");
4692 defsymbol (&Qmedial, "medial");
4693 defsymbol (&Qfinal, "final");
4694 defsymbol (&Qvertical, "vertical");
4695 defsymbol (&QnoBreak, "noBreak");
4696 defsymbol (&Qfraction, "fraction");
4697 defsymbol (&Qsuper, "super");
4698 defsymbol (&Qsub, "sub");
4699 defsymbol (&Qcircle, "circle");
4700 defsymbol (&Qsquare, "square");
4701 defsymbol (&Qwide, "wide");
4702 defsymbol (&Qnarrow, "narrow");
4703 defsymbol (&Qsmall, "small");
4704 defsymbol (&Qfont, "font");
4706 DEFSUBR (Fchar_attribute_list);
4707 DEFSUBR (Ffind_char_attribute_table);
4708 defsymbol (&Qput_char_table_map_function, "put-char-table-map-function");
4709 DEFSUBR (Fput_char_table_map_function);
4711 DEFSUBR (Fsave_char_attribute_table);
4712 DEFSUBR (Fmount_char_attribute_table);
4713 DEFSUBR (Freset_char_attribute_table);
4714 DEFSUBR (Fclose_char_attribute_table);
4715 DEFSUBR (Fclose_char_data_source);
4716 #ifndef HAVE_LIBCHISE
4717 defsymbol (&Qload_char_attribute_table_map_function,
4718 "load-char-attribute-table-map-function");
4719 DEFSUBR (Fload_char_attribute_table_map_function);
4721 DEFSUBR (Fload_char_attribute_table);
4723 DEFSUBR (Fchar_feature);
4724 DEFSUBR (Fchar_attribute_alist);
4725 DEFSUBR (Fget_char_attribute);
4726 DEFSUBR (Fput_char_attribute);
4727 DEFSUBR (Fremove_char_attribute);
4728 DEFSUBR (Fmap_char_attribute);
4729 DEFSUBR (Fdefine_char);
4730 DEFSUBR (Ffind_char);
4731 DEFSUBR (Fchar_variants);
4733 DEFSUBR (Fget_composite_char);
4736 INIT_LRECORD_IMPLEMENTATION (char_table);
4740 INIT_LRECORD_IMPLEMENTATION (char_table_entry);
4743 defsymbol (&Qcategory_table_p, "category-table-p");
4744 defsymbol (&Qcategory_designator_p, "category-designator-p");
4745 defsymbol (&Qcategory_table_value_p, "category-table-value-p");
4748 defsymbol (&Qchar_table, "char-table");
4749 defsymbol (&Qchar_tablep, "char-table-p");
4751 DEFSUBR (Fchar_table_p);
4752 DEFSUBR (Fchar_table_type_list);
4753 DEFSUBR (Fvalid_char_table_type_p);
4754 DEFSUBR (Fchar_table_type);
4755 DEFSUBR (Freset_char_table);
4756 DEFSUBR (Fmake_char_table);
4757 DEFSUBR (Fcopy_char_table);
4758 DEFSUBR (Fget_char_table);
4759 DEFSUBR (Fget_range_char_table);
4760 DEFSUBR (Fvalid_char_table_value_p);
4761 DEFSUBR (Fcheck_valid_char_table_value);
4762 DEFSUBR (Fput_char_table);
4763 DEFSUBR (Fmap_char_table);
4766 DEFSUBR (Fcategory_table_p);
4767 DEFSUBR (Fcategory_table);
4768 DEFSUBR (Fstandard_category_table);
4769 DEFSUBR (Fcopy_category_table);
4770 DEFSUBR (Fset_category_table);
4771 DEFSUBR (Fcheck_category_at);
4772 DEFSUBR (Fchar_in_category_p);
4773 DEFSUBR (Fcategory_designator_p);
4774 DEFSUBR (Fcategory_table_value_p);
4780 vars_of_chartab (void)
4783 DEFVAR_LISP ("next-defined-char-id", &Vnext_defined_char_id /*
4785 Vnext_defined_char_id = make_int (0x0F0000);
4789 DEFVAR_LISP ("char-db-stingy-mode", &Vchar_db_stingy_mode /*
4791 Vchar_db_stingy_mode = Qt;
4793 #ifdef HAVE_LIBCHISE
4794 Vchise_db_directory = build_string(chise_db_dir);
4795 DEFVAR_LISP ("chise-db-directory", &Vchise_db_directory /*
4796 Directory of CHISE character databases.
4799 Vchise_system_db_directory = build_string(chise_system_db_dir);
4800 DEFVAR_LISP ("chise-system-db-directory", &Vchise_system_db_directory /*
4801 Directory of system character database of CHISE.
4805 #endif /* HAVE_CHISE */
4806 /* DO NOT staticpro this. It works just like Vweak_hash_tables. */
4807 Vall_syntax_tables = Qnil;
4808 dump_add_weak_object_chain (&Vall_syntax_tables);
4812 structure_type_create_chartab (void)
4814 struct structure_type *st;
4816 st = define_structure_type (Qchar_table, 0, chartab_instantiate);
4818 define_structure_type_keyword (st, Qtype, chartab_type_validate);
4819 define_structure_type_keyword (st, Qdata, chartab_data_validate);
4823 complex_vars_of_chartab (void)
4826 staticpro (&Vchar_attribute_hash_table);
4827 Vchar_attribute_hash_table
4828 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
4829 #endif /* UTF2000 */
4831 /* Set this now, so first buffer creation can refer to it. */
4832 /* Make it nil before calling copy-category-table
4833 so that copy-category-table will know not to try to copy from garbage */
4834 Vstandard_category_table = Qnil;
4835 Vstandard_category_table = Fcopy_category_table (Qnil);
4836 staticpro (&Vstandard_category_table);
4838 DEFVAR_LISP ("word-combining-categories", &Vword_combining_categories /*
4839 List of pair (cons) of categories to determine word boundary.
4841 Emacs treats a sequence of word constituent characters as a single
4842 word (i.e. finds no word boundary between them) iff they belongs to
4843 the same charset. But, exceptions are allowed in the following cases.
4845 \(1) The case that characters are in different charsets is controlled
4846 by the variable `word-combining-categories'.
4848 Emacs finds no word boundary between characters of different charsets
4849 if they have categories matching some element of this list.
4851 More precisely, if an element of this list is a cons of category CAT1
4852 and CAT2, and a multibyte character C1 which has CAT1 is followed by
4853 C2 which has CAT2, there's no word boundary between C1 and C2.
4855 For instance, to tell that ASCII characters and Latin-1 characters can
4856 form a single word, the element `(?l . ?l)' should be in this list
4857 because both characters have the category `l' (Latin characters).
4859 \(2) The case that character are in the same charset is controlled by
4860 the variable `word-separating-categories'.
4862 Emacs find a word boundary between characters of the same charset
4863 if they have categories matching some element of this list.
4865 More precisely, if an element of this list is a cons of category CAT1
4866 and CAT2, and a multibyte character C1 which has CAT1 is followed by
4867 C2 which has CAT2, there's a word boundary between C1 and C2.
4869 For instance, to tell that there's a word boundary between Japanese
4870 Hiragana and Japanese Kanji (both are in the same charset), the
4871 element `(?H . ?C) should be in this list.
4874 Vword_combining_categories = Qnil;
4876 DEFVAR_LISP ("word-separating-categories", &Vword_separating_categories /*
4877 List of pair (cons) of categories to determine word boundary.
4878 See the documentation of the variable `word-combining-categories'.
4881 Vword_separating_categories = Qnil;