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