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