(decoding_table_remove_char): Change arguments to hide decoding_table
[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    Copyright (C) 1999,2000,2001 MORIOKA Tomohiko
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Rewritten by Ben Wing <ben@xemacs.org>. */
24
25 /* Rewritten by MORIOKA Tomohiko <tomo@m17n.org> for XEmacs UTF-2000. */
26
27 #include <config.h>
28 #ifdef UTF2000
29 #include <limits.h>
30 #endif
31 #include "lisp.h"
32
33 #include "buffer.h"
34 #include "chartab.h"
35 #include "elhash.h"
36 #include "lstream.h"
37 #include "device.h"
38 #include "faces.h"
39 #include "mule-ccl.h"
40
41 /* The various pre-defined charsets. */
42
43 Lisp_Object Vcharset_ascii;
44 Lisp_Object Vcharset_control_1;
45 Lisp_Object Vcharset_latin_iso8859_1;
46 Lisp_Object Vcharset_latin_iso8859_2;
47 Lisp_Object Vcharset_latin_iso8859_3;
48 Lisp_Object Vcharset_latin_iso8859_4;
49 Lisp_Object Vcharset_thai_tis620;
50 Lisp_Object Vcharset_greek_iso8859_7;
51 Lisp_Object Vcharset_arabic_iso8859_6;
52 Lisp_Object Vcharset_hebrew_iso8859_8;
53 Lisp_Object Vcharset_katakana_jisx0201;
54 Lisp_Object Vcharset_latin_jisx0201;
55 Lisp_Object Vcharset_cyrillic_iso8859_5;
56 Lisp_Object Vcharset_latin_iso8859_9;
57 Lisp_Object Vcharset_japanese_jisx0208_1978;
58 Lisp_Object Vcharset_chinese_gb2312;
59 Lisp_Object Vcharset_chinese_gb12345;
60 Lisp_Object Vcharset_japanese_jisx0208;
61 Lisp_Object Vcharset_japanese_jisx0208_1990;
62 Lisp_Object Vcharset_korean_ksc5601;
63 Lisp_Object Vcharset_japanese_jisx0212;
64 Lisp_Object Vcharset_chinese_cns11643_1;
65 Lisp_Object Vcharset_chinese_cns11643_2;
66 #ifdef UTF2000
67 Lisp_Object Vcharset_ucs;
68 Lisp_Object Vcharset_ucs_bmp;
69 Lisp_Object Vcharset_ucs_smp;
70 Lisp_Object Vcharset_ucs_sip;
71 Lisp_Object Vcharset_ucs_cns;
72 Lisp_Object Vcharset_ucs_jis;
73 Lisp_Object Vcharset_ucs_ks;
74 Lisp_Object Vcharset_ucs_big5;
75 Lisp_Object Vcharset_latin_viscii;
76 Lisp_Object Vcharset_latin_tcvn5712;
77 Lisp_Object Vcharset_latin_viscii_lower;
78 Lisp_Object Vcharset_latin_viscii_upper;
79 Lisp_Object Vcharset_chinese_big5;
80 Lisp_Object Vcharset_chinese_big5_cdp;
81 Lisp_Object Vcharset_ideograph_hanziku_1;
82 Lisp_Object Vcharset_ideograph_hanziku_2;
83 Lisp_Object Vcharset_ideograph_hanziku_3;
84 Lisp_Object Vcharset_ideograph_hanziku_4;
85 Lisp_Object Vcharset_ideograph_hanziku_5;
86 Lisp_Object Vcharset_ideograph_hanziku_6;
87 Lisp_Object Vcharset_ideograph_hanziku_7;
88 Lisp_Object Vcharset_ideograph_hanziku_8;
89 Lisp_Object Vcharset_ideograph_hanziku_9;
90 Lisp_Object Vcharset_ideograph_hanziku_10;
91 Lisp_Object Vcharset_ideograph_hanziku_11;
92 Lisp_Object Vcharset_ideograph_hanziku_12;
93 Lisp_Object Vcharset_china3_jef;
94 Lisp_Object Vcharset_ideograph_cbeta;
95 Lisp_Object Vcharset_ideograph_gt;
96 Lisp_Object Vcharset_ideograph_gt_pj_1;
97 Lisp_Object Vcharset_ideograph_gt_pj_2;
98 Lisp_Object Vcharset_ideograph_gt_pj_3;
99 Lisp_Object Vcharset_ideograph_gt_pj_4;
100 Lisp_Object Vcharset_ideograph_gt_pj_5;
101 Lisp_Object Vcharset_ideograph_gt_pj_6;
102 Lisp_Object Vcharset_ideograph_gt_pj_7;
103 Lisp_Object Vcharset_ideograph_gt_pj_8;
104 Lisp_Object Vcharset_ideograph_gt_pj_9;
105 Lisp_Object Vcharset_ideograph_gt_pj_10;
106 Lisp_Object Vcharset_ideograph_gt_pj_11;
107 Lisp_Object Vcharset_ideograph_daikanwa_2;
108 Lisp_Object Vcharset_ideograph_daikanwa;
109 Lisp_Object Vcharset_ethiopic_ucs;
110 #endif
111 Lisp_Object Vcharset_chinese_big5_1;
112 Lisp_Object Vcharset_chinese_big5_2;
113
114 #ifdef ENABLE_COMPOSITE_CHARS
115 Lisp_Object Vcharset_composite;
116
117 /* Hash tables for composite chars.  One maps string representing
118    composed chars to their equivalent chars; one goes the
119    other way. */
120 Lisp_Object Vcomposite_char_char2string_hash_table;
121 Lisp_Object Vcomposite_char_string2char_hash_table;
122
123 static int composite_char_row_next;
124 static int composite_char_col_next;
125
126 #endif /* ENABLE_COMPOSITE_CHARS */
127
128 struct charset_lookup *chlook;
129
130 static const struct lrecord_description charset_lookup_description_1[] = {
131   { XD_LISP_OBJECT_ARRAY, offsetof (struct charset_lookup, charset_by_leading_byte),
132 #ifdef UTF2000
133     128+4*128
134 #else
135     128+4*128*2 
136 #endif
137   }, { XD_END }
138 };
139
140 static const struct struct_description charset_lookup_description = {
141   sizeof (struct charset_lookup),
142   charset_lookup_description_1
143 };
144
145 #ifndef UTF2000
146 /* Table of number of bytes in the string representation of a character
147    indexed by the first byte of that representation.
148
149    rep_bytes_by_first_byte(c) is more efficient than the equivalent
150    canonical computation:
151
152    XCHARSET_REP_BYTES (CHARSET_BY_LEADING_BYTE (c)) */
153
154 const Bytecount rep_bytes_by_first_byte[0xA0] =
155 { /* 0x00 - 0x7f are for straight ASCII */
156   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
157   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
159   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
160   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
161   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
162   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
163   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164   /* 0x80 - 0x8f are for Dimension-1 official charsets */
165 #ifdef CHAR_IS_UCS4
166   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
167 #else
168   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
169 #endif
170   /* 0x90 - 0x9d are for Dimension-2 official charsets */
171   /* 0x9e is for Dimension-1 private charsets */
172   /* 0x9f is for Dimension-2 private charsets */
173   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4
174 };
175 #endif
176
177 #ifdef UTF2000
178
179 INLINE_HEADER int CHARSET_BYTE_SIZE (Lisp_Charset* cs);
180 INLINE_HEADER int
181 CHARSET_BYTE_SIZE (Lisp_Charset* cs)
182 {
183   /* ad-hoc method for `ascii' */
184   if ((CHARSET_CHARS (cs) == 94) &&
185       (CHARSET_BYTE_OFFSET (cs) != 33))
186     return 128 - CHARSET_BYTE_OFFSET (cs);
187   else
188     return CHARSET_CHARS (cs);
189 }
190
191 #define XCHARSET_BYTE_SIZE(ccs) CHARSET_BYTE_SIZE (XCHARSET (ccs))
192
193 int
194 decoding_table_check_elements (Lisp_Object v, int dim, int ccs_len)
195 {
196   int i;
197
198   if (XVECTOR_LENGTH (v) > ccs_len)
199     return -1;
200
201   for (i = 0; i < XVECTOR_LENGTH (v); i++)
202     {
203       Lisp_Object c = XVECTOR_DATA(v)[i];
204
205       if (!NILP (c) && !CHARP (c))
206         {
207           if (VECTORP (c))
208             {
209               int ret = decoding_table_check_elements (c, dim - 1, ccs_len);
210               if (ret)
211                 return ret;
212             }
213           else
214             return -2;
215         }
216     }
217   return 0;
218 }
219
220 Lisp_Object
221 put_char_ccs_code_point (Lisp_Object character,
222                          Lisp_Object ccs, Lisp_Object value)
223 {
224   if (!EQ (XCHARSET_NAME (ccs), Qucs)
225       || !INTP (value)
226       || (XCHAR (character) != XINT (value)))
227     {
228       Lisp_Object v = XCHARSET_DECODING_TABLE (ccs);
229       int dim = XCHARSET_DIMENSION (ccs);
230       int ccs_len = XCHARSET_BYTE_SIZE (ccs);
231       int byte_offset = XCHARSET_BYTE_OFFSET (ccs);
232       int code_point;
233
234       if (CONSP (value))
235         { /* obsolete representation: value must be a list of bytes */
236           Lisp_Object ret = Fcar (value);
237           Lisp_Object rest;
238
239           if (!INTP (ret))
240             signal_simple_error ("Invalid value for coded-charset", value);
241           code_point = XINT (ret);
242           if (XCHARSET_GRAPHIC (ccs) == 1)
243             code_point &= 0x7F;
244           rest = Fcdr (value);
245           while (!NILP (rest))
246             {
247               int j;
248
249               if (!CONSP (rest))
250                 signal_simple_error ("Invalid value for coded-charset",
251                                      value);
252               ret = Fcar (rest);
253               if (!INTP (ret))
254                 signal_simple_error ("Invalid value for coded-charset",
255                                      value);
256               j = XINT (ret);
257               if (XCHARSET_GRAPHIC (ccs) == 1)
258                 j &= 0x7F;
259               code_point = (code_point << 8) | j;
260               rest = Fcdr (rest);
261             }
262           value = make_int (code_point);
263         }
264       else if (INTP (value))
265         {
266           code_point = XINT (value);
267           if (XCHARSET_GRAPHIC (ccs) == 1)
268             {
269               code_point &= 0x7F7F7F7F;
270               value = make_int (code_point);
271             }
272         }
273       else
274         signal_simple_error ("Invalid value for coded-charset", value);
275
276       if (VECTORP (v))
277         {
278           Lisp_Object cpos = Fget_char_attribute (character, ccs, Qnil);
279           if (INTP (cpos))
280             {
281               decoding_table_remove_char (v, dim, byte_offset, XINT (cpos));
282             }
283         }
284       else
285         {
286           XCHARSET_DECODING_TABLE (ccs)
287             = v = make_vector (ccs_len, Qnil);
288         }
289
290       decoding_table_put_char (v, dim, byte_offset, code_point, character);
291     }
292   return value;
293 }
294
295 Lisp_Object
296 remove_char_ccs (Lisp_Object character, Lisp_Object ccs)
297 {
298   Lisp_Object decoding_table = XCHARSET_DECODING_TABLE (ccs);
299   Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (ccs);
300
301   if (VECTORP (decoding_table))
302     {
303       Lisp_Object cpos = Fget_char_attribute (character, ccs, Qnil);
304
305       if (!NILP (cpos))
306         {
307           decoding_table_remove_char (decoding_table,
308                                       XCHARSET_DIMENSION (ccs),
309                                       XCHARSET_BYTE_OFFSET (ccs),
310                                       XINT (cpos));
311         }
312     }
313   if (CHAR_TABLEP (encoding_table))
314     {
315       put_char_id_table (XCHAR_TABLE(encoding_table), character, Qnil);
316     }
317   return Qt;
318 }
319
320 #endif
321
322 #ifndef UTF2000
323 int leading_code_private_11;
324 #endif
325
326 Lisp_Object Qcharsetp;
327
328 /* Qdoc_string, Qdimension, Qchars defined in general.c */
329 Lisp_Object Qregistry, Qfinal, Qgraphic;
330 Lisp_Object Qdirection;
331 Lisp_Object Qreverse_direction_charset;
332 Lisp_Object Qleading_byte;
333 Lisp_Object Qshort_name, Qlong_name;
334 #ifdef UTF2000
335 Lisp_Object Qmin_code, Qmax_code, Qcode_offset;
336 Lisp_Object Qmother, Qconversion, Q94x60, Q94x94x60;
337 #endif
338
339 Lisp_Object Qascii,
340   Qcontrol_1,
341   Qlatin_iso8859_1,
342   Qlatin_iso8859_2,
343   Qlatin_iso8859_3,
344   Qlatin_iso8859_4,
345   Qthai_tis620,
346   Qgreek_iso8859_7,
347   Qarabic_iso8859_6,
348   Qhebrew_iso8859_8,
349   Qkatakana_jisx0201,
350   Qlatin_jisx0201,
351   Qcyrillic_iso8859_5,
352   Qlatin_iso8859_9,
353   Qjapanese_jisx0208_1978,
354   Qchinese_gb2312,
355   Qchinese_gb12345,
356   Qjapanese_jisx0208,
357   Qjapanese_jisx0208_1990,
358   Qkorean_ksc5601,
359   Qjapanese_jisx0212,
360   Qchinese_cns11643_1,
361   Qchinese_cns11643_2,
362 #ifdef UTF2000
363   Qucs,
364   Qucs_bmp,
365   Qucs_smp,
366   Qucs_sip,
367   Qucs_cns,
368   Qucs_jis,
369   Qucs_ks,
370   Qucs_big5,
371   Qlatin_viscii,
372   Qlatin_tcvn5712,
373   Qlatin_viscii_lower,
374   Qlatin_viscii_upper,
375   Qvietnamese_viscii_lower,
376   Qvietnamese_viscii_upper,
377   Qchinese_big5,
378   Qchinese_big5_cdp,
379   Qideograph_hanziku_1,
380   Qideograph_hanziku_2,
381   Qideograph_hanziku_3,
382   Qideograph_hanziku_4,
383   Qideograph_hanziku_5,
384   Qideograph_hanziku_6,
385   Qideograph_hanziku_7,
386   Qideograph_hanziku_8,
387   Qideograph_hanziku_9,
388   Qideograph_hanziku_10,
389   Qideograph_hanziku_11,
390   Qideograph_hanziku_12,
391   Qchina3_jef,
392   Qideograph_cbeta,
393   Qideograph_daikanwa_2,
394   Qideograph_daikanwa,
395   Qideograph_gt,
396   Qideograph_gt_pj_1,
397   Qideograph_gt_pj_2,
398   Qideograph_gt_pj_3,
399   Qideograph_gt_pj_4,
400   Qideograph_gt_pj_5,
401   Qideograph_gt_pj_6,
402   Qideograph_gt_pj_7,
403   Qideograph_gt_pj_8,
404   Qideograph_gt_pj_9,
405   Qideograph_gt_pj_10,
406   Qideograph_gt_pj_11,
407   Qethiopic_ucs,
408 #endif
409   Qchinese_big5_1,
410   Qchinese_big5_2,
411   Qcomposite;
412
413 Lisp_Object Ql2r, Qr2l;
414
415 Lisp_Object Vcharset_hash_table;
416
417 /* Composite characters are characters constructed by overstriking two
418    or more regular characters.
419
420    1) The old Mule implementation involves storing composite characters
421       in a buffer as a tag followed by all of the actual characters
422       used to make up the composite character.  I think this is a bad
423       idea; it greatly complicates code that wants to handle strings
424       one character at a time because it has to deal with the possibility
425       of great big ungainly characters.  It's much more reasonable to
426       simply store an index into a table of composite characters.
427
428    2) The current implementation only allows for 16,384 separate
429       composite characters over the lifetime of the XEmacs process.
430       This could become a potential problem if the user
431       edited lots of different files that use composite characters.
432       Due to FSF bogosity, increasing the number of allowable
433       composite characters under Mule would decrease the number
434       of possible faces that can exist.  Mule already has shrunk
435       this to 2048, and further shrinkage would become uncomfortable.
436       No such problems exist in XEmacs.
437
438       Composite characters could be represented as 0x80 C1 C2 C3,
439       where each C[1-3] is in the range 0xA0 - 0xFF.  This allows
440       for slightly under 2^20 (one million) composite characters
441       over the XEmacs process lifetime, and you only need to
442       increase the size of a Mule character from 19 to 21 bits.
443       Or you could use 0x80 C1 C2 C3 C4, allowing for about
444       85 million (slightly over 2^26) composite characters. */
445
446 \f
447 /************************************************************************/
448 /*                       Basic Emchar functions                         */
449 /************************************************************************/
450
451 /* Convert a non-ASCII Mule character C into a one-character Mule-encoded
452    string in STR.  Returns the number of bytes stored.
453    Do not call this directly.  Use the macro set_charptr_emchar() instead.
454  */
455
456 Bytecount
457 non_ascii_set_charptr_emchar (Bufbyte *str, Emchar c)
458 {
459   Bufbyte *p;
460 #ifndef UTF2000
461   Charset_ID lb;
462   int c1, c2;
463   Lisp_Object charset;
464 #endif
465
466   p = str;
467 #ifdef UTF2000
468   if ( c <= 0x7f )
469     {
470       *p++ = c;
471     }
472   else if ( c <= 0x7ff )
473     {
474       *p++ = (c >> 6) | 0xc0;
475       *p++ = (c & 0x3f) | 0x80;
476     }
477   else if ( c <= 0xffff )
478     {
479       *p++ =  (c >> 12) | 0xe0;
480       *p++ = ((c >>  6) & 0x3f) | 0x80;
481       *p++ =  (c        & 0x3f) | 0x80;
482     }
483   else if ( c <= 0x1fffff )
484     {
485       *p++ =  (c >> 18) | 0xf0;
486       *p++ = ((c >> 12) & 0x3f) | 0x80;
487       *p++ = ((c >>  6) & 0x3f) | 0x80;
488       *p++ =  (c        & 0x3f) | 0x80;
489     }
490   else if ( c <= 0x3ffffff )
491     {
492       *p++ =  (c >> 24) | 0xf8;
493       *p++ = ((c >> 18) & 0x3f) | 0x80;
494       *p++ = ((c >> 12) & 0x3f) | 0x80;
495       *p++ = ((c >>  6) & 0x3f) | 0x80;
496       *p++ =  (c        & 0x3f) | 0x80;
497     }
498   else
499     {
500       *p++ =  (c >> 30) | 0xfc;
501       *p++ = ((c >> 24) & 0x3f) | 0x80;
502       *p++ = ((c >> 18) & 0x3f) | 0x80;
503       *p++ = ((c >> 12) & 0x3f) | 0x80;
504       *p++ = ((c >>  6) & 0x3f) | 0x80;
505       *p++ =  (c        & 0x3f) | 0x80;
506     }
507 #else
508   BREAKUP_CHAR (c, charset, c1, c2);
509   lb = CHAR_LEADING_BYTE (c);
510   if (LEADING_BYTE_PRIVATE_P (lb))
511     *p++ = PRIVATE_LEADING_BYTE_PREFIX (lb);
512   *p++ = lb;
513   if (EQ (charset, Vcharset_control_1))
514     c1 += 0x20;
515   *p++ = c1 | 0x80;
516   if (c2)
517     *p++ = c2 | 0x80;
518 #endif
519   return (p - str);
520 }
521
522 /* Return the first character from a Mule-encoded string in STR,
523    assuming it's non-ASCII.  Do not call this directly.
524    Use the macro charptr_emchar() instead. */
525
526 Emchar
527 non_ascii_charptr_emchar (const Bufbyte *str)
528 {
529 #ifdef UTF2000
530   Bufbyte b;
531   Emchar ch;
532   int len;
533
534   b = *str++;
535   if ( b >= 0xfc )
536     {
537       ch = (b & 0x01);
538       len = 5;
539     }
540   else if ( b >= 0xf8 )
541     {
542       ch = b & 0x03;
543       len = 4;
544     }
545   else if ( b >= 0xf0 )
546     {
547       ch = b & 0x07;
548       len = 3;
549     }
550   else if ( b >= 0xe0 )
551     {
552       ch = b & 0x0f;
553       len = 2;
554     }
555   else if ( b >= 0xc0 )
556     {
557       ch = b & 0x1f;
558       len = 1;
559     }
560   else
561     {
562       ch = b;
563       len = 0;
564     }
565   for( ; len > 0; len-- )
566     {
567       b = *str++;
568       ch = ( ch << 6 ) | ( b & 0x3f );
569     }
570   return ch;
571 #else
572   Bufbyte i0 = *str, i1, i2 = 0;
573   Lisp_Object charset;
574
575   if (i0 == LEADING_BYTE_CONTROL_1)
576     return (Emchar) (*++str - 0x20);
577
578   if (LEADING_BYTE_PREFIX_P (i0))
579     i0 = *++str;
580
581   i1 = *++str & 0x7F;
582
583   charset = CHARSET_BY_LEADING_BYTE (i0);
584   if (XCHARSET_DIMENSION (charset) == 2)
585     i2 = *++str & 0x7F;
586
587   return MAKE_CHAR (charset, i1, i2);
588 #endif
589 }
590
591 /* Return whether CH is a valid Emchar, assuming it's non-ASCII.
592    Do not call this directly.  Use the macro valid_char_p() instead. */
593
594 #ifndef UTF2000
595 int
596 non_ascii_valid_char_p (Emchar ch)
597 {
598   int f1, f2, f3;
599
600   /* Must have only lowest 19 bits set */
601   if (ch & ~0x7FFFF)
602     return 0;
603
604   f1 = CHAR_FIELD1 (ch);
605   f2 = CHAR_FIELD2 (ch);
606   f3 = CHAR_FIELD3 (ch);
607
608   if (f1 == 0)
609     {
610       Lisp_Object charset;
611
612       if (f2 < MIN_CHAR_FIELD2_OFFICIAL ||
613           (f2 > MAX_CHAR_FIELD2_OFFICIAL && f2 < MIN_CHAR_FIELD2_PRIVATE) ||
614            f2 > MAX_CHAR_FIELD2_PRIVATE)
615         return 0;
616       if (f3 < 0x20)
617         return 0;
618
619       if (f3 != 0x20 && f3 != 0x7F && !(f2 >= MIN_CHAR_FIELD2_PRIVATE &&
620                                         f2 <= MAX_CHAR_FIELD2_PRIVATE))
621         return 1;
622
623       /*
624          NOTE: This takes advantage of the fact that
625          FIELD2_TO_OFFICIAL_LEADING_BYTE and
626          FIELD2_TO_PRIVATE_LEADING_BYTE are the same.
627          */
628       charset = CHARSET_BY_LEADING_BYTE (f2 + FIELD2_TO_OFFICIAL_LEADING_BYTE);
629       if (EQ (charset, Qnil))
630         return 0;
631       return (XCHARSET_CHARS (charset) == 96);
632     }
633   else
634     {
635       Lisp_Object charset;
636
637       if (f1 < MIN_CHAR_FIELD1_OFFICIAL ||
638           (f1 > MAX_CHAR_FIELD1_OFFICIAL && f1 < MIN_CHAR_FIELD1_PRIVATE) ||
639           f1 > MAX_CHAR_FIELD1_PRIVATE)
640         return 0;
641       if (f2 < 0x20 || f3 < 0x20)
642         return 0;
643
644 #ifdef ENABLE_COMPOSITE_CHARS
645       if (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE == LEADING_BYTE_COMPOSITE)
646         {
647           if (UNBOUNDP (Fgethash (make_int (ch),
648                                   Vcomposite_char_char2string_hash_table,
649                                   Qunbound)))
650             return 0;
651           return 1;
652         }
653 #endif /* ENABLE_COMPOSITE_CHARS */
654
655       if (f2 != 0x20 && f2 != 0x7F && f3 != 0x20 && f3 != 0x7F
656           && !(f1 >= MIN_CHAR_FIELD1_PRIVATE && f1 <= MAX_CHAR_FIELD1_PRIVATE))
657         return 1;
658
659       if (f1 <= MAX_CHAR_FIELD1_OFFICIAL)
660         charset =
661           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_OFFICIAL_LEADING_BYTE);
662       else
663         charset =
664           CHARSET_BY_LEADING_BYTE (f1 + FIELD1_TO_PRIVATE_LEADING_BYTE);
665
666       if (EQ (charset, Qnil))
667         return 0;
668       return (XCHARSET_CHARS (charset) == 96);
669     }
670 }
671 #endif
672
673 \f
674 /************************************************************************/
675 /*                       Basic string functions                         */
676 /************************************************************************/
677
678 /* Copy the character pointed to by SRC into DST.  Do not call this
679    directly.  Use the macro charptr_copy_char() instead.
680    Return the number of bytes copied.  */
681
682 Bytecount
683 non_ascii_charptr_copy_char (const Bufbyte *src, Bufbyte *dst)
684 {
685   unsigned int bytes = REP_BYTES_BY_FIRST_BYTE (*src);
686   unsigned int i;
687   for (i = bytes; i; i--, dst++, src++)
688     *dst = *src;
689   return bytes;
690 }
691
692 \f
693 /************************************************************************/
694 /*                        streams of Emchars                            */
695 /************************************************************************/
696
697 /* Treat a stream as a stream of Emchar's rather than a stream of bytes.
698    The functions below are not meant to be called directly; use
699    the macros in insdel.h. */
700
701 Emchar
702 Lstream_get_emchar_1 (Lstream *stream, int ch)
703 {
704   Bufbyte str[MAX_EMCHAR_LEN];
705   Bufbyte *strptr = str;
706   unsigned int bytes;
707
708   str[0] = (Bufbyte) ch;
709
710   for (bytes = REP_BYTES_BY_FIRST_BYTE (ch) - 1; bytes; bytes--)
711     {
712       int c = Lstream_getc (stream);
713       bufpos_checking_assert (c >= 0);
714       *++strptr = (Bufbyte) c;
715     }
716   return charptr_emchar (str);
717 }
718
719 int
720 Lstream_fput_emchar (Lstream *stream, Emchar ch)
721 {
722   Bufbyte str[MAX_EMCHAR_LEN];
723   Bytecount len = set_charptr_emchar (str, ch);
724   return Lstream_write (stream, str, len);
725 }
726
727 void
728 Lstream_funget_emchar (Lstream *stream, Emchar ch)
729 {
730   Bufbyte str[MAX_EMCHAR_LEN];
731   Bytecount len = set_charptr_emchar (str, ch);
732   Lstream_unread (stream, str, len);
733 }
734
735 \f
736 /************************************************************************/
737 /*                            charset object                            */
738 /************************************************************************/
739
740 static Lisp_Object
741 mark_charset (Lisp_Object obj)
742 {
743   Lisp_Charset *cs = XCHARSET (obj);
744
745   mark_object (cs->short_name);
746   mark_object (cs->long_name);
747   mark_object (cs->doc_string);
748   mark_object (cs->registry);
749   mark_object (cs->ccl_program);
750 #ifdef UTF2000
751   mark_object (cs->decoding_table);
752   mark_object (cs->mother);
753 #endif
754   return cs->name;
755 }
756
757 static void
758 print_charset (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
759 {
760   Lisp_Charset *cs = XCHARSET (obj);
761   char buf[200];
762
763   if (print_readably)
764     error ("printing unreadable object #<charset %s 0x%x>",
765            string_data (XSYMBOL (CHARSET_NAME (cs))->name),
766            cs->header.uid);
767
768   write_c_string ("#<charset ", printcharfun);
769   print_internal (CHARSET_NAME (cs), printcharfun, 0);
770   write_c_string (" ", printcharfun);
771   print_internal (CHARSET_SHORT_NAME (cs), printcharfun, 1);
772   write_c_string (" ", printcharfun);
773   print_internal (CHARSET_LONG_NAME (cs), printcharfun, 1);
774   write_c_string (" ", printcharfun);
775   print_internal (CHARSET_DOC_STRING (cs), printcharfun, 1);
776   sprintf (buf, " %d^%d %s cols=%d g%d final='%c' reg=",
777            CHARSET_CHARS (cs),
778            CHARSET_DIMENSION (cs),
779            CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? "l2r" : "r2l",
780            CHARSET_COLUMNS (cs),
781            CHARSET_GRAPHIC (cs),
782            CHARSET_FINAL (cs));
783   write_c_string (buf, printcharfun);
784   print_internal (CHARSET_REGISTRY (cs), printcharfun, 0);
785   sprintf (buf, " 0x%x>", cs->header.uid);
786   write_c_string (buf, printcharfun);
787 }
788
789 static const struct lrecord_description charset_description[] = {
790   { XD_LISP_OBJECT, offsetof (Lisp_Charset, name) },
791   { XD_LISP_OBJECT, offsetof (Lisp_Charset, doc_string) },
792   { XD_LISP_OBJECT, offsetof (Lisp_Charset, registry) },
793   { XD_LISP_OBJECT, offsetof (Lisp_Charset, short_name) },
794   { XD_LISP_OBJECT, offsetof (Lisp_Charset, long_name) },
795   { XD_LISP_OBJECT, offsetof (Lisp_Charset, reverse_direction_charset) },
796   { XD_LISP_OBJECT, offsetof (Lisp_Charset, ccl_program) },
797 #ifdef UTF2000
798   { XD_LISP_OBJECT, offsetof (Lisp_Charset, decoding_table) },
799   { XD_LISP_OBJECT, offsetof (Lisp_Charset, mother) },
800 #endif
801   { XD_END }
802 };
803
804 DEFINE_LRECORD_IMPLEMENTATION ("charset", charset,
805                                mark_charset, print_charset, 0, 0, 0,
806                                charset_description,
807                                Lisp_Charset);
808
809 /* Make a new charset. */
810 /* #### SJT Should generic properties be allowed? */
811 static Lisp_Object
812 make_charset (Charset_ID id, Lisp_Object name,
813               unsigned short chars, unsigned char dimension,
814               unsigned char columns, unsigned char graphic,
815               Bufbyte final, unsigned char direction, Lisp_Object short_name,
816               Lisp_Object long_name, Lisp_Object doc,
817               Lisp_Object reg,
818               Lisp_Object decoding_table,
819               Emchar min_code, Emchar max_code,
820               Emchar code_offset, unsigned char byte_offset,
821               Lisp_Object mother, unsigned char conversion)
822 {
823   Lisp_Object obj;
824   Lisp_Charset *cs = alloc_lcrecord_type (Lisp_Charset, &lrecord_charset);
825
826   zero_lcrecord (cs);
827
828   XSETCHARSET (obj, cs);
829
830   CHARSET_ID            (cs) = id;
831   CHARSET_NAME          (cs) = name;
832   CHARSET_SHORT_NAME    (cs) = short_name;
833   CHARSET_LONG_NAME     (cs) = long_name;
834   CHARSET_CHARS         (cs) = chars;
835   CHARSET_DIMENSION     (cs) = dimension;
836   CHARSET_DIRECTION     (cs) = direction;
837   CHARSET_COLUMNS       (cs) = columns;
838   CHARSET_GRAPHIC       (cs) = graphic;
839   CHARSET_FINAL         (cs) = final;
840   CHARSET_DOC_STRING    (cs) = doc;
841   CHARSET_REGISTRY      (cs) = reg;
842   CHARSET_CCL_PROGRAM   (cs) = Qnil;
843   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = Qnil;
844 #ifdef UTF2000
845   CHARSET_DECODING_TABLE(cs) = Qnil;
846   CHARSET_MIN_CODE      (cs) = min_code;
847   CHARSET_MAX_CODE      (cs) = max_code;
848   CHARSET_CODE_OFFSET   (cs) = code_offset;
849   CHARSET_BYTE_OFFSET   (cs) = byte_offset;
850   CHARSET_MOTHER        (cs) = mother;
851   CHARSET_CONVERSION    (cs) = conversion;
852 #endif
853
854 #ifndef UTF2000
855   if (id == LEADING_BYTE_ASCII)
856     CHARSET_REP_BYTES (cs) = 1;
857   else if (id < 0xA0)
858     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 1;
859   else
860     CHARSET_REP_BYTES (cs) = CHARSET_DIMENSION (cs) + 2;
861 #endif
862
863   if (final)
864     {
865       /* some charsets do not have final characters.  This includes
866          ASCII, Control-1, Composite, and the two faux private
867          charsets. */
868       unsigned char iso2022_type
869         = (dimension == 1 ? 0 : 2) + (chars == 94 ? 0 : 1);
870 #if UTF2000
871       if (code_offset == 0)
872         {
873           assert (NILP (chlook->charset_by_attributes[iso2022_type][final]));
874           chlook->charset_by_attributes[iso2022_type][final] = obj;
875         }
876 #else
877       assert (NILP
878               (chlook->charset_by_attributes[iso2022_type][final][direction]));
879       chlook->charset_by_attributes[iso2022_type][final][direction] = obj;
880 #endif
881     }
882
883   assert (NILP (chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE]));
884   chlook->charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj;
885
886   /* Some charsets are "faux" and don't have names or really exist at
887      all except in the leading-byte table. */
888   if (!NILP (name))
889     Fputhash (name, obj, Vcharset_hash_table);
890   return obj;
891 }
892
893 static int
894 get_unallocated_leading_byte (int dimension)
895 {
896   Charset_ID lb;
897
898 #ifdef UTF2000
899   if (chlook->next_allocated_leading_byte > MAX_LEADING_BYTE_PRIVATE)
900     lb = 0;
901   else
902     lb = chlook->next_allocated_leading_byte++;
903 #else
904   if (dimension == 1)
905     {
906       if (chlook->next_allocated_1_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_1)
907         lb = 0;
908       else
909         lb = chlook->next_allocated_1_byte_leading_byte++;
910     }
911   else
912     {
913       if (chlook->next_allocated_2_byte_leading_byte > MAX_LEADING_BYTE_PRIVATE_2)
914         lb = 0;
915       else
916         lb = chlook->next_allocated_2_byte_leading_byte++;
917     }
918 #endif
919
920   if (!lb)
921     signal_simple_error
922       ("No more character sets free for this dimension",
923        make_int (dimension));
924
925   return lb;
926 }
927
928 #ifdef UTF2000
929 /* Number of Big5 characters which have the same code in 1st byte.  */
930
931 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
932
933 Emchar
934 decode_builtin_char (Lisp_Object charset, int code_point)
935 {
936   Lisp_Object mother = XCHARSET_MOTHER (charset);
937   int final;
938
939   if ( CHARSETP (mother) )
940     {
941       int code = code_point;
942
943       if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x60 )
944         {
945           int row = code_point >> 8;
946           int cell = code_point & 255;    
947
948           if (row < 16 + 32)
949             return -1;
950           else if (row < 16 + 32 + 30)
951             code = (row - (16 + 32)) * 94 + cell - 33;
952           else if (row < 18 + 32 + 30)
953             return -1;
954           else if (row < 18 + 32 + 60)
955             code = (row - (18 + 32)) * 94 + cell - 33;
956         }
957       else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94x60 )
958         {
959           int plane = code_point >> 16;
960           int row = (code_point >> 8) & 255;
961           int cell = code_point & 255;    
962
963           if (row < 16 + 32)
964             return -1;
965           else if (row < 16 + 32 + 30)
966             code
967               = (plane - 33) * 94 * 60
968               + (row - (16 + 32)) * 94
969               + cell - 33;
970           else if (row < 18 + 32 + 30)
971             return -1;
972           else if (row < 18 + 32 + 60)
973             code
974               = (plane - 33) * 94 * 60
975               + (row - (18 + 32)) * 94
976               + cell - 33;
977         }
978       return DECODE_CHAR (mother, code + XCHARSET_CODE_OFFSET(charset));
979     }
980   else if (EQ (charset, Vcharset_chinese_big5))
981     {
982       int c1 = code_point >> 8;
983       int c2 = code_point & 0xFF;
984       unsigned int I;
985
986       if ( (  (0xA1 <= c1) && (c1 <= 0xFE)  )
987            &&
988            ( ((0x40 <= c2) && (c2 <= 0x7E)) ||
989              ((0xA1 <= c2) && (c2 <= 0xFE)) ) )
990         {
991           I = (c1 - 0xA1) * BIG5_SAME_ROW
992             + c2 - (c2 < 0x7F ? 0x40 : 0x62);
993
994           if (c1 < 0xC9)
995             {
996               charset = Vcharset_chinese_big5_1;
997             }
998           else
999             {
1000               charset = Vcharset_chinese_big5_2;
1001               I -= (BIG5_SAME_ROW) * (0xC9 - 0xA1);
1002             }
1003           code_point = ((I / 94 + 33) << 8) | (I % 94 + 33);
1004         }
1005     }
1006   if ((final = XCHARSET_FINAL (charset)) >= '0')
1007     {
1008       if (XCHARSET_DIMENSION (charset) == 1)
1009         {
1010           switch (XCHARSET_CHARS (charset))
1011             {
1012             case 94:
1013               return MIN_CHAR_94
1014                 + (final - '0') * 94 + ((code_point & 0x7F) - 33);
1015             case 96:
1016               return MIN_CHAR_96
1017                 + (final - '0') * 96 + ((code_point & 0x7F) - 32);
1018             default:
1019               abort ();
1020               return -1;
1021             }
1022         }
1023       else
1024         {
1025           switch (XCHARSET_CHARS (charset))
1026             {
1027             case 94:
1028               return MIN_CHAR_94x94
1029                 + (final - '0') * 94 * 94
1030                 + (((code_point >> 8) & 0x7F) - 33) * 94
1031                 + ((code_point & 0x7F) - 33);
1032             case 96:
1033               return MIN_CHAR_96x96
1034                 + (final - '0') * 96 * 96
1035                 + (((code_point >> 8) & 0x7F) - 32) * 96
1036                 + ((code_point & 0x7F) - 32);
1037             default:
1038               abort ();
1039               return -1;
1040             }
1041         }
1042     }
1043   else if (XCHARSET_MAX_CODE (charset))
1044     {
1045       Emchar cid
1046         = (XCHARSET_DIMENSION (charset) == 1
1047            ?
1048            code_point - XCHARSET_BYTE_OFFSET (charset)
1049            :
1050            ((code_point >> 8) - XCHARSET_BYTE_OFFSET (charset))
1051            * XCHARSET_CHARS (charset)
1052            + (code_point & 0xFF) - XCHARSET_BYTE_OFFSET (charset))
1053         + XCHARSET_CODE_OFFSET (charset);
1054       if ((cid < XCHARSET_MIN_CODE (charset))
1055           || (XCHARSET_MAX_CODE (charset) < cid))
1056         return -1;
1057       return cid;
1058     }
1059   else
1060     return -1;
1061 }
1062
1063 int
1064 charset_code_point (Lisp_Object charset, Emchar ch)
1065 {
1066   Lisp_Object encoding_table = XCHARSET_ENCODING_TABLE (charset);
1067   Lisp_Object ret;
1068
1069   if ( CHAR_TABLEP (encoding_table)
1070        && INTP (ret = get_char_id_table (XCHAR_TABLE(encoding_table),
1071                                          ch)) )
1072     return XINT (ret);
1073   else
1074     {
1075       Lisp_Object mother = XCHARSET_MOTHER (charset);
1076       int min = XCHARSET_MIN_CODE (charset);
1077       int max = XCHARSET_MAX_CODE (charset);
1078       int code;
1079
1080       if ( CHARSETP (mother) )
1081         code = charset_code_point (mother, ch);
1082       else
1083         code = ch;
1084       if ( (min <= code) && (code <= max) )
1085         {
1086           int d = code - XCHARSET_CODE_OFFSET (charset);
1087
1088           if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x60 )
1089             {
1090               int row  = d / 94;
1091               int cell = d % 94 + 33;
1092
1093               if (row < 30)
1094                 row += 16 + 32;
1095               else
1096                 row += 18 + 32;
1097               return (row << 8) | cell;
1098             }
1099           else if ( XCHARSET_CONVERSION (charset) == CONVERSION_94x94x60 )
1100             {
1101               int plane =  d / (94 * 60) + 33;
1102               int row   = (d % (94 * 60)) / 94;
1103               int cell  =  d %  94 + 33;
1104
1105               if (row < 30)
1106                 row += 16 + 32;
1107               else
1108                 row += 18 + 32;
1109               return (plane << 16) | (row << 8) | cell;
1110             }
1111           else if (XCHARSET_CHARS (charset) == 94)
1112             {
1113               if (XCHARSET_DIMENSION (charset) == 1)
1114                 return d + 33;
1115               else if (XCHARSET_DIMENSION (charset) == 2)
1116                 return ((d / 94 + 33) << 8) | (d % 94 + 33);
1117               else if (XCHARSET_DIMENSION (charset) == 3)
1118                 return
1119                   (   (d / (94 * 94) + 33) << 16)
1120                   |  ((d / 94 % 94   + 33) <<  8)
1121                   |   (d % 94        + 33);
1122               else /* if (XCHARSET_DIMENSION (charset) == 4) */
1123                 return
1124                   (  (d / (94 * 94 * 94) + 33) << 24)
1125                   | ((d / (94 * 94) % 94 + 33) << 16)
1126                   | ((d / 94 % 94        + 33) <<  8)
1127                   |  (d % 94             + 33);
1128             }
1129           else if (XCHARSET_CHARS (charset) == 96)
1130             {
1131               if (XCHARSET_DIMENSION (charset) == 1)
1132                 return d + 32;
1133               else if (XCHARSET_DIMENSION (charset) == 2)
1134                 return ((d / 96 + 32) << 8) | (d % 96 + 32);
1135               else if (XCHARSET_DIMENSION (charset) == 3)
1136                 return
1137                   (   (d / (96 * 96) + 32) << 16)
1138                   |  ((d / 96 % 96   + 32) <<  8)
1139                   |   (d % 96        + 32);
1140               else /* if (XCHARSET_DIMENSION (charset) == 4) */
1141                 return
1142                   (  (d / (96 * 96 * 96) + 32) << 24)
1143                   | ((d / (96 * 96) % 96 + 32) << 16)
1144                   | ((d / 96 % 96        + 32) <<  8)
1145                   |  (d % 96             + 32);
1146             }
1147           else
1148             return code - XCHARSET_CODE_OFFSET (charset);
1149         }
1150       else if ( (XCHARSET_CODE_OFFSET (charset) == 0) ||
1151                 (XCHARSET_CODE_OFFSET (charset)
1152                  == XCHARSET_MIN_CODE (charset)) )
1153         {
1154           int d;
1155
1156           if (XCHARSET_DIMENSION (charset) == 1)
1157             {
1158               if (XCHARSET_CHARS (charset) == 94)
1159                 {
1160                   if (((d = ch - (MIN_CHAR_94
1161                                   + (XCHARSET_FINAL (charset) - '0') * 94))
1162                        >= 0)
1163                       && (d < 94))
1164                     return d + 33;
1165                 }
1166               else if (XCHARSET_CHARS (charset) == 96)
1167                 {
1168                   if (((d = ch - (MIN_CHAR_96
1169                                   + (XCHARSET_FINAL (charset) - '0') * 96))
1170                        >= 0)
1171                       && (d < 96))
1172                     return d + 32;
1173                 }
1174               else
1175                 return -1;
1176             }
1177           else if (XCHARSET_DIMENSION (charset) == 2)
1178             {
1179               if (XCHARSET_CHARS (charset) == 94)
1180                 {
1181                   if (((d = ch - (MIN_CHAR_94x94
1182                                   +
1183                                   (XCHARSET_FINAL (charset) - '0') * 94 * 94))
1184                        >= 0)
1185                       && (d < 94 * 94))
1186                     return (((d / 94) + 33) << 8) | (d % 94 + 33);
1187                 }
1188               else if (XCHARSET_CHARS (charset) == 96)
1189                 {
1190                   if (((d = ch - (MIN_CHAR_96x96
1191                                   +
1192                                   (XCHARSET_FINAL (charset) - '0') * 96 * 96))
1193                        >= 0)
1194                       && (d < 96 * 96))
1195                     return (((d / 96) + 32) << 8) | (d % 96 + 32);
1196                 }
1197               else
1198                 return -1;
1199             }
1200         }
1201     }
1202   return -1;
1203 }
1204
1205 int
1206 encode_builtin_char_1 (Emchar c, Lisp_Object* charset)
1207 {
1208   if (c <= MAX_CHAR_BASIC_LATIN)
1209     {
1210       *charset = Vcharset_ascii;
1211       return c;
1212     }
1213   else if (c < 0xA0)
1214     {
1215       *charset = Vcharset_control_1;
1216       return c & 0x7F;
1217     }
1218   else if (c <= 0xff)
1219     {
1220       *charset = Vcharset_latin_iso8859_1;
1221       return c & 0x7F;
1222     }
1223   /*
1224   else if ((MIN_CHAR_HEBREW <= c) && (c <= MAX_CHAR_HEBREW))
1225     {
1226       *charset = Vcharset_hebrew_iso8859_8;
1227       return c - MIN_CHAR_HEBREW + 0x20;
1228     }
1229   */
1230   else if ((MIN_CHAR_THAI <= c) && (c <= MAX_CHAR_THAI))
1231     {
1232       *charset = Vcharset_thai_tis620;
1233       return c - MIN_CHAR_THAI + 0x20;
1234     }
1235   /*
1236   else if ((MIN_CHAR_HALFWIDTH_KATAKANA <= c)
1237            && (c <= MAX_CHAR_HALFWIDTH_KATAKANA))
1238     {
1239       return list2 (Vcharset_katakana_jisx0201,
1240                     make_int (c - MIN_CHAR_HALFWIDTH_KATAKANA + 33));
1241     }
1242   */
1243   else if (c <= MAX_CHAR_BMP)
1244     {
1245       *charset = Vcharset_ucs_bmp;
1246       return c;
1247     }
1248   else if (c <= MAX_CHAR_SMP)
1249     {
1250       *charset = Vcharset_ucs_smp;
1251       return c - MIN_CHAR_SMP;
1252     }
1253   else if (c <= MAX_CHAR_SIP)
1254     {
1255       *charset = Vcharset_ucs_sip;
1256       return c - MIN_CHAR_SIP;
1257     }
1258   else if (c < MIN_CHAR_DAIKANWA)
1259     {
1260       *charset = Vcharset_ucs;
1261       return c;
1262     }
1263   else if (c <= MAX_CHAR_DAIKANWA)
1264     {
1265       *charset = Vcharset_ideograph_daikanwa;
1266       return c - MIN_CHAR_DAIKANWA;
1267     }
1268   else if (c < MIN_CHAR_94)
1269     {
1270       *charset = Vcharset_ucs;
1271       return c;
1272     }
1273   else if (c <= MAX_CHAR_94)
1274     {
1275       *charset = CHARSET_BY_ATTRIBUTES (94, 1,
1276                                         ((c - MIN_CHAR_94) / 94) + '0',
1277                                         CHARSET_LEFT_TO_RIGHT);
1278       if (!NILP (*charset))
1279         return ((c - MIN_CHAR_94) % 94) + 33;
1280       else
1281         {
1282           *charset = Vcharset_ucs;
1283           return c;
1284         }
1285     }
1286   else if (c <= MAX_CHAR_96)
1287     {
1288       *charset = CHARSET_BY_ATTRIBUTES (96, 1,
1289                                         ((c - MIN_CHAR_96) / 96) + '0',
1290                                         CHARSET_LEFT_TO_RIGHT);
1291       if (!NILP (*charset))
1292         return ((c - MIN_CHAR_96) % 96) + 32;
1293       else
1294         {
1295           *charset = Vcharset_ucs;
1296           return c;
1297         }
1298     }
1299   else if (c <= MAX_CHAR_94x94)
1300     {
1301       *charset
1302         = CHARSET_BY_ATTRIBUTES (94, 2,
1303                                  ((c - MIN_CHAR_94x94) / (94 * 94)) + '0',
1304                                  CHARSET_LEFT_TO_RIGHT);
1305       if (!NILP (*charset))
1306         return (((((c - MIN_CHAR_94x94) / 94) % 94) + 33) << 8)
1307           | (((c - MIN_CHAR_94x94) % 94) + 33);
1308       else
1309         {
1310           *charset = Vcharset_ucs;
1311           return c;
1312         }
1313     }
1314   else if (c <= MAX_CHAR_96x96)
1315     {
1316       *charset
1317         = CHARSET_BY_ATTRIBUTES (96, 2,
1318                                  ((c - MIN_CHAR_96x96) / (96 * 96)) + '0',
1319                                  CHARSET_LEFT_TO_RIGHT);
1320       if (!NILP (*charset))
1321         return ((((c - MIN_CHAR_96x96) / 96) % 96) + 32) << 8
1322           | (((c - MIN_CHAR_96x96) % 96) + 32);
1323       else
1324         {
1325           *charset = Vcharset_ucs;
1326           return c;
1327         }
1328     }
1329   else
1330     {
1331       *charset = Vcharset_ucs;
1332       return c;
1333     }
1334 }
1335
1336 Lisp_Object Vdefault_coded_charset_priority_list;
1337 #endif
1338
1339 \f
1340 /************************************************************************/
1341 /*                      Basic charset Lisp functions                    */
1342 /************************************************************************/
1343
1344 DEFUN ("charsetp", Fcharsetp, 1, 1, 0, /*
1345 Return non-nil if OBJECT is a charset.
1346 */
1347        (object))
1348 {
1349   return CHARSETP (object) ? Qt : Qnil;
1350 }
1351
1352 DEFUN ("find-charset", Ffind_charset, 1, 1, 0, /*
1353 Retrieve the charset of the given name.
1354 If CHARSET-OR-NAME is a charset object, it is simply returned.
1355 Otherwise, CHARSET-OR-NAME should be a symbol.  If there is no such charset,
1356 nil is returned.  Otherwise the associated charset object is returned.
1357 */
1358        (charset_or_name))
1359 {
1360   if (CHARSETP (charset_or_name))
1361     return charset_or_name;
1362
1363   CHECK_SYMBOL (charset_or_name);
1364   return Fgethash (charset_or_name, Vcharset_hash_table, Qnil);
1365 }
1366
1367 DEFUN ("get-charset", Fget_charset, 1, 1, 0, /*
1368 Retrieve the charset of the given name.
1369 Same as `find-charset' except an error is signalled if there is no such
1370 charset instead of returning nil.
1371 */
1372        (name))
1373 {
1374   Lisp_Object charset = Ffind_charset (name);
1375
1376   if (NILP (charset))
1377     signal_simple_error ("No such charset", name);
1378   return charset;
1379 }
1380
1381 /* We store the charsets in hash tables with the names as the key and the
1382    actual charset object as the value.  Occasionally we need to use them
1383    in a list format.  These routines provide us with that. */
1384 struct charset_list_closure
1385 {
1386   Lisp_Object *charset_list;
1387 };
1388
1389 static int
1390 add_charset_to_list_mapper (Lisp_Object key, Lisp_Object value,
1391                             void *charset_list_closure)
1392 {
1393   /* This function can GC */
1394   struct charset_list_closure *chcl =
1395     (struct charset_list_closure*) charset_list_closure;
1396   Lisp_Object *charset_list = chcl->charset_list;
1397
1398   *charset_list = Fcons (key /* XCHARSET_NAME (value) */, *charset_list);
1399   return 0;
1400 }
1401
1402 DEFUN ("charset-list", Fcharset_list, 0, 0, 0, /*
1403 Return a list of the names of all defined charsets.
1404 */
1405        ())
1406 {
1407   Lisp_Object charset_list = Qnil;
1408   struct gcpro gcpro1;
1409   struct charset_list_closure charset_list_closure;
1410
1411   GCPRO1 (charset_list);
1412   charset_list_closure.charset_list = &charset_list;
1413   elisp_maphash (add_charset_to_list_mapper, Vcharset_hash_table,
1414                  &charset_list_closure);
1415   UNGCPRO;
1416
1417   return charset_list;
1418 }
1419
1420 DEFUN ("charset-name", Fcharset_name, 1, 1, 0, /*
1421 Return the name of charset CHARSET.
1422 */
1423        (charset))
1424 {
1425   return XCHARSET_NAME (Fget_charset (charset));
1426 }
1427
1428 /* #### SJT Should generic properties be allowed? */
1429 DEFUN ("make-charset", Fmake_charset, 3, 3, 0, /*
1430 Define a new character set.
1431 This function is for use with Mule support.
1432 NAME is a symbol, the name by which the character set is normally referred.
1433 DOC-STRING is a string describing the character set.
1434 PROPS is a property list, describing the specific nature of the
1435 character set.  Recognized properties are:
1436
1437 'short-name     Short version of the charset name (ex: Latin-1)
1438 'long-name      Long version of the charset name (ex: ISO8859-1 (Latin-1))
1439 'registry       A regular expression matching the font registry field for
1440                 this character set.
1441 'dimension      Number of octets used to index a character in this charset.
1442                 Either 1 or 2.  Defaults to 1.
1443                 If UTF-2000 feature is enabled, 3 or 4 are also available.
1444 'columns        Number of columns used to display a character in this charset.
1445                 Only used in TTY mode. (Under X, the actual width of a
1446                 character can be derived from the font used to display the
1447                 characters.) If unspecified, defaults to the dimension
1448                 (this is almost always the correct value).
1449 'chars          Number of characters in each dimension (94 or 96).
1450                 Defaults to 94.  Note that if the dimension is 2, the
1451                 character set thus described is 94x94 or 96x96.
1452                 If UTF-2000 feature is enabled, 128 or 256 are also available.
1453 'final          Final byte of ISO 2022 escape sequence.  Must be
1454                 supplied.  Each combination of (DIMENSION, CHARS) defines a
1455                 separate namespace for final bytes.  Note that ISO
1456                 2022 restricts the final byte to the range
1457                 0x30 - 0x7E if dimension == 1, and 0x30 - 0x5F if
1458                 dimension == 2.  Note also that final bytes in the range
1459                 0x30 - 0x3F are reserved for user-defined (not official)
1460                 character sets.
1461 'graphic        0 (use left half of font on output) or 1 (use right half
1462                 of font on output).  Defaults to 0.  For example, for
1463                 a font whose registry is ISO8859-1, the left half
1464                 (octets 0x20 - 0x7F) is the `ascii' character set, while
1465                 the right half (octets 0xA0 - 0xFF) is the `latin-1'
1466                 character set.  With 'graphic set to 0, the octets
1467                 will have their high bit cleared; with it set to 1,
1468                 the octets will have their high bit set.
1469 'direction      'l2r (left-to-right) or 'r2l (right-to-left).
1470                 Defaults to 'l2r.
1471 'ccl-program    A compiled CCL program used to convert a character in
1472                 this charset into an index into the font.  This is in
1473                 addition to the 'graphic property.  The CCL program
1474                 is passed the octets of the character, with the high
1475                 bit cleared and set depending upon whether the value
1476                 of the 'graphic property is 0 or 1.
1477 'mother         [UTF-2000 only] Base coded-charset.
1478 'code-min       [UTF-2000 only] Minimum code-point of a base coded-charset.
1479 'code-max       [UTF-2000 only] Maximum code-point of a base coded-charset.
1480 'code-offset    [UTF-2000 only] Offset for a code-point of a base
1481                 coded-charset.
1482 'conversion     [UTF-2000 only] Conversion for a code-point of a base
1483                 coded-charset (94x60 or 94x94x60).
1484 */
1485        (name, doc_string, props))
1486 {
1487   int id, dimension = 1, chars = 94, graphic = 0, final = 0, columns = -1;
1488   int direction = CHARSET_LEFT_TO_RIGHT;
1489   Lisp_Object registry = Qnil;
1490   Lisp_Object charset;
1491   Lisp_Object ccl_program = Qnil;
1492   Lisp_Object short_name = Qnil, long_name = Qnil;
1493   Lisp_Object mother = Qnil;
1494   int min_code = 0, max_code = 0, code_offset = 0;
1495   int byte_offset = -1;
1496   int conversion = 0;
1497
1498   CHECK_SYMBOL (name);
1499   if (!NILP (doc_string))
1500     CHECK_STRING (doc_string);
1501
1502   charset = Ffind_charset (name);
1503   if (!NILP (charset))
1504     signal_simple_error ("Cannot redefine existing charset", name);
1505
1506   {
1507     EXTERNAL_PROPERTY_LIST_LOOP_3 (keyword, value, props)
1508       {
1509         if (EQ (keyword, Qshort_name))
1510           {
1511             CHECK_STRING (value);
1512             short_name = value;
1513           }
1514
1515         if (EQ (keyword, Qlong_name))
1516           {
1517             CHECK_STRING (value);
1518             long_name = value;
1519           }
1520
1521         else if (EQ (keyword, Qdimension))
1522           {
1523             CHECK_INT (value);
1524             dimension = XINT (value);
1525             if (dimension < 1 ||
1526 #ifdef UTF2000
1527                 dimension > 4
1528 #else
1529                 dimension > 2
1530 #endif
1531                 )
1532               signal_simple_error ("Invalid value for 'dimension", value);
1533           }
1534
1535         else if (EQ (keyword, Qchars))
1536           {
1537             CHECK_INT (value);
1538             chars = XINT (value);
1539             if (chars != 94 && chars != 96
1540 #ifdef UTF2000
1541                 && chars != 128 && chars != 256
1542 #endif
1543                 )
1544               signal_simple_error ("Invalid value for 'chars", value);
1545           }
1546
1547         else if (EQ (keyword, Qcolumns))
1548           {
1549             CHECK_INT (value);
1550             columns = XINT (value);
1551             if (columns != 1 && columns != 2)
1552               signal_simple_error ("Invalid value for 'columns", value);
1553           }
1554
1555         else if (EQ (keyword, Qgraphic))
1556           {
1557             CHECK_INT (value);
1558             graphic = XINT (value);
1559             if (graphic < 0 ||
1560 #ifdef UTF2000
1561                 graphic > 2
1562 #else
1563                 graphic > 1
1564 #endif
1565                 )
1566               signal_simple_error ("Invalid value for 'graphic", value);
1567           }
1568
1569         else if (EQ (keyword, Qregistry))
1570           {
1571             CHECK_STRING (value);
1572             registry = value;
1573           }
1574
1575         else if (EQ (keyword, Qdirection))
1576           {
1577             if (EQ (value, Ql2r))
1578               direction = CHARSET_LEFT_TO_RIGHT;
1579             else if (EQ (value, Qr2l))
1580               direction = CHARSET_RIGHT_TO_LEFT;
1581             else
1582               signal_simple_error ("Invalid value for 'direction", value);
1583           }
1584
1585         else if (EQ (keyword, Qfinal))
1586           {
1587             CHECK_CHAR_COERCE_INT (value);
1588             final = XCHAR (value);
1589             if (final < '0' || final > '~')
1590               signal_simple_error ("Invalid value for 'final", value);
1591           }
1592
1593 #ifdef UTF2000
1594         else if (EQ (keyword, Qmother))
1595           {
1596             mother = Fget_charset (value);
1597           }
1598
1599         else if (EQ (keyword, Qmin_code))
1600           {
1601             CHECK_INT (value);
1602             min_code = XUINT (value);
1603           }
1604
1605         else if (EQ (keyword, Qmax_code))
1606           {
1607             CHECK_INT (value);
1608             max_code = XUINT (value);
1609           }
1610
1611         else if (EQ (keyword, Qcode_offset))
1612           {
1613             CHECK_INT (value);
1614             code_offset = XUINT (value);
1615           }
1616
1617         else if (EQ (keyword, Qconversion))
1618           {
1619             if (EQ (value, Q94x60))
1620               conversion = CONVERSION_94x60;
1621             else if (EQ (value, Q94x94x60))
1622               conversion = CONVERSION_94x94x60;
1623             else
1624               signal_simple_error ("Unrecognized conversion", value);
1625           }
1626
1627 #endif
1628         else if (EQ (keyword, Qccl_program))
1629           {
1630             struct ccl_program test_ccl;
1631
1632             if (setup_ccl_program (&test_ccl, value) < 0)
1633               signal_simple_error ("Invalid value for 'ccl-program", value);
1634             ccl_program = value;
1635           }
1636
1637         else
1638           signal_simple_error ("Unrecognized property", keyword);
1639       }
1640   }
1641
1642 #ifndef UTF2000
1643   if (!final)
1644     error ("'final must be specified");
1645 #endif
1646   if (dimension == 2 && final > 0x5F)
1647     signal_simple_error
1648       ("Final must be in the range 0x30 - 0x5F for dimension == 2",
1649        make_char (final));
1650
1651   if (!NILP (CHARSET_BY_ATTRIBUTES (chars, dimension, final,
1652                                     CHARSET_LEFT_TO_RIGHT)) ||
1653       !NILP (CHARSET_BY_ATTRIBUTES (chars, dimension, final,
1654                                     CHARSET_RIGHT_TO_LEFT)))
1655     error
1656       ("Character set already defined for this DIMENSION/CHARS/FINAL combo");
1657
1658   id = get_unallocated_leading_byte (dimension);
1659
1660   if (NILP (doc_string))
1661     doc_string = build_string ("");
1662
1663   if (NILP (registry))
1664     registry = build_string ("");
1665
1666   if (NILP (short_name))
1667     XSETSTRING (short_name, XSYMBOL (name)->name);
1668
1669   if (NILP (long_name))
1670     long_name = doc_string;
1671
1672   if (columns == -1)
1673     columns = dimension;
1674
1675   if (byte_offset < 0)
1676     {
1677       if (chars == 94)
1678         byte_offset = 33;
1679       else if (chars == 96)
1680         byte_offset = 32;
1681       else
1682         byte_offset = 0;
1683     }
1684
1685   charset = make_charset (id, name, chars, dimension, columns, graphic,
1686                           final, direction, short_name, long_name,
1687                           doc_string, registry,
1688                           Qnil, min_code, max_code, code_offset, byte_offset,
1689                           mother, conversion);
1690   if (!NILP (ccl_program))
1691     XCHARSET_CCL_PROGRAM (charset) = ccl_program;
1692   return charset;
1693 }
1694
1695 DEFUN ("make-reverse-direction-charset", Fmake_reverse_direction_charset,
1696        2, 2, 0, /*
1697 Make a charset equivalent to CHARSET but which goes in the opposite direction.
1698 NEW-NAME is the name of the new charset.  Return the new charset.
1699 */
1700        (charset, new_name))
1701 {
1702   Lisp_Object new_charset = Qnil;
1703   int id, chars, dimension, columns, graphic, final;
1704   int direction;
1705   Lisp_Object registry, doc_string, short_name, long_name;
1706   Lisp_Charset *cs;
1707
1708   charset = Fget_charset (charset);
1709   if (!NILP (XCHARSET_REVERSE_DIRECTION_CHARSET (charset)))
1710     signal_simple_error ("Charset already has reverse-direction charset",
1711                          charset);
1712
1713   CHECK_SYMBOL (new_name);
1714   if (!NILP (Ffind_charset (new_name)))
1715     signal_simple_error ("Cannot redefine existing charset", new_name);
1716
1717   cs = XCHARSET (charset);
1718
1719   chars     = CHARSET_CHARS     (cs);
1720   dimension = CHARSET_DIMENSION (cs);
1721   columns   = CHARSET_COLUMNS   (cs);
1722   id = get_unallocated_leading_byte (dimension);
1723
1724   graphic = CHARSET_GRAPHIC (cs);
1725   final = CHARSET_FINAL (cs);
1726   direction = CHARSET_RIGHT_TO_LEFT;
1727   if (CHARSET_DIRECTION (cs) == CHARSET_RIGHT_TO_LEFT)
1728     direction = CHARSET_LEFT_TO_RIGHT;
1729   doc_string = CHARSET_DOC_STRING (cs);
1730   short_name = CHARSET_SHORT_NAME (cs);
1731   long_name = CHARSET_LONG_NAME (cs);
1732   registry = CHARSET_REGISTRY (cs);
1733
1734   new_charset = make_charset (id, new_name, chars, dimension, columns,
1735                               graphic, final, direction, short_name, long_name,
1736                               doc_string, registry,
1737 #ifdef UTF2000
1738                               CHARSET_DECODING_TABLE(cs),
1739                               CHARSET_MIN_CODE(cs),
1740                               CHARSET_MAX_CODE(cs),
1741                               CHARSET_CODE_OFFSET(cs),
1742                               CHARSET_BYTE_OFFSET(cs),
1743                               CHARSET_MOTHER(cs),
1744                               CHARSET_CONVERSION (cs)
1745 #else
1746                               Qnil, 0, 0, 0, 0, Qnil, 0
1747 #endif
1748 );
1749
1750   CHARSET_REVERSE_DIRECTION_CHARSET (cs) = new_charset;
1751   XCHARSET_REVERSE_DIRECTION_CHARSET (new_charset) = charset;
1752
1753   return new_charset;
1754 }
1755
1756 DEFUN ("define-charset-alias", Fdefine_charset_alias, 2, 2, 0, /*
1757 Define symbol ALIAS as an alias for CHARSET.
1758 */
1759        (alias, charset))
1760 {
1761   CHECK_SYMBOL (alias);
1762   charset = Fget_charset (charset);
1763   return Fputhash (alias, charset, Vcharset_hash_table);
1764 }
1765
1766 /* #### Reverse direction charsets not yet implemented.  */
1767 #if 0
1768 DEFUN ("charset-reverse-direction-charset", Fcharset_reverse_direction_charset,
1769        1, 1, 0, /*
1770 Return the reverse-direction charset parallel to CHARSET, if any.
1771 This is the charset with the same properties (in particular, the same
1772 dimension, number of characters per dimension, and final byte) as
1773 CHARSET but whose characters are displayed in the opposite direction.
1774 */
1775        (charset))
1776 {
1777   charset = Fget_charset (charset);
1778   return XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
1779 }
1780 #endif
1781
1782 DEFUN ("charset-from-attributes", Fcharset_from_attributes, 3, 4, 0, /*
1783 Return a charset with the given DIMENSION, CHARS, FINAL, and DIRECTION.
1784 If DIRECTION is omitted, both directions will be checked (left-to-right
1785 will be returned if character sets exist for both directions).
1786 */
1787        (dimension, chars, final, direction))
1788 {
1789   int dm, ch, fi, di = -1;
1790   Lisp_Object obj = Qnil;
1791
1792   CHECK_INT (dimension);
1793   dm = XINT (dimension);
1794   if (dm < 1 || dm > 2)
1795     signal_simple_error ("Invalid value for DIMENSION", dimension);
1796
1797   CHECK_INT (chars);
1798   ch = XINT (chars);
1799   if (ch != 94 && ch != 96)
1800     signal_simple_error ("Invalid value for CHARS", chars);
1801
1802   CHECK_CHAR_COERCE_INT (final);
1803   fi = XCHAR (final);
1804   if (fi < '0' || fi > '~')
1805     signal_simple_error ("Invalid value for FINAL", final);
1806
1807   if (EQ (direction, Ql2r))
1808     di = CHARSET_LEFT_TO_RIGHT;
1809   else if (EQ (direction, Qr2l))
1810     di = CHARSET_RIGHT_TO_LEFT;
1811   else if (!NILP (direction))
1812     signal_simple_error ("Invalid value for DIRECTION", direction);
1813
1814   if (dm == 2 && fi > 0x5F)
1815     signal_simple_error
1816       ("Final must be in the range 0x30 - 0x5F for dimension == 2", final);
1817
1818     if (di == -1)
1819     {
1820       obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, CHARSET_LEFT_TO_RIGHT);
1821       if (NILP (obj))
1822         obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, CHARSET_RIGHT_TO_LEFT);
1823     }
1824   else
1825     obj = CHARSET_BY_ATTRIBUTES (ch, dm, fi, di);
1826
1827   if (CHARSETP (obj))
1828     return XCHARSET_NAME (obj);
1829   return obj;
1830 }
1831
1832 DEFUN ("charset-short-name", Fcharset_short_name, 1, 1, 0, /*
1833 Return short name of CHARSET.
1834 */
1835        (charset))
1836 {
1837   return XCHARSET_SHORT_NAME (Fget_charset (charset));
1838 }
1839
1840 DEFUN ("charset-long-name", Fcharset_long_name, 1, 1, 0, /*
1841 Return long name of CHARSET.
1842 */
1843        (charset))
1844 {
1845   return XCHARSET_LONG_NAME (Fget_charset (charset));
1846 }
1847
1848 DEFUN ("charset-description", Fcharset_description, 1, 1, 0, /*
1849 Return description of CHARSET.
1850 */
1851        (charset))
1852 {
1853   return XCHARSET_DOC_STRING (Fget_charset (charset));
1854 }
1855
1856 DEFUN ("charset-dimension", Fcharset_dimension, 1, 1, 0, /*
1857 Return dimension of CHARSET.
1858 */
1859        (charset))
1860 {
1861   return make_int (XCHARSET_DIMENSION (Fget_charset (charset)));
1862 }
1863
1864 DEFUN ("charset-property", Fcharset_property, 2, 2, 0, /*
1865 Return property PROP of CHARSET, a charset object or symbol naming a charset.
1866 Recognized properties are those listed in `make-charset', as well as
1867 'name and 'doc-string.
1868 */
1869        (charset, prop))
1870 {
1871   Lisp_Charset *cs;
1872
1873   charset = Fget_charset (charset);
1874   cs = XCHARSET (charset);
1875
1876   CHECK_SYMBOL (prop);
1877   if (EQ (prop, Qname))        return CHARSET_NAME (cs);
1878   if (EQ (prop, Qshort_name))  return CHARSET_SHORT_NAME (cs);
1879   if (EQ (prop, Qlong_name))   return CHARSET_LONG_NAME (cs);
1880   if (EQ (prop, Qdoc_string))  return CHARSET_DOC_STRING (cs);
1881   if (EQ (prop, Qdimension))   return make_int (CHARSET_DIMENSION (cs));
1882   if (EQ (prop, Qcolumns))     return make_int (CHARSET_COLUMNS (cs));
1883   if (EQ (prop, Qgraphic))     return make_int (CHARSET_GRAPHIC (cs));
1884   if (EQ (prop, Qfinal))       return CHARSET_FINAL (cs) == 0 ?
1885                                  Qnil : make_char (CHARSET_FINAL (cs));
1886   if (EQ (prop, Qchars))       return make_int (CHARSET_CHARS (cs));
1887   if (EQ (prop, Qregistry))    return CHARSET_REGISTRY (cs);
1888   if (EQ (prop, Qccl_program)) return CHARSET_CCL_PROGRAM (cs);
1889   if (EQ (prop, Qdirection))
1890     return CHARSET_DIRECTION (cs) == CHARSET_LEFT_TO_RIGHT ? Ql2r : Qr2l;
1891   if (EQ (prop, Qreverse_direction_charset))
1892     {
1893       Lisp_Object obj = CHARSET_REVERSE_DIRECTION_CHARSET (cs);
1894       /* #### Is this translation OK?  If so, error checking sufficient? */
1895       return CHARSETP (obj) ? XCHARSET_NAME (obj) : obj;
1896     }
1897 #ifdef UTF2000
1898   if (EQ (prop, Qmother))
1899     return CHARSET_MOTHER (cs);
1900   if (EQ (prop, Qmin_code))
1901     return make_int (CHARSET_MIN_CODE (cs));
1902   if (EQ (prop, Qmax_code))
1903     return make_int (CHARSET_MAX_CODE (cs));
1904 #endif
1905   signal_simple_error ("Unrecognized charset property name", prop);
1906   return Qnil; /* not reached */
1907 }
1908
1909 DEFUN ("charset-id", Fcharset_id, 1, 1, 0, /*
1910 Return charset identification number of CHARSET.
1911 */
1912         (charset))
1913 {
1914   return make_int(XCHARSET_LEADING_BYTE (Fget_charset (charset)));
1915 }
1916
1917 /* #### We need to figure out which properties we really want to
1918    allow to be set. */
1919
1920 DEFUN ("set-charset-ccl-program", Fset_charset_ccl_program, 2, 2, 0, /*
1921 Set the 'ccl-program property of CHARSET to CCL-PROGRAM.
1922 */
1923        (charset, ccl_program))
1924 {
1925   struct ccl_program test_ccl;
1926
1927   charset = Fget_charset (charset);
1928   if (setup_ccl_program (&test_ccl, ccl_program) < 0)
1929     signal_simple_error ("Invalid ccl-program", ccl_program);
1930   XCHARSET_CCL_PROGRAM (charset) = ccl_program;
1931   return Qnil;
1932 }
1933
1934 static void
1935 invalidate_charset_font_caches (Lisp_Object charset)
1936 {
1937   /* Invalidate font cache entries for charset on all devices. */
1938   Lisp_Object devcons, concons, hash_table;
1939   DEVICE_LOOP_NO_BREAK (devcons, concons)
1940     {
1941       struct device *d = XDEVICE (XCAR (devcons));
1942       hash_table = Fgethash (charset, d->charset_font_cache, Qunbound);
1943       if (!UNBOUNDP (hash_table))
1944         Fclrhash (hash_table);
1945     }
1946 }
1947
1948 DEFUN ("set-charset-registry", Fset_charset_registry, 2, 2, 0, /*
1949 Set the 'registry property of CHARSET to REGISTRY.
1950 */
1951        (charset, registry))
1952 {
1953   charset = Fget_charset (charset);
1954   CHECK_STRING (registry);
1955   XCHARSET_REGISTRY (charset) = registry;
1956   invalidate_charset_font_caches (charset);
1957   face_property_was_changed (Vdefault_face, Qfont, Qglobal);
1958   return Qnil;
1959 }
1960
1961 #ifdef UTF2000
1962 DEFUN ("charset-mapping-table", Fcharset_mapping_table, 1, 1, 0, /*
1963 Return mapping-table of CHARSET.
1964 */
1965        (charset))
1966 {
1967   return XCHARSET_DECODING_TABLE (Fget_charset (charset));
1968 }
1969
1970 DEFUN ("set-charset-mapping-table", Fset_charset_mapping_table, 2, 2, 0, /*
1971 Set mapping-table of CHARSET to TABLE.
1972 */
1973        (charset, table))
1974 {
1975   struct Lisp_Charset *cs;
1976   size_t i;
1977   int byte_offset;
1978
1979   charset = Fget_charset (charset);
1980   cs = XCHARSET (charset);
1981
1982   if (NILP (table))
1983     {
1984       CHARSET_DECODING_TABLE(cs) = Qnil;
1985       return table;
1986     }
1987   else if (VECTORP (table))
1988     {
1989       int ccs_len = CHARSET_BYTE_SIZE (cs);
1990       int ret = decoding_table_check_elements (table,
1991                                                CHARSET_DIMENSION (cs),
1992                                                ccs_len);
1993       if (ret)
1994         {
1995           if (ret == -1)
1996             signal_simple_error ("Too big table", table);
1997           else if (ret == -2)
1998             signal_simple_error ("Invalid element is found", table);
1999           else
2000             signal_simple_error ("Something wrong", table);
2001         }
2002       CHARSET_DECODING_TABLE(cs) = Qnil;
2003     }
2004   else
2005     signal_error (Qwrong_type_argument,
2006                   list2 (build_translated_string ("vector-or-nil-p"),
2007                          table));
2008
2009   byte_offset = CHARSET_BYTE_OFFSET (cs);
2010   switch (CHARSET_DIMENSION (cs))
2011     {
2012     case 1:
2013       for (i = 0; i < XVECTOR_LENGTH (table); i++)
2014         {
2015           Lisp_Object c = XVECTOR_DATA(table)[i];
2016
2017           if (CHARP (c))
2018             Fput_char_attribute (c, XCHARSET_NAME (charset),
2019                                  make_int (i + byte_offset));
2020         }
2021       break;
2022     case 2:
2023       for (i = 0; i < XVECTOR_LENGTH (table); i++)
2024         {
2025           Lisp_Object v = XVECTOR_DATA(table)[i];
2026
2027           if (VECTORP (v))
2028             {
2029               size_t j;
2030
2031               for (j = 0; j < XVECTOR_LENGTH (v); j++)
2032                 {
2033                   Lisp_Object c = XVECTOR_DATA(v)[j];
2034
2035                   if (CHARP (c))
2036                     Fput_char_attribute
2037                       (c, XCHARSET_NAME (charset),
2038                        make_int ( ( (i + byte_offset) << 8 )
2039                                   | (j + byte_offset)
2040                                   ) );
2041                 }
2042             }
2043           else if (CHARP (v))
2044             Fput_char_attribute (v, XCHARSET_NAME (charset),
2045                                  make_int (i + byte_offset));
2046         }
2047       break;
2048     }
2049   return table;
2050 }
2051 #endif
2052
2053 \f
2054 /************************************************************************/
2055 /*              Lisp primitives for working with characters             */
2056 /************************************************************************/
2057
2058 #ifdef UTF2000
2059 DEFUN ("decode-char", Fdecode_char, 2, 3, 0, /*
2060 Make a character from CHARSET and code-point CODE.
2061 If DEFINED_ONLY is non-nil, builtin character is not returned.
2062 If corresponding character is not found, nil is returned.
2063 */
2064        (charset, code, defined_only))
2065 {
2066   int c;
2067
2068   charset = Fget_charset (charset);
2069   CHECK_INT (code);
2070   c = XINT (code);
2071   if (XCHARSET_GRAPHIC (charset) == 1)
2072     c &= 0x7F7F7F7F;
2073   if (NILP (defined_only))
2074     c = DECODE_CHAR (charset, c);
2075   else
2076     c = DECODE_DEFINED_CHAR (charset, c);
2077   return c >= 0 ? make_char (c) : Qnil;
2078 }
2079
2080 DEFUN ("decode-builtin-char", Fdecode_builtin_char, 2, 2, 0, /*
2081 Make a builtin character from CHARSET and code-point CODE.
2082 */
2083        (charset, code))
2084 {
2085   int c;
2086
2087   charset = Fget_charset (charset);
2088   CHECK_INT (code);
2089   if (EQ (charset, Vcharset_latin_viscii))
2090     {
2091       Lisp_Object chr = Fdecode_char (charset, code, Qnil);
2092       Lisp_Object ret;
2093
2094       if (!NILP (chr))
2095         {
2096           if (!NILP
2097               (ret = Fget_char_attribute (chr,
2098                                           Vcharset_latin_viscii_lower,
2099                                           Qnil)))
2100             {
2101               charset = Vcharset_latin_viscii_lower;
2102               code = ret;
2103             }
2104           else if (!NILP
2105                    (ret = Fget_char_attribute (chr,
2106                                                Vcharset_latin_viscii_upper,
2107                                                Qnil)))
2108             {
2109               charset = Vcharset_latin_viscii_upper;
2110               code = ret;
2111             }
2112         }
2113     }
2114   c = XINT (code);
2115 #if 0
2116   if (XCHARSET_GRAPHIC (charset) == 1)
2117     c &= 0x7F7F7F7F;
2118 #endif
2119   c = decode_builtin_char (charset, c);
2120   return c >= 0 ? make_char (c) : Fdecode_char (charset, code, Qnil);
2121 }
2122 #endif
2123
2124 DEFUN ("make-char", Fmake_char, 2, 3, 0, /*
2125 Make a character from CHARSET and octets ARG1 and ARG2.
2126 ARG2 is required only for characters from two-dimensional charsets.
2127 For example, (make-char 'latin-iso8859-2 185) will return the Latin 2
2128 character s with caron.
2129 */
2130        (charset, arg1, arg2))
2131 {
2132   Lisp_Charset *cs;
2133   int a1, a2;
2134   int lowlim, highlim;
2135
2136   charset = Fget_charset (charset);
2137   cs = XCHARSET (charset);
2138
2139   if      (EQ (charset, Vcharset_ascii))     lowlim =  0, highlim = 127;
2140   else if (EQ (charset, Vcharset_control_1)) lowlim =  0, highlim =  31;
2141 #ifdef UTF2000
2142   else if (CHARSET_CHARS (cs) == 256)        lowlim =  0, highlim = 255;
2143 #endif
2144   else if (CHARSET_CHARS (cs) == 94)         lowlim = 33, highlim = 126;
2145   else  /* CHARSET_CHARS (cs) == 96) */      lowlim = 32, highlim = 127;
2146
2147   CHECK_INT (arg1);
2148   /* It is useful (and safe, according to Olivier Galibert) to strip
2149      the 8th bit off ARG1 and ARG2 because it allows programmers to
2150      write (make-char 'latin-iso8859-2 CODE) where code is the actual
2151      Latin 2 code of the character.  */
2152 #ifdef UTF2000
2153   a1 = XINT (arg1);
2154   if (highlim < 128)
2155     a1 &= 0x7f;
2156 #else
2157   a1 = XINT (arg1);
2158 #endif
2159   if (a1 < lowlim || a1 > highlim)
2160     args_out_of_range_3 (arg1, make_int (lowlim), make_int (highlim));
2161
2162   if (CHARSET_DIMENSION (cs) == 1)
2163     {
2164       if (!NILP (arg2))
2165         signal_simple_error
2166           ("Charset is of dimension one; second octet must be nil", arg2);
2167       return make_char (MAKE_CHAR (charset, a1, 0));
2168     }
2169
2170   CHECK_INT (arg2);
2171 #ifdef UTF2000
2172   a2 = XINT (arg2);
2173   if (highlim < 128)
2174     a2 &= 0x7f;
2175 #else
2176   a2 = XINT (arg2) & 0x7f;
2177 #endif
2178   if (a2 < lowlim || a2 > highlim)
2179     args_out_of_range_3 (arg2, make_int (lowlim), make_int (highlim));
2180
2181   return make_char (MAKE_CHAR (charset, a1, a2));
2182 }
2183
2184 DEFUN ("char-charset", Fchar_charset, 1, 1, 0, /*
2185 Return the character set of CHARACTER.
2186 */
2187        (character))
2188 {
2189   CHECK_CHAR_COERCE_INT (character);
2190
2191   return XCHARSET_NAME (CHAR_CHARSET (XCHAR (character)));
2192 }
2193
2194 DEFUN ("char-octet", Fchar_octet, 1, 2, 0, /*
2195 Return the octet numbered N (should be 0 or 1) of CHARACTER.
2196 N defaults to 0 if omitted.
2197 */
2198        (character, n))
2199 {
2200   Lisp_Object charset;
2201   int octet0, octet1;
2202
2203   CHECK_CHAR_COERCE_INT (character);
2204
2205   BREAKUP_CHAR (XCHAR (character), charset, octet0, octet1);
2206
2207   if (NILP (n) || EQ (n, Qzero))
2208     return make_int (octet0);
2209   else if (EQ (n, make_int (1)))
2210     return make_int (octet1);
2211   else
2212     signal_simple_error ("Octet number must be 0 or 1", n);
2213 }
2214
2215 #ifdef UTF2000
2216 DEFUN ("encode-char", Fencode_char, 2, 2, 0, /*
2217 Return code-point of CHARACTER in specified CHARSET.
2218 */
2219        (character, charset))
2220 {
2221   int code_point;
2222
2223   CHECK_CHAR_COERCE_INT (character);
2224   charset = Fget_charset (charset);
2225   code_point = charset_code_point (charset, XCHAR (character));
2226   if (code_point >= 0)
2227     return make_int (code_point);
2228   else
2229     return Qnil;
2230 }
2231 #endif
2232
2233 DEFUN ("split-char", Fsplit_char, 1, 1, 0, /*
2234 Return list of charset and one or two position-codes of CHARACTER.
2235 */
2236        (character))
2237 {
2238   /* This function can GC */
2239   struct gcpro gcpro1, gcpro2;
2240   Lisp_Object charset = Qnil;
2241   Lisp_Object rc = Qnil;
2242 #ifdef UTF2000
2243   int code_point;
2244   int dimension;
2245 #else
2246   int c1, c2;
2247 #endif
2248
2249   GCPRO2 (charset, rc);
2250   CHECK_CHAR_COERCE_INT (character);
2251
2252 #ifdef UTF2000
2253   code_point = ENCODE_CHAR (XCHAR (character), charset);
2254   dimension = XCHARSET_DIMENSION (charset);
2255   while (dimension > 0)
2256     {
2257       rc = Fcons (make_int (code_point & 255), rc);
2258       code_point >>= 8;
2259       dimension--;
2260     }
2261   rc = Fcons (XCHARSET_NAME (charset), rc);
2262 #else
2263   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
2264
2265   if (XCHARSET_DIMENSION (Fget_charset (charset)) == 2)
2266     {
2267       rc = list3 (XCHARSET_NAME (charset), make_int (c1), make_int (c2));
2268     }
2269   else
2270     {
2271       rc = list2 (XCHARSET_NAME (charset), make_int (c1));
2272     }
2273 #endif
2274   UNGCPRO;
2275
2276   return rc;
2277 }
2278
2279 \f
2280 #ifdef ENABLE_COMPOSITE_CHARS
2281 /************************************************************************/
2282 /*                     composite character functions                    */
2283 /************************************************************************/
2284
2285 Emchar
2286 lookup_composite_char (Bufbyte *str, int len)
2287 {
2288   Lisp_Object lispstr = make_string (str, len);
2289   Lisp_Object ch = Fgethash (lispstr,
2290                              Vcomposite_char_string2char_hash_table,
2291                              Qunbound);
2292   Emchar emch;
2293
2294   if (UNBOUNDP (ch))
2295     {
2296       if (composite_char_row_next >= 128)
2297         signal_simple_error ("No more composite chars available", lispstr);
2298       emch = MAKE_CHAR (Vcharset_composite, composite_char_row_next,
2299                         composite_char_col_next);
2300       Fputhash (make_char (emch), lispstr,
2301                 Vcomposite_char_char2string_hash_table);
2302       Fputhash (lispstr, make_char (emch),
2303                 Vcomposite_char_string2char_hash_table);
2304       composite_char_col_next++;
2305       if (composite_char_col_next >= 128)
2306         {
2307           composite_char_col_next = 32;
2308           composite_char_row_next++;
2309         }
2310     }
2311   else
2312     emch = XCHAR (ch);
2313   return emch;
2314 }
2315
2316 Lisp_Object
2317 composite_char_string (Emchar ch)
2318 {
2319   Lisp_Object str = Fgethash (make_char (ch),
2320                               Vcomposite_char_char2string_hash_table,
2321                               Qunbound);
2322   assert (!UNBOUNDP (str));
2323   return str;
2324 }
2325
2326 xxDEFUN ("make-composite-char", Fmake_composite_char, 1, 1, 0, /*
2327 Convert a string into a single composite character.
2328 The character is the result of overstriking all the characters in
2329 the string.
2330 */
2331        (string))
2332 {
2333   CHECK_STRING (string);
2334   return make_char (lookup_composite_char (XSTRING_DATA (string),
2335                                            XSTRING_LENGTH (string)));
2336 }
2337
2338 xxDEFUN ("composite-char-string", Fcomposite_char_string, 1, 1, 0, /*
2339 Return a string of the characters comprising a composite character.
2340 */
2341        (ch))
2342 {
2343   Emchar emch;
2344
2345   CHECK_CHAR (ch);
2346   emch = XCHAR (ch);
2347   if (CHAR_LEADING_BYTE (emch) != LEADING_BYTE_COMPOSITE)
2348     signal_simple_error ("Must be composite char", ch);
2349   return composite_char_string (emch);
2350 }
2351 #endif /* ENABLE_COMPOSITE_CHARS */
2352
2353 \f
2354 /************************************************************************/
2355 /*                            initialization                            */
2356 /************************************************************************/
2357
2358 void
2359 syms_of_mule_charset (void)
2360 {
2361   INIT_LRECORD_IMPLEMENTATION (charset);
2362
2363   DEFSUBR (Fcharsetp);
2364   DEFSUBR (Ffind_charset);
2365   DEFSUBR (Fget_charset);
2366   DEFSUBR (Fcharset_list);
2367   DEFSUBR (Fcharset_name);
2368   DEFSUBR (Fmake_charset);
2369   DEFSUBR (Fmake_reverse_direction_charset);
2370   /*  DEFSUBR (Freverse_direction_charset); */
2371   DEFSUBR (Fdefine_charset_alias);
2372   DEFSUBR (Fcharset_from_attributes);
2373   DEFSUBR (Fcharset_short_name);
2374   DEFSUBR (Fcharset_long_name);
2375   DEFSUBR (Fcharset_description);
2376   DEFSUBR (Fcharset_dimension);
2377   DEFSUBR (Fcharset_property);
2378   DEFSUBR (Fcharset_id);
2379   DEFSUBR (Fset_charset_ccl_program);
2380   DEFSUBR (Fset_charset_registry);
2381 #ifdef UTF2000
2382   DEFSUBR (Fcharset_mapping_table);
2383   DEFSUBR (Fset_charset_mapping_table);
2384 #endif
2385
2386 #ifdef UTF2000
2387   DEFSUBR (Fdecode_char);
2388   DEFSUBR (Fdecode_builtin_char);
2389   DEFSUBR (Fencode_char);
2390 #endif
2391   DEFSUBR (Fmake_char);
2392   DEFSUBR (Fchar_charset);
2393   DEFSUBR (Fchar_octet);
2394   DEFSUBR (Fsplit_char);
2395
2396 #ifdef ENABLE_COMPOSITE_CHARS
2397   DEFSUBR (Fmake_composite_char);
2398   DEFSUBR (Fcomposite_char_string);
2399 #endif
2400
2401   defsymbol (&Qcharsetp, "charsetp");
2402   defsymbol (&Qregistry, "registry");
2403   defsymbol (&Qfinal, "final");
2404   defsymbol (&Qgraphic, "graphic");
2405   defsymbol (&Qdirection, "direction");
2406   defsymbol (&Qreverse_direction_charset, "reverse-direction-charset");
2407   defsymbol (&Qshort_name, "short-name");
2408   defsymbol (&Qlong_name, "long-name");
2409 #ifdef UTF2000
2410   defsymbol (&Qmother, "mother");
2411   defsymbol (&Qmin_code, "min-code");
2412   defsymbol (&Qmax_code, "max-code");
2413   defsymbol (&Qcode_offset, "code-offset");
2414   defsymbol (&Qconversion, "conversion");
2415   defsymbol (&Q94x60, "94x60");
2416   defsymbol (&Q94x94x60, "94x94x60");
2417 #endif
2418
2419   defsymbol (&Ql2r, "l2r");
2420   defsymbol (&Qr2l, "r2l");
2421
2422   /* Charsets, compatible with FSF 20.3
2423      Naming convention is Script-Charset[-Edition] */
2424   defsymbol (&Qascii,                   "ascii");
2425   defsymbol (&Qcontrol_1,               "control-1");
2426   defsymbol (&Qlatin_iso8859_1,         "latin-iso8859-1");
2427   defsymbol (&Qlatin_iso8859_2,         "latin-iso8859-2");
2428   defsymbol (&Qlatin_iso8859_3,         "latin-iso8859-3");
2429   defsymbol (&Qlatin_iso8859_4,         "latin-iso8859-4");
2430   defsymbol (&Qthai_tis620,             "thai-tis620");
2431   defsymbol (&Qgreek_iso8859_7,         "greek-iso8859-7");
2432   defsymbol (&Qarabic_iso8859_6,        "arabic-iso8859-6");
2433   defsymbol (&Qhebrew_iso8859_8,        "hebrew-iso8859-8");
2434   defsymbol (&Qkatakana_jisx0201,       "katakana-jisx0201");
2435   defsymbol (&Qlatin_jisx0201,          "latin-jisx0201");
2436   defsymbol (&Qcyrillic_iso8859_5,      "cyrillic-iso8859-5");
2437   defsymbol (&Qlatin_iso8859_9,         "latin-iso8859-9");
2438   defsymbol (&Qjapanese_jisx0208_1978,  "japanese-jisx0208-1978");
2439   defsymbol (&Qchinese_gb2312,          "chinese-gb2312");
2440   defsymbol (&Qchinese_gb12345,         "chinese-gb12345");
2441   defsymbol (&Qjapanese_jisx0208,       "japanese-jisx0208");
2442   defsymbol (&Qjapanese_jisx0208_1990,  "japanese-jisx0208-1990");
2443   defsymbol (&Qkorean_ksc5601,          "korean-ksc5601");
2444   defsymbol (&Qjapanese_jisx0212,       "japanese-jisx0212");
2445   defsymbol (&Qchinese_cns11643_1,      "chinese-cns11643-1");
2446   defsymbol (&Qchinese_cns11643_2,      "chinese-cns11643-2");
2447 #ifdef UTF2000
2448   defsymbol (&Qucs,                     "ucs");
2449   defsymbol (&Qucs_bmp,                 "ucs-bmp");
2450   defsymbol (&Qucs_smp,                 "ucs-smp");
2451   defsymbol (&Qucs_sip,                 "ucs-sip");
2452   defsymbol (&Qucs_cns,                 "ucs-cns");
2453   defsymbol (&Qucs_jis,                 "ucs-jis");
2454   defsymbol (&Qucs_ks,                  "ucs-ks");
2455   defsymbol (&Qucs_big5,                "ucs-big5");
2456   defsymbol (&Qlatin_viscii,            "latin-viscii");
2457   defsymbol (&Qlatin_tcvn5712,          "latin-tcvn5712");
2458   defsymbol (&Qlatin_viscii_lower,      "latin-viscii-lower");
2459   defsymbol (&Qlatin_viscii_upper,      "latin-viscii-upper");
2460   defsymbol (&Qvietnamese_viscii_lower, "vietnamese-viscii-lower");
2461   defsymbol (&Qvietnamese_viscii_upper, "vietnamese-viscii-upper");
2462   defsymbol (&Qideograph_gt,            "ideograph-gt");
2463   defsymbol (&Qideograph_gt_pj_1,       "ideograph-gt-pj-1");
2464   defsymbol (&Qideograph_gt_pj_2,       "ideograph-gt-pj-2");
2465   defsymbol (&Qideograph_gt_pj_3,       "ideograph-gt-pj-3");
2466   defsymbol (&Qideograph_gt_pj_4,       "ideograph-gt-pj-4");
2467   defsymbol (&Qideograph_gt_pj_5,       "ideograph-gt-pj-5");
2468   defsymbol (&Qideograph_gt_pj_6,       "ideograph-gt-pj-6");
2469   defsymbol (&Qideograph_gt_pj_7,       "ideograph-gt-pj-7");
2470   defsymbol (&Qideograph_gt_pj_8,       "ideograph-gt-pj-8");
2471   defsymbol (&Qideograph_gt_pj_9,       "ideograph-gt-pj-9");
2472   defsymbol (&Qideograph_gt_pj_10,      "ideograph-gt-pj-10");
2473   defsymbol (&Qideograph_gt_pj_11,      "ideograph-gt-pj-11");
2474   defsymbol (&Qideograph_daikanwa_2,    "ideograph-daikanwa-2");
2475   defsymbol (&Qideograph_daikanwa,      "ideograph-daikanwa");
2476   defsymbol (&Qchinese_big5,            "chinese-big5");
2477   defsymbol (&Qchinese_big5_cdp,        "chinese-big5-cdp");
2478   defsymbol (&Qideograph_hanziku_1,     "ideograph-hanziku-1");
2479   defsymbol (&Qideograph_hanziku_2,     "ideograph-hanziku-2");
2480   defsymbol (&Qideograph_hanziku_3,     "ideograph-hanziku-3");
2481   defsymbol (&Qideograph_hanziku_4,     "ideograph-hanziku-4");
2482   defsymbol (&Qideograph_hanziku_5,     "ideograph-hanziku-5");
2483   defsymbol (&Qideograph_hanziku_6,     "ideograph-hanziku-6");
2484   defsymbol (&Qideograph_hanziku_7,     "ideograph-hanziku-7");
2485   defsymbol (&Qideograph_hanziku_8,     "ideograph-hanziku-8");
2486   defsymbol (&Qideograph_hanziku_9,     "ideograph-hanziku-9");
2487   defsymbol (&Qideograph_hanziku_10,    "ideograph-hanziku-10");
2488   defsymbol (&Qideograph_hanziku_11,    "ideograph-hanziku-11");
2489   defsymbol (&Qideograph_hanziku_12,    "ideograph-hanziku-12");
2490   defsymbol (&Qchina3_jef,              "china3-jef");
2491   defsymbol (&Qideograph_cbeta,         "ideograph-cbeta");
2492   defsymbol (&Qethiopic_ucs,            "ethiopic-ucs");
2493 #endif
2494   defsymbol (&Qchinese_big5_1,          "chinese-big5-1");
2495   defsymbol (&Qchinese_big5_2,          "chinese-big5-2");
2496
2497   defsymbol (&Qcomposite,               "composite");
2498 }
2499
2500 void
2501 vars_of_mule_charset (void)
2502 {
2503   int i, j;
2504 #ifndef UTF2000
2505   int k;
2506 #endif
2507
2508   chlook = xnew_and_zero (struct charset_lookup); /* zero for Purify. */
2509   dump_add_root_struct_ptr (&chlook, &charset_lookup_description);
2510
2511   /* Table of charsets indexed by leading byte. */
2512   for (i = 0; i < countof (chlook->charset_by_leading_byte); i++)
2513     chlook->charset_by_leading_byte[i] = Qnil;
2514
2515 #ifdef UTF2000
2516   /* Table of charsets indexed by type/final-byte. */
2517   for (i = 0; i < countof (chlook->charset_by_attributes); i++)
2518     for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
2519       chlook->charset_by_attributes[i][j] = Qnil;
2520 #else
2521   /* Table of charsets indexed by type/final-byte/direction. */
2522   for (i = 0; i < countof (chlook->charset_by_attributes); i++)
2523     for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++)
2524       for (k = 0; k < countof (chlook->charset_by_attributes[0][0]); k++)
2525         chlook->charset_by_attributes[i][j][k] = Qnil;
2526 #endif
2527
2528 #ifdef UTF2000
2529   chlook->next_allocated_leading_byte = MIN_LEADING_BYTE_PRIVATE;
2530 #else
2531   chlook->next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1;
2532   chlook->next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2;
2533 #endif
2534
2535 #ifndef UTF2000
2536   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2537   DEFVAR_INT ("leading-code-private-11", &leading_code_private_11 /*
2538 Leading-code of private TYPE9N charset of column-width 1.
2539 */ );
2540   leading_code_private_11 = PRE_LEADING_BYTE_PRIVATE_1;
2541 #endif
2542
2543 #ifdef UTF2000
2544   Vdefault_coded_charset_priority_list = Qnil;
2545   DEFVAR_LISP ("default-coded-charset-priority-list",
2546                &Vdefault_coded_charset_priority_list /*
2547 Default order of preferred coded-character-sets.
2548 */ );
2549 #endif
2550 }
2551
2552 void
2553 complex_vars_of_mule_charset (void)
2554 {
2555   staticpro (&Vcharset_hash_table);
2556   Vcharset_hash_table =
2557     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
2558
2559   /* Predefined character sets.  We store them into variables for
2560      ease of access. */
2561
2562 #ifdef UTF2000
2563   staticpro (&Vcharset_ucs);
2564   Vcharset_ucs =
2565     make_charset (LEADING_BYTE_UCS, Qucs, 256, 4,
2566                   1, 2, 0, CHARSET_LEFT_TO_RIGHT,
2567                   build_string ("UCS"),
2568                   build_string ("UCS"),
2569                   build_string ("ISO/IEC 10646"),
2570                   build_string (""),
2571                   Qnil, 0, 0xFFFFFFF, 0, 0, Qnil, CONVERSION_IDENTICAL);
2572   staticpro (&Vcharset_ucs_bmp);
2573   Vcharset_ucs_bmp =
2574     make_charset (LEADING_BYTE_UCS_BMP, Qucs_bmp, 256, 2,
2575                   1, 2, 0, CHARSET_LEFT_TO_RIGHT,
2576                   build_string ("BMP"),
2577                   build_string ("UCS-BMP"),
2578                   build_string ("ISO/IEC 10646 Group 0 Plane 0 (BMP)"),
2579                   build_string
2580                   ("\\(ISO10646.*-[01]\\|UCS00-0\\|UNICODE[23]?-0\\)"),
2581                   Qnil, 0, 0xFFFF, 0, 0, Qnil, CONVERSION_IDENTICAL);
2582   staticpro (&Vcharset_ucs_smp);
2583   Vcharset_ucs_smp =
2584     make_charset (LEADING_BYTE_UCS_SMP, Qucs_smp, 256, 2,
2585                   1, 2, 0, CHARSET_LEFT_TO_RIGHT,
2586                   build_string ("SMP"),
2587                   build_string ("UCS-SMP"),
2588                   build_string ("ISO/IEC 10646 Group 0 Plane 1 (SMP)"),
2589                   build_string ("UCS00-1"),
2590                   Qnil, MIN_CHAR_SMP, MAX_CHAR_SMP,
2591                   MIN_CHAR_SMP, 0, Qnil, CONVERSION_IDENTICAL);
2592   staticpro (&Vcharset_ucs_sip);
2593   Vcharset_ucs_sip =
2594     make_charset (LEADING_BYTE_UCS_SIP, Qucs_sip, 256, 2,
2595                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2596                   build_string ("SIP"),
2597                   build_string ("UCS-SIP"),
2598                   build_string ("ISO/IEC 10646 Group 0 Plane 2 (SIP)"),
2599                   build_string ("\\(ISO10646.*-2\\|UCS00-2\\)"),
2600                   Qnil, MIN_CHAR_SIP, MAX_CHAR_SIP,
2601                   MIN_CHAR_SIP, 0, Qnil, CONVERSION_IDENTICAL);
2602   staticpro (&Vcharset_ucs_cns);
2603   Vcharset_ucs_cns =
2604     make_charset (LEADING_BYTE_UCS_CNS, Qucs_cns, 256, 3,
2605                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2606                   build_string ("UCS for CNS"),
2607                   build_string ("UCS for CNS 11643"),
2608                   build_string ("ISO/IEC 10646 for CNS 11643"),
2609                   build_string (""),
2610                   Qnil, 0, 0, 0, 0,
2611                   Qnil, CONVERSION_IDENTICAL);
2612   staticpro (&Vcharset_ucs_jis);
2613   Vcharset_ucs_jis =
2614     make_charset (LEADING_BYTE_UCS_JIS, Qucs_jis, 256, 3,
2615                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2616                   build_string ("UCS for JIS"),
2617                   build_string ("UCS for JIS X 0208, 0212 and 0213"),
2618                   build_string ("ISO/IEC 10646 for JIS X 0208, 0212 and 0213"),
2619                   build_string (""),
2620                   Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL);
2621   staticpro (&Vcharset_ucs_ks);
2622   Vcharset_ucs_ks =
2623     make_charset (LEADING_BYTE_UCS_KS, Qucs_ks, 256, 3,
2624                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2625                   build_string ("UCS for KS"),
2626                   build_string ("UCS for CCS defined by KS"),
2627                   build_string ("ISO/IEC 10646 for Korean Standards"),
2628                   build_string (""),
2629                   Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL);
2630   staticpro (&Vcharset_ucs_big5);
2631   Vcharset_ucs_big5 =
2632     make_charset (LEADING_BYTE_UCS_BIG5, Qucs_big5, 256, 3,
2633                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2634                   build_string ("UCS for Big5"),
2635                   build_string ("UCS for Big5"),
2636                   build_string ("ISO/IEC 10646 for Big5"),
2637                   build_string (""),
2638                   Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL);
2639 #else
2640 # define MIN_CHAR_THAI 0
2641 # define MAX_CHAR_THAI 0
2642   /* # define MIN_CHAR_HEBREW 0 */
2643   /* # define MAX_CHAR_HEBREW 0 */
2644 # define MIN_CHAR_HALFWIDTH_KATAKANA 0
2645 # define MAX_CHAR_HALFWIDTH_KATAKANA 0
2646 #endif
2647   staticpro (&Vcharset_ascii);
2648   Vcharset_ascii =
2649     make_charset (LEADING_BYTE_ASCII, Qascii, 94, 1,
2650                   1, 0, 'B', CHARSET_LEFT_TO_RIGHT,
2651                   build_string ("ASCII"),
2652                   build_string ("ASCII)"),
2653                   build_string ("ASCII (ISO646 IRV)"),
2654                   build_string ("\\(iso8859-[0-9]*\\|-ascii\\)"),
2655                   Qnil, 0, 0x7F, 0, 0, Qnil, CONVERSION_IDENTICAL);
2656   staticpro (&Vcharset_control_1);
2657   Vcharset_control_1 =
2658     make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1, 94, 1,
2659                   1, 1, 0, CHARSET_LEFT_TO_RIGHT,
2660                   build_string ("C1"),
2661                   build_string ("Control characters"),
2662                   build_string ("Control characters 128-191"),
2663                   build_string (""),
2664                   Qnil, 0x80, 0x9F, 0x80, 0, Qnil, CONVERSION_IDENTICAL);
2665   staticpro (&Vcharset_latin_iso8859_1);
2666   Vcharset_latin_iso8859_1 =
2667     make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1, 96, 1,
2668                   1, 1, 'A', CHARSET_LEFT_TO_RIGHT,
2669                   build_string ("Latin-1"),
2670                   build_string ("ISO8859-1 (Latin-1)"),
2671                   build_string ("ISO8859-1 (Latin-1)"),
2672                   build_string ("iso8859-1"),
2673                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2674   staticpro (&Vcharset_latin_iso8859_2);
2675   Vcharset_latin_iso8859_2 =
2676     make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2, 96, 1,
2677                   1, 1, 'B', CHARSET_LEFT_TO_RIGHT,
2678                   build_string ("Latin-2"),
2679                   build_string ("ISO8859-2 (Latin-2)"),
2680                   build_string ("ISO8859-2 (Latin-2)"),
2681                   build_string ("iso8859-2"),
2682                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2683   staticpro (&Vcharset_latin_iso8859_3);
2684   Vcharset_latin_iso8859_3 =
2685     make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3, 96, 1,
2686                   1, 1, 'C', CHARSET_LEFT_TO_RIGHT,
2687                   build_string ("Latin-3"),
2688                   build_string ("ISO8859-3 (Latin-3)"),
2689                   build_string ("ISO8859-3 (Latin-3)"),
2690                   build_string ("iso8859-3"),
2691                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2692   staticpro (&Vcharset_latin_iso8859_4);
2693   Vcharset_latin_iso8859_4 =
2694     make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4, 96, 1,
2695                   1, 1, 'D', CHARSET_LEFT_TO_RIGHT,
2696                   build_string ("Latin-4"),
2697                   build_string ("ISO8859-4 (Latin-4)"),
2698                   build_string ("ISO8859-4 (Latin-4)"),
2699                   build_string ("iso8859-4"),
2700                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2701   staticpro (&Vcharset_thai_tis620);
2702   Vcharset_thai_tis620 =
2703     make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620, 96, 1,
2704                   1, 1, 'T', CHARSET_LEFT_TO_RIGHT,
2705                   build_string ("TIS620"),
2706                   build_string ("TIS620 (Thai)"),
2707                   build_string ("TIS620.2529 (Thai)"),
2708                   build_string ("tis620"),
2709                   Qnil, MIN_CHAR_THAI, MAX_CHAR_THAI,
2710                   MIN_CHAR_THAI, 32, Qnil, CONVERSION_IDENTICAL);
2711   staticpro (&Vcharset_greek_iso8859_7);
2712   Vcharset_greek_iso8859_7 =
2713     make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7, 96, 1,
2714                   1, 1, 'F', CHARSET_LEFT_TO_RIGHT,
2715                   build_string ("ISO8859-7"),
2716                   build_string ("ISO8859-7 (Greek)"),
2717                   build_string ("ISO8859-7 (Greek)"),
2718                   build_string ("iso8859-7"),
2719                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2720   staticpro (&Vcharset_arabic_iso8859_6);
2721   Vcharset_arabic_iso8859_6 =
2722     make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6, 96, 1,
2723                   1, 1, 'G', CHARSET_RIGHT_TO_LEFT,
2724                   build_string ("ISO8859-6"),
2725                   build_string ("ISO8859-6 (Arabic)"),
2726                   build_string ("ISO8859-6 (Arabic)"),
2727                   build_string ("iso8859-6"),
2728                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2729   staticpro (&Vcharset_hebrew_iso8859_8);
2730   Vcharset_hebrew_iso8859_8 =
2731     make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8, 96, 1,
2732                   1, 1, 'H', CHARSET_RIGHT_TO_LEFT,
2733                   build_string ("ISO8859-8"),
2734                   build_string ("ISO8859-8 (Hebrew)"),
2735                   build_string ("ISO8859-8 (Hebrew)"),
2736                   build_string ("iso8859-8"),
2737                   Qnil,
2738                   0 /* MIN_CHAR_HEBREW */,
2739                   0 /* MAX_CHAR_HEBREW */, 0, 32,
2740                   Qnil, CONVERSION_IDENTICAL);
2741   staticpro (&Vcharset_katakana_jisx0201);
2742   Vcharset_katakana_jisx0201 =
2743     make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201, 94, 1,
2744                   1, 1, 'I', CHARSET_LEFT_TO_RIGHT,
2745                   build_string ("JISX0201 Kana"),
2746                   build_string ("JISX0201.1976 (Japanese Kana)"),
2747                   build_string ("JISX0201.1976 Japanese Kana"),
2748                   build_string ("jisx0201\\.1976"),
2749                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2750   staticpro (&Vcharset_latin_jisx0201);
2751   Vcharset_latin_jisx0201 =
2752     make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201, 94, 1,
2753                   1, 0, 'J', CHARSET_LEFT_TO_RIGHT,
2754                   build_string ("JISX0201 Roman"),
2755                   build_string ("JISX0201.1976 (Japanese Roman)"),
2756                   build_string ("JISX0201.1976 Japanese Roman"),
2757                   build_string ("jisx0201\\.1976"),
2758                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2759   staticpro (&Vcharset_cyrillic_iso8859_5);
2760   Vcharset_cyrillic_iso8859_5 =
2761     make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5, 96, 1,
2762                   1, 1, 'L', CHARSET_LEFT_TO_RIGHT,
2763                   build_string ("ISO8859-5"),
2764                   build_string ("ISO8859-5 (Cyrillic)"),
2765                   build_string ("ISO8859-5 (Cyrillic)"),
2766                   build_string ("iso8859-5"),
2767                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2768   staticpro (&Vcharset_latin_iso8859_9);
2769   Vcharset_latin_iso8859_9 =
2770     make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9, 96, 1,
2771                   1, 1, 'M', CHARSET_LEFT_TO_RIGHT,
2772                   build_string ("Latin-5"),
2773                   build_string ("ISO8859-9 (Latin-5)"),
2774                   build_string ("ISO8859-9 (Latin-5)"),
2775                   build_string ("iso8859-9"),
2776                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2777   staticpro (&Vcharset_japanese_jisx0208_1978);
2778   Vcharset_japanese_jisx0208_1978 =
2779     make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978,
2780                   Qjapanese_jisx0208_1978, 94, 2,
2781                   2, 0, '@', CHARSET_LEFT_TO_RIGHT,
2782                   build_string ("JIS X0208:1978"),
2783                   build_string ("JIS X0208:1978 (Japanese)"),
2784                   build_string
2785                   ("JIS X0208:1978 Japanese Kanji (so called \"old JIS\")"),
2786                   build_string ("\\(jisx0208\\|jisc6226\\)\\.1978"),
2787                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2788   staticpro (&Vcharset_chinese_gb2312);
2789   Vcharset_chinese_gb2312 =
2790     make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312, 94, 2,
2791                   2, 0, 'A', CHARSET_LEFT_TO_RIGHT,
2792                   build_string ("GB2312"),
2793                   build_string ("GB2312)"),
2794                   build_string ("GB2312 Chinese simplified"),
2795                   build_string ("gb2312"),
2796                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2797   staticpro (&Vcharset_chinese_gb12345);
2798   Vcharset_chinese_gb12345 =
2799     make_charset (LEADING_BYTE_CHINESE_GB12345, Qchinese_gb12345, 94, 2,
2800                   2, 0, 0, CHARSET_LEFT_TO_RIGHT,
2801                   build_string ("G1"),
2802                   build_string ("GB 12345)"),
2803                   build_string ("GB 12345-1990"),
2804                   build_string ("GB12345\\(\\.1990\\)?-0"),
2805                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2806   staticpro (&Vcharset_japanese_jisx0208);
2807   Vcharset_japanese_jisx0208 =
2808     make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208, 94, 2,
2809                   2, 0, 'B', CHARSET_LEFT_TO_RIGHT,
2810                   build_string ("JISX0208"),
2811                   build_string ("JIS X0208:1983 (Japanese)"),
2812                   build_string ("JIS X0208:1983 Japanese Kanji"),
2813                   build_string ("jisx0208\\.1983"),
2814                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2815 #ifdef UTF2000
2816   staticpro (&Vcharset_japanese_jisx0208_1990);
2817   Vcharset_japanese_jisx0208_1990 =
2818     make_charset (LEADING_BYTE_JAPANESE_JISX0208_1990,
2819                   Qjapanese_jisx0208_1990, 94, 2,
2820                   2, 0, 0, CHARSET_LEFT_TO_RIGHT,
2821                   build_string ("JISX0208-1990"),
2822                   build_string ("JIS X0208:1990 (Japanese)"),
2823                   build_string ("JIS X0208:1990 Japanese Kanji"),
2824                   build_string ("jisx0208\\.1990"),
2825                   Qnil,
2826                   MIN_CHAR_JIS_X0208_1990,
2827                   MAX_CHAR_JIS_X0208_1990, MIN_CHAR_JIS_X0208_1990, 33,
2828                   Qnil, CONVERSION_IDENTICAL);
2829 #endif
2830   staticpro (&Vcharset_korean_ksc5601);
2831   Vcharset_korean_ksc5601 =
2832     make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601, 94, 2,
2833                   2, 0, 'C', CHARSET_LEFT_TO_RIGHT,
2834                   build_string ("KSC5601"),
2835                   build_string ("KSC5601 (Korean"),
2836                   build_string ("KSC5601 Korean Hangul and Hanja"),
2837                   build_string ("ksc5601"),
2838                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2839   staticpro (&Vcharset_japanese_jisx0212);
2840   Vcharset_japanese_jisx0212 =
2841     make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212, 94, 2,
2842                   2, 0, 'D', CHARSET_LEFT_TO_RIGHT,
2843                   build_string ("JISX0212"),
2844                   build_string ("JISX0212 (Japanese)"),
2845                   build_string ("JISX0212 Japanese Supplement"),
2846                   build_string ("jisx0212"),
2847                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2848
2849 #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$"
2850   staticpro (&Vcharset_chinese_cns11643_1);
2851   Vcharset_chinese_cns11643_1 =
2852     make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1, 94, 2,
2853                   2, 0, 'G', CHARSET_LEFT_TO_RIGHT,
2854                   build_string ("CNS11643-1"),
2855                   build_string ("CNS11643-1 (Chinese traditional)"),
2856                   build_string
2857                   ("CNS 11643 Plane 1 Chinese traditional"),
2858                   build_string (CHINESE_CNS_PLANE_RE("1")),
2859                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2860   staticpro (&Vcharset_chinese_cns11643_2);
2861   Vcharset_chinese_cns11643_2 =
2862     make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2, 94, 2,
2863                   2, 0, 'H', CHARSET_LEFT_TO_RIGHT,
2864                   build_string ("CNS11643-2"),
2865                   build_string ("CNS11643-2 (Chinese traditional)"),
2866                   build_string
2867                   ("CNS 11643 Plane 2 Chinese traditional"),
2868                   build_string (CHINESE_CNS_PLANE_RE("2")),
2869                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2870 #ifdef UTF2000
2871   staticpro (&Vcharset_latin_tcvn5712);
2872   Vcharset_latin_tcvn5712 =
2873     make_charset (LEADING_BYTE_LATIN_TCVN5712, Qlatin_tcvn5712, 96, 1,
2874                   1, 1, 'Z', CHARSET_LEFT_TO_RIGHT,
2875                   build_string ("TCVN 5712"),
2876                   build_string ("TCVN 5712 (VSCII-2)"),
2877                   build_string ("Vietnamese TCVN 5712:1983 (VSCII-2)"),
2878                   build_string ("tcvn5712\\(\\.1993\\)?-1"),
2879                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2880   staticpro (&Vcharset_latin_viscii_lower);
2881   Vcharset_latin_viscii_lower =
2882     make_charset (LEADING_BYTE_LATIN_VISCII_LOWER, Qlatin_viscii_lower, 96, 1,
2883                   1, 1, '1', CHARSET_LEFT_TO_RIGHT,
2884                   build_string ("VISCII lower"),
2885                   build_string ("VISCII lower (Vietnamese)"),
2886                   build_string ("VISCII lower (Vietnamese)"),
2887                   build_string ("MULEVISCII-LOWER"),
2888                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2889   staticpro (&Vcharset_latin_viscii_upper);
2890   Vcharset_latin_viscii_upper =
2891     make_charset (LEADING_BYTE_LATIN_VISCII_UPPER, Qlatin_viscii_upper, 96, 1,
2892                   1, 1, '2', CHARSET_LEFT_TO_RIGHT,
2893                   build_string ("VISCII upper"),
2894                   build_string ("VISCII upper (Vietnamese)"),
2895                   build_string ("VISCII upper (Vietnamese)"),
2896                   build_string ("MULEVISCII-UPPER"),
2897                   Qnil, 0, 0, 0, 32, Qnil, CONVERSION_IDENTICAL);
2898   staticpro (&Vcharset_latin_viscii);
2899   Vcharset_latin_viscii =
2900     make_charset (LEADING_BYTE_LATIN_VISCII, Qlatin_viscii, 256, 1,
2901                   1, 2, 0, CHARSET_LEFT_TO_RIGHT,
2902                   build_string ("VISCII"),
2903                   build_string ("VISCII 1.1 (Vietnamese)"),
2904                   build_string ("VISCII 1.1 (Vietnamese)"),
2905                   build_string ("VISCII1\\.1"),
2906                   Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL);
2907   staticpro (&Vcharset_chinese_big5);
2908   Vcharset_chinese_big5 =
2909     make_charset (LEADING_BYTE_CHINESE_BIG5, Qchinese_big5, 256, 2,
2910                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2911                   build_string ("Big5"),
2912                   build_string ("Big5"),
2913                   build_string ("Big5 Chinese traditional"),
2914                   build_string ("big5"),
2915                   Qnil,
2916                   0 /* MIN_CHAR_BIG5_CDP */,
2917                   0 /* MAX_CHAR_BIG5_CDP */, 0, 0,
2918                   Qnil, CONVERSION_IDENTICAL);
2919   staticpro (&Vcharset_chinese_big5_cdp);
2920   Vcharset_chinese_big5_cdp =
2921     make_charset (LEADING_BYTE_CHINESE_BIG5_CDP, Qchinese_big5_cdp, 256, 2,
2922                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2923                   build_string ("Big5-CDP"),
2924                   build_string ("Big5 + CDP extension"),
2925                   build_string ("Big5 with CDP extension"),
2926                   build_string ("big5\\.cdp-0"),
2927                   Qnil, MIN_CHAR_BIG5_CDP, MAX_CHAR_BIG5_CDP,
2928                   MIN_CHAR_BIG5_CDP, 0, Qnil, CONVERSION_IDENTICAL);
2929 #define DEF_HANZIKU(n)                                                  \
2930   staticpro (&Vcharset_ideograph_hanziku_##n);                          \
2931   Vcharset_ideograph_hanziku_##n =                                      \
2932     make_charset (LEADING_BYTE_HANZIKU_##n, Qideograph_hanziku_##n, 256, 2, \
2933                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,                       \
2934                   build_string ("HZK-"#n),                              \
2935                   build_string ("HANZIKU-"#n),  \
2936                   build_string ("HANZIKU (pseudo BIG5 encoding) part "#n), \
2937                   build_string                                          \
2938                   ("hanziku-"#n"$"),                                    \
2939                   Qnil, MIN_CHAR_HANZIKU_##n, MAX_CHAR_HANZIKU_##n,     \
2940                   MIN_CHAR_HANZIKU_##n, 0, Qnil, CONVERSION_IDENTICAL);
2941   DEF_HANZIKU (1);
2942   DEF_HANZIKU (2);
2943   DEF_HANZIKU (3);
2944   DEF_HANZIKU (4);
2945   DEF_HANZIKU (5);
2946   DEF_HANZIKU (6);
2947   DEF_HANZIKU (7);
2948   DEF_HANZIKU (8);
2949   DEF_HANZIKU (9);
2950   DEF_HANZIKU (10);
2951   DEF_HANZIKU (11);
2952   DEF_HANZIKU (12);
2953   staticpro (&Vcharset_china3_jef);
2954   Vcharset_china3_jef =
2955     make_charset (LEADING_BYTE_CHINA3_JEF, Qchina3_jef, 256, 2,
2956                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2957                   build_string ("JC3"),
2958                   build_string ("JEF + CHINA3"),
2959                   build_string ("JEF + CHINA3 private characters"),
2960                   build_string ("china3jef-0"),
2961                   Qnil, MIN_CHAR_CHINA3_JEF, MAX_CHAR_CHINA3_JEF,
2962                   MIN_CHAR_CHINA3_JEF, 0, Qnil, CONVERSION_IDENTICAL);
2963   staticpro (&Vcharset_ideograph_cbeta);
2964   Vcharset_ideograph_cbeta =
2965     make_charset (LEADING_BYTE_CBETA, Qideograph_cbeta, 256, 2,
2966                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2967                   build_string ("CB"),
2968                   build_string ("CBETA"),
2969                   build_string ("CBETA private characters"),
2970                   build_string ("cbeta-0"),
2971                   Qnil, MIN_CHAR_CBETA, MAX_CHAR_CBETA,
2972                   MIN_CHAR_CBETA, 0, Qnil, CONVERSION_IDENTICAL);
2973   staticpro (&Vcharset_ideograph_gt);
2974   Vcharset_ideograph_gt =
2975     make_charset (LEADING_BYTE_GT, Qideograph_gt, 256, 3,
2976                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
2977                   build_string ("GT"),
2978                   build_string ("GT"),
2979                   build_string ("GT"),
2980                   build_string (""),
2981                   Qnil, MIN_CHAR_GT, MAX_CHAR_GT,
2982                   MIN_CHAR_GT, 0, Qnil, CONVERSION_IDENTICAL);
2983 #define DEF_GT_PJ(n)                                                    \
2984   staticpro (&Vcharset_ideograph_gt_pj_##n);                            \
2985   Vcharset_ideograph_gt_pj_##n =                                        \
2986     make_charset (LEADING_BYTE_GT_PJ_##n, Qideograph_gt_pj_##n, 94, 2,  \
2987                   2, 0, 0, CHARSET_LEFT_TO_RIGHT,                       \
2988                   build_string ("GT-PJ-"#n),                            \
2989                   build_string ("GT (pseudo JIS encoding) part "#n),    \
2990                   build_string ("GT 2000 (pseudo JIS encoding) part "#n), \
2991                   build_string                                          \
2992                   ("\\(GTpj-"#n "\\|jisx0208\\.GT-"#n "\\)$"),  \
2993                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
2994   DEF_GT_PJ (1);
2995   DEF_GT_PJ (2);
2996   DEF_GT_PJ (3);
2997   DEF_GT_PJ (4);
2998   DEF_GT_PJ (5);
2999   DEF_GT_PJ (6);
3000   DEF_GT_PJ (7);
3001   DEF_GT_PJ (8);
3002   DEF_GT_PJ (9);
3003   DEF_GT_PJ (10);
3004   DEF_GT_PJ (11);
3005
3006   staticpro (&Vcharset_ideograph_daikanwa_2);
3007   Vcharset_ideograph_daikanwa_2 =
3008     make_charset (LEADING_BYTE_DAIKANWA_2, Qideograph_daikanwa_2, 256, 2,
3009                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3010                   build_string ("Daikanwa Rev."),
3011                   build_string ("Morohashi's Daikanwa Rev."),
3012                   build_string
3013                   ("Daikanwa dictionary (revised version)"),
3014                   build_string ("Daikanwa\\(\\.[0-9]+\\)?-2"),
3015                   Qnil, 0, 0, 0, 0, Qnil, CONVERSION_IDENTICAL);
3016   staticpro (&Vcharset_ideograph_daikanwa);
3017   Vcharset_ideograph_daikanwa =
3018     make_charset (LEADING_BYTE_DAIKANWA_3, Qideograph_daikanwa, 256, 2,
3019                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3020                   build_string ("Daikanwa"),
3021                   build_string ("Morohashi's Daikanwa Rev.2"),
3022                   build_string
3023                   ("Daikanwa dictionary (second revised version)"),
3024                   build_string ("Daikanwa\\(\\.[0-9]+\\)?-3"),
3025                   Qnil, MIN_CHAR_DAIKANWA, MAX_CHAR_DAIKANWA,
3026                   MIN_CHAR_DAIKANWA, 0, Qnil, CONVERSION_IDENTICAL);
3027
3028   staticpro (&Vcharset_ethiopic_ucs);
3029   Vcharset_ethiopic_ucs =
3030     make_charset (LEADING_BYTE_ETHIOPIC_UCS, Qethiopic_ucs, 256, 2,
3031                   2, 2, 0, CHARSET_LEFT_TO_RIGHT,
3032                   build_string ("Ethiopic (UCS)"),
3033                   build_string ("Ethiopic (UCS)"),
3034                   build_string ("Ethiopic of UCS"),
3035                   build_string ("Ethiopic-Unicode"),
3036                   Qnil, 0x1200, 0x137F, 0, 0,
3037                   Qnil, CONVERSION_IDENTICAL);
3038 #endif
3039   staticpro (&Vcharset_chinese_big5_1);
3040   Vcharset_chinese_big5_1 =
3041     make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1, 94, 2,
3042                   2, 0, '0', CHARSET_LEFT_TO_RIGHT,
3043                   build_string ("Big5"),
3044                   build_string ("Big5 (Level-1)"),
3045                   build_string
3046                   ("Big5 Level-1 Chinese traditional"),
3047                   build_string ("big5"),
3048                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
3049   staticpro (&Vcharset_chinese_big5_2);
3050   Vcharset_chinese_big5_2 =
3051     make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2, 94, 2,
3052                   2, 0, '1', CHARSET_LEFT_TO_RIGHT,
3053                   build_string ("Big5"),
3054                   build_string ("Big5 (Level-2)"),
3055                   build_string
3056                   ("Big5 Level-2 Chinese traditional"),
3057                   build_string ("big5"),
3058                   Qnil, 0, 0, 0, 33, Qnil, CONVERSION_IDENTICAL);
3059
3060 #ifdef ENABLE_COMPOSITE_CHARS
3061   /* #### For simplicity, we put composite chars into a 96x96 charset.
3062      This is going to lead to problems because you can run out of
3063      room, esp. as we don't yet recycle numbers. */
3064   staticpro (&Vcharset_composite);
3065   Vcharset_composite =
3066     make_charset (LEADING_BYTE_COMPOSITE, Qcomposite, 96, 2,
3067                   2, 0, 0, CHARSET_LEFT_TO_RIGHT,
3068                   build_string ("Composite"),
3069                   build_string ("Composite characters"),
3070                   build_string ("Composite characters"),
3071                   build_string (""));
3072
3073   /* #### not dumped properly */
3074   composite_char_row_next = 32;
3075   composite_char_col_next = 32;
3076
3077   Vcomposite_char_string2char_hash_table =
3078     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
3079   Vcomposite_char_char2string_hash_table =
3080     make_lisp_hash_table (500, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
3081   staticpro (&Vcomposite_char_string2char_hash_table);
3082   staticpro (&Vcomposite_char_char2string_hash_table);
3083 #endif /* ENABLE_COMPOSITE_CHARS */
3084
3085 }