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,2001,2002,2003,2004,2008,2009 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 /* Rewritten by Ben Wing <ben@xemacs.org>. */
25 /* Rewritten by MORIOKA Tomohiko <tomo@m17n.org> for XEmacs CHISE. */
44 /* The various pre-defined charsets. */
46 Lisp_Object Vcharset_ascii;
47 Lisp_Object Vcharset_control_1;
48 Lisp_Object Vcharset_latin_iso8859_1;
49 Lisp_Object Vcharset_latin_iso8859_2;
50 Lisp_Object Vcharset_latin_iso8859_3;
51 Lisp_Object Vcharset_latin_iso8859_4;
52 Lisp_Object Vcharset_thai_tis620;
53 Lisp_Object Vcharset_greek_iso8859_7;
54 Lisp_Object Vcharset_arabic_iso8859_6;
55 Lisp_Object Vcharset_hebrew_iso8859_8;
56 Lisp_Object Vcharset_katakana_jisx0201;
57 Lisp_Object Vcharset_latin_jisx0201;
58 Lisp_Object Vcharset_cyrillic_iso8859_5;
59 Lisp_Object Vcharset_latin_iso8859_9;
60 /* Lisp_Object Vcharset_japanese_jisx0208_1978; */
61 Lisp_Object Vcharset_chinese_gb2312;
62 Lisp_Object Vcharset_chinese_gb12345;
63 Lisp_Object Vcharset_japanese_jisx0208;
64 Lisp_Object Vcharset_japanese_jisx0208_1990;
65 Lisp_Object Vcharset_korean_ksc5601;
66 Lisp_Object Vcharset_japanese_jisx0212;
67 Lisp_Object Vcharset_chinese_cns11643_1;
68 Lisp_Object Vcharset_chinese_cns11643_2;
70 Lisp_Object Vcharset_system_char_id;
71 Lisp_Object Vcharset_ucs;
72 Lisp_Object Vcharset_ucs_bmp;
73 Lisp_Object Vcharset_ucs_smp;
74 Lisp_Object Vcharset_ucs_sip;
75 Lisp_Object Vcharset_latin_viscii;
76 Lisp_Object Vcharset_latin_tcvn5712;
77 Lisp_Object Vcharset_latin_viscii_lower;
78 Lisp_Object Vcharset_latin_viscii_upper;
79 Lisp_Object Vcharset_jis_x0208;
80 Lisp_Object Vcharset_chinese_big5;
81 Lisp_Object Vcharset_ethiopic_ucs;
83 Lisp_Object Vcharset_chinese_big5_1;
84 Lisp_Object Vcharset_chinese_big5_2;
86 #ifdef ENABLE_COMPOSITE_CHARS
87 Lisp_Object Vcharset_composite;
89 /* Hash tables for composite chars. One maps string representing
90 composed chars to their equivalent chars; one goes the
92 Lisp_Object Vcomposite_char_char2string_hash_table;
93 Lisp_Object Vcomposite_char_string2char_hash_table;
95 static int composite_char_row_next;
96 static int composite_char_col_next;
98 #endif /* ENABLE_COMPOSITE_CHARS */
100 struct charset_lookup *chlook;
102 static const struct lrecord_description charset_lookup_description_1[] = {
103 { XD_LISP_OBJECT_ARRAY, offsetof (struct charset_lookup, charset_by_leading_byte),
105 NUM_LEADING_BYTES+4*128
112 static const struct struct_description charset_lookup_description = {
113 sizeof (struct charset_lookup),
114 charset_lookup_description_1
118 /* Table of number of bytes in the string representation of a character
119 indexed by the first byte of that representation.
121 rep_bytes_by_first_byte(c) is more efficient than the equivalent
122 canonical computation:
124 XCHARSET_REP_BYTES (CHARSET_BY_LEADING_BYTE (c)) */
126 const Bytecount rep_bytes_by_first_byte[0xA0] =
127 { /* 0x00 - 0x7f are for straight ASCII */
128 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
129 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
130 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
131 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
132 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
133 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
134 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
135 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
136 /* 0x80 - 0x8f are for Dimension-1 official charsets */
138 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
140 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
142 /* 0x90 - 0x9d are for Dimension-2 official charsets */
143 /* 0x9e is for Dimension-1 private charsets */
144 /* 0x9f is for Dimension-2 private charsets */
145 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
151 int decoding_table_check_elements (Lisp_Object v, int dim, int ccs_len);
153 decoding_table_check_elements (Lisp_Object v, int dim, int ccs_len)
157 if (XVECTOR_LENGTH (v) > ccs_len)
160 for (i = 0; i < XVECTOR_LENGTH (v); i++)
162 Lisp_Object c = XVECTOR_DATA(v)[i];
164 if (!NILP (c) && !CHARP (c))
168 int ret = decoding_table_check_elements (c, dim - 1, ccs_len);
180 decoding_table_put_char (Lisp_Object ccs,
181 int code_point, Lisp_Object character)
184 Lisp_Object table1 = XCHARSET_DECODING_TABLE (ccs);
185 int dim = XCHARSET_DIMENSION (ccs);
188 XCHARSET_DECODING_TABLE (ccs)
189 = put_ccs_octet_table (table1, ccs, code_point, character);
193 = get_ccs_octet_table (table1, ccs, (unsigned char)(code_point >> 8));
195 table2 = put_ccs_octet_table (table2, ccs,
196 (unsigned char)code_point, character);
197 XCHARSET_DECODING_TABLE (ccs)
198 = put_ccs_octet_table (table1, ccs,
199 (unsigned char)(code_point >> 8), table2);
204 = get_ccs_octet_table (table1, ccs, (unsigned char)(code_point >> 16));
206 = get_ccs_octet_table (table2, ccs, (unsigned char)(code_point >> 8));
208 table3 = put_ccs_octet_table (table3, ccs,
209 (unsigned char)code_point, character);
210 table2 = put_ccs_octet_table (table2, ccs,
211 (unsigned char)(code_point >> 8), table3);
212 XCHARSET_DECODING_TABLE (ccs)
213 = put_ccs_octet_table (table1, ccs,
214 (unsigned char)(code_point >> 16), table2);
216 else /* if (dim == 4) */
219 = get_ccs_octet_table (table1, ccs, (unsigned char)(code_point >> 24));
221 = get_ccs_octet_table (table2, ccs, (unsigned char)(code_point >> 16));
223 = get_ccs_octet_table (table3, ccs, (unsigned char)(code_point >> 8));
225 table4 = put_ccs_octet_table (table4, ccs,
226 (unsigned char)code_point, character);
227 table3 = put_ccs_octet_table (table3, ccs,
228 (unsigned char)(code_point >> 8), table4);
229 table2 = put_ccs_octet_table (table2, ccs,
230 (unsigned char)(code_point >> 16), table3);
231 XCHARSET_DECODING_TABLE (ccs)
232 = put_ccs_octet_table (table1, ccs,
233 (unsigned char)(code_point >> 24), table2);
236 Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
237 int dim = XCHARSET_DIMENSION (ccs);
238 int byte_offset = XCHARSET_BYTE_OFFSET (ccs);
241 int ccs_len = XVECTOR_LENGTH (v);
246 i = ((code_point >> (8 * dim)) & 255) - byte_offset;
247 nv = XVECTOR_DATA(v)[i];
252 if (EQ (nv, character))
255 nv = (XVECTOR_DATA(v)[i] = make_vector (ccs_len, Qnil));
262 XVECTOR_DATA(v)[i] = character;
267 put_char_ccs_code_point (Lisp_Object character,
268 Lisp_Object ccs, Lisp_Object value)
270 if ( !( EQ (XCHARSET_NAME (ccs), Qrep_ucs)
271 && INTP (value) && (XINT (value) < 0xF0000)
272 && XCHAR (character) == XINT (value) )
275 Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
279 { /* obsolete representation: value must be a list of bytes */
280 Lisp_Object ret = Fcar (value);
284 signal_simple_error ("Invalid value for coded-charset", value);
285 code_point = XINT (ret);
286 if (XCHARSET_GRAPHIC (ccs) == 1)
294 signal_simple_error ("Invalid value for coded-charset",
298 signal_simple_error ("Invalid value for coded-charset",
301 if (XCHARSET_GRAPHIC (ccs) == 1)
303 code_point = (code_point << 8) | j;
306 value = make_int (code_point);
308 else if (INTP (value))
310 code_point = XINT (value);
311 if (XCHARSET_GRAPHIC (ccs) == 1)
313 code_point &= 0x7F7F7F7F;
314 value = make_int (code_point);
318 signal_simple_error ("Invalid value for coded-charset", value);
322 Lisp_Object cpos = Fget_char_attribute (character, ccs, Qnil);
325 decoding_table_remove_char (ccs, XINT (cpos));
328 decoding_table_put_char (ccs, code_point, character);
334 remove_char_ccs (Lisp_Object character, Lisp_Object ccs)
336 Lisp_Object decoding_table = XCHARSET_DECODING_TABLE (ccs);
337 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
339 if (VECTORP (decoding_table))
341 Lisp_Object cpos = Fget_char_attribute (character, ccs, Qnil);
345 decoding_table_remove_char (ccs, XINT (cpos));
348 if (CHAR_TABLEP (encoding_table))
350 put_char_id_table (XCHAR_TABLE(encoding_table), character, Qunbound);
358 int leading_code_private_11;
361 Lisp_Object Qcharsetp;
363 /* Qdoc_string, Qdimension, Qchars defined in general.c */
364 Lisp_Object Qregistry, Qfinal, Qgraphic;
365 Lisp_Object Qdirection;
366 Lisp_Object Qreverse_direction_charset;
367 Lisp_Object Qleading_byte;
368 Lisp_Object Qshort_name, Qlong_name;
371 Lisp_Object Qto_iso_ir;
372 Lisp_Object Qpartial;
373 Lisp_Object Qmin_code, Qmax_code, Qcode_offset;
374 Lisp_Object Qmother, Qconversion, Q94x60, Q94x94x60, Qbig5_1, Qbig5_2;
391 /* Qrep_jis_x0208_1978, */
409 Qvietnamese_viscii_lower,
410 Qvietnamese_viscii_upper,
420 Lisp_Object Ql2r, Qr2l;
422 Lisp_Object Vcharset_hash_table;
424 /* Composite characters are characters constructed by overstriking two
425 or more regular characters.
427 1) The old Mule implementation involves storing composite characters
428 in a buffer as a tag followed by all of the actual characters
429 used to make up the composite character. I think this is a bad
430 idea; it greatly complicates code that wants to handle strings
431 one character at a time because it has to deal with the possibility
432 of great big ungainly characters. It's much more reasonable to
433 simply store an index into a table of composite characters.
435 2) The current implementation only allows for 16,384 separate
436 composite characters over the lifetime of the XEmacs process.
437 This could become a potential problem if the user
438 edited lots of different files that use composite characters.
439 Due to FSF bogosity, increasing the number of allowable
440 composite characters under Mule would decrease the number
441 of possible faces that can exist. Mule already has shrunk
442 this to 2048, and further shrinkage would become uncomfortable.
443 No such problems exist in XEmacs.
445 Composite characters could be represented as 0x80 C1 C2 C3,
446 where each C[1-3] is in the range 0xA0 - 0xFF. This allows
447 for slightly under 2^20 (one million) composite characters
448 over the XEmacs process lifetime, and you only need to
449 increase the size of a Mule character from 19 to 21 bits.
450 Or you could use 0x80 C1 C2 C3 C4, allowing for about
451 85 million (slightly over 2^26) composite characters. */
454 /************************************************************************/
455 /* Basic Emchar functions */
456 /************************************************************************/
458 /* Convert a non-ASCII Mule character C into a one-character Mule-encoded
459 string in STR. Returns the number of bytes stored.
460 Do not call this directly. Use the macro set_charptr_emchar() instead.
464 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
479 else if ( c <= 0x7ff )
481 *p++ = (c >> 6) | 0xc0;
482 *p++ = (c & 0x3f) | 0x80;
484 else if ( c <= 0xffff )
486 *p++ = (c >> 12) | 0xe0;
487 *p++ = ((c >> 6) & 0x3f) | 0x80;
488 *p++ = (c & 0x3f) | 0x80;
490 else if ( c <= 0x1fffff )
492 *p++ = (c >> 18) | 0xf0;
493 *p++ = ((c >> 12) & 0x3f) | 0x80;
494 *p++ = ((c >> 6) & 0x3f) | 0x80;
495 *p++ = (c & 0x3f) | 0x80;
497 else if ( c <= 0x3ffffff )
499 *p++ = (c >> 24) | 0xf8;
500 *p++ = ((c >> 18) & 0x3f) | 0x80;
501 *p++ = ((c >> 12) & 0x3f) | 0x80;
502 *p++ = ((c >> 6) & 0x3f) | 0x80;
503 *p++ = (c & 0x3f) | 0x80;
507 *p++ = (c >> 30) | 0xfc;
508 *p++ = ((c >> 24) & 0x3f) | 0x80;
509 *p++ = ((c >> 18) & 0x3f) | 0x80;
510 *p++ = ((c >> 12) & 0x3f) | 0x80;
511 *p++ = ((c >> 6) & 0x3f) | 0x80;
512 *p++ = (c & 0x3f) | 0x80;
515 BREAKUP_CHAR (c, charset, c1, c2);
516 lb = CHAR_LEADING_BYTE (c);
517 if (LEADING_BYTE_PRIVATE_P (lb))
518 *p++ = PRIVATE_LEADING_BYTE_PREFIX (lb);
520 if (EQ (charset, Vcharset_control_1))
529 /* Return the first character from a Mule-encoded string in STR,
530 assuming it's non-ASCII. Do not call this directly.
531 Use the macro charptr_emchar() instead. */
534 non_ascii_charptr_emchar (const Bufbyte *str)
547 else if ( b >= 0xf8 )
552 else if ( b >= 0xf0 )
557 else if ( b >= 0xe0 )
562 else if ( b >= 0xc0 )
572 for( ; len > 0; len-- )
575 ch = ( ch << 6 ) | ( b & 0x3f );
579 Bufbyte i0 = *str, i1, i2 = 0;
582 if (i0 == LEADING_BYTE_CONTROL_1)
583 return (Emchar) (*++str - 0x20);
585 if (LEADING_BYTE_PREFIX_P (i0))
590 charset = CHARSET_BY_LEADING_BYTE (i0);
591 if (XCHARSET_DIMENSION (charset) == 2)
594 return MAKE_CHAR (charset, i1, i2);
598 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
599 Do not call this directly. Use the macro valid_char_p() instead. */
603 non_ascii_valid_char_p (Emchar ch)
607 /* Must have only lowest 19 bits set */
611 f1 = CHAR_FIELD1 (ch);
612 f2 = CHAR_FIELD2 (ch);
613 f3 = CHAR_FIELD3 (ch);
619 if (f2 < MIN_CHAR_FIELD2_OFFICIAL ||
620 (f2 > MAX_CHAR_FIELD2_OFFICIAL && f2 < MIN_CHAR_FIELD2_PRIVATE) ||
621 f2 > MAX_CHAR_FIELD2_PRIVATE)
626 if (f3 != 0x20 && f3 != 0x7F && !(f2 >= MIN_CHAR_FIELD2_PRIVATE &&
627 f2 <= MAX_CHAR_FIELD2_PRIVATE))
631 NOTE: This takes advantage of the fact that
632 FIELD2_TO_OFFICIAL_LEADING_BYTE and
633 FIELD2_TO_PRIVATE_LEADING_BYTE are the same.
635 charset = CHARSET_BY_LEADING_BYTE (f2 + FIELD2_TO_OFFICIAL_LEADING_BYTE);
636 if (EQ (charset, Qnil))
638 return (XCHARSET_CHARS (charset) == 96);
644 if (f1 < MIN_CHAR_FIELD1_OFFICIAL ||
645 (f1 > MAX_CHAR_FIELD1_OFFICIAL && f1 < MIN_CHAR_FIELD1_PRIVATE) ||
646 f1 > MAX_CHAR_FIELD1_PRIVATE)
648 if (f2 < 0x20 || f3 < 0x20)
651 #ifdef ENABLE_COMPOSITE_CHARS
652 if (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE == LEADING_BYTE_COMPOSITE)
654 if (UNBOUNDP (Fgethash (make_int (ch),
655 Vcomposite_char_char2string_hash_table,
660 #endif /* ENABLE_COMPOSITE_CHARS */
662 if (f2 != 0x20 && f2 != 0x7F && f3 != 0x20 && f3 != 0x7F
663 && !(f1 >= MIN_CHAR_FIELD1_PRIVATE && f1 <= MAX_CHAR_FIELD1_PRIVATE))
666 if (f1 <= MAX_CHAR_FIELD1_OFFICIAL)
668 CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE);
671 CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_PRIVATE_LEADING_BYTE);
673 if (EQ (charset, Qnil))
675 return (XCHARSET_CHARS (charset) == 96);
681 /************************************************************************/
682 /* Basic string functions */
683 /************************************************************************/
685 /* Copy the character pointed to by SRC into DST. Do not call this
686 directly. Use the macro charptr_copy_char() instead.
687 Return the number of bytes copied. */
690 non_ascii_charptr_copy_char (const Bufbyte *src, Bufbyte *dst)
692 unsigned int bytes = REP_BYTES_BY_FIRST_BYTE (*src);
694 for (i = bytes; i; i--, dst++, src++)
700 /************************************************************************/
701 /* streams of Emchars */
702 /************************************************************************/
704 /* Treat a stream as a stream of Emchar's rather than a stream of bytes.
705 The functions below are not meant to be called directly; use
706 the macros in insdel.h. */
709 Lstream_get_emchar_1 (Lstream *stream, int ch)
711 Bufbyte str[MAX_EMCHAR_LEN];
712 Bufbyte *strptr = str;
715 str[0] = (Bufbyte) ch;
717 for (bytes = REP_BYTES_BY_FIRST_BYTE (ch) - 1; bytes; bytes--)
719 int c = Lstream_getc (stream);
720 bufpos_checking_assert (c >= 0);
721 *++strptr = (Bufbyte) c;
723 return charptr_emchar (str);
727 Lstream_fput_emchar (Lstream *stream, Emchar ch)
729 Bufbyte str[MAX_EMCHAR_LEN];
730 Bytecount len = set_charptr_emchar (str, ch);
731 return Lstream_write (stream, str, len);
735 Lstream_funget_emchar (Lstream *stream, Emchar ch)
737 Bufbyte str[MAX_EMCHAR_LEN];
738 Bytecount len = set_charptr_emchar (str, ch);
739 Lstream_unread (stream, str, len);
743 /************************************************************************/
745 /************************************************************************/
748 mark_charset (Lisp_Object obj)
750 Lisp_Charset *cs = XCHARSET (obj);
752 mark_object (cs->short_name);
753 mark_object (cs->long_name);
754 mark_object (cs->doc_string);
755 mark_object (cs->registry);
756 mark_object (cs->ccl_program);
758 mark_object (cs->decoding_table);
759 mark_object (cs->mother);
765 print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
767 Lisp_Charset *cs = XCHARSET (obj);
771 error ("printing unreadable object #<charset %s 0x%x>",
772 string_data (XSYMBOL (CHARSET_NAME (cs))->name),
775 write_c_string ("#<charset ", printcharfun);
776 print_internal (CHARSET_NAME (cs), printcharfun, 0);
777 write_c_string (" ", printcharfun);
778 print_internal (CHARSET_SHORT_NAME (cs), printcharfun, 1);
779 write_c_string (" ", printcharfun);
780 print_internal (CHARSET_LONG_NAME (cs), printcharfun, 1);
781 write_c_string (" ", printcharfun);
782 print_internal (CHARSET_DOC_STRING (cs), printcharfun, 1);
783 sprintf (buf, " %d^%d %s cols=%d g%d final='%c' reg=",
785 CHARSET_DIMENSION (cs),
786 CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? "l2r" : "r2l",
787 CHARSET_COLUMNS (cs),
788 CHARSET_GRAPHIC (cs),
790 write_c_string (buf, printcharfun);
791 print_internal (CHARSET_REGISTRY (cs), printcharfun, 0);
792 sprintf (buf, " 0x%x>", cs->header.uid);
793 write_c_string (buf, printcharfun);
796 static const struct lrecord_description charset_description[] = {
797 { XD_LISP_OBJECT, offsetof (Lisp_Charset, name) },
798 { XD_LISP_OBJECT, offsetof (Lisp_Charset, doc_string) },
799 { XD_LISP_OBJECT, offsetof (Lisp_Charset, registry) },
800 { XD_LISP_OBJECT, offsetof (Lisp_Charset, short_name) },
801 { XD_LISP_OBJECT, offsetof (Lisp_Charset, long_name) },
802 { XD_LISP_OBJECT, offsetof (Lisp_Charset, reverse_direction_charset) },
803 { XD_LISP_OBJECT, offsetof (Lisp_Charset, ccl_program) },
805 { XD_LISP_OBJECT, offsetof (Lisp_Charset, decoding_table) },
806 { XD_LISP_OBJECT, offsetof (Lisp_Charset, mother) },
811 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
812 mark_charset, print_charset, 0, 0, 0,
816 /* Make a new charset. */
817 /* #### SJT Should generic properties be allowed? */
819 make_charset (Charset_ID id, Lisp_Object name,
820 unsigned short chars, unsigned char dimension,
821 unsigned char columns, unsigned char graphic,
822 Bufbyte final, unsigned char direction, Lisp_Object short_name,
823 Lisp_Object long_name, Lisp_Object doc,
826 Lisp_Object decoding_table,
827 Emchar min_code, Emchar max_code,
828 Emchar code_offset, unsigned char byte_offset,
829 Lisp_Object mother, unsigned char conversion,
833 Lisp_Charset *cs = alloc_lcrecord_type (Lisp_Charset, &lrecord_charset);
837 XSETCHARSET (obj, cs);
839 CHARSET_ID (cs) = id;
840 CHARSET_NAME (cs) = name;
841 CHARSET_SHORT_NAME (cs) = short_name;
842 CHARSET_LONG_NAME (cs) = long_name;
843 CHARSET_CHARS (cs) = chars;
844 CHARSET_DIMENSION (cs) = dimension;
845 CHARSET_DIRECTION (cs) = direction;
846 CHARSET_COLUMNS (cs) = columns;
847 CHARSET_GRAPHIC (cs) = graphic;
848 CHARSET_FINAL (cs) = final;
849 CHARSET_DOC_STRING (cs) = doc;
850 CHARSET_REGISTRY (cs) = reg;
851 CHARSET_CCL_PROGRAM (cs) = Qnil;
852 CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
854 CHARSET_ISO_IR (cs) = iso_ir;
855 CHARSET_DECODING_TABLE(cs) = Qunbound;
856 CHARSET_MIN_CODE (cs) = min_code;
857 CHARSET_MAX_CODE (cs) = max_code;
858 CHARSET_CODE_OFFSET (cs) = code_offset;
859 CHARSET_BYTE_OFFSET (cs) = byte_offset;
860 CHARSET_MOTHER (cs) = mother;
861 CHARSET_CONVERSION (cs) = conversion;
865 if (id == LEADING_BYTE_ASCII)
866 CHARSET_REP_BYTES (cs) = 1;
868 CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
870 CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
875 /* some charsets do not have final characters. This includes
876 ASCII, Control-1, Composite, and the two faux private
878 unsigned char iso2022_type
879 = (dimension == 1 ? 0 : 2) + (chars == 94 ? 0 : 1);
881 if ( ( !partial ) && ( code_offset == 0 ) )
883 assert (NILP (chlook->charset_by_attributes[iso2022_type][final]));
884 chlook->charset_by_attributes[iso2022_type][final] = obj;
888 (chlook->charset_by_attributes[iso2022_type][final][direction]));
889 chlook->charset_by_attributes[iso2022_type][final][direction] = obj;
893 assert (NILP (chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE]));
894 chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
896 /* Some charsets are "faux" and don't have names or really exist at
897 all except in the leading-byte table. */
899 Fputhash (name, obj, Vcharset_hash_table);
904 get_unallocated_leading_byte (int dimension)
909 if (chlook->next_allocated_leading_byte > MAX_LEADING_BYTE_PRIVATE)
912 lb = chlook->next_allocated_leading_byte++;
916 if (chlook->next_allocated_1_byte_leading_byte >
917 MAX_LEADING_BYTE_PRIVATE_1)
920 lb = chlook->next_allocated_1_byte_leading_byte++;
924 /* awfully fragile, but correct */
925 #if MAX_LEADING_BYTE_PRIVATE_2 == 255
926 if (chlook->next_allocated_2_byte_leading_byte == 0)
928 if (chlook->next_allocated_2_byte_leading_byte >
929 MAX_LEADING_BYTE_PRIVATE_2)
933 lb = chlook->next_allocated_2_byte_leading_byte++;
939 ("No more character sets free for this dimension",
940 make_int (dimension));
946 /* Number of Big5 characters which have the same code in 1st byte. */
948 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
951 decode_ccs_conversion (int conv_type, int code_point)
953 if ( conv_type == CONVERSION_IDENTICAL )
957 if ( conv_type == CONVERSION_94x60 )
959 int row = code_point >> 8;
960 int cell = code_point & 255;
964 else if (row < 16 + 32 + 30)
965 return (row - (16 + 32)) * 94 + cell - 33;
966 else if (row < 18 + 32 + 30)
968 else if (row < 18 + 32 + 60)
969 return (row - (18 + 32)) * 94 + cell - 33;
971 else if ( conv_type == CONVERSION_94x94x60 )
973 int plane = code_point >> 16;
974 int row = (code_point >> 8) & 255;
975 int cell = code_point & 255;
979 else if (row < 16 + 32 + 30)
981 (plane - 33) * 94 * 60
982 + (row - (16 + 32)) * 94
984 else if (row < 18 + 32 + 30)
986 else if (row < 18 + 32 + 60)
988 (plane - 33) * 94 * 60
989 + (row - (18 + 32)) * 94
992 else if ( conv_type == CONVERSION_BIG5_1 )
995 = (((code_point >> 8) & 0x7F) - 33) * 94
996 + (( code_point & 0x7F) - 33);
997 unsigned char b1 = I / (0xFF - 0xA1 + 0x7F - 0x40) + 0xA1;
998 unsigned char b2 = I % (0xFF - 0xA1 + 0x7F - 0x40);
1000 b2 += b2 < 0x3F ? 0x40 : 0x62;
1001 return (b1 << 8) | b2;
1003 else if ( conv_type == CONVERSION_BIG5_2 )
1006 = (((code_point >> 8) & 0x7F) - 33) * 94
1007 + (( code_point & 0x7F) - 33)
1008 + BIG5_SAME_ROW * (0xC9 - 0xA1);
1009 unsigned char b1 = I / (0xFF - 0xA1 + 0x7F - 0x40) + 0xA1;
1010 unsigned char b2 = I % (0xFF - 0xA1 + 0x7F - 0x40);
1012 b2 += b2 < 0x3F ? 0x40 : 0x62;
1013 return (b1 << 8) | b2;
1019 decode_defined_char (Lisp_Object ccs, int code_point, int without_inheritance)
1021 int dim = XCHARSET_DIMENSION (ccs);
1022 Lisp_Object decoding_table = XCHARSET_DECODING_TABLE (ccs);
1023 Emchar char_id = -1;
1030 = get_ccs_octet_table (decoding_table, ccs,
1031 (code_point >> (dim * 8)) & 255);
1033 if (CHARP (decoding_table))
1034 return XCHAR (decoding_table);
1036 if (EQ (decoding_table, Qunloaded))
1038 char_id = load_char_decoding_entry_maybe (ccs, code_point);
1040 #endif /* HAVE_CHISE */
1043 else if ( !without_inheritance
1044 && CHARSETP (mother = XCHARSET_MOTHER (ccs)) )
1047 = decode_ccs_conversion (XCHARSET_CONVERSION (ccs), code_point);
1051 code += XCHARSET_CODE_OFFSET(ccs);
1052 if ( EQ (mother, Vcharset_ucs) )
1053 return DECODE_CHAR (mother, code, without_inheritance);
1055 return decode_defined_char (mother, code,
1056 without_inheritance);
1063 decode_builtin_char (Lisp_Object charset, int code_point)
1065 Lisp_Object mother = XCHARSET_MOTHER (charset);
1068 if ( XCHARSET_MAX_CODE (charset) > 0 )
1070 if ( CHARSETP (mother) )
1073 = decode_ccs_conversion (XCHARSET_CONVERSION (charset),
1078 decode_builtin_char (mother,
1079 code + XCHARSET_CODE_OFFSET(charset));
1086 = (XCHARSET_DIMENSION (charset) == 1
1088 code_point - XCHARSET_BYTE_OFFSET (charset)
1090 ((code_point >> 8) - XCHARSET_BYTE_OFFSET (charset))
1091 * XCHARSET_CHARS (charset)
1092 + (code_point & 0xFF) - XCHARSET_BYTE_OFFSET (charset))
1093 + XCHARSET_CODE_OFFSET (charset);
1094 if ((cid < XCHARSET_MIN_CODE (charset))
1095 || (XCHARSET_MAX_CODE (charset) < cid))
1100 else if ((final = XCHARSET_FINAL (charset)) >= '0')
1102 if (XCHARSET_DIMENSION (charset) == 1)
1104 switch (XCHARSET_CHARS (charset))
1108 + (final - '0') * 94 + ((code_point & 0x7F) - 33);
1111 + (final - '0') * 96 + ((code_point & 0x7F) - 32);
1119 switch (XCHARSET_CHARS (charset))
1122 return MIN_CHAR_94x94
1123 + (final - '0') * 94 * 94
1124 + (((code_point >> 8) & 0x7F) - 33) * 94
1125 + ((code_point & 0x7F) - 33);
1127 return MIN_CHAR_96x96
1128 + (final - '0') * 96 * 96
1129 + (((code_point >> 8) & 0x7F) - 32) * 96
1130 + ((code_point & 0x7F) - 32);
1142 charset_code_point (Lisp_Object charset, Emchar ch, int defined_only)
1144 Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (charset);
1147 if ( CHAR_TABLEP (encoding_table)
1148 && INTP (ret = get_char_id_table (XCHAR_TABLE(encoding_table),
1153 Lisp_Object mother = XCHARSET_MOTHER (charset);
1154 int min = XCHARSET_MIN_CODE (charset);
1155 int max = XCHARSET_MAX_CODE (charset);
1158 if ( CHARSETP (mother) )
1160 if (XCHARSET_FINAL (charset) >= '0')
1161 code = charset_code_point (mother, ch, 1);
1163 code = charset_code_point (mother, ch, defined_only);
1165 else if (defined_only)
1167 else if ( ((max == 0) && CHARSETP (mother)
1168 && (XCHARSET_FINAL (charset) == 0))
1169 || ((min <= ch) && (ch <= max)) )
1171 if ( ((max == 0) && CHARSETP (mother) && (code >= 0))
1172 || ((min <= code) && (code <= max)) )
1174 int d = code - XCHARSET_CODE_OFFSET (charset);
1176 if ( XCHARSET_CONVERSION (charset) == CONVERSION_IDENTICAL )
1178 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94 )
1180 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_96 )
1182 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x60 )
1185 int cell = d % 94 + 33;
1191 return (row << 8) | cell;
1193 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_BIG5_1 )
1195 int B1 = d >> 8, B2 = d & 0xFF;
1197 = (B1 - 0xA1) * BIG5_SAME_ROW + B2
1198 - (B2 < 0x7F ? 0x40 : 0x62);
1202 return ((I / 94 + 33) << 8) | (I % 94 + 33);
1205 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_BIG5_2 )
1207 int B1 = d >> 8, B2 = d & 0xFF;
1209 = (B1 - 0xA1) * BIG5_SAME_ROW + B2
1210 - (B2 < 0x7F ? 0x40 : 0x62);
1214 I -= (BIG5_SAME_ROW) * (0xC9 - 0xA1);
1215 return ((I / 94 + 33) << 8) | (I % 94 + 33);
1218 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94 )
1219 return ((d / 94 + 33) << 8) | (d % 94 + 33);
1220 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_96x96 )
1221 return ((d / 96 + 32) << 8) | (d % 96 + 32);
1222 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94x60 )
1224 int plane = d / (94 * 60) + 33;
1225 int row = (d % (94 * 60)) / 94;
1226 int cell = d % 94 + 33;
1232 return (plane << 16) | (row << 8) | cell;
1234 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94x94 )
1236 ( (d / (94 * 94) + 33) << 16)
1237 | ((d / 94 % 94 + 33) << 8)
1239 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_96x96x96 )
1241 ( (d / (96 * 96) + 32) << 16)
1242 | ((d / 96 % 96 + 32) << 8)
1244 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94x94x94 )
1246 ( (d / (94 * 94 * 94) + 33) << 24)
1247 | ((d / (94 * 94) % 94 + 33) << 16)
1248 | ((d / 94 % 94 + 33) << 8)
1250 else if ( XCHARSET_CONVERSION (charset) == CONVERSION_96x96x96x96 )
1252 ( (d / (96 * 96 * 96) + 32) << 24)
1253 | ((d / (96 * 96) % 96 + 32) << 16)
1254 | ((d / 96 % 96 + 32) << 8)
1258 printf ("Unknown CCS-conversion %d is specified!",
1259 XCHARSET_CONVERSION (charset));
1263 else if (defined_only)
1265 else if ( ( XCHARSET_FINAL (charset) >= '0' ) &&
1266 ( XCHARSET_MIN_CODE (charset) == 0 )
1268 (XCHARSET_CODE_OFFSET (charset) == 0) ||
1269 (XCHARSET_CODE_OFFSET (charset)
1270 == XCHARSET_MIN_CODE (charset))
1275 if (XCHARSET_DIMENSION (charset) == 1)
1277 if (XCHARSET_CHARS (charset) == 94)
1279 if (((d = ch - (MIN_CHAR_94
1280 + (XCHARSET_FINAL (charset) - '0') * 94))
1285 else if (XCHARSET_CHARS (charset) == 96)
1287 if (((d = ch - (MIN_CHAR_96
1288 + (XCHARSET_FINAL (charset) - '0') * 96))
1296 else if (XCHARSET_DIMENSION (charset) == 2)
1298 if (XCHARSET_CHARS (charset) == 94)
1300 if (((d = ch - (MIN_CHAR_94x94
1302 (XCHARSET_FINAL (charset) - '0') * 94 * 94))
1305 return (((d / 94) + 33) << 8) | (d % 94 + 33);
1307 else if (XCHARSET_CHARS (charset) == 96)
1309 if (((d = ch - (MIN_CHAR_96x96
1311 (XCHARSET_FINAL (charset) - '0') * 96 * 96))
1314 return (((d / 96) + 32) << 8) | (d % 96 + 32);
1325 encode_char_2 (Emchar ch, Lisp_Object* charset)
1327 Lisp_Object charsets = Vdefault_coded_charset_priority_list;
1330 while (!NILP (charsets))
1332 *charset = Ffind_charset (Fcar (charsets));
1333 if ( !NILP (*charset)
1334 && (XCHARSET_DIMENSION (*charset) <= 2) )
1336 code_point = charset_code_point (*charset, ch, 0);
1337 if (code_point >= 0)
1340 if ( !NILP (Vdisplay_coded_charset_priority_use_inheritance) &&
1341 NILP (Vdisplay_coded_charset_priority_use_hierarchy_order) )
1343 code_point = encode_char_2_search_children (ch, charset);
1344 if (code_point >= 0)
1348 charsets = Fcdr (charsets);
1351 if ( !NILP (Vdisplay_coded_charset_priority_use_inheritance) &&
1352 !NILP (Vdisplay_coded_charset_priority_use_hierarchy_order) )
1354 charsets = Vdefault_coded_charset_priority_list;
1355 while (!NILP (charsets))
1357 *charset = Ffind_charset (Fcar (charsets));
1358 if ( !NILP (*charset)
1359 && (XCHARSET_DIMENSION (*charset) <= 2) )
1361 code_point = encode_char_2_search_children (ch, charset);
1362 if (code_point >= 0)
1365 charsets = Fcdr (charsets);
1369 /* otherwise --- maybe for bootstrap */
1370 return encode_builtin_char_1 (ch, charset);
1374 encode_builtin_char_1 (Emchar c, Lisp_Object* charset)
1376 if (c <= MAX_CHAR_BASIC_LATIN)
1378 *charset = Vcharset_ascii;
1383 *charset = Vcharset_control_1;
1388 *charset = Vcharset_latin_iso8859_1;
1392 else if ((MIN_CHAR_HEBREW <= c) && (c <= MAX_CHAR_HEBREW))
1394 *charset = Vcharset_hebrew_iso8859_8;
1395 return c - MIN_CHAR_HEBREW + 0x20;
1398 else if ((MIN_CHAR_THAI <= c) && (c <= MAX_CHAR_THAI))
1400 *charset = Vcharset_thai_tis620;
1401 return c - MIN_CHAR_THAI + 0x20;
1404 else if ((MIN_CHAR_HALFWIDTH_KATAKANA <= c)
1405 && (c <= MAX_CHAR_HALFWIDTH_KATAKANA))
1407 return list2 (Vcharset_katakana_jisx0201,
1408 make_int (c - MIN_CHAR_HALFWIDTH_KATAKANA + 33));
1411 else if (c <= MAX_CHAR_BMP)
1413 *charset = Vcharset_ucs_bmp;
1416 else if (c <= MAX_CHAR_SMP)
1418 *charset = Vcharset_ucs_smp;
1419 return c - MIN_CHAR_SMP;
1421 else if (c <= MAX_CHAR_SIP)
1423 *charset = Vcharset_ucs_sip;
1424 return c - MIN_CHAR_SIP;
1426 else if (c < MIN_CHAR_94)
1428 *charset = Vcharset_ucs;
1431 else if (c <= MAX_CHAR_94)
1433 *charset = CHARSET_BY_ATTRIBUTES (94, 1,
1434 ((c - MIN_CHAR_94) / 94) + '0',
1435 CHARSET_LEFT_TO_RIGHT);
1436 if (!NILP (*charset))
1437 return ((c - MIN_CHAR_94) % 94) + 33;
1440 *charset = Vcharset_ucs;
1444 else if (c <= MAX_CHAR_96)
1446 *charset = CHARSET_BY_ATTRIBUTES (96, 1,
1447 ((c - MIN_CHAR_96) / 96) + '0',
1448 CHARSET_LEFT_TO_RIGHT);
1449 if (!NILP (*charset))
1450 return ((c - MIN_CHAR_96) % 96) + 32;
1453 *charset = Vcharset_ucs;
1457 else if (c <= MAX_CHAR_94x94)
1460 = CHARSET_BY_ATTRIBUTES (94, 2,
1461 ((c - MIN_CHAR_94x94) / (94 * 94)) + '0',
1462 CHARSET_LEFT_TO_RIGHT);
1463 if (!NILP (*charset))
1464 return (((((c - MIN_CHAR_94x94) / 94) % 94) + 33) << 8)
1465 | (((c - MIN_CHAR_94x94) % 94) + 33);
1468 *charset = Vcharset_ucs;
1472 else if (c <= MAX_CHAR_96x96)
1475 = CHARSET_BY_ATTRIBUTES (96, 2,
1476 ((c - MIN_CHAR_96x96) / (96 * 96)) + '0',
1477 CHARSET_LEFT_TO_RIGHT);
1478 if (!NILP (*charset))
1479 return ((((c - MIN_CHAR_96x96) / 96) % 96) + 32) << 8
1480 | (((c - MIN_CHAR_96x96) % 96) + 32);
1483 *charset = Vcharset_ucs;
1489 *charset = Vcharset_ucs;
1494 Lisp_Object Vdefault_coded_charset_priority_list;
1495 Lisp_Object Vdisplay_coded_charset_priority_use_inheritance;
1496 Lisp_Object Vdisplay_coded_charset_priority_use_hierarchy_order;
1500 /************************************************************************/
1501 /* Basic charset Lisp functions */
1502 /************************************************************************/
1504 DEFUN ("charsetp", Fcharsetp, 1, 1, 0, /*
1505 Return non-nil if OBJECT is a charset.
1509 return CHARSETP (object) ? Qt : Qnil;
1512 DEFUN ("find-charset", Ffind_charset, 1, 1, 0, /*
1513 Retrieve the charset of the given name.
1514 If CHARSET-OR-NAME is a charset object, it is simply returned.
1515 Otherwise, CHARSET-OR-NAME should be a symbol. If there is no such charset,
1516 nil is returned. Otherwise the associated charset object is returned.
1520 if (CHARSETP (charset_or_name))
1521 return charset_or_name;
1523 CHECK_SYMBOL (charset_or_name);
1524 return Fgethash (charset_or_name, Vcharset_hash_table, Qnil);
1527 DEFUN ("get-charset", Fget_charset, 1, 1, 0, /*
1528 Retrieve the charset of the given name.
1529 Same as `find-charset' except an error is signalled if there is no such
1530 charset instead of returning nil.
1534 Lisp_Object charset = Ffind_charset (name);
1537 signal_simple_error ("No such charset", name);
1541 /* We store the charsets in hash tables with the names as the key and the
1542 actual charset object as the value. Occasionally we need to use them
1543 in a list format. These routines provide us with that. */
1544 struct charset_list_closure
1546 Lisp_Object *charset_list;
1550 add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
1551 void *charset_list_closure)
1553 /* This function can GC */
1554 struct charset_list_closure *chcl =
1555 (struct charset_list_closure*) charset_list_closure;
1556 Lisp_Object *charset_list = chcl->charset_list;
1558 *charset_list = Fcons (key /* XCHARSET_NAME (value) */, *charset_list);
1562 DEFUN ("charset-list", Fcharset_list, 0, 0, 0, /*
1563 Return a list of the names of all defined charsets.
1567 Lisp_Object charset_list = Qnil;
1568 struct gcpro gcpro1;
1569 struct charset_list_closure charset_list_closure;
1571 GCPRO1 (charset_list);
1572 charset_list_closure.charset_list = &charset_list;
1573 elisp_maphash (add_charset_to_list_mapper, Vcharset_hash_table,
1574 &charset_list_closure);
1577 return charset_list;
1580 DEFUN ("charset-name", Fcharset_name, 1, 1, 0, /*
1581 Return the name of charset CHARSET.
1585 return XCHARSET_NAME (Fget_charset (charset));
1588 /* #### SJT Should generic properties be allowed? */
1589 DEFUN ("make-charset", Fmake_charset, 3, 3, 0, /*
1590 Define a new character set.
1591 This function is for use with Mule support.
1592 NAME is a symbol, the name by which the character set is normally referred.
1593 DOC-STRING is a string describing the character set.
1594 PROPS is a property list, describing the specific nature of the
1595 character set. Recognized properties are:
1597 'short-name Short version of the charset name (ex: Latin-1)
1598 'long-name Long version of the charset name (ex: ISO8859-1 (Latin-1))
1599 'registry A regular expression matching the font registry field for
1601 'dimension Number of octets used to index a character in this charset.
1602 Either 1 or 2. Defaults to 1.
1603 If UTF-2000 feature is enabled, 3 or 4 are also available.
1604 'columns Number of columns used to display a character in this charset.
1605 Only used in TTY mode. (Under X, the actual width of a
1606 character can be derived from the font used to display the
1607 characters.) If unspecified, defaults to the dimension
1608 (this is almost always the correct value).
1609 'chars Number of characters in each dimension (94 or 96).
1610 Defaults to 94. Note that if the dimension is 2, the
1611 character set thus described is 94x94 or 96x96.
1612 If UTF-2000 feature is enabled, 128 or 256 are also available.
1613 'final Final byte of ISO 2022 escape sequence. Must be
1614 supplied. Each combination of (DIMENSION, CHARS) defines a
1615 separate namespace for final bytes. Note that ISO
1616 2022 restricts the final byte to the range
1617 0x30 - 0x7E if dimension == 1, and 0x30 - 0x5F if
1618 dimension == 2. Note also that final bytes in the range
1619 0x30 - 0x3F are reserved for user-defined (not official)
1621 'graphic 0 (use left half of font on output) or 1 (use right half
1622 of font on output). Defaults to 0. For example, for
1623 a font whose registry is ISO8859-1, the left half
1624 (octets 0x20 - 0x7F) is the `ascii' character set, while
1625 the right half (octets 0xA0 - 0xFF) is the `latin-1'
1626 character set. With 'graphic set to 0, the octets
1627 will have their high bit cleared; with it set to 1,
1628 the octets will have their high bit set.
1629 'direction 'l2r (left-to-right) or 'r2l (right-to-left).
1631 'ccl-program A compiled CCL program used to convert a character in
1632 this charset into an index into the font. This is in
1633 addition to the 'graphic property. The CCL program
1634 is passed the octets of the character, with the high
1635 bit cleared and set depending upon whether the value
1636 of the 'graphic property is 0 or 1.
1637 'mother [UTF-2000 only] Base coded-charset.
1638 'code-min [UTF-2000 only] Minimum code-point of a base coded-charset.
1639 'code-max [UTF-2000 only] Maximum code-point of a base coded-charset.
1640 'code-offset [UTF-2000 only] Offset for a code-point of a base
1642 'conversion [UTF-2000 only] Conversion for a code-point of a base
1643 coded-charset (94x60, 94x94x60, big5-1 or big5-2).
1644 'partial [UTF-2000 only] If t, specify as a partial coded-charset.
1646 (name, doc_string, props))
1648 int id = 0, dimension = 1, chars = 94, graphic = 0, final = 0, columns = -1;
1650 int direction = CHARSET_LEFT_TO_RIGHT;
1651 Lisp_Object registry = Qnil;
1652 Lisp_Object charset;
1653 Lisp_Object ccl_program = Qnil;
1654 Lisp_Object short_name = Qnil, long_name = Qnil;
1655 Lisp_Object mother = Qnil;
1657 int min_code = 0, max_code = 0, code_offset = 0;
1658 int byte_offset = -1;
1661 CHECK_SYMBOL (name);
1662 if (!NILP (doc_string))
1663 CHECK_STRING (doc_string);
1665 charset = Ffind_charset (name);
1666 if (!NILP (charset))
1667 signal_simple_error ("Cannot redefine existing charset", name);
1670 EXTERNAL_PROPERTY_LIST_LOOP_3 (keyword, value, props)
1672 if (EQ (keyword, Qshort_name))
1674 CHECK_STRING (value);
1678 else if (EQ (keyword, Qlong_name))
1680 CHECK_STRING (value);
1684 else if (EQ (keyword, Qiso_ir))
1688 iso_ir = XINT (value);
1694 else if (EQ (keyword, Qto_iso_ir))
1697 iso_ir = XINT (value);
1701 else if (EQ (keyword, Qdimension))
1704 dimension = XINT (value);
1705 if (dimension < 1 ||
1712 signal_simple_error ("Invalid value for 'dimension", value);
1715 else if (EQ (keyword, Qchars))
1718 chars = XINT (value);
1719 if (chars != 94 && chars != 96
1721 && chars != 128 && chars != 256
1724 signal_simple_error ("Invalid value for 'chars", value);
1727 else if (EQ (keyword, Qcolumns))
1730 columns = XINT (value);
1731 if (columns != 1 && columns != 2)
1732 signal_simple_error ("Invalid value for 'columns", value);
1735 else if (EQ (keyword, Qgraphic))
1738 graphic = XINT (value);
1746 signal_simple_error ("Invalid value for 'graphic", value);
1749 else if (EQ (keyword, Qregistry))
1751 CHECK_STRING (value);
1755 else if (EQ (keyword, Qdirection))
1757 if (EQ (value, Ql2r))
1758 direction = CHARSET_LEFT_TO_RIGHT;
1759 else if (EQ (value, Qr2l))
1760 direction = CHARSET_RIGHT_TO_LEFT;
1762 signal_simple_error ("Invalid value for 'direction", value);
1765 else if (EQ (keyword, Qfinal))
1767 CHECK_CHAR_COERCE_INT (value);
1768 final = XCHAR (value);
1769 if (final < '0' || final > '~')
1770 signal_simple_error ("Invalid value for 'final", value);
1774 else if (EQ (keyword, Qpartial))
1776 partial = !NILP (value);
1779 else if (EQ (keyword, Qmother))
1781 mother = Fget_charset (value);
1784 else if (EQ (keyword, Qmin_code))
1787 min_code = XUINT (value);
1790 else if (EQ (keyword, Qmax_code))
1793 max_code = XUINT (value);
1796 else if (EQ (keyword, Qcode_offset))
1799 code_offset = XUINT (value);
1802 else if (EQ (keyword, Qconversion))
1804 if (EQ (value, Q94x60))
1805 conversion = CONVERSION_94x60;
1806 else if (EQ (value, Q94x94x60))
1807 conversion = CONVERSION_94x94x60;
1808 else if (EQ (value, Qbig5_1))
1809 conversion = CONVERSION_BIG5_1;
1810 else if (EQ (value, Qbig5_2))
1811 conversion = CONVERSION_BIG5_2;
1813 signal_simple_error ("Unrecognized conversion", value);
1817 else if (EQ (keyword, Qccl_program))
1819 struct ccl_program test_ccl;
1821 if (setup_ccl_program (&test_ccl, value) < 0)
1822 signal_simple_error ("Invalid value for 'ccl-program", value);
1823 ccl_program = value;
1827 signal_simple_error ("Unrecognized property", keyword);
1833 error ("'final must be specified");
1835 if (dimension == 2 && final > 0x5F)
1837 ("Final must be in the range 0x30 - 0x5F for dimension == 2",
1840 if (!NILP (CHARSET_BY_ATTRIBUTES (chars, dimension, final,
1841 CHARSET_LEFT_TO_RIGHT)) ||
1842 !NILP (CHARSET_BY_ATTRIBUTES (chars, dimension, final,
1843 CHARSET_RIGHT_TO_LEFT)))
1845 ("Character set already defined for this DIMENSION/CHARS/FINAL combo");
1848 id = get_unallocated_leading_byte (dimension);
1850 if (NILP (doc_string))
1851 doc_string = build_string ("");
1853 if (NILP (registry))
1854 registry = build_string ("");
1856 if (NILP (short_name))
1857 XSETSTRING (short_name, XSYMBOL (name)->name);
1859 if (NILP (long_name))
1860 long_name = doc_string;
1863 columns = dimension;
1865 if (byte_offset < 0)
1869 else if (chars == 96)
1875 charset = make_charset (id, name, chars, dimension, columns, graphic,
1876 final, direction, short_name, long_name,
1877 doc_string, registry, iso_ir,
1878 Qnil, min_code, max_code, code_offset, byte_offset,
1879 mother, conversion, partial);
1880 if (!NILP (ccl_program))
1881 XCHARSET_CCL_PROGRAM (charset) = ccl_program;
1885 DEFUN ("make-reverse-direction-charset", Fmake_reverse_direction_charset,
1887 Make a charset equivalent to CHARSET but which goes in the opposite direction.
1888 NEW-NAME is the name of the new charset. Return the new charset.
1890 (charset, new_name))
1892 Lisp_Object new_charset = Qnil;
1893 int id, chars, dimension, columns, graphic, final;
1895 Lisp_Object registry, doc_string, short_name, long_name;
1898 charset = Fget_charset (charset);
1899 if (!NILP (XCHARSET_REVERSE_DIRECTION_CHARSET (charset)))
1900 signal_simple_error ("Charset already has reverse-direction charset",
1903 CHECK_SYMBOL (new_name);
1904 if (!NILP (Ffind_charset (new_name)))
1905 signal_simple_error ("Cannot redefine existing charset", new_name);
1907 cs = XCHARSET (charset);
1909 chars = CHARSET_CHARS (cs);
1910 dimension = CHARSET_DIMENSION (cs);
1911 columns = CHARSET_COLUMNS (cs);
1912 id = get_unallocated_leading_byte (dimension);
1914 graphic = CHARSET_GRAPHIC (cs);
1915 final = CHARSET_FINAL (cs);
1916 direction = CHARSET_RIGHT_TO_LEFT;
1917 if (CHARSET_DIRECTION (cs) == CHARSET_RIGHT_TO_LEFT)
1918 direction = CHARSET_LEFT_TO_RIGHT;
1919 doc_string = CHARSET_DOC_STRING (cs);
1920 short_name = CHARSET_SHORT_NAME (cs);
1921 long_name = CHARSET_LONG_NAME (cs);
1922 registry = CHARSET_REGISTRY (cs);
1924 new_charset = make_charset (id, new_name, chars, dimension, columns,
1925 graphic, final, direction, short_name, long_name,
1926 doc_string, registry,
1929 CHARSET_DECODING_TABLE(cs),
1930 CHARSET_MIN_CODE(cs),
1931 CHARSET_MAX_CODE(cs),
1932 CHARSET_CODE_OFFSET(cs),
1933 CHARSET_BYTE_OFFSET(cs),
1935 CHARSET_CONVERSION (cs)
1937 Qnil, 0, 0, 0, 0, Qnil, 0
1941 CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
1942 XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
1947 DEFUN ("define-charset-alias", Fdefine_charset_alias, 2, 2, 0, /*
1948 Define symbol ALIAS as an alias for CHARSET.
1952 CHECK_SYMBOL (alias);
1953 charset = Fget_charset (charset);
1954 return Fputhash (alias, charset, Vcharset_hash_table);
1957 /* #### Reverse direction charsets not yet implemented. */
1959 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
1961 Return the reverse-direction charset parallel to CHARSET, if any.
1962 This is the charset with the same properties (in particular, the same
1963 dimension, number of characters per dimension, and final byte) as
1964 CHARSET but whose characters are displayed in the opposite direction.
1968 charset = Fget_charset (charset);
1969 return XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
1973 DEFUN ("charset-from-attributes", Fcharset_from_attributes, 3, 4, 0, /*
1974 Return a charset with the given DIMENSION, CHARS, FINAL, and DIRECTION.
1975 If DIRECTION is omitted, both directions will be checked (left-to-right
1976 will be returned if character sets exist for both directions).
1978 (dimension, chars, final, direction))
1980 int dm, ch, fi, di = -1;
1981 Lisp_Object obj = Qnil;
1983 CHECK_INT (dimension);
1984 dm = XINT (dimension);
1985 if (dm < 1 || dm > 2)
1986 signal_simple_error ("Invalid value for DIMENSION", dimension);
1990 if (ch != 94 && ch != 96)
1991 signal_simple_error ("Invalid value for CHARS", chars);
1993 CHECK_CHAR_COERCE_INT (final);
1995 if (fi < '0' || fi > '~')
1996 signal_simple_error ("Invalid value for FINAL", final);
1998 if (EQ (direction, Ql2r))
1999 di = CHARSET_LEFT_TO_RIGHT;
2000 else if (EQ (direction, Qr2l))
2001 di = CHARSET_RIGHT_TO_LEFT;
2002 else if (!NILP (direction))
2003 signal_simple_error ("Invalid value for DIRECTION", direction);
2005 if (dm == 2 && fi > 0x5F)
2007 ("Final must be in the range 0x30 - 0x5F for dimension == 2", final);
2011 obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, CHARSET_LEFT_TO_RIGHT);
2013 obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, CHARSET_RIGHT_TO_LEFT);
2016 obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, di);
2019 return XCHARSET_NAME (obj);
2023 DEFUN ("charset-short-name", Fcharset_short_name, 1, 1, 0, /*
2024 Return short name of CHARSET.
2028 return XCHARSET_SHORT_NAME (Fget_charset (charset));
2031 DEFUN ("charset-long-name", Fcharset_long_name, 1, 1, 0, /*
2032 Return long name of CHARSET.
2036 return XCHARSET_LONG_NAME (Fget_charset (charset));
2039 DEFUN ("charset-description", Fcharset_description, 1, 1, 0, /*
2040 Return description of CHARSET.
2044 return XCHARSET_DOC_STRING (Fget_charset (charset));
2047 DEFUN ("charset-dimension", Fcharset_dimension, 1, 1, 0, /*
2048 Return dimension of CHARSET.
2052 return make_int (XCHARSET_DIMENSION (Fget_charset (charset)));
2055 DEFUN ("charset-property", Fcharset_property, 2, 2, 0, /*
2056 Return property PROP of CHARSET, a charset object or symbol naming a charset.
2057 Recognized properties are those listed in `make-charset', as well as
2058 'name and 'doc-string.
2064 charset = Fget_charset (charset);
2065 cs = XCHARSET (charset);
2067 CHECK_SYMBOL (prop);
2068 if (EQ (prop, Qname)) return CHARSET_NAME (cs);
2069 if (EQ (prop, Qshort_name)) return CHARSET_SHORT_NAME (cs);
2070 if (EQ (prop, Qlong_name)) return CHARSET_LONG_NAME (cs);
2071 if (EQ (prop, Qdoc_string)) return CHARSET_DOC_STRING (cs);
2072 if (EQ (prop, Qdimension)) return make_int (CHARSET_DIMENSION (cs));
2073 if (EQ (prop, Qcolumns)) return make_int (CHARSET_COLUMNS (cs));
2074 if (EQ (prop, Qgraphic)) return make_int (CHARSET_GRAPHIC (cs));
2075 if (EQ (prop, Qfinal)) return CHARSET_FINAL (cs) == 0 ?
2076 Qnil : make_char (CHARSET_FINAL (cs));
2077 if (EQ (prop, Qchars)) return make_int (CHARSET_CHARS (cs));
2078 if (EQ (prop, Qregistry)) return CHARSET_REGISTRY (cs);
2079 if (EQ (prop, Qccl_program)) return CHARSET_CCL_PROGRAM (cs);
2080 if (EQ (prop, Qdirection))
2081 return CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? Ql2r : Qr2l;
2082 if (EQ (prop, Qreverse_direction_charset))
2084 Lisp_Object obj = CHARSET_REVERSE_DIRECTION_CHARSET (cs);
2085 /* #### Is this translation OK? If so, error checking sufficient? */
2086 return CHARSETP (obj) ? XCHARSET_NAME (obj) : obj;
2089 if (EQ (prop, Qiso_ir))
2091 if ( CHARSET_ISO_IR (cs) > 0 )
2092 return make_int (CHARSET_ISO_IR (cs));
2096 if (EQ (prop, Qmother))
2097 return CHARSET_MOTHER (cs);
2098 if (EQ (prop, Qmin_code))
2099 return make_int (CHARSET_MIN_CODE (cs));
2100 if (EQ (prop, Qmax_code))
2101 return make_int (CHARSET_MAX_CODE (cs));
2103 signal_simple_error ("Unrecognized charset property name", prop);
2104 return Qnil; /* not reached */
2107 DEFUN ("charset-id", Fcharset_id, 1, 1, 0, /*
2108 Return charset identification number of CHARSET.
2112 return make_int(XCHARSET_LEADING_BYTE (Fget_charset (charset)));
2115 /* #### We need to figure out which properties we really want to
2118 DEFUN ("set-charset-ccl-program", Fset_charset_ccl_program, 2, 2, 0, /*
2119 Set the 'ccl-program property of CHARSET to CCL-PROGRAM.
2121 (charset, ccl_program))
2123 struct ccl_program test_ccl;
2125 charset = Fget_charset (charset);
2126 if (setup_ccl_program (&test_ccl, ccl_program) < 0)
2127 signal_simple_error ("Invalid ccl-program", ccl_program);
2128 XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2133 invalidate_charset_font_caches (Lisp_Object charset)
2135 /* Invalidate font cache entries for charset on all devices. */
2136 Lisp_Object devcons, concons, hash_table;
2137 DEVICE_LOOP_NO_BREAK (devcons, concons)
2139 struct device *d = XDEVICE (XCAR (devcons));
2140 hash_table = Fgethash (charset, d->charset_font_cache, Qunbound);
2141 if (!UNBOUNDP (hash_table))
2142 Fclrhash (hash_table);
2146 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
2147 Set the 'registry property of CHARSET to REGISTRY.
2149 (charset, registry))
2151 charset = Fget_charset (charset);
2152 CHECK_STRING (registry);
2153 XCHARSET_REGISTRY (charset) = registry;
2154 invalidate_charset_font_caches (charset);
2155 face_property_was_changed (Vdefault_face, Qfont, Qglobal);
2160 DEFUN ("charset-mapping-table", Fcharset_mapping_table, 1, 1, 0, /*
2161 Return mapping-table of CHARSET.
2165 return XCHARSET_DECODING_TABLE (Fget_charset (charset));
2168 DEFUN ("set-charset-mapping-table", Fset_charset_mapping_table, 2, 2, 0, /*
2169 Set mapping-table of CHARSET to TABLE.
2173 struct Lisp_Charset *cs;
2177 charset = Fget_charset (charset);
2178 cs = XCHARSET (charset);
2182 CHARSET_DECODING_TABLE(cs) = Qnil;
2185 else if (VECTORP (table))
2187 int ccs_len = CHARSET_BYTE_SIZE (cs);
2188 int ret = decoding_table_check_elements (table,
2189 CHARSET_DIMENSION (cs),
2194 signal_simple_error ("Too big table", table);
2196 signal_simple_error ("Invalid element is found", table);
2198 signal_simple_error ("Something wrong", table);
2200 CHARSET_DECODING_TABLE(cs) = Qnil;
2203 signal_error (Qwrong_type_argument,
2204 list2 (build_translated_string ("vector-or-nil-p"),
2207 byte_offset = CHARSET_BYTE_OFFSET (cs);
2208 switch (CHARSET_DIMENSION (cs))
2211 for (i = 0; i < XVECTOR_LENGTH (table); i++)
2213 Lisp_Object c = XVECTOR_DATA(table)[i];
2216 Fput_char_attribute (c, XCHARSET_NAME (charset),
2217 make_int (i + byte_offset));
2221 for (i = 0; i < XVECTOR_LENGTH (table); i++)
2223 Lisp_Object v = XVECTOR_DATA(table)[i];
2229 for (j = 0; j < XVECTOR_LENGTH (v); j++)
2231 Lisp_Object c = XVECTOR_DATA(v)[j];
2235 (c, XCHARSET_NAME (charset),
2236 make_int ( ( (i + byte_offset) << 8 )
2242 Fput_char_attribute (v, XCHARSET_NAME (charset),
2243 make_int (i + byte_offset));
2251 DEFUN ("save-charset-mapping-table", Fsave_charset_mapping_table, 1, 1, 0, /*
2252 Save mapping-table of CHARSET.
2256 struct Lisp_Charset *cs;
2257 int byte_min, byte_max;
2258 #ifdef HAVE_LIBCHISE
2260 #else /* HAVE_LIBCHISE */
2262 Lisp_Object db_file;
2263 #endif /* not HAVE_LIBCHISE */
2265 charset = Fget_charset (charset);
2266 cs = XCHARSET (charset);
2268 #ifdef HAVE_LIBCHISE
2269 if ( open_chise_data_source_maybe () )
2273 = chise_ds_get_ccs (default_chise_data_source,
2274 XSTRING_DATA (Fsymbol_name (XCHARSET_NAME(charset))));
2277 printf ("Can't open decoding-table %s\n",
2278 XSTRING_DATA (Fsymbol_name (XCHARSET_NAME(charset))));
2281 #else /* HAVE_LIBCHISE */
2282 db_file = char_attribute_system_db_file (CHARSET_NAME (cs),
2283 Qsystem_char_id, 1);
2284 db = Fopen_database (db_file, Qnil, Qnil, build_string ("w+"), Qnil);
2285 #endif /* not HAVE_LIBCHISE */
2287 byte_min = CHARSET_BYTE_OFFSET (cs);
2288 byte_max = byte_min + CHARSET_BYTE_SIZE (cs);
2289 switch (CHARSET_DIMENSION (cs))
2293 Lisp_Object table_c = XCHARSET_DECODING_TABLE (charset);
2296 for (cell = byte_min; cell < byte_max; cell++)
2298 Lisp_Object c = get_ccs_octet_table (table_c, charset, cell);
2302 #ifdef HAVE_LIBCHISE
2303 chise_ccs_set_decoded_char (dt_ccs, cell, XCHAR (c));
2304 #else /* HAVE_LIBCHISE */
2305 Fput_database (Fprin1_to_string (make_int (cell), Qnil),
2306 Fprin1_to_string (c, Qnil),
2308 #endif /* not HAVE_LIBCHISE */
2315 Lisp_Object table_r = XCHARSET_DECODING_TABLE (charset);
2318 for (row = byte_min; row < byte_max; row++)
2320 Lisp_Object table_c = get_ccs_octet_table (table_r, charset, row);
2323 for (cell = byte_min; cell < byte_max; cell++)
2325 Lisp_Object c = get_ccs_octet_table (table_c, charset, cell);
2329 #ifdef HAVE_LIBCHISE
2330 chise_ccs_set_decoded_char
2332 (row << 8) | cell, XCHAR (c));
2333 #else /* HAVE_LIBCHISE */
2334 Fput_database (Fprin1_to_string (make_int ((row << 8)
2337 Fprin1_to_string (c, Qnil),
2339 #endif /* not HAVE_LIBCHISE */
2347 Lisp_Object table_p = XCHARSET_DECODING_TABLE (charset);
2350 for (plane = byte_min; plane < byte_max; plane++)
2353 = get_ccs_octet_table (table_p, charset, plane);
2356 for (row = byte_min; row < byte_max; row++)
2359 = get_ccs_octet_table (table_r, charset, row);
2362 for (cell = byte_min; cell < byte_max; cell++)
2364 Lisp_Object c = get_ccs_octet_table (table_c, charset,
2369 #ifdef HAVE_LIBCHISE
2370 chise_ccs_set_decoded_char
2375 #else /* HAVE_LIBCHISE */
2376 Fput_database (Fprin1_to_string
2377 (make_int ((plane << 16)
2381 Fprin1_to_string (c, Qnil),
2383 #endif /* not HAVE_LIBCHISE */
2392 Lisp_Object table_g = XCHARSET_DECODING_TABLE (charset);
2395 for (group = byte_min; group < byte_max; group++)
2398 = get_ccs_octet_table (table_g, charset, group);
2401 for (plane = byte_min; plane < byte_max; plane++)
2404 = get_ccs_octet_table (table_p, charset, plane);
2407 for (row = byte_min; row < byte_max; row++)
2410 = get_ccs_octet_table (table_r, charset, row);
2413 for (cell = byte_min; cell < byte_max; cell++)
2416 = get_ccs_octet_table (table_c, charset, cell);
2420 #ifdef HAVE_LIBCHISE
2421 chise_ccs_set_decoded_char
2427 #else /* HAVE_LIBCHISE */
2428 Fput_database (Fprin1_to_string
2429 (make_int (( group << 24)
2434 Fprin1_to_string (c, Qnil),
2436 #endif /* not HAVE_LIBCHISE */
2444 #ifdef HAVE_LIBCHISE
2445 chise_ccs_sync (dt_ccs);
2447 #else /* HAVE_LIBCHISE */
2448 return Fclose_database (db);
2449 #endif /* not HAVE_LIBCHISE */
2452 DEFUN ("reset-charset-mapping-table", Freset_charset_mapping_table, 1, 1, 0, /*
2453 Reset mapping-table of CCS with database file.
2457 #ifdef HAVE_LIBCHISE
2458 CHISE_CCS chise_ccs;
2460 Lisp_Object db_file;
2463 ccs = Fget_charset (ccs);
2465 #ifdef HAVE_LIBCHISE
2466 if ( open_chise_data_source_maybe () )
2469 chise_ccs = chise_ds_get_ccs (default_chise_data_source,
2470 XSTRING_DATA (Fsymbol_name
2471 (XCHARSET_NAME(ccs))));
2472 if (chise_ccs == NULL)
2475 db_file = char_attribute_system_db_file (XCHARSET_NAME(ccs),
2476 Qsystem_char_id, 0);
2480 #ifdef HAVE_LIBCHISE
2481 chise_ccs_setup_db (chise_ccs, 0) == 0
2483 !NILP (Ffile_exists_p (db_file))
2487 XCHARSET_DECODING_TABLE(ccs) = Qunloaded;
2494 load_char_decoding_entry_maybe (Lisp_Object ccs, int code_point)
2496 #ifdef HAVE_LIBCHISE
2497 CHISE_Char_ID char_id;
2499 if ( open_chise_data_source_maybe () )
2503 = chise_ds_decode_char (default_chise_data_source,
2504 XSTRING_DATA(Fsymbol_name (XCHARSET_NAME(ccs))),
2507 decoding_table_put_char (ccs, code_point, make_char (char_id));
2509 decoding_table_put_char (ccs, code_point, Qnil);
2511 /* chise_ccst_close (dt_ccs); */
2513 #else /* HAVE_LIBCHISE */
2516 = char_attribute_system_db_file (XCHARSET_NAME(ccs), Qsystem_char_id,
2519 db = Fopen_database (db_file, Qnil, Qnil, build_string ("r"), Qnil);
2523 = Fget_database (Fprin1_to_string (make_int (code_point), Qnil),
2530 decoding_table_put_char (ccs, code_point, ret);
2531 Fclose_database (db);
2535 decoding_table_put_char (ccs, code_point, Qnil);
2536 Fclose_database (db);
2539 #endif /* not HAVE_LIBCHISE */
2542 #ifdef HAVE_LIBCHISE
2543 DEFUN ("save-charset-properties", Fsave_charset_properties, 1, 1, 0, /*
2544 Save properties of CHARSET.
2548 struct Lisp_Charset *cs;
2549 CHISE_Property property;
2551 unsigned char* feature_name;
2553 ccs = Fget_charset (charset);
2554 cs = XCHARSET (ccs);
2556 if ( open_chise_data_source_maybe () )
2559 if ( SYMBOLP (charset) && !EQ (charset, XCHARSET_NAME (ccs)) )
2561 property = chise_ds_get_property (default_chise_data_source,
2563 feature_name = XSTRING_DATA (Fsymbol_name (charset));
2564 chise_feature_set_property_value
2565 (chise_ds_get_feature (default_chise_data_source, feature_name),
2566 property, XSTRING_DATA (Fprin1_to_string (CHARSET_NAME (cs),
2568 chise_property_sync (property);
2570 charset = XCHARSET_NAME (ccs);
2571 feature_name = XSTRING_DATA (Fsymbol_name (charset));
2573 property = chise_ds_get_property (default_chise_data_source,
2575 chise_feature_set_property_value
2576 (chise_ds_get_feature (default_chise_data_source, feature_name),
2577 property, XSTRING_DATA (Fprin1_to_string
2578 (CHARSET_DOC_STRING (cs), Qnil)));
2579 chise_property_sync (property);
2581 property = chise_ds_get_property (default_chise_data_source, "type");
2582 chise_feature_set_property_value
2583 (chise_ds_get_feature (default_chise_data_source, feature_name),
2585 chise_property_sync (property);
2587 property = chise_ds_get_property (default_chise_data_source, "chars");
2588 chise_feature_set_property_value
2589 (chise_ds_get_feature (default_chise_data_source, feature_name),
2590 property, XSTRING_DATA (Fprin1_to_string (make_int
2591 (CHARSET_CHARS (cs)),
2593 chise_property_sync (property);
2595 property = chise_ds_get_property (default_chise_data_source, "dimension");
2596 chise_feature_set_property_value
2597 (chise_ds_get_feature (default_chise_data_source, feature_name),
2598 property, XSTRING_DATA (Fprin1_to_string (make_int
2599 (CHARSET_DIMENSION (cs)),
2601 chise_property_sync (property);
2603 if ( CHARSET_FINAL (cs) != 0 )
2605 property = chise_ds_get_property (default_chise_data_source,
2607 chise_feature_set_property_value
2608 (chise_ds_get_feature (default_chise_data_source, feature_name),
2609 property, XSTRING_DATA (Fprin1_to_string (make_int
2610 (CHARSET_FINAL (cs)),
2612 chise_property_sync (property);
2615 if ( !NILP (CHARSET_MOTHER (cs)) )
2617 Lisp_Object mother = CHARSET_MOTHER (cs);
2619 if ( CHARSETP (mother) )
2620 mother = XCHARSET_NAME (mother);
2622 property = chise_ds_get_property (default_chise_data_source,
2624 chise_feature_set_property_value
2625 (chise_ds_get_feature (default_chise_data_source, feature_name),
2626 property, XSTRING_DATA (Fprin1_to_string (mother, Qnil)));
2627 chise_property_sync (property);
2630 if ( CHARSET_MAX_CODE (cs) != 0 )
2634 property = chise_ds_get_property (default_chise_data_source,
2636 if ( CHARSET_MIN_CODE (cs) == 0 )
2637 chise_feature_set_property_value
2638 (chise_ds_get_feature (default_chise_data_source, feature_name),
2642 sprintf (str, "#x%X", CHARSET_MIN_CODE (cs));
2643 chise_feature_set_property_value
2644 (chise_ds_get_feature (default_chise_data_source, feature_name),
2647 chise_property_sync (property);
2649 property = chise_ds_get_property (default_chise_data_source,
2651 sprintf (str, "#x%X", CHARSET_MAX_CODE (cs));
2652 chise_feature_set_property_value
2653 (chise_ds_get_feature (default_chise_data_source, feature_name),
2655 chise_property_sync (property);
2657 property = chise_ds_get_property (default_chise_data_source,
2658 "mother-code-offset");
2659 if ( CHARSET_CODE_OFFSET (cs) == 0 )
2660 chise_feature_set_property_value
2661 (chise_ds_get_feature (default_chise_data_source, feature_name),
2665 sprintf (str, "#x%X", CHARSET_CODE_OFFSET (cs));
2666 chise_feature_set_property_value
2667 (chise_ds_get_feature (default_chise_data_source, feature_name),
2670 chise_property_sync (property);
2672 property = chise_ds_get_property (default_chise_data_source,
2673 "mother-code-conversion");
2674 if ( CHARSET_CONVERSION (cs) == CONVERSION_IDENTICAL )
2675 chise_feature_set_property_value
2676 (chise_ds_get_feature (default_chise_data_source, feature_name),
2677 property, "identical");
2680 Lisp_Object sym = Qnil;
2682 if ( CHARSET_CONVERSION (cs) == CONVERSION_94x60 )
2684 else if ( CHARSET_CONVERSION (cs) == CONVERSION_94x94x60 )
2686 else if ( CHARSET_CONVERSION (cs) == CONVERSION_BIG5_1 )
2688 else if ( CHARSET_CONVERSION (cs) == CONVERSION_BIG5_2 )
2691 chise_feature_set_property_value
2692 (chise_ds_get_feature (default_chise_data_source, feature_name),
2693 property, XSTRING_DATA (Fprin1_to_string (sym, Qnil)));
2695 chise_feature_set_property_value
2696 (chise_ds_get_feature (default_chise_data_source, feature_name),
2697 property, "unknown");
2699 chise_property_sync (property);
2703 #endif /* HAVE_LIBCHISE */
2705 #endif /* HAVE_CHISE */
2706 #endif /* UTF2000 */
2709 /************************************************************************/
2710 /* Lisp primitives for working with characters */
2711 /************************************************************************/
2714 DEFUN ("decode-char", Fdecode_char, 2, 4, 0, /*
2715 Make a character from CHARSET and code-point CODE.
2716 If DEFINED_ONLY is non-nil, builtin character is not returned.
2717 If WITHOUT_INHERITANCE is non-nil, inherited character is not returned.
2718 If corresponding character is not found, nil is returned.
2720 (charset, code, defined_only, without_inheritance))
2724 charset = Fget_charset (charset);
2727 if ( (XCHARSET_GRAPHIC (charset) == 0) ||
2728 (XCHARSET_GRAPHIC (charset) == 1) )
2730 if (NILP (defined_only))
2731 c = DECODE_CHAR (charset, c, !NILP (without_inheritance));
2733 c = decode_defined_char (charset, c, !NILP (without_inheritance));
2734 return c >= 0 ? make_char (c) : Qnil;
2737 DEFUN ("decode-builtin-char", Fdecode_builtin_char, 2, 2, 0, /*
2738 Make a builtin character from CHARSET and code-point CODE.
2745 charset = Fget_charset (charset);
2747 if (EQ (charset, Vcharset_latin_viscii))
2749 Lisp_Object chr = Fdecode_char (charset, code, Qnil, Qnil);
2755 (ret = Fget_char_attribute (chr,
2756 Vcharset_latin_viscii_lower,
2759 charset = Vcharset_latin_viscii_lower;
2763 (ret = Fget_char_attribute (chr,
2764 Vcharset_latin_viscii_upper,
2767 charset = Vcharset_latin_viscii_upper;
2774 if (XCHARSET_GRAPHIC (charset) == 1)
2777 ch = decode_builtin_char (charset, c);
2779 ch >= 0 ? make_char (ch) : Fdecode_char (charset, code, Qnil, Qnil);
2783 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
2784 Make a character from CHARSET and octets ARG1 and ARG2.
2785 ARG2 is required only for characters from two-dimensional charsets.
2786 For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
2787 character s with caron.
2789 (charset, arg1, arg2))
2793 int lowlim, highlim;
2795 charset = Fget_charset (charset);
2796 cs = XCHARSET (charset);
2798 if (EQ (charset, Vcharset_ascii)) lowlim = 0, highlim = 127;
2799 else if (EQ (charset, Vcharset_control_1)) lowlim = 0, highlim = 31;
2801 else if (CHARSET_CHARS (cs) == 256) lowlim = 0, highlim = 255;
2803 else if (CHARSET_CHARS (cs) == 94) lowlim = 33, highlim = 126;
2804 else /* CHARSET_CHARS (cs) == 96) */ lowlim = 32, highlim = 127;
2807 /* It is useful (and safe, according to Olivier Galibert) to strip
2808 the 8th bit off ARG1 and ARG2 because it allows programmers to
2809 write (make-char 'latin-iso8859-2 CODE) where code is the actual
2810 Latin 2 code of the character. */
2818 if (a1 < lowlim || a1 > highlim)
2819 args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
2821 if (CHARSET_DIMENSION (cs) == 1)
2825 ("Charset is of dimension one; second octet must be nil", arg2);
2826 return make_char (MAKE_CHAR (charset, a1, 0));
2835 a2 = XINT (arg2) & 0x7f;
2837 if (a2 < lowlim || a2 > highlim)
2838 args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
2840 return make_char (MAKE_CHAR (charset, a1, a2));
2843 DEFUN ("char-charset", Fchar_charset, 1, 1, 0, /*
2844 Return the character set of CHARACTER.
2848 CHECK_CHAR_COERCE_INT (character);
2850 return XCHARSET_NAME (CHAR_CHARSET (XCHAR (character)));
2853 DEFUN ("char-octet", Fchar_octet, 1, 2, 0, /*
2854 Return the octet numbered N (should be 0 or 1) of CHARACTER.
2855 N defaults to 0 if omitted.
2859 Lisp_Object charset;
2862 CHECK_CHAR_COERCE_INT (character);
2864 BREAKUP_CHAR (XCHAR (character), charset, octet0, octet1);
2866 if (NILP (n) || EQ (n, Qzero))
2867 return make_int (octet0);
2868 else if (EQ (n, make_int (1)))
2869 return make_int (octet1);
2871 signal_simple_error ("Octet number must be 0 or 1", n);
2875 DEFUN ("encode-char", Fencode_char, 2, 3, 0, /*
2876 Return code-point of CHARACTER in specified CHARSET.
2878 (character, charset, defined_only))
2882 CHECK_CHAR_COERCE_INT (character);
2883 charset = Fget_charset (charset);
2884 code_point = charset_code_point (charset, XCHAR (character),
2885 !NILP (defined_only));
2886 if (code_point >= 0)
2887 return make_int (code_point);
2893 DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
2894 Return list of charset and one or two position-codes of CHARACTER.
2898 /* This function can GC */
2899 struct gcpro gcpro1, gcpro2;
2900 Lisp_Object charset = Qnil;
2901 Lisp_Object rc = Qnil;
2909 GCPRO2 (charset, rc);
2910 CHECK_CHAR_COERCE_INT (character);
2913 code_point = ENCODE_CHAR (XCHAR (character), charset);
2914 dimension = XCHARSET_DIMENSION (charset);
2915 while (dimension > 0)
2917 rc = Fcons (make_int (code_point & 255), rc);
2921 rc = Fcons (XCHARSET_NAME (charset), rc);
2923 BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
2925 if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
2927 rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
2931 rc = list2 (XCHARSET_NAME (charset), make_int (c1));
2940 #ifdef ENABLE_COMPOSITE_CHARS
2941 /************************************************************************/
2942 /* composite character functions */
2943 /************************************************************************/
2946 lookup_composite_char (Bufbyte *str, int len)
2948 Lisp_Object lispstr = make_string (str, len);
2949 Lisp_Object ch = Fgethash (lispstr,
2950 Vcomposite_char_string2char_hash_table,
2956 if (composite_char_row_next >= 128)
2957 signal_simple_error ("No more composite chars available", lispstr);
2958 emch = MAKE_CHAR (Vcharset_composite, composite_char_row_next,
2959 composite_char_col_next);
2960 Fputhash (make_char (emch), lispstr,
2961 Vcomposite_char_char2string_hash_table);
2962 Fputhash (lispstr, make_char (emch),
2963 Vcomposite_char_string2char_hash_table);
2964 composite_char_col_next++;
2965 if (composite_char_col_next >= 128)
2967 composite_char_col_next = 32;
2968 composite_char_row_next++;
2977 composite_char_string (Emchar ch)
2979 Lisp_Object str = Fgethash (make_char (ch),
2980 Vcomposite_char_char2string_hash_table,
2982 assert (!UNBOUNDP (str));
2986 xxDEFUN ("make-composite-char", Fmake_composite_char, 1, 1, 0, /*
2987 Convert a string into a single composite character.
2988 The character is the result of overstriking all the characters in
2993 CHECK_STRING (string);
2994 return make_char (lookup_composite_char (XSTRING_DATA (string),
2995 XSTRING_LENGTH (string)));
2998 xxDEFUN ("composite-char-string", Fcomposite_char_string, 1, 1, 0, /*
2999 Return a string of the characters comprising a composite character.
3007 if (CHAR_LEADING_BYTE (emch) != LEADING_BYTE_COMPOSITE)
3008 signal_simple_error ("Must be composite char", ch);
3009 return composite_char_string (emch);
3011 #endif /* ENABLE_COMPOSITE_CHARS */
3014 /************************************************************************/
3015 /* initialization */
3016 /************************************************************************/
3019 syms_of_mule_charset (void)
3021 INIT_LRECORD_IMPLEMENTATION (charset);
3023 DEFSUBR (Fcharsetp);
3024 DEFSUBR (Ffind_charset);
3025 DEFSUBR (Fget_charset);
3026 DEFSUBR (Fcharset_list);
3027 DEFSUBR (Fcharset_name);
3028 DEFSUBR (Fmake_charset);
3029 DEFSUBR (Fmake_reverse_direction_charset);
3030 /* DEFSUBR (Freverse_direction_charset); */
3031 DEFSUBR (Fdefine_charset_alias);
3032 DEFSUBR (Fcharset_from_attributes);
3033 DEFSUBR (Fcharset_short_name);
3034 DEFSUBR (Fcharset_long_name);
3035 DEFSUBR (Fcharset_description);
3036 DEFSUBR (Fcharset_dimension);
3037 DEFSUBR (Fcharset_property);
3038 DEFSUBR (Fcharset_id);
3039 DEFSUBR (Fset_charset_ccl_program);
3040 DEFSUBR (Fset_charset_registry);
3043 DEFSUBR (Fcharset_mapping_table);
3044 DEFSUBR (Fset_charset_mapping_table);
3046 DEFSUBR (Fsave_charset_mapping_table);
3047 DEFSUBR (Freset_charset_mapping_table);
3048 #ifdef HAVE_LIBCHISE
3049 DEFSUBR (Fsave_charset_properties);
3050 #endif /* HAVE_LIBCHISE */
3051 #endif /* HAVE_CHISE */
3052 DEFSUBR (Fdecode_char);
3053 DEFSUBR (Fdecode_builtin_char);
3054 DEFSUBR (Fencode_char);
3057 DEFSUBR (Fmake_char);
3058 DEFSUBR (Fchar_charset);
3059 DEFSUBR (Fchar_octet);
3060 DEFSUBR (Fsplit_char);
3062 #ifdef ENABLE_COMPOSITE_CHARS
3063 DEFSUBR (Fmake_composite_char);
3064 DEFSUBR (Fcomposite_char_string);
3067 defsymbol (&Qcharsetp, "charsetp");
3068 defsymbol (&Qregistry, "registry");
3069 defsymbol (&Qfinal, "final");
3070 defsymbol (&Qgraphic, "graphic");
3071 defsymbol (&Qdirection, "direction");
3072 defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
3073 defsymbol (&Qshort_name, "short-name");
3074 defsymbol (&Qlong_name, "long-name");
3075 defsymbol (&Qiso_ir, "iso-ir");
3077 defsymbol (&Qto_iso_ir, "=>iso-ir");
3078 defsymbol (&Qpartial, "partial");
3079 defsymbol (&Qmother, "mother");
3080 defsymbol (&Qmin_code, "min-code");
3081 defsymbol (&Qmax_code, "max-code");
3082 defsymbol (&Qcode_offset, "code-offset");
3083 defsymbol (&Qconversion, "conversion");
3084 defsymbol (&Q94x60, "94x60");
3085 defsymbol (&Q94x94x60, "94x94x60");
3086 defsymbol (&Qbig5_1, "big5-1");
3087 defsymbol (&Qbig5_2, "big5-2");
3090 defsymbol (&Ql2r, "l2r");
3091 defsymbol (&Qr2l, "r2l");
3093 /* Charsets, compatible with FSF 20.3
3094 Naming convention is Script-Charset[-Edition] */
3095 defsymbol (&Qascii, "ascii");
3096 defsymbol (&Qcontrol_1, "control-1");
3097 defsymbol (&Qlatin_iso8859_1, "latin-iso8859-1");
3098 defsymbol (&Qlatin_iso8859_2, "latin-iso8859-2");
3099 defsymbol (&Qlatin_iso8859_3, "latin-iso8859-3");
3100 defsymbol (&Qlatin_iso8859_4, "latin-iso8859-4");
3101 defsymbol (&Qthai_tis620, "thai-tis620");
3102 defsymbol (&Qgreek_iso8859_7, "greek-iso8859-7");
3103 defsymbol (&Qarabic_iso8859_6, "arabic-iso8859-6");
3104 defsymbol (&Qhebrew_iso8859_8, "hebrew-iso8859-8");
3105 defsymbol (&Qkatakana_jisx0201, "katakana-jisx0201");
3106 defsymbol (&Qlatin_jisx0201, "latin-jisx0201");
3107 defsymbol (&Qcyrillic_iso8859_5, "cyrillic-iso8859-5");
3108 defsymbol (&Qlatin_iso8859_9, "latin-iso8859-9");
3109 /* defsymbol (&Qrep_jis_x0208_1978, "=jis-x0208@1978"); */
3110 defsymbol (&Qrep_gb2312, "=gb2312");
3111 defsymbol (&Qrep_gb12345, "=gb12345");
3112 defsymbol (&Qrep_jis_x0208_1983, "=jis-x0208@1983");
3113 defsymbol (&Qrep_ks_x1001, "=ks-x1001");
3114 defsymbol (&Qrep_jis_x0212, "=jis-x0212");
3115 defsymbol (&Qrep_cns11643_1, "=cns11643-1");
3116 defsymbol (&Qrep_cns11643_2, "=cns11643-2");
3118 defsymbol (&Qsystem_char_id, "system-char-id");
3119 defsymbol (&Qrep_ucs, "=ucs");
3120 defsymbol (&Qucs, "ucs");
3121 defsymbol (&Qucs_bmp, "ucs-bmp");
3122 defsymbol (&Qucs_smp, "ucs-smp");
3123 defsymbol (&Qucs_sip, "ucs-sip");
3124 defsymbol (&Qlatin_viscii, "latin-viscii");
3125 defsymbol (&Qlatin_tcvn5712, "latin-tcvn5712");
3126 defsymbol (&Qlatin_viscii_lower, "latin-viscii-lower");
3127 defsymbol (&Qlatin_viscii_upper, "latin-viscii-upper");
3128 defsymbol (&Qvietnamese_viscii_lower, "vietnamese-viscii-lower");
3129 defsymbol (&Qvietnamese_viscii_upper, "vietnamese-viscii-upper");
3130 defsymbol (&Qrep_jis_x0208, "=jis-x0208");
3131 defsymbol (&Qrep_jis_x0208_1990, "=jis-x0208@1990");
3132 defsymbol (&Qrep_big5, "=big5");
3133 defsymbol (&Qethiopic_ucs, "ethiopic-ucs");
3135 defsymbol (&Qchinese_big5_1, "chinese-big5-1");
3136 defsymbol (&Qchinese_big5_2, "chinese-big5-2");
3138 defsymbol (&Qcomposite, "composite");
3142 vars_of_mule_charset (void)
3149 chlook = xnew_and_zero (struct charset_lookup); /* zero for Purify. */
3150 dump_add_root_struct_ptr (&chlook, &charset_lookup_description);
3152 /* Table of charsets indexed by leading byte. */
3153 for (i = 0; i < countof (chlook->charset_by_leading_byte); i++)
3154 chlook->charset_by_leading_byte[i] = Qnil;
3157 /* Table of charsets indexed by type/final-byte. */
3158 for (i = 0; i < countof (chlook->charset_by_attributes); i++)
3159 for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
3160 chlook->charset_by_attributes[i][j] = Qnil;
3162 /* Table of charsets indexed by type/final-byte/direction. */
3163 for (i = 0; i < countof (chlook->charset_by_attributes); i++)
3164 for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
3165 for (k = 0; k < countof (chlook->charset_by_attributes[0][0]); k++)
3166 chlook->charset_by_attributes[i][j][k] = Qnil;
3170 chlook->next_allocated_leading_byte = MIN_LEADING_BYTE_PRIVATE;
3172 chlook->next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
3173 chlook->next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
3177 leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
3178 DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
3179 Leading-code of private TYPE9N charset of column-width 1.
3181 leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
3185 Vdefault_coded_charset_priority_list = Qnil;
3186 DEFVAR_LISP ("default-coded-charset-priority-list",
3187 &Vdefault_coded_charset_priority_list /*
3188 Default order of preferred coded-character-sets.
3190 Vdisplay_coded_charset_priority_use_inheritance = Qt;
3191 DEFVAR_LISP ("display-coded-charset-priority-use-inheritance",
3192 &Vdisplay_coded_charset_priority_use_inheritance /*
3193 If non-nil, use character inheritance.
3195 Vdisplay_coded_charset_priority_use_hierarchy_order = Qt;
3196 DEFVAR_LISP ("display-coded-charset-priority-use-hierarchy-order",
3197 &Vdisplay_coded_charset_priority_use_hierarchy_order /*
3198 If non-nil, prefer nearest character in hierarchy order.
3204 complex_vars_of_mule_charset (void)
3206 staticpro (&Vcharset_hash_table);
3207 Vcharset_hash_table =
3208 make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3210 /* Predefined character sets. We store them into variables for
3214 staticpro (&Vcharset_system_char_id);
3215 Vcharset_system_char_id =
3216 make_charset (LEADING_BYTE_SYSTEM_CHAR_ID, Qsystem_char_id, 256, 4,
3217 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3218 build_string ("SCID"),
3219 build_string ("CHAR-ID"),
3220 build_string ("System char-id"),
3223 Qnil, 0, 0x7FFFFFFF, 0, 0, Qnil, CONVERSION_IDENTICAL,
3225 staticpro (&Vcharset_ucs);
3227 make_charset (LEADING_BYTE_UCS, Qrep_ucs, 256, 4,
3228 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3229 build_string ("UCS"),
3230 build_string ("UCS"),
3231 build_string ("ISO/IEC 10646"),
3234 Qnil, 0, 0xEFFFF, 0, 0, Qnil, CONVERSION_IDENTICAL,
3236 staticpro (&Vcharset_ucs_bmp);
3238 make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp, 256, 2,
3239 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3240 build_string ("BMP"),
3241 build_string ("UCS-BMP"),
3242 build_string ("ISO/IEC 10646 Group 0 Plane 0 (BMP)"),
3244 ("\\(ISO10646\\(\\.[0-9]+\\)?-[01]\\|UCS00-0\\|UNICODE[23]?-0\\)"),
3245 - LEADING_BYTE_UCS_BMP,
3246 Qnil, 0, 0xFFFF, 0, 0, Qnil, CONVERSION_IDENTICAL,
3248 staticpro (&Vcharset_ucs_smp);
3250 make_charset (LEADING_BYTE_UCS_SMP, Qucs_smp, 256, 2,
3251 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3252 build_string ("SMP"),
3253 build_string ("UCS-SMP"),
3254 build_string ("ISO/IEC 10646 Group 0 Plane 1 (SMP)"),
3255 build_string ("UCS00-1"),
3257 Qnil, MIN_CHAR_SMP, MAX_CHAR_SMP,
3258 MIN_CHAR_SMP, 0, Qnil, CONVERSION_IDENTICAL,
3260 staticpro (&Vcharset_ucs_sip);
3262 make_charset (LEADING_BYTE_UCS_SIP, Qucs_sip, 256, 2,
3263 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3264 build_string ("SIP"),
3265 build_string ("UCS-SIP"),
3266 build_string ("ISO/IEC 10646 Group 0 Plane 2 (SIP)"),
3267 build_string ("\\(ISO10646.*-2\\|UCS00-2\\)"),
3269 Qnil, MIN_CHAR_SIP, MAX_CHAR_SIP,
3270 MIN_CHAR_SIP, 0, Qnil, CONVERSION_IDENTICAL,
3273 # define MIN_CHAR_THAI 0
3274 # define MAX_CHAR_THAI 0
3275 /* # define MIN_CHAR_HEBREW 0 */
3276 /* # define MAX_CHAR_HEBREW 0 */
3277 # define MIN_CHAR_HALFWIDTH_KATAKANA 0
3278 # define MAX_CHAR_HALFWIDTH_KATAKANA 0
3280 staticpro (&Vcharset_ascii);
3282 make_charset (LEADING_BYTE_ASCII, Qascii, 94, 1,
3283 1, 0, 'B', CHARSET_LEFT_TO_RIGHT,
3284 build_string ("ASCII"),
3285 build_string ("ASCII)"),
3286 build_string ("ASCII (ISO646 IRV)"),
3287 build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
3288 - LEADING_BYTE_ASCII,
3289 Qnil, 0, 0x7F, 0, 0, Qnil, CONVERSION_IDENTICAL,
3291 staticpro (&Vcharset_control_1);
3292 Vcharset_control_1 =
3293 make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1, 94, 1,
3294 1, 1, 0, CHARSET_LEFT_TO_RIGHT,
3295 build_string ("C1"),
3296 build_string ("Control characters"),
3297 build_string ("Control characters 128-191"),
3299 - LEADING_BYTE_CONTROL_1,
3300 Qnil, 0x80, 0x9F, 0x80, 0, Qnil, CONVERSION_IDENTICAL,
3302 staticpro (&Vcharset_latin_iso8859_1);
3303 Vcharset_latin_iso8859_1 =
3304 make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1, 96, 1,
3305 1, 1, 'A', CHARSET_LEFT_TO_RIGHT,
3306 build_string ("Latin-1"),
3307 build_string ("ISO8859-1 (Latin-1)"),
3308 build_string ("ISO8859-1 (Latin-1)"),
3309 build_string ("iso8859-1"),
3310 - LEADING_BYTE_LATIN_ISO8859_1,
3311 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3313 staticpro (&Vcharset_latin_iso8859_2);
3314 Vcharset_latin_iso8859_2 =
3315 make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2, 96, 1,
3316 1, 1, 'B', CHARSET_LEFT_TO_RIGHT,
3317 build_string ("Latin-2"),
3318 build_string ("ISO8859-2 (Latin-2)"),
3319 build_string ("ISO8859-2 (Latin-2)"),
3320 build_string ("iso8859-2"),
3321 - LEADING_BYTE_LATIN_ISO8859_2,
3322 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3324 staticpro (&Vcharset_latin_iso8859_3);
3325 Vcharset_latin_iso8859_3 =
3326 make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3, 96, 1,
3327 1, 1, 'C', CHARSET_LEFT_TO_RIGHT,
3328 build_string ("Latin-3"),
3329 build_string ("ISO8859-3 (Latin-3)"),
3330 build_string ("ISO8859-3 (Latin-3)"),
3331 build_string ("iso8859-3"),
3332 - LEADING_BYTE_LATIN_ISO8859_3,
3333 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3335 staticpro (&Vcharset_latin_iso8859_4);
3336 Vcharset_latin_iso8859_4 =
3337 make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4, 96, 1,
3338 1, 1, 'D', CHARSET_LEFT_TO_RIGHT,
3339 build_string ("Latin-4"),
3340 build_string ("ISO8859-4 (Latin-4)"),
3341 build_string ("ISO8859-4 (Latin-4)"),
3342 build_string ("iso8859-4"),
3343 - LEADING_BYTE_LATIN_ISO8859_4,
3344 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3346 staticpro (&Vcharset_thai_tis620);
3347 Vcharset_thai_tis620 =
3348 make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620, 96, 1,
3349 1, 1, 'T', CHARSET_LEFT_TO_RIGHT,
3350 build_string ("TIS620"),
3351 build_string ("TIS620 (Thai)"),
3352 build_string ("TIS620.2529 (Thai)"),
3353 build_string ("tis620"),
3354 - LEADING_BYTE_THAI_TIS620,
3355 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3357 staticpro (&Vcharset_greek_iso8859_7);
3358 Vcharset_greek_iso8859_7 =
3359 make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7, 96, 1,
3360 1, 1, 'F', CHARSET_LEFT_TO_RIGHT,
3361 build_string ("ISO8859-7"),
3362 build_string ("ISO8859-7 (Greek)"),
3363 build_string ("ISO8859-7 (Greek)"),
3364 build_string ("iso8859-7"),
3365 - LEADING_BYTE_GREEK_ISO8859_7,
3366 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3368 staticpro (&Vcharset_arabic_iso8859_6);
3369 Vcharset_arabic_iso8859_6 =
3370 make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6, 96, 1,
3371 1, 1, 'G', CHARSET_RIGHT_TO_LEFT,
3372 build_string ("ISO8859-6"),
3373 build_string ("ISO8859-6 (Arabic)"),
3374 build_string ("ISO8859-6 (Arabic)"),
3375 build_string ("iso8859-6"),
3376 - LEADING_BYTE_ARABIC_ISO8859_6,
3377 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3379 staticpro (&Vcharset_hebrew_iso8859_8);
3380 Vcharset_hebrew_iso8859_8 =
3381 make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8, 96, 1,
3382 1, 1, 'H', CHARSET_RIGHT_TO_LEFT,
3383 build_string ("ISO8859-8"),
3384 build_string ("ISO8859-8 (Hebrew)"),
3385 build_string ("ISO8859-8 (Hebrew)"),
3386 build_string ("iso8859-8"),
3387 - LEADING_BYTE_HEBREW_ISO8859_8,
3389 0 /* MIN_CHAR_HEBREW */,
3390 0 /* MAX_CHAR_HEBREW */, 0, 32,
3391 Qnil, CONVERSION_IDENTICAL,
3393 staticpro (&Vcharset_katakana_jisx0201);
3394 Vcharset_katakana_jisx0201 =
3395 make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201, 94, 1,
3396 1, 1, 'I', CHARSET_LEFT_TO_RIGHT,
3397 build_string ("JISX0201 Kana"),
3398 build_string ("JISX0201.1976 (Japanese Kana)"),
3399 build_string ("JISX0201.1976 Japanese Kana"),
3400 build_string ("jisx0201\\.1976"),
3401 - LEADING_BYTE_KATAKANA_JISX0201,
3402 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3404 staticpro (&Vcharset_latin_jisx0201);
3405 Vcharset_latin_jisx0201 =
3406 make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201, 94, 1,
3407 1, 0, 'J', CHARSET_LEFT_TO_RIGHT,
3408 build_string ("JISX0201 Roman"),
3409 build_string ("JISX0201.1976 (Japanese Roman)"),
3410 build_string ("JISX0201.1976 Japanese Roman"),
3411 build_string ("jisx0201\\.1976"),
3412 - LEADING_BYTE_LATIN_JISX0201,
3413 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3415 staticpro (&Vcharset_cyrillic_iso8859_5);
3416 Vcharset_cyrillic_iso8859_5 =
3417 make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5, 96, 1,
3418 1, 1, 'L', CHARSET_LEFT_TO_RIGHT,
3419 build_string ("ISO8859-5"),
3420 build_string ("ISO8859-5 (Cyrillic)"),
3421 build_string ("ISO8859-5 (Cyrillic)"),
3422 build_string ("iso8859-5"),
3423 - LEADING_BYTE_CYRILLIC_ISO8859_5,
3424 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3426 staticpro (&Vcharset_latin_iso8859_9);
3427 Vcharset_latin_iso8859_9 =
3428 make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9, 96, 1,
3429 1, 1, 'M', CHARSET_LEFT_TO_RIGHT,
3430 build_string ("Latin-5"),
3431 build_string ("ISO8859-9 (Latin-5)"),
3432 build_string ("ISO8859-9 (Latin-5)"),
3433 build_string ("iso8859-9"),
3434 - LEADING_BYTE_LATIN_ISO8859_9,
3435 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3438 staticpro (&Vcharset_jis_x0208);
3439 Vcharset_jis_x0208 =
3440 make_charset (LEADING_BYTE_JIS_X0208,
3441 Qrep_jis_x0208, 94, 2,
3442 2, 0, 'B', CHARSET_LEFT_TO_RIGHT,
3443 build_string ("JIS X0208"),
3444 build_string ("JIS X0208 Common"),
3445 build_string ("JIS X0208 Common part"),
3446 build_string ("jisx0208\\.1990"),
3447 - LEADING_BYTE_JAPANESE_JISX0208_1978,
3449 MIN_CHAR_JIS_X0208_1990,
3450 MAX_CHAR_JIS_X0208_1990, MIN_CHAR_JIS_X0208_1990, 33,
3451 Qnil, CONVERSION_94x94,
3455 staticpro (&Vcharset_japanese_jisx0208_1978);
3456 Vcharset_japanese_jisx0208_1978 =
3457 make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978,
3458 Qrep_jis_x0208_1978, 94, 2,
3459 2, 0, '@', CHARSET_LEFT_TO_RIGHT,
3460 build_string ("JIS X0208:1978"),
3461 build_string ("JIS X0208:1978 (Japanese)"),
3463 ("JIS X0208:1978 Japanese Kanji (so called \"old JIS\")"),
3464 build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
3465 - LEADING_BYTE_JAPANESE_JISX0208_1978,
3472 CONVERSION_IDENTICAL,
3475 staticpro (&Vcharset_chinese_gb2312);
3476 Vcharset_chinese_gb2312 =
3477 make_charset (LEADING_BYTE_CHINESE_GB2312, Qrep_gb2312, 94, 2,
3478 2, 0, 'A', CHARSET_LEFT_TO_RIGHT,
3479 build_string ("GB2312"),
3480 build_string ("GB2312)"),
3481 build_string ("GB2312 Chinese simplified"),
3482 build_string ("gb2312"),
3483 - LEADING_BYTE_CHINESE_GB2312,
3484 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3486 staticpro (&Vcharset_chinese_gb12345);
3487 Vcharset_chinese_gb12345 =
3488 make_charset (LEADING_BYTE_CHINESE_GB12345, Qrep_gb12345, 94, 2,
3489 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3490 build_string ("G1"),
3491 build_string ("GB 12345)"),
3492 build_string ("GB 12345-1990"),
3493 build_string ("GB12345\\(\\.1990\\)?-0"),
3495 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3497 staticpro (&Vcharset_japanese_jisx0208);
3498 Vcharset_japanese_jisx0208 =
3499 make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qrep_jis_x0208_1983, 94, 2,
3500 2, 0, 'B', CHARSET_LEFT_TO_RIGHT,
3501 build_string ("JISX0208"),
3502 build_string ("JIS X0208:1983 (Japanese)"),
3503 build_string ("JIS X0208:1983 Japanese Kanji"),
3504 build_string ("jisx0208\\.1983"),
3505 - LEADING_BYTE_JAPANESE_JISX0208,
3512 CONVERSION_IDENTICAL,
3515 staticpro (&Vcharset_japanese_jisx0208_1990);
3516 Vcharset_japanese_jisx0208_1990 =
3517 make_charset (LEADING_BYTE_JAPANESE_JISX0208_1990,
3518 Qrep_jis_x0208_1990, 94, 2,
3519 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3520 build_string ("JISX0208-1990"),
3521 build_string ("JIS X0208:1990 (Japanese)"),
3522 build_string ("JIS X0208:1990 Japanese Kanji"),
3523 build_string ("jisx0208\\.1990"),
3524 - LEADING_BYTE_JAPANESE_JISX0208_1990,
3526 0x2121 /* MIN_CHAR_JIS_X0208_1990 */,
3527 0x7426 /* MAX_CHAR_JIS_X0208_1990 */,
3528 0 /* MIN_CHAR_JIS_X0208_1990 */, 33,
3529 Vcharset_jis_x0208 /* Qnil */,
3530 CONVERSION_IDENTICAL /* CONVERSION_94x94 */,
3533 staticpro (&Vcharset_korean_ksc5601);
3534 Vcharset_korean_ksc5601 =
3535 make_charset (LEADING_BYTE_KOREAN_KSC5601, Qrep_ks_x1001, 94, 2,
3536 2, 0, 'C', CHARSET_LEFT_TO_RIGHT,
3537 build_string ("KSC5601"),
3538 build_string ("KSC5601 (Korean"),
3539 build_string ("KSC5601 Korean Hangul and Hanja"),
3540 build_string ("ksc5601"),
3541 - LEADING_BYTE_KOREAN_KSC5601,
3542 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3544 staticpro (&Vcharset_japanese_jisx0212);
3545 Vcharset_japanese_jisx0212 =
3546 make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qrep_jis_x0212, 94, 2,
3547 2, 0, 'D', CHARSET_LEFT_TO_RIGHT,
3548 build_string ("JISX0212"),
3549 build_string ("JISX0212 (Japanese)"),
3550 build_string ("JISX0212 Japanese Supplement"),
3551 build_string ("jisx0212"),
3552 - LEADING_BYTE_JAPANESE_JISX0212,
3553 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3556 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
3557 staticpro (&Vcharset_chinese_cns11643_1);
3558 Vcharset_chinese_cns11643_1 =
3559 make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qrep_cns11643_1, 94, 2,
3560 2, 0, 'G', CHARSET_LEFT_TO_RIGHT,
3561 build_string ("CNS11643-1"),
3562 build_string ("CNS11643-1 (Chinese traditional)"),
3564 ("CNS 11643 Plane 1 Chinese traditional"),
3565 build_string (CHINESE_CNS_PLANE_RE("1")),
3566 - LEADING_BYTE_CHINESE_CNS11643_1,
3567 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3569 staticpro (&Vcharset_chinese_cns11643_2);
3570 Vcharset_chinese_cns11643_2 =
3571 make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qrep_cns11643_2, 94, 2,
3572 2, 0, 'H', CHARSET_LEFT_TO_RIGHT,
3573 build_string ("CNS11643-2"),
3574 build_string ("CNS11643-2 (Chinese traditional)"),
3576 ("CNS 11643 Plane 2 Chinese traditional"),
3577 build_string (CHINESE_CNS_PLANE_RE("2")),
3578 - LEADING_BYTE_CHINESE_CNS11643_2,
3579 Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL,
3582 staticpro (&Vcharset_latin_tcvn5712);
3583 Vcharset_latin_tcvn5712 =
3584 make_charset (LEADING_BYTE_LATIN_TCVN5712, Qlatin_tcvn5712, 96, 1,
3585 1, 1, 'Z', CHARSET_LEFT_TO_RIGHT,
3586 build_string ("TCVN 5712"),
3587 build_string ("TCVN 5712 (VSCII-2)"),
3588 build_string ("Vietnamese TCVN 5712:1983 (VSCII-2)"),
3589 build_string ("tcvn5712\\(\\.1993\\)?-1"),
3590 - LEADING_BYTE_LATIN_TCVN5712,
3591 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3593 staticpro (&Vcharset_latin_viscii_lower);
3594 Vcharset_latin_viscii_lower =
3595 make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower, 96, 1,
3596 1, 1, '1', CHARSET_LEFT_TO_RIGHT,
3597 build_string ("VISCII lower"),
3598 build_string ("VISCII lower (Vietnamese)"),
3599 build_string ("VISCII lower (Vietnamese)"),
3600 build_string ("MULEVISCII-LOWER"),
3602 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3604 staticpro (&Vcharset_latin_viscii_upper);
3605 Vcharset_latin_viscii_upper =
3606 make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper, 96, 1,
3607 1, 1, '2', CHARSET_LEFT_TO_RIGHT,
3608 build_string ("VISCII upper"),
3609 build_string ("VISCII upper (Vietnamese)"),
3610 build_string ("VISCII upper (Vietnamese)"),
3611 build_string ("MULEVISCII-UPPER"),
3613 Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL,
3615 staticpro (&Vcharset_latin_viscii);
3616 Vcharset_latin_viscii =
3617 make_charset (LEADING_BYTE_LATIN_VISCII, Qlatin_viscii, 256, 1,
3618 1, 2, 0, CHARSET_LEFT_TO_RIGHT,
3619 build_string ("VISCII"),
3620 build_string ("VISCII 1.1 (Vietnamese)"),
3621 build_string ("VISCII 1.1 (Vietnamese)"),
3622 build_string ("VISCII1\\.1"),
3624 Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL,
3626 staticpro (&Vcharset_chinese_big5);
3627 Vcharset_chinese_big5 =
3628 make_charset (LEADING_BYTE_CHINESE_BIG5, Qrep_big5, 256, 2,
3629 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3630 build_string ("Big5"),
3631 build_string ("Big5"),
3632 build_string ("Big5 Chinese traditional"),
3633 build_string ("big5-0"),
3636 MIN_CHAR_BIG5_CDP, MAX_CHAR_BIG5_CDP,
3637 MIN_CHAR_BIG5_CDP, 0, Qnil, CONVERSION_IDENTICAL,
3640 staticpro (&Vcharset_ethiopic_ucs);
3641 Vcharset_ethiopic_ucs =
3642 make_charset (LEADING_BYTE_ETHIOPIC_UCS, Qethiopic_ucs, 256, 2,
3643 2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3644 build_string ("Ethiopic (UCS)"),
3645 build_string ("Ethiopic (UCS)"),
3646 build_string ("Ethiopic of UCS"),
3647 build_string ("Ethiopic-Unicode"),
3649 Qnil, 0x1200, 0x137F, 0, 0,
3650 Qnil, CONVERSION_IDENTICAL,
3653 staticpro (&Vcharset_chinese_big5_1);
3654 Vcharset_chinese_big5_1 =
3655 make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1, 94, 2,
3656 2, 0, '0', CHARSET_LEFT_TO_RIGHT,
3657 build_string ("Big5"),
3658 build_string ("Big5 (Level-1)"),
3660 ("Big5 Level-1 Chinese traditional"),
3661 build_string ("big5"),
3663 Qnil, 0, 0, 0, 33, /* Qnil, CONVERSION_IDENTICAL */
3664 Vcharset_chinese_big5, CONVERSION_BIG5_1,
3666 staticpro (&Vcharset_chinese_big5_2);
3667 Vcharset_chinese_big5_2 =
3668 make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2, 94, 2,
3669 2, 0, '1', CHARSET_LEFT_TO_RIGHT,
3670 build_string ("Big5"),
3671 build_string ("Big5 (Level-2)"),
3673 ("Big5 Level-2 Chinese traditional"),
3674 build_string ("big5"),
3676 Qnil, 0, 0, 0, 33, /* Qnil, CONVERSION_IDENTICAL */
3677 Vcharset_chinese_big5, CONVERSION_BIG5_2,
3680 #ifdef ENABLE_COMPOSITE_CHARS
3681 /* #### For simplicity, we put composite chars into a 96x96 charset.
3682 This is going to lead to problems because you can run out of
3683 room, esp. as we don't yet recycle numbers. */
3684 staticpro (&Vcharset_composite);
3685 Vcharset_composite =
3686 make_charset (LEADING_BYTE_COMPOSITE, Qcomposite, 96, 2,
3687 2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3688 build_string ("Composite"),
3689 build_string ("Composite characters"),
3690 build_string ("Composite characters"),
3693 /* #### not dumped properly */
3694 composite_char_row_next = 32;
3695 composite_char_col_next = 32;
3697 Vcomposite_char_string2char_hash_table =
3698 make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
3699 Vcomposite_char_char2string_hash_table =
3700 make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3701 staticpro (&Vcomposite_char_string2char_hash_table);
3702 staticpro (&Vcomposite_char_char2string_hash_table);
3703 #endif /* ENABLE_COMPOSITE_CHARS */