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