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