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