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