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