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