771
+ − 1 /* Conversion functions for I18N encodings, but not Unicode (in separate file).
+ − 2 Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ − 3 Copyright (C) 1995 Sun Microsystems, Inc.
+ − 4 Copyright (C) 2000, 2001, 2002 Ben Wing.
+ − 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 /* For previous history, see file-coding.c.
+ − 26
+ − 27 September 10, 2001: Extracted from file-coding.c by Ben Wing.
+ − 28
+ − 29 Later in September: Finished abstraction of detection system, rewrote
+ − 30 all the detectors to include multiple levels of likelihood.
+ − 31 */
+ − 32
+ − 33 #include <config.h>
+ − 34 #include "lisp.h"
+ − 35
+ − 36 #include "charset.h"
+ − 37 #include "mule-ccl.h"
+ − 38 #include "file-coding.h"
+ − 39
+ − 40 Lisp_Object Qshift_jis, Qiso2022, Qbig5, Qccl;
+ − 41
+ − 42 Lisp_Object Qcharset_g0, Qcharset_g1, Qcharset_g2, Qcharset_g3;
+ − 43 Lisp_Object Qforce_g0_on_output, Qforce_g1_on_output;
+ − 44 Lisp_Object Qforce_g2_on_output, Qforce_g3_on_output;
+ − 45 Lisp_Object Qno_iso6429;
+ − 46 Lisp_Object Qinput_charset_conversion, Qoutput_charset_conversion;
+ − 47 Lisp_Object Qshort, Qno_ascii_eol, Qno_ascii_cntl, Qseven, Qlock_shift;
+ − 48
+ − 49 Lisp_Object Qiso_7, Qiso_8_designate, Qiso_8_1, Qiso_8_2, Qiso_lock_shift;
+ − 50
+ − 51
+ − 52 /************************************************************************/
+ − 53 /* Shift-JIS methods */
+ − 54 /************************************************************************/
+ − 55
+ − 56 /* Shift-JIS; Hankaku (half-width) KANA is also supported. */
+ − 57 DEFINE_CODING_SYSTEM_TYPE (shift_jis);
+ − 58
+ − 59 /* Shift-JIS is a coding system encoding three character sets: ASCII, right
+ − 60 half of JISX0201-Kana, and JISX0208. An ASCII character is encoded
+ − 61 as is. A character of JISX0201-Kana (DIMENSION1_CHARS94 character set) is
+ − 62 encoded by "position-code + 0x80". A character of JISX0208
+ − 63 (DIMENSION2_CHARS94 character set) is encoded in 2-byte but two
+ − 64 position-codes are divided and shifted so that it fit in the range
+ − 65 below.
+ − 66
+ − 67 --- CODE RANGE of Shift-JIS ---
+ − 68 (character set) (range)
+ − 69 ASCII 0x00 .. 0x7F
+ − 70 JISX0201-Kana 0xA0 .. 0xDF
+ − 71 JISX0208 (1st byte) 0x80 .. 0x9F and 0xE0 .. 0xEF
+ − 72 (2nd byte) 0x40 .. 0x7E and 0x80 .. 0xFC
+ − 73 -------------------------------
+ − 74
+ − 75 */
+ − 76
+ − 77 /* Is this the first byte of a Shift-JIS two-byte char? */
+ − 78
826
+ − 79 inline static int
+ − 80 byte_shift_jis_two_byte_1_p (int c)
+ − 81 {
+ − 82 return (c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xEF);
+ − 83 }
771
+ − 84
+ − 85 /* Is this the second byte of a Shift-JIS two-byte char? */
+ − 86
826
+ − 87 inline static int
+ − 88 byte_shift_jis_two_byte_2_p (int c)
+ − 89 {
+ − 90 return (c >= 0x40 && c <= 0x7E) || (c >= 0x80 && c <= 0xFC);
+ − 91 }
+ − 92
+ − 93 inline static int
+ − 94 byte_shift_jis_katakana_p (int c)
+ − 95 {
+ − 96 return c >= 0xA1 && c <= 0xDF;
+ − 97 }
771
+ − 98
+ − 99 /* Convert Shift-JIS data to internal format. */
+ − 100
+ − 101 static Bytecount
+ − 102 shift_jis_convert (struct coding_stream *str, const UExtbyte *src,
+ − 103 unsigned_char_dynarr *dst, Bytecount n)
+ − 104 {
+ − 105 unsigned int ch = str->ch;
+ − 106 Bytecount orign = n;
+ − 107
+ − 108 if (str->direction == CODING_DECODE)
+ − 109 {
+ − 110 while (n--)
+ − 111 {
+ − 112 UExtbyte c = *src++;
+ − 113
+ − 114 if (ch)
+ − 115 {
+ − 116 /* Previous character was first byte of Shift-JIS Kanji char. */
826
+ − 117 if (byte_shift_jis_two_byte_2_p (c))
771
+ − 118 {
867
+ − 119 Ibyte e1, e2;
771
+ − 120
+ − 121 Dynarr_add (dst, LEADING_BYTE_JAPANESE_JISX0208);
+ − 122 DECODE_SHIFT_JIS (ch, c, e1, e2);
+ − 123 Dynarr_add (dst, e1);
+ − 124 Dynarr_add (dst, e2);
+ − 125 }
+ − 126 else
+ − 127 {
+ − 128 DECODE_ADD_BINARY_CHAR (ch, dst);
+ − 129 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 130 }
+ − 131 ch = 0;
+ − 132 }
+ − 133 else
+ − 134 {
826
+ − 135 if (byte_shift_jis_two_byte_1_p (c))
771
+ − 136 ch = c;
826
+ − 137 else if (byte_shift_jis_katakana_p (c))
771
+ − 138 {
+ − 139 Dynarr_add (dst, LEADING_BYTE_KATAKANA_JISX0201);
+ − 140 Dynarr_add (dst, c);
+ − 141 }
+ − 142 else
+ − 143 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 144 }
+ − 145 }
+ − 146
+ − 147 if (str->eof)
+ − 148 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 149 }
+ − 150 else
+ − 151 {
+ − 152 while (n--)
+ − 153 {
867
+ − 154 Ibyte c = *src++;
826
+ − 155 if (byte_ascii_p (c))
771
+ − 156 {
+ − 157 Dynarr_add (dst, c);
+ − 158 ch = 0;
+ − 159 }
867
+ − 160 else if (ibyte_leading_byte_p (c))
771
+ − 161 ch = (c == LEADING_BYTE_KATAKANA_JISX0201 ||
+ − 162 c == LEADING_BYTE_JAPANESE_JISX0208_1978 ||
+ − 163 c == LEADING_BYTE_JAPANESE_JISX0208) ? c : 0;
+ − 164 else if (ch)
+ − 165 {
+ − 166 if (ch == LEADING_BYTE_KATAKANA_JISX0201)
+ − 167 {
+ − 168 Dynarr_add (dst, c);
+ − 169 ch = 0;
+ − 170 }
+ − 171 else if (ch == LEADING_BYTE_JAPANESE_JISX0208_1978 ||
+ − 172 ch == LEADING_BYTE_JAPANESE_JISX0208)
+ − 173 ch = c;
+ − 174 else
+ − 175 {
+ − 176 UExtbyte j1, j2;
+ − 177 ENCODE_SHIFT_JIS (ch, c, j1, j2);
+ − 178 Dynarr_add (dst, j1);
+ − 179 Dynarr_add (dst, j2);
+ − 180 ch = 0;
+ − 181 }
+ − 182 }
+ − 183 }
+ − 184 }
+ − 185
+ − 186 str->ch = ch;
+ − 187
+ − 188 return orign;
+ − 189 }
+ − 190
+ − 191 DEFUN ("decode-shift-jis-char", Fdecode_shift_jis_char, 1, 1, 0, /*
+ − 192 Decode a JISX0208 character of Shift-JIS coding-system.
+ − 193 CODE is the character code in Shift-JIS as a cons of type bytes.
+ − 194 Return the corresponding character.
+ − 195 */
+ − 196 (code))
+ − 197 {
+ − 198 int c1, c2, s1, s2;
+ − 199
+ − 200 CHECK_CONS (code);
+ − 201 CHECK_INT (XCAR (code));
+ − 202 CHECK_INT (XCDR (code));
+ − 203 s1 = XINT (XCAR (code));
+ − 204 s2 = XINT (XCDR (code));
826
+ − 205 if (byte_shift_jis_two_byte_1_p (s1) &&
+ − 206 byte_shift_jis_two_byte_2_p (s2))
771
+ − 207 {
+ − 208 DECODE_SHIFT_JIS (s1, s2, c1, c2);
867
+ − 209 return make_char (make_ichar (Vcharset_japanese_jisx0208,
831
+ − 210 c1 & 0x7F, c2 & 0x7F));
771
+ − 211 }
+ − 212 else
+ − 213 return Qnil;
+ − 214 }
+ − 215
+ − 216 DEFUN ("encode-shift-jis-char", Fencode_shift_jis_char, 1, 1, 0, /*
+ − 217 Encode a JISX0208 character CHARACTER to SHIFT-JIS coding-system.
+ − 218 Return the corresponding character code in SHIFT-JIS as a cons of two bytes.
+ − 219 */
+ − 220 (character))
+ − 221 {
+ − 222 Lisp_Object charset;
+ − 223 int c1, c2, s1, s2;
+ − 224
+ − 225 CHECK_CHAR_COERCE_INT (character);
867
+ − 226 BREAKUP_ICHAR (XCHAR (character), charset, c1, c2);
771
+ − 227 if (EQ (charset, Vcharset_japanese_jisx0208))
+ − 228 {
+ − 229 ENCODE_SHIFT_JIS (c1 | 0x80, c2 | 0x80, s1, s2);
+ − 230 return Fcons (make_int (s1), make_int (s2));
+ − 231 }
+ − 232 else
+ − 233 return Qnil;
+ − 234 }
+ − 235
+ − 236
+ − 237 /************************************************************************/
+ − 238 /* Shift-JIS detector */
+ − 239 /************************************************************************/
+ − 240
+ − 241 DEFINE_DETECTOR (shift_jis);
+ − 242 DEFINE_DETECTOR_CATEGORY (shift_jis, shift_jis);
+ − 243
+ − 244 struct shift_jis_detector
+ − 245 {
+ − 246 int seen_jisx0208_char_in_c1;
+ − 247 int seen_jisx0208_char_in_upper;
+ − 248 int seen_jisx0201_char;
+ − 249 unsigned int seen_iso2022_esc:1;
+ − 250 unsigned int seen_bad_first_byte:1;
+ − 251 unsigned int seen_bad_second_byte:1;
+ − 252 /* temporary */
+ − 253 unsigned int in_second_byte:1;
+ − 254 unsigned int first_byte_was_c1:1;
+ − 255 };
+ − 256
+ − 257 static void
+ − 258 shift_jis_detect (struct detection_state *st, const UExtbyte *src,
+ − 259 Bytecount n)
+ − 260 {
+ − 261 struct shift_jis_detector *data = DETECTION_STATE_DATA (st, shift_jis);
+ − 262
+ − 263 while (n--)
+ − 264 {
+ − 265 UExtbyte c = *src++;
+ − 266 if (!data->in_second_byte)
+ − 267 {
+ − 268 if (c >= 0x80 && c <= 0x9F)
+ − 269 data->first_byte_was_c1 = 1;
+ − 270 if (c >= 0xA0 && c <= 0xDF)
+ − 271 data->seen_jisx0201_char++;
+ − 272 else if ((c >= 0x80 && c <= 0x9F) || (c >= 0xE0 && c <= 0xEF))
+ − 273 data->in_second_byte = 1;
+ − 274 else if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
+ − 275 data->seen_iso2022_esc = 1;
+ − 276 else if (c >= 0x80)
+ − 277 data->seen_bad_first_byte = 1;
+ − 278 }
+ − 279 else
+ − 280 {
+ − 281 if ((c >= 0x40 && c <= 0x7E) || (c >= 0x80 && c <= 0xFC))
+ − 282 {
+ − 283 if (data->first_byte_was_c1 || (c >= 0x80 && c <= 0x9F))
+ − 284 data->seen_jisx0208_char_in_c1++;
+ − 285 else
+ − 286 data->seen_jisx0208_char_in_upper++;
+ − 287 }
+ − 288 else
+ − 289 data->seen_bad_second_byte = 1;
+ − 290 data->in_second_byte = 0;
+ − 291 data->first_byte_was_c1 = 0;
+ − 292 }
+ − 293 }
+ − 294
+ − 295 if (data->seen_bad_second_byte)
+ − 296 DET_RESULT (st, shift_jis) = DET_NEARLY_IMPOSSIBLE;
+ − 297 else if (data->seen_bad_first_byte)
+ − 298 DET_RESULT (st, shift_jis) = DET_QUITE_IMPROBABLE;
+ − 299 else if (data->seen_iso2022_esc)
+ − 300 DET_RESULT (st, shift_jis) = DET_SOMEWHAT_UNLIKELY;
+ − 301 else if (data->seen_jisx0208_char_in_c1 >= 20 ||
+ − 302 (data->seen_jisx0208_char_in_c1 >= 10 &&
+ − 303 data->seen_jisx0208_char_in_upper >= 10))
+ − 304 DET_RESULT (st, shift_jis) = DET_QUITE_PROBABLE;
+ − 305 else if (data->seen_jisx0208_char_in_c1 > 3 ||
+ − 306 data->seen_jisx0208_char_in_upper >= 10 ||
+ − 307 /* Since the range is limited compared to what is often seen
+ − 308 is typical Latin-X charsets, the fact that we've seen a
+ − 309 bunch of them and none that are invalid is reasonably
+ − 310 strong statistical evidence of this encoding, or at least
+ − 311 not of the common Latin-X ones. */
+ − 312 data->seen_jisx0201_char >= 100)
+ − 313 DET_RESULT (st, shift_jis) = DET_SOMEWHAT_LIKELY;
+ − 314 else if (data->seen_jisx0208_char_in_c1 > 0 ||
+ − 315 data->seen_jisx0208_char_in_upper > 0 ||
+ − 316 data->seen_jisx0201_char > 0)
+ − 317 DET_RESULT (st, shift_jis) = DET_SLIGHTLY_LIKELY;
+ − 318 else
+ − 319 DET_RESULT (st, shift_jis) = DET_AS_LIKELY_AS_UNLIKELY;
+ − 320 }
+ − 321
+ − 322
+ − 323 /************************************************************************/
+ − 324 /* Big5 methods */
+ − 325 /************************************************************************/
+ − 326
+ − 327 /* BIG5 (used for Taiwanese). */
+ − 328 DEFINE_CODING_SYSTEM_TYPE (big5);
+ − 329
+ − 330 /* BIG5 is a coding system encoding two character sets: ASCII and
+ − 331 Big5. An ASCII character is encoded as is. Big5 is a two-byte
+ − 332 character set and is encoded in two-byte.
+ − 333
+ − 334 --- CODE RANGE of BIG5 ---
+ − 335 (character set) (range)
+ − 336 ASCII 0x00 .. 0x7F
+ − 337 Big5 (1st byte) 0xA1 .. 0xFE
+ − 338 (2nd byte) 0x40 .. 0x7E and 0xA1 .. 0xFE
+ − 339 --------------------------
+ − 340
+ − 341 Since the number of characters in Big5 is larger than maximum
+ − 342 characters in Emacs' charset (96x96), it can't be handled as one
+ − 343 charset. So, in XEmacs, Big5 is divided into two: `charset-big5-1'
+ − 344 and `charset-big5-2'. Both <type>s are DIMENSION2_CHARS94. The former
+ − 345 contains frequently used characters and the latter contains less
+ − 346 frequently used characters. */
+ − 347
826
+ − 348 inline static int
+ − 349 byte_big5_two_byte_1_p (int c)
+ − 350 {
+ − 351 return c >= 0xA1 && c <= 0xFE;
+ − 352 }
771
+ − 353
+ − 354 /* Is this the second byte of a Shift-JIS two-byte char? */
+ − 355
826
+ − 356 inline static int
+ − 357 byte_big5_two_byte_2_p (int c)
+ − 358 {
+ − 359 return (c >= 0x40 && c <= 0x7E) || (c >= 0xA1 && c <= 0xFE);
+ − 360 }
771
+ − 361
+ − 362 /* Number of Big5 characters which have the same code in 1st byte. */
+ − 363
+ − 364 #define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40)
+ − 365
+ − 366 /* Code conversion macros. These are macros because they are used in
+ − 367 inner loops during code conversion.
+ − 368
+ − 369 Note that temporary variables in macros introduce the classic
+ − 370 dynamic-scoping problems with variable names. We use capital-
+ − 371 lettered variables in the assumption that XEmacs does not use
+ − 372 capital letters in variables except in a very formalized way
+ − 373 (e.g. Qstring). */
+ − 374
+ − 375 /* Convert Big5 code (b1, b2) into its internal string representation
+ − 376 (lb, c1, c2). */
+ − 377
+ − 378 /* There is a much simpler way to split the Big5 charset into two.
+ − 379 For the moment I'm going to leave the algorithm as-is because it
+ − 380 claims to separate out the most-used characters into a single
+ − 381 charset, which perhaps will lead to optimizations in various
+ − 382 places.
+ − 383
+ − 384 The way the algorithm works is something like this:
+ − 385
+ − 386 Big5 can be viewed as a 94x157 charset, where the row is
+ − 387 encoded into the bytes 0xA1 .. 0xFE and the column is encoded
+ − 388 into the bytes 0x40 .. 0x7E and 0xA1 .. 0xFE. As for frequency,
+ − 389 the split between low and high column numbers is apparently
+ − 390 meaningless; ascending rows produce less and less frequent chars.
+ − 391 Therefore, we assign the lower half of rows (0xA1 .. 0xC8) to
+ − 392 the first charset, and the upper half (0xC9 .. 0xFE) to the
+ − 393 second. To do the conversion, we convert the character into
+ − 394 a single number where 0 .. 156 is the first row, 157 .. 313
+ − 395 is the second, etc. That way, the characters are ordered by
+ − 396 decreasing frequency. Then we just chop the space in two
+ − 397 and coerce the result into a 94x94 space.
+ − 398 */
+ − 399
+ − 400 #define DECODE_BIG5(b1, b2, lb, c1, c2) do \
+ − 401 { \
+ − 402 int B1 = b1, B2 = b2; \
+ − 403 int I \
+ − 404 = (B1 - 0xA1) * BIG5_SAME_ROW + B2 - (B2 < 0x7F ? 0x40 : 0x62); \
+ − 405 \
+ − 406 if (B1 < 0xC9) \
+ − 407 { \
+ − 408 lb = LEADING_BYTE_CHINESE_BIG5_1; \
+ − 409 } \
+ − 410 else \
+ − 411 { \
+ − 412 lb = LEADING_BYTE_CHINESE_BIG5_2; \
+ − 413 I -= (BIG5_SAME_ROW) * (0xC9 - 0xA1); \
+ − 414 } \
+ − 415 c1 = I / (0xFF - 0xA1) + 0xA1; \
+ − 416 c2 = I % (0xFF - 0xA1) + 0xA1; \
+ − 417 } while (0)
+ − 418
+ − 419 /* Convert the internal string representation of a Big5 character
+ − 420 (lb, c1, c2) into Big5 code (b1, b2). */
+ − 421
+ − 422 #define ENCODE_BIG5(lb, c1, c2, b1, b2) do \
+ − 423 { \
+ − 424 int I = ((c1) - 0xA1) * (0xFF - 0xA1) + ((c2) - 0xA1); \
+ − 425 \
+ − 426 if (lb == LEADING_BYTE_CHINESE_BIG5_2) \
+ − 427 { \
+ − 428 I += BIG5_SAME_ROW * (0xC9 - 0xA1); \
+ − 429 } \
+ − 430 b1 = I / BIG5_SAME_ROW + 0xA1; \
+ − 431 b2 = I % BIG5_SAME_ROW; \
+ − 432 b2 += b2 < 0x3F ? 0x40 : 0x62; \
+ − 433 } while (0)
+ − 434
+ − 435 /* Convert Big5 data to internal format. */
+ − 436
+ − 437 static Bytecount
+ − 438 big5_convert (struct coding_stream *str, const UExtbyte *src,
+ − 439 unsigned_char_dynarr *dst, Bytecount n)
+ − 440 {
+ − 441 unsigned int ch = str->ch;
+ − 442 Bytecount orign = n;
+ − 443
+ − 444 if (str->direction == CODING_DECODE)
+ − 445 {
+ − 446 while (n--)
+ − 447 {
+ − 448 UExtbyte c = *src++;
+ − 449 if (ch)
+ − 450 {
+ − 451 /* Previous character was first byte of Big5 char. */
826
+ − 452 if (byte_big5_two_byte_2_p (c))
771
+ − 453 {
867
+ − 454 Ibyte b1, b2, b3;
771
+ − 455 DECODE_BIG5 (ch, c, b1, b2, b3);
+ − 456 Dynarr_add (dst, b1);
+ − 457 Dynarr_add (dst, b2);
+ − 458 Dynarr_add (dst, b3);
+ − 459 }
+ − 460 else
+ − 461 {
+ − 462 DECODE_ADD_BINARY_CHAR (ch, dst);
+ − 463 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 464 }
+ − 465 ch = 0;
+ − 466 }
+ − 467 else
+ − 468 {
826
+ − 469 if (byte_big5_two_byte_1_p (c))
771
+ − 470 ch = c;
+ − 471 else
+ − 472 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 473 }
+ − 474 }
+ − 475
+ − 476 if (str->eof)
+ − 477 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 478 }
+ − 479 else
+ − 480 {
+ − 481 while (n--)
+ − 482 {
867
+ − 483 Ibyte c = *src++;
826
+ − 484 if (byte_ascii_p (c))
771
+ − 485 {
+ − 486 /* ASCII. */
+ − 487 Dynarr_add (dst, c);
+ − 488 }
867
+ − 489 else if (ibyte_leading_byte_p (c))
771
+ − 490 {
+ − 491 if (c == LEADING_BYTE_CHINESE_BIG5_1 ||
+ − 492 c == LEADING_BYTE_CHINESE_BIG5_2)
+ − 493 {
+ − 494 /* A recognized leading byte. */
+ − 495 ch = c;
+ − 496 continue; /* not done with this character. */
+ − 497 }
+ − 498 /* otherwise just ignore this character. */
+ − 499 }
+ − 500 else if (ch == LEADING_BYTE_CHINESE_BIG5_1 ||
+ − 501 ch == LEADING_BYTE_CHINESE_BIG5_2)
+ − 502 {
+ − 503 /* Previous char was a recognized leading byte. */
+ − 504 ch = (ch << 8) | c;
+ − 505 continue; /* not done with this character. */
+ − 506 }
+ − 507 else if (ch)
+ − 508 {
+ − 509 /* Encountering second byte of a Big5 character. */
+ − 510 UExtbyte b1, b2;
+ − 511
+ − 512 ENCODE_BIG5 (ch >> 8, ch & 0xFF, c, b1, b2);
+ − 513 Dynarr_add (dst, b1);
+ − 514 Dynarr_add (dst, b2);
+ − 515 }
+ − 516
+ − 517 ch = 0;
+ − 518 }
+ − 519 }
+ − 520
+ − 521 str->ch = ch;
+ − 522 return orign;
+ − 523 }
+ − 524
867
+ − 525 Ichar
771
+ − 526 decode_big5_char (int b1, int b2)
+ − 527 {
826
+ − 528 if (byte_big5_two_byte_1_p (b1) &&
+ − 529 byte_big5_two_byte_2_p (b2))
771
+ − 530 {
+ − 531 int leading_byte;
+ − 532 Lisp_Object charset;
+ − 533 int c1, c2;
+ − 534
+ − 535 DECODE_BIG5 (b1, b2, leading_byte, c1, c2);
826
+ − 536 charset = charset_by_leading_byte (leading_byte);
867
+ − 537 return make_ichar (charset, c1 & 0x7F, c2 & 0x7F);
771
+ − 538 }
+ − 539 else
+ − 540 return -1;
+ − 541 }
+ − 542
+ − 543 DEFUN ("decode-big5-char", Fdecode_big5_char, 1, 1, 0, /*
+ − 544 Convert Big Five character codes in CODE into a character.
+ − 545 CODE is a cons of two integers specifying the codepoints in Big Five.
+ − 546 Return the corresponding character, or nil if the codepoints are out of range.
+ − 547
+ − 548 The term `decode' is used because the codepoints can be viewed as the
+ − 549 representation of the character in the external Big Five encoding, and thus
+ − 550 converting them to a character is analogous to any other operation that
+ − 551 decodes an external representation.
+ − 552 */
+ − 553 (code))
+ − 554 {
867
+ − 555 Ichar ch;
771
+ − 556
+ − 557 CHECK_CONS (code);
+ − 558 CHECK_INT (XCAR (code));
+ − 559 CHECK_INT (XCDR (code));
+ − 560 ch = decode_big5_char (XINT (XCAR (code)), XINT (XCDR (code)));
+ − 561 if (ch == -1)
+ − 562 return Qnil;
+ − 563 else
+ − 564 return make_char (ch);
+ − 565 }
+ − 566
+ − 567 DEFUN ("encode-big5-char", Fencode_big5_char, 1, 1, 0, /*
+ − 568 Convert the specified Big Five character into its codepoints.
+ − 569 The codepoints are returned as a cons of two integers, specifying the
+ − 570 Big Five codepoints. See `decode-big5-char' for the reason why the
+ − 571 term `encode' is used for this operation.
+ − 572 */
+ − 573 (character))
+ − 574 {
+ − 575 Lisp_Object charset;
+ − 576 int c1, c2, b1, b2;
+ − 577
+ − 578 CHECK_CHAR_COERCE_INT (character);
867
+ − 579 BREAKUP_ICHAR (XCHAR (character), charset, c1, c2);
771
+ − 580 if (EQ (charset, Vcharset_chinese_big5_1) ||
+ − 581 EQ (charset, Vcharset_chinese_big5_2))
+ − 582 {
+ − 583 ENCODE_BIG5 (XCHARSET_LEADING_BYTE (charset), c1 | 0x80, c2 | 0x80,
+ − 584 b1, b2);
+ − 585 return Fcons (make_int (b1), make_int (b2));
+ − 586 }
+ − 587 else
+ − 588 return Qnil;
+ − 589 }
+ − 590
+ − 591
+ − 592 /************************************************************************/
+ − 593 /* Big5 detector */
+ − 594 /************************************************************************/
+ − 595
+ − 596 DEFINE_DETECTOR (big5);
+ − 597 DEFINE_DETECTOR_CATEGORY (big5, big5);
+ − 598
+ − 599 struct big5_detector
+ − 600 {
+ − 601 int seen_big5_char;
985
+ − 602 int seen_euc_char;
771
+ − 603 unsigned int seen_iso2022_esc:1;
+ − 604 unsigned int seen_bad_first_byte:1;
+ − 605 unsigned int seen_bad_second_byte:1;
+ − 606
+ − 607 /* temporary */
+ − 608 unsigned int in_second_byte:1;
+ − 609 };
+ − 610
+ − 611 static void
+ − 612 big5_detect (struct detection_state *st, const UExtbyte *src,
+ − 613 Bytecount n)
+ − 614 {
+ − 615 struct big5_detector *data = DETECTION_STATE_DATA (st, big5);
+ − 616
+ − 617 while (n--)
+ − 618 {
+ − 619 UExtbyte c = *src++;
+ − 620 if (!data->in_second_byte)
+ − 621 {
+ − 622 if (c >= 0xA1 && c <= 0xFE)
+ − 623 data->in_second_byte = 1;
+ − 624 else if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)
+ − 625 data->seen_iso2022_esc = 1;
+ − 626 else if (c >= 0x80)
+ − 627 data->seen_bad_first_byte = 1;
+ − 628 }
+ − 629 else
+ − 630 {
+ − 631 data->in_second_byte = 0;
985
+ − 632 if (c >= 0xA1 && c <= 0xFE)
+ − 633 data->seen_euc_char++;
+ − 634 else if (c >= 0x40 && c <= 0x7E)
771
+ − 635 data->seen_big5_char++;
+ − 636 else
+ − 637 data->seen_bad_second_byte = 1;
+ − 638 }
+ − 639 }
+ − 640
+ − 641 if (data->seen_bad_second_byte)
+ − 642 DET_RESULT (st, big5) = DET_NEARLY_IMPOSSIBLE;
+ − 643 else if (data->seen_bad_first_byte)
+ − 644 DET_RESULT (st, big5) = DET_QUITE_IMPROBABLE;
+ − 645 else if (data->seen_iso2022_esc)
+ − 646 DET_RESULT (st, big5) = DET_SOMEWHAT_UNLIKELY;
+ − 647 else if (data->seen_big5_char >= 4)
+ − 648 DET_RESULT (st, big5) = DET_SOMEWHAT_LIKELY;
985
+ − 649 else if (data->seen_euc_char)
+ − 650 DET_RESULT (st, big5) = DET_SLIGHTLY_LIKELY;
771
+ − 651 else
+ − 652 DET_RESULT (st, big5) = DET_AS_LIKELY_AS_UNLIKELY;
+ − 653 }
+ − 654
+ − 655
+ − 656 /************************************************************************/
+ − 657 /* ISO2022 methods */
+ − 658 /************************************************************************/
+ − 659
+ − 660 /* Any ISO-2022-compliant coding system. Includes JIS, EUC, CTEXT
+ − 661 (Compound Text, the encoding of selections in X Windows). See below for
+ − 662 a complete description of ISO-2022. */
+ − 663
+ − 664 /* Flags indicating what we've seen so far when parsing an
+ − 665 ISO2022 escape sequence. */
+ − 666 enum iso_esc_flag
+ − 667 {
+ − 668 /* Partial sequences */
+ − 669 ISO_ESC_NOTHING, /* Nothing has been seen. */
+ − 670 ISO_ESC, /* We've seen ESC. */
+ − 671 ISO_ESC_2_4, /* We've seen ESC $. This indicates
+ − 672 that we're designating a multi-byte, rather
+ − 673 than a single-byte, character set. */
+ − 674 ISO_ESC_2_8, /* We've seen ESC 0x28, i.e. ESC (.
+ − 675 This means designate a 94-character
+ − 676 character set into G0. */
+ − 677 ISO_ESC_2_9, /* We've seen ESC 0x29 -- designate a
+ − 678 94-character character set into G1. */
+ − 679 ISO_ESC_2_10, /* We've seen ESC 0x2A. */
+ − 680 ISO_ESC_2_11, /* We've seen ESC 0x2B. */
+ − 681 ISO_ESC_2_12, /* We've seen ESC 0x2C -- designate a
+ − 682 96-character character set into G0.
+ − 683 (This is not ISO2022-standard.
+ − 684 The following 96-character
+ − 685 control sequences are standard,
+ − 686 though.) */
+ − 687 ISO_ESC_2_13, /* We've seen ESC 0x2D -- designate a
+ − 688 96-character character set into G1.
+ − 689 */
+ − 690 ISO_ESC_2_14, /* We've seen ESC 0x2E. */
+ − 691 ISO_ESC_2_15, /* We've seen ESC 0x2F. */
+ − 692 ISO_ESC_2_4_8, /* We've seen ESC $ 0x28 -- designate
+ − 693 a 94^N character set into G0. */
+ − 694 ISO_ESC_2_4_9, /* We've seen ESC $ 0x29. */
+ − 695 ISO_ESC_2_4_10, /* We've seen ESC $ 0x2A. */
+ − 696 ISO_ESC_2_4_11, /* We've seen ESC $ 0x2B. */
+ − 697 ISO_ESC_2_4_12, /* We've seen ESC $ 0x2C. */
+ − 698 ISO_ESC_2_4_13, /* We've seen ESC $ 0x2D. */
+ − 699 ISO_ESC_2_4_14, /* We've seen ESC $ 0x2E. */
+ − 700 ISO_ESC_2_4_15, /* We've seen ESC $ 0x2F. */
+ − 701 ISO_ESC_5_11, /* We've seen ESC [ or 0x9B. This
+ − 702 starts a directionality-control
+ − 703 sequence. The next character
+ − 704 must be 0, 1, 2, or ]. */
+ − 705 ISO_ESC_5_11_0, /* We've seen 0x9B 0. The next character must be ]. */
+ − 706 ISO_ESC_5_11_1, /* We've seen 0x9B 1. The next character must be ]. */
+ − 707 ISO_ESC_5_11_2, /* We've seen 0x9B 2. The next character must be ]. */
+ − 708
+ − 709 /* Full sequences. */
+ − 710 ISO_ESC_START_COMPOSITE, /* Private usage for START COMPOSING */
+ − 711 ISO_ESC_END_COMPOSITE, /* Private usage for END COMPOSING */
+ − 712 ISO_ESC_SINGLE_SHIFT, /* We've seen a complete single-shift sequence. */
+ − 713 ISO_ESC_LOCKING_SHIFT,/* We've seen a complete locking-shift sequence. */
+ − 714 ISO_ESC_DESIGNATE, /* We've seen a complete designation sequence. */
+ − 715 ISO_ESC_DIRECTIONALITY,/* We've seen a complete ISO6429 directionality
+ − 716 sequence. */
+ − 717 ISO_ESC_LITERAL /* We've seen a literal character ala
+ − 718 escape-quoting. */
+ − 719 };
+ − 720
+ − 721 enum iso_error
+ − 722 {
+ − 723 ISO_ERROR_BAD_FINAL,
+ − 724 ISO_ERROR_UNKWOWN_ESC_SEQUENCE,
+ − 725 ISO_ERROR_INVALID_CODE_POINT_CHARACTER,
+ − 726 };
+ − 727
+ − 728
+ − 729 /* Flags indicating current state while converting code. */
+ − 730
+ − 731 /************ Used during encoding and decoding: ************/
+ − 732 /* If set, the current directionality is right-to-left. Otherwise, it's
+ − 733 left-to-right. */
+ − 734 #define ISO_STATE_R2L (1 << 0)
+ − 735
+ − 736 /************ Used during encoding: ************/
+ − 737 /* If set, we just saw a CR. */
+ − 738 #define ISO_STATE_CR (1 << 1)
+ − 739
+ − 740 /************ Used during decoding: ************/
+ − 741 /* If set, we're currently parsing an escape sequence and the upper 16 bits
+ − 742 should be looked at to indicate what partial escape sequence we've seen
+ − 743 so far. Otherwise, we're running through actual text. */
+ − 744 #define ISO_STATE_ESCAPE (1 << 2)
+ − 745 /* If set, G2 is invoked into GL, but only for the next character. */
+ − 746 #define ISO_STATE_SS2 (1 << 3)
+ − 747 /* If set, G3 is invoked into GL, but only for the next character. If both
+ − 748 ISO_STATE_SS2 and ISO_STATE_SS3 are set, ISO_STATE_SS2 overrides; but
+ − 749 this probably indicates an error in the text encoding. */
+ − 750 #define ISO_STATE_SS3 (1 << 4)
+ − 751 /* If set, we're currently processing a composite character (i.e. a
+ − 752 character constructed by overstriking two or more characters). */
+ − 753 #define ISO_STATE_COMPOSITE (1 << 5)
+ − 754
+ − 755 /* ISO_STATE_LOCK is the mask of flags that remain on until explicitly
+ − 756 turned off when in the ISO2022 encoder/decoder. Other flags are turned
+ − 757 off at the end of processing each character or escape sequence. */
+ − 758 # define ISO_STATE_LOCK \
+ − 759 (ISO_STATE_COMPOSITE | ISO_STATE_R2L)
+ − 760
+ − 761 typedef struct charset_conversion_spec
+ − 762 {
+ − 763 Lisp_Object from_charset;
+ − 764 Lisp_Object to_charset;
+ − 765 } charset_conversion_spec;
+ − 766
+ − 767 typedef struct
+ − 768 {
+ − 769 Dynarr_declare (charset_conversion_spec);
+ − 770 } charset_conversion_spec_dynarr;
+ − 771
+ − 772 struct iso2022_coding_system
+ − 773 {
+ − 774 /* What are the charsets to be initially designated to G0, G1,
+ − 775 G2, G3? If t, no charset is initially designated. If nil,
+ − 776 no charset is initially designated and no charset is allowed
+ − 777 to be designated. */
+ − 778 Lisp_Object initial_charset[4];
+ − 779
+ − 780 /* If true, a designation escape sequence needs to be sent on output
+ − 781 for the charset in G[0-3] before that charset is used. */
+ − 782 unsigned char force_charset_on_output[4];
+ − 783
+ − 784 charset_conversion_spec_dynarr *input_conv;
+ − 785 charset_conversion_spec_dynarr *output_conv;
+ − 786
+ − 787 unsigned int shoort :1; /* C makes you speak Dutch */
+ − 788 unsigned int no_ascii_eol :1;
+ − 789 unsigned int no_ascii_cntl :1;
+ − 790 unsigned int seven :1;
+ − 791 unsigned int lock_shift :1;
+ − 792 unsigned int no_iso6429 :1;
+ − 793 unsigned int escape_quoted :1;
+ − 794 };
+ − 795
+ − 796 #define CODING_SYSTEM_ISO2022_INITIAL_CHARSET(codesys, g) \
+ − 797 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->initial_charset[g])
+ − 798 #define CODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT(codesys, g) \
+ − 799 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->force_charset_on_output[g])
+ − 800 #define CODING_SYSTEM_ISO2022_SHORT(codesys) \
+ − 801 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->shoort)
+ − 802 #define CODING_SYSTEM_ISO2022_NO_ASCII_EOL(codesys) \
+ − 803 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->no_ascii_eol)
+ − 804 #define CODING_SYSTEM_ISO2022_NO_ASCII_CNTL(codesys) \
+ − 805 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->no_ascii_cntl)
+ − 806 #define CODING_SYSTEM_ISO2022_SEVEN(codesys) \
+ − 807 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->seven)
+ − 808 #define CODING_SYSTEM_ISO2022_LOCK_SHIFT(codesys) \
+ − 809 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->lock_shift)
+ − 810 #define CODING_SYSTEM_ISO2022_NO_ISO6429(codesys) \
+ − 811 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->no_iso6429)
+ − 812 #define CODING_SYSTEM_ISO2022_ESCAPE_QUOTED(codesys) \
+ − 813 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->escape_quoted)
+ − 814 #define CODING_SYSTEM_ISO2022_INPUT_CONV(codesys) \
+ − 815 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->input_conv)
+ − 816 #define CODING_SYSTEM_ISO2022_OUTPUT_CONV(codesys) \
+ − 817 (CODING_SYSTEM_TYPE_DATA (codesys, iso2022)->output_conv)
+ − 818
+ − 819 #define XCODING_SYSTEM_ISO2022_INITIAL_CHARSET(codesys, g) \
+ − 820 CODING_SYSTEM_ISO2022_INITIAL_CHARSET (XCODING_SYSTEM (codesys), g)
+ − 821 #define XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT(codesys, g) \
+ − 822 CODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (XCODING_SYSTEM (codesys), g)
+ − 823 #define XCODING_SYSTEM_ISO2022_SHORT(codesys) \
+ − 824 CODING_SYSTEM_ISO2022_SHORT (XCODING_SYSTEM (codesys))
+ − 825 #define XCODING_SYSTEM_ISO2022_NO_ASCII_EOL(codesys) \
+ − 826 CODING_SYSTEM_ISO2022_NO_ASCII_EOL (XCODING_SYSTEM (codesys))
+ − 827 #define XCODING_SYSTEM_ISO2022_NO_ASCII_CNTL(codesys) \
+ − 828 CODING_SYSTEM_ISO2022_NO_ASCII_CNTL (XCODING_SYSTEM (codesys))
+ − 829 #define XCODING_SYSTEM_ISO2022_SEVEN(codesys) \
+ − 830 CODING_SYSTEM_ISO2022_SEVEN (XCODING_SYSTEM (codesys))
+ − 831 #define XCODING_SYSTEM_ISO2022_LOCK_SHIFT(codesys) \
+ − 832 CODING_SYSTEM_ISO2022_LOCK_SHIFT (XCODING_SYSTEM (codesys))
+ − 833 #define XCODING_SYSTEM_ISO2022_NO_ISO6429(codesys) \
+ − 834 CODING_SYSTEM_ISO2022_NO_ISO6429 (XCODING_SYSTEM (codesys))
+ − 835 #define XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED(codesys) \
+ − 836 CODING_SYSTEM_ISO2022_ESCAPE_QUOTED (XCODING_SYSTEM (codesys))
+ − 837 #define XCODING_SYSTEM_ISO2022_INPUT_CONV(codesys) \
+ − 838 CODING_SYSTEM_ISO2022_INPUT_CONV (XCODING_SYSTEM (codesys))
+ − 839 #define XCODING_SYSTEM_ISO2022_OUTPUT_CONV(codesys) \
+ − 840 CODING_SYSTEM_ISO2022_OUTPUT_CONV (XCODING_SYSTEM (codesys))
+ − 841
+ − 842 /* Additional information used by the ISO2022 decoder and detector. */
+ − 843 struct iso2022_coding_stream
+ − 844 {
+ − 845 /* CHARSET holds the character sets currently assigned to the G0
+ − 846 through G3 variables. It is initialized from the array
+ − 847 INITIAL_CHARSET in CODESYS. */
+ − 848 Lisp_Object charset[4];
+ − 849
+ − 850 /* Which registers are currently invoked into the left (GL) and
+ − 851 right (GR) halves of the 8-bit encoding space? */
+ − 852 int register_left, register_right;
+ − 853
+ − 854 /* FLAGS holds flags indicating the current state of the encoding. Some of
+ − 855 these flags are actually part of the state-dependent data and should be
+ − 856 moved there. */
+ − 857 unsigned int flags;
+ − 858
+ − 859 /**************** for decoding ****************/
+ − 860
+ − 861 /* ISO_ESC holds a value indicating part of an escape sequence
+ − 862 that has already been seen. */
+ − 863 enum iso_esc_flag esc;
+ − 864
+ − 865 /* This records the bytes we've seen so far in an escape sequence,
+ − 866 in case the sequence is invalid (we spit out the bytes unchanged). */
+ − 867 unsigned char esc_bytes[8];
+ − 868
+ − 869 /* Index for next byte to store in ISO escape sequence. */
+ − 870 int esc_bytes_index;
+ − 871
+ − 872 #ifdef ENABLE_COMPOSITE_CHARS
+ − 873 /* Stuff seen so far when composing a string. */
+ − 874 unsigned_char_dynarr *composite_chars;
+ − 875 #endif
+ − 876
+ − 877 /* If we saw an invalid designation sequence for a particular
+ − 878 register, we flag it here and switch to ASCII. The next time we
+ − 879 see a valid designation for this register, we turn off the flag
+ − 880 and do the designation normally, but pretend the sequence was
+ − 881 invalid. The effect of all this is that (most of the time) the
+ − 882 escape sequences for both the switch to the unknown charset, and
+ − 883 the switch back to the known charset, get inserted literally into
+ − 884 the buffer and saved out as such. The hope is that we can
+ − 885 preserve the escape sequences so that the resulting written out
+ − 886 file makes sense. If we don't do any of this, the designation
+ − 887 to the invalid charset will be preserved but that switch back
+ − 888 to the known charset will probably get eaten because it was
+ − 889 the same charset that was already present in the register. */
+ − 890 unsigned char invalid_designated[4];
+ − 891
+ − 892 /* We try to do similar things as above for direction-switching
+ − 893 sequences. If we encountered a direction switch while an
+ − 894 invalid designation was present, or an invalid designation
+ − 895 just after a direction switch (i.e. no valid designation
+ − 896 encountered yet), we insert the direction-switch escape
+ − 897 sequence literally into the output stream, and later on
+ − 898 insert the corresponding direction-restoring escape sequence
+ − 899 literally also. */
+ − 900 unsigned int switched_dir_and_no_valid_charset_yet :1;
+ − 901 unsigned int invalid_switch_dir :1;
+ − 902
+ − 903 /* Tells the decoder to output the escape sequence literally
+ − 904 even though it was valid. Used in the games we play to
+ − 905 avoid lossage when we encounter invalid designations. */
+ − 906 unsigned int output_literally :1;
+ − 907 /* We encountered a direction switch followed by an invalid
+ − 908 designation. We didn't output the direction switch
+ − 909 literally because we didn't know about the invalid designation;
+ − 910 but we have to do so now. */
+ − 911 unsigned int output_direction_sequence :1;
+ − 912
+ − 913 /**************** for encoding ****************/
+ − 914
+ − 915 /* Whether we need to explicitly designate the charset in the
+ − 916 G? register before using it. It is initialized from the
+ − 917 array FORCE_CHARSET_ON_OUTPUT in CODESYS. */
+ − 918 unsigned char force_charset_on_output[4];
+ − 919
+ − 920 /* Other state variables that need to be preserved across
+ − 921 invocations. */
+ − 922 Lisp_Object current_charset;
+ − 923 int current_half;
+ − 924 int current_char_boundary;
+ − 925 };
+ − 926
1204
+ − 927 static const struct memory_description ccs_description_1[] =
771
+ − 928 {
+ − 929 { XD_LISP_OBJECT, offsetof (charset_conversion_spec, from_charset) },
+ − 930 { XD_LISP_OBJECT, offsetof (charset_conversion_spec, to_charset) },
+ − 931 { XD_END }
+ − 932 };
+ − 933
1204
+ − 934 static const struct sized_memory_description ccs_description =
771
+ − 935 {
+ − 936 sizeof (charset_conversion_spec),
+ − 937 ccs_description_1
+ − 938 };
+ − 939
1204
+ − 940 static const struct memory_description ccsd_description_1[] =
771
+ − 941 {
+ − 942 XD_DYNARR_DESC (charset_conversion_spec_dynarr, &ccs_description),
+ − 943 { XD_END }
+ − 944 };
+ − 945
1204
+ − 946 static const struct sized_memory_description ccsd_description =
771
+ − 947 {
+ − 948 sizeof (charset_conversion_spec_dynarr),
+ − 949 ccsd_description_1
+ − 950 };
+ − 951
1204
+ − 952 static const struct memory_description iso2022_coding_system_description[] = {
+ − 953 { XD_LISP_OBJECT_ARRAY, offsetof (struct iso2022_coding_system,
+ − 954 initial_charset), 4 },
2367
+ − 955 { XD_BLOCK_PTR, offsetof (struct iso2022_coding_system, input_conv),
771
+ − 956 1, &ccsd_description },
2367
+ − 957 { XD_BLOCK_PTR, offsetof (struct iso2022_coding_system, output_conv),
771
+ − 958 1, &ccsd_description },
+ − 959 { XD_END }
+ − 960 };
+ − 961
1204
+ − 962 DEFINE_CODING_SYSTEM_TYPE_WITH_DATA (iso2022);
+ − 963
771
+ − 964 /* The following note taken directly from FSF 21.0.103. */
+ − 965
+ − 966 /* The following note describes the coding system ISO2022 briefly.
+ − 967 Since the intention of this note is to help understand the
+ − 968 functions in this file, some parts are NOT ACCURATE or are OVERLY
+ − 969 SIMPLIFIED. For thorough understanding, please refer to the
+ − 970 original document of ISO2022. This is equivalent to the standard
+ − 971 ECMA-35, obtainable from <URL:http://www.ecma.ch/> (*).
+ − 972
+ − 973 ISO2022 provides many mechanisms to encode several character sets
+ − 974 in 7-bit and 8-bit environments. For 7-bit environments, all text
+ − 975 is encoded using bytes less than 128. This may make the encoded
+ − 976 text a little bit longer, but the text passes more easily through
+ − 977 several types of gateway, some of which strip off the MSB (Most
+ − 978 Significant Bit).
+ − 979
+ − 980 There are two kinds of character sets: control character sets and
+ − 981 graphic character sets. The former contain control characters such
+ − 982 as `newline' and `escape' to provide control functions (control
+ − 983 functions are also provided by escape sequences). The latter
+ − 984 contain graphic characters such as 'A' and '-'. Emacs recognizes
+ − 985 two control character sets and many graphic character sets.
+ − 986
+ − 987 Graphic character sets are classified into one of the following
+ − 988 four classes, according to the number of bytes (DIMENSION) and
+ − 989 number of characters in one dimension (CHARS) of the set:
+ − 990 - DIMENSION1_CHARS94
+ − 991 - DIMENSION1_CHARS96
+ − 992 - DIMENSION2_CHARS94
+ − 993 - DIMENSION2_CHARS96
+ − 994
+ − 995 In addition, each character set is assigned an identification tag,
+ − 996 unique for each set, called the "final character" (denoted as <F>
+ − 997 hereafter). The <F> of each character set is decided by ECMA(*)
+ − 998 when it is registered in ISO. The code range of <F> is 0x30..0x7F
+ − 999 (0x30..0x3F are for private use only).
+ − 1000
+ − 1001 Note (*): ECMA = European Computer Manufacturers Association
+ − 1002
+ − 1003 Here are examples of graphic character sets [NAME(<F>)]:
+ − 1004 o DIMENSION1_CHARS94 -- ASCII('B'), right-half-of-JISX0201('I'), ...
+ − 1005 o DIMENSION1_CHARS96 -- right-half-of-ISO8859-1('A'), ...
+ − 1006 o DIMENSION2_CHARS94 -- GB2312('A'), JISX0208('B'), ...
+ − 1007 o DIMENSION2_CHARS96 -- none for the moment
+ − 1008
+ − 1009 A code area (1 byte=8 bits) is divided into 4 areas, C0, GL, C1, and GR.
+ − 1010 C0 [0x00..0x1F] -- control character plane 0
+ − 1011 GL [0x20..0x7F] -- graphic character plane 0
+ − 1012 C1 [0x80..0x9F] -- control character plane 1
+ − 1013 GR [0xA0..0xFF] -- graphic character plane 1
+ − 1014
+ − 1015 A control character set is directly designated and invoked to C0 or
+ − 1016 C1 by an escape sequence. The most common case is that:
+ − 1017 - ISO646's control character set is designated/invoked to C0, and
+ − 1018 - ISO6429's control character set is designated/invoked to C1,
+ − 1019 and usually these designations/invocations are omitted in encoded
+ − 1020 text. In a 7-bit environment, only C0 can be used, and a control
+ − 1021 character for C1 is encoded by an appropriate escape sequence to
+ − 1022 fit into the environment. All control characters for C1 are
+ − 1023 defined to have corresponding escape sequences.
+ − 1024
+ − 1025 A graphic character set is at first designated to one of four
+ − 1026 graphic registers (G0 through G3), then these graphic registers are
+ − 1027 invoked to GL or GR. These designations and invocations can be
+ − 1028 done independently. The most common case is that G0 is invoked to
+ − 1029 GL, G1 is invoked to GR, and ASCII is designated to G0. Usually
+ − 1030 these invocations and designations are omitted in encoded text.
+ − 1031 In a 7-bit environment, only GL can be used.
+ − 1032
+ − 1033 When a graphic character set of CHARS94 is invoked to GL, codes
+ − 1034 0x20 and 0x7F of the GL area work as control characters SPACE and
+ − 1035 DEL respectively, and codes 0xA0 and 0xFF of the GR area should not
+ − 1036 be used.
+ − 1037
+ − 1038 There are two ways of invocation: locking-shift and single-shift.
+ − 1039 With locking-shift, the invocation lasts until the next different
+ − 1040 invocation, whereas with single-shift, the invocation affects the
+ − 1041 following character only and doesn't affect the locking-shift
+ − 1042 state. Invocations are done by the following control characters or
+ − 1043 escape sequences:
+ − 1044
+ − 1045 ----------------------------------------------------------------------
+ − 1046 abbrev function cntrl escape seq description
+ − 1047 ----------------------------------------------------------------------
+ − 1048 SI/LS0 (shift-in) 0x0F none invoke G0 into GL
+ − 1049 SO/LS1 (shift-out) 0x0E none invoke G1 into GL
+ − 1050 LS2 (locking-shift-2) none ESC 'n' invoke G2 into GL
+ − 1051 LS3 (locking-shift-3) none ESC 'o' invoke G3 into GL
+ − 1052 LS1R (locking-shift-1 right) none ESC '~' invoke G1 into GR (*)
+ − 1053 LS2R (locking-shift-2 right) none ESC '}' invoke G2 into GR (*)
+ − 1054 LS3R (locking-shift 3 right) none ESC '|' invoke G3 into GR (*)
+ − 1055 SS2 (single-shift-2) 0x8E ESC 'N' invoke G2 for one char
+ − 1056 SS3 (single-shift-3) 0x8F ESC 'O' invoke G3 for one char
+ − 1057 ----------------------------------------------------------------------
+ − 1058 (*) These are not used by any known coding system.
+ − 1059
+ − 1060 Control characters for these functions are defined by macros
+ − 1061 ISO_CODE_XXX in `coding.h'.
+ − 1062
+ − 1063 Designations are done by the following escape sequences:
+ − 1064 ----------------------------------------------------------------------
+ − 1065 escape sequence description
+ − 1066 ----------------------------------------------------------------------
+ − 1067 ESC '(' <F> designate DIMENSION1_CHARS94<F> to G0
+ − 1068 ESC ')' <F> designate DIMENSION1_CHARS94<F> to G1
+ − 1069 ESC '*' <F> designate DIMENSION1_CHARS94<F> to G2
+ − 1070 ESC '+' <F> designate DIMENSION1_CHARS94<F> to G3
+ − 1071 ESC ',' <F> designate DIMENSION1_CHARS96<F> to G0 (*)
+ − 1072 ESC '-' <F> designate DIMENSION1_CHARS96<F> to G1
+ − 1073 ESC '.' <F> designate DIMENSION1_CHARS96<F> to G2
+ − 1074 ESC '/' <F> designate DIMENSION1_CHARS96<F> to G3
+ − 1075 ESC '$' '(' <F> designate DIMENSION2_CHARS94<F> to G0 (**)
+ − 1076 ESC '$' ')' <F> designate DIMENSION2_CHARS94<F> to G1
+ − 1077 ESC '$' '*' <F> designate DIMENSION2_CHARS94<F> to G2
+ − 1078 ESC '$' '+' <F> designate DIMENSION2_CHARS94<F> to G3
+ − 1079 ESC '$' ',' <F> designate DIMENSION2_CHARS96<F> to G0 (*)
+ − 1080 ESC '$' '-' <F> designate DIMENSION2_CHARS96<F> to G1
+ − 1081 ESC '$' '.' <F> designate DIMENSION2_CHARS96<F> to G2
+ − 1082 ESC '$' '/' <F> designate DIMENSION2_CHARS96<F> to G3
+ − 1083 ----------------------------------------------------------------------
+ − 1084
+ − 1085 In this list, "DIMENSION1_CHARS94<F>" means a graphic character set
+ − 1086 of dimension 1, chars 94, and final character <F>, etc...
+ − 1087
+ − 1088 Note (*): Although these designations are not allowed in ISO2022,
+ − 1089 Emacs accepts them on decoding, and produces them on encoding
+ − 1090 CHARS96 character sets in a coding system which is characterized as
+ − 1091 7-bit environment, non-locking-shift, and non-single-shift.
+ − 1092
+ − 1093 Note (**): If <F> is '@', 'A', or 'B', the intermediate character
+ − 1094 '(' can be omitted. We refer to this as "short-form" hereafter.
+ − 1095
+ − 1096 Now you may notice that there are a lot of ways of encoding the
+ − 1097 same multilingual text in ISO2022. Actually, there exist many
+ − 1098 coding systems such as Compound Text (used in X11's inter client
+ − 1099 communication, ISO-2022-JP (used in Japanese Internet), ISO-2022-KR
+ − 1100 (used in Korean Internet), EUC (Extended UNIX Code, used in Asian
+ − 1101 localized platforms), and all of these are variants of ISO2022.
+ − 1102
+ − 1103 In addition to the above, Emacs handles two more kinds of escape
+ − 1104 sequences: ISO6429's direction specification and Emacs' private
+ − 1105 sequence for specifying character composition.
+ − 1106
+ − 1107 ISO6429's direction specification takes the following form:
+ − 1108 o CSI ']' -- end of the current direction
+ − 1109 o CSI '0' ']' -- end of the current direction
+ − 1110 o CSI '1' ']' -- start of left-to-right text
+ − 1111 o CSI '2' ']' -- start of right-to-left text
+ − 1112 The control character CSI (0x9B: control sequence introducer) is
+ − 1113 abbreviated to the escape sequence ESC '[' in a 7-bit environment.
+ − 1114
+ − 1115 Character composition specification takes the following form:
+ − 1116 o ESC '0' -- start relative composition
+ − 1117 o ESC '1' -- end composition
+ − 1118 o ESC '2' -- start rule-base composition (*)
+ − 1119 o ESC '3' -- start relative composition with alternate chars (**)
+ − 1120 o ESC '4' -- start rule-base composition with alternate chars (**)
+ − 1121 Since these are not standard escape sequences of any ISO standard,
+ − 1122 the use of them with these meanings is restricted to Emacs only.
+ − 1123
+ − 1124 (*) This form is used only in Emacs 20.5 and older versions,
+ − 1125 but the newer versions can safely decode it.
+ − 1126 (**) This form is used only in Emacs 21.1 and newer versions,
+ − 1127 and the older versions can't decode it.
+ − 1128
+ − 1129 Here's a list of example usages of these composition escape
+ − 1130 sequences (categorized by `enum composition_method').
+ − 1131
+ − 1132 COMPOSITION_RELATIVE:
+ − 1133 ESC 0 CHAR [ CHAR ] ESC 1
+ − 1134 COMPOSITION_WITH_RULE:
+ − 1135 ESC 2 CHAR [ RULE CHAR ] ESC 1
+ − 1136 COMPOSITION_WITH_ALTCHARS:
+ − 1137 ESC 3 ALTCHAR [ ALTCHAR ] ESC 0 CHAR [ CHAR ] ESC 1
+ − 1138 COMPOSITION_WITH_RULE_ALTCHARS:
+ − 1139 ESC 4 ALTCHAR [ RULE ALTCHAR ] ESC 0 CHAR [ CHAR ] ESC 1 */
+ − 1140
+ − 1141 static void
+ − 1142 reset_iso2022_decode (Lisp_Object coding_system,
+ − 1143 struct iso2022_coding_stream *data)
+ − 1144 {
+ − 1145 int i;
+ − 1146 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1147 unsigned_char_dynarr *old_composite_chars = data->composite_chars;
+ − 1148 #endif
+ − 1149
+ − 1150 xzero (*data);
+ − 1151
+ − 1152 for (i = 0; i < 4; i++)
+ − 1153 {
+ − 1154 if (!NILP (coding_system))
+ − 1155 data->charset[i] =
+ − 1156 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, i);
+ − 1157 else
+ − 1158 data->charset[i] = Qt;
+ − 1159 }
+ − 1160 data->esc = ISO_ESC_NOTHING;
+ − 1161 data->register_right = 1;
+ − 1162 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1163 if (old_composite_chars)
+ − 1164 {
+ − 1165 data->composite_chars = old_composite_chars;
+ − 1166 Dynarr_reset (data->composite_chars);
+ − 1167 }
+ − 1168 #endif
+ − 1169 }
+ − 1170
+ − 1171 static void
+ − 1172 reset_iso2022_encode (Lisp_Object coding_system,
+ − 1173 struct iso2022_coding_stream *data)
+ − 1174 {
+ − 1175 int i;
+ − 1176
+ − 1177 xzero (*data);
+ − 1178
+ − 1179 for (i = 0; i < 4; i++)
+ − 1180 {
+ − 1181 data->charset[i] =
+ − 1182 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, i);
+ − 1183 data->force_charset_on_output[i] =
+ − 1184 XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (coding_system, i);
+ − 1185 }
+ − 1186 data->register_right = 1;
+ − 1187 data->current_charset = Qnil;
+ − 1188 data->current_char_boundary = 1;
+ − 1189 }
+ − 1190
+ − 1191 static void
+ − 1192 iso2022_init_coding_stream (struct coding_stream *str)
+ − 1193 {
+ − 1194 if (str->direction == CODING_DECODE)
+ − 1195 reset_iso2022_decode (str->codesys,
+ − 1196 CODING_STREAM_TYPE_DATA (str, iso2022));
+ − 1197 else
+ − 1198 reset_iso2022_encode (str->codesys,
+ − 1199 CODING_STREAM_TYPE_DATA (str, iso2022));
+ − 1200 }
+ − 1201
+ − 1202 static void
+ − 1203 iso2022_rewind_coding_stream (struct coding_stream *str)
+ − 1204 {
+ − 1205 iso2022_init_coding_stream (str);
+ − 1206 }
+ − 1207
+ − 1208 static int
+ − 1209 fit_to_be_escape_quoted (unsigned char c)
+ − 1210 {
+ − 1211 switch (c)
+ − 1212 {
+ − 1213 case ISO_CODE_ESC:
+ − 1214 case ISO_CODE_CSI:
+ − 1215 case ISO_CODE_SS2:
+ − 1216 case ISO_CODE_SS3:
+ − 1217 case ISO_CODE_SO:
+ − 1218 case ISO_CODE_SI:
+ − 1219 return 1;
+ − 1220
+ − 1221 default:
+ − 1222 return 0;
+ − 1223 }
+ − 1224 }
+ − 1225
+ − 1226 static Lisp_Object
867
+ − 1227 charset_by_attributes_or_create_one (int type, Ibyte final, int dir)
771
+ − 1228 {
826
+ − 1229 Lisp_Object charset = charset_by_attributes (type, final, dir);
771
+ − 1230
+ − 1231 if (NILP (charset))
+ − 1232 {
+ − 1233 int chars, dim;
+ − 1234
+ − 1235 switch (type)
+ − 1236 {
+ − 1237 case CHARSET_TYPE_94:
+ − 1238 chars = 94; dim = 1;
+ − 1239 break;
+ − 1240 case CHARSET_TYPE_96:
+ − 1241 chars = 96; dim = 1;
+ − 1242 break;
+ − 1243 case CHARSET_TYPE_94X94:
+ − 1244 chars = 94; dim = 2;
+ − 1245 break;
+ − 1246 case CHARSET_TYPE_96X96:
+ − 1247 chars = 96; dim = 2;
+ − 1248 break;
+ − 1249 default:
+ − 1250 abort (); chars = 0; dim = 0;
+ − 1251 }
+ − 1252
+ − 1253 charset = Fmake_charset (Qunbound, Qnil,
+ − 1254 nconc2 (list6 (Qfinal, make_char (final),
+ − 1255 Qchars, make_int (chars),
+ − 1256 Qdimension, make_int (dim)),
+ − 1257 list2 (Qdirection,
+ − 1258 dir == CHARSET_LEFT_TO_RIGHT ?
+ − 1259 Ql2r : Qr2l)));
+ − 1260 }
+ − 1261
+ − 1262 return charset;
+ − 1263 }
+ − 1264
+ − 1265 /* Parse one byte of an ISO2022 escape sequence.
+ − 1266 If the result is an invalid escape sequence, return 0 and
+ − 1267 do not change anything in STR. Otherwise, if the result is
+ − 1268 an incomplete escape sequence, update ISO2022.ESC and
+ − 1269 ISO2022.ESC_BYTES and return -1. Otherwise, update
+ − 1270 all the state variables (but not ISO2022.ESC_BYTES) and
+ − 1271 return 1.
+ − 1272
+ − 1273 If CHECK_INVALID_CHARSETS is non-zero, check for designation
+ − 1274 or invocation of an invalid character set and treat that as
+ − 1275 an unrecognized escape sequence.
+ − 1276
2367
+ − 1277 */
771
+ − 1278
+ − 1279 static int
+ − 1280 parse_iso2022_esc (Lisp_Object codesys, struct iso2022_coding_stream *iso,
+ − 1281 unsigned char c, unsigned int *flags,
+ − 1282 int check_invalid_charsets)
+ − 1283 {
+ − 1284 /* (1) If we're at the end of a designation sequence, CS is the
+ − 1285 charset being designated and REG is the register to designate
+ − 1286 it to.
+ − 1287
+ − 1288 (2) If we're at the end of a locking-shift sequence, REG is
+ − 1289 the register to invoke and HALF (0 == left, 1 == right) is
+ − 1290 the half to invoke it into.
+ − 1291
+ − 1292 (3) If we're at the end of a single-shift sequence, REG is
+ − 1293 the register to invoke. */
+ − 1294 Lisp_Object cs = Qnil;
+ − 1295 int reg, half;
+ − 1296
+ − 1297 /* NOTE: This code does goto's all over the fucking place.
+ − 1298 The reason for this is that we're basically implementing
+ − 1299 a state machine here, and hierarchical languages like C
+ − 1300 don't really provide a clean way of doing this. */
+ − 1301
+ − 1302 if (! (*flags & ISO_STATE_ESCAPE))
+ − 1303 /* At beginning of escape sequence; we need to reset our
+ − 1304 escape-state variables. */
+ − 1305 iso->esc = ISO_ESC_NOTHING;
+ − 1306
+ − 1307 iso->output_literally = 0;
+ − 1308 iso->output_direction_sequence = 0;
+ − 1309
+ − 1310 switch (iso->esc)
+ − 1311 {
+ − 1312 case ISO_ESC_NOTHING:
+ − 1313 iso->esc_bytes_index = 0;
+ − 1314 switch (c)
+ − 1315 {
+ − 1316 case ISO_CODE_ESC: /* Start escape sequence */
+ − 1317 *flags |= ISO_STATE_ESCAPE;
+ − 1318 iso->esc = ISO_ESC;
+ − 1319 goto not_done;
+ − 1320
+ − 1321 case ISO_CODE_CSI: /* ISO6429 (specifying directionality) */
+ − 1322 *flags |= ISO_STATE_ESCAPE;
+ − 1323 iso->esc = ISO_ESC_5_11;
+ − 1324 goto not_done;
+ − 1325
+ − 1326 case ISO_CODE_SO: /* locking shift 1 */
+ − 1327 reg = 1; half = 0;
+ − 1328 goto locking_shift;
+ − 1329 case ISO_CODE_SI: /* locking shift 0 */
+ − 1330 reg = 0; half = 0;
+ − 1331 goto locking_shift;
+ − 1332
+ − 1333 case ISO_CODE_SS2: /* single shift */
+ − 1334 reg = 2;
+ − 1335 goto single_shift;
+ − 1336 case ISO_CODE_SS3: /* single shift */
+ − 1337 reg = 3;
+ − 1338 goto single_shift;
+ − 1339
+ − 1340 default: /* Other control characters */
+ − 1341 error:
+ − 1342 *flags &= ISO_STATE_LOCK;
+ − 1343 return 0;
+ − 1344 }
+ − 1345
+ − 1346 case ISO_ESC:
+ − 1347 switch (c)
+ − 1348 {
+ − 1349 /**** single shift ****/
+ − 1350
+ − 1351 case 'N': /* single shift 2 */
+ − 1352 reg = 2;
+ − 1353 goto single_shift;
+ − 1354 case 'O': /* single shift 3 */
+ − 1355 reg = 3;
+ − 1356 goto single_shift;
+ − 1357
+ − 1358 /**** locking shift ****/
+ − 1359
+ − 1360 case '~': /* locking shift 1 right */
+ − 1361 reg = 1; half = 1;
+ − 1362 goto locking_shift;
+ − 1363 case 'n': /* locking shift 2 */
+ − 1364 reg = 2; half = 0;
+ − 1365 goto locking_shift;
+ − 1366 case '}': /* locking shift 2 right */
+ − 1367 reg = 2; half = 1;
+ − 1368 goto locking_shift;
+ − 1369 case 'o': /* locking shift 3 */
+ − 1370 reg = 3; half = 0;
+ − 1371 goto locking_shift;
+ − 1372 case '|': /* locking shift 3 right */
+ − 1373 reg = 3; half = 1;
+ − 1374 goto locking_shift;
+ − 1375
+ − 1376 /**** composite ****/
+ − 1377
+ − 1378 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1379 case '0':
+ − 1380 iso->esc = ISO_ESC_START_COMPOSITE;
+ − 1381 *flags = (*flags & ISO_STATE_LOCK) |
+ − 1382 ISO_STATE_COMPOSITE;
+ − 1383 return 1;
+ − 1384
+ − 1385 case '1':
+ − 1386 iso->esc = ISO_ESC_END_COMPOSITE;
+ − 1387 *flags = (*flags & ISO_STATE_LOCK) &
+ − 1388 ~ISO_STATE_COMPOSITE;
+ − 1389 return 1;
+ − 1390 #else
+ − 1391 case '0': case '1': case '2': case '3': case '4':
+ − 1392 /* We simply return a flag indicating that some composite
+ − 1393 escape was seen. The caller will use the particular
+ − 1394 character to encode the appropriate "composite hack"
+ − 1395 character out of Vcharset_composite, so that we will
+ − 1396 preserve these values on output. */
+ − 1397 iso->esc = ISO_ESC_START_COMPOSITE;
+ − 1398 *flags &= ISO_STATE_LOCK;
+ − 1399 return 1;
+ − 1400 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 1401
+ − 1402 /**** directionality ****/
+ − 1403
+ − 1404 case '[':
+ − 1405 iso->esc = ISO_ESC_5_11;
+ − 1406 goto not_done;
+ − 1407
+ − 1408 /**** designation ****/
+ − 1409
+ − 1410 case '$': /* multibyte charset prefix */
+ − 1411 iso->esc = ISO_ESC_2_4;
+ − 1412 goto not_done;
+ − 1413
+ − 1414 default:
+ − 1415 if (0x28 <= c && c <= 0x2F)
+ − 1416 {
+ − 1417 iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_8);
+ − 1418 goto not_done;
+ − 1419 }
+ − 1420
+ − 1421 /* This function is called with CODESYS equal to nil when
+ − 1422 doing coding-system detection. */
+ − 1423 if (!NILP (codesys)
+ − 1424 && XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
+ − 1425 && fit_to_be_escape_quoted (c))
+ − 1426 {
+ − 1427 iso->esc = ISO_ESC_LITERAL;
+ − 1428 *flags &= ISO_STATE_LOCK;
+ − 1429 return 1;
+ − 1430 }
+ − 1431
+ − 1432 /* bzzzt! */
+ − 1433 goto error;
+ − 1434 }
+ − 1435
+ − 1436
+ − 1437
+ − 1438 /**** directionality ****/
+ − 1439
+ − 1440 case ISO_ESC_5_11: /* ISO6429 direction control */
+ − 1441 if (c == ']')
+ − 1442 {
+ − 1443 *flags &= (ISO_STATE_LOCK & ~ISO_STATE_R2L);
+ − 1444 goto directionality;
+ − 1445 }
+ − 1446 if (c == '0') iso->esc = ISO_ESC_5_11_0;
+ − 1447 else if (c == '1') iso->esc = ISO_ESC_5_11_1;
+ − 1448 else if (c == '2') iso->esc = ISO_ESC_5_11_2;
+ − 1449 else goto error;
+ − 1450 goto not_done;
+ − 1451
+ − 1452 case ISO_ESC_5_11_0:
+ − 1453 if (c == ']')
+ − 1454 {
+ − 1455 *flags &= (ISO_STATE_LOCK & ~ISO_STATE_R2L);
+ − 1456 goto directionality;
+ − 1457 }
+ − 1458 goto error;
+ − 1459
+ − 1460 case ISO_ESC_5_11_1:
+ − 1461 if (c == ']')
+ − 1462 {
+ − 1463 *flags = (ISO_STATE_LOCK & ~ISO_STATE_R2L);
+ − 1464 goto directionality;
+ − 1465 }
+ − 1466 goto error;
+ − 1467
+ − 1468 case ISO_ESC_5_11_2:
+ − 1469 if (c == ']')
+ − 1470 {
+ − 1471 *flags = (*flags & ISO_STATE_LOCK) | ISO_STATE_R2L;
+ − 1472 goto directionality;
+ − 1473 }
+ − 1474 goto error;
+ − 1475
+ − 1476 directionality:
+ − 1477 iso->esc = ISO_ESC_DIRECTIONALITY;
+ − 1478 /* Various junk here to attempt to preserve the direction sequences
+ − 1479 literally in the text if they would otherwise be swallowed due
+ − 1480 to invalid designations that don't show up as actual charset
+ − 1481 changes in the text. */
+ − 1482 if (iso->invalid_switch_dir)
+ − 1483 {
+ − 1484 /* We already inserted a direction switch literally into the
+ − 1485 text. We assume (#### this may not be right) that the
+ − 1486 next direction switch is the one going the other way,
+ − 1487 and we need to output that literally as well. */
+ − 1488 iso->output_literally = 1;
+ − 1489 iso->invalid_switch_dir = 0;
+ − 1490 }
+ − 1491 else
+ − 1492 {
+ − 1493 int jj;
+ − 1494
+ − 1495 /* If we are in the thrall of an invalid designation,
+ − 1496 then stick the directionality sequence literally into the
+ − 1497 output stream so it ends up in the original text again. */
+ − 1498 for (jj = 0; jj < 4; jj++)
+ − 1499 if (iso->invalid_designated[jj])
+ − 1500 break;
+ − 1501 if (jj < 4)
+ − 1502 {
+ − 1503 iso->output_literally = 1;
+ − 1504 iso->invalid_switch_dir = 1;
+ − 1505 }
+ − 1506 else
+ − 1507 /* Indicate that we haven't yet seen a valid designation,
+ − 1508 so that if a switch-dir is directly followed by an
+ − 1509 invalid designation, both get inserted literally. */
+ − 1510 iso->switched_dir_and_no_valid_charset_yet = 1;
+ − 1511 }
+ − 1512 return 1;
+ − 1513
+ − 1514
+ − 1515 /**** designation ****/
+ − 1516
+ − 1517 case ISO_ESC_2_4:
+ − 1518 if (0x28 <= c && c <= 0x2F)
+ − 1519 {
+ − 1520 iso->esc = (enum iso_esc_flag) (c - 0x28 + ISO_ESC_2_4_8);
+ − 1521 goto not_done;
+ − 1522 }
+ − 1523 if (0x40 <= c && c <= 0x42)
+ − 1524 {
+ − 1525 cs = charset_by_attributes_or_create_one (CHARSET_TYPE_94X94, c,
+ − 1526 *flags & ISO_STATE_R2L ?
+ − 1527 CHARSET_RIGHT_TO_LEFT :
+ − 1528 CHARSET_LEFT_TO_RIGHT);
+ − 1529 reg = 0;
+ − 1530 goto designated;
+ − 1531 }
+ − 1532 goto error;
+ − 1533
+ − 1534 default:
+ − 1535 {
+ − 1536 int type = -1;
+ − 1537
+ − 1538 if (iso->esc >= ISO_ESC_2_8 &&
+ − 1539 iso->esc <= ISO_ESC_2_15)
+ − 1540 {
+ − 1541 type = ((iso->esc >= ISO_ESC_2_12) ?
+ − 1542 CHARSET_TYPE_96 : CHARSET_TYPE_94);
+ − 1543 reg = (iso->esc - ISO_ESC_2_8) & 3;
+ − 1544 }
+ − 1545 else if (iso->esc >= ISO_ESC_2_4_8 &&
+ − 1546 iso->esc <= ISO_ESC_2_4_15)
+ − 1547 {
+ − 1548 type = ((iso->esc >= ISO_ESC_2_4_12) ?
+ − 1549 CHARSET_TYPE_96X96 : CHARSET_TYPE_94X94);
+ − 1550 reg = (iso->esc - ISO_ESC_2_4_8) & 3;
+ − 1551 }
+ − 1552 else
+ − 1553 {
+ − 1554 /* Can this ever be reached? -slb */
+ − 1555 abort ();
+ − 1556 goto error;
+ − 1557 }
+ − 1558
+ − 1559 if (c < '0' || c > '~' ||
+ − 1560 (c > 0x5F && (type == CHARSET_TYPE_94X94 ||
+ − 1561 type == CHARSET_TYPE_96X96)))
+ − 1562 goto error; /* bad final byte */
+ − 1563
+ − 1564 cs = charset_by_attributes_or_create_one (type, c,
+ − 1565 *flags & ISO_STATE_R2L ?
+ − 1566 CHARSET_RIGHT_TO_LEFT :
+ − 1567 CHARSET_LEFT_TO_RIGHT);
+ − 1568 goto designated;
+ − 1569 }
+ − 1570 }
+ − 1571
+ − 1572 not_done:
+ − 1573 iso->esc_bytes[iso->esc_bytes_index++] = (unsigned char) c;
+ − 1574 return -1;
+ − 1575
+ − 1576 single_shift:
+ − 1577 if (check_invalid_charsets && !CHARSETP (iso->charset[reg]))
+ − 1578 /* can't invoke something that ain't there. */
+ − 1579 goto error;
+ − 1580 iso->esc = ISO_ESC_SINGLE_SHIFT;
+ − 1581 *flags &= ISO_STATE_LOCK;
+ − 1582 if (reg == 2)
+ − 1583 *flags |= ISO_STATE_SS2;
+ − 1584 else
+ − 1585 *flags |= ISO_STATE_SS3;
+ − 1586 return 1;
+ − 1587
+ − 1588 locking_shift:
+ − 1589 if (check_invalid_charsets &&
+ − 1590 !CHARSETP (iso->charset[reg]))
+ − 1591 /* can't invoke something that ain't there. */
+ − 1592 goto error;
+ − 1593 if (half)
+ − 1594 iso->register_right = reg;
+ − 1595 else
+ − 1596 iso->register_left = reg;
+ − 1597 *flags &= ISO_STATE_LOCK;
+ − 1598 iso->esc = ISO_ESC_LOCKING_SHIFT;
+ − 1599 return 1;
+ − 1600
+ − 1601 designated:
+ − 1602 if (NILP (cs) && check_invalid_charsets)
+ − 1603 {
+ − 1604 abort ();
+ − 1605 /* #### This should never happen now that we automatically create
+ − 1606 temporary charsets as necessary. We should probably remove
+ − 1607 this code. --ben */
+ − 1608 iso->invalid_designated[reg] = 1;
+ − 1609 iso->charset[reg] = Vcharset_ascii;
+ − 1610 iso->esc = ISO_ESC_DESIGNATE;
+ − 1611 *flags &= ISO_STATE_LOCK;
+ − 1612 iso->output_literally = 1;
+ − 1613 if (iso->switched_dir_and_no_valid_charset_yet)
+ − 1614 {
+ − 1615 /* We encountered a switch-direction followed by an
+ − 1616 invalid designation. Ensure that the switch-direction
+ − 1617 gets outputted; otherwise it will probably get eaten
+ − 1618 when the text is written out again. */
+ − 1619 iso->switched_dir_and_no_valid_charset_yet = 0;
+ − 1620 iso->output_direction_sequence = 1;
+ − 1621 /* And make sure that the switch-dir going the other
+ − 1622 way gets outputted, as well. */
+ − 1623 iso->invalid_switch_dir = 1;
+ − 1624 }
+ − 1625 return 1;
+ − 1626 }
+ − 1627 /* This function is called with CODESYS equal to nil when
+ − 1628 doing coding-system detection. */
+ − 1629 if (!NILP (codesys))
+ − 1630 {
+ − 1631 charset_conversion_spec_dynarr *dyn =
+ − 1632 XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys);
+ − 1633
+ − 1634 if (dyn)
+ − 1635 {
+ − 1636 int i;
+ − 1637
+ − 1638 for (i = 0; i < Dynarr_length (dyn); i++)
+ − 1639 {
+ − 1640 struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
+ − 1641 if (EQ (cs, spec->from_charset))
+ − 1642 cs = spec->to_charset;
+ − 1643 }
+ − 1644 }
+ − 1645 }
+ − 1646
+ − 1647 iso->charset[reg] = cs;
+ − 1648 iso->esc = ISO_ESC_DESIGNATE;
+ − 1649 *flags &= ISO_STATE_LOCK;
+ − 1650 if (iso->invalid_designated[reg])
+ − 1651 {
+ − 1652 iso->invalid_designated[reg] = 0;
+ − 1653 iso->output_literally = 1;
+ − 1654 }
+ − 1655 if (iso->switched_dir_and_no_valid_charset_yet)
+ − 1656 iso->switched_dir_and_no_valid_charset_yet = 0;
+ − 1657 return 1;
+ − 1658 }
+ − 1659
+ − 1660 /* If FLAGS is a null pointer or specifies right-to-left motion,
+ − 1661 output a switch-dir-to-left-to-right sequence to DST.
+ − 1662 Also update FLAGS if it is not a null pointer.
+ − 1663 If INTERNAL_P is set, we are outputting in internal format and
+ − 1664 need to handle the CSI differently. */
+ − 1665
+ − 1666 static void
+ − 1667 restore_left_to_right_direction (Lisp_Object codesys,
+ − 1668 unsigned_char_dynarr *dst,
+ − 1669 unsigned int *flags,
+ − 1670 int internal_p)
+ − 1671 {
+ − 1672 if (!flags || (*flags & ISO_STATE_R2L))
+ − 1673 {
+ − 1674 if (XCODING_SYSTEM_ISO2022_SEVEN (codesys))
+ − 1675 {
+ − 1676 Dynarr_add (dst, ISO_CODE_ESC);
+ − 1677 Dynarr_add (dst, '[');
+ − 1678 }
+ − 1679 else if (internal_p)
+ − 1680 DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
+ − 1681 else
+ − 1682 Dynarr_add (dst, ISO_CODE_CSI);
+ − 1683 Dynarr_add (dst, '0');
+ − 1684 Dynarr_add (dst, ']');
+ − 1685 if (flags)
+ − 1686 *flags &= ~ISO_STATE_R2L;
+ − 1687 }
+ − 1688 }
+ − 1689
+ − 1690 /* If FLAGS is a null pointer or specifies a direction different from
+ − 1691 DIRECTION (which should be either CHARSET_RIGHT_TO_LEFT or
+ − 1692 CHARSET_LEFT_TO_RIGHT), output the appropriate switch-dir escape
+ − 1693 sequence to DST. Also update FLAGS if it is not a null pointer.
+ − 1694 If INTERNAL_P is set, we are outputting in internal format and
+ − 1695 need to handle the CSI differently. */
+ − 1696
+ − 1697 static void
+ − 1698 ensure_correct_direction (int direction, Lisp_Object codesys,
+ − 1699 unsigned_char_dynarr *dst, unsigned int *flags,
+ − 1700 int internal_p)
+ − 1701 {
+ − 1702 if ((!flags || (*flags & ISO_STATE_R2L)) &&
+ − 1703 direction == CHARSET_LEFT_TO_RIGHT)
+ − 1704 restore_left_to_right_direction (codesys, dst, flags, internal_p);
+ − 1705 else if (!XCODING_SYSTEM_ISO2022_NO_ISO6429 (codesys)
+ − 1706 && (!flags || !(*flags & ISO_STATE_R2L)) &&
+ − 1707 direction == CHARSET_RIGHT_TO_LEFT)
+ − 1708 {
+ − 1709 if (XCODING_SYSTEM_ISO2022_SEVEN (codesys))
+ − 1710 {
+ − 1711 Dynarr_add (dst, ISO_CODE_ESC);
+ − 1712 Dynarr_add (dst, '[');
+ − 1713 }
+ − 1714 else if (internal_p)
+ − 1715 DECODE_ADD_BINARY_CHAR (ISO_CODE_CSI, dst);
+ − 1716 else
+ − 1717 Dynarr_add (dst, ISO_CODE_CSI);
+ − 1718 Dynarr_add (dst, '2');
+ − 1719 Dynarr_add (dst, ']');
+ − 1720 if (flags)
+ − 1721 *flags |= ISO_STATE_R2L;
+ − 1722 }
+ − 1723 }
+ − 1724
+ − 1725 /* Convert ISO2022-format data to internal format. */
+ − 1726
+ − 1727 static Bytecount
+ − 1728 iso2022_decode (struct coding_stream *str, const UExtbyte *src,
+ − 1729 unsigned_char_dynarr *dst, Bytecount n)
+ − 1730 {
+ − 1731 unsigned int ch = str->ch;
+ − 1732 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1733 unsigned_char_dynarr *real_dst = dst;
+ − 1734 #endif
+ − 1735 struct iso2022_coding_stream *data =
+ − 1736 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 1737 unsigned int flags = data->flags;
+ − 1738 Bytecount orign = n;
+ − 1739
+ − 1740 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1741 if (flags & ISO_STATE_COMPOSITE)
+ − 1742 dst = data->composite_chars;
+ − 1743 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 1744
+ − 1745 while (n--)
+ − 1746 {
+ − 1747 UExtbyte c = *src++;
+ − 1748 if (flags & ISO_STATE_ESCAPE)
+ − 1749 { /* Within ESC sequence */
+ − 1750 int retval = parse_iso2022_esc (str->codesys, data,
+ − 1751 c, &flags, 1);
+ − 1752
+ − 1753 if (retval)
+ − 1754 {
+ − 1755 switch (data->esc)
+ − 1756 {
+ − 1757 #ifdef ENABLE_COMPOSITE_CHARS
+ − 1758 case ISO_ESC_START_COMPOSITE:
+ − 1759 if (data->composite_chars)
+ − 1760 Dynarr_reset (data->composite_chars);
+ − 1761 else
+ − 1762 data->composite_chars = Dynarr_new (unsigned_char);
+ − 1763 dst = data->composite_chars;
+ − 1764 break;
+ − 1765 case ISO_ESC_END_COMPOSITE:
+ − 1766 {
867
+ − 1767 Ibyte comstr[MAX_ICHAR_LEN];
771
+ − 1768 Bytecount len;
867
+ − 1769 Ichar emch = lookup_composite_char (Dynarr_atp (dst, 0),
771
+ − 1770 Dynarr_length (dst));
+ − 1771 dst = real_dst;
867
+ − 1772 len = set_itext_ichar (comstr, emch);
771
+ − 1773 Dynarr_add_many (dst, comstr, len);
+ − 1774 break;
+ − 1775 }
+ − 1776 #else
+ − 1777 case ISO_ESC_START_COMPOSITE:
+ − 1778 {
867
+ − 1779 Ibyte comstr[MAX_ICHAR_LEN];
771
+ − 1780 Bytecount len;
867
+ − 1781 Ichar emch = make_ichar (Vcharset_composite, c - '0' + ' ',
771
+ − 1782 0);
867
+ − 1783 len = set_itext_ichar (comstr, emch);
771
+ − 1784 Dynarr_add_many (dst, comstr, len);
+ − 1785 break;
+ − 1786 }
+ − 1787 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 1788
+ − 1789 case ISO_ESC_LITERAL:
+ − 1790 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 1791 break;
+ − 1792
+ − 1793 default:
+ − 1794 /* Everything else handled already */
+ − 1795 break;
+ − 1796 }
+ − 1797 }
+ − 1798
+ − 1799 /* Attempted error recovery. */
+ − 1800 if (data->output_direction_sequence)
+ − 1801 ensure_correct_direction (flags & ISO_STATE_R2L ?
+ − 1802 CHARSET_RIGHT_TO_LEFT :
+ − 1803 CHARSET_LEFT_TO_RIGHT,
+ − 1804 str->codesys, dst, 0, 1);
+ − 1805 /* More error recovery. */
+ − 1806 if (!retval || data->output_literally)
+ − 1807 {
+ − 1808 /* Output the (possibly invalid) sequence */
+ − 1809 int i;
+ − 1810 for (i = 0; i < data->esc_bytes_index; i++)
+ − 1811 DECODE_ADD_BINARY_CHAR (data->esc_bytes[i], dst);
+ − 1812 flags &= ISO_STATE_LOCK;
+ − 1813 if (!retval)
+ − 1814 n++, src--;/* Repeat the loop with the same character. */
+ − 1815 else
+ − 1816 {
+ − 1817 /* No sense in reprocessing the final byte of the
+ − 1818 escape sequence; it could mess things up anyway.
+ − 1819 Just add it now. */
+ − 1820 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 1821 }
+ − 1822 }
+ − 1823 ch = 0;
+ − 1824 }
826
+ − 1825 else if (byte_c0_p (c) || byte_c1_p (c))
771
+ − 1826 { /* Control characters */
+ − 1827
+ − 1828 /***** Error-handling *****/
+ − 1829
+ − 1830 /* If we were in the middle of a character, dump out the
+ − 1831 partial character. */
+ − 1832 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1833
+ − 1834 /* If we just saw a single-shift character, dump it out.
+ − 1835 This may dump out the wrong sort of single-shift character,
+ − 1836 but least it will give an indication that something went
+ − 1837 wrong. */
+ − 1838 if (flags & ISO_STATE_SS2)
+ − 1839 {
+ − 1840 DECODE_ADD_BINARY_CHAR (ISO_CODE_SS2, dst);
+ − 1841 flags &= ~ISO_STATE_SS2;
+ − 1842 }
+ − 1843 if (flags & ISO_STATE_SS3)
+ − 1844 {
+ − 1845 DECODE_ADD_BINARY_CHAR (ISO_CODE_SS3, dst);
+ − 1846 flags &= ~ISO_STATE_SS3;
+ − 1847 }
+ − 1848
+ − 1849 /***** Now handle the control characters. *****/
+ − 1850
+ − 1851 flags &= ISO_STATE_LOCK;
+ − 1852
+ − 1853 if (!parse_iso2022_esc (str->codesys, data, c, &flags, 1))
+ − 1854 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 1855 }
+ − 1856 else
+ − 1857 { /* Graphic characters */
+ − 1858 Lisp_Object charset;
+ − 1859 int lb;
+ − 1860 int reg;
+ − 1861
+ − 1862 /* Now determine the charset. */
+ − 1863 reg = ((flags & ISO_STATE_SS2) ? 2
+ − 1864 : (flags & ISO_STATE_SS3) ? 3
826
+ − 1865 : !byte_ascii_p (c) ? data->register_right
771
+ − 1866 : data->register_left);
+ − 1867 charset = data->charset[reg];
+ − 1868
+ − 1869 /* Error checking: */
+ − 1870 if (! CHARSETP (charset)
+ − 1871 || data->invalid_designated[reg]
+ − 1872 || (((c & 0x7F) == ' ' || (c & 0x7F) == ISO_CODE_DEL)
+ − 1873 && XCHARSET_CHARS (charset) == 94))
+ − 1874 /* Mrmph. We are trying to invoke a register that has no
+ − 1875 or an invalid charset in it, or trying to add a character
+ − 1876 outside the range of the charset. Insert that char literally
+ − 1877 to preserve it for the output. */
+ − 1878 {
+ − 1879 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1880 DECODE_ADD_BINARY_CHAR (c, dst);
+ − 1881 }
+ − 1882
+ − 1883 else
+ − 1884 {
+ − 1885 /* Things are probably hunky-dorey. */
+ − 1886
+ − 1887 /* Fetch reverse charset, maybe. */
+ − 1888 if (((flags & ISO_STATE_R2L) &&
+ − 1889 XCHARSET_DIRECTION (charset) == CHARSET_LEFT_TO_RIGHT)
+ − 1890 ||
+ − 1891 (!(flags & ISO_STATE_R2L) &&
+ − 1892 XCHARSET_DIRECTION (charset) == CHARSET_RIGHT_TO_LEFT))
+ − 1893 {
+ − 1894 Lisp_Object new_charset =
+ − 1895 XCHARSET_REVERSE_DIRECTION_CHARSET (charset);
+ − 1896 if (!NILP (new_charset))
+ − 1897 charset = new_charset;
+ − 1898 }
+ − 1899
+ − 1900 lb = XCHARSET_LEADING_BYTE (charset);
+ − 1901 switch (XCHARSET_REP_BYTES (charset))
+ − 1902 {
+ − 1903 case 1: /* ASCII */
+ − 1904 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1905 Dynarr_add (dst, c & 0x7F);
+ − 1906 break;
+ − 1907
+ − 1908 case 2: /* one-byte official */
+ − 1909 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1910 Dynarr_add (dst, lb);
+ − 1911 Dynarr_add (dst, c | 0x80);
+ − 1912 break;
+ − 1913
+ − 1914 case 3: /* one-byte private or two-byte official */
+ − 1915 if (XCHARSET_PRIVATE_P (charset))
+ − 1916 {
+ − 1917 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1918 Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_1);
+ − 1919 Dynarr_add (dst, lb);
+ − 1920 Dynarr_add (dst, c | 0x80);
+ − 1921 }
+ − 1922 else
+ − 1923 {
+ − 1924 if (ch)
+ − 1925 {
+ − 1926 Dynarr_add (dst, lb);
+ − 1927 Dynarr_add (dst, ch | 0x80);
+ − 1928 Dynarr_add (dst, c | 0x80);
+ − 1929 ch = 0;
+ − 1930 }
+ − 1931 else
+ − 1932 ch = c;
+ − 1933 }
+ − 1934 break;
+ − 1935
+ − 1936 default: /* two-byte private */
+ − 1937 if (ch)
+ − 1938 {
+ − 1939 Dynarr_add (dst, PRE_LEADING_BYTE_PRIVATE_2);
+ − 1940 Dynarr_add (dst, lb);
+ − 1941 Dynarr_add (dst, ch | 0x80);
+ − 1942 Dynarr_add (dst, c | 0x80);
+ − 1943 ch = 0;
+ − 1944 }
+ − 1945 else
+ − 1946 ch = c;
+ − 1947 }
+ − 1948 }
+ − 1949
+ − 1950 if (!ch)
+ − 1951 flags &= ISO_STATE_LOCK;
+ − 1952 }
+ − 1953
+ − 1954 }
+ − 1955
+ − 1956 if (str->eof)
+ − 1957 DECODE_OUTPUT_PARTIAL_CHAR (ch, dst);
+ − 1958
+ − 1959 data->flags = flags;
+ − 1960 str->ch = ch;
+ − 1961 return orign;
+ − 1962 }
+ − 1963
+ − 1964
+ − 1965 /***** ISO2022 encoder *****/
+ − 1966
+ − 1967 /* Designate CHARSET into register REG. */
+ − 1968
+ − 1969 static void
+ − 1970 iso2022_designate (Lisp_Object charset, int reg,
+ − 1971 struct coding_stream *str, unsigned_char_dynarr *dst)
+ − 1972 {
+ − 1973 static const char inter94[] = "()*+";
+ − 1974 static const char inter96[] = ",-./";
+ − 1975 int type;
+ − 1976 unsigned char final;
+ − 1977 struct iso2022_coding_stream *data =
+ − 1978 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 1979 Lisp_Object old_charset = data->charset[reg];
+ − 1980
+ − 1981 data->charset[reg] = charset;
+ − 1982 if (!CHARSETP (charset))
+ − 1983 /* charset might be an initial nil or t. */
+ − 1984 return;
+ − 1985 type = XCHARSET_TYPE (charset);
+ − 1986 final = XCHARSET_FINAL (charset);
+ − 1987 if (!data->force_charset_on_output[reg] &&
+ − 1988 CHARSETP (old_charset) &&
+ − 1989 XCHARSET_TYPE (old_charset) == type &&
+ − 1990 XCHARSET_FINAL (old_charset) == final)
+ − 1991 return;
+ − 1992
+ − 1993 data->force_charset_on_output[reg] = 0;
+ − 1994
+ − 1995 {
+ − 1996 charset_conversion_spec_dynarr *dyn =
+ − 1997 XCODING_SYSTEM_ISO2022_OUTPUT_CONV (str->codesys);
+ − 1998
+ − 1999 if (dyn)
+ − 2000 {
+ − 2001 int i;
+ − 2002
+ − 2003 for (i = 0; i < Dynarr_length (dyn); i++)
+ − 2004 {
+ − 2005 struct charset_conversion_spec *spec = Dynarr_atp (dyn, i);
+ − 2006 if (EQ (charset, spec->from_charset))
+ − 2007 charset = spec->to_charset;
+ − 2008 }
+ − 2009 }
+ − 2010 }
+ − 2011
+ − 2012 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2013 switch (type)
+ − 2014 {
+ − 2015 case CHARSET_TYPE_94:
+ − 2016 Dynarr_add (dst, inter94[reg]);
+ − 2017 break;
+ − 2018 case CHARSET_TYPE_96:
+ − 2019 Dynarr_add (dst, inter96[reg]);
+ − 2020 break;
+ − 2021 case CHARSET_TYPE_94X94:
+ − 2022 Dynarr_add (dst, '$');
+ − 2023 if (reg != 0
+ − 2024 || !(XCODING_SYSTEM_ISO2022_SHORT (str->codesys))
+ − 2025 || final < '@'
+ − 2026 || final > 'B')
+ − 2027 Dynarr_add (dst, inter94[reg]);
+ − 2028 break;
+ − 2029 case CHARSET_TYPE_96X96:
+ − 2030 Dynarr_add (dst, '$');
+ − 2031 Dynarr_add (dst, inter96[reg]);
+ − 2032 break;
+ − 2033 }
+ − 2034 Dynarr_add (dst, final);
+ − 2035 }
+ − 2036
+ − 2037 static void
+ − 2038 ensure_normal_shift (struct coding_stream *str, unsigned_char_dynarr *dst)
+ − 2039 {
+ − 2040 struct iso2022_coding_stream *data =
+ − 2041 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 2042
+ − 2043 if (data->register_left != 0)
+ − 2044 {
+ − 2045 Dynarr_add (dst, ISO_CODE_SI);
+ − 2046 data->register_left = 0;
+ − 2047 }
+ − 2048 }
+ − 2049
+ − 2050 static void
+ − 2051 ensure_shift_out (struct coding_stream *str, unsigned_char_dynarr *dst)
+ − 2052 {
+ − 2053 struct iso2022_coding_stream *data =
+ − 2054 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 2055
+ − 2056 if (data->register_left != 1)
+ − 2057 {
+ − 2058 Dynarr_add (dst, ISO_CODE_SO);
+ − 2059 data->register_left = 1;
+ − 2060 }
+ − 2061 }
+ − 2062
+ − 2063 /* Convert internally-formatted data to ISO2022 format. */
+ − 2064
+ − 2065 static Bytecount
867
+ − 2066 iso2022_encode (struct coding_stream *str, const Ibyte *src,
771
+ − 2067 unsigned_char_dynarr *dst, Bytecount n)
+ − 2068 {
+ − 2069 unsigned char charmask;
867
+ − 2070 Ibyte c;
771
+ − 2071 unsigned char char_boundary;
+ − 2072 unsigned int ch = str->ch;
+ − 2073 Lisp_Object codesys = str->codesys;
+ − 2074 int i;
+ − 2075 Lisp_Object charset;
+ − 2076 int half;
+ − 2077 struct iso2022_coding_stream *data =
+ − 2078 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 2079 unsigned int flags = data->flags;
+ − 2080 Bytecount orign = n;
+ − 2081
+ − 2082 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2083 /* flags for handling composite chars. We do a little switcheroo
+ − 2084 on the source while we're outputting the composite char. */
+ − 2085 Bytecount saved_n = 0;
867
+ − 2086 const Ibyte *saved_src = NULL;
771
+ − 2087 int in_composite = 0;
+ − 2088 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 2089
+ − 2090 char_boundary = data->current_char_boundary;
+ − 2091 charset = data->current_charset;
+ − 2092 half = data->current_half;
+ − 2093
+ − 2094 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2095 back_to_square_n:
+ − 2096 #endif
+ − 2097 while (n--)
+ − 2098 {
+ − 2099 c = *src++;
+ − 2100
826
+ − 2101 if (byte_ascii_p (c))
771
+ − 2102 { /* Processing ASCII character */
+ − 2103 ch = 0;
+ − 2104
+ − 2105 restore_left_to_right_direction (codesys, dst, &flags, 0);
+ − 2106
+ − 2107 /* Make sure G0 contains ASCII */
+ − 2108 if ((c > ' ' && c < ISO_CODE_DEL) ||
+ − 2109 !XCODING_SYSTEM_ISO2022_NO_ASCII_CNTL (codesys))
+ − 2110 {
+ − 2111 ensure_normal_shift (str, dst);
+ − 2112 iso2022_designate (Vcharset_ascii, 0, str, dst);
+ − 2113 }
+ − 2114
+ − 2115 /* If necessary, restore everything to the default state
+ − 2116 at end-of-line */
+ − 2117 if (!(XCODING_SYSTEM_ISO2022_NO_ASCII_EOL (codesys)))
+ − 2118 {
+ − 2119 /* NOTE: CRLF encoding happens *BEFORE* other encoding.
+ − 2120 Thus, even though we're working with internal-format
+ − 2121 data, there may be CR's or CRLF sequences representing
+ − 2122 newlines. */
+ − 2123 if (c == '\r' || (c == '\n' && !(flags & ISO_STATE_CR)))
+ − 2124 {
+ − 2125 restore_left_to_right_direction (codesys, dst, &flags, 0);
+ − 2126
+ − 2127 ensure_normal_shift (str, dst);
+ − 2128
+ − 2129 for (i = 0; i < 4; i++)
+ − 2130 {
+ − 2131 Lisp_Object initial_charset =
+ − 2132 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
+ − 2133 iso2022_designate (initial_charset, i, str, dst);
+ − 2134 }
+ − 2135 }
+ − 2136 if (c == '\r')
+ − 2137 flags |= ISO_STATE_CR;
+ − 2138 else
+ − 2139 flags &= ~ISO_STATE_CR;
+ − 2140 }
+ − 2141
+ − 2142 if (XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
+ − 2143 && fit_to_be_escape_quoted (c))
+ − 2144 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2145 Dynarr_add (dst, c);
+ − 2146 char_boundary = 1;
+ − 2147 }
+ − 2148
867
+ − 2149 else if (ibyte_leading_byte_p (c) || ibyte_leading_byte_p (ch))
771
+ − 2150 { /* Processing Leading Byte */
+ − 2151 ch = 0;
826
+ − 2152 charset = charset_by_leading_byte (c);
+ − 2153 if (leading_byte_prefix_p (c))
771
+ − 2154 ch = c;
+ − 2155 else if (!EQ (charset, Vcharset_control_1)
+ − 2156 && !EQ (charset, Vcharset_composite))
+ − 2157 {
+ − 2158 int reg;
+ − 2159
+ − 2160 ensure_correct_direction (XCHARSET_DIRECTION (charset),
+ − 2161 codesys, dst, &flags, 0);
+ − 2162
+ − 2163 /* Now determine which register to use. */
+ − 2164 reg = -1;
+ − 2165 for (i = 0; i < 4; i++)
+ − 2166 {
+ − 2167 if (EQ (charset, data->charset[i]) ||
+ − 2168 EQ (charset,
+ − 2169 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i)))
+ − 2170 {
+ − 2171 reg = i;
+ − 2172 break;
+ − 2173 }
+ − 2174 }
+ − 2175
+ − 2176 if (reg == -1)
+ − 2177 {
+ − 2178 if (XCHARSET_GRAPHIC (charset) != 0)
+ − 2179 {
+ − 2180 if (!NILP (data->charset[1]) &&
+ − 2181 (!XCODING_SYSTEM_ISO2022_SEVEN (codesys) ||
+ − 2182 XCODING_SYSTEM_ISO2022_LOCK_SHIFT (codesys)))
+ − 2183 reg = 1;
+ − 2184 else if (!NILP (data->charset[2]))
+ − 2185 reg = 2;
+ − 2186 else if (!NILP (data->charset[3]))
+ − 2187 reg = 3;
+ − 2188 else
+ − 2189 reg = 0;
+ − 2190 }
+ − 2191 else
+ − 2192 reg = 0;
+ − 2193 }
+ − 2194
+ − 2195 iso2022_designate (charset, reg, str, dst);
+ − 2196
+ − 2197 /* Now invoke that register. */
+ − 2198 switch (reg)
+ − 2199 {
+ − 2200 case 0:
+ − 2201 ensure_normal_shift (str, dst);
+ − 2202 half = 0;
+ − 2203 break;
+ − 2204
+ − 2205 case 1:
+ − 2206 if (XCODING_SYSTEM_ISO2022_SEVEN (codesys))
+ − 2207 {
+ − 2208 ensure_shift_out (str, dst);
+ − 2209 half = 0;
+ − 2210 }
+ − 2211 else
+ − 2212 half = 1;
+ − 2213 break;
+ − 2214
+ − 2215 case 2:
+ − 2216 if (XCODING_SYSTEM_ISO2022_SEVEN (str->codesys))
+ − 2217 {
+ − 2218 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2219 Dynarr_add (dst, 'N');
+ − 2220 half = 0;
+ − 2221 }
+ − 2222 else
+ − 2223 {
+ − 2224 Dynarr_add (dst, ISO_CODE_SS2);
+ − 2225 half = 1;
+ − 2226 }
+ − 2227 break;
+ − 2228
+ − 2229 case 3:
+ − 2230 if (XCODING_SYSTEM_ISO2022_SEVEN (str->codesys))
+ − 2231 {
+ − 2232 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2233 Dynarr_add (dst, 'O');
+ − 2234 half = 0;
+ − 2235 }
+ − 2236 else
+ − 2237 {
+ − 2238 Dynarr_add (dst, ISO_CODE_SS3);
+ − 2239 half = 1;
+ − 2240 }
+ − 2241 break;
+ − 2242
+ − 2243 default:
+ − 2244 abort ();
+ − 2245 }
+ − 2246 }
+ − 2247 char_boundary = 0;
+ − 2248 }
+ − 2249 else
+ − 2250 { /* Processing Non-ASCII character */
+ − 2251 charmask = (half == 0 ? 0x7F : 0xFF);
+ − 2252 char_boundary = 1;
+ − 2253 if (EQ (charset, Vcharset_control_1))
+ − 2254 {
+ − 2255 if (XCODING_SYSTEM_ISO2022_ESCAPE_QUOTED (codesys)
+ − 2256 && fit_to_be_escape_quoted (c))
+ − 2257 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2258 /* you asked for it ... */
+ − 2259 Dynarr_add (dst, c - 0x20);
+ − 2260 }
+ − 2261 #ifndef ENABLE_COMPOSITE_CHARS
+ − 2262 else if (EQ (charset, Vcharset_composite))
+ − 2263 {
+ − 2264 if (c >= 160 || c <= 164) /* Someone might have stuck in
+ − 2265 something else */
+ − 2266 {
+ − 2267 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2268 Dynarr_add (dst, c - 160 + '0');
+ − 2269 }
+ − 2270 }
+ − 2271 #endif
+ − 2272 else
+ − 2273 {
+ − 2274 switch (XCHARSET_REP_BYTES (charset))
+ − 2275 {
+ − 2276 case 2:
+ − 2277 Dynarr_add (dst, c & charmask);
+ − 2278 break;
+ − 2279 case 3:
+ − 2280 if (XCHARSET_PRIVATE_P (charset))
+ − 2281 {
+ − 2282 Dynarr_add (dst, c & charmask);
+ − 2283 ch = 0;
+ − 2284 }
+ − 2285 else if (ch)
+ − 2286 {
+ − 2287 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2288 if (EQ (charset, Vcharset_composite))
+ − 2289 {
+ − 2290 if (in_composite)
+ − 2291 {
+ − 2292 /* #### Bother! We don't know how to
+ − 2293 handle this yet. */
+ − 2294 Dynarr_add (dst, '~');
+ − 2295 }
+ − 2296 else
+ − 2297 {
867
+ − 2298 Ichar emch = make_ichar (Vcharset_composite,
771
+ − 2299 ch & 0x7F, c & 0x7F);
+ − 2300 Lisp_Object lstr = composite_char_string (emch);
+ − 2301 saved_n = n;
+ − 2302 saved_src = src;
+ − 2303 in_composite = 1;
+ − 2304 src = XSTRING_DATA (lstr);
+ − 2305 n = XSTRING_LENGTH (lstr);
+ − 2306 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2307 Dynarr_add (dst, '0'); /* start composing */
+ − 2308 }
+ − 2309 }
+ − 2310 else
+ − 2311 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 2312 {
+ − 2313 Dynarr_add (dst, ch & charmask);
+ − 2314 Dynarr_add (dst, c & charmask);
+ − 2315 }
+ − 2316 ch = 0;
+ − 2317 }
+ − 2318 else
+ − 2319 {
+ − 2320 ch = c;
+ − 2321 char_boundary = 0;
+ − 2322 }
+ − 2323 break;
+ − 2324 case 4:
+ − 2325 if (ch)
+ − 2326 {
+ − 2327 Dynarr_add (dst, ch & charmask);
+ − 2328 Dynarr_add (dst, c & charmask);
+ − 2329 ch = 0;
+ − 2330 }
+ − 2331 else
+ − 2332 {
+ − 2333 ch = c;
+ − 2334 char_boundary = 0;
+ − 2335 }
+ − 2336 break;
+ − 2337 default:
+ − 2338 abort ();
+ − 2339 }
+ − 2340 }
+ − 2341 }
+ − 2342 }
+ − 2343
+ − 2344 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2345 if (in_composite)
+ − 2346 {
+ − 2347 n = saved_n;
+ − 2348 src = saved_src;
+ − 2349 in_composite = 0;
+ − 2350 Dynarr_add (dst, ISO_CODE_ESC);
+ − 2351 Dynarr_add (dst, '1'); /* end composing */
+ − 2352 goto back_to_square_n; /* Wheeeeeeeee ..... */
+ − 2353 }
+ − 2354 #endif /* ENABLE_COMPOSITE_CHARS */
+ − 2355
+ − 2356 if (char_boundary && str->eof)
+ − 2357 {
+ − 2358 restore_left_to_right_direction (codesys, dst, &flags, 0);
+ − 2359 ensure_normal_shift (str, dst);
+ − 2360 for (i = 0; i < 4; i++)
+ − 2361 {
+ − 2362 Lisp_Object initial_charset =
+ − 2363 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i);
+ − 2364 iso2022_designate (initial_charset, i, str, dst);
+ − 2365 }
+ − 2366 }
+ − 2367
+ − 2368 data->flags = flags;
+ − 2369 str->ch = ch;
+ − 2370 data->current_char_boundary = char_boundary;
+ − 2371 data->current_charset = charset;
+ − 2372 data->current_half = half;
+ − 2373
+ − 2374 /* Verbum caro factum est! */
+ − 2375 return orign;
+ − 2376 }
+ − 2377
+ − 2378 static Bytecount
+ − 2379 iso2022_convert (struct coding_stream *str,
+ − 2380 const UExtbyte *src,
+ − 2381 unsigned_char_dynarr *dst, Bytecount n)
+ − 2382 {
+ − 2383 if (str->direction == CODING_DECODE)
+ − 2384 return iso2022_decode (str, src, dst, n);
+ − 2385 else
+ − 2386 return iso2022_encode (str, src, dst, n);
+ − 2387 }
+ − 2388
+ − 2389 static void
+ − 2390 iso2022_mark (Lisp_Object codesys)
+ − 2391 {
+ − 2392 int i;
+ − 2393
+ − 2394 for (i = 0; i < 4; i++)
+ − 2395 mark_object (XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i));
+ − 2396 if (XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys))
+ − 2397 {
+ − 2398 for (i = 0;
+ − 2399 i < Dynarr_length (XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys));
+ − 2400 i++)
+ − 2401 {
+ − 2402 struct charset_conversion_spec *ccs =
+ − 2403 Dynarr_atp (XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys), i);
+ − 2404 mark_object (ccs->from_charset);
+ − 2405 mark_object (ccs->to_charset);
+ − 2406 }
+ − 2407 }
+ − 2408 if (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (codesys))
+ − 2409 {
+ − 2410 for (i = 0;
+ − 2411 i < Dynarr_length (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (codesys));
+ − 2412 i++)
+ − 2413 {
+ − 2414 struct charset_conversion_spec *ccs =
+ − 2415 Dynarr_atp (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (codesys), i);
+ − 2416 mark_object (ccs->from_charset);
+ − 2417 mark_object (ccs->to_charset);
+ − 2418 }
+ − 2419 }
+ − 2420 }
+ − 2421
+ − 2422 static void
+ − 2423 iso2022_finalize (Lisp_Object cs)
+ − 2424 {
+ − 2425 if (XCODING_SYSTEM_ISO2022_INPUT_CONV (cs))
+ − 2426 {
+ − 2427 Dynarr_free (XCODING_SYSTEM_ISO2022_INPUT_CONV (cs));
+ − 2428 XCODING_SYSTEM_ISO2022_INPUT_CONV (cs) = 0;
+ − 2429 }
+ − 2430 if (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (cs))
+ − 2431 {
+ − 2432 Dynarr_free (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (cs));
+ − 2433 XCODING_SYSTEM_ISO2022_OUTPUT_CONV (cs) = 0;
+ − 2434 }
+ − 2435 }
+ − 2436
+ − 2437 /* Given a list of charset conversion specs as specified in a Lisp
+ − 2438 program, parse it into STORE_HERE. */
+ − 2439
+ − 2440 static void
+ − 2441 parse_charset_conversion_specs (charset_conversion_spec_dynarr *store_here,
+ − 2442 Lisp_Object spec_list)
+ − 2443 {
2367
+ − 2444 EXTERNAL_LIST_LOOP_2 (car, spec_list)
771
+ − 2445 {
+ − 2446 Lisp_Object from, to;
+ − 2447 struct charset_conversion_spec spec;
+ − 2448
+ − 2449 if (!CONSP (car) || !CONSP (XCDR (car)) || !NILP (XCDR (XCDR (car))))
+ − 2450 invalid_argument ("Invalid charset conversion spec", car);
+ − 2451 from = Fget_charset (XCAR (car));
+ − 2452 to = Fget_charset (XCAR (XCDR (car)));
+ − 2453 if (XCHARSET_TYPE (from) != XCHARSET_TYPE (to))
+ − 2454 invalid_operation_2
+ − 2455 ("Attempted conversion between different charset types",
+ − 2456 from, to);
+ − 2457 spec.from_charset = from;
+ − 2458 spec.to_charset = to;
+ − 2459
+ − 2460 Dynarr_add (store_here, spec);
+ − 2461 }
+ − 2462 }
+ − 2463
+ − 2464 /* Given a dynarr LOAD_HERE of internally-stored charset conversion
+ − 2465 specs, return the equivalent as the Lisp programmer would see it.
+ − 2466
+ − 2467 If LOAD_HERE is 0, return Qnil. */
+ − 2468
+ − 2469 static Lisp_Object
+ − 2470 unparse_charset_conversion_specs (charset_conversion_spec_dynarr *load_here,
+ − 2471 int names)
+ − 2472 {
+ − 2473 int i;
+ − 2474 Lisp_Object result;
+ − 2475
+ − 2476 if (!load_here)
+ − 2477 return Qnil;
+ − 2478 for (i = 0, result = Qnil; i < Dynarr_length (load_here); i++)
+ − 2479 {
+ − 2480 struct charset_conversion_spec *ccs = Dynarr_atp (load_here, i);
+ − 2481 if (names)
+ − 2482 result = Fcons (list2 (XCHARSET_NAME (ccs->from_charset),
+ − 2483 XCHARSET_NAME (ccs->to_charset)), result);
+ − 2484 else
+ − 2485 result = Fcons (list2 (ccs->from_charset, ccs->to_charset), result);
+ − 2486 }
+ − 2487
+ − 2488 return Fnreverse (result);
+ − 2489 }
+ − 2490
+ − 2491 static int
+ − 2492 iso2022_putprop (Lisp_Object codesys,
+ − 2493 Lisp_Object key,
+ − 2494 Lisp_Object value)
+ − 2495 {
+ − 2496 #define FROB_INITIAL_CHARSET(charset_num) \
+ − 2497 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, charset_num) = \
+ − 2498 ((EQ (value, Qt) || EQ (value, Qnil)) ? value : Fget_charset (value))
+ − 2499
+ − 2500 if (EQ (key, Qcharset_g0)) FROB_INITIAL_CHARSET (0);
+ − 2501 else if (EQ (key, Qcharset_g1)) FROB_INITIAL_CHARSET (1);
+ − 2502 else if (EQ (key, Qcharset_g2)) FROB_INITIAL_CHARSET (2);
+ − 2503 else if (EQ (key, Qcharset_g3)) FROB_INITIAL_CHARSET (3);
+ − 2504
+ − 2505 #define FROB_FORCE_CHARSET(charset_num) \
+ − 2506 XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (codesys, charset_num) = \
+ − 2507 !NILP (value)
+ − 2508
+ − 2509 else if (EQ (key, Qforce_g0_on_output)) FROB_FORCE_CHARSET (0);
+ − 2510 else if (EQ (key, Qforce_g1_on_output)) FROB_FORCE_CHARSET (1);
+ − 2511 else if (EQ (key, Qforce_g2_on_output)) FROB_FORCE_CHARSET (2);
+ − 2512 else if (EQ (key, Qforce_g3_on_output)) FROB_FORCE_CHARSET (3);
+ − 2513
+ − 2514 #define FROB_BOOLEAN_PROPERTY(prop) \
+ − 2515 XCODING_SYSTEM_ISO2022_##prop (codesys) = !NILP (value)
+ − 2516
+ − 2517 else if (EQ (key, Qshort)) FROB_BOOLEAN_PROPERTY (SHORT);
+ − 2518 else if (EQ (key, Qno_ascii_eol)) FROB_BOOLEAN_PROPERTY (NO_ASCII_EOL);
+ − 2519 else if (EQ (key, Qno_ascii_cntl)) FROB_BOOLEAN_PROPERTY (NO_ASCII_CNTL);
+ − 2520 else if (EQ (key, Qseven)) FROB_BOOLEAN_PROPERTY (SEVEN);
+ − 2521 else if (EQ (key, Qlock_shift)) FROB_BOOLEAN_PROPERTY (LOCK_SHIFT);
+ − 2522 else if (EQ (key, Qno_iso6429)) FROB_BOOLEAN_PROPERTY (NO_ISO6429);
+ − 2523 else if (EQ (key, Qescape_quoted)) FROB_BOOLEAN_PROPERTY (ESCAPE_QUOTED);
+ − 2524
+ − 2525 else if (EQ (key, Qinput_charset_conversion))
+ − 2526 {
+ − 2527 XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys) =
+ − 2528 Dynarr_new (charset_conversion_spec);
+ − 2529 parse_charset_conversion_specs
+ − 2530 (XCODING_SYSTEM_ISO2022_INPUT_CONV (codesys), value);
+ − 2531 }
+ − 2532 else if (EQ (key, Qoutput_charset_conversion))
+ − 2533 {
+ − 2534 XCODING_SYSTEM_ISO2022_OUTPUT_CONV (codesys) =
+ − 2535 Dynarr_new (charset_conversion_spec);
+ − 2536 parse_charset_conversion_specs
+ − 2537 (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (codesys), value);
+ − 2538 }
+ − 2539 else
+ − 2540 return 0;
+ − 2541
+ − 2542 return 1;
+ − 2543 }
+ − 2544
+ − 2545 static void
2286
+ − 2546 iso2022_finalize_coding_stream (
+ − 2547 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2548 struct coding_stream *str
+ − 2549 #else
+ − 2550 struct coding_stream *UNUSED (str)
+ − 2551 #endif
+ − 2552 )
771
+ − 2553 {
+ − 2554 #ifdef ENABLE_COMPOSITE_CHARS
+ − 2555 struct iso2022_coding_stream *data =
+ − 2556 CODING_STREAM_TYPE_DATA (str, iso2022);
+ − 2557
+ − 2558 if (data->composite_chars)
+ − 2559 Dynarr_free (data->composite_chars);
+ − 2560 #endif
+ − 2561 }
+ − 2562
+ − 2563 static void
+ − 2564 iso2022_init (Lisp_Object codesys)
+ − 2565 {
+ − 2566 int i;
+ − 2567 for (i = 0; i < 4; i++)
+ − 2568 XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i) = Qnil;
+ − 2569 }
+ − 2570
+ − 2571 static Lisp_Object
+ − 2572 coding_system_charset (Lisp_Object coding_system, int gnum)
+ − 2573 {
+ − 2574 Lisp_Object cs
+ − 2575 = XCODING_SYSTEM_ISO2022_INITIAL_CHARSET (coding_system, gnum);
+ − 2576
+ − 2577 return CHARSETP (cs) ? XCHARSET_NAME (cs) : Qnil;
+ − 2578 }
+ − 2579
+ − 2580 static Lisp_Object
+ − 2581 iso2022_getprop (Lisp_Object coding_system, Lisp_Object prop)
+ − 2582 {
+ − 2583 if (EQ (prop, Qcharset_g0))
+ − 2584 return coding_system_charset (coding_system, 0);
+ − 2585 else if (EQ (prop, Qcharset_g1))
+ − 2586 return coding_system_charset (coding_system, 1);
+ − 2587 else if (EQ (prop, Qcharset_g2))
+ − 2588 return coding_system_charset (coding_system, 2);
+ − 2589 else if (EQ (prop, Qcharset_g3))
+ − 2590 return coding_system_charset (coding_system, 3);
+ − 2591
+ − 2592 #define FORCE_CHARSET(charset_num) \
+ − 2593 (XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT \
+ − 2594 (coding_system, charset_num) ? Qt : Qnil)
+ − 2595
+ − 2596 else if (EQ (prop, Qforce_g0_on_output))
+ − 2597 return FORCE_CHARSET (0);
+ − 2598 else if (EQ (prop, Qforce_g1_on_output))
+ − 2599 return FORCE_CHARSET (1);
+ − 2600 else if (EQ (prop, Qforce_g2_on_output))
+ − 2601 return FORCE_CHARSET (2);
+ − 2602 else if (EQ (prop, Qforce_g3_on_output))
+ − 2603 return FORCE_CHARSET (3);
+ − 2604
+ − 2605 #define LISP_BOOLEAN(prop) \
+ − 2606 (XCODING_SYSTEM_ISO2022_##prop (coding_system) ? Qt : Qnil)
+ − 2607
+ − 2608 else if (EQ (prop, Qshort)) return LISP_BOOLEAN (SHORT);
+ − 2609 else if (EQ (prop, Qno_ascii_eol)) return LISP_BOOLEAN (NO_ASCII_EOL);
+ − 2610 else if (EQ (prop, Qno_ascii_cntl)) return LISP_BOOLEAN (NO_ASCII_CNTL);
+ − 2611 else if (EQ (prop, Qseven)) return LISP_BOOLEAN (SEVEN);
+ − 2612 else if (EQ (prop, Qlock_shift)) return LISP_BOOLEAN (LOCK_SHIFT);
+ − 2613 else if (EQ (prop, Qno_iso6429)) return LISP_BOOLEAN (NO_ISO6429);
+ − 2614 else if (EQ (prop, Qescape_quoted)) return LISP_BOOLEAN (ESCAPE_QUOTED);
+ − 2615
+ − 2616 else if (EQ (prop, Qinput_charset_conversion))
+ − 2617 return
+ − 2618 unparse_charset_conversion_specs
+ − 2619 (XCODING_SYSTEM_ISO2022_INPUT_CONV (coding_system), 0);
+ − 2620 else if (EQ (prop, Qoutput_charset_conversion))
+ − 2621 return
+ − 2622 unparse_charset_conversion_specs
+ − 2623 (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (coding_system), 0);
+ − 2624 else
+ − 2625 return Qunbound;
+ − 2626 }
+ − 2627
+ − 2628 static void
2286
+ − 2629 iso2022_print (Lisp_Object cs, Lisp_Object printcharfun,
+ − 2630 int UNUSED (escapeflag))
771
+ − 2631 {
+ − 2632 int i;
+ − 2633
826
+ − 2634 write_c_string (printcharfun, "(");
771
+ − 2635 for (i = 0; i < 4; i++)
+ − 2636 {
+ − 2637 Lisp_Object charset = coding_system_charset (cs, i);
+ − 2638 if (i > 0)
826
+ − 2639 write_c_string (printcharfun, ", ");
771
+ − 2640 write_fmt_string (printcharfun, "g%d=", i);
800
+ − 2641 print_internal (CHARSETP (charset) ? XCHARSET_NAME (charset) : charset, printcharfun, 0);
771
+ − 2642 if (XCODING_SYSTEM_ISO2022_FORCE_CHARSET_ON_OUTPUT (cs, i))
826
+ − 2643 write_c_string (printcharfun, "(force)");
771
+ − 2644 }
+ − 2645
800
+ − 2646 #define FROB(prop) \
+ − 2647 if (!NILP (iso2022_getprop (cs, prop))) \
+ − 2648 { \
+ − 2649 write_fmt_string (printcharfun, ", %s", prop); \
771
+ − 2650 }
+ − 2651
+ − 2652 FROB (Qshort);
+ − 2653 FROB (Qno_ascii_eol);
+ − 2654 FROB (Qno_ascii_cntl);
+ − 2655 FROB (Qseven);
+ − 2656 FROB (Qlock_shift);
+ − 2657 FROB (Qno_iso6429);
+ − 2658 FROB (Qescape_quoted);
+ − 2659
+ − 2660 {
+ − 2661 Lisp_Object val =
+ − 2662 unparse_charset_conversion_specs
+ − 2663 (XCODING_SYSTEM_ISO2022_INPUT_CONV (cs), 1);
+ − 2664 if (!NILP (val))
+ − 2665 {
800
+ − 2666 write_fmt_string_lisp (printcharfun, ", input-charset-conversion=%s", 1, val);
771
+ − 2667 }
+ − 2668 val =
+ − 2669 unparse_charset_conversion_specs
+ − 2670 (XCODING_SYSTEM_ISO2022_OUTPUT_CONV (cs), 1);
+ − 2671 if (!NILP (val))
+ − 2672 {
800
+ − 2673 write_fmt_string_lisp (printcharfun, ", output-charset-conversion=%s", 1, val);
771
+ − 2674 }
826
+ − 2675 write_c_string (printcharfun, ")");
771
+ − 2676 }
+ − 2677 }
+ − 2678
+ − 2679
+ − 2680 /************************************************************************/
+ − 2681 /* ISO2022 detector */
+ − 2682 /************************************************************************/
+ − 2683
+ − 2684 DEFINE_DETECTOR (iso2022);
+ − 2685 /* ISO2022 system using only seven-bit bytes, no locking shift */
+ − 2686 DEFINE_DETECTOR_CATEGORY (iso2022, iso_7);
+ − 2687 /* ISO2022 system using eight-bit bytes, no locking shift, no single shift,
+ − 2688 using designation to switch charsets */
+ − 2689 DEFINE_DETECTOR_CATEGORY (iso2022, iso_8_designate);
+ − 2690 /* ISO2022 system using eight-bit bytes, no locking shift, no designation
+ − 2691 sequences, one-dimension characters in the upper half. */
+ − 2692 DEFINE_DETECTOR_CATEGORY (iso2022, iso_8_1);
+ − 2693 /* ISO2022 system using eight-bit bytes, no locking shift, no designation
+ − 2694 sequences, two-dimension characters in the upper half. */
+ − 2695 DEFINE_DETECTOR_CATEGORY (iso2022, iso_8_2);
+ − 2696 /* ISO2022 system using locking shift */
+ − 2697 DEFINE_DETECTOR_CATEGORY (iso2022, iso_lock_shift);
+ − 2698
+ − 2699 struct iso2022_detector
+ − 2700 {
+ − 2701 int initted;
+ − 2702 struct iso2022_coding_stream *iso;
+ − 2703 unsigned int flags;
+ − 2704
+ − 2705 /* for keeping temporary track of high-byte groups */
+ − 2706 int high_byte_count;
+ − 2707 unsigned int saw_single_shift_just_now:1;
+ − 2708
+ − 2709 /* running state; we set the likelihoods at the end */
+ − 2710 unsigned int seen_high_byte:1;
+ − 2711 unsigned int seen_single_shift:1;
+ − 2712 unsigned int seen_locking_shift:1;
+ − 2713 unsigned int seen_designate:1;
+ − 2714 unsigned int bad_single_byte_sequences;
+ − 2715 unsigned int bad_multibyte_escape_sequences;
+ − 2716 unsigned int good_multibyte_escape_sequences;
+ − 2717 int even_high_byte_groups;
985
+ − 2718 int longest_even_high_byte;
771
+ − 2719 int odd_high_byte_groups;
+ − 2720 };
+ − 2721
+ − 2722 static void
+ − 2723 iso2022_detect (struct detection_state *st, const UExtbyte *src,
+ − 2724 Bytecount n)
+ − 2725 {
+ − 2726 Bytecount orign = n;
+ − 2727 struct iso2022_detector *data = DETECTION_STATE_DATA (st, iso2022);
+ − 2728
+ − 2729 /* #### There are serious deficiencies in the recognition mechanism
+ − 2730 here. This needs to be much smarter if it's going to cut it.
+ − 2731 The sequence "\xff\x0f" is currently detected as LOCK_SHIFT while
+ − 2732 it should be detected as Latin-1.
+ − 2733 All the ISO2022 stuff in this file should be synced up with the
+ − 2734 code from FSF Emacs-21.0, in which Mule should be more or less stable.
+ − 2735 Perhaps we should wait till R2L works in FSF Emacs? */
+ − 2736
+ − 2737 /* We keep track of running state on our own, and set the categories at the
+ − 2738 end; that way we can reflect the correct state each time we finish, but
+ − 2739 not get confused by those results the next time around. */
+ − 2740
+ − 2741 if (!data->initted)
+ − 2742 {
+ − 2743 xzero (*data);
+ − 2744 data->iso = xnew_and_zero (struct iso2022_coding_stream);
+ − 2745 reset_iso2022_decode (Qnil, data->iso);
+ − 2746 data->initted = 1;
+ − 2747 }
+ − 2748
+ − 2749 while (n--)
+ − 2750 {
+ − 2751 UExtbyte c = *src++;
+ − 2752 if (c >= 0x80)
+ − 2753 data->seen_high_byte = 1;
+ − 2754 if (c >= 0xA0)
+ − 2755 data->high_byte_count++;
+ − 2756 else
+ − 2757 {
+ − 2758 if (data->high_byte_count &&
+ − 2759 !data->saw_single_shift_just_now)
+ − 2760 {
+ − 2761 if (data->high_byte_count & 1)
+ − 2762 data->odd_high_byte_groups++;
+ − 2763 else
985
+ − 2764 {
+ − 2765 data->even_high_byte_groups++;
+ − 2766 if (data->longest_even_high_byte < data->high_byte_count)
+ − 2767 data->longest_even_high_byte = data->high_byte_count;
+ − 2768 }
771
+ − 2769 }
+ − 2770 data->high_byte_count = 0;
+ − 2771 data->saw_single_shift_just_now = 0;
+ − 2772 }
+ − 2773 if (!(data->flags & ISO_STATE_ESCAPE)
826
+ − 2774 && (byte_c0_p (c) || byte_c1_p (c)))
771
+ − 2775 { /* control chars */
+ − 2776 switch (c)
+ − 2777 {
+ − 2778 /* Allow and ignore control characters that you might
+ − 2779 reasonably see in a text file */
+ − 2780 case '\r':
+ − 2781 case '\n':
+ − 2782 case '\t':
+ − 2783 case 7: /* bell */
+ − 2784 case 8: /* backspace */
+ − 2785 case 11: /* vertical tab */
+ − 2786 case 12: /* form feed */
+ − 2787 case 26: /* MS-DOS C-z junk */
+ − 2788 case 31: /* '^_' -- for info */
+ − 2789 goto label_continue_loop;
+ − 2790
+ − 2791 default:
+ − 2792 break;
+ − 2793 }
+ − 2794 }
+ − 2795
826
+ − 2796 if ((data->flags & ISO_STATE_ESCAPE) || byte_c0_p (c)
+ − 2797 || byte_c1_p (c))
771
+ − 2798 {
+ − 2799 switch (parse_iso2022_esc (Qnil, data->iso, c,
+ − 2800 &data->flags, 0))
+ − 2801 {
+ − 2802 case 1: /* done */
+ − 2803 if (data->iso->esc_bytes_index > 0)
+ − 2804 data->good_multibyte_escape_sequences++;
+ − 2805 switch (data->iso->esc)
+ − 2806 {
+ − 2807 case ISO_ESC_DESIGNATE:
+ − 2808 data->seen_designate = 1;
+ − 2809 break;
+ − 2810 case ISO_ESC_LOCKING_SHIFT:
+ − 2811 data->seen_locking_shift = 1;
+ − 2812 break;
+ − 2813 case ISO_ESC_SINGLE_SHIFT:
+ − 2814 data->saw_single_shift_just_now = 1;
+ − 2815 data->seen_single_shift = 1;
+ − 2816 break;
+ − 2817 default:
+ − 2818 break;
+ − 2819 }
+ − 2820 break;
+ − 2821
+ − 2822 case -1: /* not done */
+ − 2823 break;
+ − 2824
+ − 2825 case 0: /* error */
+ − 2826 if (data->iso->esc == ISO_ESC_NOTHING)
+ − 2827 data->bad_single_byte_sequences++;
+ − 2828 else
+ − 2829 data->bad_multibyte_escape_sequences++;
+ − 2830 }
+ − 2831 }
+ − 2832 label_continue_loop:;
+ − 2833 }
+ − 2834
985
+ − 2835 if (data->high_byte_count &&
+ − 2836 !data->saw_single_shift_just_now)
+ − 2837 {
+ − 2838 if (data->high_byte_count & 1)
+ − 2839 data->odd_high_byte_groups++;
+ − 2840 else
+ − 2841 {
+ − 2842 data->even_high_byte_groups++;
+ − 2843 if (data->longest_even_high_byte < data->high_byte_count)
+ − 2844 data->longest_even_high_byte = data->high_byte_count;
+ − 2845 }
+ − 2846 }
+ − 2847
771
+ − 2848 if (data->bad_multibyte_escape_sequences > 2 ||
+ − 2849 (data->bad_multibyte_escape_sequences > 0 &&
+ − 2850 data->good_multibyte_escape_sequences /
+ − 2851 data->bad_multibyte_escape_sequences < 10))
+ − 2852 /* Just making it up ... */
+ − 2853 SET_DET_RESULTS (st, iso2022, DET_NEARLY_IMPOSSIBLE);
+ − 2854 else if (data->bad_single_byte_sequences > 5 ||
+ − 2855 (data->bad_single_byte_sequences > 0 &&
+ − 2856 (data->good_multibyte_escape_sequences +
+ − 2857 data->even_high_byte_groups +
+ − 2858 data->odd_high_byte_groups) /
+ − 2859 data->bad_single_byte_sequences < 10))
+ − 2860 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2861 else if (data->seen_locking_shift)
+ − 2862 {
+ − 2863 SET_DET_RESULTS (st, iso2022, DET_QUITE_IMPROBABLE);
+ − 2864 DET_RESULT (st, iso_lock_shift) = DET_QUITE_PROBABLE;
+ − 2865 }
+ − 2866 else if (!data->seen_high_byte)
+ − 2867 {
+ − 2868 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2869 if (data->good_multibyte_escape_sequences)
+ − 2870 DET_RESULT (st, iso_7) = DET_QUITE_PROBABLE;
+ − 2871 else if (data->seen_single_shift)
+ − 2872 DET_RESULT (st, iso_7) = DET_SOMEWHAT_LIKELY;
+ − 2873 else
+ − 2874 {
+ − 2875 /* If we've just seen pure 7-bit data, no escape sequences,
+ − 2876 then we can't give much likelihood; but if we've seen enough
+ − 2877 of this data, we can assume some unlikelihood of any 8-bit
+ − 2878 encoding */
+ − 2879 if (orign + st->bytes_seen >= 1000)
+ − 2880 DET_RESULT (st, iso_7) = DET_AS_LIKELY_AS_UNLIKELY;
+ − 2881 else
+ − 2882 SET_DET_RESULTS (st, iso2022, DET_AS_LIKELY_AS_UNLIKELY);
+ − 2883 }
+ − 2884 }
+ − 2885 else if (data->seen_designate)
+ − 2886 {
+ − 2887 SET_DET_RESULTS (st, iso2022, DET_QUITE_IMPROBABLE);
+ − 2888 if (data->seen_single_shift)
+ − 2889 /* #### Does this really make sense? */
+ − 2890 DET_RESULT (st, iso_8_designate) = DET_SOMEWHAT_UNLIKELY;
+ − 2891 else
+ − 2892 DET_RESULT (st, iso_8_designate) = DET_QUITE_PROBABLE;
+ − 2893 }
+ − 2894 else if (data->odd_high_byte_groups > 0 &&
+ − 2895 data->even_high_byte_groups == 0)
+ − 2896 {
+ − 2897 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2898 if (data->seen_single_shift)
+ − 2899 DET_RESULT (st, iso_8_1) = DET_QUITE_PROBABLE;
+ − 2900 else
+ − 2901 DET_RESULT (st, iso_8_1) = DET_SOMEWHAT_LIKELY;
+ − 2902 }
+ − 2903 else if (data->odd_high_byte_groups == 0 &&
+ − 2904 data->even_high_byte_groups > 0)
+ − 2905 {
985
+ − 2906 #if 0
771
+ − 2907 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2908 if (data->even_high_byte_groups > 10)
+ − 2909 {
+ − 2910 if (data->seen_single_shift)
+ − 2911 DET_RESULT (st, iso_8_2) = DET_QUITE_PROBABLE;
+ − 2912 else
+ − 2913 DET_RESULT (st, iso_8_2) = DET_SOMEWHAT_LIKELY;
+ − 2914 if (data->even_high_byte_groups < 50)
+ − 2915 DET_RESULT (st, iso_8_1) = DET_SOMEWHAT_UNLIKELY;
+ − 2916 /* else it stays at quite improbable */
+ − 2917 }
985
+ − 2918 #else
+ − 2919 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2920 if (data->seen_single_shift)
+ − 2921 DET_RESULT (st, iso_8_2) = DET_QUITE_PROBABLE;
+ − 2922 else if (data->even_high_byte_groups > 10)
+ − 2923 DET_RESULT (st, iso_8_2) = DET_SOMEWHAT_LIKELY;
+ − 2924 else if (data->longest_even_high_byte > 6)
+ − 2925 DET_RESULT (st, iso_8_2) = DET_SLIGHTLY_LIKELY;
+ − 2926 #endif
771
+ − 2927 }
+ − 2928 else if (data->odd_high_byte_groups > 0 &&
+ − 2929 data->even_high_byte_groups > 0)
+ − 2930 SET_DET_RESULTS (st, iso2022, DET_SOMEWHAT_UNLIKELY);
+ − 2931 else
+ − 2932 SET_DET_RESULTS (st, iso2022, DET_AS_LIKELY_AS_UNLIKELY);
+ − 2933 }
+ − 2934
+ − 2935 static void
+ − 2936 iso2022_finalize_detection_state (struct detection_state *st)
+ − 2937 {
+ − 2938 struct iso2022_detector *data = DETECTION_STATE_DATA (st, iso2022);
+ − 2939 if (data->iso)
1726
+ − 2940 xfree (data->iso, struct iso2022_coding_stream *);
771
+ − 2941 }
+ − 2942
+ − 2943
+ − 2944 /************************************************************************/
+ − 2945 /* CCL methods */
+ − 2946 /************************************************************************/
+ − 2947
+ − 2948 /* Converter written in CCL. */
+ − 2949
+ − 2950 struct ccl_coding_system
+ − 2951 {
+ − 2952 /* For a CCL coding system, these specify the CCL programs used for
+ − 2953 decoding (input) and encoding (output). */
+ − 2954 Lisp_Object decode;
+ − 2955 Lisp_Object encode;
+ − 2956 };
+ − 2957
+ − 2958 #define CODING_SYSTEM_CCL_DECODE(codesys) \
+ − 2959 (CODING_SYSTEM_TYPE_DATA (codesys, ccl)->decode)
+ − 2960 #define CODING_SYSTEM_CCL_ENCODE(codesys) \
+ − 2961 (CODING_SYSTEM_TYPE_DATA (codesys, ccl)->encode)
+ − 2962 #define XCODING_SYSTEM_CCL_DECODE(codesys) \
+ − 2963 CODING_SYSTEM_CCL_DECODE (XCODING_SYSTEM (codesys))
+ − 2964 #define XCODING_SYSTEM_CCL_ENCODE(codesys) \
+ − 2965 CODING_SYSTEM_CCL_ENCODE (XCODING_SYSTEM (codesys))
+ − 2966
+ − 2967 struct ccl_coding_stream
+ − 2968 {
+ − 2969 /* state of the running CCL program */
+ − 2970 struct ccl_program ccl;
+ − 2971 };
+ − 2972
1204
+ − 2973 static const struct memory_description ccl_coding_system_description[] = {
+ − 2974 { XD_LISP_OBJECT, offsetof (struct ccl_coding_system, decode) },
+ − 2975 { XD_LISP_OBJECT, offsetof (struct ccl_coding_system, encode) },
771
+ − 2976 { XD_END }
+ − 2977 };
+ − 2978
1204
+ − 2979 DEFINE_CODING_SYSTEM_TYPE_WITH_DATA (ccl);
+ − 2980
771
+ − 2981 static void
+ − 2982 ccl_mark (Lisp_Object codesys)
+ − 2983 {
+ − 2984 mark_object (XCODING_SYSTEM_CCL_DECODE (codesys));
+ − 2985 mark_object (XCODING_SYSTEM_CCL_ENCODE (codesys));
+ − 2986 }
+ − 2987
+ − 2988 static Bytecount
+ − 2989 ccl_convert (struct coding_stream *str, const UExtbyte *src,
+ − 2990 unsigned_char_dynarr *dst, Bytecount n)
+ − 2991 {
+ − 2992 struct ccl_coding_stream *data =
+ − 2993 CODING_STREAM_TYPE_DATA (str, ccl);
+ − 2994 Bytecount orign = n;
+ − 2995
+ − 2996 data->ccl.last_block = str->eof;
+ − 2997 /* When applying a CCL program to a stream, SRC must not be NULL -- this
+ − 2998 is a special signal to the driver that read and write operations are
+ − 2999 not allowed. The code does not actually look at what SRC points to if
+ − 3000 N == 0.
+ − 3001 */
+ − 3002 ccl_driver (&data->ccl, src ? src : (const unsigned char *) "",
+ − 3003 dst, n, 0,
+ − 3004 str->direction == CODING_DECODE ? CCL_MODE_DECODING :
+ − 3005 CCL_MODE_ENCODING);
+ − 3006 return orign;
+ − 3007 }
+ − 3008
+ − 3009 static void
+ − 3010 ccl_init_coding_stream (struct coding_stream *str)
+ − 3011 {
+ − 3012 struct ccl_coding_stream *data =
+ − 3013 CODING_STREAM_TYPE_DATA (str, ccl);
+ − 3014
+ − 3015 setup_ccl_program (&data->ccl,
+ − 3016 str->direction == CODING_DECODE ?
+ − 3017 XCODING_SYSTEM_CCL_DECODE (str->codesys) :
+ − 3018 XCODING_SYSTEM_CCL_ENCODE (str->codesys));
+ − 3019 }
+ − 3020
+ − 3021 static void
+ − 3022 ccl_rewind_coding_stream (struct coding_stream *str)
+ − 3023 {
+ − 3024 ccl_init_coding_stream (str);
+ − 3025 }
+ − 3026
+ − 3027 static void
+ − 3028 ccl_init (Lisp_Object codesys)
+ − 3029 {
+ − 3030 XCODING_SYSTEM_CCL_DECODE (codesys) = Qnil;
+ − 3031 XCODING_SYSTEM_CCL_ENCODE (codesys) = Qnil;
+ − 3032 }
+ − 3033
+ − 3034 static int
+ − 3035 ccl_putprop (Lisp_Object codesys, Lisp_Object key, Lisp_Object value)
+ − 3036 {
+ − 3037 Lisp_Object sym;
+ − 3038 struct ccl_program test_ccl;
2367
+ − 3039 Ascbyte *suffix;
771
+ − 3040
+ − 3041 /* Check key first. */
+ − 3042 if (EQ (key, Qdecode))
+ − 3043 suffix = "-ccl-decode";
+ − 3044 else if (EQ (key, Qencode))
+ − 3045 suffix = "-ccl-encode";
+ − 3046 else
+ − 3047 return 0;
+ − 3048
+ − 3049 /* If value is vector, register it as a ccl program
+ − 3050 associated with a newly created symbol for
+ − 3051 backward compatibility.
+ − 3052
+ − 3053 #### Bogosity alert! Do we really have to do this crap???? --ben */
+ − 3054 if (VECTORP (value))
+ − 3055 {
+ − 3056 sym = Fintern (concat2 (Fsymbol_name (XCODING_SYSTEM_NAME (codesys)),
+ − 3057 build_string (suffix)),
+ − 3058 Qnil);
+ − 3059 Fregister_ccl_program (sym, value);
+ − 3060 }
+ − 3061 else
+ − 3062 {
+ − 3063 CHECK_SYMBOL (value);
+ − 3064 sym = value;
+ − 3065 }
+ − 3066 /* check if the given ccl programs are valid. */
+ − 3067 if (setup_ccl_program (&test_ccl, sym) < 0)
+ − 3068 invalid_argument ("Invalid CCL program", value);
+ − 3069
+ − 3070 if (EQ (key, Qdecode))
+ − 3071 XCODING_SYSTEM_CCL_DECODE (codesys) = sym;
+ − 3072 else if (EQ (key, Qencode))
+ − 3073 XCODING_SYSTEM_CCL_ENCODE (codesys) = sym;
+ − 3074
+ − 3075 return 1;
+ − 3076 }
+ − 3077
+ − 3078 static Lisp_Object
+ − 3079 ccl_getprop (Lisp_Object coding_system, Lisp_Object prop)
+ − 3080 {
+ − 3081 if (EQ (prop, Qdecode))
+ − 3082 return XCODING_SYSTEM_CCL_DECODE (coding_system);
+ − 3083 else if (EQ (prop, Qencode))
+ − 3084 return XCODING_SYSTEM_CCL_ENCODE (coding_system);
+ − 3085 else
+ − 3086 return Qunbound;
+ − 3087 }
+ − 3088
+ − 3089
+ − 3090 /************************************************************************/
+ − 3091 /* Initialization */
+ − 3092 /************************************************************************/
+ − 3093
+ − 3094 void
+ − 3095 syms_of_mule_coding (void)
+ − 3096 {
+ − 3097 DEFSUBR (Fdecode_shift_jis_char);
+ − 3098 DEFSUBR (Fencode_shift_jis_char);
+ − 3099 DEFSUBR (Fdecode_big5_char);
+ − 3100 DEFSUBR (Fencode_big5_char);
+ − 3101
+ − 3102 DEFSYMBOL (Qbig5);
+ − 3103 DEFSYMBOL (Qshift_jis);
+ − 3104 DEFSYMBOL (Qccl);
+ − 3105 DEFSYMBOL (Qiso2022);
+ − 3106
+ − 3107 DEFSYMBOL (Qcharset_g0);
+ − 3108 DEFSYMBOL (Qcharset_g1);
+ − 3109 DEFSYMBOL (Qcharset_g2);
+ − 3110 DEFSYMBOL (Qcharset_g3);
+ − 3111 DEFSYMBOL (Qforce_g0_on_output);
+ − 3112 DEFSYMBOL (Qforce_g1_on_output);
+ − 3113 DEFSYMBOL (Qforce_g2_on_output);
+ − 3114 DEFSYMBOL (Qforce_g3_on_output);
+ − 3115 DEFSYMBOL (Qno_iso6429);
+ − 3116 DEFSYMBOL (Qinput_charset_conversion);
+ − 3117 DEFSYMBOL (Qoutput_charset_conversion);
+ − 3118
+ − 3119 DEFSYMBOL (Qshort);
+ − 3120 DEFSYMBOL (Qno_ascii_eol);
+ − 3121 DEFSYMBOL (Qno_ascii_cntl);
+ − 3122 DEFSYMBOL (Qseven);
+ − 3123 DEFSYMBOL (Qlock_shift);
+ − 3124
+ − 3125 DEFSYMBOL (Qiso_7);
+ − 3126 DEFSYMBOL (Qiso_8_designate);
+ − 3127 DEFSYMBOL (Qiso_8_1);
+ − 3128 DEFSYMBOL (Qiso_8_2);
+ − 3129 DEFSYMBOL (Qiso_lock_shift);
+ − 3130 }
+ − 3131
+ − 3132 void
+ − 3133 coding_system_type_create_mule_coding (void)
+ − 3134 {
+ − 3135 INITIALIZE_CODING_SYSTEM_TYPE_WITH_DATA (iso2022, "iso2022-coding-system-p");
+ − 3136 CODING_SYSTEM_HAS_METHOD (iso2022, mark);
+ − 3137 CODING_SYSTEM_HAS_METHOD (iso2022, convert);
+ − 3138 CODING_SYSTEM_HAS_METHOD (iso2022, finalize_coding_stream);
+ − 3139 CODING_SYSTEM_HAS_METHOD (iso2022, init_coding_stream);
+ − 3140 CODING_SYSTEM_HAS_METHOD (iso2022, rewind_coding_stream);
+ − 3141 CODING_SYSTEM_HAS_METHOD (iso2022, init);
+ − 3142 CODING_SYSTEM_HAS_METHOD (iso2022, print);
+ − 3143 CODING_SYSTEM_HAS_METHOD (iso2022, finalize);
+ − 3144 CODING_SYSTEM_HAS_METHOD (iso2022, putprop);
+ − 3145 CODING_SYSTEM_HAS_METHOD (iso2022, getprop);
+ − 3146
+ − 3147 INITIALIZE_DETECTOR (iso2022);
+ − 3148 DETECTOR_HAS_METHOD (iso2022, detect);
+ − 3149 DETECTOR_HAS_METHOD (iso2022, finalize_detection_state);
+ − 3150 INITIALIZE_DETECTOR_CATEGORY (iso2022, iso_7);
+ − 3151 INITIALIZE_DETECTOR_CATEGORY (iso2022, iso_8_designate);
+ − 3152 INITIALIZE_DETECTOR_CATEGORY (iso2022, iso_8_1);
+ − 3153 INITIALIZE_DETECTOR_CATEGORY (iso2022, iso_8_2);
+ − 3154 INITIALIZE_DETECTOR_CATEGORY (iso2022, iso_lock_shift);
+ − 3155
+ − 3156 INITIALIZE_CODING_SYSTEM_TYPE_WITH_DATA (ccl, "ccl-coding-system-p");
+ − 3157 CODING_SYSTEM_HAS_METHOD (ccl, mark);
+ − 3158 CODING_SYSTEM_HAS_METHOD (ccl, convert);
+ − 3159 CODING_SYSTEM_HAS_METHOD (ccl, init);
+ − 3160 CODING_SYSTEM_HAS_METHOD (ccl, init_coding_stream);
+ − 3161 CODING_SYSTEM_HAS_METHOD (ccl, rewind_coding_stream);
+ − 3162 CODING_SYSTEM_HAS_METHOD (ccl, putprop);
+ − 3163 CODING_SYSTEM_HAS_METHOD (ccl, getprop);
+ − 3164
+ − 3165 INITIALIZE_CODING_SYSTEM_TYPE (shift_jis, "shift-jis-coding-system-p");
+ − 3166 CODING_SYSTEM_HAS_METHOD (shift_jis, convert);
+ − 3167
+ − 3168 INITIALIZE_DETECTOR (shift_jis);
+ − 3169 DETECTOR_HAS_METHOD (shift_jis, detect);
+ − 3170 INITIALIZE_DETECTOR_CATEGORY (shift_jis, shift_jis);
+ − 3171
+ − 3172 INITIALIZE_CODING_SYSTEM_TYPE (big5, "big5-coding-system-p");
+ − 3173 CODING_SYSTEM_HAS_METHOD (big5, convert);
+ − 3174
+ − 3175 INITIALIZE_DETECTOR (big5);
+ − 3176 DETECTOR_HAS_METHOD (big5, detect);
+ − 3177 INITIALIZE_DETECTOR_CATEGORY (big5, big5);
+ − 3178 }
+ − 3179
+ − 3180 void
+ − 3181 reinit_coding_system_type_create_mule_coding (void)
+ − 3182 {
+ − 3183 REINITIALIZE_CODING_SYSTEM_TYPE (iso2022);
+ − 3184 REINITIALIZE_CODING_SYSTEM_TYPE (ccl);
+ − 3185 REINITIALIZE_CODING_SYSTEM_TYPE (shift_jis);
+ − 3186 REINITIALIZE_CODING_SYSTEM_TYPE (big5);
+ − 3187 }
+ − 3188
+ − 3189 void
+ − 3190 reinit_vars_of_mule_coding (void)
+ − 3191 {
+ − 3192 }
+ − 3193
+ − 3194 void
+ − 3195 vars_of_mule_coding (void)
+ − 3196 {
+ − 3197 }