update.
[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 Charset_ID latin_a_char_to_charset[128] = {
1000   /* U+0100 */ LEADING_BYTE_LATIN_ISO8859_4,
1001   /* U+0101 */ LEADING_BYTE_LATIN_ISO8859_4,
1002   /* U+0102 */ LEADING_BYTE_LATIN_ISO8859_2,
1003   /* U+0103 */ LEADING_BYTE_LATIN_ISO8859_2,
1004   /* U+0104 */ LEADING_BYTE_LATIN_ISO8859_2,
1005   /* U+0105 */ LEADING_BYTE_LATIN_ISO8859_2,
1006   /* U+0106 */ LEADING_BYTE_LATIN_ISO8859_2,
1007   /* U+0107 */ LEADING_BYTE_LATIN_ISO8859_2,
1008   /* U+0108 */ LEADING_BYTE_LATIN_ISO8859_3,
1009   /* U+0109 */ LEADING_BYTE_LATIN_ISO8859_3,
1010   /* U+010A */ LEADING_BYTE_LATIN_ISO8859_3,
1011   /* U+010B */ LEADING_BYTE_LATIN_ISO8859_3,
1012   /* U+010C */ LEADING_BYTE_LATIN_ISO8859_2,
1013   /* U+010D */ LEADING_BYTE_LATIN_ISO8859_2,
1014   /* U+010E */ LEADING_BYTE_LATIN_ISO8859_2,
1015   /* U+010F */ LEADING_BYTE_LATIN_ISO8859_2,
1016   /* U+0110 */ LEADING_BYTE_LATIN_ISO8859_2,
1017   /* U+0111 */ LEADING_BYTE_LATIN_ISO8859_2,
1018   /* U+0112 */ LEADING_BYTE_LATIN_ISO8859_4,
1019   /* U+0113 */ LEADING_BYTE_LATIN_ISO8859_4,
1020   /* U+0114 */ LEADING_BYTE_UCS_BMP,
1021   /* U+0115 */ LEADING_BYTE_UCS_BMP,
1022   /* U+0116 */ LEADING_BYTE_LATIN_ISO8859_4,
1023   /* U+0117 */ LEADING_BYTE_LATIN_ISO8859_4,
1024   /* U+0118 */ LEADING_BYTE_LATIN_ISO8859_2,
1025   /* U+0119 */ LEADING_BYTE_LATIN_ISO8859_2,
1026   /* U+011A */ LEADING_BYTE_LATIN_ISO8859_2,
1027   /* U+011B */ LEADING_BYTE_LATIN_ISO8859_2,
1028   /* U+011C */ LEADING_BYTE_LATIN_ISO8859_3,
1029   /* U+011D */ LEADING_BYTE_LATIN_ISO8859_3,
1030   /* U+011E */ LEADING_BYTE_LATIN_ISO8859_3,
1031   /* U+011F */ LEADING_BYTE_LATIN_ISO8859_3,
1032   /* U+0120 */ LEADING_BYTE_LATIN_ISO8859_3,
1033   /* U+0121 */ LEADING_BYTE_LATIN_ISO8859_3,
1034   /* U+0122 */ LEADING_BYTE_LATIN_ISO8859_4,
1035   /* U+0123 */ LEADING_BYTE_LATIN_ISO8859_4,
1036   /* U+0124 */ LEADING_BYTE_LATIN_ISO8859_3,
1037   /* U+0125 */ LEADING_BYTE_LATIN_ISO8859_3,
1038   /* U+0126 */ LEADING_BYTE_LATIN_ISO8859_3,
1039   /* U+0127 */ LEADING_BYTE_LATIN_ISO8859_3,
1040   /* U+0128 */ LEADING_BYTE_LATIN_ISO8859_4,
1041   /* U+0129 */ LEADING_BYTE_LATIN_ISO8859_4,
1042   /* U+012A */ LEADING_BYTE_LATIN_ISO8859_4,
1043   /* U+012B */ LEADING_BYTE_LATIN_ISO8859_4,
1044   /* U+012C */ LEADING_BYTE_UCS_BMP,
1045   /* U+012D */ LEADING_BYTE_UCS_BMP,
1046   /* U+012E */ LEADING_BYTE_LATIN_ISO8859_4,
1047   /* U+012F */ LEADING_BYTE_LATIN_ISO8859_4,
1048   /* U+0130 */ LEADING_BYTE_LATIN_ISO8859_3,
1049   /* U+0131 */ LEADING_BYTE_LATIN_ISO8859_3,
1050   /* U+0132 */ LEADING_BYTE_JAPANESE_JISX0212,
1051   /* U+0133 */ LEADING_BYTE_JAPANESE_JISX0212,
1052   /* U+0134 */ LEADING_BYTE_LATIN_ISO8859_3,
1053   /* U+0135 */ LEADING_BYTE_LATIN_ISO8859_3,
1054   /* U+0136 */ LEADING_BYTE_LATIN_ISO8859_4,
1055   /* U+0137 */ LEADING_BYTE_LATIN_ISO8859_4,
1056   /* U+0138 */ LEADING_BYTE_LATIN_ISO8859_4,
1057   /* U+0139 */ LEADING_BYTE_LATIN_ISO8859_2,
1058   /* U+013A */ LEADING_BYTE_LATIN_ISO8859_2,
1059   /* U+013B */ LEADING_BYTE_LATIN_ISO8859_4,
1060   /* U+013C */ LEADING_BYTE_LATIN_ISO8859_4,
1061   /* U+013D */ LEADING_BYTE_LATIN_ISO8859_2,
1062   /* U+013E */ LEADING_BYTE_LATIN_ISO8859_2,
1063   /* U+013F */ LEADING_BYTE_JAPANESE_JISX0212,
1064   /* U+0140 */ LEADING_BYTE_JAPANESE_JISX0212,
1065   /* U+0141 */ LEADING_BYTE_LATIN_ISO8859_2,
1066   /* U+0142 */ LEADING_BYTE_LATIN_ISO8859_2,
1067   /* U+0143 */ LEADING_BYTE_LATIN_ISO8859_2,
1068   /* U+0144 */ LEADING_BYTE_LATIN_ISO8859_2,
1069   /* U+0145 */ LEADING_BYTE_LATIN_ISO8859_4,
1070   /* U+0146 */ LEADING_BYTE_LATIN_ISO8859_4,
1071   /* U+0147 */ LEADING_BYTE_LATIN_ISO8859_2,
1072   /* U+0148 */ LEADING_BYTE_LATIN_ISO8859_2,
1073   /* U+0149 */ LEADING_BYTE_JAPANESE_JISX0212,
1074   /* U+014A */ LEADING_BYTE_LATIN_ISO8859_4,
1075   /* U+014B */ LEADING_BYTE_LATIN_ISO8859_4,
1076   /* U+014C */ LEADING_BYTE_LATIN_ISO8859_4,
1077   /* U+014D */ LEADING_BYTE_LATIN_ISO8859_4,
1078   /* U+014E */ LEADING_BYTE_UCS_BMP,
1079   /* U+014F */ LEADING_BYTE_UCS_BMP,
1080   /* U+0150 */ LEADING_BYTE_LATIN_ISO8859_2,
1081   /* U+0151 */ LEADING_BYTE_LATIN_ISO8859_2,
1082   /* U+0152 */ LEADING_BYTE_JAPANESE_JISX0212,
1083   /* U+0153 */ LEADING_BYTE_JAPANESE_JISX0212,
1084   /* U+0154 */ LEADING_BYTE_LATIN_ISO8859_2,
1085   /* U+0155 */ LEADING_BYTE_LATIN_ISO8859_2,
1086   /* U+0156 */ LEADING_BYTE_LATIN_ISO8859_4,
1087   /* U+0157 */ LEADING_BYTE_LATIN_ISO8859_4,
1088   /* U+0158 */ LEADING_BYTE_LATIN_ISO8859_2,
1089   /* U+0159 */ LEADING_BYTE_LATIN_ISO8859_2,
1090   /* U+015A */ LEADING_BYTE_LATIN_ISO8859_2,
1091   /* U+015B */ LEADING_BYTE_LATIN_ISO8859_2,
1092   /* U+015C */ LEADING_BYTE_LATIN_ISO8859_3,
1093   /* U+015D */ LEADING_BYTE_LATIN_ISO8859_3,
1094   /* U+015E */ LEADING_BYTE_LATIN_ISO8859_2,
1095   /* U+015F */ LEADING_BYTE_LATIN_ISO8859_2,
1096   /* U+0160 */ LEADING_BYTE_LATIN_ISO8859_2,
1097   /* U+0161 */ LEADING_BYTE_LATIN_ISO8859_2,
1098   /* U+0162 */ LEADING_BYTE_LATIN_ISO8859_2,
1099   /* U+0163 */ LEADING_BYTE_LATIN_ISO8859_2,
1100   /* U+0164 */ LEADING_BYTE_LATIN_ISO8859_2,
1101   /* U+0165 */ LEADING_BYTE_LATIN_ISO8859_2,
1102   /* U+0166 */ LEADING_BYTE_LATIN_ISO8859_4,
1103   /* U+0167 */ LEADING_BYTE_LATIN_ISO8859_4,
1104   /* U+0168 */ LEADING_BYTE_LATIN_ISO8859_4,
1105   /* U+0169 */ LEADING_BYTE_LATIN_ISO8859_4,
1106   /* U+016A */ LEADING_BYTE_LATIN_ISO8859_4,
1107   /* U+016B */ LEADING_BYTE_LATIN_ISO8859_4,
1108   /* U+016C */ LEADING_BYTE_LATIN_ISO8859_3,
1109   /* U+016D */ LEADING_BYTE_LATIN_ISO8859_3,
1110   /* U+016E */ LEADING_BYTE_LATIN_ISO8859_2,
1111   /* U+016F */ LEADING_BYTE_LATIN_ISO8859_2,
1112   /* U+0170 */ LEADING_BYTE_LATIN_ISO8859_2,
1113   /* U+0171 */ LEADING_BYTE_LATIN_ISO8859_2,
1114   /* U+0172 */ LEADING_BYTE_LATIN_ISO8859_4,
1115   /* U+0173 */ LEADING_BYTE_LATIN_ISO8859_4,
1116   /* U+0174 */ LEADING_BYTE_JAPANESE_JISX0212,
1117   /* U+0175 */ LEADING_BYTE_JAPANESE_JISX0212,
1118   /* U+0176 */ LEADING_BYTE_JAPANESE_JISX0212,
1119   /* U+0177 */ LEADING_BYTE_JAPANESE_JISX0212,
1120   /* U+0178 */ LEADING_BYTE_JAPANESE_JISX0212,
1121   /* U+0179 */ LEADING_BYTE_LATIN_ISO8859_2,
1122   /* U+017A */ LEADING_BYTE_LATIN_ISO8859_2,
1123   /* U+017B */ LEADING_BYTE_LATIN_ISO8859_2,
1124   /* U+017C */ LEADING_BYTE_LATIN_ISO8859_2,
1125   /* U+017D */ LEADING_BYTE_LATIN_ISO8859_2,
1126   /* U+017E */ LEADING_BYTE_LATIN_ISO8859_2,
1127   /* U+017F */ LEADING_BYTE_UCS_BMP
1128 };
1129
1130 unsigned char latin_a_char_to_byte1[128] = {
1131   /* U+0100 */ 0xC0 - 0x80,
1132   /* U+0101 */ 0xE0 - 0x80,
1133   /* U+0102 */ 0xC3 - 0x80,
1134   /* U+0103 */ 0xE3 - 0x80,
1135   /* U+0104 */ 0xA1 - 0x80,
1136   /* U+0105 */ 0xB1 - 0x80,
1137   /* U+0106 */ 0xC6 - 0x80,
1138   /* U+0107 */ 0xE6 - 0x80,
1139   /* U+0108 */ 0xC6 - 0x80,
1140   /* U+0109 */ 0xE6 - 0x80,
1141   /* U+010A */ 0xC5 - 0x80,
1142   /* U+010B */ 0xE5 - 0x80,
1143   /* U+010C */ 0xC8 - 0x80,
1144   /* U+010D */ 0xE8 - 0x80,
1145   /* U+010E */ 0xCF - 0x80,
1146   /* U+010F */ 0xEF - 0x80,
1147   /* U+0110 */ 0xD0 - 0x80,
1148   /* U+0111 */ 0xF0 - 0x80,
1149   /* U+0112 */ 0xAA - 0x80,
1150   /* U+0113 */ 0xBA - 0x80,
1151   /* U+0114 */ 0x01,
1152   /* U+0115 */ 0x01,
1153   /* U+0116 */ 0xCC - 0x80,
1154   /* U+0117 */ 0xEC - 0x80,
1155   /* U+0118 */ 0xCA - 0x80,
1156   /* U+0119 */ 0xEA - 0x80,
1157   /* U+011A */ 0xCC - 0x80,
1158   /* U+011B */ 0xEC - 0x80,
1159   /* U+011C */ 0xD8 - 0x80,
1160   /* U+011D */ 0xF8 - 0x80,
1161   /* U+011E */ 0xAB - 0x80,
1162   /* U+011F */ 0xBB - 0x80,
1163   /* U+0120 */ 0xD5 - 0x80,
1164   /* U+0121 */ 0xF5 - 0x80,
1165   /* U+0122 */ 0xAB - 0x80,
1166   /* U+0123 */ 0xBB - 0x80,
1167   /* U+0124 */ 0xA6 - 0x80,
1168   /* U+0125 */ 0xB6 - 0x80,
1169   /* U+0126 */ 0xA1 - 0x80,
1170   /* U+0127 */ 0xB1 - 0x80,
1171   /* U+0128 */ 0xA5 - 0x80,
1172   /* U+0129 */ 0xB5 - 0x80,
1173   /* U+012A */ 0xCF - 0x80,
1174   /* U+012B */ 0xEF - 0x80,
1175   /* U+012C */ 0x01,
1176   /* U+012D */ 0x01,
1177   /* U+012E */ 0xC7 - 0x80,
1178   /* U+012F */ 0xE7 - 0x80,
1179   /* U+0130 */ 0xA9 - 0x80,
1180   /* U+0131 */ 0xB9 - 0x80,
1181   /* U+0132 */ 0x29,
1182   /* U+0133 */ 0x29,
1183   /* U+0134 */ 0xAC - 0x80,
1184   /* U+0135 */ 0xBC - 0x80,
1185   /* U+0136 */ 0xD3 - 0x80,
1186   /* U+0137 */ 0xF3 - 0x80,
1187   /* U+0138 */ 0xA2 - 0x80,
1188   /* U+0139 */ 0xC5 - 0x80,
1189   /* U+013A */ 0xE5 - 0x80,
1190   /* U+013B */ 0xA6 - 0x80,
1191   /* U+013C */ 0xB6 - 0x80,
1192   /* U+013D */ 0xA5 - 0x80,
1193   /* U+013E */ 0xB5 - 0x80,
1194   /* U+013F */ 0x29,
1195   /* U+0140 */ 0x29,
1196   /* U+0141 */ 0xA3 - 0x80,
1197   /* U+0142 */ 0xB3 - 0x80,
1198   /* U+0143 */ 0xD1 - 0x80,
1199   /* U+0144 */ 0xF1 - 0x80,
1200   /* U+0145 */ 0xD1 - 0x80,
1201   /* U+0146 */ 0xF1 - 0x80,
1202   /* U+0147 */ 0xD2 - 0x80,
1203   /* U+0148 */ 0xF2 - 0x80,
1204   /* U+0149 */ 0x29,
1205   /* U+014A */ 0xBD - 0x80,
1206   /* U+014B */ 0xBF - 0x80,
1207   /* U+014C */ 0xD2 - 0x80,
1208   /* U+014D */ 0xF2 - 0x80,
1209   /* U+014E */ 0x01,
1210   /* U+014F */ 0x01,
1211   /* U+0150 */ 0xD5 - 0x80,
1212   /* U+0151 */ 0xF5 - 0x80,
1213   /* U+0152 */ 0x29,
1214   /* U+0153 */ 0x29,
1215   /* U+0154 */ 0xC0 - 0x80,
1216   /* U+0155 */ 0xE0 - 0x80,
1217   /* U+0156 */ 0xA3 - 0x80,
1218   /* U+0157 */ 0xB3 - 0x80,
1219   /* U+0158 */ 0xD8 - 0x80,
1220   /* U+0159 */ 0xF8 - 0x80,
1221   /* U+015A */ 0xA6 - 0x80,
1222   /* U+015B */ 0xB6 - 0x80,
1223   /* U+015C */ 0xDE - 0x80,
1224   /* U+015D */ 0xFE - 0x80,
1225   /* U+015E */ 0xAA - 0x80,
1226   /* U+015F */ 0xBA - 0x80,
1227   /* U+0160 */ 0xA9 - 0x80,
1228   /* U+0161 */ 0xB9 - 0x80,
1229   /* U+0162 */ 0xDE - 0x80,
1230   /* U+0163 */ 0xFE - 0x80,
1231   /* U+0164 */ 0xAB - 0x80,
1232   /* U+0165 */ 0xBB - 0x80,
1233   /* U+0166 */ 0xAC - 0x80,
1234   /* U+0167 */ 0xBC - 0x80,
1235   /* U+0168 */ 0xDD - 0x80,
1236   /* U+0169 */ 0xFD - 0x80,
1237   /* U+016A */ 0xDE - 0x80,
1238   /* U+016B */ 0xFE - 0x80,
1239   /* U+016C */ 0xDD - 0x80,
1240   /* U+016D */ 0xFD - 0x80,
1241   /* U+016E */ 0xD9 - 0x80,
1242   /* U+016F */ 0xF9 - 0x80,
1243   /* U+0170 */ 0xDB - 0x80,
1244   /* U+0171 */ 0xFB - 0x80,
1245   /* U+0172 */ 0xD9 - 0x80,
1246   /* U+0173 */ 0xF9 - 0x80,
1247   /* U+0174 */ 0x2A,
1248   /* U+0175 */ 0x2B,
1249   /* U+0176 */ 0x2A,
1250   /* U+0177 */ 0x2B,
1251   /* U+0178 */ 0x2A,
1252   /* U+0179 */ 0xAC - 0x80,
1253   /* U+017A */ 0xBC - 0x80,
1254   /* U+017B */ 0xAF - 0x80,
1255   /* U+017C */ 0xBF - 0x80,
1256   /* U+017D */ 0xAE - 0x80,
1257   /* U+017E */ 0xBE - 0x80,
1258   /* U+017F */ 0x01
1259 };
1260
1261 unsigned char latin_a_char_to_byte2[128] = {
1262   /* U+0100 */ 0x00,
1263   /* U+0101 */ 0x00,
1264   /* U+0102 */ 0x00,
1265   /* U+0103 */ 0x00,
1266   /* U+0104 */ 0x00,
1267   /* U+0105 */ 0x00,
1268   /* U+0106 */ 0x00,
1269   /* U+0107 */ 0x00,
1270   /* U+0108 */ 0x00,
1271   /* U+0109 */ 0x00,
1272   /* U+010A */ 0x00,
1273   /* U+010B */ 0x00,
1274   /* U+010C */ 0x00,
1275   /* U+010D */ 0x00,
1276   /* U+010E */ 0x00,
1277   /* U+010F */ 0x00,
1278   /* U+0110 */ 0x00,
1279   /* U+0111 */ 0x00,
1280   /* U+0112 */ 0x00,
1281   /* U+0113 */ 0x00,
1282   /* U+0114 */ 0x14,
1283   /* U+0115 */ 0x15,
1284   /* U+0116 */ 0x00,
1285   /* U+0117 */ 0x00,
1286   /* U+0118 */ 0x00,
1287   /* U+0119 */ 0x00,
1288   /* U+011A */ 0x00,
1289   /* U+011B */ 0x00,
1290   /* U+011C */ 0x00,
1291   /* U+011D */ 0x00,
1292   /* U+011E */ 0x00,
1293   /* U+011F */ 0x00,
1294   /* U+0120 */ 0x00,
1295   /* U+0121 */ 0x00,
1296   /* U+0122 */ 0x00,
1297   /* U+0123 */ 0x00,
1298   /* U+0124 */ 0x00,
1299   /* U+0125 */ 0x00,
1300   /* U+0126 */ 0x00,
1301   /* U+0127 */ 0x00,
1302   /* U+0128 */ 0x00,
1303   /* U+0129 */ 0x00,
1304   /* U+012A */ 0x00,
1305   /* U+012B */ 0x00,
1306   /* U+012C */ 0x2C,
1307   /* U+012D */ 0x2D,
1308   /* U+012E */ 0x00,
1309   /* U+012F */ 0x00,
1310   /* U+0130 */ 0x00,
1311   /* U+0131 */ 0x00,
1312   /* U+0132 */ 0x26,
1313   /* U+0133 */ 0x46,
1314   /* U+0134 */ 0x00,
1315   /* U+0135 */ 0x00,
1316   /* U+0136 */ 0x00,
1317   /* U+0137 */ 0x00,
1318   /* U+0138 */ 0x00,
1319   /* U+0139 */ 0x00,
1320   /* U+013A */ 0x00,
1321   /* U+013B */ 0x00,
1322   /* U+013C */ 0x00,
1323   /* U+013D */ 0x00,
1324   /* U+013E */ 0x00,
1325   /* U+013F */ 0x29,
1326   /* U+0140 */ 0x49,
1327   /* U+0141 */ 0x00,
1328   /* U+0142 */ 0x00,
1329   /* U+0143 */ 0x00,
1330   /* U+0144 */ 0x00,
1331   /* U+0145 */ 0x00,
1332   /* U+0146 */ 0x00,
1333   /* U+0147 */ 0x00,
1334   /* U+0148 */ 0x00,
1335   /* U+0149 */ 0x4A,
1336   /* U+014A */ 0x00,
1337   /* U+014B */ 0x00,
1338   /* U+014C */ 0x00,
1339   /* U+014D */ 0x00,
1340   /* U+014E */ 0x4E,
1341   /* U+014F */ 0x4F,
1342   /* U+0150 */ 0x00,
1343   /* U+0151 */ 0x00,
1344   /* U+0152 */ 0x2D,
1345   /* U+0153 */ 0x4D,
1346   /* U+0154 */ 0x00,
1347   /* U+0155 */ 0x00,
1348   /* U+0156 */ 0x00,
1349   /* U+0157 */ 0x00,
1350   /* U+0158 */ 0x00,
1351   /* U+0159 */ 0x00,
1352   /* U+015A */ 0x00,
1353   /* U+015B */ 0x00,
1354   /* U+015C */ 0x00,
1355   /* U+015D */ 0x00,
1356   /* U+015E */ 0x00,
1357   /* U+015F */ 0x00,
1358   /* U+0160 */ 0x00,
1359   /* U+0161 */ 0x00,
1360   /* U+0162 */ 0x00,
1361   /* U+0163 */ 0x00,
1362   /* U+0164 */ 0x00,
1363   /* U+0165 */ 0x00,
1364   /* U+0166 */ 0x00,
1365   /* U+0167 */ 0x00,
1366   /* U+0168 */ 0x00,
1367   /* U+0169 */ 0x00,
1368   /* U+016A */ 0x00,
1369   /* U+016B */ 0x00,
1370   /* U+016C */ 0x00,
1371   /* U+016D */ 0x00,
1372   /* U+016E */ 0x00,
1373   /* U+016F */ 0x00,
1374   /* U+0170 */ 0x00,
1375   /* U+0171 */ 0x00,
1376   /* U+0172 */ 0x00,
1377   /* U+0173 */ 0x00,
1378   /* U+0174 */ 0x71,
1379   /* U+0175 */ 0x71,
1380   /* U+0176 */ 0x74,
1381   /* U+0177 */ 0x74,
1382   /* U+0178 */ 0x73,
1383   /* U+0179 */ 0x00,
1384   /* U+017A */ 0x00,
1385   /* U+017B */ 0x00,
1386   /* U+017C */ 0x00,
1387   /* U+017D */ 0x00,
1388   /* U+017E */ 0x00,
1389   /* U+017F */ 0x7F
1390 };
1391
1392 Lisp_Object Vutf_2000_version;
1393 #endif
1394
1395 #ifndef UTF2000
1396 int leading_code_private_11;
1397 #endif
1398
1399 Lisp_Object Qcharsetp;
1400
1401 /* Qdoc_string, Qdimension, Qchars defined in general.c */
1402 Lisp_Object Qregistry, Qfinal, Qgraphic;
1403 Lisp_Object Qdirection;
1404 Lisp_Object Qreverse_direction_charset;
1405 Lisp_Object Qleading_byte;
1406 Lisp_Object Qshort_name, Qlong_name;
1407
1408 Lisp_Object Qascii,
1409   Qcontrol_1,
1410   Qlatin_iso8859_1,
1411   Qlatin_iso8859_2,
1412   Qlatin_iso8859_3,
1413   Qlatin_iso8859_4,
1414   Qthai_tis620,
1415   Qgreek_iso8859_7,
1416   Qarabic_iso8859_6,
1417   Qhebrew_iso8859_8,
1418   Qkatakana_jisx0201,
1419   Qlatin_jisx0201,
1420   Qcyrillic_iso8859_5,
1421   Qlatin_iso8859_9,
1422   Qjapanese_jisx0208_1978,
1423   Qchinese_gb2312,
1424   Qjapanese_jisx0208,
1425   Qkorean_ksc5601,
1426   Qjapanese_jisx0212,
1427   Qchinese_cns11643_1,
1428   Qchinese_cns11643_2,
1429 #ifdef UTF2000
1430   Qchinese_cns11643_3,
1431   Qchinese_cns11643_4,
1432   Qchinese_cns11643_5,
1433   Qchinese_cns11643_6,
1434   Qchinese_cns11643_7,
1435   Qucs_bmp,
1436   Qlatin_viscii_lower,
1437   Qlatin_viscii_upper,
1438 #endif
1439   Qchinese_big5_1,
1440   Qchinese_big5_2,
1441   Qcomposite;
1442
1443 Lisp_Object Ql2r, Qr2l;
1444
1445 Lisp_Object Vcharset_hash_table;
1446
1447 static Charset_ID next_allocated_1_byte_leading_byte;
1448 static Charset_ID next_allocated_2_byte_leading_byte;
1449
1450 /* Composite characters are characters constructed by overstriking two
1451    or more regular characters.
1452
1453    1) The old Mule implementation involves storing composite characters
1454       in a buffer as a tag followed by all of the actual characters
1455       used to make up the composite character.  I think this is a bad
1456       idea; it greatly complicates code that wants to handle strings
1457       one character at a time because it has to deal with the possibility
1458       of great big ungainly characters.  It's much more reasonable to
1459       simply store an index into a table of composite characters.
1460
1461    2) The current implementation only allows for 16,384 separate
1462       composite characters over the lifetime of the XEmacs process.
1463       This could become a potential problem if the user
1464       edited lots of different files that use composite characters.
1465       Due to FSF bogosity, increasing the number of allowable
1466       composite characters under Mule would decrease the number
1467       of possible faces that can exist.  Mule already has shrunk
1468       this to 2048, and further shrinkage would become uncomfortable.
1469       No such problems exist in XEmacs.
1470
1471       Composite characters could be represented as 0x80 C1 C2 C3,
1472       where each C[1-3] is in the range 0xA0 - 0xFF.  This allows
1473       for slightly under 2^20 (one million) composite characters
1474       over the XEmacs process lifetime, and you only need to
1475       increase the size of a Mule character from 19 to 21 bits.
1476       Or you could use 0x80 C1 C2 C3 C4, allowing for about
1477       85 million (slightly over 2^26) composite characters. */
1478
1479 \f
1480 /************************************************************************/
1481 /*                       Basic Emchar functions                         */
1482 /************************************************************************/
1483
1484 /* Convert a non-ASCII Mule character C into a one-character Mule-encoded
1485    string in STR.  Returns the number of bytes stored.
1486    Do not call this directly.  Use the macro set_charptr_emchar() instead.
1487  */
1488
1489 Bytecount
1490 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
1491 {
1492   Bufbyte *p;
1493 #ifndef UTF2000
1494   Charset_ID lb;
1495   int c1, c2;
1496   Lisp_Object charset;
1497 #endif
1498
1499   p = str;
1500 #ifdef UTF2000
1501   if ( c <= 0x7f )
1502     {
1503       *p++ = c;
1504     }
1505   else if ( c <= 0x7ff )
1506     {
1507       *p++ = (c >> 6) | 0xc0;
1508       *p++ = (c & 0x3f) | 0x80;
1509     }
1510   else if ( c <= 0xffff )
1511     {
1512       *p++ =  (c >> 12) | 0xe0;
1513       *p++ = ((c >>  6) & 0x3f) | 0x80;
1514       *p++ =  (c        & 0x3f) | 0x80;
1515     }
1516   else if ( c <= 0x1fffff )
1517     {
1518       *p++ =  (c >> 18) | 0xf0;
1519       *p++ = ((c >> 12) & 0x3f) | 0x80;
1520       *p++ = ((c >>  6) & 0x3f) | 0x80;
1521       *p++ =  (c        & 0x3f) | 0x80;
1522     }
1523   else if ( c <= 0x3ffffff )
1524     {
1525       *p++ =  (c >> 24) | 0xf8;
1526       *p++ = ((c >> 18) & 0x3f) | 0x80;
1527       *p++ = ((c >> 12) & 0x3f) | 0x80;
1528       *p++ = ((c >>  6) & 0x3f) | 0x80;
1529       *p++ =  (c        & 0x3f) | 0x80;
1530     }
1531   else
1532     {
1533       *p++ =  (c >> 30) | 0xfc;
1534       *p++ = ((c >> 24) & 0x3f) | 0x80;
1535       *p++ = ((c >> 18) & 0x3f) | 0x80;
1536       *p++ = ((c >> 12) & 0x3f) | 0x80;
1537       *p++ = ((c >>  6) & 0x3f) | 0x80;
1538       *p++ =  (c        & 0x3f) | 0x80;
1539     }
1540 #else
1541   BREAKUP_CHAR (c, charset, c1, c2);
1542   lb = CHAR_LEADING_BYTE (c);
1543   if (LEADING_BYTE_PRIVATE_P (lb))
1544     *p++ = PRIVATE_LEADING_BYTE_PREFIX (lb);
1545   *p++ = lb;
1546   if (EQ (charset, Vcharset_control_1))
1547     c1 += 0x20;
1548   *p++ = c1 | 0x80;
1549   if (c2)
1550     *p++ = c2 | 0x80;
1551 #endif
1552   return (p - str);
1553 }
1554
1555 /* Return the first character from a Mule-encoded string in STR,
1556    assuming it's non-ASCII.  Do not call this directly.
1557    Use the macro charptr_emchar() instead. */
1558
1559 Emchar
1560 non_ascii_charptr_emchar (CONST Bufbyte *str)
1561 {
1562 #ifdef UTF2000
1563   Bufbyte b;
1564   Emchar ch;
1565   int len;
1566
1567   b = *str++;
1568   if ( b >= 0xfc )
1569     {
1570       ch = (b & 0x01);
1571       len = 5;
1572     }
1573   else if ( b >= 0xf8 )
1574     {
1575       ch = b & 0x03;
1576       len = 4;
1577     }
1578   else if ( b >= 0xf0 )
1579     {
1580       ch = b & 0x07;
1581       len = 3;
1582     }
1583   else if ( b >= 0xe0 )
1584     {
1585       ch = b & 0x0f;
1586       len = 2;
1587     }
1588   else if ( b >= 0xc0 )
1589     {
1590       ch = b & 0x1f;
1591       len = 1;
1592     }
1593   else
1594     {
1595       ch = b;
1596       len = 0;
1597     }
1598   for( ; len > 0; len-- )
1599     {
1600       b = *str++;
1601       ch = ( ch << 6 ) | ( b & 0x3f );
1602     }
1603   return ch;
1604 #else
1605   Bufbyte i0 = *str, i1, i2 = 0;
1606   Lisp_Object charset;
1607
1608   if (i0 == LEADING_BYTE_CONTROL_1)
1609     return (Emchar) (*++str - 0x20);
1610
1611   if (LEADING_BYTE_PREFIX_P (i0))
1612     i0 = *++str;
1613
1614   i1 = *++str & 0x7F;
1615
1616   charset = CHARSET_BY_LEADING_BYTE (i0);
1617   if (XCHARSET_DIMENSION (charset) == 2)
1618     i2 = *++str & 0x7F;
1619
1620   return MAKE_CHAR (charset, i1, i2);
1621 #endif
1622 }
1623
1624 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
1625    Do not call this directly.  Use the macro valid_char_p() instead. */
1626
1627 #ifndef UTF2000
1628 int
1629 non_ascii_valid_char_p (Emchar ch)
1630 {
1631   int f1, f2, f3;
1632
1633   /* Must have only lowest 19 bits set */
1634   if (ch & ~0x7FFFF)
1635     return 0;
1636
1637   f1 = CHAR_FIELD1 (ch);
1638   f2 = CHAR_FIELD2 (ch);
1639   f3 = CHAR_FIELD3 (ch);
1640
1641   if (f1 == 0)
1642     {
1643       Lisp_Object charset;
1644
1645       if (f2 < MIN_CHAR_FIELD2_OFFICIAL ||
1646           (f2 > MAX_CHAR_FIELD2_OFFICIAL && f2 < MIN_CHAR_FIELD2_PRIVATE) ||
1647            f2 > MAX_CHAR_FIELD2_PRIVATE)
1648         return 0;
1649       if (f3 < 0x20)
1650         return 0;
1651
1652       if (f3 != 0x20 && f3 != 0x7F)
1653         return 1;
1654
1655       /*
1656          NOTE: This takes advantage of the fact that
1657          FIELD2_TO_OFFICIAL_LEADING_BYTE and
1658          FIELD2_TO_PRIVATE_LEADING_BYTE are the same.
1659          */
1660       charset = CHARSET_BY_LEADING_BYTE (f2 + FIELD2_TO_OFFICIAL_LEADING_BYTE);
1661       return (XCHARSET_CHARS (charset) == 96);
1662     }
1663   else
1664     {
1665       Lisp_Object charset;
1666
1667       if (f1 < MIN_CHAR_FIELD1_OFFICIAL ||
1668           (f1 > MAX_CHAR_FIELD1_OFFICIAL && f1 < MIN_CHAR_FIELD1_PRIVATE) ||
1669           f1 > MAX_CHAR_FIELD1_PRIVATE)
1670         return 0;
1671       if (f2 < 0x20 || f3 < 0x20)
1672         return 0;
1673
1674 #ifdef ENABLE_COMPOSITE_CHARS
1675       if (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE == LEADING_BYTE_COMPOSITE)
1676         {
1677           if (UNBOUNDP (Fgethash (make_int (ch),
1678                                   Vcomposite_char_char2string_hash_table,
1679                                   Qunbound)))
1680             return 0;
1681           return 1;
1682         }
1683 #endif /* ENABLE_COMPOSITE_CHARS */
1684
1685       if (f2 != 0x20 && f2 != 0x7F && f3 != 0x20 && f3 != 0x7F)
1686         return 1;
1687
1688       if (f1 <= MAX_CHAR_FIELD1_OFFICIAL)
1689         charset =
1690           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE);
1691       else
1692         charset =
1693           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_PRIVATE_LEADING_BYTE);
1694
1695       return (XCHARSET_CHARS (charset) == 96);
1696     }
1697 }
1698 #endif
1699
1700 \f
1701 /************************************************************************/
1702 /*                       Basic string functions                         */
1703 /************************************************************************/
1704
1705 /* Copy the character pointed to by PTR into STR, assuming it's
1706    non-ASCII.  Do not call this directly.  Use the macro
1707    charptr_copy_char() instead. */
1708
1709 Bytecount
1710 non_ascii_charptr_copy_char (CONST Bufbyte *ptr, Bufbyte *str)
1711 {
1712   Bufbyte *strptr = str;
1713   *strptr = *ptr++;
1714   switch (REP_BYTES_BY_FIRST_BYTE (*strptr))
1715     {
1716       /* Notice fallthrough. */
1717 #ifdef UTF2000
1718     case 6: *++strptr = *ptr++;
1719     case 5: *++strptr = *ptr++;
1720 #endif
1721     case 4: *++strptr = *ptr++;
1722     case 3: *++strptr = *ptr++;
1723     case 2: *++strptr = *ptr;
1724       break;
1725     default:
1726       abort ();
1727     }
1728   return strptr + 1 - str;
1729 }
1730
1731 \f
1732 /************************************************************************/
1733 /*                        streams of Emchars                            */
1734 /************************************************************************/
1735
1736 /* Treat a stream as a stream of Emchar's rather than a stream of bytes.
1737    The functions below are not meant to be called directly; use
1738    the macros in insdel.h. */
1739
1740 Emchar
1741 Lstream_get_emchar_1 (Lstream *stream, int ch)
1742 {
1743   Bufbyte str[MAX_EMCHAR_LEN];
1744   Bufbyte *strptr = str;
1745
1746   str[0] = (Bufbyte) ch;
1747   switch (REP_BYTES_BY_FIRST_BYTE (ch))
1748     {
1749       /* Notice fallthrough. */
1750 #ifdef UTF2000
1751     case 6:
1752       ch = Lstream_getc (stream);
1753       assert (ch >= 0);
1754       *++strptr = (Bufbyte) ch;
1755     case 5:
1756       ch = Lstream_getc (stream);
1757       assert (ch >= 0);
1758       *++strptr = (Bufbyte) ch;
1759 #endif
1760     case 4:
1761       ch = Lstream_getc (stream);
1762       assert (ch >= 0);
1763       *++strptr = (Bufbyte) ch;
1764     case 3:
1765       ch = Lstream_getc (stream);
1766       assert (ch >= 0);
1767       *++strptr = (Bufbyte) ch;
1768     case 2:
1769       ch = Lstream_getc (stream);
1770       assert (ch >= 0);
1771       *++strptr = (Bufbyte) ch;
1772       break;
1773     default:
1774       abort ();
1775     }
1776   return charptr_emchar (str);
1777 }
1778
1779 int
1780 Lstream_fput_emchar (Lstream *stream, Emchar ch)
1781 {
1782   Bufbyte str[MAX_EMCHAR_LEN];
1783   Bytecount len = set_charptr_emchar (str, ch);
1784   return Lstream_write (stream, str, len);
1785 }
1786
1787 void
1788 Lstream_funget_emchar (Lstream *stream, Emchar ch)
1789 {
1790   Bufbyte str[MAX_EMCHAR_LEN];
1791   Bytecount len = set_charptr_emchar (str, ch);
1792   Lstream_unread (stream, str, len);
1793 }
1794
1795 \f
1796 /************************************************************************/
1797 /*                            charset object                            */
1798 /************************************************************************/
1799
1800 static Lisp_Object
1801 mark_charset (Lisp_Object obj, void (*markobj) (Lisp_Object))
1802 {
1803   struct Lisp_Charset *cs = XCHARSET (obj);
1804
1805   markobj (cs->short_name);
1806   markobj (cs->long_name);
1807   markobj (cs->doc_string);
1808   markobj (cs->registry);
1809   markobj (cs->ccl_program);
1810   return cs->name;
1811 }
1812
1813 static void
1814 print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
1815 {
1816   struct Lisp_Charset *cs = XCHARSET (obj);
1817   char buf[200];
1818
1819   if (print_readably)
1820     error ("printing unreadable object #<charset %s 0x%x>",
1821            string_data (XSYMBOL (CHARSET_NAME (cs))->name),
1822            cs->header.uid);
1823
1824   write_c_string ("#<charset ", printcharfun);
1825   print_internal (CHARSET_NAME (cs), printcharfun, 0);
1826   write_c_string (" ", printcharfun);
1827   print_internal (CHARSET_SHORT_NAME (cs), printcharfun, 1);
1828   write_c_string (" ", printcharfun);
1829   print_internal (CHARSET_LONG_NAME (cs), printcharfun, 1);
1830   write_c_string (" ", printcharfun);
1831   print_internal (CHARSET_DOC_STRING (cs), printcharfun, 1);
1832   sprintf (buf, " %s %s cols=%d g%d final='%c' reg=",
1833            CHARSET_TYPE (cs) == CHARSET_TYPE_94    ? "94" :
1834            CHARSET_TYPE (cs) == CHARSET_TYPE_96    ? "96" :
1835            CHARSET_TYPE (cs) == CHARSET_TYPE_94X94 ? "94x94" :
1836            "96x96",
1837            CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? "l2r" : "r2l",
1838            CHARSET_COLUMNS (cs),
1839            CHARSET_GRAPHIC (cs),
1840            CHARSET_FINAL (cs));
1841   write_c_string (buf, printcharfun);
1842   print_internal (CHARSET_REGISTRY (cs), printcharfun, 0);
1843   sprintf (buf, " 0x%x>", cs->header.uid);
1844   write_c_string (buf, printcharfun);
1845 }
1846
1847 static const struct lrecord_description charset_description[] = {
1848   { XD_LISP_OBJECT, offsetof(struct Lisp_Charset, name), 7 },
1849   { XD_END }
1850 };
1851
1852 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
1853                                mark_charset, print_charset, 0, 0, 0,
1854                                charset_description,
1855                                struct Lisp_Charset);
1856 /* Make a new charset. */
1857
1858 static Lisp_Object
1859 make_charset (Charset_ID id, Lisp_Object name,
1860               unsigned char type, unsigned char columns, unsigned char graphic,
1861               Bufbyte final, unsigned char direction, Lisp_Object short_name,
1862               Lisp_Object long_name, Lisp_Object doc,
1863               Lisp_Object reg,
1864               Emchar* decoding_table,
1865               Emchar ucs_min, Emchar ucs_max, Emchar code_offset)
1866 {
1867   Lisp_Object obj;
1868   struct Lisp_Charset *cs =
1869     alloc_lcrecord_type (struct Lisp_Charset, &lrecord_charset);
1870   XSETCHARSET (obj, cs);
1871
1872   CHARSET_ID            (cs) = id;
1873   CHARSET_NAME          (cs) = name;
1874   CHARSET_SHORT_NAME    (cs) = short_name;
1875   CHARSET_LONG_NAME     (cs) = long_name;
1876   CHARSET_DIRECTION     (cs) = direction;
1877   CHARSET_TYPE          (cs) = type;
1878   CHARSET_COLUMNS       (cs) = columns;
1879   CHARSET_GRAPHIC       (cs) = graphic;
1880   CHARSET_FINAL         (cs) = final;
1881   CHARSET_DOC_STRING    (cs) = doc;
1882   CHARSET_REGISTRY      (cs) = reg;
1883   CHARSET_CCL_PROGRAM   (cs) = Qnil;
1884   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
1885 #ifdef UTF2000
1886   CHARSET_DECODING_TABLE(cs) = decoding_table;
1887   CHARSET_UCS_MIN(cs) = ucs_min;
1888   CHARSET_UCS_MAX(cs) = ucs_max;
1889   CHARSET_CODE_OFFSET(cs) = code_offset;
1890 #endif
1891   
1892   switch ( CHARSET_TYPE (cs) )
1893     {
1894     case CHARSET_TYPE_94:
1895       CHARSET_DIMENSION (cs) = 1;
1896       CHARSET_CHARS (cs) = 94;
1897 #ifdef UTF2000
1898       if (decoding_table != NULL)
1899         {
1900           size_t i;
1901           CHARSET_TO_BYTE1_TABLE(cs) = make_byte_from_character_table();
1902           for (i = 0; i < 94; i++)
1903             {
1904               Emchar c = decoding_table[i];
1905
1906               if (c <= 0xffff)
1907                 put_byte_from_character_table (c, i + 33,
1908                                                CHARSET_TO_BYTE1_TABLE(cs));
1909             }
1910         }
1911       else
1912         CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1913       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1914 #endif
1915       break;
1916     case CHARSET_TYPE_96:
1917       CHARSET_DIMENSION (cs) = 1;
1918       CHARSET_CHARS (cs) = 96;
1919 #ifdef UTF2000
1920       if (decoding_table != NULL)
1921         {
1922           size_t i;
1923           CHARSET_TO_BYTE1_TABLE(cs) = make_byte_from_character_table();
1924           for (i = 0; i < 96; i++)
1925             {
1926               Emchar c = decoding_table[i];
1927
1928               if (c <= 0xffff)
1929                 put_byte_from_character_table (c, i + 32,
1930                                                CHARSET_TO_BYTE1_TABLE(cs));
1931             }
1932         }
1933       else
1934         CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1935       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1936 #endif
1937       break;
1938     case CHARSET_TYPE_94X94:
1939       CHARSET_DIMENSION (cs) = 2;
1940       CHARSET_CHARS (cs) = 94;
1941 #ifdef UTF2000
1942       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1943       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1944 #endif
1945       break;
1946     case CHARSET_TYPE_96X96:
1947       CHARSET_DIMENSION (cs) = 2;
1948       CHARSET_CHARS (cs) = 96;
1949 #ifdef UTF2000
1950       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1951       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1952 #endif
1953       break;
1954 #ifdef UTF2000
1955     case CHARSET_TYPE_128X128:
1956       CHARSET_DIMENSION (cs) = 2;
1957       CHARSET_CHARS (cs) = 128;
1958 #ifdef UTF2000
1959       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1960       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1961 #endif
1962       break;
1963     case CHARSET_TYPE_256X256:
1964       CHARSET_DIMENSION (cs) = 2;
1965       CHARSET_CHARS (cs) = 256;
1966 #ifdef UTF2000
1967       CHARSET_TO_BYTE1_TABLE(cs) = NULL;
1968       CHARSET_TO_BYTE2_TABLE(cs) = NULL;
1969 #endif
1970       break;
1971 #endif
1972     }
1973
1974 #ifndef UTF2000
1975   if (id == LEADING_BYTE_ASCII)
1976     CHARSET_REP_BYTES (cs) = 1;
1977   else if (id < 0xA0)
1978     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
1979   else
1980     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
1981 #endif
1982   
1983   if (final)
1984     {
1985       /* some charsets do not have final characters.  This includes
1986          ASCII, Control-1, Composite, and the two faux private
1987          charsets. */
1988 #if UTF2000
1989       assert (NILP (charset_by_attributes[type][final]));
1990       charset_by_attributes[type][final] = obj;
1991 #else
1992       assert (NILP (charset_by_attributes[type][final][direction]));
1993       charset_by_attributes[type][final][direction] = obj;
1994 #endif
1995     }
1996
1997   assert (NILP (charset_by_leading_byte[id - MIN_LEADING_BYTE]));
1998   charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
1999 #ifndef UTF2000
2000   if (id < 0xA0)
2001     /* official leading byte */
2002     rep_bytes_by_first_byte[id] = CHARSET_REP_BYTES (cs);
2003 #endif
2004
2005   /* Some charsets are "faux" and don't have names or really exist at
2006      all except in the leading-byte table. */
2007   if (!NILP (name))
2008     Fputhash (name, obj, Vcharset_hash_table);
2009   return obj;
2010 }
2011
2012 static int
2013 get_unallocated_leading_byte (int dimension)
2014 {
2015   Charset_ID lb;
2016
2017   if (dimension == 1)
2018     {
2019       if (next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
2020         lb = 0;
2021       else
2022         lb = next_allocated_1_byte_leading_byte++;
2023     }
2024   else
2025     {
2026       if (next_allocated_2_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_2)
2027         lb = 0;
2028       else
2029         lb = next_allocated_2_byte_leading_byte++;
2030     }
2031
2032   if (!lb)
2033     signal_simple_error
2034       ("No more character sets free for this dimension",
2035        make_int (dimension));
2036
2037   return lb;
2038 }
2039
2040 #ifdef UTF2000
2041 unsigned char
2042 charset_get_byte1 (Lisp_Object charset, Emchar ch)
2043 {
2044   Emchar_to_byte_table* table;
2045   int d;
2046
2047   if ((table = XCHARSET_TO_BYTE1_TABLE (charset)) != NULL)
2048     return get_byte_from_character_table (ch, table);
2049   else if ((CHARSET_UCS_MIN (XCHARSET (charset)) <= ch)
2050            && (ch <= CHARSET_UCS_MAX (XCHARSET (charset))))
2051     return ch - CHARSET_UCS_MIN (XCHARSET (charset))
2052       +  CHARSET_CODE_OFFSET (XCHARSET (charset));
2053   else if (XCHARSET_DIMENSION (charset) == 1)
2054     {
2055       if (XCHARSET_CHARS (charset) == 94)
2056         {
2057           if (((d = ch - (MIN_CHAR_94
2058                           + (XCHARSET_FINAL (charset) - '0') * 94)) >= 0)
2059               && (d < 94))
2060             return d + 32;
2061         }
2062       else if (XCHARSET_CHARS (charset) == 96)
2063         {
2064           if (((d = ch - (MIN_CHAR_96
2065                           + (XCHARSET_FINAL (charset) - '0') * 96)) >= 0)
2066               && (d < 96))
2067             return d + 33;
2068         }
2069       else
2070         return 0;
2071     }
2072   else if (XCHARSET_DIMENSION (charset) == 2)
2073     {
2074       if (XCHARSET_CHARS (charset) == 94)
2075         {
2076           if (((d = ch - (MIN_CHAR_94x94
2077                           + (XCHARSET_FINAL (charset) - '0') * 94 * 94)) >= 0)
2078               && (d < 94 * 94))
2079             return (d / 94) + 33;
2080         }
2081       else if (XCHARSET_CHARS (charset) == 96)
2082         {
2083           if (((d = ch - (MIN_CHAR_96x96
2084                           + (XCHARSET_FINAL (charset) - '0') * 96 * 96)) >= 0)
2085               && (d < 96 * 96))
2086             return (d / 96) + 32;
2087         }
2088     }
2089   return 0;
2090 }
2091
2092 unsigned char
2093 charset_get_byte2 (Lisp_Object charset, Emchar ch)
2094 {
2095   if (XCHARSET_DIMENSION (charset) == 1)
2096     return 0;
2097   else
2098     {
2099       Emchar_to_byte_table* table;
2100
2101       if ((table = XCHARSET_TO_BYTE2_TABLE (charset)) != NULL)
2102         return get_byte_from_character_table (ch, table);
2103       else if (EQ (charset, Vcharset_ucs_bmp))
2104         return (ch >> 8) & 0xff;
2105       else if (XCHARSET_CHARS (charset) == 94)
2106         return (MIN_CHAR_94x94
2107                 + (XCHARSET_FINAL (charset) - '0') * 94 * 94 <= ch)
2108           && (ch < MIN_CHAR_94x94
2109               + (XCHARSET_FINAL (charset) - '0' + 1) * 94 * 94) ?
2110           ((ch - MIN_CHAR_94x94) % 94) + 33 : 0;
2111       else /* if (XCHARSET_CHARS (charset) == 96) */
2112         return (MIN_CHAR_96x96
2113                 + (XCHARSET_FINAL (charset) - '0') * 96 * 96 <= ch)
2114           && (ch < MIN_CHAR_96x96
2115               + (XCHARSET_FINAL (charset) - '0' + 1) * 96 * 96) ?
2116           ((ch - MIN_CHAR_96x96) % 96) + 32 : 0;
2117     }
2118 }
2119
2120 Lisp_Object Vdefault_coded_charset_priority_list;
2121 #endif
2122
2123 \f
2124 /************************************************************************/
2125 /*                      Basic charset Lisp functions                    */
2126 /************************************************************************/
2127
2128 DEFUN ("charsetp", Fcharsetp, 1, 1, 0, /*
2129 Return non-nil if OBJECT is a charset.
2130 */
2131        (object))
2132 {
2133   return CHARSETP (object) ? Qt : Qnil;
2134 }
2135
2136 DEFUN ("find-charset", Ffind_charset, 1, 1, 0, /*
2137 Retrieve the charset of the given name.
2138 If CHARSET-OR-NAME is a charset object, it is simply returned.
2139 Otherwise, CHARSET-OR-NAME should be a symbol.  If there is no such charset,
2140 nil is returned.  Otherwise the associated charset object is returned.
2141 */
2142        (charset_or_name))
2143 {
2144   if (CHARSETP (charset_or_name))
2145     return charset_or_name;
2146
2147   CHECK_SYMBOL (charset_or_name);
2148   return Fgethash (charset_or_name, Vcharset_hash_table, Qnil);
2149 }
2150
2151 DEFUN ("get-charset", Fget_charset, 1, 1, 0, /*
2152 Retrieve the charset of the given name.
2153 Same as `find-charset' except an error is signalled if there is no such
2154 charset instead of returning nil.
2155 */
2156        (name))
2157 {
2158   Lisp_Object charset = Ffind_charset (name);
2159
2160   if (NILP (charset))
2161     signal_simple_error ("No such charset", name);
2162   return charset;
2163 }
2164
2165 /* We store the charsets in hash tables with the names as the key and the
2166    actual charset object as the value.  Occasionally we need to use them
2167    in a list format.  These routines provide us with that. */
2168 struct charset_list_closure
2169 {
2170   Lisp_Object *charset_list;
2171 };
2172
2173 static int
2174 add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
2175                             void *charset_list_closure)
2176 {
2177   /* This function can GC */
2178   struct charset_list_closure *chcl =
2179     (struct charset_list_closure*) charset_list_closure;
2180   Lisp_Object *charset_list = chcl->charset_list;
2181
2182   *charset_list = Fcons (XCHARSET_NAME (value), *charset_list);
2183   return 0;
2184 }
2185
2186 DEFUN ("charset-list", Fcharset_list, 0, 0, 0, /*
2187 Return a list of the names of all defined charsets.
2188 */
2189        ())
2190 {
2191   Lisp_Object charset_list = Qnil;
2192   struct gcpro gcpro1;
2193   struct charset_list_closure charset_list_closure;
2194
2195   GCPRO1 (charset_list);
2196   charset_list_closure.charset_list = &charset_list;
2197   elisp_maphash (add_charset_to_list_mapper, Vcharset_hash_table,
2198                  &charset_list_closure);
2199   UNGCPRO;
2200
2201   return charset_list;
2202 }
2203
2204 DEFUN ("charset-name", Fcharset_name, 1, 1, 0, /*
2205 Return the name of the given charset.
2206 */
2207        (charset))
2208 {
2209   return XCHARSET_NAME (Fget_charset (charset));
2210 }
2211
2212 DEFUN ("make-charset", Fmake_charset, 3, 3, 0, /*
2213 Define a new character set.
2214 This function is for use with Mule support.
2215 NAME is a symbol, the name by which the character set is normally referred.
2216 DOC-STRING is a string describing the character set.
2217 PROPS is a property list, describing the specific nature of the
2218 character set.  Recognized properties are:
2219
2220 'short-name     Short version of the charset name (ex: Latin-1)
2221 'long-name      Long version of the charset name (ex: ISO8859-1 (Latin-1))
2222 'registry       A regular expression matching the font registry field for
2223                 this character set.
2224 'dimension      Number of octets used to index a character in this charset.
2225                 Either 1 or 2.  Defaults to 1.
2226 'columns        Number of columns used to display a character in this charset.
2227                 Only used in TTY mode. (Under X, the actual width of a
2228                 character can be derived from the font used to display the
2229                 characters.) If unspecified, defaults to the dimension
2230                 (this is almost always the correct value).
2231 'chars          Number of characters in each dimension (94 or 96).
2232                 Defaults to 94.  Note that if the dimension is 2, the
2233                 character set thus described is 94x94 or 96x96.
2234 'final          Final byte of ISO 2022 escape sequence.  Must be
2235                 supplied.  Each combination of (DIMENSION, CHARS) defines a
2236                 separate namespace for final bytes.  Note that ISO
2237                 2022 restricts the final byte to the range
2238                 0x30 - 0x7E if dimension == 1, and 0x30 - 0x5F if
2239                 dimension == 2.  Note also that final bytes in the range
2240                 0x30 - 0x3F are reserved for user-defined (not official)
2241                 character sets.
2242 'graphic        0 (use left half of font on output) or 1 (use right half
2243                 of font on output).  Defaults to 0.  For example, for
2244                 a font whose registry is ISO8859-1, the left half
2245                 (octets 0x20 - 0x7F) is the `ascii' character set, while
2246                 the right half (octets 0xA0 - 0xFF) is the `latin-1'
2247                 character set.  With 'graphic set to 0, the octets
2248                 will have their high bit cleared; with it set to 1,
2249                 the octets will have their high bit set.
2250 'direction      'l2r (left-to-right) or 'r2l (right-to-left).
2251                 Defaults to 'l2r.
2252 'ccl-program    A compiled CCL program used to convert a character in
2253                 this charset into an index into the font.  This is in
2254                 addition to the 'graphic property.  The CCL program
2255                 is passed the octets of the character, with the high
2256                 bit cleared and set depending upon whether the value
2257                 of the 'graphic property is 0 or 1.
2258 */
2259        (name, doc_string, props))
2260 {
2261   int id, dimension = 1, chars = 94, graphic = 0, final = 0, columns = -1;
2262   int direction = CHARSET_LEFT_TO_RIGHT;
2263   int type;
2264   Lisp_Object registry = Qnil;
2265   Lisp_Object charset;
2266   Lisp_Object rest, keyword, value;
2267   Lisp_Object ccl_program = Qnil;
2268   Lisp_Object short_name = Qnil, long_name = Qnil;
2269
2270   CHECK_SYMBOL (name);
2271   if (!NILP (doc_string))
2272     CHECK_STRING (doc_string);
2273
2274   charset = Ffind_charset (name);
2275   if (!NILP (charset))
2276     signal_simple_error ("Cannot redefine existing charset", name);
2277
2278   EXTERNAL_PROPERTY_LIST_LOOP (rest, keyword, value, props)
2279     {
2280       if (EQ (keyword, Qshort_name))
2281         {
2282           CHECK_STRING (value);
2283           short_name = value;
2284         }
2285
2286       if (EQ (keyword, Qlong_name))
2287         {
2288           CHECK_STRING (value);
2289           long_name = value;
2290         }
2291
2292       else if (EQ (keyword, Qdimension))
2293         {
2294           CHECK_INT (value);
2295           dimension = XINT (value);
2296           if (dimension < 1 || dimension > 2)
2297             signal_simple_error ("Invalid value for 'dimension", value);
2298         }
2299
2300       else if (EQ (keyword, Qchars))
2301         {
2302           CHECK_INT (value);
2303           chars = XINT (value);
2304           if (chars != 94 && chars != 96)
2305             signal_simple_error ("Invalid value for 'chars", value);
2306         }
2307
2308       else if (EQ (keyword, Qcolumns))
2309         {
2310           CHECK_INT (value);
2311           columns = XINT (value);
2312           if (columns != 1 && columns != 2)
2313             signal_simple_error ("Invalid value for 'columns", value);
2314         }
2315
2316       else if (EQ (keyword, Qgraphic))
2317         {
2318           CHECK_INT (value);
2319           graphic = XINT (value);
2320           if (graphic < 0 || graphic > 1)
2321             signal_simple_error ("Invalid value for 'graphic", value);
2322         }
2323
2324       else if (EQ (keyword, Qregistry))
2325         {
2326           CHECK_STRING (value);
2327           registry = value;
2328         }
2329
2330       else if (EQ (keyword, Qdirection))
2331         {
2332           if (EQ (value, Ql2r))
2333             direction = CHARSET_LEFT_TO_RIGHT;
2334           else if (EQ (value, Qr2l))
2335             direction = CHARSET_RIGHT_TO_LEFT;
2336           else
2337             signal_simple_error ("Invalid value for 'direction", value);
2338         }
2339
2340       else if (EQ (keyword, Qfinal))
2341         {
2342           CHECK_CHAR_COERCE_INT (value);
2343           final = XCHAR (value);
2344           if (final < '0' || final > '~')
2345             signal_simple_error ("Invalid value for 'final", value);
2346         }
2347
2348       else if (EQ (keyword, Qccl_program))
2349         {
2350           CHECK_VECTOR (value);
2351           ccl_program = value;
2352         }
2353
2354       else
2355         signal_simple_error ("Unrecognized property", keyword);
2356     }
2357
2358   if (!final)
2359     error ("'final must be specified");
2360   if (dimension == 2 && final > 0x5F)
2361     signal_simple_error
2362       ("Final must be in the range 0x30 - 0x5F for dimension == 2",
2363        make_char (final));
2364
2365   if (dimension == 1)
2366     type = (chars == 94) ? CHARSET_TYPE_94    : CHARSET_TYPE_96;
2367   else
2368     type = (chars == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
2369
2370   if (!NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_LEFT_TO_RIGHT)) ||
2371       !NILP (CHARSET_BY_ATTRIBUTES (type, final, CHARSET_RIGHT_TO_LEFT)))
2372     error
2373       ("Character set already defined for this DIMENSION/CHARS/FINAL combo");
2374
2375 #ifdef UTF2000
2376   if (dimension == 1)
2377     {
2378       if (chars == 94)
2379         {
2380           /* id = CHARSET_ID_OFFSET_94 + final; */
2381           id = get_unallocated_leading_byte (dimension);
2382         }
2383       else if (chars == 96)
2384         {
2385           id = get_unallocated_leading_byte (dimension);
2386         }
2387       else
2388         {
2389           abort ();
2390         }
2391     }
2392   else if (dimension == 2)
2393     {
2394       if (chars == 94)
2395         {
2396           id = get_unallocated_leading_byte (dimension);
2397         }
2398       else if (chars == 96)
2399         {
2400           id = get_unallocated_leading_byte (dimension);
2401         }
2402       else
2403         {
2404           abort ();
2405         }
2406     }
2407   else
2408     {
2409       abort ();
2410     }
2411 #else
2412   id = get_unallocated_leading_byte (dimension);
2413 #endif
2414
2415   if (NILP (doc_string))
2416     doc_string = build_string ("");
2417
2418   if (NILP (registry))
2419     registry = build_string ("");
2420
2421   if (NILP (short_name))
2422     XSETSTRING (short_name, XSYMBOL (name)->name);
2423
2424   if (NILP (long_name))
2425     long_name = doc_string;
2426
2427   if (columns == -1)
2428     columns = dimension;
2429   charset = make_charset (id, name, type, columns, graphic,
2430                           final, direction, short_name, long_name,
2431                           doc_string, registry,
2432                           NULL,
2433                           0, 0, 0);
2434   if (!NILP (ccl_program))
2435     XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2436   return charset;
2437 }
2438
2439 DEFUN ("make-reverse-direction-charset", Fmake_reverse_direction_charset,
2440        2, 2, 0, /*
2441 Make a charset equivalent to CHARSET but which goes in the opposite direction.
2442 NEW-NAME is the name of the new charset.  Return the new charset.
2443 */
2444        (charset, new_name))
2445 {
2446   Lisp_Object new_charset = Qnil;
2447   int id, dimension, columns, graphic, final;
2448   int direction, type;
2449   Lisp_Object registry, doc_string, short_name, long_name;
2450   struct Lisp_Charset *cs;
2451
2452   charset = Fget_charset (charset);
2453   if (!NILP (XCHARSET_REVERSE_DIRECTION_CHARSET (charset)))
2454     signal_simple_error ("Charset already has reverse-direction charset",
2455                          charset);
2456
2457   CHECK_SYMBOL (new_name);
2458   if (!NILP (Ffind_charset (new_name)))
2459     signal_simple_error ("Cannot redefine existing charset", new_name);
2460
2461   cs = XCHARSET (charset);
2462
2463   type      = CHARSET_TYPE      (cs);
2464   columns   = CHARSET_COLUMNS   (cs);
2465   dimension = CHARSET_DIMENSION (cs);
2466   id = get_unallocated_leading_byte (dimension);
2467
2468   graphic = CHARSET_GRAPHIC (cs);
2469   final = CHARSET_FINAL (cs);
2470   direction = CHARSET_RIGHT_TO_LEFT;
2471   if (CHARSET_DIRECTION (cs) == CHARSET_RIGHT_TO_LEFT)
2472     direction = CHARSET_LEFT_TO_RIGHT;
2473   doc_string = CHARSET_DOC_STRING (cs);
2474   short_name = CHARSET_SHORT_NAME (cs);
2475   long_name = CHARSET_LONG_NAME (cs);
2476   registry = CHARSET_REGISTRY (cs);
2477
2478   new_charset = make_charset (id, new_name, type, columns,
2479                               graphic, final, direction, short_name, long_name,
2480                               doc_string, registry,
2481                               NULL,
2482                               0, 0, 0);
2483
2484   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
2485   XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
2486
2487   return new_charset;
2488 }
2489
2490 /* #### Reverse direction charsets not yet implemented.  */
2491 #if 0
2492 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
2493        1, 1, 0, /*
2494 Return the reverse-direction charset parallel to CHARSET, if any.
2495 This is the charset with the same properties (in particular, the same
2496 dimension, number of characters per dimension, and final byte) as
2497 CHARSET but whose characters are displayed in the opposite direction.
2498 */
2499        (charset))
2500 {
2501   charset = Fget_charset (charset);
2502   return XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
2503 }
2504 #endif
2505
2506 DEFUN ("charset-from-attributes", Fcharset_from_attributes, 3, 4, 0, /*
2507 Return a charset with the given DIMENSION, CHARS, FINAL, and DIRECTION.
2508 If DIRECTION is omitted, both directions will be checked (left-to-right
2509 will be returned if character sets exist for both directions).
2510 */
2511        (dimension, chars, final, direction))
2512 {
2513   int dm, ch, fi, di = -1;
2514   int type;
2515   Lisp_Object obj = Qnil;
2516
2517   CHECK_INT (dimension);
2518   dm = XINT (dimension);
2519   if (dm < 1 || dm > 2)
2520     signal_simple_error ("Invalid value for DIMENSION", dimension);
2521
2522   CHECK_INT (chars);
2523   ch = XINT (chars);
2524   if (ch != 94 && ch != 96)
2525     signal_simple_error ("Invalid value for CHARS", chars);
2526
2527   CHECK_CHAR_COERCE_INT (final);
2528   fi = XCHAR (final);
2529   if (fi < '0' || fi > '~')
2530     signal_simple_error ("Invalid value for FINAL", final);
2531
2532   if (EQ (direction, Ql2r))
2533     di = CHARSET_LEFT_TO_RIGHT;
2534   else if (EQ (direction, Qr2l))
2535     di = CHARSET_RIGHT_TO_LEFT;
2536   else if (!NILP (direction))
2537     signal_simple_error ("Invalid value for DIRECTION", direction);
2538
2539   if (dm == 2 && fi > 0x5F)
2540     signal_simple_error
2541       ("Final must be in the range 0x30 - 0x5F for dimension == 2", final);
2542
2543   if (dm == 1)
2544     type = (ch == 94) ? CHARSET_TYPE_94    : CHARSET_TYPE_96;
2545   else
2546     type = (ch == 94) ? CHARSET_TYPE_94X94 : CHARSET_TYPE_96X96;
2547
2548   if (di == -1)
2549     {
2550       obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_LEFT_TO_RIGHT);
2551       if (NILP (obj))
2552         obj = CHARSET_BY_ATTRIBUTES (type, fi, CHARSET_RIGHT_TO_LEFT);
2553     }
2554   else
2555     obj = CHARSET_BY_ATTRIBUTES (type, fi, di);
2556
2557   if (CHARSETP (obj))
2558     return XCHARSET_NAME (obj);
2559   return obj;
2560 }
2561
2562 DEFUN ("charset-short-name", Fcharset_short_name, 1, 1, 0, /*
2563 Return short name of CHARSET.
2564 */
2565        (charset))
2566 {
2567   return XCHARSET_SHORT_NAME (Fget_charset (charset));
2568 }
2569
2570 DEFUN ("charset-long-name", Fcharset_long_name, 1, 1, 0, /*
2571 Return long name of CHARSET.
2572 */
2573        (charset))
2574 {
2575   return XCHARSET_LONG_NAME (Fget_charset (charset));
2576 }
2577
2578 DEFUN ("charset-description", Fcharset_description, 1, 1, 0, /*
2579 Return description of CHARSET.
2580 */
2581        (charset))
2582 {
2583   return XCHARSET_DOC_STRING (Fget_charset (charset));
2584 }
2585
2586 DEFUN ("charset-dimension", Fcharset_dimension, 1, 1, 0, /*
2587 Return dimension of CHARSET.
2588 */
2589        (charset))
2590 {
2591   return make_int (XCHARSET_DIMENSION (Fget_charset (charset)));
2592 }
2593
2594 DEFUN ("charset-property", Fcharset_property, 2, 2, 0, /*
2595 Return property PROP of CHARSET.
2596 Recognized properties are those listed in `make-charset', as well as
2597 'name and 'doc-string.
2598 */
2599        (charset, prop))
2600 {
2601   struct Lisp_Charset *cs;
2602
2603   charset = Fget_charset (charset);
2604   cs = XCHARSET (charset);
2605
2606   CHECK_SYMBOL (prop);
2607   if (EQ (prop, Qname))        return CHARSET_NAME (cs);
2608   if (EQ (prop, Qshort_name))  return CHARSET_SHORT_NAME (cs);
2609   if (EQ (prop, Qlong_name))   return CHARSET_LONG_NAME (cs);
2610   if (EQ (prop, Qdoc_string))  return CHARSET_DOC_STRING (cs);
2611   if (EQ (prop, Qdimension))   return make_int (CHARSET_DIMENSION (cs));
2612   if (EQ (prop, Qcolumns))     return make_int (CHARSET_COLUMNS (cs));
2613   if (EQ (prop, Qgraphic))     return make_int (CHARSET_GRAPHIC (cs));
2614   if (EQ (prop, Qfinal))       return make_char (CHARSET_FINAL (cs));
2615   if (EQ (prop, Qchars))       return make_int (CHARSET_CHARS (cs));
2616   if (EQ (prop, Qregistry))    return CHARSET_REGISTRY (cs);
2617   if (EQ (prop, Qccl_program)) return CHARSET_CCL_PROGRAM (cs);
2618   if (EQ (prop, Qdirection))
2619     return CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? Ql2r : Qr2l;
2620   if (EQ (prop, Qreverse_direction_charset))
2621     {
2622       Lisp_Object obj = CHARSET_REVERSE_DIRECTION_CHARSET (cs);
2623       if (NILP (obj))
2624         return Qnil;
2625       else
2626         return XCHARSET_NAME (obj);
2627     }
2628   signal_simple_error ("Unrecognized charset property name", prop);
2629   return Qnil; /* not reached */
2630 }
2631
2632 DEFUN ("charset-id", Fcharset_id, 1, 1, 0, /*
2633 Return charset identification number of CHARSET.
2634 */
2635         (charset))
2636 {
2637   return make_int(XCHARSET_LEADING_BYTE (Fget_charset (charset)));
2638 }
2639
2640 /* #### We need to figure out which properties we really want to
2641    allow to be set. */
2642
2643 DEFUN ("set-charset-ccl-program", Fset_charset_ccl_program, 2, 2, 0, /*
2644 Set the 'ccl-program property of CHARSET to CCL-PROGRAM.
2645 */
2646        (charset, ccl_program))
2647 {
2648   charset = Fget_charset (charset);
2649   CHECK_VECTOR (ccl_program);
2650   XCHARSET_CCL_PROGRAM (charset) = ccl_program;
2651   return Qnil;
2652 }
2653
2654 static void
2655 invalidate_charset_font_caches (Lisp_Object charset)
2656 {
2657   /* Invalidate font cache entries for charset on all devices. */
2658   Lisp_Object devcons, concons, hash_table;
2659   DEVICE_LOOP_NO_BREAK (devcons, concons)
2660     {
2661       struct device *d = XDEVICE (XCAR (devcons));
2662       hash_table = Fgethash (charset, d->charset_font_cache, Qunbound);
2663       if (!UNBOUNDP (hash_table))
2664         Fclrhash (hash_table);
2665     }
2666 }
2667
2668 /* Japanese folks may want to (set-charset-registry 'ascii "jisx0201") */
2669 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
2670 Set the 'registry property of CHARSET to REGISTRY.
2671 */
2672        (charset, registry))
2673 {
2674   charset = Fget_charset (charset);
2675   CHECK_STRING (registry);
2676   XCHARSET_REGISTRY (charset) = registry;
2677   invalidate_charset_font_caches (charset);
2678   face_property_was_changed (Vdefault_face, Qfont, Qglobal);
2679   return Qnil;
2680 }
2681
2682 \f
2683 /************************************************************************/
2684 /*              Lisp primitives for working with characters             */
2685 /************************************************************************/
2686
2687 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
2688 Make a character from CHARSET and octets ARG1 and ARG2.
2689 ARG2 is required only for characters from two-dimensional charsets.
2690 For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
2691 character s with caron.
2692 */
2693        (charset, arg1, arg2))
2694 {
2695   struct Lisp_Charset *cs;
2696   int a1, a2;
2697   int lowlim, highlim;
2698
2699   charset = Fget_charset (charset);
2700   cs = XCHARSET (charset);
2701
2702   if      (EQ (charset, Vcharset_ascii))     lowlim =  0, highlim = 127;
2703   else if (EQ (charset, Vcharset_control_1)) lowlim =  0, highlim =  31;
2704 #ifdef UTF2000
2705   else if (CHARSET_CHARS (cs) == 256)        lowlim =  0, highlim = 255;
2706 #endif
2707   else if (CHARSET_CHARS (cs) == 94)         lowlim = 33, highlim = 126;
2708   else  /* CHARSET_CHARS (cs) == 96) */      lowlim = 32, highlim = 127;
2709
2710   CHECK_INT (arg1);
2711   /* It is useful (and safe, according to Olivier Galibert) to strip
2712      the 8th bit off ARG1 and ARG2 becaue it allows programmers to
2713      write (make-char 'latin-iso8859-2 CODE) where code is the actual
2714      Latin 2 code of the character.  */
2715 #ifdef UTF2000
2716   a1 = XINT (arg1);
2717   if (highlim < 128)
2718     a1 &= 0x7f;
2719 #else
2720   a1 = XINT (arg1);
2721 #endif
2722   if (a1 < lowlim || a1 > highlim)
2723     args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
2724
2725   if (CHARSET_DIMENSION (cs) == 1)
2726     {
2727       if (!NILP (arg2))
2728         signal_simple_error
2729           ("Charset is of dimension one; second octet must be nil", arg2);
2730       return make_char (MAKE_CHAR (charset, a1, 0));
2731     }
2732
2733   CHECK_INT (arg2);
2734 #ifdef UTF2000
2735   a2 = XINT (arg2);
2736   if (highlim < 128)
2737     a2 &= 0x7f;
2738 #else
2739   a2 = XINT (arg2) & 0x7f;
2740 #endif
2741   if (a2 < lowlim || a2 > highlim)
2742     args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
2743
2744   return make_char (MAKE_CHAR (charset, a1, a2));
2745 }
2746
2747 DEFUN ("char-charset", Fchar_charset, 1, 1, 0, /*
2748 Return the character set of char CH.
2749 */
2750        (ch))
2751 {
2752   CHECK_CHAR_COERCE_INT (ch);
2753
2754   return XCHARSET_NAME (CHAR_CHARSET (XCHAR (ch)));
2755 }
2756
2757 DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
2758 Return list of charset and one or two position-codes of CHAR.
2759 */
2760        (character))
2761 {
2762   /* This function can GC */
2763   struct gcpro gcpro1, gcpro2;
2764   Lisp_Object charset = Qnil;
2765   Lisp_Object rc = Qnil;
2766   int c1, c2;
2767
2768   GCPRO2 (charset, rc);
2769   CHECK_CHAR_COERCE_INT (character);
2770
2771   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
2772
2773   if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
2774     {
2775       rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
2776     }
2777   else
2778     {
2779       rc = list2 (XCHARSET_NAME (charset), make_int (c1));
2780     }
2781   UNGCPRO;
2782
2783   return rc;
2784 }
2785
2786 \f
2787 #ifdef ENABLE_COMPOSITE_CHARS
2788 /************************************************************************/
2789 /*                     composite character functions                    */
2790 /************************************************************************/
2791
2792 Emchar
2793 lookup_composite_char (Bufbyte *str, int len)
2794 {
2795   Lisp_Object lispstr = make_string (str, len);
2796   Lisp_Object ch = Fgethash (lispstr,
2797                              Vcomposite_char_string2char_hash_table,
2798                              Qunbound);
2799   Emchar emch;
2800
2801   if (UNBOUNDP (ch))
2802     {
2803       if (composite_char_row_next >= 128)
2804         signal_simple_error ("No more composite chars available", lispstr);
2805       emch = MAKE_CHAR (Vcharset_composite, composite_char_row_next,
2806                         composite_char_col_next);
2807       Fputhash (make_char (emch), lispstr,
2808                 Vcomposite_char_char2string_hash_table);
2809       Fputhash (lispstr, make_char (emch),
2810                 Vcomposite_char_string2char_hash_table);
2811       composite_char_col_next++;
2812       if (composite_char_col_next >= 128)
2813         {
2814           composite_char_col_next = 32;
2815           composite_char_row_next++;
2816         }
2817     }
2818   else
2819     emch = XCHAR (ch);
2820   return emch;
2821 }
2822
2823 Lisp_Object
2824 composite_char_string (Emchar ch)
2825 {
2826   Lisp_Object str = Fgethash (make_char (ch),
2827                               Vcomposite_char_char2string_hash_table,
2828                               Qunbound);
2829   assert (!UNBOUNDP (str));
2830   return str;
2831 }
2832
2833 xxDEFUN ("make-composite-char", Fmake_composite_char, 1, 1, 0, /*
2834 Convert a string into a single composite character.
2835 The character is the result of overstriking all the characters in
2836 the string.
2837 */
2838        (string))
2839 {
2840   CHECK_STRING (string);
2841   return make_char (lookup_composite_char (XSTRING_DATA (string),
2842                                            XSTRING_LENGTH (string)));
2843 }
2844
2845 xxDEFUN ("composite-char-string", Fcomposite_char_string, 1, 1, 0, /*
2846 Return a string of the characters comprising a composite character.
2847 */
2848        (ch))
2849 {
2850   Emchar emch;
2851
2852   CHECK_CHAR (ch);
2853   emch = XCHAR (ch);
2854   if (CHAR_LEADING_BYTE (emch) != LEADING_BYTE_COMPOSITE)
2855     signal_simple_error ("Must be composite char", ch);
2856   return composite_char_string (emch);
2857 }
2858 #endif /* ENABLE_COMPOSITE_CHARS */
2859
2860 \f
2861 /************************************************************************/
2862 /*                            initialization                            */
2863 /************************************************************************/
2864
2865 void
2866 syms_of_mule_charset (void)
2867 {
2868   DEFSUBR (Fcharsetp);
2869   DEFSUBR (Ffind_charset);
2870   DEFSUBR (Fget_charset);
2871   DEFSUBR (Fcharset_list);
2872   DEFSUBR (Fcharset_name);
2873   DEFSUBR (Fmake_charset);
2874   DEFSUBR (Fmake_reverse_direction_charset);
2875   /*  DEFSUBR (Freverse_direction_charset); */
2876   DEFSUBR (Fcharset_from_attributes);
2877   DEFSUBR (Fcharset_short_name);
2878   DEFSUBR (Fcharset_long_name);
2879   DEFSUBR (Fcharset_description);
2880   DEFSUBR (Fcharset_dimension);
2881   DEFSUBR (Fcharset_property);
2882   DEFSUBR (Fcharset_id);
2883   DEFSUBR (Fset_charset_ccl_program);
2884   DEFSUBR (Fset_charset_registry);
2885
2886   DEFSUBR (Fmake_char);
2887   DEFSUBR (Fchar_charset);
2888   DEFSUBR (Fsplit_char);
2889
2890 #ifdef ENABLE_COMPOSITE_CHARS
2891   DEFSUBR (Fmake_composite_char);
2892   DEFSUBR (Fcomposite_char_string);
2893 #endif
2894
2895   defsymbol (&Qcharsetp, "charsetp");
2896   defsymbol (&Qregistry, "registry");
2897   defsymbol (&Qfinal, "final");
2898   defsymbol (&Qgraphic, "graphic");
2899   defsymbol (&Qdirection, "direction");
2900   defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
2901   defsymbol (&Qshort_name, "short-name");
2902   defsymbol (&Qlong_name, "long-name");
2903
2904   defsymbol (&Ql2r, "l2r");
2905   defsymbol (&Qr2l, "r2l");
2906
2907   /* Charsets, compatible with FSF 20.3
2908      Naming convention is Script-Charset[-Edition] */
2909   defsymbol (&Qascii,                   "ascii");
2910   defsymbol (&Qcontrol_1,               "control-1");
2911   defsymbol (&Qlatin_iso8859_1,         "latin-iso8859-1");
2912   defsymbol (&Qlatin_iso8859_2,         "latin-iso8859-2");
2913   defsymbol (&Qlatin_iso8859_3,         "latin-iso8859-3");
2914   defsymbol (&Qlatin_iso8859_4,         "latin-iso8859-4");
2915   defsymbol (&Qthai_tis620,             "thai-tis620");
2916   defsymbol (&Qgreek_iso8859_7,         "greek-iso8859-7");
2917   defsymbol (&Qarabic_iso8859_6,        "arabic-iso8859-6");
2918   defsymbol (&Qhebrew_iso8859_8,        "hebrew-iso8859-8");
2919   defsymbol (&Qkatakana_jisx0201,       "katakana-jisx0201");
2920   defsymbol (&Qlatin_jisx0201,          "latin-jisx0201");
2921   defsymbol (&Qcyrillic_iso8859_5,      "cyrillic-iso8859-5");
2922   defsymbol (&Qlatin_iso8859_9,         "latin-iso8859-9");
2923   defsymbol (&Qjapanese_jisx0208_1978,  "japanese-jisx0208-1978");
2924   defsymbol (&Qchinese_gb2312,          "chinese-gb2312");
2925   defsymbol (&Qjapanese_jisx0208,       "japanese-jisx0208");
2926   defsymbol (&Qkorean_ksc5601,          "korean-ksc5601");
2927   defsymbol (&Qjapanese_jisx0212,       "japanese-jisx0212");
2928   defsymbol (&Qchinese_cns11643_1,      "chinese-cns11643-1");
2929   defsymbol (&Qchinese_cns11643_2,      "chinese-cns11643-2");
2930 #ifdef UTF2000
2931   defsymbol (&Qchinese_cns11643_3,      "chinese-cns11643-3");
2932   defsymbol (&Qchinese_cns11643_4,      "chinese-cns11643-4");
2933   defsymbol (&Qchinese_cns11643_5,      "chinese-cns11643-5");
2934   defsymbol (&Qchinese_cns11643_6,      "chinese-cns11643-6");
2935   defsymbol (&Qchinese_cns11643_7,      "chinese-cns11643-7");
2936   defsymbol (&Qucs_bmp,                 "ucs-bmp");
2937   defsymbol (&Qlatin_viscii_lower,      "vietnamese-viscii-lower");
2938   defsymbol (&Qlatin_viscii_upper,      "vietnamese-viscii-upper");
2939 #endif
2940   defsymbol (&Qchinese_big5_1,          "chinese-big5-1");
2941   defsymbol (&Qchinese_big5_2,          "chinese-big5-2");
2942
2943   defsymbol (&Qcomposite,               "composite");
2944 }
2945
2946 void
2947 vars_of_mule_charset (void)
2948 {
2949   int i, j;
2950 #ifndef UTF2000
2951   int k;
2952 #endif
2953
2954   /* Table of charsets indexed by leading byte. */
2955   for (i = 0; i < countof (charset_by_leading_byte); i++)
2956     charset_by_leading_byte[i] = Qnil;
2957
2958 #ifdef UTF2000
2959   /* Table of charsets indexed by type/final-byte. */
2960   for (i = 0; i < countof (charset_by_attributes); i++)
2961     for (j = 0; j < countof (charset_by_attributes[0]); j++)
2962         charset_by_attributes[i][j] = Qnil;
2963 #else
2964   /* Table of charsets indexed by type/final-byte/direction. */
2965   for (i = 0; i < countof (charset_by_attributes); i++)
2966     for (j = 0; j < countof (charset_by_attributes[0]); j++)
2967       for (k = 0; k < countof (charset_by_attributes[0][0]); k++)
2968         charset_by_attributes[i][j][k] = Qnil;
2969 #endif
2970
2971   next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
2972 #ifdef UTF2000
2973   next_allocated_2_byte_leading_byte = LEADING_BYTE_CHINESE_BIG5_2 + 1;
2974 #else
2975   next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
2976 #endif
2977
2978 #ifndef UTF2000
2979   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2980   DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
2981 Leading-code of private TYPE9N charset of column-width 1.
2982 */ );
2983   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2984 #endif
2985
2986 #ifdef UTF2000
2987   Vutf_2000_version = build_string("0.7 (Hirano)");
2988   DEFVAR_LISP ("utf-2000-version", &Vutf_2000_version /*
2989 Version number of UTF-2000.
2990 */ );
2991
2992   Vdefault_coded_charset_priority_list = Qnil;
2993   DEFVAR_LISP ("default-coded-charset-priority-list",
2994                &Vdefault_coded_charset_priority_list /*
2995 Default order of preferred coded-character-set.
2996 */ );
2997 #endif
2998 }
2999
3000 void
3001 complex_vars_of_mule_charset (void)
3002 {
3003   staticpro (&Vcharset_hash_table);
3004   Vcharset_hash_table =
3005     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3006
3007   /* Predefined character sets.  We store them into variables for
3008      ease of access. */
3009
3010 #ifdef UTF2000
3011   Vcharset_ucs_bmp =
3012     make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp,
3013                   CHARSET_TYPE_256X256, 1, 0, 0,
3014                   CHARSET_LEFT_TO_RIGHT,
3015                   build_string ("BMP"),
3016                   build_string ("BMP"),
3017                   build_string ("BMP"),
3018                   build_string (""),
3019                   NULL, 0, 0xFFFF, 0);
3020 #endif
3021   Vcharset_ascii =
3022     make_charset (LEADING_BYTE_ASCII, Qascii,
3023                   CHARSET_TYPE_94, 1, 0, 'B',
3024                   CHARSET_LEFT_TO_RIGHT,
3025                   build_string ("ASCII"),
3026                   build_string ("ASCII)"),
3027                   build_string ("ASCII (ISO646 IRV)"),
3028                   build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
3029                   NULL, 0, 0x7F, 0);
3030   Vcharset_control_1 =
3031     make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1,
3032                   CHARSET_TYPE_94, 1, 1, 0,
3033                   CHARSET_LEFT_TO_RIGHT,
3034                   build_string ("C1"),
3035                   build_string ("Control characters"),
3036                   build_string ("Control characters 128-191"),
3037                   build_string (""),
3038                   NULL, 0x80, 0x9F, 0);
3039   Vcharset_latin_iso8859_1 =
3040     make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1,
3041                   CHARSET_TYPE_96, 1, 1, 'A',
3042                   CHARSET_LEFT_TO_RIGHT,
3043                   build_string ("Latin-1"),
3044                   build_string ("ISO8859-1 (Latin-1)"),
3045                   build_string ("ISO8859-1 (Latin-1)"),
3046                   build_string ("iso8859-1"),
3047                   NULL, 0xA0, 0xFF, 32);
3048   Vcharset_latin_iso8859_2 =
3049     make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2,
3050                   CHARSET_TYPE_96, 1, 1, 'B',
3051                   CHARSET_LEFT_TO_RIGHT,
3052                   build_string ("Latin-2"),
3053                   build_string ("ISO8859-2 (Latin-2)"),
3054                   build_string ("ISO8859-2 (Latin-2)"),
3055                   build_string ("iso8859-2"),
3056                   latin_iso8859_2_to_ucs, 0, 0, 32);
3057   Vcharset_latin_iso8859_3 =
3058     make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3,
3059                   CHARSET_TYPE_96, 1, 1, 'C',
3060                   CHARSET_LEFT_TO_RIGHT,
3061                   build_string ("Latin-3"),
3062                   build_string ("ISO8859-3 (Latin-3)"),
3063                   build_string ("ISO8859-3 (Latin-3)"),
3064                   build_string ("iso8859-3"),
3065                   latin_iso8859_3_to_ucs, 0, 0, 32);
3066   Vcharset_latin_iso8859_4 =
3067     make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4,
3068                   CHARSET_TYPE_96, 1, 1, 'D',
3069                   CHARSET_LEFT_TO_RIGHT,
3070                   build_string ("Latin-4"),
3071                   build_string ("ISO8859-4 (Latin-4)"),
3072                   build_string ("ISO8859-4 (Latin-4)"),
3073                   build_string ("iso8859-4"),
3074                   latin_iso8859_4_to_ucs, 0, 0, 32);
3075   Vcharset_thai_tis620 =
3076     make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620,
3077                   CHARSET_TYPE_96, 1, 1, 'T',
3078                   CHARSET_LEFT_TO_RIGHT,
3079                   build_string ("TIS620"),
3080                   build_string ("TIS620 (Thai)"),
3081                   build_string ("TIS620.2529 (Thai)"),
3082                   build_string ("tis620"),
3083                   NULL, MIN_CHAR_THAI, MAX_CHAR_THAI, 32);
3084   Vcharset_greek_iso8859_7 =
3085     make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7,
3086                   CHARSET_TYPE_96, 1, 1, 'F',
3087                   CHARSET_LEFT_TO_RIGHT,
3088                   build_string ("ISO8859-7"),
3089                   build_string ("ISO8859-7 (Greek)"),
3090                   build_string ("ISO8859-7 (Greek)"),
3091                   build_string ("iso8859-7"),
3092                   NULL, MIN_CHAR_GREEK, MAX_CHAR_GREEK, 32);
3093   Vcharset_arabic_iso8859_6 =
3094     make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6,
3095                   CHARSET_TYPE_96, 1, 1, 'G',
3096                   CHARSET_RIGHT_TO_LEFT,
3097                   build_string ("ISO8859-6"),
3098                   build_string ("ISO8859-6 (Arabic)"),
3099                   build_string ("ISO8859-6 (Arabic)"),
3100                   build_string ("iso8859-6"),
3101                   NULL, 0, 0, 32);
3102   Vcharset_hebrew_iso8859_8 =
3103     make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8,
3104                   CHARSET_TYPE_96, 1, 1, 'H',
3105                   CHARSET_RIGHT_TO_LEFT,
3106                   build_string ("ISO8859-8"),
3107                   build_string ("ISO8859-8 (Hebrew)"),
3108                   build_string ("ISO8859-8 (Hebrew)"),
3109                   build_string ("iso8859-8"),
3110                   NULL, MIN_CHAR_HEBREW, MAX_CHAR_HEBREW, 32);
3111   Vcharset_katakana_jisx0201 =
3112     make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201,
3113                   CHARSET_TYPE_94, 1, 1, 'I',
3114                   CHARSET_LEFT_TO_RIGHT,
3115                   build_string ("JISX0201 Kana"),
3116                   build_string ("JISX0201.1976 (Japanese Kana)"),
3117                   build_string ("JISX0201.1976 Japanese Kana"),
3118                   build_string ("jisx0201.1976"),
3119                   NULL,
3120                   MIN_CHAR_HALFWIDTH_KATAKANA,
3121                   MAX_CHAR_HALFWIDTH_KATAKANA, 33);
3122   Vcharset_latin_jisx0201 =
3123     make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201,
3124                   CHARSET_TYPE_94, 1, 0, 'J',
3125                   CHARSET_LEFT_TO_RIGHT,
3126                   build_string ("JISX0201 Roman"),
3127                   build_string ("JISX0201.1976 (Japanese Roman)"),
3128                   build_string ("JISX0201.1976 Japanese Roman"),
3129                   build_string ("jisx0201.1976"),
3130                   latin_jisx0201_to_ucs, 0, 0, 33);
3131   Vcharset_cyrillic_iso8859_5 =
3132     make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5,
3133                   CHARSET_TYPE_96, 1, 1, 'L',
3134                   CHARSET_LEFT_TO_RIGHT,
3135                   build_string ("ISO8859-5"),
3136                   build_string ("ISO8859-5 (Cyrillic)"),
3137                   build_string ("ISO8859-5 (Cyrillic)"),
3138                   build_string ("iso8859-5"),
3139                   NULL, MIN_CHAR_CYRILLIC, MAX_CHAR_CYRILLIC, 32);
3140   Vcharset_latin_iso8859_9 =
3141     make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9,
3142                   CHARSET_TYPE_96, 1, 1, 'M',
3143                   CHARSET_LEFT_TO_RIGHT,
3144                   build_string ("Latin-5"),
3145                   build_string ("ISO8859-9 (Latin-5)"),
3146                   build_string ("ISO8859-9 (Latin-5)"),
3147                   build_string ("iso8859-9"),
3148                   latin_iso8859_9_to_ucs, 0, 0, 32);
3149   Vcharset_japanese_jisx0208_1978 =
3150     make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978, Qjapanese_jisx0208_1978,
3151                   CHARSET_TYPE_94X94, 2, 0, '@',
3152                   CHARSET_LEFT_TO_RIGHT,
3153                   build_string ("JISX0208.1978"),
3154                   build_string ("JISX0208.1978 (Japanese)"),
3155                   build_string
3156                   ("JISX0208.1978 Japanese Kanji (so called \"old JIS\")"),
3157                   build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
3158                   NULL, 0, 0, 33);
3159   Vcharset_chinese_gb2312 =
3160     make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312,
3161                   CHARSET_TYPE_94X94, 2, 0, 'A',
3162                   CHARSET_LEFT_TO_RIGHT,
3163                   build_string ("GB2312"),
3164                   build_string ("GB2312)"),
3165                   build_string ("GB2312 Chinese simplified"),
3166                   build_string ("gb2312"),
3167                   NULL, 0, 0, 33);
3168   Vcharset_japanese_jisx0208 =
3169     make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208,
3170                   CHARSET_TYPE_94X94, 2, 0, 'B',
3171                   CHARSET_LEFT_TO_RIGHT,
3172                   build_string ("JISX0208"),
3173                   build_string ("JISX0208.1983/1990 (Japanese)"),
3174                   build_string ("JISX0208.1983/1990 Japanese Kanji"),
3175                   build_string ("jisx0208.19\\(83\\|90\\)"),
3176                   NULL, 0, 0, 33);
3177   Vcharset_korean_ksc5601 =
3178     make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601,
3179                   CHARSET_TYPE_94X94, 2, 0, 'C',
3180                   CHARSET_LEFT_TO_RIGHT,
3181                   build_string ("KSC5601"),
3182                   build_string ("KSC5601 (Korean"),
3183                   build_string ("KSC5601 Korean Hangul and Hanja"),
3184                   build_string ("ksc5601"),
3185                   NULL, 0, 0, 33);
3186   Vcharset_japanese_jisx0212 =
3187     make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212,
3188                   CHARSET_TYPE_94X94, 2, 0, 'D',
3189                   CHARSET_LEFT_TO_RIGHT,
3190                   build_string ("JISX0212"),
3191                   build_string ("JISX0212 (Japanese)"),
3192                   build_string ("JISX0212 Japanese Supplement"),
3193                   build_string ("jisx0212"),
3194                   NULL, 0, 0, 33);
3195
3196 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
3197   Vcharset_chinese_cns11643_1 =
3198     make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1,
3199                   CHARSET_TYPE_94X94, 2, 0, 'G',
3200                   CHARSET_LEFT_TO_RIGHT,
3201                   build_string ("CNS11643-1"),
3202                   build_string ("CNS11643-1 (Chinese traditional)"),
3203                   build_string
3204                   ("CNS 11643 Plane 1 Chinese traditional"),
3205                   build_string (CHINESE_CNS_PLANE_RE("1")),
3206                   NULL, 0, 0, 33);
3207   Vcharset_chinese_cns11643_2 =
3208     make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2,
3209                   CHARSET_TYPE_94X94, 2, 0, 'H',
3210                   CHARSET_LEFT_TO_RIGHT,
3211                   build_string ("CNS11643-2"),
3212                   build_string ("CNS11643-2 (Chinese traditional)"),
3213                   build_string
3214                   ("CNS 11643 Plane 2 Chinese traditional"),
3215                   build_string (CHINESE_CNS_PLANE_RE("2")),
3216                   NULL, 0, 0, 33);
3217 #ifdef UTF2000
3218   Vcharset_chinese_cns11643_3 =
3219     make_charset (LEADING_BYTE_CHINESE_CNS11643_3, Qchinese_cns11643_3,
3220                   CHARSET_TYPE_94X94, 2, 0, 'I',
3221                   CHARSET_LEFT_TO_RIGHT,
3222                   build_string ("CNS11643-3"),
3223                   build_string ("CNS11643-3 (Chinese traditional)"),
3224                   build_string
3225                   ("CNS 11643 Plane 3 Chinese traditional"),
3226                   build_string (CHINESE_CNS_PLANE_RE("3")),
3227                   NULL, 0, 0, 33);
3228   Vcharset_chinese_cns11643_4 =
3229     make_charset (LEADING_BYTE_CHINESE_CNS11643_4, Qchinese_cns11643_4,
3230                   CHARSET_TYPE_94X94, 2, 0, 'J',
3231                   CHARSET_LEFT_TO_RIGHT,
3232                   build_string ("CNS11643-4"),
3233                   build_string ("CNS11643-4 (Chinese traditional)"),
3234                   build_string
3235                   ("CNS 11643 Plane 4 Chinese traditional"),
3236                   build_string (CHINESE_CNS_PLANE_RE("4")),
3237                   NULL, 0, 0, 33);
3238   Vcharset_chinese_cns11643_5 =
3239     make_charset (LEADING_BYTE_CHINESE_CNS11643_5, Qchinese_cns11643_5,
3240                   CHARSET_TYPE_94X94, 2, 0, 'K',
3241                   CHARSET_LEFT_TO_RIGHT,
3242                   build_string ("CNS11643-5"),
3243                   build_string ("CNS11643-5 (Chinese traditional)"),
3244                   build_string
3245                   ("CNS 11643 Plane 5 Chinese traditional"),
3246                   build_string (CHINESE_CNS_PLANE_RE("5")),
3247                   NULL, 0, 0, 33);
3248   Vcharset_chinese_cns11643_6 =
3249     make_charset (LEADING_BYTE_CHINESE_CNS11643_6, Qchinese_cns11643_6,
3250                   CHARSET_TYPE_94X94, 2, 0, 'L',
3251                   CHARSET_LEFT_TO_RIGHT,
3252                   build_string ("CNS11643-6"),
3253                   build_string ("CNS11643-6 (Chinese traditional)"),
3254                   build_string
3255                   ("CNS 11643 Plane 6 Chinese traditional"),
3256                   build_string (CHINESE_CNS_PLANE_RE("6")),
3257                   NULL, 0, 0, 33);
3258   Vcharset_chinese_cns11643_7 =
3259     make_charset (LEADING_BYTE_CHINESE_CNS11643_7, Qchinese_cns11643_7,
3260                   CHARSET_TYPE_94X94, 2, 0, 'M',
3261                   CHARSET_LEFT_TO_RIGHT,
3262                   build_string ("CNS11643-7"),
3263                   build_string ("CNS11643-7 (Chinese traditional)"),
3264                   build_string
3265                   ("CNS 11643 Plane 7 Chinese traditional"),
3266                   build_string (CHINESE_CNS_PLANE_RE("7")),
3267                   NULL, 0, 0, 33);
3268   Vcharset_latin_viscii_lower =
3269     make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower,
3270                   CHARSET_TYPE_96, 1, 1, '1',
3271                   CHARSET_LEFT_TO_RIGHT,
3272                   build_string ("VISCII lower"),
3273                   build_string ("VISCII lower (Vietnamese)"),
3274                   build_string ("VISCII lower (Vietnamese)"),
3275                   build_string ("VISCII1.1"),
3276                   latin_viscii_lower_to_ucs, 0, 0, 32);
3277   Vcharset_latin_viscii_upper =
3278     make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper,
3279                   CHARSET_TYPE_96, 1, 1, '2',
3280                   CHARSET_LEFT_TO_RIGHT,
3281                   build_string ("VISCII upper"),
3282                   build_string ("VISCII upper (Vietnamese)"),
3283                   build_string ("VISCII upper (Vietnamese)"),
3284                   build_string ("VISCII1.1"),
3285                   latin_viscii_upper_to_ucs, 0, 0, 32);
3286 #endif
3287   Vcharset_chinese_big5_1 =
3288     make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1,
3289                   CHARSET_TYPE_94X94, 2, 0, '0',
3290                   CHARSET_LEFT_TO_RIGHT,
3291                   build_string ("Big5"),
3292                   build_string ("Big5 (Level-1)"),
3293                   build_string
3294                   ("Big5 Level-1 Chinese traditional"),
3295                   build_string ("big5"),
3296                   NULL, 0, 0, 33);
3297   Vcharset_chinese_big5_2 =
3298     make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2,
3299                   CHARSET_TYPE_94X94, 2, 0, '1',
3300                   CHARSET_LEFT_TO_RIGHT,
3301                   build_string ("Big5"),
3302                   build_string ("Big5 (Level-2)"),
3303                   build_string
3304                   ("Big5 Level-2 Chinese traditional"),
3305                   build_string ("big5"),
3306                   NULL, 0, 0, 33);
3307
3308 #ifdef ENABLE_COMPOSITE_CHARS
3309   /* #### For simplicity, we put composite chars into a 96x96 charset.
3310      This is going to lead to problems because you can run out of
3311      room, esp. as we don't yet recycle numbers. */
3312   Vcharset_composite =
3313     make_charset (LEADING_BYTE_COMPOSITE, Qcomposite,
3314                   CHARSET_TYPE_96X96, 2, 0, 0,
3315                   CHARSET_LEFT_TO_RIGHT,
3316                   build_string ("Composite"),
3317                   build_string ("Composite characters"),
3318                   build_string ("Composite characters"),
3319                   build_string (""));
3320
3321   composite_char_row_next = 32;
3322   composite_char_col_next = 32;
3323
3324   Vcomposite_char_string2char_hash_table =
3325     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
3326   Vcomposite_char_char2string_hash_table =
3327     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3328   staticpro (&Vcomposite_char_string2char_hash_table);
3329   staticpro (&Vcomposite_char_char2string_hash_table);
3330 #endif /* ENABLE_COMPOSITE_CHARS */
3331
3332 }