(mfont__ft_init): Add oblique and boldoblique.
[m17n/m17n-lib.git] / src / charset.c
1 /* charset.c -- charset module.
2    Copyright (C) 2003, 2004
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nCharset
25     @brief Charset objects and API for them.
26
27     The m17n library uses @e charset objects to represent a coded
28     character sets (CCS).  The m17n library supports many predefined
29     coded character sets.  Moreover, application programs can add
30     other charsets.  A character can belong to multiple charsets.
31
32     The m17n library distinguishes the following three concepts:
33
34     @li A @e code-point is a number assigned by the CCS to each
35     character.  Code-points may or may not be continuous.  The type
36     @c unsigned is used to represent a code-point.  An invalid
37     code-point is represented by the macro @c MCHAR_INVALID_CODE.
38
39     @li A @e character @e index is the canonical index of a character
40     in a CCS.  The character that has the character index N occupies
41     the Nth position when all the characters in the current CCS are
42     sorted by their code-points.  Character indices in a CCS are
43     continuous and start with 0.
44
45     @li A @e character @e code is the internal representation in the
46     m17n library of a character.  A character code is a signed integer
47     of 21 bits or longer.
48
49     Each charset object defines how characters are converted between
50     code-points and character codes.  To @e encode means converting
51     code-points to character codes and to @e decode means converting
52     character codes to code-points.  */
53
54 /***ja
55     @addtogroup m17nCharset
56     @brief Ê¸»ú¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API
57
58     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢Éä¹æ²½Ê¸»ú½¸¹ç (CCS) ¤ò @e Ê¸»ú¥»¥Ã¥È ¤È¸Æ¤Ö¥ª
59     ¥Ö¥¸¥§¥¯¥È¤Çɽ¸½¤¹¤ë¡£m17n ¥é¥¤¥Ö¥é¥ê¤Ï¿¤¯¤ÎÉä¹æ²½Ê¸»ú½¸¹ç¤òͽ¤á
60     ¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¤¬¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤¬Æȼ«¤Ëʸ»ú¥»¥Ã¥È¤ò
61     Äɲ乤뤳¤È¤â²Äǽ¤Ç¤¢¤ë¡£°ì¤Ä¤Îʸ»ú¤ÏÊ£¿ô¤Îʸ»ú¥»¥Ã¥È¤Ë°¤·¤Æ¤â¤è
62     ¤¤¡£
63
64     m17n ¥é¥¤¥Ö¥é¥ê¤Ë¤Ï¡¢°Ê²¼¤Î°Û¤Ê¤ë³µÇ°¤¬¤¢¤ë:
65
66     @li @e ¥³¡¼¥É¥Ý¥¤¥ó¥È ¤È¤Ï¡¢CCS ¤¬¤½¤ÎÃæ¤Î¸Ä¡¹¤Îʸ»ú¤ËÂФ·¤ÆÄêµÁ¤¹
67     ¤ë¿ôÃͤǤ¢¤ë¡£¥³¡¼¥É¥Ý¥¤¥ó¥È¤ÏϢ³¤·¤Æ¤¤¤ë¤È¤Ï¸Â¤é¤Ê¤¤¡£
68
69     @li @e Ê¸»ú¥¤¥ó¥Ç¥Ã¥¯¥¹ ¤È¤Ï¡¢CCS Æâ¤Ç³Æʸ»ú¤Ë³ä¤êÅö¤Æ¤é¤ì¤ëÀµµ¬²½¤µ
70     ¤ì¤¿¥¤¥ó¥Ç¥Ã¥¯¥¹¤Ç¤¢¤ë¡£Ê¸»ú¥¤¥ó¥Ç¥Ã¥¯¥¹¤¬N¤Îʸ»ú¤Ï¡¢CCS Ãæ¤ÎÁ´Ê¸»ú¤ò
71     ¥³¡¼¥É¥Ý¥¤¥ó¥È¤Ç¥½¡¼¥È¤·¤¿¤È¤­¤ËNÈÖÌܤËÍè¤ë¡£
72
73     @li @e Ê¸»ú¥³¡¼¥É¤È¤Ï¡¢m17n ¥é¥¤¥Ö¥é¥êÆâ¤Ë¤ª¤±¤ëʸ»ú¤ÎÆâÉôɽ¸½¤Ç¤¢
74     ¤ê¡¢21 ¥Ó¥Ã¥È°Ê¾å¤ÎŤµ¤ò»ý¤ÄÉä¹çÉÕ¤­À°¿ô¤Ç¤¢¤ë¡£
75
76     ³Æʸ»ú¥»¥Ã¥È¥ª¥Ö¥¸¥§¥¯¥È¤Ï¡¢¤½¤ì¤Ë°¤¹¤ëʸ»ú¤Î¥³¡¼¥É¥Ý¥¤¥ó¥È¤Èʸ»ú
77     ¥³¡¼¥É¤È¤ÎÁê¸ßÊÑ´¹¤òµ¬Äꤹ¤ë¡£¥³¡¼¥É¥Ý¥¤¥ó¥È¤«¤éʸ»ú¥³¡¼¥É¤Ø¤ÎÊÑ´¹
78     ¤ò @e ¥Ç¥³¡¼¥É ¤È¸Æ¤Ó¡¢Ê¸»ú¥³¡¼¥É¤«¤é¥³¡¼¥É¥Ý¥¤¥ó¥È¤Ø¤ÎÊÑ´¹¤ò @e 
79     ¥¨¥ó¥³¡¼¥É ¤È¸Æ¤Ö¡£  */
80
81 /*=*/
82 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
83 /*** @addtogroup m17nInternal
84      @{ */
85
86 #include <config.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <string.h>
90 #include <limits.h>
91
92 #include "m17n.h"
93 #include "m17n-misc.h"
94 #include "internal.h"
95 #include "symbol.h"
96 #include "charset.h"
97 #include "coding.h"
98 #include "chartab.h"
99 #include "plist.h"
100
101 static int unified_max = MCHAR_MAX;
102
103 /** List of all charsets ever defined.  */
104
105 struct MCharsetList
106 {
107   int size, inc, used;
108   MCharset **charsets;
109 };
110
111 static struct MCharsetList charset_list;
112
113 static MPlist *charset_definition_list;
114
115 /** Make a charset object from the template of MCharset structure
116     CHARSET, and return a pointer to the new charset object.
117     CHARSET->code_range[4N + 2] and TMPL->code_range[4N + 3] are not
118     yet set.  */
119
120 static MCharset *
121 make_charset (MCharset *charset)
122 {
123   unsigned min_code, max_code;
124   int i, n;
125   int *range = charset->code_range;
126
127   if (charset->dimension < 1 || charset->dimension > 4)
128     MERROR (MERROR_CHARSET, NULL);
129   if ((charset->final_byte > 0 && charset->final_byte < '0')
130       || charset->final_byte > 127)
131     MERROR (MERROR_CHARSET, NULL);
132
133   for (i = 0, n = 1; i < 4; i++)
134     {
135       if (range[i * 4] > range[i * 4 + 1])
136         MERROR (MERROR_CHARSET, NULL);
137       range[i * 4 + 2] = range[i * 4 + 1] - range[i * 4] + 1;
138       n *= range[i * 4 + 2];
139       range[i * 4 + 3] = n;
140     }
141
142   min_code = range[0] | (range[4] << 8) | (range[8] << 16) | (range[12] << 24);
143   if (charset->min_code == 0)
144     charset->min_code = min_code;
145   else if (charset->min_code < min_code)
146     MERROR (MERROR_CHARSET, NULL);
147   max_code = range[1] | (range[5] << 8) | (range[9] << 16) | (range[13] << 24);
148   if (charset->max_code == 0)  
149     charset->max_code = max_code;
150   else if (charset->max_code > max_code)
151     MERROR (MERROR_CHARSET, NULL);
152
153   charset->code_range_min_code = min_code;
154
155   if (charset->method == Msubset)
156     {
157       MCharset *parent;
158
159       if (charset->nparents != 1)
160         MERROR (MERROR_CHARSET, NULL);
161       parent = charset->parents[0];
162       if (parent->method == Msuperset
163           || charset->min_code - charset->subset_offset < parent->min_code
164           || charset->max_code - charset->subset_offset > parent->max_code)
165         MERROR (MERROR_CHARSET, NULL);
166       if (parent->method == Moffset)
167         {
168           unsigned code;
169
170           code = charset->min_code - charset->subset_offset;
171           charset->min_char = DECODE_CHAR (parent, code);
172           code = charset->max_code - charset->subset_offset;
173           charset->max_char = DECODE_CHAR (parent, code);
174         }
175       else
176         {
177           unsigned min_code = charset->min_code - charset->subset_offset;
178           unsigned max_code = charset->max_code - charset->subset_offset;
179           int min_char = DECODE_CHAR (parent, min_code);
180           int max_char = min_char;
181           
182           for (++min_code; min_code <= max_code; min_code++)
183             {
184               int c = DECODE_CHAR (parent, min_code);
185
186               if (c >= 0)
187                 {
188                   if (c < min_char)
189                     min_char = c;
190                   else if (c > max_char)
191                     max_char = c;
192                 }
193             }
194           charset->min_char = min_char;
195           charset->max_char = max_char;
196         }
197       charset->simple = 0;
198     }
199   else if (charset->method == Msuperset)
200     {
201       int min_char = 0, max_char = 0;
202
203       if (charset->nparents < 2)
204         MERROR (MERROR_CHARSET, NULL);
205       for (i = 0; i < charset->nparents; i++)
206         if (charset->min_code > charset->parents[i]->min_code
207             || charset->max_code < charset->parents[i]->max_code)
208           MERROR (MERROR_CHARSET, NULL);
209
210       for (i = 0; i < charset->nparents; i++)
211         {
212           MCharset *parent = charset->parents[i];
213
214           if (charset->min_code > parent->min_code
215             || charset->max_code < parent->max_code)
216             MERROR (MERROR_CHARSET, NULL);
217           if (i == 0)
218             min_char = parent->min_char, max_char = parent->max_char;
219           else if (parent->min_char < min_char)
220             min_char = parent->min_char;
221           else if (parent->max_char > max_char)
222             max_char = parent->max_char;
223         }
224       charset->min_char = min_char;
225       charset->max_char = max_char;
226       charset->simple = 0;
227     }
228   else
229     {
230       charset->no_code_gap
231         = (charset->dimension == 1
232            || (range[2] == 256
233                && (charset->dimension == 2
234                    || (range[6] == 256
235                        && (charset->dimension == 3
236                            || range[10] == 256)))));
237
238       if (! charset->no_code_gap)
239         {
240           int j;
241
242           memset (charset->code_range_mask, 0,
243                   sizeof charset->code_range_mask);
244           for (i = 0; i < 4; i++)
245             for (j = range[i * 4]; j <= range[i * 4 + 1]; j++)
246               charset->code_range_mask[j] |= (1 << i);
247         }
248
249       if (charset->method == Moffset)
250         {
251           charset->max_char = charset->min_char + range[15] - 1;
252           if (charset->min_char < 0
253               || charset->max_char < 0 || charset->max_char > unified_max)
254             MERROR (MERROR_CHARSET, NULL);
255           charset->simple = charset->no_code_gap;
256         }
257       else if (charset->method == Mmap || charset->method == Munify)
258         {
259           MDatabase *mdb = mdatabase_find (Mcharset, charset->name,
260                                            Mnil, Mnil);
261           MPlist *plist;
262
263           charset->simple = 0;
264           if (charset->method == Munify)
265             {
266               /* The magic number 12 below is to align to the
267                  SUB_BITS_2 (defined in chartab.c) boundary in a
268                  char-table.  */
269               unified_max -= ((range[15] >> 12) + 1) << 12;
270               charset->unified_max = unified_max;
271             }
272
273           if (! mdb || ! (plist = mdatabase_load (mdb)))
274             MERROR (MERROR_CHARSET, NULL);
275           charset->decoder = mplist_value (plist);
276           charset->encoder = mplist_value (mplist_next (plist));
277           M17N_OBJECT_UNREF (plist);
278           mchartable_range (charset->encoder,
279                             &charset->min_char, &charset->max_char);
280           if (charset->method == Mmap)
281             charset->simple = charset->no_code_gap;
282           else
283             charset->max_char
284               = charset->unified_max + 1 + charset->code_range[15];
285         }
286       else
287         MERROR (MERROR_CHARSET, NULL);
288     }
289
290   MLIST_APPEND1 (&charset_list, charsets, charset, MERROR_CHARSET);
291
292   if (charset->final_byte > 0)
293     {
294       MLIST_APPEND1 (&mcharset__iso_2022_table, charsets, charset,
295                      MERROR_CHARSET);
296       if (charset->revision <= 0)
297         {
298           int chars = range[2];
299
300           if (chars == 128)     /* ASCII case */
301             chars = 94;
302           else if (chars == 256) /* ISO-8859-X case */
303             chars = 96;
304           MCHARSET_ISO_2022 (charset->dimension, chars, charset->final_byte)
305             = charset;
306         }
307     }
308
309   charset->fully_loaded = 1;
310   return charset;
311 }
312
313 static int
314 load_charset_fully (MCharset *charset)
315 {
316   if (charset->method == Msubset)
317     {
318       MCharset *parent = charset->parents[0];
319
320       if (! parent->fully_loaded
321           && load_charset_fully (parent) < 0)
322         MERROR (MERROR_CHARSET, -1);
323       if (parent->method == Moffset)
324         {
325           unsigned code;
326
327           code = charset->min_code - charset->subset_offset;
328           charset->min_char = DECODE_CHAR (parent, code);
329           code = charset->max_code - charset->subset_offset;
330           charset->max_char = DECODE_CHAR (parent, code);
331         }
332       else
333         {
334           unsigned min_code = charset->min_code - charset->subset_offset;
335           unsigned max_code = charset->max_code - charset->subset_offset;
336           int min_char = DECODE_CHAR (parent, min_code);
337           int max_char = min_char;
338           
339           for (++min_code; min_code <= max_code; min_code++)
340             {
341               int c = DECODE_CHAR (parent, min_code);
342
343               if (c >= 0)
344                 {
345                   if (c < min_char)
346                     min_char = c;
347                   else if (c > max_char)
348                     max_char = c;
349                 }
350             }
351           charset->min_char = min_char;
352           charset->max_char = max_char;
353         }
354     }
355   else if (charset->method == Msuperset)
356     {
357       int min_char = 0, max_char = 0;
358       int i;
359
360       for (i = 0; i < charset->nparents; i++)
361         {
362           MCharset *parent = charset->parents[i];
363
364           if (! parent->fully_loaded
365               && load_charset_fully (parent) < 0)
366             MERROR (MERROR_CHARSET, -1);
367           if (i == 0)
368             min_char = parent->min_char, max_char = parent->max_char;
369           else if (parent->min_char < min_char)
370             min_char = parent->min_char;
371           else if (parent->max_char > max_char)
372             max_char = parent->max_char;
373         }
374       charset->min_char = min_char;
375       charset->max_char = max_char;
376     }
377   else                          /* charset->method is Mmap or Munify */
378     {
379       MDatabase *mdb = mdatabase_find (Mcharset, charset->name, Mnil, Mnil);
380       MPlist *plist;
381
382       if (! mdb || ! (plist = mdatabase_load (mdb)))
383         MERROR (MERROR_CHARSET, -1);
384       charset->decoder = mplist_value (plist);
385       charset->encoder = mplist_value (mplist_next (plist));
386       M17N_OBJECT_UNREF (plist);
387       mchartable_range (charset->encoder,
388                         &charset->min_char, &charset->max_char);
389       if (charset->method == Mmap)
390         charset->simple = charset->no_code_gap;
391       else
392         charset->max_char = charset->unified_max + 1 + charset->code_range[15];
393     }
394
395   charset->fully_loaded = 1;
396   return 0;
397 }
398
399 \f
400 /* Internal API */
401
402 MPlist *mcharset__cache;
403
404 /* Predefined charsets.  */
405 MCharset *mcharset__ascii;
406 MCharset *mcharset__binary;
407 MCharset *mcharset__m17n;
408 MCharset *mcharset__unicode;
409
410 MCharsetISO2022Table mcharset__iso_2022_table;
411
412 /** Initialize charset handler.  */
413
414 int
415 mcharset__init ()
416 {
417   MPlist *param, *pl;
418
419   mcharset__cache = mplist ();
420   mplist_set (mcharset__cache, Mt, NULL);
421
422   MLIST_INIT1 (&charset_list, charsets, 128);
423   MLIST_INIT1 (&mcharset__iso_2022_table, charsets, 128);
424   charset_definition_list = mplist ();
425
426   memset (mcharset__iso_2022_table.classified, 0,
427           sizeof (mcharset__iso_2022_table.classified));
428
429   Mcharset = msymbol ("charset");
430
431   Mmethod = msymbol ("method");
432   Moffset = msymbol ("offset");
433   Mmap = msymbol ("map");
434   Munify = msymbol ("unify");
435   Msubset = msymbol ("subset");
436   Msuperset = msymbol ("superset");
437
438   Mdimension = msymbol ("dimension");
439   Mmin_range = msymbol ("min-range");
440   Mmax_range = msymbol ("max-range");
441   Mmin_code = msymbol ("min-code");
442   Mmax_code = msymbol ("max-code");
443   Mascii_compatible = msymbol ("ascii-compatible");
444   Mfinal_byte = msymbol ("final-byte");
445   Mrevision = msymbol ("revision");
446   Mmin_char = msymbol ("min-char");
447   Mmapfile = msymbol_as_managing_key ("mapfile");
448   Mparents = msymbol_as_managing_key ("parents");
449   Msubset_offset = msymbol ("subset-offset");
450   Mdefine_coding = msymbol ("define-coding");
451   Maliases = msymbol_as_managing_key ("aliases");
452
453   param = mplist ();
454   pl = param;
455   /* Setup predefined charsets.  */
456   pl = mplist_add (pl, Mmethod, Moffset);
457   pl = mplist_add (pl, Mmin_range, (void *) 0);
458   pl = mplist_add (pl, Mmax_range, (void *) 0x7F);
459   pl = mplist_add (pl, Mascii_compatible, Mt);
460   pl = mplist_add (pl, Mfinal_byte, (void *) 'B');
461   pl = mplist_add (pl, Mmin_char, (void *) 0);
462   Mcharset_ascii = mchar_define_charset ("ascii", param);
463
464   mplist_put (param, Mmax_range, (void *) 0xFF);
465   mplist_put (param, Mfinal_byte, NULL);
466   Mcharset_iso_8859_1 = mchar_define_charset ("iso-8859-1", param);
467
468   mplist_put (param, Mmax_range, (void *) 0x10FFFF);
469   Mcharset_unicode = mchar_define_charset ("unicode", param);
470
471   mplist_put (param, Mmax_range, (void *) MCHAR_MAX);
472   Mcharset_m17n = mchar_define_charset ("m17n", param);
473
474   mplist_put (param, Mmax_range, (void *) 0xFF);
475   Mcharset_binary = mchar_define_charset ("binary", param);
476
477   M17N_OBJECT_UNREF (param);
478
479   mcharset__ascii = MCHARSET (Mcharset_ascii);
480   mcharset__binary = MCHARSET (Mcharset_binary);
481   mcharset__m17n = MCHARSET (Mcharset_m17n);
482   mcharset__unicode = MCHARSET (Mcharset_unicode);
483
484   return 0;
485 }
486
487 void
488 mcharset__fini (void)
489 {
490   int i;
491   MPlist *plist;
492
493   for (i = 0; i < charset_list.used; i++)
494     {
495       MCharset *charset = charset_list.charsets[i];
496
497       if (charset->decoder)
498         free (charset->decoder);
499       if (charset->encoder)
500         M17N_OBJECT_UNREF (charset->encoder);
501       free (charset);
502     }
503   M17N_OBJECT_UNREF (mcharset__cache);
504   MLIST_FREE1 (&charset_list, charsets);
505   MLIST_FREE1 (&mcharset__iso_2022_table, charsets);
506   MPLIST_DO (plist, charset_definition_list)
507     M17N_OBJECT_UNREF (MPLIST_VAL (plist));
508   M17N_OBJECT_UNREF (charset_definition_list);
509 }
510
511
512 MCharset *
513 mcharset__find (MSymbol name)
514 {
515   MCharset *charset;
516
517   charset = msymbol_get (name, Mcharset);
518   if (! charset)
519     {
520       MPlist *param = mplist_get (charset_definition_list, name);
521
522       MPLIST_KEY (mcharset__cache) = Mt;
523       if (! param)
524         return NULL;
525       param = mplist__from_plist (param);
526       mchar_define_charset (MSYMBOL_NAME (name), param);
527       charset = msymbol_get (name, Mcharset);
528       M17N_OBJECT_UNREF (param);
529     }
530   MPLIST_KEY (mcharset__cache) = name;
531   MPLIST_VAL (mcharset__cache) = charset;
532   return charset;
533 }
534
535
536 /** Return the character corresponding to code-point CODE in CHARSET.
537     If CODE is invalid for CHARSET, return -1.  */
538
539 int
540 mcharset__decode_char (MCharset *charset, unsigned code)
541 {
542   int idx;
543
544   if (code < 128 && charset->ascii_compatible)
545     return (int) code;
546   if (code < charset->min_code || code > charset->max_code)
547     return -1;
548
549   if (! charset->fully_loaded
550       && load_charset_fully (charset) < 0)
551     MERROR (MERROR_CHARSET, -1);
552
553   if (charset->method == Msubset)
554     {
555       MCharset *parent = charset->parents[0];
556
557       code -= charset->subset_offset;
558       return DECODE_CHAR (parent, code);
559     }
560
561   if (charset->method == Msuperset)
562     {
563       int i;
564
565       for (i = 0; i < charset->nparents; i++)
566         {
567           MCharset *parent = charset->parents[i];
568           int c = DECODE_CHAR (parent, code);
569
570           if (c >= 0)
571             return c;
572         }
573       return -1;
574     }
575
576   idx = CODE_POINT_TO_INDEX (charset, code);
577   if (idx < 0)
578     return -1;
579
580   if (charset->method == Mmap)
581     return charset->decoder[idx];
582
583   if (charset->method == Munify)
584     {
585       int c = charset->decoder[idx];
586
587       if (c < 0)
588         c = charset->unified_max + 1 + idx;
589       return c;
590     }
591
592   /* Now charset->method should be Moffset.  */
593   return (charset->min_char + idx);
594 }
595
596
597 /** Return the code point of character C in CHARSET.  If CHARSET does not
598     contain C, return MCHAR_INVALID_CODE.  */
599
600 unsigned
601 mcharset__encode_char (MCharset *charset, int c)
602 {
603   if (! charset->fully_loaded
604       && load_charset_fully (charset) < 0)
605     MERROR (MERROR_CHARSET, MCHAR_INVALID_CODE);
606
607   if (charset->method == Msubset)
608     {
609       MCharset *parent = charset->parents[0];
610       unsigned code = ENCODE_CHAR (parent, c);
611
612       if (code == MCHAR_INVALID_CODE)
613         return code;
614       code += charset->subset_offset;
615       if (code >= charset->min_code && code <= charset->max_code)
616         return code;
617       return MCHAR_INVALID_CODE;
618     }
619
620   if (charset->method == Msuperset)
621     {
622       int i;
623
624       for (i = 0; i < charset->nparents; i++)
625         {
626           MCharset *parent = charset->parents[i];
627           unsigned code = ENCODE_CHAR (parent, c);
628
629           if (code != MCHAR_INVALID_CODE)
630             return code;
631         }
632       return MCHAR_INVALID_CODE;
633     }
634
635   if (c < charset->min_char || c > charset->max_char)
636     return MCHAR_INVALID_CODE;
637
638   if (charset->method == Mmap)
639     return (unsigned) mchartable_lookup (charset->encoder, c);
640
641   if (charset->method == Munify)
642     {
643       if (c > charset->unified_max)
644         {
645           c -= charset->unified_max - 1;
646           return INDEX_TO_CODE_POINT (charset, c);
647         }
648       return (unsigned) mchartable_lookup (charset->encoder, c);
649     }
650
651   /* Now charset->method should be Moffset */
652   c -= charset->min_char;
653   return INDEX_TO_CODE_POINT (charset, c);
654 }
655
656 int
657 mcharset__load_from_database ()
658 {
659   MDatabase *mdb = mdatabase_find (msymbol ("charset-list"), Mnil, Mnil, Mnil);
660   MPlist *def_list, *plist;
661   MPlist *definitions = charset_definition_list;
662   int mdebug_mask = MDEBUG_CHARSET;
663
664   if (! mdb)
665     return 0;
666   MDEBUG_PUSH_TIME ();
667   def_list = (MPlist *) mdatabase_load (mdb);
668   MDEBUG_PRINT_TIME ("CHARSET", (stderr, " to load data."));
669   MDEBUG_POP_TIME ();
670   if (! def_list)
671     return -1;
672
673   MDEBUG_PUSH_TIME ();
674   MPLIST_DO (plist, def_list)
675     {
676       MPlist *pl;
677       MSymbol name;
678
679       if (! MPLIST_PLIST_P (plist))
680         MERROR (MERROR_CHARSET, -1);
681       pl = MPLIST_PLIST (plist);
682       if (! MPLIST_SYMBOL_P (pl))
683         MERROR (MERROR_CHARSET, -1);
684       name = MPLIST_SYMBOL (pl);
685       pl = MPLIST_NEXT (pl);
686       definitions = mplist_add (definitions, name, pl);
687       M17N_OBJECT_REF (pl);
688       mchar_define_charset (MSYMBOL_NAME (name), mplist__from_plist (pl));
689       if ((pl = mplist_find_by_value (pl, Mdefine_coding))
690           && (MSymbol) MPLIST_VAL (MPLIST_NEXT (pl)) == Mt)
691         mconv__register_charset_coding (name);
692     }
693
694   M17N_OBJECT_UNREF (def_list);
695   MDEBUG_PRINT_TIME ("CHARSET", (stderr, " to parse the loaded data."));
696   MDEBUG_POP_TIME ();
697   return 0;
698 }
699
700 /*** @} */
701 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
702
703 \f
704 /* External API */
705
706 /*** @addtogroup m17nCharset */
707 /*** @{ */
708 /*=*/
709
710 #ifdef FOR_DOXYGEN
711 /***en
712     @brief Invalid code-point.
713
714     The macro #MCHAR_INVALID_CODE gives the invalid code-point.  */
715
716 /***ja
717     @brief Ìµ¸ú¤Ê¥³¡¼¥É¥Ý¥¤¥ó¥È
718
719     ¥Þ¥¯¥í #MCHAR_INVALID_CODE ¤Ï̵¸ú¤Ê¥³¡¼¥É¥Ý¥¤¥ó¥È¤òÍ¿¤¨¤ë¡£  */
720
721 #define MCHAR_INVALID_CODE
722 #endif
723 /*=*/
724 /***en
725     @brief The symbol @c Mcharset.
726
727     Any decoded M-text has a text property whose key is the predefined
728     symbol @c Mcharset.  The name of @c Mcharset is
729     <tt>"charset"</tt>.  */
730
731 /***ja
732     @brief ¥·¥ó¥Ü¥ë @c Mcharset
733
734     ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥­¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È
735     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£¥·¥ó¥Ü¥ë @c Mcharset ¤Ï <tt>"charset"</tt> ¤È¤¤
736     ¤¦Ì¾Á°¤Ç¤¢¤é¤«¤¸¤áÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£  */
737
738 MSymbol Mcharset;
739 /*=*/
740
741 /***en
742     @name Variables: Symbols representing a charset.
743
744     Each of the following symbols represents a predefined charset.  */
745
746 /***ja
747     @name ÊÑ¿ô: Ê¸»ú¥»¥Ã¥È¤òɽ¤ï¤¹ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë
748
749     °Ê²¼¤Î³Æ¥·¥ó¥Ü¥ë¤Ï¡¢¥­¡¼¤¬ @c Mcharset ¤Ç¤¢¤ê¡¢Ãͤ¬Âбþ¤¹¤ëʸ»ú¥»¥Ã
750     ¥È¥ª¥Ö¥¸¥§¥¯¥È¡Ê @c MCharset ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ
751     ¥Æ¥£¤ò»ý¤Ä¡£  */
752 /*=*/
753 /*** @{ */
754 /*=*/
755 /***en
756     @brief Symbol representing the charset ASCII.
757
758     The symbol #Mcharset_ascii has name <tt>"ascii"</tt> and represents
759     the charset ISO 646, USA Version X3.4-1968 (ISO-IR-6).  */
760 /***ja
761     @brief ISO 646, USA Version ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
762
763     ¥·¥ó¥Ü¥ë #Mcharset_ascii ¤Ï <tt>"ascii"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢ 
764     ISO 646, USA Version X3.4-1968 (ISO-IR-6) ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»Ø
765     Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ë¡£  */
766
767 MSymbol Mcharset_ascii;
768
769 /*=*/
770 /***en
771     @brief Symbol representing the charset ISO/IEC 8859/1.
772
773     The symbol #Mcharset_iso_8859_1 has name <tt>"iso-8859-1"</tt>
774     and represents the charset ISO/IEC 8859-1:1998.  */
775 /***ja
776     @brief ISO/IEC 8859-1:1998 ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
777
778     ¥·¥ó¥Ü¥ë #Mcharset_iso_8859_1 ¤Ï <tt>"iso-8859-1"</tt> ¤È¤¤¤¦Ì¾
779     Á°¤ò»ý¤Á¡¢ISO/IEC 8859-1:1998 ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë
780     »È¤ï¤ì¤ë¡£ */
781
782 MSymbol Mcharset_iso_8859_1;
783
784 /***en
785     @brief Symbol representing the charset Unicode.
786
787     The symbol #Mcharset_unicode has name <tt>"unicode"</tt> and
788     represents the charset Unicode.  */
789 /***ja
790     @brief Unicode ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
791
792     ¥·¥ó¥Ü¥ë #Mcharset_unicode ¤Ï <tt>"unicode"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý
793     ¤Á¡¢Unicode ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ë¡£ */
794
795 MSymbol Mcharset_unicode;
796
797 /*=*/
798 /***en
799     @brief Symbol representing the largest charset.
800
801     The symbol #Mcharset_m17n has name <tt>"m17n"</tt> and
802     represents the charset that contains all characters supported by
803     the m17n library.  */ 
804 /***ja
805     @brief Á´Ê¸»ú¤ò´Þ¤àʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
806
807     ¥·¥ó¥Ü¥ë #Mcharset_m17n ¤Ï <tt>"m17n"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
808     m17n ¥é¥¤¥Ö¥é¥ê¤¬°·¤¦Á´¤Æ¤Îʸ»ú¤ò´Þ¤àʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë»È
809     ¤ï¤ì¤ë¡£ */
810
811 MSymbol Mcharset_m17n;
812
813 /*=*/
814 /***en
815     @brief Symbol representing the charset for ill-decoded characters.
816
817     The symbol #Mcharset_binary has name <tt>"binary"</tt> and
818     represents the fake charset which the decoding functions put to an
819     M-text as a text property when they encounter an invalid byte
820     (sequence).  See @ref m17nConv @latexonly
821     (P.\pageref{group__m17nConv}) @endlatexonly for more detail.  */
822
823 MSymbol Mcharset_binary;
824
825 /*=*/
826 /*** @} */
827 /*=*/
828
829 /***en
830     @name Variables: Parameter keys for mchar_define_charset ().
831
832     These are the predefined symbols to use as parameter keys for the
833     function mchar_define_charset () (which see).  */
834
835 /***ja
836     @name ÊÑ¿ô: mchar_define_charset ÍѤΥѥé¥á¡¼¥¿¡¦¥­¡¼
837
838     ¤³¤ì¤é¤Ï¡¢´Ø¿ô mchar_define_charset () ÍѤΥѥé¥á¡¼¥¿¡¦¥­¡¼¤È¤·¤Æ
839     »È¤ï¤ì¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ ¾Ü¤·¤¯¤Ï¤³¤Î´Ø¿ô¤Î²òÀâ¤ò»²¾È¤Î¤³¤È¡£*/
840 /*** @{ */
841 /*=*/
842
843 /***en
844     Parameter key for mchar_define_charset () (which see). */ 
845
846 MSymbol Mmethod;
847 MSymbol Mdimension;
848 MSymbol Mmin_range;
849 MSymbol Mmax_range;
850 MSymbol Mmin_code;
851 MSymbol Mmax_code;
852 MSymbol Mascii_compatible;
853 MSymbol Mfinal_byte;
854 MSymbol Mrevision;
855 MSymbol Mmin_char;
856 MSymbol Mmapfile;
857 MSymbol Mparents;
858 MSymbol Msubset_offset;
859 MSymbol Mdefine_coding;
860 MSymbol Maliases;
861 /*=*/
862 /*** @} */
863 /*=*/
864
865 /***en
866     @name Variables: Symbols representing charset methods.
867
868     These are the predefined symbols that can be a value of the
869     #Mmethod parameter of a charset used in an argument to the
870     mchar_define_charset () function.
871
872     A method specifies how code-points and character codes are
873     converted.  See the documentation of the mchar_define_charset ()
874     function for the details.  */
875
876 /***ja
877     @name ÊÑ¿ô: Ê¸»ú¥»¥Ã¥È¤Î¥á¥½¥Ã¥É»ØÄê¤Ë»È¤ï¤ì¤ë¥·¥ó¥Ü¥ë
878
879     ¤³¤ì¤é¤Ï¡¢Ê¸»ú¥»¥Ã¥È¤Î @e ¥á¥½¥Ã¥É ¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
880     ´Ø¿ô mchar_define_charset () ¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
881
882     ¥á¥½¥Ã¥É¤È¤Ï¡¢¥³¡¼¥É¥Ý¥¤¥ó¥È¤Èʸ»ú¥³¡¼¥É¤òÁê¸ßÊÑ´¹¤¹¤ëºÝ¤ÎÊý¼°¤Î¤³
883     ¤È¤Ç¤¢¤ë¡£¾Ü¤·¤¯¤Ï´Ø¿ô mchar_define_charset () ¤Î²òÀâ¤ò»²¾È¤Î¤³¤È¡£  */
884 /*** @{ */
885 /*=*/
886 /***en
887     @brief Symbol for the offset type method of charset.
888
889     The symbol #Moffset has the name <tt>"offset"</tt> and, when used
890     as a value of #Mmethod parameter of a charset, it means that the
891     conversion of code-points and character codes of the charset is
892     done by this calculation:
893
894 @verbatim
895 CHARACTER-CODE = CODE-POINT - MIN-CODE + MIN-CHAR
896 @endverbatim
897
898     where, MIN-CODE is a value of #Mmin_code parameter of the charset,
899     and MIN-CHAR is a value of #Mmin_char parameter.  */
900
901 /***ja
902     @brief ¥ª¥Õ¥»¥Ã¥È·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
903
904     ¥·¥ó¥Ü¥ë #Moffset ¤Ï <tt>"offset"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
905     mchar_define_charset () ¤Ç¥ª¥Õ¥»¥Ã¥È·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú
906     ¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£*/
907
908 MSymbol Moffset;
909 /*=*/
910
911 /***en @brief Symbol for the map type method of charset.
912
913     The symbol #Mmap has the name <tt>"map"</tt> and, when use as a
914     value of #Mmethod parameter of a charset, it means that the
915     conversion of code-points and character codes of the charset is
916     done by map looking up.  The map must be given by #Mmapfile
917     parameter.  */
918
919 /***ja @brief ¥Þ¥Ã¥×·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
920
921     ¥·¥ó¥Ü¥ë #Mmap ¤Ï <tt>"map"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
922     mchar_define_charset () ¤Ç¥Þ¥Ã¥×·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú¿ô¤È
923     ¤·¤ÆÍѤ¤¤é¤ì¤ë¡£*/
924
925 MSymbol Mmap;
926 /*=*/
927
928 /***en @brief Symbol for the unify type method of charset.
929
930     The symbol #Munify has the name <tt>"unify"</tt> and, when used as
931     a value of #Mmethod parameter of a charset, it means that the
932     conversion of code-points and character codes of the charset is
933     done by map looking up and offsetting.  The map must be given by
934     #Mmapfile parameter.  For this kind of charset, a unique
935     consequent character code space for all characters is assigned.
936     If the map has an entry for a code-point, the conversion is done
937     by looking up the map.  Otherwise, the conversion is done by this
938     calculation:
939
940 @verbatim
941 CHARACTER-CODE = CODE-POINT - MIN-CODE + LOWEST-CHAR-CODE
942 @endverbatim
943
944     where, MIN-CODE is a value of #Mmin_code parameter of the charset,
945     and LOWEST-CHAR-CODE is the lowest character code of the assigned
946     code space.  */
947
948 /***ja @brief Áê³·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
949
950     ¥·¥ó¥Ü¥ë #Minherit ¤Ï <tt>"inherit"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
951     mchar_define_charset () ¤ÇÁê³·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú¿ô¤È¤·
952     ¤ÆÍѤ¤¤é¤ì¤ë¡£*/
953
954 MSymbol Munify;
955 /*=*/
956
957 /***en
958     @brief Symbol for the subset type method of charset.
959
960     The symbol #Msubset has the name <tt>"subset"</tt> and, when used
961     as a value of #Mmethod parameter of a charset, it means that the
962     charset is a subset of a parent charset.  The parent charset must
963     be given by #Mparents parameter.  The conversion of code-points
964     and character codes of the charset is done conceptually by this
965     calculation:
966
967 @verbatim
968 CHARACTER-CODE = PARENT-CODE (CODE-POINT) + SUBSET-OFFSET
969 @endverbatim
970
971     where, PARENT-CODE is a pseudo function that returns a character
972     code of CODE-POINT in the parent charset, and SUBSET-OFFSET is a
973     value given by #Msubset_offset parameter.  */
974
975 MSymbol Msubset;
976 /*=*/
977
978 /***en
979     @brief Symbol for the superset type method of charset.
980
981     The symbol #Msuperset has the name <tt>"superset"</tt> and, when
982     used as a value of #Mmethod parameter of a charset, it means that
983     the charset is a superset of parent charsets.  The parent charsets
984     must be given by #Mparents parameter.  */
985
986 MSymbol Msuperset;
987 /*=*/
988 /*** @}  */ 
989
990 /***en
991     @brief Define a charset.
992
993     The mchar_define_charset () function defines a new charset and
994     makes it accessible via a symbol whose name is $NAME.  $PLIST
995     specifies parameters of the charset as below:
996
997     <ul>
998
999     <li> Key is #Mmethod, value is a symbol.
1000
1001     The value specifies the method for decoding/encoding code-points
1002     in the charset.  It must be #Moffset, #Mmap (default), #Munify,
1003     #Msubset, or #Msuperset.
1004
1005     <li> Key is #Mdimension, value is an integer
1006
1007     The value specifies the dimension of code-points of the charset.
1008     It must be 1 (default), 2, 3, or 4.
1009
1010     <li> Key is #Mmin_range, value is an unsigned integer
1011
1012     The value specifies the minimum range of a code-point, which means
1013     that the Nth byte of the value is the minimum Nth byte of
1014     code-points of the charset.   The default value is 0.
1015
1016     <li> Key is #Mmax_range, value is an unsigned integer
1017
1018     The value specifies the maximum range of a code-point, which means
1019     that the Nth byte of the value is the maximum Nth byte of
1020     code-points of the charset.  The default value is 0xFF, 0xFFFF,
1021     0xFFFFFF, or 0xFFFFFFFF if the dimension is 1, 2, 3, or 4
1022     respectively.
1023
1024     <li> Key is #Mmin_code, value is an unsigned integer
1025
1026     The value specifies the minimum code-point of
1027     the charset.  The default value is the minimum range.
1028
1029     <li> Key is #Mmax_code, value is an unsigned integer
1030
1031     The value specifies the maximum code-point of
1032     the charset.  The default value is the maximum range.
1033
1034     <li> Key is #Mascii_compatible, value is a symbol
1035
1036     The value specifies whether the charset is ASCII compatible or
1037     not.  If the value is #Mnil (default), it is not ASCII
1038     compatible, else compatible.
1039
1040     <li> Key is #Mfinal_byte, value is an integer
1041
1042     The value specifies the @e final @e byte of the charset registered
1043     in The International Registry.  It must be 0 (default) or 32..127.
1044     The value 0 means that the charset is not in the registry.
1045
1046     <li> Key is #Mrevision, value is an integer
1047
1048     The value specifies the @e revision @e number of the charset
1049     registered in The International Registry.  it must be 0..127.  If
1050     the charset is not in The International Registry, the value is
1051     ignored.  The value 0 means that the charset has no revision
1052     number.
1053
1054     <li> Key is #Mmin_char, value is an integer
1055
1056     The value specifies the minimum character code of the charset.
1057     The default value is 0.
1058
1059     <li> Key is #Mmapfile, value is an M-text
1060
1061     If the method is #Mmap or #Munify, a data that contains
1062     mapping information is added to the m17n database by calling
1063     mdatabase_define () with the value as an argument $EXTRA_INFO,
1064     i.e. the value is used as a file name of the data.
1065
1066     Otherwise, this parameter is ignored.
1067
1068     <li> Key is #Mparents, value is a plist
1069
1070     If the method is #Msubset, the value must is a plist of length
1071     1, and the value of the plist must be a symbol representing a
1072     parent charset.
1073
1074     If the method is #Msuperset, the value must be a plist of length
1075     less than 9, and the values of the plist must be symbols
1076     representing subset charsets.
1077
1078     Otherwise, this parameter is ignored.
1079
1080     <li> Key is #Mdefine_coding, value is a symbol
1081
1082     If the dimension of the charset is 1, the value specifies whether
1083     or not to define a coding system of the same name whose method is
1084     @c charset.
1085
1086     Otherwise, this parameter is ignored.
1087
1088     </ul>
1089
1090     @return
1091     If the operation was successful, mchar_define_charset () returns a
1092     symbol whose name is $NAME.  Otherwise it returns #Mnil and
1093     assigns an error code to the external variable #merror_code.  */
1094
1095 /***ja
1096     @brief Ê¸»ú¥»¥Ã¥È¤òÄêµÁ¤¹¤ë.
1097
1098     ´Ø¿ô mchar_define_charset () ¤Ï¿·¤·¤¤Ê¸»ú¥»¥Ã¥È¤òÄêµÁ¤·¡¢¤½¤ì¤ò 
1099     $NAME ¤È¤¤¤¦Ì¾Á°¤Î¥·¥ó¥Ü¥ë·Ðͳ¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£$METHOD 
1100     ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤Ë¤ª¤±¤ë¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î¥Ç¥³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥á¥½¥Ã
1101     ¥É¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Moffset, #Mmap, #Munify,
1102     #Msubset, #Msuperset ¤Î¤¤¤º¤ì¤«¤ÎÃͤò¤È¤ë¡£
1103
1104     $DIMENSION ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤Î¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î¼¡¸µ¤Ç¤¢¤ê¡¢1, 2, 3,
1105     4¤Î¤¤¤º¤ì¤«¤ÎÃͤò¤È¤ë¡£
1106
1107     $CODE_RANGE ¤ÏÂ礭¤µ¤¬8¥Ð¥¤¥È¤ÎÇÛÎó¤Ç¤¢¤ê¡¢ÄêµÁ¤µ¤ì¤ëʸ»ú¥»¥Ã¥È¤Î
1108     ¥³¡¼¥É¥Ý¥¤¥ó¥È¶õ´Ö¤òɽ¤ï¤¹¡£Âè1¥Ð¥¤¥È¤ÈÂè2¥Ð¥¤¥È¤ÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó
1109     ¥È¤ÎºÇ½é¤Î¼¡¸µ¤Ç¤ÎºÇ¾®¡¿ºÇÂç¥Ð¥¤¥È¤ÎÃͤǤ¢¤ë¡£Âè3¥Ð¥¤¥È¤ÈÂè4¥Ð¥¤¥È
1110     ¤Ï¡¢2ÈÖÌܤμ¡¸µ¤ÎºÇ¾®¡¿ºÇÂçÃͤǤ¢¤ê¡¢ °Ê²¼Æ±Íͤ˳¤¯¡£°ìÈÌŪ¤Ë¡¢Âè
1111     (2N-1)¥Ð¥¤¥È¤ÈÂè(2N)¥Ð¥¤¥È¤¬NÈÖÌܤμ¡¸µ¤ÎºÇ¾®¡¿ºÇÂçÃͤȤʤë (N =
1112     1, 2, 3, 4)¡£¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î @e Ê¸»ú¥¤¥ó¥Ç¥Ã¥¯¥¹ ¤Ï¤³¤ì¤é¤ÎÃͤ«¤é
1113     ·×»»¤µ¤ì¤ë¡£
1114
1115     $MIN_CODE ¤È $MAX_CODE ¤Ï¡¢¤½¤ì¤¾¤ì¤³¤Îʸ»ú¥»¥Ã¥È¤ÎºÇ¾®¤ª¤è¤ÓºÇÂç
1116     ¥³¡¼¥É¥Ý¥¤¥ó¥È¤òɽ¤ï¤¹¡£0¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ï $CODE_RANGE ¤ÎÃͤ«¤é·×
1117     »»¤µ¤ì¤ë¡£
1118
1119     $FINAL_BYTE ¤Ï The International Registry ¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë
1120     @e ½ªÃ¼¥Ð¥¤¥È ¤Ç¤¢¤ë¡£ÅÐÏ¿¤µ¤ì¤Æ¤¤¤Ê¤¤ CCS ¤Î¾ì¹ç¤Ë¤Ï -1 ¤Ç¤Ê¤¯¤Æ¤Ï
1121     ¤Ê¤é¤Ê¤¤¡£
1122
1123     $REVISION ¤Ï¡¢The International Registry ¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë@e revision
1124     @e number ¤Ç¤¢¤ë¡£¤â¤· revision number ¤¬Â¸ºß¤·¤Ê¤¤¤Ê¤é -1 ¤Ç¤Ê¤¯
1125     ¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1126
1127     @par ¥á¥½¥Ã¥É¤¬ Moffset ¤Î¾ì¹ç
1128
1129     $MIN_CHAR ¤Ë¤ÏºÇ¾®¤Î¥³¡¼¥É¥Ý¥¤¥ó¥È¤ËÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤òÍ¿¤¨¤ë¡£
1130     $NPARENTS, $PARENTS, ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1131
1132     @par ¥á¥½¥Ã¥É¤¬ Mmap ¤Î¾ì¹ç
1133
1134     m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç \<#Mcharset, $NAME\> ¤È¤¤¤¦¥¿¥°¤ÎÉÕ¤¤¤¿
1135     ¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¡¢¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤ËÍѤ¤¤ë¡£$MIN_CHAR,
1136     $NPARENTS, $PARENTS, ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1137
1138     @par ¥á¥½¥Ã¥É¤¬ Msubset ¤Î¾ì¹ç
1139
1140     $NPARENTS ¤Ï1¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿ $PARENTS ¤Ï·Ñ¾µ¤Î¸µ¤È¤Ê¤ëʸ
1141     »ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¸µ¤Îʸ»ú¥»¥Ã¥È¤Î¥³¡¼¥É
1142     ¥Ý¥¤¥ó¥È¤Ë $SUBSET_OFFSET ¤ò²Ã¤¨¤¿¤â¤Î¤¬¡¢¿·¤·¤¤Ê¸»ú¥»¥Ã¥ÈÃæ¤Ç¤Î¥³¡¼
1143     ¥É¥Ý¥¤¥ó¥È¤Ë¤Ê¤ë¡£$MIN_CHAR ¤Ï̵»ë¤µ¤ì¤ë¡£
1144
1145     @par ¥á¥½¥Ã¥É¤¬ Msuperset ¤Î¾ì¹ç
1146
1147     $NPARENTS ¤Ï¿Æ¤È¤Ê¤ëʸ»ú¥»¥Ã¥È¤Î¿ô¡¢$PARENTS ¤Ï¿Æʸ»ú¥»¥Ã¥È¤Î¥·¥ó
1148     ¥Ü¥ë¤ÎÇÛÎó¤òɽ¤ï¤¹¡£$MIN_CHAR ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1149
1150     @return
1151     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_define_charset () ¤Ï $NAME ¤È¤¤¤¦Ì¾Á°¤Î¥·
1152     ¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c
1153     merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1154
1155 /***
1156     @errors
1157     @c MERROR_CHARSET  */
1158
1159 MSymbol
1160 mchar_define_charset (char *name, MPlist *plist)
1161 {
1162   MSymbol sym = msymbol (name);
1163   MCharset *charset;
1164   int i;
1165   unsigned min_range, max_range;
1166   MPlist *pl;
1167   MText *mapfile = (MText *) mplist_get (plist, Mmapfile);
1168
1169   MSTRUCT_CALLOC (charset, MERROR_CHARSET);
1170   charset->name = sym;
1171   charset->method = (MSymbol) mplist_get (plist, Mmethod);
1172   if (! charset->method)
1173     {
1174       if (mapfile)
1175         charset->method = Mmap;
1176       else
1177         charset->method = Moffset;
1178     }
1179   if (charset->method == Mmap || charset->method == Munify)
1180     {
1181       if (! mapfile)
1182         MERROR (MERROR_CHARSET, Mnil);
1183       mdatabase_define (Mcharset, sym, Mnil, Mnil, NULL, mapfile->data);
1184     }
1185   if (! (charset->dimension = (int) mplist_get (plist, Mdimension)))
1186     charset->dimension = 1;
1187
1188   min_range = (unsigned) mplist_get (plist, Mmin_range);
1189   if ((pl = mplist_find_by_key (plist, Mmax_range)))
1190     {
1191       max_range = (unsigned) MPLIST_VAL (pl);
1192       if (max_range >= 0x1000000)
1193         charset->dimension = 4;
1194       else if (max_range >= 0x10000 && charset->dimension < 3)
1195         charset->dimension = 3;
1196       else if (max_range >= 0x100 && charset->dimension < 2)
1197         charset->dimension = 2;
1198     }
1199   else if (charset->dimension == 1)
1200     max_range = 0xFF;
1201   else if (charset->dimension == 2)
1202     max_range = 0xFFFF;
1203   else if (charset->dimension == 3)
1204     max_range = 0xFFFFFF;
1205   else
1206     max_range = 0xFFFFFFFF;
1207
1208   memset (charset->code_range, 0, sizeof charset->code_range);
1209   for (i = 0; i < charset->dimension; i++, min_range >>= 8, max_range >>= 8)
1210     {
1211       charset->code_range[i * 4] = min_range & 0xFF;
1212       charset->code_range[i * 4 + 1] = max_range & 0xFF;
1213     }
1214   if ((charset->min_code = (int) mplist_get (plist, Mmin_code)) < min_range)
1215     charset->min_code = min_range;
1216   if ((charset->max_code = (int) mplist_get (plist, Mmax_code)) > max_range)
1217     charset->max_code = max_range;
1218   charset->ascii_compatible
1219     = (MSymbol) mplist_get (plist, Mascii_compatible) != Mnil;
1220   charset->final_byte = (int) mplist_get (plist, Mfinal_byte);
1221   charset->revision = (int) mplist_get (plist, Mrevision);
1222   charset->min_char = (int) mplist_get (plist, Mmin_char);
1223   pl = (MPlist *) mplist_get (plist, Mparents);
1224   charset->nparents = pl ? mplist_length (pl) : 0;
1225   if (charset->nparents > 8)
1226     charset->nparents = 8;
1227   for (i = 0; i < charset->nparents; i++, pl = MPLIST_NEXT (pl))
1228     {
1229       MSymbol parent_name;
1230
1231       if (MPLIST_KEY (pl) != Msymbol)
1232         MERROR (MERROR_CHARSET, Mnil);
1233       parent_name = MPLIST_SYMBOL (pl);
1234       if (! (charset->parents[i] = MCHARSET (parent_name)))
1235         MERROR (MERROR_CHARSET, Mnil);
1236     }
1237
1238   charset->subset_offset = (int) mplist_get (plist, Msubset_offset);
1239
1240   msymbol_put (sym, Mcharset, charset);
1241   charset = make_charset (charset);
1242   if (! charset)
1243     return Mnil;
1244   msymbol_put (msymbol__canonicalize (sym), Mcharset, charset);
1245
1246   for (pl = (MPlist *) mplist_get (plist, Maliases);
1247        pl && MPLIST_KEY (pl) == Msymbol;
1248        pl = MPLIST_NEXT (pl))
1249     {
1250       MSymbol alias = MPLIST_SYMBOL (pl);
1251
1252       msymbol_put (alias, Mcharset, charset);
1253       msymbol_put (msymbol__canonicalize (alias), Mcharset, charset);
1254     }
1255
1256   if (mplist_get (plist, Mdefine_coding)
1257       && charset->dimension == 1
1258       && charset->code_range[0] == 0 && charset->code_range[1] == 255)
1259     mconv__register_charset_coding (sym);
1260   return (sym);
1261 }
1262
1263 /*=*/
1264
1265 /***en
1266     @brief Resolve charset name.
1267
1268     The mchar_resolve_charset () function returns $SYMBOL if it
1269     represents a charset.  Otherwise, canonicalize $SYMBOL as to a
1270     charset name, and if the canonicalized name represents a charset,
1271     return it.  Otherwise, return #Mnil.  */
1272
1273 MSymbol
1274 mchar_resolve_charset (MSymbol symbol)
1275 {
1276   MCharset *charset = (MCharset *) msymbol_get (symbol, Mcharset);
1277
1278   if (! charset)
1279     {
1280       symbol = msymbol__canonicalize (symbol);
1281       charset = (MCharset *) msymbol_get (symbol, Mcharset);
1282     }
1283
1284   return (charset ? charset->name : Mnil);
1285 }
1286
1287 /*=*/
1288
1289 /***en
1290     @brief List symbols representing a charset.
1291
1292     The mchar_list_charsets () function makes an array of symbols
1293     representing a charset, stores the pointer to the array in a place
1294     pointed to by $SYMBOLS, and returns the length of the array.  */
1295
1296 int
1297 mchar_list_charset (MSymbol **symbols)
1298 {
1299   int i;
1300
1301   MTABLE_MALLOC ((*symbols), charset_list.used, MERROR_CHARSET);
1302   for (i = 0; i < charset_list.used; i++)
1303     (*symbols)[i] = charset_list.charsets[i]->name;
1304   return i;
1305 }
1306
1307 /*=*/
1308
1309 /***en
1310     @brief Decode a code-point.
1311
1312     The mchar_decode () function decodes code-point $CODE in the
1313     charset represented by the symbol $CHARSET_NAME to get a character
1314     code.
1315
1316     @return
1317     If decoding was successful, mchar_decode () returns the decoded
1318     character code.  Otherwise it returns -1.  */
1319
1320 /***ja
1321     @brief ¥³¡¼¥É¥Ý¥¤¥ó¥È¤ò¥Ç¥³¡¼¥É¤¹¤ë
1322
1323     ´Ø¿ô mchar_decode () ¤Ï¡¢¥·¥ó¥Ü¥ë $CHARSET_NAME ¤Ç¼¨¤µ¤ì¤ëʸ»ú¥»¥Ã
1324     ¥ÈÆâ¤Î $CODE ¤È¤¤¤¦¥³¡¼¥É¥Ý¥¤¥ó¥È¤ò¥Ç¥³¡¼¥É¤·¤Æʸ»ú¥³¡¼¥É¤òÆÀ¤ë¡£
1325
1326     @return
1327     ¥Ç¥³¡¼¥É¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_decode () ¤Ï¥Ç¥³¡¼¥É¤µ¤ì¤¿Ê¸»ú¥³¡¼¥É¤ò
1328     ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£  */
1329
1330 /***
1331     @seealso
1332     mchar_encode ()  */
1333
1334 int
1335 mchar_decode (MSymbol charset_name, unsigned code)
1336 {
1337   MCharset *charset = MCHARSET (charset_name);
1338
1339   if (! charset)
1340     return MCHAR_INVALID_CODE;
1341   return DECODE_CHAR (charset, code);
1342 }
1343
1344 /*=*/
1345
1346 /***en
1347     @brief Encode a character code.
1348
1349     The mchar_encode () function encodes character code $C to get a
1350     code-point in the charset represented by the symbol $CHARSET_NAME.
1351
1352     @return
1353     If encoding was successful, mchar_encode () returns the encoded
1354     code-point.  Otherwise it returns #MCHAR_INVALID_CODE.  */
1355
1356 /***ja
1357     @brief Ê¸»ú¥³¡¼¥É¤ò¥¨¥ó¥³¡¼¥É¤¹¤ë
1358
1359     ´Ø¿ô mchar_encode () ¤Ï¡¢Ê¸»ú¥³¡¼¥É $C ¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¥·¥ó¥Ü¥ë
1360     $CHARSET_NAME ¤Ç¼¨¤µ¤ì¤ëʸ»ú¥»¥Ã¥ÈÆâ¤Ë¤ª¤±¤ë¥³¡¼¥É¥Ý¥¤¥ó¥È¤òÆÀ¤ë¡£
1361
1362     @return
1363     ¥¨¥ó¥³¡¼¥É¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_encode () ¤Ï¥¨¥ó¡¼¥É¤µ¤ì¤¿¥³¡¼¥É¥Ý¥¤
1364     ¥ó¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #MCHAR_INVALID_CODE ¤òÊÖ¤¹¡£  */
1365
1366 /***
1367     @seealso
1368     mchar_decode ()  */
1369
1370 unsigned
1371 mchar_encode (MSymbol charset_name, int c)
1372 {
1373   MCharset *charset = MCHARSET (charset_name);
1374
1375   if (! charset)
1376     return MCHAR_INVALID_CODE;
1377   return ENCODE_CHAR (charset, c);
1378 }
1379
1380 /*=*/
1381
1382 /***en
1383     @brief Call a function for all the characters in a specified charset.
1384
1385     The mcharset_map_chars () function calls $FUNC for all the
1386     characters in the charset named $CHARSET_NAME.  A call is done for
1387     a chunk of consecutive characters rather than character by
1388     character.
1389
1390     $FUNC receives three arguments: $FROM, $TO, and $ARG.  $FROM and
1391     $TO specify the range of character codes in $CHARSET.  $ARG is the
1392     same as $FUNC_ARG.
1393
1394     @return
1395     If the operation was successful, mcharset_map_chars () returns 0.
1396     Otherwise, it returns -1 and assigns an error code to the external
1397     variable #merror_code.  */
1398
1399 /***ja
1400     @brief »ØÄꤷ¤¿Ê¸»ú¥»¥Ã¥È¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ËÂФ·¤Æ´Ø¿ô¤ò¸Æ¤Ö
1401
1402     ´Ø¿ô mcharset_map_chars () ¤Ï $CHARSET_NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Äʸ»ú¥»¥Ã
1403     ¥ÈÃæ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ËÂФ·¤Æ $FUNC ¤ò¸Æ¤Ö¡£¸Æ¤Ó½Ð¤·¤Ï°ìʸ»úËè¤Ç¤Ï¤Ê
1404     ¤¯¡¢Ï¢Â³¤·¤¿Ê¸»ú¤Î¤Þ¤È¤Þ¤êñ°Ì¤Ç¹Ô¤Ê¤ï¤ì¤ë¡£
1405
1406     ´Ø¿ô $FUNC ¤Ë¤Ï$FROM, $TO, $ARG ¤Î£³°ú¿ô¤¬ÅϤµ¤ì¤ë¡£$FROM ¤È $TO 
1407     ¤Ï $CHARSET Ãæ¤Îʸ»ú¥³¡¼¥É¤ÎÈϰϤò»ØÄꤹ¤ë¡£$ARG ¤Ï $FUNC_ARG ¤ÈƱ
1408     ¤¸¤Ç¤¢¤ë¡£
1409
1410     @return
1411     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mcharset_map_chars () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 
1412     -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
1413
1414 /*** 
1415     @errors
1416     @c MERROR_CHARSET */
1417
1418 int
1419 mchar_map_charset (MSymbol charset_name,
1420                    void (*func) (int from, int to, void *arg),
1421                    void *func_arg)
1422 {
1423   MCharset *charset;
1424
1425   charset = MCHARSET (charset_name);
1426   if (! charset)
1427     MERROR (MERROR_CHARSET, -1);
1428
1429   if (charset->encoder)
1430     {
1431       int c = charset->min_char;
1432       int next_c;
1433
1434       if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) < 0)
1435         c = next_c;
1436       while (c <= charset->max_char)
1437         {
1438           if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) >= 0)
1439             (*func) (c, next_c - 1, func_arg);    
1440           c = next_c;
1441         }
1442     }
1443   else
1444     (*func) (charset->min_char, charset->max_char, func_arg);
1445   return 0;
1446 }
1447
1448 /*=*/
1449
1450 /*** @} */
1451
1452 /*
1453   Local Variables:
1454   coding: euc-japan
1455   End:
1456 */