This commit was manufactured by cvs2svn to create branch 'utf-2000'.
[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       int base;
3222
3223       while (!NILP (rest))
3224         {                     
3225           cell = Fcar (rest);
3226           ccs = Fcar (cell);
3227           if (NILP (ccs = Ffind_charset (ccs)))
3228             continue;
3229
3230           cell = Fcdr (cell);
3231           ret = Fcar (cell);
3232           if (STRINGP (ret))
3233             pat = ret;
3234           else
3235             continue;
3236
3237           cell = Fcdr (cell);
3238           cell = Fcdr (cell);
3239           ret = Fcar (cell);
3240           if (EQ (ret, Qd))
3241             {
3242               pat = concat3 (build_string ("^&"),
3243                              pat, build_string ("\\([0-9]+\\)$"));
3244               base = 10;
3245             }
3246           else if (EQ (ret, Qx))
3247             {
3248               pat = concat3 (build_string ("^&"),
3249                              pat, build_string ("\\([0-9a-f]+\\)$"));
3250               base = 16;
3251             }
3252           else if (EQ (ret, QX))
3253             {
3254               pat = concat3 (build_string ("^&"),
3255                              pat, build_string ("\\([0-9A-F]+\\)$"));
3256               base = 16;
3257             }
3258           else
3259             continue;
3260
3261           if (!NILP (Fstring_match (pat, string, Qnil, Qnil)))
3262             {
3263               int code
3264                 = XINT (Fstring_to_number
3265                         (Fsubstring (string,
3266                                      Fmatch_beginning (make_int (1)),
3267                                      Fmatch_end (make_int (1))),
3268                          make_int (base)));
3269
3270               DECODE_ADD_UCS_CHAR (DECODE_CHAR (ccs, code), dst);
3271               goto decoded;
3272             }
3273           rest = Fcdr (rest);
3274         }
3275       if (!NILP (Fstring_match (build_string ("^&MCS-\\([0-9A-F]+\\)$"),
3276                                 string, Qnil, Qnil)))
3277         {
3278           int code
3279             = XINT (Fstring_to_number
3280                     (Fsubstring (string,
3281                                  Fmatch_beginning (make_int (1)),
3282                                  Fmatch_end (make_int (1))),
3283                      make_int (16)));
3284
3285           DECODE_ADD_UCS_CHAR (code, dst);
3286         }
3287       else
3288         {
3289           Dynarr_add_many (dst, str->er_buf, str->er_counter);
3290           Dynarr_add (dst, ';');
3291         }
3292     decoded:
3293       str->er_counter = 0;
3294     }
3295   else if ( (str->er_counter >= 16) || (c >= 0x7F) )
3296     {
3297       Dynarr_add_many (dst, str->er_buf, str->er_counter);
3298       str->er_counter = 0;
3299       DECODE_ADD_UCS_CHAR (c, dst);
3300     }
3301   else
3302     str->er_buf[str->er_counter++] = c;
3303 }
3304
3305 void char_encode_as_entity_reference (Emchar ch, char* buf);
3306 void
3307 char_encode_as_entity_reference (Emchar ch, char* buf)
3308 {
3309   Lisp_Object rest = Vcoded_charset_entity_reference_alist;
3310   Lisp_Object cell;
3311   Lisp_Object ccs;
3312   int format_columns, idx;
3313   char format[18];
3314
3315   while (!NILP (rest))
3316     {
3317       cell = Fcar (rest);
3318       ccs = Fcar (cell);
3319       if (!NILP (ccs = Ffind_charset (ccs)))
3320         {
3321           int code_point = charset_code_point (ccs, ch);
3322
3323           if ( code_point >= 0 )
3324             {
3325               Lisp_Object ret;
3326
3327               cell = Fcdr (cell);
3328               ret = Fcar (cell);
3329               if (STRINGP (ret) && ((idx = XSTRING_LENGTH (ret)) <= 6))
3330                 {
3331                   format[0] = '&';
3332                   strncpy (&format[1], XSTRING_DATA (ret), idx);
3333                   idx++;
3334                 }
3335               else
3336                 continue;
3337
3338               cell = Fcdr (cell);
3339               ret = Fcar (cell);
3340               if (INTP (ret))
3341                 {
3342                   format[idx++] = '%';
3343                   format_columns = XINT (ret);
3344                   if ( (2 <= format_columns) && (format_columns <= 8) )
3345                     {
3346                       format [idx++] = '0';
3347                       format [idx++] = '0' + format_columns;
3348                     }
3349                 }
3350
3351               cell = Fcdr (cell);
3352               ret = Fcar (cell);
3353               if (EQ (ret, Qd))
3354                 format [idx++] = 'd';
3355               else if (EQ (ret, Qx))
3356                 format [idx++] = 'x';
3357               else if (EQ (ret, QX))
3358                 format [idx++] = 'X';
3359               else
3360                 continue;
3361               format [idx++] = ';';
3362               format [idx++] = 0;
3363
3364               sprintf (buf, format, code_point);
3365               return;
3366             }
3367         }
3368       rest = Fcdr (rest);
3369     }
3370   sprintf (buf, "&MCS-%08X;", ch);
3371 }
3372
3373 \f
3374 /************************************************************************/
3375 /*                          character composition                       */
3376 /************************************************************************/
3377 extern Lisp_Object Qcomposition;
3378
3379 INLINE_HEADER void
3380 COMPOSE_FLUSH_CHARS (struct decoding_stream *str, unsigned_char_dynarr* dst);
3381 INLINE_HEADER void
3382 COMPOSE_FLUSH_CHARS (struct decoding_stream *str, unsigned_char_dynarr* dst)
3383 {
3384   unsigned i;
3385
3386   for (i = 0; i < str->combined_char_count; i++)
3387     decode_add_er_char (str, str->combined_chars[i], dst);
3388   str->combined_char_count = 0;
3389   str->combining_table = Qnil;
3390 }
3391
3392 void COMPOSE_ADD_CHAR (struct decoding_stream *str, Emchar character,
3393                        unsigned_char_dynarr* dst);
3394 void
3395 COMPOSE_ADD_CHAR (struct decoding_stream *str,
3396                   Emchar character, unsigned_char_dynarr* dst)
3397 {
3398   if (CODING_SYSTEM_DISABLE_COMPOSITION (str->codesys))
3399     decode_add_er_char (str, character, dst);
3400   else if (!CONSP (str->combining_table))
3401     {
3402       Lisp_Object ret
3403         = Fget_char_attribute (make_char (character), Qcomposition, Qnil);
3404
3405       if (NILP (ret))
3406         decode_add_er_char (str, character, dst);
3407       else
3408         {
3409           str->combined_chars[0] = character;
3410           str->combined_char_count = 1;
3411           str->combining_table = ret;
3412         }
3413     }
3414   else
3415     {
3416       Lisp_Object ret
3417         = Fcdr (Fassq (make_char (character), str->combining_table));
3418
3419       if (CHARP (ret))
3420         {
3421           Emchar char2 = XCHARVAL (ret);
3422           ret = Fget_char_attribute (make_char (character), Qcomposition,
3423                                      Qnil);
3424           if (NILP (ret))
3425             {
3426               decode_add_er_char (str, character, dst);
3427               str->combined_char_count = 0;
3428               str->combining_table = Qnil;
3429             }
3430           else
3431             {
3432               str->combined_chars[0] = char2;
3433               str->combined_char_count = 1;
3434               str->combining_table = ret;
3435             }
3436         }
3437       else
3438         {
3439           COMPOSE_FLUSH_CHARS (str, dst);
3440           decode_add_er_char (str, character, dst);
3441         }
3442     }
3443 }
3444 #else /* not UTF2000 */
3445 #define COMPOSE_FLUSH_CHARS(str, dst)
3446 #define COMPOSE_ADD_CHAR(str, ch, dst) DECODE_ADD_UCS_CHAR (ch, dst)
3447 #endif /* UTF2000 */
3448
3449 \f
3450 /************************************************************************/
3451 /*                          Shift-JIS methods                           */
3452 /************************************************************************/
3453
3454 /* Shift-JIS is a coding system encoding three character sets: ASCII, right
3455    half of JISX0201-Kana, and JISX0208.  An ASCII character is encoded
3456    as is.  A character of JISX0201-Kana (DIMENSION1_CHARS94 character set) is
3457    encoded by "position-code + 0x80".  A character of JISX0208
3458    (DIMENSION2_CHARS94 character set) is encoded in 2-byte but two
3459    position-codes are divided and shifted so that it fit in the range
3460    below.
3461
3462    --- CODE RANGE of Shift-JIS ---
3463    (character set)      (range)
3464    ASCII                0x00 .. 0x7F
3465    JISX0201-Kana        0xA0 .. 0xDF
3466    JISX0208 (1st byte)  0x80 .. 0x9F and 0xE0 .. 0xEF
3467             (2nd byte)  0x40 .. 0x7E and 0x80 .. 0xFC
3468    -------------------------------
3469
3470 */
3471
3472 /* Is this the first byte of a Shift-JIS two-byte char? */
3473
3474 #define BYTE_SJIS_TWO_BYTE_1_P(c) \
3475   (((c) >= 0x81 && (c) <= 0x9F) || ((c) >= 0xE0 && (c) <= 0xEF))
3476
3477 /* Is this the second byte of a Shift-JIS two-byte char? */
3478
3479 #define BYTE_SJIS_TWO_BYTE_2_P(c) \
3480   (((c) >= 0x40 && (c) <= 0x7E) || ((c) >= 0x80 && (c) <= 0xFC))
3481
3482 #define BYTE_SJIS_KATAKANA_P(c) \
3483   ((c) >= 0xA1 && (c) <= 0xDF)
3484
3485 static int
3486 detect_coding_sjis (struct detection_state *st, const Extbyte *src, size_t n)
3487 {
3488   while (n--)
3489     {
3490       unsigned char c = *(unsigned char *)src++;
3491       if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
3492         return 0;
3493       if (st->shift_jis.in_second_byte)
3494         {
3495           st->shift_jis.in_second_byte = 0;
3496           if (c < 0x40)
3497             return 0;
3498         }
3499       else if ((c >= 0x80 && c < 0xA0) || c >= 0xE0)
3500         st->shift_jis.in_second_byte = 1;
3501     }
3502   return CODING_CATEGORY_SHIFT_JIS_MASK;
3503 }
3504
3505 /* Convert Shift-JIS data to internal format. */
3506
3507 static void
3508 decode_coding_sjis (Lstream *decoding, const Extbyte *src,
3509                     unsigned_char_dynarr *dst, size_t n)
3510 {
3511   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
3512   unsigned int flags  = str->flags;
3513   unsigned int cpos   = str->cpos;
3514   eol_type_t eol_type = str->eol_type;
3515
3516   while (n--)
3517     {
3518       unsigned char c = *(unsigned char *)src++;
3519
3520       if (cpos)
3521         {
3522           /* Previous character was first byte of Shift-JIS Kanji char. */
3523           if (BYTE_SJIS_TWO_BYTE_2_P (c))
3524             {
3525               unsigned char e1, e2;
3526
3527               DECODE_SJIS (cpos, c, e1, e2);
3528 #ifdef UTF2000
3529               DECODE_ADD_UCS_CHAR(MAKE_CHAR(Vcharset_japanese_jisx0208,
3530                                             e1 & 0x7F,
3531                                             e2 & 0x7F), dst);
3532 #else
3533               Dynarr_add (dst, LEADING_BYTE_JAPANESE_JISX0208);
3534               Dynarr_add (dst, e1);
3535               Dynarr_add (dst, e2);
3536 #endif
3537             }
3538           else
3539             {
3540               DECODE_ADD_BINARY_CHAR (cpos, dst);
3541               DECODE_ADD_BINARY_CHAR (c, dst);
3542             }
3543           cpos = 0;
3544         }
3545       else
3546         {
3547           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
3548           if (BYTE_SJIS_TWO_BYTE_1_P (c))
3549             cpos = c;
3550           else if (BYTE_SJIS_KATAKANA_P (c))
3551             {
3552 #ifdef UTF2000
3553               DECODE_ADD_UCS_CHAR(MAKE_CHAR(Vcharset_katakana_jisx0201,
3554                                             c & 0x7F, 0), dst);
3555 #else
3556               Dynarr_add (dst, LEADING_BYTE_KATAKANA_JISX0201);
3557               Dynarr_add (dst, c);
3558 #endif
3559             }
3560 #ifdef UTF2000
3561           else if (c > 32)
3562             DECODE_ADD_UCS_CHAR(MAKE_CHAR(Vcharset_latin_jisx0201,
3563                                           c, 0), dst);
3564 #endif
3565           else
3566             DECODE_ADD_BINARY_CHAR (c, dst);
3567         }
3568     label_continue_loop:;
3569     }
3570
3571   DECODE_HANDLE_END_OF_CONVERSION (flags, cpos, dst);
3572
3573   str->flags = flags;
3574   str->cpos  = cpos;
3575 }
3576
3577 /* Convert internal character representation to Shift_JIS. */
3578
3579 void
3580 char_encode_shift_jis (struct encoding_stream *str, Emchar ch,
3581                        unsigned_char_dynarr *dst, unsigned int *flags)
3582 {
3583   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
3584
3585   if (ch == '\n')
3586     {
3587       if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
3588         Dynarr_add (dst, '\r');
3589       if (eol_type != EOL_CR)
3590         Dynarr_add (dst, ch);
3591     }
3592   else
3593     {
3594       unsigned int s1, s2;
3595 #ifdef UTF2000
3596       int code_point = charset_code_point (Vcharset_latin_jisx0201, ch);
3597
3598       if (code_point >= 0)
3599         Dynarr_add (dst, code_point);
3600       else if ((code_point
3601                 = charset_code_point (Vcharset_japanese_jisx0208_1990, ch))
3602                >= 0)
3603         {
3604           ENCODE_SJIS ((code_point >> 8) | 0x80,
3605                        (code_point & 0xFF) | 0x80, s1, s2);
3606           Dynarr_add (dst, s1);
3607           Dynarr_add (dst, s2);
3608         }
3609       else if ((code_point
3610                 = charset_code_point (Vcharset_katakana_jisx0201, ch))
3611                >= 0)
3612         Dynarr_add (dst, code_point | 0x80);
3613       else if ((code_point
3614                 = charset_code_point (Vcharset_japanese_jisx0208, ch))
3615                >= 0)
3616         {
3617           ENCODE_SJIS ((code_point >> 8) | 0x80,
3618                        (code_point & 0xFF) | 0x80, s1, s2);
3619           Dynarr_add (dst, s1);
3620           Dynarr_add (dst, s2);
3621         }
3622       else if ((code_point = charset_code_point (Vcharset_ascii, ch))
3623                >= 0)
3624         Dynarr_add (dst, code_point);
3625       else
3626         Dynarr_add (dst, '?');
3627 #else
3628       Lisp_Object charset;
3629       unsigned int c1, c2;
3630
3631       BREAKUP_CHAR (ch, charset, c1, c2);
3632           
3633       if (EQ(charset, Vcharset_katakana_jisx0201))
3634         {
3635           Dynarr_add (dst, c1 | 0x80);
3636         }
3637       else if (c2 == 0)
3638         {
3639           Dynarr_add (dst, c1);
3640         }
3641       else if (EQ(charset, Vcharset_japanese_jisx0208))
3642         {
3643           ENCODE_SJIS (c1 | 0x80, c2 | 0x80, s1, s2);
3644           Dynarr_add (dst, s1);
3645           Dynarr_add (dst, s2);
3646         }
3647       else
3648         Dynarr_add (dst, '?');
3649 #endif
3650     }
3651 }
3652
3653 void
3654 char_finish_shift_jis (struct encoding_stream *str, unsigned_char_dynarr *dst,
3655                        unsigned int *flags)
3656 {
3657 }
3658
3659 DEFUN ("decode-shift-jis-char", Fdecode_shift_jis_char, 1, 1, 0, /*
3660 Decode a JISX0208 character of Shift-JIS coding-system.
3661 CODE is the character code in Shift-JIS as a cons of type bytes.
3662 Return the corresponding character.
3663 */
3664        (code))
3665 {
3666   unsigned char c1, c2, s1, s2;
3667
3668   CHECK_CONS (code);
3669   CHECK_INT (XCAR (code));
3670   CHECK_INT (XCDR (code));
3671   s1 = XINT (XCAR (code));
3672   s2 = XINT (XCDR (code));
3673   if (BYTE_SJIS_TWO_BYTE_1_P (s1) &&
3674       BYTE_SJIS_TWO_BYTE_2_P (s2))
3675     {
3676       DECODE_SJIS (s1, s2, c1, c2);
3677       return make_char (MAKE_CHAR (Vcharset_japanese_jisx0208,
3678                                    c1 & 0x7F, c2 & 0x7F));
3679     }
3680   else
3681     return Qnil;
3682 }
3683
3684 DEFUN ("encode-shift-jis-char", Fencode_shift_jis_char, 1, 1, 0, /*
3685 Encode a JISX0208 character CHARACTER to SHIFT-JIS coding-system.
3686 Return the corresponding character code in SHIFT-JIS as a cons of two bytes.
3687 */
3688        (character))
3689 {
3690   Lisp_Object charset;
3691   int c1, c2, s1, s2;
3692
3693   CHECK_CHAR_COERCE_INT (character);
3694   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
3695   if (EQ (charset, Vcharset_japanese_jisx0208))
3696     {
3697       ENCODE_SJIS (c1 | 0x80, c2 | 0x80, s1, s2);
3698       return Fcons (make_int (s1), make_int (s2));
3699     }
3700   else
3701     return Qnil;
3702 }
3703
3704 \f
3705 /************************************************************************/
3706 /*                            Big5 methods                              */
3707 /************************************************************************/
3708
3709 /* BIG5 is a coding system encoding two character sets: ASCII and
3710    Big5.  An ASCII character is encoded as is.  Big5 is a two-byte
3711    character set and is encoded in two-byte.
3712
3713    --- CODE RANGE of BIG5 ---
3714    (character set)      (range)
3715    ASCII                0x00 .. 0x7F
3716    Big5 (1st byte)      0xA1 .. 0xFE
3717         (2nd byte)      0x40 .. 0x7E and 0xA1 .. 0xFE
3718    --------------------------
3719
3720    Since the number of characters in Big5 is larger than maximum
3721    characters in Emacs' charset (96x96), it can't be handled as one
3722    charset.  So, in Emacs, Big5 is divided into two: `charset-big5-1'
3723    and `charset-big5-2'.  Both <type>s are DIMENSION2_CHARS94.  The former
3724    contains frequently used characters and the latter contains less
3725    frequently used characters.  */
3726
3727 #ifdef UTF2000
3728 #define BYTE_BIG5_TWO_BYTE_1_P(c) \
3729   ((c) >= 0x81 && (c) <= 0xFE)
3730 #else
3731 #define BYTE_BIG5_TWO_BYTE_1_P(c) \
3732   ((c) >= 0xA1 && (c) <= 0xFE)
3733 #endif
3734
3735 /* Is this the second byte of a Shift-JIS two-byte char? */
3736
3737 #define BYTE_BIG5_TWO_BYTE_2_P(c) \
3738   (((c) >= 0x40 && (c) <= 0x7E) || ((c) >= 0xA1 && (c) <= 0xFE))
3739
3740 /* Number of Big5 characters which have the same code in 1st byte.  */
3741
3742 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
3743
3744 /* Code conversion macros.  These are macros because they are used in
3745    inner loops during code conversion.
3746
3747    Note that temporary variables in macros introduce the classic
3748    dynamic-scoping problems with variable names.  We use capital-
3749    lettered variables in the assumption that XEmacs does not use
3750    capital letters in variables except in a very formalized way
3751    (e.g. Qstring). */
3752
3753 /* Convert Big5 code (b1, b2) into its internal string representation
3754    (lb, c1, c2). */
3755
3756 /* There is a much simpler way to split the Big5 charset into two.
3757    For the moment I'm going to leave the algorithm as-is because it
3758    claims to separate out the most-used characters into a single
3759    charset, which perhaps will lead to optimizations in various
3760    places.
3761
3762    The way the algorithm works is something like this:
3763
3764    Big5 can be viewed as a 94x157 charset, where the row is
3765    encoded into the bytes 0xA1 .. 0xFE and the column is encoded
3766    into the bytes 0x40 .. 0x7E and 0xA1 .. 0xFE.  As for frequency,
3767    the split between low and high column numbers is apparently
3768    meaningless; ascending rows produce less and less frequent chars.
3769    Therefore, we assign the lower half of rows (0xA1 .. 0xC8) to
3770    the first charset, and the upper half (0xC9 .. 0xFE) to the
3771    second.  To do the conversion, we convert the character into
3772    a single number where 0 .. 156 is the first row, 157 .. 313
3773    is the second, etc.  That way, the characters are ordered by
3774    decreasing frequency.  Then we just chop the space in two
3775    and coerce the result into a 94x94 space.
3776    */
3777
3778 #define DECODE_BIG5(b1, b2, lb, c1, c2) do                              \
3779 {                                                                       \
3780   int B1 = b1, B2 = b2;                                                 \
3781   unsigned int I                                                        \
3782     = (B1 - 0xA1) * BIG5_SAME_ROW + B2 - (B2 < 0x7F ? 0x40 : 0x62);     \
3783                                                                         \
3784   if (B1 < 0xC9)                                                        \
3785     {                                                                   \
3786       lb = LEADING_BYTE_CHINESE_BIG5_1;                                 \
3787     }                                                                   \
3788   else                                                                  \
3789     {                                                                   \
3790       lb = LEADING_BYTE_CHINESE_BIG5_2;                                 \
3791       I -= (BIG5_SAME_ROW) * (0xC9 - 0xA1);                             \
3792     }                                                                   \
3793   c1 = I / (0xFF - 0xA1) + 0xA1;                                        \
3794   c2 = I % (0xFF - 0xA1) + 0xA1;                                        \
3795 } while (0)
3796
3797 /* Convert the internal string representation of a Big5 character
3798    (lb, c1, c2) into Big5 code (b1, b2). */
3799
3800 #define ENCODE_BIG5(lb, c1, c2, b1, b2) do                              \
3801 {                                                                       \
3802   unsigned int I = ((c1) - 0xA1) * (0xFF - 0xA1) + ((c2) - 0xA1);       \
3803                                                                         \
3804   if (lb == LEADING_BYTE_CHINESE_BIG5_2)                                \
3805     {                                                                   \
3806       I += BIG5_SAME_ROW * (0xC9 - 0xA1);                               \
3807     }                                                                   \
3808   b1 = I / BIG5_SAME_ROW + 0xA1;                                        \
3809   b2 = I % BIG5_SAME_ROW;                                               \
3810   b2 += b2 < 0x3F ? 0x40 : 0x62;                                        \
3811 } while (0)
3812
3813 static int
3814 detect_coding_big5 (struct detection_state *st, const Extbyte *src, size_t n)
3815 {
3816   while (n--)
3817     {
3818       unsigned char c = *(unsigned char *)src++;
3819       if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO
3820 #ifndef UTF2000
3821           || (c >= 0x80 && c <= 0xA0)
3822 #endif
3823           )
3824         return 0;
3825       if (st->big5.in_second_byte)
3826         {
3827           st->big5.in_second_byte = 0;
3828           if (c < 0x40 || (c >= 0x80 && c <= 0xA0))
3829             return 0;
3830         }
3831       else if (
3832 #ifdef UTF2000
3833                c >= 0x81
3834 #else
3835                c >= 0xA1
3836 #endif
3837                )
3838         st->big5.in_second_byte = 1;
3839     }
3840   return CODING_CATEGORY_BIG5_MASK;
3841 }
3842
3843 /* Convert Big5 data to internal format. */
3844
3845 static void
3846 decode_coding_big5 (Lstream *decoding, const Extbyte *src,
3847                     unsigned_char_dynarr *dst, size_t n)
3848 {
3849   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
3850   unsigned int flags  = str->flags;
3851   unsigned int cpos   = str->cpos;
3852   eol_type_t eol_type = str->eol_type;
3853 #ifdef UTF2000
3854   Lisp_Object ccs
3855     = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (DECODING_STREAM_DATA
3856                                              (decoding)->codesys, 1);
3857 #endif
3858
3859   while (n--)
3860     {
3861       unsigned char c = *(unsigned char *)src++;
3862       if (cpos)
3863         {
3864           /* Previous character was first byte of Big5 char. */
3865           if (BYTE_BIG5_TWO_BYTE_2_P (c))
3866             {
3867 #ifdef UTF2000
3868               int code_point = (cpos << 8) | c;
3869               Emchar char_id = decode_defined_char (ccs, code_point);
3870
3871               if (char_id < 0)
3872                 char_id = DECODE_CHAR (Vcharset_chinese_big5, code_point);
3873               DECODE_ADD_UCS_CHAR (char_id, dst);
3874 #else
3875               unsigned char b1, b2, b3;
3876               DECODE_BIG5 (cpos, c, b1, b2, b3);
3877               Dynarr_add (dst, b1);
3878               Dynarr_add (dst, b2);
3879               Dynarr_add (dst, b3);
3880 #endif
3881             }
3882           else
3883             {
3884               DECODE_ADD_BINARY_CHAR (cpos, dst);
3885               DECODE_ADD_BINARY_CHAR (c, dst);
3886             }
3887           cpos = 0;
3888         }
3889       else
3890         {
3891           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
3892           if (BYTE_BIG5_TWO_BYTE_1_P (c))
3893             {
3894               decode_flush_er_chars (str, dst);
3895               cpos = c;
3896             }
3897           else if ( c < ' ' )
3898             {
3899               decode_flush_er_chars (str, dst);
3900               DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
3901               DECODE_ADD_BINARY_CHAR (c, dst);
3902             }
3903           else
3904             {
3905               /* DECODE_ADD_BINARY_CHAR (c, dst); */
3906               decode_add_er_char (str, c, dst);
3907             }
3908         }
3909     label_continue_loop:;
3910     }
3911
3912   /* DECODE_HANDLE_END_OF_CONVERSION (flags, cpos, dst); */
3913   if (flags & CODING_STATE_END)
3914     {
3915       decode_flush_er_chars (str, dst);
3916       DECODE_OUTPUT_PARTIAL_CHAR (cpos);
3917       if (flags & CODING_STATE_CR)
3918         Dynarr_add (dst, '\r');
3919     }
3920
3921   str->flags = flags;
3922   str->cpos  = cpos;
3923 }
3924
3925 /* Convert internally-formatted data to Big5. */
3926
3927 void
3928 char_encode_big5 (struct encoding_stream *str, Emchar ch,
3929                   unsigned_char_dynarr *dst, unsigned int *flags)
3930 {
3931   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
3932
3933   if (ch == '\n')
3934     {
3935       if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
3936         Dynarr_add (dst, '\r');
3937       if (eol_type != EOL_CR)
3938         Dynarr_add (dst, ch);
3939     }
3940   else
3941     {
3942 #ifdef UTF2000
3943       int code_point;
3944       Lisp_Object ccs
3945         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, 1);
3946
3947       if ((code_point = charset_code_point (Vcharset_ascii, ch)) >= 0)
3948         Dynarr_add (dst, code_point);
3949       else if ((code_point = charset_code_point (ccs, ch)) >= 0)
3950         {
3951           Dynarr_add (dst, code_point >> 8);
3952           Dynarr_add (dst, code_point & 0xFF);
3953         }
3954       else if ((code_point
3955                 = charset_code_point (Vcharset_chinese_big5, ch)) >= 0)
3956         {
3957           Dynarr_add (dst, code_point >> 8);
3958           Dynarr_add (dst, code_point & 0xFF);
3959         }
3960       else if ((code_point
3961                 = charset_code_point (Vcharset_chinese_big5_1, ch)) >= 0)
3962         {
3963           unsigned int I
3964             = ((code_point >> 8) - 33) * (0xFF - 0xA1)
3965             + ((code_point & 0xFF) - 33);
3966           unsigned char b1 = I / BIG5_SAME_ROW + 0xA1;
3967           unsigned char b2 = I % BIG5_SAME_ROW;
3968
3969           b2 += b2 < 0x3F ? 0x40 : 0x62;
3970           Dynarr_add (dst, b1);
3971           Dynarr_add (dst, b2);
3972         }
3973       else if ((code_point
3974                 = charset_code_point (Vcharset_chinese_big5_2, ch)) >= 0)
3975         {
3976           unsigned int I
3977             = ((code_point >> 8) - 33) * (0xFF - 0xA1)
3978             + ((code_point & 0xFF) - 33);
3979           unsigned char b1, b2;
3980
3981           I += BIG5_SAME_ROW * (0xC9 - 0xA1);
3982           b1 = I / BIG5_SAME_ROW + 0xA1;
3983           b2 = I % BIG5_SAME_ROW;
3984           b2 += b2 < 0x3F ? 0x40 : 0x62;
3985           Dynarr_add (dst, b1);
3986           Dynarr_add (dst, b2);
3987         }
3988       else if (CODING_SYSTEM_USE_ENTITY_REFERENCE (str->codesys))
3989         {
3990           char buf[18];
3991
3992           char_encode_as_entity_reference (ch, buf);
3993           Dynarr_add_many (dst, buf, strlen (buf));
3994         }
3995       else
3996         Dynarr_add (dst, '?');
3997 #else
3998 #endif
3999     }
4000 }
4001
4002 void
4003 char_finish_big5 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4004                   unsigned int *flags)
4005 {
4006 }
4007
4008
4009 DEFUN ("decode-big5-char", Fdecode_big5_char, 1, 1, 0, /*
4010 Decode a Big5 character CODE of BIG5 coding-system.
4011 CODE is the character code in BIG5, a cons of two integers.
4012 Return the corresponding character.
4013 */
4014        (code))
4015 {
4016   unsigned char c1, c2, b1, b2;
4017
4018   CHECK_CONS (code);
4019   CHECK_INT (XCAR (code));
4020   CHECK_INT (XCDR (code));
4021   b1 = XINT (XCAR (code));
4022   b2 = XINT (XCDR (code));
4023   if (BYTE_BIG5_TWO_BYTE_1_P (b1) &&
4024       BYTE_BIG5_TWO_BYTE_2_P (b2))
4025     {
4026       Charset_ID leading_byte;
4027       Lisp_Object charset;
4028       DECODE_BIG5 (b1, b2, leading_byte, c1, c2);
4029       charset = CHARSET_BY_LEADING_BYTE (leading_byte);
4030       return make_char (MAKE_CHAR (charset, c1 & 0x7F, c2 & 0x7F));
4031     }
4032   else
4033     return Qnil;
4034 }
4035
4036 DEFUN ("encode-big5-char", Fencode_big5_char, 1, 1, 0, /*
4037 Encode the Big5 character CHARACTER in the BIG5 coding-system.
4038 Return the corresponding character code in Big5.
4039 */
4040        (character))
4041 {
4042   Lisp_Object charset;
4043   int c1, c2, b1, b2;
4044
4045   CHECK_CHAR_COERCE_INT (character);
4046   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
4047   if (EQ (charset, Vcharset_chinese_big5_1) ||
4048       EQ (charset, Vcharset_chinese_big5_2))
4049     {
4050       ENCODE_BIG5 (XCHARSET_LEADING_BYTE (charset), c1 | 0x80, c2 | 0x80,
4051                    b1, b2);
4052       return Fcons (make_int (b1), make_int (b2));
4053     }
4054   else
4055     return Qnil;
4056 }
4057
4058 \f
4059 /************************************************************************/
4060 /*                           UCS-4 methods                              */
4061 /************************************************************************/
4062
4063 static int
4064 detect_coding_ucs4 (struct detection_state *st, const Extbyte *src, size_t n)
4065 {
4066   while (n--)
4067     {
4068       unsigned char c = *(unsigned char *)src++;
4069       switch (st->ucs4.in_byte)
4070         {
4071         case 0:
4072           if (c >= 128)
4073             return 0;
4074           else
4075             st->ucs4.in_byte++;
4076           break;
4077         case 3:
4078           st->ucs4.in_byte = 0;
4079           break;
4080         default:
4081           st->ucs4.in_byte++;
4082         }
4083     }
4084   return CODING_CATEGORY_UCS4_MASK;
4085 }
4086
4087 static void
4088 decode_coding_ucs4 (Lstream *decoding, const Extbyte *src,
4089                     unsigned_char_dynarr *dst, size_t n)
4090 {
4091   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4092   unsigned int flags = str->flags;
4093   unsigned int cpos  = str->cpos;
4094   unsigned char counter = str->counter;
4095
4096   while (n--)
4097     {
4098       unsigned char c = *(unsigned char *)src++;
4099       switch (counter)
4100         {
4101         case 0:
4102           cpos = c;
4103           counter = 3;
4104           break;
4105         case 1:
4106           DECODE_ADD_UCS_CHAR ((cpos << 8) | c, dst);
4107           cpos = 0;
4108           counter = 0;
4109           break;
4110         default:
4111           cpos = ( cpos << 8 ) | c;
4112           counter--;
4113         }
4114     }
4115   if (counter & CODING_STATE_END)
4116     DECODE_OUTPUT_PARTIAL_CHAR (cpos);
4117
4118   str->flags    = flags;
4119   str->cpos     = cpos;
4120   str->counter  = counter;
4121 }
4122
4123 void
4124 char_encode_ucs4 (struct encoding_stream *str, Emchar ch,
4125                   unsigned_char_dynarr *dst, unsigned int *flags)
4126 {
4127   Dynarr_add (dst, ch >> 24);
4128   Dynarr_add (dst, ch >> 16);
4129   Dynarr_add (dst, ch >>  8);
4130   Dynarr_add (dst, ch      );
4131 }
4132
4133 void
4134 char_finish_ucs4 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4135                   unsigned int *flags)
4136 {
4137 }
4138
4139 \f
4140 /************************************************************************/
4141 /*                           UTF-8 methods                              */
4142 /************************************************************************/
4143
4144 static int
4145 detect_coding_utf8 (struct detection_state *st, const Extbyte *src, size_t n)
4146 {
4147   while (n--)
4148     {
4149       unsigned char c = *(unsigned char *)src++;
4150       switch (st->utf8.in_byte)
4151         {
4152         case 0:
4153           if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
4154             return 0;
4155           else if (c >= 0xfc)
4156             st->utf8.in_byte = 5;
4157           else if (c >= 0xf8)
4158             st->utf8.in_byte = 4;
4159           else if (c >= 0xf0)
4160             st->utf8.in_byte = 3;
4161           else if (c >= 0xe0)
4162             st->utf8.in_byte = 2;
4163           else if (c >= 0xc0)
4164             st->utf8.in_byte = 1;
4165           else if (c >= 0x80)
4166             return 0;
4167           break;
4168         default:
4169           if ((c & 0xc0) != 0x80)
4170             return 0;
4171           else
4172             st->utf8.in_byte--;
4173         }
4174     }
4175   return CODING_CATEGORY_UTF8_MASK;
4176 }
4177
4178 static void
4179 decode_output_utf8_partial_char (unsigned char counter,
4180                                  unsigned int cpos,
4181                                  unsigned_char_dynarr *dst)
4182 {
4183   if (counter == 5)
4184     DECODE_ADD_BINARY_CHAR ( (cpos|0xFC), dst);
4185   else if (counter == 4)
4186     {
4187       if (cpos < (1 << 6))
4188         DECODE_ADD_BINARY_CHAR ( (cpos|0xF8), dst);
4189       else
4190         {
4191           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xFC), dst);
4192           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4193         }
4194     }
4195   else if (counter == 3)
4196     {
4197       if (cpos < (1 << 6))
4198         DECODE_ADD_BINARY_CHAR ( (cpos|0xF0), dst);
4199       else if (cpos < (1 << 12))
4200         {
4201           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xF8), dst);
4202           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4203         }
4204       else
4205         {
4206           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xFC), dst);
4207           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4208           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4209         }
4210     }
4211   else if (counter == 2)
4212     {
4213       if (cpos < (1 << 6))
4214         DECODE_ADD_BINARY_CHAR ( (cpos|0xE0), dst);
4215       else if (cpos < (1 << 12))
4216         {
4217           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xF0), dst);
4218           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4219         }
4220       else if (cpos < (1 << 18))
4221         {
4222           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xF8), dst);
4223           DECODE_ADD_BINARY_CHAR ( (((cpos >> 6)&0x3F)|0x80), dst);
4224           DECODE_ADD_BINARY_CHAR ( ( (cpos      &0x3F)|0x80), dst);
4225         }
4226       else
4227         {
4228           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 18)|0xFC), dst);
4229           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4230           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4231           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4232         }
4233     }
4234   else
4235     {
4236       if (cpos < (1 << 6))
4237         DECODE_ADD_BINARY_CHAR ( (cpos|0xC0), dst);
4238       else if (cpos < (1 << 12))
4239         {
4240           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xE0), dst);
4241           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4242         }
4243       else if (cpos < (1 << 18))
4244         {
4245           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xF0), dst);
4246           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4247           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4248         }
4249       else if (cpos < (1 << 24))
4250         {
4251           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 18)|0xF8), dst);
4252           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4253           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4254           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4255         }
4256       else
4257         {
4258           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 24)|0xFC), dst);
4259           DECODE_ADD_BINARY_CHAR ( (((cpos >> 18)&0x3F)|0x80), dst);
4260           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4261           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4262           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4263         }
4264     }
4265 }
4266
4267 static void
4268 decode_coding_utf8 (Lstream *decoding, const Extbyte *src,
4269                     unsigned_char_dynarr *dst, size_t n)
4270 {
4271   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4272   unsigned int flags    = str->flags;
4273   unsigned int cpos     = str->cpos;
4274   eol_type_t eol_type   = str->eol_type;
4275   unsigned char counter = str->counter;
4276 #ifdef UTF2000
4277   Lisp_Object ccs
4278     = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (DECODING_STREAM_DATA
4279                                              (decoding)->codesys, 0);
4280 #endif
4281
4282   while (n--)
4283     {
4284       unsigned char c = *(unsigned char *)src++;
4285       if (counter == 0)
4286         {
4287           if ( c < ' ' )
4288             {
4289               COMPOSE_FLUSH_CHARS (str, dst);
4290               decode_flush_er_chars (str, dst);
4291               DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
4292               DECODE_ADD_UCS_CHAR (c, dst);
4293             }
4294           else if ( c < 0xC0 )
4295             /* decode_add_er_char (str, c, dst); */
4296             COMPOSE_ADD_CHAR (str, c, dst);
4297           else
4298             {
4299               /* decode_flush_er_chars (str, dst); */
4300               if ( c < 0xE0 )
4301                 {
4302                   cpos = c & 0x1f;
4303                   counter = 1;
4304                 }
4305               else if ( c < 0xF0 )
4306                 {
4307                   cpos = c & 0x0f;
4308                   counter = 2;
4309                 }
4310               else if ( c < 0xF8 )
4311                 {
4312                   cpos = c & 0x07;
4313                   counter = 3;
4314                 }
4315               else if ( c < 0xFC )
4316                 {
4317                   cpos = c & 0x03;
4318                   counter = 4;
4319                 }
4320               else
4321                 {
4322                   cpos = c & 0x01;
4323                   counter = 5;
4324                 }
4325             }
4326         }
4327       else if ( (c & 0xC0) == 0x80 )
4328         {
4329           cpos = ( cpos << 6 ) | ( c & 0x3f );
4330           if (counter == 1)
4331             {
4332               Emchar char_id = decode_defined_char (ccs, cpos);
4333
4334               if (char_id < 0)
4335                 char_id = cpos;
4336               COMPOSE_ADD_CHAR (str, char_id, dst);
4337               cpos = 0;
4338               counter = 0;
4339             }
4340           else
4341             counter--;
4342         }
4343       else
4344         {
4345           COMPOSE_FLUSH_CHARS (str, dst);
4346           decode_flush_er_chars (str, dst);
4347           decode_output_utf8_partial_char (counter, cpos, dst);
4348           DECODE_ADD_BINARY_CHAR (c, dst);
4349           cpos = 0;
4350           counter = 0;
4351         }
4352     label_continue_loop:;
4353     }
4354
4355   if (flags & CODING_STATE_END)
4356     {
4357       COMPOSE_FLUSH_CHARS (str, dst);
4358       decode_flush_er_chars (str, dst);
4359       if (counter > 0)
4360         {
4361           decode_output_utf8_partial_char (counter, cpos, dst);
4362           cpos = 0;
4363           counter = 0;
4364         }
4365     }
4366   str->flags    = flags;
4367   str->cpos     = cpos;
4368   str->counter  = counter;
4369 }
4370
4371 void
4372 char_encode_utf8 (struct encoding_stream *str, Emchar ch,
4373                   unsigned_char_dynarr *dst, unsigned int *flags)
4374 {
4375   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
4376
4377   if (ch == '\n')
4378     {
4379       if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
4380         Dynarr_add (dst, '\r');
4381       if (eol_type != EOL_CR)
4382         Dynarr_add (dst, ch);
4383     }
4384   else if (ch <= 0x7f)
4385     {
4386       Dynarr_add (dst, ch);
4387     }
4388   else
4389     {
4390       Lisp_Object ucs_ccs
4391         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, 0);
4392       int code_point = charset_code_point (ucs_ccs, ch);
4393
4394       if ( (code_point < 0) || (code_point > 0x10FFFF) )
4395         {
4396           Lisp_Object map
4397             = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, 1);
4398           Lisp_Object ret;
4399
4400           if ( !NILP (map)
4401                && INTP (ret = Fget_char_attribute (make_char (ch),
4402                                                    map, Qnil)) )
4403             code_point = XINT (ret);
4404           else if ( !NILP (map =
4405                            CODING_SYSTEM_ISO2022_INITIAL_CHARSET
4406                            (str->codesys, 2))
4407                     && INTP (ret = Fget_char_attribute (make_char (ch),
4408                                                         map, Qnil)) )
4409             code_point = XINT (ret);
4410           else if (CODING_SYSTEM_USE_ENTITY_REFERENCE (str->codesys))
4411             {
4412               char buf[18];
4413
4414               char_encode_as_entity_reference (ch, buf);
4415               Dynarr_add_many (dst, buf, strlen (buf));
4416               return;
4417             }
4418           else
4419             code_point = ch;
4420         }
4421       if (code_point <= 0x7ff)
4422         {
4423           Dynarr_add (dst, (code_point >> 6) | 0xc0);
4424           Dynarr_add (dst, (code_point & 0x3f) | 0x80);
4425         }
4426       else if (code_point <= 0xffff)
4427         {
4428           Dynarr_add (dst,  (code_point >> 12) | 0xe0);
4429           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4430           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4431         }
4432       else if (code_point <= 0x1fffff)
4433         {
4434           Dynarr_add (dst,  (code_point >> 18) | 0xf0);
4435           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4436           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4437           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4438         }
4439       else if (code_point <= 0x3ffffff)
4440         {
4441           Dynarr_add (dst,  (code_point >> 24) | 0xf8);
4442           Dynarr_add (dst, ((code_point >> 18) & 0x3f) | 0x80);
4443           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4444           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4445           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4446         }
4447       else
4448         {
4449           Dynarr_add (dst,  (code_point >> 30) | 0xfc);
4450           Dynarr_add (dst, ((code_point >> 24) & 0x3f) | 0x80);
4451           Dynarr_add (dst, ((code_point >> 18) & 0x3f) | 0x80);
4452           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4453           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4454           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4455         }
4456     }
4457 }
4458
4459 void
4460 char_finish_utf8 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4461                   unsigned int *flags)
4462 {
4463 }
4464
4465 \f
4466 /************************************************************************/
4467 /*                           ISO2022 methods                            */
4468 /************************************************************************/
4469
4470 /* The following note describes the coding system ISO2022 briefly.
4471    Since the intention of this note is to help understand the
4472    functions in this file, some parts are NOT ACCURATE or OVERLY
4473    SIMPLIFIED.  For thorough understanding, please refer to the
4474    original document of ISO2022.
4475
4476    ISO2022 provides many mechanisms to encode several character sets
4477    in 7-bit and 8-bit environments.  For 7-bit environments, all text
4478    is encoded using bytes less than 128.  This may make the encoded
4479    text a little bit longer, but the text passes more easily through
4480    several gateways, some of which strip off MSB (Most Signigant Bit).
4481
4482    There are two kinds of character sets: control character set and
4483    graphic character set.  The former contains control characters such
4484    as `newline' and `escape' to provide control functions (control
4485    functions are also provided by escape sequences).  The latter
4486    contains graphic characters such as 'A' and '-'.  Emacs recognizes
4487    two control character sets and many graphic character sets.
4488
4489    Graphic character sets are classified into one of the following
4490    four classes, according to the number of bytes (DIMENSION) and
4491    number of characters in one dimension (CHARS) of the set:
4492    - DIMENSION1_CHARS94
4493    - DIMENSION1_CHARS96
4494    - DIMENSION2_CHARS94
4495    - DIMENSION2_CHARS96
4496
4497    In addition, each character set is assigned an identification tag,
4498    unique for each set, called "final character" (denoted as <F>
4499    hereafter).  The <F> of each character set is decided by ECMA(*)
4500    when it is registered in ISO.  The code range of <F> is 0x30..0x7F
4501    (0x30..0x3F are for private use only).
4502
4503    Note (*): ECMA = European Computer Manufacturers Association
4504
4505    Here are examples of graphic character set [NAME(<F>)]:
4506         o DIMENSION1_CHARS94 -- ASCII('B'), right-half-of-JISX0201('I'), ...
4507         o DIMENSION1_CHARS96 -- right-half-of-ISO8859-1('A'), ...
4508         o DIMENSION2_CHARS94 -- GB2312('A'), JISX0208('B'), ...
4509         o DIMENSION2_CHARS96 -- none for the moment
4510
4511    A code area (1 byte = 8 bits) is divided into 4 areas, C0, GL, C1, and GR.
4512         C0 [0x00..0x1F] -- control character plane 0
4513         GL [0x20..0x7F] -- graphic character plane 0
4514         C1 [0x80..0x9F] -- control character plane 1
4515         GR [0xA0..0xFF] -- graphic character plane 1
4516
4517    A control character set is directly designated and invoked to C0 or
4518    C1 by an escape sequence.  The most common case is that:
4519    - ISO646's  control character set is designated/invoked to C0, and
4520    - ISO6429's control character set is designated/invoked to C1,
4521    and usually these designations/invocations are omitted in encoded
4522    text.  In a 7-bit environment, only C0 can be used, and a control
4523    character for C1 is encoded by an appropriate escape sequence to
4524    fit into the environment.  All control characters for C1 are
4525    defined to have corresponding escape sequences.
4526
4527    A graphic character set is at first designated to one of four
4528    graphic registers (G0 through G3), then these graphic registers are
4529    invoked to GL or GR.  These designations and invocations can be
4530    done independently.  The most common case is that G0 is invoked to
4531    GL, G1 is invoked to GR, and ASCII is designated to G0.  Usually
4532    these invocations and designations are omitted in encoded text.
4533    In a 7-bit environment, only GL can be used.
4534
4535    When a graphic character set of CHARS94 is invoked to GL, codes
4536    0x20 and 0x7F of the GL area work as control characters SPACE and
4537    DEL respectively, and codes 0xA0 and 0xFF of the GR area should not
4538    be used.
4539
4540    There are two ways of invocation: locking-shift and single-shift.
4541    With locking-shift, the invocation lasts until the next different
4542    invocation, whereas with single-shift, the invocation affects the
4543    following character only and doesn't affect the locking-shift
4544    state.  Invocations are done by the following control characters or
4545    escape sequences:
4546
4547    ----------------------------------------------------------------------
4548    abbrev  function                  cntrl escape seq   description
4549    ----------------------------------------------------------------------
4550    SI/LS0  (shift-in)                0x0F  none         invoke G0 into GL
4551    SO/LS1  (shift-out)               0x0E  none         invoke G1 into GL
4552    LS2     (locking-shift-2)         none  ESC 'n'      invoke G2 into GL
4553    LS3     (locking-shift-3)         none  ESC 'o'      invoke G3 into GL
4554    LS1R    (locking-shift-1 right)   none  ESC '~'      invoke G1 into GR (*)
4555    LS2R    (locking-shift-2 right)   none  ESC '}'      invoke G2 into GR (*)
4556    LS3R    (locking-shift 3 right)   none  ESC '|'      invoke G3 into GR (*)
4557    SS2     (single-shift-2)          0x8E  ESC 'N'      invoke G2 for one char
4558    SS3     (single-shift-3)          0x8F  ESC 'O'      invoke G3 for one char
4559    ----------------------------------------------------------------------
4560    (*) These are not used by any known coding system.
4561
4562    Control characters for these functions are defined by macros
4563    ISO_CODE_XXX in `coding.h'.
4564
4565    Designations are done by the following escape sequences:
4566    ----------------------------------------------------------------------
4567    escape sequence      description
4568    ----------------------------------------------------------------------
4569    ESC '(' <F>          designate DIMENSION1_CHARS94<F> to G0
4570    ESC ')' <F>          designate DIMENSION1_CHARS94<F> to G1
4571    ESC '*' <F>          designate DIMENSION1_CHARS94<F> to G2
4572    ESC '+' <F>          designate DIMENSION1_CHARS94<F> to G3
4573    ESC ',' <F>          designate DIMENSION1_CHARS96<F> to G0 (*)
4574    ESC '-' <F>          designate DIMENSION1_CHARS96<F> to G1
4575    ESC '.' <F>          designate DIMENSION1_CHARS96<F> to G2
4576    ESC '/' <F>          designate DIMENSION1_CHARS96<F> to G3
4577    ESC '$' '(' <F>      designate DIMENSION2_CHARS94<F> to G0 (**)
4578    ESC '$' ')' <F>      designate DIMENSION2_CHARS94<F> to G1
4579    ESC '$' '*' <F>      designate DIMENSION2_CHARS94<F> to G2
4580    ESC '$' '+' <F>      designate DIMENSION2_CHARS94<F> to G3
4581    ESC '$' ',' <F>      designate DIMENSION2_CHARS96<F> to G0 (*)
4582    ESC '$' '-' <F>      designate DIMENSION2_CHARS96<F> to G1
4583    ESC '$' '.' <F>      designate DIMENSION2_CHARS96<F> to G2
4584    ESC '$' '/' <F>      designate DIMENSION2_CHARS96<F> to G3
4585    ----------------------------------------------------------------------
4586
4587    In this list, "DIMENSION1_CHARS94<F>" means a graphic character set
4588    of dimension 1, chars 94, and final character <F>, etc...
4589
4590    Note (*): Although these designations are not allowed in ISO2022,
4591    Emacs accepts them on decoding, and produces them on encoding
4592    CHARS96 character sets in a coding system which is characterized as
4593    7-bit environment, non-locking-shift, and non-single-shift.
4594
4595    Note (**): If <F> is '@', 'A', or 'B', the intermediate character
4596    '(' can be omitted.  We refer to this as "short-form" hereafter.
4597
4598    Now you may notice that there are a lot of ways for encoding the
4599    same multilingual text in ISO2022.  Actually, there exist many
4600    coding systems such as Compound Text (used in X11's inter client
4601    communication, ISO-2022-JP (used in Japanese internet), ISO-2022-KR
4602    (used in Korean internet), EUC (Extended UNIX Code, used in Asian
4603    localized platforms), and all of these are variants of ISO2022.
4604
4605    In addition to the above, Emacs handles two more kinds of escape
4606    sequences: ISO6429's direction specification and Emacs' private
4607    sequence for specifying character composition.
4608
4609    ISO6429's direction specification takes the following form:
4610         o CSI ']'      -- end of the current direction
4611         o CSI '0' ']'  -- end of the current direction
4612         o CSI '1' ']'  -- start of left-to-right text
4613         o CSI '2' ']'  -- start of right-to-left text
4614    The control character CSI (0x9B: control sequence introducer) is
4615    abbreviated to the escape sequence ESC '[' in a 7-bit environment.
4616
4617    Character composition specification takes the following form:
4618         o ESC '0' -- start character composition
4619         o ESC '1' -- end character composition
4620    Since these are not standard escape sequences of any ISO standard,
4621    their use with these meanings is restricted to Emacs only.  */
4622
4623 static void
4624 reset_iso2022 (Lisp_Object coding_system, struct iso2022_decoder *iso)
4625 {
4626   int i;
4627
4628   for (i = 0; i < 4; i++)
4629     {
4630       if (!NILP (coding_system))
4631         iso->charset[i] =
4632           XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, i);
4633       else
4634         iso->charset[i] = Qt;
4635       iso->invalid_designated[i] = 0;
4636     }
4637   iso->esc = ISO_ESC_NOTHING;
4638   iso->esc_bytes_index = 0;
4639   iso->register_left = 0;
4640   iso->register_right = 1;
4641   iso->switched_dir_and_no_valid_charset_yet = 0;
4642   iso->invalid_switch_dir = 0;
4643   iso->output_direction_sequence = 0;
4644   iso->output_literally = 0;
4645 #ifdef ENABLE_COMPOSITE_CHARS
4646   if (iso->composite_chars)
4647     Dynarr_reset (iso->composite_chars);
4648 #endif
4649 }
4650
4651 static int
4652 fit_to_be_escape_quoted (unsigned char c)
4653 {
4654   switch (c)
4655     {
4656     case ISO_CODE_ESC:
4657     case ISO_CODE_CSI:
4658     case ISO_CODE_SS2:
4659     case ISO_CODE_SS3:
4660     case ISO_CODE_SO:
4661     case ISO_CODE_SI:
4662       return 1;
4663
4664     default:
4665       return 0;
4666     }
4667 }
4668
4669 /* Parse one byte of an ISO2022 escape sequence.
4670    If the result is an invalid escape sequence, return 0 and
4671    do not change anything in STR.  Otherwise, if the result is
4672    an incomplete escape sequence, update ISO2022.ESC and
4673    ISO2022.ESC_BYTES and return -1.  Otherwise, update
4674    all the state variables (but not ISO2022.ESC_BYTES) and
4675    return 1.
4676
4677    If CHECK_INVALID_CHARSETS is non-zero, check for designation
4678    or invocation of an invalid character set and treat that as
4679    an unrecognized escape sequence. */
4680
4681 static int
4682 parse_iso2022_esc (Lisp_Object codesys, struct iso2022_decoder *iso,
4683                    unsigned char c, unsigned int *flags,
4684                    int check_invalid_charsets)
4685 {
4686   /* (1) If we're at the end of a designation sequence, CS is the
4687      charset being designated and REG is the register to designate
4688      it to.
4689
4690      (2) If we're at the end of a locking-shift sequence, REG is
4691      the register to invoke and HALF (0 == left, 1 == right) is
4692      the half to invoke it into.
4693
4694      (3) If we're at the end of a single-shift sequence, REG is
4695      the register to invoke. */
4696   Lisp_Object cs = Qnil;
4697   int reg, half;
4698
4699   /* NOTE: This code does goto's all over the fucking place.
4700      The reason for this is that we're basically implementing
4701      a state machine here, and hierarchical languages like C
4702      don't really provide a clean way of doing this. */
4703
4704   if (! (*flags & CODING_STATE_ESCAPE))
4705     /* At beginning of escape sequence; we need to reset our
4706        escape-state variables. */
4707     iso->esc = ISO_ESC_NOTHING;
4708
4709   iso->output_literally = 0;
4710   iso->output_direction_sequence = 0;
4711
4712   switch (iso->esc)
4713     {
4714     case ISO_ESC_NOTHING:
4715       iso->esc_bytes_index = 0;
4716       switch (c)
4717         {
4718         case ISO_CODE_ESC:      /* Start escape sequence */
4719           *flags |= CODING_STATE_ESCAPE;
4720           iso->esc = ISO_ESC;
4721           goto not_done;
4722
4723         case ISO_CODE_CSI:      /* ISO6429 (specifying directionality) */
4724           *flags |= CODING_STATE_ESCAPE;
4725           iso->esc = ISO_ESC_5_11;
4726           goto not_done;
4727
4728         case ISO_CODE_SO:       /* locking shift 1 */
4729           reg = 1; half = 0;
4730           goto locking_shift;
4731         case ISO_CODE_SI:       /* locking shift 0 */
4732           reg = 0; half = 0;
4733           goto locking_shift;
4734
4735         case ISO_CODE_SS2:      /* single shift */
4736           reg = 2;
4737           goto single_shift;
4738         case ISO_CODE_SS3:      /* single shift */
4739           reg = 3;
4740           goto single_shift;
4741
4742         default:                        /* Other control characters */
4743           return 0;
4744         }
4745
4746     case ISO_ESC:
4747       switch (c)
4748         {
4749           /**** single shift ****/
4750
4751         case 'N':       /* single shift 2 */
4752           reg = 2;
4753           goto single_shift;
4754         case 'O':       /* single shift 3 */
4755           reg = 3;
4756           goto single_shift;
4757
4758           /**** locking shift ****/
4759
4760         case '~':       /* locking shift 1 right */
4761           reg = 1; half = 1;
4762           goto locking_shift;
4763         case 'n':       /* locking shift 2 */
4764           reg = 2; half = 0;
4765           goto locking_shift;
4766         case '}':       /* locking shift 2 right */
4767           reg = 2; half = 1;
4768           goto locking_shift;
4769         case 'o':       /* locking shift 3 */
4770           reg = 3; half = 0;
4771           goto locking_shift;
4772         case '|':       /* locking shift 3 right */
4773           reg = 3; half = 1;
4774           goto locking_shift;
4775
4776 #ifdef ENABLE_COMPOSITE_CHARS
4777           /**** composite ****/
4778
4779         case '0':
4780           iso->esc = ISO_ESC_START_COMPOSITE;
4781           *flags = (*flags & CODING_STATE_ISO2022_LOCK) |
4782             CODING_STATE_COMPOSITE;
4783           return 1;
4784
4785         case '1':
4786           iso->esc = ISO_ESC_END_COMPOSITE;
4787           *flags = (*flags & CODING_STATE_ISO2022_LOCK) &
4788             ~CODING_STATE_COMPOSITE;
4789           return 1;
4790 #endif /* ENABLE_COMPOSITE_CHARS */
4791
4792           /**** directionality ****/
4793
4794         case '[':
4795           iso->esc = ISO_ESC_5_11;
4796           goto not_done;
4797
4798           /**** designation ****/
4799
4800         case '$':       /* multibyte charset prefix */
4801           iso->esc = ISO_ESC_2_4;
4802           goto not_done;
4803
4804         default:
4805           if (0x28 <= c && c <= 0x2F)
4806             {
4807               iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_8);
4808               goto not_done;
4809             }
4810
4811           /* This function is called with CODESYS equal to nil when
4812              doing coding-system detection. */
4813           if (!NILP (codesys)
4814               && XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
4815               && fit_to_be_escape_quoted (c))
4816             {
4817               iso->esc = ISO_ESC_LITERAL;
4818               *flags &= CODING_STATE_ISO2022_LOCK;
4819               return 1;
4820             }
4821
4822           /* bzzzt! */
4823           return 0;
4824         }
4825
4826
4827
4828       /**** directionality ****/
4829
4830     case ISO_ESC_5_11:          /* ISO6429 direction control */
4831       if (c == ']')
4832         {
4833           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4834           goto directionality;
4835         }
4836       if      (c == '0') iso->esc = ISO_ESC_5_11_0;
4837       else if (c == '1') iso->esc = ISO_ESC_5_11_1;
4838       else if (c == '2') iso->esc = ISO_ESC_5_11_2;
4839       else               return 0;
4840       goto not_done;
4841
4842     case ISO_ESC_5_11_0:
4843       if (c == ']')
4844         {
4845           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4846           goto directionality;
4847         }
4848       return 0;
4849
4850     case ISO_ESC_5_11_1:
4851       if (c == ']')
4852         {
4853           *flags = (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4854           goto directionality;
4855         }
4856       return 0;
4857
4858     case ISO_ESC_5_11_2:
4859       if (c == ']')
4860         {
4861           *flags = (*flags & CODING_STATE_ISO2022_LOCK) | CODING_STATE_R2L;
4862           goto directionality;
4863         }
4864       return 0;
4865
4866     directionality:
4867       iso->esc = ISO_ESC_DIRECTIONALITY;
4868       /* Various junk here to attempt to preserve the direction sequences
4869          literally in the text if they would otherwise be swallowed due
4870          to invalid designations that don't show up as actual charset
4871          changes in the text. */
4872       if (iso->invalid_switch_dir)
4873         {
4874           /* We already inserted a direction switch literally into the
4875              text.  We assume (#### this may not be right) that the
4876              next direction switch is the one going the other way,
4877              and we need to output that literally as well. */
4878           iso->output_literally = 1;
4879           iso->invalid_switch_dir = 0;
4880         }
4881       else
4882         {
4883           int jj;
4884
4885           /* If we are in the thrall of an invalid designation,
4886            then stick the directionality sequence literally into the
4887            output stream so it ends up in the original text again. */
4888           for (jj = 0; jj < 4; jj++)
4889             if (iso->invalid_designated[jj])
4890               break;
4891           if (jj < 4)
4892             {
4893               iso->output_literally = 1;
4894               iso->invalid_switch_dir = 1;
4895             }
4896           else
4897             /* Indicate that we haven't yet seen a valid designation,
4898                so that if a switch-dir is directly followed by an
4899                invalid designation, both get inserted literally. */
4900             iso->switched_dir_and_no_valid_charset_yet = 1;
4901         }
4902       return 1;
4903
4904
4905       /**** designation ****/
4906
4907     case ISO_ESC_2_4:
4908       if (0x28 <= c && c <= 0x2F)
4909         {
4910           iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_4_8);
4911           goto not_done;
4912         }
4913       if (0x40 <= c && c <= 0x42)
4914         {
4915           /* 94^n-set */
4916           cs = CHARSET_BY_ATTRIBUTES (94, -1, c,
4917                                       *flags & CODING_STATE_R2L ?
4918                                       CHARSET_RIGHT_TO_LEFT :
4919                                       CHARSET_LEFT_TO_RIGHT);
4920           reg = 0;
4921           goto designated;
4922         }
4923       return 0;
4924
4925     default:
4926       {
4927         int chars = 0;
4928         int single = 0;
4929
4930         if (c < '0' || c > '~')
4931           return 0; /* bad final byte */
4932
4933         if (iso->esc >= ISO_ESC_2_8 &&
4934             iso->esc <= ISO_ESC_2_15)
4935           {
4936             chars = (iso->esc >= ISO_ESC_2_12) ? 96 : 94;
4937             single = 1; /* single-byte */
4938             reg = (iso->esc - ISO_ESC_2_8) & 3;
4939           }
4940         else if (iso->esc >= ISO_ESC_2_4_8 &&
4941                  iso->esc <= ISO_ESC_2_4_15)
4942           {
4943             chars = (iso->esc >= ISO_ESC_2_4_12) ? 96 : 94;
4944             single = -1; /* multi-byte */
4945             reg = (iso->esc - ISO_ESC_2_4_8) & 3;
4946           }
4947         else
4948           {
4949             /* Can this ever be reached? -slb */
4950             abort();
4951           }
4952
4953         cs = CHARSET_BY_ATTRIBUTES (chars, single, c,
4954                                     *flags & CODING_STATE_R2L ?
4955                                     CHARSET_RIGHT_TO_LEFT :
4956                                     CHARSET_LEFT_TO_RIGHT);
4957         goto designated;
4958       }
4959     }
4960
4961  not_done:
4962   iso->esc_bytes[iso->esc_bytes_index++] = (unsigned char) c;
4963   return -1;
4964
4965  single_shift:
4966   if (check_invalid_charsets && !CHARSETP (iso->charset[reg]))
4967     /* can't invoke something that ain't there. */
4968     return 0;
4969   iso->esc = ISO_ESC_SINGLE_SHIFT;
4970   *flags &= CODING_STATE_ISO2022_LOCK;
4971   if (reg == 2)
4972     *flags |= CODING_STATE_SS2;
4973   else
4974     *flags |= CODING_STATE_SS3;
4975   return 1;
4976
4977  locking_shift:
4978   if (check_invalid_charsets &&
4979       !CHARSETP (iso->charset[reg]))
4980     /* can't invoke something that ain't there. */
4981     return 0;
4982   if (half)
4983     iso->register_right = reg;
4984   else
4985     iso->register_left = reg;
4986   *flags &= CODING_STATE_ISO2022_LOCK;
4987   iso->esc = ISO_ESC_LOCKING_SHIFT;
4988   return 1;
4989
4990  designated:
4991   if (NILP (cs) && check_invalid_charsets)
4992     {
4993       iso->invalid_designated[reg] = 1;
4994       iso->charset[reg] = Vcharset_ascii;
4995       iso->esc = ISO_ESC_DESIGNATE;
4996       *flags &= CODING_STATE_ISO2022_LOCK;
4997       iso->output_literally = 1;
4998       if (iso->switched_dir_and_no_valid_charset_yet)
4999         {
5000           /* We encountered a switch-direction followed by an
5001              invalid designation.  Ensure that the switch-direction
5002              gets outputted; otherwise it will probably get eaten
5003              when the text is written out again. */
5004           iso->switched_dir_and_no_valid_charset_yet = 0;
5005           iso->output_direction_sequence = 1;
5006           /* And make sure that the switch-dir going the other
5007              way gets outputted, as well. */
5008           iso->invalid_switch_dir = 1;
5009         }
5010       return 1;
5011     }
5012   /* This function is called with CODESYS equal to nil when
5013      doing coding-system detection. */
5014   if (!NILP (codesys))
5015     {
5016       charset_conversion_spec_dynarr *dyn =
5017         XCODING_SYSTEM (codesys)->iso2022.input_conv;
5018
5019       if (dyn)
5020         {
5021           int i;
5022
5023           for (i = 0; i < Dynarr_length (dyn); i++)
5024             {
5025               struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
5026               if (EQ (cs, spec->from_charset))
5027                 cs = spec->to_charset;
5028             }
5029         }
5030     }
5031
5032   iso->charset[reg] = cs;
5033   iso->esc = ISO_ESC_DESIGNATE;
5034   *flags &= CODING_STATE_ISO2022_LOCK;
5035   if (iso->invalid_designated[reg])
5036     {
5037       iso->invalid_designated[reg] = 0;
5038       iso->output_literally = 1;
5039     }
5040   if (iso->switched_dir_and_no_valid_charset_yet)
5041     iso->switched_dir_and_no_valid_charset_yet = 0;
5042   return 1;
5043 }
5044
5045 static int
5046 detect_coding_iso2022 (struct detection_state *st, const Extbyte *src, size_t n)
5047 {
5048   int mask;
5049
5050   /* #### There are serious deficiencies in the recognition mechanism
5051      here.  This needs to be much smarter if it's going to cut it.
5052      The sequence "\xff\x0f" is currently detected as LOCK_SHIFT while
5053      it should be detected as Latin-1.
5054      All the ISO2022 stuff in this file should be synced up with the
5055      code from FSF Emacs-20.4, in which Mule should be more or less stable.
5056      Perhaps we should wait till R2L works in FSF Emacs? */
5057
5058   if (!st->iso2022.initted)
5059     {
5060       reset_iso2022 (Qnil, &st->iso2022.iso);
5061       st->iso2022.mask = (CODING_CATEGORY_ISO_7_MASK |
5062                           CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
5063                           CODING_CATEGORY_ISO_8_1_MASK |
5064                           CODING_CATEGORY_ISO_8_2_MASK |
5065                           CODING_CATEGORY_ISO_LOCK_SHIFT_MASK);
5066       st->iso2022.flags = 0;
5067       st->iso2022.high_byte_count = 0;
5068       st->iso2022.saw_single_shift = 0;
5069       st->iso2022.initted = 1;
5070     }
5071
5072   mask = st->iso2022.mask;
5073
5074   while (n--)
5075     {
5076       unsigned char c = *(unsigned char *)src++;
5077       if (c >= 0xA0)
5078         {
5079           mask &= ~CODING_CATEGORY_ISO_7_MASK;
5080           st->iso2022.high_byte_count++;
5081         }
5082       else
5083         {
5084           if (st->iso2022.high_byte_count && !st->iso2022.saw_single_shift)
5085             {
5086               if (st->iso2022.high_byte_count & 1)
5087                 /* odd number of high bytes; assume not iso-8-2 */
5088                 mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
5089             }
5090           st->iso2022.high_byte_count = 0;
5091           st->iso2022.saw_single_shift = 0;
5092           if (c > 0x80)
5093             mask &= ~CODING_CATEGORY_ISO_7_MASK;
5094         }
5095       if (!(st->iso2022.flags & CODING_STATE_ESCAPE)
5096           && (BYTE_C0_P (c) || BYTE_C1_P (c)))
5097         { /* control chars */
5098           switch (c)
5099             {
5100               /* Allow and ignore control characters that you might
5101                  reasonably see in a text file */
5102             case '\r':
5103             case '\n':
5104             case '\t':
5105             case  7: /* bell */
5106             case  8: /* backspace */
5107             case 11: /* vertical tab */
5108             case 12: /* form feed */
5109             case 26: /* MS-DOS C-z junk */
5110             case 31: /* '^_' -- for info */
5111               goto label_continue_loop;
5112
5113             default:
5114               break;
5115             }
5116         }
5117
5118       if ((st->iso2022.flags & CODING_STATE_ESCAPE) || BYTE_C0_P (c)
5119           || BYTE_C1_P (c))
5120         {
5121           if (parse_iso2022_esc (Qnil, &st->iso2022.iso, c,
5122                                  &st->iso2022.flags, 0))
5123             {
5124               switch (st->iso2022.iso.esc)
5125                 {
5126                 case ISO_ESC_DESIGNATE:
5127                   mask &= ~CODING_CATEGORY_ISO_8_1_MASK;
5128                   mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
5129                   break;
5130                 case ISO_ESC_LOCKING_SHIFT:
5131                   mask = CODING_CATEGORY_ISO_LOCK_SHIFT_MASK;
5132                   goto ran_out_of_chars;
5133                 case ISO_ESC_SINGLE_SHIFT:
5134                   mask &= ~CODING_CATEGORY_ISO_8_DESIGNATE_MASK;
5135                   st->iso2022.saw_single_shift = 1;
5136                   break;
5137                 default:
5138                   break;
5139                 }
5140             }
5141           else
5142             {
5143               mask = 0;
5144               goto ran_out_of_chars;
5145             }
5146         }
5147     label_continue_loop:;
5148     }
5149
5150  ran_out_of_chars:
5151
5152   return mask;
5153 }
5154
5155 static int
5156 postprocess_iso2022_mask (int mask)
5157 {
5158   /* #### kind of cheesy */
5159   /* If seven-bit ISO is allowed, then assume that the encoding is
5160      entirely seven-bit and turn off the eight-bit ones. */
5161   if (mask & CODING_CATEGORY_ISO_7_MASK)
5162     mask &= ~ (CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
5163                CODING_CATEGORY_ISO_8_1_MASK |
5164                CODING_CATEGORY_ISO_8_2_MASK);
5165   return mask;
5166 }
5167
5168 /* If FLAGS is a null pointer or specifies right-to-left motion,
5169    output a switch-dir-to-left-to-right sequence to DST.
5170    Also update FLAGS if it is not a null pointer.
5171    If INTERNAL_P is set, we are outputting in internal format and
5172    need to handle the CSI differently. */
5173
5174 static void
5175 restore_left_to_right_direction (Lisp_Coding_System *codesys,
5176                                  unsigned_char_dynarr *dst,
5177                                  unsigned int *flags,
5178                                  int internal_p)
5179 {
5180   if (!flags || (*flags & CODING_STATE_R2L))
5181     {
5182       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5183         {
5184           Dynarr_add (dst, ISO_CODE_ESC);
5185           Dynarr_add (dst, '[');
5186         }
5187       else if (internal_p)
5188         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
5189       else
5190         Dynarr_add (dst, ISO_CODE_CSI);
5191       Dynarr_add (dst, '0');
5192       Dynarr_add (dst, ']');
5193       if (flags)
5194         *flags &= ~CODING_STATE_R2L;
5195     }
5196 }
5197
5198 /* If FLAGS is a null pointer or specifies a direction different from
5199    DIRECTION (which should be either CHARSET_RIGHT_TO_LEFT or
5200    CHARSET_LEFT_TO_RIGHT), output the appropriate switch-dir escape
5201    sequence to DST.  Also update FLAGS if it is not a null pointer.
5202    If INTERNAL_P is set, we are outputting in internal format and
5203    need to handle the CSI differently. */
5204
5205 static void
5206 ensure_correct_direction (int direction, Lisp_Coding_System *codesys,
5207                           unsigned_char_dynarr *dst, unsigned int *flags,
5208                           int internal_p)
5209 {
5210   if ((!flags || (*flags & CODING_STATE_R2L)) &&
5211       direction == CHARSET_LEFT_TO_RIGHT)
5212     restore_left_to_right_direction (codesys, dst, flags, internal_p);
5213   else if (!CODING_SYSTEM_ISO2022_NO_ISO6429 (codesys)
5214            && (!flags || !(*flags & CODING_STATE_R2L)) &&
5215            direction == CHARSET_RIGHT_TO_LEFT)
5216     {
5217       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5218         {
5219           Dynarr_add (dst, ISO_CODE_ESC);
5220           Dynarr_add (dst, '[');
5221         }
5222       else if (internal_p)
5223         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
5224       else
5225         Dynarr_add (dst, ISO_CODE_CSI);
5226       Dynarr_add (dst, '2');
5227       Dynarr_add (dst, ']');
5228       if (flags)
5229         *flags |= CODING_STATE_R2L;
5230     }
5231 }
5232
5233 /* Convert ISO2022-format data to internal format. */
5234
5235 static void
5236 decode_coding_iso2022 (Lstream *decoding, const Extbyte *src,
5237                        unsigned_char_dynarr *dst, size_t n)
5238 {
5239   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
5240   unsigned int flags    = str->flags;
5241   unsigned int cpos     = str->cpos;
5242   unsigned char counter = str->counter;
5243   eol_type_t eol_type   = str->eol_type;
5244 #ifdef ENABLE_COMPOSITE_CHARS
5245   unsigned_char_dynarr *real_dst = dst;
5246 #endif
5247   Lisp_Object coding_system;
5248
5249   XSETCODING_SYSTEM (coding_system, str->codesys);
5250
5251 #ifdef ENABLE_COMPOSITE_CHARS
5252   if (flags & CODING_STATE_COMPOSITE)
5253     dst = str->iso2022.composite_chars;
5254 #endif /* ENABLE_COMPOSITE_CHARS */
5255
5256   while (n--)
5257     {
5258       unsigned char c = *(unsigned char *)src++;
5259       if (flags & CODING_STATE_ESCAPE)
5260         {       /* Within ESC sequence */
5261           int retval = parse_iso2022_esc (coding_system, &str->iso2022,
5262                                           c, &flags, 1);
5263
5264           if (retval)
5265             {
5266               switch (str->iso2022.esc)
5267                 {
5268 #ifdef ENABLE_COMPOSITE_CHARS
5269                 case ISO_ESC_START_COMPOSITE:
5270                   if (str->iso2022.composite_chars)
5271                     Dynarr_reset (str->iso2022.composite_chars);
5272                   else
5273                     str->iso2022.composite_chars = Dynarr_new (unsigned_char);
5274                   dst = str->iso2022.composite_chars;
5275                   break;
5276                 case ISO_ESC_END_COMPOSITE:
5277                   {
5278                     Bufbyte comstr[MAX_EMCHAR_LEN];
5279                     Bytecount len;
5280                     Emchar emch = lookup_composite_char (Dynarr_atp (dst, 0),
5281                                                          Dynarr_length (dst));
5282                     dst = real_dst;
5283                     len = set_charptr_emchar (comstr, emch);
5284                     Dynarr_add_many (dst, comstr, len);
5285                     break;
5286                   }
5287 #endif /* ENABLE_COMPOSITE_CHARS */
5288
5289                 case ISO_ESC_LITERAL:
5290                   COMPOSE_FLUSH_CHARS (str, dst);
5291                   decode_flush_er_chars (str, dst);
5292                   DECODE_ADD_BINARY_CHAR (c, dst);
5293                   break;
5294
5295                 default:
5296                   /* Everything else handled already */
5297                   break;
5298                 }
5299             }
5300
5301           /* Attempted error recovery. */
5302           if (str->iso2022.output_direction_sequence)
5303             ensure_correct_direction (flags & CODING_STATE_R2L ?
5304                                       CHARSET_RIGHT_TO_LEFT :
5305                                       CHARSET_LEFT_TO_RIGHT,
5306                                       str->codesys, dst, 0, 1);
5307           /* More error recovery. */
5308           if (!retval || str->iso2022.output_literally)
5309             {
5310               /* Output the (possibly invalid) sequence */
5311               int i;
5312               COMPOSE_FLUSH_CHARS (str, dst);
5313               decode_flush_er_chars (str, dst);
5314               for (i = 0; i < str->iso2022.esc_bytes_index; i++)
5315                 DECODE_ADD_BINARY_CHAR (str->iso2022.esc_bytes[i], dst);
5316               flags &= CODING_STATE_ISO2022_LOCK;
5317               if (!retval)
5318                 n++, src--;/* Repeat the loop with the same character. */
5319               else
5320                 {
5321                   /* No sense in reprocessing the final byte of the
5322                      escape sequence; it could mess things up anyway.
5323                      Just add it now. */
5324                   COMPOSE_FLUSH_CHARS (str, dst);
5325                   decode_flush_er_chars (str, dst);
5326                   DECODE_ADD_BINARY_CHAR (c, dst);
5327                 }
5328             }
5329           cpos = 0;
5330           counter = 0;
5331         }
5332       else if (BYTE_C0_P (c) || BYTE_C1_P (c))
5333         { /* Control characters */
5334
5335           /***** Error-handling *****/
5336
5337           /* If we were in the middle of a character, dump out the
5338              partial character. */
5339           if (counter)
5340             {
5341               COMPOSE_FLUSH_CHARS (str, dst);
5342               decode_flush_er_chars (str, dst);
5343               while (counter > 0)
5344                 {
5345                   counter--;
5346                   DECODE_ADD_BINARY_CHAR
5347                     ((unsigned char)(cpos >> (counter * 8)), dst);
5348                 }
5349               cpos = 0;
5350             }
5351
5352           /* If we just saw a single-shift character, dump it out.
5353              This may dump out the wrong sort of single-shift character,
5354              but least it will give an indication that something went
5355              wrong. */
5356           if (flags & CODING_STATE_SS2)
5357             {
5358               COMPOSE_FLUSH_CHARS (str, dst);
5359               decode_flush_er_chars (str, dst);
5360               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS2, dst);
5361               flags &= ~CODING_STATE_SS2;
5362             }
5363           if (flags & CODING_STATE_SS3)
5364             {
5365               COMPOSE_FLUSH_CHARS (str, dst);
5366               decode_flush_er_chars (str, dst);
5367               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS3, dst);
5368               flags &= ~CODING_STATE_SS3;
5369             }
5370
5371           /***** Now handle the control characters. *****/
5372
5373           /* Handle CR/LF */
5374 #ifdef UTF2000
5375           if (c == '\r')
5376             {
5377               COMPOSE_FLUSH_CHARS (str, dst);
5378               decode_flush_er_chars (str, dst);
5379               if (eol_type == EOL_CR)
5380                 Dynarr_add (dst, '\n');
5381               else if (eol_type != EOL_CRLF || flags & CODING_STATE_CR)
5382                 Dynarr_add (dst, c);
5383               else
5384                 flags |= CODING_STATE_CR;
5385               goto label_continue_loop;
5386             }
5387           else if (flags & CODING_STATE_CR)
5388             {   /* eol_type == CODING_SYSTEM_EOL_CRLF */
5389               if (c != '\n')
5390                 Dynarr_add (dst, '\r');
5391               flags &= ~CODING_STATE_CR;
5392             }
5393 #else
5394           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5395 #endif
5396
5397           flags &= CODING_STATE_ISO2022_LOCK;
5398
5399           if (!parse_iso2022_esc (coding_system, &str->iso2022, c, &flags, 1))
5400             {
5401               COMPOSE_FLUSH_CHARS (str, dst);
5402               decode_flush_er_chars (str, dst);
5403               DECODE_ADD_BINARY_CHAR (c, dst);
5404             }
5405         }
5406       else
5407         {                       /* Graphic characters */
5408           Lisp_Object charset;
5409 #ifndef UTF2000
5410           Charset_ID lb;
5411 #endif
5412           int reg;
5413
5414 #ifdef UTF2000
5415           if (c == '\r')
5416             {
5417               COMPOSE_FLUSH_CHARS (str, dst);
5418               decode_flush_er_chars (str, dst);
5419               if (eol_type == EOL_CR)
5420                 Dynarr_add (dst, '\n');
5421               else if (eol_type != EOL_CRLF || flags & CODING_STATE_CR)
5422                 Dynarr_add (dst, c);
5423               else
5424                 flags |= CODING_STATE_CR;
5425               goto label_continue_loop;
5426             }
5427           else if (flags & CODING_STATE_CR)
5428             {   /* eol_type == CODING_SYSTEM_EOL_CRLF */
5429               if (c != '\n')
5430                 Dynarr_add (dst, '\r');
5431               flags &= ~CODING_STATE_CR;
5432             }
5433 #else
5434           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5435 #endif
5436
5437           /* Now determine the charset. */
5438           reg = ((flags & CODING_STATE_SS2) ? 2
5439                  : (flags & CODING_STATE_SS3) ? 3
5440                  : !BYTE_ASCII_P (c) ? str->iso2022.register_right
5441                  : str->iso2022.register_left);
5442           charset = str->iso2022.charset[reg];
5443
5444           /* Error checking: */
5445           if (! CHARSETP (charset)
5446               || str->iso2022.invalid_designated[reg]
5447               || (((c & 0x7F) == ' ' || (c & 0x7F) == ISO_CODE_DEL)
5448                   && XCHARSET_CHARS (charset) == 94))
5449             /* Mrmph.  We are trying to invoke a register that has no
5450                or an invalid charset in it, or trying to add a character
5451                outside the range of the charset.  Insert that char literally
5452                to preserve it for the output. */
5453             {
5454               COMPOSE_FLUSH_CHARS (str, dst);
5455               decode_flush_er_chars (str, dst);
5456               while (counter > 0)
5457                 {
5458                   counter--;
5459                   DECODE_ADD_BINARY_CHAR
5460                     ((unsigned char)(cpos >> (counter * 8)), dst);
5461                 }
5462               cpos = 0;
5463               DECODE_ADD_BINARY_CHAR (c, dst);
5464             }
5465
5466           else
5467             {
5468               /* Things are probably hunky-dorey. */
5469
5470               /* Fetch reverse charset, maybe. */
5471               if (((flags & CODING_STATE_R2L) &&
5472                    XCHARSET_DIRECTION (charset) == CHARSET_LEFT_TO_RIGHT)
5473                   ||
5474                   (!(flags & CODING_STATE_R2L) &&
5475                    XCHARSET_DIRECTION (charset) == CHARSET_RIGHT_TO_LEFT))
5476                 {
5477                   Lisp_Object new_charset =
5478                     XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
5479                   if (!NILP (new_charset))
5480                     charset = new_charset;
5481                 }
5482
5483 #ifdef UTF2000
5484               counter++;
5485               if (XCHARSET_DIMENSION (charset) == counter)
5486                 {
5487                   COMPOSE_ADD_CHAR (str,
5488                                     DECODE_CHAR (charset,
5489                                                  ((cpos & 0x7F7F7F) << 8)
5490                                                  | (c & 0x7F)),
5491                                     dst);
5492                   cpos = 0;
5493                   counter = 0;
5494                 }
5495               else
5496                 cpos = (cpos << 8) | c;
5497 #else
5498               lb = XCHARSET_LEADING_BYTE (charset);
5499               switch (XCHARSET_REP_BYTES (charset))
5500                 {
5501                 case 1: /* ASCII */
5502                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
5503                   Dynarr_add (dst, c & 0x7F);
5504                   break;
5505
5506                 case 2: /* one-byte official */
5507                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
5508                   Dynarr_add (dst, lb);
5509                   Dynarr_add (dst, c | 0x80);
5510                   break;
5511
5512                 case 3: /* one-byte private or two-byte official */
5513                   if (XCHARSET_PRIVATE_P (charset))
5514                     {
5515                       DECODE_OUTPUT_PARTIAL_CHAR (ch);
5516                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_1);
5517                       Dynarr_add (dst, lb);
5518                       Dynarr_add (dst, c | 0x80);
5519                     }
5520                   else
5521                     {
5522                       if (ch)
5523                         {
5524                           Dynarr_add (dst, lb);
5525                           Dynarr_add (dst, ch | 0x80);
5526                           Dynarr_add (dst, c | 0x80);
5527                           ch = 0;
5528                         }
5529                       else
5530                         ch = c;
5531                     }
5532                   break;
5533
5534                 default:        /* two-byte private */
5535                   if (ch)
5536                     {
5537                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_2);
5538                       Dynarr_add (dst, lb);
5539                       Dynarr_add (dst, ch | 0x80);
5540                       Dynarr_add (dst, c | 0x80);
5541                       ch = 0;
5542                     }
5543                   else
5544                     ch = c;
5545                 }
5546 #endif
5547             }
5548
5549           if (!cpos)
5550             flags &= CODING_STATE_ISO2022_LOCK;
5551         }
5552
5553     label_continue_loop:;
5554     }
5555
5556   if (flags & CODING_STATE_END)
5557     {
5558       COMPOSE_FLUSH_CHARS (str, dst);
5559       decode_flush_er_chars (str, dst);
5560       DECODE_OUTPUT_PARTIAL_CHAR (cpos);
5561     }
5562   str->flags   = flags;
5563   str->cpos    = cpos;
5564   str->counter = counter;
5565 }
5566
5567
5568 /***** ISO2022 encoder *****/
5569
5570 /* Designate CHARSET into register REG. */
5571
5572 static void
5573 iso2022_designate (Lisp_Object charset, unsigned char reg,
5574                    struct encoding_stream *str, unsigned_char_dynarr *dst)
5575 {
5576   static const char inter94[] = "()*+";
5577   static const char inter96[] = ",-./";
5578   unsigned short chars;
5579   unsigned char dimension;
5580   unsigned char final;
5581   Lisp_Object old_charset = str->iso2022.charset[reg];
5582
5583   str->iso2022.charset[reg] = charset;
5584   if (!CHARSETP (charset))
5585     /* charset might be an initial nil or t. */
5586     return;
5587   chars = XCHARSET_CHARS (charset);
5588   dimension = XCHARSET_DIMENSION (charset);
5589   final = XCHARSET_FINAL (charset);
5590   if (!str->iso2022.force_charset_on_output[reg] &&
5591       CHARSETP (old_charset) &&
5592       XCHARSET_CHARS (old_charset) == chars &&
5593       XCHARSET_DIMENSION (old_charset) == dimension &&
5594       XCHARSET_FINAL (old_charset) == final)
5595     return;
5596
5597   str->iso2022.force_charset_on_output[reg] = 0;
5598
5599   {
5600     charset_conversion_spec_dynarr *dyn =
5601       str->codesys->iso2022.output_conv;
5602
5603     if (dyn)
5604       {
5605         int i;
5606
5607         for (i = 0; i < Dynarr_length (dyn); i++)
5608           {
5609             struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
5610             if (EQ (charset, spec->from_charset))
5611                 charset = spec->to_charset;
5612           }
5613       }
5614   }
5615
5616   Dynarr_add (dst, ISO_CODE_ESC);
5617   switch (chars)
5618     {
5619     case 94:
5620       if (dimension == 1)
5621         Dynarr_add (dst, inter94[reg]);
5622       else
5623         {
5624           Dynarr_add (dst, '$');
5625           if (reg != 0
5626               || !(CODING_SYSTEM_ISO2022_SHORT (str->codesys))
5627               || final < '@'
5628               || final > 'B')
5629             Dynarr_add (dst, inter94[reg]);
5630         }
5631       break;
5632     case 96:
5633       if (dimension == 1)
5634         Dynarr_add (dst, inter96[reg]);
5635       else
5636         {
5637           Dynarr_add (dst, '$');
5638           Dynarr_add (dst, inter96[reg]);
5639         }
5640       break;
5641     }
5642   Dynarr_add (dst, final);
5643 }
5644
5645 static void
5646 ensure_normal_shift (struct encoding_stream *str, unsigned_char_dynarr *dst)
5647 {
5648   if (str->iso2022.register_left != 0)
5649     {
5650       Dynarr_add (dst, ISO_CODE_SI);
5651       str->iso2022.register_left = 0;
5652     }
5653 }
5654
5655 static void
5656 ensure_shift_out (struct encoding_stream *str, unsigned_char_dynarr *dst)
5657 {
5658   if (str->iso2022.register_left != 1)
5659     {
5660       Dynarr_add (dst, ISO_CODE_SO);
5661       str->iso2022.register_left = 1;
5662     }
5663 }
5664
5665 void
5666 char_encode_iso2022 (struct encoding_stream *str, Emchar ch,
5667                      unsigned_char_dynarr *dst, unsigned int *flags)
5668 {
5669   unsigned char charmask;
5670   Lisp_Coding_System* codesys = str->codesys;
5671   eol_type_t eol_type         = CODING_SYSTEM_EOL_TYPE (str->codesys);
5672   int i;
5673   Lisp_Object charset = str->iso2022.current_charset;
5674   int half = str->iso2022.current_half;
5675   int code_point = -1;
5676
5677   if (ch <= 0x7F)
5678     {
5679       restore_left_to_right_direction (codesys, dst, flags, 0);
5680               
5681       /* Make sure G0 contains ASCII */
5682       if ((ch > ' ' && ch < ISO_CODE_DEL)
5683           || !CODING_SYSTEM_ISO2022_NO_ASCII_CNTL (codesys))
5684         {
5685           ensure_normal_shift (str, dst);
5686           iso2022_designate (Vcharset_ascii, 0, str, dst);
5687         }
5688               
5689       /* If necessary, restore everything to the default state
5690          at end-of-line */
5691       if (ch == '\n' && !(CODING_SYSTEM_ISO2022_NO_ASCII_EOL (codesys)))
5692         {
5693           restore_left_to_right_direction (codesys, dst, flags, 0);
5694
5695           ensure_normal_shift (str, dst);
5696
5697           for (i = 0; i < 4; i++)
5698             {
5699               Lisp_Object initial_charset =
5700                 CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
5701               iso2022_designate (initial_charset, i, str, dst);
5702             }
5703         }
5704       if (ch == '\n')
5705         {
5706           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5707             Dynarr_add (dst, '\r');
5708           if (eol_type != EOL_CR)
5709             Dynarr_add (dst, ch);
5710         }
5711       else
5712         {
5713           if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
5714               && fit_to_be_escape_quoted (ch))
5715             Dynarr_add (dst, ISO_CODE_ESC);
5716           Dynarr_add (dst, ch);
5717         }
5718     }
5719   else if ( (0x80 <= ch) && (ch <= 0x9f) )
5720     {
5721       charmask = (half == 0 ? 0x00 : 0x80);
5722           
5723       if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
5724           && fit_to_be_escape_quoted (ch))
5725         Dynarr_add (dst, ISO_CODE_ESC);
5726       /* you asked for it ... */
5727       Dynarr_add (dst, ch);
5728     }
5729   else
5730     {
5731       int reg;
5732
5733       /* Now determine which register to use. */
5734       reg = -1;
5735       for (i = 0; i < 4; i++)
5736         {
5737           if ((CHARSETP (charset = str->iso2022.charset[i])
5738                && ((code_point = charset_code_point (charset, ch)) >= 0))
5739               ||
5740               (CHARSETP
5741                (charset
5742                 = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i))
5743                && ((code_point = charset_code_point (charset, ch)) >= 0)))
5744             {
5745               reg = i;
5746               break;
5747             }
5748         }
5749       if (reg == -1)
5750         {
5751           Lisp_Object original_default_coded_charset_priority_list
5752             = Vdefault_coded_charset_priority_list;
5753
5754           while (!EQ (Vdefault_coded_charset_priority_list, Qnil))
5755             {
5756               code_point = ENCODE_CHAR (ch, charset);
5757               if (XCHARSET_FINAL (charset))
5758                 goto found;
5759               Vdefault_coded_charset_priority_list
5760                 = Fcdr (Fmemq (XCHARSET_NAME (charset),
5761                                Vdefault_coded_charset_priority_list));
5762             }
5763           code_point = ENCODE_CHAR (ch, charset);
5764           if (!XCHARSET_FINAL (charset))
5765             {
5766               charset = Vcharset_ascii;
5767               code_point = '~';
5768             }
5769         found:
5770           Vdefault_coded_charset_priority_list
5771             = original_default_coded_charset_priority_list;
5772         }
5773       ensure_correct_direction (XCHARSET_DIRECTION (charset),
5774                                 codesys, dst, flags, 0);
5775       
5776       if (reg == -1)
5777         {
5778           if (XCHARSET_GRAPHIC (charset) != 0)
5779             {
5780               if (!NILP (str->iso2022.charset[1]) &&
5781                   (!CODING_SYSTEM_ISO2022_SEVEN (codesys)
5782                    || CODING_SYSTEM_ISO2022_LOCK_SHIFT (codesys)))
5783                 reg = 1;
5784               else if (!NILP (str->iso2022.charset[2]))
5785                 reg = 2;
5786               else if (!NILP (str->iso2022.charset[3]))
5787                 reg = 3;
5788               else
5789                 reg = 0;
5790             }
5791           else
5792             reg = 0;
5793         }
5794
5795       iso2022_designate (charset, reg, str, dst);
5796               
5797       /* Now invoke that register. */
5798       switch (reg)
5799         {
5800         case 0:
5801           ensure_normal_shift (str, dst);
5802           half = 0;
5803           break;
5804         case 1:
5805           if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5806             {
5807               ensure_shift_out (str, dst);
5808               half = 0;
5809             }
5810           else
5811             half = 1;
5812           break;
5813         case 2:
5814           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
5815             {
5816               Dynarr_add (dst, ISO_CODE_ESC);
5817               Dynarr_add (dst, 'N');
5818               half = 0;
5819             }
5820           else
5821             {
5822               Dynarr_add (dst, ISO_CODE_SS2);
5823               half = 1;
5824             }
5825           break;
5826         case 3:
5827           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
5828             {
5829               Dynarr_add (dst, ISO_CODE_ESC);
5830               Dynarr_add (dst, 'O');
5831               half = 0;
5832             }
5833           else
5834             {
5835               Dynarr_add (dst, ISO_CODE_SS3);
5836               half = 1;
5837             }
5838           break;
5839         default:
5840           abort ();
5841         }
5842       
5843       charmask = (half == 0 ? 0x00 : 0x80);
5844       
5845       switch (XCHARSET_DIMENSION (charset))
5846         {
5847         case 1:
5848           Dynarr_add (dst, (code_point & 0xFF) | charmask);
5849           break;
5850         case 2:
5851           Dynarr_add (dst, ((code_point >> 8) & 0xFF) | charmask);
5852           Dynarr_add (dst, ( code_point       & 0xFF) | charmask);
5853           break;
5854         case 3:
5855           Dynarr_add (dst, ((code_point >> 16) & 0xFF) | charmask);
5856           Dynarr_add (dst, ((code_point >>  8) & 0xFF) | charmask);
5857           Dynarr_add (dst, ( code_point        & 0xFF) | charmask);
5858           break;
5859         case 4:
5860           Dynarr_add (dst, ((code_point >> 24) & 0xFF) | charmask);
5861           Dynarr_add (dst, ((code_point >> 16) & 0xFF) | charmask);
5862           Dynarr_add (dst, ((code_point >>  8) & 0xFF) | charmask);
5863           Dynarr_add (dst, ( code_point        & 0xFF) | charmask);
5864           break;
5865         default:
5866           abort ();
5867         }
5868     }
5869   str->iso2022.current_charset = charset;
5870   str->iso2022.current_half = half;
5871 }
5872
5873 void
5874 char_finish_iso2022 (struct encoding_stream *str, unsigned_char_dynarr *dst,
5875                      unsigned int *flags)
5876 {
5877   Lisp_Coding_System* codesys = str->codesys;
5878   int i;
5879
5880   restore_left_to_right_direction (codesys, dst, flags, 0);
5881   ensure_normal_shift (str, dst);
5882   for (i = 0; i < 4; i++)
5883     {
5884       Lisp_Object initial_charset
5885         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
5886       iso2022_designate (initial_charset, i, str, dst);
5887     }
5888 }
5889 #endif /* MULE */
5890 \f
5891 /************************************************************************/
5892 /*                     No-conversion methods                            */
5893 /************************************************************************/
5894
5895 /* This is used when reading in "binary" files -- i.e. files that may
5896    contain all 256 possible byte values and that are not to be
5897    interpreted as being in any particular decoding. */
5898 static void
5899 decode_coding_no_conversion (Lstream *decoding, const Extbyte *src,
5900                              unsigned_char_dynarr *dst, size_t n)
5901 {
5902   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
5903   unsigned int flags  = str->flags;
5904   unsigned int cpos   = str->cpos;
5905   eol_type_t eol_type = str->eol_type;
5906
5907   while (n--)
5908     {
5909       unsigned char c = *(unsigned char *)src++;
5910
5911       DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5912       DECODE_ADD_BINARY_CHAR (c, dst);
5913     label_continue_loop:;
5914     }
5915
5916   DECODE_HANDLE_END_OF_CONVERSION (flags, cpos, dst);
5917
5918   str->flags = flags;
5919   str->cpos  = cpos;
5920 }
5921
5922 static void
5923 encode_coding_no_conversion (Lstream *encoding, const Bufbyte *src,
5924                              unsigned_char_dynarr *dst, size_t n)
5925 {
5926   unsigned char c;
5927   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
5928   unsigned int flags  = str->flags;
5929   unsigned int ch     = str->ch;
5930   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
5931 #ifdef UTF2000
5932   unsigned char char_boundary = str->iso2022.current_char_boundary;
5933 #endif
5934
5935   while (n--)
5936     {
5937       c = *src++;         
5938 #ifdef UTF2000
5939       if (char_boundary == 0)
5940         if ( c >= 0xfc )
5941           {
5942             ch = c & 0x01;
5943             char_boundary = 5;
5944           }
5945         else if ( c >= 0xf8 )
5946           {
5947             ch = c & 0x03;
5948             char_boundary = 4;
5949           }
5950         else if ( c >= 0xf0 )
5951           {
5952             ch = c & 0x07;
5953             char_boundary = 3;
5954           }
5955         else if ( c >= 0xe0 )
5956           {
5957             ch = c & 0x0f;
5958             char_boundary = 2;
5959           }
5960         else if ( c >= 0xc0 )
5961           {
5962             ch = c & 0x1f;
5963             char_boundary = 1;
5964           }
5965         else
5966           {
5967             ch = 0;
5968             if (c == '\n')
5969               {
5970                 if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5971                   Dynarr_add (dst, '\r');
5972                 if (eol_type != EOL_CR)
5973                   Dynarr_add (dst, c);
5974               }
5975             else
5976               Dynarr_add (dst, c);
5977             char_boundary = 0;
5978           }
5979       else if (char_boundary == 1)
5980         {
5981           ch = ( ch << 6 ) | ( c & 0x3f );
5982           Dynarr_add (dst, ch & 0xff);
5983           char_boundary = 0;
5984         }
5985       else
5986         {
5987           ch = ( ch << 6 ) | ( c & 0x3f );
5988           char_boundary--;
5989         }
5990 #else /* not UTF2000 */
5991       if (c == '\n')
5992         {
5993           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5994             Dynarr_add (dst, '\r');
5995           if (eol_type != EOL_CR)
5996             Dynarr_add (dst, '\n');
5997           ch = 0;
5998         }
5999       else if (BYTE_ASCII_P (c))
6000         {
6001           assert (ch == 0);
6002           Dynarr_add (dst, c);
6003         }
6004       else if (BUFBYTE_LEADING_BYTE_P (c))
6005         {
6006           assert (ch == 0);
6007           if (c == LEADING_BYTE_LATIN_ISO8859_1 ||
6008               c == LEADING_BYTE_CONTROL_1)
6009             ch = c;
6010           else
6011             Dynarr_add (dst, '~'); /* untranslatable character */
6012         }
6013       else
6014         {
6015           if (ch == LEADING_BYTE_LATIN_ISO8859_1)
6016             Dynarr_add (dst, c);
6017           else if (ch == LEADING_BYTE_CONTROL_1)
6018             {
6019               assert (c < 0xC0);
6020               Dynarr_add (dst, c - 0x20);
6021             }
6022           /* else it should be the second or third byte of an
6023              untranslatable character, so ignore it */
6024           ch = 0;
6025         }
6026 #endif /* not UTF2000 */
6027     }
6028
6029   str->flags = flags;
6030   str->ch    = ch;
6031 #ifdef UTF2000
6032   str->iso2022.current_char_boundary = char_boundary;
6033 #endif
6034 }
6035
6036 \f
6037
6038 /************************************************************************/
6039 /*                             Initialization                           */
6040 /************************************************************************/
6041
6042 void
6043 syms_of_file_coding (void)
6044 {
6045   INIT_LRECORD_IMPLEMENTATION (coding_system);
6046
6047   deferror (&Qcoding_system_error, "coding-system-error",
6048             "Coding-system error", Qio_error);
6049
6050   DEFSUBR (Fcoding_system_p);
6051   DEFSUBR (Ffind_coding_system);
6052   DEFSUBR (Fget_coding_system);
6053   DEFSUBR (Fcoding_system_list);
6054   DEFSUBR (Fcoding_system_name);
6055   DEFSUBR (Fmake_coding_system);
6056   DEFSUBR (Fcopy_coding_system);
6057   DEFSUBR (Fcoding_system_canonical_name_p);
6058   DEFSUBR (Fcoding_system_alias_p);
6059   DEFSUBR (Fcoding_system_aliasee);
6060   DEFSUBR (Fdefine_coding_system_alias);
6061   DEFSUBR (Fsubsidiary_coding_system);
6062
6063   DEFSUBR (Fcoding_system_type);
6064   DEFSUBR (Fcoding_system_doc_string);
6065 #ifdef MULE
6066   DEFSUBR (Fcoding_system_charset);
6067 #endif
6068   DEFSUBR (Fcoding_system_property);
6069
6070   DEFSUBR (Fcoding_category_list);
6071   DEFSUBR (Fset_coding_priority_list);
6072   DEFSUBR (Fcoding_priority_list);
6073   DEFSUBR (Fset_coding_category_system);
6074   DEFSUBR (Fcoding_category_system);
6075
6076   DEFSUBR (Fdetect_coding_region);
6077   DEFSUBR (Fdecode_coding_region);
6078   DEFSUBR (Fencode_coding_region);
6079 #ifdef MULE
6080   DEFSUBR (Fdecode_shift_jis_char);
6081   DEFSUBR (Fencode_shift_jis_char);
6082   DEFSUBR (Fdecode_big5_char);
6083   DEFSUBR (Fencode_big5_char);
6084 #endif /* MULE */
6085   defsymbol (&Qcoding_systemp, "coding-system-p");
6086   defsymbol (&Qno_conversion, "no-conversion");
6087   defsymbol (&Qraw_text, "raw-text");
6088 #ifdef MULE
6089   defsymbol (&Qbig5, "big5");
6090   defsymbol (&Qshift_jis, "shift-jis");
6091   defsymbol (&Qucs4, "ucs-4");
6092   defsymbol (&Qutf8, "utf-8");
6093   defsymbol (&Qccl, "ccl");
6094   defsymbol (&Qiso2022, "iso2022");
6095 #endif /* MULE */
6096   defsymbol (&Qmnemonic, "mnemonic");
6097   defsymbol (&Qeol_type, "eol-type");
6098   defsymbol (&Qpost_read_conversion, "post-read-conversion");
6099   defsymbol (&Qpre_write_conversion, "pre-write-conversion");
6100
6101   defsymbol (&Qcr, "cr");
6102   defsymbol (&Qlf, "lf");
6103   defsymbol (&Qcrlf, "crlf");
6104   defsymbol (&Qeol_cr, "eol-cr");
6105   defsymbol (&Qeol_lf, "eol-lf");
6106   defsymbol (&Qeol_crlf, "eol-crlf");
6107 #ifdef MULE
6108   defsymbol (&Qcharset_g0, "charset-g0");
6109   defsymbol (&Qcharset_g1, "charset-g1");
6110   defsymbol (&Qcharset_g2, "charset-g2");
6111   defsymbol (&Qcharset_g3, "charset-g3");
6112   defsymbol (&Qforce_g0_on_output, "force-g0-on-output");
6113   defsymbol (&Qforce_g1_on_output, "force-g1-on-output");
6114   defsymbol (&Qforce_g2_on_output, "force-g2-on-output");
6115   defsymbol (&Qforce_g3_on_output, "force-g3-on-output");
6116   defsymbol (&Qno_iso6429, "no-iso6429");
6117   defsymbol (&Qinput_charset_conversion, "input-charset-conversion");
6118   defsymbol (&Qoutput_charset_conversion, "output-charset-conversion");
6119
6120   defsymbol (&Qshort, "short");
6121   defsymbol (&Qno_ascii_eol, "no-ascii-eol");
6122   defsymbol (&Qno_ascii_cntl, "no-ascii-cntl");
6123   defsymbol (&Qseven, "seven");
6124   defsymbol (&Qlock_shift, "lock-shift");
6125   defsymbol (&Qescape_quoted, "escape-quoted");
6126 #endif /* MULE */
6127 #ifdef UTF2000
6128   defsymbol (&Qutf_8_mcs, "utf-8-mcs");
6129   defsymbol (&Qdisable_composition, "disable-composition");
6130   defsymbol (&Quse_entity_reference, "use-entity-reference");
6131   defsymbol (&Qd, "d");
6132   defsymbol (&Qx, "x");
6133   defsymbol (&QX, "X");
6134 #endif
6135   defsymbol (&Qencode, "encode");
6136   defsymbol (&Qdecode, "decode");
6137
6138 #ifdef MULE
6139   defsymbol (&coding_category_symbol[CODING_CATEGORY_SHIFT_JIS],
6140              "shift-jis");
6141   defsymbol (&coding_category_symbol[CODING_CATEGORY_BIG5],
6142              "big5");
6143   defsymbol (&coding_category_symbol[CODING_CATEGORY_UCS4],
6144              "ucs-4");
6145   defsymbol (&coding_category_symbol[CODING_CATEGORY_UTF8],
6146              "utf-8");
6147   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_7],
6148              "iso-7");
6149   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_DESIGNATE],
6150              "iso-8-designate");
6151   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_1],
6152              "iso-8-1");
6153   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_2],
6154              "iso-8-2");
6155   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_LOCK_SHIFT],
6156              "iso-lock-shift");
6157 #endif /* MULE */
6158   defsymbol (&coding_category_symbol[CODING_CATEGORY_NO_CONVERSION],
6159              "no-conversion");
6160 }
6161
6162 void
6163 lstream_type_create_file_coding (void)
6164 {
6165   LSTREAM_HAS_METHOD (decoding, reader);
6166   LSTREAM_HAS_METHOD (decoding, writer);
6167   LSTREAM_HAS_METHOD (decoding, rewinder);
6168   LSTREAM_HAS_METHOD (decoding, seekable_p);
6169   LSTREAM_HAS_METHOD (decoding, flusher);
6170   LSTREAM_HAS_METHOD (decoding, closer);
6171   LSTREAM_HAS_METHOD (decoding, marker);
6172
6173   LSTREAM_HAS_METHOD (encoding, reader);
6174   LSTREAM_HAS_METHOD (encoding, writer);
6175   LSTREAM_HAS_METHOD (encoding, rewinder);
6176   LSTREAM_HAS_METHOD (encoding, seekable_p);
6177   LSTREAM_HAS_METHOD (encoding, flusher);
6178   LSTREAM_HAS_METHOD (encoding, closer);
6179   LSTREAM_HAS_METHOD (encoding, marker);
6180 }
6181
6182 void
6183 vars_of_file_coding (void)
6184 {
6185   int i;
6186
6187   fcd = xnew (struct file_coding_dump);
6188   dump_add_root_struct_ptr (&fcd, &fcd_description);
6189
6190   /* Initialize to something reasonable ... */
6191   for (i = 0; i < CODING_CATEGORY_LAST; i++)
6192     {
6193       fcd->coding_category_system[i] = Qnil;
6194       fcd->coding_category_by_priority[i] = i;
6195     }
6196
6197   Fprovide (intern ("file-coding"));
6198
6199   DEFVAR_LISP ("keyboard-coding-system", &Vkeyboard_coding_system /*
6200 Coding system used for TTY keyboard input.
6201 Not used under a windowing system.
6202 */ );
6203   Vkeyboard_coding_system = Qnil;
6204
6205   DEFVAR_LISP ("terminal-coding-system", &Vterminal_coding_system /*
6206 Coding system used for TTY display output.
6207 Not used under a windowing system.
6208 */ );
6209   Vterminal_coding_system = Qnil;
6210
6211   DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read /*
6212 Overriding coding system used when reading from a file or process.
6213 You should bind this variable with `let', but do not set it globally.
6214 If this is non-nil, it specifies the coding system that will be used
6215 to decode input on read operations, such as from a file or process.
6216 It overrides `buffer-file-coding-system-for-read',
6217 `insert-file-contents-pre-hook', etc.  Use those variables instead of
6218 this one for permanent changes to the environment.  */ );
6219   Vcoding_system_for_read = Qnil;
6220
6221   DEFVAR_LISP ("coding-system-for-write",
6222                &Vcoding_system_for_write /*
6223 Overriding coding system used when writing to a file or process.
6224 You should bind this variable with `let', but do not set it globally.
6225 If this is non-nil, it specifies the coding system that will be used
6226 to encode output for write operations, such as to a file or process.
6227 It overrides `buffer-file-coding-system', `write-region-pre-hook', etc.
6228 Use those variables instead of this one for permanent changes to the
6229 environment.  */ );
6230   Vcoding_system_for_write = Qnil;
6231
6232   DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system /*
6233 Coding system used to convert pathnames when accessing files.
6234 */ );
6235   Vfile_name_coding_system = Qnil;
6236
6237   DEFVAR_LISP ("coded-charset-entity-reference-alist",
6238                &Vcoded_charset_entity_reference_alist /*
6239 Alist of coded-charset vs corresponding entity-reference.
6240 Each element looks like (CCS PREFIX CODE-COLUMNS CODE-TYPE).
6241 CCS is coded-charset.
6242 CODE-COLUMNS is columns of code-point of entity-reference.
6243 CODE-TYPE is format type of code-point of entity-reference.
6244 `d' means decimal value and `x' means hexadecimal value.
6245 */ );
6246   Vcoded_charset_entity_reference_alist = Qnil;
6247
6248   DEFVAR_BOOL ("enable-multibyte-characters", &enable_multibyte_characters /*
6249 Non-nil means the buffer contents are regarded as multi-byte form
6250 of characters, not a binary code.  This affects the display, file I/O,
6251 and behaviors of various editing commands.
6252
6253 Setting this to nil does not do anything.
6254 */ );
6255   enable_multibyte_characters = 1;
6256 }
6257
6258 void
6259 complex_vars_of_file_coding (void)
6260 {
6261   staticpro (&Vcoding_system_hash_table);
6262   Vcoding_system_hash_table =
6263     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
6264
6265   the_codesys_prop_dynarr = Dynarr_new (codesys_prop);
6266   dump_add_root_struct_ptr (&the_codesys_prop_dynarr, &codesys_prop_dynarr_description);
6267
6268 #define DEFINE_CODESYS_PROP(Prop_Type, Sym) do  \
6269 {                                               \
6270   struct codesys_prop csp;                      \
6271   csp.sym = (Sym);                              \
6272   csp.prop_type = (Prop_Type);                  \
6273   Dynarr_add (the_codesys_prop_dynarr, csp);    \
6274 } while (0)
6275
6276   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qmnemonic);
6277   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_type);
6278   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_cr);
6279   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_crlf);
6280   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_lf);
6281   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpost_read_conversion);
6282   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpre_write_conversion);
6283 #ifdef MULE
6284   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g0);
6285   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g1);
6286   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g2);
6287   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g3);
6288   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g0_on_output);
6289   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g1_on_output);
6290   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g2_on_output);
6291   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g3_on_output);
6292   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qshort);
6293   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_eol);
6294   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_cntl);
6295   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qseven);
6296   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qlock_shift);
6297   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_iso6429);
6298   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qescape_quoted);
6299   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qinput_charset_conversion);
6300   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qoutput_charset_conversion);
6301
6302   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qencode);
6303   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qdecode);
6304 #ifdef UTF2000
6305   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qdisable_composition);
6306   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Quse_entity_reference);
6307 #endif
6308 #endif /* MULE */
6309   /* Need to create this here or we're really screwed. */
6310   Fmake_coding_system
6311     (Qraw_text, Qno_conversion,
6312      build_string ("Raw text, which means it converts only line-break-codes."),
6313      list2 (Qmnemonic, build_string ("Raw")));
6314
6315   Fmake_coding_system
6316     (Qbinary, Qno_conversion,
6317      build_string ("Binary, which means it does not convert anything."),
6318      list4 (Qeol_type, Qlf,
6319             Qmnemonic, build_string ("Binary")));
6320
6321 #ifdef UTF2000
6322   Fmake_coding_system
6323     (Qutf_8_mcs, Qutf8,
6324      build_string
6325      ("Coding-system of UTF-8 with Multiple Coded-character-Sets extension."),
6326      list2 (Qmnemonic, build_string ("MTF8")));
6327 #endif
6328
6329   Fdefine_coding_system_alias (Qno_conversion, Qraw_text);
6330
6331   Fdefine_coding_system_alias (Qfile_name, Qbinary);
6332
6333   Fdefine_coding_system_alias (Qterminal, Qbinary);
6334   Fdefine_coding_system_alias (Qkeyboard, Qbinary);
6335
6336   /* Need this for bootstrapping */
6337   fcd->coding_category_system[CODING_CATEGORY_NO_CONVERSION] =
6338     Fget_coding_system (Qraw_text);
6339
6340 #ifdef UTF2000
6341   fcd->coding_category_system[CODING_CATEGORY_UTF8]
6342    = Fget_coding_system (Qutf_8_mcs);
6343 #endif
6344
6345 #if defined(MULE) && !defined(UTF2000)
6346   {
6347     size_t i;
6348
6349     for (i = 0; i < countof (fcd->ucs_to_mule_table); i++)
6350       fcd->ucs_to_mule_table[i] = Qnil;
6351   }
6352   staticpro (&mule_to_ucs_table);
6353   mule_to_ucs_table = Fmake_char_table(Qgeneric);
6354 #endif /* defined(MULE) && !defined(UTF2000) */
6355 }