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_subscript_of;
1138 Lisp_Object Q_compat_of;
1139 Lisp_Object Q_decomposition;
1140 Lisp_Object Q_identical;
1141 Lisp_Object Q_identical_from;
1142 Lisp_Object Q_denotational;
1143 Lisp_Object Q_denotational_from;
1144 Lisp_Object Q_subsumptive;
1145 Lisp_Object Q_subsumptive_from;
1146 Lisp_Object Q_component;
1147 Lisp_Object Q_component_of;
1148 Lisp_Object Qto_ucs;
1149 Lisp_Object Q_ucs_unified;
1150 Lisp_Object Qcompat;
1151 Lisp_Object Qisolated;
1152 Lisp_Object Qinitial;
1153 Lisp_Object Qmedial;
1155 Lisp_Object Qvertical;
1156 Lisp_Object QnoBreak;
1157 Lisp_Object Qfraction;
1160 Lisp_Object Qcircle;
1161 Lisp_Object Qsquare;
1163 Lisp_Object Qnarrow;
1167 Emchar to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg);
1170 to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
1176 else if (EQ (v, Qcompat))
1178 else if (EQ (v, Qisolated))
1180 else if (EQ (v, Qinitial))
1182 else if (EQ (v, Qmedial))
1184 else if (EQ (v, Qfinal))
1186 else if (EQ (v, Qvertical))
1188 else if (EQ (v, QnoBreak))
1190 else if (EQ (v, Qfraction))
1192 else if (EQ (v, Qsuper))
1194 else if (EQ (v, Qsub))
1196 else if (EQ (v, Qcircle))
1198 else if (EQ (v, Qsquare))
1200 else if (EQ (v, Qwide))
1202 else if (EQ (v, Qnarrow))
1204 else if (EQ (v, Qsmall))
1206 else if (EQ (v, Qfont))
1209 signal_simple_error (err_msg, err_arg);
1212 DEFUN ("get-composite-char", Fget_composite_char, 1, 1, 0, /*
1213 Return character corresponding with list.
1217 Lisp_Object base, modifier;
1221 signal_simple_error ("Invalid value for composition", list);
1224 while (!NILP (rest))
1229 signal_simple_error ("Invalid value for composition", list);
1230 modifier = Fcar (rest);
1232 base = Fcdr (Fassq (modifier,
1233 Fchar_feature (base, Qcomposition, Qnil,
1239 DEFUN ("char-variants", Fchar_variants, 1, 1, 0, /*
1240 Return variants of CHARACTER.
1244 CHECK_CHAR (character);
1247 (Fcopy_list (Fget_char_attribute (character, Q_subsumptive, Qnil)),
1249 (Fcopy_list (Fget_char_attribute (character, Q_denotational, Qnil)),
1251 (Fcopy_list (Fget_char_attribute (character, Q_identical, Qnil)),
1252 Fcopy_list (Fchar_feature (character, Q_ucs_unified, Qnil,
1259 /* A char table maps from ranges of characters to values.
1261 Implementing a general data structure that maps from arbitrary
1262 ranges of numbers to values is tricky to do efficiently. As it
1263 happens, it should suffice (and is usually more convenient, anyway)
1264 when dealing with characters to restrict the sorts of ranges that
1265 can be assigned values, as follows:
1268 2) All characters in a charset.
1269 3) All characters in a particular row of a charset, where a "row"
1270 means all characters with the same first byte.
1271 4) A particular character in a charset.
1273 We use char tables to generalize the 256-element vectors now
1274 littering the Emacs code.
1276 Possible uses (all should be converted at some point):
1282 5) keyboard-translate-table?
1285 abstract type to generalize the Emacs vectors and Mule
1286 vectors-of-vectors goo.
1289 /************************************************************************/
1290 /* Char Table object */
1291 /************************************************************************/
1293 #if defined(MULE)&&!defined(UTF2000)
1296 mark_char_table_entry (Lisp_Object obj)
1298 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
1301 for (i = 0; i < 96; i++)
1303 mark_object (cte->level2[i]);
1309 char_table_entry_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1311 Lisp_Char_Table_Entry *cte1 = XCHAR_TABLE_ENTRY (obj1);
1312 Lisp_Char_Table_Entry *cte2 = XCHAR_TABLE_ENTRY (obj2);
1315 for (i = 0; i < 96; i++)
1316 if (!internal_equal (cte1->level2[i], cte2->level2[i], depth + 1))
1322 static unsigned long
1323 char_table_entry_hash (Lisp_Object obj, int depth)
1325 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj);
1327 return internal_array_hash (cte->level2, 96, depth);
1330 static const struct lrecord_description char_table_entry_description[] = {
1331 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table_Entry, level2), 96 },
1335 DEFINE_LRECORD_IMPLEMENTATION ("char-table-entry", char_table_entry,
1336 mark_char_table_entry, internal_object_printer,
1337 0, char_table_entry_equal,
1338 char_table_entry_hash,
1339 char_table_entry_description,
1340 Lisp_Char_Table_Entry);
1344 mark_char_table (Lisp_Object obj)
1346 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1349 mark_object (ct->table);
1350 mark_object (ct->name);
1351 #ifndef HAVE_LIBCHISE
1352 mark_object (ct->db);
1357 for (i = 0; i < NUM_ASCII_CHARS; i++)
1358 mark_object (ct->ascii[i]);
1360 for (i = 0; i < NUM_LEADING_BYTES; i++)
1361 mark_object (ct->level1[i]);
1365 return ct->default_value;
1367 return ct->mirror_table;
1371 /* WARNING: All functions of this nature need to be written extremely
1372 carefully to avoid crashes during GC. Cf. prune_specifiers()
1373 and prune_weak_hash_tables(). */
1376 prune_syntax_tables (void)
1378 Lisp_Object rest, prev = Qnil;
1380 for (rest = Vall_syntax_tables;
1382 rest = XCHAR_TABLE (rest)->next_table)
1384 if (! marked_p (rest))
1386 /* This table is garbage. Remove it from the list. */
1388 Vall_syntax_tables = XCHAR_TABLE (rest)->next_table;
1390 XCHAR_TABLE (prev)->next_table =
1391 XCHAR_TABLE (rest)->next_table;
1397 char_table_type_to_symbol (enum char_table_type type)
1402 case CHAR_TABLE_TYPE_GENERIC: return Qgeneric;
1403 case CHAR_TABLE_TYPE_SYNTAX: return Qsyntax;
1404 case CHAR_TABLE_TYPE_DISPLAY: return Qdisplay;
1405 case CHAR_TABLE_TYPE_CHAR: return Qchar;
1407 case CHAR_TABLE_TYPE_CATEGORY: return Qcategory;
1412 static enum char_table_type
1413 symbol_to_char_table_type (Lisp_Object symbol)
1415 CHECK_SYMBOL (symbol);
1417 if (EQ (symbol, Qgeneric)) return CHAR_TABLE_TYPE_GENERIC;
1418 if (EQ (symbol, Qsyntax)) return CHAR_TABLE_TYPE_SYNTAX;
1419 if (EQ (symbol, Qdisplay)) return CHAR_TABLE_TYPE_DISPLAY;
1420 if (EQ (symbol, Qchar)) return CHAR_TABLE_TYPE_CHAR;
1422 if (EQ (symbol, Qcategory)) return CHAR_TABLE_TYPE_CATEGORY;
1425 signal_simple_error ("Unrecognized char table type", symbol);
1426 return CHAR_TABLE_TYPE_GENERIC; /* not reached */
1431 print_chartab_range (Emchar first, Emchar last, Lisp_Object val,
1432 Lisp_Object printcharfun)
1436 write_c_string (" (", printcharfun);
1437 print_internal (make_char (first), printcharfun, 0);
1438 write_c_string (" ", printcharfun);
1439 print_internal (make_char (last), printcharfun, 0);
1440 write_c_string (") ", printcharfun);
1444 write_c_string (" ", printcharfun);
1445 print_internal (make_char (first), printcharfun, 0);
1446 write_c_string (" ", printcharfun);
1448 print_internal (val, printcharfun, 1);
1452 #if defined(MULE)&&!defined(UTF2000)
1455 print_chartab_charset_row (Lisp_Object charset,
1457 Lisp_Char_Table_Entry *cte,
1458 Lisp_Object printcharfun)
1461 Lisp_Object cat = Qunbound;
1464 for (i = 32; i < 128; i++)
1466 Lisp_Object pam = cte->level2[i - 32];
1478 print_chartab_range (MAKE_CHAR (charset, first, 0),
1479 MAKE_CHAR (charset, i - 1, 0),
1482 print_chartab_range (MAKE_CHAR (charset, row, first),
1483 MAKE_CHAR (charset, row, i - 1),
1493 print_chartab_range (MAKE_CHAR (charset, first, 0),
1494 MAKE_CHAR (charset, i - 1, 0),
1497 print_chartab_range (MAKE_CHAR (charset, row, first),
1498 MAKE_CHAR (charset, row, i - 1),
1504 print_chartab_two_byte_charset (Lisp_Object charset,
1505 Lisp_Char_Table_Entry *cte,
1506 Lisp_Object printcharfun)
1510 for (i = 32; i < 128; i++)
1512 Lisp_Object jen = cte->level2[i - 32];
1514 if (!CHAR_TABLE_ENTRYP (jen))
1518 write_c_string (" [", printcharfun);
1519 print_internal (XCHARSET_NAME (charset), printcharfun, 0);
1520 sprintf (buf, " %d] ", i);
1521 write_c_string (buf, printcharfun);
1522 print_internal (jen, printcharfun, 0);
1525 print_chartab_charset_row (charset, i, XCHAR_TABLE_ENTRY (jen),
1533 print_char_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1535 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1538 struct gcpro gcpro1, gcpro2;
1539 GCPRO2 (obj, printcharfun);
1541 write_c_string ("#s(char-table ", printcharfun);
1542 write_c_string (" ", printcharfun);
1543 write_c_string (string_data
1545 (XSYMBOL (char_table_type_to_symbol (ct->type)))),
1547 write_c_string ("\n ", printcharfun);
1548 print_internal (ct->default_value, printcharfun, escapeflag);
1549 for (i = 0; i < 256; i++)
1551 Lisp_Object elt = get_byte_table (ct->table, i);
1552 if (i != 0) write_c_string ("\n ", printcharfun);
1553 if (EQ (elt, Qunbound))
1554 write_c_string ("void", printcharfun);
1556 print_internal (elt, printcharfun, escapeflag);
1559 #else /* non UTF2000 */
1562 sprintf (buf, "#s(char-table type %s data (",
1563 string_data (symbol_name (XSYMBOL
1564 (char_table_type_to_symbol (ct->type)))));
1565 write_c_string (buf, printcharfun);
1567 /* Now write out the ASCII/Control-1 stuff. */
1571 Lisp_Object val = Qunbound;
1573 for (i = 0; i < NUM_ASCII_CHARS; i++)
1582 if (!EQ (ct->ascii[i], val))
1584 print_chartab_range (first, i - 1, val, printcharfun);
1591 print_chartab_range (first, i - 1, val, printcharfun);
1598 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
1601 Lisp_Object ann = ct->level1[i - MIN_LEADING_BYTE];
1602 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (i);
1604 if (!CHARSETP (charset) || i == LEADING_BYTE_ASCII
1605 || i == LEADING_BYTE_CONTROL_1)
1607 if (!CHAR_TABLE_ENTRYP (ann))
1609 write_c_string (" ", printcharfun);
1610 print_internal (XCHARSET_NAME (charset),
1612 write_c_string (" ", printcharfun);
1613 print_internal (ann, printcharfun, 0);
1617 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (ann);
1618 if (XCHARSET_DIMENSION (charset) == 1)
1619 print_chartab_charset_row (charset, -1, cte, printcharfun);
1621 print_chartab_two_byte_charset (charset, cte, printcharfun);
1626 #endif /* non UTF2000 */
1628 write_c_string ("))", printcharfun);
1632 char_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1634 Lisp_Char_Table *ct1 = XCHAR_TABLE (obj1);
1635 Lisp_Char_Table *ct2 = XCHAR_TABLE (obj2);
1638 if (CHAR_TABLE_TYPE (ct1) != CHAR_TABLE_TYPE (ct2))
1642 for (i = 0; i < 256; i++)
1644 if (!internal_equal (get_byte_table (ct1->table, i),
1645 get_byte_table (ct2->table, i), 0))
1649 for (i = 0; i < NUM_ASCII_CHARS; i++)
1650 if (!internal_equal (ct1->ascii[i], ct2->ascii[i], depth + 1))
1654 for (i = 0; i < NUM_LEADING_BYTES; i++)
1655 if (!internal_equal (ct1->level1[i], ct2->level1[i], depth + 1))
1658 #endif /* non UTF2000 */
1663 static unsigned long
1664 char_table_hash (Lisp_Object obj, int depth)
1666 Lisp_Char_Table *ct = XCHAR_TABLE (obj);
1668 return byte_table_hash (ct->table, depth + 1);
1670 unsigned long hashval = internal_array_hash (ct->ascii, NUM_ASCII_CHARS,
1673 hashval = HASH2 (hashval,
1674 internal_array_hash (ct->level1, NUM_LEADING_BYTES, depth));
1680 static const struct lrecord_description char_table_description[] = {
1682 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, table) },
1683 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, default_value) },
1684 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, name) },
1685 #ifndef HAVE_LIBCHISE
1686 { XD_LISP_OBJECT, offsetof(Lisp_Char_Table, db) },
1689 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table, ascii), NUM_ASCII_CHARS },
1691 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Char_Table, level1), NUM_LEADING_BYTES },
1695 { XD_LISP_OBJECT, offsetof (Lisp_Char_Table, mirror_table) },
1697 { XD_LO_LINK, offsetof (Lisp_Char_Table, next_table) },
1701 DEFINE_LRECORD_IMPLEMENTATION ("char-table", char_table,
1702 mark_char_table, print_char_table, 0,
1703 char_table_equal, char_table_hash,
1704 char_table_description,
1707 DEFUN ("char-table-p", Fchar_table_p, 1, 1, 0, /*
1708 Return non-nil if OBJECT is a char table.
1710 A char table is a table that maps characters (or ranges of characters)
1711 to values. Char tables are specialized for characters, only allowing
1712 particular sorts of ranges to be assigned values. Although this
1713 loses in generality, it makes for extremely fast (constant-time)
1714 lookups, and thus is feasible for applications that do an extremely
1715 large number of lookups (e.g. scanning a buffer for a character in
1716 a particular syntax, where a lookup in the syntax table must occur
1717 once per character).
1719 When Mule support exists, the types of ranges that can be assigned
1723 -- an entire charset
1724 -- a single row in a two-octet charset
1725 -- a single character
1727 When Mule support is not present, the types of ranges that can be
1731 -- a single character
1733 To create a char table, use `make-char-table'.
1734 To modify a char table, use `put-char-table' or `remove-char-table'.
1735 To retrieve the value for a particular character, use `get-char-table'.
1736 See also `map-char-table', `clear-char-table', `copy-char-table',
1737 `valid-char-table-type-p', `char-table-type-list',
1738 `valid-char-table-value-p', and `check-char-table-value'.
1742 return CHAR_TABLEP (object) ? Qt : Qnil;
1745 DEFUN ("char-table-type-list", Fchar_table_type_list, 0, 0, 0, /*
1746 Return a list of the recognized char table types.
1747 See `valid-char-table-type-p'.
1752 return list5 (Qchar, Qcategory, Qdisplay, Qgeneric, Qsyntax);
1754 return list4 (Qchar, Qdisplay, Qgeneric, Qsyntax);
1758 DEFUN ("valid-char-table-type-p", Fvalid_char_table_type_p, 1, 1, 0, /*
1759 Return t if TYPE if a recognized char table type.
1761 Each char table type is used for a different purpose and allows different
1762 sorts of values. The different char table types are
1765 Used for category tables, which specify the regexp categories
1766 that a character is in. The valid values are nil or a
1767 bit vector of 95 elements. Higher-level Lisp functions are
1768 provided for working with category tables. Currently categories
1769 and category tables only exist when Mule support is present.
1771 A generalized char table, for mapping from one character to
1772 another. Used for case tables, syntax matching tables,
1773 `keyboard-translate-table', etc. The valid values are characters.
1775 An even more generalized char table, for mapping from a
1776 character to anything.
1778 Used for display tables, which specify how a particular character
1779 is to appear when displayed. #### Not yet implemented.
1781 Used for syntax tables, which specify the syntax of a particular
1782 character. Higher-level Lisp functions are provided for
1783 working with syntax tables. The valid values are integers.
1788 return (EQ (type, Qchar) ||
1790 EQ (type, Qcategory) ||
1792 EQ (type, Qdisplay) ||
1793 EQ (type, Qgeneric) ||
1794 EQ (type, Qsyntax)) ? Qt : Qnil;
1797 DEFUN ("char-table-type", Fchar_table_type, 1, 1, 0, /*
1798 Return the type of CHAR-TABLE.
1799 See `valid-char-table-type-p'.
1803 CHECK_CHAR_TABLE (char_table);
1804 return char_table_type_to_symbol (XCHAR_TABLE (char_table)->type);
1808 fill_char_table (Lisp_Char_Table *ct, Lisp_Object value)
1811 ct->table = Qunbound;
1812 ct->default_value = value;
1817 for (i = 0; i < NUM_ASCII_CHARS; i++)
1818 ct->ascii[i] = value;
1820 for (i = 0; i < NUM_LEADING_BYTES; i++)
1821 ct->level1[i] = value;
1826 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
1827 update_syntax_table (ct);
1831 DEFUN ("reset-char-table", Freset_char_table, 1, 1, 0, /*
1832 Reset CHAR-TABLE to its default state.
1836 Lisp_Char_Table *ct;
1838 CHECK_CHAR_TABLE (char_table);
1839 ct = XCHAR_TABLE (char_table);
1843 case CHAR_TABLE_TYPE_CHAR:
1844 fill_char_table (ct, make_char (0));
1846 case CHAR_TABLE_TYPE_DISPLAY:
1847 case CHAR_TABLE_TYPE_GENERIC:
1849 case CHAR_TABLE_TYPE_CATEGORY:
1851 fill_char_table (ct, Qnil);
1854 case CHAR_TABLE_TYPE_SYNTAX:
1855 fill_char_table (ct, make_int (Sinherit));
1865 DEFUN ("make-char-table", Fmake_char_table, 1, 1, 0, /*
1866 Return a new, empty char table of type TYPE.
1867 Currently recognized types are 'char, 'category, 'display, 'generic,
1868 and 'syntax. See `valid-char-table-type-p'.
1872 Lisp_Char_Table *ct;
1874 enum char_table_type ty = symbol_to_char_table_type (type);
1876 ct = alloc_lcrecord_type (Lisp_Char_Table, &lrecord_char_table);
1879 if (ty == CHAR_TABLE_TYPE_SYNTAX)
1881 ct->mirror_table = Fmake_char_table (Qgeneric);
1882 fill_char_table (XCHAR_TABLE (ct->mirror_table),
1886 ct->mirror_table = Qnil;
1889 #ifndef HAVE_LIBCHISE
1893 ct->next_table = Qnil;
1894 XSETCHAR_TABLE (obj, ct);
1895 if (ty == CHAR_TABLE_TYPE_SYNTAX)
1897 ct->next_table = Vall_syntax_tables;
1898 Vall_syntax_tables = obj;
1900 Freset_char_table (obj);
1904 #if defined(MULE)&&!defined(UTF2000)
1907 make_char_table_entry (Lisp_Object initval)
1911 Lisp_Char_Table_Entry *cte =
1912 alloc_lcrecord_type (Lisp_Char_Table_Entry, &lrecord_char_table_entry);
1914 for (i = 0; i < 96; i++)
1915 cte->level2[i] = initval;
1917 XSETCHAR_TABLE_ENTRY (obj, cte);
1922 copy_char_table_entry (Lisp_Object entry)
1924 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (entry);
1927 Lisp_Char_Table_Entry *ctenew =
1928 alloc_lcrecord_type (Lisp_Char_Table_Entry, &lrecord_char_table_entry);
1930 for (i = 0; i < 96; i++)
1932 Lisp_Object new = cte->level2[i];
1933 if (CHAR_TABLE_ENTRYP (new))
1934 ctenew->level2[i] = copy_char_table_entry (new);
1936 ctenew->level2[i] = new;
1939 XSETCHAR_TABLE_ENTRY (obj, ctenew);
1945 DEFUN ("copy-char-table", Fcopy_char_table, 1, 1, 0, /*
1946 Return a new char table which is a copy of CHAR-TABLE.
1947 It will contain the same values for the same characters and ranges
1948 as CHAR-TABLE. The values will not themselves be copied.
1952 Lisp_Char_Table *ct, *ctnew;
1958 CHECK_CHAR_TABLE (char_table);
1959 ct = XCHAR_TABLE (char_table);
1960 ctnew = alloc_lcrecord_type (Lisp_Char_Table, &lrecord_char_table);
1961 ctnew->type = ct->type;
1963 ctnew->default_value = ct->default_value;
1964 /* [tomo:2002-01-21] Perhaps this code seems wrong */
1965 ctnew->name = ct->name;
1966 #ifndef HAVE_LIBCHISE
1970 if (UINT8_BYTE_TABLE_P (ct->table))
1972 ctnew->table = copy_uint8_byte_table (ct->table);
1974 else if (UINT16_BYTE_TABLE_P (ct->table))
1976 ctnew->table = copy_uint16_byte_table (ct->table);
1978 else if (BYTE_TABLE_P (ct->table))
1980 ctnew->table = copy_byte_table (ct->table);
1982 else if (!UNBOUNDP (ct->table))
1983 ctnew->table = ct->table;
1984 #else /* non UTF2000 */
1986 for (i = 0; i < NUM_ASCII_CHARS; i++)
1988 Lisp_Object new = ct->ascii[i];
1990 assert (! (CHAR_TABLE_ENTRYP (new)));
1992 ctnew->ascii[i] = new;
1997 for (i = 0; i < NUM_LEADING_BYTES; i++)
1999 Lisp_Object new = ct->level1[i];
2000 if (CHAR_TABLE_ENTRYP (new))
2001 ctnew->level1[i] = copy_char_table_entry (new);
2003 ctnew->level1[i] = new;
2007 #endif /* non UTF2000 */
2010 if (CHAR_TABLEP (ct->mirror_table))
2011 ctnew->mirror_table = Fcopy_char_table (ct->mirror_table);
2013 ctnew->mirror_table = ct->mirror_table;
2015 ctnew->next_table = Qnil;
2016 XSETCHAR_TABLE (obj, ctnew);
2017 if (ctnew->type == CHAR_TABLE_TYPE_SYNTAX)
2019 ctnew->next_table = Vall_syntax_tables;
2020 Vall_syntax_tables = obj;
2025 INLINE_HEADER int XCHARSET_CELL_RANGE (Lisp_Object ccs);
2027 XCHARSET_CELL_RANGE (Lisp_Object ccs)
2029 switch (XCHARSET_CHARS (ccs))
2032 return (33 << 8) | 126;
2034 return (32 << 8) | 127;
2037 return (0 << 8) | 127;
2039 return (0 << 8) | 255;
2051 decode_char_table_range (Lisp_Object range, struct chartab_range *outrange)
2054 outrange->type = CHARTAB_RANGE_ALL;
2056 else if (EQ (range, Qnil))
2057 outrange->type = CHARTAB_RANGE_DEFAULT;
2059 else if (CHAR_OR_CHAR_INTP (range))
2061 outrange->type = CHARTAB_RANGE_CHAR;
2062 outrange->ch = XCHAR_OR_CHAR_INT (range);
2066 signal_simple_error ("Range must be t or a character", range);
2068 else if (VECTORP (range))
2070 Lisp_Vector *vec = XVECTOR (range);
2071 Lisp_Object *elts = vector_data (vec);
2072 int cell_min, cell_max;
2074 outrange->type = CHARTAB_RANGE_ROW;
2075 outrange->charset = Fget_charset (elts[0]);
2076 CHECK_INT (elts[1]);
2077 outrange->row = XINT (elts[1]);
2078 if (XCHARSET_DIMENSION (outrange->charset) < 2)
2079 signal_simple_error ("Charset in row vector must be multi-byte",
2083 int ret = XCHARSET_CELL_RANGE (outrange->charset);
2085 cell_min = ret >> 8;
2086 cell_max = ret & 0xFF;
2088 if (XCHARSET_DIMENSION (outrange->charset) == 2)
2089 check_int_range (outrange->row, cell_min, cell_max);
2091 else if (XCHARSET_DIMENSION (outrange->charset) == 3)
2093 check_int_range (outrange->row >> 8 , cell_min, cell_max);
2094 check_int_range (outrange->row & 0xFF, cell_min, cell_max);
2096 else if (XCHARSET_DIMENSION (outrange->charset) == 4)
2098 check_int_range ( outrange->row >> 16 , cell_min, cell_max);
2099 check_int_range ((outrange->row >> 8) & 0xFF, cell_min, cell_max);
2100 check_int_range ( outrange->row & 0xFF, cell_min, cell_max);
2108 if (!CHARSETP (range) && !SYMBOLP (range))
2110 ("Char table range must be t, charset, char, or vector", range);
2111 outrange->type = CHARTAB_RANGE_CHARSET;
2112 outrange->charset = Fget_charset (range);
2117 #if defined(MULE)&&!defined(UTF2000)
2119 /* called from CHAR_TABLE_VALUE(). */
2121 get_non_ascii_char_table_value (Lisp_Char_Table *ct, Charset_ID leading_byte,
2126 Lisp_Object charset;
2128 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (leading_byte);
2133 BREAKUP_CHAR (c, charset, byte1, byte2);
2135 BREAKUP_CHAR_1_UNSAFE (c, charset, byte1, byte2);
2137 val = ct->level1[leading_byte - MIN_LEADING_BYTE];
2138 if (CHAR_TABLE_ENTRYP (val))
2140 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2141 val = cte->level2[byte1 - 32];
2142 if (CHAR_TABLE_ENTRYP (val))
2144 cte = XCHAR_TABLE_ENTRY (val);
2145 assert (byte2 >= 32);
2146 val = cte->level2[byte2 - 32];
2147 assert (!CHAR_TABLE_ENTRYP (val));
2157 get_char_table (Emchar ch, Lisp_Char_Table *ct)
2161 Lisp_Object ret = get_char_id_table (ct, ch);
2166 if (EQ (CHAR_TABLE_NAME (ct), Qdowncase))
2167 ret = Fchar_feature (make_char (ch), Q_lowercase, Qnil,
2169 else if (EQ (CHAR_TABLE_NAME (ct), Qflippedcase))
2170 ret = Fchar_feature (make_char (ch), Q_uppercase, Qnil,
2176 ret = Ffind_char (ret);
2184 Lisp_Object charset;
2188 BREAKUP_CHAR (ch, charset, byte1, byte2);
2190 if (EQ (charset, Vcharset_ascii))
2191 val = ct->ascii[byte1];
2192 else if (EQ (charset, Vcharset_control_1))
2193 val = ct->ascii[byte1 + 128];
2196 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
2197 val = ct->level1[lb];
2198 if (CHAR_TABLE_ENTRYP (val))
2200 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2201 val = cte->level2[byte1 - 32];
2202 if (CHAR_TABLE_ENTRYP (val))
2204 cte = XCHAR_TABLE_ENTRY (val);
2205 assert (byte2 >= 32);
2206 val = cte->level2[byte2 - 32];
2207 assert (!CHAR_TABLE_ENTRYP (val));
2214 #else /* not MULE */
2215 return ct->ascii[(unsigned char)ch];
2216 #endif /* not MULE */
2220 DEFUN ("get-char-table", Fget_char_table, 2, 2, 0, /*
2221 Find value for CHARACTER in CHAR-TABLE.
2223 (character, char_table))
2225 CHECK_CHAR_TABLE (char_table);
2226 CHECK_CHAR_COERCE_INT (character);
2228 return get_char_table (XCHAR (character), XCHAR_TABLE (char_table));
2231 DEFUN ("get-range-char-table", Fget_range_char_table, 2, 3, 0, /*
2232 Find value for a range in CHAR-TABLE.
2233 If there is more than one value, return MULTI (defaults to nil).
2235 (range, char_table, multi))
2237 Lisp_Char_Table *ct;
2238 struct chartab_range rainj;
2240 if (CHAR_OR_CHAR_INTP (range))
2241 return Fget_char_table (range, char_table);
2242 CHECK_CHAR_TABLE (char_table);
2243 ct = XCHAR_TABLE (char_table);
2245 decode_char_table_range (range, &rainj);
2248 case CHARTAB_RANGE_ALL:
2251 if (UINT8_BYTE_TABLE_P (ct->table))
2253 else if (UINT16_BYTE_TABLE_P (ct->table))
2255 else if (BYTE_TABLE_P (ct->table))
2259 #else /* non UTF2000 */
2261 Lisp_Object first = ct->ascii[0];
2263 for (i = 1; i < NUM_ASCII_CHARS; i++)
2264 if (!EQ (first, ct->ascii[i]))
2268 for (i = MIN_LEADING_BYTE; i < MIN_LEADING_BYTE + NUM_LEADING_BYTES;
2271 if (!CHARSETP (CHARSET_BY_LEADING_BYTE (i))
2272 || i == LEADING_BYTE_ASCII
2273 || i == LEADING_BYTE_CONTROL_1)
2275 if (!EQ (first, ct->level1[i - MIN_LEADING_BYTE]))
2281 #endif /* non UTF2000 */
2285 case CHARTAB_RANGE_CHARSET:
2289 if (EQ (rainj.charset, Vcharset_ascii))
2292 Lisp_Object first = ct->ascii[0];
2294 for (i = 1; i < 128; i++)
2295 if (!EQ (first, ct->ascii[i]))
2300 if (EQ (rainj.charset, Vcharset_control_1))
2303 Lisp_Object first = ct->ascii[128];
2305 for (i = 129; i < 160; i++)
2306 if (!EQ (first, ct->ascii[i]))
2312 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
2314 if (CHAR_TABLE_ENTRYP (val))
2320 case CHARTAB_RANGE_ROW:
2325 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (rainj.charset) -
2327 if (!CHAR_TABLE_ENTRYP (val))
2329 val = XCHAR_TABLE_ENTRY (val)->level2[rainj.row - 32];
2330 if (CHAR_TABLE_ENTRYP (val))
2334 #endif /* not UTF2000 */
2335 #endif /* not MULE */
2338 case CHARTAB_RANGE_DEFAULT:
2339 return ct->default_value;
2340 #endif /* not UTF2000 */
2346 return Qnil; /* not reached */
2350 check_valid_char_table_value (Lisp_Object value, enum char_table_type type,
2351 Error_behavior errb)
2355 case CHAR_TABLE_TYPE_SYNTAX:
2356 if (!ERRB_EQ (errb, ERROR_ME))
2357 return INTP (value) || (CONSP (value) && INTP (XCAR (value))
2358 && CHAR_OR_CHAR_INTP (XCDR (value)));
2361 Lisp_Object cdr = XCDR (value);
2362 CHECK_INT (XCAR (value));
2363 CHECK_CHAR_COERCE_INT (cdr);
2370 case CHAR_TABLE_TYPE_CATEGORY:
2371 if (!ERRB_EQ (errb, ERROR_ME))
2372 return CATEGORY_TABLE_VALUEP (value);
2373 CHECK_CATEGORY_TABLE_VALUE (value);
2377 case CHAR_TABLE_TYPE_GENERIC:
2380 case CHAR_TABLE_TYPE_DISPLAY:
2382 maybe_signal_simple_error ("Display char tables not yet implemented",
2383 value, Qchar_table, errb);
2386 case CHAR_TABLE_TYPE_CHAR:
2387 if (!ERRB_EQ (errb, ERROR_ME))
2388 return CHAR_OR_CHAR_INTP (value);
2389 CHECK_CHAR_COERCE_INT (value);
2396 return 0; /* not reached */
2400 canonicalize_char_table_value (Lisp_Object value, enum char_table_type type)
2404 case CHAR_TABLE_TYPE_SYNTAX:
2407 Lisp_Object car = XCAR (value);
2408 Lisp_Object cdr = XCDR (value);
2409 CHECK_CHAR_COERCE_INT (cdr);
2410 return Fcons (car, cdr);
2413 case CHAR_TABLE_TYPE_CHAR:
2414 CHECK_CHAR_COERCE_INT (value);
2422 DEFUN ("valid-char-table-value-p", Fvalid_char_table_value_p, 2, 2, 0, /*
2423 Return non-nil if VALUE is a valid value for CHAR-TABLE-TYPE.
2425 (value, char_table_type))
2427 enum char_table_type type = symbol_to_char_table_type (char_table_type);
2429 return check_valid_char_table_value (value, type, ERROR_ME_NOT) ? Qt : Qnil;
2432 DEFUN ("check-valid-char-table-value", Fcheck_valid_char_table_value, 2, 2, 0, /*
2433 Signal an error if VALUE is not a valid value for CHAR-TABLE-TYPE.
2435 (value, char_table_type))
2437 enum char_table_type type = symbol_to_char_table_type (char_table_type);
2439 check_valid_char_table_value (value, type, ERROR_ME);
2444 Lisp_Char_Table* char_attribute_table_to_put;
2445 Lisp_Object Qput_char_table_map_function;
2446 Lisp_Object value_to_put;
2448 DEFUN ("put-char-table-map-function",
2449 Fput_char_table_map_function, 2, 2, 0, /*
2450 For internal use. Don't use it.
2454 put_char_id_table_0 (char_attribute_table_to_put,
2455 XCHAR (c), value_to_put);
2460 /* Assign VAL to all characters in RANGE in char table CT. */
2463 put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
2466 switch (range->type)
2468 case CHARTAB_RANGE_ALL:
2469 fill_char_table (ct, val);
2470 return; /* avoid the duplicate call to update_syntax_table() below,
2471 since fill_char_table() also did that. */
2474 case CHARTAB_RANGE_DEFAULT:
2475 ct->default_value = val;
2480 case CHARTAB_RANGE_CHARSET:
2483 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (range->charset);
2485 if ( CHAR_TABLEP (encoding_table) )
2487 Lisp_Object mother = XCHARSET_MOTHER (range->charset);
2489 char_attribute_table_to_put = ct;
2491 Fmap_char_attribute (Qput_char_table_map_function,
2492 XCHAR_TABLE_NAME (encoding_table),
2494 if ( CHARSETP (mother) )
2496 struct chartab_range r;
2498 r.type = CHARTAB_RANGE_CHARSET;
2500 put_char_table (ct, &r, val);
2508 for (c = 0; c < 1 << 24; c++)
2510 if ( charset_code_point (range->charset, c) >= 0 )
2511 put_char_id_table_0 (ct, c, val);
2517 if (EQ (range->charset, Vcharset_ascii))
2520 for (i = 0; i < 128; i++)
2523 else if (EQ (range->charset, Vcharset_control_1))
2526 for (i = 128; i < 160; i++)
2531 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
2532 ct->level1[lb] = val;
2537 case CHARTAB_RANGE_ROW:
2540 int cell_min, cell_max, i;
2542 i = XCHARSET_CELL_RANGE (range->charset);
2544 cell_max = i & 0xFF;
2545 for (i = cell_min; i <= cell_max; i++)
2548 = DECODE_CHAR (range->charset, (range->row << 8) | i, 0);
2550 if ( charset_code_point (range->charset, ch, 0) >= 0 )
2551 put_char_id_table_0 (ct, ch, val);
2556 Lisp_Char_Table_Entry *cte;
2557 int lb = XCHARSET_LEADING_BYTE (range->charset) - MIN_LEADING_BYTE;
2558 /* make sure that there is a separate entry for the row. */
2559 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
2560 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
2561 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
2562 cte->level2[range->row - 32] = val;
2564 #endif /* not UTF2000 */
2568 case CHARTAB_RANGE_CHAR:
2570 put_char_id_table_0 (ct, range->ch, val);
2574 Lisp_Object charset;
2577 BREAKUP_CHAR (range->ch, charset, byte1, byte2);
2578 if (EQ (charset, Vcharset_ascii))
2579 ct->ascii[byte1] = val;
2580 else if (EQ (charset, Vcharset_control_1))
2581 ct->ascii[byte1 + 128] = val;
2584 Lisp_Char_Table_Entry *cte;
2585 int lb = XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE;
2586 /* make sure that there is a separate entry for the row. */
2587 if (!CHAR_TABLE_ENTRYP (ct->level1[lb]))
2588 ct->level1[lb] = make_char_table_entry (ct->level1[lb]);
2589 cte = XCHAR_TABLE_ENTRY (ct->level1[lb]);
2590 /* now CTE is a char table entry for the charset;
2591 each entry is for a single row (or character of
2592 a one-octet charset). */
2593 if (XCHARSET_DIMENSION (charset) == 1)
2594 cte->level2[byte1 - 32] = val;
2597 /* assigning to one character in a two-octet charset. */
2598 /* make sure that the charset row contains a separate
2599 entry for each character. */
2600 if (!CHAR_TABLE_ENTRYP (cte->level2[byte1 - 32]))
2601 cte->level2[byte1 - 32] =
2602 make_char_table_entry (cte->level2[byte1 - 32]);
2603 cte = XCHAR_TABLE_ENTRY (cte->level2[byte1 - 32]);
2604 cte->level2[byte2 - 32] = val;
2608 #else /* not MULE */
2609 ct->ascii[(unsigned char) (range->ch)] = val;
2611 #endif /* not MULE */
2615 if (ct->type == CHAR_TABLE_TYPE_SYNTAX)
2616 update_syntax_table (ct);
2620 DEFUN ("put-char-table", Fput_char_table, 3, 3, 0, /*
2621 Set the value for chars in RANGE to be VALUE in CHAR-TABLE.
2623 RANGE specifies one or more characters to be affected and should be
2624 one of the following:
2626 -- t (all characters are affected)
2627 -- A charset (only allowed when Mule support is present)
2628 -- A vector of two elements: a two-octet charset and a row number
2629 (only allowed when Mule support is present)
2630 -- A single character
2632 VALUE must be a value appropriate for the type of CHAR-TABLE.
2633 See `valid-char-table-type-p'.
2635 (range, value, char_table))
2637 Lisp_Char_Table *ct;
2638 struct chartab_range rainj;
2640 CHECK_CHAR_TABLE (char_table);
2641 ct = XCHAR_TABLE (char_table);
2642 check_valid_char_table_value (value, ct->type, ERROR_ME);
2643 decode_char_table_range (range, &rainj);
2644 value = canonicalize_char_table_value (value, ct->type);
2645 put_char_table (ct, &rainj, value);
2650 /* Map FN over the ASCII chars in CT. */
2653 map_over_charset_ascii (Lisp_Char_Table *ct,
2654 int (*fn) (struct chartab_range *range,
2655 Lisp_Object val, void *arg),
2658 struct chartab_range rainj;
2667 rainj.type = CHARTAB_RANGE_CHAR;
2669 for (i = start, retval = 0; i < stop && retval == 0; i++)
2671 rainj.ch = (Emchar) i;
2672 retval = (fn) (&rainj, ct->ascii[i], arg);
2680 /* Map FN over the Control-1 chars in CT. */
2683 map_over_charset_control_1 (Lisp_Char_Table *ct,
2684 int (*fn) (struct chartab_range *range,
2685 Lisp_Object val, void *arg),
2688 struct chartab_range rainj;
2691 int stop = start + 32;
2693 rainj.type = CHARTAB_RANGE_CHAR;
2695 for (i = start, retval = 0; i < stop && retval == 0; i++)
2697 rainj.ch = (Emchar) (i);
2698 retval = (fn) (&rainj, ct->ascii[i], arg);
2704 /* Map FN over the row ROW of two-byte charset CHARSET.
2705 There must be a separate value for that row in the char table.
2706 CTE specifies the char table entry for CHARSET. */
2709 map_over_charset_row (Lisp_Char_Table_Entry *cte,
2710 Lisp_Object charset, int row,
2711 int (*fn) (struct chartab_range *range,
2712 Lisp_Object val, void *arg),
2715 Lisp_Object val = cte->level2[row - 32];
2717 if (!CHAR_TABLE_ENTRYP (val))
2719 struct chartab_range rainj;
2721 rainj.type = CHARTAB_RANGE_ROW;
2722 rainj.charset = charset;
2724 return (fn) (&rainj, val, arg);
2728 struct chartab_range rainj;
2730 int charset94_p = (XCHARSET_CHARS (charset) == 94);
2731 int start = charset94_p ? 33 : 32;
2732 int stop = charset94_p ? 127 : 128;
2734 cte = XCHAR_TABLE_ENTRY (val);
2736 rainj.type = CHARTAB_RANGE_CHAR;
2738 for (i = start, retval = 0; i < stop && retval == 0; i++)
2740 rainj.ch = MAKE_CHAR (charset, row, i);
2741 retval = (fn) (&rainj, cte->level2[i - 32], arg);
2749 map_over_other_charset (Lisp_Char_Table *ct, Charset_ID lb,
2750 int (*fn) (struct chartab_range *range,
2751 Lisp_Object val, void *arg),
2754 Lisp_Object val = ct->level1[lb - MIN_LEADING_BYTE];
2755 Lisp_Object charset = CHARSET_BY_LEADING_BYTE (lb);
2757 if (!CHARSETP (charset)
2758 || lb == LEADING_BYTE_ASCII
2759 || lb == LEADING_BYTE_CONTROL_1)
2762 if (!CHAR_TABLE_ENTRYP (val))
2764 struct chartab_range rainj;
2766 rainj.type = CHARTAB_RANGE_CHARSET;
2767 rainj.charset = charset;
2768 return (fn) (&rainj, val, arg);
2772 Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (val);
2773 int charset94_p = (XCHARSET_CHARS (charset) == 94);
2774 int start = charset94_p ? 33 : 32;
2775 int stop = charset94_p ? 127 : 128;
2778 if (XCHARSET_DIMENSION (charset) == 1)
2780 struct chartab_range rainj;
2781 rainj.type = CHARTAB_RANGE_CHAR;
2783 for (i = start, retval = 0; i < stop && retval == 0; i++)
2785 rainj.ch = MAKE_CHAR (charset, i, 0);
2786 retval = (fn) (&rainj, cte->level2[i - 32], arg);
2791 for (i = start, retval = 0; i < stop && retval == 0; i++)
2792 retval = map_over_charset_row (cte, charset, i, fn, arg);
2800 #endif /* not UTF2000 */
2803 struct map_char_table_for_charset_arg
2805 int (*fn) (struct chartab_range *range, Lisp_Object val, void *arg);
2806 Lisp_Char_Table *ct;
2811 map_char_table_for_charset_fun (struct chartab_range *range,
2812 Lisp_Object val, void *arg)
2814 struct map_char_table_for_charset_arg *closure =
2815 (struct map_char_table_for_charset_arg *) arg;
2818 switch (range->type)
2820 case CHARTAB_RANGE_ALL:
2823 case CHARTAB_RANGE_DEFAULT:
2826 case CHARTAB_RANGE_CHARSET:
2829 case CHARTAB_RANGE_ROW:
2832 case CHARTAB_RANGE_CHAR:
2833 ret = get_char_table (range->ch, closure->ct);
2834 if (!UNBOUNDP (ret))
2835 return (closure->fn) (range, ret, closure->arg);
2847 /* Map FN (with client data ARG) over range RANGE in char table CT.
2848 Mapping stops the first time FN returns non-zero, and that value
2849 becomes the return value of map_char_table(). */
2852 map_char_table (Lisp_Char_Table *ct,
2853 struct chartab_range *range,
2854 int (*fn) (struct chartab_range *range,
2855 Lisp_Object val, void *arg),
2858 switch (range->type)
2860 case CHARTAB_RANGE_ALL:
2862 if (!UNBOUNDP (ct->default_value))
2864 struct chartab_range rainj;
2867 rainj.type = CHARTAB_RANGE_DEFAULT;
2868 retval = (fn) (&rainj, ct->default_value, arg);
2872 if (UINT8_BYTE_TABLE_P (ct->table))
2873 return map_over_uint8_byte_table (XUINT8_BYTE_TABLE(ct->table), ct,
2875 else if (UINT16_BYTE_TABLE_P (ct->table))
2876 return map_over_uint16_byte_table (XUINT16_BYTE_TABLE(ct->table), ct,
2878 else if (BYTE_TABLE_P (ct->table))
2879 return map_over_byte_table (XBYTE_TABLE(ct->table), ct,
2881 else if (EQ (ct->table, Qunloaded))
2884 struct chartab_range rainj;
2887 Emchar c1 = c + unit;
2890 rainj.type = CHARTAB_RANGE_CHAR;
2892 for (retval = 0; c < c1 && retval == 0; c++)
2894 Lisp_Object ret = get_char_id_table (ct, c);
2896 if (!UNBOUNDP (ret))
2899 retval = (fn) (&rainj, ct->table, arg);
2904 ct->table = Qunbound;
2907 else if (!UNBOUNDP (ct->table))
2908 return (fn) (range, ct->table, arg);
2914 retval = map_over_charset_ascii (ct, fn, arg);
2918 retval = map_over_charset_control_1 (ct, fn, arg);
2923 Charset_ID start = MIN_LEADING_BYTE;
2924 Charset_ID stop = start + NUM_LEADING_BYTES;
2926 for (i = start, retval = 0; i < stop && retval == 0; i++)
2928 retval = map_over_other_charset (ct, i, fn, arg);
2937 case CHARTAB_RANGE_DEFAULT:
2938 if (!UNBOUNDP (ct->default_value))
2939 return (fn) (range, ct->default_value, arg);
2944 case CHARTAB_RANGE_CHARSET:
2947 Lisp_Object encoding_table
2948 = XCHARSET_ENCODING_TABLE (range->charset);
2950 if (!NILP (encoding_table))
2952 struct chartab_range rainj;
2953 struct map_char_table_for_charset_arg mcarg;
2956 if (XCHAR_TABLE_UNLOADED(encoding_table))
2957 Fload_char_attribute_table (XCHAR_TABLE_NAME (encoding_table));
2962 rainj.type = CHARTAB_RANGE_ALL;
2963 return map_char_table (XCHAR_TABLE(encoding_table),
2965 &map_char_table_for_charset_fun,
2971 return map_over_other_charset (ct,
2972 XCHARSET_LEADING_BYTE (range->charset),
2976 case CHARTAB_RANGE_ROW:
2979 int cell_min, cell_max, i;
2981 struct chartab_range rainj;
2983 i = XCHARSET_CELL_RANGE (range->charset);
2985 cell_max = i & 0xFF;
2986 rainj.type = CHARTAB_RANGE_CHAR;
2987 for (retval =0, i = cell_min; i <= cell_max && retval == 0; i++)
2990 = DECODE_CHAR (range->charset, (range->row << 8) | i, 0);
2992 if ( charset_code_point (range->charset, ch, 0) >= 0 )
2995 = get_byte_table (get_byte_table
2999 (unsigned char)(ch >> 24)),
3000 (unsigned char) (ch >> 16)),
3001 (unsigned char) (ch >> 8)),
3002 (unsigned char) ch);
3005 val = ct->default_value;
3007 retval = (fn) (&rainj, val, arg);
3014 Lisp_Object val = ct->level1[XCHARSET_LEADING_BYTE (range->charset)
3015 - MIN_LEADING_BYTE];
3016 if (!CHAR_TABLE_ENTRYP (val))
3018 struct chartab_range rainj;
3020 rainj.type = CHARTAB_RANGE_ROW;
3021 rainj.charset = range->charset;
3022 rainj.row = range->row;
3023 return (fn) (&rainj, val, arg);
3026 return map_over_charset_row (XCHAR_TABLE_ENTRY (val),
3027 range->charset, range->row,
3030 #endif /* not UTF2000 */
3033 case CHARTAB_RANGE_CHAR:
3035 Emchar ch = range->ch;
3036 Lisp_Object val = CHAR_TABLE_VALUE_UNSAFE (ct, ch);
3038 if (!UNBOUNDP (val))
3040 struct chartab_range rainj;
3042 rainj.type = CHARTAB_RANGE_CHAR;
3044 return (fn) (&rainj, val, arg);
3056 struct slow_map_char_table_arg
3058 Lisp_Object function;
3063 slow_map_char_table_fun (struct chartab_range *range,
3064 Lisp_Object val, void *arg)
3066 Lisp_Object ranjarg = Qnil;
3067 struct slow_map_char_table_arg *closure =
3068 (struct slow_map_char_table_arg *) arg;
3070 switch (range->type)
3072 case CHARTAB_RANGE_ALL:
3077 case CHARTAB_RANGE_DEFAULT:
3083 case CHARTAB_RANGE_CHARSET:
3084 ranjarg = XCHARSET_NAME (range->charset);
3087 case CHARTAB_RANGE_ROW:
3088 ranjarg = vector2 (XCHARSET_NAME (range->charset),
3089 make_int (range->row));
3092 case CHARTAB_RANGE_CHAR:
3093 ranjarg = make_char (range->ch);
3099 closure->retval = call2 (closure->function, ranjarg, val);
3100 return !NILP (closure->retval);
3103 DEFUN ("map-char-table", Fmap_char_table, 2, 3, 0, /*
3104 Map FUNCTION over entries in CHAR-TABLE, calling it with two args,
3105 each key and value in the table.
3107 RANGE specifies a subrange to map over and is in the same format as
3108 the RANGE argument to `put-range-table'. If omitted or t, it defaults to
3111 (function, char_table, range))
3113 Lisp_Char_Table *ct;
3114 struct slow_map_char_table_arg slarg;
3115 struct gcpro gcpro1, gcpro2;
3116 struct chartab_range rainj;
3118 CHECK_CHAR_TABLE (char_table);
3119 ct = XCHAR_TABLE (char_table);
3122 decode_char_table_range (range, &rainj);
3123 slarg.function = function;
3124 slarg.retval = Qnil;
3125 GCPRO2 (slarg.function, slarg.retval);
3126 map_char_table (ct, &rainj, slow_map_char_table_fun, &slarg);
3129 return slarg.retval;
3133 /************************************************************************/
3134 /* Character Attributes */
3135 /************************************************************************/
3139 Lisp_Object Vchar_attribute_hash_table;
3141 /* We store the char-attributes in hash tables with the names as the
3142 key and the actual char-id-table object as the value. Occasionally
3143 we need to use them in a list format. These routines provide us
3145 struct char_attribute_list_closure
3147 Lisp_Object *char_attribute_list;
3151 add_char_attribute_to_list_mapper (Lisp_Object key, Lisp_Object value,
3152 void *char_attribute_list_closure)
3154 /* This function can GC */
3155 struct char_attribute_list_closure *calcl
3156 = (struct char_attribute_list_closure*) char_attribute_list_closure;
3157 Lisp_Object *char_attribute_list = calcl->char_attribute_list;
3159 *char_attribute_list = Fcons (key, *char_attribute_list);
3163 #ifdef HAVE_LIBCHISE
3165 char_attribute_list_reset_map_func (CHISE_DS *ds, unsigned char *name)
3167 Fmount_char_attribute_table (intern (name));
3171 DEFUN ("char-attribute-list", Fchar_attribute_list, 0, 1, 0, /*
3172 Return the list of all existing character attributes except coded-charsets.
3176 DEFUN ("char-attribute-list", Fchar_attribute_list, 0, 0, 0, /*
3177 Return the list of all existing character attributes except coded-charsets.
3182 Lisp_Object char_attribute_list = Qnil;
3183 struct gcpro gcpro1;
3184 struct char_attribute_list_closure char_attribute_list_closure;
3186 #ifdef HAVE_LIBCHISE
3189 open_chise_data_source_maybe ();
3190 chise_ds_foreach_char_feature_name
3191 (default_chise_data_source, &char_attribute_list_reset_map_func);
3194 GCPRO1 (char_attribute_list);
3195 char_attribute_list_closure.char_attribute_list = &char_attribute_list;
3196 elisp_maphash (add_char_attribute_to_list_mapper,
3197 Vchar_attribute_hash_table,
3198 &char_attribute_list_closure);
3200 return char_attribute_list;
3203 DEFUN ("find-char-attribute-table", Ffind_char_attribute_table, 1, 1, 0, /*
3204 Return char-id-table corresponding to ATTRIBUTE.
3208 return Fgethash (attribute, Vchar_attribute_hash_table, Qnil);
3212 /* We store the char-id-tables in hash tables with the attributes as
3213 the key and the actual char-id-table object as the value. Each
3214 char-id-table stores values of an attribute corresponding with
3215 characters. Occasionally we need to get attributes of a character
3216 in a association-list format. These routines provide us with
3218 struct char_attribute_alist_closure
3221 Lisp_Object *char_attribute_alist;
3225 add_char_attribute_alist_mapper (Lisp_Object key, Lisp_Object value,
3226 void *char_attribute_alist_closure)
3228 /* This function can GC */
3229 struct char_attribute_alist_closure *caacl =
3230 (struct char_attribute_alist_closure*) char_attribute_alist_closure;
3232 = get_char_id_table (XCHAR_TABLE(value), caacl->char_id);
3233 if (!UNBOUNDP (ret))
3235 Lisp_Object *char_attribute_alist = caacl->char_attribute_alist;
3236 *char_attribute_alist
3237 = Fcons (Fcons (key, ret), *char_attribute_alist);
3242 DEFUN ("char-attribute-alist", Fchar_attribute_alist, 1, 1, 0, /*
3243 Return the alist of attributes of CHARACTER.
3247 struct gcpro gcpro1;
3248 struct char_attribute_alist_closure char_attribute_alist_closure;
3249 Lisp_Object alist = Qnil;
3251 CHECK_CHAR (character);
3254 char_attribute_alist_closure.char_id = XCHAR (character);
3255 char_attribute_alist_closure.char_attribute_alist = &alist;
3256 elisp_maphash (add_char_attribute_alist_mapper,
3257 Vchar_attribute_hash_table,
3258 &char_attribute_alist_closure);
3264 DEFUN ("get-char-attribute", Fget_char_attribute, 2, 3, 0, /*
3265 Return the value of CHARACTER's ATTRIBUTE.
3266 Return DEFAULT-VALUE if the value is not exist.
3268 (character, attribute, default_value))
3272 CHECK_CHAR (character);
3274 if (CHARSETP (attribute))
3275 attribute = XCHARSET_NAME (attribute);
3277 table = Fgethash (attribute, Vchar_attribute_hash_table,
3279 if (!UNBOUNDP (table))
3281 Lisp_Object ret = get_char_id_table (XCHAR_TABLE(table),
3283 if (!UNBOUNDP (ret))
3286 return default_value;
3290 find_char_feature_in_family (Lisp_Object character,
3291 Lisp_Object con_feature,
3292 Lisp_Object feature,
3293 Lisp_Object feature_rel_max)
3295 Lisp_Object ancestors
3296 = Fget_char_attribute (character, con_feature, Qnil);
3298 while (!NILP (ancestors))
3300 Lisp_Object ancestor = XCAR (ancestors);
3303 if (EQ (ancestor, character))
3306 ret = Fchar_feature (ancestor, feature, Qunbound,
3307 Qnil, make_int (0));
3308 if (!UNBOUNDP (ret))
3311 ancestors = XCDR (ancestors);
3313 ret = Fget_char_attribute (ancestor, Q_subsumptive_from, Qnil);
3315 ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
3317 ret = Fget_char_attribute (ancestor, Q_denotational_from, Qnil);
3319 ancestors = nconc2 (Fcopy_sequence (ancestors), ret);
3324 DEFUN ("char-feature", Fchar_feature, 2, 5, 0, /*
3325 Return the value of CHARACTER's FEATURE.
3326 Return DEFAULT-VALUE if the value is not exist.
3328 (character, attribute, default_value,
3329 feature_rel_max, char_rel_max))
3332 = Fget_char_attribute (character, attribute, Qunbound);
3334 if (!UNBOUNDP (ret))
3337 if (NILP (feature_rel_max)
3338 || (INTP (feature_rel_max) &&
3339 XINT (feature_rel_max) > 0))
3341 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3342 Bufbyte *name_str = string_data (name);
3344 if (name_str[0] == '=' && name_str[1] == '>')
3346 Bytecount length = string_length (name) - 1;
3347 Lisp_Object map_to = make_uninit_string (length);
3349 memcpy (XSTRING_DATA (map_to) + 1, name_str + 2, length - 1);
3350 XSTRING_DATA(map_to)[0] = '=';
3351 ret = Fchar_feature (character, Fintern (map_to, Qnil),
3353 NILP (feature_rel_max)
3355 : make_int (XINT (feature_rel_max) - 1),
3357 if (!UNBOUNDP (ret))
3362 if ( !(EQ (attribute, Q_identical)) &&
3363 !(EQ (attribute, Q_subsumptive_from)) &&
3364 !(EQ (attribute, Q_denotational_from)) &&
3365 ( (NILP (char_rel_max)
3366 || (INTP (char_rel_max) &&
3367 XINT (char_rel_max) > 0)) ) )
3369 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3370 Bufbyte *name_str = string_data (name);
3372 if ( (name_str[0] != '=') || (name_str[1] == '>') )
3374 ret = find_char_feature_in_family (character, Q_identical,
3375 attribute, feature_rel_max);
3376 if (!UNBOUNDP (ret))
3379 ret = find_char_feature_in_family (character, Q_subsumptive_from,
3380 attribute, feature_rel_max);
3381 if (!UNBOUNDP (ret))
3384 ret = find_char_feature_in_family (character, Q_denotational_from,
3385 attribute, feature_rel_max);
3386 if (!UNBOUNDP (ret))
3390 return default_value;
3394 put_char_composition (Lisp_Object character, Lisp_Object value);
3396 put_char_composition (Lisp_Object character, Lisp_Object value)
3399 signal_simple_error ("Invalid value for =decomposition",
3402 if (CONSP (XCDR (value)))
3404 if (NILP (Fcdr (XCDR (value))))
3406 Lisp_Object base = XCAR (value);
3407 Lisp_Object modifier = XCAR (XCDR (value));
3411 base = make_char (XINT (base));
3412 Fsetcar (value, base);
3414 if (INTP (modifier))
3416 modifier = make_char (XINT (modifier));
3417 Fsetcar (XCDR (value), modifier);
3422 = Fchar_feature (base, Qcomposition, Qnil,
3424 Lisp_Object ret = Fassq (modifier, alist);
3427 Fput_char_attribute (base, Qcomposition,
3428 Fcons (Fcons (modifier, character),
3431 Fsetcdr (ret, character);
3433 else if (EQ (base, Qsuper))
3434 return Q_superscript_of;
3435 else if (EQ (base, Qsub))
3436 return Q_subscript_of;
3437 else if (EQ (base, Qcompat))
3440 else if (EQ (XCAR (value), Qsuper))
3441 return Qto_decomposition_at_superscript;
3444 Fintern (concat2 (build_string ("=>decomposition@"),
3445 symbol_name (XSYMBOL (XCAR (value)))),
3452 Lisp_Object v = Fcar (value);
3456 Emchar c = DECODE_CHAR (Vcharset_ucs, XINT (v), 0);
3458 = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
3463 Fput_char_attribute (make_char (c), Q_ucs_unified,
3464 Fcons (character, Qnil));
3466 else if (NILP (Fmemq (character, ret)))
3468 Fput_char_attribute (make_char (c), Q_ucs_unified,
3469 Fcons (character, ret));
3474 return Qmap_decomposition;
3478 put_char_attribute (Lisp_Object character, Lisp_Object attribute,
3481 Lisp_Object table = Fgethash (attribute,
3482 Vchar_attribute_hash_table,
3487 table = make_char_id_table (Qunbound);
3488 Fputhash (attribute, table, Vchar_attribute_hash_table);
3490 XCHAR_TABLE_NAME (table) = attribute;
3493 put_char_id_table (XCHAR_TABLE(table), character, value);
3497 DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
3498 Store CHARACTER's ATTRIBUTE with VALUE.
3500 (character, attribute, value))
3502 Lisp_Object ccs = Ffind_charset (attribute);
3504 CHECK_CHAR (character);
3508 value = put_char_ccs_code_point (character, ccs, value);
3509 attribute = XCHARSET_NAME (ccs);
3511 else if ( EQ (attribute, Qmap_decomposition) ||
3512 EQ (attribute, Q_decomposition) )
3514 attribute = put_char_composition (character, value);
3515 if ( !EQ (attribute, Qmap_decomposition) &&
3516 SYMBOLP (XCAR (value)) )
3517 value = XCDR (value);
3519 else if (EQ (attribute, Qto_ucs))
3525 signal_simple_error ("Invalid value for =>ucs", value);
3527 c = DECODE_CHAR (Vcharset_ucs, XINT (value), 0);
3529 ret = Fchar_feature (make_char (c), Q_ucs_unified, Qnil,
3532 put_char_attribute (make_char (c), Q_ucs_unified,
3534 else if (NILP (Fmemq (character, ret)))
3535 Fput_char_attribute (make_char (c), Q_ucs_unified,
3536 Fcons (character, ret));
3538 if ( EQ (attribute, Q_subsumptive) ||
3539 EQ (attribute, Q_subsumptive_from) ||
3540 EQ (attribute, Q_denotational) ||
3541 EQ (attribute, Q_denotational_from) ||
3542 EQ (attribute, Q_identical) ||
3543 EQ (attribute, Q_identical_from) ||
3544 EQ (attribute, Q_canonical) ||
3545 EQ (attribute, Q_superscript_of) ||
3546 EQ (attribute, Q_subscript_of) ||
3547 EQ (attribute, Q_compat_of) ||
3548 EQ (attribute, Q_component) ||
3549 EQ (attribute, Q_component_of) ||
3550 !NILP (Fstring_match
3551 (build_string ("^\\(<-\\|->\\)\\("
3553 "\\|superscript\\|subscript\\|compat"
3554 "\\|fullwidth\\|halfwidth"
3555 "\\|simplified\\|vulgar\\|wrong"
3556 "\\|same\\|original\\|ancient"
3557 "\\|Oracle-Bones\\)[^*]*$"),
3558 Fsymbol_name (attribute),
3561 Lisp_Object rest = value;
3563 Lisp_Object rev_feature = Qnil;
3564 struct gcpro gcpro1;
3565 GCPRO1 (rev_feature);
3567 if (EQ (attribute, Q_identical))
3568 rev_feature = Q_identical_from;
3569 else if (EQ (attribute, Q_identical_from))
3570 rev_feature = Q_identical;
3571 else if (EQ (attribute, Q_subsumptive))
3572 rev_feature = Q_subsumptive_from;
3573 else if (EQ (attribute, Q_subsumptive_from))
3574 rev_feature = Q_subsumptive;
3575 else if (EQ (attribute, Q_denotational))
3576 rev_feature = Q_denotational_from;
3577 else if (EQ (attribute, Q_denotational_from))
3578 rev_feature = Q_denotational;
3579 else if (EQ (attribute, Q_component))
3580 rev_feature = Q_component_of;
3581 else if (EQ (attribute, Q_component_of))
3582 rev_feature = Q_component;
3585 Lisp_String* name = symbol_name (XSYMBOL (attribute));
3586 Bufbyte *name_str = string_data (name);
3588 if ( (name_str[0] == '<' && name_str[1] == '-') ||
3589 (name_str[0] == '-' && name_str[1] == '>') )
3591 Bytecount length = string_length (name);
3592 Bufbyte *rev_name_str = alloca (length + 1);
3594 memcpy (rev_name_str + 2, name_str + 2, length - 2);
3595 if (name_str[0] == '<')
3597 rev_name_str[0] = '-';
3598 rev_name_str[1] = '>';
3602 rev_name_str[0] = '<';
3603 rev_name_str[1] = '-';
3605 rev_name_str[length] = 0;
3606 rev_feature = intern (rev_name_str);
3610 while (CONSP (rest))
3615 ret = Fdefine_char (ret);
3616 else if (INTP (ret))
3618 int code_point = XINT (ret);
3619 Emchar cid = DECODE_CHAR (Vcharset_ucs, code_point, 0);
3622 ret = make_char (cid);
3624 ret = make_char (code_point);
3627 if ( !NILP (ret) && !EQ (ret, character) )
3631 ffv = Fget_char_attribute (ret, rev_feature, Qnil);
3633 put_char_attribute (ret, rev_feature, list1 (character));
3634 else if (NILP (Fmemq (character, ffv)))
3637 nconc2 (Fcopy_sequence (ffv), list1 (character)));
3638 Fsetcar (rest, ret);
3645 else if ( EQ (attribute, Qideographic_structure) ||
3646 !NILP (Fstring_match
3647 (build_string ("^=>decomposition\\(\\|@[^*]+\\)$"),
3648 Fsymbol_name (attribute),
3650 value = Fcopy_sequence (Fchar_refs_simplify_char_specs (value));
3652 return put_char_attribute (character, attribute, value);
3655 DEFUN ("remove-char-attribute", Fremove_char_attribute, 2, 2, 0, /*
3656 Remove CHARACTER's ATTRIBUTE.
3658 (character, attribute))
3662 CHECK_CHAR (character);
3663 ccs = Ffind_charset (attribute);
3666 return remove_char_ccs (character, ccs);
3670 Lisp_Object table = Fgethash (attribute,
3671 Vchar_attribute_hash_table,
3673 if (!UNBOUNDP (table))
3675 put_char_id_table (XCHAR_TABLE(table), character, Qunbound);
3684 int char_table_open_db_maybe (Lisp_Char_Table* cit);
3685 void char_table_close_db_maybe (Lisp_Char_Table* cit);
3686 Lisp_Object char_table_get_db (Lisp_Char_Table* cit, Emchar ch);
3688 #ifdef HAVE_LIBCHISE
3690 open_chise_data_source_maybe ()
3692 if (default_chise_data_source == NULL)
3694 Lisp_Object db_dir = Vdata_directory;
3695 int modemask = 0755; /* rwxr-xr-x */
3698 db_dir = build_string ("../etc");
3699 db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
3701 default_chise_data_source
3702 = CHISE_DS_open (CHISE_DS_Berkeley_DB, XSTRING_DATA (db_dir),
3703 0 /* DB_HASH */, modemask);
3704 if (default_chise_data_source == NULL)
3707 chise_ds_set_make_string_function (default_chise_data_source,
3713 #endif /* HAVE_LIBCHISE */
3715 DEFUN ("close-char-data-source", Fclose_char_data_source, 0, 0, 0, /*
3716 Close data-source of CHISE.
3720 #ifdef HAVE_LIBCHISE
3721 int status = CHISE_DS_close (default_chise_data_source);
3723 default_chise_data_source = NULL;
3726 #endif /* HAVE_LIBCHISE */
3731 char_table_open_db_maybe (Lisp_Char_Table* cit)
3733 Lisp_Object attribute = CHAR_TABLE_NAME (cit);
3735 if (!NILP (attribute))
3737 #ifdef HAVE_LIBCHISE
3738 if ( open_chise_data_source_maybe () )
3740 #else /* HAVE_LIBCHISE */
3741 if (NILP (Fdatabase_live_p (cit->db)))
3744 = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
3746 cit->db = Fopen_database (db_file, Qnil, Qnil,
3747 build_string ("r"), Qnil);
3751 #endif /* not HAVE_LIBCHISE */
3759 char_table_close_db_maybe (Lisp_Char_Table* cit)
3761 #ifndef HAVE_LIBCHISE
3762 if (!NILP (cit->db))
3764 if (!NILP (Fdatabase_live_p (cit->db)))
3765 Fclose_database (cit->db);
3768 #endif /* not HAVE_LIBCHISE */
3772 char_table_get_db (Lisp_Char_Table* cit, Emchar ch)
3775 #ifdef HAVE_LIBCHISE
3778 = chise_ds_load_char_feature_value (default_chise_data_source, ch,
3779 XSTRING_DATA(Fsymbol_name
3786 val = Fread (make_string (chise_value_data (&value),
3787 chise_value_size (&value) ));
3789 val = read_from_c_string (chise_value_data (&value),
3790 chise_value_size (&value) );
3795 #else /* HAVE_LIBCHISE */
3796 val = Fget_database (Fprin1_to_string (make_char (ch), Qnil),
3798 if (!UNBOUNDP (val))
3802 #endif /* not HAVE_LIBCHISE */
3806 #ifndef HAVE_LIBCHISE
3808 char_attribute_system_db_file (Lisp_Object key_type, Lisp_Object attribute,
3811 Lisp_Object db_dir = Vdata_directory;
3814 db_dir = build_string ("../etc");
3816 db_dir = Fexpand_file_name (build_string ("chise-db"), db_dir);
3817 if (writing_mode && NILP (Ffile_exists_p (db_dir)))
3818 Fmake_directory_internal (db_dir);
3820 db_dir = Fexpand_file_name (Fsymbol_name (key_type), db_dir);
3821 if (writing_mode && NILP (Ffile_exists_p (db_dir)))
3822 Fmake_directory_internal (db_dir);
3825 Lisp_Object attribute_name = Fsymbol_name (attribute);
3826 Lisp_Object dest = Qnil, ret;
3828 struct gcpro gcpro1, gcpro2;
3829 int len = XSTRING_CHAR_LENGTH (attribute_name);
3833 for (i = 0; i < len; i++)
3835 Emchar c = string_char (XSTRING (attribute_name), i);
3837 if ( (c == '/') || (c == '%') )
3841 sprintf (str, "%%%02X", c);
3842 dest = concat3 (dest,
3843 Fsubstring (attribute_name,
3844 make_int (base), make_int (i)),
3845 build_string (str));
3849 ret = Fsubstring (attribute_name, make_int (base), make_int (len));
3850 dest = concat2 (dest, ret);
3852 return Fexpand_file_name (dest, db_dir);
3855 #endif /* not HAVE_LIBCHISE */
3857 DEFUN ("save-char-attribute-table", Fsave_char_attribute_table, 1, 1, 0, /*
3858 Save values of ATTRIBUTE into database file.
3862 Lisp_Object table = Fgethash (attribute,
3863 Vchar_attribute_hash_table, Qunbound);
3864 Lisp_Char_Table *ct;
3865 #ifdef HAVE_LIBCHISE
3866 CHISE_Feature feature;
3867 #else /* HAVE_LIBCHISE */
3868 Lisp_Object db_file;
3870 #endif /* not HAVE_LIBCHISE */
3872 if (CHAR_TABLEP (table))
3873 ct = XCHAR_TABLE (table);
3877 #ifdef HAVE_LIBCHISE
3878 if ( open_chise_data_source_maybe () )
3881 = chise_ds_get_feature (default_chise_data_source,
3882 XSTRING_DATA (Fsymbol_name (attribute)));
3883 #else /* HAVE_LIBCHISE */
3884 db_file = char_attribute_system_db_file (Qsystem_char_id, attribute, 1);
3885 db = Fopen_database (db_file, Qnil, Qnil, build_string ("w+"), Qnil);
3886 #endif /* not HAVE_LIBCHISE */
3888 #ifdef HAVE_LIBCHISE
3890 #else /* HAVE_LIBCHISE */
3892 #endif /* not HAVE_LIBCHISE */
3895 Lisp_Object (*filter)(Lisp_Object value);
3897 if ( !NILP (Ffind_charset (attribute)) )
3899 else if ( EQ (attribute, Qideographic_structure) ||
3900 EQ (attribute, Q_identical) ||
3901 EQ (attribute, Q_identical_from) ||
3902 EQ (attribute, Q_canonical) ||
3903 EQ (attribute, Q_superscript_of) ||
3904 EQ (attribute, Q_subscript_of) ||
3905 EQ (attribute, Q_compat_of) ||
3906 !NILP (Fstring_match
3907 (build_string ("^\\(<-\\|->\\)\\(simplified"
3908 "\\|same\\|vulgar\\|wrong"
3909 "\\|original\\|ancient"
3910 "\\|Oracle-Bones\\)[^*]*$"),
3911 Fsymbol_name (attribute),
3913 filter = &Fchar_refs_simplify_char_specs;
3917 if (UINT8_BYTE_TABLE_P (ct->table))
3918 save_uint8_byte_table (XUINT8_BYTE_TABLE(ct->table), ct,
3919 #ifdef HAVE_LIBCHISE
3921 #else /* HAVE_LIBCHISE */
3923 #endif /* not HAVE_LIBCHISE */
3925 else if (UINT16_BYTE_TABLE_P (ct->table))
3926 save_uint16_byte_table (XUINT16_BYTE_TABLE(ct->table), ct,
3927 #ifdef HAVE_LIBCHISE
3929 #else /* HAVE_LIBCHISE */
3931 #endif /* not HAVE_LIBCHISE */
3933 else if (BYTE_TABLE_P (ct->table))
3934 save_byte_table (XBYTE_TABLE(ct->table), ct,
3935 #ifdef HAVE_LIBCHISE
3937 #else /* HAVE_LIBCHISE */
3939 #endif /* not HAVE_LIBCHISE */
3941 #ifdef HAVE_LIBCHISE
3942 chise_feature_sync (feature);
3943 #else /* HAVE_LIBCHISE */
3944 Fclose_database (db);
3945 #endif /* not HAVE_LIBCHISE */
3952 DEFUN ("mount-char-attribute-table", Fmount_char_attribute_table, 1, 1, 0, /*
3953 Mount database file on char-attribute-table ATTRIBUTE.
3957 Lisp_Object table = Fgethash (attribute,
3958 Vchar_attribute_hash_table, Qunbound);
3960 if (UNBOUNDP (table))
3962 Lisp_Char_Table *ct;
3964 table = make_char_id_table (Qunbound);
3965 Fputhash (attribute, table, Vchar_attribute_hash_table);
3966 XCHAR_TABLE_NAME(table) = attribute;
3967 ct = XCHAR_TABLE (table);
3968 ct->table = Qunloaded;
3969 XCHAR_TABLE_UNLOADED(table) = 1;
3970 #ifndef HAVE_LIBCHISE
3972 #endif /* not HAVE_LIBCHISE */
3978 DEFUN ("close-char-attribute-table", Fclose_char_attribute_table, 1, 1, 0, /*
3979 Close database of ATTRIBUTE.
3983 Lisp_Object table = Fgethash (attribute,
3984 Vchar_attribute_hash_table, Qunbound);
3985 Lisp_Char_Table *ct;
3987 if (CHAR_TABLEP (table))
3988 ct = XCHAR_TABLE (table);
3991 char_table_close_db_maybe (ct);
3995 DEFUN ("reset-char-attribute-table", Freset_char_attribute_table, 1, 1, 0, /*
3996 Reset values of ATTRIBUTE with database file.
4000 #ifdef HAVE_LIBCHISE
4001 CHISE_Feature feature
4002 = chise_ds_get_feature (default_chise_data_source,
4003 XSTRING_DATA (Fsymbol_name
4006 if (feature == NULL)
4009 if (chise_feature_setup_db (feature, 0) == 0)
4011 Lisp_Object table = Fgethash (attribute,
4012 Vchar_attribute_hash_table, Qunbound);
4013 Lisp_Char_Table *ct;
4015 chise_feature_sync (feature);
4016 if (UNBOUNDP (table))
4018 table = make_char_id_table (Qunbound);
4019 Fputhash (attribute, table, Vchar_attribute_hash_table);
4020 XCHAR_TABLE_NAME(table) = attribute;
4022 ct = XCHAR_TABLE (table);
4023 ct->table = Qunloaded;
4024 char_table_close_db_maybe (ct);
4025 XCHAR_TABLE_UNLOADED(table) = 1;
4029 Lisp_Object table = Fgethash (attribute,
4030 Vchar_attribute_hash_table, Qunbound);
4031 Lisp_Char_Table *ct;
4033 = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
4035 if (!NILP (Ffile_exists_p (db_file)))
4037 if (UNBOUNDP (table))
4039 table = make_char_id_table (Qunbound);
4040 Fputhash (attribute, table, Vchar_attribute_hash_table);
4041 XCHAR_TABLE_NAME(table) = attribute;
4043 ct = XCHAR_TABLE (table);
4044 ct->table = Qunloaded;
4045 char_table_close_db_maybe (ct);
4046 XCHAR_TABLE_UNLOADED(table) = 1;
4054 load_char_attribute_maybe (Lisp_Char_Table* cit, Emchar ch)
4056 Lisp_Object attribute = CHAR_TABLE_NAME (cit);
4058 if (!NILP (attribute))
4062 if (char_table_open_db_maybe (cit))
4065 val = char_table_get_db (cit, ch);
4067 if (!NILP (Vchar_db_stingy_mode))
4068 char_table_close_db_maybe (cit);
4075 Lisp_Char_Table* char_attribute_table_to_load;
4077 #ifdef HAVE_LIBCHISE
4079 load_char_attribute_table_map_func (CHISE_Char_ID cid,
4080 CHISE_Feature feature,
4081 CHISE_Value *value);
4083 load_char_attribute_table_map_func (CHISE_Char_ID cid,
4084 CHISE_Feature feature,
4088 Lisp_Object ret = get_char_id_table_0 (char_attribute_table_to_load, code);
4090 if (EQ (ret, Qunloaded))
4091 put_char_id_table_0 (char_attribute_table_to_load, code,
4092 Fread (make_string ((Bufbyte *) value->data,
4096 #else /* HAVE_LIBCHISE */
4097 Lisp_Object Qload_char_attribute_table_map_function;
4099 DEFUN ("load-char-attribute-table-map-function",
4100 Fload_char_attribute_table_map_function, 2, 2, 0, /*
4101 For internal use. Don't use it.
4105 Lisp_Object c = Fread (key);
4106 Emchar code = XCHAR (c);
4107 Lisp_Object ret = get_char_id_table_0 (char_attribute_table_to_load, code);
4109 if (EQ (ret, Qunloaded))
4110 put_char_id_table_0 (char_attribute_table_to_load, code, Fread (value));
4113 #endif /* not HAVE_LIBCHISE */
4115 DEFUN ("load-char-attribute-table", Fload_char_attribute_table, 1, 1, 0, /*
4116 Load values of ATTRIBUTE into database file.
4120 Lisp_Object table = Fgethash (attribute,
4121 Vchar_attribute_hash_table,
4123 if (CHAR_TABLEP (table))
4125 Lisp_Char_Table *cit = XCHAR_TABLE (table);
4127 if (char_table_open_db_maybe (cit))
4130 char_attribute_table_to_load = XCHAR_TABLE (table);
4132 struct gcpro gcpro1;
4135 #ifdef HAVE_LIBCHISE
4136 chise_feature_foreach_char_with_value
4137 (chise_ds_get_feature (default_chise_data_source,
4138 XSTRING_DATA (Fsymbol_name (cit->name))),
4139 &load_char_attribute_table_map_func);
4140 #else /* HAVE_LIBCHISE */
4141 Fmap_database (Qload_char_attribute_table_map_function, cit->db);
4142 #endif /* not HAVE_LIBCHISE */
4145 char_table_close_db_maybe (cit);
4146 XCHAR_TABLE_UNLOADED(table) = 0;
4151 #endif /* HAVE_CHISE */
4153 DEFUN ("map-char-attribute", Fmap_char_attribute, 2, 3, 0, /*
4154 Map FUNCTION over entries in ATTRIBUTE, calling it with two args,
4155 each key and value in the table.
4157 RANGE specifies a subrange to map over and is in the same format as
4158 the RANGE argument to `put-range-table'. If omitted or t, it defaults to
4161 (function, attribute, range))
4164 Lisp_Char_Table *ct;
4165 struct slow_map_char_table_arg slarg;
4166 struct gcpro gcpro1, gcpro2;
4167 struct chartab_range rainj;
4169 if (!NILP (ccs = Ffind_charset (attribute)))
4171 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
4173 if (CHAR_TABLEP (encoding_table))
4174 ct = XCHAR_TABLE (encoding_table);
4180 Lisp_Object table = Fgethash (attribute,
4181 Vchar_attribute_hash_table,
4183 if (CHAR_TABLEP (table))
4184 ct = XCHAR_TABLE (table);
4190 decode_char_table_range (range, &rainj);
4192 if (CHAR_TABLE_UNLOADED(ct))
4193 Fload_char_attribute_table (attribute);
4195 slarg.function = function;
4196 slarg.retval = Qnil;
4197 GCPRO2 (slarg.function, slarg.retval);
4198 map_char_table (ct, &rainj, slow_map_char_table_fun, &slarg);
4201 return slarg.retval;
4204 DEFUN ("define-char", Fdefine_char, 1, 1, 0, /*
4205 Store character's ATTRIBUTES.
4210 Lisp_Object code = Fcdr (Fassq (Qmap_ucs, attributes));
4211 Lisp_Object character;
4214 code = Fcdr (Fassq (Qucs, attributes));
4219 while (CONSP (rest))
4221 Lisp_Object cell = Fcar (rest);
4224 if ( !LISTP (cell) )
4225 signal_simple_error ("Invalid argument", attributes);
4227 ccs = Ffind_charset (Fcar (cell));
4233 character = Fdecode_char (ccs, cell, Qt, Qt);
4234 if (!NILP (character))
4235 goto setup_attributes;
4237 if ( (XCHARSET_FINAL (ccs) != 0) ||
4238 (XCHARSET_MAX_CODE (ccs) > 0) ||
4239 (EQ (ccs, Vcharset_chinese_big5)) )
4243 = Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
4245 character = Fdecode_char (ccs, cell, Qnil, Qt);
4246 if (!NILP (character))
4247 goto setup_attributes;
4254 int cid = XINT (Vnext_defined_char_id);
4256 if (cid <= 0xE00000)
4258 character = make_char (cid);
4259 Vnext_defined_char_id = make_int (cid + 1);
4260 goto setup_attributes;
4264 if ( (!NILP (code = Fcdr (Fassq (Qto_ucs, attributes)))) )
4267 signal_simple_error ("Invalid argument", attributes);
4269 character = make_char (XINT (code) + 0x100000);
4270 goto setup_attributes;
4275 else if (!INTP (code))
4276 signal_simple_error ("Invalid argument", attributes);
4278 character = make_char (XINT (code));
4282 while (CONSP (rest))
4284 Lisp_Object cell = Fcar (rest);
4287 signal_simple_error ("Invalid argument", attributes);
4289 Fput_char_attribute (character, Fcar (cell), Fcdr (cell));
4295 DEFUN ("find-char", Ffind_char, 1, 1, 0, /*
4296 Retrieve the character of the given ATTRIBUTES.
4300 Lisp_Object rest = attributes;
4303 while (CONSP (rest))
4305 Lisp_Object cell = Fcar (rest);
4309 signal_simple_error ("Invalid argument", attributes);
4310 if (!NILP (ccs = Ffind_charset (Fcar (cell))))
4314 return Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
4316 return Fdecode_char (ccs, cell, Qnil, Qnil);
4320 if ( (!NILP (code = Fcdr (Fassq (Qto_ucs, attributes)))) )
4323 signal_simple_error ("Invalid argument", attributes);
4325 return make_char (XINT (code) + 0x100000);
4333 /************************************************************************/
4334 /* Char table read syntax */
4335 /************************************************************************/
4338 chartab_type_validate (Lisp_Object keyword, Lisp_Object value,
4339 Error_behavior errb)
4341 /* #### should deal with ERRB */
4342 symbol_to_char_table_type (value);
4347 chartab_data_validate (Lisp_Object keyword, Lisp_Object value,
4348 Error_behavior errb)
4352 /* #### should deal with ERRB */
4353 EXTERNAL_LIST_LOOP (rest, value)
4355 Lisp_Object range = XCAR (rest);
4356 struct chartab_range dummy;
4360 signal_simple_error ("Invalid list format", value);
4363 if (!CONSP (XCDR (range))
4364 || !NILP (XCDR (XCDR (range))))
4365 signal_simple_error ("Invalid range format", range);
4366 decode_char_table_range (XCAR (range), &dummy);
4367 decode_char_table_range (XCAR (XCDR (range)), &dummy);
4370 decode_char_table_range (range, &dummy);
4377 chartab_instantiate (Lisp_Object data)
4379 Lisp_Object chartab;
4380 Lisp_Object type = Qgeneric;
4381 Lisp_Object dataval = Qnil;
4383 while (!NILP (data))
4385 Lisp_Object keyw = Fcar (data);
4391 if (EQ (keyw, Qtype))
4393 else if (EQ (keyw, Qdata))
4397 chartab = Fmake_char_table (type);
4400 while (!NILP (data))
4402 Lisp_Object range = Fcar (data);
4403 Lisp_Object val = Fcar (Fcdr (data));
4405 data = Fcdr (Fcdr (data));
4408 if (CHAR_OR_CHAR_INTP (XCAR (range)))
4410 Emchar first = XCHAR_OR_CHAR_INT (Fcar (range));
4411 Emchar last = XCHAR_OR_CHAR_INT (Fcar (Fcdr (range)));
4414 for (i = first; i <= last; i++)
4415 Fput_char_table (make_char (i), val, chartab);
4421 Fput_char_table (range, val, chartab);
4430 /************************************************************************/
4431 /* Category Tables, specifically */
4432 /************************************************************************/
4434 DEFUN ("category-table-p", Fcategory_table_p, 1, 1, 0, /*
4435 Return t if OBJECT is a category table.
4436 A category table is a type of char table used for keeping track of
4437 categories. Categories are used for classifying characters for use
4438 in regexps -- you can refer to a category rather than having to use
4439 a complicated [] expression (and category lookups are significantly
4442 There are 95 different categories available, one for each printable
4443 character (including space) in the ASCII charset. Each category
4444 is designated by one such character, called a "category designator".
4445 They are specified in a regexp using the syntax "\\cX", where X is
4446 a category designator.
4448 A category table specifies, for each character, the categories that
4449 the character is in. Note that a character can be in more than one
4450 category. More specifically, a category table maps from a character
4451 to either the value nil (meaning the character is in no categories)
4452 or a 95-element bit vector, specifying for each of the 95 categories
4453 whether the character is in that category.
4455 Special Lisp functions are provided that abstract this, so you do not
4456 have to directly manipulate bit vectors.
4460 return (CHAR_TABLEP (object) &&
4461 XCHAR_TABLE_TYPE (object) == CHAR_TABLE_TYPE_CATEGORY) ?
4466 check_category_table (Lisp_Object object, Lisp_Object default_)
4470 while (NILP (Fcategory_table_p (object)))
4471 object = wrong_type_argument (Qcategory_table_p, object);
4476 check_category_char (Emchar ch, Lisp_Object table,
4477 unsigned int designator, unsigned int not_p)
4479 REGISTER Lisp_Object temp;
4480 Lisp_Char_Table *ctbl;
4481 #ifdef ERROR_CHECK_TYPECHECK
4482 if (NILP (Fcategory_table_p (table)))
4483 signal_simple_error ("Expected category table", table);
4485 ctbl = XCHAR_TABLE (table);
4486 temp = get_char_table (ch, ctbl);
4491 return bit_vector_bit (XBIT_VECTOR (temp), designator) ? !not_p : not_p;
4494 DEFUN ("check-category-at", Fcheck_category_at, 2, 4, 0, /*
4495 Return t if category of the character at POSITION includes DESIGNATOR.
4496 Optional third arg BUFFER specifies which buffer to use, and defaults
4497 to the current buffer.
4498 Optional fourth arg CATEGORY-TABLE specifies the category table to
4499 use, and defaults to BUFFER's category table.
4501 (position, designator, buffer, category_table))
4506 struct buffer *buf = decode_buffer (buffer, 0);
4508 CHECK_INT (position);
4509 CHECK_CATEGORY_DESIGNATOR (designator);
4510 des = XCHAR (designator);
4511 ctbl = check_category_table (category_table, Vstandard_category_table);
4512 ch = BUF_FETCH_CHAR (buf, XINT (position));
4513 return check_category_char (ch, ctbl, des, 0) ? Qt : Qnil;
4516 DEFUN ("char-in-category-p", Fchar_in_category_p, 2, 3, 0, /*
4517 Return t if category of CHARACTER includes DESIGNATOR, else nil.
4518 Optional third arg CATEGORY-TABLE specifies the category table to use,
4519 and defaults to the standard category table.
4521 (character, designator, category_table))
4527 CHECK_CATEGORY_DESIGNATOR (designator);
4528 des = XCHAR (designator);
4529 CHECK_CHAR (character);
4530 ch = XCHAR (character);
4531 ctbl = check_category_table (category_table, Vstandard_category_table);
4532 return check_category_char (ch, ctbl, des, 0) ? Qt : Qnil;
4535 DEFUN ("category-table", Fcategory_table, 0, 1, 0, /*
4536 Return BUFFER's current category table.
4537 BUFFER defaults to the current buffer.
4541 return decode_buffer (buffer, 0)->category_table;
4544 DEFUN ("standard-category-table", Fstandard_category_table, 0, 0, 0, /*
4545 Return the standard category table.
4546 This is the one used for new buffers.
4550 return Vstandard_category_table;
4553 DEFUN ("copy-category-table", Fcopy_category_table, 0, 1, 0, /*
4554 Return a new category table which is a copy of CATEGORY-TABLE.
4555 CATEGORY-TABLE defaults to the standard category table.
4559 if (NILP (Vstandard_category_table))
4560 return Fmake_char_table (Qcategory);
4563 check_category_table (category_table, Vstandard_category_table);
4564 return Fcopy_char_table (category_table);
4567 DEFUN ("set-category-table", Fset_category_table, 1, 2, 0, /*
4568 Select CATEGORY-TABLE as the new category table for BUFFER.
4569 BUFFER defaults to the current buffer if omitted.
4571 (category_table, buffer))
4573 struct buffer *buf = decode_buffer (buffer, 0);
4574 category_table = check_category_table (category_table, Qnil);
4575 buf->category_table = category_table;
4576 /* Indicate that this buffer now has a specified category table. */
4577 buf->local_var_flags |= XINT (buffer_local_flags.category_table);
4578 return category_table;
4581 DEFUN ("category-designator-p", Fcategory_designator_p, 1, 1, 0, /*
4582 Return t if OBJECT is a category designator (a char in the range ' ' to '~').
4586 return CATEGORY_DESIGNATORP (object) ? Qt : Qnil;
4589 DEFUN ("category-table-value-p", Fcategory_table_value_p, 1, 1, 0, /*
4590 Return t if OBJECT is a category table value.
4591 Valid values are nil or a bit vector of size 95.
4595 return CATEGORY_TABLE_VALUEP (object) ? Qt : Qnil;
4599 #define CATEGORYP(x) \
4600 (CHARP (x) && XCHAR (x) >= 0x20 && XCHAR (x) <= 0x7E)
4602 #define CATEGORY_SET(c) \
4603 (get_char_table(c, XCHAR_TABLE(current_buffer->category_table)))
4605 /* Return 1 if CATEGORY_SET contains CATEGORY, else return 0.
4606 The faster version of `!NILP (Faref (category_set, category))'. */
4607 #define CATEGORY_MEMBER(category, category_set) \
4608 (bit_vector_bit(XBIT_VECTOR (category_set), category - 32))
4610 /* Return 1 if there is a word boundary between two word-constituent
4611 characters C1 and C2 if they appear in this order, else return 0.
4612 Use the macro WORD_BOUNDARY_P instead of calling this function
4615 int word_boundary_p (Emchar c1, Emchar c2);
4617 word_boundary_p (Emchar c1, Emchar c2)
4619 Lisp_Object category_set1, category_set2;
4624 if (COMPOSITE_CHAR_P (c1))
4625 c1 = cmpchar_component (c1, 0, 1);
4626 if (COMPOSITE_CHAR_P (c2))
4627 c2 = cmpchar_component (c2, 0, 1);
4631 if (EQ (CHAR_CHARSET (c1), CHAR_CHARSET (c2)))
4634 tail = Vword_separating_categories;
4640 tail = Vword_combining_categories;
4645 category_set1 = CATEGORY_SET (c1);
4646 if (NILP (category_set1))
4647 return default_result;
4648 category_set2 = CATEGORY_SET (c2);
4649 if (NILP (category_set2))
4650 return default_result;
4652 for (; CONSP (tail); tail = XCONS (tail)->cdr)
4654 Lisp_Object elt = XCONS(tail)->car;
4657 && CATEGORYP (XCONS (elt)->car)
4658 && CATEGORYP (XCONS (elt)->cdr)
4659 && CATEGORY_MEMBER (XCHAR (XCONS (elt)->car), category_set1)
4660 && CATEGORY_MEMBER (XCHAR (XCONS (elt)->cdr), category_set2))
4661 return !default_result;
4663 return default_result;
4669 syms_of_chartab (void)
4672 INIT_LRECORD_IMPLEMENTATION (uint8_byte_table);
4673 INIT_LRECORD_IMPLEMENTATION (uint16_byte_table);
4674 INIT_LRECORD_IMPLEMENTATION (byte_table);
4676 defsymbol (&Qto_ucs, "=>ucs");
4677 defsymbol (&Q_ucs_unified, "->ucs-unified");
4678 defsymbol (&Q_subsumptive, "->subsumptive");
4679 defsymbol (&Q_subsumptive_from, "<-subsumptive");
4680 defsymbol (&Q_denotational, "->denotational");
4681 defsymbol (&Q_denotational_from, "<-denotational");
4682 defsymbol (&Q_identical, "->identical");
4683 defsymbol (&Q_identical_from, "<-identical");
4684 defsymbol (&Q_component, "->ideographic-component-forms");
4685 defsymbol (&Q_component_of, "<-ideographic-component-forms");
4686 defsymbol (&Qcomposition, "composition");
4687 defsymbol (&Qmap_decomposition, "=decomposition");
4688 defsymbol (&Qto_decomposition_at_superscript,
4689 "=>decomposition@superscript");
4690 defsymbol (&Q_canonical, "->canonical");
4691 defsymbol (&Q_superscript_of, "<-superscript");
4692 defsymbol (&Q_subscript_of, "<-subscript");
4693 defsymbol (&Q_compat_of, "<-compat");
4694 defsymbol (&Q_decomposition, "->decomposition");
4695 defsymbol (&Qcompat, "compat");
4696 defsymbol (&Qisolated, "isolated");
4697 defsymbol (&Qinitial, "initial");
4698 defsymbol (&Qmedial, "medial");
4699 defsymbol (&Qfinal, "final");
4700 defsymbol (&Qvertical, "vertical");
4701 defsymbol (&QnoBreak, "noBreak");
4702 defsymbol (&Qfraction, "fraction");
4703 defsymbol (&Qsuper, "super");
4704 defsymbol (&Qsub, "sub");
4705 defsymbol (&Qcircle, "circle");
4706 defsymbol (&Qsquare, "square");
4707 defsymbol (&Qwide, "wide");
4708 defsymbol (&Qnarrow, "narrow");
4709 defsymbol (&Qsmall, "small");
4710 defsymbol (&Qfont, "font");
4712 DEFSUBR (Fchar_attribute_list);
4713 DEFSUBR (Ffind_char_attribute_table);
4714 defsymbol (&Qput_char_table_map_function, "put-char-table-map-function");
4715 DEFSUBR (Fput_char_table_map_function);
4717 DEFSUBR (Fsave_char_attribute_table);
4718 DEFSUBR (Fmount_char_attribute_table);
4719 DEFSUBR (Freset_char_attribute_table);
4720 DEFSUBR (Fclose_char_attribute_table);
4721 DEFSUBR (Fclose_char_data_source);
4722 #ifndef HAVE_LIBCHISE
4723 defsymbol (&Qload_char_attribute_table_map_function,
4724 "load-char-attribute-table-map-function");
4725 DEFSUBR (Fload_char_attribute_table_map_function);
4727 DEFSUBR (Fload_char_attribute_table);
4729 DEFSUBR (Fchar_feature);
4730 DEFSUBR (Fchar_attribute_alist);
4731 DEFSUBR (Fget_char_attribute);
4732 DEFSUBR (Fput_char_attribute);
4733 DEFSUBR (Fremove_char_attribute);
4734 DEFSUBR (Fmap_char_attribute);
4735 DEFSUBR (Fdefine_char);
4736 DEFSUBR (Ffind_char);
4737 DEFSUBR (Fchar_variants);
4739 DEFSUBR (Fget_composite_char);
4742 INIT_LRECORD_IMPLEMENTATION (char_table);
4746 INIT_LRECORD_IMPLEMENTATION (char_table_entry);
4749 defsymbol (&Qcategory_table_p, "category-table-p");
4750 defsymbol (&Qcategory_designator_p, "category-designator-p");
4751 defsymbol (&Qcategory_table_value_p, "category-table-value-p");
4754 defsymbol (&Qchar_table, "char-table");
4755 defsymbol (&Qchar_tablep, "char-table-p");
4757 DEFSUBR (Fchar_table_p);
4758 DEFSUBR (Fchar_table_type_list);
4759 DEFSUBR (Fvalid_char_table_type_p);
4760 DEFSUBR (Fchar_table_type);
4761 DEFSUBR (Freset_char_table);
4762 DEFSUBR (Fmake_char_table);
4763 DEFSUBR (Fcopy_char_table);
4764 DEFSUBR (Fget_char_table);
4765 DEFSUBR (Fget_range_char_table);
4766 DEFSUBR (Fvalid_char_table_value_p);
4767 DEFSUBR (Fcheck_valid_char_table_value);
4768 DEFSUBR (Fput_char_table);
4769 DEFSUBR (Fmap_char_table);
4772 DEFSUBR (Fcategory_table_p);
4773 DEFSUBR (Fcategory_table);
4774 DEFSUBR (Fstandard_category_table);
4775 DEFSUBR (Fcopy_category_table);
4776 DEFSUBR (Fset_category_table);
4777 DEFSUBR (Fcheck_category_at);
4778 DEFSUBR (Fchar_in_category_p);
4779 DEFSUBR (Fcategory_designator_p);
4780 DEFSUBR (Fcategory_table_value_p);
4786 vars_of_chartab (void)
4789 DEFVAR_LISP ("next-defined-char-id", &Vnext_defined_char_id /*
4791 Vnext_defined_char_id = make_int (0x0F0000);
4795 DEFVAR_LISP ("char-db-stingy-mode", &Vchar_db_stingy_mode /*
4797 Vchar_db_stingy_mode = Qt;
4799 #ifdef HAVE_LIBCHISE
4800 Vchise_db_directory = build_string(chise_db_dir);
4801 DEFVAR_LISP ("chise-db-directory", &Vchise_db_directory /*
4802 Directory of CHISE character databases.
4805 Vchise_system_db_directory = build_string(chise_system_db_dir);
4806 DEFVAR_LISP ("chise-system-db-directory", &Vchise_system_db_directory /*
4807 Directory of system character database of CHISE.
4811 #endif /* HAVE_CHISE */
4812 /* DO NOT staticpro this. It works just like Vweak_hash_tables. */
4813 Vall_syntax_tables = Qnil;
4814 dump_add_weak_object_chain (&Vall_syntax_tables);
4818 structure_type_create_chartab (void)
4820 struct structure_type *st;
4822 st = define_structure_type (Qchar_table, 0, chartab_instantiate);
4824 define_structure_type_keyword (st, Qtype, chartab_type_validate);
4825 define_structure_type_keyword (st, Qdata, chartab_data_validate);
4829 complex_vars_of_chartab (void)
4832 staticpro (&Vchar_attribute_hash_table);
4833 Vchar_attribute_hash_table
4834 = make_lisp_hash_table (16, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
4835 #endif /* UTF2000 */
4837 /* Set this now, so first buffer creation can refer to it. */
4838 /* Make it nil before calling copy-category-table
4839 so that copy-category-table will know not to try to copy from garbage */
4840 Vstandard_category_table = Qnil;
4841 Vstandard_category_table = Fcopy_category_table (Qnil);
4842 staticpro (&Vstandard_category_table);
4844 DEFVAR_LISP ("word-combining-categories", &Vword_combining_categories /*
4845 List of pair (cons) of categories to determine word boundary.
4847 Emacs treats a sequence of word constituent characters as a single
4848 word (i.e. finds no word boundary between them) iff they belongs to
4849 the same charset. But, exceptions are allowed in the following cases.
4851 \(1) The case that characters are in different charsets is controlled
4852 by the variable `word-combining-categories'.
4854 Emacs finds no word boundary between characters of different charsets
4855 if they have categories matching some element of this list.
4857 More precisely, if an element of this list is a cons of category CAT1
4858 and CAT2, and a multibyte character C1 which has CAT1 is followed by
4859 C2 which has CAT2, there's no word boundary between C1 and C2.
4861 For instance, to tell that ASCII characters and Latin-1 characters can
4862 form a single word, the element `(?l . ?l)' should be in this list
4863 because both characters have the category `l' (Latin characters).
4865 \(2) The case that character are in the same charset is controlled by
4866 the variable `word-separating-categories'.
4868 Emacs find a word boundary between characters of the same charset
4869 if they have categories matching some element of this list.
4871 More precisely, if an element of this list is a cons of category CAT1
4872 and CAT2, and a multibyte character C1 which has CAT1 is followed by
4873 C2 which has CAT2, there's a word boundary between C1 and C2.
4875 For instance, to tell that there's a word boundary between Japanese
4876 Hiragana and Japanese Kanji (both are in the same charset), the
4877 element `(?H . ?C) should be in this list.
4880 Vword_combining_categories = Qnil;
4882 DEFVAR_LISP ("word-separating-categories", &Vword_separating_categories /*
4883 List of pair (cons) of categories to determine word boundary.
4884 See the documentation of the variable `word-combining-categories'.
4887 Vword_separating_categories = Qnil;