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