update.
[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
3989         Dynarr_add (dst, '?');
3990 #else
3991 #endif
3992     }
3993 }
3994
3995 void
3996 char_finish_big5 (struct encoding_stream *str, unsigned_char_dynarr *dst,
3997                   unsigned int *flags)
3998 {
3999 }
4000
4001
4002 DEFUN ("decode-big5-char", Fdecode_big5_char, 1, 1, 0, /*
4003 Decode a Big5 character CODE of BIG5 coding-system.
4004 CODE is the character code in BIG5, a cons of two integers.
4005 Return the corresponding character.
4006 */
4007        (code))
4008 {
4009   unsigned char c1, c2, b1, b2;
4010
4011   CHECK_CONS (code);
4012   CHECK_INT (XCAR (code));
4013   CHECK_INT (XCDR (code));
4014   b1 = XINT (XCAR (code));
4015   b2 = XINT (XCDR (code));
4016   if (BYTE_BIG5_TWO_BYTE_1_P (b1) &&
4017       BYTE_BIG5_TWO_BYTE_2_P (b2))
4018     {
4019       Charset_ID leading_byte;
4020       Lisp_Object charset;
4021       DECODE_BIG5 (b1, b2, leading_byte, c1, c2);
4022       charset = CHARSET_BY_LEADING_BYTE (leading_byte);
4023       return make_char (MAKE_CHAR (charset, c1 & 0x7F, c2 & 0x7F));
4024     }
4025   else
4026     return Qnil;
4027 }
4028
4029 DEFUN ("encode-big5-char", Fencode_big5_char, 1, 1, 0, /*
4030 Encode the Big5 character CHARACTER in the BIG5 coding-system.
4031 Return the corresponding character code in Big5.
4032 */
4033        (character))
4034 {
4035   Lisp_Object charset;
4036   int c1, c2, b1, b2;
4037
4038   CHECK_CHAR_COERCE_INT (character);
4039   BREAKUP_CHAR (XCHAR (character), charset, c1, c2);
4040   if (EQ (charset, Vcharset_chinese_big5_1) ||
4041       EQ (charset, Vcharset_chinese_big5_2))
4042     {
4043       ENCODE_BIG5 (XCHARSET_LEADING_BYTE (charset), c1 | 0x80, c2 | 0x80,
4044                    b1, b2);
4045       return Fcons (make_int (b1), make_int (b2));
4046     }
4047   else
4048     return Qnil;
4049 }
4050
4051 \f
4052 /************************************************************************/
4053 /*                           UCS-4 methods                              */
4054 /************************************************************************/
4055
4056 static int
4057 detect_coding_ucs4 (struct detection_state *st, const Extbyte *src, size_t n)
4058 {
4059   while (n--)
4060     {
4061       unsigned char c = *(unsigned char *)src++;
4062       switch (st->ucs4.in_byte)
4063         {
4064         case 0:
4065           if (c >= 128)
4066             return 0;
4067           else
4068             st->ucs4.in_byte++;
4069           break;
4070         case 3:
4071           st->ucs4.in_byte = 0;
4072           break;
4073         default:
4074           st->ucs4.in_byte++;
4075         }
4076     }
4077   return CODING_CATEGORY_UCS4_MASK;
4078 }
4079
4080 static void
4081 decode_coding_ucs4 (Lstream *decoding, const Extbyte *src,
4082                     unsigned_char_dynarr *dst, size_t n)
4083 {
4084   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4085   unsigned int flags = str->flags;
4086   unsigned int cpos  = str->cpos;
4087   unsigned char counter = str->counter;
4088
4089   while (n--)
4090     {
4091       unsigned char c = *(unsigned char *)src++;
4092       switch (counter)
4093         {
4094         case 0:
4095           cpos = c;
4096           counter = 3;
4097           break;
4098         case 1:
4099           DECODE_ADD_UCS_CHAR ((cpos << 8) | c, dst);
4100           cpos = 0;
4101           counter = 0;
4102           break;
4103         default:
4104           cpos = ( cpos << 8 ) | c;
4105           counter--;
4106         }
4107     }
4108   if (counter & CODING_STATE_END)
4109     DECODE_OUTPUT_PARTIAL_CHAR (cpos);
4110
4111   str->flags    = flags;
4112   str->cpos     = cpos;
4113   str->counter  = counter;
4114 }
4115
4116 void
4117 char_encode_ucs4 (struct encoding_stream *str, Emchar ch,
4118                   unsigned_char_dynarr *dst, unsigned int *flags)
4119 {
4120   Dynarr_add (dst, ch >> 24);
4121   Dynarr_add (dst, ch >> 16);
4122   Dynarr_add (dst, ch >>  8);
4123   Dynarr_add (dst, ch      );
4124 }
4125
4126 void
4127 char_finish_ucs4 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4128                   unsigned int *flags)
4129 {
4130 }
4131
4132 \f
4133 /************************************************************************/
4134 /*                           UTF-8 methods                              */
4135 /************************************************************************/
4136
4137 static int
4138 detect_coding_utf8 (struct detection_state *st, const Extbyte *src, size_t n)
4139 {
4140   while (n--)
4141     {
4142       unsigned char c = *(unsigned char *)src++;
4143       switch (st->utf8.in_byte)
4144         {
4145         case 0:
4146           if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
4147             return 0;
4148           else if (c >= 0xfc)
4149             st->utf8.in_byte = 5;
4150           else if (c >= 0xf8)
4151             st->utf8.in_byte = 4;
4152           else if (c >= 0xf0)
4153             st->utf8.in_byte = 3;
4154           else if (c >= 0xe0)
4155             st->utf8.in_byte = 2;
4156           else if (c >= 0xc0)
4157             st->utf8.in_byte = 1;
4158           else if (c >= 0x80)
4159             return 0;
4160           break;
4161         default:
4162           if ((c & 0xc0) != 0x80)
4163             return 0;
4164           else
4165             st->utf8.in_byte--;
4166         }
4167     }
4168   return CODING_CATEGORY_UTF8_MASK;
4169 }
4170
4171 static void
4172 decode_output_utf8_partial_char (unsigned char counter,
4173                                  unsigned int cpos,
4174                                  unsigned_char_dynarr *dst)
4175 {
4176   if (counter == 5)
4177     DECODE_ADD_BINARY_CHAR ( (cpos|0xFC), dst);
4178   else if (counter == 4)
4179     {
4180       if (cpos < (1 << 6))
4181         DECODE_ADD_BINARY_CHAR ( (cpos|0xF8), dst);
4182       else
4183         {
4184           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xFC), dst);
4185           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4186         }
4187     }
4188   else if (counter == 3)
4189     {
4190       if (cpos < (1 << 6))
4191         DECODE_ADD_BINARY_CHAR ( (cpos|0xF0), dst);
4192       else if (cpos < (1 << 12))
4193         {
4194           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xF8), dst);
4195           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4196         }
4197       else
4198         {
4199           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xFC), dst);
4200           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4201           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4202         }
4203     }
4204   else if (counter == 2)
4205     {
4206       if (cpos < (1 << 6))
4207         DECODE_ADD_BINARY_CHAR ( (cpos|0xE0), dst);
4208       else if (cpos < (1 << 12))
4209         {
4210           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xF0), dst);
4211           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4212         }
4213       else if (cpos < (1 << 18))
4214         {
4215           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xF8), dst);
4216           DECODE_ADD_BINARY_CHAR ( (((cpos >> 6)&0x3F)|0x80), dst);
4217           DECODE_ADD_BINARY_CHAR ( ( (cpos      &0x3F)|0x80), dst);
4218         }
4219       else
4220         {
4221           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 18)|0xFC), dst);
4222           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4223           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4224           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4225         }
4226     }
4227   else
4228     {
4229       if (cpos < (1 << 6))
4230         DECODE_ADD_BINARY_CHAR ( (cpos|0xC0), dst);
4231       else if (cpos < (1 << 12))
4232         {
4233           DECODE_ADD_BINARY_CHAR ( ((cpos >> 6)|0xE0), dst);
4234           DECODE_ADD_BINARY_CHAR ( ((cpos&0x3F)|0x80), dst);
4235         }
4236       else if (cpos < (1 << 18))
4237         {
4238           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 12)|0xF0), dst);
4239           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4240           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4241         }
4242       else if (cpos < (1 << 24))
4243         {
4244           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 18)|0xF8), dst);
4245           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4246           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4247           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4248         }
4249       else
4250         {
4251           DECODE_ADD_BINARY_CHAR ( ( (cpos >> 24)|0xFC), dst);
4252           DECODE_ADD_BINARY_CHAR ( (((cpos >> 18)&0x3F)|0x80), dst);
4253           DECODE_ADD_BINARY_CHAR ( (((cpos >> 12)&0x3F)|0x80), dst);
4254           DECODE_ADD_BINARY_CHAR ( (((cpos >>  6)&0x3F)|0x80), dst);
4255           DECODE_ADD_BINARY_CHAR ( ( (cpos       &0x3F)|0x80), dst);
4256         }
4257     }
4258 }
4259
4260 static void
4261 decode_coding_utf8 (Lstream *decoding, const Extbyte *src,
4262                     unsigned_char_dynarr *dst, size_t n)
4263 {
4264   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
4265   unsigned int flags    = str->flags;
4266   unsigned int cpos     = str->cpos;
4267   eol_type_t eol_type   = str->eol_type;
4268   unsigned char counter = str->counter;
4269 #ifdef UTF2000
4270   Lisp_Object ccs
4271     = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (DECODING_STREAM_DATA
4272                                              (decoding)->codesys, 0);
4273 #endif
4274
4275   while (n--)
4276     {
4277       unsigned char c = *(unsigned char *)src++;
4278       if (counter == 0)
4279         {
4280           if ( c < ' ' )
4281             {
4282               COMPOSE_FLUSH_CHARS (str, dst);
4283               decode_flush_er_chars (str, dst);
4284               DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
4285               DECODE_ADD_UCS_CHAR (c, dst);
4286             }
4287           else if ( c < 0xC0 )
4288             /* decode_add_er_char (str, c, dst); */
4289             COMPOSE_ADD_CHAR (str, c, dst);
4290           else
4291             {
4292               /* decode_flush_er_chars (str, dst); */
4293               if ( c < 0xE0 )
4294                 {
4295                   cpos = c & 0x1f;
4296                   counter = 1;
4297                 }
4298               else if ( c < 0xF0 )
4299                 {
4300                   cpos = c & 0x0f;
4301                   counter = 2;
4302                 }
4303               else if ( c < 0xF8 )
4304                 {
4305                   cpos = c & 0x07;
4306                   counter = 3;
4307                 }
4308               else if ( c < 0xFC )
4309                 {
4310                   cpos = c & 0x03;
4311                   counter = 4;
4312                 }
4313               else
4314                 {
4315                   cpos = c & 0x01;
4316                   counter = 5;
4317                 }
4318             }
4319         }
4320       else if ( (c & 0xC0) == 0x80 )
4321         {
4322           cpos = ( cpos << 6 ) | ( c & 0x3f );
4323           if (counter == 1)
4324             {
4325               Emchar char_id = decode_defined_char (ccs, cpos);
4326
4327               if (char_id < 0)
4328                 char_id = cpos;
4329               COMPOSE_ADD_CHAR (str, char_id, dst);
4330               cpos = 0;
4331               counter = 0;
4332             }
4333           else
4334             counter--;
4335         }
4336       else
4337         {
4338           COMPOSE_FLUSH_CHARS (str, dst);
4339           decode_flush_er_chars (str, dst);
4340           decode_output_utf8_partial_char (counter, cpos, dst);
4341           DECODE_ADD_BINARY_CHAR (c, dst);
4342           cpos = 0;
4343           counter = 0;
4344         }
4345     label_continue_loop:;
4346     }
4347
4348   if (flags & CODING_STATE_END)
4349     {
4350       COMPOSE_FLUSH_CHARS (str, dst);
4351       decode_flush_er_chars (str, dst);
4352       if (counter > 0)
4353         {
4354           decode_output_utf8_partial_char (counter, cpos, dst);
4355           cpos = 0;
4356           counter = 0;
4357         }
4358     }
4359   str->flags    = flags;
4360   str->cpos     = cpos;
4361   str->counter  = counter;
4362 }
4363
4364 void
4365 char_encode_utf8 (struct encoding_stream *str, Emchar ch,
4366                   unsigned_char_dynarr *dst, unsigned int *flags)
4367 {
4368   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
4369
4370   if (ch == '\n')
4371     {
4372       if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
4373         Dynarr_add (dst, '\r');
4374       if (eol_type != EOL_CR)
4375         Dynarr_add (dst, ch);
4376     }
4377   else if (ch <= 0x7f)
4378     {
4379       Dynarr_add (dst, ch);
4380     }
4381   else
4382     {
4383       Lisp_Object ucs_ccs
4384         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, 0);
4385       int code_point = charset_code_point (ucs_ccs, ch);
4386
4387       if ( (code_point < 0) || (code_point > 0x10FFFF) )
4388         {
4389           Lisp_Object map
4390             = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (str->codesys, 1);
4391           Lisp_Object ret;
4392
4393           if ( !NILP (map)
4394                && INTP (ret = Fget_char_attribute (make_char (ch),
4395                                                    map, Qnil)) )
4396             code_point = XINT (ret);
4397           else if ( !NILP (map =
4398                            CODING_SYSTEM_ISO2022_INITIAL_CHARSET
4399                            (str->codesys, 2))
4400                     && INTP (ret = Fget_char_attribute (make_char (ch),
4401                                                         map, Qnil)) )
4402             code_point = XINT (ret);
4403           else if (CODING_SYSTEM_USE_ENTITY_REFERENCE (str->codesys))
4404             {
4405               char buf[18];
4406
4407               char_encode_as_entity_reference (ch, buf);
4408               Dynarr_add_many (dst, buf, strlen (buf));
4409               return;
4410             }
4411           else
4412             code_point = ch;
4413         }
4414       if (code_point <= 0x7ff)
4415         {
4416           Dynarr_add (dst, (code_point >> 6) | 0xc0);
4417           Dynarr_add (dst, (code_point & 0x3f) | 0x80);
4418         }
4419       else if (code_point <= 0xffff)
4420         {
4421           Dynarr_add (dst,  (code_point >> 12) | 0xe0);
4422           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4423           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4424         }
4425       else if (code_point <= 0x1fffff)
4426         {
4427           Dynarr_add (dst,  (code_point >> 18) | 0xf0);
4428           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4429           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4430           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4431         }
4432       else if (code_point <= 0x3ffffff)
4433         {
4434           Dynarr_add (dst,  (code_point >> 24) | 0xf8);
4435           Dynarr_add (dst, ((code_point >> 18) & 0x3f) | 0x80);
4436           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4437           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4438           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4439         }
4440       else
4441         {
4442           Dynarr_add (dst,  (code_point >> 30) | 0xfc);
4443           Dynarr_add (dst, ((code_point >> 24) & 0x3f) | 0x80);
4444           Dynarr_add (dst, ((code_point >> 18) & 0x3f) | 0x80);
4445           Dynarr_add (dst, ((code_point >> 12) & 0x3f) | 0x80);
4446           Dynarr_add (dst, ((code_point >>  6) & 0x3f) | 0x80);
4447           Dynarr_add (dst,  (code_point        & 0x3f) | 0x80);
4448         }
4449     }
4450 }
4451
4452 void
4453 char_finish_utf8 (struct encoding_stream *str, unsigned_char_dynarr *dst,
4454                   unsigned int *flags)
4455 {
4456 }
4457
4458 \f
4459 /************************************************************************/
4460 /*                           ISO2022 methods                            */
4461 /************************************************************************/
4462
4463 /* The following note describes the coding system ISO2022 briefly.
4464    Since the intention of this note is to help understand the
4465    functions in this file, some parts are NOT ACCURATE or OVERLY
4466    SIMPLIFIED.  For thorough understanding, please refer to the
4467    original document of ISO2022.
4468
4469    ISO2022 provides many mechanisms to encode several character sets
4470    in 7-bit and 8-bit environments.  For 7-bit environments, all text
4471    is encoded using bytes less than 128.  This may make the encoded
4472    text a little bit longer, but the text passes more easily through
4473    several gateways, some of which strip off MSB (Most Signigant Bit).
4474
4475    There are two kinds of character sets: control character set and
4476    graphic character set.  The former contains control characters such
4477    as `newline' and `escape' to provide control functions (control
4478    functions are also provided by escape sequences).  The latter
4479    contains graphic characters such as 'A' and '-'.  Emacs recognizes
4480    two control character sets and many graphic character sets.
4481
4482    Graphic character sets are classified into one of the following
4483    four classes, according to the number of bytes (DIMENSION) and
4484    number of characters in one dimension (CHARS) of the set:
4485    - DIMENSION1_CHARS94
4486    - DIMENSION1_CHARS96
4487    - DIMENSION2_CHARS94
4488    - DIMENSION2_CHARS96
4489
4490    In addition, each character set is assigned an identification tag,
4491    unique for each set, called "final character" (denoted as <F>
4492    hereafter).  The <F> of each character set is decided by ECMA(*)
4493    when it is registered in ISO.  The code range of <F> is 0x30..0x7F
4494    (0x30..0x3F are for private use only).
4495
4496    Note (*): ECMA = European Computer Manufacturers Association
4497
4498    Here are examples of graphic character set [NAME(<F>)]:
4499         o DIMENSION1_CHARS94 -- ASCII('B'), right-half-of-JISX0201('I'), ...
4500         o DIMENSION1_CHARS96 -- right-half-of-ISO8859-1('A'), ...
4501         o DIMENSION2_CHARS94 -- GB2312('A'), JISX0208('B'), ...
4502         o DIMENSION2_CHARS96 -- none for the moment
4503
4504    A code area (1 byte = 8 bits) is divided into 4 areas, C0, GL, C1, and GR.
4505         C0 [0x00..0x1F] -- control character plane 0
4506         GL [0x20..0x7F] -- graphic character plane 0
4507         C1 [0x80..0x9F] -- control character plane 1
4508         GR [0xA0..0xFF] -- graphic character plane 1
4509
4510    A control character set is directly designated and invoked to C0 or
4511    C1 by an escape sequence.  The most common case is that:
4512    - ISO646's  control character set is designated/invoked to C0, and
4513    - ISO6429's control character set is designated/invoked to C1,
4514    and usually these designations/invocations are omitted in encoded
4515    text.  In a 7-bit environment, only C0 can be used, and a control
4516    character for C1 is encoded by an appropriate escape sequence to
4517    fit into the environment.  All control characters for C1 are
4518    defined to have corresponding escape sequences.
4519
4520    A graphic character set is at first designated to one of four
4521    graphic registers (G0 through G3), then these graphic registers are
4522    invoked to GL or GR.  These designations and invocations can be
4523    done independently.  The most common case is that G0 is invoked to
4524    GL, G1 is invoked to GR, and ASCII is designated to G0.  Usually
4525    these invocations and designations are omitted in encoded text.
4526    In a 7-bit environment, only GL can be used.
4527
4528    When a graphic character set of CHARS94 is invoked to GL, codes
4529    0x20 and 0x7F of the GL area work as control characters SPACE and
4530    DEL respectively, and codes 0xA0 and 0xFF of the GR area should not
4531    be used.
4532
4533    There are two ways of invocation: locking-shift and single-shift.
4534    With locking-shift, the invocation lasts until the next different
4535    invocation, whereas with single-shift, the invocation affects the
4536    following character only and doesn't affect the locking-shift
4537    state.  Invocations are done by the following control characters or
4538    escape sequences:
4539
4540    ----------------------------------------------------------------------
4541    abbrev  function                  cntrl escape seq   description
4542    ----------------------------------------------------------------------
4543    SI/LS0  (shift-in)                0x0F  none         invoke G0 into GL
4544    SO/LS1  (shift-out)               0x0E  none         invoke G1 into GL
4545    LS2     (locking-shift-2)         none  ESC 'n'      invoke G2 into GL
4546    LS3     (locking-shift-3)         none  ESC 'o'      invoke G3 into GL
4547    LS1R    (locking-shift-1 right)   none  ESC '~'      invoke G1 into GR (*)
4548    LS2R    (locking-shift-2 right)   none  ESC '}'      invoke G2 into GR (*)
4549    LS3R    (locking-shift 3 right)   none  ESC '|'      invoke G3 into GR (*)
4550    SS2     (single-shift-2)          0x8E  ESC 'N'      invoke G2 for one char
4551    SS3     (single-shift-3)          0x8F  ESC 'O'      invoke G3 for one char
4552    ----------------------------------------------------------------------
4553    (*) These are not used by any known coding system.
4554
4555    Control characters for these functions are defined by macros
4556    ISO_CODE_XXX in `coding.h'.
4557
4558    Designations are done by the following escape sequences:
4559    ----------------------------------------------------------------------
4560    escape sequence      description
4561    ----------------------------------------------------------------------
4562    ESC '(' <F>          designate DIMENSION1_CHARS94<F> to G0
4563    ESC ')' <F>          designate DIMENSION1_CHARS94<F> to G1
4564    ESC '*' <F>          designate DIMENSION1_CHARS94<F> to G2
4565    ESC '+' <F>          designate DIMENSION1_CHARS94<F> to G3
4566    ESC ',' <F>          designate DIMENSION1_CHARS96<F> to G0 (*)
4567    ESC '-' <F>          designate DIMENSION1_CHARS96<F> to G1
4568    ESC '.' <F>          designate DIMENSION1_CHARS96<F> to G2
4569    ESC '/' <F>          designate DIMENSION1_CHARS96<F> to G3
4570    ESC '$' '(' <F>      designate DIMENSION2_CHARS94<F> to G0 (**)
4571    ESC '$' ')' <F>      designate DIMENSION2_CHARS94<F> to G1
4572    ESC '$' '*' <F>      designate DIMENSION2_CHARS94<F> to G2
4573    ESC '$' '+' <F>      designate DIMENSION2_CHARS94<F> to G3
4574    ESC '$' ',' <F>      designate DIMENSION2_CHARS96<F> to G0 (*)
4575    ESC '$' '-' <F>      designate DIMENSION2_CHARS96<F> to G1
4576    ESC '$' '.' <F>      designate DIMENSION2_CHARS96<F> to G2
4577    ESC '$' '/' <F>      designate DIMENSION2_CHARS96<F> to G3
4578    ----------------------------------------------------------------------
4579
4580    In this list, "DIMENSION1_CHARS94<F>" means a graphic character set
4581    of dimension 1, chars 94, and final character <F>, etc...
4582
4583    Note (*): Although these designations are not allowed in ISO2022,
4584    Emacs accepts them on decoding, and produces them on encoding
4585    CHARS96 character sets in a coding system which is characterized as
4586    7-bit environment, non-locking-shift, and non-single-shift.
4587
4588    Note (**): If <F> is '@', 'A', or 'B', the intermediate character
4589    '(' can be omitted.  We refer to this as "short-form" hereafter.
4590
4591    Now you may notice that there are a lot of ways for encoding the
4592    same multilingual text in ISO2022.  Actually, there exist many
4593    coding systems such as Compound Text (used in X11's inter client
4594    communication, ISO-2022-JP (used in Japanese internet), ISO-2022-KR
4595    (used in Korean internet), EUC (Extended UNIX Code, used in Asian
4596    localized platforms), and all of these are variants of ISO2022.
4597
4598    In addition to the above, Emacs handles two more kinds of escape
4599    sequences: ISO6429's direction specification and Emacs' private
4600    sequence for specifying character composition.
4601
4602    ISO6429's direction specification takes the following form:
4603         o CSI ']'      -- end of the current direction
4604         o CSI '0' ']'  -- end of the current direction
4605         o CSI '1' ']'  -- start of left-to-right text
4606         o CSI '2' ']'  -- start of right-to-left text
4607    The control character CSI (0x9B: control sequence introducer) is
4608    abbreviated to the escape sequence ESC '[' in a 7-bit environment.
4609
4610    Character composition specification takes the following form:
4611         o ESC '0' -- start character composition
4612         o ESC '1' -- end character composition
4613    Since these are not standard escape sequences of any ISO standard,
4614    their use with these meanings is restricted to Emacs only.  */
4615
4616 static void
4617 reset_iso2022 (Lisp_Object coding_system, struct iso2022_decoder *iso)
4618 {
4619   int i;
4620
4621   for (i = 0; i < 4; i++)
4622     {
4623       if (!NILP (coding_system))
4624         iso->charset[i] =
4625           XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, i);
4626       else
4627         iso->charset[i] = Qt;
4628       iso->invalid_designated[i] = 0;
4629     }
4630   iso->esc = ISO_ESC_NOTHING;
4631   iso->esc_bytes_index = 0;
4632   iso->register_left = 0;
4633   iso->register_right = 1;
4634   iso->switched_dir_and_no_valid_charset_yet = 0;
4635   iso->invalid_switch_dir = 0;
4636   iso->output_direction_sequence = 0;
4637   iso->output_literally = 0;
4638 #ifdef ENABLE_COMPOSITE_CHARS
4639   if (iso->composite_chars)
4640     Dynarr_reset (iso->composite_chars);
4641 #endif
4642 }
4643
4644 static int
4645 fit_to_be_escape_quoted (unsigned char c)
4646 {
4647   switch (c)
4648     {
4649     case ISO_CODE_ESC:
4650     case ISO_CODE_CSI:
4651     case ISO_CODE_SS2:
4652     case ISO_CODE_SS3:
4653     case ISO_CODE_SO:
4654     case ISO_CODE_SI:
4655       return 1;
4656
4657     default:
4658       return 0;
4659     }
4660 }
4661
4662 /* Parse one byte of an ISO2022 escape sequence.
4663    If the result is an invalid escape sequence, return 0 and
4664    do not change anything in STR.  Otherwise, if the result is
4665    an incomplete escape sequence, update ISO2022.ESC and
4666    ISO2022.ESC_BYTES and return -1.  Otherwise, update
4667    all the state variables (but not ISO2022.ESC_BYTES) and
4668    return 1.
4669
4670    If CHECK_INVALID_CHARSETS is non-zero, check for designation
4671    or invocation of an invalid character set and treat that as
4672    an unrecognized escape sequence. */
4673
4674 static int
4675 parse_iso2022_esc (Lisp_Object codesys, struct iso2022_decoder *iso,
4676                    unsigned char c, unsigned int *flags,
4677                    int check_invalid_charsets)
4678 {
4679   /* (1) If we're at the end of a designation sequence, CS is the
4680      charset being designated and REG is the register to designate
4681      it to.
4682
4683      (2) If we're at the end of a locking-shift sequence, REG is
4684      the register to invoke and HALF (0 == left, 1 == right) is
4685      the half to invoke it into.
4686
4687      (3) If we're at the end of a single-shift sequence, REG is
4688      the register to invoke. */
4689   Lisp_Object cs = Qnil;
4690   int reg, half;
4691
4692   /* NOTE: This code does goto's all over the fucking place.
4693      The reason for this is that we're basically implementing
4694      a state machine here, and hierarchical languages like C
4695      don't really provide a clean way of doing this. */
4696
4697   if (! (*flags & CODING_STATE_ESCAPE))
4698     /* At beginning of escape sequence; we need to reset our
4699        escape-state variables. */
4700     iso->esc = ISO_ESC_NOTHING;
4701
4702   iso->output_literally = 0;
4703   iso->output_direction_sequence = 0;
4704
4705   switch (iso->esc)
4706     {
4707     case ISO_ESC_NOTHING:
4708       iso->esc_bytes_index = 0;
4709       switch (c)
4710         {
4711         case ISO_CODE_ESC:      /* Start escape sequence */
4712           *flags |= CODING_STATE_ESCAPE;
4713           iso->esc = ISO_ESC;
4714           goto not_done;
4715
4716         case ISO_CODE_CSI:      /* ISO6429 (specifying directionality) */
4717           *flags |= CODING_STATE_ESCAPE;
4718           iso->esc = ISO_ESC_5_11;
4719           goto not_done;
4720
4721         case ISO_CODE_SO:       /* locking shift 1 */
4722           reg = 1; half = 0;
4723           goto locking_shift;
4724         case ISO_CODE_SI:       /* locking shift 0 */
4725           reg = 0; half = 0;
4726           goto locking_shift;
4727
4728         case ISO_CODE_SS2:      /* single shift */
4729           reg = 2;
4730           goto single_shift;
4731         case ISO_CODE_SS3:      /* single shift */
4732           reg = 3;
4733           goto single_shift;
4734
4735         default:                        /* Other control characters */
4736           return 0;
4737         }
4738
4739     case ISO_ESC:
4740       switch (c)
4741         {
4742           /**** single shift ****/
4743
4744         case 'N':       /* single shift 2 */
4745           reg = 2;
4746           goto single_shift;
4747         case 'O':       /* single shift 3 */
4748           reg = 3;
4749           goto single_shift;
4750
4751           /**** locking shift ****/
4752
4753         case '~':       /* locking shift 1 right */
4754           reg = 1; half = 1;
4755           goto locking_shift;
4756         case 'n':       /* locking shift 2 */
4757           reg = 2; half = 0;
4758           goto locking_shift;
4759         case '}':       /* locking shift 2 right */
4760           reg = 2; half = 1;
4761           goto locking_shift;
4762         case 'o':       /* locking shift 3 */
4763           reg = 3; half = 0;
4764           goto locking_shift;
4765         case '|':       /* locking shift 3 right */
4766           reg = 3; half = 1;
4767           goto locking_shift;
4768
4769 #ifdef ENABLE_COMPOSITE_CHARS
4770           /**** composite ****/
4771
4772         case '0':
4773           iso->esc = ISO_ESC_START_COMPOSITE;
4774           *flags = (*flags & CODING_STATE_ISO2022_LOCK) |
4775             CODING_STATE_COMPOSITE;
4776           return 1;
4777
4778         case '1':
4779           iso->esc = ISO_ESC_END_COMPOSITE;
4780           *flags = (*flags & CODING_STATE_ISO2022_LOCK) &
4781             ~CODING_STATE_COMPOSITE;
4782           return 1;
4783 #endif /* ENABLE_COMPOSITE_CHARS */
4784
4785           /**** directionality ****/
4786
4787         case '[':
4788           iso->esc = ISO_ESC_5_11;
4789           goto not_done;
4790
4791           /**** designation ****/
4792
4793         case '$':       /* multibyte charset prefix */
4794           iso->esc = ISO_ESC_2_4;
4795           goto not_done;
4796
4797         default:
4798           if (0x28 <= c && c <= 0x2F)
4799             {
4800               iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_8);
4801               goto not_done;
4802             }
4803
4804           /* This function is called with CODESYS equal to nil when
4805              doing coding-system detection. */
4806           if (!NILP (codesys)
4807               && XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
4808               && fit_to_be_escape_quoted (c))
4809             {
4810               iso->esc = ISO_ESC_LITERAL;
4811               *flags &= CODING_STATE_ISO2022_LOCK;
4812               return 1;
4813             }
4814
4815           /* bzzzt! */
4816           return 0;
4817         }
4818
4819
4820
4821       /**** directionality ****/
4822
4823     case ISO_ESC_5_11:          /* ISO6429 direction control */
4824       if (c == ']')
4825         {
4826           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4827           goto directionality;
4828         }
4829       if      (c == '0') iso->esc = ISO_ESC_5_11_0;
4830       else if (c == '1') iso->esc = ISO_ESC_5_11_1;
4831       else if (c == '2') iso->esc = ISO_ESC_5_11_2;
4832       else               return 0;
4833       goto not_done;
4834
4835     case ISO_ESC_5_11_0:
4836       if (c == ']')
4837         {
4838           *flags &= (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4839           goto directionality;
4840         }
4841       return 0;
4842
4843     case ISO_ESC_5_11_1:
4844       if (c == ']')
4845         {
4846           *flags = (CODING_STATE_ISO2022_LOCK & ~CODING_STATE_R2L);
4847           goto directionality;
4848         }
4849       return 0;
4850
4851     case ISO_ESC_5_11_2:
4852       if (c == ']')
4853         {
4854           *flags = (*flags & CODING_STATE_ISO2022_LOCK) | CODING_STATE_R2L;
4855           goto directionality;
4856         }
4857       return 0;
4858
4859     directionality:
4860       iso->esc = ISO_ESC_DIRECTIONALITY;
4861       /* Various junk here to attempt to preserve the direction sequences
4862          literally in the text if they would otherwise be swallowed due
4863          to invalid designations that don't show up as actual charset
4864          changes in the text. */
4865       if (iso->invalid_switch_dir)
4866         {
4867           /* We already inserted a direction switch literally into the
4868              text.  We assume (#### this may not be right) that the
4869              next direction switch is the one going the other way,
4870              and we need to output that literally as well. */
4871           iso->output_literally = 1;
4872           iso->invalid_switch_dir = 0;
4873         }
4874       else
4875         {
4876           int jj;
4877
4878           /* If we are in the thrall of an invalid designation,
4879            then stick the directionality sequence literally into the
4880            output stream so it ends up in the original text again. */
4881           for (jj = 0; jj < 4; jj++)
4882             if (iso->invalid_designated[jj])
4883               break;
4884           if (jj < 4)
4885             {
4886               iso->output_literally = 1;
4887               iso->invalid_switch_dir = 1;
4888             }
4889           else
4890             /* Indicate that we haven't yet seen a valid designation,
4891                so that if a switch-dir is directly followed by an
4892                invalid designation, both get inserted literally. */
4893             iso->switched_dir_and_no_valid_charset_yet = 1;
4894         }
4895       return 1;
4896
4897
4898       /**** designation ****/
4899
4900     case ISO_ESC_2_4:
4901       if (0x28 <= c && c <= 0x2F)
4902         {
4903           iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_4_8);
4904           goto not_done;
4905         }
4906       if (0x40 <= c && c <= 0x42)
4907         {
4908           /* 94^n-set */
4909           cs = CHARSET_BY_ATTRIBUTES (94, -1, c,
4910                                       *flags & CODING_STATE_R2L ?
4911                                       CHARSET_RIGHT_TO_LEFT :
4912                                       CHARSET_LEFT_TO_RIGHT);
4913           reg = 0;
4914           goto designated;
4915         }
4916       return 0;
4917
4918     default:
4919       {
4920         int chars = 0;
4921         int single = 0;
4922
4923         if (c < '0' || c > '~')
4924           return 0; /* bad final byte */
4925
4926         if (iso->esc >= ISO_ESC_2_8 &&
4927             iso->esc <= ISO_ESC_2_15)
4928           {
4929             chars = (iso->esc >= ISO_ESC_2_12) ? 96 : 94;
4930             single = 1; /* single-byte */
4931             reg = (iso->esc - ISO_ESC_2_8) & 3;
4932           }
4933         else if (iso->esc >= ISO_ESC_2_4_8 &&
4934                  iso->esc <= ISO_ESC_2_4_15)
4935           {
4936             chars = (iso->esc >= ISO_ESC_2_4_12) ? 96 : 94;
4937             single = -1; /* multi-byte */
4938             reg = (iso->esc - ISO_ESC_2_4_8) & 3;
4939           }
4940         else
4941           {
4942             /* Can this ever be reached? -slb */
4943             abort();
4944           }
4945
4946         cs = CHARSET_BY_ATTRIBUTES (chars, single, c,
4947                                     *flags & CODING_STATE_R2L ?
4948                                     CHARSET_RIGHT_TO_LEFT :
4949                                     CHARSET_LEFT_TO_RIGHT);
4950         goto designated;
4951       }
4952     }
4953
4954  not_done:
4955   iso->esc_bytes[iso->esc_bytes_index++] = (unsigned char) c;
4956   return -1;
4957
4958  single_shift:
4959   if (check_invalid_charsets && !CHARSETP (iso->charset[reg]))
4960     /* can't invoke something that ain't there. */
4961     return 0;
4962   iso->esc = ISO_ESC_SINGLE_SHIFT;
4963   *flags &= CODING_STATE_ISO2022_LOCK;
4964   if (reg == 2)
4965     *flags |= CODING_STATE_SS2;
4966   else
4967     *flags |= CODING_STATE_SS3;
4968   return 1;
4969
4970  locking_shift:
4971   if (check_invalid_charsets &&
4972       !CHARSETP (iso->charset[reg]))
4973     /* can't invoke something that ain't there. */
4974     return 0;
4975   if (half)
4976     iso->register_right = reg;
4977   else
4978     iso->register_left = reg;
4979   *flags &= CODING_STATE_ISO2022_LOCK;
4980   iso->esc = ISO_ESC_LOCKING_SHIFT;
4981   return 1;
4982
4983  designated:
4984   if (NILP (cs) && check_invalid_charsets)
4985     {
4986       iso->invalid_designated[reg] = 1;
4987       iso->charset[reg] = Vcharset_ascii;
4988       iso->esc = ISO_ESC_DESIGNATE;
4989       *flags &= CODING_STATE_ISO2022_LOCK;
4990       iso->output_literally = 1;
4991       if (iso->switched_dir_and_no_valid_charset_yet)
4992         {
4993           /* We encountered a switch-direction followed by an
4994              invalid designation.  Ensure that the switch-direction
4995              gets outputted; otherwise it will probably get eaten
4996              when the text is written out again. */
4997           iso->switched_dir_and_no_valid_charset_yet = 0;
4998           iso->output_direction_sequence = 1;
4999           /* And make sure that the switch-dir going the other
5000              way gets outputted, as well. */
5001           iso->invalid_switch_dir = 1;
5002         }
5003       return 1;
5004     }
5005   /* This function is called with CODESYS equal to nil when
5006      doing coding-system detection. */
5007   if (!NILP (codesys))
5008     {
5009       charset_conversion_spec_dynarr *dyn =
5010         XCODING_SYSTEM (codesys)->iso2022.input_conv;
5011
5012       if (dyn)
5013         {
5014           int i;
5015
5016           for (i = 0; i < Dynarr_length (dyn); i++)
5017             {
5018               struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
5019               if (EQ (cs, spec->from_charset))
5020                 cs = spec->to_charset;
5021             }
5022         }
5023     }
5024
5025   iso->charset[reg] = cs;
5026   iso->esc = ISO_ESC_DESIGNATE;
5027   *flags &= CODING_STATE_ISO2022_LOCK;
5028   if (iso->invalid_designated[reg])
5029     {
5030       iso->invalid_designated[reg] = 0;
5031       iso->output_literally = 1;
5032     }
5033   if (iso->switched_dir_and_no_valid_charset_yet)
5034     iso->switched_dir_and_no_valid_charset_yet = 0;
5035   return 1;
5036 }
5037
5038 static int
5039 detect_coding_iso2022 (struct detection_state *st, const Extbyte *src, size_t n)
5040 {
5041   int mask;
5042
5043   /* #### There are serious deficiencies in the recognition mechanism
5044      here.  This needs to be much smarter if it's going to cut it.
5045      The sequence "\xff\x0f" is currently detected as LOCK_SHIFT while
5046      it should be detected as Latin-1.
5047      All the ISO2022 stuff in this file should be synced up with the
5048      code from FSF Emacs-20.4, in which Mule should be more or less stable.
5049      Perhaps we should wait till R2L works in FSF Emacs? */
5050
5051   if (!st->iso2022.initted)
5052     {
5053       reset_iso2022 (Qnil, &st->iso2022.iso);
5054       st->iso2022.mask = (CODING_CATEGORY_ISO_7_MASK |
5055                           CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
5056                           CODING_CATEGORY_ISO_8_1_MASK |
5057                           CODING_CATEGORY_ISO_8_2_MASK |
5058                           CODING_CATEGORY_ISO_LOCK_SHIFT_MASK);
5059       st->iso2022.flags = 0;
5060       st->iso2022.high_byte_count = 0;
5061       st->iso2022.saw_single_shift = 0;
5062       st->iso2022.initted = 1;
5063     }
5064
5065   mask = st->iso2022.mask;
5066
5067   while (n--)
5068     {
5069       unsigned char c = *(unsigned char *)src++;
5070       if (c >= 0xA0)
5071         {
5072           mask &= ~CODING_CATEGORY_ISO_7_MASK;
5073           st->iso2022.high_byte_count++;
5074         }
5075       else
5076         {
5077           if (st->iso2022.high_byte_count && !st->iso2022.saw_single_shift)
5078             {
5079               if (st->iso2022.high_byte_count & 1)
5080                 /* odd number of high bytes; assume not iso-8-2 */
5081                 mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
5082             }
5083           st->iso2022.high_byte_count = 0;
5084           st->iso2022.saw_single_shift = 0;
5085           if (c > 0x80)
5086             mask &= ~CODING_CATEGORY_ISO_7_MASK;
5087         }
5088       if (!(st->iso2022.flags & CODING_STATE_ESCAPE)
5089           && (BYTE_C0_P (c) || BYTE_C1_P (c)))
5090         { /* control chars */
5091           switch (c)
5092             {
5093               /* Allow and ignore control characters that you might
5094                  reasonably see in a text file */
5095             case '\r':
5096             case '\n':
5097             case '\t':
5098             case  7: /* bell */
5099             case  8: /* backspace */
5100             case 11: /* vertical tab */
5101             case 12: /* form feed */
5102             case 26: /* MS-DOS C-z junk */
5103             case 31: /* '^_' -- for info */
5104               goto label_continue_loop;
5105
5106             default:
5107               break;
5108             }
5109         }
5110
5111       if ((st->iso2022.flags & CODING_STATE_ESCAPE) || BYTE_C0_P (c)
5112           || BYTE_C1_P (c))
5113         {
5114           if (parse_iso2022_esc (Qnil, &st->iso2022.iso, c,
5115                                  &st->iso2022.flags, 0))
5116             {
5117               switch (st->iso2022.iso.esc)
5118                 {
5119                 case ISO_ESC_DESIGNATE:
5120                   mask &= ~CODING_CATEGORY_ISO_8_1_MASK;
5121                   mask &= ~CODING_CATEGORY_ISO_8_2_MASK;
5122                   break;
5123                 case ISO_ESC_LOCKING_SHIFT:
5124                   mask = CODING_CATEGORY_ISO_LOCK_SHIFT_MASK;
5125                   goto ran_out_of_chars;
5126                 case ISO_ESC_SINGLE_SHIFT:
5127                   mask &= ~CODING_CATEGORY_ISO_8_DESIGNATE_MASK;
5128                   st->iso2022.saw_single_shift = 1;
5129                   break;
5130                 default:
5131                   break;
5132                 }
5133             }
5134           else
5135             {
5136               mask = 0;
5137               goto ran_out_of_chars;
5138             }
5139         }
5140     label_continue_loop:;
5141     }
5142
5143  ran_out_of_chars:
5144
5145   return mask;
5146 }
5147
5148 static int
5149 postprocess_iso2022_mask (int mask)
5150 {
5151   /* #### kind of cheesy */
5152   /* If seven-bit ISO is allowed, then assume that the encoding is
5153      entirely seven-bit and turn off the eight-bit ones. */
5154   if (mask & CODING_CATEGORY_ISO_7_MASK)
5155     mask &= ~ (CODING_CATEGORY_ISO_8_DESIGNATE_MASK |
5156                CODING_CATEGORY_ISO_8_1_MASK |
5157                CODING_CATEGORY_ISO_8_2_MASK);
5158   return mask;
5159 }
5160
5161 /* If FLAGS is a null pointer or specifies right-to-left motion,
5162    output a switch-dir-to-left-to-right sequence to DST.
5163    Also update FLAGS if it is not a null pointer.
5164    If INTERNAL_P is set, we are outputting in internal format and
5165    need to handle the CSI differently. */
5166
5167 static void
5168 restore_left_to_right_direction (Lisp_Coding_System *codesys,
5169                                  unsigned_char_dynarr *dst,
5170                                  unsigned int *flags,
5171                                  int internal_p)
5172 {
5173   if (!flags || (*flags & CODING_STATE_R2L))
5174     {
5175       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5176         {
5177           Dynarr_add (dst, ISO_CODE_ESC);
5178           Dynarr_add (dst, '[');
5179         }
5180       else if (internal_p)
5181         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
5182       else
5183         Dynarr_add (dst, ISO_CODE_CSI);
5184       Dynarr_add (dst, '0');
5185       Dynarr_add (dst, ']');
5186       if (flags)
5187         *flags &= ~CODING_STATE_R2L;
5188     }
5189 }
5190
5191 /* If FLAGS is a null pointer or specifies a direction different from
5192    DIRECTION (which should be either CHARSET_RIGHT_TO_LEFT or
5193    CHARSET_LEFT_TO_RIGHT), output the appropriate switch-dir escape
5194    sequence to DST.  Also update FLAGS if it is not a null pointer.
5195    If INTERNAL_P is set, we are outputting in internal format and
5196    need to handle the CSI differently. */
5197
5198 static void
5199 ensure_correct_direction (int direction, Lisp_Coding_System *codesys,
5200                           unsigned_char_dynarr *dst, unsigned int *flags,
5201                           int internal_p)
5202 {
5203   if ((!flags || (*flags & CODING_STATE_R2L)) &&
5204       direction == CHARSET_LEFT_TO_RIGHT)
5205     restore_left_to_right_direction (codesys, dst, flags, internal_p);
5206   else if (!CODING_SYSTEM_ISO2022_NO_ISO6429 (codesys)
5207            && (!flags || !(*flags & CODING_STATE_R2L)) &&
5208            direction == CHARSET_RIGHT_TO_LEFT)
5209     {
5210       if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5211         {
5212           Dynarr_add (dst, ISO_CODE_ESC);
5213           Dynarr_add (dst, '[');
5214         }
5215       else if (internal_p)
5216         DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
5217       else
5218         Dynarr_add (dst, ISO_CODE_CSI);
5219       Dynarr_add (dst, '2');
5220       Dynarr_add (dst, ']');
5221       if (flags)
5222         *flags |= CODING_STATE_R2L;
5223     }
5224 }
5225
5226 /* Convert ISO2022-format data to internal format. */
5227
5228 static void
5229 decode_coding_iso2022 (Lstream *decoding, const Extbyte *src,
5230                        unsigned_char_dynarr *dst, size_t n)
5231 {
5232   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
5233   unsigned int flags    = str->flags;
5234   unsigned int cpos     = str->cpos;
5235   unsigned char counter = str->counter;
5236   eol_type_t eol_type   = str->eol_type;
5237 #ifdef ENABLE_COMPOSITE_CHARS
5238   unsigned_char_dynarr *real_dst = dst;
5239 #endif
5240   Lisp_Object coding_system;
5241
5242   XSETCODING_SYSTEM (coding_system, str->codesys);
5243
5244 #ifdef ENABLE_COMPOSITE_CHARS
5245   if (flags & CODING_STATE_COMPOSITE)
5246     dst = str->iso2022.composite_chars;
5247 #endif /* ENABLE_COMPOSITE_CHARS */
5248
5249   while (n--)
5250     {
5251       unsigned char c = *(unsigned char *)src++;
5252       if (flags & CODING_STATE_ESCAPE)
5253         {       /* Within ESC sequence */
5254           int retval = parse_iso2022_esc (coding_system, &str->iso2022,
5255                                           c, &flags, 1);
5256
5257           if (retval)
5258             {
5259               switch (str->iso2022.esc)
5260                 {
5261 #ifdef ENABLE_COMPOSITE_CHARS
5262                 case ISO_ESC_START_COMPOSITE:
5263                   if (str->iso2022.composite_chars)
5264                     Dynarr_reset (str->iso2022.composite_chars);
5265                   else
5266                     str->iso2022.composite_chars = Dynarr_new (unsigned_char);
5267                   dst = str->iso2022.composite_chars;
5268                   break;
5269                 case ISO_ESC_END_COMPOSITE:
5270                   {
5271                     Bufbyte comstr[MAX_EMCHAR_LEN];
5272                     Bytecount len;
5273                     Emchar emch = lookup_composite_char (Dynarr_atp (dst, 0),
5274                                                          Dynarr_length (dst));
5275                     dst = real_dst;
5276                     len = set_charptr_emchar (comstr, emch);
5277                     Dynarr_add_many (dst, comstr, len);
5278                     break;
5279                   }
5280 #endif /* ENABLE_COMPOSITE_CHARS */
5281
5282                 case ISO_ESC_LITERAL:
5283                   COMPOSE_FLUSH_CHARS (str, dst);
5284                   decode_flush_er_chars (str, dst);
5285                   DECODE_ADD_BINARY_CHAR (c, dst);
5286                   break;
5287
5288                 default:
5289                   /* Everything else handled already */
5290                   break;
5291                 }
5292             }
5293
5294           /* Attempted error recovery. */
5295           if (str->iso2022.output_direction_sequence)
5296             ensure_correct_direction (flags & CODING_STATE_R2L ?
5297                                       CHARSET_RIGHT_TO_LEFT :
5298                                       CHARSET_LEFT_TO_RIGHT,
5299                                       str->codesys, dst, 0, 1);
5300           /* More error recovery. */
5301           if (!retval || str->iso2022.output_literally)
5302             {
5303               /* Output the (possibly invalid) sequence */
5304               int i;
5305               COMPOSE_FLUSH_CHARS (str, dst);
5306               decode_flush_er_chars (str, dst);
5307               for (i = 0; i < str->iso2022.esc_bytes_index; i++)
5308                 DECODE_ADD_BINARY_CHAR (str->iso2022.esc_bytes[i], dst);
5309               flags &= CODING_STATE_ISO2022_LOCK;
5310               if (!retval)
5311                 n++, src--;/* Repeat the loop with the same character. */
5312               else
5313                 {
5314                   /* No sense in reprocessing the final byte of the
5315                      escape sequence; it could mess things up anyway.
5316                      Just add it now. */
5317                   COMPOSE_FLUSH_CHARS (str, dst);
5318                   decode_flush_er_chars (str, dst);
5319                   DECODE_ADD_BINARY_CHAR (c, dst);
5320                 }
5321             }
5322           cpos = 0;
5323           counter = 0;
5324         }
5325       else if (BYTE_C0_P (c) || BYTE_C1_P (c))
5326         { /* Control characters */
5327
5328           /***** Error-handling *****/
5329
5330           /* If we were in the middle of a character, dump out the
5331              partial character. */
5332           if (counter)
5333             {
5334               COMPOSE_FLUSH_CHARS (str, dst);
5335               decode_flush_er_chars (str, dst);
5336               while (counter > 0)
5337                 {
5338                   counter--;
5339                   DECODE_ADD_BINARY_CHAR
5340                     ((unsigned char)(cpos >> (counter * 8)), dst);
5341                 }
5342               cpos = 0;
5343             }
5344
5345           /* If we just saw a single-shift character, dump it out.
5346              This may dump out the wrong sort of single-shift character,
5347              but least it will give an indication that something went
5348              wrong. */
5349           if (flags & CODING_STATE_SS2)
5350             {
5351               COMPOSE_FLUSH_CHARS (str, dst);
5352               decode_flush_er_chars (str, dst);
5353               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS2, dst);
5354               flags &= ~CODING_STATE_SS2;
5355             }
5356           if (flags & CODING_STATE_SS3)
5357             {
5358               COMPOSE_FLUSH_CHARS (str, dst);
5359               decode_flush_er_chars (str, dst);
5360               DECODE_ADD_BINARY_CHAR (ISO_CODE_SS3, dst);
5361               flags &= ~CODING_STATE_SS3;
5362             }
5363
5364           /***** Now handle the control characters. *****/
5365
5366           /* Handle CR/LF */
5367 #ifdef UTF2000
5368           if (c == '\r')
5369             {
5370               COMPOSE_FLUSH_CHARS (str, dst);
5371               decode_flush_er_chars (str, dst);
5372               if (eol_type == EOL_CR)
5373                 Dynarr_add (dst, '\n');
5374               else if (eol_type != EOL_CRLF || flags & CODING_STATE_CR)
5375                 Dynarr_add (dst, c);
5376               else
5377                 flags |= CODING_STATE_CR;
5378               goto label_continue_loop;
5379             }
5380           else if (flags & CODING_STATE_CR)
5381             {   /* eol_type == CODING_SYSTEM_EOL_CRLF */
5382               if (c != '\n')
5383                 Dynarr_add (dst, '\r');
5384               flags &= ~CODING_STATE_CR;
5385             }
5386 #else
5387           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5388 #endif
5389
5390           flags &= CODING_STATE_ISO2022_LOCK;
5391
5392           if (!parse_iso2022_esc (coding_system, &str->iso2022, c, &flags, 1))
5393             {
5394               COMPOSE_FLUSH_CHARS (str, dst);
5395               decode_flush_er_chars (str, dst);
5396               DECODE_ADD_BINARY_CHAR (c, dst);
5397             }
5398         }
5399       else
5400         {                       /* Graphic characters */
5401           Lisp_Object charset;
5402 #ifndef UTF2000
5403           Charset_ID lb;
5404 #endif
5405           int reg;
5406
5407 #ifdef UTF2000
5408           if (c == '\r')
5409             {
5410               COMPOSE_FLUSH_CHARS (str, dst);
5411               decode_flush_er_chars (str, dst);
5412               if (eol_type == EOL_CR)
5413                 Dynarr_add (dst, '\n');
5414               else if (eol_type != EOL_CRLF || flags & CODING_STATE_CR)
5415                 Dynarr_add (dst, c);
5416               else
5417                 flags |= CODING_STATE_CR;
5418               goto label_continue_loop;
5419             }
5420           else if (flags & CODING_STATE_CR)
5421             {   /* eol_type == CODING_SYSTEM_EOL_CRLF */
5422               if (c != '\n')
5423                 Dynarr_add (dst, '\r');
5424               flags &= ~CODING_STATE_CR;
5425             }
5426 #else
5427           DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5428 #endif
5429
5430           /* Now determine the charset. */
5431           reg = ((flags & CODING_STATE_SS2) ? 2
5432                  : (flags & CODING_STATE_SS3) ? 3
5433                  : !BYTE_ASCII_P (c) ? str->iso2022.register_right
5434                  : str->iso2022.register_left);
5435           charset = str->iso2022.charset[reg];
5436
5437           /* Error checking: */
5438           if (! CHARSETP (charset)
5439               || str->iso2022.invalid_designated[reg]
5440               || (((c & 0x7F) == ' ' || (c & 0x7F) == ISO_CODE_DEL)
5441                   && XCHARSET_CHARS (charset) == 94))
5442             /* Mrmph.  We are trying to invoke a register that has no
5443                or an invalid charset in it, or trying to add a character
5444                outside the range of the charset.  Insert that char literally
5445                to preserve it for the output. */
5446             {
5447               COMPOSE_FLUSH_CHARS (str, dst);
5448               decode_flush_er_chars (str, dst);
5449               while (counter > 0)
5450                 {
5451                   counter--;
5452                   DECODE_ADD_BINARY_CHAR
5453                     ((unsigned char)(cpos >> (counter * 8)), dst);
5454                 }
5455               cpos = 0;
5456               DECODE_ADD_BINARY_CHAR (c, dst);
5457             }
5458
5459           else
5460             {
5461               /* Things are probably hunky-dorey. */
5462
5463               /* Fetch reverse charset, maybe. */
5464               if (((flags & CODING_STATE_R2L) &&
5465                    XCHARSET_DIRECTION (charset) == CHARSET_LEFT_TO_RIGHT)
5466                   ||
5467                   (!(flags & CODING_STATE_R2L) &&
5468                    XCHARSET_DIRECTION (charset) == CHARSET_RIGHT_TO_LEFT))
5469                 {
5470                   Lisp_Object new_charset =
5471                     XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
5472                   if (!NILP (new_charset))
5473                     charset = new_charset;
5474                 }
5475
5476 #ifdef UTF2000
5477               counter++;
5478               if (XCHARSET_DIMENSION (charset) == counter)
5479                 {
5480                   COMPOSE_ADD_CHAR (str,
5481                                     DECODE_CHAR (charset,
5482                                                  ((cpos & 0x7F7F7F) << 8)
5483                                                  | (c & 0x7F)),
5484                                     dst);
5485                   cpos = 0;
5486                   counter = 0;
5487                 }
5488               else
5489                 cpos = (cpos << 8) | c;
5490 #else
5491               lb = XCHARSET_LEADING_BYTE (charset);
5492               switch (XCHARSET_REP_BYTES (charset))
5493                 {
5494                 case 1: /* ASCII */
5495                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
5496                   Dynarr_add (dst, c & 0x7F);
5497                   break;
5498
5499                 case 2: /* one-byte official */
5500                   DECODE_OUTPUT_PARTIAL_CHAR (ch);
5501                   Dynarr_add (dst, lb);
5502                   Dynarr_add (dst, c | 0x80);
5503                   break;
5504
5505                 case 3: /* one-byte private or two-byte official */
5506                   if (XCHARSET_PRIVATE_P (charset))
5507                     {
5508                       DECODE_OUTPUT_PARTIAL_CHAR (ch);
5509                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_1);
5510                       Dynarr_add (dst, lb);
5511                       Dynarr_add (dst, c | 0x80);
5512                     }
5513                   else
5514                     {
5515                       if (ch)
5516                         {
5517                           Dynarr_add (dst, lb);
5518                           Dynarr_add (dst, ch | 0x80);
5519                           Dynarr_add (dst, c | 0x80);
5520                           ch = 0;
5521                         }
5522                       else
5523                         ch = c;
5524                     }
5525                   break;
5526
5527                 default:        /* two-byte private */
5528                   if (ch)
5529                     {
5530                       Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_2);
5531                       Dynarr_add (dst, lb);
5532                       Dynarr_add (dst, ch | 0x80);
5533                       Dynarr_add (dst, c | 0x80);
5534                       ch = 0;
5535                     }
5536                   else
5537                     ch = c;
5538                 }
5539 #endif
5540             }
5541
5542           if (!cpos)
5543             flags &= CODING_STATE_ISO2022_LOCK;
5544         }
5545
5546     label_continue_loop:;
5547     }
5548
5549   if (flags & CODING_STATE_END)
5550     {
5551       COMPOSE_FLUSH_CHARS (str, dst);
5552       decode_flush_er_chars (str, dst);
5553       DECODE_OUTPUT_PARTIAL_CHAR (cpos);
5554     }
5555   str->flags   = flags;
5556   str->cpos    = cpos;
5557   str->counter = counter;
5558 }
5559
5560
5561 /***** ISO2022 encoder *****/
5562
5563 /* Designate CHARSET into register REG. */
5564
5565 static void
5566 iso2022_designate (Lisp_Object charset, unsigned char reg,
5567                    struct encoding_stream *str, unsigned_char_dynarr *dst)
5568 {
5569   static const char inter94[] = "()*+";
5570   static const char inter96[] = ",-./";
5571   unsigned short chars;
5572   unsigned char dimension;
5573   unsigned char final;
5574   Lisp_Object old_charset = str->iso2022.charset[reg];
5575
5576   str->iso2022.charset[reg] = charset;
5577   if (!CHARSETP (charset))
5578     /* charset might be an initial nil or t. */
5579     return;
5580   chars = XCHARSET_CHARS (charset);
5581   dimension = XCHARSET_DIMENSION (charset);
5582   final = XCHARSET_FINAL (charset);
5583   if (!str->iso2022.force_charset_on_output[reg] &&
5584       CHARSETP (old_charset) &&
5585       XCHARSET_CHARS (old_charset) == chars &&
5586       XCHARSET_DIMENSION (old_charset) == dimension &&
5587       XCHARSET_FINAL (old_charset) == final)
5588     return;
5589
5590   str->iso2022.force_charset_on_output[reg] = 0;
5591
5592   {
5593     charset_conversion_spec_dynarr *dyn =
5594       str->codesys->iso2022.output_conv;
5595
5596     if (dyn)
5597       {
5598         int i;
5599
5600         for (i = 0; i < Dynarr_length (dyn); i++)
5601           {
5602             struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
5603             if (EQ (charset, spec->from_charset))
5604                 charset = spec->to_charset;
5605           }
5606       }
5607   }
5608
5609   Dynarr_add (dst, ISO_CODE_ESC);
5610   switch (chars)
5611     {
5612     case 94:
5613       if (dimension == 1)
5614         Dynarr_add (dst, inter94[reg]);
5615       else
5616         {
5617           Dynarr_add (dst, '$');
5618           if (reg != 0
5619               || !(CODING_SYSTEM_ISO2022_SHORT (str->codesys))
5620               || final < '@'
5621               || final > 'B')
5622             Dynarr_add (dst, inter94[reg]);
5623         }
5624       break;
5625     case 96:
5626       if (dimension == 1)
5627         Dynarr_add (dst, inter96[reg]);
5628       else
5629         {
5630           Dynarr_add (dst, '$');
5631           Dynarr_add (dst, inter96[reg]);
5632         }
5633       break;
5634     }
5635   Dynarr_add (dst, final);
5636 }
5637
5638 static void
5639 ensure_normal_shift (struct encoding_stream *str, unsigned_char_dynarr *dst)
5640 {
5641   if (str->iso2022.register_left != 0)
5642     {
5643       Dynarr_add (dst, ISO_CODE_SI);
5644       str->iso2022.register_left = 0;
5645     }
5646 }
5647
5648 static void
5649 ensure_shift_out (struct encoding_stream *str, unsigned_char_dynarr *dst)
5650 {
5651   if (str->iso2022.register_left != 1)
5652     {
5653       Dynarr_add (dst, ISO_CODE_SO);
5654       str->iso2022.register_left = 1;
5655     }
5656 }
5657
5658 void
5659 char_encode_iso2022 (struct encoding_stream *str, Emchar ch,
5660                      unsigned_char_dynarr *dst, unsigned int *flags)
5661 {
5662   unsigned char charmask;
5663   Lisp_Coding_System* codesys = str->codesys;
5664   eol_type_t eol_type         = CODING_SYSTEM_EOL_TYPE (str->codesys);
5665   int i;
5666   Lisp_Object charset = str->iso2022.current_charset;
5667   int half = str->iso2022.current_half;
5668   int code_point = -1;
5669
5670   if (ch <= 0x7F)
5671     {
5672       restore_left_to_right_direction (codesys, dst, flags, 0);
5673               
5674       /* Make sure G0 contains ASCII */
5675       if ((ch > ' ' && ch < ISO_CODE_DEL)
5676           || !CODING_SYSTEM_ISO2022_NO_ASCII_CNTL (codesys))
5677         {
5678           ensure_normal_shift (str, dst);
5679           iso2022_designate (Vcharset_ascii, 0, str, dst);
5680         }
5681               
5682       /* If necessary, restore everything to the default state
5683          at end-of-line */
5684       if (ch == '\n' && !(CODING_SYSTEM_ISO2022_NO_ASCII_EOL (codesys)))
5685         {
5686           restore_left_to_right_direction (codesys, dst, flags, 0);
5687
5688           ensure_normal_shift (str, dst);
5689
5690           for (i = 0; i < 4; i++)
5691             {
5692               Lisp_Object initial_charset =
5693                 CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
5694               iso2022_designate (initial_charset, i, str, dst);
5695             }
5696         }
5697       if (ch == '\n')
5698         {
5699           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5700             Dynarr_add (dst, '\r');
5701           if (eol_type != EOL_CR)
5702             Dynarr_add (dst, ch);
5703         }
5704       else
5705         {
5706           if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
5707               && fit_to_be_escape_quoted (ch))
5708             Dynarr_add (dst, ISO_CODE_ESC);
5709           Dynarr_add (dst, ch);
5710         }
5711     }
5712   else if ( (0x80 <= ch) && (ch <= 0x9f) )
5713     {
5714       charmask = (half == 0 ? 0x00 : 0x80);
5715           
5716       if (CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
5717           && fit_to_be_escape_quoted (ch))
5718         Dynarr_add (dst, ISO_CODE_ESC);
5719       /* you asked for it ... */
5720       Dynarr_add (dst, ch);
5721     }
5722   else
5723     {
5724       int reg;
5725
5726       /* Now determine which register to use. */
5727       reg = -1;
5728       for (i = 0; i < 4; i++)
5729         {
5730           if ((CHARSETP (charset = str->iso2022.charset[i])
5731                && ((code_point = charset_code_point (charset, ch)) >= 0))
5732               ||
5733               (CHARSETP
5734                (charset
5735                 = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i))
5736                && ((code_point = charset_code_point (charset, ch)) >= 0)))
5737             {
5738               reg = i;
5739               break;
5740             }
5741         }
5742       if (reg == -1)
5743         {
5744           Lisp_Object original_default_coded_charset_priority_list
5745             = Vdefault_coded_charset_priority_list;
5746
5747           while (!EQ (Vdefault_coded_charset_priority_list, Qnil))
5748             {
5749               code_point = ENCODE_CHAR (ch, charset);
5750               if (XCHARSET_FINAL (charset))
5751                 goto found;
5752               Vdefault_coded_charset_priority_list
5753                 = Fcdr (Fmemq (XCHARSET_NAME (charset),
5754                                Vdefault_coded_charset_priority_list));
5755             }
5756           code_point = ENCODE_CHAR (ch, charset);
5757           if (!XCHARSET_FINAL (charset))
5758             {
5759               charset = Vcharset_ascii;
5760               code_point = '~';
5761             }
5762         found:
5763           Vdefault_coded_charset_priority_list
5764             = original_default_coded_charset_priority_list;
5765         }
5766       ensure_correct_direction (XCHARSET_DIRECTION (charset),
5767                                 codesys, dst, flags, 0);
5768       
5769       if (reg == -1)
5770         {
5771           if (XCHARSET_GRAPHIC (charset) != 0)
5772             {
5773               if (!NILP (str->iso2022.charset[1]) &&
5774                   (!CODING_SYSTEM_ISO2022_SEVEN (codesys)
5775                    || CODING_SYSTEM_ISO2022_LOCK_SHIFT (codesys)))
5776                 reg = 1;
5777               else if (!NILP (str->iso2022.charset[2]))
5778                 reg = 2;
5779               else if (!NILP (str->iso2022.charset[3]))
5780                 reg = 3;
5781               else
5782                 reg = 0;
5783             }
5784           else
5785             reg = 0;
5786         }
5787
5788       iso2022_designate (charset, reg, str, dst);
5789               
5790       /* Now invoke that register. */
5791       switch (reg)
5792         {
5793         case 0:
5794           ensure_normal_shift (str, dst);
5795           half = 0;
5796           break;
5797         case 1:
5798           if (CODING_SYSTEM_ISO2022_SEVEN (codesys))
5799             {
5800               ensure_shift_out (str, dst);
5801               half = 0;
5802             }
5803           else
5804             half = 1;
5805           break;
5806         case 2:
5807           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
5808             {
5809               Dynarr_add (dst, ISO_CODE_ESC);
5810               Dynarr_add (dst, 'N');
5811               half = 0;
5812             }
5813           else
5814             {
5815               Dynarr_add (dst, ISO_CODE_SS2);
5816               half = 1;
5817             }
5818           break;
5819         case 3:
5820           if (CODING_SYSTEM_ISO2022_SEVEN (str->codesys))
5821             {
5822               Dynarr_add (dst, ISO_CODE_ESC);
5823               Dynarr_add (dst, 'O');
5824               half = 0;
5825             }
5826           else
5827             {
5828               Dynarr_add (dst, ISO_CODE_SS3);
5829               half = 1;
5830             }
5831           break;
5832         default:
5833           abort ();
5834         }
5835       
5836       charmask = (half == 0 ? 0x00 : 0x80);
5837       
5838       switch (XCHARSET_DIMENSION (charset))
5839         {
5840         case 1:
5841           Dynarr_add (dst, (code_point & 0xFF) | charmask);
5842           break;
5843         case 2:
5844           Dynarr_add (dst, ((code_point >> 8) & 0xFF) | charmask);
5845           Dynarr_add (dst, ( code_point       & 0xFF) | charmask);
5846           break;
5847         case 3:
5848           Dynarr_add (dst, ((code_point >> 16) & 0xFF) | charmask);
5849           Dynarr_add (dst, ((code_point >>  8) & 0xFF) | charmask);
5850           Dynarr_add (dst, ( code_point        & 0xFF) | charmask);
5851           break;
5852         case 4:
5853           Dynarr_add (dst, ((code_point >> 24) & 0xFF) | charmask);
5854           Dynarr_add (dst, ((code_point >> 16) & 0xFF) | charmask);
5855           Dynarr_add (dst, ((code_point >>  8) & 0xFF) | charmask);
5856           Dynarr_add (dst, ( code_point        & 0xFF) | charmask);
5857           break;
5858         default:
5859           abort ();
5860         }
5861     }
5862   str->iso2022.current_charset = charset;
5863   str->iso2022.current_half = half;
5864 }
5865
5866 void
5867 char_finish_iso2022 (struct encoding_stream *str, unsigned_char_dynarr *dst,
5868                      unsigned int *flags)
5869 {
5870   Lisp_Coding_System* codesys = str->codesys;
5871   int i;
5872
5873   restore_left_to_right_direction (codesys, dst, flags, 0);
5874   ensure_normal_shift (str, dst);
5875   for (i = 0; i < 4; i++)
5876     {
5877       Lisp_Object initial_charset
5878         = CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
5879       iso2022_designate (initial_charset, i, str, dst);
5880     }
5881 }
5882 #endif /* MULE */
5883 \f
5884 /************************************************************************/
5885 /*                     No-conversion methods                            */
5886 /************************************************************************/
5887
5888 /* This is used when reading in "binary" files -- i.e. files that may
5889    contain all 256 possible byte values and that are not to be
5890    interpreted as being in any particular decoding. */
5891 static void
5892 decode_coding_no_conversion (Lstream *decoding, const Extbyte *src,
5893                              unsigned_char_dynarr *dst, size_t n)
5894 {
5895   struct decoding_stream *str = DECODING_STREAM_DATA (decoding);
5896   unsigned int flags  = str->flags;
5897   unsigned int cpos   = str->cpos;
5898   eol_type_t eol_type = str->eol_type;
5899
5900   while (n--)
5901     {
5902       unsigned char c = *(unsigned char *)src++;
5903
5904       DECODE_HANDLE_EOL_TYPE (eol_type, c, flags, dst);
5905       DECODE_ADD_BINARY_CHAR (c, dst);
5906     label_continue_loop:;
5907     }
5908
5909   DECODE_HANDLE_END_OF_CONVERSION (flags, cpos, dst);
5910
5911   str->flags = flags;
5912   str->cpos  = cpos;
5913 }
5914
5915 static void
5916 encode_coding_no_conversion (Lstream *encoding, const Bufbyte *src,
5917                              unsigned_char_dynarr *dst, size_t n)
5918 {
5919   unsigned char c;
5920   struct encoding_stream *str = ENCODING_STREAM_DATA (encoding);
5921   unsigned int flags  = str->flags;
5922   unsigned int ch     = str->ch;
5923   eol_type_t eol_type = CODING_SYSTEM_EOL_TYPE (str->codesys);
5924 #ifdef UTF2000
5925   unsigned char char_boundary = str->iso2022.current_char_boundary;
5926 #endif
5927
5928   while (n--)
5929     {
5930       c = *src++;         
5931 #ifdef UTF2000
5932       if (char_boundary == 0)
5933         if ( c >= 0xfc )
5934           {
5935             ch = c & 0x01;
5936             char_boundary = 5;
5937           }
5938         else if ( c >= 0xf8 )
5939           {
5940             ch = c & 0x03;
5941             char_boundary = 4;
5942           }
5943         else if ( c >= 0xf0 )
5944           {
5945             ch = c & 0x07;
5946             char_boundary = 3;
5947           }
5948         else if ( c >= 0xe0 )
5949           {
5950             ch = c & 0x0f;
5951             char_boundary = 2;
5952           }
5953         else if ( c >= 0xc0 )
5954           {
5955             ch = c & 0x1f;
5956             char_boundary = 1;
5957           }
5958         else
5959           {
5960             ch = 0;
5961             if (c == '\n')
5962               {
5963                 if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5964                   Dynarr_add (dst, '\r');
5965                 if (eol_type != EOL_CR)
5966                   Dynarr_add (dst, c);
5967               }
5968             else
5969               Dynarr_add (dst, c);
5970             char_boundary = 0;
5971           }
5972       else if (char_boundary == 1)
5973         {
5974           ch = ( ch << 6 ) | ( c & 0x3f );
5975           Dynarr_add (dst, ch & 0xff);
5976           char_boundary = 0;
5977         }
5978       else
5979         {
5980           ch = ( ch << 6 ) | ( c & 0x3f );
5981           char_boundary--;
5982         }
5983 #else /* not UTF2000 */
5984       if (c == '\n')
5985         {
5986           if (eol_type != EOL_LF && eol_type != EOL_AUTODETECT)
5987             Dynarr_add (dst, '\r');
5988           if (eol_type != EOL_CR)
5989             Dynarr_add (dst, '\n');
5990           ch = 0;
5991         }
5992       else if (BYTE_ASCII_P (c))
5993         {
5994           assert (ch == 0);
5995           Dynarr_add (dst, c);
5996         }
5997       else if (BUFBYTE_LEADING_BYTE_P (c))
5998         {
5999           assert (ch == 0);
6000           if (c == LEADING_BYTE_LATIN_ISO8859_1 ||
6001               c == LEADING_BYTE_CONTROL_1)
6002             ch = c;
6003           else
6004             Dynarr_add (dst, '~'); /* untranslatable character */
6005         }
6006       else
6007         {
6008           if (ch == LEADING_BYTE_LATIN_ISO8859_1)
6009             Dynarr_add (dst, c);
6010           else if (ch == LEADING_BYTE_CONTROL_1)
6011             {
6012               assert (c < 0xC0);
6013               Dynarr_add (dst, c - 0x20);
6014             }
6015           /* else it should be the second or third byte of an
6016              untranslatable character, so ignore it */
6017           ch = 0;
6018         }
6019 #endif /* not UTF2000 */
6020     }
6021
6022   str->flags = flags;
6023   str->ch    = ch;
6024 #ifdef UTF2000
6025   str->iso2022.current_char_boundary = char_boundary;
6026 #endif
6027 }
6028
6029 \f
6030
6031 /************************************************************************/
6032 /*                             Initialization                           */
6033 /************************************************************************/
6034
6035 void
6036 syms_of_file_coding (void)
6037 {
6038   INIT_LRECORD_IMPLEMENTATION (coding_system);
6039
6040   deferror (&Qcoding_system_error, "coding-system-error",
6041             "Coding-system error", Qio_error);
6042
6043   DEFSUBR (Fcoding_system_p);
6044   DEFSUBR (Ffind_coding_system);
6045   DEFSUBR (Fget_coding_system);
6046   DEFSUBR (Fcoding_system_list);
6047   DEFSUBR (Fcoding_system_name);
6048   DEFSUBR (Fmake_coding_system);
6049   DEFSUBR (Fcopy_coding_system);
6050   DEFSUBR (Fcoding_system_canonical_name_p);
6051   DEFSUBR (Fcoding_system_alias_p);
6052   DEFSUBR (Fcoding_system_aliasee);
6053   DEFSUBR (Fdefine_coding_system_alias);
6054   DEFSUBR (Fsubsidiary_coding_system);
6055
6056   DEFSUBR (Fcoding_system_type);
6057   DEFSUBR (Fcoding_system_doc_string);
6058 #ifdef MULE
6059   DEFSUBR (Fcoding_system_charset);
6060 #endif
6061   DEFSUBR (Fcoding_system_property);
6062
6063   DEFSUBR (Fcoding_category_list);
6064   DEFSUBR (Fset_coding_priority_list);
6065   DEFSUBR (Fcoding_priority_list);
6066   DEFSUBR (Fset_coding_category_system);
6067   DEFSUBR (Fcoding_category_system);
6068
6069   DEFSUBR (Fdetect_coding_region);
6070   DEFSUBR (Fdecode_coding_region);
6071   DEFSUBR (Fencode_coding_region);
6072 #ifdef MULE
6073   DEFSUBR (Fdecode_shift_jis_char);
6074   DEFSUBR (Fencode_shift_jis_char);
6075   DEFSUBR (Fdecode_big5_char);
6076   DEFSUBR (Fencode_big5_char);
6077 #endif /* MULE */
6078   defsymbol (&Qcoding_systemp, "coding-system-p");
6079   defsymbol (&Qno_conversion, "no-conversion");
6080   defsymbol (&Qraw_text, "raw-text");
6081 #ifdef MULE
6082   defsymbol (&Qbig5, "big5");
6083   defsymbol (&Qshift_jis, "shift-jis");
6084   defsymbol (&Qucs4, "ucs-4");
6085   defsymbol (&Qutf8, "utf-8");
6086   defsymbol (&Qccl, "ccl");
6087   defsymbol (&Qiso2022, "iso2022");
6088 #endif /* MULE */
6089   defsymbol (&Qmnemonic, "mnemonic");
6090   defsymbol (&Qeol_type, "eol-type");
6091   defsymbol (&Qpost_read_conversion, "post-read-conversion");
6092   defsymbol (&Qpre_write_conversion, "pre-write-conversion");
6093
6094   defsymbol (&Qcr, "cr");
6095   defsymbol (&Qlf, "lf");
6096   defsymbol (&Qcrlf, "crlf");
6097   defsymbol (&Qeol_cr, "eol-cr");
6098   defsymbol (&Qeol_lf, "eol-lf");
6099   defsymbol (&Qeol_crlf, "eol-crlf");
6100 #ifdef MULE
6101   defsymbol (&Qcharset_g0, "charset-g0");
6102   defsymbol (&Qcharset_g1, "charset-g1");
6103   defsymbol (&Qcharset_g2, "charset-g2");
6104   defsymbol (&Qcharset_g3, "charset-g3");
6105   defsymbol (&Qforce_g0_on_output, "force-g0-on-output");
6106   defsymbol (&Qforce_g1_on_output, "force-g1-on-output");
6107   defsymbol (&Qforce_g2_on_output, "force-g2-on-output");
6108   defsymbol (&Qforce_g3_on_output, "force-g3-on-output");
6109   defsymbol (&Qno_iso6429, "no-iso6429");
6110   defsymbol (&Qinput_charset_conversion, "input-charset-conversion");
6111   defsymbol (&Qoutput_charset_conversion, "output-charset-conversion");
6112
6113   defsymbol (&Qshort, "short");
6114   defsymbol (&Qno_ascii_eol, "no-ascii-eol");
6115   defsymbol (&Qno_ascii_cntl, "no-ascii-cntl");
6116   defsymbol (&Qseven, "seven");
6117   defsymbol (&Qlock_shift, "lock-shift");
6118   defsymbol (&Qescape_quoted, "escape-quoted");
6119 #endif /* MULE */
6120 #ifdef UTF2000
6121   defsymbol (&Qutf_8_mcs, "utf-8-mcs");
6122   defsymbol (&Qdisable_composition, "disable-composition");
6123   defsymbol (&Quse_entity_reference, "use-entity-reference");
6124   defsymbol (&Qd, "d");
6125   defsymbol (&Qx, "x");
6126   defsymbol (&QX, "X");
6127 #endif
6128   defsymbol (&Qencode, "encode");
6129   defsymbol (&Qdecode, "decode");
6130
6131 #ifdef MULE
6132   defsymbol (&coding_category_symbol[CODING_CATEGORY_SHIFT_JIS],
6133              "shift-jis");
6134   defsymbol (&coding_category_symbol[CODING_CATEGORY_BIG5],
6135              "big5");
6136   defsymbol (&coding_category_symbol[CODING_CATEGORY_UCS4],
6137              "ucs-4");
6138   defsymbol (&coding_category_symbol[CODING_CATEGORY_UTF8],
6139              "utf-8");
6140   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_7],
6141              "iso-7");
6142   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_DESIGNATE],
6143              "iso-8-designate");
6144   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_1],
6145              "iso-8-1");
6146   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_8_2],
6147              "iso-8-2");
6148   defsymbol (&coding_category_symbol[CODING_CATEGORY_ISO_LOCK_SHIFT],
6149              "iso-lock-shift");
6150 #endif /* MULE */
6151   defsymbol (&coding_category_symbol[CODING_CATEGORY_NO_CONVERSION],
6152              "no-conversion");
6153 }
6154
6155 void
6156 lstream_type_create_file_coding (void)
6157 {
6158   LSTREAM_HAS_METHOD (decoding, reader);
6159   LSTREAM_HAS_METHOD (decoding, writer);
6160   LSTREAM_HAS_METHOD (decoding, rewinder);
6161   LSTREAM_HAS_METHOD (decoding, seekable_p);
6162   LSTREAM_HAS_METHOD (decoding, flusher);
6163   LSTREAM_HAS_METHOD (decoding, closer);
6164   LSTREAM_HAS_METHOD (decoding, marker);
6165
6166   LSTREAM_HAS_METHOD (encoding, reader);
6167   LSTREAM_HAS_METHOD (encoding, writer);
6168   LSTREAM_HAS_METHOD (encoding, rewinder);
6169   LSTREAM_HAS_METHOD (encoding, seekable_p);
6170   LSTREAM_HAS_METHOD (encoding, flusher);
6171   LSTREAM_HAS_METHOD (encoding, closer);
6172   LSTREAM_HAS_METHOD (encoding, marker);
6173 }
6174
6175 void
6176 vars_of_file_coding (void)
6177 {
6178   int i;
6179
6180   fcd = xnew (struct file_coding_dump);
6181   dump_add_root_struct_ptr (&fcd, &fcd_description);
6182
6183   /* Initialize to something reasonable ... */
6184   for (i = 0; i < CODING_CATEGORY_LAST; i++)
6185     {
6186       fcd->coding_category_system[i] = Qnil;
6187       fcd->coding_category_by_priority[i] = i;
6188     }
6189
6190   Fprovide (intern ("file-coding"));
6191
6192   DEFVAR_LISP ("keyboard-coding-system", &Vkeyboard_coding_system /*
6193 Coding system used for TTY keyboard input.
6194 Not used under a windowing system.
6195 */ );
6196   Vkeyboard_coding_system = Qnil;
6197
6198   DEFVAR_LISP ("terminal-coding-system", &Vterminal_coding_system /*
6199 Coding system used for TTY display output.
6200 Not used under a windowing system.
6201 */ );
6202   Vterminal_coding_system = Qnil;
6203
6204   DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read /*
6205 Overriding coding system used when reading from a file or process.
6206 You should bind this variable with `let', but do not set it globally.
6207 If this is non-nil, it specifies the coding system that will be used
6208 to decode input on read operations, such as from a file or process.
6209 It overrides `buffer-file-coding-system-for-read',
6210 `insert-file-contents-pre-hook', etc.  Use those variables instead of
6211 this one for permanent changes to the environment.  */ );
6212   Vcoding_system_for_read = Qnil;
6213
6214   DEFVAR_LISP ("coding-system-for-write",
6215                &Vcoding_system_for_write /*
6216 Overriding coding system used when writing to a file or process.
6217 You should bind this variable with `let', but do not set it globally.
6218 If this is non-nil, it specifies the coding system that will be used
6219 to encode output for write operations, such as to a file or process.
6220 It overrides `buffer-file-coding-system', `write-region-pre-hook', etc.
6221 Use those variables instead of this one for permanent changes to the
6222 environment.  */ );
6223   Vcoding_system_for_write = Qnil;
6224
6225   DEFVAR_LISP ("file-name-coding-system", &Vfile_name_coding_system /*
6226 Coding system used to convert pathnames when accessing files.
6227 */ );
6228   Vfile_name_coding_system = Qnil;
6229
6230   DEFVAR_LISP ("coded-charset-entity-reference-alist",
6231                &Vcoded_charset_entity_reference_alist /*
6232 Alist of coded-charset vs corresponding entity-reference.
6233 Each element looks like (CCS PREFIX CODE-COLUMNS CODE-TYPE).
6234 CCS is coded-charset.
6235 CODE-COLUMNS is columns of code-point of entity-reference.
6236 CODE-TYPE is format type of code-point of entity-reference.
6237 `d' means decimal value and `x' means hexadecimal value.
6238 */ );
6239   Vcoded_charset_entity_reference_alist = Qnil;
6240
6241   DEFVAR_BOOL ("enable-multibyte-characters", &enable_multibyte_characters /*
6242 Non-nil means the buffer contents are regarded as multi-byte form
6243 of characters, not a binary code.  This affects the display, file I/O,
6244 and behaviors of various editing commands.
6245
6246 Setting this to nil does not do anything.
6247 */ );
6248   enable_multibyte_characters = 1;
6249 }
6250
6251 void
6252 complex_vars_of_file_coding (void)
6253 {
6254   staticpro (&Vcoding_system_hash_table);
6255   Vcoding_system_hash_table =
6256     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
6257
6258   the_codesys_prop_dynarr = Dynarr_new (codesys_prop);
6259   dump_add_root_struct_ptr (&the_codesys_prop_dynarr, &codesys_prop_dynarr_description);
6260
6261 #define DEFINE_CODESYS_PROP(Prop_Type, Sym) do  \
6262 {                                               \
6263   struct codesys_prop csp;                      \
6264   csp.sym = (Sym);                              \
6265   csp.prop_type = (Prop_Type);                  \
6266   Dynarr_add (the_codesys_prop_dynarr, csp);    \
6267 } while (0)
6268
6269   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qmnemonic);
6270   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_type);
6271   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_cr);
6272   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_crlf);
6273   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qeol_lf);
6274   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpost_read_conversion);
6275   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qpre_write_conversion);
6276 #ifdef MULE
6277   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g0);
6278   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g1);
6279   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g2);
6280   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qcharset_g3);
6281   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g0_on_output);
6282   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g1_on_output);
6283   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g2_on_output);
6284   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qforce_g3_on_output);
6285   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qshort);
6286   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_eol);
6287   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_ascii_cntl);
6288   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qseven);
6289   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qlock_shift);
6290   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qno_iso6429);
6291   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qescape_quoted);
6292   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qinput_charset_conversion);
6293   DEFINE_CODESYS_PROP (CODESYS_PROP_ISO2022, Qoutput_charset_conversion);
6294
6295   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qencode);
6296   DEFINE_CODESYS_PROP (CODESYS_PROP_CCL,     Qdecode);
6297 #ifdef UTF2000
6298   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Qdisable_composition);
6299   DEFINE_CODESYS_PROP (CODESYS_PROP_ALL_OK,  Quse_entity_reference);
6300 #endif
6301 #endif /* MULE */
6302   /* Need to create this here or we're really screwed. */
6303   Fmake_coding_system
6304     (Qraw_text, Qno_conversion,
6305      build_string ("Raw text, which means it converts only line-break-codes."),
6306      list2 (Qmnemonic, build_string ("Raw")));
6307
6308   Fmake_coding_system
6309     (Qbinary, Qno_conversion,
6310      build_string ("Binary, which means it does not convert anything."),
6311      list4 (Qeol_type, Qlf,
6312             Qmnemonic, build_string ("Binary")));
6313
6314 #ifdef UTF2000
6315   Fmake_coding_system
6316     (Qutf_8_mcs, Qutf8,
6317      build_string
6318      ("Coding-system of UTF-8 with Multiple Coded-character-Sets extension."),
6319      list2 (Qmnemonic, build_string ("MTF8")));
6320 #endif
6321
6322   Fdefine_coding_system_alias (Qno_conversion, Qraw_text);
6323
6324   Fdefine_coding_system_alias (Qfile_name, Qbinary);
6325
6326   Fdefine_coding_system_alias (Qterminal, Qbinary);
6327   Fdefine_coding_system_alias (Qkeyboard, Qbinary);
6328
6329   /* Need this for bootstrapping */
6330   fcd->coding_category_system[CODING_CATEGORY_NO_CONVERSION] =
6331     Fget_coding_system (Qraw_text);
6332
6333 #ifdef UTF2000
6334   fcd->coding_category_system[CODING_CATEGORY_UTF8]
6335    = Fget_coding_system (Qutf_8_mcs);
6336 #endif
6337
6338 #if defined(MULE) && !defined(UTF2000)
6339   {
6340     size_t i;
6341
6342     for (i = 0; i < countof (fcd->ucs_to_mule_table); i++)
6343       fcd->ucs_to_mule_table[i] = Qnil;
6344   }
6345   staticpro (&mule_to_ucs_table);
6346   mule_to_ucs_table = Fmake_char_table(Qgeneric);
6347 #endif /* defined(MULE) && !defined(UTF2000) */
6348 }