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