*** empty log message ***
[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       if ((pl = mplist_find_by_value (pl, Mdefine_coding))
689           && (MSymbol) MPLIST_VAL (MPLIST_NEXT (pl)) == Mt)
690         mconv__register_charset_coding (name);
691     }
692
693   M17N_OBJECT_UNREF (def_list);
694   MDEBUG_PRINT_TIME ("CHARSET", (stderr, " to parse the loaded data."));
695   MDEBUG_POP_TIME ();
696   return 0;
697 }
698
699 /*** @} */
700 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
701
702 \f
703 /* External API */
704
705 /*** @addtogroup m17nCharset */
706 /*** @{ */
707 /*=*/
708
709 #ifdef FOR_DOXYGEN
710 /***en
711     @brief Invalid code-point.
712
713     The macro #MCHAR_INVALID_CODE gives the invalid code-point.  */
714
715 /***ja
716     @brief Ìµ¸ú¤Ê¥³¡¼¥É¥Ý¥¤¥ó¥È
717
718     ¥Þ¥¯¥í #MCHAR_INVALID_CODE ¤Ï̵¸ú¤Ê¥³¡¼¥É¥Ý¥¤¥ó¥È¤òÍ¿¤¨¤ë¡£  */
719
720 #define MCHAR_INVALID_CODE
721 #endif
722 /*=*/
723 /***en
724     @brief The symbol @c Mcharset.
725
726     Any decoded M-text has a text property whose key is the predefined
727     symbol @c Mcharset.  The name of @c Mcharset is
728     <tt>"charset"</tt>.  */
729
730 /***ja
731     @brief ¥·¥ó¥Ü¥ë @c Mcharset
732
733     ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥­¡¼¤¬ @c Mcharset ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È
734     ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£¥·¥ó¥Ü¥ë @c Mcharset ¤Ï <tt>"charset"</tt> ¤È¤¤
735     ¤¦Ì¾Á°¤Ç¤¢¤é¤«¤¸¤áÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£  */
736
737 MSymbol Mcharset;
738 /*=*/
739
740 /***en
741     @name Variables: Symbols representing a charset.
742
743     Each of the following symbols represents a predefined charset.  */
744
745 /***ja
746     @name ÊÑ¿ô: Ê¸»ú¥»¥Ã¥È¤òɽ¤ï¤¹ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë
747
748     °Ê²¼¤Î³Æ¥·¥ó¥Ü¥ë¤Ï¡¢¥­¡¼¤¬ @c Mcharset ¤Ç¤¢¤ê¡¢Ãͤ¬Âбþ¤¹¤ëʸ»ú¥»¥Ã
749     ¥È¥ª¥Ö¥¸¥§¥¯¥È¡Ê @c MCharset ·¿¡Ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ
750     ¥Æ¥£¤ò»ý¤Ä¡£  */
751 /*=*/
752 /*** @{ */
753 /*=*/
754 /***en
755     @brief Symbol representing the charset ASCII.
756
757     The symbol #Mcharset_ascii has name <tt>"ascii"</tt> and represents
758     the charset ISO 646, USA Version X3.4-1968 (ISO-IR-6).  */
759 /***ja
760     @brief ISO 646, USA Version ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
761
762     ¥·¥ó¥Ü¥ë #Mcharset_ascii ¤Ï <tt>"ascii"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢ 
763     ISO 646, USA Version X3.4-1968 (ISO-IR-6) ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»Ø
764     Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ë¡£  */
765
766 MSymbol Mcharset_ascii;
767
768 /*=*/
769 /***en
770     @brief Symbol representing the charset ISO/IEC 8859/1.
771
772     The symbol #Mcharset_iso_8859_1 has name <tt>"iso-8859-1"</tt>
773     and represents the charset ISO/IEC 8859-1:1998.  */
774 /***ja
775     @brief ISO/IEC 8859-1:1998 ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
776
777     ¥·¥ó¥Ü¥ë #Mcharset_iso_8859_1 ¤Ï <tt>"iso-8859-1"</tt> ¤È¤¤¤¦Ì¾
778     Á°¤ò»ý¤Á¡¢ISO/IEC 8859-1:1998 ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë
779     »È¤ï¤ì¤ë¡£ */
780
781 MSymbol Mcharset_iso_8859_1;
782
783 /***en
784     @brief Symbol representing the charset Unicode.
785
786     The symbol #Mcharset_unicode has name <tt>"unicode"</tt> and
787     represents the charset Unicode.  */
788 /***ja
789     @brief Unicode ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
790
791     ¥·¥ó¥Ü¥ë #Mcharset_unicode ¤Ï <tt>"unicode"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý
792     ¤Á¡¢Unicode ¤ËÂбþ¤¹¤ëʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ë¡£ */
793
794 MSymbol Mcharset_unicode;
795
796 /*=*/
797 /***en
798     @brief Symbol representing the largest charset.
799
800     The symbol #Mcharset_m17n has name <tt>"m17n"</tt> and
801     represents the charset that contains all characters supported by
802     the m17n library.  */ 
803 /***ja
804     @brief Á´Ê¸»ú¤ò´Þ¤àʸ»ú¥»¥Ã¥È¤Î¥·¥ó¥Ü¥ë
805
806     ¥·¥ó¥Ü¥ë #Mcharset_m17n ¤Ï <tt>"m17n"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
807     m17n ¥é¥¤¥Ö¥é¥ê¤¬°·¤¦Á´¤Æ¤Îʸ»ú¤ò´Þ¤àʸ»ú¥»¥Ã¥È¤ò»ØÄꤹ¤ë¤¿¤á¤Ë»È
808     ¤ï¤ì¤ë¡£ */
809
810 MSymbol Mcharset_m17n;
811
812 /*=*/
813 /***en
814     @brief Symbol representing the charset for ill-decoded characters.
815
816     The symbol #Mcharset_binary has name <tt>"binary"</tt> and
817     represents the fake charset which the decoding functions put to an
818     M-text as a text property when they encounter an invalid byte
819     (sequence).  See @ref m17nConv @latexonly
820     (P.\pageref{group__m17nConv}) @endlatexonly for more detail.  */
821
822 MSymbol Mcharset_binary;
823
824 /*=*/
825 /*** @} */
826 /*=*/
827
828 /***en
829     @name Variables: Parameter keys for mchar_define_charset ().
830
831     These are the predefined symbols to use as parameter keys for the
832     function mchar_define_charset () (which see).  */
833
834 /***ja
835     @name ÊÑ¿ô: mchar_define_charset ÍѤΥѥé¥á¡¼¥¿¡¦¥­¡¼
836
837     ¤³¤ì¤é¤Ï¡¢´Ø¿ô mchar_define_charset () ÍѤΥѥé¥á¡¼¥¿¡¦¥­¡¼¤È¤·¤Æ
838     »È¤ï¤ì¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¡£ ¾Ü¤·¤¯¤Ï¤³¤Î´Ø¿ô¤Î²òÀâ¤ò»²¾È¤Î¤³¤È¡£*/
839 /*** @{ */
840 /*=*/
841
842 /***en
843     Parameter key for mchar_define_charset () (which see). */ 
844
845 MSymbol Mmethod;
846 MSymbol Mdimension;
847 MSymbol Mmin_range;
848 MSymbol Mmax_range;
849 MSymbol Mmin_code;
850 MSymbol Mmax_code;
851 MSymbol Mascii_compatible;
852 MSymbol Mfinal_byte;
853 MSymbol Mrevision;
854 MSymbol Mmin_char;
855 MSymbol Mmapfile;
856 MSymbol Mparents;
857 MSymbol Msubset_offset;
858 MSymbol Mdefine_coding;
859 MSymbol Maliases;
860 /*=*/
861 /*** @} */
862 /*=*/
863
864 /***en
865     @name Variables: Symbols representing charset methods.
866
867     These are the predefined symbols that can be a value of the
868     #Mmethod parameter of a charset used in an argument to the
869     mchar_define_charset () function.
870
871     A method specifies how code-points and character codes are
872     converted.  See the documentation of the mchar_define_charset ()
873     function for the details.  */
874
875 /***ja
876     @name ÊÑ¿ô: Ê¸»ú¥»¥Ã¥È¤Î¥á¥½¥Ã¥É»ØÄê¤Ë»È¤ï¤ì¤ë¥·¥ó¥Ü¥ë
877
878     ¤³¤ì¤é¤Ï¡¢Ê¸»ú¥»¥Ã¥È¤Î @e ¥á¥½¥Ã¥É ¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢
879     ´Ø¿ô mchar_define_charset () ¤Î°ú¿ô¤È¤·¤Æ»È¤ï¤ì¤ë¡£
880
881     ¥á¥½¥Ã¥É¤È¤Ï¡¢¥³¡¼¥É¥Ý¥¤¥ó¥È¤Èʸ»ú¥³¡¼¥É¤òÁê¸ßÊÑ´¹¤¹¤ëºÝ¤ÎÊý¼°¤Î¤³
882     ¤È¤Ç¤¢¤ë¡£¾Ü¤·¤¯¤Ï´Ø¿ô mchar_define_charset () ¤Î²òÀâ¤ò»²¾È¤Î¤³¤È¡£  */
883 /*** @{ */
884 /*=*/
885 /***en
886     @brief Symbol for the offset type method of charset.
887
888     The symbol #Moffset has the name <tt>"offset"</tt> and, when used
889     as a value of #Mmethod parameter of a charset, it means that the
890     conversion of code-points and character codes of the charset is
891     done by this calculation:
892
893 @verbatim
894 CHARACTER-CODE = CODE-POINT - MIN-CODE + MIN-CHAR
895 @endverbatim
896
897     where, MIN-CODE is a value of #Mmin_code parameter of the charset,
898     and MIN-CHAR is a value of #Mmin_char parameter.  */
899
900 /***ja
901     @brief ¥ª¥Õ¥»¥Ã¥È·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
902
903     ¥·¥ó¥Ü¥ë #Moffset ¤Ï <tt>"offset"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
904     mchar_define_charset () ¤Ç¥ª¥Õ¥»¥Ã¥È·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú
905     ¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¡£*/
906
907 MSymbol Moffset;
908 /*=*/
909
910 /***en @brief Symbol for the map type method of charset.
911
912     The symbol #Mmap has the name <tt>"map"</tt> and, when use as a
913     value of #Mmethod parameter of a charset, it means that the
914     conversion of code-points and character codes of the charset is
915     done by map looking up.  The map must be given by #Mmapfile
916     parameter.  */
917
918 /***ja @brief ¥Þ¥Ã¥×·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
919
920     ¥·¥ó¥Ü¥ë #Mmap ¤Ï <tt>"map"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
921     mchar_define_charset () ¤Ç¥Þ¥Ã¥×·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú¿ô¤È
922     ¤·¤ÆÍѤ¤¤é¤ì¤ë¡£*/
923
924 MSymbol Mmap;
925 /*=*/
926
927 /***en @brief Symbol for the unify type method of charset.
928
929     The symbol #Munify has the name <tt>"unify"</tt> and, when used as
930     a value of #Mmethod parameter of a charset, it means that the
931     conversion of code-points and character codes of the charset is
932     done by map looking up and offsetting.  The map must be given by
933     #Mmapfile parameter.  For this kind of charset, a unique
934     consequent character code space for all characters is assigned.
935     If the map has an entry for a code-point, the conversion is done
936     by looking up the map.  Otherwise, the conversion is done by this
937     calculation:
938
939 @verbatim
940 CHARACTER-CODE = CODE-POINT - MIN-CODE + LOWEST-CHAR-CODE
941 @endverbatim
942
943     where, MIN-CODE is a value of #Mmin_code parameter of the charset,
944     and LOWEST-CHAR-CODE is the lowest character code of the assigned
945     code space.  */
946
947 /***ja @brief Áê³·¿¤Î¥á¥½¥Ã¥É¤ò¼¨¤¹¥·¥ó¥Ü¥ë
948
949     ¥·¥ó¥Ü¥ë #Minherit ¤Ï <tt>"inherit"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
950     mchar_define_charset () ¤ÇÁê³·¿¤Î¥á¥½¥Ã¥É¤ò»ØÄꤹ¤ë¾ì¹ç¤Î°ú¿ô¤È¤·
951     ¤ÆÍѤ¤¤é¤ì¤ë¡£*/
952
953 MSymbol Munify;
954 /*=*/
955
956 /***en
957     @brief Symbol for the subset type method of charset.
958
959     The symbol #Msubset has the name <tt>"subset"</tt> and, when used
960     as a value of #Mmethod parameter of a charset, it means that the
961     charset is a subset of a parent charset.  The parent charset must
962     be given by #Mparents parameter.  The conversion of code-points
963     and character codes of the charset is done conceptually by this
964     calculation:
965
966 @verbatim
967 CHARACTER-CODE = PARENT-CODE (CODE-POINT) + SUBSET-OFFSET
968 @endverbatim
969
970     where, PARENT-CODE is a pseudo function that returns a character
971     code of CODE-POINT in the parent charset, and SUBSET-OFFSET is a
972     value given by #Msubset_offset parameter.  */
973
974 MSymbol Msubset;
975 /*=*/
976
977 /***en
978     @brief Symbol for the superset type method of charset.
979
980     The symbol #Msuperset has the name <tt>"superset"</tt> and, when
981     used as a value of #Mmethod parameter of a charset, it means that
982     the charset is a superset of parent charsets.  The parent charsets
983     must be given by #Mparents parameter.  */
984
985 MSymbol Msuperset;
986 /*=*/
987 /*** @}  */ 
988
989 /***en
990     @brief Define a charset.
991
992     The mchar_define_charset () function defines a new charset and
993     makes it accessible via a symbol whose name is $NAME.  $PLIST
994     specifies parameters of the charset as below:
995
996     <ul>
997
998     <li> Key is #Mmethod, value is a symbol.
999
1000     The value specifies the method for decoding/encoding code-points
1001     in the charset.  It must be #Moffset, #Mmap (default), #Munify,
1002     #Msubset, or #Msuperset.
1003
1004     <li> Key is #Mdimension, value is an integer
1005
1006     The value specifies the dimension of code-points of the charset.
1007     It must be 1 (default), 2, 3, or 4.
1008
1009     <li> Key is #Mmin_range, value is an unsigned integer
1010
1011     The value specifies the minimum range of a code-point, which means
1012     that the Nth byte of the value is the minimum Nth byte of
1013     code-points of the charset.   The default value is 0.
1014
1015     <li> Key is #Mmax_range, value is an unsigned integer
1016
1017     The value specifies the maximum range of a code-point, which means
1018     that the Nth byte of the value is the maximum Nth byte of
1019     code-points of the charset.  The default value is 0xFF, 0xFFFF,
1020     0xFFFFFF, or 0xFFFFFFFF if the dimension is 1, 2, 3, or 4
1021     respectively.
1022
1023     <li> Key is #Mmin_code, value is an unsigned integer
1024
1025     The value specifies the minimum code-point of
1026     the charset.  The default value is the minimum range.
1027
1028     <li> Key is #Mmax_code, value is an unsigned integer
1029
1030     The value specifies the maximum code-point of
1031     the charset.  The default value is the maximum range.
1032
1033     <li> Key is #Mascii_compatible, value is a symbol
1034
1035     The value specifies whether the charset is ASCII compatible or
1036     not.  If the value is #Mnil (default), it is not ASCII
1037     compatible, else compatible.
1038
1039     <li> Key is #Mfinal_byte, value is an integer
1040
1041     The value specifies the @e final @e byte of the charset registered
1042     in The International Registry.  It must be 0 (default) or 32..127.
1043     The value 0 means that the charset is not in the registry.
1044
1045     <li> Key is #Mrevision, value is an integer
1046
1047     The value specifies the @e revision @e number of the charset
1048     registered in The International Registry.  it must be 0..127.  If
1049     the charset is not in The International Registry, the value is
1050     ignored.  The value 0 means that the charset has no revision
1051     number.
1052
1053     <li> Key is #Mmin_char, value is an integer
1054
1055     The value specifies the minimum character code of the charset.
1056     The default value is 0.
1057
1058     <li> Key is #Mmapfile, value is an M-text
1059
1060     If the method is #Mmap or #Munify, a data that contains
1061     mapping information is added to the m17n database by calling
1062     mdatabase_define () with the value as an argument $EXTRA_INFO,
1063     i.e. the value is used as a file name of the data.
1064
1065     Otherwise, this parameter is ignored.
1066
1067     <li> Key is #Mparents, value is a plist
1068
1069     If the method is #Msubset, the value must is a plist of length
1070     1, and the value of the plist must be a symbol representing a
1071     parent charset.
1072
1073     If the method is #Msuperset, the value must be a plist of length
1074     less than 9, and the values of the plist must be symbols
1075     representing subset charsets.
1076
1077     Otherwise, this parameter is ignored.
1078
1079     <li> Key is #Mdefine_coding, value is a symbol
1080
1081     If the dimension of the charset is 1, the value specifies whether
1082     or not to define a coding system of the same name whose method is
1083     @c charset.
1084
1085     Otherwise, this parameter is ignored.
1086
1087     </ul>
1088
1089     @return
1090     If the operation was successful, mchar_define_charset () returns a
1091     symbol whose name is $NAME.  Otherwise it returns #Mnil and
1092     assigns an error code to the external variable #merror_code.  */
1093
1094 /***ja
1095     @brief Ê¸»ú¥»¥Ã¥È¤òÄêµÁ¤¹¤ë.
1096
1097     ´Ø¿ô mchar_define_charset () ¤Ï¿·¤·¤¤Ê¸»ú¥»¥Ã¥È¤òÄêµÁ¤·¡¢¤½¤ì¤ò 
1098     $NAME ¤È¤¤¤¦Ì¾Á°¤Î¥·¥ó¥Ü¥ë·Ðͳ¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£$METHOD 
1099     ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤Ë¤ª¤±¤ë¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î¥Ç¥³¡¼¥É¡¿¥¨¥ó¥³¡¼¥É¥á¥½¥Ã
1100     ¥É¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë¤Ç¤¢¤ê¡¢#Moffset, #Mmap, #Munify,
1101     #Msubset, #Msuperset ¤Î¤¤¤º¤ì¤«¤ÎÃͤò¤È¤ë¡£
1102
1103     $DIMENSION ¤Ï¤½¤Îʸ»ú¥»¥Ã¥È¤Î¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î¼¡¸µ¤Ç¤¢¤ê¡¢1, 2, 3,
1104     4¤Î¤¤¤º¤ì¤«¤ÎÃͤò¤È¤ë¡£
1105
1106     $CODE_RANGE ¤ÏÂ礭¤µ¤¬8¥Ð¥¤¥È¤ÎÇÛÎó¤Ç¤¢¤ê¡¢ÄêµÁ¤µ¤ì¤ëʸ»ú¥»¥Ã¥È¤Î
1107     ¥³¡¼¥É¥Ý¥¤¥ó¥È¶õ´Ö¤òɽ¤ï¤¹¡£Âè1¥Ð¥¤¥È¤ÈÂè2¥Ð¥¤¥È¤ÎÃͤϥ³¡¼¥É¥Ý¥¤¥ó
1108     ¥È¤ÎºÇ½é¤Î¼¡¸µ¤Ç¤ÎºÇ¾®¡¿ºÇÂç¥Ð¥¤¥È¤ÎÃͤǤ¢¤ë¡£Âè3¥Ð¥¤¥È¤ÈÂè4¥Ð¥¤¥È
1109     ¤Ï¡¢2ÈÖÌܤμ¡¸µ¤ÎºÇ¾®¡¿ºÇÂçÃͤǤ¢¤ê¡¢ °Ê²¼Æ±Íͤ˳¤¯¡£°ìÈÌŪ¤Ë¡¢Âè
1110     (2N-1)¥Ð¥¤¥È¤ÈÂè(2N)¥Ð¥¤¥È¤¬NÈÖÌܤμ¡¸µ¤ÎºÇ¾®¡¿ºÇÂçÃͤȤʤë (N =
1111     1, 2, 3, 4)¡£¥³¡¼¥É¥Ý¥¤¥ó¥È¤Î @e Ê¸»ú¥¤¥ó¥Ç¥Ã¥¯¥¹ ¤Ï¤³¤ì¤é¤ÎÃͤ«¤é
1112     ·×»»¤µ¤ì¤ë¡£
1113
1114     $MIN_CODE ¤È $MAX_CODE ¤Ï¡¢¤½¤ì¤¾¤ì¤³¤Îʸ»ú¥»¥Ã¥È¤ÎºÇ¾®¤ª¤è¤ÓºÇÂç
1115     ¥³¡¼¥É¥Ý¥¤¥ó¥È¤òɽ¤ï¤¹¡£0¤¬»ØÄꤵ¤ì¤¿¾ì¹ç¤Ï $CODE_RANGE ¤ÎÃͤ«¤é·×
1116     »»¤µ¤ì¤ë¡£
1117
1118     $FINAL_BYTE ¤Ï The International Registry ¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë
1119     @e ½ªÃ¼¥Ð¥¤¥È ¤Ç¤¢¤ë¡£ÅÐÏ¿¤µ¤ì¤Æ¤¤¤Ê¤¤ CCS ¤Î¾ì¹ç¤Ë¤Ï -1 ¤Ç¤Ê¤¯¤Æ¤Ï
1120     ¤Ê¤é¤Ê¤¤¡£
1121
1122     $REVISION ¤Ï¡¢The International Registry ¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë@e revision
1123     @e number ¤Ç¤¢¤ë¡£¤â¤· revision number ¤¬Â¸ºß¤·¤Ê¤¤¤Ê¤é -1 ¤Ç¤Ê¤¯
1124     ¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1125
1126     @par ¥á¥½¥Ã¥É¤¬ Moffset ¤Î¾ì¹ç
1127
1128     $MIN_CHAR ¤Ë¤ÏºÇ¾®¤Î¥³¡¼¥É¥Ý¥¤¥ó¥È¤ËÂбþ¤¹¤ëʸ»ú¥³¡¼¥É¤òÍ¿¤¨¤ë¡£
1129     $NPARENTS, $PARENTS, ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1130
1131     @par ¥á¥½¥Ã¥É¤¬ Mmap ¤Î¾ì¹ç
1132
1133     m17n ¸À¸ì¾ðÊó¥Ù¡¼¥¹Ãæ¤Ç \<#Mcharset, $NAME\> ¤È¤¤¤¦¥¿¥°¤ÎÉÕ¤¤¤¿
1134     ¥Þ¥Ã¥Ô¥ó¥°¥Æ¡¼¥Ö¥ë¤ò¡¢¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤ËÍѤ¤¤ë¡£$MIN_CHAR,
1135     $NPARENTS, $PARENTS, ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1136
1137     @par ¥á¥½¥Ã¥É¤¬ Msubset ¤Î¾ì¹ç
1138
1139     $NPARENTS ¤Ï1¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£¤Þ¤¿ $PARENTS ¤Ï·Ñ¾µ¤Î¸µ¤È¤Ê¤ëʸ
1140     »ú¥»¥Ã¥È¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¸µ¤Îʸ»ú¥»¥Ã¥È¤Î¥³¡¼¥É
1141     ¥Ý¥¤¥ó¥È¤Ë $SUBSET_OFFSET ¤ò²Ã¤¨¤¿¤â¤Î¤¬¡¢¿·¤·¤¤Ê¸»ú¥»¥Ã¥ÈÃæ¤Ç¤Î¥³¡¼
1142     ¥É¥Ý¥¤¥ó¥È¤Ë¤Ê¤ë¡£$MIN_CHAR ¤Ï̵»ë¤µ¤ì¤ë¡£
1143
1144     @par ¥á¥½¥Ã¥É¤¬ Msuperset ¤Î¾ì¹ç
1145
1146     $NPARENTS ¤Ï¿Æ¤È¤Ê¤ëʸ»ú¥»¥Ã¥È¤Î¿ô¡¢$PARENTS ¤Ï¿Æʸ»ú¥»¥Ã¥È¤Î¥·¥ó
1147     ¥Ü¥ë¤ÎÇÛÎó¤òɽ¤ï¤¹¡£$MIN_CHAR ¤ª¤è¤Ó $SUBSET_OFFSET ¤Ï̵»ë¤µ¤ì¤ë¡£
1148
1149     @return
1150     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_define_charset () ¤Ï $NAME ¤È¤¤¤¦Ì¾Á°¤Î¥·
1151     ¥ó¥Ü¥ë¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #Mnil ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô @c
1152     merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1153
1154 /***
1155     @errors
1156     @c MERROR_CHARSET  */
1157
1158 MSymbol
1159 mchar_define_charset (char *name, MPlist *plist)
1160 {
1161   MSymbol sym = msymbol (name);
1162   MCharset *charset;
1163   int i;
1164   unsigned min_range, max_range;
1165   MPlist *pl;
1166   MText *mapfile = (MText *) mplist_get (plist, Mmapfile);
1167
1168   MSTRUCT_CALLOC (charset, MERROR_CHARSET);
1169   charset->name = sym;
1170   charset->method = (MSymbol) mplist_get (plist, Mmethod);
1171   if (! charset->method)
1172     {
1173       if (mapfile)
1174         charset->method = Mmap;
1175       else
1176         charset->method = Moffset;
1177     }
1178   if (charset->method == Mmap || charset->method == Munify)
1179     {
1180       if (! mapfile)
1181         MERROR (MERROR_CHARSET, Mnil);
1182       mdatabase_define (Mcharset, sym, Mnil, Mnil, NULL, mapfile->data);
1183     }
1184   if (! (charset->dimension = (int) mplist_get (plist, Mdimension)))
1185     charset->dimension = 1;
1186
1187   min_range = (unsigned) mplist_get (plist, Mmin_range);
1188   if ((pl = mplist_find_by_key (plist, Mmax_range)))
1189     {
1190       max_range = (unsigned) MPLIST_VAL (pl);
1191       if (max_range >= 0x1000000)
1192         charset->dimension = 4;
1193       else if (max_range >= 0x10000 && charset->dimension < 3)
1194         charset->dimension = 3;
1195       else if (max_range >= 0x100 && charset->dimension < 2)
1196         charset->dimension = 2;
1197     }
1198   else if (charset->dimension == 1)
1199     max_range = 0xFF;
1200   else if (charset->dimension == 2)
1201     max_range = 0xFFFF;
1202   else if (charset->dimension == 3)
1203     max_range = 0xFFFFFF;
1204   else
1205     max_range = 0xFFFFFFFF;
1206
1207   memset (charset->code_range, 0, sizeof charset->code_range);
1208   for (i = 0; i < charset->dimension; i++, min_range >>= 8, max_range >>= 8)
1209     {
1210       charset->code_range[i * 4] = min_range & 0xFF;
1211       charset->code_range[i * 4 + 1] = max_range & 0xFF;
1212     }
1213   if ((charset->min_code = (int) mplist_get (plist, Mmin_code)) < min_range)
1214     charset->min_code = min_range;
1215   if ((charset->max_code = (int) mplist_get (plist, Mmax_code)) > max_range)
1216     charset->max_code = max_range;
1217   charset->ascii_compatible
1218     = (MSymbol) mplist_get (plist, Mascii_compatible) != Mnil;
1219   charset->final_byte = (int) mplist_get (plist, Mfinal_byte);
1220   charset->revision = (int) mplist_get (plist, Mrevision);
1221   charset->min_char = (int) mplist_get (plist, Mmin_char);
1222   pl = (MPlist *) mplist_get (plist, Mparents);
1223   charset->nparents = pl ? mplist_length (pl) : 0;
1224   if (charset->nparents > 8)
1225     charset->nparents = 8;
1226   for (i = 0; i < charset->nparents; i++, pl = MPLIST_NEXT (pl))
1227     {
1228       MSymbol parent_name;
1229
1230       if (MPLIST_KEY (pl) != Msymbol)
1231         MERROR (MERROR_CHARSET, Mnil);
1232       parent_name = MPLIST_SYMBOL (pl);
1233       if (! (charset->parents[i] = MCHARSET (parent_name)))
1234         MERROR (MERROR_CHARSET, Mnil);
1235     }
1236
1237   charset->subset_offset = (int) mplist_get (plist, Msubset_offset);
1238
1239   msymbol_put (sym, Mcharset, charset);
1240   charset = make_charset (charset);
1241   if (! charset)
1242     return Mnil;
1243   msymbol_put (msymbol__canonicalize (sym), Mcharset, charset);
1244
1245   for (pl = (MPlist *) mplist_get (plist, Maliases);
1246        pl && MPLIST_KEY (pl) == Msymbol;
1247        pl = MPLIST_NEXT (pl))
1248     {
1249       MSymbol alias = MPLIST_SYMBOL (pl);
1250
1251       msymbol_put (alias, Mcharset, charset);
1252       msymbol_put (msymbol__canonicalize (alias), Mcharset, charset);
1253     }
1254
1255   if (mplist_get (plist, Mdefine_coding)
1256       && charset->dimension == 1
1257       && charset->code_range[0] == 0 && charset->code_range[1] == 255)
1258     mconv__register_charset_coding (sym);
1259   return (sym);
1260 }
1261
1262 /*=*/
1263
1264 /***en
1265     @brief Resolve charset name.
1266
1267     The mchar_resolve_charset () function returns $SYMBOL if it
1268     represents a charset.  Otherwise, canonicalize $SYMBOL as to a
1269     charset name, and if the canonicalized name represents a charset,
1270     return it.  Otherwise, return #Mnil.  */
1271
1272 MSymbol
1273 mchar_resolve_charset (MSymbol symbol)
1274 {
1275   MCharset *charset = (MCharset *) msymbol_get (symbol, Mcharset);
1276
1277   if (! charset)
1278     {
1279       symbol = msymbol__canonicalize (symbol);
1280       charset = (MCharset *) msymbol_get (symbol, Mcharset);
1281     }
1282
1283   return (charset ? charset->name : Mnil);
1284 }
1285
1286 /*=*/
1287
1288 /***en
1289     @brief List symbols representing a charset.
1290
1291     The mchar_list_charsets () function makes an array of symbols
1292     representing a charset, stores the pointer to the array in a place
1293     pointed to by $SYMBOLS, and returns the length of the array.  */
1294
1295 int
1296 mchar_list_charset (MSymbol **symbols)
1297 {
1298   int i;
1299
1300   MTABLE_MALLOC ((*symbols), charset_list.used, MERROR_CHARSET);
1301   for (i = 0; i < charset_list.used; i++)
1302     (*symbols)[i] = charset_list.charsets[i]->name;
1303   return i;
1304 }
1305
1306 /*=*/
1307
1308 /***en
1309     @brief Decode a code-point.
1310
1311     The mchar_decode () function decodes code-point $CODE in the
1312     charset represented by the symbol $CHARSET_NAME to get a character
1313     code.
1314
1315     @return
1316     If decoding was successful, mchar_decode () returns the decoded
1317     character code.  Otherwise it returns -1.  */
1318
1319 /***ja
1320     @brief ¥³¡¼¥É¥Ý¥¤¥ó¥È¤ò¥Ç¥³¡¼¥É¤¹¤ë
1321
1322     ´Ø¿ô mchar_decode () ¤Ï¡¢¥·¥ó¥Ü¥ë $CHARSET_NAME ¤Ç¼¨¤µ¤ì¤ëʸ»ú¥»¥Ã
1323     ¥ÈÆâ¤Î $CODE ¤È¤¤¤¦¥³¡¼¥É¥Ý¥¤¥ó¥È¤ò¥Ç¥³¡¼¥É¤·¤Æʸ»ú¥³¡¼¥É¤òÆÀ¤ë¡£
1324
1325     @return
1326     ¥Ç¥³¡¼¥É¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_decode () ¤Ï¥Ç¥³¡¼¥É¤µ¤ì¤¿Ê¸»ú¥³¡¼¥É¤ò
1327     ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£  */
1328
1329 /***
1330     @seealso
1331     mchar_encode ()  */
1332
1333 int
1334 mchar_decode (MSymbol charset_name, unsigned code)
1335 {
1336   MCharset *charset = MCHARSET (charset_name);
1337
1338   if (! charset)
1339     return MCHAR_INVALID_CODE;
1340   return DECODE_CHAR (charset, code);
1341 }
1342
1343 /*=*/
1344
1345 /***en
1346     @brief Encode a character code.
1347
1348     The mchar_encode () function encodes character code $C to get a
1349     code-point in the charset represented by the symbol $CHARSET_NAME.
1350
1351     @return
1352     If encoding was successful, mchar_encode () returns the encoded
1353     code-point.  Otherwise it returns #MCHAR_INVALID_CODE.  */
1354
1355 /***ja
1356     @brief Ê¸»ú¥³¡¼¥É¤ò¥¨¥ó¥³¡¼¥É¤¹¤ë
1357
1358     ´Ø¿ô mchar_encode () ¤Ï¡¢Ê¸»ú¥³¡¼¥É $C ¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¥·¥ó¥Ü¥ë
1359     $CHARSET_NAME ¤Ç¼¨¤µ¤ì¤ëʸ»ú¥»¥Ã¥ÈÆâ¤Ë¤ª¤±¤ë¥³¡¼¥É¥Ý¥¤¥ó¥È¤òÆÀ¤ë¡£
1360
1361     @return
1362     ¥¨¥ó¥³¡¼¥É¤¬À®¸ù¤¹¤ì¤Ð¡¢mchar_encode () ¤Ï¥¨¥ó¡¼¥É¤µ¤ì¤¿¥³¡¼¥É¥Ý¥¤
1363     ¥ó¥È¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð #MCHAR_INVALID_CODE ¤òÊÖ¤¹¡£  */
1364
1365 /***
1366     @seealso
1367     mchar_decode ()  */
1368
1369 unsigned
1370 mchar_encode (MSymbol charset_name, int c)
1371 {
1372   MCharset *charset = MCHARSET (charset_name);
1373
1374   if (! charset)
1375     return MCHAR_INVALID_CODE;
1376   return ENCODE_CHAR (charset, c);
1377 }
1378
1379 /*=*/
1380
1381 /***en
1382     @brief Call a function for all the characters in a specified charset.
1383
1384     The mcharset_map_chars () function calls $FUNC for all the
1385     characters in the charset named $CHARSET_NAME.  A call is done for
1386     a chunk of consecutive characters rather than character by
1387     character.
1388
1389     $FUNC receives three arguments: $FROM, $TO, and $ARG.  $FROM and
1390     $TO specify the range of character codes in $CHARSET.  $ARG is the
1391     same as $FUNC_ARG.
1392
1393     @return
1394     If the operation was successful, mcharset_map_chars () returns 0.
1395     Otherwise, it returns -1 and assigns an error code to the external
1396     variable #merror_code.  */
1397
1398 /***ja
1399     @brief »ØÄꤷ¤¿Ê¸»ú¥»¥Ã¥È¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ËÂФ·¤Æ´Ø¿ô¤ò¸Æ¤Ö
1400
1401     ´Ø¿ô mcharset_map_chars () ¤Ï $CHARSET_NAME ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Äʸ»ú¥»¥Ã
1402     ¥ÈÃæ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ËÂФ·¤Æ $FUNC ¤ò¸Æ¤Ö¡£¸Æ¤Ó½Ð¤·¤Ï°ìʸ»úËè¤Ç¤Ï¤Ê
1403     ¤¯¡¢Ï¢Â³¤·¤¿Ê¸»ú¤Î¤Þ¤È¤Þ¤êñ°Ì¤Ç¹Ô¤Ê¤ï¤ì¤ë¡£
1404
1405     ´Ø¿ô $FUNC ¤Ë¤Ï$FROM, $TO, $ARG ¤Î£³°ú¿ô¤¬ÅϤµ¤ì¤ë¡£$FROM ¤È $TO 
1406     ¤Ï $CHARSET Ãæ¤Îʸ»ú¥³¡¼¥É¤ÎÈϰϤò»ØÄꤹ¤ë¡£$ARG ¤Ï $FUNC_ARG ¤ÈƱ
1407     ¤¸¤Ç¤¢¤ë¡£
1408
1409     @return
1410     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mcharset_map_chars () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð 
1411     -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
1412
1413 /*** 
1414     @errors
1415     @c MERROR_CHARSET */
1416
1417 int
1418 mchar_map_charset (MSymbol charset_name,
1419                    void (*func) (int from, int to, void *arg),
1420                    void *func_arg)
1421 {
1422   MCharset *charset;
1423
1424   charset = MCHARSET (charset_name);
1425   if (! charset)
1426     MERROR (MERROR_CHARSET, -1);
1427
1428   if (charset->encoder)
1429     {
1430       int c = charset->min_char;
1431       int next_c;
1432
1433       if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) < 0)
1434         c = next_c;
1435       while (c <= charset->max_char)
1436         {
1437           if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) >= 0)
1438             (*func) (c, next_c - 1, func_arg);    
1439           c = next_c;
1440         }
1441     }
1442   else
1443     (*func) (charset->min_char, charset->max_char, func_arg);
1444   return 0;
1445 }
1446
1447 /*=*/
1448
1449 /*** @} */
1450
1451 /*
1452   Local Variables:
1453   coding: euc-japan
1454   End:
1455 */