(char_encode_ucs4): New function.
[chise/xemacs-chise.git-] / src / text-coding.c
1 /* Code conversion functions.
2    Copyright (C) 1991, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Mule 2.3.   Not in FSF. */
23
24 /* Rewritten by Ben Wing <ben@xemacs.org>. */
25
26 #include <config.h>
27 #include "lisp.h"
28
29 #include "buffer.h"
30 #include "elhash.h"
31 #include "insdel.h"
32 #include "lstream.h"
33 #ifdef MULE
34 #include "mule-ccl.h"
35 #include "chartab.h"
36 #endif
37 #include "file-coding.h"
38
39 Lisp_Object Qbuffer_file_coding_system, Qcoding_system_error;
40
41 Lisp_Object Vkeyboard_coding_system;
42 Lisp_Object Vterminal_coding_system;
43 Lisp_Object Vcoding_system_for_read;
44 Lisp_Object Vcoding_system_for_write;
45 Lisp_Object Vfile_name_coding_system;
46
47 /* Table of symbols identifying each coding category. */
48 Lisp_Object coding_category_symbol[CODING_CATEGORY_LAST + 1];
49
50 /* Coding system currently associated with each coding category. */
51 Lisp_Object coding_category_system[CODING_CATEGORY_LAST + 1];
52
53 /* Table of all coding categories in decreasing order of priority.
54    This describes a permutation of the possible coding categories. */
55 int coding_category_by_priority[CODING_CATEGORY_LAST + 1];
56
57 Lisp_Object Qcoding_system_p;
58
59 Lisp_Object Qraw_text, Qno_conversion, Qccl, Qiso2022;
60 /* Qinternal in general.c */
61
62 Lisp_Object Qmnemonic, Qeol_type;
63 Lisp_Object Qcr, Qcrlf, Qlf;
64 Lisp_Object Qeol_cr, Qeol_crlf, Qeol_lf;
65 Lisp_Object Qpost_read_conversion;
66 Lisp_Object Qpre_write_conversion;
67
68 #ifdef MULE
69 Lisp_Object Qucs4, Qutf8;
70 Lisp_Object Qbig5, Qshift_jis;
71 Lisp_Object Qcharset_g0, Qcharset_g1, Qcharset_g2, Qcharset_g3;
72 Lisp_Object Qforce_g0_on_output, Qforce_g1_on_output;
73 Lisp_Object Qforce_g2_on_output, Qforce_g3_on_output;
74 Lisp_Object Qno_iso6429;
75 Lisp_Object Qinput_charset_conversion, Qoutput_charset_conversion;
76 Lisp_Object Qctext, Qescape_quoted;
77 Lisp_Object Qshort, Qno_ascii_eol, Qno_ascii_cntl, Qseven, Qlock_shift;
78 #endif
79 Lisp_Object Qencode, Qdecode;
80
81 Lisp_Object Vcoding_system_hash_table;
82
83 int enable_multibyte_characters;
84
85 #ifdef MULE
86 /* Additional information used by the ISO2022 decoder and detector. */
87 struct iso2022_decoder
88 {
89   /* CHARSET holds the character sets currently assigned to the G0
90      through G3 variables.  It is initialized from the array
91      INITIAL_CHARSET in CODESYS. */
92   Lisp_Object charset[4];
93
94   /* Which registers are currently invoked into the left (GL) and
95      right (GR) halves of the 8-bit encoding space? */
96   int register_left, register_right;
97
98   /* ISO_ESC holds a value indicating part of an escape sequence
99      that has already been seen. */
100   enum iso_esc_flag esc;
101
102   /* This records the bytes we've seen so far in an escape sequence,
103      in case the sequence is invalid (we spit out the bytes unchanged). */
104   unsigned char esc_bytes[8];
105
106   /* Index for next byte to store in ISO escape sequence. */
107   int esc_bytes_index;
108
109 #ifdef ENABLE_COMPOSITE_CHARS
110   /* Stuff seen so far when composing a string. */
111   unsigned_char_dynarr *composite_chars;
112 #endif
113
114   /* If we saw an invalid designation sequence for a particular
115      register, we flag it here and switch to ASCII.  The next time we
116      see a valid designation for this register, we turn off the flag
117      and do the designation normally, but pretend the sequence was
118      invalid.  The effect of all this is that (most of the time) the
119      escape sequences for both the switch to the unknown charset, and
120      the switch back to the known charset, get inserted literally into
121      the buffer and saved out as such.  The hope is that we can
122      preserve the escape sequences so that the resulting written out
123      file makes sense.  If we don't do any of this, the designation
124      to the invalid charset will be preserved but that switch back
125      to the known charset will probably get eaten because it was
126      the same charset that was already present in the register. */
127   unsigned char invalid_designated[4];
128
129   /* We try to do similar things as above for direction-switching
130      sequences.  If we encountered a direction switch while an
131      invalid designation was present, or an invalid designation
132      just after a direction switch (i.e. no valid designation
133      encountered yet), we insert the direction-switch escape
134      sequence literally into the output stream, and later on
135      insert the corresponding direction-restoring escape sequence
136      literally also. */
137   unsigned int switched_dir_and_no_valid_charset_yet :1;
138   unsigned int invalid_switch_dir :1;
139
140   /* Tells the decoder to output the escape sequence literally
141      even though it was valid.  Used in the games we play to
142      avoid lossage when we encounter invalid designations. */
143   unsigned int output_literally :1;
144   /* We encountered a direction switch followed by an invalid
145      designation.  We didn't output the direction switch
146      literally because we didn't know about the invalid designation;
147      but we have to do so now. */
148   unsigned int output_direction_sequence :1;
149 };
150 #endif /* MULE */
151 EXFUN (Fcopy_coding_system, 2);
152 #ifdef MULE
153 struct detection_state;
154
155 static void
156 text_encode_generic (Lstream *encoding, CONST unsigned char *src,
157                      unsigned_char_dynarr *dst, unsigned int n);
158
159 static int detect_coding_sjis (struct detection_state *st,
160                                CONST unsigned char *src,
161                                unsigned int n);
162 static void decode_coding_sjis (Lstream *decoding,
163                                 CONST unsigned char *src,
164                                 unsigned_char_dynarr *dst,
165                                 unsigned int n);
166 static void encode_coding_sjis (Lstream *encoding,
167                                 CONST unsigned char *src,
168                                 unsigned_char_dynarr *dst,
169                                 unsigned int n);
170 static int detect_coding_big5 (struct detection_state *st,
171                                CONST unsigned char *src,
172                                unsigned int n);
173 static void decode_coding_big5 (Lstream *decoding,
174                                 CONST unsigned char *src,
175                                 unsigned_char_dynarr *dst, unsigned int n);
176 static void encode_coding_big5 (Lstream *encoding,
177                                 CONST unsigned char *src,
178                                 unsigned_char_dynarr *dst, unsigned int n);
179 static int detect_coding_ucs4 (struct detection_state *st,
180                                CONST unsigned char *src,
181                                unsigned int n);
182 static void decode_coding_ucs4 (Lstream *decoding,
183                                 CONST unsigned char *src,
184                                 unsigned_char_dynarr *dst, unsigned int n);
185 void char_encode_ucs4 (struct encoding_stream *str, Emchar c,
186                        unsigned_char_dynarr *dst, unsigned int *flags);
187 void char_finish_ucs4 (struct encoding_stream *str,
188                        unsigned_char_dynarr *dst, unsigned int *flags);
189
190 static int detect_coding_utf8 (struct detection_state *st,
191                                CONST unsigned char *src,
192                                unsigned int n);
193 static void decode_coding_utf8 (Lstream *decoding,
194                                 CONST unsigned char *src,
195                                 unsigned_char_dynarr *dst, unsigned int n);
196 void char_encode_utf8 (struct encoding_stream *str, Emchar c,
197                        unsigned_char_dynarr *dst, unsigned int *flags);
198 void char_finish_utf8 (struct encoding_stream *str,
199                        unsigned_char_dynarr *dst, unsigned int *flags);
200
201 static int postprocess_iso2022_mask (int mask);
202 static void reset_iso2022 (Lisp_Object coding_system,
203                            struct iso2022_decoder *iso);
204 static int detect_coding_iso2022 (struct detection_state *st,
205                                   CONST unsigned char *src,
206                                   unsigned int n);
207 static void decode_coding_iso2022 (Lstream *decoding,
208                                    CONST unsigned char *src,
209                                    unsigned_char_dynarr *dst, unsigned int n);
210 void char_encode_iso2022 (struct encoding_stream *str, Emchar c,
211                           unsigned_char_dynarr *dst, unsigned int *flags);
212 void char_finish_iso2022 (struct encoding_stream *str,
213                           unsigned_char_dynarr *dst, unsigned int *flags);
214 #endif /* MULE */
215 static void decode_coding_no_conversion (Lstream *decoding,
216                                          CONST unsigned char *src,
217                                          unsigned_char_dynarr *dst,
218                                          unsigned int n);
219 static void encode_coding_no_conversion (Lstream *encoding,
220                                          CONST unsigned char *src,
221                                          unsigned_char_dynarr *dst,
222                                          unsigned int n);
223 static void mule_decode (Lstream *decoding, CONST unsigned char *src,
224                          unsigned_char_dynarr *dst, unsigned int n);
225 static void mule_encode (Lstream *encoding, CONST unsigned char *src,
226                          unsigned_char_dynarr *dst, unsigned int n);
227
228 typedef struct codesys_prop codesys_prop;
229 struct codesys_prop
230 {
231   Lisp_Object sym;
232   int prop_type;
233 };
234
235 typedef struct
236 {
237   Dynarr_declare (codesys_prop);
238 } codesys_prop_dynarr;
239
240 codesys_prop_dynarr *the_codesys_prop_dynarr;
241
242 enum codesys_prop_enum
243 {
244   CODESYS_PROP_ALL_OK,
245   CODESYS_PROP_ISO2022,
246   CODESYS_PROP_CCL
247 };
248
249 \f
250 /************************************************************************/
251 /*                       Coding system functions                        */
252 /************************************************************************/
253
254 static Lisp_Object mark_coding_system (Lisp_Object, void (*) (Lisp_Object));
255 static void print_coding_system (Lisp_Object, Lisp_Object, int);
256 static void finalize_coding_system (void *header, int for_disksave);
257
258 #ifdef MULE
259 static const struct lrecord_description ccs_description_1[] = {
260   { XD_LISP_OBJECT, offsetof(charset_conversion_spec, from_charset), 2 },
261   { XD_END }
262 };
263
264 static const struct struct_description ccs_description = {
265   sizeof(charset_conversion_spec),
266   ccs_description_1
267 };
268   
269 static const struct lrecord_description ccsd_description_1[] = {
270   XD_DYNARR_DESC(charset_conversion_spec_dynarr, &ccs_description),
271   { XD_END }
272 };
273
274 static const struct struct_description ccsd_description = {
275   sizeof(charset_conversion_spec_dynarr),
276   ccsd_description_1
277 };
278 #endif
279
280 static const struct lrecord_description coding_system_description[] = {
281   { XD_LISP_OBJECT, offsetof(struct Lisp_Coding_System, name), 2 },
282   { XD_LISP_OBJECT, offsetof(struct Lisp_Coding_System, mnemonic), 3 },
283   { XD_LISP_OBJECT, offsetof(struct Lisp_Coding_System, eol_lf), 3 },
284 #ifdef MULE
285   { XD_LISP_OBJECT, offsetof(struct Lisp_Coding_System, iso2022.initial_charset), 4 },
286   { XD_STRUCT_PTR,  offsetof(struct Lisp_Coding_System, iso2022.input_conv),  1, &ccsd_description },
287   { XD_STRUCT_PTR,  offsetof(struct Lisp_Coding_System, iso2022.output_conv), 1, &ccsd_description },
288   { XD_LISP_OBJECT, offsetof(struct Lisp_Coding_System, ccl.decode), 2 },
289 #endif
290   { XD_END }
291 };
292
293 DEFINE_LRECORD_IMPLEMENTATION ("coding-system", coding_system,
294                                mark_coding_system, print_coding_system,
295                                finalize_coding_system,
296                                0, 0, coding_system_description,
297                                struct Lisp_Coding_System);
298
299 static Lisp_Object
300 mark_coding_system (Lisp_Object obj, void (*markobj) (Lisp_Object))
301 {
302   Lisp_Coding_System *codesys = XCODING_SYSTEM (obj);
303
304   markobj (CODING_SYSTEM_NAME (codesys));
305   markobj (CODING_SYSTEM_DOC_STRING (codesys));
306   markobj (CODING_SYSTEM_MNEMONIC (codesys));
307   markobj (CODING_SYSTEM_EOL_LF (codesys));
308   markobj (CODING_SYSTEM_EOL_CRLF (codesys));
309   markobj (CODING_SYSTEM_EOL_CR (codesys));
310
311   switch (CODING_SYSTEM_TYPE (codesys))
312     {
313 #ifdef MULE
314       int i;
315     case CODESYS_ISO2022:
316       for (i = 0; i < 4; i++)
317         markobj (CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i));
318       if (codesys->iso2022.input_conv)
319         {
320           for (i = 0; i < Dynarr_length (codesys->iso2022.input_conv); i++)
321             {
322               struct charset_conversion_spec *ccs =
323                 Dynarr_atp (codesys->iso2022.input_conv, i);
324               markobj (ccs->from_charset);
325               markobj (ccs->to_charset);
326             }
327         }
328       if (codesys->iso2022.output_conv)
329         {
330           for (i = 0; i < Dynarr_length (codesys->iso2022.output_conv); i++)
331             {
332               struct charset_conversion_spec *ccs =
333                 Dynarr_atp (codesys->iso2022.output_conv, i);
334               markobj (ccs->from_charset);
335               markobj (ccs->to_charset);
336             }
337         }
338       break;
339
340     case CODESYS_CCL:
341       markobj (CODING_SYSTEM_CCL_DECODE (codesys));
342       markobj (CODING_SYSTEM_CCL_ENCODE (codesys));
343       break;
344 #endif /* MULE */
345     default:
346       break;
347     }
348
349   markobj (CODING_SYSTEM_PRE_WRITE_CONVERSION (codesys));
350   return CODING_SYSTEM_POST_READ_CONVERSION (codesys);
351 }
352
353 static void
354 print_coding_system (Lisp_Object obj, Lisp_Object printcharfun,
355                      int escapeflag)
356 {
357   Lisp_Coding_System *c = XCODING_SYSTEM (obj);
358   if (print_readably)
359     error ("printing unreadable object #<coding_system 0x%x>",
360            c->header.uid);
361
362   write_c_string ("#<coding_system ", printcharfun);
363   print_internal (c->name, printcharfun, 1);
364   write_c_string (">", printcharfun);
365 }
366
367 static void
368 finalize_coding_system (void *header, int for_disksave)
369 {
370   Lisp_Coding_System *c = (Lisp_Coding_System *) header;
371   /* Since coding systems never go away, this function is not
372      necessary.  But it would be necessary if we changed things
373      so that coding systems could go away. */
374   if (!for_disksave) /* see comment in lstream.c */
375     {
376       switch (CODING_SYSTEM_TYPE (c))
377         {
378 #ifdef MULE
379         case CODESYS_ISO2022:
380           if (c->iso2022.input_conv)
381             {
382               Dynarr_free (c->iso2022.input_conv);
383               c->iso2022.input_conv = 0;
384             }
385           if (c->iso2022.output_conv)
386             {
387               Dynarr_free (c->iso2022.output_conv);
388               c->iso2022.output_conv = 0;
389             }
390           break;
391 #endif /* MULE */
392         default:
393           break;
394         }
395     }
396 }
397
398 static enum eol_type
399 symbol_to_eol_type (Lisp_Object symbol)
400 {
401   CHECK_SYMBOL (symbol);
402   if (NILP (symbol))      return EOL_AUTODETECT;
403   if (EQ (symbol, Qlf))   return EOL_LF;
404   if (EQ (symbol, Qcrlf)) return EOL_CRLF;
405   if (EQ (symbol, Qcr))   return EOL_CR;
406
407   signal_simple_error ("Unrecognized eol type", symbol);
408   return EOL_AUTODETECT; /* not reached */
409 }
410
411 static Lisp_Object
412 eol_type_to_symbol (enum eol_type type)
413 {
414   switch (type)
415     {
416     default: abort ();
417     case EOL_LF:         return Qlf;
418     case EOL_CRLF:       return Qcrlf;
419     case EOL_CR:         return Qcr;
420     case EOL_AUTODETECT: return Qnil;
421     }
422 }
423
424 static void
425 setup_eol_coding_systems (Lisp_Coding_System *codesys)
426 {
427   Lisp_Object codesys_obj;
428   int len = string_length (XSYMBOL (CODING_SYSTEM_NAME (codesys))->name);
429   char *codesys_name = (char *) alloca (len + 7);
430   int mlen = -1;
431   char *codesys_mnemonic=0;
432
433   Lisp_Object codesys_name_sym, sub_codesys_obj;
434
435   /* kludge */
436
437   XSETCODING_SYSTEM (codesys_obj, codesys);
438
439   memcpy (codesys_name,
440           string_data (XSYMBOL (CODING_SYSTEM_NAME (codesys))->name), len);
441
442   if (STRINGP (CODING_SYSTEM_MNEMONIC (codesys)))
443     {
444       mlen = XSTRING_LENGTH (CODING_SYSTEM_MNEMONIC (codesys));
445       codesys_mnemonic = (char *) alloca (mlen + 7);
446       memcpy (codesys_mnemonic,
447               XSTRING_DATA (CODING_SYSTEM_MNEMONIC (codesys)), mlen);
448     }
449
450 #define DEFINE_SUB_CODESYS(op_sys, op_sys_abbr, Type) do {                      \
451   strcpy (codesys_name + len, "-" op_sys);                                      \
452   if (mlen != -1)                                                               \
453     strcpy (codesys_mnemonic + mlen, op_sys_abbr);                              \
454   codesys_name_sym = intern (codesys_name);                                     \
455   sub_codesys_obj = Fcopy_coding_system (codesys_obj, codesys_name_sym);        \
456   XCODING_SYSTEM_EOL_TYPE (sub_codesys_obj) = Type;                             \
457   if (mlen != -1)                                                               \
458     XCODING_SYSTEM_MNEMONIC(sub_codesys_obj) =                                  \
459       build_string (codesys_mnemonic);                                          \
460   CODING_SYSTEM_##Type (codesys) = sub_codesys_obj;                             \
461 } while (0)
462
463   DEFINE_SUB_CODESYS("unix", "", EOL_LF);
464   DEFINE_SUB_CODESYS("dos",  ":T", EOL_CRLF);
465   DEFINE_SUB_CODESYS("mac",  ":t", EOL_CR);
466 }
467
468 DEFUN ("coding-system-p", Fcoding_system_p, 1, 1, 0, /*
469 Return t if OBJECT is a coding system.
470 A coding system is an object that defines how text containing multiple
471 character sets is encoded into a stream of (typically 8-bit) bytes.
472 The coding system is used to decode the stream into a series of
473 characters (which may be from multiple charsets) when the text is read
474 from a file or process, and is used to encode the text back into the
475 same format when it is written out to a file or process.
476
477 For example, many ISO2022-compliant coding systems (such as Compound
478 Text, which is used for inter-client data under the X Window System)
479 use escape sequences to switch between different charsets -- Japanese
480 Kanji, for example, is invoked with "ESC $ ( B"; ASCII is invoked
481 with "ESC ( B"; and Cyrillic is invoked with "ESC - L".  See
482 `make-coding-system' for more information.
483
484 Coding systems are normally identified using a symbol, and the
485 symbol is accepted in place of the actual coding system object whenever
486 a coding system is called for. (This is similar to how faces work.)
487 */
488        (object))
489 {
490   return CODING_SYSTEMP (object) ? Qt : Qnil;
491 }
492
493 DEFUN ("find-coding-system", Ffind_coding_system, 1, 1, 0, /*
494 Retrieve the coding system of the given name.
495
496 If CODING-SYSTEM-OR-NAME is a coding-system object, it is simply
497 returned.  Otherwise, CODING-SYSTEM-OR-NAME should be a symbol.
498 If there is no such coding system, nil is returned.  Otherwise the
499 associated coding system object is returned.
500 */
501        (coding_system_or_name))
502 {
503   if (CODING_SYSTEMP (coding_system_or_name))
504     return coding_system_or_name;
505
506   if (NILP (coding_system_or_name))
507     coding_system_or_name = Qbinary;
508   else
509     CHECK_SYMBOL (coding_system_or_name);
510
511   return Fgethash (coding_system_or_name, Vcoding_system_hash_table, Qnil);
512 }
513
514 DEFUN ("get-coding-system", Fget_coding_system, 1, 1, 0, /*
515 Retrieve the coding system of the given name.
516 Same as `find-coding-system' except that if there is no such
517 coding system, an error is signaled instead of returning nil.
518 */
519        (name))
520 {
521   Lisp_Object coding_system = Ffind_coding_system (name);
522
523   if (NILP (coding_system))
524     signal_simple_error ("No such coding system", name);
525   return coding_system;
526 }
527
528 /* We store the coding systems in hash tables with the names as the key and the
529    actual coding system object as the value.  Occasionally we need to use them
530    in a list format.  These routines provide us with that. */
531 struct coding_system_list_closure
532 {
533   Lisp_Object *coding_system_list;
534 };
535
536 static int
537 add_coding_system_to_list_mapper (Lisp_Object key, Lisp_Object value,
538                                   void *coding_system_list_closure)
539 {
540   /* This function can GC */
541   struct coding_system_list_closure *cscl =
542     (struct coding_system_list_closure *) coding_system_list_closure;
543   Lisp_Object *coding_system_list = cscl->coding_system_list;
544
545   *coding_system_list = Fcons (XCODING_SYSTEM (value)->name,
546                                *coding_system_list);
547   return 0;
548 }
549
550 DEFUN ("coding-system-list", Fcoding_system_list, 0, 0, 0, /*
551 Return a list of the names of all defined coding systems.
552 */
553        ())
554 {
555   Lisp_Object coding_system_list = Qnil;
556   struct gcpro gcpro1;
557   struct coding_system_list_closure coding_system_list_closure;
558
559   GCPRO1 (coding_system_list);
560   coding_system_list_closure.coding_system_list = &coding_system_list;
561   elisp_maphash (add_coding_system_to_list_mapper, Vcoding_system_hash_table,
562                  &coding_system_list_closure);
563   UNGCPRO;
564
565   return coding_system_list;
566 }
567
568 DEFUN ("coding-system-name", Fcoding_system_name, 1, 1, 0, /*
569 Return the name of the given coding system.
570 */
571        (coding_system))
572 {
573   coding_system = Fget_coding_system (coding_system);
574   return XCODING_SYSTEM_NAME (coding_system);
575 }
576
577 static Lisp_Coding_System *
578 allocate_coding_system (enum coding_system_type type, Lisp_Object name)
579 {
580   Lisp_Coding_System *codesys =
581     alloc_lcrecord_type (Lisp_Coding_System, &lrecord_coding_system);
582
583   zero_lcrecord (codesys);
584   CODING_SYSTEM_PRE_WRITE_CONVERSION (codesys) = Qnil;
585   CODING_SYSTEM_POST_READ_CONVERSION (codesys) = Qnil;
586   CODING_SYSTEM_EOL_TYPE (codesys) = EOL_AUTODETECT;
587   CODING_SYSTEM_EOL_CRLF (codesys) = Qnil;
588   CODING_SYSTEM_EOL_CR   (codesys) = Qnil;
589   CODING_SYSTEM_EOL_LF   (codesys) = Qnil;
590   CODING_SYSTEM_TYPE     (codesys) = type;
591   CODING_SYSTEM_MNEMONIC (codesys) = Qnil;
592 #ifdef MULE
593   if (type == CODESYS_ISO2022)
594     {
595       int i;
596       for (i = 0; i < 4; i++)
597         CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i) = Qnil;
598     }
599   else if (type == CODESYS_CCL)
600     {
601       CODING_SYSTEM_CCL_DECODE (codesys) = Qnil;
602       CODING_SYSTEM_CCL_ENCODE (codesys) = Qnil;
603     }
604 #endif /* MULE */
605   CODING_SYSTEM_NAME (codesys) = name;
606
607   return codesys;
608 }
609
610 #ifdef MULE
611 /* Given a list of charset conversion specs as specified in a Lisp
612    program, parse it into STORE_HERE. */
613
614 static void
615 parse_charset_conversion_specs (charset_conversion_spec_dynarr *store_here,
616                                 Lisp_Object spec_list)
617 {
618   Lisp_Object rest;
619
620   EXTERNAL_LIST_LOOP (rest, spec_list)
621     {
622       Lisp_Object car = XCAR (rest);
623       Lisp_Object from, to;
624       struct charset_conversion_spec spec;
625
626       if (!CONSP (car) || !CONSP (XCDR (car)) || !NILP (XCDR (XCDR (car))))
627         signal_simple_error ("Invalid charset conversion spec", car);
628       from = Fget_charset (XCAR (car));
629       to = Fget_charset (XCAR (XCDR (car)));
630       if (XCHARSET_TYPE (from) != XCHARSET_TYPE (to))
631         signal_simple_error_2
632           ("Attempted conversion between different charset types",
633            from, to);
634       spec.from_charset = from;
635       spec.to_charset = to;
636
637       Dynarr_add (store_here, spec);
638     }
639 }
640
641 /* Given a dynarr LOAD_HERE of internally-stored charset conversion
642    specs, return the equivalent as the Lisp programmer would see it.
643
644    If LOAD_HERE is 0, return Qnil. */
645
646 static Lisp_Object
647 unparse_charset_conversion_specs (charset_conversion_spec_dynarr *load_here)
648 {
649   int i;
650   Lisp_Object result;
651
652   if (!load_here)
653     return Qnil;
654   for (i = 0, result = Qnil; i < Dynarr_length (load_here); i++)
655     {
656       struct charset_conversion_spec *ccs = Dynarr_atp (load_here, i);
657       result = Fcons (list2 (ccs->from_charset, ccs->to_charset), result);
658     }
659
660   return Fnreverse (result);
661 }
662
663 #endif /* MULE */
664
665 DEFUN ("make-coding-system", Fmake_coding_system, 2, 4, 0, /*
666 Register symbol NAME as a coding system.
667
668 TYPE describes the conversion method used and should be one of
669
670 nil or 'undecided
671      Automatic conversion.  XEmacs attempts to detect the coding system
672      used in the file.
673 'no-conversion
674      No conversion.  Use this for binary files and such.  On output,
675      graphic characters that are not in ASCII or Latin-1 will be
676      replaced by a ?. (For a no-conversion-encoded buffer, these
677      characters will only be present if you explicitly insert them.)
678 'shift-jis
679      Shift-JIS (a Japanese encoding commonly used in PC operating systems).
680 'ucs-4
681      ISO 10646 UCS-4 encoding.
682 'utf-8
683      ISO 10646 UTF-8 encoding.
684 'iso2022
685      Any ISO2022-compliant encoding.  Among other things, this includes
686      JIS (the Japanese encoding commonly used for e-mail), EUC (the
687      standard Unix encoding for Japanese and other languages), and
688      Compound Text (the encoding used in X11).  You can specify more
689      specific information about the conversion with the FLAGS argument.
690 'big5
691      Big5 (the encoding commonly used for Taiwanese).
692 'ccl
693      The conversion is performed using a user-written pseudo-code
694      program.  CCL (Code Conversion Language) is the name of this
695      pseudo-code.
696 'internal
697      Write out or read in the raw contents of the memory representing
698      the buffer's text.  This is primarily useful for debugging
699      purposes, and is only enabled when XEmacs has been compiled with
700      DEBUG_XEMACS defined (via the --debug configure option).
701      WARNING: Reading in a file using 'internal conversion can result
702      in an internal inconsistency in the memory representing a
703      buffer's text, which will produce unpredictable results and may
704      cause XEmacs to crash.  Under normal circumstances you should
705      never use 'internal conversion.
706
707 DOC-STRING is a string describing the coding system.
708
709 PROPS is a property list, describing the specific nature of the
710 character set.  Recognized properties are:
711
712 'mnemonic
713      String to be displayed in the modeline when this coding system is
714      active.
715
716 'eol-type
717      End-of-line conversion to be used.  It should be one of
718
719         nil
720                 Automatically detect the end-of-line type (LF, CRLF,
721                 or CR).  Also generate subsidiary coding systems named
722                 `NAME-unix', `NAME-dos', and `NAME-mac', that are
723                 identical to this coding system but have an EOL-TYPE
724                 value of 'lf, 'crlf, and 'cr, respectively.
725         'lf
726                 The end of a line is marked externally using ASCII LF.
727                 Since this is also the way that XEmacs represents an
728                 end-of-line internally, specifying this option results
729                 in no end-of-line conversion.  This is the standard
730                 format for Unix text files.
731         'crlf
732                 The end of a line is marked externally using ASCII
733                 CRLF.  This is the standard format for MS-DOS text
734                 files.
735         'cr
736                 The end of a line is marked externally using ASCII CR.
737                 This is the standard format for Macintosh text files.
738         t
739                 Automatically detect the end-of-line type but do not
740                 generate subsidiary coding systems.  (This value is
741                 converted to nil when stored internally, and
742                 `coding-system-property' will return nil.)
743
744 'post-read-conversion
745      Function called after a file has been read in, to perform the
746      decoding.  Called with two arguments, BEG and END, denoting
747      a region of the current buffer to be decoded.
748
749 'pre-write-conversion
750      Function called before a file is written out, to perform the
751      encoding.  Called with two arguments, BEG and END, denoting
752      a region of the current buffer to be encoded.
753
754
755 The following additional properties are recognized if TYPE is 'iso2022:
756
757 'charset-g0
758 'charset-g1
759 'charset-g2
760 'charset-g3
761      The character set initially designated to the G0 - G3 registers.
762      The value should be one of
763
764           -- A charset object (designate that character set)
765           -- nil (do not ever use this register)
766           -- t (no character set is initially designated to
767                 the register, but may be later on; this automatically
768                 sets the corresponding `force-g*-on-output' property)
769
770 'force-g0-on-output
771 'force-g1-on-output
772 'force-g2-on-output
773 'force-g2-on-output
774      If non-nil, send an explicit designation sequence on output before
775      using the specified register.
776
777 'short
778      If non-nil, use the short forms "ESC $ @", "ESC $ A", and
779      "ESC $ B" on output in place of the full designation sequences
780      "ESC $ ( @", "ESC $ ( A", and "ESC $ ( B".
781
782 'no-ascii-eol
783      If non-nil, don't designate ASCII to G0 at each end of line on output.
784      Setting this to non-nil also suppresses other state-resetting that
785      normally happens at the end of a line.
786
787 'no-ascii-cntl
788      If non-nil, don't designate ASCII to G0 before control chars on output.
789
790 'seven
791      If non-nil, use 7-bit environment on output.  Otherwise, use 8-bit
792      environment.
793
794 'lock-shift
795      If non-nil, use locking-shift (SO/SI) instead of single-shift
796      or designation by escape sequence.
797
798 'no-iso6429
799      If non-nil, don't use ISO6429's direction specification.
800
801 'escape-quoted
802      If non-nil, literal control characters that are the same as
803      the beginning of a recognized ISO2022 or ISO6429 escape sequence
804      (in particular, ESC (0x1B), SO (0x0E), SI (0x0F), SS2 (0x8E),
805      SS3 (0x8F), and CSI (0x9B)) are "quoted" with an escape character
806      so that they can be properly distinguished from an escape sequence.
807      (Note that doing this results in a non-portable encoding.) This
808      encoding flag is used for byte-compiled files.  Note that ESC
809      is a good choice for a quoting character because there are no
810      escape sequences whose second byte is a character from the Control-0
811      or Control-1 character sets; this is explicitly disallowed by the
812      ISO2022 standard.
813
814 'input-charset-conversion
815      A list of conversion specifications, specifying conversion of
816      characters in one charset to another when decoding is performed.
817      Each specification is a list of two elements: the source charset,
818      and the destination charset.
819
820 'output-charset-conversion
821      A list of conversion specifications, specifying conversion of
822      characters in one charset to another when encoding is performed.
823      The form of each specification is the same as for
824      'input-charset-conversion.
825
826
827 The following additional properties are recognized (and required)
828 if TYPE is 'ccl:
829
830 'decode
831      CCL program used for decoding (converting to internal format).
832
833 'encode
834      CCL program used for encoding (converting to external format).
835 */
836        (name, type, doc_string, props))
837 {
838   Lisp_Coding_System *codesys;
839   Lisp_Object rest, key, value;
840   enum coding_system_type ty;
841   int need_to_setup_eol_systems = 1;
842
843   /* Convert type to constant */
844   if (NILP (type) || EQ (type, Qundecided))
845                                       { ty = CODESYS_AUTODETECT; }
846 #ifdef MULE
847   else if (EQ (type, Qshift_jis))     { ty = CODESYS_SHIFT_JIS; }
848   else if (EQ (type, Qiso2022))       { ty = CODESYS_ISO2022; }
849   else if (EQ (type, Qbig5))          { ty = CODESYS_BIG5; }
850   else if (EQ (type, Qucs4))          { ty = CODESYS_UCS4; }
851   else if (EQ (type, Qutf8))          { ty = CODESYS_UTF8; }
852   else if (EQ (type, Qccl))           { ty = CODESYS_CCL; }
853 #endif
854   else if (EQ (type, Qno_conversion)) { ty = CODESYS_NO_CONVERSION; }
855 #ifdef DEBUG_XEMACS
856   else if (EQ (type, Qinternal))      { ty = CODESYS_INTERNAL; }
857 #endif
858   else
859     signal_simple_error ("Invalid coding system type", type);
860
861   CHECK_SYMBOL (name);
862
863   codesys = allocate_coding_system (ty, name);
864
865   if (NILP (doc_string))
866     doc_string = build_string ("");
867   else
868     CHECK_STRING (doc_string);
869   CODING_SYSTEM_DOC_STRING (codesys) = doc_string;
870
871 #ifdef UTF2000
872   if (ty == CODESYS_NO_CONVERSION)
873     codesys->fixed.size = 1;
874 #endif
875   EXTERNAL_PROPERTY_LIST_LOOP (rest, key, value, props)
876     {
877       if (EQ (key, Qmnemonic))
878         {
879           if (!NILP (value))
880             CHECK_STRING (value);
881           CODING_SYSTEM_MNEMONIC (codesys) = value;
882         }
883
884       else if (EQ (key, Qeol_type))
885         {
886           need_to_setup_eol_systems = NILP (value);
887           if (EQ (value, Qt))
888             value = Qnil;
889           CODING_SYSTEM_EOL_TYPE (codesys) = symbol_to_eol_type (value);
890         }
891
892       else if (EQ (key, Qpost_read_conversion)) CODING_SYSTEM_POST_READ_CONVERSION (codesys) = value;
893       else if (EQ (key, Qpre_write_conversion)) CODING_SYSTEM_PRE_WRITE_CONVERSION (codesys) = value;
894 #ifdef MULE
895       else if (ty == CODESYS_ISO2022)
896         {
897 #define FROB_INITIAL_CHARSET(charset_num) \
898   CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, charset_num) = \
899     ((EQ (value, Qt) || EQ (value, Qnil)) ? value : Fget_charset (value))
900
901           if      (EQ (key, Qcharset_g0)) FROB_INITIAL_CHARSET (0);
902           else if (EQ (key, Qcharset_g1)) FROB_INITIAL_CHARSET (1);
903           else if (EQ (key, Qcharset_g2)) FROB_INITIAL_CHARSET (2);
904           else if (EQ (key, Qcharset_g3)) FROB_INITIAL_CHARSET (3);
905
906 #define FROB_FORCE_CHARSET(charset_num) \
907   CODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (codesys, charset_num) = !NILP (value)
908
909           else if (EQ (key, Qforce_g0_on_output)) FROB_FORCE_CHARSET (0);
910           else if (EQ (key, Qforce_g1_on_output)) FROB_FORCE_CHARSET (1);
911           else if (EQ (key, Qforce_g2_on_output)) FROB_FORCE_CHARSET (2);
912           else if (EQ (key, Qforce_g3_on_output)) FROB_FORCE_CHARSET (3);
913
914 #define FROB_BOOLEAN_PROPERTY(prop) \
915   CODING_SYSTEM_ISO2022_##prop (codesys) = !NILP (value)
916
917           else if (EQ (key, Qshort))         FROB_BOOLEAN_PROPERTY (SHORT);
918           else if (EQ (key, Qno_ascii_eol))  FROB_BOOLEAN_PROPERTY (NO_ASCII_EOL);
919           else if (EQ (key, Qno_ascii_cntl)) FROB_BOOLEAN_PROPERTY (NO_ASCII_CNTL);
920           else if (EQ (key, Qseven))         FROB_BOOLEAN_PROPERTY (SEVEN);
921           else if (EQ (key, Qlock_shift))    FROB_BOOLEAN_PROPERTY (LOCK_SHIFT);
922           else if (EQ (key, Qno_iso6429))    FROB_BOOLEAN_PROPERTY (NO_ISO6429);
923           else if (EQ (key, Qescape_quoted)) FROB_BOOLEAN_PROPERTY (ESCAPE_QUOTED);
924
925           else if (EQ (key, Qinput_charset_conversion))
926             {
927               codesys->iso2022.input_conv =
928                 Dynarr_new (charset_conversion_spec);
929               parse_charset_conversion_specs (codesys->iso2022.input_conv,
930                                               value);
931             }
932           else if (EQ (key, Qoutput_charset_conversion))
933             {
934               codesys->iso2022.output_conv =
935                 Dynarr_new (charset_conversion_spec);
936               parse_charset_conversion_specs (codesys->iso2022.output_conv,
937                                               value);
938             }
939           else
940             signal_simple_error ("Unrecognized property", key);
941         }
942       else if (EQ (type, Qccl))
943         {
944           if (EQ (key, Qdecode))
945             {
946               CHECK_VECTOR (value);
947               CODING_SYSTEM_CCL_DECODE (codesys) = value;
948             }
949           else if (EQ (key, Qencode))
950             {
951               CHECK_VECTOR (value);
952               CODING_SYSTEM_CCL_ENCODE (codesys) = value;
953             }
954           else
955             signal_simple_error ("Unrecognized property", key);
956         }
957 #endif /* MULE */
958       else
959         signal_simple_error ("Unrecognized property", key);
960     }
961
962   if (need_to_setup_eol_systems)
963     setup_eol_coding_systems (codesys);
964
965   {
966     Lisp_Object codesys_obj;
967     XSETCODING_SYSTEM (codesys_obj, codesys);
968     Fputhash (name, codesys_obj, Vcoding_system_hash_table);
969     return codesys_obj;
970   }
971 }
972
973 DEFUN ("copy-coding-system", Fcopy_coding_system, 2, 2, 0, /*
974 Copy OLD-CODING-SYSTEM to NEW-NAME.
975 If NEW-NAME does not name an existing coding system, a new one will
976 be created.
977 */
978        (old_coding_system, new_name))
979 {
980   Lisp_Object new_coding_system;
981   old_coding_system = Fget_coding_system (old_coding_system);
982   new_coding_system = Ffind_coding_system (new_name);
983   if (NILP (new_coding_system))
984     {
985       XSETCODING_SYSTEM (new_coding_system,
986                          allocate_coding_system
987                          (XCODING_SYSTEM_TYPE (old_coding_system),
988                           new_name));
989       Fputhash (new_name, new_coding_system, Vcoding_system_hash_table);
990     }
991
992   {
993     Lisp_Coding_System *to = XCODING_SYSTEM (new_coding_system);
994     Lisp_Coding_System *from = XCODING_SYSTEM (old_coding_system);
995     memcpy (((char *) to  ) + sizeof (to->header),
996             ((char *) from) + sizeof (from->header),
997             sizeof (*from) - sizeof (from->header));
998     to->name = new_name;
999   }
1000   return new_coding_system;
1001 }
1002
1003 DEFUN ("define-coding-system-alias", Fdefine_coding_system_alias, 2, 2, 0, /*
1004 Define symbol ALIAS as an alias for coding system CODING-SYSTEM.
1005 */
1006        (alias, coding_system))
1007 {
1008   CHECK_SYMBOL (alias);
1009   if (!NILP (Ffind_coding_system (alias)))
1010     signal_simple_error ("Symbol already names a coding system", alias);
1011   coding_system = Fget_coding_system (coding_system);
1012   Fputhash (alias, coding_system, Vcoding_system_hash_table);
1013
1014   /* Set up aliases for subsidiaries. */
1015   if (XCODING_SYSTEM_EOL_TYPE (coding_system) == EOL_AUTODETECT)
1016     {
1017       Lisp_Object str;
1018       XSETSTRING (str, symbol_name (XSYMBOL (alias)));
1019 #define FROB(type, name)                                                        \
1020       do {                                                                      \
1021         Lisp_Object subsidiary = XCODING_SYSTEM_EOL_##type (coding_system);     \
1022         if (!NILP (subsidiary))                                                 \
1023           Fdefine_coding_system_alias                                           \
1024             (Fintern (concat2 (str, build_string (name)), Qnil), subsidiary);   \
1025       } while (0)
1026       FROB (LF,   "-unix");
1027       FROB (CRLF, "-dos");
1028       FROB (CR,   "-mac");
1029 #undef FROB
1030     }
1031   /* FSF return value is a vector of [ALIAS-unix ALIAS-doc ALIAS-mac],
1032      but it doesn't look intentional, so I'd rather return something
1033      meaningful or nothing at all. */
1034   return Qnil;
1035 }
1036
1037 static Lisp_Object
1038 subsidiary_coding_system (Lisp_Object coding_system, enum eol_type type)
1039 {
1040   Lisp_Coding_System *cs = XCODING_SYSTEM (coding_system);
1041   Lisp_Object new_coding_system;
1042
1043   if (CODING_SYSTEM_EOL_TYPE (cs) != EOL_AUTODETECT)
1044     return coding_system;
1045
1046   switch (type)
1047     {
1048     case EOL_AUTODETECT: return coding_system;
1049     case EOL_LF:   new_coding_system = CODING_SYSTEM_EOL_LF   (cs); break;
1050     case EOL_CR:   new_coding_system = CODING_SYSTEM_EOL_CR   (cs); break;
1051     case EOL_CRLF: new_coding_system = CODING_SYSTEM_EOL_CRLF (cs); break;
1052     default:       abort ();
1053     }
1054
1055   return NILP (new_coding_system) ? coding_system : new_coding_system;
1056 }
1057
1058 DEFUN ("subsidiary-coding-system", Fsubsidiary_coding_system, 2, 2, 0, /*
1059 Return the subsidiary coding system of CODING-SYSTEM with eol type EOL-TYPE.
1060 */
1061        (coding_system, eol_type))
1062 {
1063   coding_system = Fget_coding_system (coding_system);
1064
1065   return subsidiary_coding_system (coding_system,
1066                                    symbol_to_eol_type (eol_type));
1067 }
1068
1069 \f
1070 /************************************************************************/
1071 /*                         Coding system accessors                      */
1072 /************************************************************************/
1073
1074 DEFUN ("coding-system-doc-string", Fcoding_system_doc_string, 1, 1, 0, /*
1075 Return the doc string for CODING-SYSTEM.
1076 */
1077        (coding_system))
1078 {
1079   coding_system = Fget_coding_system (coding_system);
1080   return XCODING_SYSTEM_DOC_STRING (coding_system);
1081 }
1082
1083 DEFUN ("coding-system-type", Fcoding_system_type, 1, 1, 0, /*
1084 Return the type of CODING-SYSTEM.
1085 */
1086        (coding_system))
1087 {
1088   switch (XCODING_SYSTEM_TYPE (Fget_coding_system (coding_system)))
1089     {
1090     default: abort ();
1091     case CODESYS_AUTODETECT:    return Qundecided;
1092 #ifdef MULE
1093     case CODESYS_SHIFT_JIS:     return Qshift_jis;
1094     case CODESYS_ISO2022:       return Qiso2022;
1095     case CODESYS_BIG5:          return Qbig5;
1096     case CODESYS_UCS4:          return Qucs4;
1097     case CODESYS_UTF8:          return Qutf8;
1098     case CODESYS_CCL:           return Qccl;
1099 #endif
1100     case CODESYS_NO_CONVERSION: return Qno_conversion;
1101 #ifdef DEBUG_XEMACS
1102     case CODESYS_INTERNAL:      return Qinternal;
1103 #endif
1104     }
1105 }
1106
1107 #ifdef MULE
1108 static
1109 Lisp_Object coding_system_charset (Lisp_Object coding_system, int gnum)
1110 {
1111   Lisp_Object cs
1112     = XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, gnum);
1113
1114   return CHARSETP (cs) ? XCHARSET_NAME (cs) : Qnil;
1115 }
1116
1117 DEFUN ("coding-system-charset", Fcoding_system_charset, 2, 2, 0, /*
1118 Return initial charset of CODING-SYSTEM designated to GNUM.
1119 GNUM allows 0 .. 3.
1120 */
1121        (coding_system, gnum))
1122 {
1123   coding_system = Fget_coding_system (coding_system);
1124   CHECK_INT (gnum);
1125
1126   return coding_system_charset (coding_system, XINT (gnum));
1127 }
1128 #endif /* MULE */
1129
1130 DEFUN ("coding-system-property", Fcoding_system_property, 2, 2, 0, /*
1131 Return the PROP property of CODING-SYSTEM.
1132 */
1133        (coding_system, prop))
1134 {
1135   int i, ok = 0;
1136   enum coding_system_type type;
1137
1138   coding_system = Fget_coding_system (coding_system);
1139   CHECK_SYMBOL (prop);
1140   type = XCODING_SYSTEM_TYPE (coding_system);
1141
1142   for (i = 0; !ok && i < Dynarr_length (the_codesys_prop_dynarr); i++)
1143     if (EQ (Dynarr_at (the_codesys_prop_dynarr, i).sym, prop))
1144       {
1145         ok = 1;
1146         switch (Dynarr_at (the_codesys_prop_dynarr, i).prop_type)
1147           {
1148           case CODESYS_PROP_ALL_OK:
1149             break;
1150 #ifdef MULE
1151           case CODESYS_PROP_ISO2022:
1152             if (type != CODESYS_ISO2022)
1153               signal_simple_error
1154                 ("Property only valid in ISO2022 coding systems",
1155                  prop);
1156             break;
1157
1158           case CODESYS_PROP_CCL:
1159             if (type != CODESYS_CCL)
1160               signal_simple_error
1161                 ("Property only valid in CCL coding systems",
1162                  prop);
1163             break;
1164 #endif /* MULE */
1165           default:
1166             abort ();
1167           }
1168       }
1169
1170   if (!ok)
1171     signal_simple_error ("Unrecognized property", prop);
1172
1173   if (EQ (prop, Qname))
1174     return XCODING_SYSTEM_NAME (coding_system);
1175   else if (EQ (prop, Qtype))
1176     return Fcoding_system_type (coding_system);
1177   else if (EQ (prop, Qdoc_string))
1178     return XCODING_SYSTEM_DOC_STRING (coding_system);
1179   else if (EQ (prop, Qmnemonic))
1180     return XCODING_SYSTEM_MNEMONIC (coding_system);
1181   else if (EQ (prop, Qeol_type))
1182     return eol_type_to_symbol (XCODING_SYSTEM_EOL_TYPE (coding_system));
1183   else if (EQ (prop, Qeol_lf))
1184     return XCODING_SYSTEM_EOL_LF (coding_system);
1185   else if (EQ (prop, Qeol_crlf))
1186     return XCODING_SYSTEM_EOL_CRLF (coding_system);
1187   else if (EQ (prop, Qeol_cr))
1188     return XCODING_SYSTEM_EOL_CR (coding_system);
1189   else if (EQ (prop, Qpost_read_conversion))
1190     return XCODING_SYSTEM_POST_READ_CONVERSION (coding_system);
1191   else if (EQ (prop, Qpre_write_conversion))
1192     return XCODING_SYSTEM_PRE_WRITE_CONVERSION (coding_system);
1193 #ifdef MULE
1194   else if (type == CODESYS_ISO2022)
1195     {
1196       if (EQ (prop, Qcharset_g0))
1197         return coding_system_charset (coding_system, 0);
1198       else if (EQ (prop, Qcharset_g1))
1199         return coding_system_charset (coding_system, 1);
1200       else if (EQ (prop, Qcharset_g2))
1201         return coding_system_charset (coding_system, 2);
1202       else if (EQ (prop, Qcharset_g3))
1203         return coding_system_charset (coding_system, 3);
1204
1205 #define FORCE_CHARSET(charset_num) \
1206   (XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT \
1207    (coding_system, charset_num) ? Qt : Qnil)
1208
1209       else if (EQ (prop, Qforce_g0_on_output)) return FORCE_CHARSET (0);
1210       else if (EQ (prop, Qforce_g1_on_output)) return FORCE_CHARSET (1);
1211       else if (EQ (prop, Qforce_g2_on_output)) return FORCE_CHARSET (2);
1212       else if (EQ (prop, Qforce_g3_on_output)) return FORCE_CHARSET (3);
1213
1214 #define LISP_BOOLEAN(prop) \
1215   (XCODING_SYSTEM_ISO2022_##prop (coding_system) ? Qt : Qnil)
1216
1217       else if (EQ (prop, Qshort))         return LISP_BOOLEAN (SHORT);
1218       else if (EQ (prop, Qno_ascii_eol))  return LISP_BOOLEAN (NO_ASCII_EOL);
1219       else if (EQ (prop, Qno_ascii_cntl)) return LISP_BOOLEAN (NO_ASCII_CNTL);
1220       else if (EQ (prop, Qseven))         return LISP_BOOLEAN (SEVEN);
1221       else if (EQ (prop, Qlock_shift))    return LISP_BOOLEAN (LOCK_SHIFT);
1222       else if (EQ (prop, Qno_iso6429))    return LISP_BOOLEAN (NO_ISO6429);
1223       else if (EQ (prop, Qescape_quoted)) return LISP_BOOLEAN (ESCAPE_QUOTED);
1224
1225       else if (EQ (prop, Qinput_charset_conversion))
1226         return
1227           unparse_charset_conversion_specs
1228             (XCODING_SYSTEM (coding_system)->iso2022.input_conv);
1229       else if (EQ (prop, Qoutput_charset_conversion))
1230         return
1231           unparse_charset_conversion_specs
1232             (XCODING_SYSTEM (coding_system)->iso2022.output_conv);
1233       else
1234         abort ();
1235     }
1236   else if (type == CODESYS_CCL)
1237     {
1238       if (EQ (prop, Qdecode))
1239         return XCODING_SYSTEM_CCL_DECODE (coding_system);
1240       else if (EQ (prop, Qencode))
1241         return XCODING_SYSTEM_CCL_ENCODE (coding_system);
1242       else
1243         abort ();
1244     }
1245 #endif /* MULE */
1246   else
1247     abort ();
1248
1249   return Qnil; /* not reached */
1250 }
1251
1252 \f
1253 /************************************************************************/
1254 /*                       Coding category functions                      */
1255 /************************************************************************/
1256
1257 static int
1258 decode_coding_category (Lisp_Object symbol)
1259 {
1260   int i;
1261
1262   CHECK_SYMBOL (symbol);
1263   for (i = 0; i <= CODING_CATEGORY_LAST; i++)
1264     if (EQ (coding_category_symbol[i], symbol))
1265       return i;
1266
1267   signal_simple_error ("Unrecognized coding category", symbol);
1268   return 0; /* not reached */
1269 }
1270
1271 DEFUN ("coding-category-list", Fcoding_category_list, 0, 0, 0, /*
1272 Return a list of all recognized coding categories.
1273 */
1274        ())
1275 {
1276   int i;
1277   Lisp_Object list = Qnil;
1278
1279   for (i = CODING_CATEGORY_LAST; i >= 0; i--)
1280     list = Fcons (coding_category_symbol[i], list);
1281   return list;
1282 }
1283
1284 DEFUN ("set-coding-priority-list", Fset_coding_priority_list, 1, 1, 0, /*
1285 Change the priority order of the coding categories.
1286 LIST should be list of coding categories, in descending order of
1287 priority.  Unspecified coding categories will be lower in priority
1288 than all specified ones, in the same relative order they were in
1289 previously.
1290 */
1291        (list))
1292 {
1293   int category_to_priority[CODING_CATEGORY_LAST + 1];
1294   int i, j;
1295   Lisp_Object rest;
1296
1297   /* First generate a list that maps coding categories to priorities. */
1298
1299   for (i = 0; i <= CODING_CATEGORY_LAST; i++)
1300     category_to_priority[i] = -1;
1301
1302   /* Highest priority comes from the specified list. */
1303   i = 0;
1304   EXTERNAL_LIST_LOOP (rest, list)
1305     {
1306       int cat = decode_coding_category (XCAR (rest));
1307
1308       if (category_to_priority[cat] >= 0)
1309         signal_simple_error ("Duplicate coding category in list", XCAR (rest));
1310       category_to_priority[cat] = i++;
1311     }
1312
1313   /* Now go through the existing categories by priority to retrieve
1314      the categories not yet specified and preserve their priority
1315      order. */
1316   for (j = 0; j <= CODING_CATEGORY_LAST; j++)
1317     {
1318       int cat = coding_category_by_priority[j];
1319       if (category_to_priority[cat] < 0)
1320         category_to_priority[cat] = i++;
1321     }
1322
1323   /* Now we need to construct the inverse of the mapping we just
1324      constructed. */
1325
1326   for (i = 0; i <= CODING_CATEGORY_LAST; i++)
1327     coding_category_by_priority[category_to_priority[i]] = i;
1328
1329   /* Phew!  That was confusing. */
1330   return Qnil;
1331 }
1332
1333 DEFUN ("coding-priority-list", Fcoding_priority_list, 0, 0, 0, /*
1334 Return a list of coding categories in descending order of priority.
1335 */
1336        ())
1337 {
1338   int i;
1339   Lisp_Object list = Qnil;
1340
1341   for (i = CODING_CATEGORY_LAST; i >= 0; i--)
1342     list = Fcons (coding_category_symbol[coding_category_by_priority[i]],
1343                   list);
1344   return list;
1345 }
1346
1347 DEFUN ("set-coding-category-system", Fset_coding_category_system, 2, 2, 0, /*
1348 Change the coding system associated with a coding category.
1349 */
1350        (coding_category, coding_system))
1351 {
1352   int cat = decode_coding_category (coding_category);
1353
1354   coding_system = Fget_coding_system (coding_system);
1355   coding_category_system[cat] = coding_system;
1356   return Qnil;
1357 }
1358
1359 DEFUN ("coding-category-system", Fcoding_category_system, 1, 1, 0, /*
1360 Return the coding system associated with a coding category.
1361 */
1362        (coding_category))
1363 {
1364   int cat = decode_coding_category (coding_category);
1365   Lisp_Object sys = coding_category_system[cat];
1366
1367   if (!NILP (sys))
1368     return XCODING_SYSTEM_NAME (sys);
1369   return Qnil;
1370 }
1371
1372 \f
1373 /************************************************************************/
1374 /*                     Detecting the encoding of data                   */
1375 /************************************************************************/
1376
1377 struct detection_state
1378 {
1379   enum eol_type eol_type;
1380   int seen_non_ascii;
1381   int mask;
1382 #ifdef MULE
1383   struct
1384     {
1385       int mask;
1386       int in_second_byte;
1387     }
1388   big5;
1389
1390   struct
1391     {
1392       int mask;
1393       int in_second_byte;
1394     }
1395   shift_jis;
1396
1397   struct
1398     {
1399       int mask;
1400       int in_byte;
1401   }
1402   ucs4;
1403
1404   struct
1405     {
1406       int mask;
1407       int in_byte;
1408     }
1409   utf8;
1410
1411   struct
1412     {
1413       int mask;
1414       int initted;
1415       struct iso2022_decoder iso;
1416       unsigned int flags;
1417       int high_byte_count;
1418       unsigned int saw_single_shift:1;
1419     }
1420   iso2022;
1421 #endif
1422   struct
1423     {
1424       int seen_anything;
1425       int just_saw_cr;
1426     }
1427   eol;
1428 };
1429
1430 static int
1431 acceptable_control_char_p (int c)
1432 {
1433   switch (c)
1434     {
1435       /* Allow and ignore control characters that you might
1436          reasonably see in a text file */
1437     case '\r':
1438     case '\n':
1439     case '\t':
1440     case  7: /* bell */
1441     case  8: /* backspace */
1442     case 11: /* vertical tab */
1443     case 12: /* form feed */
1444     case 26: /* MS-DOS C-z junk */
1445     case 31: /* '^_' -- for info */
1446       return 1;
1447     default:
1448       return 0;
1449     }
1450 }
1451
1452 static int
1453 mask_has_at_most_one_bit_p (int mask)
1454 {
1455   /* Perhaps the only thing useful you learn from intensive Microsoft
1456      technical interviews */
1457   return (mask & (mask - 1)) == 0;
1458 }
1459
1460 static enum eol_type
1461 detect_eol_type (struct detection_state *st, CONST unsigned char *src,
1462                  unsigned int n)
1463 {
1464   int c;
1465
1466   while (n--)
1467     {
1468       c = *src++;
1469       if (c == '\r')
1470         st->eol.just_saw_cr = 1;
1471       else
1472         {
1473           if (c == '\n')
1474             {
1475               if (st->eol.just_saw_cr)
1476                 return EOL_CRLF;
1477               else if (st->eol.seen_anything)
1478                 return EOL_LF;
1479             }
1480           else if (st->eol.just_saw_cr)
1481             return EOL_CR;
1482           st->eol.just_saw_cr = 0;
1483         }
1484       st->eol.seen_anything = 1;
1485     }
1486
1487   return EOL_AUTODETECT;
1488 }
1489
1490 /* Attempt to determine the encoding and EOL type of the given text.
1491    Before calling this function for the first type, you must initialize
1492    st->eol_type as appropriate and initialize st->mask to ~0.
1493
1494    st->eol_type holds the determined EOL type, or EOL_AUTODETECT if
1495    not yet known.
1496
1497    st->mask holds the determined coding category mask, or ~0 if only
1498    ASCII has been seen so far.
1499
1500    Returns:
1501
1502    0 == st->eol_type is EOL_AUTODETECT and/or more than coding category
1503         is present in st->mask
1504    1 == definitive answers are here for both st->eol_type and st->mask
1505 */
1506
1507 static int
1508 detect_coding_type (struct detection_state *st, CONST unsigned char *src,
1509                     unsigned int n, int just_do_eol)
1510 {
1511   int c;
1512
1513   if (st->eol_type == EOL_AUTODETECT)
1514     st->eol_type = detect_eol_type (st, src, n);
1515
1516   if (just_do_eol)
1517     return st->eol_type != EOL_AUTODETECT;
1518
1519   if (!st->seen_non_ascii)
1520     {
1521       for (; n; n--, src++)
1522         {
1523           c = *src;
1524           if ((c < 0x20 && !acceptable_control_char_p (c)) || c >= 0x80)
1525             {
1526               st->seen_non_ascii = 1;
1527 #ifdef MULE
1528               st->shift_jis.mask = ~0;
1529               st->big5.mask = ~0;
1530               st->ucs4.mask = ~0;
1531               st->utf8.mask = ~0;
1532               st->iso2022.mask = ~0;
1533 #endif
1534               break;
1535             }
1536         }
1537     }
1538
1539   if (!n)
1540     return 0;
1541 #ifdef MULE
1542   if (!mask_has_at_most_one_bit_p (st->iso2022.mask))
1543     st->iso2022.mask = detect_coding_iso2022 (st, src, n);
1544   if (!mask_has_at_most_one_bit_p (st->shift_jis.mask))
1545     st->shift_jis.mask = detect_coding_sjis (st, src, n);
1546   if (!mask_has_at_most_one_bit_p (st->big5.mask))
1547     st->big5.mask = detect_coding_big5 (st, src, n);
1548   if (!mask_has_at_most_one_bit_p (st->utf8.mask))
1549     st->utf8.mask = detect_coding_utf8 (st, src, n);
1550   if (!mask_has_at_most_one_bit_p (st->ucs4.mask))
1551     st->ucs4.mask = detect_coding_ucs4 (st, src, n);
1552
1553   st->mask
1554     = st->iso2022.mask | st->shift_jis.mask | st->big5.mask
1555     | st->utf8.mask | st->ucs4.mask;
1556 #endif
1557   {
1558     int retval = mask_has_at_most_one_bit_p (st->mask);
1559     st->mask |= CODING_CATEGORY_NO_CONVERSION_MASK;
1560     return retval && st->eol_type != EOL_AUTODETECT;
1561   }
1562 }
1563
1564 static Lisp_Object
1565 coding_system_from_mask (int mask)
1566 {
1567   if (mask == ~0)
1568     {
1569       /* If the file was entirely or basically ASCII, use the
1570          default value of `buffer-file-coding-system'. */
1571       Lisp_Object retval =
1572         XBUFFER (Vbuffer_defaults)->buffer_file_coding_system;
1573       if (!NILP (retval))
1574         {
1575           retval = Ffind_coding_system (retval);
1576           if (NILP (retval))
1577             {
1578               warn_when_safe
1579                 (Qbad_variable, Qwarning,
1580                  "Invalid `default-buffer-file-coding-system', set to nil");
1581               XBUFFER (Vbuffer_defaults)->buffer_file_coding_system = Qnil;
1582             }
1583         }
1584       if (NILP (retval))
1585         retval = Fget_coding_system (Qraw_text);
1586       return retval;
1587     }
1588   else
1589     {
1590       int i;
1591       int cat = -1;
1592 #ifdef MULE
1593       mask = postprocess_iso2022_mask (mask);
1594 #endif
1595       /* Look through the coding categories by priority and find
1596          the first one that is allowed. */
1597       for (i = 0; i <= CODING_CATEGORY_LAST; i++)
1598         {
1599           cat = coding_category_by_priority[i];
1600           if ((mask & (1 << cat)) &&
1601               !NILP (coding_category_system[cat]))
1602             break;
1603         }
1604       if (cat >= 0)
1605         return coding_category_system[cat];
1606       else
1607         return Fget_coding_system (Qraw_text);
1608     }
1609 }
1610
1611 /* Given a seekable read stream and potential coding system and EOL type
1612    as specified, do any autodetection that is called for.  If the
1613    coding system and/or EOL type are not autodetect, they will be left
1614    alone; but this function will never return an autodetect coding system
1615    or EOL type.
1616
1617    This function does not automatically fetch subsidiary coding systems;
1618    that should be unnecessary with the explicit eol-type argument. */
1619
1620 void
1621 determine_real_coding_system (Lstream *stream, Lisp_Object *codesys_in_out,
1622                               enum eol_type *eol_type_in_out)
1623 {
1624   struct detection_state decst;
1625
1626   if (*eol_type_in_out == EOL_AUTODETECT)
1627     *eol_type_in_out = XCODING_SYSTEM_EOL_TYPE (*codesys_in_out);
1628
1629   xzero (decst);
1630   decst.eol_type = *eol_type_in_out;
1631   decst.mask = ~0;
1632
1633   /* If autodetection is called for, do it now. */
1634   if (XCODING_SYSTEM_TYPE (*codesys_in_out) == CODESYS_AUTODETECT ||
1635       *eol_type_in_out == EOL_AUTODETECT)
1636     {
1637       unsigned char random_buffer[4096];
1638       int nread;
1639       Lisp_Object coding_system = Qnil;
1640
1641       nread = Lstream_read (stream, random_buffer, sizeof (random_buffer));
1642       if (nread)
1643         {
1644           unsigned char *cp = random_buffer;
1645
1646           while (cp < random_buffer + nread)
1647             {
1648               if ((*cp++ == 'c') && (cp < random_buffer + nread) &&
1649                   (*cp++ == 'o') && (cp < random_buffer + nread) &&
1650                   (*cp++ == 'd') && (cp < random_buffer + nread) &&
1651                   (*cp++ == 'i') && (cp < random_buffer + nread) &&
1652                   (*cp++ == 'n') && (cp < random_buffer + nread) &&
1653                   (*cp++ == 'g') && (cp < random_buffer + nread) &&
1654                   (*cp++ == ':') && (cp < random_buffer + nread))
1655                 {
1656                   unsigned char coding_system_name[4096 - 6];
1657                   unsigned char *np = coding_system_name;
1658
1659                   while ( (cp < random_buffer + nread)
1660                           && ((*cp == ' ') || (*cp == '\t')) )
1661                     {
1662                       cp++;
1663                     }
1664                   while ( (cp < random_buffer + nread) &&
1665                           (*cp != ' ') && (*cp != '\t') && (*cp != ';') )
1666                     {
1667                       *np++ = *cp++;
1668                     }
1669                   *np = 0;
1670                   coding_system
1671                     = Ffind_coding_system (intern (coding_system_name));
1672                   break;
1673                 }
1674             }
1675           if (EQ(coding_system, Qnil))
1676             do{
1677               if (detect_coding_type (&decst, random_buffer, nread,
1678                                       XCODING_SYSTEM_TYPE (*codesys_in_out)
1679                                       != CODESYS_AUTODETECT))
1680                 break;
1681               nread = Lstream_read (stream,
1682                                     random_buffer, sizeof (random_buffer));
1683               if (!nread)
1684                 break;
1685             } while(1);
1686         }
1687       *eol_type_in_out = decst.eol_type;
1688       if (XCODING_SYSTEM_TYPE (*codesys_in_out) == CODESYS_AUTODETECT)
1689         {
1690           if (EQ(coding_system, Qnil))
1691             *codesys_in_out = coding_system_from_mask (decst.mask);
1692           else
1693             *codesys_in_out = coding_system;
1694         }
1695     }
1696   /* If we absolutely can't determine the EOL type, just assume LF. */
1697   if (*eol_type_in_out == EOL_AUTODETECT)
1698     *eol_type_in_out = EOL_LF;
1699
1700   Lstream_rewind (stream);
1701 }
1702
1703 DEFUN ("detect-coding-region", Fdetect_coding_region, 2, 3, 0, /*
1704 Detect coding system of the text in the region between START and END.
1705 Returned a list of possible coding systems ordered by priority.
1706 If only ASCII characters are found, it returns 'undecided or one of
1707 its subsidiary coding systems according to a detected end-of-line
1708 type.  Optional arg BUFFER defaults to the current buffer.
1709 */
1710        (start, end, buffer))
1711 {
1712   Lisp_Object val = Qnil;
1713   struct buffer *buf = decode_buffer (buffer, 0);
1714   Bufpos b, e;
1715   Lisp_Object instream, lb_instream;
1716   Lstream *istr, *lb_istr;
1717   struct detection_state decst;
1718   struct gcpro gcpro1, gcpro2;
1719
1720   get_buffer_range_char (buf, start, end, &b, &e, 0);
1721   lb_instream = make_lisp_buffer_input_stream (buf, b, e, 0);
1722   lb_istr = XLSTREAM (lb_instream);
1723   instream = make_encoding_input_stream (lb_istr, Fget_coding_system (Qbinary));
1724   istr = XLSTREAM (instream);
1725   GCPRO2 (instream, lb_instream);
1726   xzero (decst);
1727   decst.eol_type = EOL_AUTODETECT;
1728   decst.mask = ~0;
1729   while (1)
1730     {
1731       unsigned char random_buffer[4096];
1732       int nread = Lstream_read (istr, random_buffer, sizeof (random_buffer));
1733
1734       if (!nread)
1735         break;
1736       if (detect_coding_type (&decst, random_buffer, nread, 0))
1737         break;
1738     }
1739
1740   if (decst.mask == ~0)
1741     val = subsidiary_coding_system (Fget_coding_system (Qundecided),
1742                                     decst.eol_type);
1743   else
1744     {
1745       int i;
1746
1747       val = Qnil;
1748 #ifdef MULE
1749       decst.mask = postprocess_iso2022_mask (decst.mask);
1750 #endif
1751       for (i = CODING_CATEGORY_LAST; i >= 0; i--)
1752         {
1753           int sys = coding_category_by_priority[i];
1754           if (decst.mask & (1 << sys))
1755             {
1756               Lisp_Object codesys = coding_category_system[sys];
1757               if (!NILP (codesys))
1758                 codesys = subsidiary_coding_system (codesys, decst.eol_type);
1759               val = Fcons (codesys, val);
1760             }
1761         }
1762     }
1763   Lstream_close (istr);
1764   UNGCPRO;
1765   Lstream_delete (istr);
1766   Lstream_delete (lb_istr);
1767   return val;
1768 }
1769
1770 \f
1771 /************************************************************************/
1772 /*           Converting to internal Mule format ("decoding")            */
1773 /************************************************************************/
1774
1775 /* A decoding stream is a stream used for decoding text (i.e.
1776    converting from some external format to internal format).
1777    The decoding-stream object keeps track of the actual coding
1778    stream, the stream that is at the other end, and data that
1779    needs to be persistent across the lifetime of the stream. */
1780
1781 /* Handle the EOL stuff related to just-read-in character C.
1782    EOL_TYPE is the EOL type of the coding stream.
1783    FLAGS is the current value of FLAGS in the coding stream, and may
1784    be modified by this macro.  (The macro only looks at the
1785    CODING_STATE_CR flag.)  DST is the Dynarr to which the decoded
1786    bytes are to be written.  You need to also define a local goto
1787    label "label_continue_loop" that is at the end of the main
1788    character-reading loop.
1789
1790    If C is a CR character, then this macro handles it entirely and
1791    jumps to label_continue_loop.  Otherwise, this macro does not add
1792    anything to DST, and continues normally.  You should continue
1793    processing C normally after this macro. */
1794
1795 #define DECODE_HANDLE_EOL_TYPE(eol_type, c, flags, dst)         \
1796 do {                                                            \
1797   if (c == '\r')                                                \
1798     {                                                           \
1799       if (eol_type == EOL_CR)                                   \
1800         Dynarr_add (dst, '\n');                                 \
1801       else if (eol_type != EOL_CRLF || flags & CODING_STATE_CR) \
1802         Dynarr_add (dst, c);                                    \
1803       else                                                      \
1804         flags |= CODING_STATE_CR;                               \
1805       goto label_continue_loop;                                 \
1806     }                                                           \
1807   else if (flags & CODING_STATE_CR)                             \
1808     {   /* eol_type == CODING_SYSTEM_EOL_CRLF */                \
1809       if (c != '\n')                                            \
1810         Dynarr_add (dst, '\r');                                 \
1811       flags &= ~CODING_STATE_CR;                                \
1812     }                                                           \
1813 } while (0)
1814
1815 /* C should be a binary character in the range 0 - 255; convert
1816    to internal format and add to Dynarr DST. */
1817
1818 #ifdef UTF2000
1819 #define DECODE_ADD_BINARY_CHAR(c, dst) \
1820 do {                                            \
1821   if (BYTE_ASCII_P (c))                         \
1822     Dynarr_add (dst, c);                        \
1823   else                                          \
1824     {                                           \
1825       Dynarr_add (dst, (c >> 6) | 0xc0);        \
1826       Dynarr_add (dst, (c & 0x3f) | 0x80);      \
1827     }                                           \
1828 } while (0)
1829
1830 INLINE void
1831 DECODE_ADD_UCS_CHAR(Emchar c, unsigned_char_dynarr* dst)
1832 {
1833   if ( c <= 0x7f )
1834     {
1835       Dynarr_add (dst, c);
1836     }
1837   else if ( c <= 0x7ff )
1838     {
1839       Dynarr_add (dst, (c >> 6) | 0xc0);
1840       Dynarr_add (dst, (c & 0x3f) | 0x80);
1841     }
1842   else if ( c <= 0xffff )
1843     {
1844       Dynarr_add (dst,  (c >> 12) | 0xe0);
1845       Dynarr_add (dst, ((c >>  6) & 0x3f) | 0x80);
1846       Dynarr_add (dst,  (c        & 0x3f) | 0x80);
1847     }
1848   else if ( c <= 0x1fffff )
1849     {
1850       Dynarr_add (dst,  (c >> 18) | 0xf0);
1851       Dynarr_add (dst, ((c >> 12) & 0x3f) | 0x80);
1852       Dynarr_add (dst, ((c >>  6) & 0x3f) | 0x80);
1853       Dynarr_add (dst,  (c        & 0x3f) | 0x80);
1854     }
1855   else if ( c <= 0x3ffffff )
1856     {
1857       Dynarr_add (dst,  (c >> 24) | 0xf8);
1858       Dynarr_add (dst, ((c >> 18) & 0x3f) | 0x80);
1859       Dynarr_add (dst, ((c >> 12) & 0x3f) | 0x80);
1860       Dynarr_add (dst, ((c >>  6) & 0x3f) | 0x80);
1861       Dynarr_add (dst,  (c        & 0x3f) | 0x80);
1862     }
1863   else
1864     {
1865       Dynarr_add (dst,  (c >> 30) | 0xfc);
1866       Dynarr_add (dst, ((c >> 24) & 0x3f) | 0x80);
1867       Dynarr_add (dst, ((c >> 18) & 0x3f) | 0x80);
1868       Dynarr_add (dst, ((c >> 12) & 0x3f) | 0x80);
1869       Dynarr_add (dst, ((c >>  6) & 0x3f) | 0x80);
1870       Dynarr_add (dst,  (c        & 0x3f) | 0x80);
1871     }
1872 }
1873 #else
1874 #define DECODE_ADD_BINARY_CHAR(c, dst)          \
1875 do {                                            \
1876   if (BYTE_ASCII_P (c))                         \
1877     Dynarr_add (dst, c);                        \
1878   else if (BYTE_C1_P (c))                       \
1879     {                                           \
1880       Dynarr_add (dst, LEADING_BYTE_CONTROL_1); \
1881       Dynarr_add (dst, c + 0x20);               \
1882     }                                           \
1883   else                                          \
1884     {                                           \
1885       Dynarr_add (dst, LEADING_BYTE_LATIN_ISO8859_1); \
1886       Dynarr_add (dst, c);                      \
1887     }                                           \
1888 } while (0)
1889 #endif
1890
1891 #define DECODE_OUTPUT_PARTIAL_CHAR(ch)  \
1892 do {                                    \
1893   if (ch)                               \
1894     {                                   \
1895       DECODE_ADD_BINARY_CHAR (ch, dst); \
1896       ch = 0;                           \
1897     }                                   \
1898 } while (0)
1899
1900 #define DECODE_HANDLE_END_OF_CONVERSION(flags, ch, dst) \
1901 do {                                    \
1902   if (flags & CODING_STATE_END)         \
1903     {                                   \
1904       DECODE_OUTPUT_PARTIAL_CHAR (ch);  \
1905       if (flags & CODING_STATE_CR)      \
1906         Dynarr_add (dst, '\r');         \
1907     }                                   \
1908 } while (0)
1909
1910 #define DECODING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, decoding)
1911
1912 struct decoding_stream
1913 {
1914   /* Coding system that governs the conversion. */
1915   Lisp_Coding_System *codesys;
1916
1917   /* Stream that we read the encoded data from or
1918      write the decoded data to. */
1919   Lstream *other_end;
1920
1921   /* If we are reading, then we can return only a fixed amount of
1922      data, so if the conversion resulted in too much data, we store it
1923      here for retrieval the next time around. */
1924   unsigned_char_dynarr *runoff;
1925
1926   /* FLAGS holds flags indicating the current state of the decoding.
1927      Some of these flags are dependent on the coding system. */
1928   unsigned int flags;
1929
1930   /* CH holds a partially built-up character.  Since we only deal
1931      with one- and two-byte characters at the moment, we only use
1932      this to store the first byte of a two-byte character. */
1933   unsigned int ch;
1934
1935   /* EOL_TYPE specifies the type of end-of-line conversion that
1936      currently applies.  We need to keep this separate from the
1937      EOL type stored in CODESYS because the latter might indicate
1938      automatic EOL-type detection while the former will always
1939      indicate a particular EOL type. */
1940   enum eol_type eol_type;
1941 #ifdef MULE
1942   /* Additional ISO2022 information.  We define the structure above
1943      because it's also needed by the detection routines. */
1944   struct iso2022_decoder iso2022;
1945
1946   /* Additional information (the state of the running CCL program)
1947      used by the CCL decoder. */
1948   struct ccl_program ccl;
1949
1950   /* counter for UTF-8 or UCS-4 */
1951   unsigned char counter;
1952 #endif
1953   struct detection_state decst;
1954 };
1955
1956 static int decoding_reader     (Lstream *stream,       unsigned char *data, size_t size);
1957 static int decoding_writer     (Lstream *stream, CONST unsigned char *data, size_t size);
1958 static int decoding_rewinder   (Lstream *stream);
1959 static int decoding_seekable_p (Lstream *stream);
1960 static int decoding_flusher    (Lstream *stream);
1961 static int decoding_closer     (Lstream *stream);
1962
1963 static Lisp_Object decoding_marker (Lisp_Object stream,
1964                                     void (*markobj) (Lisp_Object));
1965
1966 DEFINE_LSTREAM_IMPLEMENTATION ("decoding", lstream_decoding,
1967                                sizeof (struct decoding_stream));
1968
1969 static Lisp_Object
1970 decoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
1971 {
1972   Lstream *str = DECODING_STREAM_DATA (XLSTREAM (stream))->other_end;
1973   Lisp_Object str_obj;
1974
1975   /* We do not need to mark the coding systems or charsets stored
1976      within the stream because they are stored in a global list
1977      and automatically marked. */
1978
1979   XSETLSTREAM (str_obj, str);
1980   markobj (str_obj);
1981   if (str->imp->marker)
1982     return (str->imp->marker) (str_obj, markobj);
1983   else
1984     return Qnil;
1985 }
1986
1987 /* Read SIZE bytes of data and store it into DATA.  We are a decoding stream
1988    so we read data from the other end, decode it, and store it into DATA. */
1989
1990 static int
1991 decoding_reader (Lstream *stream, unsigned char *data, size_t size)
1992 {
1993   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
1994   unsigned char *orig_data = data;
1995   int read_size;
1996   int error_occurred = 0;
1997
1998   /* We need to interface to mule_decode(), which expects to take some
1999      amount of data and store the result into a Dynarr.  We have
2000      mule_decode() store into str->runoff, and take data from there
2001      as necessary. */
2002
2003   /* We loop until we have enough data, reading chunks from the other
2004      end and decoding it. */
2005   while (1)
2006     {
2007       /* Take data from the runoff if we can.  Make sure to take at
2008          most SIZE bytes, and delete the data from the runoff. */
2009       if (Dynarr_length (str->runoff) > 0)
2010         {
2011           size_t chunk = min (size, (size_t) Dynarr_length (str->runoff));
2012           memcpy (data, Dynarr_atp (str->runoff, 0), chunk);
2013           Dynarr_delete_many (str->runoff, 0, chunk);
2014           data += chunk;
2015           size -= chunk;
2016         }
2017
2018       if (size == 0)
2019         break; /* No more room for data */
2020
2021       if (str->flags & CODING_STATE_END)
2022         /* This means that on the previous iteration, we hit the EOF on
2023            the other end.  We loop once more so that mule_decode() can
2024            output any final stuff it may be holding, or any "go back
2025            to a sane state" escape sequences. (This latter makes sense
2026            during encoding.) */
2027         break;
2028
2029       /* Exhausted the runoff, so get some more.  DATA has at least
2030          SIZE bytes left of storage in it, so it's OK to read directly
2031          into it.  (We'll be overwriting above, after we've decoded it
2032          into the runoff.) */
2033       read_size = Lstream_read (str->other_end, data, size);
2034       if (read_size < 0)
2035         {
2036           error_occurred = 1;
2037           break;
2038         }
2039       if (read_size == 0)
2040         /* There might be some more end data produced in the translation.
2041            See the comment above. */
2042         str->flags |= CODING_STATE_END;
2043       mule_decode (stream, data, str->runoff, read_size);
2044     }
2045
2046   if (data - orig_data == 0)
2047     return error_occurred ? -1 : 0;
2048   else
2049     return data - orig_data;
2050 }
2051
2052 static int
2053 decoding_writer (Lstream *stream, CONST unsigned char *data, size_t size)
2054 {
2055   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2056   int retval;
2057
2058   /* Decode all our data into the runoff, and then attempt to write
2059      it all out to the other end.  Remove whatever chunk we succeeded
2060      in writing. */
2061   mule_decode (stream, data, str->runoff, size);
2062   retval = Lstream_write (str->other_end, Dynarr_atp (str->runoff, 0),
2063                           Dynarr_length (str->runoff));
2064   if (retval > 0)
2065     Dynarr_delete_many (str->runoff, 0, retval);
2066   /* Do NOT return retval.  The return value indicates how much
2067      of the incoming data was written, not how many bytes were
2068      written. */
2069   return size;
2070 }
2071
2072 static void
2073 reset_decoding_stream (struct decoding_stream *str)
2074 {
2075 #ifdef MULE
2076   if (CODING_SYSTEM_TYPE (str->codesys) == CODESYS_ISO2022)
2077     {
2078       Lisp_Object coding_system;
2079       XSETCODING_SYSTEM (coding_system, str->codesys);
2080       reset_iso2022 (coding_system, &str->iso2022);
2081     }
2082   else if (CODING_SYSTEM_TYPE (str->codesys) == CODESYS_CCL)
2083     {
2084       setup_ccl_program (&str->ccl, CODING_SYSTEM_CCL_DECODE (str->codesys));
2085     }
2086   str->counter = 0;
2087 #endif /* MULE */
2088   str->flags = str->ch = 0;
2089 }
2090
2091 static int
2092 decoding_rewinder (Lstream *stream)
2093 {
2094   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2095   reset_decoding_stream (str);
2096   Dynarr_reset (str->runoff);
2097   return Lstream_rewind (str->other_end);
2098 }
2099
2100 static int
2101 decoding_seekable_p (Lstream *stream)
2102 {
2103   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2104   return Lstream_seekable_p (str->other_end);
2105 }
2106
2107 static int
2108 decoding_flusher (Lstream *stream)
2109 {
2110   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2111   return Lstream_flush (str->other_end);
2112 }
2113
2114 static int
2115 decoding_closer (Lstream *stream)
2116 {
2117   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2118   if (stream->flags & LSTREAM_FL_WRITE)
2119     {
2120       str->flags |= CODING_STATE_END;
2121       decoding_writer (stream, 0, 0);
2122     }
2123   Dynarr_free (str->runoff);
2124 #ifdef MULE
2125 #ifdef ENABLE_COMPOSITE_CHARS
2126   if (str->iso2022.composite_chars)
2127     Dynarr_free (str->iso2022.composite_chars);
2128 #endif
2129 #endif
2130   return Lstream_close (str->other_end);
2131 }
2132
2133 Lisp_Object
2134 decoding_stream_coding_system (Lstream *stream)
2135 {
2136   Lisp_Object coding_system;
2137   struct decoding_stream *str = DECODING_STREAM_DATA (stream);
2138
2139   XSETCODING_SYSTEM (coding_system, str->codesys);
2140   return subsidiary_coding_system (coding_system, str->eol_type);
2141 }
2142
2143 void
2144 set_decoding_stream_coding_system (Lstream *lstr, Lisp_Object codesys)
2145 {
2146   Lisp_Coding_System *cs = XCODING_SYSTEM (codesys);
2147   struct decoding_stream *str = DECODING_STREAM_DATA (lstr);
2148   str->codesys = cs;
2149   if (CODING_SYSTEM_EOL_TYPE (cs) != EOL_AUTODETECT)
2150     str->eol_type = CODING_SYSTEM_EOL_TYPE (cs);
2151   reset_decoding_stream (str);
2152 }
2153
2154 /* WARNING WARNING WARNING WARNING!!!!!  If you open up a decoding
2155    stream for writing, no automatic code detection will be performed.
2156    The reason for this is that automatic code detection requires a
2157    seekable input.  Things will also fail if you open a decoding
2158    stream for reading using a non-fully-specified coding system and
2159    a non-seekable input stream. */
2160
2161 static Lisp_Object
2162 make_decoding_stream_1 (Lstream *stream, Lisp_Object codesys,
2163                         CONST char *mode)
2164 {
2165   Lstream *lstr = Lstream_new (lstream_decoding, mode);
2166   struct decoding_stream *str = DECODING_STREAM_DATA (lstr);
2167   Lisp_Object obj;
2168
2169   xzero (*str);
2170   str->other_end = stream;
2171   str->runoff = (unsigned_char_dynarr *) Dynarr_new (unsigned_char);
2172   str->eol_type = EOL_AUTODETECT;
2173   if (!strcmp (mode, "r")
2174       && Lstream_seekable_p (stream))
2175     /* We can determine the coding system now. */
2176     determine_real_coding_system (stream, &codesys, &str->eol_type);
2177   set_decoding_stream_coding_system (lstr, codesys);
2178   str->decst.eol_type = str->eol_type;
2179   str->decst.mask = ~0;
2180   XSETLSTREAM (obj, lstr);
2181   return obj;
2182 }
2183
2184 Lisp_Object
2185 make_decoding_input_stream (Lstream *stream, Lisp_Object codesys)
2186 {
2187   return make_decoding_stream_1 (stream, codesys, "r");
2188 }
2189
2190 Lisp_Object
2191 make_decoding_output_stream (Lstream *stream, Lisp_Object codesys)
2192 {
2193   return make_decoding_stream_1 (stream, codesys, "w");
2194 }
2195
2196 /* Note: the decode_coding_* functions all take the same
2197    arguments as mule_decode(), which is to say some SRC data of
2198    size N, which is to be stored into dynamic array DST.
2199    DECODING is the stream within which the decoding is
2200    taking place, but no data is actually read from or
2201    written to that stream; that is handled in decoding_reader()
2202    or decoding_writer().  This allows the same functions to
2203    be used for both reading and writing. */
2204
2205 static void
2206 mule_decode (Lstream *decoding, CONST unsigned char *src,
2207              unsigned_char_dynarr *dst, unsigned int n)
2208 {
2209   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
2210
2211   /* If necessary, do encoding-detection now.  We do this when
2212      we're a writing stream or a non-seekable reading stream,
2213      meaning that we can't just process the whole input,
2214      rewind, and start over. */
2215
2216   if (CODING_SYSTEM_TYPE (str->codesys) == CODESYS_AUTODETECT ||
2217       str->eol_type == EOL_AUTODETECT)
2218     {
2219       Lisp_Object codesys;
2220
2221       XSETCODING_SYSTEM (codesys, str->codesys);
2222       detect_coding_type (&str->decst, src, n,
2223                           CODING_SYSTEM_TYPE (str->codesys) !=
2224                           CODESYS_AUTODETECT);
2225       if (CODING_SYSTEM_TYPE (str->codesys) == CODESYS_AUTODETECT &&
2226           str->decst.mask != ~0)
2227         /* #### This is cheesy.  What we really ought to do is
2228            buffer up a certain amount of data so as to get a
2229            less random result. */
2230         codesys = coding_system_from_mask (str->decst.mask);
2231       str->eol_type = str->decst.eol_type;
2232       if (XCODING_SYSTEM (codesys) != str->codesys)
2233         {
2234           /* Preserve the CODING_STATE_END flag in case it was set.
2235              If we erase it, bad things might happen. */
2236           int was_end = str->flags & CODING_STATE_END;
2237           set_decoding_stream_coding_system (decoding, codesys);
2238           if (was_end)
2239             str->flags |= CODING_STATE_END;
2240         }
2241     }
2242
2243   switch (CODING_SYSTEM_TYPE (str->codesys))
2244     {
2245 #ifdef DEBUG_XEMACS
2246     case CODESYS_INTERNAL:
2247       Dynarr_add_many (dst, src, n);
2248       break;
2249 #endif
2250     case CODESYS_AUTODETECT:
2251       /* If we got this far and still haven't decided on the coding
2252          system, then do no conversion. */
2253     case CODESYS_NO_CONVERSION:
2254       decode_coding_no_conversion (decoding, src, dst, n);
2255       break;
2256 #ifdef MULE
2257     case CODESYS_SHIFT_JIS:
2258       decode_coding_sjis (decoding, src, dst, n);
2259       break;
2260     case CODESYS_BIG5:
2261       decode_coding_big5 (decoding, src, dst, n);
2262       break;
2263     case CODESYS_UCS4:
2264       decode_coding_ucs4 (decoding, src, dst, n);
2265       break;
2266     case CODESYS_UTF8:
2267       decode_coding_utf8 (decoding, src, dst, n);
2268       break;
2269     case CODESYS_CCL:
2270       str->ccl.last_block = str->flags & CODING_STATE_END;
2271       ccl_driver (&str->ccl, src, dst, n, 0, CCL_MODE_DECODING);
2272       break;
2273     case CODESYS_ISO2022:
2274       decode_coding_iso2022 (decoding, src, dst, n);
2275       break;
2276 #endif /* MULE */
2277     default:
2278       abort ();
2279     }
2280 }
2281
2282 DEFUN ("decode-coding-region", Fdecode_coding_region, 3, 4, 0, /*
2283 Decode the text between START and END which is encoded in CODING-SYSTEM.
2284 This is useful if you've read in encoded text from a file without decoding
2285 it (e.g. you read in a JIS-formatted file but used the `binary' or
2286 `no-conversion' coding system, so that it shows up as "^[$B!<!+^[(B").
2287 Return length of decoded text.
2288 BUFFER defaults to the current buffer if unspecified.
2289 */
2290        (start, end, coding_system, buffer))
2291 {
2292   Bufpos b, e;
2293   struct buffer *buf = decode_buffer (buffer, 0);
2294   Lisp_Object instream, lb_outstream, de_outstream, outstream;
2295   Lstream *istr, *ostr;
2296   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2297
2298   get_buffer_range_char (buf, start, end, &b, &e, 0);
2299
2300   barf_if_buffer_read_only (buf, b, e);
2301
2302   coding_system = Fget_coding_system (coding_system);
2303   instream = make_lisp_buffer_input_stream  (buf, b, e, 0);
2304   lb_outstream = make_lisp_buffer_output_stream (buf, b, 0);
2305   de_outstream = make_decoding_output_stream (XLSTREAM (lb_outstream),
2306                                               coding_system);
2307   outstream = make_encoding_output_stream (XLSTREAM (de_outstream),
2308                                            Fget_coding_system (Qbinary));
2309   istr = XLSTREAM (instream);
2310   ostr = XLSTREAM (outstream);
2311   GCPRO4 (instream, lb_outstream, de_outstream, outstream);
2312
2313   /* The chain of streams looks like this:
2314
2315      [BUFFER] <----- send through
2316                      ------> [ENCODE AS BINARY]
2317                              ------> [DECODE AS SPECIFIED]
2318                                      ------> [BUFFER]
2319    */
2320
2321   while (1)
2322     {
2323       char tempbuf[1024]; /* some random amount */
2324       Bufpos newpos, even_newer_pos;
2325       Bufpos oldpos = lisp_buffer_stream_startpos (istr);
2326       int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
2327
2328       if (!size_in_bytes)
2329         break;
2330       newpos = lisp_buffer_stream_startpos (istr);
2331       Lstream_write (ostr, tempbuf, size_in_bytes);
2332       even_newer_pos = lisp_buffer_stream_startpos (istr);
2333       buffer_delete_range (buf, even_newer_pos - (newpos - oldpos),
2334                            even_newer_pos, 0);
2335     }
2336   Lstream_close (istr);
2337   Lstream_close (ostr);
2338   UNGCPRO;
2339   Lstream_delete (istr);
2340   Lstream_delete (ostr);
2341   Lstream_delete (XLSTREAM (de_outstream));
2342   Lstream_delete (XLSTREAM (lb_outstream));
2343   return Qnil;
2344 }
2345
2346 \f
2347 /************************************************************************/
2348 /*           Converting to an external encoding ("encoding")            */
2349 /************************************************************************/
2350
2351 /* An encoding stream is an output stream.  When you create the
2352    stream, you specify the coding system that governs the encoding
2353    and another stream that the resulting encoded data is to be
2354    sent to, and then start sending data to it. */
2355
2356 #define ENCODING_STREAM_DATA(stream) LSTREAM_TYPE_DATA (stream, encoding)
2357
2358 struct encoding_stream
2359 {
2360   /* Coding system that governs the conversion. */
2361   Lisp_Coding_System *codesys;
2362
2363   /* Stream that we read the encoded data from or
2364      write the decoded data to. */
2365   Lstream *other_end;
2366
2367   /* If we are reading, then we can return only a fixed amount of
2368      data, so if the conversion resulted in too much data, we store it
2369      here for retrieval the next time around. */
2370   unsigned_char_dynarr *runoff;
2371
2372   /* FLAGS holds flags indicating the current state of the encoding.
2373      Some of these flags are dependent on the coding system. */
2374   unsigned int flags;
2375
2376   /* CH holds a partially built-up character.  Since we only deal
2377      with one- and two-byte characters at the moment, we only use
2378      this to store the first byte of a two-byte character. */
2379   unsigned int ch;
2380 #ifdef MULE
2381   /* Additional information used by the ISO2022 encoder. */
2382   struct
2383     {
2384       /* CHARSET holds the character sets currently assigned to the G0
2385          through G3 registers.  It is initialized from the array
2386          INITIAL_CHARSET in CODESYS. */
2387       Lisp_Object charset[4];
2388
2389       /* Which registers are currently invoked into the left (GL) and
2390          right (GR) halves of the 8-bit encoding space? */
2391       int register_left, register_right;
2392
2393       /* Whether we need to explicitly designate the charset in the
2394          G? register before using it.  It is initialized from the
2395          array FORCE_CHARSET_ON_OUTPUT in CODESYS. */
2396       unsigned char force_charset_on_output[4];
2397
2398       /* Other state variables that need to be preserved across
2399          invocations. */
2400       Lisp_Object current_charset;
2401       int current_half;
2402       int current_char_boundary;
2403     } iso2022;
2404
2405   void (*encode_char) (struct encoding_stream *str, Emchar c,
2406                        unsigned_char_dynarr *dst, unsigned int *flags);
2407   void (*finish) (struct encoding_stream *str,
2408                   unsigned_char_dynarr *dst, unsigned int *flags);
2409
2410   /* Additional information (the state of the running CCL program)
2411      used by the CCL encoder. */
2412   struct ccl_program ccl;
2413 #endif /* MULE */
2414 };
2415
2416 static int encoding_reader (Lstream *stream, unsigned char *data, size_t size);
2417 static int encoding_writer (Lstream *stream, CONST unsigned char *data,
2418                             size_t size);
2419 static int encoding_rewinder   (Lstream *stream);
2420 static int encoding_seekable_p (Lstream *stream);
2421 static int encoding_flusher    (Lstream *stream);
2422 static int encoding_closer     (Lstream *stream);
2423
2424 static Lisp_Object encoding_marker (Lisp_Object stream,
2425                                     void (*markobj) (Lisp_Object));
2426
2427 DEFINE_LSTREAM_IMPLEMENTATION ("encoding", lstream_encoding,
2428                                sizeof (struct encoding_stream));
2429
2430 static Lisp_Object
2431 encoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object))
2432 {
2433   Lstream *str = ENCODING_STREAM_DATA (XLSTREAM (stream))->other_end;
2434   Lisp_Object str_obj;
2435
2436   /* We do not need to mark the coding systems or charsets stored
2437      within the stream because they are stored in a global list
2438      and automatically marked. */
2439
2440   XSETLSTREAM (str_obj, str);
2441   markobj (str_obj);
2442   if (str->imp->marker)
2443     return (str->imp->marker) (str_obj, markobj);
2444   else
2445     return Qnil;
2446 }
2447
2448 /* Read SIZE bytes of data and store it into DATA.  We are a encoding stream
2449    so we read data from the other end, encode it, and store it into DATA. */
2450
2451 static int
2452 encoding_reader (Lstream *stream, unsigned char *data, size_t size)
2453 {
2454   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2455   unsigned char *orig_data = data;
2456   int read_size;
2457   int error_occurred = 0;
2458
2459   /* We need to interface to mule_encode(), which expects to take some
2460      amount of data and store the result into a Dynarr.  We have
2461      mule_encode() store into str->runoff, and take data from there
2462      as necessary. */
2463
2464   /* We loop until we have enough data, reading chunks from the other
2465      end and encoding it. */
2466   while (1)
2467     {
2468       /* Take data from the runoff if we can.  Make sure to take at
2469          most SIZE bytes, and delete the data from the runoff. */
2470       if (Dynarr_length (str->runoff) > 0)
2471         {
2472           int chunk = min ((int) size, Dynarr_length (str->runoff));
2473           memcpy (data, Dynarr_atp (str->runoff, 0), chunk);
2474           Dynarr_delete_many (str->runoff, 0, chunk);
2475           data += chunk;
2476           size -= chunk;
2477         }
2478
2479       if (size == 0)
2480         break; /* No more room for data */
2481
2482       if (str->flags & CODING_STATE_END)
2483         /* This means that on the previous iteration, we hit the EOF on
2484            the other end.  We loop once more so that mule_encode() can
2485            output any final stuff it may be holding, or any "go back
2486            to a sane state" escape sequences. (This latter makes sense
2487            during encoding.) */
2488         break;
2489
2490       /* Exhausted the runoff, so get some more.  DATA at least SIZE bytes
2491          left of storage in it, so it's OK to read directly into it.
2492          (We'll be overwriting above, after we've encoded it into the
2493          runoff.) */
2494       read_size = Lstream_read (str->other_end, data, size);
2495       if (read_size < 0)
2496         {
2497           error_occurred = 1;
2498           break;
2499         }
2500       if (read_size == 0)
2501         /* There might be some more end data produced in the translation.
2502            See the comment above. */
2503         str->flags |= CODING_STATE_END;
2504       mule_encode (stream, data, str->runoff, read_size);
2505     }
2506
2507   if (data == orig_data)
2508     return error_occurred ? -1 : 0;
2509   else
2510     return data - orig_data;
2511 }
2512
2513 static int
2514 encoding_writer (Lstream *stream, CONST unsigned char *data, size_t size)
2515 {
2516   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2517   int retval;
2518
2519   /* Encode all our data into the runoff, and then attempt to write
2520      it all out to the other end.  Remove whatever chunk we succeeded
2521      in writing. */
2522   mule_encode (stream, data, str->runoff, size);
2523   retval = Lstream_write (str->other_end, Dynarr_atp (str->runoff, 0),
2524                           Dynarr_length (str->runoff));
2525   if (retval > 0)
2526     Dynarr_delete_many (str->runoff, 0, retval);
2527   /* Do NOT return retval.  The return value indicates how much
2528      of the incoming data was written, not how many bytes were
2529      written. */
2530   return size;
2531 }
2532
2533 static void
2534 reset_encoding_stream (struct encoding_stream *str)
2535 {
2536 #ifdef MULE
2537   switch (CODING_SYSTEM_TYPE (str->codesys))
2538     {
2539     case CODESYS_ISO2022:
2540       {
2541         int i;
2542
2543         str->encode_char = &char_encode_iso2022;
2544         str->finish = &char_finish_iso2022;
2545         for (i = 0; i < 4; i++)
2546           {
2547             str->iso2022.charset[i] =
2548               CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, i);
2549             str->iso2022.force_charset_on_output[i] =
2550               CODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (str->codesys, i);
2551           }
2552         str->iso2022.register_left = 0;
2553         str->iso2022.register_right = 1;
2554         str->iso2022.current_charset = Qnil;
2555         str->iso2022.current_half = 0;
2556         break;
2557       }
2558     case CODESYS_CCL:
2559       setup_ccl_program (&str->ccl, CODING_SYSTEM_CCL_ENCODE (str->codesys));
2560       break;
2561     case CODESYS_UTF8:
2562       str->encode_char = &char_encode_utf8;
2563       str->finish = &char_finish_utf8;
2564     default:
2565       break;
2566     }
2567 #endif /* MULE */
2568   str->iso2022.current_char_boundary = 0;
2569   str->flags = str->ch = 0;
2570 }
2571
2572 static int
2573 encoding_rewinder (Lstream *stream)
2574 {
2575   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2576   reset_encoding_stream (str);
2577   Dynarr_reset (str->runoff);
2578   return Lstream_rewind (str->other_end);
2579 }
2580
2581 static int
2582 encoding_seekable_p (Lstream *stream)
2583 {
2584   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2585   return Lstream_seekable_p (str->other_end);
2586 }
2587
2588 static int
2589 encoding_flusher (Lstream *stream)
2590 {
2591   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2592   return Lstream_flush (str->other_end);
2593 }
2594
2595 static int
2596 encoding_closer (Lstream *stream)
2597 {
2598   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2599   if (stream->flags & LSTREAM_FL_WRITE)
2600     {
2601       str->flags |= CODING_STATE_END;
2602       encoding_writer (stream, 0, 0);
2603     }
2604   Dynarr_free (str->runoff);
2605   return Lstream_close (str->other_end);
2606 }
2607
2608 Lisp_Object
2609 encoding_stream_coding_system (Lstream *stream)
2610 {
2611   Lisp_Object coding_system;
2612   struct encoding_stream *str = ENCODING_STREAM_DATA (stream);
2613
2614   XSETCODING_SYSTEM (coding_system, str->codesys);
2615   return coding_system;
2616 }
2617
2618 void
2619 set_encoding_stream_coding_system (Lstream *lstr, Lisp_Object codesys)
2620 {
2621   Lisp_Coding_System *cs = XCODING_SYSTEM (codesys);
2622   struct encoding_stream *str = ENCODING_STREAM_DATA (lstr);
2623   str->codesys = cs;
2624   reset_encoding_stream (str);
2625 }
2626
2627 static Lisp_Object
2628 make_encoding_stream_1 (Lstream *stream, Lisp_Object codesys,
2629                         CONST char *mode)
2630 {
2631   Lstream *lstr = Lstream_new (lstream_encoding, mode);
2632   struct encoding_stream *str = ENCODING_STREAM_DATA (lstr);
2633   Lisp_Object obj;
2634
2635   xzero (*str);
2636   str->runoff = Dynarr_new (unsigned_char);
2637   str->other_end = stream;
2638   set_encoding_stream_coding_system (lstr, codesys);
2639   XSETLSTREAM (obj, lstr);
2640   return obj;
2641 }
2642
2643 Lisp_Object
2644 make_encoding_input_stream (Lstream *stream, Lisp_Object codesys)
2645 {
2646   return make_encoding_stream_1 (stream, codesys, "r");
2647 }
2648
2649 Lisp_Object
2650 make_encoding_output_stream (Lstream *stream, Lisp_Object codesys)
2651 {
2652   return make_encoding_stream_1 (stream, codesys, "w");
2653 }
2654
2655 /* Convert N bytes of internally-formatted data stored in SRC to an
2656    external format, according to the encoding stream ENCODING.
2657    Store the encoded data into DST. */
2658
2659 static void
2660 mule_encode (Lstream *encoding, CONST unsigned char *src,
2661              unsigned_char_dynarr *dst, unsigned int n)
2662 {
2663   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
2664
2665   switch (CODING_SYSTEM_TYPE (str->codesys))
2666     {
2667 #ifdef DEBUG_XEMACS
2668     case CODESYS_INTERNAL:
2669       Dynarr_add_many (dst, src, n);
2670       break;
2671 #endif
2672     case CODESYS_AUTODETECT:
2673       /* If we got this far and still haven't decided on the coding
2674          system, then do no conversion. */
2675     case CODESYS_NO_CONVERSION:
2676       encode_coding_no_conversion (encoding, src, dst, n);
2677       break;
2678 #ifdef MULE
2679     case CODESYS_SHIFT_JIS:
2680       encode_coding_sjis (encoding, src, dst, n);
2681       break;
2682     case CODESYS_BIG5:
2683       encode_coding_big5 (encoding, src, dst, n);
2684       break;
2685     case CODESYS_CCL:
2686       str->ccl.last_block = str->flags & CODING_STATE_END;
2687       ccl_driver (&str->ccl, src, dst, n, 0, CCL_MODE_ENCODING);
2688       break;
2689 #endif /* MULE */
2690     default:
2691       text_encode_generic (encoding, src, dst, n);
2692     }
2693 }
2694
2695 DEFUN ("encode-coding-region", Fencode_coding_region, 3, 4, 0, /*
2696 Encode the text between START and END using CODING-SYSTEM.
2697 This will, for example, convert Japanese characters into stuff such as
2698 "^[$B!<!+^[(B" if you use the JIS encoding.  Return length of encoded
2699 text.  BUFFER defaults to the current buffer if unspecified.
2700 */
2701        (start, end, coding_system, buffer))
2702 {
2703   Bufpos b, e;
2704   struct buffer *buf = decode_buffer (buffer, 0);
2705   Lisp_Object instream, lb_outstream, de_outstream, outstream;
2706   Lstream *istr, *ostr;
2707   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2708
2709   get_buffer_range_char (buf, start, end, &b, &e, 0);
2710
2711   barf_if_buffer_read_only (buf, b, e);
2712
2713   coding_system = Fget_coding_system (coding_system);
2714   instream  = make_lisp_buffer_input_stream  (buf, b, e, 0);
2715   lb_outstream = make_lisp_buffer_output_stream (buf, b, 0);
2716   de_outstream = make_decoding_output_stream (XLSTREAM (lb_outstream),
2717                                               Fget_coding_system (Qbinary));
2718   outstream = make_encoding_output_stream (XLSTREAM (de_outstream),
2719                                            coding_system);
2720   istr = XLSTREAM (instream);
2721   ostr = XLSTREAM (outstream);
2722   GCPRO4 (instream, outstream, de_outstream, lb_outstream);
2723   /* The chain of streams looks like this:
2724
2725      [BUFFER] <----- send through
2726                      ------> [ENCODE AS SPECIFIED]
2727                              ------> [DECODE AS BINARY]
2728                                      ------> [BUFFER]
2729    */
2730   while (1)
2731     {
2732       char tempbuf[1024]; /* some random amount */
2733       Bufpos newpos, even_newer_pos;
2734       Bufpos oldpos = lisp_buffer_stream_startpos (istr);
2735       int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
2736
2737       if (!size_in_bytes)
2738         break;
2739       newpos = lisp_buffer_stream_startpos (istr);
2740       Lstream_write (ostr, tempbuf, size_in_bytes);
2741       even_newer_pos = lisp_buffer_stream_startpos (istr);
2742       buffer_delete_range (buf, even_newer_pos - (newpos - oldpos),
2743                            even_newer_pos, 0);
2744     }
2745
2746   {
2747     Charcount retlen =
2748       lisp_buffer_stream_startpos (XLSTREAM (instream)) - b;
2749     Lstream_close (istr);
2750     Lstream_close (ostr);
2751     UNGCPRO;
2752     Lstream_delete (istr);
2753     Lstream_delete (ostr);
2754     Lstream_delete (XLSTREAM (de_outstream));
2755     Lstream_delete (XLSTREAM (lb_outstream));
2756     return make_int (retlen);
2757   }
2758 }
2759
2760 #ifdef MULE
2761 \f
2762 static void
2763 text_encode_generic (Lstream *encoding, CONST unsigned char *src,
2764                      unsigned_char_dynarr *dst, unsigned int n)
2765 {
2766   unsigned char c;
2767   unsigned char char_boundary;
2768   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
2769   unsigned int flags          = str->flags;
2770   Emchar ch                   = str->ch;
2771
2772   char_boundary = str->iso2022.current_char_boundary;
2773
2774   while (n--)
2775     {
2776       c = *src++;
2777
2778       switch (char_boundary)
2779         {
2780         case 0:
2781           if ( c >= 0xfc )
2782             {
2783               ch = c & 0x01;
2784               char_boundary = 5;
2785             }
2786           else if ( c >= 0xf8 )
2787             {
2788               ch = c & 0x03;
2789               char_boundary = 4;
2790             }
2791           else if ( c >= 0xf0 )
2792             {
2793               ch = c & 0x07;
2794               char_boundary = 3;
2795             }
2796           else if ( c >= 0xe0 )
2797             {
2798               ch = c & 0x0f;
2799               char_boundary = 2;
2800             }
2801           else if ( c >= 0xc0 )
2802             {
2803               ch = c & 0x1f;
2804               char_boundary = 1;
2805             }
2806           else
2807             {
2808               (*str->encode_char) (str, c, dst, &flags);
2809               ch = 0;
2810               char_boundary = 0;
2811             }
2812           break;
2813         case 1:
2814           (*str->encode_char) (str, (ch << 6) | (c & 0x3f), dst, &flags);
2815           ch =0;
2816           char_boundary = 0;
2817           break;
2818         default:
2819           ch = ( ch << 6 ) | ( c & 0x3f );
2820           char_boundary--;
2821         }
2822     }
2823
2824   if ( (char_boundary == 0) && flags & CODING_STATE_END)
2825     {
2826       (*str->finish) (str, dst, &flags);
2827     }
2828
2829   str->flags = flags;
2830   str->ch    = ch;
2831   str->iso2022.current_char_boundary = char_boundary;
2832
2833   /* Verbum caro factum est! */
2834 }
2835
2836 \f
2837 /************************************************************************/
2838 /*                          Shift-JIS methods                           */
2839 /************************************************************************/
2840
2841 /* Shift-JIS is a coding system encoding three character sets: ASCII, right
2842    half of JISX0201-Kana, and JISX0208.  An ASCII character is encoded
2843    as is.  A character of JISX0201-Kana (DIMENSION1_CHARS94 character set) is
2844    encoded by "position-code + 0x80".  A character of JISX0208
2845    (DIMENSION2_CHARS94 character set) is encoded in 2-byte but two
2846    position-codes are divided and shifted so that it fit in the range
2847    below.
2848
2849    --- CODE RANGE of Shift-JIS ---
2850    (character set)      (range)
2851    ASCII                0x00 .. 0x7F
2852    JISX0201-Kana        0xA0 .. 0xDF
2853    JISX0208 (1st byte)  0x80 .. 0x9F and 0xE0 .. 0xEF
2854             (2nd byte)  0x40 .. 0x7E and 0x80 .. 0xFC
2855    -------------------------------
2856
2857 */
2858
2859 /* Is this the first byte of a Shift-JIS two-byte char? */
2860
2861 #define BYTE_SJIS_TWO_BYTE_1_P(c) \
2862   (((c) >= 0x81 && (c) <= 0x9F) || ((c) >= 0xE0 && (c) <= 0xEF))
2863
2864 /* Is this the second byte of a Shift-JIS two-byte char? */
2865
2866 #define BYTE_SJIS_TWO_BYTE_2_P(c) \
2867   (((c) >= 0x40 && (c) <= 0x7E) || ((c) >= 0x80 && (c) <= 0xFC))
2868
2869 #define BYTE_SJIS_KATAKANA_P(c) \
2870   ((c) >= 0xA1 && (c) <= 0xDF)
2871
2872 static int
2873 detect_coding_sjis (struct detection_state *st, CONST unsigned char *src,
2874                     unsigned int n)
2875 {
2876   int c;
2877
2878   while (n--)
2879     {
2880       c = *src++;
2881       if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
2882         return 0;
2883       if (st->shift_jis.in_second_byte)
2884         {
2885           st->shift_jis.in_second_byte = 0;
2886           if (c < 0x40)
2887             return 0;
2888         }
2889       else if ((c >= 0x80 && c < 0xA0) || c >= 0xE0)
2890         st->shift_jis.in_second_byte = 1;
2891     }
2892   return CODING_CATEGORY_SHIFT_JIS_MASK;
2893 }
2894
2895 /* Convert Shift-JIS data to internal format. */
2896
2897 static void
2898 decode_coding_sjis (Lstream *decoding, CONST unsigned char *src,
2899                     unsigned_char_dynarr *dst, unsigned int n)
2900 {
2901   unsigned char c;
2902   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
2903   unsigned int flags  = str->flags;
2904   unsigned int ch     = str->ch;
2905   eol_type_t eol_type = str->eol_type;
2906
2907   while (n--)
2908     {
2909       c = *src++;
2910
2911       if (ch)
2912         {
2913           /* Previous character was first byte of Shift-JIS Kanji char. */
2914           if (BYTE_SJIS_TWO_BYTE_2_P (c))
2915             {
2916               unsigned char e1, e2;
2917
2918               DECODE_SJIS (ch, c, e1, e2);
2919 #ifdef UTF2000
2920               DECODE_ADD_UCS_CHAR(MAKE_CHAR(Vcharset_japanese_jisx0208,
2921                                             e1 & 0x7F,
2922                                             e2 & 0x7F), dst);
2923 #else
2924               Dynarr_add (dst, LEADING_BYTE_JAPANESE_JISX0208);
2925               Dynarr_add (dst, e1);
2926               Dynarr_add (dst, e2);
2927 #endif
2928             }
2929           else
2930             {
2931               DECODE_ADD_BINARY_CHAR (ch, dst);
2932               DECODE_ADD_BINARY_CHAR (c, dst);
2933             }
2934           ch = 0;
2935         }
2936       else
2937         {
2938           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
2939           if (BYTE_SJIS_TWO_BYTE_1_P (c))
2940             ch = c;
2941           else if (BYTE_SJIS_KATAKANA_P (c))
2942             {
2943 #ifdef UTF2000
2944               DECODE_ADD_UCS_CHAR(MAKE_CHAR(Vcharset_katakana_jisx0201,
2945                                             c & 0x7F, 0), dst);
2946 #else
2947               Dynarr_add (dst, LEADING_BYTE_KATAKANA_JISX0201);
2948               Dynarr_add (dst, c);
2949 #endif
2950             }
2951           else
2952             DECODE_ADD_BINARY_CHAR (c, dst);
2953         }
2954     label_continue_loop:;
2955     }
2956
2957   DECODE_HANDLE_END_OF_CONVERSION (flags, ch, dst);
2958
2959   str->flags = flags;
2960   str->ch    = ch;
2961 }
2962
2963 /* Convert internally-formatted data to Shift-JIS. */
2964
2965 static void
2966 encode_coding_sjis (Lstream *encoding, CONST unsigned char *src,
2967                     unsigned_char_dynarr *dst, unsigned int n)
2968 {
2969   unsigned char c;
2970   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
2971   unsigned int flags  = str->flags;
2972   unsigned int ch     = str->ch;
2973   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
2974 #ifdef UTF2000
2975   unsigned char char_boundary = str->iso2022.current_char_boundary;
2976 #endif
2977
2978   while (n--)
2979     {
2980       c = *src++;
2981 #ifdef UTF2000
2982       switch (char_boundary)
2983         {
2984         case 0:
2985           if ( c >= 0xfc )
2986             {
2987               ch = c & 0x01;
2988               char_boundary = 5;
2989             }
2990           else if ( c >= 0xf8 )
2991             {
2992               ch = c & 0x03;
2993               char_boundary = 4;
2994             }
2995           else if ( c >= 0xf0 )
2996             {
2997               ch = c & 0x07;
2998               char_boundary = 3;
2999             }
3000           else if ( c >= 0xe0 )
3001             {
3002               ch = c & 0x0f;
3003               char_boundary = 2;
3004             }
3005           else if ( c >= 0xc0 )
3006             {
3007               ch = c & 0x1f;
3008               char_boundary = 1;
3009             }
3010           else
3011             {
3012               ch = 0;
3013               if (c == '\n')
3014                 {
3015                   if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
3016                     Dynarr_add (dst, '\r');
3017                   if (eol_type != EOL_CR)
3018                     Dynarr_add (dst, c);
3019                 }
3020               else
3021                 Dynarr_add (dst, c);
3022               char_boundary = 0;
3023             }
3024           break;
3025         case 1:
3026           ch = ( ch << 6 ) | ( c & 0x3f );
3027           {
3028             Lisp_Object charset;
3029             unsigned int c1, c2, s1, s2;
3030             
3031             BREAKUP_CHAR (ch, charset, c1, c2);
3032             if (EQ(charset, Vcharset_katakana_jisx0201))
3033               {
3034                 Dynarr_add (dst, c1 | 0x80);
3035               }
3036             else if (EQ(charset, Vcharset_japanese_jisx0208))
3037               {
3038                 ENCODE_SJIS (c1 | 0x80, c2 | 0x80, s1, s2);
3039                 Dynarr_add (dst, s1);
3040                 Dynarr_add (dst, s2);
3041               }
3042           }
3043           char_boundary = 0;
3044           break;
3045         default:
3046           ch = ( ch << 6 ) | ( c & 0x3f );
3047           char_boundary--;
3048         }
3049 #else
3050       if (c == '\n')
3051         {
3052           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
3053             Dynarr_add (dst, '\r');
3054           if (eol_type != EOL_CR)
3055             Dynarr_add (dst, '\n');
3056           ch = 0;
3057         }
3058       else if (BYTE_ASCII_P (c))
3059         {
3060           Dynarr_add (dst, c);
3061           ch = 0;
3062         }
3063       else if (BUFBYTE_LEADING_BYTE_P (c))
3064         ch = (c == LEADING_BYTE_KATAKANA_JISX0201 ||
3065               c == LEADING_BYTE_JAPANESE_JISX0208_1978 ||
3066               c == LEADING_BYTE_JAPANESE_JISX0208) ? c : 0;
3067       else if (ch)
3068         {
3069           if (ch == LEADING_BYTE_KATAKANA_JISX0201)
3070             {
3071               Dynarr_add (dst, c);
3072               ch = 0;
3073             }
3074           else if (ch == LEADING_BYTE_JAPANESE_JISX0208_1978 ||
3075                    ch == LEADING_BYTE_JAPANESE_JISX0208)
3076             ch = c;
3077           else
3078             {
3079               unsigned char j1, j2;
3080               ENCODE_SJIS (ch, c, j1, j2);
3081               Dynarr_add (dst, j1);
3082               Dynarr_add (dst, j2);
3083               ch = 0;
3084             }
3085         }
3086 #endif
3087     }
3088
3089   str->flags = flags;
3090   str->ch    = ch;
3091 #ifdef UTF2000
3092   str->iso2022.current_char_boundary = char_boundary;
3093 #endif
3094 }
3095
3096 DEFUN ("decode-shift-jis-char", Fdecode_shift_jis_char, 1, 1, 0, /*
3097 Decode a JISX0208 character of Shift-JIS coding-system.
3098 CODE is the character code in Shift-JIS as a cons of type bytes.
3099 Return the corresponding character.
3100 */
3101        (code))
3102 {
3103   unsigned char c1, c2, s1, s2;
3104
3105   CHECK_CONS (code);
3106   CHECK_INT (XCAR (code));
3107   CHECK_INT (XCDR (code));
3108   s1 = XINT (XCAR (code));
3109   s2 = XINT (XCDR (code));
3110   if (BYTE_SJIS_TWO_BYTE_1_P (s1) &&
3111       BYTE_SJIS_TWO_BYTE_2_P (s2))
3112     {
3113       DECODE_SJIS (s1, s2, c1, c2);
3114       return make_char (MAKE_CHAR (Vcharset_japanese_jisx0208,
3115                                    c1 & 0x7F, c2 & 0x7F));
3116     }
3117   else
3118     return Qnil;
3119 }
3120
3121 DEFUN ("encode-shift-jis-char", Fencode_shift_jis_char, 1, 1, 0, /*
3122 Encode a JISX0208 character CHAR to SHIFT-JIS coding-system.
3123 Return the corresponding character code in SHIFT-JIS as a cons of two bytes.
3124 */
3125        (ch))
3126 {
3127   Lisp_Object charset;
3128   int c1, c2, s1, s2;
3129
3130   CHECK_CHAR_COERCE_INT (ch);
3131   BREAKUP_CHAR (XCHAR (ch), charset, c1, c2);
3132   if (EQ (charset, Vcharset_japanese_jisx0208))
3133     {
3134       ENCODE_SJIS (c1 | 0x80, c2 | 0x80, s1, s2);
3135       return Fcons (make_int (s1), make_int (s2));
3136     }
3137   else
3138     return Qnil;
3139 }
3140
3141 \f
3142 /************************************************************************/
3143 /*                            Big5 methods                              */
3144 /************************************************************************/
3145
3146 /* BIG5 is a coding system encoding two character sets: ASCII and
3147    Big5.  An ASCII character is encoded as is.  Big5 is a two-byte
3148    character set and is encoded in two-byte.
3149
3150    --- CODE RANGE of BIG5 ---
3151    (character set)      (range)
3152    ASCII                0x00 .. 0x7F
3153    Big5 (1st byte)      0xA1 .. 0xFE
3154         (2nd byte)      0x40 .. 0x7E and 0xA1 .. 0xFE
3155    --------------------------
3156
3157    Since the number of characters in Big5 is larger than maximum
3158    characters in Emacs' charset (96x96), it can't be handled as one
3159    charset.  So, in Emacs, Big5 is divided into two: `charset-big5-1'
3160    and `charset-big5-2'.  Both <type>s are DIMENSION2_CHARS94.  The former
3161    contains frequently used characters and the latter contains less
3162    frequently used characters.  */
3163
3164 #define BYTE_BIG5_TWO_BYTE_1_P(c) \
3165   ((c) >= 0xA1 && (c) <= 0xFE)
3166
3167 /* Is this the second byte of a Shift-JIS two-byte char? */
3168
3169 #define BYTE_BIG5_TWO_BYTE_2_P(c) \
3170   (((c) >= 0x40 && (c) <= 0x7E) || ((c) >= 0xA1 && (c) <= 0xFE))
3171
3172 /* Number of Big5 characters which have the same code in 1st byte.  */
3173
3174 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
3175
3176 /* Code conversion macros.  These are macros because they are used in
3177    inner loops during code conversion.
3178
3179    Note that temporary variables in macros introduce the classic
3180    dynamic-scoping problems with variable names.  We use capital-
3181    lettered variables in the assumption that XEmacs does not use
3182    capital letters in variables except in a very formalized way
3183    (e.g. Qstring). */
3184
3185 /* Convert Big5 code (b1, b2) into its internal string representation
3186    (lb, c1, c2). */
3187
3188 /* There is a much simpler way to split the Big5 charset into two.
3189    For the moment I'm going to leave the algorithm as-is because it
3190    claims to separate out the most-used characters into a single
3191    charset, which perhaps will lead to optimizations in various
3192    places.
3193
3194    The way the algorithm works is something like this:
3195
3196    Big5 can be viewed as a 94x157 charset, where the row is
3197    encoded into the bytes 0xA1 .. 0xFE and the column is encoded
3198    into the bytes 0x40 .. 0x7E and 0xA1 .. 0xFE.  As for frequency,
3199    the split between low and high column numbers is apparently
3200    meaningless; ascending rows produce less and less frequent chars.
3201    Therefore, we assign the lower half of rows (0xA1 .. 0xC8) to
3202    the first charset, and the upper half (0xC9 .. 0xFE) to the
3203    second.  To do the conversion, we convert the character into
3204    a single number where 0 .. 156 is the first row, 157 .. 313
3205    is the second, etc.  That way, the characters are ordered by
3206    decreasing frequency.  Then we just chop the space in two
3207    and coerce the result into a 94x94 space.
3208    */
3209
3210 #define DECODE_BIG5(b1, b2, lb, c1, c2) do                              \
3211 {                                                                       \
3212   int B1 = b1, B2 = b2;                                                 \
3213   unsigned int I                                                        \
3214     = (B1 - 0xA1) * BIG5_SAME_ROW + B2 - (B2 < 0x7F ? 0x40 : 0x62);     \
3215                                                                         \
3216   if (B1 < 0xC9)                                                        \
3217     {                                                                   \
3218       lb = LEADING_BYTE_CHINESE_BIG5_1;                                 \
3219     }                                                                   \
3220   else                                                                  \
3221     {                                                                   \
3222       lb = LEADING_BYTE_CHINESE_BIG5_2;                                 \
3223       I -= (BIG5_SAME_ROW) * (0xC9 - 0xA1);                             \
3224     }                                                                   \
3225   c1 = I / (0xFF - 0xA1) + 0xA1;                                        \
3226   c2 = I % (0xFF - 0xA1) + 0xA1;                                        \
3227 } while (0)
3228
3229 /* Convert the internal string representation of a Big5 character
3230    (lb, c1, c2) into Big5 code (b1, b2). */
3231
3232 #define ENCODE_BIG5(lb, c1, c2, b1, b2) do                              \
3233 {                                                                       \
3234   unsigned int I = ((c1) - 0xA1) * (0xFF - 0xA1) + ((c2) - 0xA1);       \
3235                                                                         \
3236   if (lb == LEADING_BYTE_CHINESE_BIG5_2)                                \
3237     {                                                                   \
3238       I += BIG5_SAME_ROW * (0xC9 - 0xA1);                               \
3239     }                                                                   \
3240   b1 = I / BIG5_SAME_ROW + 0xA1;                                        \
3241   b2 = I % BIG5_SAME_ROW;                                               \
3242   b2 += b2 < 0x3F ? 0x40 : 0x62;                                        \
3243 } while (0)
3244
3245 static int
3246 detect_coding_big5 (struct detection_state *st, CONST unsigned char *src,
3247                     unsigned int n)
3248 {
3249   int c;
3250
3251   while (n--)
3252     {
3253       c = *src++;
3254       if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO ||
3255           (c >= 0x80 && c <= 0xA0))
3256         return 0;
3257       if (st->big5.in_second_byte)
3258         {
3259           st->big5.in_second_byte = 0;
3260           if (c < 0x40 || (c >= 0x80 && c <= 0xA0))
3261             return 0;
3262         }
3263       else if (c >= 0xA1)
3264         st->big5.in_second_byte = 1;
3265     }
3266   return CODING_CATEGORY_BIG5_MASK;
3267 }
3268
3269 /* Convert Big5 data to internal format. */
3270
3271 static void
3272 decode_coding_big5 (Lstream *decoding, CONST unsigned char *src,
3273                     unsigned_char_dynarr *dst, unsigned int n)
3274 {
3275   unsigned char c;
3276   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
3277   unsigned int flags  = str->flags;
3278   unsigned int ch     = str->ch;
3279   eol_type_t eol_type = str->eol_type;
3280
3281   while (n--)
3282     {
3283       c = *src++;
3284       if (ch)
3285         {
3286           /* Previous character was first byte of Big5 char. */
3287           if (BYTE_BIG5_TWO_BYTE_2_P (c))
3288             {
3289               unsigned char b1, b2, b3;
3290               DECODE_BIG5 (ch, c, b1, b2, b3);
3291               Dynarr_add (dst, b1);
3292               Dynarr_add (dst, b2);
3293               Dynarr_add (dst, b3);
3294             }
3295           else
3296             {
3297               DECODE_ADD_BINARY_CHAR (ch, dst);
3298               DECODE_ADD_BINARY_CHAR (c, dst);
3299             }
3300           ch = 0;
3301         }
3302       else
3303         {
3304           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
3305           if (BYTE_BIG5_TWO_BYTE_1_P (c))
3306             ch = c;
3307           else
3308             DECODE_ADD_BINARY_CHAR (c, dst);
3309         }
3310     label_continue_loop:;
3311     }
3312
3313   DECODE_HANDLE_END_OF_CONVERSION (flags, ch, dst);
3314
3315   str->flags = flags;
3316   str->ch    = ch;
3317 }
3318
3319 /* Convert internally-formatted data to Big5. */
3320
3321 static void
3322 encode_coding_big5 (Lstream *encoding, CONST unsigned char *src,
3323                     unsigned_char_dynarr *dst, unsigned int n)
3324 {
3325 #ifndef UTF2000
3326   unsigned char c;
3327   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
3328   unsigned int flags  = str->flags;
3329   unsigned int ch     = str->ch;
3330   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
3331
3332   while (n--)
3333     {
3334       c = *src++;
3335       if (c == '\n')
3336         {
3337           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
3338             Dynarr_add (dst, '\r');
3339           if (eol_type != EOL_CR)
3340             Dynarr_add (dst, '\n');
3341         }
3342       else if (BYTE_ASCII_P (c))
3343         {
3344           /* ASCII. */
3345           Dynarr_add (dst, c);
3346         }
3347       else if (BUFBYTE_LEADING_BYTE_P (c))
3348         {
3349           if (c == LEADING_BYTE_CHINESE_BIG5_1 ||
3350               c == LEADING_BYTE_CHINESE_BIG5_2)
3351             {
3352               /* A recognized leading byte. */
3353               ch = c;
3354               continue; /* not done with this character. */
3355             }
3356           /* otherwise just ignore this character. */
3357         }
3358       else if (ch == LEADING_BYTE_CHINESE_BIG5_1 ||
3359                ch == LEADING_BYTE_CHINESE_BIG5_2)
3360         {
3361           /* Previous char was a recognized leading byte. */
3362           ch = (ch << 8) | c;
3363           continue; /* not done with this character. */
3364         }
3365       else if (ch)
3366         {
3367           /* Encountering second byte of a Big5 character. */
3368           unsigned char b1, b2;
3369
3370           ENCODE_BIG5 (ch >> 8, ch & 0xFF, c, b1, b2);
3371           Dynarr_add (dst, b1);
3372           Dynarr_add (dst, b2);
3373         }
3374
3375       ch = 0;
3376     }
3377
3378   str->flags = flags;
3379   str->ch    = ch;
3380 #endif
3381 }
3382
3383
3384 DEFUN ("decode-big5-char", Fdecode_big5_char, 1, 1, 0, /*
3385 Decode a Big5 character CODE of BIG5 coding-system.
3386 CODE is the character code in BIG5, a cons of two integers.
3387 Return the corresponding character.
3388 */
3389        (code))
3390 {
3391   unsigned char c1, c2, b1, b2;
3392
3393   CHECK_CONS (code);
3394   CHECK_INT (XCAR (code));
3395   CHECK_INT (XCDR (code));
3396   b1 = XINT (XCAR (code));
3397   b2 = XINT (XCDR (code));
3398   if (BYTE_BIG5_TWO_BYTE_1_P (b1) &&
3399       BYTE_BIG5_TWO_BYTE_2_P (b2))
3400     {
3401       Charset_ID leading_byte;
3402       Lisp_Object charset;
3403       DECODE_BIG5 (b1, b2, leading_byte, c1, c2);
3404       charset = CHARSET_BY_LEADING_BYTE (leading_byte);
3405       return make_char (MAKE_CHAR (charset, c1 & 0x7F, c2 & 0x7F));
3406     }
3407   else
3408     return Qnil;
3409 }
3410
3411 DEFUN ("encode-big5-char", Fencode_big5_char, 1, 1, 0, /*
3412 Encode the Big5 character CH to BIG5 coding-system.
3413 Return the corresponding character code in Big5.
3414 */
3415        (ch))
3416 {
3417   Lisp_Object charset;
3418   int c1, c2, b1, b2;
3419
3420   CHECK_CHAR_COERCE_INT (ch);
3421   BREAKUP_CHAR (XCHAR (ch), charset, c1, c2);
3422   if (EQ (charset, Vcharset_chinese_big5_1) ||
3423       EQ (charset, Vcharset_chinese_big5_2))
3424     {
3425       ENCODE_BIG5 (XCHARSET_LEADING_BYTE (charset), c1 | 0x80, c2 | 0x80,
3426                    b1, b2);
3427       return Fcons (make_int (b1), make_int (b2));
3428     }
3429   else
3430     return Qnil;
3431 }
3432
3433 \f
3434 /************************************************************************/
3435 /*                           UCS-4 methods                              */
3436 /************************************************************************/
3437
3438 static int
3439 detect_coding_ucs4 (struct detection_state *st, CONST unsigned char *src,
3440                     unsigned int n)
3441 {
3442   while (n--)
3443     {
3444       int c = *src++;
3445       switch (st->ucs4.in_byte)
3446         {
3447         case 0:
3448           if (c >= 128)
3449             return 0;
3450           else
3451             st->ucs4.in_byte++;
3452           break;
3453         case 3:
3454           st->ucs4.in_byte = 0;
3455           break;
3456         default:
3457           st->ucs4.in_byte++;
3458         }
3459     }
3460   return CODING_CATEGORY_UCS4_MASK;
3461 }
3462
3463 static void
3464 decode_coding_ucs4 (Lstream *decoding, CONST unsigned char *src,
3465                     unsigned_char_dynarr *dst, unsigned int n)
3466 {
3467   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
3468   unsigned int flags = str->flags;
3469   unsigned int ch    = str->ch;
3470   unsigned char counter = str->counter;
3471
3472   while (n--)
3473     {
3474       unsigned char c = *src++;
3475       switch (counter)
3476         {
3477         case 0:
3478           ch = c;
3479           counter = 3;
3480           break;
3481         case 1:
3482           DECODE_ADD_UCS_CHAR ((ch << 8) | c, dst);
3483           ch = 0;
3484           counter = 0;
3485           break;
3486         default:
3487           ch = ( ch << 8 ) | c;
3488           counter--;
3489         }
3490     }
3491   if (counter & CODING_STATE_END)
3492     DECODE_OUTPUT_PARTIAL_CHAR (ch);
3493
3494   str->flags = flags;
3495   str->ch    = ch;
3496   str->counter = counter;
3497 }
3498
3499 void
3500 char_encode_ucs4 (struct encoding_stream *str, Emchar ch,
3501                   unsigned_char_dynarr *dst, unsigned int *flags)
3502 {
3503   Dynarr_add (dst,  ch >> 24);
3504   Dynarr_add (dst, (ch >> 16) & 255);
3505   Dynarr_add (dst, (ch >>  8) & 255);
3506   Dynarr_add (dst,  ch        & 255);
3507 }
3508
3509 void
3510 char_finish_ucs4 (struct encoding_stream *str, unsigned_char_dynarr *dst,
3511                   unsigned int *flags)
3512 {
3513 }
3514
3515 \f
3516 /************************************************************************/
3517 /*                           UTF-8 methods                              */
3518 /************************************************************************/
3519
3520 static int
3521 detect_coding_utf8 (struct detection_state *st, CONST unsigned char *src,
3522                     unsigned int n)
3523 {
3524   while (n--)
3525     {
3526       unsigned char c = *src++;
3527       switch (st->utf8.in_byte)
3528         {
3529         case 0:
3530           if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
3531             return 0;
3532           else if (c >= 0xfc)
3533             st->utf8.in_byte = 5;
3534           else if (c >= 0xf8)
3535             st->utf8.in_byte = 4;
3536           else if (c >= 0xf0)
3537             st->utf8.in_byte = 3;
3538           else if (c >= 0xe0)
3539             st->utf8.in_byte = 2;
3540           else if (c >= 0xc0)
3541             st->utf8.in_byte = 1;
3542           else if (c >= 0x80)
3543             return 0;
3544           break;
3545         default:
3546           if ((c & 0xc0) != 0x80)
3547             return 0;
3548           else
3549             st->utf8.in_byte--;
3550         }
3551     }
3552   return CODING_CATEGORY_UTF8_MASK;
3553 }
3554
3555 static void
3556 decode_coding_utf8 (Lstream *decoding, CONST unsigned char *src,
3557                     unsigned_char_dynarr *dst, unsigned int n)
3558 {
3559   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
3560   unsigned int flags  = str->flags;
3561   unsigned int ch     = str->ch;
3562   eol_type_t eol_type = str->eol_type;
3563   unsigned char counter = str->counter;
3564
3565   while (n--)
3566     {
3567       unsigned char c = *src++;
3568       switch (counter)
3569         {
3570         case 0:
3571           if ( c >= 0xfc )
3572             {
3573               ch = c & 0x01;
3574               counter = 5;
3575             }
3576           else if ( c >= 0xf8 )
3577             {
3578               ch = c & 0x03;
3579               counter = 4;
3580             }
3581           else if ( c >= 0xf0 )
3582             {
3583               ch = c & 0x07;
3584               counter = 3;
3585             }
3586           else if ( c >= 0xe0 )
3587             {
3588               ch = c & 0x0f;
3589               counter = 2;
3590             }
3591           else if ( c >= 0xc0 )
3592             {
3593               ch = c & 0x1f;
3594               counter = 1;
3595             }
3596           else
3597             {
3598               DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
3599               DECODE_ADD_UCS_CHAR (c, dst);
3600             }
3601           break;
3602         case 1:
3603           ch = ( ch << 6 ) | ( c & 0x3f );
3604           DECODE_ADD_UCS_CHAR (ch, dst);
3605           ch = 0;
3606           counter = 0;
3607           break;
3608         default:
3609           ch = ( ch << 6 ) | ( c & 0x3f );
3610           counter--;
3611         }
3612     label_continue_loop:;
3613     }
3614
3615   if (flags & CODING_STATE_END)
3616     DECODE_OUTPUT_PARTIAL_CHAR (ch);
3617
3618   str->flags = flags;
3619   str->ch    = ch;
3620   str->counter = counter;
3621 }
3622
3623 void
3624 char_encode_utf8 (struct encoding_stream *str, Emchar code,
3625                   unsigned_char_dynarr *dst, unsigned int *flags)
3626 {
3627   if ( code <= 0x7f )
3628     {
3629       Dynarr_add (dst, code);
3630     }
3631   else if ( code <= 0x7ff )
3632     {
3633       Dynarr_add (dst, (code >> 6) | 0xc0);
3634       Dynarr_add (dst, (code & 0x3f) | 0x80);
3635     }
3636   else if ( code <= 0xffff )
3637     {
3638       Dynarr_add (dst,  (code >> 12) | 0xe0);
3639       Dynarr_add (dst, ((code >>  6) & 0x3f) | 0x80);
3640       Dynarr_add (dst,  (code        & 0x3f) | 0x80);
3641     }
3642   else if ( code <= 0x1fffff )
3643     {
3644       Dynarr_add (dst,  (code >> 18) | 0xf0);
3645       Dynarr_add (dst, ((code >> 12) & 0x3f) | 0x80);
3646       Dynarr_add (dst, ((code >>  6) & 0x3f) | 0x80);
3647       Dynarr_add (dst,  (code        & 0x3f) | 0x80);
3648     }
3649   else if ( code <= 0x3ffffff )
3650     {
3651       Dynarr_add (dst,  (code >> 24) | 0xf8);
3652       Dynarr_add (dst, ((code >> 18) & 0x3f) | 0x80);
3653       Dynarr_add (dst, ((code >> 12) & 0x3f) | 0x80);
3654       Dynarr_add (dst, ((code >>  6) & 0x3f) | 0x80);
3655       Dynarr_add (dst,  (code        & 0x3f) | 0x80);
3656     }
3657   else
3658     {
3659       Dynarr_add (dst,  (code >> 30) | 0xfc);
3660       Dynarr_add (dst, ((code >> 24) & 0x3f) | 0x80);
3661       Dynarr_add (dst, ((code >> 18) & 0x3f) | 0x80);
3662       Dynarr_add (dst, ((code >> 12) & 0x3f) | 0x80);
3663       Dynarr_add (dst, ((code >>  6) & 0x3f) | 0x80);
3664       Dynarr_add (dst,  (code        & 0x3f) | 0x80);
3665     }
3666 }
3667
3668 void
3669 char_finish_utf8 (struct encoding_stream *str, unsigned_char_dynarr *dst,
3670                   unsigned int *flags)
3671 {
3672 }
3673
3674 \f
3675 /************************************************************************/
3676 /*                           ISO2022 methods                            */
3677 /************************************************************************/
3678
3679 /* The following note describes the coding system ISO2022 briefly.
3680    Since the intention of this note is to help understand the
3681    functions in this file, some parts are NOT ACCURATE or OVERLY
3682    SIMPLIFIED.  For thorough understanding, please refer to the
3683    original document of ISO2022.
3684
3685    ISO2022 provides many mechanisms to encode several character sets
3686    in 7-bit and 8-bit environments.  For 7-bit environments, all text
3687    is encoded using bytes less than 128.  This may make the encoded
3688    text a little bit longer, but the text passes more easily through
3689    several gateways, some of which strip off MSB (Most Signigant Bit).
3690
3691    There are two kinds of character sets: control character set and
3692    graphic character set.  The former contains control characters such
3693    as `newline' and `escape' to provide control functions (control
3694    functions are also provided by escape sequences).  The latter
3695    contains graphic characters such as 'A' and '-'.  Emacs recognizes
3696    two control character sets and many graphic character sets.
3697
3698    Graphic character sets are classified into one of the following
3699    four classes, according to the number of bytes (DIMENSION) and
3700    number of characters in one dimension (CHARS) of the set:
3701    - DIMENSION1_CHARS94
3702    - DIMENSION1_CHARS96
3703    - DIMENSION2_CHARS94
3704    - DIMENSION2_CHARS96
3705
3706    In addition, each character set is assigned an identification tag,
3707    unique for each set, called "final character" (denoted as <F>
3708    hereafter).  The <F> of each character set is decided by ECMA(*)
3709    when it is registered in ISO.  The code range of <F> is 0x30..0x7F
3710    (0x30..0x3F are for private use only).
3711
3712    Note (*): ECMA = European Computer Manufacturers Association
3713
3714    Here are examples of graphic character set [NAME(<F>)]:
3715         o DIMENSION1_CHARS94 -- ASCII('B'), right-half-of-JISX0201('I'), ...
3716         o DIMENSION1_CHARS96 -- right-half-of-ISO8859-1('A'), ...
3717         o DIMENSION2_CHARS94 -- GB2312('A'), JISX0208('B'), ...
3718         o DIMENSION2_CHARS96 -- none for the moment
3719
3720    A code area (1 byte = 8 bits) is divided into 4 areas, C0, GL, C1, and GR.
3721         C0 [0x00..0x1F] -- control character plane 0
3722         GL [0x20..0x7F] -- graphic character plane 0
3723         C1 [0x80..0x9F] -- control character plane 1
3724         GR [0xA0..0xFF] -- graphic character plane 1
3725
3726    A control character set is directly designated and invoked to C0 or
3727    C1 by an escape sequence.  The most common case is that:
3728    - ISO646's  control character set is designated/invoked to C0, and
3729    - ISO6429's control character set is designated/invoked to C1,
3730    and usually these designations/invocations are omitted in encoded
3731    text.  In a 7-bit environment, only C0 can be used, and a control
3732    character for C1 is encoded by an appropriate escape sequence to
3733    fit into the environment.  All control characters for C1 are
3734    defined to have corresponding escape sequences.
3735
3736    A graphic character set is at first designated to one of four
3737    graphic registers (G0 through G3), then these graphic registers are
3738    invoked to GL or GR.  These designations and invocations can be
3739    done independently.  The most common case is that G0 is invoked to
3740    GL, G1 is invoked to GR, and ASCII is designated to G0.  Usually
3741    these invocations and designations are omitted in encoded text.
3742    In a 7-bit environment, only GL can be used.
3743
3744    When a graphic character set of CHARS94 is invoked to GL, codes
3745    0x20 and 0x7F of the GL area work as control characters SPACE and
3746    DEL respectively, and codes 0xA0 and 0xFF of the GR area should not
3747    be used.
3748
3749    There are two ways of invocation: locking-shift and single-shift.
3750    With locking-shift, the invocation lasts until the next different
3751    invocation, whereas with single-shift, the invocation affects the
3752    following character only and doesn't affect the locking-shift
3753    state.  Invocations are done by the following control characters or
3754    escape sequences:
3755
3756    ----------------------------------------------------------------------
3757    abbrev  function                  cntrl escape seq   description
3758    ----------------------------------------------------------------------
3759    SI/LS0  (shift-in)                0x0F  none         invoke G0 into GL
3760    SO/LS1  (shift-out)               0x0E  none         invoke G1 into GL
3761    LS2     (locking-shift-2)         none  ESC 'n'      invoke G2 into GL
3762    LS3     (locking-shift-3)         none  ESC 'o'      invoke G3 into GL
3763    LS1R    (locking-shift-1 right)   none  ESC '~'      invoke G1 into GR (*)
3764    LS2R    (locking-shift-2 right)   none  ESC '}'      invoke G2 into GR (*)
3765    LS3R    (locking-shift 3 right)   none  ESC '|'      invoke G3 into GR (*)
3766    SS2     (single-shift-2)          0x8E  ESC 'N'      invoke G2 for one char
3767    SS3     (single-shift-3)          0x8F  ESC 'O'      invoke G3 for one char
3768    ----------------------------------------------------------------------
3769    (*) These are not used by any known coding system.
3770
3771    Control characters for these functions are defined by macros
3772    ISO_CODE_XXX in `coding.h'.
3773
3774    Designations are done by the following escape sequences:
3775    ----------------------------------------------------------------------
3776    escape sequence      description
3777    ----------------------------------------------------------------------
3778    ESC '(' <F>          designate DIMENSION1_CHARS94<F> to G0
3779    ESC ')' <F>          designate DIMENSION1_CHARS94<F> to G1
3780    ESC '*' <F>          designate DIMENSION1_CHARS94<F> to G2
3781    ESC '+' <F>          designate DIMENSION1_CHARS94<F> to G3
3782    ESC ',' <F>          designate DIMENSION1_CHARS96<F> to G0 (*)
3783    ESC '-' <F>          designate DIMENSION1_CHARS96<F> to G1
3784    ESC '.' <F>          designate DIMENSION1_CHARS96<F> to G2
3785    ESC '/' <F>          designate DIMENSION1_CHARS96<F> to G3
3786    ESC '$' '(' <F>      designate DIMENSION2_CHARS94<F> to G0 (**)
3787    ESC '$' ')' <F>      designate DIMENSION2_CHARS94<F> to G1
3788    ESC '$' '*' <F>      designate DIMENSION2_CHARS94<F> to G2
3789    ESC '$' '+' <F>      designate DIMENSION2_CHARS94<F> to G3
3790    ESC '$' ',' <F>      designate DIMENSION2_CHARS96<F> to G0 (*)
3791    ESC '$' '-' <F>      designate DIMENSION2_CHARS96<F> to G1
3792    ESC '$' '.' <F>      designate DIMENSION2_CHARS96<F> to G2
3793    ESC '$' '/' <F>      designate DIMENSION2_CHARS96<F> to G3
3794    ----------------------------------------------------------------------
3795
3796    In this list, "DIMENSION1_CHARS94<F>" means a graphic character set
3797    of dimension 1, chars 94, and final character <F>, etc...
3798
3799    Note (*): Although these designations are not allowed in ISO2022,
3800    Emacs accepts them on decoding, and produces them on encoding
3801    CHARS96 character sets in a coding system which is characterized as
3802    7-bit environment, non-locking-shift, and non-single-shift.
3803
3804    Note (**): If <F> is '@', 'A', or 'B', the intermediate character
3805    '(' can be omitted.  We refer to this as "short-form" hereafter.
3806
3807    Now you may notice that there are a lot of ways for encoding the
3808    same multilingual text in ISO2022.  Actually, there exist many
3809    coding systems such as Compound Text (used in X11's inter client
3810    communication, ISO-2022-JP (used in Japanese internet), ISO-2022-KR
3811    (used in Korean internet), EUC (Extended UNIX Code, used in Asian
3812    localized platforms), and all of these are variants of ISO2022.
3813
3814    In addition to the above, Emacs handles two more kinds of escape
3815    sequences: ISO6429's direction specification and Emacs' private
3816    sequence for specifying character composition.
3817
3818    ISO6429's direction specification takes the following form:
3819         o CSI ']'      -- end of the current direction
3820         o CSI '0' ']'  -- end of the current direction
3821         o CSI '1' ']'  -- start of left-to-right text
3822         o CSI '2' ']'  -- start of right-to-left text
3823    The control character CSI (0x9B: control sequence introducer) is
3824    abbreviated to the escape sequence ESC '[' in a 7-bit environment.
3825
3826    Character composition specification takes the following form:
3827         o ESC '0' -- start character composition
3828         o ESC '1' -- end character composition
3829    Since these are not standard escape sequences of any ISO standard,
3830    their use with these meanings is restricted to Emacs only.  */
3831
3832 static void
3833 reset_iso2022 (Lisp_Object coding_system, struct iso2022_decoder *iso)
3834 {
3835   int i;
3836
3837   for (i = 0; i < 4; i++)
3838     {
3839       if (!NILP (coding_system))
3840         iso->charset[i] =
3841           XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, i);
3842       else
3843         iso->charset[i] = Qt;
3844       iso->invalid_designated[i] = 0;
3845     }
3846   iso->esc = ISO_ESC_NOTHING;
3847   iso->esc_bytes_index = 0;
3848   iso->register_left = 0;
3849   iso->register_right = 1;
3850   iso->switched_dir_and_no_valid_charset_yet = 0;
3851   iso->invalid_switch_dir = 0;
3852   iso->output_direction_sequence = 0;
3853   iso->output_literally = 0;
3854 #ifdef ENABLE_COMPOSITE_CHARS
3855   if (iso->composite_chars)
3856     Dynarr_reset (iso->composite_chars);
3857 #endif
3858 }
3859
3860 static int
3861 fit_to_be_escape_quoted (unsigned char c)
3862 {
3863   switch (c)
3864     {
3865     case ISO_CODE_ESC:
3866     case ISO_CODE_CSI:
3867     case ISO_CODE_SS2:
3868     case ISO_CODE_SS3:
3869     case ISO_CODE_SO:
3870     case ISO_CODE_SI:
3871       return 1;
3872
3873     default:
3874       return 0;
3875     }
3876 }
3877
3878 /* Parse one byte of an ISO2022 escape sequence.
3879    If the result is an invalid escape sequence, return 0 and
3880    do not change anything in STR.  Otherwise, if the result is
3881    an incomplete escape sequence, update ISO2022.ESC and
3882    ISO2022.ESC_BYTES and return -1.  Otherwise, update
3883    all the state variables (but not ISO2022.ESC_BYTES) and
3884    return 1.
3885
3886    If CHECK_INVALID_CHARSETS is non-zero, check for designation
3887    or invocation of an invalid character set and treat that as
3888    an unrecognized escape sequence. */
3889
3890 static int
3891 parse_iso2022_esc (Lisp_Object codesys, struct iso2022_decoder *iso,
3892                    unsigned char c, unsigned int *flags,
3893                    int check_invalid_charsets)
3894 {
3895   /* (1) If we're at the end of a designation sequence, CS is the
3896      charset being designated and REG is the register to designate
3897      it to.
3898
3899      (2) If we're at the end of a locking-shift sequence, REG is
3900      the register to invoke and HALF (0 == left, 1 == right) is
3901      the half to invoke it into.
3902
3903      (3) If we're at the end of a single-shift sequence, REG is
3904      the register to invoke. */
3905   Lisp_Object cs = Qnil;
3906   int reg, half;
3907
3908   /* NOTE: This code does goto's all over the fucking place.
3909      The reason for this is that we're basically implementing
3910      a state machine here, and hierarchical languages like C
3911      don't really provide a clean way of doing this. */
3912
3913   if (! (*flags & CODING_STATE_ESCAPE))
3914     /* At beginning of escape sequence; we need to reset our
3915        escape-state variables. */
3916     iso->esc = ISO_ESC_NOTHING;
3917
3918   iso->output_literally = 0;
3919   iso->output_direction_sequence = 0;
3920
3921   switch (iso->esc)
3922     {
3923     case ISO_ESC_NOTHING:
3924       iso->esc_bytes_index = 0;
3925       switch (c)
3926         {
3927         case ISO_CODE_ESC:      /* Start escape sequence */
3928           *flags |= CODING_STATE_ESCAPE;
3929           iso->esc = ISO_ESC;
3930           goto not_done;
3931
3932         case ISO_CODE_CSI:      /* ISO6429 (specifying directionality) */
3933           *flags |= CODING_STATE_ESCAPE;
3934           iso->esc = ISO_ESC_5_11;
3935           goto not_done;
3936
3937         case ISO_CODE_SO:       /* locking shift 1 */
3938           reg = 1; half = 0;
3939           goto locking_shift;
3940         case ISO_CODE_SI:       /* locking shift 0 */
3941           reg = 0; half = 0;
3942           goto locking_shift;
3943
3944         case ISO_CODE_SS2:      /* single shift */
3945           reg = 2;
3946           goto single_shift;
3947         case ISO_CODE_SS3:      /* single shift */
3948           reg = 3;
3949           goto single_shift;
3950
3951         default:                        /* Other control characters */
3952           return 0;
3953         }
3954
3955     case ISO_ESC:
3956       switch (c)
3957         {
3958           /**** single shift ****/
3959
3960         case 'N':       /* single shift 2 */
3961           reg = 2;
3962           goto single_shift;
3963         case 'O':       /* single shift 3 */
3964           reg = 3;
3965           goto single_shift;
3966
3967           /**** locking shift ****/
3968
3969         case '~':       /* locking shift 1 right */
3970           reg = 1; half = 1;
3971           goto locking_shift;
3972         case 'n':       /* locking shift 2 */
3973           reg = 2; half = 0;
3974           goto locking_shift;
3975         case '}':       /* locking shift 2 right */
3976           reg = 2; half = 1;
3977           goto locking_shift;
3978         case 'o':       /* locking shift 3 */
3979           reg = 3; half = 0;
3980           goto locking_shift;
3981         case '|':       /* locking shift 3 right */
3982           reg = 3; half = 1;
3983           goto locking_shift;
3984
3985 #ifdef ENABLE_COMPOSITE_CHARS
3986           /**** composite ****/
3987
3988         case '0':
3989           iso->esc = ISO_ESC_START_COMPOSITE;
3990           *flags = (*flags & CODING_STATE_ISO2022_LOCK) |
3991             CODING_STATE_COMPOSITE;
3992           return 1;
3993
3994         case '1':
3995           iso->esc = ISO_ESC_END_COMPOSITE;
3996           *flags = (*flags & CODING_STATE_ISO2022_LOCK) &
3997             ~CODING_STATE_COMPOSITE;
3998           return 1;
3999 #endif /* ENABLE_COMPOSITE_CHARS */
4000
4001           /**** directionality ****/
4002
4003         case '[':
4004           iso->esc = ISO_ESC_5_11;
4005           goto not_done;
4006
4007           /**** designation ****/
4008
4009         case '$':       /* multibyte charset prefix */
4010           iso->esc = ISO_ESC_2_4;
4011           goto not_done;
4012
4013         default:
4014           if (0x28 <= c && c <= 0x2F)
4015             {
4016               iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_8);
4017               goto not_done;
4018             }
4019
4020           /* This function is called with CODESYS equal to nil when
4021              doing coding-system detection. */
4022           if (!NILP (codesys)
4023               && XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
4024               && fit_to_be_escape_quoted (c))
4025             {
4026               iso->esc = ISO_ESC_LITERAL;
4027               *flags &= CODING_STATE_ISO2022_LOCK;
4028               return 1;
4029             }
4030
4031           /* bzzzt! */
4032           return 0;
4033         }
4034
4035
4036
4037       /**** directionality ****/
4038
4039     case ISO_ESC_5_11:          /* ISO6429 direction control */
4040       if (c == ']')
4041         {
4042           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4043           goto directionality;
4044         }
4045       if      (c == '0') iso->esc = ISO_ESC_5_11_0;
4046       else if (c == '1') iso->esc = ISO_ESC_5_11_1;
4047       else if (c == '2') iso->esc = ISO_ESC_5_11_2;
4048       else               return 0;
4049       goto not_done;
4050
4051     case ISO_ESC_5_11_0:
4052       if (c == ']')
4053         {
4054           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4055           goto directionality;
4056         }
4057       return 0;
4058
4059     case ISO_ESC_5_11_1:
4060       if (c == ']')
4061         {
4062           *flags = (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4063           goto directionality;
4064         }
4065       return 0;
4066
4067     case ISO_ESC_5_11_2:
4068       if (c == ']')
4069         {
4070           *flags = (*flags & CODING_STATE_ISO2022_LOCK) | CODING_STATE_R2L;
4071           goto directionality;
4072         }
4073       return 0;
4074
4075     directionality:
4076       iso->esc = ISO_ESC_DIRECTIONALITY;
4077       /* Various junk here to attempt to preserve the direction sequences
4078          literally in the text if they would otherwise be swallowed due
4079          to invalid designations that don't show up as actual charset
4080          changes in the text. */
4081       if (iso->invalid_switch_dir)
4082         {
4083           /* We already inserted a direction switch literally into the
4084              text.  We assume (#### this may not be right) that the
4085              next direction switch is the one going the other way,
4086              and we need to output that literally as well. */
4087           iso->output_literally = 1;
4088           iso->invalid_switch_dir = 0;
4089         }
4090       else
4091         {
4092           int jj;
4093
4094           /* If we are in the thrall of an invalid designation,
4095            then stick the directionality sequence literally into the
4096            output stream so it ends up in the original text again. */
4097           for (jj = 0; jj < 4; jj++)
4098             if (iso->invalid_designated[jj])
4099               break;
4100           if (jj < 4)
4101             {
4102               iso->output_literally = 1;
4103               iso->invalid_switch_dir = 1;
4104             }
4105           else
4106             /* Indicate that we haven't yet seen a valid designation,
4107                so that if a switch-dir is directly followed by an
4108                invalid designation, both get inserted literally. */
4109             iso->switched_dir_and_no_valid_charset_yet = 1;
4110         }
4111       return 1;
4112
4113
4114       /**** designation ****/
4115
4116     case ISO_ESC_2_4:
4117       if (0x28 <= c && c <= 0x2F)
4118         {
4119           iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_4_8);
4120           goto not_done;
4121         }
4122       if (0x40 <= c && c <= 0x42)
4123         {
4124           cs = CHARSET_BY_ATTRIBUTES (CHARSET_TYPE_94X94, c,
4125                                       *flags & CODING_STATE_R2L ?
4126                                       CHARSET_RIGHT_TO_LEFT :
4127                                       CHARSET_LEFT_TO_RIGHT);
4128           reg = 0;
4129           goto designated;
4130         }
4131       return 0;
4132
4133     default:
4134       {
4135         int type =-1;
4136
4137         if (c < '0' || c > '~')
4138           return 0; /* bad final byte */
4139
4140         if (iso->esc >= ISO_ESC_2_8 &&
4141             iso->esc <= ISO_ESC_2_15)
4142           {
4143             type = ((iso->esc >= ISO_ESC_2_12) ?
4144                     CHARSET_TYPE_96 : CHARSET_TYPE_94);
4145             reg = (iso->esc - ISO_ESC_2_8) & 3;
4146           }
4147         else if (iso->esc >= ISO_ESC_2_4_8 &&
4148                  iso->esc <= ISO_ESC_2_4_15)
4149           {
4150             type = ((iso->esc >= ISO_ESC_2_4_12) ?
4151                     CHARSET_TYPE_96X96 : CHARSET_TYPE_94X94);
4152             reg = (iso->esc - ISO_ESC_2_4_8) & 3;
4153           }
4154         else
4155           {
4156             /* Can this ever be reached? -slb */
4157             abort();
4158           }
4159
4160         cs = CHARSET_BY_ATTRIBUTES (type, c,
4161                                     *flags & CODING_STATE_R2L ?
4162                                     CHARSET_RIGHT_TO_LEFT :
4163                                     CHARSET_LEFT_TO_RIGHT);
4164         goto designated;
4165       }
4166     }
4167
4168  not_done:
4169   iso->esc_bytes[iso->esc_bytes_index++] = (unsigned char) c;
4170   return -1;
4171
4172  single_shift:
4173   if (check_invalid_charsets && !CHARSETP (iso->charset[reg]))
4174     /* can't invoke something that ain't there. */
4175     return 0;
4176   iso->esc = ISO_ESC_SINGLE_SHIFT;
4177   *flags &= CODING_STATE_ISO2022_LOCK;
4178   if (reg == 2)
4179     *flags |= CODING_STATE_SS2;
4180   else
4181     *flags |= CODING_STATE_SS3;
4182   return 1;
4183
4184  locking_shift:
4185   if (check_invalid_charsets &&
4186       !CHARSETP (iso->charset[reg]))
4187     /* can't invoke something that ain't there. */
4188     return 0;
4189   if (half)
4190     iso->register_right = reg;
4191   else
4192     iso->register_left = reg;
4193   *flags &= CODING_STATE_ISO2022_LOCK;
4194   iso->esc = ISO_ESC_LOCKING_SHIFT;
4195   return 1;
4196
4197  designated:
4198   if (NILP (cs) && check_invalid_charsets)
4199     {
4200       iso->invalid_designated[reg] = 1;
4201       iso->charset[reg] = Vcharset_ascii;
4202       iso->esc = ISO_ESC_DESIGNATE;
4203       *flags &= CODING_STATE_ISO2022_LOCK;
4204       iso->output_literally = 1;
4205       if (iso->switched_dir_and_no_valid_charset_yet)
4206         {
4207           /* We encountered a switch-direction followed by an
4208              invalid designation.  Ensure that the switch-direction
4209              gets outputted; otherwise it will probably get eaten
4210              when the text is written out again. */
4211           iso->switched_dir_and_no_valid_charset_yet = 0;
4212           iso->output_direction_sequence = 1;
4213           /* And make sure that the switch-dir going the other
4214              way gets outputted, as well. */
4215           iso->invalid_switch_dir = 1;
4216         }
4217       return 1;
4218     }
4219   /* This function is called with CODESYS equal to nil when
4220      doing coding-system detection. */
4221   if (!NILP (codesys))
4222     {
4223       charset_conversion_spec_dynarr *dyn =
4224         XCODING_SYSTEM (codesys)->iso2022.input_conv;
4225
4226       if (dyn)
4227         {
4228           int i;
4229
4230           for (i = 0; i < Dynarr_length (dyn); i++)
4231             {
4232               struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
4233               if (EQ (cs, spec->from_charset))
4234                 cs = spec->to_charset;
4235             }
4236         }
4237     }
4238
4239   iso->charset[reg] = cs;
4240   iso->esc = ISO_ESC_DESIGNATE;
4241   *flags &= CODING_STATE_ISO2022_LOCK;
4242   if (iso->invalid_designated[reg])
4243     {
4244       iso->invalid_designated[reg] = 0;
4245       iso->output_literally = 1;
4246     }
4247   if (iso->switched_dir_and_no_valid_charset_yet)
4248     iso->switched_dir_and_no_valid_charset_yet = 0;
4249   return 1;
4250 }
4251
4252 static int
4253 detect_coding_iso2022 (struct detection_state *st, CONST unsigned char *src,
4254                        unsigned int n)
4255 {
4256   int mask;
4257
4258   /* #### There are serious deficiencies in the recognition mechanism
4259      here.  This needs to be much smarter if it's going to cut it.
4260      The sequence "\xff\x0f" is currently detected as LOCK_SHIFT while
4261      it should be detected as Latin-1.
4262      All the ISO2022 stuff in this file should be synced up with the
4263      code from FSF Emacs-20.4, in which Mule should be more or less stable.
4264      Perhaps we should wait till R2L works in FSF Emacs? */
4265
4266   if (!st->iso2022.initted)
4267     {
4268       reset_iso2022 (Qnil, &st->iso2022.iso);
4269       st->iso2022.mask = (CODING_CATEGORY_ISO_7_MASK |
4270                           CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
4271                           CODING_CATEGORY_ISO_8_1_MASK |
4272                           CODING_CATEGORY_ISO_8_2_MASK |
4273                           CODING_CATEGORY_ISO_LOCK_SHIFT_MASK);
4274       st->iso2022.flags = 0;
4275       st->iso2022.high_byte_count = 0;
4276       st->iso2022.saw_single_shift = 0;
4277       st->iso2022.initted = 1;
4278     }
4279
4280   mask = st->iso2022.mask;
4281
4282   while (n--)
4283     {
4284       int c = *src++;
4285       if (c >= 0xA0)
4286         {
4287           mask &= ~CODING_CATEGORY_ISO_7_MASK;
4288           st->iso2022.high_byte_count++;
4289         }
4290       else
4291         {
4292           if (st->iso2022.high_byte_count && !st->iso2022.saw_single_shift)
4293             {
4294               if (st->iso2022.high_byte_count & 1)
4295                 /* odd number of high bytes; assume not iso-8-2 */
4296                 mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
4297             }
4298           st->iso2022.high_byte_count = 0;
4299           st->iso2022.saw_single_shift = 0;
4300           if (c > 0x80)
4301             mask &= ~CODING_CATEGORY_ISO_7_MASK;
4302         }
4303       if (!(st->iso2022.flags & CODING_STATE_ESCAPE)
4304           && (BYTE_C0_P (c) || BYTE_C1_P (c)))
4305         { /* control chars */
4306           switch (c)
4307             {
4308               /* Allow and ignore control characters that you might
4309                  reasonably see in a text file */
4310             case '\r':
4311             case '\n':
4312             case '\t':
4313             case  7: /* bell */
4314             case  8: /* backspace */
4315             case 11: /* vertical tab */
4316             case 12: /* form feed */
4317             case 26: /* MS-DOS C-z junk */
4318             case 31: /* '^_' -- for info */
4319               goto label_continue_loop;
4320
4321             default:
4322               break;
4323             }
4324         }
4325
4326       if ((st->iso2022.flags & CODING_STATE_ESCAPE) || BYTE_C0_P (c)
4327           || BYTE_C1_P (c))
4328         {
4329           if (parse_iso2022_esc (Qnil, &st->iso2022.iso, c,
4330                                  &st->iso2022.flags, 0))
4331             {
4332               switch (st->iso2022.iso.esc)
4333                 {
4334                 case ISO_ESC_DESIGNATE:
4335                   mask &= ~CODING_CATEGORY_ISO_8_1_MASK;
4336                   mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
4337                   break;
4338                 case ISO_ESC_LOCKING_SHIFT:
4339                   mask = CODING_CATEGORY_ISO_LOCK_SHIFT_MASK;
4340                   goto ran_out_of_chars;
4341                 case ISO_ESC_SINGLE_SHIFT:
4342                   mask &= ~CODING_CATEGORY_ISO_8_DESIGNATE_MASK;
4343                   st->iso2022.saw_single_shift = 1;
4344                   break;
4345                 default:
4346                   break;
4347                 }
4348             }
4349           else
4350             {
4351               mask = 0;
4352               goto ran_out_of_chars;
4353             }
4354         }
4355     label_continue_loop:;
4356     }
4357
4358  ran_out_of_chars:
4359
4360   return mask;
4361 }
4362
4363 static int
4364 postprocess_iso2022_mask (int mask)
4365 {
4366   /* #### kind of cheesy */
4367   /* If seven-bit ISO is allowed, then assume that the encoding is
4368      entirely seven-bit and turn off the eight-bit ones. */
4369   if (mask & CODING_CATEGORY_ISO_7_MASK)
4370     mask &= ~ (CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
4371                CODING_CATEGORY_ISO_8_1_MASK |
4372                CODING_CATEGORY_ISO_8_2_MASK);
4373   return mask;
4374 }
4375
4376 /* If FLAGS is a null pointer or specifies right-to-left motion,
4377    output a switch-dir-to-left-to-right sequence to DST.
4378    Also update FLAGS if it is not a null pointer.
4379    If INTERNAL_P is set, we are outputting in internal format and
4380    need to handle the CSI differently. */
4381
4382 static void
4383 restore_left_to_right_direction (Lisp_Coding_System *codesys,
4384                                  unsigned_char_dynarr *dst,
4385                                  unsigned int *flags,
4386                                  int internal_p)
4387 {
4388   if (!flags || (*flags & CODING_STATE_R2L))
4389     {
4390       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
4391         {
4392           Dynarr_add (dst, ISO_CODE_ESC);
4393           Dynarr_add (dst, '[');
4394         }
4395       else if (internal_p)
4396         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
4397       else
4398         Dynarr_add (dst, ISO_CODE_CSI);
4399       Dynarr_add (dst, '0');
4400       Dynarr_add (dst, ']');
4401       if (flags)
4402         *flags &= ~CODING_STATE_R2L;
4403     }
4404 }
4405
4406 /* If FLAGS is a null pointer or specifies a direction different from
4407    DIRECTION (which should be either CHARSET_RIGHT_TO_LEFT or
4408    CHARSET_LEFT_TO_RIGHT), output the appropriate switch-dir escape
4409    sequence to DST.  Also update FLAGS if it is not a null pointer.
4410    If INTERNAL_P is set, we are outputting in internal format and
4411    need to handle the CSI differently. */
4412
4413 static void
4414 ensure_correct_direction (int direction, Lisp_Coding_System *codesys,
4415                           unsigned_char_dynarr *dst, unsigned int *flags,
4416                           int internal_p)
4417 {
4418   if ((!flags || (*flags & CODING_STATE_R2L)) &&
4419       direction == CHARSET_LEFT_TO_RIGHT)
4420     restore_left_to_right_direction (codesys, dst, flags, internal_p);
4421   else if (!CODING_SYSTEM_ISO2022_NO_ISO6429 (codesys)
4422            && (!flags || !(*flags & CODING_STATE_R2L)) &&
4423            direction == CHARSET_RIGHT_TO_LEFT)
4424     {
4425       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
4426         {
4427           Dynarr_add (dst, ISO_CODE_ESC);
4428           Dynarr_add (dst, '[');
4429         }
4430       else if (internal_p)
4431         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
4432       else
4433         Dynarr_add (dst, ISO_CODE_CSI);
4434       Dynarr_add (dst, '2');
4435       Dynarr_add (dst, ']');
4436       if (flags)
4437         *flags |= CODING_STATE_R2L;
4438     }
4439 }
4440
4441 /* Convert ISO2022-format data to internal format. */
4442
4443 static void
4444 decode_coding_iso2022 (Lstream *decoding, CONST unsigned char *src,
4445                        unsigned_char_dynarr *dst, unsigned int n)
4446 {
4447   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4448   unsigned int flags  = str->flags;
4449   unsigned int ch     = str->ch;
4450   eol_type_t eol_type = str->eol_type;
4451 #ifdef ENABLE_COMPOSITE_CHARS
4452   unsigned_char_dynarr *real_dst = dst;
4453 #endif
4454   Lisp_Object coding_system;
4455
4456   XSETCODING_SYSTEM (coding_system, str->codesys);
4457
4458 #ifdef ENABLE_COMPOSITE_CHARS
4459   if (flags & CODING_STATE_COMPOSITE)
4460     dst = str->iso2022.composite_chars;
4461 #endif /* ENABLE_COMPOSITE_CHARS */
4462
4463   while (n--)
4464     {
4465       unsigned char c = *src++;
4466       if (flags & CODING_STATE_ESCAPE)
4467         {       /* Within ESC sequence */
4468           int retval = parse_iso2022_esc (coding_system, &str->iso2022,
4469                                           c, &flags, 1);
4470
4471           if (retval)
4472             {
4473               switch (str->iso2022.esc)
4474                 {
4475 #ifdef ENABLE_COMPOSITE_CHARS
4476                 case ISO_ESC_START_COMPOSITE:
4477                   if (str->iso2022.composite_chars)
4478                     Dynarr_reset (str->iso2022.composite_chars);
4479                   else
4480                     str->iso2022.composite_chars = Dynarr_new (unsigned_char);
4481                   dst = str->iso2022.composite_chars;
4482                   break;
4483                 case ISO_ESC_END_COMPOSITE:
4484                   {
4485                     Bufbyte comstr[MAX_EMCHAR_LEN];
4486                     Bytecount len;
4487                     Emchar emch = lookup_composite_char (Dynarr_atp (dst, 0),
4488                                                          Dynarr_length (dst));
4489                     dst = real_dst;
4490                     len = set_charptr_emchar (comstr, emch);
4491                     Dynarr_add_many (dst, comstr, len);
4492                     break;
4493                   }
4494 #endif /* ENABLE_COMPOSITE_CHARS */
4495
4496                 case ISO_ESC_LITERAL:
4497                   DECODE_ADD_BINARY_CHAR (c, dst);
4498                   break;
4499
4500                 default:
4501                   /* Everything else handled already */
4502                   break;
4503                 }
4504             }
4505
4506           /* Attempted error recovery. */
4507           if (str->iso2022.output_direction_sequence)
4508             ensure_correct_direction (flags & CODING_STATE_R2L ?
4509                                       CHARSET_RIGHT_TO_LEFT :
4510                                       CHARSET_LEFT_TO_RIGHT,
4511                                       str->codesys, dst, 0, 1);
4512           /* More error recovery. */
4513           if (!retval || str->iso2022.output_literally)
4514             {
4515               /* Output the (possibly invalid) sequence */
4516               int i;
4517               for (i = 0; i < str->iso2022.esc_bytes_index; i++)
4518                 DECODE_ADD_BINARY_CHAR (str->iso2022.esc_bytes[i], dst);
4519               flags &= CODING_STATE_ISO2022_LOCK;
4520               if (!retval)
4521                 n++, src--;/* Repeat the loop with the same character. */
4522               else
4523                 {
4524                   /* No sense in reprocessing the final byte of the
4525                      escape sequence; it could mess things up anyway.
4526                      Just add it now. */
4527                   DECODE_ADD_BINARY_CHAR (c, dst);
4528                 }
4529             }
4530           ch = 0;
4531         }
4532       else if (BYTE_C0_P (c) || BYTE_C1_P (c))
4533         { /* Control characters */
4534
4535           /***** Error-handling *****/
4536
4537           /* If we were in the middle of a character, dump out the
4538              partial character. */
4539           DECODE_OUTPUT_PARTIAL_CHAR (ch);
4540
4541           /* If we just saw a single-shift character, dump it out.
4542              This may dump out the wrong sort of single-shift character,
4543              but least it will give an indication that something went
4544              wrong. */
4545           if (flags & CODING_STATE_SS2)
4546             {
4547               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS2, dst);
4548               flags &= ~CODING_STATE_SS2;
4549             }
4550           if (flags & CODING_STATE_SS3)
4551             {
4552               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS3, dst);
4553               flags &= ~CODING_STATE_SS3;
4554             }
4555
4556           /***** Now handle the control characters. *****/
4557
4558           /* Handle CR/LF */
4559           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
4560
4561           flags &= CODING_STATE_ISO2022_LOCK;
4562
4563           if (!parse_iso2022_esc (coding_system, &str->iso2022, c, &flags, 1))
4564             DECODE_ADD_BINARY_CHAR (c, dst);
4565         }
4566       else
4567         {                       /* Graphic characters */
4568           Lisp_Object charset;
4569 #ifndef UTF2000
4570           Charset_ID lb;
4571 #endif
4572           int reg;
4573
4574           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
4575
4576           /* Now determine the charset. */
4577           reg = ((flags & CODING_STATE_SS2) ? 2
4578                  : (flags & CODING_STATE_SS3) ? 3
4579                  : !BYTE_ASCII_P (c) ? str->iso2022.register_right
4580                  : str->iso2022.register_left);
4581           charset = str->iso2022.charset[reg];
4582
4583           /* Error checking: */
4584           if (! CHARSETP (charset)
4585               || str->iso2022.invalid_designated[reg]
4586               || (((c & 0x7F) == ' ' || (c & 0x7F) == ISO_CODE_DEL)
4587                   && XCHARSET_CHARS (charset) == 94))
4588             /* Mrmph.  We are trying to invoke a register that has no
4589                or an invalid charset in it, or trying to add a character
4590                outside the range of the charset.  Insert that char literally
4591                to preserve it for the output. */
4592             {
4593               DECODE_OUTPUT_PARTIAL_CHAR (ch);
4594               DECODE_ADD_BINARY_CHAR (c, dst);
4595             }
4596
4597           else
4598             {
4599               /* Things are probably hunky-dorey. */
4600
4601               /* Fetch reverse charset, maybe. */
4602               if (((flags & CODING_STATE_R2L) &&
4603                    XCHARSET_DIRECTION (charset) == CHARSET_LEFT_TO_RIGHT)
4604                   ||
4605                   (!(flags & CODING_STATE_R2L) &&
4606                    XCHARSET_DIRECTION (charset) == CHARSET_RIGHT_TO_LEFT))
4607                 {
4608                   Lisp_Object new_charset =
4609                     XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
4610                   if (!NILP (new_charset))
4611                     charset = new_charset;
4612                 }
4613
4614 #ifdef UTF2000
4615               if (XCHARSET_DIMENSION (charset) == 1)
4616                 {
4617                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
4618                   DECODE_ADD_UCS_CHAR
4619                     (MAKE_CHAR (charset, c & 0x7F, 0), dst);
4620                 }
4621               else if (ch)
4622                 {
4623                   DECODE_ADD_UCS_CHAR
4624                     (MAKE_CHAR (charset, ch & 0x7F, c & 0x7F), dst);
4625                   ch = 0;
4626                 }
4627               else
4628                 ch = c;
4629 #else
4630               lb = XCHARSET_LEADING_BYTE (charset);
4631               switch (XCHARSET_REP_BYTES (charset))
4632                 {
4633                 case 1: /* ASCII */
4634                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
4635                   Dynarr_add (dst, c & 0x7F);
4636                   break;
4637
4638                 case 2: /* one-byte official */
4639                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
4640                   Dynarr_add (dst, lb);
4641                   Dynarr_add (dst, c | 0x80);
4642                   break;
4643
4644                 case 3: /* one-byte private or two-byte official */
4645                   if (XCHARSET_PRIVATE_P (charset))
4646                     {
4647                       DECODE_OUTPUT_PARTIAL_CHAR (ch);
4648                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_1);
4649                       Dynarr_add (dst, lb);
4650                       Dynarr_add (dst, c | 0x80);
4651                     }
4652                   else
4653                     {
4654                       if (ch)
4655                         {
4656                           Dynarr_add (dst, lb);
4657                           Dynarr_add (dst, ch | 0x80);
4658                           Dynarr_add (dst, c | 0x80);
4659                           ch = 0;
4660                         }
4661                       else
4662                         ch = c;
4663                     }
4664                   break;
4665
4666                 default:        /* two-byte private */
4667                   if (ch)
4668                     {
4669                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_2);
4670                       Dynarr_add (dst, lb);
4671                       Dynarr_add (dst, ch | 0x80);
4672                       Dynarr_add (dst, c | 0x80);
4673                       ch = 0;
4674                     }
4675                   else
4676                     ch = c;
4677                 }
4678 #endif
4679             }
4680
4681           if (!ch)
4682             flags &= CODING_STATE_ISO2022_LOCK;
4683         }
4684
4685     label_continue_loop:;
4686     }
4687
4688   if (flags & CODING_STATE_END)
4689     DECODE_OUTPUT_PARTIAL_CHAR (ch);
4690
4691   str->flags = flags;
4692   str->ch    = ch;
4693 }
4694
4695
4696 /***** ISO2022 encoder *****/
4697
4698 /* Designate CHARSET into register REG. */
4699
4700 static void
4701 iso2022_designate (Lisp_Object charset, unsigned char reg,
4702                    struct encoding_stream *str, unsigned_char_dynarr *dst)
4703 {
4704   static CONST char inter94[] = "()*+";
4705   static CONST char inter96[] = ",-./";
4706   unsigned int type;
4707   unsigned char final;
4708   Lisp_Object old_charset = str->iso2022.charset[reg];
4709
4710   str->iso2022.charset[reg] = charset;
4711   if (!CHARSETP (charset))
4712     /* charset might be an initial nil or t. */
4713     return;
4714   type = XCHARSET_TYPE (charset);
4715   final = XCHARSET_FINAL (charset);
4716   if (!str->iso2022.force_charset_on_output[reg] &&
4717       CHARSETP (old_charset) &&
4718       XCHARSET_TYPE (old_charset) == type &&
4719       XCHARSET_FINAL (old_charset) == final)
4720     return;
4721
4722   str->iso2022.force_charset_on_output[reg] = 0;
4723
4724   {
4725     charset_conversion_spec_dynarr *dyn =
4726       str->codesys->iso2022.output_conv;
4727
4728     if (dyn)
4729       {
4730         int i;
4731
4732         for (i = 0; i < Dynarr_length (dyn); i++)
4733           {
4734             struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
4735             if (EQ (charset, spec->from_charset))
4736                 charset = spec->to_charset;
4737           }
4738       }
4739   }
4740
4741   Dynarr_add (dst, ISO_CODE_ESC);
4742   switch (type)
4743     {
4744     case CHARSET_TYPE_94:
4745       Dynarr_add (dst, inter94[reg]);
4746       break;
4747     case CHARSET_TYPE_96:
4748       Dynarr_add (dst, inter96[reg]);
4749       break;
4750     case CHARSET_TYPE_94X94:
4751       Dynarr_add (dst, '$');
4752       if (reg != 0
4753           || !(CODING_SYSTEM_ISO2022_SHORT (str->codesys))
4754           || final < '@'
4755           || final > 'B')
4756         Dynarr_add (dst, inter94[reg]);
4757       break;
4758     case CHARSET_TYPE_96X96:
4759       Dynarr_add (dst, '$');
4760       Dynarr_add (dst, inter96[reg]);
4761       break;
4762     }
4763   Dynarr_add (dst, final);
4764 }
4765
4766 static void
4767 ensure_normal_shift (struct encoding_stream *str, unsigned_char_dynarr *dst)
4768 {
4769   if (str->iso2022.register_left != 0)
4770     {
4771       Dynarr_add (dst, ISO_CODE_SI);
4772       str->iso2022.register_left = 0;
4773     }
4774 }
4775
4776 static void
4777 ensure_shift_out (struct encoding_stream *str, unsigned_char_dynarr *dst)
4778 {
4779   if (str->iso2022.register_left != 1)
4780     {
4781       Dynarr_add (dst, ISO_CODE_SO);
4782       str->iso2022.register_left = 1;
4783     }
4784 }
4785
4786 void
4787 char_encode_iso2022 (struct encoding_stream *str, Emchar ch,
4788                      unsigned_char_dynarr *dst, unsigned int *flags)
4789 {
4790   unsigned char charmask;
4791   Lisp_Coding_System* codesys = str->codesys;
4792   eol_type_t eol_type         = CODING_SYSTEM_EOL_TYPE (str->codesys);
4793   int i;
4794   Lisp_Object charset = str->iso2022.current_charset;
4795   int half = str->iso2022.current_half;
4796   unsigned int byte1, byte2;
4797
4798   if (ch <= 0x7F)
4799     {
4800       restore_left_to_right_direction (codesys, dst, flags, 0);
4801               
4802       /* Make sure G0 contains ASCII */
4803       if ((ch > ' ' && ch < ISO_CODE_DEL)
4804           || !CODING_SYSTEM_ISO2022_NO_ASCII_CNTL (codesys))
4805         {
4806           ensure_normal_shift (str, dst);
4807           iso2022_designate (Vcharset_ascii, 0, str, dst);
4808         }
4809               
4810       /* If necessary, restore everything to the default state
4811          at end-of-line */
4812       if (ch == '\n' && !(CODING_SYSTEM_ISO2022_NO_ASCII_EOL (codesys)))
4813         {
4814           restore_left_to_right_direction (codesys, dst, flags, 0);
4815
4816           ensure_normal_shift (str, dst);
4817
4818           for (i = 0; i < 4; i++)
4819             {
4820               Lisp_Object initial_charset =
4821                 CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
4822               iso2022_designate (initial_charset, i, str, dst);
4823             }
4824         }
4825       if (ch == '\n')
4826         {
4827           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
4828             Dynarr_add (dst, '\r');
4829           if (eol_type != EOL_CR)
4830             Dynarr_add (dst, ch);
4831         }
4832       else
4833         {
4834           if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
4835               && fit_to_be_escape_quoted (ch))
4836             Dynarr_add (dst, ISO_CODE_ESC);
4837           Dynarr_add (dst, ch);
4838         }
4839     }
4840   else if ( (0x80 <= ch) && (ch <= 0x9f) )
4841     {
4842       charmask = (half == 0 ? 0x00 : 0x80);
4843           
4844       if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
4845           && fit_to_be_escape_quoted (ch))
4846         Dynarr_add (dst, ISO_CODE_ESC);
4847       /* you asked for it ... */
4848       Dynarr_add (dst, ch);
4849     }
4850   else
4851     {
4852       int reg;
4853
4854       BREAKUP_CHAR (ch, charset, byte1, byte2);
4855       ensure_correct_direction (XCHARSET_DIRECTION (charset),
4856                                 codesys, dst, flags, 0);
4857
4858       /* Now determine which register to use. */
4859       reg = -1;
4860       for (i = 0; i < 4; i++)
4861         {
4862           if (EQ (charset, str->iso2022.charset[i]) ||
4863               EQ (charset,
4864                   CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i)))
4865             {
4866               reg = i;
4867               break;
4868             }
4869         }
4870               
4871       if (reg == -1)
4872         {
4873           if (XCHARSET_GRAPHIC (charset) != 0)
4874             {
4875               if (!NILP (str->iso2022.charset[1]) &&
4876                   (!CODING_SYSTEM_ISO2022_SEVEN (codesys)
4877                    || CODING_SYSTEM_ISO2022_LOCK_SHIFT (codesys)))
4878                 reg = 1;
4879               else if (!NILP (str->iso2022.charset[2]))
4880                 reg = 2;
4881               else if (!NILP (str->iso2022.charset[3]))
4882                 reg = 3;
4883               else
4884                 reg = 0;
4885             }
4886           else
4887             reg = 0;
4888         }
4889
4890       iso2022_designate (charset, reg, str, dst);
4891               
4892       /* Now invoke that register. */
4893       switch (reg)
4894         {
4895         case 0:
4896           ensure_normal_shift (str, dst);
4897           half = 0;
4898           break;
4899         case 1:
4900           if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
4901             {
4902               ensure_shift_out (str, dst);
4903               half = 0;
4904             }
4905           else
4906             half = 1;
4907           break;
4908         case 2:
4909           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
4910             {
4911               Dynarr_add (dst, ISO_CODE_ESC);
4912               Dynarr_add (dst, 'N');
4913               half = 0;
4914             }
4915           else
4916             {
4917               Dynarr_add (dst, ISO_CODE_SS2);
4918               half = 1;
4919             }
4920           break;
4921         case 3:
4922           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
4923             {
4924               Dynarr_add (dst, ISO_CODE_ESC);
4925               Dynarr_add (dst, 'O');
4926               half = 0;
4927             }
4928           else
4929             {
4930               Dynarr_add (dst, ISO_CODE_SS3);
4931               half = 1;
4932             }
4933           break;
4934         default:
4935           abort ();
4936         }
4937       
4938       charmask = (half == 0 ? 0x00 : 0x80);
4939       
4940       switch (XCHARSET_DIMENSION (charset))
4941         {
4942         case 1:
4943           Dynarr_add (dst, byte1 | charmask);
4944           break;
4945         case 2:
4946           Dynarr_add (dst, byte1 | charmask);
4947           Dynarr_add (dst, byte2 | charmask);
4948           break;
4949         default:
4950           abort ();
4951         }
4952     }
4953   str->iso2022.current_charset = charset;
4954   str->iso2022.current_half = half;
4955 }
4956
4957 void
4958 char_finish_iso2022 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4959                      unsigned int *flags)
4960 {
4961   Lisp_Coding_System* codesys = str->codesys;
4962   int i;
4963
4964   restore_left_to_right_direction (codesys, dst, flags, 0);
4965   ensure_normal_shift (str, dst);
4966   for (i = 0; i < 4; i++)
4967     {
4968       Lisp_Object initial_charset
4969         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
4970       iso2022_designate (initial_charset, i, str, dst);
4971     }
4972 }
4973 #endif /* MULE */
4974 \f
4975 /************************************************************************/
4976 /*                     No-conversion methods                            */
4977 /************************************************************************/
4978
4979 /* This is used when reading in "binary" files -- i.e. files that may
4980    contain all 256 possible byte values and that are not to be
4981    interpreted as being in any particular decoding. */
4982 static void
4983 decode_coding_no_conversion (Lstream *decoding, CONST unsigned char *src,
4984                              unsigned_char_dynarr *dst, unsigned int n)
4985 {
4986   unsigned char c;
4987   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4988   unsigned int flags  = str->flags;
4989   unsigned int ch     = str->ch;
4990   eol_type_t eol_type = str->eol_type;
4991
4992   while (n--)
4993     {
4994       c = *src++;
4995
4996       DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
4997       DECODE_ADD_BINARY_CHAR (c, dst);
4998     label_continue_loop:;
4999     }
5000
5001   DECODE_HANDLE_END_OF_CONVERSION (flags, ch, dst);
5002
5003   str->flags = flags;
5004   str->ch    = ch;
5005 }
5006
5007 static void
5008 encode_coding_no_conversion (Lstream *encoding, CONST unsigned char *src,
5009                              unsigned_char_dynarr *dst, unsigned int n)
5010 {
5011   unsigned char c;
5012   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
5013   unsigned int flags  = str->flags;
5014   unsigned int ch     = str->ch;
5015   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
5016 #ifdef UTF2000
5017   unsigned char char_boundary = str->iso2022.current_char_boundary;
5018 #endif
5019
5020   while (n--)
5021     {
5022       c = *src++;         
5023 #ifdef UTF2000
5024       switch (char_boundary)
5025         {
5026         case 0:
5027           if ( c >= 0xfc )
5028             {
5029               ch = c & 0x01;
5030               char_boundary = 5;
5031             }
5032           else if ( c >= 0xf8 )
5033             {
5034               ch = c & 0x03;
5035               char_boundary = 4;
5036             }
5037           else if ( c >= 0xf0 )
5038             {
5039               ch = c & 0x07;
5040               char_boundary = 3;
5041             }
5042           else if ( c >= 0xe0 )
5043             {
5044               ch = c & 0x0f;
5045               char_boundary = 2;
5046             }
5047           else if ( c >= 0xc0 )
5048             {
5049               ch = c & 0x1f;
5050               char_boundary = 1;
5051             }
5052           else
5053             {
5054               ch = 0;
5055
5056               if (c == '\n')
5057                 {
5058                   if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5059                     Dynarr_add (dst, '\r');
5060                   if (eol_type != EOL_CR)
5061                     Dynarr_add (dst, c);
5062                 }
5063               else
5064                 Dynarr_add (dst, c);
5065               char_boundary = 0;
5066             }
5067           break;
5068         case 1:
5069           ch = ( ch << 6 ) | ( c & 0x3f );
5070           switch ( str->codesys->fixed.size )
5071             {
5072             case 1:
5073               Dynarr_add (dst, ch & 0xff);
5074               break;
5075             case 2:
5076               Dynarr_add (dst, (ch >> 8) & 0xff);
5077               Dynarr_add (dst,  ch       & 0xff);
5078               break;
5079             case 3:
5080               Dynarr_add (dst, (ch >> 16) & 0xff);
5081               Dynarr_add (dst, (ch >>  8) & 0xff);
5082               Dynarr_add (dst,  ch        & 0xff);
5083               break;
5084             case 4:
5085               Dynarr_add (dst, (ch >> 24) & 0xff);
5086               Dynarr_add (dst, (ch >> 16) & 0xff);
5087               Dynarr_add (dst, (ch >>  8) & 0xff);
5088               Dynarr_add (dst,  ch        & 0xff);
5089               break;
5090             default:
5091               fprintf(stderr, "It seems %d bytes stream.\n",
5092                       str->codesys->fixed.size);
5093               abort ();
5094             }
5095           char_boundary = 0;
5096           break;
5097         default:
5098           ch = ( ch << 6 ) | ( c & 0x3f );
5099           char_boundary--;
5100         }
5101 #else /* not UTF2000 */
5102       if (c == '\n')
5103         {
5104           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5105             Dynarr_add (dst, '\r');
5106           if (eol_type != EOL_CR)
5107             Dynarr_add (dst, '\n');
5108           ch = 0;
5109         }
5110       else if (BYTE_ASCII_P (c))
5111         {
5112           assert (ch == 0);
5113           Dynarr_add (dst, c);
5114         }
5115       else if (BUFBYTE_LEADING_BYTE_P (c))
5116         {
5117           assert (ch == 0);
5118           if (c == LEADING_BYTE_LATIN_ISO8859_1 ||
5119               c == LEADING_BYTE_CONTROL_1)
5120             ch = c;
5121           else
5122             Dynarr_add (dst, '~'); /* untranslatable character */
5123         }
5124       else
5125         {
5126           if (ch == LEADING_BYTE_LATIN_ISO8859_1)
5127             Dynarr_add (dst, c);
5128           else if (ch == LEADING_BYTE_CONTROL_1)
5129             {
5130               assert (c < 0xC0);
5131               Dynarr_add (dst, c - 0x20);
5132             }
5133           /* else it should be the second or third byte of an
5134              untranslatable character, so ignore it */
5135           ch = 0;
5136         }
5137 #endif /* not UTF2000 */
5138     }
5139
5140   str->flags = flags;
5141   str->ch    = ch;
5142 #ifdef UTF2000
5143   str->iso2022.current_char_boundary = char_boundary;
5144 #endif
5145 }
5146
5147 \f
5148 /************************************************************************/
5149 /*                   Simple internal/external functions                 */
5150 /************************************************************************/
5151
5152 static Extbyte_dynarr *conversion_out_dynarr;
5153 static Bufbyte_dynarr *conversion_in_dynarr;
5154
5155 /* Determine coding system from coding format */
5156
5157 /* #### not correct for all values of `fmt'! */
5158 static Lisp_Object
5159 external_data_format_to_coding_system (enum external_data_format fmt)
5160 {
5161   switch (fmt)
5162     {
5163     case FORMAT_FILENAME:
5164     case FORMAT_TERMINAL:
5165       if (EQ (Vfile_name_coding_system, Qnil) ||
5166           EQ (Vfile_name_coding_system, Qbinary))
5167         return Qnil;
5168       else
5169         return Fget_coding_system (Vfile_name_coding_system);
5170 #ifdef MULE
5171     case FORMAT_CTEXT:
5172       return Fget_coding_system (Qctext);
5173 #endif
5174     default:
5175       return Qnil;
5176     }
5177 }
5178
5179 Extbyte *
5180 convert_to_external_format (CONST Bufbyte *ptr,
5181                             Bytecount len,
5182                             Extcount *len_out,
5183                             enum external_data_format fmt)
5184 {
5185   Lisp_Object coding_system = external_data_format_to_coding_system (fmt);
5186
5187   if (!conversion_out_dynarr)
5188     conversion_out_dynarr = Dynarr_new (Extbyte);
5189   else
5190     Dynarr_reset (conversion_out_dynarr);
5191
5192   if (NILP (coding_system))
5193     {
5194       CONST Bufbyte *end = ptr + len;
5195
5196       for (; ptr < end;)
5197         {
5198 #ifdef UTF2000
5199           Bufbyte c =
5200             (*ptr < 0xc0) ? *ptr :
5201             ((*ptr & 0x1f) << 6) | (*(ptr+1) & 0x3f);
5202 #else
5203           Bufbyte c =
5204             (BYTE_ASCII_P (*ptr))                  ? *ptr :
5205             (*ptr == LEADING_BYTE_CONTROL_1)       ? (*(ptr+1) - 0x20) :
5206             (*ptr == LEADING_BYTE_LATIN_ISO8859_1) ? (*(ptr+1)) :
5207             '~';
5208 #endif
5209           Dynarr_add (conversion_out_dynarr, (Extbyte) c);
5210           INC_CHARPTR (ptr);
5211         }
5212
5213 #ifdef ERROR_CHECK_BUFPOS
5214       assert (ptr == end);
5215 #endif
5216     }
5217   else
5218     {
5219       Lisp_Object instream, outstream, da_outstream;
5220       Lstream *istr, *ostr;
5221       struct gcpro gcpro1, gcpro2, gcpro3;
5222       char tempbuf[1024]; /* some random amount */
5223
5224       instream = make_fixed_buffer_input_stream ((unsigned char *) ptr, len);
5225       da_outstream = make_dynarr_output_stream
5226         ((unsigned_char_dynarr *) conversion_out_dynarr);
5227       outstream =
5228         make_encoding_output_stream (XLSTREAM (da_outstream), coding_system);
5229       istr = XLSTREAM (instream);
5230       ostr = XLSTREAM (outstream);
5231       GCPRO3 (instream, outstream, da_outstream);
5232       while (1)
5233         {
5234           int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
5235           if (!size_in_bytes)
5236             break;
5237           Lstream_write (ostr, tempbuf, size_in_bytes);
5238         }
5239       Lstream_close (istr);
5240       Lstream_close (ostr);
5241       UNGCPRO;
5242       Lstream_delete (istr);
5243       Lstream_delete (ostr);
5244       Lstream_delete (XLSTREAM (da_outstream));
5245     }
5246
5247   *len_out = Dynarr_length (conversion_out_dynarr);
5248   Dynarr_add (conversion_out_dynarr, 0); /* remember to zero-terminate! */
5249   return Dynarr_atp (conversion_out_dynarr, 0);
5250 }
5251
5252 Bufbyte *
5253 convert_from_external_format (CONST Extbyte *ptr,
5254                               Extcount len,
5255                               Bytecount *len_out,
5256                               enum external_data_format fmt)
5257 {
5258   Lisp_Object coding_system = external_data_format_to_coding_system (fmt);
5259
5260   if (!conversion_in_dynarr)
5261     conversion_in_dynarr = Dynarr_new (Bufbyte);
5262   else
5263     Dynarr_reset (conversion_in_dynarr);
5264
5265   if (NILP (coding_system))
5266     {
5267       CONST Extbyte *end = ptr + len;
5268       for (; ptr < end; ptr++)
5269         {
5270           Extbyte c = *ptr;
5271           DECODE_ADD_BINARY_CHAR (c, conversion_in_dynarr);
5272         }
5273     }
5274   else
5275     {
5276       Lisp_Object instream, outstream, da_outstream;
5277       Lstream *istr, *ostr;
5278       struct gcpro gcpro1, gcpro2, gcpro3;
5279       char tempbuf[1024]; /* some random amount */
5280
5281       instream = make_fixed_buffer_input_stream ((unsigned char *) ptr, len);
5282       da_outstream = make_dynarr_output_stream
5283         ((unsigned_char_dynarr *) conversion_in_dynarr);
5284       outstream =
5285         make_decoding_output_stream (XLSTREAM (da_outstream), coding_system);
5286       istr = XLSTREAM (instream);
5287       ostr = XLSTREAM (outstream);
5288       GCPRO3 (instream, outstream, da_outstream);
5289       while (1)
5290         {
5291           int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
5292           if (!size_in_bytes)
5293             break;
5294           Lstream_write (ostr, tempbuf, size_in_bytes);
5295         }
5296       Lstream_close (istr);
5297       Lstream_close (ostr);
5298       UNGCPRO;
5299       Lstream_delete (istr);
5300       Lstream_delete (ostr);
5301       Lstream_delete (XLSTREAM (da_outstream));
5302     }
5303
5304   *len_out = Dynarr_length (conversion_in_dynarr);
5305   Dynarr_add (conversion_in_dynarr, 0); /* remember to zero-terminate! */
5306   return Dynarr_atp (conversion_in_dynarr, 0);
5307 }
5308
5309 \f
5310 /************************************************************************/
5311 /*                             Initialization                           */
5312 /************************************************************************/
5313
5314 void
5315 syms_of_file_coding (void)
5316 {
5317   defsymbol (&Qbuffer_file_coding_system, "buffer-file-coding-system");
5318   deferror (&Qcoding_system_error, "coding-system-error",
5319             "Coding-system error", Qio_error);
5320
5321   DEFSUBR (Fcoding_system_p);
5322   DEFSUBR (Ffind_coding_system);
5323   DEFSUBR (Fget_coding_system);
5324   DEFSUBR (Fcoding_system_list);
5325   DEFSUBR (Fcoding_system_name);
5326   DEFSUBR (Fmake_coding_system);
5327   DEFSUBR (Fcopy_coding_system);
5328   DEFSUBR (Fdefine_coding_system_alias);
5329   DEFSUBR (Fsubsidiary_coding_system);
5330
5331   DEFSUBR (Fcoding_system_type);
5332   DEFSUBR (Fcoding_system_doc_string);
5333 #ifdef MULE
5334   DEFSUBR (Fcoding_system_charset);
5335 #endif
5336   DEFSUBR (Fcoding_system_property);
5337
5338   DEFSUBR (Fcoding_category_list);
5339   DEFSUBR (Fset_coding_priority_list);
5340   DEFSUBR (Fcoding_priority_list);
5341   DEFSUBR (Fset_coding_category_system);
5342   DEFSUBR (Fcoding_category_system);
5343
5344   DEFSUBR (Fdetect_coding_region);
5345   DEFSUBR (Fdecode_coding_region);
5346   DEFSUBR (Fencode_coding_region);
5347 #ifdef MULE
5348   DEFSUBR (Fdecode_shift_jis_char);
5349   DEFSUBR (Fencode_shift_jis_char);
5350   DEFSUBR (Fdecode_big5_char);
5351   DEFSUBR (Fencode_big5_char);
5352 #endif /* MULE */
5353   defsymbol (&Qcoding_system_p, "coding-system-p");
5354   defsymbol (&Qno_conversion, "no-conversion");
5355   defsymbol (&Qraw_text, "raw-text");
5356 #ifdef MULE
5357   defsymbol (&Qbig5, "big5");
5358   defsymbol (&Qshift_jis, "shift-jis");
5359   defsymbol (&Qucs4, "ucs-4");
5360   defsymbol (&Qutf8, "utf-8");
5361   defsymbol (&Qccl, "ccl");
5362   defsymbol (&Qiso2022, "iso2022");
5363 #endif /* MULE */
5364   defsymbol (&Qmnemonic, "mnemonic");
5365   defsymbol (&Qeol_type, "eol-type");
5366   defsymbol (&Qpost_read_conversion, "post-read-conversion");
5367   defsymbol (&Qpre_write_conversion, "pre-write-conversion");
5368
5369   defsymbol (&Qcr, "cr");
5370   defsymbol (&Qlf, "lf");
5371   defsymbol (&Qcrlf, "crlf");
5372   defsymbol (&Qeol_cr, "eol-cr");
5373   defsymbol (&Qeol_lf, "eol-lf");
5374   defsymbol (&Qeol_crlf, "eol-crlf");
5375 #ifdef MULE
5376   defsymbol (&Qcharset_g0, "charset-g0");
5377   defsymbol (&Qcharset_g1, "charset-g1");
5378   defsymbol (&Qcharset_g2, "charset-g2");
5379   defsymbol (&Qcharset_g3, "charset-g3");
5380   defsymbol (&Qforce_g0_on_output, "force-g0-on-output");
5381   defsymbol (&Qforce_g1_on_output, "force-g1-on-output");
5382   defsymbol (&Qforce_g2_on_output, "force-g2-on-output");
5383   defsymbol (&Qforce_g3_on_output, "force-g3-on-output");
5384   defsymbol (&Qno_iso6429, "no-iso6429");
5385   defsymbol (&Qinput_charset_conversion, "input-charset-conversion");
5386   defsymbol (&Qoutput_charset_conversion, "output-charset-conversion");
5387
5388   defsymbol (&Qshort, "short");
5389   defsymbol (&Qno_ascii_eol, "no-ascii-eol");
5390   defsymbol (&Qno_ascii_cntl, "no-ascii-cntl");
5391   defsymbol (&Qseven, "seven");
5392   defsymbol (&Qlock_shift, "lock-shift");
5393   defsymbol (&Qescape_quoted, "escape-quoted");
5394 #endif /* MULE */
5395   defsymbol (&Qencode, "encode");
5396   defsymbol (&Qdecode, "decode");
5397
5398 #ifdef MULE
5399   defsymbol (&Qctext, "ctext");
5400   defsymbol (&coding_category_symbol[CODING_CATEGORY_SHIFT_JIS],
5401              "shift-jis");
5402   defsymbol (&coding_category_symbol[CODING_CATEGORY_BIG5],
5403              "big5");
5404   defsymbol (&coding_category_symbol[CODING_CATEGORY_UCS4],
5405              "ucs-4");
5406   defsymbol (&coding_category_symbol[CODING_CATEGORY_UTF8],
5407              "utf-8");
5408   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_7],
5409              "iso-7");
5410   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_DESIGNATE],
5411              "iso-8-designate");
5412   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_1],
5413              "iso-8-1");
5414   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_2],
5415              "iso-8-2");
5416   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_LOCK_SHIFT],
5417              "iso-lock-shift");
5418 #endif /* MULE */
5419   defsymbol (&coding_category_symbol[CODING_CATEGORY_NO_CONVERSION],
5420              "no-conversion");
5421 }
5422
5423 void
5424 lstream_type_create_file_coding (void)
5425 {
5426   LSTREAM_HAS_METHOD (decoding, reader);
5427   LSTREAM_HAS_METHOD (decoding, writer);
5428   LSTREAM_HAS_METHOD (decoding, rewinder);
5429   LSTREAM_HAS_METHOD (decoding, seekable_p);
5430   LSTREAM_HAS_METHOD (decoding, flusher);
5431   LSTREAM_HAS_METHOD (decoding, closer);
5432   LSTREAM_HAS_METHOD (decoding, marker);
5433
5434   LSTREAM_HAS_METHOD (encoding, reader);
5435   LSTREAM_HAS_METHOD (encoding, writer);
5436   LSTREAM_HAS_METHOD (encoding, rewinder);
5437   LSTREAM_HAS_METHOD (encoding, seekable_p);
5438   LSTREAM_HAS_METHOD (encoding, flusher);
5439   LSTREAM_HAS_METHOD (encoding, closer);
5440   LSTREAM_HAS_METHOD (encoding, marker);
5441 }
5442
5443 void
5444 vars_of_file_coding (void)
5445 {
5446   int i;
5447
5448   /* Initialize to something reasonable ... */
5449   for (i = 0; i <= CODING_CATEGORY_LAST; i++)
5450     {
5451       coding_category_system[i] = Qnil;
5452       coding_category_by_priority[i] = i;
5453     }
5454
5455   Fprovide (intern ("file-coding"));
5456
5457   DEFVAR_LISP ("keyboard-coding-system", &Vkeyboard_coding_system /*
5458 Coding system used for TTY keyboard input.
5459 Not used under a windowing system.
5460 */ );
5461   Vkeyboard_coding_system = Qnil;
5462
5463   DEFVAR_LISP ("terminal-coding-system", &Vterminal_coding_system /*
5464 Coding system used for TTY display output.
5465 Not used under a windowing system.
5466 */ );
5467   Vterminal_coding_system = Qnil;
5468
5469   DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read /*
5470 Overriding coding system used when writing a file or process.
5471 You should *bind* this, not set it.  If this is non-nil, it specifies
5472 the coding system that will be used when a file or process is read
5473 in, and overrides `buffer-file-coding-system-for-read',
5474 `insert-file-contents-pre-hook', etc.  Use those variables instead of
5475 this one for permanent changes to the environment.
5476 */ );
5477   Vcoding_system_for_read = Qnil;
5478
5479   DEFVAR_LISP ("coding-system-for-write",
5480                &Vcoding_system_for_write /*
5481 Overriding coding system used when writing a file or process.
5482 You should *bind* this, not set it.  If this is non-nil, it specifies
5483 the coding system that will be used when a file or process is wrote
5484 in, and overrides `buffer-file-coding-system',
5485 `write-region-pre-hook', etc.  Use those variables instead of this one
5486 for permanent changes to the environment.
5487 */ );
5488   Vcoding_system_for_write = Qnil;
5489
5490   DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system /*
5491 Coding system used to convert pathnames when accessing files.
5492 */ );
5493   Vfile_name_coding_system = Qnil;
5494
5495   DEFVAR_BOOL ("enable-multibyte-characters", &enable_multibyte_characters /*
5496 Non-nil means the buffer contents are regarded as multi-byte form
5497 of characters, not a binary code.  This affects the display, file I/O,
5498 and behaviors of various editing commands.
5499
5500 Setting this to nil does not do anything.
5501 */ );
5502   enable_multibyte_characters = 1;
5503 }
5504
5505 void
5506 complex_vars_of_file_coding (void)
5507 {
5508   staticpro (&Vcoding_system_hash_table);
5509   Vcoding_system_hash_table =
5510     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
5511
5512   the_codesys_prop_dynarr = Dynarr_new (codesys_prop);
5513
5514 #define DEFINE_CODESYS_PROP(Prop_Type, Sym) do  \
5515 {                                               \
5516   struct codesys_prop csp;                      \
5517   csp.sym = (Sym);                              \
5518   csp.prop_type = (Prop_Type);                  \
5519   Dynarr_add (the_codesys_prop_dynarr, csp);    \
5520 } while (0)
5521
5522   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qmnemonic);
5523   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_type);
5524   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_cr);
5525   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_crlf);
5526   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_lf);
5527   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpost_read_conversion);
5528   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpre_write_conversion);
5529 #ifdef MULE
5530   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g0);
5531   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g1);
5532   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g2);
5533   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g3);
5534   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g0_on_output);
5535   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g1_on_output);
5536   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g2_on_output);
5537   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g3_on_output);
5538   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qshort);
5539   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_eol);
5540   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_cntl);
5541   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qseven);
5542   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qlock_shift);
5543   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_iso6429);
5544   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qescape_quoted);
5545   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qinput_charset_conversion);
5546   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qoutput_charset_conversion);
5547
5548   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qencode);
5549   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qdecode);
5550 #endif /* MULE */
5551   /* Need to create this here or we're really screwed. */
5552   Fmake_coding_system
5553     (Qraw_text, Qno_conversion,
5554      build_string ("Raw text, which means it converts only line-break-codes."),
5555      list2 (Qmnemonic, build_string ("Raw")));
5556
5557   Fmake_coding_system
5558     (Qbinary, Qno_conversion,
5559      build_string ("Binary, which means it does not convert anything."),
5560      list4 (Qeol_type, Qlf,
5561             Qmnemonic, build_string ("Binary")));
5562
5563 #ifdef UTF2000
5564   Fmake_coding_system
5565     (Qutf8, Qutf8,
5566      build_string ("Coding-system of ISO/IEC 10646 UTF-8."),
5567      list2 (Qmnemonic, build_string ("UTF8")));
5568 #endif
5569
5570   Fdefine_coding_system_alias (Qno_conversion, Qraw_text);
5571
5572   /* Need this for bootstrapping */
5573   coding_category_system[CODING_CATEGORY_NO_CONVERSION] =
5574     Fget_coding_system (Qraw_text);
5575
5576 #ifdef UTF2000
5577   coding_category_system[CODING_CATEGORY_UTF8]
5578    = Fget_coding_system (Qutf8);
5579 #endif
5580 }