1 /* Functions to handle multilingual characters.
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1999,2000 MORIOKA Tomohiko
6 This file is part of XEmacs.
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* Synched up with: FSF 20.3. Not in FSF. */
25 /* Rewritten by Ben Wing <ben@xemacs.org>. */
38 /* The various pre-defined charsets. */
40 Lisp_Object Vcharset_ascii;
41 Lisp_Object Vcharset_control_1;
42 Lisp_Object Vcharset_latin_iso8859_1;
43 Lisp_Object Vcharset_latin_iso8859_2;
44 Lisp_Object Vcharset_latin_iso8859_3;
45 Lisp_Object Vcharset_latin_iso8859_4;
46 Lisp_Object Vcharset_thai_tis620;
47 Lisp_Object Vcharset_greek_iso8859_7;
48 Lisp_Object Vcharset_arabic_iso8859_6;
49 Lisp_Object Vcharset_hebrew_iso8859_8;
50 Lisp_Object Vcharset_katakana_jisx0201;
51 Lisp_Object Vcharset_latin_jisx0201;
52 Lisp_Object Vcharset_cyrillic_iso8859_5;
53 Lisp_Object Vcharset_latin_iso8859_9;
54 Lisp_Object Vcharset_japanese_jisx0208_1978;
55 Lisp_Object Vcharset_chinese_gb2312;
56 Lisp_Object Vcharset_japanese_jisx0208;
57 Lisp_Object Vcharset_japanese_jisx0208_1990;
58 Lisp_Object Vcharset_korean_ksc5601;
59 Lisp_Object Vcharset_japanese_jisx0212;
60 Lisp_Object Vcharset_chinese_cns11643_1;
61 Lisp_Object Vcharset_chinese_cns11643_2;
63 Lisp_Object Vcharset_ucs;
64 Lisp_Object Vcharset_ucs_bmp;
65 Lisp_Object Vcharset_latin_viscii;
66 Lisp_Object Vcharset_latin_tcvn5712;
67 Lisp_Object Vcharset_latin_viscii_lower;
68 Lisp_Object Vcharset_latin_viscii_upper;
69 Lisp_Object Vcharset_ideograph_daikanwa;
70 Lisp_Object Vcharset_mojikyo;
71 Lisp_Object Vcharset_mojikyo_pj_1;
72 Lisp_Object Vcharset_mojikyo_pj_2;
73 Lisp_Object Vcharset_mojikyo_pj_3;
74 Lisp_Object Vcharset_mojikyo_pj_4;
75 Lisp_Object Vcharset_mojikyo_pj_5;
76 Lisp_Object Vcharset_mojikyo_pj_6;
77 Lisp_Object Vcharset_mojikyo_pj_7;
78 Lisp_Object Vcharset_mojikyo_pj_8;
79 Lisp_Object Vcharset_mojikyo_pj_9;
80 Lisp_Object Vcharset_mojikyo_pj_10;
81 Lisp_Object Vcharset_mojikyo_pj_11;
82 Lisp_Object Vcharset_mojikyo_pj_12;
83 Lisp_Object Vcharset_mojikyo_pj_13;
84 Lisp_Object Vcharset_mojikyo_pj_14;
85 Lisp_Object Vcharset_mojikyo_pj_15;
86 Lisp_Object Vcharset_mojikyo_pj_16;
87 Lisp_Object Vcharset_mojikyo_pj_17;
88 Lisp_Object Vcharset_mojikyo_pj_18;
89 Lisp_Object Vcharset_mojikyo_pj_19;
90 Lisp_Object Vcharset_mojikyo_pj_20;
91 Lisp_Object Vcharset_mojikyo_pj_21;
92 Lisp_Object Vcharset_ethiopic_ucs;
94 Lisp_Object Vcharset_chinese_big5_1;
95 Lisp_Object Vcharset_chinese_big5_2;
97 #ifdef ENABLE_COMPOSITE_CHARS
98 Lisp_Object Vcharset_composite;
100 /* Hash tables for composite chars. One maps string representing
101 composed chars to their equivalent chars; one goes the
103 Lisp_Object Vcomposite_char_char2string_hash_table;
104 Lisp_Object Vcomposite_char_string2char_hash_table;
106 static int composite_char_row_next;
107 static int composite_char_col_next;
109 #endif /* ENABLE_COMPOSITE_CHARS */
111 struct charset_lookup *chlook;
113 static const struct lrecord_description charset_lookup_description_1[] = {
114 { XD_LISP_OBJECT_ARRAY, offsetof (struct charset_lookup, charset_by_leading_byte),
123 static const struct struct_description charset_lookup_description = {
124 sizeof (struct charset_lookup),
125 charset_lookup_description_1
129 /* Table of number of bytes in the string representation of a character
130 indexed by the first byte of that representation.
132 rep_bytes_by_first_byte(c) is more efficient than the equivalent
133 canonical computation:
135 XCHARSET_REP_BYTES (CHARSET_BY_LEADING_BYTE (c)) */
137 const Bytecount rep_bytes_by_first_byte[0xA0] =
138 { /* 0x00 - 0x7f are for straight ASCII */
139 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
141 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
142 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
143 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
144 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
145 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
146 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
147 /* 0x80 - 0x8f are for Dimension-1 official charsets */
149 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
151 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
153 /* 0x90 - 0x9d are for Dimension-2 official charsets */
154 /* 0x9e is for Dimension-1 private charsets */
155 /* 0x9f is for Dimension-2 private charsets */
156 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
163 mark_byte_table (Lisp_Object obj)
165 Lisp_Byte_Table *cte = XBYTE_TABLE (obj);
168 for (i = 0; i < 256; i++)
170 mark_object (cte->property[i]);
176 byte_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
178 Lisp_Byte_Table *cte1 = XBYTE_TABLE (obj1);
179 Lisp_Byte_Table *cte2 = XBYTE_TABLE (obj2);
182 for (i = 0; i < 256; i++)
183 if (BYTE_TABLE_P (cte1->property[i]))
185 if (BYTE_TABLE_P (cte2->property[i]))
187 if (!byte_table_equal (cte1->property[i],
188 cte2->property[i], depth + 1))
195 if (!internal_equal (cte1->property[i], cte2->property[i], depth + 1))
201 byte_table_hash (Lisp_Object obj, int depth)
203 Lisp_Byte_Table *cte = XBYTE_TABLE (obj);
205 return internal_array_hash (cte->property, 256, depth);
208 static const struct lrecord_description byte_table_description[] = {
209 { XD_LISP_OBJECT_ARRAY, offsetof(Lisp_Byte_Table, property), 256 },
213 DEFINE_LRECORD_IMPLEMENTATION ("byte-table", byte_table,
215 internal_object_printer,
218 byte_table_description,
222 make_byte_table (Lisp_Object initval, int older)
226 Lisp_Byte_Table *cte;
229 cte = alloc_older_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
231 cte = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
233 for (i = 0; i < 256; i++)
234 cte->property[i] = initval;
236 XSETBYTE_TABLE (obj, cte);
241 copy_byte_table (Lisp_Object entry)
243 Lisp_Byte_Table *cte = XBYTE_TABLE (entry);
246 Lisp_Byte_Table *ctenew
247 = alloc_lcrecord_type (Lisp_Byte_Table, &lrecord_byte_table);
249 for (i = 0; i < 256; i++)
251 Lisp_Object new = cte->property[i];
252 if (BYTE_TABLE_P (new))
253 ctenew->property[i] = copy_byte_table (new);
255 ctenew->property[i] = new;
258 XSETBYTE_TABLE (obj, ctenew);
264 mark_char_id_table (Lisp_Object obj)
266 Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
272 char_id_table_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
274 Lisp_Char_ID_Table *cte1 = XCHAR_ID_TABLE (obj1);
275 Lisp_Char_ID_Table *cte2 = XCHAR_ID_TABLE (obj2);
277 return byte_table_equal (cte1->table, cte2->table, depth + 1);
281 char_id_table_hash (Lisp_Object obj, int depth)
283 Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (obj);
285 return char_id_table_hash (cte->table, depth + 1);
288 static const struct lrecord_description char_id_table_description[] = {
289 { XD_LISP_OBJECT, offsetof(Lisp_Char_ID_Table, table) },
293 DEFINE_LRECORD_IMPLEMENTATION ("char-id-table", char_id_table,
295 internal_object_printer,
296 0, char_id_table_equal,
298 char_id_table_description,
302 make_char_id_table (Lisp_Object initval, int older)
305 Lisp_Char_ID_Table *cte;
308 cte = alloc_older_lcrecord_type (Lisp_Char_ID_Table,
309 &lrecord_char_id_table);
311 cte = alloc_lcrecord_type (Lisp_Char_ID_Table, &lrecord_char_id_table);
313 cte->table = make_byte_table (initval, older);
315 XSETCHAR_ID_TABLE (obj, cte);
322 copy_char_id_table (Lisp_Object entry)
324 Lisp_Char_ID_Table *cte = XCHAR_ID_TABLE (entry);
326 Lisp_Char_ID_Table *ctenew
327 = alloc_lcrecord_type (Lisp_Char_ID_Table, &lrecord_char_id_table);
329 ctenew->table = copy_byte_table (cte->table);
330 XSETCHAR_ID_TABLE (obj, ctenew);
337 get_char_id_table (Emchar ch, Lisp_Object table)
339 unsigned int code = ch;
341 = XBYTE_TABLE (XCHAR_ID_TABLE (table)->table);
342 Lisp_Object ret = cpt->property [(unsigned char)(code >> 24)];
344 if (BYTE_TABLE_P (ret))
345 cpt = XBYTE_TABLE (ret);
349 ret = cpt->property [(unsigned char) (code >> 16)];
350 if (BYTE_TABLE_P (ret))
351 cpt = XBYTE_TABLE (ret);
355 ret = cpt->property [(unsigned char) (code >> 8)];
356 if (BYTE_TABLE_P (ret))
357 cpt = XBYTE_TABLE (ret);
361 return cpt->property [(unsigned char) code];
364 void put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table);
366 put_char_id_table (Emchar ch, Lisp_Object value, Lisp_Object table)
368 unsigned int code = ch;
369 Lisp_Byte_Table* cpt1 = XBYTE_TABLE (XCHAR_ID_TABLE (table)->table);
370 Lisp_Object ret = cpt1->property[(unsigned char)(code >> 24)];
372 if (BYTE_TABLE_P (ret))
374 Lisp_Byte_Table* cpt2 = XBYTE_TABLE (ret);
376 ret = cpt2->property[(unsigned char)(code >> 16)];
377 if (BYTE_TABLE_P (ret))
379 Lisp_Byte_Table* cpt3 = XBYTE_TABLE (ret);
381 ret = cpt3->property[(unsigned char)(code >> 8)];
382 if (BYTE_TABLE_P (ret))
384 Lisp_Byte_Table* cpt4 = XBYTE_TABLE (ret);
386 cpt4->property[(unsigned char)code] = value;
388 else if (!EQ (ret, value))
391 = make_byte_table (ret, OLDER_RECORD_P (table));
393 XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
394 cpt3->property[(unsigned char)(code >> 8)] = cpt4;
397 else if (!EQ (ret, value))
399 int older = OLDER_RECORD_P (table);
400 Lisp_Object cpt3 = make_byte_table (ret, older);
401 Lisp_Object cpt4 = make_byte_table (ret, older);
403 XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
404 XBYTE_TABLE(cpt3)->property[(unsigned char)(code >> 8)]
406 cpt2->property[(unsigned char)(code >> 16)] = cpt3;
409 else if (!EQ (ret, value))
411 int older = OLDER_RECORD_P (table);
412 Lisp_Object cpt2 = make_byte_table (ret, older);
413 Lisp_Object cpt3 = make_byte_table (ret, older);
414 Lisp_Object cpt4 = make_byte_table (ret, older);
416 XBYTE_TABLE(cpt4)->property[(unsigned char)code] = value;
417 XBYTE_TABLE(cpt3)->property[(unsigned char)(code >> 8)] = cpt4;
418 XBYTE_TABLE(cpt2)->property[(unsigned char)(code >> 16)] = cpt3;
419 cpt1->property[(unsigned char)(code >> 24)] = cpt2;
424 Lisp_Object Vcharacter_attribute_table;
425 Lisp_Object Vcharacter_composition_table;
426 Lisp_Object Vcharacter_variant_table;
428 Lisp_Object Q_decomposition;
431 Lisp_Object Qisolated;
432 Lisp_Object Qinitial;
435 Lisp_Object Qvertical;
436 Lisp_Object QnoBreak;
437 Lisp_Object Qfraction;
447 Emchar to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg);
449 to_char_id (Lisp_Object v, char* err_msg, Lisp_Object err_arg)
455 else if (EQ (v, Qcompat))
457 else if (EQ (v, Qisolated))
459 else if (EQ (v, Qinitial))
461 else if (EQ (v, Qmedial))
463 else if (EQ (v, Qfinal))
465 else if (EQ (v, Qvertical))
467 else if (EQ (v, QnoBreak))
469 else if (EQ (v, Qfraction))
471 else if (EQ (v, Qsuper))
473 else if (EQ (v, Qsub))
475 else if (EQ (v, Qcircle))
477 else if (EQ (v, Qsquare))
479 else if (EQ (v, Qwide))
481 else if (EQ (v, Qnarrow))
483 else if (EQ (v, Qsmall))
485 else if (EQ (v, Qfont))
488 signal_simple_error (err_msg, err_arg);
491 DEFUN ("get-composite-char", Fget_composite_char, 1, 1, 0, /*
492 Return character corresponding with list.
496 Lisp_Object table = Vcharacter_composition_table;
497 Lisp_Object rest = list;
501 Lisp_Object v = Fcar (rest);
503 Emchar c = to_char_id (v, "Invalid value for composition", list);
505 ret = get_char_id_table (c, table);
510 if (!CHAR_ID_TABLE_P (ret))
515 else if (!CONSP (rest))
517 else if (CHAR_ID_TABLE_P (ret))
520 signal_simple_error ("Invalid table is found with", list);
522 signal_simple_error ("Invalid value for composition", list);
525 DEFUN ("char-variants", Fchar_variants, 1, 1, 0, /*
526 Return variants of CHARACTER.
530 CHECK_CHAR (character);
531 return Fcopy_list (get_char_id_table (XCHAR (character),
532 Vcharacter_variant_table));
535 DEFUN ("char-attribute-alist", Fchar_attribute_alist, 1, 1, 0, /*
536 Return the alist of attributes of CHARACTER.
540 CHECK_CHAR (character);
541 return Fcopy_alist (get_char_id_table (XCHAR (character),
542 Vcharacter_attribute_table));
545 DEFUN ("get-char-attribute", Fget_char_attribute, 2, 2, 0, /*
546 Return the value of CHARACTER's ATTRIBUTE.
548 (character, attribute))
552 CHECK_CHAR (character);
553 if (!NILP (ccs = Ffind_charset (attribute)))
555 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
557 if (CHAR_ID_TABLE_P (encoding_table))
558 return get_char_id_table (XCHAR (character), encoding_table);
565 = get_char_id_table (XCHAR (character), Vcharacter_attribute_table);
570 return Fcdr (Fassq (attribute, ret));
574 Lisp_Object put_char_attribute (Lisp_Object character,
575 Lisp_Object attribute, Lisp_Object value);
577 put_char_attribute (Lisp_Object character, Lisp_Object attribute,
580 Emchar char_id = XCHAR (character);
581 Lisp_Object ret = get_char_id_table (char_id, Vcharacter_attribute_table);
584 cell = Fassq (attribute, ret);
588 ret = Fcons (Fcons (attribute, value), ret);
590 else if (!EQ (Fcdr (cell), value))
592 Fsetcdr (cell, value);
594 put_char_id_table (char_id, ret, Vcharacter_attribute_table);
598 Lisp_Object remove_char_attribute (Lisp_Object character,
599 Lisp_Object attribute);
601 remove_char_attribute (Lisp_Object character, Lisp_Object attribute)
603 Emchar char_id = XCHAR (character);
604 Lisp_Object alist = get_char_id_table (char_id, Vcharacter_attribute_table);
606 if (EQ (attribute, Fcar (Fcar (alist))))
608 alist = Fcdr (alist);
612 Lisp_Object pr = alist;
613 Lisp_Object r = Fcdr (alist);
617 if (EQ (attribute, Fcar (Fcar (r))))
619 XCDR (pr) = Fcdr (r);
626 put_char_id_table (char_id, alist, Vcharacter_attribute_table);
632 DEFUN ("put-char-attribute", Fput_char_attribute, 3, 3, 0, /*
633 Store CHARACTER's ATTRIBUTE with VALUE.
635 (character, attribute, value))
639 CHECK_CHAR (character);
640 ccs = Ffind_charset (attribute);
643 Lisp_Object encoding_table;
645 if (!EQ (XCHARSET_NAME (ccs), Qucs)
646 || (XCHAR (character) != XINT (value)))
648 Lisp_Object cpos, rest;
649 Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
656 /* ad-hoc method for `ascii' */
657 if ((XCHARSET_CHARS (ccs) == 94) &&
658 (XCHARSET_BYTE_OFFSET (ccs) != 33))
659 ccs_len = 128 - XCHARSET_BYTE_OFFSET (ccs);
661 ccs_len = XCHARSET_CHARS (ccs);
665 Lisp_Object ret = Fcar (value);
668 signal_simple_error ("Invalid value for coded-charset", value);
669 code_point = XINT (ret);
670 if (XCHARSET_GRAPHIC (ccs) == 1)
678 signal_simple_error ("Invalid value for coded-charset",
682 signal_simple_error ("Invalid value for coded-charset",
685 if (XCHARSET_GRAPHIC (ccs) == 1)
687 code_point = (code_point << 8) | j;
690 value = make_int (code_point);
692 else if (INTP (value))
694 if (XCHARSET_GRAPHIC (ccs) == 1)
695 value = make_int (XINT (value) & 0x7F7F7F7F);
698 signal_simple_error ("Invalid value for coded-charset", value);
701 cpos = Fget_char_attribute (character, attribute);
706 dim = XCHARSET_DIMENSION (ccs);
707 code_point = XINT (cpos);
711 i = ((code_point >> (8 * dim)) & 255)
712 - XCHARSET_BYTE_OFFSET (ccs);
713 nv = XVECTOR_DATA(v)[i];
719 XVECTOR_DATA(v)[i] = Qnil;
720 v = XCHARSET_DECODING_TABLE (ccs);
725 XCHARSET_DECODING_TABLE (ccs) = v
726 = make_older_vector (ccs_len, Qnil);
729 dim = XCHARSET_DIMENSION (ccs);
730 code_point = XINT (value);
735 i = ((code_point >> (8 * dim)) & 255)
736 - XCHARSET_BYTE_OFFSET (ccs);
737 nv = XVECTOR_DATA(v)[i];
741 nv = (XVECTOR_DATA(v)[i]
742 = make_older_vector (ccs_len, Qnil));
748 XVECTOR_DATA(v)[i] = character;
752 if (NILP (encoding_table = XCHARSET_ENCODING_TABLE (ccs)))
754 XCHARSET_ENCODING_TABLE (ccs) = encoding_table
755 = make_char_id_table (Qnil, -1);
757 put_char_id_table (XCHAR (character), value, encoding_table);
760 else if (EQ (attribute, Q_decomposition))
763 signal_simple_error ("Invalid value for ->decomposition",
766 if (CONSP (Fcdr (value)))
768 Lisp_Object rest = value;
769 Lisp_Object table = Vcharacter_composition_table;
773 Lisp_Object v = Fcar (rest);
776 = to_char_id (v, "Invalid value for ->decomposition", value);
781 put_char_id_table (c, character, table);
786 ntable = get_char_id_table (c, table);
787 if (!CHAR_ID_TABLE_P (ntable))
790 = make_char_id_table (Qnil, OLDER_RECORD_P (table));
791 put_char_id_table (c, ntable, table);
799 Lisp_Object v = Fcar (value);
805 = get_char_id_table (c, Vcharacter_variant_table);
807 if (NILP (Fmemq (v, ret)))
809 put_char_id_table (c, Fcons (character, ret),
810 Vcharacter_variant_table);
815 else if (EQ (attribute, Q_ucs))
821 signal_simple_error ("Invalid value for ->ucs", value);
825 ret = get_char_id_table (c, Vcharacter_variant_table);
826 if (NILP (Fmemq (character, ret)))
828 put_char_id_table (c, Fcons (character, ret),
829 Vcharacter_variant_table);
832 return put_char_attribute (character, attribute, value);
835 DEFUN ("remove-char-attribute", Fremove_char_attribute, 2, 2, 0, /*
836 Remove CHARACTER's ATTRIBUTE.
838 (character, attribute))
842 CHECK_CHAR (character);
843 ccs = Ffind_charset (attribute);
847 Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
853 Lisp_Object encoding_table;
855 /* ad-hoc method for `ascii' */
856 if ((XCHARSET_CHARS (ccs) == 94) &&
857 (XCHARSET_BYTE_OFFSET (ccs) != 33))
858 ccs_len = 128 - XCHARSET_BYTE_OFFSET (ccs);
860 ccs_len = XCHARSET_CHARS (ccs);
863 cpos = Fget_char_attribute (character, attribute);
868 dim = XCHARSET_DIMENSION (ccs);
869 code_point = XINT (cpos);
873 i = ((code_point >> (8 * dim)) & 255)
874 - XCHARSET_BYTE_OFFSET (ccs);
875 nv = XVECTOR_DATA(v)[i];
881 XVECTOR_DATA(v)[i] = Qnil;
882 v = XCHARSET_DECODING_TABLE (ccs);
885 if (!NILP (encoding_table = XCHARSET_ENCODING_TABLE (ccs)))
887 put_char_id_table (XCHAR (character), Qnil, encoding_table);
891 return remove_char_attribute (character, attribute);
894 EXFUN (Fmake_char, 3);
895 EXFUN (Fdecode_char, 2);
897 DEFUN ("define-char", Fdefine_char, 1, 1, 0, /*
898 Store character's ATTRIBUTES.
902 Lisp_Object rest = attributes;
903 Lisp_Object code = Fcdr (Fassq (Qucs, attributes));
904 Lisp_Object character;
910 Lisp_Object cell = Fcar (rest);
914 signal_simple_error ("Invalid argument", attributes);
915 if (!NILP (ccs = Ffind_charset (Fcar (cell)))
916 && ((XCHARSET_FINAL (ccs) != 0) ||
917 (XCHARSET_UCS_MAX (ccs) > 0)) )
921 character = Fmake_char (ccs, Fcar (cell), Fcar (Fcdr (cell)));
923 character = Fdecode_char (ccs, cell);
924 goto setup_attributes;
928 if (!NILP (code = Fcdr (Fassq (Q_ucs, attributes))))
931 signal_simple_error ("Invalid argument", attributes);
933 character = make_char (XINT (code) + 0x100000);
934 goto setup_attributes;
938 else if (!INTP (code))
939 signal_simple_error ("Invalid argument", attributes);
941 character = make_char (XINT (code));
947 Lisp_Object cell = Fcar (rest);
950 signal_simple_error ("Invalid argument", attributes);
951 Fput_char_attribute (character, Fcar (cell), Fcdr (cell));
955 get_char_id_table (XCHAR (character), Vcharacter_attribute_table);
958 Lisp_Object Vutf_2000_version;
962 int leading_code_private_11;
965 Lisp_Object Qcharsetp;
967 /* Qdoc_string, Qdimension, Qchars defined in general.c */
968 Lisp_Object Qregistry, Qfinal, Qgraphic;
969 Lisp_Object Qdirection;
970 Lisp_Object Qreverse_direction_charset;
971 Lisp_Object Qleading_byte;
972 Lisp_Object Qshort_name, Qlong_name;
988 Qjapanese_jisx0208_1978,
991 Qjapanese_jisx0208_1990,
1000 Qlatin_viscii_lower,
1001 Qlatin_viscii_upper,
1002 Qvietnamese_viscii_lower,
1003 Qvietnamese_viscii_upper,
1004 Qideograph_daikanwa,
1033 Lisp_Object Ql2r, Qr2l;
1035 Lisp_Object Vcharset_hash_table;
1037 /* Composite characters are characters constructed by overstriking two
1038 or more regular characters.
1040 1) The old Mule implementation involves storing composite characters
1041 in a buffer as a tag followed by all of the actual characters
1042 used to make up the composite character. I think this is a bad
1043 idea; it greatly complicates code that wants to handle strings
1044 one character at a time because it has to deal with the possibility
1045 of great big ungainly characters. It's much more reasonable to
1046 simply store an index into a table of composite characters.
1048 2) The current implementation only allows for 16,384 separate
1049 composite characters over the lifetime of the XEmacs process.
1050 This could become a potential problem if the user
1051 edited lots of different files that use composite characters.
1052 Due to FSF bogosity, increasing the number of allowable
1053 composite characters under Mule would decrease the number
1054 of possible faces that can exist. Mule already has shrunk
1055 this to 2048, and further shrinkage would become uncomfortable.
1056 No such problems exist in XEmacs.
1058 Composite characters could be represented as 0x80 C1 C2 C3,
1059 where each C[1-3] is in the range 0xA0 - 0xFF. This allows
1060 for slightly under 2^20 (one million) composite characters
1061 over the XEmacs process lifetime, and you only need to
1062 increase the size of a Mule character from 19 to 21 bits.
1063 Or you could use 0x80 C1 C2 C3 C4, allowing for about
1064 85 million (slightly over 2^26) composite characters. */
1067 /************************************************************************/
1068 /* Basic Emchar functions */
1069 /************************************************************************/
1071 /* Convert a non-ASCII Mule character C into a one-character Mule-encoded
1072 string in STR. Returns the number of bytes stored.
1073 Do not call this directly. Use the macro set_charptr_emchar() instead.
1077 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
1083 Lisp_Object charset;
1092 else if ( c <= 0x7ff )
1094 *p++ = (c >> 6) | 0xc0;
1095 *p++ = (c & 0x3f) | 0x80;
1097 else if ( c <= 0xffff )
1099 *p++ = (c >> 12) | 0xe0;
1100 *p++ = ((c >> 6) & 0x3f) | 0x80;
1101 *p++ = (c & 0x3f) | 0x80;
1103 else if ( c <= 0x1fffff )
1105 *p++ = (c >> 18) | 0xf0;
1106 *p++ = ((c >> 12) & 0x3f) | 0x80;
1107 *p++ = ((c >> 6) & 0x3f) | 0x80;
1108 *p++ = (c & 0x3f) | 0x80;
1110 else if ( c <= 0x3ffffff )
1112 *p++ = (c >> 24) | 0xf8;
1113 *p++ = ((c >> 18) & 0x3f) | 0x80;
1114 *p++ = ((c >> 12) & 0x3f) | 0x80;
1115 *p++ = ((c >> 6) & 0x3f) | 0x80;
1116 *p++ = (c & 0x3f) | 0x80;
1120 *p++ = (c >> 30) | 0xfc;
1121 *p++ = ((c >> 24) & 0x3f) | 0x80;
1122 *p++ = ((c >> 18) & 0x3f) | 0x80;
1123 *p++ = ((c >> 12) & 0x3f) | 0x80;
1124 *p++ = ((c >> 6) & 0x3f) | 0x80;
1125 *p++ = (c & 0x3f) | 0x80;
1128 BREAKUP_CHAR (c, charset, c1, c2);
1129 lb = CHAR_LEADING_BYTE (c);
1130 if (LEADING_BYTE_PRIVATE_P (lb))
1131 *p++ = PRIVATE_LEADING_BYTE_PREFIX (lb);
1133 if (EQ (charset, Vcharset_control_1))
1142 /* Return the first character from a Mule-encoded string in STR,
1143 assuming it's non-ASCII. Do not call this directly.
1144 Use the macro charptr_emchar() instead. */
1147 non_ascii_charptr_emchar (const Bufbyte *str)
1160 else if ( b >= 0xf8 )
1165 else if ( b >= 0xf0 )
1170 else if ( b >= 0xe0 )
1175 else if ( b >= 0xc0 )
1185 for( ; len > 0; len-- )
1188 ch = ( ch << 6 ) | ( b & 0x3f );
1192 Bufbyte i0 = *str, i1, i2 = 0;
1193 Lisp_Object charset;
1195 if (i0 == LEADING_BYTE_CONTROL_1)
1196 return (Emchar) (*++str - 0x20);
1198 if (LEADING_BYTE_PREFIX_P (i0))
1203 charset = CHARSET_BY_LEADING_BYTE (i0);
1204 if (XCHARSET_DIMENSION (charset) == 2)
1207 return MAKE_CHAR (charset, i1, i2);
1211 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
1212 Do not call this directly. Use the macro valid_char_p() instead. */
1216 non_ascii_valid_char_p (Emchar ch)
1220 /* Must have only lowest 19 bits set */
1224 f1 = CHAR_FIELD1 (ch);
1225 f2 = CHAR_FIELD2 (ch);
1226 f3 = CHAR_FIELD3 (ch);
1230 Lisp_Object charset;
1232 if (f2 < MIN_CHAR_FIELD2_OFFICIAL ||
1233 (f2 > MAX_CHAR_FIELD2_OFFICIAL && f2 < MIN_CHAR_FIELD2_PRIVATE) ||
1234 f2 > MAX_CHAR_FIELD2_PRIVATE)
1239 if (f3 != 0x20 && f3 != 0x7F && !(f2 >= MIN_CHAR_FIELD2_PRIVATE &&
1240 f2 <= MAX_CHAR_FIELD2_PRIVATE))
1244 NOTE: This takes advantage of the fact that
1245 FIELD2_TO_OFFICIAL_LEADING_BYTE and
1246 FIELD2_TO_PRIVATE_LEADING_BYTE are the same.
1248 charset = CHARSET_BY_LEADING_BYTE (f2 + FIELD2_TO_OFFICIAL_LEADING_BYTE);
1249 if (EQ (charset, Qnil))
1251 return (XCHARSET_CHARS (charset) == 96);
1255 Lisp_Object charset;
1257 if (f1 < MIN_CHAR_FIELD1_OFFICIAL ||
1258 (f1 > MAX_CHAR_FIELD1_OFFICIAL && f1 < MIN_CHAR_FIELD1_PRIVATE) ||
1259 f1 > MAX_CHAR_FIELD1_PRIVATE)
1261 if (f2 < 0x20 || f3 < 0x20)
1264 #ifdef ENABLE_COMPOSITE_CHARS
1265 if (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE == LEADING_BYTE_COMPOSITE)
1267 if (UNBOUNDP (Fgethash (make_int (ch),
1268 Vcomposite_char_char2string_hash_table,
1273 #endif /* ENABLE_COMPOSITE_CHARS */
1275 if (f2 != 0x20 && f2 != 0x7F && f3 != 0x20 && f3 != 0x7F
1276 && !(f1 >= MIN_CHAR_FIELD1_PRIVATE && f1 <= MAX_CHAR_FIELD1_PRIVATE))
1279 if (f1 <= MAX_CHAR_FIELD1_OFFICIAL)
1281 CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE);
1284 CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_PRIVATE_LEADING_BYTE);
1286 if (EQ (charset, Qnil))
1288 return (XCHARSET_CHARS (charset) == 96);
1294 /************************************************************************/
1295 /* Basic string functions */
1296 /************************************************************************/
1298 /* Copy the character pointed to by PTR into STR, assuming it's
1299 non-ASCII. Do not call this directly. Use the macro
1300 charptr_copy_char() instead. */
1303 non_ascii_charptr_copy_char (const Bufbyte *ptr, Bufbyte *str)
1305 Bufbyte *strptr = str;
1307 switch (REP_BYTES_BY_FIRST_BYTE (*strptr))
1309 /* Notice fallthrough. */
1311 case 6: *++strptr = *ptr++;
1312 case 5: *++strptr = *ptr++;
1314 case 4: *++strptr = *ptr++;
1315 case 3: *++strptr = *ptr++;
1316 case 2: *++strptr = *ptr;
1321 return strptr + 1 - str;
1325 /************************************************************************/
1326 /* streams of Emchars */
1327 /************************************************************************/
1329 /* Treat a stream as a stream of Emchar's rather than a stream of bytes.
1330 The functions below are not meant to be called directly; use
1331 the macros in insdel.h. */
1334 Lstream_get_emchar_1 (Lstream *stream, int ch)
1336 Bufbyte str[MAX_EMCHAR_LEN];
1337 Bufbyte *strptr = str;
1339 str[0] = (Bufbyte) ch;
1340 switch (REP_BYTES_BY_FIRST_BYTE (ch))
1342 /* Notice fallthrough. */
1345 ch = Lstream_getc (stream);
1347 *++strptr = (Bufbyte) ch;
1349 ch = Lstream_getc (stream);
1351 *++strptr = (Bufbyte) ch;
1354 ch = Lstream_getc (stream);
1356 *++strptr = (Bufbyte) ch;
1358 ch = Lstream_getc (stream);
1360 *++strptr = (Bufbyte) ch;
1362 ch = Lstream_getc (stream);
1364 *++strptr = (Bufbyte) ch;
1369 return charptr_emchar (str);
1373 Lstream_fput_emchar (Lstream *stream, Emchar ch)
1375 Bufbyte str[MAX_EMCHAR_LEN];
1376 Bytecount len = set_charptr_emchar (str, ch);
1377 return Lstream_write (stream, str, len);
1381 Lstream_funget_emchar (Lstream *stream, Emchar ch)
1383 Bufbyte str[MAX_EMCHAR_LEN];
1384 Bytecount len = set_charptr_emchar (str, ch);
1385 Lstream_unread (stream, str, len);
1389 /************************************************************************/
1390 /* charset object */
1391 /************************************************************************/
1394 mark_charset (Lisp_Object obj)
1396 Lisp_Charset *cs = XCHARSET (obj);
1398 mark_object (cs->short_name);
1399 mark_object (cs->long_name);
1400 mark_object (cs->doc_string);
1401 mark_object (cs->registry);
1402 mark_object (cs->ccl_program);
1404 /* mark_object (cs->encoding_table); */
1405 /* mark_object (cs->decoding_table); */
1411 print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1413 Lisp_Charset *cs = XCHARSET (obj);
1417 error ("printing unreadable object #<charset %s 0x%x>",
1418 string_data (XSYMBOL (CHARSET_NAME (cs))->name),
1421 write_c_string ("#<charset ", printcharfun);
1422 print_internal (CHARSET_NAME (cs), printcharfun, 0);
1423 write_c_string (" ", printcharfun);
1424 print_internal (CHARSET_SHORT_NAME (cs), printcharfun, 1);
1425 write_c_string (" ", printcharfun);
1426 print_internal (CHARSET_LONG_NAME (cs), printcharfun, 1);
1427 write_c_string (" ", printcharfun);
1428 print_internal (CHARSET_DOC_STRING (cs), printcharfun, 1);
1429 sprintf (buf, " %d^%d %s cols=%d g%d final='%c' reg=",
1431 CHARSET_DIMENSION (cs),
1432 CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? "l2r" : "r2l",
1433 CHARSET_COLUMNS (cs),
1434 CHARSET_GRAPHIC (cs),
1435 CHARSET_FINAL (cs));
1436 write_c_string (buf, printcharfun);
1437 print_internal (CHARSET_REGISTRY (cs), printcharfun, 0);
1438 sprintf (buf, " 0x%x>", cs->header.uid);
1439 write_c_string (buf, printcharfun);
1442 static const struct lrecord_description charset_description[] = {
1443 { XD_LISP_OBJECT, offsetof (Lisp_Charset, name) },
1444 { XD_LISP_OBJECT, offsetof (Lisp_Charset, doc_string) },
1445 { XD_LISP_OBJECT, offsetof (Lisp_Charset, registry) },
1446 { XD_LISP_OBJECT, offsetof (Lisp_Charset, short_name) },
1447 { XD_LISP_OBJECT, offsetof (Lisp_Charset, long_name) },
1448 { XD_LISP_OBJECT, offsetof (Lisp_Charset, reverse_direction_charset) },
1449 { XD_LISP_OBJECT, offsetof (Lisp_Charset, ccl_program) },
1451 { XD_LISP_OBJECT, offsetof (Lisp_Charset, decoding_table) },
1452 { XD_LISP_OBJECT, offsetof (Lisp_Charset, encoding_table) },
1457 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
1458 mark_charset, print_charset, 0, 0, 0,
1459 charset_description,
1461 /* Make a new charset. */
1464 make_charset (Charset_ID id, Lisp_Object name,
1465 unsigned short chars, unsigned char dimension,
1466 unsigned char columns, unsigned char graphic,
1467 Bufbyte final, unsigned char direction, Lisp_Object short_name,
1468 Lisp_Object long_name, Lisp_Object doc,
1470 Lisp_Object decoding_table,
1471 Emchar ucs_min, Emchar ucs_max,
1472 Emchar code_offset, unsigned char byte_offset)
1474 unsigned char type = 0;
1476 Lisp_Charset *cs = alloc_lcrecord_type (Lisp_Charset, &lrecord_charset);
1480 XSETCHARSET (obj, cs);
1482 CHARSET_ID (cs) = id;
1483 CHARSET_NAME (cs) = name;
1484 CHARSET_SHORT_NAME (cs) = short_name;
1485 CHARSET_LONG_NAME (cs) = long_name;
1486 CHARSET_CHARS (cs) = chars;
1487 CHARSET_DIMENSION (cs) = dimension;
1488 CHARSET_DIRECTION (cs) = direction;
1489 CHARSET_COLUMNS (cs) = columns;
1490 CHARSET_GRAPHIC (cs) = graphic;
1491 CHARSET_FINAL (cs) = final;
1492 CHARSET_DOC_STRING (cs) = doc;
1493 CHARSET_REGISTRY (cs) = reg;
1494 CHARSET_CCL_PROGRAM (cs) = Qnil;
1495 CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
1497 CHARSET_DECODING_TABLE(cs) = Qnil;
1498 CHARSET_ENCODING_TABLE(cs) = Qnil;
1499 CHARSET_UCS_MIN(cs) = ucs_min;
1500 CHARSET_UCS_MAX(cs) = ucs_max;
1501 CHARSET_CODE_OFFSET(cs) = code_offset;
1502 CHARSET_BYTE_OFFSET(cs) = byte_offset;
1505 switch (CHARSET_CHARS (cs))
1508 switch (CHARSET_DIMENSION (cs))
1511 type = CHARSET_TYPE_94;
1514 type = CHARSET_TYPE_94X94;
1519 switch (CHARSET_DIMENSION (cs))
1522 type = CHARSET_TYPE_96;
1525 type = CHARSET_TYPE_96X96;
1531 switch (CHARSET_DIMENSION (cs))
1534 type = CHARSET_TYPE_128;
1537 type = CHARSET_TYPE_128X128;
1542 switch (CHARSET_DIMENSION (cs))
1545 type = CHARSET_TYPE_256;
1548 type = CHARSET_TYPE_256X256;
1555 CHARSET_TYPE (cs) = type;
1559 if (id == LEADING_BYTE_ASCII)
1560 CHARSET_REP_BYTES (cs) = 1;
1562 CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
1564 CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
1569 /* some charsets do not have final characters. This includes
1570 ASCII, Control-1, Composite, and the two faux private
1573 if (code_offset == 0)
1575 assert (NILP (chlook->charset_by_attributes[type][final]));
1576 chlook->charset_by_attributes[type][final] = obj;
1579 assert (NILP (chlook->charset_by_attributes[type][final][direction]));
1580 chlook->charset_by_attributes[type][final][direction] = obj;
1584 assert (NILP (chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE]));
1585 chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
1587 /* Some charsets are "faux" and don't have names or really exist at
1588 all except in the leading-byte table. */
1590 Fputhash (name, obj, Vcharset_hash_table);
1595 get_unallocated_leading_byte (int dimension)
1600 if (chlook->next_allocated_leading_byte > MAX_LEADING_BYTE_PRIVATE)
1603 lb = chlook->next_allocated_leading_byte++;
1607 if (chlook->next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
1610 lb = chlook->next_allocated_1_byte_leading_byte++;
1614 if (chlook->next_allocated_2_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_2)
1617 lb = chlook->next_allocated_2_byte_leading_byte++;
1623 ("No more character sets free for this dimension",
1624 make_int (dimension));
1631 make_builtin_char (Lisp_Object charset, int c1, int c2)
1633 if (XCHARSET_UCS_MAX (charset))
1636 = (XCHARSET_DIMENSION (charset) == 1
1638 c1 - XCHARSET_BYTE_OFFSET (charset)
1640 (c1 - XCHARSET_BYTE_OFFSET (charset)) * XCHARSET_CHARS (charset)
1641 + c2 - XCHARSET_BYTE_OFFSET (charset))
1642 - XCHARSET_CODE_OFFSET (charset) + XCHARSET_UCS_MIN (charset);
1643 if ((code < XCHARSET_UCS_MIN (charset))
1644 || (XCHARSET_UCS_MAX (charset) < code))
1645 signal_simple_error ("Arguments makes invalid character",
1649 else if (XCHARSET_DIMENSION (charset) == 1)
1651 switch (XCHARSET_CHARS (charset))
1655 + (XCHARSET_FINAL (charset) - '0') * 94 + (c1 - 33);
1658 + (XCHARSET_FINAL (charset) - '0') * 96 + (c1 - 32);
1665 switch (XCHARSET_CHARS (charset))
1668 return MIN_CHAR_94x94
1669 + (XCHARSET_FINAL (charset) - '0') * 94 * 94
1670 + (c1 - 33) * 94 + (c2 - 33);
1672 return MIN_CHAR_96x96
1673 + (XCHARSET_FINAL (charset) - '0') * 96 * 96
1674 + (c1 - 32) * 96 + (c2 - 32);
1682 range_charset_code_point (Lisp_Object charset, Emchar ch)
1686 if ((XCHARSET_UCS_MIN (charset) <= ch)
1687 && (ch <= XCHARSET_UCS_MAX (charset)))
1689 d = ch - XCHARSET_UCS_MIN (charset) + XCHARSET_CODE_OFFSET (charset);
1691 if (XCHARSET_CHARS (charset) == 256)
1693 else if (XCHARSET_DIMENSION (charset) == 1)
1694 return d + XCHARSET_BYTE_OFFSET (charset);
1695 else if (XCHARSET_DIMENSION (charset) == 2)
1697 ((d / XCHARSET_CHARS (charset)
1698 + XCHARSET_BYTE_OFFSET (charset)) << 8)
1699 | (d % XCHARSET_CHARS (charset) + XCHARSET_BYTE_OFFSET (charset));
1700 else if (XCHARSET_DIMENSION (charset) == 3)
1702 ((d / (XCHARSET_CHARS (charset) * XCHARSET_CHARS (charset))
1703 + XCHARSET_BYTE_OFFSET (charset)) << 16)
1704 | ((d / XCHARSET_CHARS (charset)
1705 % XCHARSET_CHARS (charset)
1706 + XCHARSET_BYTE_OFFSET (charset)) << 8)
1707 | (d % XCHARSET_CHARS (charset) + XCHARSET_BYTE_OFFSET (charset));
1708 else /* if (XCHARSET_DIMENSION (charset) == 4) */
1710 ((d / (XCHARSET_CHARS (charset)
1711 * XCHARSET_CHARS (charset) * XCHARSET_CHARS (charset))
1712 + XCHARSET_BYTE_OFFSET (charset)) << 24)
1713 | ((d / (XCHARSET_CHARS (charset) * XCHARSET_CHARS (charset))
1714 % XCHARSET_CHARS (charset)
1715 + XCHARSET_BYTE_OFFSET (charset)) << 16)
1716 | ((d / XCHARSET_CHARS (charset) % XCHARSET_CHARS (charset)
1717 + XCHARSET_BYTE_OFFSET (charset)) << 8)
1718 | (d % XCHARSET_CHARS (charset) + XCHARSET_BYTE_OFFSET (charset));
1720 else if (XCHARSET_CODE_OFFSET (charset) == 0)
1722 if (XCHARSET_DIMENSION (charset) == 1)
1724 if (XCHARSET_CHARS (charset) == 94)
1726 if (((d = ch - (MIN_CHAR_94
1727 + (XCHARSET_FINAL (charset) - '0') * 94)) >= 0)
1731 else if (XCHARSET_CHARS (charset) == 96)
1733 if (((d = ch - (MIN_CHAR_96
1734 + (XCHARSET_FINAL (charset) - '0') * 96)) >= 0)
1741 else if (XCHARSET_DIMENSION (charset) == 2)
1743 if (XCHARSET_CHARS (charset) == 94)
1745 if (((d = ch - (MIN_CHAR_94x94
1746 + (XCHARSET_FINAL (charset) - '0') * 94 * 94))
1749 return (((d / 94) + 33) << 8) | (d % 94 + 33);
1751 else if (XCHARSET_CHARS (charset) == 96)
1753 if (((d = ch - (MIN_CHAR_96x96
1754 + (XCHARSET_FINAL (charset) - '0') * 96 * 96))
1757 return (((d / 96) + 32) << 8) | (d % 96 + 32);
1767 encode_builtin_char_1 (Emchar c, Lisp_Object* charset)
1769 if (c <= MAX_CHAR_BASIC_LATIN)
1771 *charset = Vcharset_ascii;
1776 *charset = Vcharset_control_1;
1781 *charset = Vcharset_latin_iso8859_1;
1785 else if ((MIN_CHAR_GREEK <= c) && (c <= MAX_CHAR_GREEK))
1787 *charset = Vcharset_greek_iso8859_7;
1788 return c - MIN_CHAR_GREEK + 0x20;
1790 else if ((MIN_CHAR_CYRILLIC <= c) && (c <= MAX_CHAR_CYRILLIC))
1792 *charset = Vcharset_cyrillic_iso8859_5;
1793 return c - MIN_CHAR_CYRILLIC + 0x20;
1796 else if ((MIN_CHAR_HEBREW <= c) && (c <= MAX_CHAR_HEBREW))
1798 *charset = Vcharset_hebrew_iso8859_8;
1799 return c - MIN_CHAR_HEBREW + 0x20;
1801 else if ((MIN_CHAR_THAI <= c) && (c <= MAX_CHAR_THAI))
1803 *charset = Vcharset_thai_tis620;
1804 return c - MIN_CHAR_THAI + 0x20;
1807 else if ((MIN_CHAR_HALFWIDTH_KATAKANA <= c)
1808 && (c <= MAX_CHAR_HALFWIDTH_KATAKANA))
1810 return list2 (Vcharset_katakana_jisx0201,
1811 make_int (c - MIN_CHAR_HALFWIDTH_KATAKANA + 33));
1814 else if (c <= MAX_CHAR_BMP)
1816 *charset = Vcharset_ucs_bmp;
1819 else if (c < MIN_CHAR_DAIKANWA)
1821 *charset = Vcharset_ucs;
1825 else if (c <= MAX_CHAR_DAIKANWA)
1827 *charset = Vcharset_ideograph_daikanwa;
1828 return c - MIN_CHAR_DAIKANWA;
1831 else if (c <= MAX_CHAR_MOJIKYO)
1833 *charset = Vcharset_mojikyo;
1834 return c - MIN_CHAR_MOJIKYO;
1836 else if (c < MIN_CHAR_94)
1838 *charset = Vcharset_ucs;
1841 else if (c <= MAX_CHAR_94)
1843 *charset = CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_94,
1844 ((c - MIN_CHAR_94) / 94) + '0',
1845 CHARSET_LEFT_TO_RIGHT);
1846 if (!NILP (*charset))
1847 return ((c - MIN_CHAR_94) % 94) + 33;
1850 *charset = Vcharset_ucs;
1854 else if (c <= MAX_CHAR_96)
1856 *charset = CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_96,
1857 ((c - MIN_CHAR_96) / 96) + '0',
1858 CHARSET_LEFT_TO_RIGHT);
1859 if (!NILP (*charset))
1860 return ((c - MIN_CHAR_96) % 96) + 32;
1863 *charset = Vcharset_ucs;
1867 else if (c <= MAX_CHAR_94x94)
1870 = CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_94X94,
1871 ((c - MIN_CHAR_94x94) / (94 * 94)) + '0',
1872 CHARSET_LEFT_TO_RIGHT);
1873 if (!NILP (*charset))
1874 return (((((c - MIN_CHAR_94x94) / 94) % 94) + 33) << 8)
1875 | (((c - MIN_CHAR_94x94) % 94) + 33);
1878 *charset = Vcharset_ucs;
1882 else if (c <= MAX_CHAR_96x96)
1885 = CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_96X96,
1886 ((c - MIN_CHAR_96x96) / (96 * 96)) + '0',
1887 CHARSET_LEFT_TO_RIGHT);
1888 if (!NILP (*charset))
1889 return ((((c - MIN_CHAR_96x96) / 96) % 96) + 32) << 8
1890 | (((c - MIN_CHAR_96x96) % 96) + 32);
1893 *charset = Vcharset_ucs;
1899 *charset = Vcharset_ucs;
1904 Lisp_Object Vdefault_coded_charset_priority_list;
1908 /************************************************************************/
1909 /* Basic charset Lisp functions */
1910 /************************************************************************/
1912 DEFUN ("charsetp", Fcharsetp, 1, 1, 0, /*
1913 Return non-nil if OBJECT is a charset.
1917 return CHARSETP (object) ? Qt : Qnil;
1920 DEFUN ("find-charset", Ffind_charset, 1, 1, 0, /*
1921 Retrieve the charset of the given name.
1922 If CHARSET-OR-NAME is a charset object, it is simply returned.
1923 Otherwise, CHARSET-OR-NAME should be a symbol. If there is no such charset,
1924 nil is returned. Otherwise the associated charset object is returned.
1928 if (CHARSETP (charset_or_name))
1929 return charset_or_name;
1931 CHECK_SYMBOL (charset_or_name);
1932 return Fgethash (charset_or_name, Vcharset_hash_table, Qnil);
1935 DEFUN ("get-charset", Fget_charset, 1, 1, 0, /*
1936 Retrieve the charset of the given name.
1937 Same as `find-charset' except an error is signalled if there is no such
1938 charset instead of returning nil.
1942 Lisp_Object charset = Ffind_charset (name);
1945 signal_simple_error ("No such charset", name);
1949 /* We store the charsets in hash tables with the names as the key and the
1950 actual charset object as the value. Occasionally we need to use them
1951 in a list format. These routines provide us with that. */
1952 struct charset_list_closure
1954 Lisp_Object *charset_list;
1958 add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
1959 void *charset_list_closure)
1961 /* This function can GC */
1962 struct charset_list_closure *chcl =
1963 (struct charset_list_closure*) charset_list_closure;
1964 Lisp_Object *charset_list = chcl->charset_list;
1966 *charset_list = Fcons (XCHARSET_NAME (value), *charset_list);
1970 DEFUN ("charset-list", Fcharset_list, 0, 0, 0, /*
1971 Return a list of the names of all defined charsets.
1975 Lisp_Object charset_list = Qnil;
1976 struct gcpro gcpro1;
1977 struct charset_list_closure charset_list_closure;
1979 GCPRO1 (charset_list);
1980 charset_list_closure.charset_list = &charset_list;
1981 elisp_maphash (add_charset_to_list_mapper, Vcharset_hash_table,
1982 &charset_list_closure);
1985 return charset_list;
1988 DEFUN ("charset-name", Fcharset_name, 1, 1, 0, /*
1989 Return the name of the given charset.
1993 return XCHARSET_NAME (Fget_charset (charset));
1996 DEFUN ("make-charset", Fmake_charset, 3, 3, 0, /*
1997 Define a new character set.
1998 This function is for use with Mule support.
1999 NAME is a symbol, the name by which the character set is normally referred.
2000 DOC-STRING is a string describing the character set.
2001 PROPS is a property list, describing the specific nature of the
2002 character set. Recognized properties are:
2004 'short-name Short version of the charset name (ex: Latin-1)
2005 'long-name Long version of the charset name (ex: ISO8859-1 (Latin-1))
2006 'registry A regular expression matching the font registry field for
2008 'dimension Number of octets used to index a character in this charset.
2009 Either 1 or 2. Defaults to 1.
2010 'columns Number of columns used to display a character in this charset.
2011 Only used in TTY mode. (Under X, the actual width of a
2012 character can be derived from the font used to display the
2013 characters.) If unspecified, defaults to the dimension
2014 (this is almost always the correct value).
2015 'chars Number of characters in each dimension (94 or 96).
2016 Defaults to 94. Note that if the dimension is 2, the
2017 character set thus described is 94x94 or 96x96.
2018 'final Final byte of ISO 2022 escape sequence. Must be
2019 supplied. Each combination of (DIMENSION, CHARS) defines a
2020 separate namespace for final bytes. Note that ISO
2021 2022 restricts the final byte to the range
2022 0x30 - 0x7E if dimension == 1, and 0x30 - 0x5F if
2023 dimension == 2. Note also that final bytes in the range
2024 0x30 - 0x3F are reserved for user-defined (not official)
2026 'graphic 0 (use left half of font on output) or 1 (use right half
2027 of font on output). Defaults to 0. For example, for
2028 a font whose registry is ISO8859-1, the left half
2029 (octets 0x20 - 0x7F) is the `ascii' character set, while
2030 the right half (octets 0xA0 - 0xFF) is the `latin-1'
2031 character set. With 'graphic set to 0, the octets
2032 will have their high bit cleared; with it set to 1,
2033 the octets will have their high bit set.
2034 'direction 'l2r (left-to-right) or 'r2l (right-to-left).
2036 'ccl-program A compiled CCL program used to convert a character in
2037 this charset into an index into the font. This is in
2038 addition to the 'graphic property. The CCL program
2039 is passed the octets of the character, with the high
2040 bit cleared and set depending upon whether the value
2041 of the 'graphic property is 0 or 1.
2043 (name, doc_string, props))
2045 int id, dimension = 1, chars = 94, graphic = 0, final = 0, columns = -1;
2046 int direction = CHARSET_LEFT_TO_RIGHT;
2048 Lisp_Object registry = Qnil;
2049 Lisp_Object charset;
2050 Lisp_Object rest, keyword, value;
2051 Lisp_Object ccl_program = Qnil;
2052 Lisp_Object short_name = Qnil, long_name = Qnil;
2053 int byte_offset = -1;
2055 CHECK_SYMBOL (name);
2056 if (!NILP (doc_string))
2057 CHECK_STRING (doc_string);
2059 charset = Ffind_charset (name);
2060 if (!NILP (charset))
2061 signal_simple_error ("Cannot redefine existing charset", name);
2063 EXTERNAL_PROPERTY_LIST_LOOP (rest, keyword, value, props)
2065 if (EQ (keyword, Qshort_name))
2067 CHECK_STRING (value);
2071 if (EQ (keyword, Qlong_name))
2073 CHECK_STRING (value);
2077 else if (EQ (keyword, Qdimension))
2080 dimension = XINT (value);
2081 if (dimension < 1 || dimension > 2)
2082 signal_simple_error ("Invalid value for 'dimension", value);
2085 else if (EQ (keyword, Qchars))
2088 chars = XINT (value);
2089 if (chars != 94 && chars != 96)
2090 signal_simple_error ("Invalid value for 'chars", value);
2093 else if (EQ (keyword, Qcolumns))
2096 columns = XINT (value);
2097 if (columns != 1 && columns != 2)
2098 signal_simple_error ("Invalid value for 'columns", value);
2101 else if (EQ (keyword, Qgraphic))
2104 graphic = XINT (value);
2106 if (graphic < 0 || graphic > 2)
2108 if (graphic < 0 || graphic > 1)
2110 signal_simple_error ("Invalid value for 'graphic", value);
2113 else if (EQ (keyword, Qregistry))
2115 CHECK_STRING (value);
2119 else if (EQ (keyword, Qdirection))
2121 if (EQ (value, Ql2r))
2122 direction = CHARSET_LEFT_TO_RIGHT;
2123 else if (EQ (value, Qr2l))
2124 direction = CHARSET_RIGHT_TO_LEFT;
2126 signal_simple_error ("Invalid value for 'direction", value);
2129 else if (EQ (keyword, Qfinal))
2131 CHECK_CHAR_COERCE_INT (value);
2132 final = XCHAR (value);
2133 if (final < '0' || final > '~')
2134 signal_simple_error ("Invalid value for 'final", value);
2137 else if (EQ (keyword, Qccl_program))
2139 CHECK_VECTOR (value);
2140 ccl_program = value;
2144 signal_simple_error ("Unrecognized property", keyword);
2148 error ("'final must be specified");
2149 if (dimension == 2 && final > 0x5F)
2151 ("Final must be in the range 0x30 - 0x5F for dimension == 2",
2155 type = (chars == 94) ? CHARSET_TYPE_94 : CHARSET_TYPE_96;
2157 type = (chars == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
2159 if (!NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_LEFT_TO_RIGHT)) ||
2160 !NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_RIGHT_TO_LEFT)))
2162 ("Character set already defined for this DIMENSION/CHARS/FINAL combo");
2164 id = get_unallocated_leading_byte (dimension);
2166 if (NILP (doc_string))
2167 doc_string = build_string ("");
2169 if (NILP (registry))
2170 registry = build_string ("");
2172 if (NILP (short_name))
2173 XSETSTRING (short_name, XSYMBOL (name)->name);
2175 if (NILP (long_name))
2176 long_name = doc_string;
2179 columns = dimension;
2181 if (byte_offset < 0)
2185 else if (chars == 96)
2191 charset = make_charset (id, name, chars, dimension, columns, graphic,
2192 final, direction, short_name, long_name,
2193 doc_string, registry,
2194 Qnil, 0, 0, 0, byte_offset);
2195 if (!NILP (ccl_program))
2196 XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2200 DEFUN ("make-reverse-direction-charset", Fmake_reverse_direction_charset,
2202 Make a charset equivalent to CHARSET but which goes in the opposite direction.
2203 NEW-NAME is the name of the new charset. Return the new charset.
2205 (charset, new_name))
2207 Lisp_Object new_charset = Qnil;
2208 int id, chars, dimension, columns, graphic, final;
2210 Lisp_Object registry, doc_string, short_name, long_name;
2213 charset = Fget_charset (charset);
2214 if (!NILP (XCHARSET_REVERSE_DIRECTION_CHARSET (charset)))
2215 signal_simple_error ("Charset already has reverse-direction charset",
2218 CHECK_SYMBOL (new_name);
2219 if (!NILP (Ffind_charset (new_name)))
2220 signal_simple_error ("Cannot redefine existing charset", new_name);
2222 cs = XCHARSET (charset);
2224 chars = CHARSET_CHARS (cs);
2225 dimension = CHARSET_DIMENSION (cs);
2226 columns = CHARSET_COLUMNS (cs);
2227 id = get_unallocated_leading_byte (dimension);
2229 graphic = CHARSET_GRAPHIC (cs);
2230 final = CHARSET_FINAL (cs);
2231 direction = CHARSET_RIGHT_TO_LEFT;
2232 if (CHARSET_DIRECTION (cs) == CHARSET_RIGHT_TO_LEFT)
2233 direction = CHARSET_LEFT_TO_RIGHT;
2234 doc_string = CHARSET_DOC_STRING (cs);
2235 short_name = CHARSET_SHORT_NAME (cs);
2236 long_name = CHARSET_LONG_NAME (cs);
2237 registry = CHARSET_REGISTRY (cs);
2239 new_charset = make_charset (id, new_name, chars, dimension, columns,
2240 graphic, final, direction, short_name, long_name,
2241 doc_string, registry,
2243 CHARSET_DECODING_TABLE(cs),
2244 CHARSET_UCS_MIN(cs),
2245 CHARSET_UCS_MAX(cs),
2246 CHARSET_CODE_OFFSET(cs),
2247 CHARSET_BYTE_OFFSET(cs)
2253 CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
2254 XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
2259 DEFUN ("define-charset-alias", Fdefine_charset_alias, 2, 2, 0, /*
2260 Define symbol ALIAS as an alias for CHARSET.
2264 CHECK_SYMBOL (alias);
2265 charset = Fget_charset (charset);
2266 return Fputhash (alias, charset, Vcharset_hash_table);
2269 /* #### Reverse direction charsets not yet implemented. */
2271 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
2273 Return the reverse-direction charset parallel to CHARSET, if any.
2274 This is the charset with the same properties (in particular, the same
2275 dimension, number of characters per dimension, and final byte) as
2276 CHARSET but whose characters are displayed in the opposite direction.
2280 charset = Fget_charset (charset);
2281 return XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
2285 DEFUN ("charset-from-attributes", Fcharset_from_attributes, 3, 4, 0, /*
2286 Return a charset with the given DIMENSION, CHARS, FINAL, and DIRECTION.
2287 If DIRECTION is omitted, both directions will be checked (left-to-right
2288 will be returned if character sets exist for both directions).
2290 (dimension, chars, final, direction))
2292 int dm, ch, fi, di = -1;
2294 Lisp_Object obj = Qnil;
2296 CHECK_INT (dimension);
2297 dm = XINT (dimension);
2298 if (dm < 1 || dm > 2)
2299 signal_simple_error ("Invalid value for DIMENSION", dimension);
2303 if (ch != 94 && ch != 96)
2304 signal_simple_error ("Invalid value for CHARS", chars);
2306 CHECK_CHAR_COERCE_INT (final);
2308 if (fi < '0' || fi > '~')
2309 signal_simple_error ("Invalid value for FINAL", final);
2311 if (EQ (direction, Ql2r))
2312 di = CHARSET_LEFT_TO_RIGHT;
2313 else if (EQ (direction, Qr2l))
2314 di = CHARSET_RIGHT_TO_LEFT;
2315 else if (!NILP (direction))
2316 signal_simple_error ("Invalid value for DIRECTION", direction);
2318 if (dm == 2 && fi > 0x5F)
2320 ("Final must be in the range 0x30 - 0x5F for dimension == 2", final);
2323 type = (ch == 94) ? CHARSET_TYPE_94 : CHARSET_TYPE_96;
2325 type = (ch == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
2329 obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_LEFT_TO_RIGHT);
2331 obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_RIGHT_TO_LEFT);
2334 obj = CHARSET_BY_ATTRIBUTES (type, fi, di);
2337 return XCHARSET_NAME (obj);
2341 DEFUN ("charset-short-name", Fcharset_short_name, 1, 1, 0, /*
2342 Return short name of CHARSET.
2346 return XCHARSET_SHORT_NAME (Fget_charset (charset));
2349 DEFUN ("charset-long-name", Fcharset_long_name, 1, 1, 0, /*
2350 Return long name of CHARSET.
2354 return XCHARSET_LONG_NAME (Fget_charset (charset));
2357 DEFUN ("charset-description", Fcharset_description, 1, 1, 0, /*
2358 Return description of CHARSET.
2362 return XCHARSET_DOC_STRING (Fget_charset (charset));
2365 DEFUN ("charset-dimension", Fcharset_dimension, 1, 1, 0, /*
2366 Return dimension of CHARSET.
2370 return make_int (XCHARSET_DIMENSION (Fget_charset (charset)));
2373 DEFUN ("charset-property", Fcharset_property, 2, 2, 0, /*
2374 Return property PROP of CHARSET.
2375 Recognized properties are those listed in `make-charset', as well as
2376 'name and 'doc-string.
2382 charset = Fget_charset (charset);
2383 cs = XCHARSET (charset);
2385 CHECK_SYMBOL (prop);
2386 if (EQ (prop, Qname)) return CHARSET_NAME (cs);
2387 if (EQ (prop, Qshort_name)) return CHARSET_SHORT_NAME (cs);
2388 if (EQ (prop, Qlong_name)) return CHARSET_LONG_NAME (cs);
2389 if (EQ (prop, Qdoc_string)) return CHARSET_DOC_STRING (cs);
2390 if (EQ (prop, Qdimension)) return make_int (CHARSET_DIMENSION (cs));
2391 if (EQ (prop, Qcolumns)) return make_int (CHARSET_COLUMNS (cs));
2392 if (EQ (prop, Qgraphic)) return make_int (CHARSET_GRAPHIC (cs));
2393 if (EQ (prop, Qfinal)) return make_char (CHARSET_FINAL (cs));
2394 if (EQ (prop, Qchars)) return make_int (CHARSET_CHARS (cs));
2395 if (EQ (prop, Qregistry)) return CHARSET_REGISTRY (cs);
2396 if (EQ (prop, Qccl_program)) return CHARSET_CCL_PROGRAM (cs);
2397 if (EQ (prop, Qdirection))
2398 return CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? Ql2r : Qr2l;
2399 if (EQ (prop, Qreverse_direction_charset))
2401 Lisp_Object obj = CHARSET_REVERSE_DIRECTION_CHARSET (cs);
2405 return XCHARSET_NAME (obj);
2407 signal_simple_error ("Unrecognized charset property name", prop);
2408 return Qnil; /* not reached */
2411 DEFUN ("charset-id", Fcharset_id, 1, 1, 0, /*
2412 Return charset identification number of CHARSET.
2416 return make_int(XCHARSET_LEADING_BYTE (Fget_charset (charset)));
2419 /* #### We need to figure out which properties we really want to
2422 DEFUN ("set-charset-ccl-program", Fset_charset_ccl_program, 2, 2, 0, /*
2423 Set the 'ccl-program property of CHARSET to CCL-PROGRAM.
2425 (charset, ccl_program))
2427 charset = Fget_charset (charset);
2428 CHECK_VECTOR (ccl_program);
2429 XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2434 invalidate_charset_font_caches (Lisp_Object charset)
2436 /* Invalidate font cache entries for charset on all devices. */
2437 Lisp_Object devcons, concons, hash_table;
2438 DEVICE_LOOP_NO_BREAK (devcons, concons)
2440 struct device *d = XDEVICE (XCAR (devcons));
2441 hash_table = Fgethash (charset, d->charset_font_cache, Qunbound);
2442 if (!UNBOUNDP (hash_table))
2443 Fclrhash (hash_table);
2447 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
2448 Set the 'registry property of CHARSET to REGISTRY.
2450 (charset, registry))
2452 charset = Fget_charset (charset);
2453 CHECK_STRING (registry);
2454 XCHARSET_REGISTRY (charset) = registry;
2455 invalidate_charset_font_caches (charset);
2456 face_property_was_changed (Vdefault_face, Qfont, Qglobal);
2461 DEFUN ("charset-mapping-table", Fcharset_mapping_table, 1, 1, 0, /*
2462 Return mapping-table of CHARSET.
2466 return XCHARSET_DECODING_TABLE (Fget_charset (charset));
2469 DEFUN ("set-charset-mapping-table", Fset_charset_mapping_table, 2, 2, 0, /*
2470 Set mapping-table of CHARSET to TABLE.
2474 struct Lisp_Charset *cs;
2475 Lisp_Object old_table;
2478 charset = Fget_charset (charset);
2479 cs = XCHARSET (charset);
2481 if (EQ (table, Qnil))
2483 CHARSET_DECODING_TABLE(cs) = table;
2486 else if (VECTORP (table))
2490 /* ad-hoc method for `ascii' */
2491 if ((CHARSET_CHARS (cs) == 94) &&
2492 (CHARSET_BYTE_OFFSET (cs) != 33))
2493 ccs_len = 128 - CHARSET_BYTE_OFFSET (cs);
2495 ccs_len = CHARSET_CHARS (cs);
2497 if (XVECTOR_LENGTH (table) > ccs_len)
2498 args_out_of_range (table, make_int (CHARSET_CHARS (cs)));
2499 old_table = CHARSET_DECODING_TABLE(cs);
2500 CHARSET_DECODING_TABLE(cs) = table;
2503 signal_error (Qwrong_type_argument,
2504 list2 (build_translated_string ("vector-or-nil-p"),
2506 /* signal_simple_error ("Wrong type argument: vector-or-nil-p", table); */
2508 switch (CHARSET_DIMENSION (cs))
2511 for (i = 0; i < XVECTOR_LENGTH (table); i++)
2513 Lisp_Object c = XVECTOR_DATA(table)[i];
2518 make_int (i + CHARSET_BYTE_OFFSET (cs)));
2522 for (i = 0; i < XVECTOR_LENGTH (table); i++)
2524 Lisp_Object v = XVECTOR_DATA(table)[i];
2530 if (XVECTOR_LENGTH (v) > CHARSET_CHARS (cs))
2532 CHARSET_DECODING_TABLE(cs) = old_table;
2533 args_out_of_range (v, make_int (CHARSET_CHARS (cs)));
2535 for (j = 0; j < XVECTOR_LENGTH (v); j++)
2537 Lisp_Object c = XVECTOR_DATA(v)[j];
2542 make_int ( ((i + CHARSET_BYTE_OFFSET (cs)) << 8)
2543 | (j + CHARSET_BYTE_OFFSET (cs)) ));
2547 put_char_attribute (v, charset,
2548 make_int (i + CHARSET_BYTE_OFFSET (cs)));
2557 /************************************************************************/
2558 /* Lisp primitives for working with characters */
2559 /************************************************************************/
2562 DEFUN ("decode-char", Fdecode_char, 2, 2, 0, /*
2563 Make a character from CHARSET and code-point CODE.
2569 charset = Fget_charset (charset);
2572 if (XCHARSET_GRAPHIC (charset) == 1)
2574 return make_char (DECODE_CHAR (charset, c));
2578 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
2579 Make a character from CHARSET and octets ARG1 and ARG2.
2580 ARG2 is required only for characters from two-dimensional charsets.
2581 For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
2582 character s with caron.
2584 (charset, arg1, arg2))
2588 int lowlim, highlim;
2590 charset = Fget_charset (charset);
2591 cs = XCHARSET (charset);
2593 if (EQ (charset, Vcharset_ascii)) lowlim = 0, highlim = 127;
2594 else if (EQ (charset, Vcharset_control_1)) lowlim = 0, highlim = 31;
2596 else if (CHARSET_CHARS (cs) == 256) lowlim = 0, highlim = 255;
2598 else if (CHARSET_CHARS (cs) == 94) lowlim = 33, highlim = 126;
2599 else /* CHARSET_CHARS (cs) == 96) */ lowlim = 32, highlim = 127;
2602 /* It is useful (and safe, according to Olivier Galibert) to strip
2603 the 8th bit off ARG1 and ARG2 becaue it allows programmers to
2604 write (make-char 'latin-iso8859-2 CODE) where code is the actual
2605 Latin 2 code of the character. */
2613 if (a1 < lowlim || a1 > highlim)
2614 args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
2616 if (CHARSET_DIMENSION (cs) == 1)
2620 ("Charset is of dimension one; second octet must be nil", arg2);
2621 return make_char (MAKE_CHAR (charset, a1, 0));
2630 a2 = XINT (arg2) & 0x7f;
2632 if (a2 < lowlim || a2 > highlim)
2633 args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
2635 return make_char (MAKE_CHAR (charset, a1, a2));
2638 DEFUN ("char-charset", Fchar_charset, 1, 1, 0, /*
2639 Return the character set of char CH.
2643 CHECK_CHAR_COERCE_INT (ch);
2645 return XCHARSET_NAME (CHAR_CHARSET (XCHAR (ch)));
2648 DEFUN ("char-octet", Fchar_octet, 1, 2, 0, /*
2649 Return the octet numbered N (should be 0 or 1) of char CH.
2650 N defaults to 0 if omitted.
2654 Lisp_Object charset;
2657 CHECK_CHAR_COERCE_INT (ch);
2659 BREAKUP_CHAR (XCHAR (ch), charset, octet0, octet1);
2661 if (NILP (n) || EQ (n, Qzero))
2662 return make_int (octet0);
2663 else if (EQ (n, make_int (1)))
2664 return make_int (octet1);
2666 signal_simple_error ("Octet number must be 0 or 1", n);
2669 DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
2670 Return list of charset and one or two position-codes of CHAR.
2674 /* This function can GC */
2675 struct gcpro gcpro1, gcpro2;
2676 Lisp_Object charset = Qnil;
2677 Lisp_Object rc = Qnil;
2685 GCPRO2 (charset, rc);
2686 CHECK_CHAR_COERCE_INT (character);
2689 code_point = ENCODE_CHAR (XCHAR (character), charset);
2690 dimension = XCHARSET_DIMENSION (charset);
2691 while (dimension > 0)
2693 rc = Fcons (make_int (code_point & 255), rc);
2697 rc = Fcons (XCHARSET_NAME (charset), rc);
2699 BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
2701 if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
2703 rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
2707 rc = list2 (XCHARSET_NAME (charset), make_int (c1));
2716 #ifdef ENABLE_COMPOSITE_CHARS
2717 /************************************************************************/
2718 /* composite character functions */
2719 /************************************************************************/
2722 lookup_composite_char (Bufbyte *str, int len)
2724 Lisp_Object lispstr = make_string (str, len);
2725 Lisp_Object ch = Fgethash (lispstr,
2726 Vcomposite_char_string2char_hash_table,
2732 if (composite_char_row_next >= 128)
2733 signal_simple_error ("No more composite chars available", lispstr);
2734 emch = MAKE_CHAR (Vcharset_composite, composite_char_row_next,
2735 composite_char_col_next);
2736 Fputhash (make_char (emch), lispstr,
2737 Vcomposite_char_char2string_hash_table);
2738 Fputhash (lispstr, make_char (emch),
2739 Vcomposite_char_string2char_hash_table);
2740 composite_char_col_next++;
2741 if (composite_char_col_next >= 128)
2743 composite_char_col_next = 32;
2744 composite_char_row_next++;
2753 composite_char_string (Emchar ch)
2755 Lisp_Object str = Fgethash (make_char (ch),
2756 Vcomposite_char_char2string_hash_table,
2758 assert (!UNBOUNDP (str));
2762 xxDEFUN ("make-composite-char", Fmake_composite_char, 1, 1, 0, /*
2763 Convert a string into a single composite character.
2764 The character is the result of overstriking all the characters in
2769 CHECK_STRING (string);
2770 return make_char (lookup_composite_char (XSTRING_DATA (string),
2771 XSTRING_LENGTH (string)));
2774 xxDEFUN ("composite-char-string", Fcomposite_char_string, 1, 1, 0, /*
2775 Return a string of the characters comprising a composite character.
2783 if (CHAR_LEADING_BYTE (emch) != LEADING_BYTE_COMPOSITE)
2784 signal_simple_error ("Must be composite char", ch);
2785 return composite_char_string (emch);
2787 #endif /* ENABLE_COMPOSITE_CHARS */
2790 /************************************************************************/
2791 /* initialization */
2792 /************************************************************************/
2795 syms_of_mule_charset (void)
2798 INIT_LRECORD_IMPLEMENTATION (byte_table);
2799 INIT_LRECORD_IMPLEMENTATION (char_id_table);
2801 INIT_LRECORD_IMPLEMENTATION (charset);
2803 DEFSUBR (Fcharsetp);
2804 DEFSUBR (Ffind_charset);
2805 DEFSUBR (Fget_charset);
2806 DEFSUBR (Fcharset_list);
2807 DEFSUBR (Fcharset_name);
2808 DEFSUBR (Fmake_charset);
2809 DEFSUBR (Fmake_reverse_direction_charset);
2810 /* DEFSUBR (Freverse_direction_charset); */
2811 DEFSUBR (Fdefine_charset_alias);
2812 DEFSUBR (Fcharset_from_attributes);
2813 DEFSUBR (Fcharset_short_name);
2814 DEFSUBR (Fcharset_long_name);
2815 DEFSUBR (Fcharset_description);
2816 DEFSUBR (Fcharset_dimension);
2817 DEFSUBR (Fcharset_property);
2818 DEFSUBR (Fcharset_id);
2819 DEFSUBR (Fset_charset_ccl_program);
2820 DEFSUBR (Fset_charset_registry);
2822 DEFSUBR (Fchar_attribute_alist);
2823 DEFSUBR (Fget_char_attribute);
2824 DEFSUBR (Fput_char_attribute);
2825 DEFSUBR (Fremove_char_attribute);
2826 DEFSUBR (Fdefine_char);
2827 DEFSUBR (Fchar_variants);
2828 DEFSUBR (Fget_composite_char);
2829 DEFSUBR (Fcharset_mapping_table);
2830 DEFSUBR (Fset_charset_mapping_table);
2834 DEFSUBR (Fdecode_char);
2836 DEFSUBR (Fmake_char);
2837 DEFSUBR (Fchar_charset);
2838 DEFSUBR (Fchar_octet);
2839 DEFSUBR (Fsplit_char);
2841 #ifdef ENABLE_COMPOSITE_CHARS
2842 DEFSUBR (Fmake_composite_char);
2843 DEFSUBR (Fcomposite_char_string);
2846 defsymbol (&Qcharsetp, "charsetp");
2847 defsymbol (&Qregistry, "registry");
2848 defsymbol (&Qfinal, "final");
2849 defsymbol (&Qgraphic, "graphic");
2850 defsymbol (&Qdirection, "direction");
2851 defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
2852 defsymbol (&Qshort_name, "short-name");
2853 defsymbol (&Qlong_name, "long-name");
2855 defsymbol (&Ql2r, "l2r");
2856 defsymbol (&Qr2l, "r2l");
2858 /* Charsets, compatible with FSF 20.3
2859 Naming convention is Script-Charset[-Edition] */
2860 defsymbol (&Qascii, "ascii");
2861 defsymbol (&Qcontrol_1, "control-1");
2862 defsymbol (&Qlatin_iso8859_1, "latin-iso8859-1");
2863 defsymbol (&Qlatin_iso8859_2, "latin-iso8859-2");
2864 defsymbol (&Qlatin_iso8859_3, "latin-iso8859-3");
2865 defsymbol (&Qlatin_iso8859_4, "latin-iso8859-4");
2866 defsymbol (&Qthai_tis620, "thai-tis620");
2867 defsymbol (&Qgreek_iso8859_7, "greek-iso8859-7");
2868 defsymbol (&Qarabic_iso8859_6, "arabic-iso8859-6");
2869 defsymbol (&Qhebrew_iso8859_8, "hebrew-iso8859-8");
2870 defsymbol (&Qkatakana_jisx0201, "katakana-jisx0201");
2871 defsymbol (&Qlatin_jisx0201, "latin-jisx0201");
2872 defsymbol (&Qcyrillic_iso8859_5, "cyrillic-iso8859-5");
2873 defsymbol (&Qlatin_iso8859_9, "latin-iso8859-9");
2874 defsymbol (&Qjapanese_jisx0208_1978, "japanese-jisx0208-1978");
2875 defsymbol (&Qchinese_gb2312, "chinese-gb2312");
2876 defsymbol (&Qjapanese_jisx0208, "japanese-jisx0208");
2877 defsymbol (&Qjapanese_jisx0208_1990, "japanese-jisx0208-1990");
2878 defsymbol (&Qkorean_ksc5601, "korean-ksc5601");
2879 defsymbol (&Qjapanese_jisx0212, "japanese-jisx0212");
2880 defsymbol (&Qchinese_cns11643_1, "chinese-cns11643-1");
2881 defsymbol (&Qchinese_cns11643_2, "chinese-cns11643-2");
2883 defsymbol (&Q_ucs, "->ucs");
2884 defsymbol (&Q_decomposition, "->decomposition");
2885 defsymbol (&Qcompat, "compat");
2886 defsymbol (&Qisolated, "isolated");
2887 defsymbol (&Qinitial, "initial");
2888 defsymbol (&Qmedial, "medial");
2889 defsymbol (&Qfinal, "final");
2890 defsymbol (&Qvertical, "vertical");
2891 defsymbol (&QnoBreak, "noBreak");
2892 defsymbol (&Qfraction, "fraction");
2893 defsymbol (&Qsuper, "super");
2894 defsymbol (&Qsub, "sub");
2895 defsymbol (&Qcircle, "circle");
2896 defsymbol (&Qsquare, "square");
2897 defsymbol (&Qwide, "wide");
2898 defsymbol (&Qnarrow, "narrow");
2899 defsymbol (&Qsmall, "small");
2900 defsymbol (&Qfont, "font");
2901 defsymbol (&Qucs, "ucs");
2902 defsymbol (&Qucs_bmp, "ucs-bmp");
2903 defsymbol (&Qlatin_viscii, "latin-viscii");
2904 defsymbol (&Qlatin_tcvn5712, "latin-tcvn5712");
2905 defsymbol (&Qlatin_viscii_lower, "latin-viscii-lower");
2906 defsymbol (&Qlatin_viscii_upper, "latin-viscii-upper");
2907 defsymbol (&Qvietnamese_viscii_lower, "vietnamese-viscii-lower");
2908 defsymbol (&Qvietnamese_viscii_upper, "vietnamese-viscii-upper");
2909 defsymbol (&Qideograph_daikanwa, "ideograph-daikanwa");
2910 defsymbol (&Qmojikyo, "mojikyo");
2911 defsymbol (&Qmojikyo_pj_1, "mojikyo-pj-1");
2912 defsymbol (&Qmojikyo_pj_2, "mojikyo-pj-2");
2913 defsymbol (&Qmojikyo_pj_3, "mojikyo-pj-3");
2914 defsymbol (&Qmojikyo_pj_4, "mojikyo-pj-4");
2915 defsymbol (&Qmojikyo_pj_5, "mojikyo-pj-5");
2916 defsymbol (&Qmojikyo_pj_6, "mojikyo-pj-6");
2917 defsymbol (&Qmojikyo_pj_7, "mojikyo-pj-7");
2918 defsymbol (&Qmojikyo_pj_8, "mojikyo-pj-8");
2919 defsymbol (&Qmojikyo_pj_9, "mojikyo-pj-9");
2920 defsymbol (&Qmojikyo_pj_10, "mojikyo-pj-10");
2921 defsymbol (&Qmojikyo_pj_11, "mojikyo-pj-11");
2922 defsymbol (&Qmojikyo_pj_12, "mojikyo-pj-12");
2923 defsymbol (&Qmojikyo_pj_13, "mojikyo-pj-13");
2924 defsymbol (&Qmojikyo_pj_14, "mojikyo-pj-14");
2925 defsymbol (&Qmojikyo_pj_15, "mojikyo-pj-15");
2926 defsymbol (&Qmojikyo_pj_16, "mojikyo-pj-16");
2927 defsymbol (&Qmojikyo_pj_17, "mojikyo-pj-17");
2928 defsymbol (&Qmojikyo_pj_18, "mojikyo-pj-18");
2929 defsymbol (&Qmojikyo_pj_19, "mojikyo-pj-19");
2930 defsymbol (&Qmojikyo_pj_20, "mojikyo-pj-20");
2931 defsymbol (&Qmojikyo_pj_21, "mojikyo-pj-21");
2932 defsymbol (&Qethiopic_ucs, "ethiopic-ucs");
2934 defsymbol (&Qchinese_big5_1, "chinese-big5-1");
2935 defsymbol (&Qchinese_big5_2, "chinese-big5-2");
2937 defsymbol (&Qcomposite, "composite");
2941 vars_of_mule_charset (void)
2948 chlook = xnew (struct charset_lookup);
2949 dumpstruct (&chlook, &charset_lookup_description);
2951 /* Table of charsets indexed by leading byte. */
2952 for (i = 0; i < countof (chlook->charset_by_leading_byte); i++)
2953 chlook->charset_by_leading_byte[i] = Qnil;
2956 /* Table of charsets indexed by type/final-byte. */
2957 for (i = 0; i < countof (chlook->charset_by_attributes); i++)
2958 for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
2959 chlook->charset_by_attributes[i][j] = Qnil;
2961 /* Table of charsets indexed by type/final-byte/direction. */
2962 for (i = 0; i < countof (chlook->charset_by_attributes); i++)
2963 for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
2964 for (k = 0; k < countof (chlook->charset_by_attributes[0][0]); k++)
2965 chlook->charset_by_attributes[i][j][k] = Qnil;
2969 chlook->next_allocated_leading_byte = MIN_LEADING_BYTE_PRIVATE;
2971 chlook->next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
2972 chlook->next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
2976 leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2977 DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
2978 Leading-code of private TYPE9N charset of column-width 1.
2980 leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2984 Vutf_2000_version = build_string("0.15 (Sangō)");
2985 DEFVAR_LISP ("utf-2000-version", &Vutf_2000_version /*
2986 Version number of UTF-2000.
2989 staticpro (&Vcharacter_attribute_table);
2990 Vcharacter_attribute_table = make_char_id_table (Qnil, 0);
2992 /* staticpro (&Vcharacter_composition_table); */
2993 Vcharacter_composition_table = make_char_id_table (Qnil, -1);
2995 staticpro (&Vcharacter_variant_table);
2996 Vcharacter_variant_table = make_char_id_table (Qnil, 0);
2998 Vdefault_coded_charset_priority_list = Qnil;
2999 DEFVAR_LISP ("default-coded-charset-priority-list",
3000 &Vdefault_coded_charset_priority_list /*
3001 Default order of preferred coded-character-sets.
3007 complex_vars_of_mule_charset (void)
3009 staticpro (&Vcharset_hash_table);
3010 Vcharset_hash_table =
3011 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3013 /* Predefined character sets. We store them into variables for
3017 staticpro (&Vcharset_ucs);
3019 make_charset (LEADING_BYTE_UCS, Qucs, 256, 4,
3020 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3021 build_string ("UCS"),
3022 build_string ("UCS"),
3023 build_string ("ISO/IEC 10646"),
3025 Qnil, 0, 0xFFFFFFF, 0, 0);
3026 staticpro (&Vcharset_ucs_bmp);
3028 make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp, 256, 2,
3029 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3030 build_string ("BMP"),
3031 build_string ("BMP"),
3032 build_string ("ISO/IEC 10646 Group 0 Plane 0 (BMP)"),
3033 build_string ("\\(ISO10646.*-1\\|UNICODE[23]?-0\\)"),
3034 Qnil, 0, 0xFFFF, 0, 0);
3036 # define MIN_CHAR_THAI 0
3037 # define MAX_CHAR_THAI 0
3038 # define MIN_CHAR_HEBREW 0
3039 # define MAX_CHAR_HEBREW 0
3040 # define MIN_CHAR_HALFWIDTH_KATAKANA 0
3041 # define MAX_CHAR_HALFWIDTH_KATAKANA 0
3043 staticpro (&Vcharset_ascii);
3045 make_charset (LEADING_BYTE_ASCII, Qascii, 94, 1,
3046 1, 0, 'B', CHARSET_LEFT_TO_RIGHT,
3047 build_string ("ASCII"),
3048 build_string ("ASCII)"),
3049 build_string ("ASCII (ISO646 IRV)"),
3050 build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
3051 Qnil, 0, 0x7F, 0, 0);
3052 staticpro (&Vcharset_control_1);
3053 Vcharset_control_1 =
3054 make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1, 94, 1,
3055 1, 1, 0, CHARSET_LEFT_TO_RIGHT,
3056 build_string ("C1"),
3057 build_string ("Control characters"),
3058 build_string ("Control characters 128-191"),
3060 Qnil, 0x80, 0x9F, 0, 0);
3061 staticpro (&Vcharset_latin_iso8859_1);
3062 Vcharset_latin_iso8859_1 =
3063 make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1, 96, 1,
3064 1, 1, 'A', CHARSET_LEFT_TO_RIGHT,
3065 build_string ("Latin-1"),
3066 build_string ("ISO8859-1 (Latin-1)"),
3067 build_string ("ISO8859-1 (Latin-1)"),
3068 build_string ("iso8859-1"),
3069 Qnil, 0xA0, 0xFF, 0, 32);
3070 staticpro (&Vcharset_latin_iso8859_2);
3071 Vcharset_latin_iso8859_2 =
3072 make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2, 96, 1,
3073 1, 1, 'B', CHARSET_LEFT_TO_RIGHT,
3074 build_string ("Latin-2"),
3075 build_string ("ISO8859-2 (Latin-2)"),
3076 build_string ("ISO8859-2 (Latin-2)"),
3077 build_string ("iso8859-2"),
3079 staticpro (&Vcharset_latin_iso8859_3);
3080 Vcharset_latin_iso8859_3 =
3081 make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3, 96, 1,
3082 1, 1, 'C', CHARSET_LEFT_TO_RIGHT,
3083 build_string ("Latin-3"),
3084 build_string ("ISO8859-3 (Latin-3)"),
3085 build_string ("ISO8859-3 (Latin-3)"),
3086 build_string ("iso8859-3"),
3088 staticpro (&Vcharset_latin_iso8859_4);
3089 Vcharset_latin_iso8859_4 =
3090 make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4, 96, 1,
3091 1, 1, 'D', CHARSET_LEFT_TO_RIGHT,
3092 build_string ("Latin-4"),
3093 build_string ("ISO8859-4 (Latin-4)"),
3094 build_string ("ISO8859-4 (Latin-4)"),
3095 build_string ("iso8859-4"),
3097 staticpro (&Vcharset_thai_tis620);
3098 Vcharset_thai_tis620 =
3099 make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620, 96, 1,
3100 1, 1, 'T', CHARSET_LEFT_TO_RIGHT,
3101 build_string ("TIS620"),
3102 build_string ("TIS620 (Thai)"),
3103 build_string ("TIS620.2529 (Thai)"),
3104 build_string ("tis620"),
3105 Qnil, MIN_CHAR_THAI, MAX_CHAR_THAI, 0, 32);
3106 staticpro (&Vcharset_greek_iso8859_7);
3107 Vcharset_greek_iso8859_7 =
3108 make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7, 96, 1,
3109 1, 1, 'F', CHARSET_LEFT_TO_RIGHT,
3110 build_string ("ISO8859-7"),
3111 build_string ("ISO8859-7 (Greek)"),
3112 build_string ("ISO8859-7 (Greek)"),
3113 build_string ("iso8859-7"),
3115 0 /* MIN_CHAR_GREEK */,
3116 0 /* MAX_CHAR_GREEK */, 0, 32);
3117 staticpro (&Vcharset_arabic_iso8859_6);
3118 Vcharset_arabic_iso8859_6 =
3119 make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6, 96, 1,
3120 1, 1, 'G', CHARSET_RIGHT_TO_LEFT,
3121 build_string ("ISO8859-6"),
3122 build_string ("ISO8859-6 (Arabic)"),
3123 build_string ("ISO8859-6 (Arabic)"),
3124 build_string ("iso8859-6"),
3126 staticpro (&Vcharset_hebrew_iso8859_8);
3127 Vcharset_hebrew_iso8859_8 =
3128 make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8, 96, 1,
3129 1, 1, 'H', CHARSET_RIGHT_TO_LEFT,
3130 build_string ("ISO8859-8"),
3131 build_string ("ISO8859-8 (Hebrew)"),
3132 build_string ("ISO8859-8 (Hebrew)"),
3133 build_string ("iso8859-8"),
3134 Qnil, MIN_CHAR_HEBREW, MAX_CHAR_HEBREW, 0, 32);
3135 staticpro (&Vcharset_katakana_jisx0201);
3136 Vcharset_katakana_jisx0201 =
3137 make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201, 94, 1,
3138 1, 1, 'I', CHARSET_LEFT_TO_RIGHT,
3139 build_string ("JISX0201 Kana"),
3140 build_string ("JISX0201.1976 (Japanese Kana)"),
3141 build_string ("JISX0201.1976 Japanese Kana"),
3142 build_string ("jisx0201\\.1976"),
3144 staticpro (&Vcharset_latin_jisx0201);
3145 Vcharset_latin_jisx0201 =
3146 make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201, 94, 1,
3147 1, 0, 'J', CHARSET_LEFT_TO_RIGHT,
3148 build_string ("JISX0201 Roman"),
3149 build_string ("JISX0201.1976 (Japanese Roman)"),
3150 build_string ("JISX0201.1976 Japanese Roman"),
3151 build_string ("jisx0201\\.1976"),
3153 staticpro (&Vcharset_cyrillic_iso8859_5);
3154 Vcharset_cyrillic_iso8859_5 =
3155 make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5, 96, 1,
3156 1, 1, 'L', CHARSET_LEFT_TO_RIGHT,
3157 build_string ("ISO8859-5"),
3158 build_string ("ISO8859-5 (Cyrillic)"),
3159 build_string ("ISO8859-5 (Cyrillic)"),
3160 build_string ("iso8859-5"),
3162 0 /* MIN_CHAR_CYRILLIC */,
3163 0 /* MAX_CHAR_CYRILLIC */, 0, 32);
3164 staticpro (&Vcharset_latin_iso8859_9);
3165 Vcharset_latin_iso8859_9 =
3166 make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9, 96, 1,
3167 1, 1, 'M', CHARSET_LEFT_TO_RIGHT,
3168 build_string ("Latin-5"),
3169 build_string ("ISO8859-9 (Latin-5)"),
3170 build_string ("ISO8859-9 (Latin-5)"),
3171 build_string ("iso8859-9"),
3173 staticpro (&Vcharset_japanese_jisx0208_1978);
3174 Vcharset_japanese_jisx0208_1978 =
3175 make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978,
3176 Qjapanese_jisx0208_1978, 94, 2,
3177 2, 0, '@', CHARSET_LEFT_TO_RIGHT,
3178 build_string ("JIS X0208:1978"),
3179 build_string ("JIS X0208:1978 (Japanese)"),
3181 ("JIS X0208:1978 Japanese Kanji (so called \"old JIS\")"),
3182 build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
3184 staticpro (&Vcharset_chinese_gb2312);
3185 Vcharset_chinese_gb2312 =
3186 make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312, 94, 2,
3187 2, 0, 'A', CHARSET_LEFT_TO_RIGHT,
3188 build_string ("GB2312"),
3189 build_string ("GB2312)"),
3190 build_string ("GB2312 Chinese simplified"),
3191 build_string ("gb2312"),
3193 staticpro (&Vcharset_japanese_jisx0208);
3194 Vcharset_japanese_jisx0208 =
3195 make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208, 94, 2,
3196 2, 0, 'B', CHARSET_LEFT_TO_RIGHT,
3197 build_string ("JISX0208"),
3198 build_string ("JIS X0208:1983 (Japanese)"),
3199 build_string ("JIS X0208:1983 Japanese Kanji"),
3200 build_string ("jisx0208\\.1983"),
3203 staticpro (&Vcharset_japanese_jisx0208_1990);
3204 Vcharset_japanese_jisx0208_1990 =
3205 make_charset (LEADING_BYTE_JAPANESE_JISX0208_1990,
3206 Qjapanese_jisx0208_1990, 94, 2,
3207 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3208 build_string ("JISX0208-1990"),
3209 build_string ("JIS X0208:1990 (Japanese)"),
3210 build_string ("JIS X0208:1990 Japanese Kanji"),
3211 build_string ("jisx0208\\.1990"),
3213 MIN_CHAR_JIS_X0208_1990,
3214 MAX_CHAR_JIS_X0208_1990, 0, 33);
3216 staticpro (&Vcharset_korean_ksc5601);
3217 Vcharset_korean_ksc5601 =
3218 make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601, 94, 2,
3219 2, 0, 'C', CHARSET_LEFT_TO_RIGHT,
3220 build_string ("KSC5601"),
3221 build_string ("KSC5601 (Korean"),
3222 build_string ("KSC5601 Korean Hangul and Hanja"),
3223 build_string ("ksc5601"),
3225 staticpro (&Vcharset_japanese_jisx0212);
3226 Vcharset_japanese_jisx0212 =
3227 make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212, 94, 2,
3228 2, 0, 'D', CHARSET_LEFT_TO_RIGHT,
3229 build_string ("JISX0212"),
3230 build_string ("JISX0212 (Japanese)"),
3231 build_string ("JISX0212 Japanese Supplement"),
3232 build_string ("jisx0212"),
3235 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
3236 staticpro (&Vcharset_chinese_cns11643_1);
3237 Vcharset_chinese_cns11643_1 =
3238 make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1, 94, 2,
3239 2, 0, 'G', CHARSET_LEFT_TO_RIGHT,
3240 build_string ("CNS11643-1"),
3241 build_string ("CNS11643-1 (Chinese traditional)"),
3243 ("CNS 11643 Plane 1 Chinese traditional"),
3244 build_string (CHINESE_CNS_PLANE_RE("1")),
3246 staticpro (&Vcharset_chinese_cns11643_2);
3247 Vcharset_chinese_cns11643_2 =
3248 make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2, 94, 2,
3249 2, 0, 'H', CHARSET_LEFT_TO_RIGHT,
3250 build_string ("CNS11643-2"),
3251 build_string ("CNS11643-2 (Chinese traditional)"),
3253 ("CNS 11643 Plane 2 Chinese traditional"),
3254 build_string (CHINESE_CNS_PLANE_RE("2")),
3257 staticpro (&Vcharset_latin_tcvn5712);
3258 Vcharset_latin_tcvn5712 =
3259 make_charset (LEADING_BYTE_LATIN_TCVN5712, Qlatin_tcvn5712, 96, 1,
3260 1, 1, 'Z', CHARSET_LEFT_TO_RIGHT,
3261 build_string ("TCVN 5712"),
3262 build_string ("TCVN 5712 (VSCII-2)"),
3263 build_string ("Vietnamese TCVN 5712:1983 (VSCII-2)"),
3264 build_string ("tcvn5712-1"),
3266 staticpro (&Vcharset_latin_viscii_lower);
3267 Vcharset_latin_viscii_lower =
3268 make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower, 96, 1,
3269 1, 1, '1', CHARSET_LEFT_TO_RIGHT,
3270 build_string ("VISCII lower"),
3271 build_string ("VISCII lower (Vietnamese)"),
3272 build_string ("VISCII lower (Vietnamese)"),
3273 build_string ("MULEVISCII-LOWER"),
3275 staticpro (&Vcharset_latin_viscii_upper);
3276 Vcharset_latin_viscii_upper =
3277 make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper, 96, 1,
3278 1, 1, '2', CHARSET_LEFT_TO_RIGHT,
3279 build_string ("VISCII upper"),
3280 build_string ("VISCII upper (Vietnamese)"),
3281 build_string ("VISCII upper (Vietnamese)"),
3282 build_string ("MULEVISCII-UPPER"),
3284 staticpro (&Vcharset_latin_viscii);
3285 Vcharset_latin_viscii =
3286 make_charset (LEADING_BYTE_LATIN_VISCII, Qlatin_viscii, 256, 1,
3287 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3288 build_string ("VISCII"),
3289 build_string ("VISCII 1.1 (Vietnamese)"),
3290 build_string ("VISCII 1.1 (Vietnamese)"),
3291 build_string ("VISCII1\\.1"),
3293 staticpro (&Vcharset_ideograph_daikanwa);
3294 Vcharset_ideograph_daikanwa =
3295 make_charset (LEADING_BYTE_DAIKANWA, Qideograph_daikanwa, 256, 2,
3296 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3297 build_string ("Daikanwa"),
3298 build_string ("Morohashi's Daikanwa"),
3299 build_string ("Daikanwa dictionary by MOROHASHI Tetsuji"),
3300 build_string ("Daikanwa"),
3301 Qnil, MIN_CHAR_DAIKANWA, MAX_CHAR_DAIKANWA, 0, 0);
3302 staticpro (&Vcharset_mojikyo);
3304 make_charset (LEADING_BYTE_MOJIKYO, Qmojikyo, 256, 3,
3305 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3306 build_string ("Mojikyo"),
3307 build_string ("Mojikyo"),
3308 build_string ("Konjaku-Mojikyo"),
3310 Qnil, MIN_CHAR_MOJIKYO, MAX_CHAR_MOJIKYO, 0, 0);
3311 staticpro (&Vcharset_mojikyo_pj_1);
3312 Vcharset_mojikyo_pj_1 =
3313 make_charset (LEADING_BYTE_MOJIKYO_PJ_1, Qmojikyo_pj_1, 94, 2,
3314 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3315 build_string ("Mojikyo-PJ-1"),
3316 build_string ("Mojikyo (pseudo JIS encoding) part 1"),
3318 ("Konjaku-Mojikyo (pseudo JIS encoding) part 1"),
3319 build_string ("jisx0208\\.Mojikyo-1$"),
3321 staticpro (&Vcharset_mojikyo_pj_2);
3322 Vcharset_mojikyo_pj_2 =
3323 make_charset (LEADING_BYTE_MOJIKYO_PJ_2, Qmojikyo_pj_2, 94, 2,
3324 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3325 build_string ("Mojikyo-PJ-2"),
3326 build_string ("Mojikyo (pseudo JIS encoding) part 2"),
3328 ("Konjaku-Mojikyo (pseudo JIS encoding) part 2"),
3329 build_string ("jisx0208\\.Mojikyo-2$"),
3331 staticpro (&Vcharset_mojikyo_pj_3);
3332 Vcharset_mojikyo_pj_3 =
3333 make_charset (LEADING_BYTE_MOJIKYO_PJ_3, Qmojikyo_pj_3, 94, 2,
3334 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3335 build_string ("Mojikyo-PJ-3"),
3336 build_string ("Mojikyo (pseudo JIS encoding) part 3"),
3338 ("Konjaku-Mojikyo (pseudo JIS encoding) part 3"),
3339 build_string ("jisx0208\\.Mojikyo-3$"),
3341 staticpro (&Vcharset_mojikyo_pj_4);
3342 Vcharset_mojikyo_pj_4 =
3343 make_charset (LEADING_BYTE_MOJIKYO_PJ_4, Qmojikyo_pj_4, 94, 2,
3344 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3345 build_string ("Mojikyo-PJ-4"),
3346 build_string ("Mojikyo (pseudo JIS encoding) part 4"),
3348 ("Konjaku-Mojikyo (pseudo JIS encoding) part 4"),
3349 build_string ("jisx0208\\.Mojikyo-4$"),
3351 staticpro (&Vcharset_mojikyo_pj_5);
3352 Vcharset_mojikyo_pj_5 =
3353 make_charset (LEADING_BYTE_MOJIKYO_PJ_5, Qmojikyo_pj_5, 94, 2,
3354 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3355 build_string ("Mojikyo-PJ-5"),
3356 build_string ("Mojikyo (pseudo JIS encoding) part 5"),
3358 ("Konjaku-Mojikyo (pseudo JIS encoding) part 5"),
3359 build_string ("jisx0208\\.Mojikyo-5$"),
3361 staticpro (&Vcharset_mojikyo_pj_6);
3362 Vcharset_mojikyo_pj_6 =
3363 make_charset (LEADING_BYTE_MOJIKYO_PJ_6, Qmojikyo_pj_6, 94, 2,
3364 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3365 build_string ("Mojikyo-PJ-6"),
3366 build_string ("Mojikyo (pseudo JIS encoding) part 6"),
3368 ("Konjaku-Mojikyo (pseudo JIS encoding) part 6"),
3369 build_string ("jisx0208\\.Mojikyo-6$"),
3371 staticpro (&Vcharset_mojikyo_pj_7);
3372 Vcharset_mojikyo_pj_7 =
3373 make_charset (LEADING_BYTE_MOJIKYO_PJ_7, Qmojikyo_pj_7, 94, 2,
3374 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3375 build_string ("Mojikyo-PJ-7"),
3376 build_string ("Mojikyo (pseudo JIS encoding) part 7"),
3378 ("Konjaku-Mojikyo (pseudo JIS encoding) part 7"),
3379 build_string ("jisx0208\\.Mojikyo-7$"),
3381 staticpro (&Vcharset_mojikyo_pj_8);
3382 Vcharset_mojikyo_pj_8 =
3383 make_charset (LEADING_BYTE_MOJIKYO_PJ_8, Qmojikyo_pj_8, 94, 2,
3384 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3385 build_string ("Mojikyo-PJ-8"),
3386 build_string ("Mojikyo (pseudo JIS encoding) part 8"),
3388 ("Konjaku-Mojikyo (pseudo JIS encoding) part 8"),
3389 build_string ("jisx0208\\.Mojikyo-8$"),
3391 staticpro (&Vcharset_mojikyo_pj_9);
3392 Vcharset_mojikyo_pj_9 =
3393 make_charset (LEADING_BYTE_MOJIKYO_PJ_9, Qmojikyo_pj_9, 94, 2,
3394 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3395 build_string ("Mojikyo-PJ-9"),
3396 build_string ("Mojikyo (pseudo JIS encoding) part 9"),
3398 ("Konjaku-Mojikyo (pseudo JIS encoding) part 9"),
3399 build_string ("jisx0208\\.Mojikyo-9$"),
3401 staticpro (&Vcharset_mojikyo_pj_10);
3402 Vcharset_mojikyo_pj_10 =
3403 make_charset (LEADING_BYTE_MOJIKYO_PJ_10, Qmojikyo_pj_10, 94, 2,
3404 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3405 build_string ("Mojikyo-PJ-10"),
3406 build_string ("Mojikyo (pseudo JIS encoding) part 10"),
3408 ("Konjaku-Mojikyo (pseudo JIS encoding) part 10"),
3409 build_string ("jisx0208\\.Mojikyo-10$"),
3411 staticpro (&Vcharset_mojikyo_pj_11);
3412 Vcharset_mojikyo_pj_11 =
3413 make_charset (LEADING_BYTE_MOJIKYO_PJ_11, Qmojikyo_pj_11, 94, 2,
3414 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3415 build_string ("Mojikyo-PJ-11"),
3416 build_string ("Mojikyo (pseudo JIS encoding) part 11"),
3418 ("Konjaku-Mojikyo (pseudo JIS encoding) part 11"),
3419 build_string ("jisx0208\\.Mojikyo-11$"),
3421 staticpro (&Vcharset_mojikyo_pj_12);
3422 Vcharset_mojikyo_pj_12 =
3423 make_charset (LEADING_BYTE_MOJIKYO_PJ_12, Qmojikyo_pj_12, 94, 2,
3424 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3425 build_string ("Mojikyo-PJ-12"),
3426 build_string ("Mojikyo (pseudo JIS encoding) part 12"),
3428 ("Konjaku-Mojikyo (pseudo JIS encoding) part 12"),
3429 build_string ("jisx0208\\.Mojikyo-12$"),
3431 staticpro (&Vcharset_mojikyo_pj_13);
3432 Vcharset_mojikyo_pj_13 =
3433 make_charset (LEADING_BYTE_MOJIKYO_PJ_13, Qmojikyo_pj_13, 94, 2,
3434 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3435 build_string ("Mojikyo-PJ-13"),
3436 build_string ("Mojikyo (pseudo JIS encoding) part 13"),
3438 ("Konjaku-Mojikyo (pseudo JIS encoding) part 13"),
3439 build_string ("jisx0208\\.Mojikyo-13$"),
3441 staticpro (&Vcharset_mojikyo_pj_14);
3442 Vcharset_mojikyo_pj_14 =
3443 make_charset (LEADING_BYTE_MOJIKYO_PJ_14, Qmojikyo_pj_14, 94, 2,
3444 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3445 build_string ("Mojikyo-PJ-14"),
3446 build_string ("Mojikyo (pseudo JIS encoding) part 14"),
3448 ("Konjaku-Mojikyo (pseudo JIS encoding) part 14"),
3449 build_string ("jisx0208\\.Mojikyo-14$"),
3451 staticpro (&Vcharset_mojikyo_pj_15);
3452 Vcharset_mojikyo_pj_15 =
3453 make_charset (LEADING_BYTE_MOJIKYO_PJ_15, Qmojikyo_pj_15, 94, 2,
3454 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3455 build_string ("Mojikyo-PJ-15"),
3456 build_string ("Mojikyo (pseudo JIS encoding) part 15"),
3458 ("Konjaku-Mojikyo (pseudo JIS encoding) part 15"),
3459 build_string ("jisx0208\\.Mojikyo-15$"),
3461 staticpro (&Vcharset_mojikyo_pj_16);
3462 Vcharset_mojikyo_pj_16 =
3463 make_charset (LEADING_BYTE_MOJIKYO_PJ_16, Qmojikyo_pj_16, 94, 2,
3464 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3465 build_string ("Mojikyo-PJ-16"),
3466 build_string ("Mojikyo (pseudo JIS encoding) part 16"),
3468 ("Konjaku-Mojikyo (pseudo JIS encoding) part 16"),
3469 build_string ("jisx0208\\.Mojikyo-16$"),
3471 staticpro (&Vcharset_mojikyo_pj_17);
3472 Vcharset_mojikyo_pj_17 =
3473 make_charset (LEADING_BYTE_MOJIKYO_PJ_17, Qmojikyo_pj_17, 94, 2,
3474 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3475 build_string ("Mojikyo-PJ-17"),
3476 build_string ("Mojikyo (pseudo JIS encoding) part 17"),
3478 ("Konjaku-Mojikyo (pseudo JIS encoding) part 17"),
3479 build_string ("jisx0208\\.Mojikyo-17$"),
3481 staticpro (&Vcharset_mojikyo_pj_18);
3482 Vcharset_mojikyo_pj_18 =
3483 make_charset (LEADING_BYTE_MOJIKYO_PJ_18, Qmojikyo_pj_18, 94, 2,
3484 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3485 build_string ("Mojikyo-PJ-18"),
3486 build_string ("Mojikyo (pseudo JIS encoding) part 18"),
3488 ("Konjaku-Mojikyo (pseudo JIS encoding) part 18"),
3489 build_string ("jisx0208\\.Mojikyo-18$"),
3491 staticpro (&Vcharset_mojikyo_pj_19);
3492 Vcharset_mojikyo_pj_19 =
3493 make_charset (LEADING_BYTE_MOJIKYO_PJ_19, Qmojikyo_pj_19, 94, 2,
3494 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3495 build_string ("Mojikyo-PJ-19"),
3496 build_string ("Mojikyo (pseudo JIS encoding) part 19"),
3498 ("Konjaku-Mojikyo (pseudo JIS encoding) part 19"),
3499 build_string ("jisx0208\\.Mojikyo-19$"),
3501 staticpro (&Vcharset_mojikyo_pj_20);
3502 Vcharset_mojikyo_pj_20 =
3503 make_charset (LEADING_BYTE_MOJIKYO_PJ_20, Qmojikyo_pj_20, 94, 2,
3504 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3505 build_string ("Mojikyo-PJ-20"),
3506 build_string ("Mojikyo (pseudo JIS encoding) part 20"),
3508 ("Konjaku-Mojikyo (pseudo JIS encoding) part 20"),
3509 build_string ("jisx0208\\.Mojikyo-20$"),
3511 staticpro (&Vcharset_mojikyo_pj_21);
3512 Vcharset_mojikyo_pj_21 =
3513 make_charset (LEADING_BYTE_MOJIKYO_PJ_21, Qmojikyo_pj_21, 94, 2,
3514 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3515 build_string ("Mojikyo-PJ-21"),
3516 build_string ("Mojikyo (pseudo JIS encoding) part 21"),
3518 ("Konjaku-Mojikyo (pseudo JIS encoding) part 21"),
3519 build_string ("jisx0208\\.Mojikyo-21$"),
3521 staticpro (&Vcharset_ethiopic_ucs);
3522 Vcharset_ethiopic_ucs =
3523 make_charset (LEADING_BYTE_ETHIOPIC_UCS, Qethiopic_ucs, 256, 2,
3524 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3525 build_string ("Ethiopic (UCS)"),
3526 build_string ("Ethiopic (UCS)"),
3527 build_string ("Ethiopic of UCS"),
3528 build_string ("Ethiopic-Unicode"),
3529 Qnil, 0x1200, 0x137F, 0x1200, 0);
3531 staticpro (&Vcharset_chinese_big5_1);
3532 Vcharset_chinese_big5_1 =
3533 make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1, 94, 2,
3534 2, 0, '0', CHARSET_LEFT_TO_RIGHT,
3535 build_string ("Big5"),
3536 build_string ("Big5 (Level-1)"),
3538 ("Big5 Level-1 Chinese traditional"),
3539 build_string ("big5"),
3541 staticpro (&Vcharset_chinese_big5_2);
3542 Vcharset_chinese_big5_2 =
3543 make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2, 94, 2,
3544 2, 0, '1', CHARSET_LEFT_TO_RIGHT,
3545 build_string ("Big5"),
3546 build_string ("Big5 (Level-2)"),
3548 ("Big5 Level-2 Chinese traditional"),
3549 build_string ("big5"),
3552 #ifdef ENABLE_COMPOSITE_CHARS
3553 /* #### For simplicity, we put composite chars into a 96x96 charset.
3554 This is going to lead to problems because you can run out of
3555 room, esp. as we don't yet recycle numbers. */
3556 staticpro (&Vcharset_composite);
3557 Vcharset_composite =
3558 make_charset (LEADING_BYTE_COMPOSITE, Qcomposite, 96, 2,
3559 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3560 build_string ("Composite"),
3561 build_string ("Composite characters"),
3562 build_string ("Composite characters"),
3565 /* #### not dumped properly */
3566 composite_char_row_next = 32;
3567 composite_char_col_next = 32;
3569 Vcomposite_char_string2char_hash_table =
3570 make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
3571 Vcomposite_char_char2string_hash_table =
3572 make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3573 staticpro (&Vcomposite_char_string2char_hash_table);
3574 staticpro (&Vcomposite_char_char2string_hash_table);
3575 #endif /* ENABLE_COMPOSITE_CHARS */