(charset_get_byte1): Fix bug about 94- and 96-set.
[chise/xemacs-chise.git-] / src / mule-charset.c
1 /* Functions to handle multilingual characters.
2    Copyright (C) 1992, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: FSF 20.3.  Not in FSF. */
23
24 /* Rewritten by Ben Wing <ben@xemacs.org>. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "buffer.h"
30 #include "chartab.h"
31 #include "elhash.h"
32 #include "lstream.h"
33 #include "device.h"
34 #include "faces.h"
35 #include "mule-ccl.h"
36
37 /* The various pre-defined charsets. */
38
39 Lisp_Object Vcharset_ascii;
40 Lisp_Object Vcharset_control_1;
41 Lisp_Object Vcharset_latin_iso8859_1;
42 Lisp_Object Vcharset_latin_iso8859_2;
43 Lisp_Object Vcharset_latin_iso8859_3;
44 Lisp_Object Vcharset_latin_iso8859_4;
45 Lisp_Object Vcharset_thai_tis620;
46 Lisp_Object Vcharset_greek_iso8859_7;
47 Lisp_Object Vcharset_arabic_iso8859_6;
48 Lisp_Object Vcharset_hebrew_iso8859_8;
49 Lisp_Object Vcharset_katakana_jisx0201;
50 Lisp_Object Vcharset_latin_jisx0201;
51 Lisp_Object Vcharset_cyrillic_iso8859_5;
52 Lisp_Object Vcharset_latin_iso8859_9;
53 Lisp_Object Vcharset_japanese_jisx0208_1978;
54 Lisp_Object Vcharset_chinese_gb2312;
55 Lisp_Object Vcharset_japanese_jisx0208;
56 Lisp_Object Vcharset_korean_ksc5601;
57 Lisp_Object Vcharset_japanese_jisx0212;
58 Lisp_Object Vcharset_chinese_cns11643_1;
59 Lisp_Object Vcharset_chinese_cns11643_2;
60 #ifdef UTF2000
61 Lisp_Object Vcharset_chinese_cns11643_3;
62 Lisp_Object Vcharset_chinese_cns11643_4;
63 Lisp_Object Vcharset_chinese_cns11643_5;
64 Lisp_Object Vcharset_chinese_cns11643_6;
65 Lisp_Object Vcharset_chinese_cns11643_7;
66 Lisp_Object Vcharset_ucs_bmp;
67 Lisp_Object Vcharset_latin_viscii_lower;
68 Lisp_Object Vcharset_latin_viscii_upper;
69 #endif
70 Lisp_Object Vcharset_chinese_big5_1;
71 Lisp_Object Vcharset_chinese_big5_2;
72
73 #ifdef ENABLE_COMPOSITE_CHARS
74 Lisp_Object Vcharset_composite;
75
76 /* Hash tables for composite chars.  One maps string representing
77    composed chars to their equivalent chars; one goes the
78    other way. */
79 Lisp_Object Vcomposite_char_char2string_hash_table;
80 Lisp_Object Vcomposite_char_string2char_hash_table;
81
82 static int composite_char_row_next;
83 static int composite_char_col_next;
84
85 #endif /* ENABLE_COMPOSITE_CHARS */
86
87 /* Table of charsets indexed by leading byte. */
88 Lisp_Object charset_by_leading_byte[NUM_LEADING_BYTES];
89
90 /* Table of charsets indexed by type/final-byte/direction. */
91 #ifdef UTF2000
92 Lisp_Object charset_by_attributes[4][128];
93 #else
94 Lisp_Object charset_by_attributes[4][128][2];
95 #endif
96
97 #ifndef UTF2000
98 /* Table of number of bytes in the string representation of a character
99    indexed by the first byte of that representation.
100
101    rep_bytes_by_first_byte(c) is more efficient than the equivalent
102    canonical computation:
103
104    (BYTE_ASCII_P (c) ? 1 : XCHARSET_REP_BYTES (CHARSET_BY_LEADING_BYTE (c))) */
105
106 Bytecount rep_bytes_by_first_byte[0xA0] =
107 { /* 0x00 - 0x7f are for straight ASCII */
108   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
109   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
110   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
111   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
112   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
113   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
114   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
115   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
116   /* 0x80 - 0x8f are for Dimension-1 official charsets */
117 #ifdef CHAR_IS_UCS4
118   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
119 #else
120   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
121 #endif
122   /* 0x90 - 0x9d are for Dimension-2 official charsets */
123   /* 0x9e is for Dimension-1 private charsets */
124   /* 0x9f is for Dimension-2 private charsets */
125   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
126 };
127 #endif
128
129 #ifdef UTF2000
130 Emchar_to_byte_table*
131 make_byte_from_character_table ()
132 {
133   Emchar_to_byte_table* table
134     = (Emchar_to_byte_table*) xmalloc (sizeof (Emchar_to_byte_table));
135
136   table->base = NULL;
137   return table;
138 }
139
140 void
141 put_byte_from_character_table (Emchar ch, unsigned char val,
142                                Emchar_to_byte_table* table)
143 {
144   if (table->base == NULL)
145     {
146       table->base = xmalloc (128);
147       table->offset = ch - (ch % 128);
148       table->size = 128;
149       table->base[ch - table->offset] = val;
150     }
151   else
152     {
153       int i = ch - table->offset;
154
155       if (i < 0)
156         {
157           size_t new_size = table->size - i;
158           size_t j;
159
160           new_size += 128 - (new_size % 128);
161           table->base = xrealloc (table->base, new_size);
162           memmove (table->base + (new_size - table->size), table->base,
163                    table->size);
164           for (j = 0; j < (new_size - table->size); j++)
165             table->base[j] = 0;
166           table->offset -= (new_size - table->size);
167           table->base[ch - table->offset] = val;
168           table->size = new_size;
169         }
170       else if (i >= table->size)
171         {
172           size_t new_size = i + 1;
173           size_t j;
174
175           new_size += 128 - (new_size % 128);
176           table->base = xrealloc (table->base, new_size);
177           for (j = table->size; j < new_size; j++)
178             table->base[j] = 0;
179           table->base[i] = val;
180           table->size = new_size;
181         }
182       else
183         {
184           table->base[i] = val;
185         }
186     }
187 }
188
189 unsigned char
190 get_byte_from_character_table (Emchar ch, Emchar_to_byte_table* table)
191 {
192   size_t i = ch - table->offset;
193   if (i < table->size)
194     return table->base[i];
195   else
196     return 0;
197 }
198
199 #define CHAR96(ft,b)    (MIN_CHAR_96 + (ft - '0') * 96 + (b & 0x7f) - 32)
200
201 Emchar latin_jisx0201_to_ucs[94] =
202 {
203   0x0021 /* 0x21        EXCLAMATION MARK */,
204   0x0022 /* 0x22        QUOTATION MARK */,
205   0x0023 /* 0x23        NUMBER SIGN */,
206   0x0024 /* 0x24        DOLLAR SIGN */,
207   0x0025 /* 0x25        PERCENT SIGN */,
208   0x0026 /* 0x26        AMPERSAND */,
209   0x0027 /* 0x27        APOSTROPHE */,
210   0x0028 /* 0x28        LEFT PARENTHESIS */,
211   0x0029 /* 0x29        RIGHT PARENTHESIS */,
212   0x002A /* 0x2A        ASTERISK */,
213   0x002B /* 0x2B        PLUS SIGN */,
214   0x002C /* 0x2C        COMMA */,
215   0x002D /* 0x2D        HYPHEN-MINUS */,
216   0x002E /* 0x2E        FULL STOP */,
217   0x002F /* 0x2F        SOLIDUS */,
218   0x0030 /* 0x30        DIGIT ZERO */,
219   0x0031 /* 0x31        DIGIT ONE */,
220   0x0032 /* 0x32        DIGIT TWO */,
221   0x0033 /* 0x33        DIGIT THREE */,
222   0x0034 /* 0x34        DIGIT FOUR */,
223   0x0035 /* 0x35        DIGIT FIVE */,
224   0x0036 /* 0x36        DIGIT SIX */,
225   0x0037 /* 0x37        DIGIT SEVEN */,
226   0x0038 /* 0x38        DIGIT EIGHT */,
227   0x0039 /* 0x39        DIGIT NINE */,
228   0x003A /* 0x3A        COLON */,
229   0x003B /* 0x3B        SEMICOLON */,
230   0x003C /* 0x3C        LESS-THAN SIGN */,
231   0x003D /* 0x3D        EQUALS SIGN */,
232   0x003E /* 0x3E        GREATER-THAN SIGN */,
233   0x003F /* 0x3F        QUESTION MARK */,
234   0x0040 /* 0x40        COMMERCIAL AT */,
235   0x0041 /* 0x41        LATIN CAPITAL LETTER A */,
236   0x0042 /* 0x42        LATIN CAPITAL LETTER B */,
237   0x0043 /* 0x43        LATIN CAPITAL LETTER C */,
238   0x0044 /* 0x44        LATIN CAPITAL LETTER D */,
239   0x0045 /* 0x45        LATIN CAPITAL LETTER E */,
240   0x0046 /* 0x46        LATIN CAPITAL LETTER F */,
241   0x0047 /* 0x47        LATIN CAPITAL LETTER G */,
242   0x0048 /* 0x48        LATIN CAPITAL LETTER H */,
243   0x0049 /* 0x49        LATIN CAPITAL LETTER I */,
244   0x004A /* 0x4A        LATIN CAPITAL LETTER J */,
245   0x004B /* 0x4B        LATIN CAPITAL LETTER K */,
246   0x004C /* 0x4C        LATIN CAPITAL LETTER L */,
247   0x004D /* 0x4D        LATIN CAPITAL LETTER M */,
248   0x004E /* 0x4E        LATIN CAPITAL LETTER N */,
249   0x004F /* 0x4F        LATIN CAPITAL LETTER O */,
250   0x0050 /* 0x50        LATIN CAPITAL LETTER P */,
251   0x0051 /* 0x51        LATIN CAPITAL LETTER Q */,
252   0x0052 /* 0x52        LATIN CAPITAL LETTER R */,
253   0x0053 /* 0x53        LATIN CAPITAL LETTER S */,
254   0x0054 /* 0x54        LATIN CAPITAL LETTER T */,
255   0x0055 /* 0x55        LATIN CAPITAL LETTER U */,
256   0x0056 /* 0x56        LATIN CAPITAL LETTER V */,
257   0x0057 /* 0x57        LATIN CAPITAL LETTER W */,
258   0x0058 /* 0x58        LATIN CAPITAL LETTER X */,
259   0x0059 /* 0x59        LATIN CAPITAL LETTER Y */,
260   0x005A /* 0x5A        LATIN CAPITAL LETTER Z */,
261   0x005B /* 0x5B        LEFT SQUARE BRACKET */,
262   0x00A5 /* 0x5C        YEN SIGN */,
263   0x005D /* 0x5D        RIGHT SQUARE BRACKET */,
264   0x005E /* 0x5E        CIRCUMFLEX ACCENT */,
265   0x005F /* 0x5F        LOW LINE */,
266   0x0060 /* 0x60        GRAVE ACCENT */,
267   0x0061 /* 0x61        LATIN SMALL LETTER A */,
268   0x0062 /* 0x62        LATIN SMALL LETTER B */,
269   0x0063 /* 0x63        LATIN SMALL LETTER C */,
270   0x0064 /* 0x64        LATIN SMALL LETTER D */,
271   0x0065 /* 0x65        LATIN SMALL LETTER E */,
272   0x0066 /* 0x66        LATIN SMALL LETTER F */,
273   0x0067 /* 0x67        LATIN SMALL LETTER G */,
274   0x0068 /* 0x68        LATIN SMALL LETTER H */,
275   0x0069 /* 0x69        LATIN SMALL LETTER I */,
276   0x006A /* 0x6A        LATIN SMALL LETTER J */,
277   0x006B /* 0x6B        LATIN SMALL LETTER K */,
278   0x006C /* 0x6C        LATIN SMALL LETTER L */,
279   0x006D /* 0x6D        LATIN SMALL LETTER M */,
280   0x006E /* 0x6E        LATIN SMALL LETTER N */,
281   0x006F /* 0x6F        LATIN SMALL LETTER O */,
282   0x0070 /* 0x70        LATIN SMALL LETTER P */,
283   0x0071 /* 0x71        LATIN SMALL LETTER Q */,
284   0x0072 /* 0x72        LATIN SMALL LETTER R */,
285   0x0073 /* 0x73        LATIN SMALL LETTER S */,
286   0x0074 /* 0x74        LATIN SMALL LETTER T */,
287   0x0075 /* 0x75        LATIN SMALL LETTER U */,
288   0x0076 /* 0x76        LATIN SMALL LETTER V */,
289   0x0077 /* 0x77        LATIN SMALL LETTER W */,
290   0x0078 /* 0x78        LATIN SMALL LETTER X */,
291   0x0079 /* 0x79        LATIN SMALL LETTER Y */,
292   0x007A /* 0x7A        LATIN SMALL LETTER Z */,
293   0x007B /* 0x7B        LEFT CURLY BRACKET */,
294   0x007C /* 0x7C        VERTICAL LINE */,
295   0x007D /* 0x7D        RIGHT CURLY BRACKET */,
296   0x203E /* 0x7E        OVERLINE */
297 };
298
299 Emchar latin_iso8859_2_to_ucs[96] =
300 {
301   0x00A0 /* 0xA0        NO-BREAK SPACE */,
302   0x0104 /* 0xA1        LATIN CAPITAL LETTER A WITH OGONEK */,
303   0x02D8 /* 0xA2        BREVE */,
304   0x0141 /* 0xA3        LATIN CAPITAL LETTER L WITH STROKE */,
305   0x00A4 /* 0xA4        CURRENCY SIGN */,
306   0x013D /* 0xA5        LATIN CAPITAL LETTER L WITH CARON */,
307   0x015A /* 0xA6        LATIN CAPITAL LETTER S WITH ACUTE */,
308   0x00A7 /* 0xA7        SECTION SIGN */,
309   0x00A8 /* 0xA8        DIAERESIS */,
310   0x0160 /* 0xA9        LATIN CAPITAL LETTER S WITH CARON */,
311   0x015E /* 0xAA        LATIN CAPITAL LETTER S WITH CEDILLA */,
312   0x0164 /* 0xAB        LATIN CAPITAL LETTER T WITH CARON */,
313   0x0179 /* 0xAC        LATIN CAPITAL LETTER Z WITH ACUTE */,
314   0x00AD /* 0xAD        SOFT HYPHEN */,
315   0x017D /* 0xAE        LATIN CAPITAL LETTER Z WITH CARON */,
316   0x017B /* 0xAF        LATIN CAPITAL LETTER Z WITH DOT ABOVE */,
317   0x00B0 /* 0xB0        DEGREE SIGN */,
318   0x0105 /* 0xB1        LATIN SMALL LETTER A WITH OGONEK */,
319   0x02DB /* 0xB2        OGONEK */,
320   0x0142 /* 0xB3        LATIN SMALL LETTER L WITH STROKE */,
321   0x00B4 /* 0xB4        ACUTE ACCENT */,
322   0x013E /* 0xB5        LATIN SMALL LETTER L WITH CARON */,
323   0x015B /* 0xB6        LATIN SMALL LETTER S WITH ACUTE */,
324   0x02C7 /* 0xB7        CARON */,
325   0x00B8 /* 0xB8        CEDILLA */,
326   0x0161 /* 0xB9        LATIN SMALL LETTER S WITH CARON */,
327   0x015F /* 0xBA        LATIN SMALL LETTER S WITH CEDILLA */,
328   0x0165 /* 0xBB        LATIN SMALL LETTER T WITH CARON */,
329   0x017A /* 0xBC        LATIN SMALL LETTER Z WITH ACUTE */,
330   0x02DD /* 0xBD        DOUBLE ACUTE ACCENT */,
331   0x017E /* 0xBE        LATIN SMALL LETTER Z WITH CARON */,
332   0x017C /* 0xBF        LATIN SMALL LETTER Z WITH DOT ABOVE */,
333   0x0154 /* 0xC0        LATIN CAPITAL LETTER R WITH ACUTE */,
334   0x00C1 /* 0xC1        LATIN CAPITAL LETTER A WITH ACUTE */,
335   0x00C2 /* 0xC2        LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
336   0x0102 /* 0xC3        LATIN CAPITAL LETTER A WITH BREVE */,
337   0x00C4 /* 0xC4        LATIN CAPITAL LETTER A WITH DIAERESIS */,
338   0x0139 /* 0xC5        LATIN CAPITAL LETTER L WITH ACUTE */,
339   0x0106 /* 0xC6        LATIN CAPITAL LETTER C WITH ACUTE */,
340   0x00C7 /* 0xC7        LATIN CAPITAL LETTER C WITH CEDILLA */,
341   0x010C /* 0xC8        LATIN CAPITAL LETTER C WITH CARON */,
342   0x00C9 /* 0xC9        LATIN CAPITAL LETTER E WITH ACUTE */,
343   0x0118 /* 0xCA        LATIN CAPITAL LETTER E WITH OGONEK */,
344   0x00CB /* 0xCB        LATIN CAPITAL LETTER E WITH DIAERESIS */,
345   0x011A /* 0xCC        LATIN CAPITAL LETTER E WITH CARON */,
346   0x00CD /* 0xCD        LATIN CAPITAL LETTER I WITH ACUTE */,
347   0x00CE /* 0xCE        LATIN CAPITAL LETTER I WITH CIRCUMFLEX */,
348   0x010E /* 0xCF        LATIN CAPITAL LETTER D WITH CARON */,
349   0x0110 /* 0xD0        LATIN CAPITAL LETTER D WITH STROKE */,
350   0x0143 /* 0xD1        LATIN CAPITAL LETTER N WITH ACUTE */,
351   0x0147 /* 0xD2        LATIN CAPITAL LETTER N WITH CARON */,
352   0x00D3 /* 0xD3        LATIN CAPITAL LETTER O WITH ACUTE */,
353   0x00D4 /* 0xD4        LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
354   0x0150 /* 0xD5        LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */,
355   0x00D6 /* 0xD6        LATIN CAPITAL LETTER O WITH DIAERESIS */,
356   0x00D7 /* 0xD7        MULTIPLICATION SIGN */,
357   0x0158 /* 0xD8        LATIN CAPITAL LETTER R WITH CARON */,
358   0x016E /* 0xD9        LATIN CAPITAL LETTER U WITH RING ABOVE */,
359   0x00DA /* 0xDA        LATIN CAPITAL LETTER U WITH ACUTE */,
360   0x0170 /* 0xDB        LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */,
361   0x00DC /* 0xDC        LATIN CAPITAL LETTER U WITH DIAERESIS */,
362   0x00DD /* 0xDD        LATIN CAPITAL LETTER Y WITH ACUTE */,
363   0x0162 /* 0xDE        LATIN CAPITAL LETTER T WITH CEDILLA */,
364   0x00DF /* 0xDF        LATIN SMALL LETTER SHARP S */,
365   0x0155 /* 0xE0        LATIN SMALL LETTER R WITH ACUTE */,
366   0x00E1 /* 0xE1        LATIN SMALL LETTER A WITH ACUTE */,
367   0x00E2 /* 0xE2        LATIN SMALL LETTER A WITH CIRCUMFLEX */,
368   0x0103 /* 0xE3        LATIN SMALL LETTER A WITH BREVE */,
369   0x00E4 /* 0xE4        LATIN SMALL LETTER A WITH DIAERESIS */,
370   0x013A /* 0xE5        LATIN SMALL LETTER L WITH ACUTE */,
371   0x0107 /* 0xE6        LATIN SMALL LETTER C WITH ACUTE */,
372   0x00E7 /* 0xE7        LATIN SMALL LETTER C WITH CEDILLA */,
373   0x010D /* 0xE8        LATIN SMALL LETTER C WITH CARON */,
374   0x00E9 /* 0xE9        LATIN SMALL LETTER E WITH ACUTE */,
375   0x0119 /* 0xEA        LATIN SMALL LETTER E WITH OGONEK */,
376   0x00EB /* 0xEB        LATIN SMALL LETTER E WITH DIAERESIS */,
377   0x011B /* 0xEC        LATIN SMALL LETTER E WITH CARON */,
378   0x00ED /* 0xED        LATIN SMALL LETTER I WITH ACUTE */,
379   0x00EE /* 0xEE        LATIN SMALL LETTER I WITH CIRCUMFLEX */,
380   0x010F /* 0xEF        LATIN SMALL LETTER D WITH CARON */,
381   0x0111 /* 0xF0        LATIN SMALL LETTER D WITH STROKE */,
382   0x0144 /* 0xF1        LATIN SMALL LETTER N WITH ACUTE */,
383   0x0148 /* 0xF2        LATIN SMALL LETTER N WITH CARON */,
384   0x00F3 /* 0xF3        LATIN SMALL LETTER O WITH ACUTE */,
385   0x00F4 /* 0xF4        LATIN SMALL LETTER O WITH CIRCUMFLEX */,
386   0x0151 /* 0xF5        LATIN SMALL LETTER O WITH DOUBLE ACUTE */,
387   0x00F6 /* 0xF6        LATIN SMALL LETTER O WITH DIAERESIS */,
388   0x00F7 /* 0xF7        DIVISION SIGN */,
389   0x0159 /* 0xF8        LATIN SMALL LETTER R WITH CARON */,
390   0x016F /* 0xF9        LATIN SMALL LETTER U WITH RING ABOVE */,
391   0x00FA /* 0xFA        LATIN SMALL LETTER U WITH ACUTE */,
392   0x0171 /* 0xFB        LATIN SMALL LETTER U WITH DOUBLE ACUTE */,
393   0x00FC /* 0xFC        LATIN SMALL LETTER U WITH DIAERESIS */,
394   0x00FD /* 0xFD        LATIN SMALL LETTER Y WITH ACUTE */,
395   0x0163 /* 0xFE        LATIN SMALL LETTER T WITH CEDILLA */,
396   0x02D9 /* 0xFF        DOT ABOVE */
397 };
398
399 Emchar latin_iso8859_3_to_ucs[96] =
400 {
401   0x00A0 /* 0xA0        NO-BREAK SPACE */,
402   0x0126 /* 0xA1        LATIN CAPITAL LETTER H WITH STROKE */,
403   0x02D8 /* 0xA2        BREVE */,
404   0x00A3 /* 0xA3        POUND SIGN */,
405   0x00A4 /* 0xA4        CURRENCY SIGN */,
406   CHAR96('C', 0xA5),
407   0x0124 /* 0xA6        LATIN CAPITAL LETTER H WITH CIRCUMFLEX */,
408   0x00A7 /* 0xA7        SECTION SIGN */,
409   0x00A8 /* 0xA8        DIAERESIS */,
410   0x0130 /* 0xA9        LATIN CAPITAL LETTER I WITH DOT ABOVE */,
411   0x015E /* 0xAA        LATIN CAPITAL LETTER S WITH CEDILLA */,
412   0x011E /* 0xAB        LATIN CAPITAL LETTER G WITH BREVE */,
413   0x0134 /* 0xAC        LATIN CAPITAL LETTER J WITH CIRCUMFLEX */,
414   0x00AD /* 0xAD        SOFT HYPHEN */,
415   CHAR96('C', 0xAE),
416   0x017B /* 0xAF        LATIN CAPITAL LETTER Z WITH DOT ABOVE */,
417   0x00B0 /* 0xB0        DEGREE SIGN */,
418   0x0127 /* 0xB1        LATIN SMALL LETTER H WITH STROKE */,
419   0x00B2 /* 0xB2        SUPERSCRIPT TWO */,
420   0x00B3 /* 0xB3        SUPERSCRIPT THREE */,
421   0x00B4 /* 0xB4        ACUTE ACCENT */,
422   0x00B5 /* 0xB5        MICRO SIGN */,
423   0x0125 /* 0xB6        LATIN SMALL LETTER H WITH CIRCUMFLEX */,
424   0x00B7 /* 0xB7        MIDDLE DOT */,
425   0x00B8 /* 0xB8        CEDILLA */,
426   0x0131 /* 0xB9        LATIN SMALL LETTER DOTLESS I */,
427   0x015F /* 0xBA        LATIN SMALL LETTER S WITH CEDILLA */,
428   0x011F /* 0xBB        LATIN SMALL LETTER G WITH BREVE */,
429   0x0135 /* 0xBC        LATIN SMALL LETTER J WITH CIRCUMFLEX */,
430   0x00BD /* 0xBD        VULGAR FRACTION ONE HALF */,
431   CHAR96('C', 0xBE),
432   0x017C /* 0xBF        LATIN SMALL LETTER Z WITH DOT ABOVE */,
433   0x00C0 /* 0xC0        LATIN CAPITAL LETTER A WITH GRAVE */,
434   0x00C1 /* 0xC1        LATIN CAPITAL LETTER A WITH ACUTE */,
435   0x00C2 /* 0xC2        LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
436   CHAR96('C', 0xC3),
437   0x00C4 /* 0xC4        LATIN CAPITAL LETTER A WITH DIAERESIS */,
438   0x010A /* 0xC5        LATIN CAPITAL LETTER C WITH DOT ABOVE */,
439   0x0108 /* 0xC6        LATIN CAPITAL LETTER C WITH CIRCUMFLEX */,
440   0x00C7 /* 0xC7        LATIN CAPITAL LETTER C WITH CEDILLA */,
441   0x00C8 /* 0xC8        LATIN CAPITAL LETTER E WITH GRAVE */,
442   0x00C9 /* 0xC9        LATIN CAPITAL LETTER E WITH ACUTE */,
443   0x00CA /* 0xCA        LATIN CAPITAL LETTER E WITH CIRCUMFLEX */,
444   0x00CB /* 0xCB        LATIN CAPITAL LETTER E WITH DIAERESIS */,
445   0x00CC /* 0xCC        LATIN CAPITAL LETTER I WITH GRAVE */,
446   0x00CD /* 0xCD        LATIN CAPITAL LETTER I WITH ACUTE */,
447   0x00CE /* 0xCE        LATIN CAPITAL LETTER I WITH CIRCUMFLEX */,
448   0x00CF /* 0xCF        LATIN CAPITAL LETTER I WITH DIAERESIS */,
449   CHAR96('C', 0xD0),
450   0x00D1 /* 0xD1        LATIN CAPITAL LETTER N WITH TILDE */,
451   0x00D2 /* 0xD2        LATIN CAPITAL LETTER O WITH GRAVE */,
452   0x00D3 /* 0xD3        LATIN CAPITAL LETTER O WITH ACUTE */,
453   0x00D4 /* 0xD4        LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
454   0x0120 /* 0xD5        LATIN CAPITAL LETTER G WITH DOT ABOVE */,
455   0x00D6 /* 0xD6        LATIN CAPITAL LETTER O WITH DIAERESIS */,
456   0x00D7 /* 0xD7        MULTIPLICATION SIGN */,
457   0x011C /* 0xD8        LATIN CAPITAL LETTER G WITH CIRCUMFLEX */,
458   0x00D9 /* 0xD9        LATIN CAPITAL LETTER U WITH GRAVE */,
459   0x00DA /* 0xDA        LATIN CAPITAL LETTER U WITH ACUTE */,
460   0x00DB /* 0xDB        LATIN CAPITAL LETTER U WITH CIRCUMFLEX */,
461   0x00DC /* 0xDC        LATIN CAPITAL LETTER U WITH DIAERESIS */,
462   0x016C /* 0xDD        LATIN CAPITAL LETTER U WITH BREVE */,
463   0x015C /* 0xDE        LATIN CAPITAL LETTER S WITH CIRCUMFLEX */,
464   0x00DF /* 0xDF        LATIN SMALL LETTER SHARP S */,
465   0x00E0 /* 0xE0        LATIN SMALL LETTER A WITH GRAVE */,
466   0x00E1 /* 0xE1        LATIN SMALL LETTER A WITH ACUTE */,
467   0x00E2 /* 0xE2        LATIN SMALL LETTER A WITH CIRCUMFLEX */,
468   CHAR96('C', 0xE3),
469   0x00E4 /* 0xE4        LATIN SMALL LETTER A WITH DIAERESIS */,
470   0x010B /* 0xE5        LATIN SMALL LETTER C WITH DOT ABOVE */,
471   0x0109 /* 0xE6        LATIN SMALL LETTER C WITH CIRCUMFLEX */,
472   0x00E7 /* 0xE7        LATIN SMALL LETTER C WITH CEDILLA */,
473   0x00E8 /* 0xE8        LATIN SMALL LETTER E WITH GRAVE */,
474   0x00E9 /* 0xE9        LATIN SMALL LETTER E WITH ACUTE */,
475   0x00EA /* 0xEA        LATIN SMALL LETTER E WITH CIRCUMFLEX */,
476   0x00EB /* 0xEB        LATIN SMALL LETTER E WITH DIAERESIS */,
477   0x00EC /* 0xEC        LATIN SMALL LETTER I WITH GRAVE */,
478   0x00ED /* 0xED        LATIN SMALL LETTER I WITH ACUTE */,
479   0x00EE /* 0xEE        LATIN SMALL LETTER I WITH CIRCUMFLEX */,
480   0x00EF /* 0xEF        LATIN SMALL LETTER I WITH DIAERESIS */,
481   CHAR96('C', 0xF0),
482   0x00F1 /* 0xF1        LATIN SMALL LETTER N WITH TILDE */,
483   0x00F2 /* 0xF2        LATIN SMALL LETTER O WITH GRAVE */,
484   0x00F3 /* 0xF3        LATIN SMALL LETTER O WITH ACUTE */,
485   0x00F4 /* 0xF4        LATIN SMALL LETTER O WITH CIRCUMFLEX */,
486   0x0121 /* 0xF5        LATIN SMALL LETTER G WITH DOT ABOVE */,
487   0x00F6 /* 0xF6        LATIN SMALL LETTER O WITH DIAERESIS */,
488   0x00F7 /* 0xF7        DIVISION SIGN */,
489   0x011D /* 0xF8        LATIN SMALL LETTER G WITH CIRCUMFLEX */,
490   0x00F9 /* 0xF9        LATIN SMALL LETTER U WITH GRAVE */,
491   0x00FA /* 0xFA        LATIN SMALL LETTER U WITH ACUTE */,
492   0x00FB /* 0xFB        LATIN SMALL LETTER U WITH CIRCUMFLEX */,
493   0x00FC /* 0xFC        LATIN SMALL LETTER U WITH DIAERESIS */,
494   0x016D /* 0xFD        LATIN SMALL LETTER U WITH BREVE */,
495   0x015D /* 0xFE        LATIN SMALL LETTER S WITH CIRCUMFLEX */,
496   0x02D9 /* 0xFF        DOT ABOVE */
497 };
498
499 Emchar latin_iso8859_4_to_ucs[96] =
500 {
501   0x00A0 /* 0xA0        NO-BREAK SPACE */,
502   0x0104 /* 0xA1        LATIN CAPITAL LETTER A WITH OGONEK */,
503   0x0138 /* 0xA2        LATIN SMALL LETTER KRA */,
504   0x0156 /* 0xA3        LATIN CAPITAL LETTER R WITH CEDILLA */,
505   0x00A4 /* 0xA4        CURRENCY SIGN */,
506   0x0128 /* 0xA5        LATIN CAPITAL LETTER I WITH TILDE */,
507   0x013B /* 0xA6        LATIN CAPITAL LETTER L WITH CEDILLA */,
508   0x00A7 /* 0xA7        SECTION SIGN */,
509   0x00A8 /* 0xA8        DIAERESIS */,
510   0x0160 /* 0xA9        LATIN CAPITAL LETTER S WITH CARON */,
511   0x0112 /* 0xAA        LATIN CAPITAL LETTER E WITH MACRON */,
512   0x0122 /* 0xAB        LATIN CAPITAL LETTER G WITH CEDILLA */,
513   0x0166 /* 0xAC        LATIN CAPITAL LETTER T WITH STROKE */,
514   0x00AD /* 0xAD        SOFT HYPHEN */,
515   0x017D /* 0xAE        LATIN CAPITAL LETTER Z WITH CARON */,
516   0x00AF /* 0xAF        MACRON */,
517   0x00B0 /* 0xB0        DEGREE SIGN */,
518   0x0105 /* 0xB1        LATIN SMALL LETTER A WITH OGONEK */,
519   0x02DB /* 0xB2        OGONEK */,
520   0x0157 /* 0xB3        LATIN SMALL LETTER R WITH CEDILLA */,
521   0x00B4 /* 0xB4        ACUTE ACCENT */,
522   0x0129 /* 0xB5        LATIN SMALL LETTER I WITH TILDE */,
523   0x013C /* 0xB6        LATIN SMALL LETTER L WITH CEDILLA */,
524   0x02C7 /* 0xB7        CARON */,
525   0x00B8 /* 0xB8        CEDILLA */,
526   0x0161 /* 0xB9        LATIN SMALL LETTER S WITH CARON */,
527   0x0113 /* 0xBA        LATIN SMALL LETTER E WITH MACRON */,
528   0x0123 /* 0xBB        LATIN SMALL LETTER G WITH CEDILLA */,
529   0x0167 /* 0xBC        LATIN SMALL LETTER T WITH STROKE */,
530   0x014A /* 0xBD        LATIN CAPITAL LETTER ENG */,
531   0x017E /* 0xBE        LATIN SMALL LETTER Z WITH CARON */,
532   0x014B /* 0xBF        LATIN SMALL LETTER ENG */,
533   0x0100 /* 0xC0        LATIN CAPITAL LETTER A WITH MACRON */,
534   0x00C1 /* 0xC1        LATIN CAPITAL LETTER A WITH ACUTE */,
535   0x00C2 /* 0xC2        LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
536   0x00C3 /* 0xC3        LATIN CAPITAL LETTER A WITH TILDE */,
537   0x00C4 /* 0xC4        LATIN CAPITAL LETTER A WITH DIAERESIS */,
538   0x00C5 /* 0xC5        LATIN CAPITAL LETTER A WITH RING ABOVE */,
539   0x00C6 /* 0xC6        LATIN CAPITAL LETTER AE */,
540   0x012E /* 0xC7        LATIN CAPITAL LETTER I WITH OGONEK */,
541   0x010C /* 0xC8        LATIN CAPITAL LETTER C WITH CARON */,
542   0x00C9 /* 0xC9        LATIN CAPITAL LETTER E WITH ACUTE */,
543   0x0118 /* 0xCA        LATIN CAPITAL LETTER E WITH OGONEK */,
544   0x00CB /* 0xCB        LATIN CAPITAL LETTER E WITH DIAERESIS */,
545   0x0116 /* 0xCC        LATIN CAPITAL LETTER E WITH DOT ABOVE */,
546   0x00CD /* 0xCD        LATIN CAPITAL LETTER I WITH ACUTE */,
547   0x00CE /* 0xCE        LATIN CAPITAL LETTER I WITH CIRCUMFLEX */,
548   0x012A /* 0xCF        LATIN CAPITAL LETTER I WITH MACRON */,
549   0x0110 /* 0xD0        LATIN CAPITAL LETTER D WITH STROKE */,
550   0x0145 /* 0xD1        LATIN CAPITAL LETTER N WITH CEDILLA */,
551   0x014C /* 0xD2        LATIN CAPITAL LETTER O WITH MACRON */,
552   0x0136 /* 0xD3        LATIN CAPITAL LETTER K WITH CEDILLA */,
553   0x00D4 /* 0xD4        LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
554   0x00D5 /* 0xD5        LATIN CAPITAL LETTER O WITH TILDE */,
555   0x00D6 /* 0xD6        LATIN CAPITAL LETTER O WITH DIAERESIS */,
556   0x00D7 /* 0xD7        MULTIPLICATION SIGN */,
557   0x00D8 /* 0xD8        LATIN CAPITAL LETTER O WITH STROKE */,
558   0x0172 /* 0xD9        LATIN CAPITAL LETTER U WITH OGONEK */,
559   0x00DA /* 0xDA        LATIN CAPITAL LETTER U WITH ACUTE */,
560   0x00DB /* 0xDB        LATIN CAPITAL LETTER U WITH CIRCUMFLEX */,
561   0x00DC /* 0xDC        LATIN CAPITAL LETTER U WITH DIAERESIS */,
562   0x0168 /* 0xDD        LATIN CAPITAL LETTER U WITH TILDE */,
563   0x016A /* 0xDE        LATIN CAPITAL LETTER U WITH MACRON */,
564   0x00DF /* 0xDF        LATIN SMALL LETTER SHARP S */,
565   0x0101 /* 0xE0        LATIN SMALL LETTER A WITH MACRON */,
566   0x00E1 /* 0xE1        LATIN SMALL LETTER A WITH ACUTE */,
567   0x00E2 /* 0xE2        LATIN SMALL LETTER A WITH CIRCUMFLEX */,
568   0x00E3 /* 0xE3        LATIN SMALL LETTER A WITH TILDE */,
569   0x00E4 /* 0xE4        LATIN SMALL LETTER A WITH DIAERESIS */,
570   0x00E5 /* 0xE5        LATIN SMALL LETTER A WITH RING ABOVE */,
571   0x00E6 /* 0xE6        LATIN SMALL LETTER AE */,
572   0x012F /* 0xE7        LATIN SMALL LETTER I WITH OGONEK */,
573   0x010D /* 0xE8        LATIN SMALL LETTER C WITH CARON */,
574   0x00E9 /* 0xE9        LATIN SMALL LETTER E WITH ACUTE */,
575   0x0119 /* 0xEA        LATIN SMALL LETTER E WITH OGONEK */,
576   0x00EB /* 0xEB        LATIN SMALL LETTER E WITH DIAERESIS */,
577   0x0117 /* 0xEC        LATIN SMALL LETTER E WITH DOT ABOVE */,
578   0x00ED /* 0xED        LATIN SMALL LETTER I WITH ACUTE */,
579   0x00EE /* 0xEE        LATIN SMALL LETTER I WITH CIRCUMFLEX */,
580   0x012B /* 0xEF        LATIN SMALL LETTER I WITH MACRON */,
581   0x0111 /* 0xF0        LATIN SMALL LETTER D WITH STROKE */,
582   0x0146 /* 0xF1        LATIN SMALL LETTER N WITH CEDILLA */,
583   0x014D /* 0xF2        LATIN SMALL LETTER O WITH MACRON */,
584   0x0137 /* 0xF3        LATIN SMALL LETTER K WITH CEDILLA */,
585   0x00F4 /* 0xF4        LATIN SMALL LETTER O WITH CIRCUMFLEX */,
586   0x00F5 /* 0xF5        LATIN SMALL LETTER O WITH TILDE */,
587   0x00F6 /* 0xF6        LATIN SMALL LETTER O WITH DIAERESIS */,
588   0x00F7 /* 0xF7        DIVISION SIGN */,
589   0x00F8 /* 0xF8        LATIN SMALL LETTER O WITH STROKE */,
590   0x0173 /* 0xF9        LATIN SMALL LETTER U WITH OGONEK */,
591   0x00FA /* 0xFA        LATIN SMALL LETTER U WITH ACUTE */,
592   0x00FB /* 0xFB        LATIN SMALL LETTER U WITH CIRCUMFLEX */,
593   0x00FC /* 0xFC        LATIN SMALL LETTER U WITH DIAERESIS */,
594   0x0169 /* 0xFD        LATIN SMALL LETTER U WITH TILDE */,
595   0x016B /* 0xFE        LATIN SMALL LETTER U WITH MACRON */,
596   0x02D9 /* 0xFF        DOT ABOVE */
597 };
598
599 Emchar latin_iso8859_9_to_ucs[96] =
600 {
601   0x00A0 /* 0xA0        NO-BREAK SPACE */,
602   0x00A1 /* 0xA1        INVERTED EXCLAMATION MARK */,
603   0x00A2 /* 0xA2        CENT SIGN */,
604   0x00A3 /* 0xA3        POUND SIGN */,
605   0x00A4 /* 0xA4        CURRENCY SIGN */,
606   0x00A5 /* 0xA5        YEN SIGN */,
607   0x00A6 /* 0xA6        BROKEN BAR */,
608   0x00A7 /* 0xA7        SECTION SIGN */,
609   0x00A8 /* 0xA8        DIAERESIS */,
610   0x00A9 /* 0xA9        COPYRIGHT SIGN */,
611   0x00AA /* 0xAA        FEMININE ORDINAL INDICATOR */,
612   0x00AB /* 0xAB        LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */,
613   0x00AC /* 0xAC        NOT SIGN */,
614   0x00AD /* 0xAD        SOFT HYPHEN */,
615   0x00AE /* 0xAE        REGISTERED SIGN */,
616   0x00AF /* 0xAF        MACRON */,
617   0x00B0 /* 0xB0        DEGREE SIGN */,
618   0x00B1 /* 0xB1        PLUS-MINUS SIGN */,
619   0x00B2 /* 0xB2        SUPERSCRIPT TWO */,
620   0x00B3 /* 0xB3        SUPERSCRIPT THREE */,
621   0x00B4 /* 0xB4        ACUTE ACCENT */,
622   0x00B5 /* 0xB5        MICRO SIGN */,
623   0x00B6 /* 0xB6        PILCROW SIGN */,
624   0x00B7 /* 0xB7        MIDDLE DOT */,
625   0x00B8 /* 0xB8        CEDILLA */,
626   0x00B9 /* 0xB9        SUPERSCRIPT ONE */,
627   0x00BA /* 0xBA        MASCULINE ORDINAL INDICATOR */,
628   0x00BB /* 0xBB        RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */,
629   0x00BC /* 0xBC        VULGAR FRACTION ONE QUARTER */,
630   0x00BD /* 0xBD        VULGAR FRACTION ONE HALF */,
631   0x00BE /* 0xBE        VULGAR FRACTION THREE QUARTERS */,
632   0x00BF /* 0xBF        INVERTED QUESTION MARK */,
633   0x00C0 /* 0xC0        LATIN CAPITAL LETTER A WITH GRAVE */,
634   0x00C1 /* 0xC1        LATIN CAPITAL LETTER A WITH ACUTE */,
635   0x00C2 /* 0xC2        LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
636   0x00C3 /* 0xC3        LATIN CAPITAL LETTER A WITH TILDE */,
637   0x00C4 /* 0xC4        LATIN CAPITAL LETTER A WITH DIAERESIS */,
638   0x00C5 /* 0xC5        LATIN CAPITAL LETTER A WITH RING ABOVE */,
639   0x00C6 /* 0xC6        LATIN CAPITAL LETTER AE */,
640   0x00C7 /* 0xC7        LATIN CAPITAL LETTER C WITH CEDILLA */,
641   0x00C8 /* 0xC8        LATIN CAPITAL LETTER E WITH GRAVE */,
642   0x00C9 /* 0xC9        LATIN CAPITAL LETTER E WITH ACUTE */,
643   0x00CA /* 0xCA        LATIN CAPITAL LETTER E WITH CIRCUMFLEX */,
644   0x00CB /* 0xCB        LATIN CAPITAL LETTER E WITH DIAERESIS */,
645   0x00CC /* 0xCC        LATIN CAPITAL LETTER I WITH GRAVE */,
646   0x00CD /* 0xCD        LATIN CAPITAL LETTER I WITH ACUTE */,
647   0x00CE /* 0xCE        LATIN CAPITAL LETTER I WITH CIRCUMFLEX */,
648   0x00CF /* 0xCF        LATIN CAPITAL LETTER I WITH DIAERESIS */,
649   0x011E /* 0xD0        LATIN CAPITAL LETTER G WITH BREVE */,
650   0x00D1 /* 0xD1        LATIN CAPITAL LETTER N WITH TILDE */,
651   0x00D2 /* 0xD2        LATIN CAPITAL LETTER O WITH GRAVE */,
652   0x00D3 /* 0xD3        LATIN CAPITAL LETTER O WITH ACUTE */,
653   0x00D4 /* 0xD4        LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
654   0x00D5 /* 0xD5        LATIN CAPITAL LETTER O WITH TILDE */,
655   0x00D6 /* 0xD6        LATIN CAPITAL LETTER O WITH DIAERESIS */,
656   0x00D7 /* 0xD7        MULTIPLICATION SIGN */,
657   0x00D8 /* 0xD8        LATIN CAPITAL LETTER O WITH STROKE */,
658   0x00D9 /* 0xD9        LATIN CAPITAL LETTER U WITH GRAVE */,
659   0x00DA /* 0xDA        LATIN CAPITAL LETTER U WITH ACUTE */,
660   0x00DB /* 0xDB        LATIN CAPITAL LETTER U WITH CIRCUMFLEX */,
661   0x00DC /* 0xDC        LATIN CAPITAL LETTER U WITH DIAERESIS */,
662   0x0130 /* 0xDD        LATIN CAPITAL LETTER I WITH DOT ABOVE */,
663   0x015E /* 0xDE        LATIN CAPITAL LETTER S WITH CEDILLA */,
664   0x00DF /* 0xDF        LATIN SMALL LETTER SHARP S */,
665   0x00E0 /* 0xE0        LATIN SMALL LETTER A WITH GRAVE */,
666   0x00E1 /* 0xE1        LATIN SMALL LETTER A WITH ACUTE */,
667   0x00E2 /* 0xE2        LATIN SMALL LETTER A WITH CIRCUMFLEX */,
668   0x00E3 /* 0xE3        LATIN SMALL LETTER A WITH TILDE */,
669   0x00E4 /* 0xE4        LATIN SMALL LETTER A WITH DIAERESIS */,
670   0x00E5 /* 0xE5        LATIN SMALL LETTER A WITH RING ABOVE */,
671   0x00E6 /* 0xE6        LATIN SMALL LETTER AE */,
672   0x00E7 /* 0xE7        LATIN SMALL LETTER C WITH CEDILLA */,
673   0x00E8 /* 0xE8        LATIN SMALL LETTER E WITH GRAVE */,
674   0x00E9 /* 0xE9        LATIN SMALL LETTER E WITH ACUTE */,
675   0x00EA /* 0xEA        LATIN SMALL LETTER E WITH CIRCUMFLEX */,
676   0x00EB /* 0xEB        LATIN SMALL LETTER E WITH DIAERESIS */,
677   0x00EC /* 0xEC        LATIN SMALL LETTER I WITH GRAVE */,
678   0x00ED /* 0xED        LATIN SMALL LETTER I WITH ACUTE */,
679   0x00EE /* 0xEE        LATIN SMALL LETTER I WITH CIRCUMFLEX */,
680   0x00EF /* 0xEF        LATIN SMALL LETTER I WITH DIAERESIS */,
681   0x011F /* 0xF0        LATIN SMALL LETTER G WITH BREVE */,
682   0x00F1 /* 0xF1        LATIN SMALL LETTER N WITH TILDE */,
683   0x00F2 /* 0xF2        LATIN SMALL LETTER O WITH GRAVE */,
684   0x00F3 /* 0xF3        LATIN SMALL LETTER O WITH ACUTE */,
685   0x00F4 /* 0xF4        LATIN SMALL LETTER O WITH CIRCUMFLEX */,
686   0x00F5 /* 0xF5        LATIN SMALL LETTER O WITH TILDE */,
687   0x00F6 /* 0xF6        LATIN SMALL LETTER O WITH DIAERESIS */,
688   0x00F7 /* 0xF7        DIVISION SIGN */,
689   0x00F8 /* 0xF8        LATIN SMALL LETTER O WITH STROKE */,
690   0x00F9 /* 0xF9        LATIN SMALL LETTER U WITH GRAVE */,
691   0x00FA /* 0xFA        LATIN SMALL LETTER U WITH ACUTE */,
692   0x00FB /* 0xFB        LATIN SMALL LETTER U WITH CIRCUMFLEX */,
693   0x00FC /* 0xFC        LATIN SMALL LETTER U WITH DIAERESIS */,
694   0x0131 /* 0xFD        LATIN SMALL LETTER DOTLESS I */,
695   0x015F /* 0xFE        LATIN SMALL LETTER S WITH CEDILLA */,
696   0x00FF /* 0xFF        LATIN SMALL LETTER Y WITH DIAERESIS */,
697 };
698
699 Emchar latin_viscii_lower_to_ucs[96] =
700 {
701   CHAR96('1', 0x20),
702   0x1eaf /* 0x21 */,
703   0x1eb1 /* 0x22 */,
704   0x1eb7 /* 0x23 */,
705   0x1ea5 /* 0x24 */,
706   0x1ea7 /* 0x25 */,
707   0x1ea9 /* 0x26 */,
708   0x1ead /* 0x27 */,
709   0x1ebd /* 0x28 */,
710   0x1eb9 /* 0x29 */,
711   0x1ebf /* 0x2a */,
712   0x1ec1 /* 0x2b */,
713   0x1ec3 /* 0x2c */,
714   0x1ec5 /* 0x2d */,
715   0x1ec7 /* 0x2e */,
716   0x1ed1 /* 0x2f */,
717   0x1ed3 /* 0x30 */,
718   0x1ed5 /* 0x31 */,
719   0x1ed7 /* 0x32 */,
720   CHAR96('1', 0x33),
721   CHAR96('1', 0x34),
722   0x1ed9 /* 0x35 */,
723   0x1edd /* 0x36 */,
724   0x1edf /* 0x37 */,
725   0x1ecb /* 0x38 */,
726   CHAR96('1', 0x39),
727   CHAR96('1', 0x3A),
728   CHAR96('1', 0x3B),
729   CHAR96('1', 0x3C),
730   0x01a1 /* 0x3d */,
731   0x1edb /* 0x3e */,
732   CHAR96('1', 0x3F),
733   CHAR96('1', 0x40),
734   CHAR96('1', 0x41),
735   CHAR96('1', 0x42),
736   CHAR96('1', 0x43),
737   CHAR96('1', 0x44),
738   CHAR96('1', 0x45),
739   0x1eb3 /* 0x46 */,
740   0x1eb5 /* 0x47 */,
741   CHAR96('1', 0x48),
742   CHAR96('1', 0x49),
743   CHAR96('1', 0x4A),
744   CHAR96('1', 0x4B),
745   CHAR96('1', 0x4C),
746   CHAR96('1', 0x4D),
747   CHAR96('1', 0x4E),
748   0x1ef3 /* 0x4f */,
749   CHAR96('1', 0x50),
750   0x1ee9 /* 0x51 */,
751   CHAR96('1', 0x52),
752   CHAR96('1', 0x53),
753   CHAR96('1', 0x54),
754   0x1ea1 /* 0x55 */,
755   0x1ef7 /* 0x56 */,
756   0x1eeb /* 0x57 */,
757   0x1eed /* 0x58 */,
758   CHAR96('1', 0x59),
759   CHAR96('1', 0x5A),
760   0x1ef9 /* 0x5b */,
761   0x1ef5 /* 0x5c */,
762   CHAR96('1', 0x5D),
763   0x1ee1 /* 0x5e */,
764   0x01b0 /* 0x5f */,
765   0x00e0 /* 0x60 */,
766   0x00e1 /* 0x61 */,
767   0x00e2 /* 0x62 */,
768   0x00e3 /* 0x63 */,
769   0x1ea3 /* 0x64 */,
770   0x0103 /* 0x65 */,
771   0x1eef /* 0x66 */,
772   0x1eab /* 0x67 */,
773   0x00e8 /* 0x68 */,
774   0x00e9 /* 0x69 */,
775   0x00ea /* 0x6a */,
776   0x1ebb /* 0x6b */,
777   0x00ec /* 0x6c */,
778   0x00ed /* 0x6d */,
779   0x0129 /* 0x6e */,
780   0x1ec9 /* 0x6f */,
781   0x0111 /* 0x70 */,
782   0x1ef1 /* 0x71 */,
783   0x00f2 /* 0x72 */,
784   0x00f3 /* 0x73 */,
785   0x00f4 /* 0x74 */,
786   0x00f5 /* 0x75 */,
787   0x1ecf /* 0x76 */,
788   0x1ecd /* 0x77 */,
789   0x1ee5 /* 0x78 */,
790   0x00f9 /* 0x79 */,
791   0x00fa /* 0x7a */,
792   0x0169 /* 0x7b */,
793   0x1ee7 /* 0x7c */,
794   0x00fd /* 0x7d */,
795   0x1ee3 /* 0x7e */,
796   CHAR96('1', 0x7F)
797 };
798
799 Emchar latin_viscii_upper_to_ucs[96] =
800 {
801   CHAR96('2', 0x20),
802   0x1eae /* 0x21 */,
803   0x1eb0 /* 0x22 */,
804   0x1eb6 /* 0x23 */,
805   0x1ea4 /* 0x24 */,
806   0x1ea6 /* 0x25 */,
807   0x1ea8 /* 0x26 */,
808   0x1eac /* 0x27 */,
809   0x1ebc /* 0x28 */,
810   0x1eb8 /* 0x29 */,
811   0x1ebe /* 0x2a */,
812   0x1ec0 /* 0x2b */,
813   0x1ec2 /* 0x2c */,
814   0x1ec4 /* 0x2d */,
815   0x1ec6 /* 0x2e */,
816   0x1ed0 /* 0x2f */,
817   0x1ed2 /* 0x30 */,
818   0x1ed4 /* 0x31 */,
819   0x1ed6 /* 0x32 */,
820   CHAR96('2', 0x33),
821   CHAR96('2', 0x34),
822   0x1ed8 /* 0x35 */,
823   0x1edc /* 0x36 */,
824   0x1ede /* 0x37 */,
825   0x1eca /* 0x38 */,
826   CHAR96('2', 0x39),
827   CHAR96('2', 0x3a),
828   CHAR96('2', 0x3b),
829   CHAR96('2', 0x3c),
830   0x01a0 /* 0x3d */,
831   0x1eda /* 0x3e */,
832   CHAR96('2', 0x3f),
833   CHAR96('2', 0x40),
834   CHAR96('2', 0x41),
835   CHAR96('2', 0x42),
836   CHAR96('2', 0x43),
837   CHAR96('2', 0x44),
838   CHAR96('2', 0x45),
839   0x1eb2 /* 0x46 */,
840   0x1eb4 /* 0x47 */,
841   CHAR96('2', 0x48),
842   CHAR96('2', 0x49),
843   CHAR96('2', 0x4a),
844   CHAR96('2', 0x4b),
845   CHAR96('2', 0x4c),
846   CHAR96('2', 0x4d),
847   CHAR96('2', 0x4e),
848   0x1ef2 /* 0x4f */,
849   CHAR96('2', 0x50),
850   0x1ee8 /* 0x51 */,
851   CHAR96('2', 0x52),
852   CHAR96('2', 0x53),
853   CHAR96('2', 0x54),
854   0x1ea0 /* 0x55 */,
855   0x1ef6 /* 0x56 */,
856   0x1eea /* 0x57 */,
857   0x1eec /* 0x58 */,
858   CHAR96('2', 0x59),
859   CHAR96('2', 0x5a),
860   0x1ef8 /* 0x5b */,
861   0x1ef4 /* 0x5c */,
862   CHAR96('2', 0x5d),
863   0x1ee0 /* 0x5e */,
864   0x01af /* 0x5f */,
865   0x00c0 /* 0x60 */,
866   0x00c1 /* 0x61 */,
867   0x00c2 /* 0x62 */,
868   0x00c3 /* 0x63 */,
869   0x1ea2 /* 0x64 */,
870   0x0102 /* 0x65 */,
871   0x1eee /* 0x66 */,
872   0x1eaa /* 0x67 */,
873   0x00c8 /* 0x68 */,
874   0x00c9 /* 0x69 */,
875   0x00ca /* 0x6a */,
876   0x1eba /* 0x6b */,
877   0x00cc /* 0x6c */,
878   0x00cd /* 0x6d */,
879   0x0128 /* 0x6e */,
880   0x1ec8 /* 0x6f */,
881   0x0110 /* 0x70 */,
882   0x1ef0 /* 0x71 */,
883   0x00d2 /* 0x72 */,
884   0x00d3 /* 0x73 */,
885   0x00d4 /* 0x74 */,
886   0x00d5 /* 0x75 */,
887   0x1ece /* 0x76 */,
888   0x1ecc /* 0x77 */,
889   0x1ee4 /* 0x78 */,
890   0x00d9 /* 0x79 */,
891   0x00da /* 0x7a */,
892   0x0168 /* 0x7b */,
893   0x1ee6 /* 0x7c */,
894   0x00dd /* 0x7d */,
895   0x1ee2 /* 0x7e */,
896   CHAR96('2', 0x7f)
897 };
898
899 Emchar latin_tcvn5712_to_ucs[96] =
900 {
901   0x00A0 /* 0xA0  NO-BREAK SPACE */,
902   0x0102 /* 0xA1  LATIN CAPITAL LETTER A WITH BREVE */,
903   0x00C2 /* 0xA2  LATIN CAPITAL LETTER A WITH CIRCUMFLEX */,
904   0x00CA /* 0xA3  LATIN CAPITAL LETTER E WITH CIRCUMFLEX */,
905   0x00D4 /* 0xA4  LATIN CAPITAL LETTER O WITH CIRCUMFLEX */,
906   0x01A0 /* 0xA5  LATIN CAPITAL LETTER O WITH HORN */,
907   0x01AF /* 0xA6  LATIN CAPITAL LETTER U WITH HORN */,
908   0x0110 /* 0xA7  LATIN CAPITAL LETTER D WITH STROKE */,
909   0x0103 /* 0xA8  LATIN SMALL LETTER A WITH BREVE */,
910   0x00E2 /* 0xA9  LATIN SMALL LETTER A WITH CIRCUMFLEX */,
911   0x00EA /* 0xAA  LATIN SMALL LETTER E WITH CIRCUMFLEX */,
912   0x00F4 /* 0xAB  LATIN SMALL LETTER O WITH CIRCUMFLEX */,
913   0x01A1 /* 0xAC  LATIN SMALL LETTER O WITH HORN */,
914   0x01B0 /* 0xAD  LATIN SMALL LETTER U WITH HORN */,
915   0x0111 /* 0xAE  LATIN SMALL LETTER D WITH STROKE */,
916   0x1EB0 /* 0xAF  LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */,
917   0x0300 /* 0xB0  COMBINING GRAVE ACCENT */,
918   0x0309 /* 0xB1  COMBINING HOOK ABOVE */,
919   0x0303 /* 0xB2  COMBINING TILDE */,
920   0x0301 /* 0xB3  COMBINING ACUTE ACCENT */,
921   0x0323 /* 0xB4  COMBINING DOT BELOW */,
922   0x00E0 /* 0xB5  LATIN SMALL LETTER A WITH GRAVE */,
923   0x1EA3 /* 0xB6  LATIN SMALL LETTER A WITH HOOK ABOVE */,
924   0x00E3 /* 0xB7  LATIN SMALL LETTER A WITH TILDE */,
925   0x00E1 /* 0xB8  LATIN SMALL LETTER A WITH ACUTE */,
926   0x1EA1 /* 0xB9  LATIN SMALL LETTER A WITH DOT BELOW */,
927   0x1EB2 /* 0xBA  LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */,
928   0x1EB1 /* 0xBB  LATIN SMALL LETTER A WITH BREVE AND GRAVE */,
929   0x1EB3 /* 0xBC  LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */,
930   0x1EB5 /* 0xBD  LATIN SMALL LETTER A WITH BREVE AND TILDE */,
931   0x1EAF /* 0xBE  LATIN SMALL LETTER A WITH BREVE AND ACUTE */,
932   0x1EB4 /* 0xBF  LATIN CAPITAL LETTER A WITH BREVE AND TILDE */,
933   0x1EAE /* 0xC0  LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */,
934   0x1EA6 /* 0xC1  LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */,
935   0x1EA8 /* 0xC2  LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */,
936   0x1EAA /* 0xC3  LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */,
937   0x1EA4 /* 0xC4  LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */,
938   0x1EC0 /* 0xC5  LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */,
939   0x1EB7 /* 0xC6  LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */,
940   0x1EA7 /* 0xC7  LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */,
941   0x1EA9 /* 0xC8  LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */,
942   0x1EAB /* 0xC9  LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */,
943   0x1EA5 /* 0xCA  LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */,
944   0x1EAD /* 0xCB  LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */,
945   0x00E8 /* 0xCC  LATIN SMALL LETTER E WITH GRAVE */,
946   0x1EC2 /* 0xCD  LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */,
947   0x1EBB /* 0xCE  LATIN SMALL LETTER E WITH HOOK ABOVE */,
948   0x1EBD /* 0xCF  LATIN SMALL LETTER E WITH TILDE */,
949   0x00E9 /* 0xD0  LATIN SMALL LETTER E WITH ACUTE */,
950   0x1EB9 /* 0xD1  LATIN SMALL LETTER E WITH DOT BELOW */,
951   0x1EC1 /* 0xD2  LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */,
952   0x1EC3 /* 0xD3  LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */,
953   0x1EC5 /* 0xD4  LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */,
954   0x1EBF /* 0xD5  LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */,
955   0x1EC7 /* 0xD6  LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */,
956   0x00EC /* 0xD7  LATIN SMALL LETTER I WITH GRAVE */,
957   0x1EC9 /* 0xD8  LATIN SMALL LETTER I WITH HOOK ABOVE */,
958   0x1EC4 /* 0xD9  LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */,
959   0x1EBE /* 0xDA  LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */,
960   0x1ED2 /* 0xDB  LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */,
961   0x0129 /* 0xDC  LATIN SMALL LETTER I WITH TILDE */,
962   0x00ED /* 0xDD  LATIN SMALL LETTER I WITH ACUTE */,
963   0x1ECB /* 0xDE  LATIN SMALL LETTER I WITH DOT BELOW */,
964   0x00F2 /* 0xDF  LATIN SMALL LETTER O WITH GRAVE */,
965   0x1ED4 /* 0xE0  LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */,
966   0x1ECF /* 0xE1  LATIN SMALL LETTER O WITH HOOK ABOVE */,
967   0x00F5 /* 0xE2  LATIN SMALL LETTER O WITH TILDE */,
968   0x00F3 /* 0xE3  LATIN SMALL LETTER O WITH ACUTE */,
969   0x1ECD /* 0xE4  LATIN SMALL LETTER O WITH DOT BELOW */,
970   0x1ED3 /* 0xE5  LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */,
971   0x1ED5 /* 0xE6  LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */,
972   0x1ED7 /* 0xE7  LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */,
973   0x1ED1 /* 0xE8  LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */,
974   0x1ED9 /* 0xE9  LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */,
975   0x1EDD /* 0xEA  LATIN SMALL LETTER O WITH HORN AND GRAVE */,
976   0x1EDF /* 0xEB  LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */,
977   0x1EE1 /* 0xEC  LATIN SMALL LETTER O WITH HORN AND TILDE */,
978   0x1EDB /* 0xED  LATIN SMALL LETTER O WITH HORN AND ACUTE */,
979   0x1EE3 /* 0xEE  LATIN SMALL LETTER O WITH HORN AND DOT BELOW */,
980   0x00F9 /* 0xEF  LATIN SMALL LETTER U WITH GRAVE */,
981   0x1ED6 /* 0xF0  LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */,
982   0x1EE7 /* 0xF1  LATIN SMALL LETTER U WITH HOOK ABOVE */,
983   0x0169 /* 0xF2  LATIN SMALL LETTER U WITH TILDE */,
984   0x00FA /* 0xF3  LATIN SMALL LETTER U WITH ACUTE */,
985   0x1EE5 /* 0xF4  LATIN SMALL LETTER U WITH DOT BELOW */,
986   0x1EEB /* 0xF5  LATIN SMALL LETTER U WITH HORN AND GRAVE */,
987   0x1EED /* 0xF6  LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */,
988   0x1EEF /* 0xF7  LATIN SMALL LETTER U WITH HORN AND TILDE */,
989   0x1EE9 /* 0xF8  LATIN SMALL LETTER U WITH HORN AND ACUTE */,
990   0x1EF1 /* 0xF9  LATIN SMALL LETTER U WITH HORN AND DOT BELOW */,
991   0x1EF3 /* 0xFA  LATIN SMALL LETTER Y WITH GRAVE */,
992   0x1EF7 /* 0xFB  LATIN SMALL LETTER Y WITH HOOK ABOVE */,
993   0x1EF9 /* 0xFC  LATIN SMALL LETTER Y WITH TILDE */,
994   0x00FD /* 0xFD  LATIN SMALL LETTER Y WITH ACUTE */,
995   0x1EF5 /* 0xFE  LATIN SMALL LETTER Y WITH DOT BELOW */,
996   0x1ED0 /* 0xFF  LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */
997 };
998
999 Lisp_Object Vutf_2000_version;
1000 #endif
1001
1002 #ifndef UTF2000
1003 int leading_code_private_11;
1004 #endif
1005
1006 Lisp_Object Qcharsetp;
1007
1008 /* Qdoc_string, Qdimension, Qchars defined in general.c */
1009 Lisp_Object Qregistry, Qfinal, Qgraphic;
1010 Lisp_Object Qdirection;
1011 Lisp_Object Qreverse_direction_charset;
1012 Lisp_Object Qleading_byte;
1013 Lisp_Object Qshort_name, Qlong_name;
1014
1015 Lisp_Object Qascii,
1016   Qcontrol_1,
1017   Qlatin_iso8859_1,
1018   Qlatin_iso8859_2,
1019   Qlatin_iso8859_3,
1020   Qlatin_iso8859_4,
1021   Qthai_tis620,
1022   Qgreek_iso8859_7,
1023   Qarabic_iso8859_6,
1024   Qhebrew_iso8859_8,
1025   Qkatakana_jisx0201,
1026   Qlatin_jisx0201,
1027   Qcyrillic_iso8859_5,
1028   Qlatin_iso8859_9,
1029   Qjapanese_jisx0208_1978,
1030   Qchinese_gb2312,
1031   Qjapanese_jisx0208,
1032   Qkorean_ksc5601,
1033   Qjapanese_jisx0212,
1034   Qchinese_cns11643_1,
1035   Qchinese_cns11643_2,
1036 #ifdef UTF2000
1037   Qchinese_cns11643_3,
1038   Qchinese_cns11643_4,
1039   Qchinese_cns11643_5,
1040   Qchinese_cns11643_6,
1041   Qchinese_cns11643_7,
1042   Qucs_bmp,
1043   Qlatin_viscii_lower,
1044   Qlatin_viscii_upper,
1045 #endif
1046   Qchinese_big5_1,
1047   Qchinese_big5_2,
1048   Qcomposite;
1049
1050 Lisp_Object Ql2r, Qr2l;
1051
1052 Lisp_Object Vcharset_hash_table;
1053
1054 static Charset_ID next_allocated_1_byte_leading_byte;
1055 static Charset_ID next_allocated_2_byte_leading_byte;
1056
1057 /* Composite characters are characters constructed by overstriking two
1058    or more regular characters.
1059
1060    1) The old Mule implementation involves storing composite characters
1061       in a buffer as a tag followed by all of the actual characters
1062       used to make up the composite character.  I think this is a bad
1063       idea; it greatly complicates code that wants to handle strings
1064       one character at a time because it has to deal with the possibility
1065       of great big ungainly characters.  It's much more reasonable to
1066       simply store an index into a table of composite characters.
1067
1068    2) The current implementation only allows for 16,384 separate
1069       composite characters over the lifetime of the XEmacs process.
1070       This could become a potential problem if the user
1071       edited lots of different files that use composite characters.
1072       Due to FSF bogosity, increasing the number of allowable
1073       composite characters under Mule would decrease the number
1074       of possible faces that can exist.  Mule already has shrunk
1075       this to 2048, and further shrinkage would become uncomfortable.
1076       No such problems exist in XEmacs.
1077
1078       Composite characters could be represented as 0x80 C1 C2 C3,
1079       where each C[1-3] is in the range 0xA0 - 0xFF.  This allows
1080       for slightly under 2^20 (one million) composite characters
1081       over the XEmacs process lifetime, and you only need to
1082       increase the size of a Mule character from 19 to 21 bits.
1083       Or you could use 0x80 C1 C2 C3 C4, allowing for about
1084       85 million (slightly over 2^26) composite characters. */
1085
1086 \f
1087 /************************************************************************/
1088 /*                       Basic Emchar functions                         */
1089 /************************************************************************/
1090
1091 /* Convert a non-ASCII Mule character C into a one-character Mule-encoded
1092    string in STR.  Returns the number of bytes stored.
1093    Do not call this directly.  Use the macro set_charptr_emchar() instead.
1094  */
1095
1096 Bytecount
1097 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
1098 {
1099   Bufbyte *p;
1100 #ifndef UTF2000
1101   Charset_ID lb;
1102   int c1, c2;
1103   Lisp_Object charset;
1104 #endif
1105
1106   p = str;
1107 #ifdef UTF2000
1108   if ( c <= 0x7f )
1109     {
1110       *p++ = c;
1111     }
1112   else if ( c <= 0x7ff )
1113     {
1114       *p++ = (c >> 6) | 0xc0;
1115       *p++ = (c & 0x3f) | 0x80;
1116     }
1117   else if ( c <= 0xffff )
1118     {
1119       *p++ =  (c >> 12) | 0xe0;
1120       *p++ = ((c >>  6) & 0x3f) | 0x80;
1121       *p++ =  (c        & 0x3f) | 0x80;
1122     }
1123   else if ( c <= 0x1fffff )
1124     {
1125       *p++ =  (c >> 18) | 0xf0;
1126       *p++ = ((c >> 12) & 0x3f) | 0x80;
1127       *p++ = ((c >>  6) & 0x3f) | 0x80;
1128       *p++ =  (c        & 0x3f) | 0x80;
1129     }
1130   else if ( c <= 0x3ffffff )
1131     {
1132       *p++ =  (c >> 24) | 0xf8;
1133       *p++ = ((c >> 18) & 0x3f) | 0x80;
1134       *p++ = ((c >> 12) & 0x3f) | 0x80;
1135       *p++ = ((c >>  6) & 0x3f) | 0x80;
1136       *p++ =  (c        & 0x3f) | 0x80;
1137     }
1138   else
1139     {
1140       *p++ =  (c >> 30) | 0xfc;
1141       *p++ = ((c >> 24) & 0x3f) | 0x80;
1142       *p++ = ((c >> 18) & 0x3f) | 0x80;
1143       *p++ = ((c >> 12) & 0x3f) | 0x80;
1144       *p++ = ((c >>  6) & 0x3f) | 0x80;
1145       *p++ =  (c        & 0x3f) | 0x80;
1146     }
1147 #else
1148   BREAKUP_CHAR (c, charset, c1, c2);
1149   lb = CHAR_LEADING_BYTE (c);
1150   if (LEADING_BYTE_PRIVATE_P (lb))
1151     *p++ = PRIVATE_LEADING_BYTE_PREFIX (lb);
1152   *p++ = lb;
1153   if (EQ (charset, Vcharset_control_1))
1154     c1 += 0x20;
1155   *p++ = c1 | 0x80;
1156   if (c2)
1157     *p++ = c2 | 0x80;
1158 #endif
1159   return (p - str);
1160 }
1161
1162 /* Return the first character from a Mule-encoded string in STR,
1163    assuming it's non-ASCII.  Do not call this directly.
1164    Use the macro charptr_emchar() instead. */
1165
1166 Emchar
1167 non_ascii_charptr_emchar (CONST Bufbyte *str)
1168 {
1169 #ifdef UTF2000
1170   Bufbyte b;
1171   Emchar ch;
1172   int len;
1173
1174   b = *str++;
1175   if ( b >= 0xfc )
1176     {
1177       ch = (b & 0x01);
1178       len = 5;
1179     }
1180   else if ( b >= 0xf8 )
1181     {
1182       ch = b & 0x03;
1183       len = 4;
1184     }
1185   else if ( b >= 0xf0 )
1186     {
1187       ch = b & 0x07;
1188       len = 3;
1189     }
1190   else if ( b >= 0xe0 )
1191     {
1192       ch = b & 0x0f;
1193       len = 2;
1194     }
1195   else if ( b >= 0xc0 )
1196     {
1197       ch = b & 0x1f;
1198       len = 1;
1199     }
1200   else
1201     {
1202       ch = b;
1203       len = 0;
1204     }
1205   for( ; len > 0; len-- )
1206     {
1207       b = *str++;
1208       ch = ( ch << 6 ) | ( b & 0x3f );
1209     }
1210   return ch;
1211 #else
1212   Bufbyte i0 = *str, i1, i2 = 0;
1213   Lisp_Object charset;
1214
1215   if (i0 == LEADING_BYTE_CONTROL_1)
1216     return (Emchar) (*++str - 0x20);
1217
1218   if (LEADING_BYTE_PREFIX_P (i0))
1219     i0 = *++str;
1220
1221   i1 = *++str & 0x7F;
1222
1223   charset = CHARSET_BY_LEADING_BYTE (i0);
1224   if (XCHARSET_DIMENSION (charset) == 2)
1225     i2 = *++str & 0x7F;
1226
1227   return MAKE_CHAR (charset, i1, i2);
1228 #endif
1229 }
1230
1231 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
1232    Do not call this directly.  Use the macro valid_char_p() instead. */
1233
1234 #ifndef UTF2000
1235 int
1236 non_ascii_valid_char_p (Emchar ch)
1237 {
1238   int f1, f2, f3;
1239
1240   /* Must have only lowest 19 bits set */
1241   if (ch & ~0x7FFFF)
1242     return 0;
1243
1244   f1 = CHAR_FIELD1 (ch);
1245   f2 = CHAR_FIELD2 (ch);
1246   f3 = CHAR_FIELD3 (ch);
1247
1248   if (f1 == 0)
1249     {
1250       Lisp_Object charset;
1251
1252       if (f2 < MIN_CHAR_FIELD2_OFFICIAL ||
1253           (f2 > MAX_CHAR_FIELD2_OFFICIAL && f2 < MIN_CHAR_FIELD2_PRIVATE) ||
1254            f2 > MAX_CHAR_FIELD2_PRIVATE)
1255         return 0;
1256       if (f3 < 0x20)
1257         return 0;
1258
1259       if (f3 != 0x20 && f3 != 0x7F)
1260         return 1;
1261
1262       /*
1263          NOTE: This takes advantage of the fact that
1264          FIELD2_TO_OFFICIAL_LEADING_BYTE and
1265          FIELD2_TO_PRIVATE_LEADING_BYTE are the same.
1266          */
1267       charset = CHARSET_BY_LEADING_BYTE (f2 + FIELD2_TO_OFFICIAL_LEADING_BYTE);
1268       return (XCHARSET_CHARS (charset) == 96);
1269     }
1270   else
1271     {
1272       Lisp_Object charset;
1273
1274       if (f1 < MIN_CHAR_FIELD1_OFFICIAL ||
1275           (f1 > MAX_CHAR_FIELD1_OFFICIAL && f1 < MIN_CHAR_FIELD1_PRIVATE) ||
1276           f1 > MAX_CHAR_FIELD1_PRIVATE)
1277         return 0;
1278       if (f2 < 0x20 || f3 < 0x20)
1279         return 0;
1280
1281 #ifdef ENABLE_COMPOSITE_CHARS
1282       if (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE == LEADING_BYTE_COMPOSITE)
1283         {
1284           if (UNBOUNDP (Fgethash (make_int (ch),
1285                                   Vcomposite_char_char2string_hash_table,
1286                                   Qunbound)))
1287             return 0;
1288           return 1;
1289         }
1290 #endif /* ENABLE_COMPOSITE_CHARS */
1291
1292       if (f2 != 0x20 && f2 != 0x7F && f3 != 0x20 && f3 != 0x7F)
1293         return 1;
1294
1295       if (f1 <= MAX_CHAR_FIELD1_OFFICIAL)
1296         charset =
1297           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE);
1298       else
1299         charset =
1300           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_PRIVATE_LEADING_BYTE);
1301
1302       return (XCHARSET_CHARS (charset) == 96);
1303     }
1304 }
1305 #endif
1306
1307 \f
1308 /************************************************************************/
1309 /*                       Basic string functions                         */
1310 /************************************************************************/
1311
1312 /* Copy the character pointed to by PTR into STR, assuming it's
1313    non-ASCII.  Do not call this directly.  Use the macro
1314    charptr_copy_char() instead. */
1315
1316 Bytecount
1317 non_ascii_charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *str)
1318 {
1319   Bufbyte *strptr = str;
1320   *strptr = *ptr++;
1321   switch (REP_BYTES_BY_FIRST_BYTE (*strptr))
1322     {
1323       /* Notice fallthrough. */
1324 #ifdef UTF2000
1325     case 6: *++strptr = *ptr++;
1326     case 5: *++strptr = *ptr++;
1327 #endif
1328     case 4: *++strptr = *ptr++;
1329     case 3: *++strptr = *ptr++;
1330     case 2: *++strptr = *ptr;
1331       break;
1332     default:
1333       abort ();
1334     }
1335   return strptr + 1 - str;
1336 }
1337
1338 \f
1339 /************************************************************************/
1340 /*                        streams of Emchars                            */
1341 /************************************************************************/
1342
1343 /* Treat a stream as a stream of Emchar's rather than a stream of bytes.
1344    The functions below are not meant to be called directly; use
1345    the macros in insdel.h. */
1346
1347 Emchar
1348 Lstream_get_emchar_1 (Lstream *stream, int ch)
1349 {
1350   Bufbyte str[MAX_EMCHAR_LEN];
1351   Bufbyte *strptr = str;
1352
1353   str[0] = (Bufbyte) ch;
1354   switch (REP_BYTES_BY_FIRST_BYTE (ch))
1355     {
1356       /* Notice fallthrough. */
1357 #ifdef UTF2000
1358     case 6:
1359       ch = Lstream_getc (stream);
1360       assert (ch >= 0);
1361       *++strptr = (Bufbyte) ch;
1362     case 5:
1363       ch = Lstream_getc (stream);
1364       assert (ch >= 0);
1365       *++strptr = (Bufbyte) ch;
1366 #endif
1367     case 4:
1368       ch = Lstream_getc (stream);
1369       assert (ch >= 0);
1370       *++strptr = (Bufbyte) ch;
1371     case 3:
1372       ch = Lstream_getc (stream);
1373       assert (ch >= 0);
1374       *++strptr = (Bufbyte) ch;
1375     case 2:
1376       ch = Lstream_getc (stream);
1377       assert (ch >= 0);
1378       *++strptr = (Bufbyte) ch;
1379       break;
1380     default:
1381       abort ();
1382     }
1383   return charptr_emchar (str);
1384 }
1385
1386 int
1387 Lstream_fput_emchar (Lstream *stream, Emchar ch)
1388 {
1389   Bufbyte str[MAX_EMCHAR_LEN];
1390   Bytecount len = set_charptr_emchar (str, ch);
1391   return Lstream_write (stream, str, len);
1392 }
1393
1394 void
1395 Lstream_funget_emchar (Lstream *stream, Emchar ch)
1396 {
1397   Bufbyte str[MAX_EMCHAR_LEN];
1398   Bytecount len = set_charptr_emchar (str, ch);
1399   Lstream_unread (stream, str, len);
1400 }
1401
1402 \f
1403 /************************************************************************/
1404 /*                            charset object                            */
1405 /************************************************************************/
1406
1407 static Lisp_Object
1408 mark_charset (Lisp_Object obj, void (*markobj) (Lisp_Object))
1409 {
1410   struct Lisp_Charset *cs = XCHARSET (obj);
1411
1412   markobj (cs->short_name);
1413   markobj (cs->long_name);
1414   markobj (cs->doc_string);
1415   markobj (cs->registry);
1416   markobj (cs->ccl_program);
1417   return cs->name;
1418 }
1419
1420 static void
1421 print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1422 {
1423   struct Lisp_Charset *cs = XCHARSET (obj);
1424   char buf[200];
1425
1426   if (print_readably)
1427     error ("printing unreadable object #<charset %s 0x%x>",
1428            string_data (XSYMBOL (CHARSET_NAME (cs))->name),
1429            cs->header.uid);
1430
1431   write_c_string ("#<charset ", printcharfun);
1432   print_internal (CHARSET_NAME (cs), printcharfun, 0);
1433   write_c_string (" ", printcharfun);
1434   print_internal (CHARSET_SHORT_NAME (cs), printcharfun, 1);
1435   write_c_string (" ", printcharfun);
1436   print_internal (CHARSET_LONG_NAME (cs), printcharfun, 1);
1437   write_c_string (" ", printcharfun);
1438   print_internal (CHARSET_DOC_STRING (cs), printcharfun, 1);
1439   sprintf (buf, " %s %s cols=%d g%d final='%c' reg=",
1440            CHARSET_TYPE (cs) == CHARSET_TYPE_94    ? "94" :
1441            CHARSET_TYPE (cs) == CHARSET_TYPE_96    ? "96" :
1442            CHARSET_TYPE (cs) == CHARSET_TYPE_94X94 ? "94x94" :
1443            "96x96",
1444            CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? "l2r" : "r2l",
1445            CHARSET_COLUMNS (cs),
1446            CHARSET_GRAPHIC (cs),
1447            CHARSET_FINAL (cs));
1448   write_c_string (buf, printcharfun);
1449   print_internal (CHARSET_REGISTRY (cs), printcharfun, 0);
1450   sprintf (buf, " 0x%x>", cs->header.uid);
1451   write_c_string (buf, printcharfun);
1452 }
1453
1454 static const struct lrecord_description charset_description[] = {
1455   { XD_LISP_OBJECT, offsetof(struct Lisp_Charset, name), 7 },
1456   { XD_END }
1457 };
1458
1459 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
1460                                mark_charset, print_charset, 0, 0, 0,
1461                                charset_description,
1462                                struct Lisp_Charset);
1463 /* Make a new charset. */
1464
1465 static Lisp_Object
1466 make_charset (Charset_ID id, Lisp_Object name,
1467               unsigned char type, unsigned char columns, unsigned char graphic,
1468               Bufbyte final, unsigned char direction, Lisp_Object short_name,
1469               Lisp_Object long_name, Lisp_Object doc,
1470               Lisp_Object reg,
1471               Emchar* decoding_table,
1472               Emchar ucs_min, Emchar ucs_max, Emchar code_offset)
1473 {
1474   Lisp_Object obj;
1475   struct Lisp_Charset *cs =
1476     alloc_lcrecord_type (struct Lisp_Charset, &lrecord_charset);
1477   XSETCHARSET (obj, cs);
1478
1479   CHARSET_ID            (cs) = id;
1480   CHARSET_NAME          (cs) = name;
1481   CHARSET_SHORT_NAME    (cs) = short_name;
1482   CHARSET_LONG_NAME     (cs) = long_name;
1483   CHARSET_DIRECTION     (cs) = direction;
1484   CHARSET_TYPE          (cs) = type;
1485   CHARSET_COLUMNS       (cs) = columns;
1486   CHARSET_GRAPHIC       (cs) = graphic;
1487   CHARSET_FINAL         (cs) = final;
1488   CHARSET_DOC_STRING    (cs) = doc;
1489   CHARSET_REGISTRY      (cs) = reg;
1490   CHARSET_CCL_PROGRAM   (cs) = Qnil;
1491   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
1492 #ifdef UTF2000
1493   CHARSET_DECODING_TABLE(cs) = decoding_table;
1494   CHARSET_UCS_MIN(cs) = ucs_min;
1495   CHARSET_UCS_MAX(cs) = ucs_max;
1496   CHARSET_CODE_OFFSET(cs) = code_offset;
1497 #endif
1498   
1499   switch ( CHARSET_TYPE (cs) )
1500     {
1501     case CHARSET_TYPE_94:
1502       CHARSET_DIMENSION (cs) = 1;
1503       CHARSET_CHARS (cs) = 94;
1504 #ifdef UTF2000
1505       if (decoding_table != NULL)
1506         {
1507           size_t i;
1508           CHARSET_TO_BYTE1_TABLE(cs) = make_byte_from_character_table();
1509           for (i = 0; i < 94; i++)
1510             {
1511               Emchar c = decoding_table[i];
1512
1513               if (c <= 0xffff)
1514                 put_byte_from_character_table (c, i + 33,
1515                                                CHARSET_TO_BYTE1_TABLE(cs));
1516             }
1517         }
1518       else
1519         CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1520       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1521 #endif
1522       break;
1523     case CHARSET_TYPE_96:
1524       CHARSET_DIMENSION (cs) = 1;
1525       CHARSET_CHARS (cs) = 96;
1526 #ifdef UTF2000
1527       if (decoding_table != NULL)
1528         {
1529           size_t i;
1530           CHARSET_TO_BYTE1_TABLE(cs) = make_byte_from_character_table();
1531           for (i = 0; i < 96; i++)
1532             {
1533               Emchar c = decoding_table[i];
1534
1535               if (c <= 0xffff)
1536                 put_byte_from_character_table (c, i + 32,
1537                                                CHARSET_TO_BYTE1_TABLE(cs));
1538             }
1539         }
1540       else
1541         CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1542       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1543 #endif
1544       break;
1545     case CHARSET_TYPE_94X94:
1546       CHARSET_DIMENSION (cs) = 2;
1547       CHARSET_CHARS (cs) = 94;
1548 #ifdef UTF2000
1549       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1550       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1551 #endif
1552       break;
1553     case CHARSET_TYPE_96X96:
1554       CHARSET_DIMENSION (cs) = 2;
1555       CHARSET_CHARS (cs) = 96;
1556 #ifdef UTF2000
1557       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1558       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1559 #endif
1560       break;
1561 #ifdef UTF2000
1562     case CHARSET_TYPE_128X128:
1563       CHARSET_DIMENSION (cs) = 2;
1564       CHARSET_CHARS (cs) = 128;
1565 #ifdef UTF2000
1566       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1567       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1568 #endif
1569       break;
1570     case CHARSET_TYPE_256X256:
1571       CHARSET_DIMENSION (cs) = 2;
1572       CHARSET_CHARS (cs) = 256;
1573 #ifdef UTF2000
1574       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1575       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1576 #endif
1577       break;
1578 #endif
1579     }
1580
1581 #ifndef UTF2000
1582   if (id == LEADING_BYTE_ASCII)
1583     CHARSET_REP_BYTES (cs) = 1;
1584   else if (id < 0xA0)
1585     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
1586   else
1587     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
1588 #endif
1589   
1590   if (final)
1591     {
1592       /* some charsets do not have final characters.  This includes
1593          ASCII, Control-1, Composite, and the two faux private
1594          charsets. */
1595 #if UTF2000
1596       assert (NILP (charset_by_attributes[type][final]));
1597       charset_by_attributes[type][final] = obj;
1598 #else
1599       assert (NILP (charset_by_attributes[type][final][direction]));
1600       charset_by_attributes[type][final][direction] = obj;
1601 #endif
1602     }
1603
1604   assert (NILP (charset_by_leading_byte[id - MIN_LEADING_BYTE]));
1605   charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
1606 #ifndef UTF2000
1607   if (id < 0xA0)
1608     /* official leading byte */
1609     rep_bytes_by_first_byte[id] = CHARSET_REP_BYTES (cs);
1610 #endif
1611
1612   /* Some charsets are "faux" and don't have names or really exist at
1613      all except in the leading-byte table. */
1614   if (!NILP (name))
1615     Fputhash (name, obj, Vcharset_hash_table);
1616   return obj;
1617 }
1618
1619 static int
1620 get_unallocated_leading_byte (int dimension)
1621 {
1622   Charset_ID lb;
1623
1624   if (dimension == 1)
1625     {
1626       if (next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
1627         lb = 0;
1628       else
1629         lb = next_allocated_1_byte_leading_byte++;
1630     }
1631   else
1632     {
1633       if (next_allocated_2_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_2)
1634         lb = 0;
1635       else
1636         lb = next_allocated_2_byte_leading_byte++;
1637     }
1638
1639   if (!lb)
1640     signal_simple_error
1641       ("No more character sets free for this dimension",
1642        make_int (dimension));
1643
1644   return lb;
1645 }
1646
1647 #ifdef UTF2000
1648 unsigned char
1649 charset_get_byte1 (Lisp_Object charset, Emchar ch)
1650 {
1651   Emchar_to_byte_table* table;
1652   int d;
1653
1654   if ((table = XCHARSET_TO_BYTE1_TABLE (charset)) != NULL)
1655     return get_byte_from_character_table (ch, table);
1656   else if ((CHARSET_UCS_MIN (XCHARSET (charset)) <= ch)
1657            && (ch <= CHARSET_UCS_MAX (XCHARSET (charset))))
1658     return ch - CHARSET_UCS_MIN (XCHARSET (charset))
1659       +  CHARSET_CODE_OFFSET (XCHARSET (charset));
1660   else if (XCHARSET_DIMENSION (charset) == 1)
1661     {
1662       if (XCHARSET_CHARS (charset) == 94)
1663         {
1664           if (((d = ch - (MIN_CHAR_94
1665                           + (XCHARSET_FINAL (charset) - '0') * 94)) >= 0)
1666               && (d < 94))
1667             return d + 33;
1668         }
1669       else if (XCHARSET_CHARS (charset) == 96)
1670         {
1671           if (((d = ch - (MIN_CHAR_96
1672                           + (XCHARSET_FINAL (charset) - '0') * 96)) >= 0)
1673               && (d < 96))
1674             return d + 32;
1675         }
1676       else
1677         return 0;
1678     }
1679   else if (XCHARSET_DIMENSION (charset) == 2)
1680     {
1681       if (XCHARSET_CHARS (charset) == 94)
1682         {
1683           if (((d = ch - (MIN_CHAR_94x94
1684                           + (XCHARSET_FINAL (charset) - '0') * 94 * 94)) >= 0)
1685               && (d < 94 * 94))
1686             return (d / 94) + 33;
1687         }
1688       else if (XCHARSET_CHARS (charset) == 96)
1689         {
1690           if (((d = ch - (MIN_CHAR_96x96
1691                           + (XCHARSET_FINAL (charset) - '0') * 96 * 96)) >= 0)
1692               && (d < 96 * 96))
1693             return (d / 96) + 32;
1694         }
1695     }
1696   return 0;
1697 }
1698
1699 unsigned char
1700 charset_get_byte2 (Lisp_Object charset, Emchar ch)
1701 {
1702   if (XCHARSET_DIMENSION (charset) == 1)
1703     return 0;
1704   else
1705     {
1706       Emchar_to_byte_table* table;
1707
1708       if ((table = XCHARSET_TO_BYTE2_TABLE (charset)) != NULL)
1709         return get_byte_from_character_table (ch, table);
1710       else if (EQ (charset, Vcharset_ucs_bmp))
1711         return (ch >> 8) & 0xff;
1712       else if (XCHARSET_CHARS (charset) == 94)
1713         return (MIN_CHAR_94x94
1714                 + (XCHARSET_FINAL (charset) - '0') * 94 * 94 <= ch)
1715           && (ch < MIN_CHAR_94x94
1716               + (XCHARSET_FINAL (charset) - '0' + 1) * 94 * 94) ?
1717           ((ch - MIN_CHAR_94x94) % 94) + 33 : 0;
1718       else /* if (XCHARSET_CHARS (charset) == 96) */
1719         return (MIN_CHAR_96x96
1720                 + (XCHARSET_FINAL (charset) - '0') * 96 * 96 <= ch)
1721           && (ch < MIN_CHAR_96x96
1722               + (XCHARSET_FINAL (charset) - '0' + 1) * 96 * 96) ?
1723           ((ch - MIN_CHAR_96x96) % 96) + 32 : 0;
1724     }
1725 }
1726
1727 Lisp_Object Vdefault_coded_charset_priority_list;
1728 #endif
1729
1730 \f
1731 /************************************************************************/
1732 /*                      Basic charset Lisp functions                    */
1733 /************************************************************************/
1734
1735 DEFUN ("charsetp", Fcharsetp, 1, 1, 0, /*
1736 Return non-nil if OBJECT is a charset.
1737 */
1738        (object))
1739 {
1740   return CHARSETP (object) ? Qt : Qnil;
1741 }
1742
1743 DEFUN ("find-charset", Ffind_charset, 1, 1, 0, /*
1744 Retrieve the charset of the given name.
1745 If CHARSET-OR-NAME is a charset object, it is simply returned.
1746 Otherwise, CHARSET-OR-NAME should be a symbol.  If there is no such charset,
1747 nil is returned.  Otherwise the associated charset object is returned.
1748 */
1749        (charset_or_name))
1750 {
1751   if (CHARSETP (charset_or_name))
1752     return charset_or_name;
1753
1754   CHECK_SYMBOL (charset_or_name);
1755   return Fgethash (charset_or_name, Vcharset_hash_table, Qnil);
1756 }
1757
1758 DEFUN ("get-charset", Fget_charset, 1, 1, 0, /*
1759 Retrieve the charset of the given name.
1760 Same as `find-charset' except an error is signalled if there is no such
1761 charset instead of returning nil.
1762 */
1763        (name))
1764 {
1765   Lisp_Object charset = Ffind_charset (name);
1766
1767   if (NILP (charset))
1768     signal_simple_error ("No such charset", name);
1769   return charset;
1770 }
1771
1772 /* We store the charsets in hash tables with the names as the key and the
1773    actual charset object as the value.  Occasionally we need to use them
1774    in a list format.  These routines provide us with that. */
1775 struct charset_list_closure
1776 {
1777   Lisp_Object *charset_list;
1778 };
1779
1780 static int
1781 add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
1782                             void *charset_list_closure)
1783 {
1784   /* This function can GC */
1785   struct charset_list_closure *chcl =
1786     (struct charset_list_closure*) charset_list_closure;
1787   Lisp_Object *charset_list = chcl->charset_list;
1788
1789   *charset_list = Fcons (XCHARSET_NAME (value), *charset_list);
1790   return 0;
1791 }
1792
1793 DEFUN ("charset-list", Fcharset_list, 0, 0, 0, /*
1794 Return a list of the names of all defined charsets.
1795 */
1796        ())
1797 {
1798   Lisp_Object charset_list = Qnil;
1799   struct gcpro gcpro1;
1800   struct charset_list_closure charset_list_closure;
1801
1802   GCPRO1 (charset_list);
1803   charset_list_closure.charset_list = &charset_list;
1804   elisp_maphash (add_charset_to_list_mapper, Vcharset_hash_table,
1805                  &charset_list_closure);
1806   UNGCPRO;
1807
1808   return charset_list;
1809 }
1810
1811 DEFUN ("charset-name", Fcharset_name, 1, 1, 0, /*
1812 Return the name of the given charset.
1813 */
1814        (charset))
1815 {
1816   return XCHARSET_NAME (Fget_charset (charset));
1817 }
1818
1819 DEFUN ("make-charset", Fmake_charset, 3, 3, 0, /*
1820 Define a new character set.
1821 This function is for use with Mule support.
1822 NAME is a symbol, the name by which the character set is normally referred.
1823 DOC-STRING is a string describing the character set.
1824 PROPS is a property list, describing the specific nature of the
1825 character set.  Recognized properties are:
1826
1827 'short-name     Short version of the charset name (ex: Latin-1)
1828 'long-name      Long version of the charset name (ex: ISO8859-1 (Latin-1))
1829 'registry       A regular expression matching the font registry field for
1830                 this character set.
1831 'dimension      Number of octets used to index a character in this charset.
1832                 Either 1 or 2.  Defaults to 1.
1833 'columns        Number of columns used to display a character in this charset.
1834                 Only used in TTY mode. (Under X, the actual width of a
1835                 character can be derived from the font used to display the
1836                 characters.) If unspecified, defaults to the dimension
1837                 (this is almost always the correct value).
1838 'chars          Number of characters in each dimension (94 or 96).
1839                 Defaults to 94.  Note that if the dimension is 2, the
1840                 character set thus described is 94x94 or 96x96.
1841 'final          Final byte of ISO 2022 escape sequence.  Must be
1842                 supplied.  Each combination of (DIMENSION, CHARS) defines a
1843                 separate namespace for final bytes.  Note that ISO
1844                 2022 restricts the final byte to the range
1845                 0x30 - 0x7E if dimension == 1, and 0x30 - 0x5F if
1846                 dimension == 2.  Note also that final bytes in the range
1847                 0x30 - 0x3F are reserved for user-defined (not official)
1848                 character sets.
1849 'graphic        0 (use left half of font on output) or 1 (use right half
1850                 of font on output).  Defaults to 0.  For example, for
1851                 a font whose registry is ISO8859-1, the left half
1852                 (octets 0x20 - 0x7F) is the `ascii' character set, while
1853                 the right half (octets 0xA0 - 0xFF) is the `latin-1'
1854                 character set.  With 'graphic set to 0, the octets
1855                 will have their high bit cleared; with it set to 1,
1856                 the octets will have their high bit set.
1857 'direction      'l2r (left-to-right) or 'r2l (right-to-left).
1858                 Defaults to 'l2r.
1859 'ccl-program    A compiled CCL program used to convert a character in
1860                 this charset into an index into the font.  This is in
1861                 addition to the 'graphic property.  The CCL program
1862                 is passed the octets of the character, with the high
1863                 bit cleared and set depending upon whether the value
1864                 of the 'graphic property is 0 or 1.
1865 */
1866        (name, doc_string, props))
1867 {
1868   int id, dimension = 1, chars = 94, graphic = 0, final = 0, columns = -1;
1869   int direction = CHARSET_LEFT_TO_RIGHT;
1870   int type;
1871   Lisp_Object registry = Qnil;
1872   Lisp_Object charset;
1873   Lisp_Object rest, keyword, value;
1874   Lisp_Object ccl_program = Qnil;
1875   Lisp_Object short_name = Qnil, long_name = Qnil;
1876
1877   CHECK_SYMBOL (name);
1878   if (!NILP (doc_string))
1879     CHECK_STRING (doc_string);
1880
1881   charset = Ffind_charset (name);
1882   if (!NILP (charset))
1883     signal_simple_error ("Cannot redefine existing charset", name);
1884
1885   EXTERNAL_PROPERTY_LIST_LOOP (rest, keyword, value, props)
1886     {
1887       if (EQ (keyword, Qshort_name))
1888         {
1889           CHECK_STRING (value);
1890           short_name = value;
1891         }
1892
1893       if (EQ (keyword, Qlong_name))
1894         {
1895           CHECK_STRING (value);
1896           long_name = value;
1897         }
1898
1899       else if (EQ (keyword, Qdimension))
1900         {
1901           CHECK_INT (value);
1902           dimension = XINT (value);
1903           if (dimension < 1 || dimension > 2)
1904             signal_simple_error ("Invalid value for 'dimension", value);
1905         }
1906
1907       else if (EQ (keyword, Qchars))
1908         {
1909           CHECK_INT (value);
1910           chars = XINT (value);
1911           if (chars != 94 && chars != 96)
1912             signal_simple_error ("Invalid value for 'chars", value);
1913         }
1914
1915       else if (EQ (keyword, Qcolumns))
1916         {
1917           CHECK_INT (value);
1918           columns = XINT (value);
1919           if (columns != 1 && columns != 2)
1920             signal_simple_error ("Invalid value for 'columns", value);
1921         }
1922
1923       else if (EQ (keyword, Qgraphic))
1924         {
1925           CHECK_INT (value);
1926           graphic = XINT (value);
1927           if (graphic < 0 || graphic > 1)
1928             signal_simple_error ("Invalid value for 'graphic", value);
1929         }
1930
1931       else if (EQ (keyword, Qregistry))
1932         {
1933           CHECK_STRING (value);
1934           registry = value;
1935         }
1936
1937       else if (EQ (keyword, Qdirection))
1938         {
1939           if (EQ (value, Ql2r))
1940             direction = CHARSET_LEFT_TO_RIGHT;
1941           else if (EQ (value, Qr2l))
1942             direction = CHARSET_RIGHT_TO_LEFT;
1943           else
1944             signal_simple_error ("Invalid value for 'direction", value);
1945         }
1946
1947       else if (EQ (keyword, Qfinal))
1948         {
1949           CHECK_CHAR_COERCE_INT (value);
1950           final = XCHAR (value);
1951           if (final < '0' || final > '~')
1952             signal_simple_error ("Invalid value for 'final", value);
1953         }
1954
1955       else if (EQ (keyword, Qccl_program))
1956         {
1957           CHECK_VECTOR (value);
1958           ccl_program = value;
1959         }
1960
1961       else
1962         signal_simple_error ("Unrecognized property", keyword);
1963     }
1964
1965   if (!final)
1966     error ("'final must be specified");
1967   if (dimension == 2 && final > 0x5F)
1968     signal_simple_error
1969       ("Final must be in the range 0x30 - 0x5F for dimension == 2",
1970        make_char (final));
1971
1972   if (dimension == 1)
1973     type = (chars == 94) ? CHARSET_TYPE_94    : CHARSET_TYPE_96;
1974   else
1975     type = (chars == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
1976
1977   if (!NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_LEFT_TO_RIGHT)) ||
1978       !NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_RIGHT_TO_LEFT)))
1979     error
1980       ("Character set already defined for this DIMENSION/CHARS/FINAL combo");
1981
1982 #ifdef UTF2000
1983   if (dimension == 1)
1984     {
1985       if (chars == 94)
1986         {
1987           /* id = CHARSET_ID_OFFSET_94 + final; */
1988           id = get_unallocated_leading_byte (dimension);
1989         }
1990       else if (chars == 96)
1991         {
1992           id = get_unallocated_leading_byte (dimension);
1993         }
1994       else
1995         {
1996           abort ();
1997         }
1998     }
1999   else if (dimension == 2)
2000     {
2001       if (chars == 94)
2002         {
2003           id = get_unallocated_leading_byte (dimension);
2004         }
2005       else if (chars == 96)
2006         {
2007           id = get_unallocated_leading_byte (dimension);
2008         }
2009       else
2010         {
2011           abort ();
2012         }
2013     }
2014   else
2015     {
2016       abort ();
2017     }
2018 #else
2019   id = get_unallocated_leading_byte (dimension);
2020 #endif
2021
2022   if (NILP (doc_string))
2023     doc_string = build_string ("");
2024
2025   if (NILP (registry))
2026     registry = build_string ("");
2027
2028   if (NILP (short_name))
2029     XSETSTRING (short_name, XSYMBOL (name)->name);
2030
2031   if (NILP (long_name))
2032     long_name = doc_string;
2033
2034   if (columns == -1)
2035     columns = dimension;
2036   charset = make_charset (id, name, type, columns, graphic,
2037                           final, direction, short_name, long_name,
2038                           doc_string, registry,
2039                           NULL, 0, 0, 0);
2040   if (!NILP (ccl_program))
2041     XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2042   return charset;
2043 }
2044
2045 DEFUN ("make-reverse-direction-charset", Fmake_reverse_direction_charset,
2046        2, 2, 0, /*
2047 Make a charset equivalent to CHARSET but which goes in the opposite direction.
2048 NEW-NAME is the name of the new charset.  Return the new charset.
2049 */
2050        (charset, new_name))
2051 {
2052   Lisp_Object new_charset = Qnil;
2053   int id, dimension, columns, graphic, final;
2054   int direction, type;
2055   Lisp_Object registry, doc_string, short_name, long_name;
2056   struct Lisp_Charset *cs;
2057
2058   charset = Fget_charset (charset);
2059   if (!NILP (XCHARSET_REVERSE_DIRECTION_CHARSET (charset)))
2060     signal_simple_error ("Charset already has reverse-direction charset",
2061                          charset);
2062
2063   CHECK_SYMBOL (new_name);
2064   if (!NILP (Ffind_charset (new_name)))
2065     signal_simple_error ("Cannot redefine existing charset", new_name);
2066
2067   cs = XCHARSET (charset);
2068
2069   type      = CHARSET_TYPE      (cs);
2070   columns   = CHARSET_COLUMNS   (cs);
2071   dimension = CHARSET_DIMENSION (cs);
2072   id = get_unallocated_leading_byte (dimension);
2073
2074   graphic = CHARSET_GRAPHIC (cs);
2075   final = CHARSET_FINAL (cs);
2076   direction = CHARSET_RIGHT_TO_LEFT;
2077   if (CHARSET_DIRECTION (cs) == CHARSET_RIGHT_TO_LEFT)
2078     direction = CHARSET_LEFT_TO_RIGHT;
2079   doc_string = CHARSET_DOC_STRING (cs);
2080   short_name = CHARSET_SHORT_NAME (cs);
2081   long_name = CHARSET_LONG_NAME (cs);
2082   registry = CHARSET_REGISTRY (cs);
2083
2084   new_charset = make_charset (id, new_name, type, columns,
2085                               graphic, final, direction, short_name, long_name,
2086                               doc_string, registry,
2087                               CHARSET_DECODING_TABLE(cs),
2088                               CHARSET_UCS_MIN(cs),
2089                               CHARSET_UCS_MAX(cs),
2090                               CHARSET_CODE_OFFSET(cs));
2091
2092   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
2093   XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
2094
2095   return new_charset;
2096 }
2097
2098 /* #### Reverse direction charsets not yet implemented.  */
2099 #if 0
2100 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
2101        1, 1, 0, /*
2102 Return the reverse-direction charset parallel to CHARSET, if any.
2103 This is the charset with the same properties (in particular, the same
2104 dimension, number of characters per dimension, and final byte) as
2105 CHARSET but whose characters are displayed in the opposite direction.
2106 */
2107        (charset))
2108 {
2109   charset = Fget_charset (charset);
2110   return XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
2111 }
2112 #endif
2113
2114 DEFUN ("charset-from-attributes", Fcharset_from_attributes, 3, 4, 0, /*
2115 Return a charset with the given DIMENSION, CHARS, FINAL, and DIRECTION.
2116 If DIRECTION is omitted, both directions will be checked (left-to-right
2117 will be returned if character sets exist for both directions).
2118 */
2119        (dimension, chars, final, direction))
2120 {
2121   int dm, ch, fi, di = -1;
2122   int type;
2123   Lisp_Object obj = Qnil;
2124
2125   CHECK_INT (dimension);
2126   dm = XINT (dimension);
2127   if (dm < 1 || dm > 2)
2128     signal_simple_error ("Invalid value for DIMENSION", dimension);
2129
2130   CHECK_INT (chars);
2131   ch = XINT (chars);
2132   if (ch != 94 && ch != 96)
2133     signal_simple_error ("Invalid value for CHARS", chars);
2134
2135   CHECK_CHAR_COERCE_INT (final);
2136   fi = XCHAR (final);
2137   if (fi < '0' || fi > '~')
2138     signal_simple_error ("Invalid value for FINAL", final);
2139
2140   if (EQ (direction, Ql2r))
2141     di = CHARSET_LEFT_TO_RIGHT;
2142   else if (EQ (direction, Qr2l))
2143     di = CHARSET_RIGHT_TO_LEFT;
2144   else if (!NILP (direction))
2145     signal_simple_error ("Invalid value for DIRECTION", direction);
2146
2147   if (dm == 2 && fi > 0x5F)
2148     signal_simple_error
2149       ("Final must be in the range 0x30 - 0x5F for dimension == 2", final);
2150
2151   if (dm == 1)
2152     type = (ch == 94) ? CHARSET_TYPE_94    : CHARSET_TYPE_96;
2153   else
2154     type = (ch == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
2155
2156   if (di == -1)
2157     {
2158       obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_LEFT_TO_RIGHT);
2159       if (NILP (obj))
2160         obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_RIGHT_TO_LEFT);
2161     }
2162   else
2163     obj = CHARSET_BY_ATTRIBUTES (type, fi, di);
2164
2165   if (CHARSETP (obj))
2166     return XCHARSET_NAME (obj);
2167   return obj;
2168 }
2169
2170 DEFUN ("charset-short-name", Fcharset_short_name, 1, 1, 0, /*
2171 Return short name of CHARSET.
2172 */
2173        (charset))
2174 {
2175   return XCHARSET_SHORT_NAME (Fget_charset (charset));
2176 }
2177
2178 DEFUN ("charset-long-name", Fcharset_long_name, 1, 1, 0, /*
2179 Return long name of CHARSET.
2180 */
2181        (charset))
2182 {
2183   return XCHARSET_LONG_NAME (Fget_charset (charset));
2184 }
2185
2186 DEFUN ("charset-description", Fcharset_description, 1, 1, 0, /*
2187 Return description of CHARSET.
2188 */
2189        (charset))
2190 {
2191   return XCHARSET_DOC_STRING (Fget_charset (charset));
2192 }
2193
2194 DEFUN ("charset-dimension", Fcharset_dimension, 1, 1, 0, /*
2195 Return dimension of CHARSET.
2196 */
2197        (charset))
2198 {
2199   return make_int (XCHARSET_DIMENSION (Fget_charset (charset)));
2200 }
2201
2202 DEFUN ("charset-property", Fcharset_property, 2, 2, 0, /*
2203 Return property PROP of CHARSET.
2204 Recognized properties are those listed in `make-charset', as well as
2205 'name and 'doc-string.
2206 */
2207        (charset, prop))
2208 {
2209   struct Lisp_Charset *cs;
2210
2211   charset = Fget_charset (charset);
2212   cs = XCHARSET (charset);
2213
2214   CHECK_SYMBOL (prop);
2215   if (EQ (prop, Qname))        return CHARSET_NAME (cs);
2216   if (EQ (prop, Qshort_name))  return CHARSET_SHORT_NAME (cs);
2217   if (EQ (prop, Qlong_name))   return CHARSET_LONG_NAME (cs);
2218   if (EQ (prop, Qdoc_string))  return CHARSET_DOC_STRING (cs);
2219   if (EQ (prop, Qdimension))   return make_int (CHARSET_DIMENSION (cs));
2220   if (EQ (prop, Qcolumns))     return make_int (CHARSET_COLUMNS (cs));
2221   if (EQ (prop, Qgraphic))     return make_int (CHARSET_GRAPHIC (cs));
2222   if (EQ (prop, Qfinal))       return make_char (CHARSET_FINAL (cs));
2223   if (EQ (prop, Qchars))       return make_int (CHARSET_CHARS (cs));
2224   if (EQ (prop, Qregistry))    return CHARSET_REGISTRY (cs);
2225   if (EQ (prop, Qccl_program)) return CHARSET_CCL_PROGRAM (cs);
2226   if (EQ (prop, Qdirection))
2227     return CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? Ql2r : Qr2l;
2228   if (EQ (prop, Qreverse_direction_charset))
2229     {
2230       Lisp_Object obj = CHARSET_REVERSE_DIRECTION_CHARSET (cs);
2231       if (NILP (obj))
2232         return Qnil;
2233       else
2234         return XCHARSET_NAME (obj);
2235     }
2236   signal_simple_error ("Unrecognized charset property name", prop);
2237   return Qnil; /* not reached */
2238 }
2239
2240 DEFUN ("charset-id", Fcharset_id, 1, 1, 0, /*
2241 Return charset identification number of CHARSET.
2242 */
2243         (charset))
2244 {
2245   return make_int(XCHARSET_LEADING_BYTE (Fget_charset (charset)));
2246 }
2247
2248 /* #### We need to figure out which properties we really want to
2249    allow to be set. */
2250
2251 DEFUN ("set-charset-ccl-program", Fset_charset_ccl_program, 2, 2, 0, /*
2252 Set the 'ccl-program property of CHARSET to CCL-PROGRAM.
2253 */
2254        (charset, ccl_program))
2255 {
2256   charset = Fget_charset (charset);
2257   CHECK_VECTOR (ccl_program);
2258   XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2259   return Qnil;
2260 }
2261
2262 static void
2263 invalidate_charset_font_caches (Lisp_Object charset)
2264 {
2265   /* Invalidate font cache entries for charset on all devices. */
2266   Lisp_Object devcons, concons, hash_table;
2267   DEVICE_LOOP_NO_BREAK (devcons, concons)
2268     {
2269       struct device *d = XDEVICE (XCAR (devcons));
2270       hash_table = Fgethash (charset, d->charset_font_cache, Qunbound);
2271       if (!UNBOUNDP (hash_table))
2272         Fclrhash (hash_table);
2273     }
2274 }
2275
2276 /* Japanese folks may want to (set-charset-registry 'ascii "jisx0201") */
2277 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
2278 Set the 'registry property of CHARSET to REGISTRY.
2279 */
2280        (charset, registry))
2281 {
2282   charset = Fget_charset (charset);
2283   CHECK_STRING (registry);
2284   XCHARSET_REGISTRY (charset) = registry;
2285   invalidate_charset_font_caches (charset);
2286   face_property_was_changed (Vdefault_face, Qfont, Qglobal);
2287   return Qnil;
2288 }
2289
2290 \f
2291 /************************************************************************/
2292 /*              Lisp primitives for working with characters             */
2293 /************************************************************************/
2294
2295 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
2296 Make a character from CHARSET and octets ARG1 and ARG2.
2297 ARG2 is required only for characters from two-dimensional charsets.
2298 For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
2299 character s with caron.
2300 */
2301        (charset, arg1, arg2))
2302 {
2303   struct Lisp_Charset *cs;
2304   int a1, a2;
2305   int lowlim, highlim;
2306
2307   charset = Fget_charset (charset);
2308   cs = XCHARSET (charset);
2309
2310   if      (EQ (charset, Vcharset_ascii))     lowlim =  0, highlim = 127;
2311   else if (EQ (charset, Vcharset_control_1)) lowlim =  0, highlim =  31;
2312 #ifdef UTF2000
2313   else if (CHARSET_CHARS (cs) == 256)        lowlim =  0, highlim = 255;
2314 #endif
2315   else if (CHARSET_CHARS (cs) == 94)         lowlim = 33, highlim = 126;
2316   else  /* CHARSET_CHARS (cs) == 96) */      lowlim = 32, highlim = 127;
2317
2318   CHECK_INT (arg1);
2319   /* It is useful (and safe, according to Olivier Galibert) to strip
2320      the 8th bit off ARG1 and ARG2 becaue it allows programmers to
2321      write (make-char 'latin-iso8859-2 CODE) where code is the actual
2322      Latin 2 code of the character.  */
2323 #ifdef UTF2000
2324   a1 = XINT (arg1);
2325   if (highlim < 128)
2326     a1 &= 0x7f;
2327 #else
2328   a1 = XINT (arg1);
2329 #endif
2330   if (a1 < lowlim || a1 > highlim)
2331     args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
2332
2333   if (CHARSET_DIMENSION (cs) == 1)
2334     {
2335       if (!NILP (arg2))
2336         signal_simple_error
2337           ("Charset is of dimension one; second octet must be nil", arg2);
2338       return make_char (MAKE_CHAR (charset, a1, 0));
2339     }
2340
2341   CHECK_INT (arg2);
2342 #ifdef UTF2000
2343   a2 = XINT (arg2);
2344   if (highlim < 128)
2345     a2 &= 0x7f;
2346 #else
2347   a2 = XINT (arg2) & 0x7f;
2348 #endif
2349   if (a2 < lowlim || a2 > highlim)
2350     args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
2351
2352   return make_char (MAKE_CHAR (charset, a1, a2));
2353 }
2354
2355 DEFUN ("char-charset", Fchar_charset, 1, 1, 0, /*
2356 Return the character set of char CH.
2357 */
2358        (ch))
2359 {
2360   CHECK_CHAR_COERCE_INT (ch);
2361
2362   return XCHARSET_NAME (CHAR_CHARSET (XCHAR (ch)));
2363 }
2364
2365 DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
2366 Return list of charset and one or two position-codes of CHAR.
2367 */
2368        (character))
2369 {
2370   /* This function can GC */
2371   struct gcpro gcpro1, gcpro2;
2372   Lisp_Object charset = Qnil;
2373   Lisp_Object rc = Qnil;
2374   int c1, c2;
2375
2376   GCPRO2 (charset, rc);
2377   CHECK_CHAR_COERCE_INT (character);
2378
2379   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
2380
2381   if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
2382     {
2383       rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
2384     }
2385   else
2386     {
2387       rc = list2 (XCHARSET_NAME (charset), make_int (c1));
2388     }
2389   UNGCPRO;
2390
2391   return rc;
2392 }
2393
2394 \f
2395 #ifdef ENABLE_COMPOSITE_CHARS
2396 /************************************************************************/
2397 /*                     composite character functions                    */
2398 /************************************************************************/
2399
2400 Emchar
2401 lookup_composite_char (Bufbyte *str, int len)
2402 {
2403   Lisp_Object lispstr = make_string (str, len);
2404   Lisp_Object ch = Fgethash (lispstr,
2405                              Vcomposite_char_string2char_hash_table,
2406                              Qunbound);
2407   Emchar emch;
2408
2409   if (UNBOUNDP (ch))
2410     {
2411       if (composite_char_row_next >= 128)
2412         signal_simple_error ("No more composite chars available", lispstr);
2413       emch = MAKE_CHAR (Vcharset_composite, composite_char_row_next,
2414                         composite_char_col_next);
2415       Fputhash (make_char (emch), lispstr,
2416                 Vcomposite_char_char2string_hash_table);
2417       Fputhash (lispstr, make_char (emch),
2418                 Vcomposite_char_string2char_hash_table);
2419       composite_char_col_next++;
2420       if (composite_char_col_next >= 128)
2421         {
2422           composite_char_col_next = 32;
2423           composite_char_row_next++;
2424         }
2425     }
2426   else
2427     emch = XCHAR (ch);
2428   return emch;
2429 }
2430
2431 Lisp_Object
2432 composite_char_string (Emchar ch)
2433 {
2434   Lisp_Object str = Fgethash (make_char (ch),
2435                               Vcomposite_char_char2string_hash_table,
2436                               Qunbound);
2437   assert (!UNBOUNDP (str));
2438   return str;
2439 }
2440
2441 xxDEFUN ("make-composite-char", Fmake_composite_char, 1, 1, 0, /*
2442 Convert a string into a single composite character.
2443 The character is the result of overstriking all the characters in
2444 the string.
2445 */
2446        (string))
2447 {
2448   CHECK_STRING (string);
2449   return make_char (lookup_composite_char (XSTRING_DATA (string),
2450                                            XSTRING_LENGTH (string)));
2451 }
2452
2453 xxDEFUN ("composite-char-string", Fcomposite_char_string, 1, 1, 0, /*
2454 Return a string of the characters comprising a composite character.
2455 */
2456        (ch))
2457 {
2458   Emchar emch;
2459
2460   CHECK_CHAR (ch);
2461   emch = XCHAR (ch);
2462   if (CHAR_LEADING_BYTE (emch) != LEADING_BYTE_COMPOSITE)
2463     signal_simple_error ("Must be composite char", ch);
2464   return composite_char_string (emch);
2465 }
2466 #endif /* ENABLE_COMPOSITE_CHARS */
2467
2468 \f
2469 /************************************************************************/
2470 /*                            initialization                            */
2471 /************************************************************************/
2472
2473 void
2474 syms_of_mule_charset (void)
2475 {
2476   DEFSUBR (Fcharsetp);
2477   DEFSUBR (Ffind_charset);
2478   DEFSUBR (Fget_charset);
2479   DEFSUBR (Fcharset_list);
2480   DEFSUBR (Fcharset_name);
2481   DEFSUBR (Fmake_charset);
2482   DEFSUBR (Fmake_reverse_direction_charset);
2483   /*  DEFSUBR (Freverse_direction_charset); */
2484   DEFSUBR (Fcharset_from_attributes);
2485   DEFSUBR (Fcharset_short_name);
2486   DEFSUBR (Fcharset_long_name);
2487   DEFSUBR (Fcharset_description);
2488   DEFSUBR (Fcharset_dimension);
2489   DEFSUBR (Fcharset_property);
2490   DEFSUBR (Fcharset_id);
2491   DEFSUBR (Fset_charset_ccl_program);
2492   DEFSUBR (Fset_charset_registry);
2493
2494   DEFSUBR (Fmake_char);
2495   DEFSUBR (Fchar_charset);
2496   DEFSUBR (Fsplit_char);
2497
2498 #ifdef ENABLE_COMPOSITE_CHARS
2499   DEFSUBR (Fmake_composite_char);
2500   DEFSUBR (Fcomposite_char_string);
2501 #endif
2502
2503   defsymbol (&Qcharsetp, "charsetp");
2504   defsymbol (&Qregistry, "registry");
2505   defsymbol (&Qfinal, "final");
2506   defsymbol (&Qgraphic, "graphic");
2507   defsymbol (&Qdirection, "direction");
2508   defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
2509   defsymbol (&Qshort_name, "short-name");
2510   defsymbol (&Qlong_name, "long-name");
2511
2512   defsymbol (&Ql2r, "l2r");
2513   defsymbol (&Qr2l, "r2l");
2514
2515   /* Charsets, compatible with FSF 20.3
2516      Naming convention is Script-Charset[-Edition] */
2517   defsymbol (&Qascii,                   "ascii");
2518   defsymbol (&Qcontrol_1,               "control-1");
2519   defsymbol (&Qlatin_iso8859_1,         "latin-iso8859-1");
2520   defsymbol (&Qlatin_iso8859_2,         "latin-iso8859-2");
2521   defsymbol (&Qlatin_iso8859_3,         "latin-iso8859-3");
2522   defsymbol (&Qlatin_iso8859_4,         "latin-iso8859-4");
2523   defsymbol (&Qthai_tis620,             "thai-tis620");
2524   defsymbol (&Qgreek_iso8859_7,         "greek-iso8859-7");
2525   defsymbol (&Qarabic_iso8859_6,        "arabic-iso8859-6");
2526   defsymbol (&Qhebrew_iso8859_8,        "hebrew-iso8859-8");
2527   defsymbol (&Qkatakana_jisx0201,       "katakana-jisx0201");
2528   defsymbol (&Qlatin_jisx0201,          "latin-jisx0201");
2529   defsymbol (&Qcyrillic_iso8859_5,      "cyrillic-iso8859-5");
2530   defsymbol (&Qlatin_iso8859_9,         "latin-iso8859-9");
2531   defsymbol (&Qjapanese_jisx0208_1978,  "japanese-jisx0208-1978");
2532   defsymbol (&Qchinese_gb2312,          "chinese-gb2312");
2533   defsymbol (&Qjapanese_jisx0208,       "japanese-jisx0208");
2534   defsymbol (&Qkorean_ksc5601,          "korean-ksc5601");
2535   defsymbol (&Qjapanese_jisx0212,       "japanese-jisx0212");
2536   defsymbol (&Qchinese_cns11643_1,      "chinese-cns11643-1");
2537   defsymbol (&Qchinese_cns11643_2,      "chinese-cns11643-2");
2538 #ifdef UTF2000
2539   defsymbol (&Qchinese_cns11643_3,      "chinese-cns11643-3");
2540   defsymbol (&Qchinese_cns11643_4,      "chinese-cns11643-4");
2541   defsymbol (&Qchinese_cns11643_5,      "chinese-cns11643-5");
2542   defsymbol (&Qchinese_cns11643_6,      "chinese-cns11643-6");
2543   defsymbol (&Qchinese_cns11643_7,      "chinese-cns11643-7");
2544   defsymbol (&Qucs_bmp,                 "ucs-bmp");
2545   defsymbol (&Qlatin_viscii_lower,      "vietnamese-viscii-lower");
2546   defsymbol (&Qlatin_viscii_upper,      "vietnamese-viscii-upper");
2547 #endif
2548   defsymbol (&Qchinese_big5_1,          "chinese-big5-1");
2549   defsymbol (&Qchinese_big5_2,          "chinese-big5-2");
2550
2551   defsymbol (&Qcomposite,               "composite");
2552 }
2553
2554 void
2555 vars_of_mule_charset (void)
2556 {
2557   int i, j;
2558 #ifndef UTF2000
2559   int k;
2560 #endif
2561
2562   /* Table of charsets indexed by leading byte. */
2563   for (i = 0; i < countof (charset_by_leading_byte); i++)
2564     charset_by_leading_byte[i] = Qnil;
2565
2566 #ifdef UTF2000
2567   /* Table of charsets indexed by type/final-byte. */
2568   for (i = 0; i < countof (charset_by_attributes); i++)
2569     for (j = 0; j < countof (charset_by_attributes[0]); j++)
2570         charset_by_attributes[i][j] = Qnil;
2571 #else
2572   /* Table of charsets indexed by type/final-byte/direction. */
2573   for (i = 0; i < countof (charset_by_attributes); i++)
2574     for (j = 0; j < countof (charset_by_attributes[0]); j++)
2575       for (k = 0; k < countof (charset_by_attributes[0][0]); k++)
2576         charset_by_attributes[i][j][k] = Qnil;
2577 #endif
2578
2579   next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
2580 #ifdef UTF2000
2581   next_allocated_2_byte_leading_byte = LEADING_BYTE_CHINESE_BIG5_2 + 1;
2582 #else
2583   next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
2584 #endif
2585
2586 #ifndef UTF2000
2587   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2588   DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
2589 Leading-code of private TYPE9N charset of column-width 1.
2590 */ );
2591   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2592 #endif
2593
2594 #ifdef UTF2000
2595   Vutf_2000_version = build_string("0.8 (Kami)");
2596   DEFVAR_LISP ("utf-2000-version", &Vutf_2000_version /*
2597 Version number of UTF-2000.
2598 */ );
2599
2600   Vdefault_coded_charset_priority_list = Qnil;
2601   DEFVAR_LISP ("default-coded-charset-priority-list",
2602                &Vdefault_coded_charset_priority_list /*
2603 Default order of preferred coded-character-set.
2604 */ );
2605 #endif
2606 }
2607
2608 void
2609 complex_vars_of_mule_charset (void)
2610 {
2611   staticpro (&Vcharset_hash_table);
2612   Vcharset_hash_table =
2613     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
2614
2615   /* Predefined character sets.  We store them into variables for
2616      ease of access. */
2617
2618 #ifdef UTF2000
2619   Vcharset_ucs_bmp =
2620     make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp,
2621                   CHARSET_TYPE_256X256, 1, 0, 0,
2622                   CHARSET_LEFT_TO_RIGHT,
2623                   build_string ("BMP"),
2624                   build_string ("BMP"),
2625                   build_string ("BMP"),
2626                   build_string (""),
2627                   NULL, 0, 0xFFFF, 0);
2628 #else
2629 # define latin_iso8859_2_to_ucs NULL
2630 # define latin_iso8859_3_to_ucs NULL
2631 # define latin_iso8859_4_to_ucs NULL
2632 # define latin_iso8859_9_to_ucs NULL
2633 # define latin_jisx0201_to_ucs NULL
2634 # define MIN_CHAR_THAI 0
2635 # define MAX_CHAR_THAI 0
2636 # define MIN_CHAR_GREEK 0
2637 # define MAX_CHAR_GREEK 0
2638 # define MIN_CHAR_HEBREW 0
2639 # define MAX_CHAR_HEBREW 0
2640 # define MIN_CHAR_HALFWIDTH_KATAKANA 0
2641 # define MAX_CHAR_HALFWIDTH_KATAKANA 0
2642 # define MIN_CHAR_CYRILLIC 0
2643 # define MAX_CHAR_CYRILLIC 0
2644 #endif
2645   Vcharset_ascii =
2646     make_charset (LEADING_BYTE_ASCII, Qascii,
2647                   CHARSET_TYPE_94, 1, 0, 'B',
2648                   CHARSET_LEFT_TO_RIGHT,
2649                   build_string ("ASCII"),
2650                   build_string ("ASCII)"),
2651                   build_string ("ASCII (ISO646 IRV)"),
2652                   build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
2653                   NULL, 0, 0x7F, 0);
2654   Vcharset_control_1 =
2655     make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1,
2656                   CHARSET_TYPE_94, 1, 1, 0,
2657                   CHARSET_LEFT_TO_RIGHT,
2658                   build_string ("C1"),
2659                   build_string ("Control characters"),
2660                   build_string ("Control characters 128-191"),
2661                   build_string (""),
2662                   NULL, 0x80, 0x9F, 0);
2663   Vcharset_latin_iso8859_1 =
2664     make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1,
2665                   CHARSET_TYPE_96, 1, 1, 'A',
2666                   CHARSET_LEFT_TO_RIGHT,
2667                   build_string ("Latin-1"),
2668                   build_string ("ISO8859-1 (Latin-1)"),
2669                   build_string ("ISO8859-1 (Latin-1)"),
2670                   build_string ("iso8859-1"),
2671                   NULL, 0xA0, 0xFF, 32);
2672   Vcharset_latin_iso8859_2 =
2673     make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2,
2674                   CHARSET_TYPE_96, 1, 1, 'B',
2675                   CHARSET_LEFT_TO_RIGHT,
2676                   build_string ("Latin-2"),
2677                   build_string ("ISO8859-2 (Latin-2)"),
2678                   build_string ("ISO8859-2 (Latin-2)"),
2679                   build_string ("iso8859-2"),
2680                   latin_iso8859_2_to_ucs, 0, 0, 32);
2681   Vcharset_latin_iso8859_3 =
2682     make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3,
2683                   CHARSET_TYPE_96, 1, 1, 'C',
2684                   CHARSET_LEFT_TO_RIGHT,
2685                   build_string ("Latin-3"),
2686                   build_string ("ISO8859-3 (Latin-3)"),
2687                   build_string ("ISO8859-3 (Latin-3)"),
2688                   build_string ("iso8859-3"),
2689                   latin_iso8859_3_to_ucs, 0, 0, 32);
2690   Vcharset_latin_iso8859_4 =
2691     make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4,
2692                   CHARSET_TYPE_96, 1, 1, 'D',
2693                   CHARSET_LEFT_TO_RIGHT,
2694                   build_string ("Latin-4"),
2695                   build_string ("ISO8859-4 (Latin-4)"),
2696                   build_string ("ISO8859-4 (Latin-4)"),
2697                   build_string ("iso8859-4"),
2698                   latin_iso8859_4_to_ucs, 0, 0, 32);
2699   Vcharset_thai_tis620 =
2700     make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620,
2701                   CHARSET_TYPE_96, 1, 1, 'T',
2702                   CHARSET_LEFT_TO_RIGHT,
2703                   build_string ("TIS620"),
2704                   build_string ("TIS620 (Thai)"),
2705                   build_string ("TIS620.2529 (Thai)"),
2706                   build_string ("tis620"),
2707                   NULL, MIN_CHAR_THAI, MAX_CHAR_THAI, 32);
2708   Vcharset_greek_iso8859_7 =
2709     make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7,
2710                   CHARSET_TYPE_96, 1, 1, 'F',
2711                   CHARSET_LEFT_TO_RIGHT,
2712                   build_string ("ISO8859-7"),
2713                   build_string ("ISO8859-7 (Greek)"),
2714                   build_string ("ISO8859-7 (Greek)"),
2715                   build_string ("iso8859-7"),
2716                   NULL, MIN_CHAR_GREEK, MAX_CHAR_GREEK, 32);
2717   Vcharset_arabic_iso8859_6 =
2718     make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6,
2719                   CHARSET_TYPE_96, 1, 1, 'G',
2720                   CHARSET_RIGHT_TO_LEFT,
2721                   build_string ("ISO8859-6"),
2722                   build_string ("ISO8859-6 (Arabic)"),
2723                   build_string ("ISO8859-6 (Arabic)"),
2724                   build_string ("iso8859-6"),
2725                   NULL, 0, 0, 32);
2726   Vcharset_hebrew_iso8859_8 =
2727     make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8,
2728                   CHARSET_TYPE_96, 1, 1, 'H',
2729                   CHARSET_RIGHT_TO_LEFT,
2730                   build_string ("ISO8859-8"),
2731                   build_string ("ISO8859-8 (Hebrew)"),
2732                   build_string ("ISO8859-8 (Hebrew)"),
2733                   build_string ("iso8859-8"),
2734                   NULL, MIN_CHAR_HEBREW, MAX_CHAR_HEBREW, 32);
2735   Vcharset_katakana_jisx0201 =
2736     make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201,
2737                   CHARSET_TYPE_94, 1, 1, 'I',
2738                   CHARSET_LEFT_TO_RIGHT,
2739                   build_string ("JISX0201 Kana"),
2740                   build_string ("JISX0201.1976 (Japanese Kana)"),
2741                   build_string ("JISX0201.1976 Japanese Kana"),
2742                   build_string ("jisx0201.1976"),
2743                   NULL,
2744                   MIN_CHAR_HALFWIDTH_KATAKANA,
2745                   MAX_CHAR_HALFWIDTH_KATAKANA, 33);
2746   Vcharset_latin_jisx0201 =
2747     make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201,
2748                   CHARSET_TYPE_94, 1, 0, 'J',
2749                   CHARSET_LEFT_TO_RIGHT,
2750                   build_string ("JISX0201 Roman"),
2751                   build_string ("JISX0201.1976 (Japanese Roman)"),
2752                   build_string ("JISX0201.1976 Japanese Roman"),
2753                   build_string ("jisx0201.1976"),
2754                   latin_jisx0201_to_ucs, 0, 0, 33);
2755   Vcharset_cyrillic_iso8859_5 =
2756     make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5,
2757                   CHARSET_TYPE_96, 1, 1, 'L',
2758                   CHARSET_LEFT_TO_RIGHT,
2759                   build_string ("ISO8859-5"),
2760                   build_string ("ISO8859-5 (Cyrillic)"),
2761                   build_string ("ISO8859-5 (Cyrillic)"),
2762                   build_string ("iso8859-5"),
2763                   NULL, MIN_CHAR_CYRILLIC, MAX_CHAR_CYRILLIC, 32);
2764   Vcharset_latin_iso8859_9 =
2765     make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9,
2766                   CHARSET_TYPE_96, 1, 1, 'M',
2767                   CHARSET_LEFT_TO_RIGHT,
2768                   build_string ("Latin-5"),
2769                   build_string ("ISO8859-9 (Latin-5)"),
2770                   build_string ("ISO8859-9 (Latin-5)"),
2771                   build_string ("iso8859-9"),
2772                   latin_iso8859_9_to_ucs, 0, 0, 32);
2773   Vcharset_japanese_jisx0208_1978 =
2774     make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978, Qjapanese_jisx0208_1978,
2775                   CHARSET_TYPE_94X94, 2, 0, '@',
2776                   CHARSET_LEFT_TO_RIGHT,
2777                   build_string ("JISX0208.1978"),
2778                   build_string ("JISX0208.1978 (Japanese)"),
2779                   build_string
2780                   ("JISX0208.1978 Japanese Kanji (so called \"old JIS\")"),
2781                   build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
2782                   NULL, 0, 0, 33);
2783   Vcharset_chinese_gb2312 =
2784     make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312,
2785                   CHARSET_TYPE_94X94, 2, 0, 'A',
2786                   CHARSET_LEFT_TO_RIGHT,
2787                   build_string ("GB2312"),
2788                   build_string ("GB2312)"),
2789                   build_string ("GB2312 Chinese simplified"),
2790                   build_string ("gb2312"),
2791                   NULL, 0, 0, 33);
2792   Vcharset_japanese_jisx0208 =
2793     make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208,
2794                   CHARSET_TYPE_94X94, 2, 0, 'B',
2795                   CHARSET_LEFT_TO_RIGHT,
2796                   build_string ("JISX0208"),
2797                   build_string ("JISX0208.1983/1990 (Japanese)"),
2798                   build_string ("JISX0208.1983/1990 Japanese Kanji"),
2799                   build_string ("jisx0208.19\\(83\\|90\\)"),
2800                   NULL, 0, 0, 33);
2801   Vcharset_korean_ksc5601 =
2802     make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601,
2803                   CHARSET_TYPE_94X94, 2, 0, 'C',
2804                   CHARSET_LEFT_TO_RIGHT,
2805                   build_string ("KSC5601"),
2806                   build_string ("KSC5601 (Korean"),
2807                   build_string ("KSC5601 Korean Hangul and Hanja"),
2808                   build_string ("ksc5601"),
2809                   NULL, 0, 0, 33);
2810   Vcharset_japanese_jisx0212 =
2811     make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212,
2812                   CHARSET_TYPE_94X94, 2, 0, 'D',
2813                   CHARSET_LEFT_TO_RIGHT,
2814                   build_string ("JISX0212"),
2815                   build_string ("JISX0212 (Japanese)"),
2816                   build_string ("JISX0212 Japanese Supplement"),
2817                   build_string ("jisx0212"),
2818                   NULL, 0, 0, 33);
2819
2820 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
2821   Vcharset_chinese_cns11643_1 =
2822     make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1,
2823                   CHARSET_TYPE_94X94, 2, 0, 'G',
2824                   CHARSET_LEFT_TO_RIGHT,
2825                   build_string ("CNS11643-1"),
2826                   build_string ("CNS11643-1 (Chinese traditional)"),
2827                   build_string
2828                   ("CNS 11643 Plane 1 Chinese traditional"),
2829                   build_string (CHINESE_CNS_PLANE_RE("1")),
2830                   NULL, 0, 0, 33);
2831   Vcharset_chinese_cns11643_2 =
2832     make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2,
2833                   CHARSET_TYPE_94X94, 2, 0, 'H',
2834                   CHARSET_LEFT_TO_RIGHT,
2835                   build_string ("CNS11643-2"),
2836                   build_string ("CNS11643-2 (Chinese traditional)"),
2837                   build_string
2838                   ("CNS 11643 Plane 2 Chinese traditional"),
2839                   build_string (CHINESE_CNS_PLANE_RE("2")),
2840                   NULL, 0, 0, 33);
2841 #ifdef UTF2000
2842   Vcharset_chinese_cns11643_3 =
2843     make_charset (LEADING_BYTE_CHINESE_CNS11643_3, Qchinese_cns11643_3,
2844                   CHARSET_TYPE_94X94, 2, 0, 'I',
2845                   CHARSET_LEFT_TO_RIGHT,
2846                   build_string ("CNS11643-3"),
2847                   build_string ("CNS11643-3 (Chinese traditional)"),
2848                   build_string
2849                   ("CNS 11643 Plane 3 Chinese traditional"),
2850                   build_string (CHINESE_CNS_PLANE_RE("3")),
2851                   NULL, 0, 0, 33);
2852   Vcharset_chinese_cns11643_4 =
2853     make_charset (LEADING_BYTE_CHINESE_CNS11643_4, Qchinese_cns11643_4,
2854                   CHARSET_TYPE_94X94, 2, 0, 'J',
2855                   CHARSET_LEFT_TO_RIGHT,
2856                   build_string ("CNS11643-4"),
2857                   build_string ("CNS11643-4 (Chinese traditional)"),
2858                   build_string
2859                   ("CNS 11643 Plane 4 Chinese traditional"),
2860                   build_string (CHINESE_CNS_PLANE_RE("4")),
2861                   NULL, 0, 0, 33);
2862   Vcharset_chinese_cns11643_5 =
2863     make_charset (LEADING_BYTE_CHINESE_CNS11643_5, Qchinese_cns11643_5,
2864                   CHARSET_TYPE_94X94, 2, 0, 'K',
2865                   CHARSET_LEFT_TO_RIGHT,
2866                   build_string ("CNS11643-5"),
2867                   build_string ("CNS11643-5 (Chinese traditional)"),
2868                   build_string
2869                   ("CNS 11643 Plane 5 Chinese traditional"),
2870                   build_string (CHINESE_CNS_PLANE_RE("5")),
2871                   NULL, 0, 0, 33);
2872   Vcharset_chinese_cns11643_6 =
2873     make_charset (LEADING_BYTE_CHINESE_CNS11643_6, Qchinese_cns11643_6,
2874                   CHARSET_TYPE_94X94, 2, 0, 'L',
2875                   CHARSET_LEFT_TO_RIGHT,
2876                   build_string ("CNS11643-6"),
2877                   build_string ("CNS11643-6 (Chinese traditional)"),
2878                   build_string
2879                   ("CNS 11643 Plane 6 Chinese traditional"),
2880                   build_string (CHINESE_CNS_PLANE_RE("6")),
2881                   NULL, 0, 0, 33);
2882   Vcharset_chinese_cns11643_7 =
2883     make_charset (LEADING_BYTE_CHINESE_CNS11643_7, Qchinese_cns11643_7,
2884                   CHARSET_TYPE_94X94, 2, 0, 'M',
2885                   CHARSET_LEFT_TO_RIGHT,
2886                   build_string ("CNS11643-7"),
2887                   build_string ("CNS11643-7 (Chinese traditional)"),
2888                   build_string
2889                   ("CNS 11643 Plane 7 Chinese traditional"),
2890                   build_string (CHINESE_CNS_PLANE_RE("7")),
2891                   NULL, 0, 0, 33);
2892   Vcharset_latin_viscii_lower =
2893     make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower,
2894                   CHARSET_TYPE_96, 1, 1, '1',
2895                   CHARSET_LEFT_TO_RIGHT,
2896                   build_string ("VISCII lower"),
2897                   build_string ("VISCII lower (Vietnamese)"),
2898                   build_string ("VISCII lower (Vietnamese)"),
2899                   build_string ("VISCII1.1"),
2900                   latin_viscii_lower_to_ucs, 0, 0, 32);
2901   Vcharset_latin_viscii_upper =
2902     make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper,
2903                   CHARSET_TYPE_96, 1, 1, '2',
2904                   CHARSET_LEFT_TO_RIGHT,
2905                   build_string ("VISCII upper"),
2906                   build_string ("VISCII upper (Vietnamese)"),
2907                   build_string ("VISCII upper (Vietnamese)"),
2908                   build_string ("VISCII1.1"),
2909                   latin_viscii_upper_to_ucs, 0, 0, 32);
2910 #endif
2911   Vcharset_chinese_big5_1 =
2912     make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1,
2913                   CHARSET_TYPE_94X94, 2, 0, '0',
2914                   CHARSET_LEFT_TO_RIGHT,
2915                   build_string ("Big5"),
2916                   build_string ("Big5 (Level-1)"),
2917                   build_string
2918                   ("Big5 Level-1 Chinese traditional"),
2919                   build_string ("big5"),
2920                   NULL, 0, 0, 33);
2921   Vcharset_chinese_big5_2 =
2922     make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2,
2923                   CHARSET_TYPE_94X94, 2, 0, '1',
2924                   CHARSET_LEFT_TO_RIGHT,
2925                   build_string ("Big5"),
2926                   build_string ("Big5 (Level-2)"),
2927                   build_string
2928                   ("Big5 Level-2 Chinese traditional"),
2929                   build_string ("big5"),
2930                   NULL, 0, 0, 33);
2931
2932 #ifdef ENABLE_COMPOSITE_CHARS
2933   /* #### For simplicity, we put composite chars into a 96x96 charset.
2934      This is going to lead to problems because you can run out of
2935      room, esp. as we don't yet recycle numbers. */
2936   Vcharset_composite =
2937     make_charset (LEADING_BYTE_COMPOSITE, Qcomposite,
2938                   CHARSET_TYPE_96X96, 2, 0, 0,
2939                   CHARSET_LEFT_TO_RIGHT,
2940                   build_string ("Composite"),
2941                   build_string ("Composite characters"),
2942                   build_string ("Composite characters"),
2943                   build_string (""));
2944
2945   composite_char_row_next = 32;
2946   composite_char_col_next = 32;
2947
2948   Vcomposite_char_string2char_hash_table =
2949     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
2950   Vcomposite_char_char2string_hash_table =
2951     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
2952   staticpro (&Vcomposite_char_string2char_hash_table);
2953   staticpro (&Vcomposite_char_char2string_hash_table);
2954 #endif /* ENABLE_COMPOSITE_CHARS */
2955
2956 }