merge FLT
[m17n/m17n-lib.git] / src / coding.c
1 /* coding.c -- code conversion 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., 51 Franklin Street, Fifth Floor,
21    02111-1307, USA.  */
22
23 /***en
24     @addtogroup m17nConv
25     @brief Coding system objects and API for them.
26
27     The m17n library represents a character encoding scheme (CES) of
28     coded character sets (CCS) as an object called @e coding @e
29     system.  Application programs can add original coding systems.
30
31     To @e encode means converting code-points to character codes and
32     to @e decode means converting character codes back to code-points.
33
34     Application programs can decode a byte sequence with a specified
35     coding system into an M-text, and inversely, can encode an M-text
36     into a byte sequence.  */
37
38 /***ja
39     @addtogroup m17nConv
40     @brief ¥³¡¼¥É·Ï¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
41
42     m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢Éä¹æ²½Ê¸»ú½¸¹ç (coded character set; CCS) 
43     ¤Îʸ»úÉä¹ç²½Êý¼° (character encoding scheme; CES) ¤ò @e ¥³¡¼¥É·Ï 
44     ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤Çɽ¸½¤¹¤ë¡£
45     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤ÏÆȼ«¤Ë¥³¡¼¥É·Ï¤òÄɲ乤뤳¤È¤â¤Ç¤­¤ë¡£
46
47     ¥³¡¼¥É¥Ý¥¤¥ó¥È¤«¤éʸ»ú¥³¡¼¥É¤Ø¤ÎÊÑ´¹¤ò @e ¥¨¥ó¥³¡¼¥É 
48     ¤È¸Æ¤Ó¡¢Ê¸»ú¥³¡¼¥É¤«¤é¥³¡¼¥É¥Ý¥¤¥ó¥È¤Ø¤ÎÊÑ´¹¤ò @e ¥Ç¥³¡¼¥É ¤È¸Æ¤Ö¡£
49
50     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤Ï¡¢»ØÄꤵ¤ì¤¿¥³¡¼¥É·Ï¤Ç¥Ð¥¤¥ÈÎó¤ò¥Ç¥³¡¼¥É¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ
51     M-text ¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¡£¤Þ¤¿µÕ¤Ë¡¢»ØÄꤵ¤ì¤¿¥³¡¼¥É·Ï¤Ç M-text 
52     ¤ò¥¨¥ó¥³¡¼¥É¤·¤¹¤ë¤³¤È¤Ë¤è¤Ã¤Æ¥Ð¥¤¥ÈÎó¤òÆÀ¤ë¤³¤È¤¬¤Ç¤­¤ë¡£  */
53
54 /*=*/
55
56 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
57 /*** @addtogroup m17nInternal
58      @{ */
59
60 #include <config.h>
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <ctype.h>
64 #include <string.h>
65 #include <sys/types.h>
66 #include <unistd.h>
67 #include <errno.h>
68
69 #include "m17n.h"
70 #include "m17n-misc.h"
71 #include "internal.h"
72 #include "plist.h"
73 #include "character.h"
74 #include "charset.h"
75 #include "coding.h"
76 #include "mtext.h"
77 #include "symbol.h"
78 #include "mlocale.h"
79
80 #define NUM_SUPPORTED_CHARSETS 32
81
82 /** Structure for coding system object.  */
83
84 typedef struct
85 {
86   /** Name of the coding system.  */
87   MSymbol name;
88
89   /** Type of the coding system.  */
90   MSymbol type;
91
92   /* Number of supported charsets.  */
93   int ncharsets;
94
95   /** Array of supported charsets.  */
96   MCharset *charsets[NUM_SUPPORTED_CHARSETS];
97
98   /** If non-NULL, function to call at the time of creating and
99       reseting a converter.  */
100   int (*resetter) (MConverter *converter);
101
102   int (*decoder) (const unsigned char *str, int str_bytes, MText *mt,
103                   MConverter *converter);
104
105   int (*encoder) (MText *mt, int from, int to,
106                   unsigned char *str, int str_bytes,
107                   MConverter *converter);
108
109   /** If non-zero, the coding system decode/encode ASCII characters as
110       is.  */
111   int ascii_compatible;
112
113   /** Pointer to extra information given when the coding system is
114       defined.  The meaning depends on <type>.  */
115   void *extra_info;
116
117   /** Pointer to information referred on conversion.  The meaning
118       depends on <type>.  The value NULL means that the coding system
119       is not yet setup.  */
120   void *extra_spec;
121
122   int ready;
123 } MCodingSystem;
124
125 struct MCodingList
126 {
127   int size, inc, used;
128   MCodingSystem **codings;
129 };
130
131 static struct MCodingList coding_list;
132
133 static MPlist *coding_definition_list;
134
135 typedef struct {
136   /**en
137      Pointer to a structure of a coding system.  */
138   /**ja
139      ¥³¡¼¥É·Ï¤òɽ¤ï¤¹¥Ç¡¼¥¿¹½Â¤¤Ø¤Î¥Ý¥¤¥ó¥¿ */
140   MCodingSystem *coding;
141
142   /**en
143      Buffer for carryover bytes generated while decoding. */
144   /**ja
145      ¥Ç¥³¡¼¥ÉÃæ¤Î¥­¥ã¥ê¥£¥ª¡¼¥Ð¡¼¥Ð¥¤¥ÈÍѥХåե¡ */
146   unsigned char carryover[256];
147
148   /**en
149      Number of carryover bytes. */
150   /**ja
151      ¥­¥ã¥ê¥£¥ª¡¼¥Ð¡¼¥Ð¥¤¥È¿ô */
152   int carryover_bytes;
153
154   /**en
155      Beginning of the byte sequence bound to this converter. */
156   /**ja
157      ¤³¤Î¥³¥ó¥Ð¡¼¥¿¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥Ð¥¤¥ÈÎó¤ÎÀèƬ°ÌÃÖ */
158   union {
159     const unsigned char *in;
160     unsigned char *out;
161   } buf;
162
163   /**en
164      Size of buf. */
165   /**ja
166      buf ¤ÎÂ礭¤µ */
167   int bufsize;
168
169   /**en
170      Number of bytes already consumed in buf. */
171   /**ja
172      buf Æâ¤Ç¤¹¤Ç¤Ë¾ÃÈñ¤µ¤ì¤¿¥Ð¥¤¥È¿ô */
173   int used;
174
175   /**en
176      Stream bound to this converter. */
177   /**ja
178      ¤³¤Î¥³¥ó¥Ð¡¼¥¿¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥¹¥È¥ê¡¼¥à */
179   FILE *fp;
180
181   /**en
182      Which of above two is in use. */
183   /**ja
184      ¾åµ­2¼Ô¤Î¤¤¤º¤ì¤¬»È¤ï¤ì¤Æ¤¤¤ë¤« */
185   int binding;
186
187   /**en
188      Buffer for unget. */
189   /**ja
190      Unget ÍѥХåե¡ */
191   MText *unread;
192
193   /*en
194     Working area. */
195   /*ja
196     ºî¶ÈÎΰè */
197   MText *work_mt;
198
199   int seekable;
200 } MConverterStatus;
201
202
203 \f
204 /* Local macros and functions.  */
205
206 /** At first, set SRC_BASE to SRC.  Then check if we have already
207     produced AT_MOST chars.  If so, set SRC_END to SRC, and jump to
208     source_end.  Otherwise, get one more byte C from SRC.  In that
209     case, if SRC == SRC_END, jump to the label source_end.  */
210
211 #define ONE_MORE_BASE_BYTE(c)           \
212   do {                                  \
213     src_base = src;                     \
214     if (nchars == at_most)              \
215       {                                 \
216         src_end = src;                  \
217         goto source_end;                \
218       }                                 \
219     if (src == src_stop)                \
220       {                                 \
221         if (src == src_end)             \
222           goto source_end;              \
223         src_base = src = source;        \
224         if (src == src_end)             \
225           goto source_end;              \
226         src_stop = src_end;             \
227       }                                 \
228     (c) = *src++;                       \
229   } while (0)
230
231
232 /** Get one more byte C from SRC.  If SRC == SRC_END, jump to the
233    label source_end.  */
234
235 #define ONE_MORE_BYTE(c)        \
236   do {                          \
237     if (src == src_stop)        \
238       {                         \
239         if (src == src_end)     \
240           goto source_end;      \
241         src = source;           \
242         if (src == src_end)     \
243           goto source_end;      \
244         src_stop = src_end;     \
245       }                         \
246     (c) = *src++;               \
247   } while (0)
248
249
250 #define REWIND_SRC_TO_BASE()                                            \
251   do {                                                                  \
252     if (src_base < source || src_base >= src_end)                       \
253       src_stop = internal->carryover + internal->carryover_bytes;       \
254     src = src_base;                                                     \
255   } while (0)
256
257
258 /** Push back byte C to SRC.  */
259
260 #define UNGET_ONE_BYTE(c)               \
261   do {                                  \
262     if (src > source)                   \
263       src--;                            \
264     else                                \
265       {                                 \
266         internal->carryover[0] = c;     \
267         internal->carryover_bytes = 1;  \
268         src = internal->carryover;      \
269         src_stop = src + 1;             \
270       }                                 \
271   } while  (0);
272
273
274 /** Store multibyte representation of character C at DST and increment
275     DST to the next of the produced bytes.  DST must be a pointer to
276     data area of M-text MT.  If the produced bytes are going to exceed
277     DST_END, enlarge the data area of MT.  */
278
279 #define EMIT_CHAR(c)                                            \
280   do {                                                          \
281     int bytes = CHAR_BYTES (c);                                 \
282     int len;                                                    \
283                                                                 \
284     if (dst + bytes + 1 > dst_end)                              \
285       {                                                         \
286         len = dst - mt->data;                                   \
287         bytes = mt->allocated + bytes + (src_stop - src);       \
288         mtext__enlarge (mt, bytes);                             \
289         dst = mt->data + len;                                   \
290         dst_end = mt->data + mt->allocated;                     \
291       }                                                         \
292     dst += CHAR_STRING (c, dst);                                \
293     nchars++;                                                   \
294   } while (0)
295
296
297 /* Check if there is enough room to produce LEN bytes at DST.  If not,
298    go to the label insufficient_destination.  */
299
300 #define CHECK_DST(len)                  \
301   do {                                  \
302     if (dst + (len) > dst_end)          \
303       goto insufficient_destination;    \
304   } while (0)
305
306
307 /** Take NUM_CHARS characters (NUM_BYTES bytes) already stored at
308     (MT->data + MT->nbytes) into MT, and put charset property on
309     them with CHARSET->name.  */
310
311 #define TAKEIN_CHARS(mt, num_chars, num_bytes, charset)                 \
312   do {                                                                  \
313     int chars = (num_chars);                                            \
314                                                                         \
315     if (chars > 0)                                                      \
316       {                                                                 \
317         mtext__takein ((mt), chars, (num_bytes));                       \
318         if (charset)                                                    \
319           mtext_put_prop ((mt), (mt)->nchars - chars, (mt)->nchars,     \
320                           Mcharset, (void *) ((charset)->name));        \
321       }                                                                 \
322   } while (0)
323
324
325 #define SET_SRC(mt, format, from, to)                                   \
326   do {                                                                  \
327     if (format <= MTEXT_FORMAT_UTF_8)                                   \
328       {                                                                 \
329         src = mt->data + POS_CHAR_TO_BYTE (mt, from);                   \
330         src_end = mt->data + POS_CHAR_TO_BYTE (mt, to);                 \
331       }                                                                 \
332     else if (format <= MTEXT_FORMAT_UTF_16BE)                           \
333       {                                                                 \
334         src                                                             \
335           = mt->data + (sizeof (short)) * POS_CHAR_TO_BYTE (mt, from);  \
336         src_end                                                         \
337           = mt->data + (sizeof (short)) * POS_CHAR_TO_BYTE (mt, to);    \
338       }                                                                 \
339     else                                                                \
340       {                                                                 \
341         src = mt->data + (sizeof (int)) * from;                         \
342         src_end = mt->data + (sizeof (int)) * to;                       \
343       }                                                                 \
344   } while (0)
345
346
347 #define ONE_MORE_CHAR(c, bytes, format)                         \
348   do {                                                          \
349     if (src == src_end)                                         \
350       goto finish;                                              \
351     if (format <= MTEXT_FORMAT_UTF_8)                           \
352       c = STRING_CHAR_AND_BYTES (src, bytes);                   \
353     else if (format <= MTEXT_FORMAT_UTF_16BE)                   \
354       {                                                         \
355         c = mtext_ref_char (mt, from++);                        \
356         bytes = (sizeof (short)) * CHAR_UNITS_UTF16 (c);        \
357       }                                                         \
358     else                                                        \
359       {                                                         \
360         c = ((unsigned *) (mt->data))[from++];                  \
361         bytes = sizeof (int);                                   \
362       }                                                         \
363   } while (0)
364
365
366 static int
367 encode_unsupporeted_char (int c, unsigned char *dst, unsigned char *dst_end,
368                           MText *mt, int pos)
369 {
370   int len;
371   char *format;
372
373   len = c < 0x10000 ? 8 : 10;
374   if (dst + len > dst_end)
375     return 0;
376
377   mtext_put_prop (mt, pos, pos + 1, Mcoding, Mnil);
378   format = (c < 0xD800 ? "<U+%04X>"
379             : c < 0xE000 ? "<M+%04X>"
380             : c < 0x10000 ? "<U+%04X>"
381             : c < 0x110000 ? "<U+%06X>"
382             : "<M+%06X>");
383   sprintf ((char *) dst, format, c);
384   return len;
385 }
386
387
388
389 /** Finish decoding of bytes at SOURCE (ending at SRC_END) into NCHARS
390     characters by CONVERTER into M-text MT.  SRC is a pointer to the
391     not-yet processed bytes.  ERROR is 1 iff an invalid byte was
392     found.  */
393
394 static int
395 finish_decoding (MText *mt, MConverter *converter, int nchars,
396                  const unsigned char *source, const unsigned char *src_end,
397                  const unsigned char *src,
398                  int error)
399 {
400   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
401
402   if (src == src_end)
403     internal->carryover_bytes = 0;
404   else if (error
405            || (converter->last_block
406                && ! converter->lenient))
407     converter->result = MCONVERSION_RESULT_INVALID_BYTE;
408   else if (! converter->last_block)
409     {
410       unsigned char *dst = internal->carryover;
411
412       if (src < source || src > src_end)
413         {
414           dst += internal->carryover_bytes;
415           src = source;
416         }
417       while (src < src_end)
418         *dst++ = *src++;
419       internal->carryover_bytes = dst - internal->carryover;
420       converter->result = MCONVERSION_RESULT_INSUFFICIENT_SRC;
421     }
422   else
423     {
424       unsigned char *dst = mt->data + mt->nbytes;
425       unsigned char *dst_end = mt->data + mt->allocated;
426       const unsigned char *src_stop = src_end;
427       int c;
428       int last_nchars = nchars;
429
430       if (src < source || src > src_end)
431         src_stop = internal->carryover + internal->carryover_bytes;
432       while (1)
433         {
434           if (converter->at_most && nchars == converter->at_most)
435             break;
436           if (src == src_stop)
437             {
438               if (src == src_end)
439                 break;
440               src = source;
441               if (src == src_end)
442                 break;
443               src_stop = src_end;
444             }
445           c = *src++;
446           EMIT_CHAR (c);
447         }
448       TAKEIN_CHARS (mt, nchars - last_nchars, dst - (mt->data + mt->nbytes),
449                     mcharset__binary);
450       internal->carryover_bytes = 0;
451     }
452
453   converter->nchars += nchars;
454   converter->nbytes += ((src < source || src > src_end) ? 0 : src - source);
455   return (converter->result == MCONVERSION_RESULT_INVALID_BYTE ? -1 : 0);
456 }
457
458
459 \f
460 /* Staffs for coding-systems of type MCODING_TYPE_CHARSET.  */
461
462 static int
463 setup_coding_charset (MCodingSystem *coding)
464 {
465   int ncharsets = coding->ncharsets;
466   unsigned *code_charset_table;
467
468   if (ncharsets > 1)
469     {
470       /* At first, reorder charset list by dimensions (a charset of
471          smaller dimension comes first).  As the number of charsets is
472          usually very small (at most 32), we do a simple sort.  */
473       MCharset **charsets;
474       int idx = 0;
475       int i, j;
476
477       MTABLE_ALLOCA (charsets, NUM_SUPPORTED_CHARSETS, MERROR_CODING);
478       memcpy (charsets, coding->charsets,
479               sizeof (MCharset *) * NUM_SUPPORTED_CHARSETS);
480       for (i = 0; i < 4; i++)
481         for (j = 0; j < ncharsets; j++)
482           if (charsets[j]->dimension == i)
483             coding->charsets[idx++] = charsets[j];
484     }
485
486   MTABLE_CALLOC (code_charset_table, 256, MERROR_CODING);
487   while (ncharsets--)
488     {
489       int dim = coding->charsets[ncharsets]->dimension;
490       int from = coding->charsets[ncharsets]->code_range[(dim - 1) * 4];
491       int to = coding->charsets[ncharsets]->code_range[(dim - 1) * 4 + 1];
492
493       if (coding->charsets[ncharsets]->ascii_compatible)
494         coding->ascii_compatible = 1;
495       while (from <= to)
496         code_charset_table[from++] |= 1 << ncharsets;
497     }
498
499   coding->extra_spec = (void *) code_charset_table;
500   return 0;
501 }
502
503 static int
504 reset_coding_charset (MConverter *converter)
505 {
506   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
507   MCodingSystem *coding = internal->coding;
508
509   if (! coding->ready
510       && setup_coding_charset (coding) < 0)
511     return -1;
512   coding->ready = 1;
513   return 0;
514 }
515
516 static int
517 decode_coding_charset (const unsigned char *source, int src_bytes, MText *mt,
518                        MConverter *converter)
519 {
520   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
521   MCodingSystem *coding = internal->coding;
522   const unsigned char *src = internal->carryover;
523   const unsigned char *src_stop = src + internal->carryover_bytes;
524   const unsigned char *src_end = source + src_bytes;
525   const unsigned char *src_base;
526   unsigned char *dst = mt->data + mt->nbytes;
527   unsigned char *dst_end = mt->data + mt->allocated;
528   int nchars = 0;
529   int last_nchars = 0;
530   int at_most = converter->at_most > 0 ? converter->at_most : -1;
531
532   unsigned *code_charset_table = (unsigned *) coding->extra_spec;
533   MCharset **charsets = coding->charsets;
534   MCharset *charset = mcharset__ascii;
535   int error = 0;
536
537   while (1)
538     {
539       MCharset *this_charset = NULL;
540       int c;
541       unsigned mask;
542
543       ONE_MORE_BASE_BYTE (c);
544       mask = code_charset_table[c];
545       if (mask)
546         {
547           int idx = 0;
548           unsigned code = c;
549           int nbytes = 1;
550           int dim;
551           
552           while (mask)
553             {
554               while (! (mask & 1)) mask >>= 1, idx++;
555               this_charset = charsets[idx];
556               dim = this_charset->dimension;
557               while (nbytes < dim)
558                 {
559                   ONE_MORE_BYTE (c);
560                   code = (code << 8) | c;
561                   nbytes++;
562                 }
563               c = DECODE_CHAR (this_charset, code);
564               if (c >= 0)
565                 goto emit_char;
566               mask >>= 1, idx++;
567             }
568         }
569
570       if (! converter->lenient)
571         break;
572       REWIND_SRC_TO_BASE ();
573       c = *src++;
574       this_charset = mcharset__binary;
575
576     emit_char:
577       if (this_charset != mcharset__ascii
578           && this_charset != charset)
579         {
580           TAKEIN_CHARS (mt, nchars - last_nchars, 
581                         dst - (mt->data + mt->nbytes), charset);
582           charset = this_charset;
583           last_nchars = nchars;
584         }
585       EMIT_CHAR (c);
586     }
587   /* We reach here because of an invalid byte.  */
588   error = 1;
589
590  source_end:
591   TAKEIN_CHARS (mt, nchars - last_nchars,
592                 dst - (mt->data + mt->nbytes), charset);
593   return finish_decoding (mt, converter, nchars,
594                           source, src_end, src_base, error);
595 }
596
597 static int
598 encode_coding_charset (MText *mt, int from, int to,
599                        unsigned char *destination, int dst_bytes,
600                        MConverter *converter)
601 {
602   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
603   MCodingSystem *coding = internal->coding;
604   unsigned char *src, *src_end;
605   unsigned char *dst = destination;
606   unsigned char *dst_end = dst + dst_bytes;
607   int nchars = 0;
608   int ncharsets = coding->ncharsets;
609   MCharset **charsets = coding->charsets;
610   int ascii_compatible = coding->ascii_compatible;
611   enum MTextFormat format = mt->format;
612
613   SET_SRC (mt, format, from, to);
614   while (1)
615     {
616       int c, bytes;
617
618       ONE_MORE_CHAR (c, bytes, format);
619
620       if (c < 0x80 && ascii_compatible)
621         {
622           CHECK_DST (1);
623           *dst++ = c;
624         }
625       else
626         {
627           unsigned code;
628           MCharset *charset = NULL;
629           int i = 0;
630
631           while (1)
632             {
633               charset = charsets[i];
634               code = ENCODE_CHAR (charset, c);
635               if (code != MCHAR_INVALID_CODE)
636                 break;
637               if (++i == ncharsets)
638                 goto unsupported_char;
639             }
640
641           CHECK_DST (charset->dimension);
642           if (charset->dimension == 1)
643             {
644               *dst++ = code;
645             }
646           else if (charset->dimension == 2)
647             {
648               *dst++ = code >> 8;
649               *dst++ = code & 0xFF;
650             }
651           else if (charset->dimension == 3)
652             {
653               *dst++ = code >> 16;
654               *dst++ = (code >> 8) & 0xFF;
655               *dst++ = code & 0xFF;
656             }
657           else
658             {
659               *dst++ = code >> 24;
660               *dst++ = (code >> 16) & 0xFF;
661               *dst++ = (code >> 8) & 0xFF;
662               *dst++ = code & 0xFF;
663             }
664         }
665       src += bytes;
666       nchars++;
667       continue;
668
669     unsupported_char:
670       {
671         int len;
672
673         if (! converter->lenient)
674           break;
675         len = encode_unsupporeted_char (c, dst, dst_end, mt, from + nchars);
676         if (len == 0)
677           goto insufficient_destination;
678         dst += len;
679         src += bytes;
680         nchars++;
681       }
682     }
683   /* We reach here because of an unsupported char.  */
684   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
685   goto finish;
686
687  insufficient_destination:
688   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
689
690  finish:
691   converter->nchars += nchars;
692   converter->nbytes += dst - destination;
693   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
694 }
695
696 \f
697 /* Staffs for coding-systems of type MCODING_TYPE_UTF (8).  */
698
699 #define UTF8_CHARSET(p)                                 \
700   (! ((p)[0] & 0x80) ? (mcharset__unicode)                      \
701    : CHAR_HEAD_P ((p) + 1) ? (mcharset__binary)                 \
702    : ! ((p)[0] & 0x20) ? (mcharset__unicode)                    \
703    : CHAR_HEAD_P ((p) + 2) ? (mcharset__binary)                 \
704    : ! ((p)[0] & 0x10) ? (mcharset__unicode)                    \
705    : CHAR_HEAD_P ((p) + 3) ? (mcharset__binary)                 \
706    : ! ((p)[0] & 0x08) ? ((((((p)[0] & 0x07) << 2)              \
707                             & (((p)[1] & 0x30) >> 4)) <= 0x10)  \
708                           ? (mcharset__unicode)                 \
709                           : (mcharset__m17n))                   \
710    : CHAR_HEAD_P ((p) + 4) ? (mcharset__binary)                 \
711    : ! ((p)[0] & 0x04) ? (mcharset__m17n)                       \
712    : CHAR_HEAD_P ((p) + 5) ? (mcharset__binary)                 \
713    : ! ((p)[0] & 0x02) ? (mcharset__m17n)                       \
714    : (mcharset__binary))
715
716
717 static int
718 decode_coding_utf_8 (const unsigned char *source, int src_bytes, MText *mt,
719                      MConverter *converter)
720 {
721   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
722   MCodingSystem *coding = internal->coding;
723   const unsigned char *src = internal->carryover;
724   const unsigned char *src_stop = src + internal->carryover_bytes;
725   const unsigned char *src_end = source + src_bytes;
726   const unsigned char *src_base;
727   unsigned char *dst = mt->data + mt->nbytes;
728   unsigned char *dst_end = mt->data + mt->allocated;
729   int nchars = 0;
730   int last_nchars = 0;
731   int at_most = converter->at_most > 0 ? converter->at_most : -1;
732   int error = 0;
733   int full = converter->lenient || (coding->charsets[0] == mcharset__m17n);
734   MCharset *charset = NULL;
735
736   while (1)
737     {
738       int c, c1, bytes;
739       MCharset *this_charset = NULL;
740
741       ONE_MORE_BASE_BYTE (c);
742
743       if (!(c & 0x80))
744         bytes = 1;
745       else if (!(c & 0x40))
746         goto invalid_byte;
747       else if (!(c & 0x20))
748         bytes = 2, c &= 0x1F;
749       else if (!(c & 0x10))
750         bytes = 3, c &= 0x0F;
751       else if (!(c & 0x08))
752         bytes = 4, c &= 0x07;
753       else if (!(c & 0x04))
754         bytes = 5, c &= 0x03;
755       else if (!(c & 0x02))
756         bytes = 6, c &= 0x01;
757       else
758         goto invalid_byte;
759
760       while (bytes-- > 1)
761         {
762           ONE_MORE_BYTE (c1);
763           if ((c1 & 0xC0) != 0x80)
764             goto invalid_byte;
765           c = (c << 6) | (c1 & 0x3F);
766         }
767
768       if (full
769           || c < 0xD800 || (c >= 0xE000 && c < 0x110000))
770         goto emit_char;
771
772     invalid_byte:
773       if (! converter->lenient)
774         break;
775       REWIND_SRC_TO_BASE ();
776       c = *src++;
777       this_charset = mcharset__binary;
778
779     emit_char:
780       if (this_charset != charset)
781         {
782           TAKEIN_CHARS (mt, nchars - last_nchars, 
783                         dst - (mt->data + mt->nbytes), charset);
784           charset = this_charset;
785           last_nchars = nchars;
786         }
787       EMIT_CHAR (c);
788     }
789   /* We reach here because of an invalid byte.  */
790   error = 1;
791
792  source_end:
793   TAKEIN_CHARS (mt, nchars - last_nchars,
794                 dst - (mt->data + mt->nbytes), charset);
795   return finish_decoding (mt, converter, nchars,
796                           source, src_end, src_base, error);
797 }
798
799 static int
800 encode_coding_utf_8 (MText *mt, int from, int to,
801                      unsigned char *destination, int dst_bytes,
802                      MConverter *converter)
803 {
804   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
805   MCodingSystem *coding = internal->coding;
806   unsigned char *src, *src_end;
807   unsigned char *dst = destination;
808   unsigned char *dst_end = dst + dst_bytes;
809   int nchars = 0;
810   enum MTextFormat format = mt->format;
811
812   SET_SRC (mt, format, from, to);
813
814   if (format <= MTEXT_FORMAT_UTF_8
815       && (converter->lenient
816           || coding->charsets[0] == mcharset__m17n))
817     {
818       if (dst_bytes < src_end - src)
819         {
820           int byte_pos = (src + dst_bytes) - mt->data;
821
822           to = POS_BYTE_TO_CHAR (mt, byte_pos);
823           byte_pos = POS_CHAR_TO_BYTE (mt, to);
824           src_end = mt->data + byte_pos;
825           converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
826         }
827       memcpy (destination, src, src_end - src);
828       nchars = to - from;
829       dst += src_end - src;
830       goto finish;
831     }
832
833   while (1)
834     {
835       int c, bytes;
836
837       ONE_MORE_CHAR (c, bytes, format);
838
839       if ((c >= 0xD800 && c < 0xE000) || c >= 0x110000)
840         break;
841       CHECK_DST (bytes);
842       dst += CHAR_STRING (c, dst);
843       src += bytes;
844       nchars++;
845     }
846   /* We reach here because of an unsupported char.  */
847   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
848   goto finish;
849
850  insufficient_destination:
851   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
852
853  finish:
854   converter->nchars += nchars;
855   converter->nbytes += dst - destination;
856   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
857 }
858
859 \f
860 /* Staffs for coding-systems of type MCODING_TYPE_UTF (16 & 32).  */
861
862 enum utf_bom
863   {
864     UTF_BOM_MAYBE,
865     UTF_BOM_NO,
866     UTF_BOM_YES,
867     UTF_BOM_MAX
868   };
869
870 enum utf_endian
871   {
872     UTF_BIG_ENDIAN,
873     UTF_LITTLE_ENDIAN,
874     UTF_ENDIAN_MAX
875   };
876
877 struct utf_status
878 {
879   int surrogate;
880   enum utf_bom bom;
881   enum utf_endian endian;
882 };
883
884 static int
885 setup_coding_utf (MCodingSystem *coding)
886 {
887   MCodingInfoUTF *info = (MCodingInfoUTF *) (coding->extra_info);
888   MCodingInfoUTF *spec;
889
890   if (info->code_unit_bits == 8)
891     coding->ascii_compatible = 1;
892   else if (info->code_unit_bits == 16
893            || info->code_unit_bits == 32)
894     {
895       if (info->bom < 0 || info->bom > 2
896           || info->endian < 0 || info->endian > 1)
897         MERROR (MERROR_CODING, -1);
898     }
899   else
900     return -1;
901
902   MSTRUCT_CALLOC (spec, MERROR_CODING);
903   *spec = *info;
904   coding->extra_spec = (void *) (spec);
905   return 0;
906 }
907
908 static int
909 reset_coding_utf (MConverter *converter)
910 {
911   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
912   MCodingSystem *coding = internal->coding;
913   struct utf_status *status = (struct utf_status *) &(converter->status);
914
915   if (! coding->ready
916       && setup_coding_utf (coding) < 0)
917     return -1;
918   coding->ready = 1;
919
920   status->surrogate = 0;
921   status->bom = ((MCodingInfoUTF *) (coding->extra_spec))->bom;
922   status->endian = ((MCodingInfoUTF *) (coding->extra_spec))->endian;
923   return 0;
924 }
925
926 static int
927 decode_coding_utf_16 (const unsigned char *source, int src_bytes, MText *mt,
928                       MConverter *converter)
929 {
930   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
931   const unsigned char *src = internal->carryover;
932   const unsigned char *src_stop = src + internal->carryover_bytes;
933   const unsigned char *src_end = source + src_bytes;
934   const unsigned char *src_base;
935   unsigned char *dst = mt->data + mt->nbytes;
936   unsigned char *dst_end = mt->data + mt->allocated;
937   int nchars = 0;
938   int last_nchars = 0;
939   int at_most = converter->at_most > 0 ? converter->at_most : -1;
940   struct utf_status *status = (struct utf_status *) &(converter->status);
941   unsigned char b1, b2;
942   MCharset *charset = NULL;
943   int error = 0;
944
945   if (status->bom != UTF_BOM_NO)
946     {
947       int c;
948
949       ONE_MORE_BASE_BYTE (b1);
950       ONE_MORE_BYTE (b2);
951       c = (b1 << 8) | b2;
952       if (c == 0xFEFF)
953         status->endian = UTF_BIG_ENDIAN;
954       else if (c == 0xFFFE)
955         status->endian = UTF_LITTLE_ENDIAN;
956       else if (status->bom == UTF_BOM_MAYBE
957                || converter->lenient)
958         {
959           status->endian = UTF_BIG_ENDIAN;
960           REWIND_SRC_TO_BASE ();
961         }
962       else
963         {
964           error = 1;
965           goto source_end;
966         }
967       status->bom = UTF_BOM_NO;
968     }
969
970   while (1)
971     {
972       int c, c1;
973       MCharset *this_charset = NULL;
974
975       ONE_MORE_BASE_BYTE (b1);
976       ONE_MORE_BYTE (b2);
977       if (status->endian == UTF_BIG_ENDIAN)
978         c = ((b1 << 8) | b2);
979       else
980         c = ((b2 << 8) | b1);
981       if (c < 0xD800 || c >= 0xE000)
982         goto emit_char;
983       else if (c < 0xDC00)
984         {
985           ONE_MORE_BYTE (b1);
986           ONE_MORE_BYTE (b2);
987           if (status->endian == UTF_BIG_ENDIAN)
988             c1 = ((b1 << 8) | b2);
989           else
990             c1 = ((b2 << 8) | b1);
991           if (c1 < 0xDC00 || c1 >= 0xE000)
992             goto invalid_byte;
993           c = 0x10000 + ((c - 0xD800) << 10) + (c1 - 0xDC00);
994           goto emit_char;
995         }
996
997     invalid_byte:
998       if (! converter->lenient)
999         break;
1000       REWIND_SRC_TO_BASE ();
1001       ONE_MORE_BYTE (b1);
1002       ONE_MORE_BYTE (b2);
1003       if (status->endian == UTF_BIG_ENDIAN)
1004         c = ((b1 << 8) | b2);
1005       else
1006         c = ((b2 << 8) | b1);
1007       this_charset = mcharset__binary;
1008
1009     emit_char:
1010       if (this_charset != charset)
1011         {
1012           TAKEIN_CHARS (mt, nchars - last_nchars, 
1013                         dst - (mt->data + mt->nbytes), charset);
1014           charset = this_charset;
1015           last_nchars = nchars;
1016         }
1017       EMIT_CHAR (c);
1018     }
1019   /* We reach here because of an invalid byte.  */
1020   error = 1;
1021
1022  source_end:
1023   TAKEIN_CHARS (mt, nchars - last_nchars,
1024                 dst - (mt->data + mt->nbytes), charset);
1025   return finish_decoding (mt, converter, nchars,
1026                           source, src_end, src_base, error);
1027 }
1028
1029
1030 static int
1031 decode_coding_utf_32 (const unsigned char *source, int src_bytes, MText *mt,
1032                       MConverter *converter)
1033 {
1034   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
1035   const unsigned char *src = internal->carryover;
1036   const unsigned char *src_stop = src + internal->carryover_bytes;
1037   const unsigned char *src_end = source + src_bytes;
1038   const unsigned char *src_base;
1039   unsigned char *dst = mt->data + mt->nbytes;
1040   unsigned char *dst_end = mt->data + mt->allocated;
1041   int nchars = 0;
1042   int last_nchars = 0;
1043   int at_most = converter->at_most > 0 ? converter->at_most : -1;
1044   struct utf_status *status = (struct utf_status *) &(converter->status);
1045   unsigned char b1, b2, b3, b4;
1046   MCharset *charset = NULL;
1047   int error = 0;
1048
1049   if (status->bom != UTF_BOM_NO)
1050     {
1051       unsigned c;
1052
1053       ONE_MORE_BASE_BYTE (b1);
1054       ONE_MORE_BYTE (b2);
1055       ONE_MORE_BYTE (b3);
1056       ONE_MORE_BYTE (b4);
1057       c = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
1058       if (c == 0x0000FEFF)
1059         status->endian = UTF_BIG_ENDIAN;
1060       else if (c == 0xFFFE0000)
1061         status->endian = UTF_LITTLE_ENDIAN;
1062       else if (status->bom == UTF_BOM_MAYBE
1063                || converter->lenient)
1064         {
1065           status->endian = UTF_BIG_ENDIAN;
1066           REWIND_SRC_TO_BASE ();
1067         }
1068       else
1069         {
1070           error = 1;
1071           goto source_end;
1072         }
1073       status->bom = UTF_BOM_NO;
1074     }
1075
1076   while (1)
1077     {
1078       unsigned c;
1079       MCharset *this_charset = NULL;
1080
1081       ONE_MORE_BASE_BYTE (b1);
1082       ONE_MORE_BYTE (b2);
1083       ONE_MORE_BYTE (b3);
1084       ONE_MORE_BYTE (b4);
1085       if (status->endian == UTF_BIG_ENDIAN)
1086         c = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
1087       else
1088         c = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
1089       if (c < 0xD800 || (c >= 0xE000 && c < 0x110000))
1090         goto emit_char;
1091
1092       if (! converter->lenient)
1093         break;
1094       REWIND_SRC_TO_BASE ();
1095       ONE_MORE_BYTE (c);
1096       this_charset = mcharset__binary;
1097
1098     emit_char:
1099       if (this_charset != charset)
1100         {
1101           TAKEIN_CHARS (mt, nchars - last_nchars, 
1102                         dst - (mt->data + mt->nbytes), charset);
1103           charset = this_charset;
1104           last_nchars = nchars;
1105         }
1106       EMIT_CHAR (c);
1107     }
1108   /* We reach here because of an invalid byte.  */
1109   error = 1;
1110
1111  source_end:
1112   TAKEIN_CHARS (mt, nchars - last_nchars,
1113                 dst - (mt->data + mt->nbytes), charset);
1114   return finish_decoding (mt, converter, nchars,
1115                           source, src_end, src_base, error);
1116 }
1117
1118
1119 static int
1120 encode_coding_utf_16 (MText *mt, int from, int to,
1121                       unsigned char *destination, int dst_bytes,
1122                       MConverter *converter)
1123 {
1124   unsigned char *src, *src_end;
1125   unsigned char *dst = destination;
1126   unsigned char *dst_end = dst + dst_bytes;
1127   int nchars = 0;
1128   struct utf_status *status = (struct utf_status *) &(converter->status);
1129   int big_endian = status->endian == UTF_BIG_ENDIAN;
1130   enum MTextFormat format = mt->format;
1131
1132   SET_SRC (mt, format, from, to);
1133
1134   if (status->bom != UTF_BOM_NO)
1135     {
1136       CHECK_DST (2);
1137       if (big_endian)
1138         *dst++ = 0xFE, *dst++ = 0xFF;
1139       else
1140         *dst++ = 0xFF, *dst++ = 0xFE;
1141       status->bom = UTF_BOM_NO;
1142     }
1143
1144   while (1)
1145     {
1146       int c, bytes;
1147
1148       ONE_MORE_CHAR (c, bytes, format);
1149
1150       if (c < 0xD800 || (c >= 0xE000 && c < 0x10000))
1151         {
1152           CHECK_DST (2);
1153           if (big_endian)
1154             *dst++ = c >> 8, *dst++ = c & 0xFF;
1155           else
1156             *dst++ = c & 0xFF, *dst++ = c >> 8;
1157         }
1158       else if (c >= 0x10000 && c < 0x110000)
1159         {
1160           int c1, c2;
1161
1162           CHECK_DST (4);
1163           c -= 0x10000;
1164           c1 = (c >> 10) + 0xD800;
1165           c2 = (c & 0x3FF) + 0xDC00;
1166           if (big_endian)
1167             *dst++ = c1 >> 8, *dst++ = c1 & 0xFF,
1168               *dst++ = c2 >> 8, *dst++ = c2 & 0xFF;
1169           else
1170             *dst++ = c1 & 0xFF, *dst++ = c1 >> 8,
1171               *dst++ = c2 & 0xFF, *dst++ = c2 >> 8;
1172         }
1173       else
1174         {
1175           unsigned char buf[11];
1176           int len, i;
1177
1178           if (! converter->lenient)
1179             break;
1180           len = encode_unsupporeted_char (c, buf, buf + (dst_end - dst),
1181                                           mt, from + nchars);
1182           if (len == 0)
1183             goto insufficient_destination;
1184           if (big_endian)
1185             for (i = 0; i < len; i++)
1186               *dst++ = 0, *dst++ = buf[i];
1187           else
1188             for (i = 0; i < len; i++)
1189               *dst++ = buf[i], *dst++ = 0;
1190         }
1191       src += bytes;
1192       nchars++;
1193     }
1194   /* We reach here because of an unsupported char.  */
1195   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
1196   goto finish;
1197
1198  insufficient_destination:
1199   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
1200
1201  finish:
1202   converter->nchars += nchars;
1203   converter->nbytes += dst - destination;
1204   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
1205 }
1206
1207 static int
1208 encode_coding_utf_32 (MText *mt, int from, int to,
1209                       unsigned char *destination, int dst_bytes,
1210                       MConverter *converter)
1211 {
1212   unsigned char *src, *src_end;
1213   unsigned char *dst = destination;
1214   unsigned char *dst_end = dst + dst_bytes;
1215   int nchars = 0;
1216   struct utf_status *status = (struct utf_status *) &(converter->status);
1217   int big_endian = status->endian == UTF_BIG_ENDIAN;
1218   enum MTextFormat format = mt->format;
1219
1220   SET_SRC (mt, format, from, to);
1221
1222   if (status->bom != UTF_BOM_NO)
1223     {
1224       CHECK_DST (4);
1225       if (big_endian)
1226         *dst++ = 0x00, *dst++ = 0x00, *dst++ = 0xFE, *dst++ = 0xFF;
1227       else
1228         *dst++ = 0xFF, *dst++ = 0xFE, *dst++ = 0x00, *dst++ = 0x00;
1229       status->bom = UTF_BOM_NO;
1230     }
1231
1232   while (1)
1233     {
1234       int c, bytes;
1235
1236       ONE_MORE_CHAR (c, bytes, format);
1237
1238       if (c < 0xD800 || (c >= 0xE000 && c < 0x110000))
1239         {
1240           CHECK_DST (4);
1241           if (big_endian)
1242             *dst++ = 0x00, *dst++ = c >> 16,
1243               *dst++ = (c >> 8) & 0xFF, *dst++ = c & 0xFF;
1244           else
1245             *dst++ = c & 0xFF, *dst++ = (c >> 8) & 0xFF,
1246               *dst++ = c >> 16, *dst++ = 0x00;
1247         }
1248       else
1249         {
1250           unsigned char buf[11];
1251           int len, i;
1252
1253           if (! converter->lenient)
1254             break;
1255           len = encode_unsupporeted_char (c, buf, buf + (dst_end - dst),
1256                                           mt, from + nchars);
1257           if (len == 0)
1258             goto insufficient_destination;
1259           if (big_endian)
1260             for (i = 0; i < len; i++)
1261               *dst++ = 0, *dst++ = buf[i];
1262           else
1263             for (i = 0; i < len; i++)
1264               *dst++ = buf[i], *dst++ = 0;
1265         }
1266       src += bytes;
1267       nchars++;
1268     }
1269   /* We reach here because of an unsupported char.  */
1270   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
1271   goto finish;
1272
1273  insufficient_destination:
1274   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
1275
1276  finish:
1277   converter->nchars += nchars;
1278   converter->nbytes += dst - destination;
1279   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
1280 }
1281
1282 \f
1283 /* Staffs for coding-systems of type MCODING_TYPE_ISO_2022.  */
1284
1285 #define ISO_CODE_STX    0x02            /* start text */
1286 #define ISO_CODE_SO     0x0E            /* shift-out */
1287 #define ISO_CODE_SI     0x0F            /* shift-in */
1288 #define ISO_CODE_SS2_7  0x19            /* single-shift-2 for 7-bit code */
1289 #define ISO_CODE_ESC    0x1B            /* escape */
1290 #define ISO_CODE_SS2    0x8E            /* single-shift-2 */
1291 #define ISO_CODE_SS3    0x8F            /* single-shift-3 */
1292
1293 /** Structure pointed by MCodingSystem.extra_spec.  */
1294
1295 struct iso_2022_spec
1296 {
1297   unsigned flags;
1298
1299   /** Initial graphic registers (0..3) invoked to each graphic
1300       plane left and right. */
1301   int initial_invocation[2];
1302
1303   /** Initially designated charsets for each graphic register.  */
1304   MCharset *initial_designation[4];
1305
1306   int n_designations;
1307   char *designations;
1308
1309   int use_esc;
1310 };
1311
1312 struct iso_2022_status
1313 {
1314   int invocation[2];
1315   MCharset *designation[4];
1316   unsigned single_shifting : 1;
1317   unsigned bol : 1;
1318   unsigned r2l : 1;
1319   unsigned utf8_shifting : 1;
1320   MCharset *non_standard_charset;
1321   int non_standard_charset_bytes;
1322   int non_standard_encoding;
1323 };
1324
1325 enum iso_2022_code_class {
1326   ISO_control_0,                /* Control codes in the range
1327                                    0x00..0x1F and 0x7F, except for the
1328                                    following 4 codes.  */
1329   ISO_shift_out,                /* ISO_CODE_SO (0x0E) */
1330   ISO_shift_in,                 /* ISO_CODE_SI (0x0F) */
1331   ISO_single_shift_2_7,         /* ISO_CODE_SS2_7 (0x19) */
1332   ISO_escape,                   /* ISO_CODE_SO (0x1B) */
1333   ISO_control_1,                /* Control codes in the range
1334                                    0x80..0x9F, except for the
1335                                    following 3 codes.  */
1336   ISO_single_shift_2,           /* ISO_CODE_SS2 (0x8E) */
1337   ISO_single_shift_3,           /* ISO_CODE_SS3 (0x8F) */
1338   ISO_control_sequence_introducer, /* ISO_CODE_CSI (0x9B) */
1339   ISO_0x20_or_0x7F,           /* Codes of the values 0x20 or 0x7F.  */
1340   ISO_graphic_plane_0,   /* Graphic codes in the range 0x21..0x7E.  */
1341   ISO_0xA0_or_0xFF,           /* Codes of the values 0xA0 or 0xFF.  */
1342   ISO_graphic_plane_1    /* Graphic codes in the range 0xA1..0xFE.  */
1343 } iso_2022_code_class[256];
1344
1345
1346 #define MCODING_ISO_DESIGNATION_MASK    \
1347   (MCODING_ISO_DESIGNATION_G0           \
1348    | MCODING_ISO_DESIGNATION_G1         \
1349    | MCODING_ISO_DESIGNATION_CTEXT      \
1350    | MCODING_ISO_DESIGNATION_CTEXT_EXT)
1351
1352 static int
1353 setup_coding_iso_2022 (MCodingSystem *coding)
1354 {
1355   MCodingInfoISO2022 *info = (MCodingInfoISO2022 *) (coding->extra_info);
1356   int ncharsets = coding->ncharsets;
1357   struct iso_2022_spec *spec;
1358   int designation_policy = info->flags & MCODING_ISO_DESIGNATION_MASK;
1359   int i;
1360
1361   coding->ascii_compatible = 0;
1362
1363   MSTRUCT_CALLOC (spec, MERROR_CODING);
1364
1365   spec->flags = info->flags;
1366   spec->initial_invocation[0] = info->initial_invocation[0];
1367   spec->initial_invocation[1] = info->initial_invocation[1];
1368   for (i = 0; i < 4; i++)
1369     spec->initial_designation[i] = NULL;
1370   if (designation_policy)
1371     {
1372       spec->n_designations = ncharsets;
1373       if (spec->flags & MCODING_ISO_FULL_SUPPORT)
1374         spec->n_designations += mcharset__iso_2022_table.used;
1375       MTABLE_CALLOC (spec->designations, spec->n_designations, MERROR_CODING);
1376       for (i = 0; i < spec->n_designations; i++)
1377         spec->designations[i] = -1;
1378     }
1379   else
1380     {
1381       if (spec->flags & MCODING_ISO_FULL_SUPPORT)
1382         MERROR (MERROR_CODING, -1);
1383       spec->designations = NULL;
1384     }
1385
1386   for (i = 0; i < ncharsets; i++)
1387     {
1388       int reg = info->designations[i];
1389
1390       if (reg != -5
1391           && coding->charsets[i]->final_byte > 0
1392           && (reg < -4 || reg > 3))
1393         MERROR (MERROR_CODING, -1);
1394       if (reg >= 0)
1395         {
1396           if (spec->initial_designation[reg])
1397             MERROR (MERROR_CODING, -1);
1398           spec->initial_designation[reg] = coding->charsets[i];
1399         }
1400       else if (reg >= -4)
1401         {
1402           if (! designation_policy
1403               && ! (spec->flags & MCODING_ISO_EUC_TW_SHIFT))
1404             MERROR (MERROR_CODING, -1);
1405           reg += 4;
1406         }
1407
1408       if (designation_policy)
1409         spec->designations[i] = reg;
1410       if (coding->charsets[i] == mcharset__ascii)
1411         coding->ascii_compatible = 1;
1412     }
1413
1414   if (coding->ascii_compatible
1415       && (spec->flags & (MCODING_ISO_DESIGNATION_G0
1416                          | MCODING_ISO_DESIGNATION_CTEXT
1417                          | MCODING_ISO_DESIGNATION_CTEXT_EXT
1418                          | MCODING_ISO_LOCKING_SHIFT)))
1419     coding->ascii_compatible = 0;
1420
1421   if (spec->flags & MCODING_ISO_FULL_SUPPORT)
1422     for (i = 0; i < mcharset__iso_2022_table.used; i++)
1423       {
1424         MCharset *charset = mcharset__iso_2022_table.charsets[i];
1425
1426         spec->designations[ncharsets + i]
1427           = ((designation_policy == MCODING_ISO_DESIGNATION_CTEXT
1428               || designation_policy == MCODING_ISO_DESIGNATION_CTEXT_EXT)
1429              ? (charset->code_range[0] == 32
1430                 || charset->code_range[1] == 255)
1431              : designation_policy == MCODING_ISO_DESIGNATION_G1);
1432       }
1433
1434   spec->use_esc = ((spec->flags & MCODING_ISO_DESIGNATION_MASK)
1435                    || ((spec->flags & MCODING_ISO_LOCKING_SHIFT)
1436                        && (spec->initial_designation[2]
1437                            || spec->initial_designation[3]))
1438                    || (! (spec->flags & MCODING_ISO_EIGHT_BIT)
1439                        && (spec->flags & MCODING_ISO_SINGLE_SHIFT))
1440                    || (spec->flags & MCODING_ISO_ISO6429));
1441
1442   coding->extra_spec = (void *) spec;
1443
1444   return 0;
1445 }
1446
1447 static int
1448 reset_coding_iso_2022 (MConverter *converter)
1449 {
1450   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
1451   MCodingSystem *coding = internal->coding;
1452   struct iso_2022_status *status
1453     = (struct iso_2022_status *) &(converter->status);
1454   struct iso_2022_spec *spec;
1455   int i;
1456
1457   if (! coding->ready
1458       && setup_coding_iso_2022 (coding) < 0)
1459     return -1;
1460   coding->ready = 1;
1461
1462   spec = (struct iso_2022_spec *) coding->extra_spec;
1463   status->invocation[0] = spec->initial_invocation[0];
1464   status->invocation[1] = spec->initial_invocation[1];
1465   for (i = 0; i < 4; i++)
1466     status->designation[i] = spec->initial_designation[i];
1467   status->single_shifting = 0;
1468   status->bol = 1;
1469   status->r2l = 0;
1470
1471   return 0;
1472 }
1473
1474 #define ISO2022_DECODE_DESIGNATION(reg, dim, chars, final, rev)           \
1475   do {                                                                    \
1476     MCharset *charset;                                                    \
1477                                                                           \
1478     if ((final) < '0' || (final) >= 128)                                  \
1479       goto invalid_byte;                                                  \
1480     if (rev < 0)                                                          \
1481       {                                                                   \
1482         charset = MCHARSET_ISO_2022 ((dim), (chars), (final));            \
1483         if (! (spec->flags & MCODING_ISO_FULL_SUPPORT))                   \
1484           {                                                               \
1485             int i;                                                        \
1486                                                                           \
1487             for (i = 0; i < coding->ncharsets; i++)                       \
1488               if (charset == coding->charsets[i])                         \
1489                 break;                                                    \
1490             if (i == coding->ncharsets)                                   \
1491               goto invalid_byte;                                          \
1492           }                                                               \
1493       }                                                                   \
1494     else                                                                  \
1495       {                                                                   \
1496         int i;                                                            \
1497                                                                           \
1498         for (i = 0; i < mcharset__iso_2022_table.used; i++)               \
1499           {                                                               \
1500             charset = mcharset__iso_2022_table.charsets[i];               \
1501             if (charset->revision == (rev)                                \
1502                 && charset->dimension == (dim)                            \
1503                 && charset->final_byte == (final)                         \
1504                 && (charset->code_range[1] == (chars)                     \
1505                     || ((chars) == 96 && charset->code_range[1] == 255))) \
1506               break;                                                      \
1507           }                                                               \
1508         if (i == mcharset__iso_2022_table.used)                           \
1509           goto invalid_byte;                                              \
1510       }                                                                   \
1511     status->designation[reg] = charset;                                   \
1512   } while (0)
1513
1514
1515 static MCharset *
1516 find_ctext_non_standard_charset (char *charset_name)
1517 {
1518   MCharset *charset;
1519
1520   if (! strcmp (charset_name, "koi8-r"))
1521     charset = MCHARSET (msymbol ("koi8-r"));
1522   else if  (! strcmp (charset_name, "big5-0"))
1523     charset = MCHARSET (msymbol ("big5"));    
1524   else
1525     charset = NULL;
1526   return charset;
1527 }
1528
1529 static int
1530 decode_coding_iso_2022 (const unsigned char *source, int src_bytes, MText *mt,
1531                        MConverter *converter)
1532 {
1533   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
1534   MCodingSystem *coding = internal->coding;
1535   const unsigned char *src = internal->carryover;
1536   const unsigned char *src_stop = src + internal->carryover_bytes;
1537   const unsigned char *src_end = source + src_bytes;
1538   const unsigned char *src_base;
1539   unsigned char *dst = mt->data + mt->nbytes;
1540   unsigned char *dst_end = mt->data + mt->allocated;
1541   int nchars = 0;
1542   int last_nchars = 0;
1543   int at_most = converter->at_most > 0 ? converter->at_most : -1;
1544   struct iso_2022_spec *spec = (struct iso_2022_spec *) coding->extra_spec;
1545   struct iso_2022_status *status
1546     = (struct iso_2022_status *) &(converter->status);
1547   MCharset *charset0, *charset1, *charset;
1548   int error = 0;
1549   MCharset *cns_charsets[15];
1550
1551   charset0 = (status->invocation[0] >= 0
1552               ? status->designation[status->invocation[0]] : NULL);
1553   charset1 = (status->invocation[1] >= 0
1554               ? status->designation[status->invocation[1]] : NULL);
1555   charset = mcharset__ascii;
1556
1557   if (spec->flags & MCODING_ISO_EUC_TW_SHIFT)
1558     {
1559       int i;
1560
1561       memset (cns_charsets, 0, sizeof (cns_charsets));
1562       for (i = 0; i < coding->ncharsets; i++)
1563         if (coding->charsets[i]->dimension == 2
1564             && coding->charsets[i]->code_range[1] == 126)
1565           {
1566             int final = coding->charsets[i]->final_byte;
1567
1568             if (final >= 'G' && final <= 'M')
1569               cns_charsets[final - 'G'] = coding->charsets[i];
1570             else if (final < 0)
1571               cns_charsets[14] = coding->charsets[i];
1572           }
1573     }
1574
1575   while (1)
1576     {
1577       MCharset *this_charset = NULL;
1578       int c1, c2, c3;
1579
1580       ONE_MORE_BASE_BYTE (c1);
1581
1582       if (status->utf8_shifting)
1583         {
1584           int buf[6];
1585           int bytes = CHAR_BYTES_BY_HEAD (c1);
1586           int i;
1587           
1588           buf[0] = c1;
1589           for (i = 1; i < bytes; i++)
1590             {
1591               ONE_MORE_BYTE (c1);
1592               buf[i] = c1;
1593             }
1594           this_charset = UTF8_CHARSET (buf);
1595           c1 = STRING_CHAR_UTF8 (buf);
1596           goto emit_char;
1597         }
1598
1599       if (status->non_standard_encoding > 0)
1600         {
1601           int i;
1602
1603           this_charset = status->non_standard_charset;
1604           for (i = 1; i < status->non_standard_charset_bytes; i++)
1605             {
1606               ONE_MORE_BYTE (c2);
1607               c1 = (c1 << 8) | c2;
1608             }
1609           c1 = DECODE_CHAR (this_charset, c1);
1610           goto emit_char;
1611         }
1612
1613       switch (iso_2022_code_class[c1])
1614         {
1615         case ISO_graphic_plane_0:
1616           this_charset = charset0;
1617           break;
1618
1619         case ISO_0x20_or_0x7F:
1620           if (! charset0
1621               || (charset0->code_range[0] != 32
1622                   && charset0->code_range[1] != 255))
1623             /* This is SPACE or DEL.  */
1624             this_charset = mcharset__ascii;
1625           else
1626             /* This is a graphic character of plane 0.  */        
1627             this_charset = charset0;
1628           break;
1629
1630         case ISO_graphic_plane_1:
1631           if (!charset1)
1632             goto invalid_byte;
1633           this_charset = charset1;
1634           break;
1635
1636         case ISO_0xA0_or_0xFF:
1637           if (! charset1
1638               || charset1->code_range[0] == 33
1639               || ! (spec->flags & MCODING_ISO_EIGHT_BIT))
1640             goto invalid_byte;
1641           /* This is a graphic character of plane 1. */
1642           if (! charset1)
1643             goto invalid_byte;
1644           this_charset = charset1;
1645           break;
1646
1647         case ISO_control_0:
1648           this_charset = mcharset__ascii;
1649           break;
1650
1651         case ISO_control_1:
1652           goto invalid_byte;
1653
1654         case ISO_shift_out:
1655           if ((spec->flags & MCODING_ISO_LOCKING_SHIFT)
1656               &&  status->designation[1])
1657             {
1658               status->invocation[0] = 1;
1659               charset0 = status->designation[1];
1660               continue;
1661             }
1662           this_charset = mcharset__ascii;
1663           break;
1664
1665         case ISO_shift_in:
1666           if (spec->flags & MCODING_ISO_LOCKING_SHIFT)
1667             {
1668               status->invocation[0] = 0;
1669               charset0 = status->designation[0];
1670               continue;
1671             }
1672           this_charset = mcharset__ascii;
1673           break;
1674
1675         case ISO_single_shift_2_7:
1676           if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT_7))
1677             {
1678               this_charset = mcharset__ascii;
1679               break;
1680             }
1681           c1 = 'N';
1682           goto label_escape_sequence;
1683
1684         case ISO_single_shift_2:
1685           if (spec->flags & MCODING_ISO_EUC_TW_SHIFT)
1686             {
1687               ONE_MORE_BYTE (c1);
1688               if (c1 < 0xA1 || (c1 > 0xA7 && c1 < 0xAF) || c1 > 0xAF
1689                   || ! cns_charsets[c1 - 0xA1])
1690                 goto invalid_byte;
1691               status->designation[2] = cns_charsets[c1 - 0xA1];
1692             }
1693           else if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT))
1694             goto invalid_byte;
1695           /* SS2 is handled as an escape sequence of ESC 'N' */
1696           c1 = 'N';
1697           goto label_escape_sequence;
1698
1699         case ISO_single_shift_3:
1700           if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT))
1701             goto invalid_byte;
1702           /* SS2 is handled as an escape sequence of ESC 'O' */
1703           c1 = 'O';
1704           goto label_escape_sequence;
1705
1706         case ISO_control_sequence_introducer:
1707           /* CSI is handled as an escape sequence of ESC '[' ...  */
1708           c1 = '[';
1709           goto label_escape_sequence;
1710
1711         case ISO_escape:
1712           if (! spec->use_esc)
1713             {
1714               this_charset = mcharset__ascii;
1715               break;
1716             }
1717           ONE_MORE_BYTE (c1);
1718         label_escape_sequence:
1719           /* Escape sequences handled here are invocation,
1720              designation, and direction specification.  */
1721           switch (c1)
1722             {
1723             case '&':        /* revision of following character set */
1724               if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK))
1725                 goto unused_escape_sequence;
1726               ONE_MORE_BYTE (c1);
1727               if (c1 < '@' || c1 > '~')
1728                 goto invalid_byte;
1729               ONE_MORE_BYTE (c1);
1730               if (c1 != ISO_CODE_ESC)
1731                 goto invalid_byte;
1732               ONE_MORE_BYTE (c1);
1733               goto label_escape_sequence;
1734
1735             case '$':        /* designation of 2-byte character set */
1736               if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK))
1737                 goto unused_escape_sequence;
1738               ONE_MORE_BYTE (c1);
1739               if (c1 >= '@' && c1 <= 'B')
1740                 { /* designation of JISX0208.1978, GB2312.1980, or
1741                      JISX0208.1980 */
1742                   ISO2022_DECODE_DESIGNATION (0, 2, 94, c1, -1);
1743                 }
1744               else if (c1 >= 0x28 && c1 <= 0x2B)
1745                 { /* designation of (dimension 2, chars 94) character set */
1746                   ONE_MORE_BYTE (c2);
1747                   ISO2022_DECODE_DESIGNATION (c1 - 0x28, 2, 94, c2, -1);
1748                 }
1749               else if (c1 >= 0x2C && c1 <= 0x2F)
1750                 { /* designation of (dimension 2, chars 96) character set */
1751                   ONE_MORE_BYTE (c2);
1752                   ISO2022_DECODE_DESIGNATION (c1 - 0x2C, 2, 96, c2, -1);
1753                 }
1754               else
1755                 goto invalid_byte;
1756               /* We must update these variables now.  */
1757               charset0 = status->designation[status->invocation[0]];
1758               charset1 = status->designation[status->invocation[1]];
1759               continue;
1760
1761             case 'n':           /* invocation of locking-shift-2 */
1762               if (! (spec->flags & MCODING_ISO_LOCKING_SHIFT)
1763                   || ! status->designation[2])
1764                 goto invalid_byte;
1765               status->invocation[0] = 2;
1766               charset0 = status->designation[2];
1767               continue;
1768
1769             case 'o':           /* invocation of locking-shift-3 */
1770               if (! (spec->flags & MCODING_ISO_LOCKING_SHIFT)
1771                   || ! status->designation[3])
1772                 goto invalid_byte;
1773               status->invocation[0] = 3;
1774               charset0 = status->designation[3];
1775               continue;
1776
1777             case 'N':           /* invocation of single-shift-2 */
1778               if (! ((spec->flags & MCODING_ISO_SINGLE_SHIFT)
1779                      || (spec->flags & MCODING_ISO_EUC_TW_SHIFT))
1780                   || ! status->designation[2])
1781                 goto invalid_byte;
1782               this_charset = status->designation[2];
1783               ONE_MORE_BYTE (c1);
1784               if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0))
1785                 goto invalid_byte;
1786               break;
1787
1788             case 'O':           /* invocation of single-shift-3 */
1789               if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT)
1790                   || ! status->designation[3])
1791                 goto invalid_byte;
1792               this_charset = status->designation[3];
1793               ONE_MORE_BYTE (c1);
1794               if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0))
1795                 goto invalid_byte;
1796               break;
1797
1798             case '[':           /* specification of direction */
1799               if (! (spec->flags & MCODING_ISO_ISO6429))
1800                 goto invalid_byte;
1801               /* For the moment, nested direction is not supported.
1802                  So, (coding->mode & CODING_MODE_DIRECTION) zero means
1803                  left-to-right, and nonzero means right-to-left.  */
1804               ONE_MORE_BYTE (c1);
1805               switch (c1)
1806                 {
1807                 case ']':       /* end of the current direction */
1808                 case '0':       /* end of the current direction */
1809                   status->r2l = 0;
1810                   break;
1811
1812                 case '1':       /* start of left-to-right direction */
1813                   ONE_MORE_BYTE (c1);
1814                   if (c1 != ']')
1815                     goto invalid_byte;
1816                   status->r2l = 0;
1817                   break;
1818
1819                 case '2':       /* start of right-to-left direction */
1820                   ONE_MORE_BYTE (c1);
1821                   if (c1 != ']')
1822                     goto invalid_byte;
1823                   status->r2l = 1;
1824                   break;
1825
1826                 default:
1827                   goto invalid_byte;
1828                 }
1829               continue;
1830
1831             case '%':
1832               {
1833                 char charset_name[16];
1834                 int bytes;
1835                 int i;
1836
1837                 if (! spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT)
1838                   goto invalid_byte;
1839                 /* Compound-text uses these escape sequences:
1840
1841                 ESC % G  -- utf-8 bytes -- ESC % @
1842                 ESC % / 1 M L -- charset name -- STX -- bytes --
1843                 ESC % / 2 M L -- charset name -- STX -- bytes --
1844                 ESC % / 3 M L -- charset name -- STX -- bytes --
1845                 ESC % / 4 M L -- charset name -- STX -- bytes --
1846
1847                 It also uses this sequence but that is not yet
1848                 supported here.
1849
1850                 ESC % / 0 M L -- charset name -- STX -- bytes -- */
1851
1852                 ONE_MORE_BYTE (c1);
1853                 if (c1 == 'G')
1854                   {
1855                     status->utf8_shifting = 1;
1856                     continue;
1857                   }
1858                 if (c1 == '@')
1859                   {
1860                     if (! status->utf8_shifting)
1861                       goto invalid_byte;
1862                     status->utf8_shifting = 0;
1863                     continue;
1864                   }
1865                 if (c1 != '/')
1866                   goto invalid_byte;
1867                 ONE_MORE_BYTE (c1);
1868                 if (c1 < '1' || c1 > '4')
1869                   goto invalid_byte;
1870                 status->non_standard_charset_bytes = c1 - '0';
1871                 ONE_MORE_BYTE (c1);
1872                 ONE_MORE_BYTE (c2);
1873                 if (c1 < 128 || c2 < 128)
1874                   goto invalid_byte;
1875                 bytes = (c1 - 128) * 128 + (c2 - 128);
1876                 for (i = 0; i < 16; i++)
1877                   {
1878                     ONE_MORE_BYTE (c1);
1879                     if (c1 == ISO_CODE_STX)
1880                       break;
1881                     charset_name[i] = TOLOWER (c1);
1882                   }
1883                 if (i == 16)
1884                   goto invalid_byte;
1885                 charset_name[i++] = '\0';
1886                 this_charset = find_ctext_non_standard_charset (charset_name);
1887                 if (! this_charset)
1888                   goto invalid_byte;
1889                 status->non_standard_charset = this_charset;
1890                 status->non_standard_encoding = bytes - i;
1891                 continue;
1892               }
1893
1894             default:
1895               if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK))
1896                 goto unused_escape_sequence;
1897               if (c1 >= 0x28 && c1 <= 0x2B)
1898                 { /* designation of (dimension 1, chars 94) charset */
1899                   ONE_MORE_BYTE (c2);
1900                   ISO2022_DECODE_DESIGNATION (c1 - 0x28, 1, 94, c2, -1);
1901                 }
1902               else if (c1 >= 0x2C && c1 <= 0x2F)
1903                 { /* designation of (dimension 1, chars 96) charset */
1904                   ONE_MORE_BYTE (c2);
1905                   ISO2022_DECODE_DESIGNATION (c1 - 0x2C, 1, 96, c2, -1);
1906                 }
1907               else
1908                 goto invalid_byte;
1909               /* We must update these variables now.  */
1910               charset0 = status->designation[status->invocation[0]];
1911               charset1 = status->designation[status->invocation[1]];
1912               continue;
1913
1914             unused_escape_sequence:
1915               UNGET_ONE_BYTE (c1);
1916               c1 = ISO_CODE_ESC;
1917               this_charset = mcharset__ascii;
1918             }
1919         }
1920
1921       if (this_charset->dimension == 1)
1922         {
1923           if (this_charset->code_range[1] <= 128)
1924             c1 &= 0x7F;
1925         }
1926       else if (this_charset->dimension == 2)
1927         {
1928           ONE_MORE_BYTE (c2);
1929           c1 = ((c1 & 0x7F) << 8) | (c2 & 0x7F);
1930         }
1931       else                      /* i.e.  (dimension == 3) */
1932         {
1933           ONE_MORE_BYTE (c2);
1934           ONE_MORE_BYTE (c3);
1935           c1 = ((c1 & 0x7F) << 16) | ((c2 & 0x7F) << 8) | (c3 & 0x7F);
1936         }
1937       c1 = DECODE_CHAR (this_charset, c1);
1938       goto emit_char;
1939
1940     invalid_byte:
1941       if (! converter->lenient)
1942         break;
1943       REWIND_SRC_TO_BASE ();
1944       c1 = *src++;
1945       this_charset = mcharset__binary;
1946
1947     emit_char:
1948       if (this_charset != mcharset__ascii
1949           && this_charset != charset)
1950         {
1951           TAKEIN_CHARS (mt, nchars - last_nchars,
1952                         dst - (mt->data + mt->nbytes), charset);
1953           charset = this_charset;
1954           last_nchars = nchars;
1955         }
1956       EMIT_CHAR (c1);
1957       if (status->non_standard_encoding > 0)
1958         status->non_standard_encoding -= status->non_standard_charset_bytes;
1959     }
1960   /* We reach here because of an invalid byte.  */
1961   error = 1;
1962
1963
1964
1965  source_end:
1966   TAKEIN_CHARS (mt, nchars - last_nchars,
1967                 dst - (mt->data + mt->nbytes), charset);
1968   return finish_decoding (mt, converter, nchars,
1969                           source, src_end, src_base, error);
1970
1971 }
1972
1973 /* Produce codes (escape sequence) for designating CHARSET to graphic
1974    register REG at DST, and increment DST.  If CHARSET->final-char is
1975    '@', 'A', or 'B' and SHORT_FORM is nonzero, produce designation
1976    sequence of short-form.  Update STATUS->designation.  */
1977
1978 #define ISO2022_ENCODE_DESIGNATION(reg, charset, spec, status)             \
1979   do {                                                                     \
1980     char *intermediate_char_94 = "()*+";                                   \
1981     char *intermediate_char_96 = ",-./";                                   \
1982                                                                            \
1983     if (dst + 4 > dst_end)                                                 \
1984       goto memory_shortage;                                                \
1985     *dst++ = ISO_CODE_ESC;                                                 \
1986     if (charset->dimension == 1)                                           \
1987       {                                                                    \
1988         if (charset->code_range[0] != 32                                   \
1989             && charset->code_range[1] != 255)                              \
1990           *dst++ = (unsigned char) (intermediate_char_94[reg]);            \
1991         else                                                               \
1992           *dst++ = (unsigned char) (intermediate_char_96[reg]);            \
1993       }                                                                    \
1994     else                                                                   \
1995       {                                                                    \
1996         *dst++ = '$';                                                      \
1997         if (charset->code_range[0] != 32                                   \
1998             && charset->code_range[1] != 255)                              \
1999           {                                                                \
2000             if (spec->flags & MCODING_ISO_LONG_FORM                        \
2001                 || reg != 0                                                \
2002                 || charset->final_byte < '@' || charset->final_byte > 'B') \
2003               *dst++ = (unsigned char) (intermediate_char_94[reg]);        \
2004           }                                                                \
2005         else                                                               \
2006           *dst++ = (unsigned char) (intermediate_char_96[reg]);            \
2007       }                                                                    \
2008     *dst++ = charset->final_byte;                                          \
2009                                                                            \
2010     status->designation[reg] = charset;                                    \
2011   } while (0)
2012
2013
2014 /* The following two macros produce codes (control character or escape
2015    sequence) for ISO-2022 single-shift functions (single-shift-2 and
2016    single-shift-3).  */
2017
2018 #define ISO2022_ENCODE_SINGLE_SHIFT_2(spec, status)     \
2019   do {                                                  \
2020     if (dst + 2 > dst_end)                              \
2021       goto memory_shortage;                             \
2022     if (! (spec->flags & MCODING_ISO_EIGHT_BIT))        \
2023       *dst++ = ISO_CODE_ESC, *dst++ = 'N';              \
2024     else                                                \
2025       *dst++ = ISO_CODE_SS2;                            \
2026     status->single_shifting = 1;                        \
2027   } while (0)
2028
2029
2030 #define ISO2022_ENCODE_SINGLE_SHIFT_3(spec, status)     \
2031   do {                                                  \
2032     if (dst + 2 > dst_end)                              \
2033       goto memory_shortage;                             \
2034     if (! (spec->flags & MCODING_ISO_EIGHT_BIT))        \
2035       *dst++ = ISO_CODE_ESC, *dst++ = 'O';              \
2036     else                                                \
2037       *dst++ = ISO_CODE_SS3;                            \
2038     status->single_shifting = 1;                        \
2039   } while (0)
2040
2041
2042 /* The following four macros produce codes (control character or
2043    escape sequence) for ISO-2022 locking-shift functions (shift-in,
2044    shift-out, locking-shift-2, and locking-shift-3).  */
2045
2046 #define ISO2022_ENCODE_SHIFT_IN(status)         \
2047   do {                                          \
2048     if (dst + 1 > dst_end)                      \
2049       goto memory_shortage;                     \
2050     *dst++ = ISO_CODE_SI;                       \
2051     status->invocation[0] = 0;                  \
2052   } while (0)
2053
2054
2055 #define ISO2022_ENCODE_SHIFT_OUT(status)        \
2056   do {                                          \
2057     if (dst + 1 > dst_end)                      \
2058       goto memory_shortage;                     \
2059     *dst++ = ISO_CODE_SO;                       \
2060     status->invocation[0] = 1;                  \
2061   } while (0)
2062
2063
2064 #define ISO2022_ENCODE_LOCKING_SHIFT_2(status)  \
2065   do {                                          \
2066     if (dst + 2 > dst_end)                      \
2067       goto memory_shortage;                     \
2068     *dst++ = ISO_CODE_ESC, *dst++ = 'n';        \
2069     status->invocation[0] = 2;                  \
2070   } while (0)
2071
2072
2073 #define ISO2022_ENCODE_LOCKING_SHIFT_3(status)  \
2074   do {                                          \
2075     if (dst + 2 > dst_end)                      \
2076       goto memory_shortage;                     \
2077     *dst++ = ISO_CODE_ESC, *dst++ = 'o';        \
2078     status->invocation[0] = 3;                  \
2079   } while (0)
2080
2081 #define ISO2022_ENCODE_UTF8_SHIFT_START(len)    \
2082   do {                                          \
2083     CHECK_DST (3 + len);                        \
2084     *dst++ = ISO_CODE_ESC;                      \
2085     *dst++ = '%';                               \
2086     *dst++ = 'G';                               \
2087     status->utf8_shifting = 1;                  \
2088   } while (0)
2089
2090
2091 #define ISO2022_ENCODE_UTF8_SHIFT_END() \
2092   do {                                  \
2093     CHECK_DST (3);                      \
2094     *dst++ = ISO_CODE_ESC;              \
2095     *dst++ = '%';                       \
2096     *dst++ = '@';                       \
2097     status->utf8_shifting = 0;          \
2098   } while (0)
2099
2100
2101 #define ISO2022_ENCODE_NON_STANDARD(name, len)                  \
2102   do {                                                          \
2103     CHECK_DST (6 + len + 1 + non_standard_charset_bytes);       \
2104     non_standard_begin = dst;                                   \
2105     *dst++ = ISO_CODE_ESC;                                      \
2106     *dst++ = '%';                                               \
2107     *dst++ = '/';                                               \
2108     *dst++ = '0' + non_standard_charset_bytes;                  \
2109     *dst++ = 0, *dst++ = 0;     /* filled later */              \
2110     memcpy (dst, name, len);                                    \
2111     dst += len;                                                 \
2112     *dst++ = ISO_CODE_STX;                                      \
2113     non_standard_bytes = len + 1;                               \
2114   } while (0)
2115
2116
2117 static char *
2118 find_ctext_non_standard_name (MCharset *charset, int *bytes)
2119 {
2120   char *name = msymbol_name (charset->name);
2121
2122   if (! strcmp (name, "koi8-r"))
2123     *bytes = 1;
2124   else if (! strcmp (name, "big5"))
2125     name = "big5-0", *bytes = 2;
2126   else
2127     return NULL;
2128   return name;
2129 }
2130
2131 /* Designate CHARSET to a graphic register specified in
2132    SPEC->designation.  If the register is not yet invoked to graphic
2133    left not right, invoke it to graphic left.  DSTP points to a
2134    variable containing a memory address where the output must go.
2135    DST_END is the limit of that memory.
2136
2137    Return 0 if it succeeds.  Return -1 otherwise, which means that the
2138    memory area is too short.  By side effect, update the variable that
2139    DSTP points to.  */
2140
2141 static int
2142 iso_2022_designate_invoke_charset (MCodingSystem *coding,
2143                                    MCharset *charset,
2144                                    struct iso_2022_spec *spec,
2145                                    struct iso_2022_status *status,
2146                                    unsigned char **dstp,
2147                                    unsigned char *dst_end)
2148 {
2149   int i;
2150   unsigned char *dst = *dstp;
2151
2152   for (i = 0; i < 4; i++)
2153     if (charset == status->designation[i])
2154       break;
2155
2156   if (i >= 4)
2157     {
2158       /* CHARSET is not yet designated to any graphic registers.  */
2159       for (i = 0; i < coding->ncharsets; i++)
2160         if (charset == coding->charsets[i])
2161           break;
2162       if (i == coding->ncharsets)
2163         {
2164           for (i = 0; i < mcharset__iso_2022_table.used; i++)
2165             if (charset == mcharset__iso_2022_table.charsets[i])
2166               break;
2167           i += coding->ncharsets;
2168         }
2169       i = spec->designations[i];
2170       ISO2022_ENCODE_DESIGNATION (i, charset, spec, status);
2171     }
2172
2173   if (status->invocation[0] != i
2174       && status->invocation[1] != i)
2175     {
2176       /* Graphic register I is not yet invoked.  */
2177       switch (i)
2178         {
2179         case 0:                 /* graphic register 0 */
2180           ISO2022_ENCODE_SHIFT_IN (status);
2181           break;
2182
2183         case 1:                 /* graphic register 1 */
2184           ISO2022_ENCODE_SHIFT_OUT (status);
2185           break;
2186
2187         case 2:                 /* graphic register 2 */
2188           if (spec->flags & MCODING_ISO_SINGLE_SHIFT)
2189             ISO2022_ENCODE_SINGLE_SHIFT_2 (spec, status);
2190           else
2191             ISO2022_ENCODE_LOCKING_SHIFT_2 (status);
2192           break;
2193
2194         case 3:                 /* graphic register 3 */
2195           if (spec->flags & MCODING_ISO_SINGLE_SHIFT)
2196             ISO2022_ENCODE_SINGLE_SHIFT_3 (spec, status);
2197           else
2198             ISO2022_ENCODE_LOCKING_SHIFT_3 (status);
2199           break;
2200         }
2201     }
2202   *dstp = dst;
2203   return 0;
2204
2205  memory_shortage:
2206   *dstp = dst;
2207   return -1;
2208 }
2209
2210
2211 /* Reset the invocation/designation status to the initial one.  SPEC
2212    and STATUS contain information about the current and initial
2213    invocation /designation status respectively.  DSTP points to a
2214    variable containing a memory address where the output must go.
2215    DST_END is the limit of that memory.
2216
2217    Return 0 if it succeeds.  Return -1 otherwise, which means that the
2218    memory area is too short.  By side effect, update the variable that
2219    DSTP points to.  */
2220
2221 static int
2222 iso_2022_reset_invocation_designation (struct iso_2022_spec *spec,
2223                                        struct iso_2022_status *status,
2224                                        unsigned char **dstp,
2225                                        unsigned char *dst_end)
2226 {
2227   unsigned char *dst = *dstp;
2228   int i;
2229
2230   /* Reset the invocation status of GL.  We have not yet supported GR
2231      invocation.  */
2232   if (status->invocation[0] != spec->initial_invocation[0]
2233         && spec->initial_invocation[0] >= 0)
2234     {
2235       if (spec->initial_invocation[0] == 0)
2236         ISO2022_ENCODE_SHIFT_IN (status);
2237       else if (spec->initial_invocation[0] == 1)
2238         ISO2022_ENCODE_SHIFT_OUT (status);
2239       else if (spec->initial_invocation[0] == 2)
2240         ISO2022_ENCODE_LOCKING_SHIFT_2 (status);
2241       else                      /* i.e. spec->initial_invocation[0] == 3 */
2242         ISO2022_ENCODE_LOCKING_SHIFT_3 (status);
2243     }
2244
2245   /* Reset the designation status of G0..G3.  */
2246   for (i = 0; i < 4; i++)
2247     if (status->designation[i] != spec->initial_designation[i]
2248         && spec->initial_designation[i])
2249       {
2250         MCharset *charset = spec->initial_designation[i];
2251         
2252         ISO2022_ENCODE_DESIGNATION (i, charset, spec, status);
2253       }
2254
2255   *dstp = dst;
2256   return 0;
2257
2258  memory_shortage:
2259   *dstp = dst;
2260   return -1;
2261 }
2262
2263
2264 static int
2265 encode_coding_iso_2022 (MText *mt, int from, int to,
2266                        unsigned char *destination, int dst_bytes,
2267                        MConverter *converter)
2268 {
2269   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
2270   MCodingSystem *coding = internal->coding;
2271   unsigned char *src, *src_end;
2272   unsigned char *dst = destination;
2273   unsigned char *dst_end = dst + dst_bytes;
2274   int nchars = 0;
2275   unsigned char *dst_base;
2276   struct iso_2022_spec *spec = (struct iso_2022_spec *) coding->extra_spec;
2277   int full_support = spec->flags & MCODING_ISO_FULL_SUPPORT;
2278   struct iso_2022_status *status
2279     = (struct iso_2022_status *) &(converter->status);
2280   MCharset *primary, *charset0, *charset1;
2281   int next_primary_change;
2282   int ncharsets = coding->ncharsets;
2283   MCharset **charsets = coding->charsets;
2284   MCharset *cns_charsets[15];
2285   int ascii_compatible = coding->ascii_compatible;
2286   MCharset *non_standard_charset = NULL;
2287   int non_standard_charset_bytes = 0;
2288   int non_standard_bytes = 0;
2289   unsigned char *non_standard_begin = NULL;
2290   enum MTextFormat format = mt->format;
2291
2292   SET_SRC (mt, format, from, to);
2293
2294   if (spec->flags & MCODING_ISO_EUC_TW_SHIFT)
2295     {
2296       int i;
2297
2298       memset (cns_charsets, 0, sizeof (cns_charsets));
2299       for (i = 0; i < ncharsets; i++)
2300         if (charsets[i]->dimension == 2)
2301           {
2302             int final = charsets[i]->final_byte;
2303
2304             if (final >= 'G' && final <= 'M')
2305               cns_charsets[final - 'G'] = charsets[i];
2306             else if (final < 0)
2307               cns_charsets[14] = charsets[i];
2308           }
2309     }
2310
2311   next_primary_change = from;
2312   primary = NULL;
2313   charset0 = status->designation[status->invocation[0]];
2314   charset1 = (status->invocation[1] < 0 ? NULL
2315               : status->designation[status->invocation[1]]);
2316
2317   while (1)
2318     {
2319       int bytes, c;
2320
2321       dst_base = dst;
2322       ONE_MORE_CHAR (c, bytes, format);
2323
2324       if (c < 128 && ascii_compatible)
2325         {
2326           if (status->utf8_shifting)
2327             ISO2022_ENCODE_UTF8_SHIFT_END ();
2328           CHECK_DST (1);
2329           *dst++ = c;
2330         }
2331       else if (c <= 32 || c == 127)
2332         {
2333           if (status->utf8_shifting)
2334             ISO2022_ENCODE_UTF8_SHIFT_END ();
2335           if (spec->flags & MCODING_ISO_RESET_AT_CNTL
2336               || (c == '\n' && spec->flags & MCODING_ISO_RESET_AT_EOL))
2337             {
2338               if (iso_2022_reset_invocation_designation (spec, status,
2339                                                          &dst, dst_end) < 0)
2340                 goto insufficient_destination;
2341               charset0 = status->designation[status->invocation[0]];
2342               charset1 = (status->invocation[1] < 0 ? NULL
2343                           : status->designation[status->invocation[1]]);
2344             }
2345           CHECK_DST (1);
2346           *dst++ = c;
2347         }
2348       else
2349         {
2350           unsigned code = MCHAR_INVALID_CODE;
2351           MCharset *charset = NULL;
2352           int gr_mask;
2353           int pos = from + nchars;
2354
2355           if (pos >= next_primary_change)
2356             {
2357               MSymbol primary_charset
2358                 = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
2359               primary = MCHARSET (primary_charset);
2360               if (primary && primary != mcharset__binary)
2361                 {
2362                   if (primary->final_byte <= 0)
2363                     primary = NULL;
2364                   else if (! full_support)
2365                     {
2366                       int i;
2367
2368                       for (i = 0; i < ncharsets; i++)
2369                         if (primary == charsets[i])
2370                           break;
2371                       if (i == ncharsets)
2372                         primary = NULL;
2373                     }
2374                 }
2375
2376               mtext_prop_range (mt, Mcharset, pos,
2377                                 NULL, &next_primary_change, 0);
2378             }
2379
2380           if (primary && primary != mcharset__binary)
2381             {
2382               code = ENCODE_CHAR (primary, c);
2383               if (code != MCHAR_INVALID_CODE)
2384                 charset = primary;
2385             }
2386           if (! charset)
2387             {
2388               if (c <= 32 || c == 127)
2389                 {
2390                   code = c;
2391                   charset = mcharset__ascii;
2392                 }
2393               else 
2394                 {
2395                   int i;
2396
2397                   for (i = 0; i < ncharsets; i++)
2398                     {
2399                       charset = charsets[i];
2400                       code = ENCODE_CHAR (charset, c);
2401                       if (code != MCHAR_INVALID_CODE)
2402                         break;
2403                     }
2404                   if (i == ncharsets)
2405                     {
2406                       if (spec->flags & MCODING_ISO_FULL_SUPPORT)
2407                         {
2408                           for (i = 0; i < mcharset__iso_2022_table.used; i++)
2409                             {
2410                               charset = mcharset__iso_2022_table.charsets[i];
2411                               code = ENCODE_CHAR (charset, c);
2412                               if (code != MCHAR_INVALID_CODE)
2413                                 break;
2414                             }
2415                           if (i == mcharset__iso_2022_table.used)
2416                             {
2417                               if (spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT)
2418                                 goto unsupported_char;
2419                               converter->result = MCONVERSION_RESULT_INVALID_CHAR;
2420                               goto finish;
2421                             }
2422                         }
2423                       else
2424                         goto unsupported_char;
2425                     }
2426                 }
2427             }
2428
2429           if (charset
2430               && (charset->final_byte >= 0
2431                   || spec->flags & MCODING_ISO_EUC_TW_SHIFT))
2432             {
2433               if (code >= 0x80 && code < 0xA0)
2434                 goto unsupported_char;
2435               code &= 0x7F7F7F7F;
2436               if (status->utf8_shifting)
2437                 ISO2022_ENCODE_UTF8_SHIFT_END ();
2438               if (charset == charset0)
2439                 gr_mask = 0;
2440               else if (charset == charset1)
2441                 gr_mask = 0x80;
2442               else
2443                 {
2444                   unsigned char *p = NULL;
2445
2446                   if (spec->flags & MCODING_ISO_EUC_TW_SHIFT)
2447                     {
2448                       int i;
2449
2450                       if (cns_charsets[0] == charset)
2451                         {
2452                           CHECK_DST (2);
2453                         }
2454                       else
2455                         {
2456                           for (i = 1; i < 15; i++)
2457                             if (cns_charsets[i] == charset)
2458                               break;
2459                           CHECK_DST (4);
2460                           *dst++ = ISO_CODE_SS2;
2461                           *dst++ = 0xA1 + i;
2462                         }
2463                       status->single_shifting = 1;
2464                       p = dst;
2465                     }
2466                   else
2467                     {
2468                       if (iso_2022_designate_invoke_charset
2469                           (coding, charset, spec, status, &dst, dst_end) < 0)
2470                         goto insufficient_destination;
2471                       charset0 = status->designation[status->invocation[0]];
2472                       charset1 = (status->invocation[1] < 0 ? NULL
2473                                   : status->designation[status->invocation[1]]);
2474                     }
2475                   if (status->single_shifting)
2476                     gr_mask
2477                       = (spec->flags & MCODING_ISO_EIGHT_BIT) ? 0x80 : 0;
2478                   else if (charset == charset0)
2479                     gr_mask = 0;
2480                   else
2481                     gr_mask = 0x80;
2482                 }
2483               if (charset->dimension == 1)
2484                 {
2485                   CHECK_DST (1);
2486                   *dst++ = code | gr_mask;
2487                 }
2488               else if (charset->dimension == 2)
2489                 {
2490                   CHECK_DST (2);
2491                   *dst++ = (code >> 8) | gr_mask;
2492                   *dst++ = (code & 0xFF) | gr_mask;
2493                 }
2494               else
2495                 {
2496                   CHECK_DST (3);
2497                   *dst++ = (code >> 16) | gr_mask;
2498                   *dst++ = ((code >> 8) & 0xFF) | gr_mask;
2499                   *dst++ = (code & 0xFF) | gr_mask;
2500                 }
2501               status->single_shifting = 0;
2502             }
2503           else if (charset && spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT)
2504             {
2505               if (charset != non_standard_charset)
2506                 {
2507                   char *name = (find_ctext_non_standard_name
2508                                 (charset, &non_standard_charset_bytes));
2509
2510                   if (name)
2511                     {
2512                       int len = strlen (name);
2513                       
2514                       ISO2022_ENCODE_NON_STANDARD (name, len);
2515                       non_standard_charset = charset;
2516                     }
2517                   else
2518                     non_standard_charset = NULL;
2519                 }
2520
2521               if (non_standard_charset)
2522                 {
2523                   if (dst + non_standard_charset_bytes > dst_end)
2524                     goto insufficient_destination;
2525                   non_standard_bytes += non_standard_charset_bytes;
2526                   non_standard_begin[4] = (non_standard_bytes / 128) | 0x80;
2527                   non_standard_begin[5] = (non_standard_bytes % 128) | 0x80;
2528                   if (non_standard_charset_bytes == 1)
2529                     *dst++ = code;
2530                   else if (non_standard_charset_bytes == 2)
2531                     *dst++ = code >> 8, *dst++ = code & 0xFF;
2532                   else if (non_standard_charset_bytes == 3)
2533                     *dst++ = code >> 16, *dst++ = (code >> 8) & 0xFF,
2534                       *dst++ = code & 0xFF;
2535                   else          /* i.e non_standard_charset_bytes == 3 */
2536                     *dst++ = code >> 24, *dst++ = (code >> 16) & 0xFF,
2537                       *dst++ = (code >> 8) & 0xFF, *dst++ = code & 0xFF;
2538                 }
2539               else
2540                 {
2541                   int len = CHAR_BYTES (c);
2542
2543                   if (c >= 0x110000)
2544                     goto unsupported_char;
2545                   if (! status->utf8_shifting)
2546                     ISO2022_ENCODE_UTF8_SHIFT_START (len);
2547                   else
2548                     CHECK_DST (len);
2549                   CHAR_STRING (c, dst);
2550                 }
2551             }
2552           else
2553             goto unsupported_char;
2554         }
2555       src += bytes;
2556       nchars++;
2557       continue;
2558
2559     unsupported_char:
2560       {
2561         int len;
2562
2563         if (iso_2022_designate_invoke_charset (coding, mcharset__ascii,
2564                                                spec, status,
2565                                                &dst, dst_end) < 0)
2566           goto insufficient_destination;
2567         if (! converter->lenient)
2568           break;
2569         len = encode_unsupporeted_char (c, dst, dst_end, mt, from + nchars);
2570         if (len == 0)
2571           goto insufficient_destination;
2572         dst += len;
2573         src += bytes;
2574         nchars++;
2575       }
2576     }
2577   /* We reach here because of an unsupported char.  */
2578   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
2579   goto finish;
2580
2581  insufficient_destination:
2582   dst = dst_base;
2583   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
2584
2585  finish:
2586   if (converter->result == MCONVERSION_RESULT_SUCCESS
2587       && converter->last_block)
2588     {
2589       if (status->utf8_shifting)
2590         {
2591           ISO2022_ENCODE_UTF8_SHIFT_END ();
2592           dst_base = dst;
2593         }
2594       if (spec->flags & MCODING_ISO_RESET_AT_EOL
2595           && charset0 != spec->initial_designation[0])
2596         {
2597           if (iso_2022_reset_invocation_designation (spec, status,
2598                                                      &dst, dst_end) < 0)
2599             goto insufficient_destination;
2600         }
2601     }
2602   converter->nchars += nchars;
2603   converter->nbytes += dst - destination;
2604   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
2605 }
2606
2607 \f
2608 /* Staffs for coding-systems of type MCODING_TYPE_MISC.  */
2609
2610 /* For SJIS handling... */
2611
2612 #define SJIS_TO_JIS(s1, s2)                             \
2613   (s2 >= 0x9F                                           \
2614    ? (((s1 * 2 - (s1 >= 0xE0 ? 0x160 : 0xE0)) << 8)     \
2615       | (s2 - 0x7E))                                    \
2616    : (((s1 * 2 - ((s1 >= 0xE0) ? 0x161 : 0xE1)) << 8)   \
2617       | (s2 - ((s2 >= 0x7F) ? 0x20 : 0x1F))))
2618
2619 #define JIS_TO_SJIS(c1, c2)                             \
2620   ((c1 & 1)                                             \
2621    ? (((c1 / 2 + ((c1 < 0x5F) ? 0x71 : 0xB1)) << 8)     \
2622       | (c2 + ((c2 >= 0x60) ? 0x20 : 0x1F)))            \
2623    : (((c1 / 2 + ((c1 < 0x5F) ? 0x70 : 0xB0)) << 8)     \
2624       | (c2 + 0x7E)))
2625
2626
2627 static int
2628 reset_coding_sjis (MConverter *converter)
2629 {
2630   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
2631   MCodingSystem *coding = internal->coding;
2632
2633   if (! coding->ready)
2634     {
2635       MSymbol kanji_sym = msymbol ("jisx0208.1983");
2636       MCharset *kanji = MCHARSET (kanji_sym);
2637       MSymbol kana_sym = msymbol ("jisx0201-kana");
2638       MCharset *kana = MCHARSET (kana_sym);
2639
2640       if (! kanji || ! kana)
2641         return -1;
2642       coding->ncharsets = 3;
2643       coding->charsets[1] = kanji;
2644       coding->charsets[2] = kana;
2645     }
2646   coding->ready = 1;
2647   return 0;
2648 }
2649
2650 static int
2651 decode_coding_sjis (const unsigned char *source, int src_bytes, MText *mt,
2652                     MConverter *converter)
2653 {
2654   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
2655   MCodingSystem *coding = internal->coding;
2656   const unsigned char *src = internal->carryover;
2657   const unsigned char *src_stop = src + internal->carryover_bytes;
2658   const unsigned char *src_end = source + src_bytes;
2659   const unsigned char *src_base;
2660   unsigned char *dst = mt->data + mt->nbytes;
2661   unsigned char *dst_end = mt->data + mt->allocated - MAX_UTF8_CHAR_BYTES;
2662   int nchars = 0;
2663   int last_nchars = 0;
2664   int at_most = converter->at_most > 0 ? converter->at_most : -1;
2665
2666   MCharset *charset_roman = coding->charsets[0];
2667   MCharset *charset_kanji = coding->charsets[1];
2668   MCharset *charset_kana = coding->charsets[2];
2669   MCharset *charset = mcharset__ascii;
2670   int error = 0;
2671
2672   while (1)
2673     {
2674       MCharset *this_charset;
2675       int c, c1, c2;
2676
2677       ONE_MORE_BASE_BYTE (c1);
2678
2679       c2 = -1;
2680       if (c1 < 0x80)
2681         {
2682           this_charset = ((c1 <= 0x20 || c1 == 0x7F)
2683                           ? mcharset__ascii
2684                           : charset_roman);
2685         }
2686       else if ((c1 >= 0x81 && c1 <= 0x9F) || (c1 >= 0xE0 && c1 <= 0xEF))
2687         {
2688           ONE_MORE_BYTE (c2);
2689           if ((c2 >= 0x40 && c2 <= 0x7F) || (c2 >= 80 && c2 <= 0xFC))
2690             {
2691               this_charset = charset_kanji;
2692               c1 = SJIS_TO_JIS (c1, c2);
2693             }
2694           else
2695             goto invalid_byte;
2696         }
2697       else if (c1 >= 0xA1 && c1 <= 0xDF)
2698         {
2699           this_charset = charset_kana;
2700           c1 &= 0x7F;
2701         }
2702       else
2703         goto invalid_byte;
2704
2705       c = DECODE_CHAR (this_charset, c1);
2706       if (c >= 0)
2707         goto emit_char;
2708
2709     invalid_byte:
2710       if (! converter->lenient)
2711         break;
2712       REWIND_SRC_TO_BASE ();
2713       c = *src++;
2714       this_charset = mcharset__binary;
2715
2716     emit_char:
2717       if (this_charset != mcharset__ascii
2718           && this_charset != charset)
2719         {
2720           TAKEIN_CHARS (mt, nchars - last_nchars, 
2721                         dst - (mt->data + mt->nbytes), charset);
2722           charset = this_charset;
2723           last_nchars = nchars;
2724         }
2725       EMIT_CHAR (c);
2726     }
2727   /* We reach here because of an invalid byte.  */
2728   error = 1;
2729
2730  source_end:
2731   TAKEIN_CHARS (mt, nchars - last_nchars,
2732                 dst - (mt->data + mt->nbytes), charset);
2733   return finish_decoding (mt, converter, nchars,
2734                           source, src_end, src_base, error);
2735 }
2736
2737 static int
2738 encode_coding_sjis (MText *mt, int from, int to,
2739                     unsigned char *destination, int dst_bytes,
2740                     MConverter *converter)
2741 {
2742   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
2743   MCodingSystem *coding = internal->coding;
2744   unsigned char *src, *src_end;
2745   unsigned char *dst = destination;
2746   unsigned char *dst_end = dst + dst_bytes;
2747   int nchars = 0;
2748   MCharset *charset_roman = coding->charsets[0];
2749   MCharset *charset_kanji = coding->charsets[1];
2750   MCharset *charset_kana = coding->charsets[2];
2751   enum MTextFormat format = mt->format;
2752
2753   SET_SRC (mt, format, from, to);
2754
2755   while (1)
2756     {
2757       int c, bytes, len;
2758       unsigned code;
2759
2760       ONE_MORE_CHAR (c, bytes, format);
2761
2762       if (c <= 0x20 || c == 0x7F)
2763         {
2764           CHECK_DST (1);
2765           *dst++ = c;
2766         }
2767       else
2768         {
2769           if ((code = ENCODE_CHAR (charset_roman, c)) != MCHAR_INVALID_CODE)
2770             {
2771               CHECK_DST (1);
2772               *dst++ = c;
2773             }
2774           else if ((code = ENCODE_CHAR (charset_kanji, c))
2775                    != MCHAR_INVALID_CODE)
2776             {
2777               int c1 = code >> 8, c2 = code & 0xFF;
2778               code = JIS_TO_SJIS (c1, c2);
2779               CHECK_DST (2);
2780               *dst++ = code >> 8;
2781               *dst++ = code & 0xFF;
2782             }
2783           else if ((code = ENCODE_CHAR (charset_kana, c))
2784                    != MCHAR_INVALID_CODE)
2785             {
2786               CHECK_DST (1);
2787               *dst++ = code | 0x80;
2788             }
2789           else
2790             {
2791               if (! converter->lenient)
2792                 break;
2793               len = encode_unsupporeted_char (c, dst, dst_end,
2794                                               mt, from + nchars);
2795               if (len == 0)
2796                 goto insufficient_destination;
2797               dst += len;
2798             }
2799         }
2800       src += bytes;
2801       nchars++;
2802     }
2803   /* We reach here because of an unsupported char.  */
2804   converter->result = MCONVERSION_RESULT_INVALID_CHAR;
2805   goto finish;
2806
2807  insufficient_destination:
2808   converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST;
2809
2810  finish:
2811   converter->nchars += nchars;
2812   converter->nbytes += dst - destination;
2813   return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0);
2814 }
2815
2816
2817 static MCodingSystem *
2818 find_coding (MSymbol name)
2819 {
2820   MCodingSystem *coding = (MCodingSystem *) msymbol_get (name, Mcoding);
2821
2822   if (! coding)
2823     {
2824       MPlist *plist, *pl;
2825       MSymbol sym = msymbol__canonicalize (name);
2826
2827       plist = mplist_find_by_key (coding_definition_list, sym);
2828       if (! plist)
2829         return NULL;
2830       pl = MPLIST_PLIST (plist);
2831       name = MPLIST_VAL (pl);
2832       mconv_define_coding (MSYMBOL_NAME (name), MPLIST_NEXT (pl),
2833                            NULL, NULL, NULL, NULL);
2834       coding = (MCodingSystem *) msymbol_get (name, Mcoding);
2835       plist = mplist_pop (plist);
2836       M17N_OBJECT_UNREF (plist);
2837     }
2838   return coding;
2839 }
2840
2841 #define BINDING_NONE 0
2842 #define BINDING_BUFFER 1
2843 #define BINDING_STREAM 2
2844
2845 #define CONVERT_WORKSIZE 0x10000
2846
2847 \f
2848 /* Internal API */
2849
2850 int
2851 mcoding__init (void)
2852 {
2853   int i;
2854   MPlist *param, *charsets, *pl;
2855
2856   MLIST_INIT1 (&coding_list, codings, 128);
2857   coding_definition_list = mplist ();
2858
2859   /* ISO-2022 specific initialize routine.  */
2860   for (i = 0; i < 0x20; i++)
2861     iso_2022_code_class[i] = ISO_control_0;
2862   for (i = 0x21; i < 0x7F; i++)
2863     iso_2022_code_class[i] = ISO_graphic_plane_0;
2864   for (i = 0x80; i < 0xA0; i++)
2865     iso_2022_code_class[i] = ISO_control_1;
2866   for (i = 0xA1; i < 0xFF; i++)
2867     iso_2022_code_class[i] = ISO_graphic_plane_1;
2868   iso_2022_code_class[0x20] = iso_2022_code_class[0x7F] = ISO_0x20_or_0x7F;
2869   iso_2022_code_class[0xA0] = iso_2022_code_class[0xFF] = ISO_0xA0_or_0xFF;
2870   iso_2022_code_class[0x0E] = ISO_shift_out;
2871   iso_2022_code_class[0x0F] = ISO_shift_in;
2872   iso_2022_code_class[0x19] = ISO_single_shift_2_7;
2873   iso_2022_code_class[0x1B] = ISO_escape;
2874   iso_2022_code_class[0x8E] = ISO_single_shift_2;
2875   iso_2022_code_class[0x8F] = ISO_single_shift_3;
2876   iso_2022_code_class[0x9B] = ISO_control_sequence_introducer;
2877
2878   Mcoding = msymbol ("coding");
2879
2880   Mutf = msymbol ("utf");
2881   Miso_2022 = msymbol ("iso-2022");
2882
2883   Mreset_at_eol = msymbol ("reset-at-eol");
2884   Mreset_at_cntl = msymbol ("reset-at-cntl");
2885   Meight_bit = msymbol ("eight-bit");
2886   Mlong_form = msymbol ("long-form");
2887   Mdesignation_g0 = msymbol ("designation-g0");
2888   Mdesignation_g1 = msymbol ("designation-g1");
2889   Mdesignation_ctext = msymbol ("designation-ctext");
2890   Mdesignation_ctext_ext = msymbol ("designation-ctext-ext");
2891   Mlocking_shift = msymbol ("locking-shift");
2892   Msingle_shift = msymbol ("single-shift");
2893   Msingle_shift_7 = msymbol ("single-shift-7");
2894   Meuc_tw_shift = msymbol ("euc-tw-shift");
2895   Miso_6429 = msymbol ("iso-6429");
2896   Mrevision_number = msymbol ("revision-number");
2897   Mfull_support = msymbol ("full-support");
2898   Mmaybe = msymbol ("maybe");
2899
2900   Mtype = msymbol ("type");
2901   Mcharsets = msymbol_as_managing_key ("charsets");
2902   Mflags = msymbol_as_managing_key ("flags");
2903   Mdesignation = msymbol_as_managing_key ("designation");
2904   Minvocation = msymbol_as_managing_key ("invocation");
2905   Mcode_unit = msymbol ("code-unit");
2906   Mbom = msymbol ("bom");
2907   Mlittle_endian = msymbol ("little-endian");
2908
2909   param = mplist ();
2910   charsets = mplist ();
2911   pl = param;
2912   /* Setup predefined codings.  */
2913   mplist_set (charsets, Msymbol, Mcharset_ascii);
2914   pl = mplist_add (pl, Mtype, Mcharset);
2915   pl = mplist_add (pl, Mcharsets, charsets);
2916   Mcoding_us_ascii = mconv_define_coding ("us-ascii", param,
2917                                           NULL, NULL, NULL, NULL);
2918
2919   {
2920     MSymbol alias = msymbol ("ANSI_X3.4-1968");
2921     MCodingSystem *coding
2922       = (MCodingSystem *) msymbol_get (Mcoding_us_ascii, Mcoding);
2923
2924     msymbol_put (alias, Mcoding, coding);
2925     alias = msymbol__canonicalize (alias);
2926     msymbol_put (alias, Mcoding, coding);
2927   }
2928
2929   mplist_set (charsets, Msymbol, Mcharset_iso_8859_1);
2930   Mcoding_iso_8859_1 = mconv_define_coding ("iso-8859-1", param,
2931                                             NULL, NULL, NULL, NULL);
2932
2933   mplist_set (charsets, Msymbol, Mcharset_m17n);
2934   mplist_put (param, Mtype, Mutf);
2935   mplist_put (param, Mcode_unit, (void *) 8);
2936   Mcoding_utf_8_full = mconv_define_coding ("utf-8-full", param,
2937                                             NULL, NULL, NULL, NULL);
2938
2939   mplist_set (charsets, Msymbol, Mcharset_unicode);
2940   Mcoding_utf_8 = mconv_define_coding ("utf-8", param,
2941                                        NULL, NULL, NULL, NULL);
2942
2943   mplist_put (param, Mcode_unit, (void *) 16);
2944   mplist_put (param, Mbom, Mmaybe);
2945 #ifndef WORDS_BIGENDIAN
2946   mplist_put (param, Mlittle_endian, Mt);
2947 #endif
2948   Mcoding_utf_16 = mconv_define_coding ("utf-16", param,
2949                                         NULL, NULL, NULL, NULL);
2950
2951   mplist_put (param, Mcode_unit, (void *) 32);
2952   Mcoding_utf_32 = mconv_define_coding ("utf-32", param,
2953                                         NULL, NULL, NULL, NULL);
2954
2955   mplist_put (param, Mcode_unit, (void *) 16);
2956   mplist_put (param, Mbom, Mnil);
2957   mplist_put (param, Mlittle_endian, Mnil);
2958   Mcoding_utf_16be = mconv_define_coding ("utf-16be", param,
2959                                           NULL, NULL, NULL, NULL);
2960
2961   mplist_put (param, Mcode_unit, (void *) 32);
2962   Mcoding_utf_32be = mconv_define_coding ("utf-32be", param,
2963                                           NULL, NULL, NULL, NULL);
2964
2965   mplist_put (param, Mcode_unit, (void *) 16);
2966   mplist_put (param, Mlittle_endian, Mt);
2967   Mcoding_utf_16le = mconv_define_coding ("utf-16le", param,
2968                                           NULL, NULL, NULL, NULL);
2969
2970   mplist_put (param, Mcode_unit, (void *) 32);
2971   Mcoding_utf_32le = mconv_define_coding ("utf-32le", param,
2972                                           NULL, NULL, NULL, NULL);
2973
2974   mplist_put (param, Mtype, Mnil);
2975   mplist_set (charsets, Msymbol, Mcharset_ascii);
2976   Mcoding_sjis = mconv_define_coding ("sjis", param,
2977                                       reset_coding_sjis,
2978                                       decode_coding_sjis,
2979                                       encode_coding_sjis, NULL);
2980
2981   M17N_OBJECT_UNREF (charsets);
2982   M17N_OBJECT_UNREF (param);
2983
2984   return 0;
2985 }
2986
2987 void
2988 mcoding__fini (void)
2989 {
2990   int i;
2991   MPlist *plist;
2992
2993   for (i = 0; i < coding_list.used; i++)
2994     {
2995       MCodingSystem *coding = coding_list.codings[i];
2996
2997       if (coding->extra_info)
2998         free (coding->extra_info);
2999       if (coding->extra_spec)
3000         {
3001           if (coding->type == Miso_2022)
3002             free (((struct iso_2022_spec *) coding->extra_spec)->designations);
3003           free (coding->extra_spec);
3004         }
3005       free (coding);
3006     }
3007   MLIST_FREE1 (&coding_list, codings);
3008   MPLIST_DO (plist, coding_definition_list)
3009     M17N_OBJECT_UNREF (MPLIST_VAL (plist));
3010   M17N_OBJECT_UNREF (coding_definition_list);
3011 }
3012
3013 void
3014 mconv__register_charset_coding (MSymbol sym)
3015 {
3016   MSymbol name = msymbol__canonicalize (sym);
3017
3018   if (! mplist_find_by_key (coding_definition_list, name))
3019     {
3020       MPlist *param = mplist (), *charsets = mplist ();
3021
3022       mplist_set (charsets, Msymbol, sym);
3023       mplist_add (param, Msymbol, sym);
3024       mplist_add (param, Mtype, Mcharset);
3025       mplist_add (param, Mcharsets, charsets);
3026       mplist_put (coding_definition_list, name, param);
3027       M17N_OBJECT_UNREF (charsets);
3028     }
3029 }
3030
3031
3032 int
3033 mcoding__load_from_database ()
3034 {
3035   MDatabase *mdb = mdatabase_find (msymbol ("coding-list"), Mnil, Mnil, Mnil);
3036   MPlist *def_list, *plist;
3037   MPlist *definitions = coding_definition_list;
3038   int mdebug_flag = MDEBUG_CODING;
3039
3040   if (! mdb)
3041     return 0;
3042   MDEBUG_PUSH_TIME ();
3043   def_list = (MPlist *) mdatabase_load (mdb);
3044   MDEBUG_PRINT_TIME ("CODING", (stderr, " to load the data."));
3045   MDEBUG_POP_TIME ();
3046   if (! def_list)
3047     return -1;
3048
3049   MDEBUG_PUSH_TIME ();
3050   MPLIST_DO (plist, def_list)
3051     {
3052       MPlist *pl, *aliases;
3053       MSymbol name, canonicalized;
3054
3055       if (! MPLIST_PLIST_P (plist))
3056         MERROR (MERROR_CHARSET, -1);
3057       pl = MPLIST_PLIST (plist);
3058       if (! MPLIST_SYMBOL_P (pl))
3059         MERROR (MERROR_CHARSET, -1);
3060       name = MPLIST_SYMBOL (pl);
3061       canonicalized = msymbol__canonicalize (name);
3062       pl = mplist__from_plist (MPLIST_NEXT (pl));
3063       mplist_push (pl, Msymbol, name);
3064       definitions = mplist_add (definitions, canonicalized, pl);
3065       aliases = mplist_get (pl, Maliases);
3066       if (aliases)
3067         MPLIST_DO (aliases, aliases)
3068           if (MPLIST_SYMBOL_P (aliases))
3069             {
3070               name = MPLIST_SYMBOL (aliases);
3071               canonicalized = msymbol__canonicalize (name);
3072               definitions = mplist_add (definitions, canonicalized, pl);
3073               M17N_OBJECT_REF (pl);
3074             }
3075     }
3076
3077   M17N_OBJECT_UNREF (def_list);
3078   MDEBUG_PRINT_TIME ("CODING", (stderr, " to parse the loaded data."));
3079   MDEBUG_POP_TIME ();
3080   return 0;
3081 }
3082
3083 /*** @} */
3084 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
3085 \f
3086 /* External API */
3087
3088 /*** @addtogroup m17nConv */
3089 /*** @{ */
3090 /*=*/
3091
3092 /***en @name Variables: Symbols representing coding systems */
3093 /***ja @name ÊÑ¿ô: ÄêµÁºÑ¤ß¥³¡¼¥É·Ï¤ò»ØÄꤹ¤ë¤¿¤á¤Î¥·¥ó¥Ü¥ë */
3094 /*** @{ */
3095 /*=*/
3096
3097 /***en
3098     @brief Symbol for the coding system US-ASCII.
3099
3100     The symbol #Mcoding_us_ascii has name <tt>"us-ascii"</tt> and
3101     represents a coding system for the CES US-ASCII.  */
3102
3103 /***ja
3104     @brief US-ASCII ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3105
3106     ¥·¥ó¥Ü¥ë #Mcoding_us_ascii ¤Ï <tt>"us-ascii"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3107     CES US-ASCII ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£
3108     */
3109 MSymbol Mcoding_us_ascii;
3110 /*=*/
3111
3112 /***en
3113     @brief Symbol for the coding system ISO-8859-1.
3114
3115     The symbol #Mcoding_iso_8859_1 has name <tt>"iso-8859-1"</tt> and
3116     represents a coding system for the CES ISO-8859-1.  */
3117
3118 /***ja
3119     @brief ISO-8859-1 ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3120
3121     ¥·¥ó¥Ü¥ë #Mcoding_iso_8859_1 ¤Ï <tt>"iso-8859-1"</tt> 
3122     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢CES ISO-8859-1 ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£  */
3123
3124 MSymbol Mcoding_iso_8859_1;
3125 /*=*/
3126
3127 /***en
3128     @brief Symbol for the coding system UTF-8.
3129
3130     The symbol #Mcoding_utf_8 has name <tt>"utf-8"</tt> and represents
3131     a coding system for the CES UTF-8.  */
3132
3133 /***ja
3134     @brief UTF-8 ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3135
3136     ¥·¥ó¥Ü¥ë #Mcoding_utf_8 ¤Ï <tt>"utf-8"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢CES
3137     UTF-8 ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£
3138      */
3139
3140 MSymbol Mcoding_utf_8;
3141 /*=*/
3142
3143 /***en
3144     @brief Symbol for the coding system UTF-8-FULL.
3145
3146     The symbol #Mcoding_utf_8_full has name <tt>"utf-8-full"</tt> and
3147     represents a coding system that is a extension of UTF-8.  This
3148     coding system uses the same encoding algorithm as UTF-8 but is not
3149     limited to the Unicode characters.  It can encode all characters
3150     supported by the m17n library.  */
3151
3152 /***ja
3153     @brief UTF-8-FULL ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3154
3155     ¥·¥ó¥Ü¥ë #Mcoding_utf_8_full ¤Ï <tt>"utf-8-full"</tt> 
3156     ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢<tt>"UTF-8"</tt> ¤Î³ÈÄ¥¤Ç¤¢¤ë¥³¡¼¥É·Ï¤ò¼¨¤¹¡£
3157     ¤³¤Î¥³¡¼¥É·Ï¤Ï UTF-8 ¤ÈƱ¤¸¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°¥¢¥ë¥´¥ê¥º¥à¤òÍѤ¤¤ë¤¬¡¢ÂоݤÏ
3158     Unicode Ê¸»ú¤Ë¤Ï¸ÂÄꤵ¤ì¤Ê¤¤¡£
3159     ¤Þ¤¿m17n ¥é¥¤¥Ö¥é¥ê¤¬°·¤¦Á´¤Æ¤Îʸ»ú¤ò¥¨¥ó¥³¡¼¥É¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
3160     */
3161
3162 MSymbol Mcoding_utf_8_full;
3163 /*=*/
3164
3165 /***en
3166     @brief Symbol for the coding system UTF-16.
3167
3168     The symbol #Mcoding_utf_16 has name <tt>"utf-16"</tt> and
3169     represents a coding system for the CES UTF-16 (RFC 2279).  */
3170 /***ja
3171     @brief UTF-16 ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3172
3173     ¥·¥ó¥Ü¥ë #Mcoding_utf_16 ¤Ï <tt>"utf-16"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3174     CES UTF-16 (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£
3175      */
3176
3177 MSymbol Mcoding_utf_16;
3178 /*=*/
3179
3180 /***en
3181     @brief Symbol for the coding system UTF-16BE.
3182
3183     The symbol #Mcoding_utf_16be has name <tt>"utf-16be"</tt> and
3184     represents a coding system for the CES UTF-16BE (RFC 2279).  */
3185
3186 /***ja
3187     @brief UTF-16BE ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3188
3189     ¥·¥ó¥Ü¥ë #Mcoding_utf_16be ¤Ï <tt>"utf-16be"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3190     CES UTF-16BE (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£     */
3191
3192 MSymbol Mcoding_utf_16be;
3193 /*=*/
3194
3195 /***en
3196     @brief Symbol for the coding system UTF-16LE.
3197
3198     The symbol #Mcoding_utf_16le has name <tt>"utf-16le"</tt> and
3199     represents a coding system for the CES UTF-16LE (RFC 2279).  */
3200
3201 /***ja
3202     @brief UTF-16LE ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3203
3204     ¥·¥ó¥Ü¥ë #Mcoding_utf_16le ¤Ï <tt>"utf-16le"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3205     CES UTF-16LE (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£     */
3206
3207 MSymbol Mcoding_utf_16le;
3208 /*=*/
3209
3210 /***en
3211     @brief Symbol for the coding system UTF-32.
3212
3213     The symbol #Mcoding_utf_32 has name <tt>"utf-32"</tt> and
3214     represents a coding system for the CES UTF-32 (RFC 2279).  */
3215
3216 /***ja
3217     @brief UTF-32 ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3218
3219     ¥·¥ó¥Ü¥ë #Mcoding_utf_32 ¤Ï <tt>"utf-32"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3220     CES UTF-32 (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£     */
3221
3222 MSymbol Mcoding_utf_32;
3223 /*=*/
3224
3225 /***en
3226     @brief Symbol for the coding system UTF-32BE.
3227
3228     The symbol #Mcoding_utf_32be has name <tt>"utf-32be"</tt> and
3229     represents a coding system for the CES UTF-32BE (RFC 2279).  */
3230 /***ja
3231     @brief UTF-32BE ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3232
3233     ¥·¥ó¥Ü¥ë #Mcoding_utf_32be ¤Ï <tt>"utf-32be"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3234     CES UTF-32BE (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£     */
3235
3236 MSymbol Mcoding_utf_32be;
3237 /*=*/
3238
3239 /***en
3240     @brief Symbol for the coding system UTF-32LE.
3241
3242     The symbol #Mcoding_utf_32le has name <tt>"utf-32le"</tt> and
3243     represents a coding system for the CES UTF-32LE (RFC 2279).  */
3244 /***ja
3245     @brief UTF-32LE ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3246
3247     ¥·¥ó¥Ü¥ë #Mcoding_utf_32le ¤Ï <tt>"utf-32le"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3248     CES UTF-32LE (RFC 2279) ÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£     */
3249
3250 MSymbol Mcoding_utf_32le;
3251 /*=*/
3252
3253 /***en
3254     @brief Symbol for the coding system SJIS.
3255
3256     The symbol #Mcoding_sjis has name <tt>"sjis"</tt> and represents a coding
3257     system for the CES Shift-JIS.  */ 
3258 /***ja
3259     @brief SJIS ¥³¡¼¥É·Ï¤Î¥·¥ó¥Ü¥ë.
3260
3261     ¥·¥ó¥Ü¥ë #Mcoding_sjis has ¤Ï <tt>"sjis"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Á¡¢
3262     CES Shift-JISÍѤΥ³¡¼¥É·Ï¤ò¼¨¤¹¡£  */ 
3263
3264 MSymbol Mcoding_sjis;
3265 /*** @} */ 
3266 /*=*/
3267
3268 /***en
3269     @name Variables: Parameter keys for mconv_define_coding ().  */
3270 /***ja
3271     @name ÊÑ¿ô:  mconv_define_coding () Íѥѥé¥á¡¼¥¿¥­¡¼  */
3272 /*** @{ */
3273 /*=*/
3274
3275 /***en
3276     Parameter key for mconv_define_coding () (which see). */ 
3277 /***ja
3278     mconv_define_coding () Íѥѥé¥á¡¼¥¿¥­¡¼ (¾ÜºÙ¤Ï mconv_define_coding ()»²¾È). */ 
3279 MSymbol Mtype;
3280 /*=*/
3281
3282 MSymbol Mcharsets;
3283 MSymbol Mflags;
3284 MSymbol Mdesignation;
3285 MSymbol Minvocation;
3286 MSymbol Mcode_unit;
3287 MSymbol Mbom;
3288 MSymbol Mlittle_endian;
3289 /*** @} */
3290 /*=*/
3291
3292 /***en
3293     @name Variables: Symbols representing coding system types.  */
3294 /***ja
3295     @name ÊÑ¿ô¡§ ¥³¡¼¥É·Ï¤Î¥¿¥¤¥×¤ò¼¨¤¹¥·¥ó¥Ü¥ë.  */
3296 /*** @{ */
3297 /*=*/
3298
3299 /***en
3300     Symbol that can be a value of the #Mtype parameter of a coding
3301     system used in an argument to the mconv_define_coding () function
3302     (which see).  */
3303 /***ja 
3304     ´Ø¿ô mconv_define_coding () ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥³¡¼¥É·Ï¤Î¥Ñ¥é¥á¡¼¥¿
3305     #Mtype ¤ÎÃͤȤʤêÆÀ¤ë¥·¥ó¥Ü¥ë¡£(¾ÜºÙ¤Ï 
3306     mconv_define_coding ()»²¾È)¡£  */
3307  
3308 MSymbol Mutf;
3309 /*=*/
3310 MSymbol Miso_2022;
3311 /*=*/
3312 /*** @} */
3313 /*=*/
3314
3315 /***en
3316     @name Variables: Symbols appearing in the value of #Mflags parameter.  */
3317 /***ja
3318     @name ÊÑ¿ô¡§ ¥Ñ¥é¥á¡¼¥¿ #Mflags ¤ÎÃͤȤʤêÆÀ¤ë¥·¥ó¥Ü¥ë.  */
3319 /*** @{ */
3320 /*=*/
3321
3322 /***en
3323     Symbols that can be a value of the #Mflags parameter of a coding
3324     system used in an argument to the mconv_define_coding () function
3325     (which see).  */
3326 /***ja 
3327     ´Ø¿ô mconv_define_coding () ¤Î°ú¿ô¤È¤·¤ÆÍѤ¤¤é¤ì¤ë¥³¡¼¥É·Ï¤Î¥Ñ¥é¥á¡¼¥¿
3328     #Mflags ¤ÎÃͤȤʤêÆÀ¤ë¥·¥ó¥Ü¥ë¡£(¾ÜºÙ¤Ï 
3329     mconv_define_coding ()»²¾È)¡£  */
3330 MSymbol Mreset_at_eol;
3331 /*=*/
3332 MSymbol Mreset_at_cntl;
3333 MSymbol Meight_bit;
3334 MSymbol Mlong_form;
3335 MSymbol Mdesignation_g0;
3336 MSymbol Mdesignation_g1;
3337 MSymbol Mdesignation_ctext;
3338 MSymbol Mdesignation_ctext_ext;
3339 MSymbol Mlocking_shift;
3340 MSymbol Msingle_shift;
3341 MSymbol Msingle_shift_7;
3342 MSymbol Meuc_tw_shift;
3343 MSymbol Miso_6429;
3344 MSymbol Mrevision_number;
3345 MSymbol Mfull_support;
3346 /*** @} */
3347 /*=*/
3348
3349 /***en
3350     @name Variables: etc
3351
3352     Remaining variables.  */
3353 /***ja @name ÊÑ¿ô: ¤½¤Î¾ 
3354
3355     ¤Û¤«¤ÎÊÑ¿ô¡£ */
3356 /*** @{ */
3357 /*=*/
3358 /***en
3359     @brief Symbol whose name is "maybe".
3360
3361     The variable #Mmaybe is a symbol of name <tt>"maybe"</tt>.  It is
3362     used a value of #Mbom parameter of the function
3363     mconv_define_coding () (which see).  */
3364 /***ja
3365     @brief "maybe"¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.
3366
3367     ÊÑ¿ô #Mmaybe ¤Ï <tt>"maybe"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£¤³¤ì¤Ï´Ø¿ô 
3368     mconv_define_coding () ¥Ñ¥é¥á¡¼¥¿ #Mbom ¤ÎÃͤȤ·¤ÆÍѤ¤¤é¤ì¤ë¡£
3369     (¾ÜºÙ¤Ï mconv_define_coding () »²¾È)¡£ */
3370
3371 MSymbol Mmaybe;
3372 /*=*/
3373
3374 /***en
3375     @brief The symbol @c Mcoding.
3376
3377     Any decoded M-text has a text property whose key is the predefined
3378     symbol @c Mcoding.  The name of @c Mcoding is
3379     <tt>"coding"</tt>.  */
3380
3381 /***ja
3382     @brief ¥·¥ó¥Ü¥ë @c Mcoding.
3383
3384     ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¤¹¤Ù¤Æ¡¢¥­¡¼¤¬ÄêµÁºÑ¤ß¥·¥ó¥Ü¥ë @c Mcoding 
3385     ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£¥·¥ó¥Ü¥ë @c Mcoding ¤Ï 
3386     <tt>"coding"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£  */
3387
3388 MSymbol Mcoding;
3389 /*=*/
3390 /*** @} */ 
3391 /*=*/
3392
3393 /***en
3394     @brief Define a coding system.
3395
3396     The mconv_define_coding () function defines a new coding system
3397     and makes it accessible via a symbol whose name is $NAME.  $PLIST
3398     specifies parameters of the coding system as below:
3399
3400     <ul>
3401
3402     <li> Key is @c Mtype, value is a symbol
3403
3404     The value specifies the type of the coding system.  It must be
3405     #Mcharset, #Mutf, #Miso_2022, or #Mnil.
3406
3407     If the type is #Mcharset, $EXTRA_INFO is ignored.
3408
3409     If the type is #Mutf, $EXTRA_INFO must be a pointer to
3410     #MCodingInfoUTF.
3411
3412     If the type is #Miso_2022, $EXTRA_INFO must be a pointer to
3413     #MCodingInfoISO2022.
3414
3415     If the type is #Mnil, the argument $RESETTER, $DECODER, and
3416     $ENCODER must be supplied.  $EXTRA_INFO is ignored.  Otherwise,
3417     they can be @c NULL and the m17n library provides proper defaults.
3418
3419     <li> Key is #Mcharsets, value is a plist
3420
3421     The value specifies a list charsets supported by the coding
3422     system.  The keys of the plist must be #Msymbol, and the values
3423     must be symbols representing charsets.
3424
3425     <li> Key is #Mflags, value is a plist
3426
3427     If the type is #Miso_2022, the values specifies flags to control
3428     the ISO 2022 interpreter.  The keys of the plist must e #Msymbol,
3429     and values must be one of the following.
3430
3431     <ul>
3432
3433     <li> #Mreset_at_eol
3434
3435     If this flag exists, designation and invocation status is reset to
3436     the initial state at the end of line.
3437
3438     <li> #Mreset_at_cntl
3439
3440     If this flag exists, designation and invocation status is reset to
3441     the initial state at a control character.
3442
3443     <li> #Meight_bit
3444
3445     If this flag exists, the graphic plane right is used.
3446
3447     <li> #Mlong_form
3448
3449     If this flag exists, the over-long escape sequences (ESC '$' '('
3450     <final_byte>) are used for designating the CCS JISX0208.1978,
3451     GB2312, and JISX0208.
3452
3453     <li> #Mdesignation_g0
3454
3455     If this flag and #Mfull_support exists, designates charsets not
3456     listed in the charset list to the graphic register G0.
3457
3458     <li> #Mdesignation_g1
3459
3460     If this flag and #Mfull_support exists, designates charsets not
3461     listed in the charset list to the graphic register G1.
3462
3463     <li> #Mdesignation_ctext
3464
3465     If this flag and #Mfull_support exists, designates charsets not
3466     listed in the charset list to a graphic register G0 or G1 based on
3467     the criteria of the Compound Text.
3468
3469     <li> #Mdesignation_ctext_ext
3470
3471     If this flag and #Mfull_support exists, designates charsets not
3472     listed in the charset list to a graphic register G0 or G1, or use
3473     extended segment for such charsets based on the criteria of the
3474     Compound Text.
3475
3476     <li> #Mlocking_shift
3477
3478     If this flag exists, use locking shift.
3479
3480     <li> #Msingle_shift
3481
3482     If this flag exists, use single shift.
3483
3484     <li> #Msingle_shift_7
3485
3486     If this flag exists, use 7-bit single shift code (0x19).
3487
3488     <li> #Meuc_tw_shift
3489
3490     If this flag exists, use a special shifting according to EUC-TW.
3491
3492     <li> #Miso_6429
3493
3494     This flag is currently ignored.
3495
3496     <li> #Mrevision_number
3497
3498     If this flag exists, use a revision number escape sequence to
3499     designate a charset that has a revision number.
3500
3501     <li> #Mfull_support
3502
3503     If this flag exists, support all charsets registered in the
3504     International Registry.
3505
3506     </ul>
3507
3508     <li> Key is #Mdesignation, value is a plist
3509
3510     If the type is #Miso_2022, the value specifies how to designate
3511     each supported characters.  The keys of the plist must be 
3512     #Minteger, and the values must be numbers indicating a graphic
3513     registers.  The Nth element value is for the Nth charset of the
3514     charset list.  The value 0..3 means that it is assumed that a
3515     charset is already designated to the graphic register 0..3.  The
3516     negative value G (-4..-1) means that a charset is not designated
3517     to any register at first, and if necessary, is designated to the
3518     (G+4) graphic register.
3519
3520     <li> Key is #Minvocation, value is a plist
3521
3522     If the type is #Miso_2022, the value specifies how to invocate
3523     each graphic registers.  The plist length must be one or two.  The
3524     keys of the plist must be #Minteger, and the values must be
3525     numbers indicating a graphic register.  The value of the first
3526     element specifies which graphic register is invocated to the
3527     graphic plane left.  If the length is one, no graphic register is
3528     invocated to the graphic plane right.  Otherwise, the value of the
3529     second element specifies which graphic register is invocated to
3530     the graphic plane right.
3531
3532     <li> Key is #Mcode_unit, value is an integer
3533
3534     If the type is #Mutf, the value specifies the bit length of a
3535     code-unit.  It must be 8, 16, or 32.
3536
3537     <li> Key is #Mbom, value is a symbol
3538
3539     If the type is #Mutf and the code-unit bit length is 16 or 32,
3540     it specifies whether or not to use BOM (Byte Order Mark).  If the
3541     value is #Mnil (default), BOM is not used, else if the value is
3542     #Mmaybe, the existence of BOM is detected at decoding time, else
3543     BOM is used.
3544
3545     <li> Key is #Mlittle_endian, value is a symbol
3546
3547     If the type is #Mutf and the code-unit bit length is 16 or 32,
3548     it specifies whether or not the encoding is little endian.  If the
3549     value is #Mnil (default), it is big endian, else it is little
3550     endian.
3551
3552     </ul>
3553
3554     $RESETTER is a pointer to a function that resets a converter for
3555     the coding system to the initial status.  The pointed function is
3556     called with one argument, a pointer to a converter object.
3557
3558     $DECODER is a pointer to a function that decodes a byte sequence
3559     according to the coding system.  The pointed function is called
3560     with four arguments:
3561
3562         @li A pointer to the byte sequence to decode.
3563         @li The number of bytes to decode.
3564         @li A pointer to an M-text to which the decoded characters are appended.
3565         @li A pointer to a converter object.
3566
3567     $DECODER must return 0 if it succeeds.  Otherwise it must return -1.
3568
3569     $ENCODER is a pointer to a function that encodes an M-text
3570     according to the coding system.  The pointed function is called
3571     with six arguments:
3572
3573         @li A pointer to the M-text to encode.
3574         @li The starting position of the encoding.
3575         @li The ending position of the encoding.
3576         @li A pointer to a memory area where the produced bytes are stored.
3577         @li The size of the memory area.
3578         @li A pointer to a converter object.
3579
3580     $ENCODER must return 0 if it succeeds.  Otherwise it must return -1.
3581
3582     $EXTRA_INFO is a pointer to a data structure that contains extra
3583     information about the coding system.  The type of the data
3584     structure depends on $TYPE.
3585
3586     @return  
3587
3588     If the operation was successful, mconv_define_coding () returns a
3589     symbol whose name is $NAME.  If an error is detected, it returns
3590     #Mnil and assigns an error code to the external variable #merror_code.  */
3591
3592 /***ja
3593     @brief ¥³¡¼¥É·Ï¤òÄêµÁ¤¹¤ë.
3594
3595     ´Ø¿ô mconv_define_coding () ¤Ï¡¢¿·¤·¤¤¥³¡¼¥É·Ï¤òÄêµÁ¤·¡¢¤½¤ì¤ò 
3596     $NAME ¤È¤¤¤¦Ì¾Á°¤Î¥·¥ó¥Ü¥ë·Ðͳ¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£ $PLIST 
3597     ¤Ç¤ÏÄêµÁ¤¹¤ë¥³¡¼¥É·Ï¤Î¥Ñ¥é¥á¡¼¥¿¤ò°Ê²¼¤Î¤è¤¦¤Ë»ØÄꤹ¤ë¡£
3598
3599     <ul>
3600
3601     <li> ¥­¡¼¤¬ @c Mtype ¤ÇÃͤ¬¥·¥ó¥Ü¥ë¤Î»þ
3602
3603     Ãͤϥ³¡¼¥É·Ï¤Î¥¿¥¤¥×¤òɽ¤·¡¢#Mcharset, #Mutf, #Miso_2022, #Mnil 
3604     ¤Î¤¤¤º¤ì¤«¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3605
3606     ¥¿¥¤¥×¤¬ #Mcharset ¤Ê¤é¤Ð $EXTRA_INFO ¤Ï̵»ë¤µ¤ì¤ë¡£
3607
3608     ¥¿¥¤¥×¤¬ #Mutf ¤Ê¤é¤Ð $EXTRA_INFO ¤Ï #MCodingInfoUTF 
3609     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3610
3611     ¥¿¥¤¥×¤¬ #Miso_2022¤Ê¤é¤Ð $EXTRA_INFO ¤Ï #MCodingInfoISO2022 
3612     ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3613
3614     ¥¿¥¤¥×¤¬ #Mnil ¤Ê¤é¤Ð¡¢°ú¿ô $RESETTER, $DECODER, $ENCODER 
3615     ¤òÍ¿¤¨¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£$EXTRA_INFO ¤Ï̵»ë¤µ¤ì¤ë¡£
3616     ¤½¤ì°Ê³°¤Î¾ì¹ç¤Ë¤Ï¤³¤ì¤é¤Ï @c NULL ¤Ç¤è¤¯¡¢
3617     m17n ¥é¥¤¥Ö¥é¥ê¤¬Å¬Àڤʥǥե©¥ë¥ÈÃͤòÍ¿¤¨¤ë¡£
3618
3619     <li> ¥­¡¼¤¬ #Mcharsets ¤ÇÃͤ¬ plist ¤Î»þ
3620
3621     ÃͤϤ³¤Î¥³¡¼¥É·Ï¤Ç¥µ¥Ý¡¼¥È¤µ¤ì¤ëʸ»ú¥»¥Ã¥È¤Î¥ê¥¹¥È¤Ç¤¢¤ë¡£plist¤Î¥­¡¼¤Ï
3622     #Msymbol¡¢ÃͤÏʸ»ú¥»¥Ã¥È¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤Ç¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3623
3624     <li> ¥­¡¼¤¬ #Mflags Ãͤ¬ plist ¤Î»þ
3625
3626     ¥¿¥¤¥×¤¬ #Miso_2022 ¤Ê¤é¤Ð¡¢¤³¤ÎÃͤÏ, ISO 2022 
3627     ¥¤¥ó¥¿¥×¥ê¥¿ÍѤÎÀ©¸æ¥Õ¥é¥Ã¥°¤ò¼¨¤¹¡£plist ¤Î¥­¡¼¤Ï #Msymbol 
3628     ¤Ç¤¢¤ê¡¢Ãͤϰʲ¼¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
3629
3630     <ul>
3631
3632     <li> #Mreset_at_eol
3633
3634     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢¿Þ·Áʸ»ú½¸¹ç¤Î»Ø¼¨¤ä¸Æ½Ð¤Ï¹ÔËö¤Ç¥ê¥»¥Ã¥È¤µ¤ì¤ÆÅö½é¤Î¾õÂÖ¤ËÌá¤ë¡£
3635
3636     <li> #Mreset_at_cntl
3637
3638     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢¿Þ·Áʸ»ú½¸¹ç¤Î»Ø¼¨¤ä¸Æ½Ð¤ÏÀ©¸æʸ»ú¤Ë½Ð²ñ¤Ã¤¿»þÅÀ¤Ç¥ê¥»¥Ã¥È¤µ¤ì¤ÆÅö½é¤Î¾õÂÖ¤ËÌá¤ë¡£
3639
3640     <li> #Meight_bit
3641
3642     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢¿Þ·Áʸ»ú½¸¹ç¤Î±¦È¾Ì̤¬ÍѤ¤¤é¤ì¤ë¡£
3643
3644     <li> #Mlong_form
3645
3646     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢Ê¸»ú½¸¹ç JISX0208.1978, GB2312, JISX0208 
3647     ¤ò»Ø¼¨¤¹¤ëºÝ¤Ë over-long ¥¨¥¹¥±¡¼¥×¥·¡¼¥±¥ó¥¹ (ESC '$' '('
3648     <final_byte>) ¤¬ÍѤ¤¤é¤ì¤ë¡£
3649
3650     <li> #Mdesignation_g0
3651
3652     ¤³¤Î¥Õ¥é¥°¤È #Mfull_support ¤¬¤¢¤ì¤Ð¡¢Ê¸»ú¥»¥Ã¥È¥ê¥¹¥È¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¥»¥Ã¥È¤ò
3653     G0 ½¸¹ç¤Ë»Ø¼¨¤¹¤ë¡£
3654
3655     <li> #Mdesignation_g1
3656
3657     ¤³¤Î¥Õ¥é¥°¤È #Mfull_support ¤¬¤¢¤ì¤Ð¡¢Ê¸»ú¥»¥Ã¥È¥ê¥¹¥È¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¥»¥Ã¥È¤ò
3658     G1 ½¸¹ç¤Ë»Ø¼¨¤¹¤ë¡£
3659
3660     <li> #Mdesignation_ctext
3661
3662     ¤³¤Î¥Õ¥é¥°¤È #Mfull_support ¤¬¤¢¤ì¤Ð¡¢Ê¸»ú¥»¥Ã¥È¥ê¥¹¥È¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¥»¥Ã¥È¤ò
3663     G0 ½¸¹ç¤Þ¤¿¤Ï G1 ½¸¹ç¤Ë¡¢¥³¥ó¥Ñ¥¦¥ó¥É¥Æ¥­¥¹¥È¤Î´ð½à¤Ë¤½¤Ã¤Æ»Ø¼¨¤¹¤ë¡£
3664
3665     <li> #Mdesignation_ctext_ext
3666
3667     ¤³¤Î¥Õ¥é¥°¤È #Mfull_support ¤¬¤¢¤ì¤Ð¡¢Ê¸»ú¥»¥Ã¥È¥ê¥¹¥È¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¥»¥Ã¥È¤ò
3668     G0 ½¸¹ç¤Þ¤¿¤Ï G1 ½¸¹ç¤Ë¡¢¤¢¤ë¤¤¤Ï³ÈÄ¥¥»¥°¥á¥ó¥È¤Ë¥³¥ó¥Ñ¥¦¥ó¥É¥Æ¥­¥¹¥È¤Î´ð½à¤Ë¤½¤Ã¤Æ»Ø¼¨¤¹¤ë¡£
3669
3670     <li> #Mlocking_shift
3671
3672     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢¥í¥Ã¥­¥ó¥°¥·¥Õ¥È¤òÍѤ¤¤ë¡£
3673
3674     <li> #Msingle_shift
3675
3676     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢¥·¥ó¥°¥ë¥·¥Õ¥È¤òÍѤ¤¤ë¡£
3677
3678     <li> #Msingle_shift_7
3679
3680     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢7-bit ¥·¥ó¥°¥ë¥·¥Õ¥È¥³¡¼¥É (0x19) ¤òÍѤ¤¤ë¡£   
3681     
3682     <li> #Meuc_tw_shift
3683
3684     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢EUC-TW ¤Ë±è¤Ã¤¿ÆÃÊ̤ʥ·¥Õ¥È¤òÍѤ¤¤ë¡£
3685
3686     <li> #Miso_6429
3687
3688     ¸½»þÅÀ¤Ç¤ÏÍѤ¤¤é¤ì¤Æ¤¤¤Ê¤¤¡£
3689
3690     <li> #Mrevision_number
3691
3692     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢revision number ¤ò»ý¤Äʸ»ú¥»¥Ã¥È¤ò»Ø¼¨¤¹¤ëºÝ¤Ë 
3693     revision number ¥¨¥¹¥±¡¼¥×¥·¡¼¥¯¥¨¥ó¥¹¤òÍѤ¤¤ë¡£
3694
3695     <li> #Mfull_support
3696
3697     ¤³¤Î¥Õ¥é¥°¤¬¤¢¤ì¤Ð¡¢the International Registry 
3698     ¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ëÁ´Ê¸»ú¥»¥Ã¥È¤ò¥µ¥Ý¡¼¥È¤¹¤ë¡£
3699
3700     </ul>
3701
3702     <li> ¥­¡¼¤¬ #Mdesignation¤ÇÃͤ¬ plist ¤Î»þ
3703
3704     ¥¿¥¤¥×¤¬ #Miso_2022 ¤Ê¤é¤Ð¡¢ÃͤϳÆʸ»ú¤ò¤É¤Î¤è¤¦¤Ë»Ø¼¨¤¹¤ë¤«¤ò¼¨¤¹¡£
3705     plist ¤Î¥­¡¼¤Ï #Minteger¡¢ÃͤϽ¸¹ç¡Êgraphic register¡Ë
3706     ¤ò¼¨¤¹¿ô»ú¤Ç¤¢¤ë¡£NÈÖÌܤÎÍ×ÁǤÎÃͤϡ¢Ê¸»ú¥»¥Ã¥È¥ê¥¹¥È¤Î N 
3707     ÈÖÌܤÎʸ»ú¥»¥Ã¥È¤ËÂбþ¤¹¤ë¡£Ãͤ¬ 0..3 ¤Ç¤¢¤ì¤Ð¡¢Ê¸»ú¥»¥Ã¥È¤¬¤¹¤Ç¤Ë 
3708     G0..G3 ¤Ë»Ø¼¨ ¤µ¤ì¤Æ¤¤¤ë¡£
3709
3710     Ãͤ¬Éé(-4..-1) ¤Ç¤¢¤ì¤Ð¡¢½é´ü¾õÂ֤ǤÏʸ»ú¥»¥Ã¥È¤¬¤É¤³¤Ë¤â»Ø¼¨¤µ¤ì¤Æ¤¤¤Ê¤¤¤³¤È¡¢É¬ÍפʺݤˤÏ
3711     G0..G3 ¤Î¤½¤ì¤¾¤ì¤Ë»Ø¼¨¤¹¤ë¤³¤È¤ò°ÕÌ£¤¹¤ë¡£
3712
3713     <li> ¥­¡¼¤¬ #Minvocation¤ÇÃͤ¬ plist ¤Î»þ
3714
3715     ¥¿¥¤¥×¤¬ #Miso_2022 ¤Ê¤é¤Ð¡¢Ãͤϳƽ¸¹ç¤ò¤É¤Î¤è¤¦¤Ë¸Æ¤Ó½Ð¤¹¤«¤ò¼¨¤¹¡£
3716     plist ¤ÎŤµ¤Ï 1 ¤Ê¤¤¤· 2 ¤Ç¤¢¤ë¡£plist ¤Î¥­¡¼¤Ï 
3717     #Minteger¡¢ÃͤϽ¸¹ç¡Êgraphic register)¤ò¼¨¤¹¿ô»ú¤Ç¤¢¤ë¡£
3718     ºÇ½é¤ÎÍ×ÁǤÎÃͤ¬¿Þ·Áʸ»ú½¸¹çº¸È¾Ì̤˸ƤӽФµ¤ì¤ë½¸¹ç¤ò¼¨¤¹¡£
3719     plist ¤ÎŤµ¤¬ 1 ¤Ê¤é¤Ð¡¢±¦È¾Ì̤ˤϲ¿¤â¸Æ¤Ó½Ð¤µ¤ì¤Ê¤¤¡£
3720     ¤½¤¦¤Ç¤±¤ì¤Ð¡¢£²¤Ä¤á¤ÎÍ×ÁǤÎÃͤ¬¿Þ·Áʸ»ú½¸¹ç±¦È¾Ì̤˸ƤӽФµ¤ì¤ë½¸¹ç¤ò¼¨¤¹¡£
3721
3722     <li> ¥­¡¼¤¬ #Mcode_unit ¤ÇÃͤ¬À°¿ôÃͤλþ
3723
3724     ¥¿¥¤¥×¤¬ #Mutf ¤Ê¤é¤Ð¡¢Ãͤϥ³¡¼¥É¥æ¥Ë¥Ã¥È¤Î¥Ó¥Ã¥ÈŤǤ¢¤ê¡¢8, 16,
3725     32 ¤Î¤¤¤º¤ì¤«¤Ç¤¢¤ë¡£
3726
3727     <li> ¥­¡¼¤¬ #Mbom ¤ÇÃͤ¬¥·¥ó¥Ü¥ë¤Î»þ
3728
3729     ¥¿¥¤¥×¤¬ #Mutf ¤Ç¥³¡¼¥É¥æ¥Ë¥Ã¥È¤Î¥Ó¥Ã¥ÈŤ¬ 16 ¤« 32¤Ê¤é¤Ð¡¢ÃͤÏ
3730     BOM (Byte Order Mark) ¤ò»ÈÍѤ¹¤ë¤«¤É¤¦¤«¤ò¼¨¤¹¡£Ãͤ¬¥Ç¥Õ¥©¥ë¥ÈÃͤΠ
3731     #Mnil ¤Ê¤é¤Ð¡¢»ÈÍѤ·¤Ê¤¤¡£Ãͤ¬ #Mmaybe ¤Ê¤é¤Ð¥Ç¥³¡¼¥É»þ¤Ë BOM 
3732     ¤¬¤¢¤ë¤«¤É¤¦¤«¤òÄ´¤Ù¤ë¡£¤½¤ì°Ê³°¤Ê¤é¤Ð»ÈÍѤ¹¤ë¡£
3733
3734     <li> ¥­¡¼¤¬ #Mlittle_endian ¤ÇÃͤ¬¥·¥ó¥Ü¥ë¤Î»þ 
3735
3736     ¥¿¥¤¥×¤¬ #Mutf ¤Ç¥³¡¼¥É¥æ¥Ë¥Ã¥È¤Î¥Ó¥Ã¥ÈŤ¬ 16 ¤« 32
3737     ¤Ê¤é¤Ð¡¢Ãͤϥ¨¥ó¥³¡¼¥É¤¬ little endian ¤«¤É¤¦¤«¤ò¼¨¤¹¡£Ãͤ¬¥Ç¥Õ¥©¥ë¥ÈÃͤÎ
3738     #Mnil ¤Ê¤é¤Ð big endian ¤Ç¤¢¤ê¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð little endian ¤Ç¤¢¤ë¡£
3739
3740     </ul>
3741
3742     $RESETTER 
3743     ¤Ï¤³¤Î¥³¡¼¥É·ÏÍѤΥ³¥ó¥Ð¡¼¥¿¤ò½é´ü¾õÂ֤˥ꥻ¥Ã¥È¤¹¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
3744     ¤³¤Î´Ø¿ô¤Ï¥³¥ó¥Ð¡¼¥¿¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿¤È¤¤¤¦£±°ú¿ô¤ò¤È¤ë¡£
3745
3746     $DECODER ¤Ï¥Ð¥¤¥ÈÎó¤ò¤³¤Î¥³¡¼¥É·Ï¤Ë½¾¤Ã¤Æ¥Ç¥³¡¼¥É¤¹¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
3747     ¤³¤Î´Ø¿ô¤Ï°Ê²¼¤Î£´°ú¿ô¤ò¤È¤ë¡£
3748
3749         @li ¥Ç¥³¡¼¥É¤¹¤ë¥Ð¥¤¥ÈÎó¤Ø¤Î¥Ý¥¤¥ó¥¿
3750         @li ¥Ç¥³¡¼¥É¤¹¤Ù¤­¥Ð¥¤¥È¿ô
3751         @li ¥Ç¥³¡¼¥É·ë²Ì¤Îʸ»ú¤òÉղ乤ë M-text ¤Ø¤Î¥Ý¥¤¥ó¥¿
3752         @li ¥³¥ó¥Ð¡¼¥¿¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿
3753
3754     $DECODER ¤ÏÀ®¸ù¤·¤¿¤È¤­¤Ë¤Ï 0 ¤ò¡¢¼ºÇÔ¤·¤¿¤È¤­¤Ë¤Ï -1 
3755     ¤òÊÖ¤µ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3756
3757     $ENCODER ¤Ï M-text ¤ò¤³¤Î¥³¡¼¥É·Ï¤Ë½¾¤Ã¤Æ¥¨¥ó¥³¡¼¥É¤¹¤ë´Ø¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
3758     ¤³¤Î´Ø¿ô¤Ï°Ê²¼¤Î£¶°ú¿ô¤ò¤È¤ë¡£
3759
3760         @li ¥¨¥ó¥³¡¼¥É¤¹¤ëM-text ¤Ø¤Î¥Ý¥¤¥ó¥¿
3761         @li M-text ¤Î¥¨¥ó¥³¡¼¥É³«»Ï°ÌÃÖ
3762         @li M-text ¤Î¥¨¥ó¥³¡¼¥É½ªÎ»°ÌÃÖ
3763         @li À¸À®¤·¤¿¥Ð¥¤¥È¤òÊÝ»ý¤¹¤ë¥á¥â¥êÎΰè¤Ø¤Î¥Ý¥¤¥ó¥¿
3764         @li ¥á¥â¥êÎΰè¤Î¥µ¥¤¥º
3765         @li ¥³¥ó¥Ð¡¼¥¿¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î¥Ý¥¤¥ó¥¿
3766
3767     $ENCODER ¤ÏÀ®¸ù¤·¤¿¤È¤­¤Ë¤Ï 0 ¤ò¡¢¼ºÇÔ¤·¤¿¤È¤­¤Ë¤Ï -1 
3768     ¤òÊÖ¤µ¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
3769
3770     $EXTRA_INFO ¤Ï¥³¡¼¥Ç¥£¥°¥·¥¹¥Æ¥à¤Ë´Ø¤¹¤ëÄɲþðÊó¤ò´Þ¤à¥Ç¡¼¥¿¹½Â¤¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£
3771     ¤³¤Î¥Ç¡¼¥¿¹½Â¤¤Î·¿ $TYPE ¤Ë°Í¸¤¹¤ë¡£
3772
3773     @return  
3774
3775     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mconv_define_coding () ¤Ï $NAME 
3776     ¤È¤¤¤¦Ì¾Á°¤Î¥·¥ó¥Ü¥ë¤òÊÖ¤¹¡£ ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï #Mnil
3777     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
3778       */
3779
3780 /***
3781     @errors
3782     @c MERROR_CODING  */
3783
3784 MSymbol
3785 mconv_define_coding (const char *name, MPlist *plist,
3786                      int (*resetter) (MConverter *),
3787                      int (*decoder) (const unsigned char *, int, MText *,
3788                                      MConverter *),
3789                      int (*encoder) (MText *, int, int,
3790                                      unsigned char *, int,
3791                                      MConverter *),
3792                      void *extra_info)
3793 {
3794   MSymbol sym = msymbol (name);
3795   int i;
3796   MCodingSystem *coding;
3797   MPlist *pl;
3798
3799   MSTRUCT_MALLOC (coding, MERROR_CODING);
3800   coding->name = sym;
3801   if ((coding->type = (MSymbol) mplist_get (plist, Mtype)) == Mnil)
3802     coding->type = Mcharset;
3803   pl = (MPlist *) mplist_get (plist, Mcharsets);
3804   if (! pl)
3805     MERROR (MERROR_CODING, Mnil);
3806   coding->ncharsets = mplist_length (pl);
3807   if (coding->ncharsets > NUM_SUPPORTED_CHARSETS)
3808     coding->ncharsets = NUM_SUPPORTED_CHARSETS;
3809   for (i = 0; i < coding->ncharsets; i++, pl = MPLIST_NEXT (pl))
3810     {
3811       MSymbol charset_name;
3812
3813       if (MPLIST_KEY (pl) != Msymbol)
3814         MERROR (MERROR_CODING, Mnil);
3815       charset_name = MPLIST_SYMBOL (pl);
3816       if (! (coding->charsets[i] = MCHARSET (charset_name)))
3817         MERROR (MERROR_CODING, Mnil);
3818     }
3819
3820   coding->resetter = resetter;
3821   coding->decoder = decoder;
3822   coding->encoder = encoder;
3823   coding->ascii_compatible = 0;
3824   coding->extra_info = extra_info;
3825   coding->extra_spec = NULL;
3826   coding->ready = 0;
3827
3828   if (coding->type == Mcharset)
3829     {
3830       if (! coding->resetter)
3831         coding->resetter = reset_coding_charset;
3832       if (! coding->decoder)
3833         coding->decoder = decode_coding_charset;
3834       if (! coding->encoder)
3835         coding->encoder = encode_coding_charset;
3836     }
3837   else if (coding->type == Mutf)
3838     {
3839       MCodingInfoUTF *info = malloc (sizeof (MCodingInfoUTF));
3840       MSymbol val;
3841
3842       if (! coding->resetter)
3843         coding->resetter = reset_coding_utf;
3844
3845       info->code_unit_bits = (int) mplist_get (plist, Mcode_unit);
3846       if (info->code_unit_bits == 8)
3847         {
3848           if (! coding->decoder)
3849             coding->decoder = decode_coding_utf_8;
3850           if (! coding->encoder)
3851             coding->encoder = encode_coding_utf_8;
3852         }
3853       else if (info->code_unit_bits == 16)
3854         {
3855           if (! coding->decoder)
3856             coding->decoder = decode_coding_utf_16;
3857           if (! coding->encoder)
3858             coding->encoder = encode_coding_utf_16;
3859         }
3860       else if (info->code_unit_bits == 32)
3861         {
3862           if (! coding->decoder)
3863             coding->decoder = decode_coding_utf_32;
3864           if (! coding->encoder)
3865             coding->encoder = encode_coding_utf_32;
3866         }
3867       else
3868         MERROR (MERROR_CODING, Mnil);
3869       val = (MSymbol) mplist_get (plist, Mbom);
3870       if (val == Mnil)
3871         info->bom = 1;
3872       else if (val == Mmaybe)
3873         info->bom = 0;
3874       else
3875         info->bom = 2;
3876
3877       info->endian = (mplist_get (plist, Mlittle_endian) ? 1 : 0);
3878       coding->extra_info = info;
3879     }
3880   else if (coding->type == Miso_2022)
3881     {
3882       MCodingInfoISO2022 *info = malloc (sizeof (MCodingInfoISO2022));
3883
3884       if (! coding->resetter)
3885         coding->resetter = reset_coding_iso_2022;
3886       if (! coding->decoder)
3887         coding->decoder = decode_coding_iso_2022;
3888       if (! coding->encoder)
3889         coding->encoder = encode_coding_iso_2022;
3890
3891       info->initial_invocation[0] = 0;
3892       info->initial_invocation[1] = -1;
3893       pl = (MPlist *) mplist_get (plist, Minvocation);
3894       if (pl)
3895         {
3896           if (MPLIST_KEY (pl) != Minteger)
3897             MERROR (MERROR_CODING, Mnil);
3898           info->initial_invocation[0] = MPLIST_INTEGER (pl);
3899           if (! MPLIST_TAIL_P (pl))
3900             {
3901               pl = MPLIST_NEXT (pl);
3902               if (MPLIST_KEY (pl) != Minteger)
3903                 MERROR (MERROR_CODING, Mnil);
3904               info->initial_invocation[1] = MPLIST_INTEGER (pl);
3905             }
3906         }
3907       memset (info->designations, 0, sizeof (info->designations));
3908       for (i = 0, pl = (MPlist *) mplist_get (plist, Mdesignation);
3909            i < 32 && pl && MPLIST_KEY (pl) == Minteger;
3910            i++, pl = MPLIST_NEXT (pl))
3911         info->designations[i] = MPLIST_INTEGER (pl);
3912
3913       info->flags = 0;
3914       MPLIST_DO (pl, (MPlist *) mplist_get (plist, Mflags))
3915         {
3916           MSymbol val;
3917
3918           if (MPLIST_KEY (pl) != Msymbol)
3919             MERROR (MERROR_CODING, Mnil);
3920           val = MPLIST_SYMBOL (pl);
3921           if (val == Mreset_at_eol)
3922             info->flags |= MCODING_ISO_RESET_AT_EOL;
3923           else if (val == Mreset_at_cntl)
3924             info->flags |= MCODING_ISO_RESET_AT_CNTL;
3925           else if (val == Meight_bit)
3926             info->flags |= MCODING_ISO_EIGHT_BIT;
3927           else if (val == Mlong_form)
3928             info->flags |= MCODING_ISO_LOCKING_SHIFT;
3929           else if (val == Mdesignation_g0)
3930             info->flags |= MCODING_ISO_DESIGNATION_G0;
3931           else if (val == Mdesignation_g1)
3932             info->flags |= MCODING_ISO_DESIGNATION_G1;
3933           else if (val == Mdesignation_ctext)
3934             info->flags |= MCODING_ISO_DESIGNATION_CTEXT;
3935           else if (val == Mdesignation_ctext_ext)
3936             info->flags |= MCODING_ISO_DESIGNATION_CTEXT_EXT;
3937           else if (val == Mlocking_shift)
3938             info->flags |= MCODING_ISO_LOCKING_SHIFT;
3939           else if (val == Msingle_shift)
3940             info->flags |= MCODING_ISO_SINGLE_SHIFT;
3941           else if (val == Msingle_shift_7)
3942             info->flags |= MCODING_ISO_SINGLE_SHIFT_7;
3943           else if (val == Meuc_tw_shift)
3944             info->flags |= MCODING_ISO_EUC_TW_SHIFT;
3945           else if (val == Miso_6429)
3946             info->flags |= MCODING_ISO_ISO6429;
3947           else if (val == Mrevision_number)
3948             info->flags |= MCODING_ISO_REVISION_NUMBER;
3949           else if (val == Mfull_support)
3950             info->flags |= MCODING_ISO_FULL_SUPPORT;
3951         }
3952
3953       coding->extra_info = info;
3954     }
3955   else
3956     {
3957       if (! coding->decoder || ! coding->encoder)
3958         MERROR (MERROR_CODING, Mnil);
3959       if (! coding->resetter)
3960         coding->ready = 1;
3961     }
3962
3963   msymbol_put (sym, Mcoding, coding);
3964   msymbol_put (msymbol__canonicalize (sym), Mcoding, coding);
3965   plist = (MPlist *) mplist_get (plist, Maliases);
3966   if (plist)
3967     {
3968       MPLIST_DO (pl, plist)
3969         {
3970           MSymbol alias;
3971
3972           if (MPLIST_KEY (pl) != Msymbol)
3973             continue;
3974           alias = MPLIST_SYMBOL (pl);
3975           msymbol_put (alias, Mcoding, coding);
3976           msymbol_put (msymbol__canonicalize (alias), Mcoding, coding);
3977         }
3978     }
3979
3980   MLIST_APPEND1 (&coding_list, codings, coding, MERROR_CODING);
3981
3982   return sym;
3983 }
3984
3985 /*=*/
3986
3987 /***en
3988     @brief Resolve coding system name.
3989
3990     The mconv_resolve_coding () function returns $SYMBOL if it
3991     represents a coding system.  Otherwise, canonicalize $SYMBOL as to
3992     a coding system name, and if the canonicalized name represents a
3993     coding system, return it.  Otherwise, return #Mnil.  */
3994 /***ja
3995     @brief ¥³¡¼¥É·Ï¤Î̾Á°¤ò²ò·è¤¹¤ë.
3996
3997     ´Ø¿ô mconv_resolve_coding () ¤Ï $SYMBOL ¤¬¥³¡¼¥É·Ï¤ò¼¨¤·¤Æ¤¤¤ì¤Ð¤½¤ì¤òÊÖ¤¹¡£
3998     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¥³¡¼¥É·Ï¤Î̾Á°¤È¤·¤Æ $SYMBOL 
3999     ¤òÀµµ¬²½¤·¡¢¤½¤ì¤¬¥³¡¼¥É·Ï¤òɽ¤·¤Æ¤¤¤ì¤ÐÀµµ¬²½¤·¤¿ $SYMBOL ¤òÊÖ¤¹¡£
4000     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð#Mnil ¤òÊÖ¤¹¡£  */
4001
4002
4003
4004 MSymbol
4005 mconv_resolve_coding (MSymbol symbol)
4006 {
4007   MCodingSystem *coding = find_coding (symbol);
4008
4009   if (! coding)
4010     {
4011       symbol = msymbol__canonicalize (symbol);
4012       coding = find_coding (symbol);
4013     }
4014   return (coding ? coding->name : Mnil);
4015 }
4016
4017 /*=*/
4018
4019
4020 /***en
4021     @brief List symbols representing coding systems.
4022
4023     The mconv_list_codings () function makes an array of symbols
4024     representing a coding system, stores the pointer to the array in a
4025     place pointed to by $SYMBOLS, and returns the length of the array.  */
4026 /***ja
4027     @brief ¥³¡¼¥É·Ï¤òɽ¤ï¤¹¥·¥ó¥Ü¥ë¤òÎóµó¤¹¤ë.
4028
4029     ´Ø¿ô mchar_list_codings () ¤Ï¡¢¥³¡¼¥É·Ï¤ò¼¨¤¹¥·¥ó¥Ü¥ë¤òʤ٤¿ÇÛÎó¤òºî¤ê¡¢
4030     $SYMBOLS ¤Ç¥Ý¥¤¥ó¥È¤µ¤ì¤¿¾ì½ê¤Ë¤³¤ÎÇÛÎó¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÃÖ¤­¡¢ÇÛÎó¤ÎŤµ¤òÊÖ¤¹¡£ */
4031
4032 int
4033 mconv_list_codings (MSymbol **symbols)
4034 {
4035   int i = coding_list.used + mplist_length (coding_definition_list);
4036   int j;
4037   MPlist *plist;
4038
4039   MTABLE_MALLOC ((*symbols), i, MERROR_CODING);
4040   i = 0;
4041   MPLIST_DO (plist, coding_definition_list)
4042     {
4043       MPlist *pl = MPLIST_VAL (plist);
4044       (*symbols)[i++] = MPLIST_SYMBOL (pl);
4045     }
4046   for (j = 0; j < coding_list.used; j++)
4047     if (! mplist_find_by_key (coding_definition_list, 
4048                               coding_list.codings[j]->name))
4049       (*symbols)[i++] = coding_list.codings[j]->name;
4050   return i;
4051 }
4052
4053 /*=*/
4054
4055 /***en
4056     @brief Create a code converter bound to a buffer.
4057
4058     The mconv_buffer_converter () function creates a pointer to a code
4059     converter for coding system $NAME.  The code converter is bound
4060     to buffer area of $N bytes pointed to by $BUF.  Subsequent
4061     decodings and encodings are done to/from this buffer area.
4062
4063     $NAME can be #Mnil.  In this case, a coding system associated
4064     with the current locale (LC_CTYPE) is used.
4065
4066     @return
4067     If the operation was successful, mconv_buffer_converter () returns
4068     the created code converter.  Otherwise it returns @c NULL and
4069     assigns an error code to the external variable #merror_code.  */
4070
4071 /***ja
4072     @brief ¥Ð¥Ã¥Õ¥¡¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òºî¤ë.
4073
4074     ´Ø¿ô mconv_buffer_converter () ¤Ï¡¢¥³¡¼¥É·Ï $NAME 
4075     ÍѤΥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òºî¤ë¡£¤³¤Î¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤Ï¡¢$BUF ¤Ç¼¨¤µ¤ì¤ëÂ礭¤µ $N 
4076     ¥Ð¥¤¥È¤Î¥Ð¥Ã¥Õ¥¡Îΰè¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤ë¡£
4077     ¤³¤ì°Ê¹ß¤Î¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤Ï¡¢¤³¤Î¥Ð¥Ã¥Õ¥¡Îΰè¤ËÂФ·¤Æ¹Ô¤Ê¤ï¤ì¤ë¡£
4078
4079     $NAME ¤Ï #Mnil ¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¡£¤³¤Î¾ì¹ç¤Ï¸½ºß¤Î¥í¥±¡¼¥ë 
4080     (LC_CTYPE) ¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥³¡¼¥É·Ï¤¬»È¤ï¤ì¤ë¡£
4081
4082     @return
4083     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð mconv_buffer_converter () ¤Ï ºîÀ®¤·¤¿¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òÊÖ¤¹¡£
4084     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
4085     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
4086
4087     @latexonly \IPAlabel{mconverter} @endlatexonly  */
4088
4089 /***
4090     @errors
4091     @c MERROR_SYMBOL, @c MERROR_CODING
4092
4093     @seealso 
4094     mconv_stream_converter ()  */
4095
4096 MConverter *
4097 mconv_buffer_converter (MSymbol name, const unsigned char *buf, int n)
4098 {
4099   MCodingSystem *coding;
4100   MConverter *converter;
4101   MConverterStatus *internal;
4102
4103   if (name == Mnil)
4104     name = mlocale_get_prop (mlocale__ctype, Mcoding);
4105   coding = find_coding (name);
4106   if (! coding)
4107     MERROR (MERROR_CODING, NULL);
4108   MSTRUCT_CALLOC (converter, MERROR_CODING);
4109   MSTRUCT_CALLOC (internal, MERROR_CODING);
4110   converter->internal_info = internal;
4111   internal->coding = coding;
4112   if (coding->resetter
4113       && (*coding->resetter) (converter) < 0)
4114     {
4115       free (internal);
4116       free (converter);
4117       MERROR (MERROR_CODING, NULL);
4118     }
4119
4120   internal->unread = mtext ();
4121   internal->work_mt = mtext ();
4122   mtext__enlarge (internal->work_mt, MAX_UTF8_CHAR_BYTES);
4123   internal->buf.in = buf;
4124   internal->used = 0;
4125   internal->bufsize = n;
4126   internal->binding = BINDING_BUFFER;
4127
4128   return converter;
4129 }
4130
4131 /*=*/
4132
4133 /***en
4134     @brief Create a code converter bound to a stream.
4135
4136     The mconv_stream_converter () function creates a pointer to a code
4137     converter for coding system $NAME.  The code converter is bound
4138     to stream $FP.  Subsequent decodings and encodings are done
4139     to/from this stream.
4140
4141     $NAME can be #Mnil.  In this case, a coding system associated
4142     with the current locale (LC_CTYPE) is used.
4143
4144     @return If the operation was successful, mconv_stream_converter ()
4145     returns the created code converter.  Otherwise it returns @c NULL
4146     and assigns an error code to the external variable 
4147     #merror_code.  */
4148
4149 /***ja
4150     @brief ¥¹¥È¥ê¡¼¥à¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òºî¤ë.
4151
4152     ´Ø¿ô mconv_stream_converter () ¤Ï¡¢¥³¡¼¥É·Ï $NAME 
4153     ÍѤΥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òºî¤ë¡£¤³¤Î¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤Ï¡¢¥¹¥È¥ê¡¼¥à $FP 
4154     ¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤ë¡£
4155     ¤³¤ì°Ê¹ß¤Î¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤Ï¡¢¤³¤Î¥¹¥È¥ê¡¼¥à¤ËÂФ·¤Æ¹Ô¤Ê¤ï¤ì¤ë¡£
4156
4157     $NAME ¤Ï #Mnil ¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¡£¤³¤Î¾ì¹ç¤Ï¸½ºß¤Î¥í¥±¡¼¥ë 
4158     (LC_CTYPE) ¤Ë´ØÏ¢ÉÕ¤±¤é¤ì¤¿¥³¡¼¥É·Ï¤¬»È¤ï¤ì¤ë¡£
4159
4160     @return 
4161     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_stream_converter () 
4162     ¤ÏºîÀ®¤·¤¿¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL 
4163     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
4164
4165     @latexonly \IPAlabel{mconverter} @endlatexonly  */
4166
4167 /***
4168     @errors
4169     @c MERROR_SYMBOL, @c MERROR_CODING
4170
4171     @seealso
4172     mconv_buffer_converter ()  */
4173
4174 MConverter *
4175 mconv_stream_converter (MSymbol name, FILE *fp)
4176 {
4177   MCodingSystem *coding;
4178   MConverter *converter;
4179   MConverterStatus *internal;
4180
4181   if (name == Mnil)
4182     name = mlocale_get_prop (mlocale__ctype, Mcoding);
4183   coding = find_coding (name);
4184   if (! coding)
4185     MERROR (MERROR_CODING, NULL);
4186   MSTRUCT_CALLOC (converter, MERROR_CODING);
4187   MSTRUCT_CALLOC (internal, MERROR_CODING);
4188   converter->internal_info = internal;
4189   internal->coding = coding;
4190   if (coding->resetter
4191       && (*coding->resetter) (converter) < 0)
4192     {
4193       free (internal);
4194       free (converter);
4195       MERROR (MERROR_CODING, NULL);
4196     }
4197
4198   if (fseek (fp, 0, SEEK_CUR) < 0)
4199     {
4200       if (errno == EBADF)
4201         {
4202           free (internal);
4203           free (converter);
4204           return NULL;
4205         }
4206       internal->seekable = 0;
4207     }
4208   else
4209     internal->seekable = 1;
4210   internal->unread = mtext ();
4211   internal->work_mt = mtext ();
4212   mtext__enlarge (internal->work_mt, MAX_UTF8_CHAR_BYTES);
4213   internal->fp = fp;
4214   internal->binding = BINDING_STREAM;
4215
4216   return converter;
4217 }
4218
4219 /*=*/
4220
4221 /***en
4222     @brief Reset a code converter.
4223
4224     The mconv_reset_converter () function resets code converter
4225     $CONVERTER to the initial state.
4226
4227     @return
4228     If $CONVERTER->coding has its own reseter function,
4229     mconv_reset_converter () returns the result of that function
4230     applied to $CONVERTER.  Otherwise it returns 0.  */
4231
4232 /***ja
4233     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ò¥ê¥»¥Ã¥È¤¹¤ë.
4234
4235     ´Ø¿ô mconv_reset_converter () ¤Ï¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER 
4236     ¤ò½é´ü¾õÂÖ¤ËÌ᤹¡£
4237
4238     @return
4239     ¤â¤· $CONVERTER->coding ¤Ë¥ê¥»¥Ã¥ÈÍѤδؿô¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¤Ê¤é¤Ð¡¢
4240     mconv_reset_converter () ¤Ï¤½¤Î´Ø¿ô¤Ë $CONVERTER 
4241     ¤òŬÍѤ·¤¿·ë²Ì¤òÊÖ¤·¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð0¤òÊÖ¤¹¡£  */
4242
4243 int
4244 mconv_reset_converter (MConverter *converter)
4245 {
4246   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4247
4248   converter->nchars = converter->nbytes = 0;
4249   converter->result = MCONVERSION_RESULT_SUCCESS;
4250   internal->carryover_bytes = 0;
4251   internal->used = 0;
4252   mtext_reset (internal->unread);
4253   if (internal->coding->resetter)
4254     return (*internal->coding->resetter) (converter);
4255   return 0;
4256 }
4257
4258 /*=*/
4259
4260 /***en
4261     @brief Free a code converter.
4262
4263     The mconv_free_converter () function frees the code converter
4264     $CONVERTER.  */
4265
4266 /***ja
4267     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ò²òÊü¤¹¤ë.
4268
4269     ´Ø¿ô mconv_free_converter () ¤Ï¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER 
4270     ¤ò²òÊü¤¹¤ë¡£  */
4271
4272 void
4273 mconv_free_converter (MConverter *converter)
4274 {
4275   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4276
4277   M17N_OBJECT_UNREF (internal->work_mt);
4278   M17N_OBJECT_UNREF (internal->unread);
4279   free (internal);
4280   free (converter);
4281 }
4282
4283 /*=*/
4284
4285 /***en
4286     @brief Bind a buffer to a code converter.
4287
4288     The mconv_rebind_buffer () function binds buffer area of $N bytes
4289     pointed to by $BUF to code converter $CONVERTER.  Subsequent
4290     decodings and encodings are done to/from this newly bound buffer
4291     area.
4292
4293     @return
4294     This function always returns $CONVERTER.  */
4295
4296 /***ja
4297     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤Ë¥Ð¥Ã¥Õ¥¡Îΰè¤ò·ë¤ÓÉÕ¤±¤ë.
4298
4299     ´Ø¿ô mconv_rebind_buffer () ¤Ï¡¢$BUF ¤Ë¤è¤Ã¤Æ»Ø¤µ¤ì¤¿Â礭¤µ $N 
4300     ¥Ð¥¤¥È¤Î¥Ð¥Ã¥Õ¥¡Îΰè¤ò¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER ¤Ë·ë¤ÓÉÕ¤±¤ë¡£
4301     ¤³¤ì°Ê¹ß¤Î¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤Ï¡¢¤³¤Î¿·¤¿¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥Ð¥Ã¥Õ¥¡Îΰè¤ËÂФ·¤Æ¹Ô¤Ê¤ï¤ì¤ë¤è¤¦¤Ë¤Ê¤ë¡£
4302
4303     @return
4304     ¤³¤Î´Ø¿ô¤Ï¾ï¤Ë $CONVERTER ¤òÊÖ¤¹¡£
4305
4306     @latexonly \IPAlabel{mconv_rebind_buffer} @endlatexonly  */
4307
4308 /***
4309     @seealso
4310     mconv_rebind_stream () */
4311
4312 MConverter *
4313 mconv_rebind_buffer (MConverter *converter, const unsigned char *buf, int n)
4314 {
4315   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4316
4317   internal->buf.in = buf;
4318   internal->used = 0;
4319   internal->bufsize = n;
4320   internal->binding = BINDING_BUFFER;
4321   return converter;
4322 }
4323
4324 /*=*/
4325
4326 /***en
4327     @brief Bind a stream to a code converter.
4328
4329     The mconv_rebind_stream () function binds stream $FP to code
4330     converter $CONVERTER.  Following decodings and encodings are done
4331     to/from this newly bound stream.
4332
4333     @return
4334     This function always returns $CONVERTER.  */
4335
4336 /***ja
4337     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤Ë¥¹¥È¥ê¡¼¥à¤ò·ë¤ÓÉÕ¤±¤ë.
4338
4339     ´Ø¿ô mconv_rebind_stream () ¤Ï¡¢¥¹¥È¥ê¡¼¥à $FP ¤ò¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ 
4340     $CONVERTER ¤Ë·ë¤ÓÉÕ¤±¤ë¡£
4341     ¤³¤ì°Ê¹ß¤Î¥Ç¥³¡¼¥É¤ª¤è¤Ó¥¨¥ó¥³¡¼¥É¤Ï¡¢¤³¤Î¿·¤¿¤Ë·ë¤ÓÉÕ¤±¤é¤ì¤¿¥¹¥È¥ê¡¼¥à¤ËÂФ·¤Æ¹Ô¤Ê¤ï¤ì¤ë¤è¤¦¤Ë¤Ê¤ë¡£
4342
4343     @return
4344     ¤³¤Î´Ø¿ô¤Ï¾ï¤Ë $CONVERTER ¤òÊÖ¤¹¡£
4345
4346     @latexonly \IPAlabel{mconv_rebind_stream} @endlatexonly  */
4347
4348 /***
4349     @seealso
4350     mconv_rebind_buffer () */
4351
4352 MConverter *
4353 mconv_rebind_stream (MConverter *converter, FILE *fp)
4354 {
4355   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4356
4357   if (fseek (fp, 0, SEEK_CUR) < 0)
4358     {
4359       if (errno == EBADF)
4360         return NULL;
4361       internal->seekable = 0;
4362     }
4363   else
4364     internal->seekable = 1;
4365   internal->fp = fp;
4366   internal->binding = BINDING_STREAM;
4367   return converter;
4368 }
4369
4370 /*=*/
4371
4372 /***en
4373     @brief Decode a byte sequence into an M-text.
4374
4375     The mconv_decode () function decodes a byte sequence and appends
4376     the result at the end of M-text $MT.  The source byte sequence is
4377     taken from either the buffer area or the stream that is currently
4378     bound to $CONVERTER.
4379
4380     @return
4381     If the operation was successful, mconv_decode () returns updated
4382     $MT.  Otherwise it returns @c NULL and assigns an error code to
4383     the external variable #merror_code.  */
4384
4385 /***ja
4386     @brief ¥Ð¥¤¥ÈÎó¤ò M-text ¤Ë¥Ç¥³¡¼¥É¤¹¤ë.
4387
4388     ´Ø¿ô mconv_decode () ¤Ï¡¢¥Ð¥¤¥ÈÎó¤ò¥Ç¥³¡¼¥É¤·¤Æ¤½¤Î·ë²Ì¤ò M-text
4389     $MT ¤ÎËöÈø¤ËÄɲ乤롣¥Ç¥³¡¼¥É¸µ¤Î¥Ð¥¤¥ÈÎó¤Ï¡¢$CONVERTER 
4390     ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤«¤é¼è¤é¤ì¤ë¡£
4391
4392     @return
4393     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_decode () ¤Ï¹¹¿·¤µ¤ì¤¿ $MT ¤òÊÖ¤¹¡£
4394     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
4395     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4396
4397 /***
4398     @errors
4399     @c MERROR_IO, @c MERROR_CODING
4400
4401     @seealso
4402     mconv_rebind_buffer (), mconv_rebind_stream (),
4403     mconv_encode (), mconv_encode_range (),
4404     mconv_decode_buffer (), mconv_decode_stream ()  */
4405
4406 MText *
4407 mconv_decode (MConverter *converter, MText *mt)
4408 {
4409   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4410   int at_most = converter->at_most > 0 ? converter->at_most : -1;
4411   int n;
4412
4413   M_CHECK_READONLY (mt, NULL);
4414
4415   if (mt->format != MTEXT_FORMAT_UTF_8)
4416     mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
4417
4418   if (! mt->data)
4419     mtext__enlarge (mt, MAX_UTF8_CHAR_BYTES);
4420
4421   converter->nchars = converter->nbytes = 0;
4422   converter->result = MCONVERSION_RESULT_SUCCESS;
4423
4424   n = mtext_nchars (internal->unread);
4425   if (n > 0)
4426     {
4427       int limit = n;
4428       int i;
4429
4430       if (at_most > 0 && at_most < limit)
4431         limit = at_most;
4432
4433       for (i = 0, n -= 1; i < limit; i++, converter->nchars++, n--)
4434         mtext_cat_char (mt, mtext_ref_char (internal->unread, n));
4435       mtext_del (internal->unread, n + 1, internal->unread->nchars);
4436       if (at_most > 0)
4437         {
4438           if (at_most == limit)
4439             return mt;
4440           converter->at_most -= converter->nchars;
4441         }
4442     }
4443
4444   if (internal->binding == BINDING_BUFFER)
4445     {
4446       (*internal->coding->decoder) (internal->buf.in + internal->used,
4447                                     internal->bufsize - internal->used,
4448                                     mt, converter);
4449       internal->used += converter->nbytes;
4450     }  
4451   else if (internal->binding == BINDING_STREAM)
4452     {
4453       unsigned char work[CONVERT_WORKSIZE];
4454       int last_block = converter->last_block;
4455       int use_fread = at_most < 0 && internal->seekable;
4456
4457       converter->last_block = 0;
4458       while (1)
4459         {
4460           int nbytes, prev_nbytes;
4461
4462           if (feof (internal->fp))
4463             nbytes = 0;
4464           else if (use_fread)
4465             nbytes = fread (work, sizeof (unsigned char), CONVERT_WORKSIZE,
4466                             internal->fp);
4467           else
4468             {
4469               int c = getc (internal->fp);
4470
4471               if (c != EOF)
4472                 work[0] = c, nbytes = 1;
4473               else
4474                 nbytes = 0;
4475             }
4476
4477           if (ferror (internal->fp))
4478             {
4479               converter->result = MCONVERSION_RESULT_IO_ERROR;
4480               break;
4481             }
4482
4483           if (nbytes == 0)
4484             converter->last_block = last_block;
4485           prev_nbytes = converter->nbytes;
4486           (*internal->coding->decoder) (work, nbytes, mt, converter);
4487           if (converter->nbytes - prev_nbytes < nbytes)
4488             {
4489               if (use_fread)
4490                 fseek (internal->fp, converter->nbytes - prev_nbytes - nbytes,
4491                        SEEK_CUR);
4492               else
4493                 ungetc (work[0], internal->fp);
4494               break;
4495             }
4496           if (nbytes == 0
4497               || (converter->at_most > 0
4498                   && converter->nchars == converter->at_most))
4499             break;
4500         }
4501       converter->last_block = last_block;
4502     }
4503   else                          /* internal->binding == BINDING_NONE */
4504     MERROR (MERROR_CODING, NULL);
4505
4506   converter->at_most = at_most;
4507   return ((converter->result == MCONVERSION_RESULT_SUCCESS
4508            || converter->result == MCONVERSION_RESULT_INSUFFICIENT_SRC)
4509           ? mt : NULL);
4510 }
4511
4512 /*=*/
4513
4514 /***en
4515     @brief Decode a buffer area based on a coding system.
4516
4517     The mconv_decode_buffer () function decodes $N bytes of the buffer
4518     area pointed to by $BUF based on the coding system $NAME.  A
4519     temporary code converter for decoding is automatically created
4520     and freed.
4521
4522     @return 
4523     If the operation was successful, mconv_decode_buffer ()
4524     returns the resulting M-text.  Otherwise it returns @c NULL and
4525     assigns an error code to the external variable #merror_code.  */
4526
4527 /***ja
4528     @brief ¥³¡¼¥É·Ï¤Ë´ð¤Å¤¤¤Æ¥Ð¥Ã¥Õ¥¡Îΰè¤ò¥Ç¥³¡¼¥É¤¹¤ë.
4529
4530     ´Ø¿ô mconv_decode_buffer () ¤Ï¡¢$BUF ¤Ë¤è¤Ã¤Æ»Ø¤µ¤ì¤¿ $N 
4531     ¥Ð¥¤¥È¤Î¥Ð¥Ã¥Õ¥¡Îΰè¤ò¡¢¥³¡¼¥É·Ï $NAME ¤Ë´ð¤Å¤¤¤Æ¥Ç¥³¡¼¥É¤¹¤ë¡£
4532     ¥Ç¥³¡¼¥É¤ËɬÍפʥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ÎºîÀ®¤È²òÊü¤Ï¼«Æ°Åª¤Ë¹Ô¤Ê¤ï¤ì¤ë¡£
4533
4534     @return
4535     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_decode_buffer () ¤ÏÆÀ¤é¤ì¤¿ M-text ¤òÊÖ¤¹¡£
4536     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
4537     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4538
4539 /***
4540     @errors
4541     @c MERROR_IO, @c MERROR_CODING
4542
4543     @seealso
4544     mconv_decode (), mconv_decode_stream ()  */
4545
4546 MText *
4547 mconv_decode_buffer (MSymbol name, const unsigned char *buf, int n)
4548 {
4549   MConverter *converter = mconv_buffer_converter (name, buf, n);
4550   MText *mt;
4551
4552   if (! converter)
4553     return NULL;
4554   mt = mtext ();
4555   if (! mconv_decode (converter, mt))
4556     {
4557       M17N_OBJECT_UNREF (mt);
4558       mt = NULL;
4559     }
4560   mconv_free_converter (converter);
4561   return mt;
4562 }
4563
4564 /*=*/
4565
4566 /***en
4567     @brief Decode a stream input based on a coding system.
4568
4569     The mconv_decode_stream () function decodes the entire byte
4570     sequence read in from stream $FP based on the coding system $NAME.
4571     A code converter for decoding is automatically created and freed.
4572
4573     @return
4574     If the operation was successful, mconv_decode_stream () returns
4575     the resulting M-text.  Otherwise it returns @c NULL and assigns an
4576     error code to the external variable #merror_code.  */
4577
4578 /***ja
4579     @brief ¥³¡¼¥É·Ï¤Ë´ð¤Å¤¤¤Æ¥¹¥È¥ê¡¼¥àÆþÎϤò¥Ç¥³¡¼¥É¤¹¤ë.
4580
4581     ´Ø¿ô mconv_decode_stream () ¤Ï¡¢¥¹¥È¥ê¡¼¥à $FP 
4582     ¤«¤éÆɤ߹þ¤Þ¤ì¤ë¥Ð¥¤¥ÈÎóÁ´ÂΤò¡¢¥³¡¼¥É·Ï $NAME 
4583     ¤Ë´ð¤Å¤¤¤Æ¥Ç¥³¡¼¥É¤¹¤ë¡£¥Ç¥³¡¼¥É¤ËɬÍפʥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ÎºîÀ®¤È²òÊü¤Ï¼«Æ°Åª¤Ë¹Ô¤Ê¤ï¤ì¤ë¡£
4584
4585     @return
4586     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_decode_stream () ¤ÏÆÀ¤é¤ì¤¿ M-text 
4587     ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
4588     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4589
4590 /***
4591     @errors
4592     @c MERROR_IO, @c MERROR_CODING
4593
4594     @seealso
4595     mconv_decode (), mconv_decode_buffer ()  */
4596
4597 MText *
4598 mconv_decode_stream (MSymbol name, FILE *fp)
4599 {
4600   MConverter *converter = mconv_stream_converter (name, fp);
4601   MText *mt;
4602
4603   if (! converter)
4604     return NULL;
4605   mt = mtext ();
4606   if (! mconv_decode (converter, mt))
4607     {
4608       M17N_OBJECT_UNREF (mt);
4609       mt = NULL;
4610     }
4611   mconv_free_converter (converter);
4612   return mt;
4613 }
4614
4615 /*=*/
4616
4617 /***en @brief Encode an M-text into a byte sequence.
4618
4619     The mconv_encode () function encodes M-text $MT and writes the
4620     resulting byte sequence into the buffer area or the stream that is
4621     currently bound to code converter $CONVERTER.
4622
4623     @return
4624     If the operation was successful, mconv_encode () returns the
4625     number of written bytes.  Otherwise it returns -1 and assigns an
4626     error code to the external variable #merror_code.  */
4627
4628 /***ja
4629     @brief M-text ¤ò¥Ð¥¤¥ÈÎó¤Ë¥¨¥ó¥³¡¼¥É¤¹¤ë.
4630
4631     ´Ø¿ô mconv_encode () ¤Ï¡¢M-text $MT ¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿
4632     $CONVERTER ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤ËÆÀ¤é¤ì¤¿¥Ð¥¤¥ÈÎó¤ò½ñ¤­¹þ¤à¡£
4633
4634     @return
4635     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_encode () ¤Ï½ñ¤­¹þ¤Þ¤ì¤¿¥Ð¥¤¥È¿ô¤òÊÖ¤¹¡£
4636     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
4637     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4638
4639 /***
4640     @errors
4641     @c MERROR_IO, @c MERROR_CODING
4642
4643     @seealso
4644     mconv_rebind_buffer (), mconv_rebind_stream(),
4645     mconv_decode (), mconv_encode_range ()  */
4646
4647 int
4648 mconv_encode (MConverter *converter, MText *mt)
4649 {
4650   return mconv_encode_range (converter, mt, 0, mtext_nchars (mt));
4651 }
4652
4653 /*=*/
4654
4655 /***en
4656     @brief Encode a part of an M-text.
4657
4658     The mconv_encode_range () function encodes the text between $FROM
4659     (inclusive) and $TO (exclusive) in M-text $MT and writes the
4660     resulting byte sequence into the buffer area or the stream that is
4661     currently bound to code converter $CONVERTER.
4662
4663     @return
4664     If the operation was successful, mconv_encode_range () returns the
4665     number of written bytes. Otherwise it returns -1 and assigns an
4666     error code to the external variable #merror_code.  */
4667
4668 /***ja
4669     @brief M-text ¤Î°ìÉô¤ò¥Ð¥¤¥ÈÎó¤Ë¥¨¥ó¥³¡¼¥É¤¹¤ë.
4670
4671     ´Ø¿ô mconv_encode_range () ¤Ï¡¢M-text $MT ¤Î $FROM 
4672     ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é $TO ¡Ê$TO¼«ÂΤϴޤޤʤ¤¡Ë
4673     ¤Þ¤Ç¤ÎÈϰϤΥƥ­¥¹¥È¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿
4674     $CONVERTER ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤ËÆÀ¤é¤ì¤¿¥Ð¥¤¥ÈÎó¤ò½ñ¤­¹þ¤à¡£
4675
4676     @return
4677     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_encode_range () 
4678     ¤Ï½ñ¤­¹þ¤Þ¤ì¤¿¥Ð¥¤¥È¿ô¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
4679     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4680
4681 /***
4682     @errors
4683     @c MERROR_RANGE, @c MERROR_IO, @c MERROR_CODING
4684
4685     @seealso
4686     mconv_rebind_buffer (), mconv_rebind_stream(),
4687     mconv_decode (), mconv_encode ()  */
4688
4689 int
4690 mconv_encode_range (MConverter *converter, MText *mt, int from, int to)
4691 {
4692   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4693
4694   M_CHECK_POS_X (mt, from, -1);
4695   M_CHECK_POS_X (mt, to, -1);
4696   if (to < from)
4697     to = from;
4698
4699   if (converter->at_most > 0 && from + converter->at_most < to)
4700     to = from + converter->at_most;
4701
4702   converter->nchars = converter->nbytes = 0;
4703   converter->result = MCONVERSION_RESULT_SUCCESS;
4704
4705   mtext_put_prop (mt, from, to, Mcoding, internal->coding->name);
4706   if (internal->binding == BINDING_BUFFER)
4707     {
4708       (*internal->coding->encoder) (mt, from, to,
4709                                     internal->buf.out + internal->used,
4710                                     internal->bufsize - internal->used,
4711                                     converter);
4712       internal->used += converter->nbytes;
4713     }
4714   else if (internal->binding == BINDING_STREAM)
4715     {
4716       unsigned char work[CONVERT_WORKSIZE];
4717
4718       while (from < to)
4719         {
4720           int written = 0;
4721           int prev_nbytes = converter->nbytes;
4722           int this_nbytes;
4723
4724           (*internal->coding->encoder) (mt, from, to, work,
4725                                         CONVERT_WORKSIZE, converter);
4726           this_nbytes = converter->nbytes - prev_nbytes;
4727           while (written < this_nbytes)
4728             {
4729               int wrtn = fwrite (work + written, sizeof (unsigned char),
4730                                  this_nbytes - written, internal->fp);
4731
4732               if (ferror (internal->fp))
4733                 break;
4734               written += wrtn;
4735             }
4736           if (written < this_nbytes)
4737             {
4738               converter->result = MCONVERSION_RESULT_IO_ERROR;
4739               break;
4740             }
4741           from += converter->nchars;
4742         }
4743     }
4744   else                          /* fail safe */
4745     MERROR (MERROR_CODING, -1);
4746
4747   return ((converter->result == MCONVERSION_RESULT_SUCCESS
4748            || converter->result == MCONVERSION_RESULT_INSUFFICIENT_DST)
4749           ? converter->nbytes : -1);
4750 }
4751
4752 /*=*/
4753
4754 /***en
4755     @brief Encode an M-text into a buffer area.
4756
4757     The mconv_encode_buffer () function encodes M-text $MT based on
4758     coding system $NAME and writes the resulting byte sequence into the
4759     buffer area pointed to by $BUF.  At most $N bytes are written.  A
4760     temporary code converter for encoding is automatically created
4761     and freed.
4762
4763     @return
4764     If the operation was successful, mconv_encode_buffer () returns
4765     the number of written bytes.  Otherwise it returns -1 and assigns
4766     an error code to the external variable #merror_code.  */
4767
4768 /***ja
4769     @brief M-text ¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¥Ð¥Ã¥Õ¥¡Îΰè¤Ë½ñ¤­¹þ¤à.
4770
4771     ´Ø¿ô mconv_encode_buffer () ¤ÏM-text $MT ¤ò¥³¡¼¥É·Ï $NAME 
4772     ¤Ë´ð¤Å¤¤¤Æ¥¨¥ó¥³¡¼¥É¤·¡¢ÆÀ¤é¤ì¤¿¥Ð¥¤¥ÈÎó¤ò $BUF ¤Î»Ø¤¹¥Ð¥Ã¥Õ¥¡Îΰè¤Ë½ñ¤­¹þ¤à¡£
4773     $N ¤Ï½ñ¤­¹þ¤àºÇÂç¥Ð¥¤¥È¿ô¤Ç¤¢¤ë¡£
4774     ¥¨¥ó¥³¡¼¥É¤ËɬÍפʥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ÎºîÀ®¤È²òÊü¤Ï¼«Æ°Åª¤Ë¹Ô¤Ê¤ï¤ì¤ë¡£
4775
4776     @return
4777     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_encode_buffer () ¤Ï½ñ¤­¹þ¤Þ¤ì¤¿¥Ð¥¤¥È¿ô¤òÊÖ¤¹¡£
4778     ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð-1¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4779
4780 /***
4781     @errors
4782     @c MERROR_IO, @c MERROR_CODING
4783
4784     @seealso
4785     mconv_encode (), mconv_encode_stream ()  */
4786
4787 int
4788 mconv_encode_buffer (MSymbol name, MText *mt, unsigned char *buf, int n)
4789 {
4790   MConverter *converter = mconv_buffer_converter (name, buf, n);
4791   int ret;
4792
4793   if (! converter)
4794     return -1;
4795   ret = mconv_encode (converter, mt);
4796   mconv_free_converter (converter);
4797   return ret;
4798 }
4799
4800 /*=*/
4801
4802 /***en
4803     @brief Encode an M-text to write to a stream.
4804
4805     The mconv_encode_stream () function encodes M-text $MT based on
4806     coding system $NAME and writes the resulting byte sequence to
4807     stream $FP.  A temporary code converter for encoding is
4808     automatically created and freed.
4809
4810     @return
4811     If the operation was successful, mconv_encode_stream () returns
4812     the number of written bytes.  Otherwise it returns -1 and assigns
4813     an error code to the external variable #merror_code.  */
4814
4815 /***ja
4816     @brief M-text ¤ò¥¨¥ó¥³¡¼¥É¤·¤Æ¥¹¥È¥ê¡¼¥à¤Ë½ñ¤­¹þ¤à.
4817
4818     ´Ø¿ô mconv_encode_stream () ¤ÏM-text $MT ¤ò¥³¡¼¥É·Ï $NAME 
4819     ¤Ë´ð¤Å¤¤¤Æ¥¨¥ó¥³¡¼¥É¤·¡¢ÆÀ¤é¤ì¤¿¥Ð¥¤¥ÈÎó¤ò¥¹¥È¥ê¡¼¥à $FP 
4820     ¤Ë½ñ¤­½Ð¤¹¡£¥¨¥ó¥³¡¼¥É¤ËɬÍפʥ³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ÎºîÀ®¤È²òÊü¤Ï¼«Æ°Åª¤Ë¹Ô¤Ê¤ï¤ì¤ë¡£
4821
4822     @return
4823     ¤â¤·½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_encode_stream () 
4824     ¤Ï½ñ¤­¹þ¤Þ¤ì¤¿¥Ð¥¤¥È¿ô¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
4825     ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4826
4827 /***
4828     @errors
4829     @c MERROR_IO, @c MERROR_CODING
4830
4831     @seealso
4832     mconv_encode (), mconv_encode_buffer (), mconv_encode_file ()  */
4833
4834 int
4835 mconv_encode_stream (MSymbol name, MText *mt, FILE *fp)
4836 {
4837   MConverter *converter = mconv_stream_converter (name, fp);
4838   int ret;
4839
4840   if (! converter)
4841     return -1;
4842   ret = mconv_encode (converter, mt);
4843   mconv_free_converter (converter);
4844   return ret;
4845 }
4846
4847 /*=*/
4848
4849 /***en
4850     @brief Read a character via a code converter.
4851
4852     The mconv_getc () function reads one character from the buffer
4853     area or the stream that is currently bound to code converter
4854     $CONVERTER.  The decoder of $CONVERTER is used to decode the byte
4855     sequence.  The internal status of $CONVERTER is updated
4856     appropriately.
4857
4858     @return
4859     If the operation was successful, mconv_getc () returns the
4860     character read in.  If the input source reaches EOF, it returns @c
4861     EOF without changing the external variable #merror_code.  If an
4862     error is detected, it returns @c EOF and assigns an error code to
4863     #merror_code.  */
4864
4865 /***ja
4866     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿·Ðͳ¤Ç°ìʸ»ú¤òÆɤߤ³¤à.
4867
4868     ´Ø¿ô mconv_getc () ¤Ï¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER 
4869     ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤«¤éʸ»ú¤ò°ì¤ÄÆɤ߹þ¤à¡£
4870     ¥Ð¥¤¥ÈÎó¤Î¥Ç¥³¡¼¥É¤Ë¤Ï $CONVERTER ¤Î¥Ç¥³¡¼¥À¤¬ÍѤ¤¤é¤ì¤ë¡£
4871     $CONVERTER ¤ÎÆâÉô¾õÂÖ¤ÏɬÍפ˱þ¤¸¤Æ¹¹¿·¤µ¤ì¤ë¡£
4872
4873     @return
4874     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_getc () ¤ÏÆɤ߹þ¤Þ¤ì¤¿Ê¸»ú¤òÊÖ¤¹¡£ÆþÎϸ»¤¬ 
4875     EOF ¤Ë㤷¤¿¾ì¹ç¤Ï¡¢³°ÉôÊÑ¿ô #merror_code ¤òÊѤ¨¤º¤Ë @c EOF 
4876     ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c EOF ¤òÊÖ¤·¡¢#merror_code 
4877     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4878
4879 /***
4880     @errors
4881     @c MERROR_CODING
4882
4883     @seealso
4884     mconv_ungetc (), mconv_putc (), mconv_gets ()  */
4885
4886 int
4887 mconv_getc (MConverter *converter)
4888 {
4889   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4890   int at_most = converter->at_most;
4891
4892   mtext_reset (internal->work_mt);
4893   converter->at_most = 1;
4894   mconv_decode (converter, internal->work_mt);
4895   converter->at_most = at_most;
4896   return (converter->nchars == 1
4897           ? STRING_CHAR (internal->work_mt->data)
4898           : EOF);
4899 }
4900
4901 /*=*/
4902
4903 /***en
4904     @brief Push a character back to a code converter.
4905
4906     The mconv_ungetc () function pushes character $C back to code
4907     converter $CONVERTER.  Any number of characters can be pushed
4908     back.  The lastly pushed back character is firstly read by the
4909     subsequent mconv_getc () call.  The characters pushed back are
4910     registered only in $CONVERTER; they are not written to the input
4911     source.  The internal status of $CONVERTER is updated
4912     appropriately.
4913
4914     @return
4915     If the operation was successful, mconv_ungetc () returns $C.
4916     Otherwise it returns @c EOF and assigns an error code to the
4917     external variable #merror_code.  */
4918
4919 /***ja
4920     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤Ë°ìʸ»úÌ᤹.
4921
4922     ´Ø¿ô mconv_ungetc () ¤Ï¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER ¤Ëʸ»ú $C 
4923     ¤ò²¡¤·Ì᤹¡£Ìᤵ¤ì¤ëʸ»ú¿ô¤ËÀ©¸Â¤Ï¤Ê¤¤¡£¤³¤Î¸å¤Ç mconv_getc () 
4924     ¤ò¸Æ¤Ó½Ð¤·¤¿ºÝ¤Ë¤Ï¡¢ºÇ¸å¤ËÌᤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤ËÆɤޤì¤ë¡£Ìᤵ¤ì¤¿Ê¸»ú¤Ï 
4925     $CONVERTER ¤ÎÆâÉô¤ËÃߤ¨¤é¤ì¤ë¤À¤±¤Ç¤¢¤ê¡¢¼ÂºÝ¤ËÆþÎϸ»¤Ë½ñ¤­¹þ¤Þ¤ì¤ë¤ï¤±¤Ç¤Ï¤Ê¤¤¡£
4926     $CONVERTER ¤ÎÆâÉô¾õÂÖ¤ÏɬÍפ˱þ¤¸¤Æ¹¹¿·¤µ¤ì¤ë¡£
4927
4928     @return
4929     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_ungetc () ¤Ï $C ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c
4930     EOF ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4931
4932 /***
4933     @errors
4934     @c MERROR_CODING, @c MERROR_CHAR
4935
4936     @seealso
4937     mconv_getc (), mconv_putc (), mconv_gets ()  */
4938
4939 int
4940 mconv_ungetc (MConverter *converter, int c)
4941 {
4942   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4943
4944   M_CHECK_CHAR (c, EOF);
4945
4946   converter->result = MCONVERSION_RESULT_SUCCESS;
4947   mtext_cat_char (internal->unread, c);
4948   return c;
4949 }
4950
4951 /*=*/
4952
4953 /***en
4954     @brief Write a character via a code converter.
4955
4956     The mconv_putc () function writes character $C to the buffer area
4957     or the stream that is currently bound to code converter
4958     $CONVERTER.  The encoder of $CONVERTER is used to encode the
4959     character.  The number of bytes actually written is set to the @c
4960     nbytes member of $CONVERTER.  The internal status of $CONVERTER
4961     is updated appropriately.
4962
4963     @return
4964     If the operation was successful, mconv_putc () returns $C.
4965     If an error is detected, it returns @c EOF and assigns
4966     an error code to the external variable #merror_code.  */
4967
4968 /***ja
4969     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ò·Ðͳ¤·¤Æ°ìʸ»ú½ñ¤­½Ð¤¹.
4970
4971     ´Ø¿ô mconv_putc () ¤Ï¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER 
4972     ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤Ëʸ»ú $C 
4973     ¤ò½ñ¤­½Ð¤¹¡£Ê¸»ú¤Î¥¨¥ó¥³¡¼¥É¤Ë¤Ï $CONVERTER 
4974     ¤Î¥¨¥ó¥³¡¼¥À¤¬ÍѤ¤¤é¤ì¤ë¡£¼ÂºÝ¤Ë½ñ¤­½Ð¤µ¤ì¤¿¥Ð¥¤¥È¿ô¤Ï¡¢$CONVERTER ¤Î¥á¥ó¥Ð¡¼
4975     @c nbytes ¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£$CONVERTER ¤ÎÆâÉô¾õÂÖ¤ÏɬÍפ˱þ¤¸¤Æ¹¹¿·¤µ¤ì¤ë¡£
4976
4977     @return
4978     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_putc () ¤Ï $C ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
4979     @c EOF ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
4980
4981 /***
4982     @errors
4983     @c MERROR_CODING, @c MERROR_IO, @c MERROR_CHAR
4984
4985     @seealso
4986     mconv_getc (), mconv_ungetc (), mconv_gets ()  */
4987
4988 int
4989 mconv_putc (MConverter *converter, int c)
4990 {
4991   MConverterStatus *internal = (MConverterStatus *) converter->internal_info;
4992
4993   M_CHECK_CHAR (c, EOF);
4994   mtext_reset (internal->work_mt);
4995   mtext_cat_char (internal->work_mt, c);
4996   if (mconv_encode_range (converter, internal->work_mt, 0, 1) < 0)
4997     return EOF;
4998   return c;
4999 }
5000
5001 /*=*/
5002
5003 /***en
5004     @brief Read a line using a code converter.
5005
5006     The mconv_gets () function reads one line from the buffer area or
5007     the stream that is currently bound to code converter $CONVERTER.
5008     The decoder of $CONVERTER is used for decoding.  The decoded
5009     character sequence is appended at the end of M-text $MT.  The
5010     final newline character in the original byte sequence is not
5011     appended.  The internal status of $CONVERTER is updated
5012     appropriately.
5013
5014     @return
5015     If the operation was successful, mconv_gets () returns the
5016     modified $MT.  If it encounters EOF without reading a single
5017     character, it returns $MT without changing it.  If an error is
5018     detected, it returns @c NULL and assigns an error code to 
5019     #merror_code.  */
5020
5021 /***ja
5022     @brief ¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿¤ò»È¤Ã¤Æ°ì¹ÔÆɤ߹þ¤à.
5023
5024     ´Ø¿ô mconv_gets () ¤Ï¡¢¥³¡¼¥É¥³¥ó¥Ð¡¼¥¿ $CONVERTER 
5025     ¤Ë¸½ºß·ë¤ÓÉÕ¤±¤é¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡Îΰ褢¤ë¤¤¤Ï¥¹¥È¥ê¡¼¥à¤«¤é 1 ¹Ô¤òÆɤ߹þ¤à¡£
5026     ¥Ð¥¤¥ÈÎó¤Î¥Ç¥³¡¼¥É¤Ë¤Ï $CONVERTER 
5027     ¤Î¥Ç¥³¡¼¥À¤¬ÍѤ¤¤é¤ì¤ë¡£¥Ç¥³¡¼¥É¤µ¤ì¤¿Ê¸»úÎó¤Ï M-text $MT 
5028     ¤ÎËöÈø¤ËÄɲ䵤ì¤ë¡£¸µ¤Î¥Ð¥¤¥ÈÎó¤Î½ªÃ¼²þ¹Ôʸ»ú¤ÏÄɲ䵤ì¤Ê¤¤¡£
5029     $CONVERTER ¤ÎÆâÉô¾õÂÖ¤ÏɬÍפ˱þ¤¸¤Æ¹¹¿·¤µ¤ì¤ë¡£
5030
5031     @return
5032     ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mconv_gets () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT
5033     ¤òÊÖ¤¹¡£¤â¤·1ʸ»ú¤âÆɤޤº¤Ë EOF ¤ËÁø¶ø¤·¤¿¾ì¹ç¤Ï¡¢$MT 
5034     ¤òÊѹ¹¤»¤º¤Ë¤½¤Î¤Þ¤ÞÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢
5035     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
5036
5037 /***
5038     @errors
5039     @c MERROR_CODING
5040
5041     @seealso
5042     mconv_getc (), mconv_ungetc (), mconv_putc ()  */
5043
5044 MText *
5045 mconv_gets (MConverter *converter, MText *mt)
5046 {
5047   int c;
5048
5049   M_CHECK_READONLY (mt, NULL);
5050   if (mt->format != MTEXT_FORMAT_UTF_8)
5051     mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
5052
5053   while (1)
5054     {
5055       c = mconv_getc (converter);
5056       if (c == EOF || c == '\n')
5057         break;
5058       mtext_cat_char (mt, c);
5059     }
5060   if (c == EOF && converter->result != MCONVERSION_RESULT_SUCCESS)
5061     /* mconv_getc () sets #merror_code */
5062     return NULL;
5063   return mt;
5064 }
5065
5066 /*=*/
5067
5068 /*** @} */
5069
5070 /*
5071   Local Variables:
5072   coding: euc-japan
5073   End:
5074 */