Mercurial > emacs
changeset 20718:c600dea3b06b
Vselect_safe_coding_system_function): New variable.
(coding_category_table): This variable deleted.
(Vcoding_category_table): New variable.
(coding_category_name): Add "coding-category-iso-7-tight".
(detect_coding_iso2022): Check the mask
CODING_FLAG_ISO_DESIGNATION in CODING->FLAGS. Check a new coding
category coding-category-iso-7-tight.
(DECODE_DESIGNATION): Decode only such designations that CODING
can handle.
(check_composing_code): New function.
(decode_coding_iso2022): Decode only such characters that CODING
can handle.
(encode_coding_iso2022): Before and after encoding composite
characters, reset designation and invocation status.
(detect_coding_sjis): Delete unnecessary check.
(detect_coding_big5): Likewise.
(encode_designation_at_bol): Check the validity of requested
designation register.
(setup_coding_system): Set requested designation registers for
non-supported charsets to
CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION. Set mask
CODING_FLAG_ISO_DESIGNATION in CODING->FLAGS. Code tuned for
no-conversion and undecided.
(detect_coding): Adjusted for the new variable
Vcoding_category_table.
(syms_of_coding): Initialize Vcoding_category_table and staticpro
it. Register select-safe-coding-system as a Lisp variable.
(DECODE_CHARACTER_ASCII): Update coding->produced_char;
(DECODE_CHARACTER_DIMENSION1): Likewise.
(Qraw_text, Qcoding_category): New variables.
(syms_of_coding): Intern and staticpro them.
(coding_system_table): New variable.
(CHARSET_OK, SHIFT_OUT_OK): New macros.
(detect_coding_iso2022): Detection algorithm improved.
(decode_coding_iso2022): Arg CONSUMED deleted, and the meaning of
return value changed. Update members produced, produced_char,
consumed, consumed_char of the struct *coding. Pay attention to
CODING_MODE_INHIBIT_INCONSISTENT_EOL.
(encode_coding_iso2022): Likewise.
(decode_coding_sjis_big5, encode_coding_sjis_big5): Likewise.
(decode_eol, encode_eol): Likewise.
(ENCODE_ISO_CHARACTER): Update coding->consumed_char.
(DECODE_SJIS_BIG5_CHARACTER): Update coding->produced_char.
(ENCODE_SJIS_BIG5_CHARACTER): Update coding->consumed_char.
(detect_coding(detect_coding(detect_ITIES and SKIP.
(detect_coding): Adjusted for the change of detect_coding_mask.
Update coding->heading_ascii.
(detect_eol_type): New arg SKIP.
(detect_eol): Adjusted for the change of detect_eol_type.
(ccl_codign_driver): New function.
(decode_coding): Arg CONSUMED deleted, and the meaning of return
value changed. Update members produced, produced_char, consumed,
consumed_char of the struct *coding.
(encode_coding): Likewise.
(shrink_decoding_region, shrink_encoding_region): New function.
(code_convert_region, code_convert_string): Completely rewritten.
(detect_coding_sy(detect_coding_sy(detect_coding_sy(detect_coding_sy(detect_codiT.
(Fdetect_coding_string): New function.
(Fdecode_coding_region, Fencode_coding_region): Adjusted for the
change of code_convert_region.
(Fdecode_coding_string, Fencode_coding_string): Adjusted for the
change of code_convert_string.
(Fupdate_iso_coding_systems): New function.
(init_coding_once): Initialize coding_system_table.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Thu, 22 Jan 1998 01:26:45 +0000 |
parents | 19463997fbc6 |
children | 78d95f2a9d92 |
files | src/coding.c |
diffstat | 1 files changed, 1852 insertions(+), 1041 deletions(-) [+] |
line wrap: on
line diff
--- a/src/coding.c Thu Jan 22 01:26:45 1998 +0000 +++ b/src/coding.c Thu Jan 22 01:26:45 1998 +0000 @@ -79,8 +79,8 @@ (Code Conversion Language) programs. Emacs executes the CCL program while reading/writing. - Emacs represents a coding-system by a Lisp symbol that has a property - `coding-system'. But, before actually using the coding-system, the + Emacs represents a coding system by a Lisp symbol that has a property + `coding-system'. But, before actually using the coding system, the information about it is set in a structure of type `struct coding_system' for rapid processing. See section 6 for more details. @@ -91,7 +91,8 @@ How end-of-line of a text is encoded depends on a system. For instance, Unix's format is just one byte of `line-feed' code, whereas DOS's format is two-byte sequence of `carriage-return' and - `line-feed' codes. MacOS's format is one byte of `carriage-return'. + `line-feed' codes. MacOS's format is usually one byte of + `carriage-return'. Since text characters encoding and end-of-line encoding are independent, any coding system described above can take @@ -120,16 +121,24 @@ These functions decode SRC_BYTES length text at SOURCE encoded in CODING to Emacs' internal format (emacs-mule). The resulting text - goes to a place pointed to by DESTINATION, the length of which should - not exceed DST_BYTES. The number of bytes actually processed is - returned as *CONSUMED. The return value is the length of the decoded - text. Below is a template of these functions. */ + goes to a place pointed to by DESTINATION, the length of which + should not exceed DST_BYTES. These functions set the information of + original and decoded texts in the members produced, produced_char, + consumed, and consumed_char of the structure *CODING. + + The return value is an integer (CODING_FINISH_XXX) indicating how + the decoding finished. + + DST_BYTES zero means that source area and destination area are + overlapped, which means that we can produce a decoded text until it + reaches at the head of not-yet-decoded source text. + + Below is a template of these functions. */ #if 0 -decode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed) +decode_coding_XXX (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { ... } @@ -140,15 +149,23 @@ These functions encode SRC_BYTES length text at SOURCE of Emacs' internal format (emacs-mule) to CODING. The resulting text goes to a place pointed to by DESTINATION, the length of which should not - exceed DST_BYTES. The number of bytes actually processed is - returned as *CONSUMED. The return value is the length of the - encoded text. Below is a template of these functions. */ + exceed DST_BYTES. These functions set the information of + original and encoded texts in the members produced, produced_char, + consumed, and consumed_char of the structure *CODING. + + The return value is an integer (CODING_FINISH_XXX) indicating how + the encoding finished. + + DST_BYTES zero means that source area and destination area are + overlapped, which means that we can produce a decoded text until it + reaches at the head of not-yet-decoded source text. + + Below is a template of these functions. */ #if 0 -encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes, consumed) +encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { ... } @@ -200,7 +217,10 @@ if (COMPOSING_P (coding->composing)) \ *dst++ = 0xA0, *dst++ = (c) | 0x80; \ else \ - *dst++ = (c); \ + { \ + *dst++ = (c); \ + coding->produced_char++; \ + } \ } while (0) /* Decode one DIMENSION1 character whose charset is CHARSET and whose @@ -212,7 +232,10 @@ if (COMPOSING_P (coding->composing)) \ *dst++ = leading_code + 0x20; \ else \ - *dst++ = leading_code; \ + { \ + *dst++ = leading_code; \ + coding->produced_char++; \ + } \ if (leading_code = CHARSET_LEADING_CODE_EXT (charset)) \ *dst++ = leading_code; \ *dst++ = (c) | 0x80; \ @@ -260,6 +283,8 @@ Lisp_Object Qstart_process, Qopen_network_stream; Lisp_Object Qtarget_idx; +Lisp_Object Vselect_safe_coding_system_function; + /* Mnemonic character of each format of end-of-line. */ int eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac; /* Mnemonic character to indicate format of end-of-line is not yet @@ -276,8 +301,9 @@ Lisp_Object Qcoding_system_p, Qcoding_system_error; -/* Coding system emacs-mule is for converting only end-of-line format. */ -Lisp_Object Qemacs_mule; +/* Coding system emacs-mule and raw-text are for converting only + end-of-line format. */ +Lisp_Object Qemacs_mule, Qraw_text; /* Coding-systems are handed between Emacs Lisp programs and C internal routines by the following three variables. */ @@ -311,19 +337,20 @@ #endif /* emacs */ -Lisp_Object Qcoding_category_index; +Lisp_Object Qcoding_category, Qcoding_category_index; /* List of symbols `coding-category-xxx' ordered by priority. */ Lisp_Object Vcoding_category_list; -/* Table of coding-systems currently assigned to each coding-category. */ -Lisp_Object coding_category_table[CODING_CATEGORY_IDX_MAX]; +/* Table of coding categories (Lisp symbols). */ +Lisp_Object Vcoding_category_table; /* Table of names of symbol for each coding-category. */ char *coding_category_name[CODING_CATEGORY_IDX_MAX] = { "coding-category-emacs-mule", "coding-category-sjis", "coding-category-iso-7", + "coding-category-iso-7-tight", "coding-category-iso-8-1", "coding-category-iso-8-2", "coding-category-iso-7-else", @@ -333,6 +360,10 @@ "coding-category-binary" }; +/* Table pointers to coding systems corresponding to each coding + categories. */ +struct coding_system *coding_system_table[CODING_CATEGORY_IDX_MAX]; + /* Flag to tell if we look up unification table on character code conversion. */ Lisp_Object Venable_character_unification; @@ -399,7 +430,7 @@ /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". Check if a text is encoded in Emacs' internal format. If it is, - return CODING_CATEGORY_MASK_EMASC_MULE, else return 0. */ + return CODING_CATEGORY_MASK_EMACS_MULE, else return 0. */ int detect_coding_emacs_mule (src, src_end) @@ -609,10 +640,19 @@ enum iso_code_class_type iso_code_class[256]; +#define CHARSET_OK(idx, charset) \ + (CODING_SPEC_ISO_REQUESTED_DESIGNATION \ + (coding_system_table[idx], charset) \ + != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION) + +#define SHIFT_OUT_OK(idx) \ + (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding_system_table[idx], 1) >= 0) + /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". Check if a text is encoded in ISO2022. If it is, returns an integer in which appropriate flag bits any of: CODING_CATEGORY_MASK_ISO_7 + CODING_CATEGORY_MASK_ISO_7_TIGHT CODING_CATEGORY_MASK_ISO_8_1 CODING_CATEGORY_MASK_ISO_8_2 CODING_CATEGORY_MASK_ISO_7_ELSE @@ -624,24 +664,12 @@ detect_coding_iso2022 (src, src_end) unsigned char *src, *src_end; { - int mask = (CODING_CATEGORY_MASK_ISO_7 - | CODING_CATEGORY_MASK_ISO_8_1 - | CODING_CATEGORY_MASK_ISO_8_2 - | CODING_CATEGORY_MASK_ISO_7_ELSE - | CODING_CATEGORY_MASK_ISO_8_ELSE - ); - int g1 = 0; /* 1 iff designating to G1. */ - int c, i; - struct coding_system coding_iso_8_1, coding_iso_8_2; - - /* Coding systems of these categories may accept latin extra codes. */ - setup_coding_system - (XSYMBOL (coding_category_table[CODING_CATEGORY_IDX_ISO_8_1])->value, - &coding_iso_8_1); - setup_coding_system - (XSYMBOL (coding_category_table[CODING_CATEGORY_IDX_ISO_8_2])->value, - &coding_iso_8_2); - + int mask = CODING_CATEGORY_MASK_ISO; + int mask_found = 0; + int reg[4], shift_out = 0; + int c, c1, i, charset; + + reg[0] = CHARSET_ASCII, reg[1] = reg[2] = reg[3] = -1; while (mask && src < src_end) { c = *src++; @@ -651,15 +679,17 @@ if (src >= src_end) break; c = *src++; - if ((c >= '(' && c <= '/')) + if (c >= '(' && c <= '/') { /* Designation sequence for a charset of dimension 1. */ if (src >= src_end) break; - c = *src++; - if (c < ' ' || c >= 0x80) - /* Invalid designation sequence. */ - return 0; + c1 = *src++; + if (c1 < ' ' || c1 >= 0x80 + || (charset = iso_charset_table[0][c >= ','][c1]) < 0) + /* Invalid designation sequence. Just ignore. */ + break; + reg[(c - '(') % 4] = charset; } else if (c == '$') { @@ -669,37 +699,91 @@ c = *src++; if (c >= '@' && c <= 'B') /* Designation for JISX0208.1978, GB2312, or JISX0208. */ - ; + reg[0] = charset = iso_charset_table[1][0][c]; else if (c >= '(' && c <= '/') { if (src >= src_end) break; - c = *src++; - if (c < ' ' || c >= 0x80) - /* Invalid designation sequence. */ - return 0; + c1 = *src++; + if (c1 < ' ' || c1 >= 0x80 + || (charset = iso_charset_table[1][c >= ','][c1]) < 0) + /* Invalid designation sequence. Just ignore. */ + break; + reg[(c - '(') % 4] = charset; } else - /* Invalid designation sequence. */ - return 0; + /* Invalid designation sequence. Just ignore. */ + break; + } + else if (c == 'N' || c == 'n') + { + if (shift_out == 0 + && (reg[1] >= 0 + || SHIFT_OUT_OK (CODING_CATEGORY_IDX_ISO_7_ELSE) + || SHIFT_OUT_OK (CODING_CATEGORY_IDX_ISO_8_ELSE))) + { + /* Locking shift out. */ + mask &= ~CODING_CATEGORY_MASK_ISO_7BIT; + mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT; + shift_out = 1; + } + break; } - else if (c == 'N' || c == 'O' || c == 'n' || c == 'o') - /* Locking shift. */ - mask &= (CODING_CATEGORY_MASK_ISO_7_ELSE - | CODING_CATEGORY_MASK_ISO_8_ELSE); + else if (c == 'O' || c == 'o') + { + if (shift_out == 1) + { + /* Locking shift in. */ + mask &= ~CODING_CATEGORY_MASK_ISO_7BIT; + mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT; + shift_out = 0; + } + break; + } else if (c == '0' || c == '1' || c == '2') - /* Start/end composition. */ - ; + /* Start/end composition. Just ignore. */ + break; else - /* Invalid escape sequence. */ - return 0; + /* Invalid escape sequence. Just ignore. */ + break; + + /* We found a valid designation sequence for CHARSET. */ + mask &= ~CODING_CATEGORY_MASK_ISO_8BIT; + if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_7, charset)) + mask_found |= CODING_CATEGORY_MASK_ISO_7; + else + mask &= ~CODING_CATEGORY_MASK_ISO_7; + if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_7_TIGHT, charset)) + mask_found |= CODING_CATEGORY_MASK_ISO_7_TIGHT; + else + mask &= ~CODING_CATEGORY_MASK_ISO_7_TIGHT; + if (! CHARSET_OK (CODING_CATEGORY_IDX_ISO_7_ELSE, charset)) + mask &= ~CODING_CATEGORY_MASK_ISO_7_ELSE; + if (! CHARSET_OK (CODING_CATEGORY_IDX_ISO_8_ELSE, charset)) + mask &= ~CODING_CATEGORY_MASK_ISO_8_ELSE; break; case ISO_CODE_SO: - mask &= (CODING_CATEGORY_MASK_ISO_7_ELSE - | CODING_CATEGORY_MASK_ISO_8_ELSE); + if (shift_out == 0 + && (reg[1] >= 0 + || SHIFT_OUT_OK (CODING_CATEGORY_IDX_ISO_7_ELSE) + || SHIFT_OUT_OK (CODING_CATEGORY_IDX_ISO_8_ELSE))) + { + /* Locking shift out. */ + mask &= ~CODING_CATEGORY_MASK_ISO_7BIT; + mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT; + } break; + case ISO_CODE_SI: + if (shift_out == 1) + { + /* Locking shift in. */ + mask &= ~CODING_CATEGORY_MASK_ISO_7BIT; + mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT; + } + break; + case ISO_CODE_CSI: case ISO_CODE_SS2: case ISO_CODE_SS3: @@ -708,20 +792,25 @@ if (c != ISO_CODE_CSI) { - if (coding_iso_8_1.flags & CODING_FLAG_ISO_SINGLE_SHIFT) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_1]->flags + & CODING_FLAG_ISO_SINGLE_SHIFT) newmask |= CODING_CATEGORY_MASK_ISO_8_1; - if (coding_iso_8_2.flags & CODING_FLAG_ISO_SINGLE_SHIFT) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_2]->flags + & CODING_FLAG_ISO_SINGLE_SHIFT) newmask |= CODING_CATEGORY_MASK_ISO_8_2; } if (VECTORP (Vlatin_extra_code_table) && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) { - if (coding_iso_8_1.flags & CODING_FLAG_ISO_LATIN_EXTRA) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_1]->flags + & CODING_FLAG_ISO_LATIN_EXTRA) newmask |= CODING_CATEGORY_MASK_ISO_8_1; - if (coding_iso_8_2.flags & CODING_FLAG_ISO_LATIN_EXTRA) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_2]->flags + & CODING_FLAG_ISO_LATIN_EXTRA) newmask |= CODING_CATEGORY_MASK_ISO_8_2; } mask &= newmask; + mask_found |= newmask; } break; @@ -735,11 +824,14 @@ { int newmask = 0; - if (coding_iso_8_1.flags & CODING_FLAG_ISO_LATIN_EXTRA) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_1]->flags + & CODING_FLAG_ISO_LATIN_EXTRA) newmask |= CODING_CATEGORY_MASK_ISO_8_1; - if (coding_iso_8_2.flags & CODING_FLAG_ISO_LATIN_EXTRA) + if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_2]->flags + & CODING_FLAG_ISO_LATIN_EXTRA) newmask |= CODING_CATEGORY_MASK_ISO_8_2; mask &= newmask; + mask_found |= newmask; } else return 0; @@ -748,18 +840,21 @@ { unsigned char *src_begin = src; - mask &= ~(CODING_CATEGORY_MASK_ISO_7 + mask &= ~(CODING_CATEGORY_MASK_ISO_7BIT | CODING_CATEGORY_MASK_ISO_7_ELSE); + mask_found |= CODING_CATEGORY_MASK_ISO_8_1; while (src < src_end && *src >= 0xA0) src++; if ((src - src_begin - 1) & 1 && src < src_end) mask &= ~CODING_CATEGORY_MASK_ISO_8_2; + else + mask_found |= CODING_CATEGORY_MASK_ISO_8_2; } break; } } - return mask; + return (mask & mask_found); } /* Decode a character of which charset is CHARSET and the 1st position @@ -808,29 +903,89 @@ } while (0) /* Set designation state into CODING. */ -#define DECODE_DESIGNATION(reg, dimension, chars, final_char) \ - do { \ - int charset = ISO_CHARSET_TABLE (make_number (dimension), \ - make_number (chars), \ - make_number (final_char)); \ - if (charset >= 0) \ - { \ - if (coding->direction == 1 \ - && CHARSET_REVERSE_CHARSET (charset) >= 0) \ - charset = CHARSET_REVERSE_CHARSET (charset); \ - CODING_SPEC_ISO_DESIGNATION (coding, reg) = charset; \ - } \ +#define DECODE_DESIGNATION(reg, dimension, chars, final_char) \ + do { \ + int charset = ISO_CHARSET_TABLE (make_number (dimension), \ + make_number (chars), \ + make_number (final_char)); \ + if (charset >= 0 \ + && CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) == reg) \ + { \ + if (coding->spec.iso2022.last_invalid_designation_register == 0 \ + && reg == 0 \ + && charset == CHARSET_ASCII) \ + { \ + /* We should insert this designation sequence as is so \ + that it is surely written back to a file. */ \ + coding->spec.iso2022.last_invalid_designation_register = -1; \ + goto label_invalid_code; \ + } \ + coding->spec.iso2022.last_invalid_designation_register = -1; \ + if ((coding->mode & CODING_MODE_DIRECTION) \ + && CHARSET_REVERSE_CHARSET (charset) >= 0) \ + charset = CHARSET_REVERSE_CHARSET (charset); \ + CODING_SPEC_ISO_DESIGNATION (coding, reg) = charset; \ + } \ + else \ + { \ + coding->spec.iso2022.last_invalid_designation_register = reg; \ + goto label_invalid_code; \ + } \ } while (0) +/* Check if the current composing sequence contains only valid codes. + If the composing sequence doesn't end before SRC_END, return -1. + Else, if it contains only valid codes, return 0. + Else return the length of the composing sequence. */ + +int check_composing_code (coding, src, src_end) + struct coding_system *coding; + unsigned char *src, *src_end; +{ + unsigned char *src_start = src; + int invalid_code_found = 0; + int charset, c, c1, dim; + + while (src < src_end) + { + if (*src++ != ISO_CODE_ESC) continue; + if (src >= src_end) break; + if ((c = *src++) == '1') /* end of compsition */ + return (invalid_code_found ? src - src_start : 0); + if (src + 2 >= src_end) break; + if (!coding->flags & CODING_FLAG_ISO_DESIGNATION) + invalid_code_found = 1; + else + { + dim = 0; + if (c == '$') + { + dim = 1; + c = (*src >= '@' && *src <= 'B') ? '(' : *src++; + } + if (c >= '(' && c <= '/') + { + c1 = *src++; + if ((c1 < ' ' || c1 >= 0x80) + || (charset = iso_charset_table[dim][c >= ','][c1]) < 0 + || (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) + == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)) + invalid_code_found = 1; + } + else + invalid_code_found = 1; + } + } + return ((coding->mode & CODING_MODE_LAST_BLOCK) ? src_end - src_start : -1); +} + /* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ int -decode_coding_iso2022 (coding, source, destination, - src_bytes, dst_bytes, consumed) +decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { unsigned char *src = source; unsigned char *src_end = source + src_bytes; @@ -845,12 +1000,16 @@ int charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); int charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1); Lisp_Object unification_table - = coding->character_unification_table_for_decode; + = coding->character_unification_table_for_decode; + int result = CODING_FINISH_NORMAL; if (!NILP (Venable_character_unification) && NILP (unification_table)) unification_table = Vstandard_character_unification_table_for_decode; - while (src < src_end && dst < adjusted_dst_end) + coding->produced_char = 0; + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 6))) { /* SRC_BASE remembers the start position in source in each loop. The loop will be exited when there's not enough source text @@ -868,6 +1027,7 @@ { /* This is SPACE or DEL. */ *dst++ = c1; + coding->produced_char++; break; } /* This is a graphic character, we fall down ... */ @@ -884,29 +1044,45 @@ break; case ISO_0xA0_or_0xFF: - if (charset1 < 0 || CHARSET_CHARS (charset1) == 94) + if (charset1 < 0 || CHARSET_CHARS (charset1) == 94 + || coding->flags & CODING_FLAG_ISO_SEVEN_BITS) { /* Invalid code. */ *dst++ = c1; + coding->produced_char++; break; } /* This is a graphic character, we fall down ... */ case ISO_graphic_plane_1: - DECODE_ISO_CHARACTER (charset1, c1); + if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) + { + /* Invalid code. */ + *dst++ = c1; + coding->produced_char++; + } + else + DECODE_ISO_CHARACTER (charset1, c1); break; case ISO_control_code: /* All ISO2022 control characters in this class have the same representation in Emacs internal format. */ + if (c1 == '\n' + && (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + && (coding->eol_type == CODING_EOL_CR + || coding->eol_type == CODING_EOL_CRLF)) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } *dst++ = c1; + coding->produced_char++; break; case ISO_carriage_return: if (coding->eol_type == CODING_EOL_CR) - { - *dst++ = '\n'; - } + *dst++ = '\n'; else if (coding->eol_type == CODING_EOL_CRLF) { ONE_MORE_BYTE (c1); @@ -914,35 +1090,46 @@ *dst++ = '\n'; else { + if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } src--; - *dst++ = c1; + *dst++ = '\r'; } } else - { - *dst++ = c1; - } + *dst++ = c1; + coding->produced_char++; break; case ISO_shift_out: - if (CODING_SPEC_ISO_DESIGNATION (coding, 1) < 0) - goto label_invalid_escape_sequence; + if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) + || CODING_SPEC_ISO_DESIGNATION (coding, 1) < 0) + goto label_invalid_code; CODING_SPEC_ISO_INVOCATION (coding, 0) = 1; charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); break; case ISO_shift_in: + if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT)) + goto label_invalid_code; CODING_SPEC_ISO_INVOCATION (coding, 0) = 0; charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); break; case ISO_single_shift_2_7: case ISO_single_shift_2: + if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) + goto label_invalid_code; /* SS2 is handled as an escape sequence of ESC 'N' */ c1 = 'N'; goto label_escape_sequence; case ISO_single_shift_3: + if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) + goto label_invalid_code; /* SS2 is handled as an escape sequence of ESC 'O' */ c1 = 'O'; goto label_escape_sequence; @@ -963,14 +1150,16 @@ case '&': /* revision of following character set */ ONE_MORE_BYTE (c1); if (!(c1 >= '@' && c1 <= '~')) - goto label_invalid_escape_sequence; + goto label_invalid_code; ONE_MORE_BYTE (c1); if (c1 != ISO_CODE_ESC) - goto label_invalid_escape_sequence; + goto label_invalid_code; ONE_MORE_BYTE (c1); goto label_escape_sequence; case '$': /* designation of 2-byte character set */ + if (! (coding->flags & CODING_FLAG_ISO_DESIGNATION)) + goto label_invalid_code; ONE_MORE_BYTE (c1); if (c1 >= '@' && c1 <= 'B') { /* designation of JISX0208.1978, GB2312.1980, @@ -988,84 +1177,118 @@ DECODE_DESIGNATION (c1 - 0x2C, 2, 96, c2); } else - goto label_invalid_escape_sequence; + goto label_invalid_code; break; case 'n': /* invocation of locking-shift-2 */ - if (CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) - goto label_invalid_escape_sequence; + if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) + || CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) + goto label_invalid_code; CODING_SPEC_ISO_INVOCATION (coding, 0) = 2; charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); break; case 'o': /* invocation of locking-shift-3 */ - if (CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) - goto label_invalid_escape_sequence; + if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) + || CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) + goto label_invalid_code; CODING_SPEC_ISO_INVOCATION (coding, 0) = 3; charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); break; case 'N': /* invocation of single-shift-2 */ - if (CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) - goto label_invalid_escape_sequence; + if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) + || CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) + goto label_invalid_code; ONE_MORE_BYTE (c1); charset = CODING_SPEC_ISO_DESIGNATION (coding, 2); DECODE_ISO_CHARACTER (charset, c1); break; case 'O': /* invocation of single-shift-3 */ - if (CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) - goto label_invalid_escape_sequence; + if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) + || CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) + goto label_invalid_code; ONE_MORE_BYTE (c1); charset = CODING_SPEC_ISO_DESIGNATION (coding, 3); DECODE_ISO_CHARACTER (charset, c1); break; - case '0': /* start composing without embeded rules */ - coding->composing = COMPOSING_NO_RULE_HEAD; + case '0': case '2': /* start composing */ + /* Before processing composing, we must be sure that all + characters being composed are supported by CODING. + If not, we must give up composing and insert the + bunch of codes for composing as is without decoding. */ + { + int result1; + + result1 = check_composing_code (coding, src, src_end); + if (result1 == 0) + coding->composing = (c1 == '0' + ? COMPOSING_NO_RULE_HEAD + : COMPOSING_WITH_RULE_HEAD); + else if (result1 > 0) + { + if (result1 + 2 < (dst_bytes ? dst_end : src_base) - dst) + { + bcopy (src_base, dst, result1 + 2); + src += result1; + dst += result1 + 2; + coding->produced_char += result1 + 2; + } + else + { + result = CODING_FINISH_INSUFFICIENT_DST; + goto label_end_of_loop_2; + } + } + else + goto label_end_of_loop; + } break; case '1': /* end composing */ coding->composing = COMPOSING_NO; - break; - - case '2': /* start composing with embeded rules */ - coding->composing = COMPOSING_WITH_RULE_HEAD; + coding->produced_char++; break; case '[': /* specification of direction */ + if (coding->flags & CODING_FLAG_ISO_NO_DIRECTION) + goto label_invalid_code; /* For the moment, nested direction is not supported. - So, the value of `coding->direction' is 0 or 1: 0 - means left-to-right, 1 means right-to-left. */ + So, `coding->mode & CODING_MODE_DIRECTION' zero means + left-to-right, and nozero means right-to-left. */ ONE_MORE_BYTE (c1); switch (c1) { case ']': /* end of the current direction */ - coding->direction = 0; + coding->mode &= ~CODING_MODE_DIRECTION; case '0': /* end of the current direction */ case '1': /* start of left-to-right direction */ ONE_MORE_BYTE (c1); if (c1 == ']') - coding->direction = 0; + coding->mode &= ~CODING_MODE_DIRECTION; else - goto label_invalid_escape_sequence; + goto label_invalid_code; break; case '2': /* start of right-to-left direction */ ONE_MORE_BYTE (c1); if (c1 == ']') - coding->direction= 1; + coding->mode |= CODING_MODE_DIRECTION; else - goto label_invalid_escape_sequence; + goto label_invalid_code; break; default: - goto label_invalid_escape_sequence; + goto label_invalid_code; } break; default: + if (! (coding->flags & CODING_FLAG_ISO_DESIGNATION)) + goto label_invalid_code; if (c1 >= 0x28 && c1 <= 0x2B) { /* designation of DIMENSION1_CHARS94 character set */ ONE_MORE_BYTE (c2); @@ -1078,7 +1301,7 @@ } else { - goto label_invalid_escape_sequence; + goto label_invalid_code; } } /* We must update these variables now. */ @@ -1086,41 +1309,43 @@ charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1); break; - label_invalid_escape_sequence: - { - int length = src - src_base; - - bcopy (src_base, dst, length); - dst += length; - } + label_invalid_code: + coding->produced_char += src - src_base; + while (src_base < src) + *dst++ = *src_base++; } continue; label_end_of_loop: - coding->carryover_size = src - src_base; - bcopy (src_base, coding->carryover, coding->carryover_size); + result = CODING_FINISH_INSUFFICIENT_SRC; + label_end_of_loop_2: src = src_base; break; } + if (result == CODING_FINISH_NORMAL + && src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; + /* If this is the last block of the text to be decoded, we had better just flush out all remaining codes in the text although they are not valid characters. */ - if (coding->last_block) + if (coding->mode & CODING_MODE_LAST_BLOCK) { bcopy (src, dst, src_end - src); dst += (src_end - src); src = src_end; } - *consumed = src - source; - return dst - destination; + coding->consumed = coding->consumed_char = src - source; + coding->produced = dst - destination; + return result; } /* ISO2022 encoding stuff. */ /* It is not enough to say just "ISO2022" on encoding, we have to - specify more details. In Emacs, each coding-system of ISO2022 + specify more details. In Emacs, each coding system of ISO2022 variant has the following specifications: 1. Initial designation to G0 thru G3. 2. Allows short-form designation? @@ -1329,6 +1554,8 @@ ENCODE_ISO_CHARACTER_DIMENSION1 (charset_alt, c1); \ else \ ENCODE_ISO_CHARACTER_DIMENSION2 (charset_alt, c1, c2); \ + if (! COMPOSING_P (coding->composing)) \ + coding->consumed_char++; \ } while (0) /* Produce designation and invocation codes at a place pointed by DST @@ -1431,10 +1658,11 @@ } while (0) /* Produce designation sequences of charsets in the line started from - *SRC to a place pointed by DSTP. + SRC to a place pointed by *DSTP, and update DSTP. If the current block ends before any end-of-line, we may fail to - find all the necessary *designations. */ + find all the necessary designations. */ + encode_designation_at_bol (coding, table, src, src_end, dstp) struct coding_system *coding; Lisp_Object table; @@ -1465,7 +1693,7 @@ } reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset); - if (r[reg] < 0) + if (reg != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION && r[reg] < 0) { found++; r[reg] = charset; @@ -1487,12 +1715,10 @@ /* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". */ int -encode_coding_iso2022 (coding, source, destination, - src_bytes, dst_bytes, consumed) +encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { unsigned char *src = source; unsigned char *src_end = source + src_bytes; @@ -1504,11 +1730,15 @@ unsigned char *adjusted_dst_end = dst_end - 19; Lisp_Object unification_table = coding->character_unification_table_for_encode; + int result = CODING_FINISH_NORMAL; if (!NILP (Venable_character_unification) && NILP (unification_table)) unification_table = Vstandard_character_unification_table_for_encode; - while (src < src_end && dst < adjusted_dst_end) + coding->consumed_char = 0; + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 19))) { /* SRC_BASE remembers the start position in source in each loop. The loop will be exited when there's not enough source text @@ -1529,16 +1759,18 @@ c1 = *src++; /* If we are seeing a component of a composite character, we are - seeing a leading-code specially encoded for composition, or a - composition rule if composing with rule. We must set C1 - to a normal leading-code or an ASCII code. If we are not at - a composed character, we must reset the composition state. */ + seeing a leading-code encoded irregularly for composition, or + a composition rule if composing with rule. We must set C1 to + a normal leading-code or an ASCII code. If we are not seeing + a composite character, we must reset composition, + designation, and invocation states. */ if (COMPOSING_P (coding->composing)) { if (c1 < 0xA0) { /* We are not in a composite character any longer. */ coding->composing = COMPOSING_NO; + ENCODE_RESET_PLANE_AND_REGISTER; ENCODE_COMPOSITION_END; } else @@ -1575,14 +1807,16 @@ if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL) ENCODE_RESET_PLANE_AND_REGISTER; *dst++ = c1; + coding->consumed_char++; break; case EMACS_carriage_return_code: - if (!coding->selective) + if (! (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)) { if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL) ENCODE_RESET_PLANE_AND_REGISTER; *dst++ = c1; + coding->consumed_char++; break; } /* fall down to treat '\r' as '\n' ... */ @@ -1602,6 +1836,7 @@ else *dst++ = ISO_CODE_CR; CODING_SPEC_ISO_BOL (coding) = 1; + coding->consumed_char++; break; case EMACS_leading_code_2: @@ -1611,6 +1846,7 @@ /* invalid sequence */ *dst++ = c1; *dst++ = c2; + coding->consumed_char += 2; } else ENCODE_ISO_CHARACTER (c1, c2, /* dummy */ c3); @@ -1624,6 +1860,7 @@ *dst++ = c1; *dst++ = c2; *dst++ = c3; + coding->consumed_char += 3; } else if (c1 < LEADING_CODE_PRIVATE_11) ENCODE_ISO_CHARACTER (c1, c2, c3); @@ -1640,6 +1877,7 @@ *dst++ = c2; *dst++ = c3; *dst++ = c4; + coding->consumed_char += 4; } else ENCODE_ISO_CHARACTER (c2, c3, c4); @@ -1652,51 +1890,52 @@ /* invalid sequence */ *dst++ = c1; *dst++ = c2; + coding->consumed_char += 2; } else if (c2 == 0xFF) { + ENCODE_RESET_PLANE_AND_REGISTER; coding->composing = COMPOSING_WITH_RULE_HEAD; ENCODE_COMPOSITION_WITH_RULE_START; + coding->consumed_char++; } else { + ENCODE_RESET_PLANE_AND_REGISTER; /* Rewind one byte because it is a character code of composition elements. */ src--; coding->composing = COMPOSING_NO_RULE_HEAD; ENCODE_COMPOSITION_NO_RULE_START; + coding->consumed_char++; } break; case EMACS_invalid_code: *dst++ = c1; + coding->consumed_char++; break; } continue; label_end_of_loop: - /* We reach here because the source date ends not at character - boundary. */ - coding->carryover_size = src_end - src_base; - bcopy (src_base, coding->carryover, coding->carryover_size); - src = src_end; + result = CODING_FINISH_INSUFFICIENT_SRC; + src = src_base; break; } + if (result == CODING_FINISH_NORMAL + && src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; + /* If this is the last block of the text to be encoded, we must - reset graphic planes and registers to the initial state. */ - if (src >= src_end && coding->last_block) - { - ENCODE_RESET_PLANE_AND_REGISTER; - if (coding->carryover_size > 0 - && coding->carryover_size < (dst_end - dst)) - { - bcopy (coding->carryover, dst, coding->carryover_size); - dst += coding->carryover_size; - coding->carryover_size = 0; - } - } - *consumed = src - source; - return dst - destination; + reset graphic planes and registers to the initial state, and + flush out the carryover if any. */ + if (coding->mode & CODING_MODE_LAST_BLOCK) + ENCODE_RESET_PLANE_AND_REGISTER; + + coding->consumed = src - source; + coding->produced = coding->produced_char = dst - destination; + return result; } @@ -1787,6 +2026,7 @@ DECODE_CHARACTER_DIMENSION1 (charset_alt, c1); \ else \ DECODE_CHARACTER_DIMENSION2 (charset_alt, c1, c2); \ + coding->produced_char++; \ } while (0) #define ENCODE_SJIS_BIG5_CHARACTER(charset, c1, c2) \ @@ -1829,6 +2069,7 @@ else \ *dst++ = charset_alt, *dst++ = c1, *dst++ = c2; \ } \ + coding->consumed_char++; \ } while (0); /* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". @@ -1844,8 +2085,6 @@ while (src < src_end) { c = *src++; - if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO) - return 0; if ((c >= 0x80 && c < 0xA0) || c >= 0xE0) { if (src < src_end && *src++ < 0x40) @@ -1868,8 +2107,6 @@ while (src < src_end) { c = *src++; - if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO) - return 0; if (c >= 0xA1) { if (src >= src_end) @@ -1887,11 +2124,10 @@ int decode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, sjis_p) + src_bytes, dst_bytes, sjis_p) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; int sjis_p; { unsigned char *src = source; @@ -1904,11 +2140,15 @@ unsigned char *adjusted_dst_end = dst_end - 3; Lisp_Object unification_table = coding->character_unification_table_for_decode; + int result = CODING_FINISH_NORMAL; if (!NILP (Venable_character_unification) && NILP (unification_table)) unification_table = Vstandard_character_unification_table_for_decode; - while (src < src_end && dst < adjusted_dst_end) + coding->produced_char = 0; + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 3))) { /* SRC_BASE remembers the start position in source in each loop. The loop will be exited when there's not enough source text @@ -1917,24 +2157,41 @@ unsigned char *src_base = src; unsigned char c1 = *src++, c2, c3, c4; - if (c1 == '\r') + if (c1 < 0x20) { - if (coding->eol_type == CODING_EOL_CRLF) + if (c1 == '\r') { - ONE_MORE_BYTE (c2); - if (c2 == '\n') - *dst++ = c2; + if (coding->eol_type == CODING_EOL_CRLF) + { + ONE_MORE_BYTE (c2); + if (c2 == '\n') + *dst++ = c2; + else if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } + else + /* To process C2 again, SRC is subtracted by 1. */ + *dst++ = c1, src--; + } + else if (coding->eol_type == CODING_EOL_CR) + *dst++ = '\n'; else - /* To process C2 again, SRC is subtracted by 1. */ - *dst++ = c1, src--; + *dst++ = c1; } - else if (coding->eol_type == CODING_EOL_CR) - *dst++ = '\n'; + else if (c1 == '\n' + && (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + && (coding->eol_type == CODING_EOL_CR + || coding->eol_type == CODING_EOL_CRLF)) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } else *dst++ = c1; + coding->produced_char++; } - else if (c1 < 0x20) - *dst++ = c1; else if (c1 < 0x80) DECODE_SJIS_BIG5_CHARACTER (charset_ascii, c1, /* dummy */ c2); else if (c1 < 0xA0 || c1 >= 0xE0) @@ -1955,13 +2212,17 @@ DECODE_SJIS_BIG5_CHARACTER (charset, c3, c4); } else /* Invalid code */ - *dst++ = c1; + { + *dst++ = c1; + coding->produced_char++; + } } else { /* SJIS -> JISX0201-Kana, BIG5 -> Big5 */ if (sjis_p) - DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1, /* dummy */ c2); + DECODE_SJIS_BIG5_CHARACTER (charset_katakana_jisx0201, c1, + /* dummy */ c2); else { int charset; @@ -1974,14 +2235,19 @@ continue; label_end_of_loop: - coding->carryover_size = src - src_base; - bcopy (src_base, coding->carryover, coding->carryover_size); + result = CODING_FINISH_INSUFFICIENT_SRC; + label_end_of_loop_2: src = src_base; break; } - *consumed = src - source; - return dst - destination; + if (result == CODING_FINISH_NORMAL + && src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; + + coding->consumed = coding->consumed_char = src - source; + coding->produced = dst - destination; + return result; } /* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". @@ -1994,11 +2260,10 @@ int encode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, sjis_p) + src_bytes, dst_bytes, sjis_p) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; int sjis_p; { unsigned char *src = source; @@ -2011,11 +2276,15 @@ unsigned char *adjusted_dst_end = dst_end - 1; Lisp_Object unification_table = coding->character_unification_table_for_encode; + int result = CODING_FINISH_NORMAL; if (!NILP (Venable_character_unification) && NILP (unification_table)) unification_table = Vstandard_character_unification_table_for_encode; - while (src < src_end && dst < adjusted_dst_end) + coding->consumed_char = 0; + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 1))) { /* SRC_BASE remembers the start position in source in each loop. The loop will be exited when there's not enough source text @@ -2046,12 +2315,14 @@ case EMACS_control_code: *dst++ = c1; + coding->consumed_char++; break; case EMACS_carriage_return_code: - if (!coding->selective) + if (! (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)) { *dst++ = c1; + coding->consumed_char++; break; } /* fall down to treat '\r' as '\n' ... */ @@ -2064,6 +2335,7 @@ *dst++ = '\r', *dst++ = '\n'; else *dst++ = '\r'; + coding->consumed_char++; break; case EMACS_leading_code_2: @@ -2087,18 +2359,22 @@ default: /* i.e. case EMACS_invalid_code: */ *dst++ = c1; + coding->consumed_char++; } continue; label_end_of_loop: - coding->carryover_size = src_end - src_base; - bcopy (src_base, coding->carryover, coding->carryover_size); - src = src_end; + result = CODING_FINISH_INSUFFICIENT_SRC; + src = src_base; break; } - *consumed = src - source; - return dst - destination; + if (result == CODING_FINISH_NORMAL + && src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; + coding->consumed = src - source; + coding->produced = coding->produced_char = dst - destination; + return result; } @@ -2108,17 +2384,19 @@ This function is called only when `coding->eol_type' is CODING_EOL_CRLF or CODING_EOL_CR. */ -decode_eol (coding, source, destination, src_bytes, dst_bytes, consumed) +decode_eol (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { unsigned char *src = source; unsigned char *src_end = source + src_bytes; unsigned char *dst = destination; unsigned char *dst_end = destination + dst_bytes; - int produced; + int result = CODING_FINISH_NORMAL; + + if (src_bytes <= 0) + return result; switch (coding->eol_type) { @@ -2129,7 +2407,9 @@ necessary only at the head of loop. */ unsigned char *adjusted_dst_end = dst_end - 1; - while (src < src_end && dst < adjusted_dst_end) + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 1))) { unsigned char *src_base = src; unsigned char c = *src++; @@ -2137,110 +2417,147 @@ { ONE_MORE_BYTE (c); if (c != '\n') - *dst++ = '\r'; + { + if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } + *dst++ = '\r'; + } *dst++ = c; } + else if (c == '\n' + && (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)) + { + result = CODING_FINISH_INCONSISTENT_EOL; + goto label_end_of_loop_2; + } else *dst++ = c; continue; label_end_of_loop: - coding->carryover_size = src - src_base; - bcopy (src_base, coding->carryover, coding->carryover_size); + result = CODING_FINISH_INSUFFICIENT_SRC; + label_end_of_loop_2: src = src_base; break; } - *consumed = src - source; - produced = dst - destination; - break; + if (result == CODING_FINISH_NORMAL + && src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; } + break; case CODING_EOL_CR: - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - bcopy (source, destination, produced); - dst_end = destination + produced; - while (dst < dst_end) - if (*dst++ == '\r') dst[-1] = '\n'; - *consumed = produced; + if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) + { + while (src < src_end) if (*src++ == '\n') break; + if (*--src == '\n') + { + src_bytes = src - source; + result = CODING_FINISH_INCONSISTENT_EOL; + } + } + if (dst_bytes && src_bytes > dst_bytes) + { + result = CODING_FINISH_INSUFFICIENT_DST; + src_bytes = dst_bytes; + } + if (dst_bytes) + bcopy (source, destination, src_bytes); + else + safe_bcopy (source, destination, src_bytes); + src = source + src_bytes; + while (src_bytes--) if (*dst++ == '\r') dst[-1] = '\n'; break; default: /* i.e. case: CODING_EOL_LF */ - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - bcopy (source, destination, produced); - *consumed = produced; + if (dst_bytes && src_bytes > dst_bytes) + { + result = CODING_FINISH_INSUFFICIENT_DST; + src_bytes = dst_bytes; + } + if (dst_bytes) + bcopy (source, destination, src_bytes); + else + safe_bcopy (source, destination, src_bytes); + src += src_bytes; + dst += dst_bytes; break; } - return produced; + coding->consumed = coding->consumed_char = src - source; + coding->produced = coding->produced_char = dst - destination; + return result; } /* See "GENERAL NOTES about `encode_coding_XXX ()' functions". Encode format of end-of-line according to `coding->eol_type'. If - `coding->selective' is 1, code '\r' in source text also means - end-of-line. */ - -encode_eol (coding, source, destination, src_bytes, dst_bytes, consumed) + `coding->mode & CODING_MODE_SELECTIVE_DISPLAY' is nonzero, code + '\r' in source text also means end-of-line. */ + +encode_eol (coding, source, destination, src_bytes, dst_bytes) struct coding_system *coding; unsigned char *source, *destination; int src_bytes, dst_bytes; - int *consumed; { unsigned char *src = source; unsigned char *dst = destination; - int produced; - - if (src_bytes <= 0) - return 0; - - switch (coding->eol_type) + int result = CODING_FINISH_NORMAL; + + if (coding->eol_type == CODING_EOL_CRLF) { - case CODING_EOL_LF: - case CODING_EOL_UNDECIDED: - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - bcopy (source, destination, produced); - if (coding->selective) + unsigned char c; + unsigned char *src_end = source + src_bytes; + unsigned char *dst_end = destination + dst_bytes; + /* Since the maximum bytes produced by each loop is 2, we + subtract 1 from DST_END to assure overflow checking is + necessary only at the head of loop. */ + unsigned char *adjusted_dst_end = dst_end - 1; + + while (src < src_end && (dst_bytes + ? (dst < adjusted_dst_end) + : (dst < src - 1))) { - int i = produced; - while (i--) + c = *src++; + if (c == '\n' + || (c == '\r' && (coding->mode & CODING_MODE_SELECTIVE_DISPLAY))) + *dst++ = '\r', *dst++ = '\n'; + else + *dst++ = c; + } + if (src < src_end) + result = CODING_FINISH_INSUFFICIENT_DST; + } + else + { + if (dst_bytes && src_bytes > dst_bytes) + { + src_bytes = dst_bytes; + result = CODING_FINISH_INSUFFICIENT_DST; + } + if (dst_bytes) + bcopy (source, destination, src_bytes); + else + safe_bcopy (source, destination, src_bytes); + if (coding->eol_type == CODING_EOL_CRLF) + { + while (src_bytes--) + if (*dst++ == '\n') dst[-1] = '\r'; + } + else if (coding->mode & CODING_MODE_SELECTIVE_DISPLAY) + { + while (src_bytes--) if (*dst++ == '\r') dst[-1] = '\n'; } - *consumed = produced; - - case CODING_EOL_CRLF: - { - unsigned char c; - unsigned char *src_end = source + src_bytes; - unsigned char *dst_end = destination + dst_bytes; - /* Since the maximum bytes produced by each loop is 2, we - subtract 1 from DST_END to assure overflow checking is - necessary only at the head of loop. */ - unsigned char *adjusted_dst_end = dst_end - 1; - - while (src < src_end && dst < adjusted_dst_end) - { - c = *src++; - if (c == '\n' || (c == '\r' && coding->selective)) - *dst++ = '\r', *dst++ = '\n'; - else - *dst++ = c; - } - produced = dst - destination; - *consumed = src - source; - break; - } - - default: /* i.e. case CODING_EOL_CR: */ - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - bcopy (source, destination, produced); - { - int i = produced; - while (i--) - if (*dst++ == '\n') dst[-1] = '\r'; - } - *consumed = produced; + src += src_bytes; + dst += src_bytes; } - return produced; + coding->consumed = coding->consumed_char = src - source; + coding->produced = coding->produced_char = dst - destination; + return result; } @@ -2317,67 +2634,23 @@ Lisp_Object coding_system; struct coding_system *coding; { - Lisp_Object coding_spec, plist, type, eol_type; + Lisp_Object coding_spec, coding_type, eol_type, plist; Lisp_Object val; int i; - /* At first, set several fields to default values. */ - coding->last_block = 0; - coding->selective = 0; - coding->composing = 0; - coding->direction = 0; - coding->carryover_size = 0; + /* Initialize some fields required for all kinds of coding systems. */ + coding->symbol = coding_system; + coding->common_flags = 0; + coding->mode = 0; + coding->heading_ascii = -1; coding->post_read_conversion = coding->pre_write_conversion = Qnil; - coding->character_unification_table_for_decode = Qnil; - coding->character_unification_table_for_encode = Qnil; - - coding->symbol = coding_system; - eol_type = Qnil; - - /* Get values of property `coding-system' and `eol-type'. - Also get values of coding system properties: - `post-read-conversion', `pre-write-conversion', - `character-unification-table-for-decode', - `character-unification-table-for-encode'. */ coding_spec = Fget (coding_system, Qcoding_system); if (!VECTORP (coding_spec) || XVECTOR (coding_spec)->size != 5 || !CONSP (XVECTOR (coding_spec)->contents[3])) goto label_invalid_coding_system; - if (!inhibit_eol_conversion) - eol_type = Fget (coding_system, Qeol_type); - - plist = XVECTOR (coding_spec)->contents[3]; - coding->post_read_conversion = Fplist_get (plist, Qpost_read_conversion); - coding->pre_write_conversion = Fplist_get (plist, Qpre_write_conversion); - val = Fplist_get (plist, Qcharacter_unification_table_for_decode); - if (SYMBOLP (val)) - val = Fget (val, Qcharacter_unification_table_for_decode); - coding->character_unification_table_for_decode - = CHAR_TABLE_P (val) ? val : Qnil; - val = Fplist_get (plist, Qcharacter_unification_table_for_encode); - if (SYMBOLP (val)) - val = Fget (val, Qcharacter_unification_table_for_encode); - coding->character_unification_table_for_encode - = CHAR_TABLE_P (val) ? val : Qnil; - - val = Fplist_get (plist, Qsafe_charsets); - if (EQ (val, Qt)) - { - for (i = 0; i <= MAX_CHARSET; i++) - coding->safe_charsets[i] = 1; - } - else - { - bzero (coding->safe_charsets, MAX_CHARSET + 1); - while (CONSP (val)) - { - if ((i = get_charset_id (XCONS (val)->car)) >= 0) - coding->safe_charsets[i] = 1; - val = XCONS (val)->cdr; - } - } - + + eol_type = inhibit_eol_conversion ? Qnil : Fget (coding_system, Qeol_type); if (VECTORP (eol_type)) { coding->eol_type = CODING_EOL_UNDECIDED; @@ -2396,13 +2669,74 @@ = CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; } else + coding->eol_type = CODING_EOL_LF; + + coding_type = XVECTOR (coding_spec)->contents[0]; + /* Try short cut. */ + if (SYMBOLP (coding_type)) { - coding->eol_type = CODING_EOL_LF; - coding->common_flags = 0; + if (EQ (coding_type, Qt)) + { + coding->type = coding_type_undecided; + coding->common_flags |= CODING_REQUIRE_DETECTION_MASK; + } + else + coding->type = coding_type_no_conversion; + return 0; } - type = XVECTOR (coding_spec)->contents[0]; - switch (XFASTINT (type)) + /* Initialize remaining fields. */ + coding->composing = 0; + coding->character_unification_table_for_decode = Qnil; + coding->character_unification_table_for_encode = Qnil; + + /* Get values of coding system properties: + `post-read-conversion', `pre-write-conversion', + `character-unification-table-for-decode', + `character-unification-table-for-encode'. */ + plist = XVECTOR (coding_spec)->contents[3]; + coding->post_read_conversion = Fplist_get (plist, Qpost_read_conversion); + coding->pre_write_conversion = Fplist_get (plist, Qpre_write_conversion); + val = Fplist_get (plist, Qcharacter_unification_table_for_decode); + if (SYMBOLP (val)) + val = Fget (val, Qcharacter_unification_table_for_decode); + coding->character_unification_table_for_decode + = CHAR_TABLE_P (val) ? val : Qnil; + val = Fplist_get (plist, Qcharacter_unification_table_for_encode); + if (SYMBOLP (val)) + val = Fget (val, Qcharacter_unification_table_for_encode); + coding->character_unification_table_for_encode + = CHAR_TABLE_P (val) ? val : Qnil; + val = Fplist_get (plist, Qcoding_category); + if (!NILP (val)) + { + val = Fget (val, Qcoding_category_index); + if (INTEGERP (val)) + coding->category_idx = XINT (val); + else + goto label_invalid_coding_system; + } + else + goto label_invalid_coding_system; + + val = Fplist_get (plist, Qsafe_charsets); + if (EQ (val, Qt)) + { + for (i = 0; i <= MAX_CHARSET; i++) + coding->safe_charsets[i] = 1; + } + else + { + bzero (coding->safe_charsets, MAX_CHARSET + 1); + while (CONSP (val)) + { + if ((i = get_charset_id (XCONS (val)->car)) >= 0) + coding->safe_charsets[i] = 1; + val = XCONS (val)->cdr; + } + } + + switch (XFASTINT (coding_type)) { case 0: coding->type = coding_type_emacs_mule; @@ -2425,7 +2759,7 @@ { Lisp_Object val, temp; Lisp_Object *flags; - int i, charset, default_reg_bits = 0; + int i, charset, reg_bits = 0; val = XVECTOR (coding_spec)->contents[4]; @@ -2480,7 +2814,7 @@ list of integer, nil, or t: designate the first element (if integer) to REG initially, the remaining elements (if integer) is designated to REG on request, - if an element is t, REG can be used by any charset, + if an element is t, REG can be used by any charsets, nil: REG is never used. */ for (charset = 0; charset <= MAX_CHARSET; charset++) CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) @@ -2497,12 +2831,14 @@ else if (EQ (flags[i], Qt)) { CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1; - default_reg_bits |= 1 << i; + reg_bits |= 1 << i; + coding->flags |= CODING_FLAG_ISO_DESIGNATION; } else if (CONSP (flags[i])) { Lisp_Object tail = flags[i]; + coding->flags |= CODING_FLAG_ISO_DESIGNATION; if (INTEGERP (XCONS (tail)->car) && (charset = XINT (XCONS (tail)->car), CHARSET_VALID_P (charset)) @@ -2523,7 +2859,7 @@ CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) = i; else if (EQ (XCONS (tail)->car, Qt)) - default_reg_bits |= 1 << i; + reg_bits |= 1 << i; tail = XCONS (tail)->cdr; } } @@ -2534,46 +2870,39 @@ = CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i); } - if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT)) + if (reg_bits && ! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT)) { /* REG 1 can be used only by locking shift in 7-bit env. */ if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) - default_reg_bits &= ~2; + reg_bits &= ~2; if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) /* Without any shifting, only REG 0 and 1 can be used. */ - default_reg_bits &= 3; + reg_bits &= 3; } - for (charset = 0; charset <= MAX_CHARSET; charset++) - if (CHARSET_VALID_P (charset) - && (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) - == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)) + if (reg_bits) + for (charset = 0; charset <= MAX_CHARSET; charset++) { - /* We have not yet decided where to designate CHARSET. */ - int reg_bits = default_reg_bits; - - if (CHARSET_CHARS (charset) == 96) - /* A charset of CHARS96 can't be designated to REG 0. */ - reg_bits &= ~1; - - if (reg_bits) - /* There exist some default graphic register. */ - CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) - = (reg_bits & 1 - ? 0 : (reg_bits & 2 ? 1 : (reg_bits & 4 ? 2 : 3))); - else - /* We anyway have to designate CHARSET to somewhere. */ - CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) - = (CHARSET_CHARS (charset) == 94 - ? 0 - : ((coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT - || ! coding->flags & CODING_FLAG_ISO_SEVEN_BITS) - ? 1 - : (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT - ? 2 : 0))); + if (CHARSET_VALID_P (charset)) + { + /* There exist some default graphic registers to be + used CHARSET. */ + + /* We had better avoid designating a charset of + CHARS96 to REG 0 as far as possible. */ + if (CHARSET_CHARS (charset) == 96) + CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) + = (reg_bits & 2 + ? 1 : (reg_bits & 4 ? 2 : (reg_bits & 8 ? 3 : 0))); + else + CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) + = (reg_bits & 1 + ? 0 : (reg_bits & 2 ? 1 : (reg_bits & 4 ? 2 : 3))); + } } } coding->common_flags |= CODING_REQUIRE_FLUSHING_MASK; + coding->spec.iso2022.last_invalid_designation_register = -1; break; case 3: @@ -2610,23 +2939,16 @@ break; default: - if (EQ (type, Qt)) - { - coding->type = coding_type_undecided; - coding->common_flags |= CODING_REQUIRE_DETECTION_MASK; - } - else - coding->type = coding_type_no_conversion; - break; + goto label_invalid_coding_system; } return 0; label_invalid_coding_system: coding->type = coding_type_no_conversion; + coding->category_idx = CODING_CATEGORY_IDX_BINARY; coding->common_flags = 0; coding->eol_type = CODING_EOL_LF; - coding->symbol = coding->pre_write_conversion = coding->post_read_conversion - = Qnil; + coding->pre_write_conversion = coding->post_read_conversion = Qnil; return -1; } @@ -2652,8 +2974,14 @@ The category for a coding system which has the same code range as ISO2022 of 7-bit environment. This doesn't use any locking - shift and single shift functions. Assigned the coding-system - (Lisp symbol) `iso-2022-7bit' by default. + shift and single shift functions. This can encode/decode all + charsets. Assigned the coding-system (Lisp symbol) + `iso-2022-7bit' by default. + + o coding-category-iso-7-tight + + Same as coding-category-iso-7 except that this can + encode/decode only the specified charsets. o coding-category-iso-8-1 @@ -2707,19 +3035,23 @@ */ -/* Detect how a text of length SRC_BYTES pointed by SRC is encoded. +/* Detect how a text of length SRC_BYTES pointed by SOURCE is encoded. If it detects possible coding systems, return an integer in which appropriate flag bits are set. Flag bits are defined by macros - CODING_CATEGORY_MASK_XXX in `coding.h'. */ - -int -detect_coding_mask (src, src_bytes) - unsigned char *src; - int src_bytes; + CODING_CATEGORY_MASK_XXX in `coding.h'. + + How many ASCII characters are at the head is returned as *SKIP. */ + +static int +detect_coding_mask (source, src_bytes, priorities, skip) + unsigned char *source; + int src_bytes, *priorities, *skip; { register unsigned char c; - unsigned char *src_end = src + src_bytes; - int mask; + unsigned char *src = source, *src_end = source + src_bytes; + unsigned int mask = (CODING_CATEGORY_MASK_ISO_7BIT + | CODING_CATEGORY_MASK_ISO_SHIFT); + int i; /* At first, skip all ASCII characters and control characters except for three ISO2022 specific control characters. */ @@ -2728,14 +3060,18 @@ { c = *src; if (c >= 0x80 - || (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)) + || ((mask & CODING_CATEGORY_MASK_ISO_7BIT) + && c == ISO_CODE_ESC) + || ((mask & CODING_CATEGORY_MASK_ISO_SHIFT) + && (c == ISO_CODE_SI || c == ISO_CODE_SO))) break; src++; } + *skip = src - source; if (src >= src_end) /* We found nothing other than ASCII. There's nothing to do. */ - return CODING_CATEGORY_MASK_ANY; + return 0; /* The text seems to be encoded in some multilingual coding system. Now, try to find in which coding system the text is encoded. */ @@ -2744,49 +3080,90 @@ /* i.e. (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO) */ /* C is an ISO2022 specific control code of C0. */ mask = detect_coding_iso2022 (src, src_end); - src++; if (mask == 0) - /* No valid ISO2022 code follows C. Try again. */ - goto label_loop_detect_coding; - mask |= CODING_CATEGORY_MASK_RAW_TEXT; - } - else if (c < 0xA0) - { - /* If C is a special latin extra code, - or is an ISO2022 specific control code of C1 (SS2 or SS3), - or is an ISO2022 control-sequence-introducer (CSI), - we should also consider the possibility of ISO2022 codings. */ - if ((VECTORP (Vlatin_extra_code_table) - && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) - || (c == ISO_CODE_SS2 || c == ISO_CODE_SS3) - || (c == ISO_CODE_CSI - && (src < src_end - && (*src == ']' - || (src + 1 < src_end - && src[1] == ']' - && (*src == '0' || *src == '1' || *src == '2')))))) - mask = (detect_coding_iso2022 (src, src_end) - | detect_coding_sjis (src, src_end) - | detect_coding_emacs_mule (src, src_end) - | CODING_CATEGORY_MASK_RAW_TEXT); - - else - /* C is the first byte of SJIS character code, - or a leading-code of Emacs' internal format (emacs-mule). */ - mask = (detect_coding_sjis (src, src_end) - | detect_coding_emacs_mule (src, src_end) - | CODING_CATEGORY_MASK_RAW_TEXT); + { + /* No valid ISO2022 code follows C. Try again. */ + src++; + mask = (c != ISO_CODE_ESC + ? CODING_CATEGORY_MASK_ISO_7BIT + : CODING_CATEGORY_MASK_ISO_SHIFT); + goto label_loop_detect_coding; + } + if (priorities) + goto label_return_highest_only; } else - /* C is a character of ISO2022 in graphic plane right, - or a SJIS's 1-byte character code (i.e. JISX0201), - or the first byte of BIG5's 2-byte code. */ - mask = (detect_coding_iso2022 (src, src_end) - | detect_coding_sjis (src, src_end) - | detect_coding_big5 (src, src_end) - | CODING_CATEGORY_MASK_RAW_TEXT); - - return mask; + { + int try; + + if (c < 0xA0) + { + /* C is the first byte of SJIS character code, + or a leading-code of Emacs' internal format (emacs-mule). */ + try = CODING_CATEGORY_MASK_SJIS | CODING_CATEGORY_MASK_EMACS_MULE; + + /* Or, if C is a special latin extra code, + or is an ISO2022 specific control code of C1 (SS2 or SS3), + or is an ISO2022 control-sequence-introducer (CSI), + we should also consider the possibility of ISO2022 codings. */ + if ((VECTORP (Vlatin_extra_code_table) + && !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) + || (c == ISO_CODE_SS2 || c == ISO_CODE_SS3) + || (c == ISO_CODE_CSI + && (src < src_end + && (*src == ']' + || ((*src == '0' || *src == '1' || *src == '2') + && src + 1 < src_end + && src[1] == ']'))))) + try |= (CODING_CATEGORY_MASK_ISO_8_ELSE + | CODING_CATEGORY_MASK_ISO_8BIT); + } + else + /* C is a character of ISO2022 in graphic plane right, + or a SJIS's 1-byte character code (i.e. JISX0201), + or the first byte of BIG5's 2-byte code. */ + try = (CODING_CATEGORY_MASK_ISO_8_ELSE + | CODING_CATEGORY_MASK_ISO_8BIT + | CODING_CATEGORY_MASK_SJIS + | CODING_CATEGORY_MASK_BIG5); + + mask = 0; + if (priorities) + { + for (i = 0; i < CODING_CATEGORY_IDX_MAX; i++) + { + priorities[i] &= try; + if (priorities[i] & CODING_CATEGORY_MASK_ISO) + mask = detect_coding_iso2022 (src, src_end); + else if (priorities[i] & CODING_CATEGORY_MASK_SJIS) + mask = detect_coding_sjis (src, src_end); + else if (priorities[i] & CODING_CATEGORY_MASK_BIG5) + mask = detect_coding_big5 (src, src_end); + else if (priorities[i] & CODING_CATEGORY_MASK_EMACS_MULE) + mask = detect_coding_emacs_mule (src, src_end); + if (mask) + goto label_return_highest_only; + } + return CODING_CATEGORY_MASK_RAW_TEXT; + } + if (try & CODING_CATEGORY_MASK_ISO) + mask |= detect_coding_iso2022 (src, src_end); + if (try & CODING_CATEGORY_MASK_SJIS) + mask |= detect_coding_sjis (src, src_end); + if (try & CODING_CATEGORY_MASK_BIG5) + mask |= detect_coding_big5 (src, src_end); + if (try & CODING_CATEGORY_MASK_EMACS_MULE) + mask |= detect_coding_emacs_mule (src, src_end); + } + return (mask | CODING_CATEGORY_MASK_RAW_TEXT); + + label_return_highest_only: + for (i = 0; i < CODING_CATEGORY_IDX_MAX; i++) + { + if (mask & priorities[i]) + return priorities[i]; + } + return CODING_CATEGORY_MASK_RAW_TEXT; } /* Detect how a text of length SRC_BYTES pointed by SRC is encoded. @@ -2798,61 +3175,81 @@ unsigned char *src; int src_bytes; { - int mask = detect_coding_mask (src, src_bytes); - int idx; + unsigned int idx; + int skip, mask, i; + int priorities[CODING_CATEGORY_IDX_MAX]; Lisp_Object val = Vcoding_category_list; - if (mask == CODING_CATEGORY_MASK_ANY) - /* We found nothing other than ASCII. There's nothing to do. */ - return; - - /* We found some plausible coding systems. Let's use a coding - system of the highest priority. */ - - if (CONSP (val)) - while (!NILP (val)) - { - idx = XFASTINT (Fget (XCONS (val)->car, Qcoding_category_index)); - if ((idx < CODING_CATEGORY_IDX_MAX) && (mask & (1 << idx))) - break; - val = XCONS (val)->cdr; - } - else - val = Qnil; - - if (NILP (val)) + i = 0; + while (CONSP (val) && i < CODING_CATEGORY_IDX_MAX) { - /* For unknown reason, `Vcoding_category_list' contains none of - found categories. Let's use any of them. */ - for (idx = 0; idx < CODING_CATEGORY_IDX_MAX; idx++) - if (mask & (1 << idx)) - break; + if (! SYMBOLP (XCONS (val)->car)) + break; + idx = XFASTINT (Fget (XCONS (val)->car, Qcoding_category_index)); + if (idx >= CODING_CATEGORY_IDX_MAX) + break; + priorities[i++] = (1 << idx); + val = XCONS (val)->cdr; } - setup_coding_system (XSYMBOL (coding_category_table[idx])->value, coding); + /* If coding-category-list is valid and contains all coding + categories, `i' should be CODING_CATEGORY_IDX_MAX now. If not, + the following code saves Emacs from craching. */ + while (i < CODING_CATEGORY_IDX_MAX) + priorities[i++] = CODING_CATEGORY_MASK_RAW_TEXT; + + mask = detect_coding_mask (src, src_bytes, priorities, &skip); + coding->heading_ascii = skip; + + if (!mask) return; + + /* We found a single coding system of the highest priority in MASK. */ + idx = 0; + while (mask && ! (mask & 1)) mask >>= 1, idx++; + if (! mask) + idx = CODING_CATEGORY_IDX_RAW_TEXT; + + val = XSYMBOL (XVECTOR (Vcoding_category_table)->contents[idx])->value; + + if (coding->eol_type != CODING_EOL_UNDECIDED) + { + Lisp_Object tmp = Fget (val, Qeol_type); + + if (VECTORP (tmp)) + val = XVECTOR (tmp)->contents[coding->eol_type]; + } + setup_coding_system (val, coding); + /* Set this again because setup_coding_system reset this member. */ + coding->heading_ascii = skip; } -/* Detect how end-of-line of a text of length SRC_BYTES pointed by SRC - is encoded. Return one of CODING_EOL_LF, CODING_EOL_CRLF, - CODING_EOL_CR, and CODING_EOL_UNDECIDED. */ +/* Detect how end-of-line of a text of length SRC_BYTES pointed by + SOURCE is encoded. Return one of CODING_EOL_LF, CODING_EOL_CRLF, + CODING_EOL_CR, and CODING_EOL_UNDECIDED. + + How many non-eol characters are at the head is returned as *SKIP. */ #define MAX_EOL_CHECK_COUNT 3 -int -detect_eol_type (src, src_bytes) - unsigned char *src; - int src_bytes; +static int +detect_eol_type (source, src_bytes, skip) + unsigned char *source; + int src_bytes, *skip; { - unsigned char *src_end = src + src_bytes; + unsigned char *src = source, *src_end = src + src_bytes; unsigned char c; int total = 0; /* How many end-of-lines are found so far. */ int eol_type = CODING_EOL_UNDECIDED; int this_eol_type; + *skip = 0; + while (src < src_end && total < MAX_EOL_CHECK_COUNT) { c = *src++; if (c == '\n' || c == '\r') { + if (*skip == 0) + *skip = src - 1 - source; total++; if (c == '\n') this_eol_type = CODING_EOL_LF; @@ -2865,12 +3262,16 @@ /* This is the first end-of-line. */ eol_type = this_eol_type; else if (eol_type != this_eol_type) - /* The found type is different from what found before. - Let's notice the caller about this inconsistency. */ - return CODING_EOL_INCONSISTENT; + { + /* The found type is different from what found before. */ + eol_type = CODING_EOL_INCONSISTENT; + break; + } } } + if (*skip == 0) + *skip = src_end - source; return eol_type; } @@ -2885,12 +3286,16 @@ int src_bytes; { Lisp_Object val; - int eol_type = detect_eol_type (src, src_bytes); + int skip; + int eol_type = detect_eol_type (src, src_bytes, &skip); + + if (coding->heading_ascii > skip) + coding->heading_ascii = skip; + else + skip = coding->heading_ascii; if (eol_type == CODING_EOL_UNDECIDED) - /* We found no end-of-line in the source text. */ return; - if (eol_type == CODING_EOL_INCONSISTENT) { #if 0 @@ -2911,147 +3316,25 @@ val = Fget (coding->symbol, Qeol_type); if (VECTORP (val) && XVECTOR (val)->size == 3) - setup_coding_system (XVECTOR (val)->contents[eol_type], coding); -} - -/* See "GENERAL NOTES about `decode_coding_XXX ()' functions". Before - decoding, it may detect coding system and format of end-of-line if - those are not yet decided. */ - -int -decode_coding (coding, source, destination, src_bytes, dst_bytes, consumed) - struct coding_system *coding; - unsigned char *source, *destination; - int src_bytes, dst_bytes; - int *consumed; -{ - int produced; - - if (src_bytes <= 0) { - *consumed = 0; - return 0; + setup_coding_system (XVECTOR (val)->contents[eol_type], coding); + coding->heading_ascii = skip; } - - if (coding->type == coding_type_undecided) - detect_coding (coding, source, src_bytes); - - if (coding->eol_type == CODING_EOL_UNDECIDED) - detect_eol (coding, source, src_bytes); - - coding->carryover_size = 0; - switch (coding->type) - { - case coding_type_no_conversion: - label_no_conversion: - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - bcopy (source, destination, produced); - *consumed = produced; - break; - - case coding_type_emacs_mule: - case coding_type_undecided: - case coding_type_raw_text: - if (coding->eol_type == CODING_EOL_LF - || coding->eol_type == CODING_EOL_UNDECIDED) - goto label_no_conversion; - produced = decode_eol (coding, source, destination, - src_bytes, dst_bytes, consumed); - break; - - case coding_type_sjis: - produced = decode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, - 1); - break; - - case coding_type_iso2022: - produced = decode_coding_iso2022 (coding, source, destination, - src_bytes, dst_bytes, consumed); - break; - - case coding_type_big5: - produced = decode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, - 0); - break; - - case coding_type_ccl: - produced = ccl_driver (&coding->spec.ccl.decoder, source, destination, - src_bytes, dst_bytes, consumed); - break; - } - - return produced; -} - -/* See "GENERAL NOTES about `encode_coding_XXX ()' functions". */ - -int -encode_coding (coding, source, destination, src_bytes, dst_bytes, consumed) - struct coding_system *coding; - unsigned char *source, *destination; - int src_bytes, dst_bytes; - int *consumed; -{ - int produced; - - switch (coding->type) - { - case coding_type_no_conversion: - label_no_conversion: - produced = (src_bytes > dst_bytes) ? dst_bytes : src_bytes; - if (produced > 0) - { - bcopy (source, destination, produced); - if (coding->selective) - { - unsigned char *p = destination, *pend = destination + produced; - while (p < pend) - if (*p++ == '\015') p[-1] = '\n'; - } - } - *consumed = produced; - break; - - case coding_type_emacs_mule: - case coding_type_undecided: - case coding_type_raw_text: - if (coding->eol_type == CODING_EOL_LF - || coding->eol_type == CODING_EOL_UNDECIDED) - goto label_no_conversion; - produced = encode_eol (coding, source, destination, - src_bytes, dst_bytes, consumed); - break; - - case coding_type_sjis: - produced = encode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, - 1); - break; - - case coding_type_iso2022: - produced = encode_coding_iso2022 (coding, source, destination, - src_bytes, dst_bytes, consumed); - break; - - case coding_type_big5: - produced = encode_coding_sjis_big5 (coding, source, destination, - src_bytes, dst_bytes, consumed, - 0); - break; - - case coding_type_ccl: - produced = ccl_driver (&coding->spec.ccl.encoder, source, destination, - src_bytes, dst_bytes, consumed); - break; - } - - return produced; } #define CONVERSION_BUFFER_EXTRA_ROOM 256 +#define DECODING_BUFFER_MAG(coding) \ + (coding->type == coding_type_iso2022 \ + ? 3 \ + : ((coding->type == coding_type_sjis || coding->type == coding_type_big5) \ + ? 2 \ + : (coding->type == coding_type_raw_text \ + ? 1 \ + : (coding->type == coding_type_ccl \ + ? coding->spec.ccl.decoder.buf_magnification \ + : 2)))) + /* Return maximum size (bytes) of a buffer enough for decoding SRC_BYTES of text encoded in CODING. */ @@ -3060,16 +3343,8 @@ struct coding_system *coding; int src_bytes; { - int magnification; - - if (coding->type == coding_type_iso2022) - magnification = 3; - else if (coding->type == coding_type_ccl) - magnification = coding->spec.ccl.decoder.buf_magnification; - else - magnification = 2; - - return (src_bytes * magnification + CONVERSION_BUFFER_EXTRA_ROOM); + return (src_bytes * DECODING_BUFFER_MAG (coding) + + CONVERSION_BUFFER_EXTRA_ROOM); } /* Return maximum size (bytes) of a buffer enough for encoding @@ -3119,6 +3394,780 @@ return conversion_buffer; } +int +ccl_coding_driver (coding, source, destination, src_bytes, dst_bytes, encodep) + struct coding_system *coding; + unsigned char *source, *destination; + int src_bytes, dst_bytes, encodep; +{ + struct ccl_program *ccl + = encodep ? &coding->spec.ccl.encoder : &coding->spec.ccl.decoder; + int result; + + coding->produced = ccl_driver (ccl, source, destination, + src_bytes, dst_bytes, &(coding->consumed)); + if (encodep) + { + coding->produced_char = coding->produced; + coding->consumed_char + = multibyte_chars_in_text (source, coding->consumed); + } + else + { + coding->produced_char + = multibyte_chars_in_text (destination, coding->produced); + coding->consumed_char = coding->consumed; + } + switch (ccl->status) + { + case CCL_STAT_SUSPEND_BY_SRC: + result = CODING_FINISH_INSUFFICIENT_SRC; + break; + case CCL_STAT_SUSPEND_BY_DST: + result = CODING_FINISH_INSUFFICIENT_DST; + break; + default: + result = CODING_FINISH_NORMAL; + break; + } + return result; +} + +/* See "GENERAL NOTES about `decode_coding_XXX ()' functions". Before + decoding, it may detect coding system and format of end-of-line if + those are not yet decided. */ + +int +decode_coding (coding, source, destination, src_bytes, dst_bytes) + struct coding_system *coding; + unsigned char *source, *destination; + int src_bytes, dst_bytes; +{ + int result; + + if (src_bytes <= 0) + { + coding->produced = coding->produced_char = 0; + coding->consumed = coding->consumed_char = 0; + return CODING_FINISH_NORMAL; + } + + if (coding->type == coding_type_undecided) + detect_coding (coding, source, src_bytes); + + if (coding->eol_type == CODING_EOL_UNDECIDED) + detect_eol (coding, source, src_bytes); + + switch (coding->type) + { + case coding_type_emacs_mule: + case coding_type_undecided: + case coding_type_raw_text: + if (coding->eol_type == CODING_EOL_LF + || coding->eol_type == CODING_EOL_UNDECIDED) + goto label_no_conversion; + result = decode_eol (coding, source, destination, src_bytes, dst_bytes); + break; + + case coding_type_sjis: + result = decode_coding_sjis_big5 (coding, source, destination, + src_bytes, dst_bytes, 1); + break; + + case coding_type_iso2022: + result = decode_coding_iso2022 (coding, source, destination, + src_bytes, dst_bytes); + break; + + case coding_type_big5: + result = decode_coding_sjis_big5 (coding, source, destination, + src_bytes, dst_bytes, 0); + break; + + case coding_type_ccl: + result = ccl_coding_driver (coding, source, destination, + src_bytes, dst_bytes, 0); + break; + + default: /* i.e. case coding_type_no_conversion: */ + label_no_conversion: + if (dst_bytes && src_bytes > dst_bytes) + { + coding->produced = dst_bytes; + result = CODING_FINISH_INSUFFICIENT_DST; + } + else + { + coding->produced = src_bytes; + result = CODING_FINISH_NORMAL; + } + if (dst_bytes) + bcopy (source, destination, coding->produced); + else + safe_bcopy (source, destination, coding->produced); + coding->consumed + = coding->consumed_char = coding->produced_char = coding->produced; + break; + } + + return result; +} + +/* See "GENERAL NOTES about `encode_coding_XXX ()' functions". */ + +int +encode_coding (coding, source, destination, src_bytes, dst_bytes) + struct coding_system *coding; + unsigned char *source, *destination; + int src_bytes, dst_bytes; +{ + int result; + + if (src_bytes <= 0) + { + coding->produced = coding->produced_char = 0; + coding->consumed = coding->consumed_char = 0; + return CODING_FINISH_NORMAL; + } + + switch (coding->type) + { + case coding_type_emacs_mule: + case coding_type_undecided: + case coding_type_raw_text: + if (coding->eol_type == CODING_EOL_LF + || coding->eol_type == CODING_EOL_UNDECIDED) + goto label_no_conversion; + result = encode_eol (coding, source, destination, src_bytes, dst_bytes); + break; + + case coding_type_sjis: + result = encode_coding_sjis_big5 (coding, source, destination, + src_bytes, dst_bytes, 1); + break; + + case coding_type_iso2022: + result = encode_coding_iso2022 (coding, source, destination, + src_bytes, dst_bytes); + break; + + case coding_type_big5: + result = encode_coding_sjis_big5 (coding, source, destination, + src_bytes, dst_bytes, 0); + break; + + case coding_type_ccl: + result = ccl_coding_driver (coding, source, destination, + src_bytes, dst_bytes, 1); + break; + + default: /* i.e. case coding_type_no_conversion: */ + label_no_conversion: + if (dst_bytes && src_bytes > dst_bytes) + { + coding->produced = dst_bytes; + result = CODING_FINISH_INSUFFICIENT_DST; + } + else + { + coding->produced = src_bytes; + result = CODING_FINISH_NORMAL; + } + if (dst_bytes) + bcopy (source, destination, coding->produced); + else + safe_bcopy (source, destination, coding->produced); + if (coding->mode & CODING_MODE_SELECTIVE_DISPLAY) + { + unsigned char *p = destination, *pend = p + coding->produced; + while (p < pend) + if (*p++ == '\015') p[-1] = '\n'; + } + coding->consumed + = coding->consumed_char = coding->produced_char = coding->produced; + break; + } + + return result; +} + +/* Scan text in the region between *BEG and *END, skip characters + which we don't have to decode by coding system CODING at the head + and tail, then set *BEG and *END to the region of the text we + actually have to convert. + + If STR is not NULL, *BEG and *END are indices into STR. */ + +static void +shrink_decoding_region (beg, end, coding, str) + int *beg, *end; + struct coding_system *coding; + unsigned char *str; +{ + unsigned char *begp_orig, *begp, *endp_orig, *endp; + int eol_conversion; + + if (coding->type == coding_type_ccl + || coding->type == coding_type_undecided + || !NILP (coding->post_read_conversion)) + { + /* We can't skip any data. */ + return; + } + else if (coding->type == coding_type_no_conversion) + { + /* We need no conversion. */ + *beg = *end; + return; + } + + if (coding->heading_ascii >= 0) + /* Detection routine has already found how much we can skip at the + head. */ + *beg += coding->heading_ascii; + + if (str) + { + begp_orig = begp = str + *beg; + endp_orig = endp = str + *end; + } + else + { + move_gap (*beg); + begp_orig = begp = GAP_END_ADDR; + endp_orig = endp = begp + *end - *beg; + } + + eol_conversion = (coding->eol_type != CODING_EOL_LF); + + switch (coding->type) + { + case coding_type_emacs_mule: + case coding_type_raw_text: + if (eol_conversion) + { + if (coding->heading_ascii < 0) + while (begp < endp && *begp != '\r') begp++; + while (begp < endp && *(endp - 1) != '\r') endp--; + } + else + begp = endp; + break; + + case coding_type_sjis: + case coding_type_big5: + /* We can skip all ASCII characters at the head. */ + if (coding->heading_ascii < 0) + { + if (eol_conversion) + while (begp < endp && *begp < 0x80 && *begp != '\n') begp++; + else + while (begp < endp && *begp < 0x80) begp++; + } + /* We can skip all ASCII characters at the tail except for the + second byte of SJIS or BIG5 code. */ + if (eol_conversion) + while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\n') endp--; + else + while (begp < endp && endp[-1] < 0x80) endp--; + if (begp < endp && endp < endp_orig && endp[-1] >= 0x80) + endp++; + break; + + default: /* i.e. case coding_type_iso2022: */ + if (coding->heading_ascii < 0) + { + unsigned char c; + + /* We can skip all ASCII characters at the head except for a + few control codes. */ + while (begp < endp && (c = *begp) < 0x80 + && c != ISO_CODE_CR && c != ISO_CODE_SO + && c != ISO_CODE_SI && c != ISO_CODE_ESC + && (!eol_conversion || c != ISO_CODE_LF)) + begp++; + } + switch (coding->category_idx) + { + case CODING_CATEGORY_IDX_ISO_8_1: + case CODING_CATEGORY_IDX_ISO_8_2: + /* We can skip all ASCII characters at the tail. */ + if (eol_conversion) + while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\n') endp--; + else + while (begp < endp && endp[-1] < 0x80) endp--; + break; + + case CODING_CATEGORY_IDX_ISO_7: + case CODING_CATEGORY_IDX_ISO_7_TIGHT: + /* We can skip all charactes at the tail except for ESC and + the following 2-byte at the tail. */ + if (eol_conversion) + while (begp < endp && endp[-1] != ISO_CODE_ESC && endp[-1] != '\n') + endp--; + else + while (begp < endp && endp[-1] != ISO_CODE_ESC) + endp--; + if (begp < endp && endp[-1] == ISO_CODE_ESC) + { + if (endp + 1 < endp_orig && end[0] == '(' && end[1] == 'B') + /* This is an ASCII designation sequence. We can + surely skip the tail. */ + endp += 2; + else + /* Hmmm, we can't skip the tail. */ + endp = endp_orig; + } + } + } + *beg += begp - begp_orig; + *end += endp - endp_orig; + return; +} + +/* Like shrink_decoding_region but for encoding. */ + +static void +shrink_encoding_region (beg, end, coding, str) + int *beg, *end; + struct coding_system *coding; + unsigned char *str; +{ + unsigned char *begp_orig, *begp, *endp_orig, *endp; + int eol_conversion; + + if (coding->type == coding_type_ccl) + /* We can't skip any data. */ + return; + else if (coding->type == coding_type_no_conversion) + { + /* We need no conversion. */ + *beg = *end; + return; + } + + if (str) + { + begp_orig = begp = str + *beg; + endp_orig = endp = str + *end; + } + else + { + move_gap (*beg); + begp_orig = begp = GAP_END_ADDR; + endp_orig = endp = begp + *end - *beg; + } + + eol_conversion = (coding->eol_type == CODING_EOL_CR + || coding->eol_type == CODING_EOL_CRLF); + + /* Here, we don't have to check coding->pre_write_conversion because + the caller is expected to have handled it already. */ + switch (coding->type) + { + case coding_type_undecided: + case coding_type_emacs_mule: + case coding_type_raw_text: + if (eol_conversion) + { + while (begp < endp && *begp != '\n') begp++; + while (begp < endp && endp[-1] != '\n') endp--; + } + else + begp = endp; + break; + + case coding_type_iso2022: + if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL) + { + unsigned char *bol = begp; + while (begp < endp && *begp < 0x80) + { + begp++; + if (begp[-1] == '\n') + bol = begp; + } + begp = bol; + goto label_skip_tail; + } + /* fall down ... */ + + default: + /* We can skip all ASCII characters at the head and tail. */ + if (eol_conversion) + while (begp < endp && *begp < 0x80 && *begp != '\n') begp++; + else + while (begp < endp && *begp < 0x80) begp++; + label_skip_tail: + if (eol_conversion) + while (begp < endp && endp[-1] < 0x80 && endp[-1] != '\n') endp--; + else + while (begp < endp && *(endp - 1) < 0x80) endp--; + break; + } + + *beg += begp - begp_orig; + *end += endp - endp_orig; + return; +} + +/* Decode (if ENCODEP is zero) or encode (if ENCODEP is nonzero) the + text from FROM to TO by coding system CODING, and return number of + characters in the resulting text. + + If ADJUST is nonzero, we do various things as if the original text + is deleted and a new text is inserted. See the comments in + replace_range (insdel.c) to know what we are doing. + + ADJUST nonzero also means that post-read-conversion or + pre-write-conversion functions (if any) should be processed. */ + +int +code_convert_region (from, to, coding, encodep, adjust) + int from, to, encodep, adjust; + struct coding_system *coding; +{ + int len = to - from, require, inserted, inserted_byte; + int from_byte, to_byte, len_byte; + int from_byte_orig, to_byte_orig; + Lisp_Object saved_coding_symbol = Qnil; + + if (adjust) + { + prepare_to_modify_buffer (from, to, &from); + to = from + len; + } + from_byte = CHAR_TO_BYTE (from); to_byte = CHAR_TO_BYTE (to); + len_byte = from_byte - to_byte; + + if (! encodep && CODING_REQUIRE_DETECTION (coding)) + { + /* We must detect encoding of text and eol. Even if detection + routines can't decide the encoding, we should not let them + undecided because the deeper decoding routine (decode_coding) + tries to detect the encodings in vain in that case. */ + + if (from < GPT && to > GPT) + move_gap_both (from, from_byte); + if (coding->type == coding_type_undecided) + { + detect_coding (coding, BYTE_POS_ADDR (from), len); + if (coding->type == coding_type_undecided) + coding->type = coding_type_emacs_mule; + } + if (coding->eol_type == CODING_EOL_UNDECIDED) + { + saved_coding_symbol = coding->symbol; + detect_eol (coding, BYTE_POS_ADDR (from_byte), len_byte); + if (coding->eol_type == CODING_EOL_UNDECIDED) + coding->eol_type = CODING_EOL_LF; + /* We had better recover the original eol format if we + encounter an inconsitent eol format while decoding. */ + coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; + } + } + + if (encodep + ? ! CODING_REQUIRE_ENCODING (coding) + : ! CODING_REQUIRE_DECODING (coding)) + return len; + + /* Now we convert the text. */ + + /* For encoding, we must process pre-write-conversion in advance. */ + if (encodep + && adjust + && ! NILP (coding->pre_write_conversion) + && SYMBOLP (coding->pre_write_conversion) + && ! NILP (Ffboundp (coding->pre_write_conversion))) + { + /* The function in pre-write-conversion put a new text in a new + buffer. */ + struct buffer *prev = current_buffer, *new; + + call2 (coding->pre_write_conversion, from, to); + if (current_buffer != prev) + { + len = ZV - BEGV; + new = current_buffer; + set_buffer_internal_1 (prev); + del_range (from, to); + insert_from_buffer (new, BEG, len, 0); + to = from + len; + to_byte = CHAR_TO_BYTE (to); + len_byte = to_byte - from_byte; + } + } + + /* Try to skip the heading and tailing ASCIIs. */ + from_byte_orig = from_byte; to_byte_orig = to_byte; + if (encodep) + shrink_encoding_region (&from_byte, &to_byte, coding, NULL); + else + shrink_decoding_region (&from_byte, &to_byte, coding, NULL); + if (from_byte == to_byte) + return len; + /* Here, the excluded region by shrinking contains only ASCIIs. */ + from += (from_byte - from_byte_orig); + to += (to_byte - to_byte_orig); + len = to - from; + len_byte = to_byte - from_byte; + + /* For converion, we must put the gap before the text to be decoded + in addition to make the gap larger for efficient decoding. The + required gap size starts from 2000 which is the magic number used + in make_gap. But, after one batch of conversion, it will be + incremented if we find that it is not enough . */ + require = 2000; + + if (GAP_SIZE < require) + make_gap (require - GAP_SIZE); + move_gap_both (from, from_byte); + + if (adjust) + adjust_before_replace (from, from_byte, to, to_byte); + + if (GPT - BEG < beg_unchanged) + beg_unchanged = GPT - BEG; + if (Z - GPT < end_unchanged) + end_unchanged = Z - GPT; + + inserted = inserted_byte = 0; + for (;;) + { + int result, diff_char, diff_byte; + + /* The buffer memory is changed from: + +--------+converted-text+------------+-----original-text-----+---+ + |<-from->|<--inserted-->|<-GAP_SIZE->|<---------len--------->|---| */ + + if (encodep) + result = encode_coding (coding, GAP_END_ADDR, GPT_ADDR, len_byte, 0); + else + result = decode_coding (coding, GAP_END_ADDR, GPT_ADDR, len_byte, 0); + /* to: + +--------+-------converted-text--------+--+---original-text--+---+ + |<-from->|<----(inserted+produced)---->|--|<-(len-consumed)->|---| */ + + diff_char = coding->produced_char - coding->consumed_char; + diff_byte = coding->produced - coding->consumed; + + GAP_SIZE -= diff_byte; + ZV += diff_char; ZV_BYTE += diff_byte; + Z += diff_char; Z_BYTE += diff_byte; + GPT += coding->produced_char; GPT_BYTE += coding->produced; + + inserted += coding->produced_char; + inserted_byte += coding->produced; + len -= coding->consumed_char; + len_byte -= coding->consumed; + + if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL) + { + unsigned char *p = GPT_ADDR - inserted_byte, *pend = GPT_ADDR; + + /* Encode LFs back to the original eol format (CR or CRLF). */ + if (coding->eol_type == CODING_EOL_CR) + { + while (p < pend) if (*p++ == '\n') p[-1] = '\r'; + } + else + { + unsigned char *p2 = p; + int count = 0; + + while (p2 < pend) if (*p2++ == '\n') count++; + if (GAP_SIZE < count) + make_gap (count - GAP_SIZE); + p2 = GPT_ADDR + count; + while (p < pend) + { + *--p2 = *--pend; + if (*pend == '\n') *--p2 = '\r'; + } + GPT += count; GAP_SIZE -= count; ZV += count; Z += count; + ZV_BYTE += count; Z_BYTE += count; + coding->produced += count; + coding->produced_char += count; + inserted += count; + inserted_byte += count; + } + + /* Suppress eol-format conversion in the further conversion. */ + coding->eol_type = CODING_EOL_LF; + + /* Restore the original symbol. */ + coding->symbol = saved_coding_symbol; + } + if (len_byte <= 0) + break; + if (result == CODING_FINISH_INSUFFICIENT_SRC) + { + /* The source text ends in invalid codes. Let's just + make them valid buffer contents, and finish conversion. */ + inserted += len; + inserted_byte += len_byte; + break; + } + if (inserted == coding->produced_char) + /* We have just done the first batch of conversion. Let's + reconsider the required gap size now. + + We have converted CONSUMED bytes into PRODUCED bytes. To + convert the remaining LEN bytes, we may need REQUIRE bytes + of gap, where: + REQUIRE + LEN = (LEN * PRODUCED / CONSUMED) + REQUIRE = LEN * (PRODUCED - CONSUMED) / CONSUMED + = LEN * DIFF / CONSUMED + Here, we are sure that DIFF is positive. */ + require = len_byte * diff_byte / coding->consumed; + if (GAP_SIZE < require) + make_gap (require - GAP_SIZE); + } + if (GAP_SIZE > 0) *GPT_ADDR = 0; /* Put an anchor. */ + + if (adjust) + { + adjust_after_replace (from, from_byte, to, to_byte, + inserted, inserted_byte); + + if (! encodep && ! NILP (coding->post_read_conversion)) + { + Lisp_Object val; + int orig_inserted = inserted, pos = PT; + + temp_set_point_both (current_buffer, from, from_byte); + val = call1 (coding->post_read_conversion, make_number (inserted)); + if (! NILP (val)) + { + CHECK_NUMBER (val, 0); + inserted = XFASTINT (val); + } + if (pos >= from + orig_inserted) + temp_set_point (current_buffer, pos + (inserted - orig_inserted)); + } + } + + return ((from_byte - from_byte_orig) + inserted + (to_byte_orig - to_byte)); +} + +Lisp_Object +code_convert_string (str, coding, encodep, nocopy) + Lisp_Object str; + struct coding_system *coding; + int encodep, nocopy; +{ + int len; + char *buf; + int from = 0, to = XSTRING (str)->size, to_byte = XSTRING (str)->size_byte; + struct gcpro gcpro1; + Lisp_Object saved_coding_symbol = Qnil; + int result; + + if (encodep && !NILP (coding->pre_write_conversion) + || !encodep && !NILP (coding->post_read_conversion)) + { + /* Since we have to call Lisp functions which assume target text + is in a buffer, after setting a temporary buffer, call + code_convert_region. */ + int count = specpdl_ptr - specpdl; + struct buffer *prev = current_buffer; + + record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); + temp_output_buffer_setup (" *code-converting-work*"); + set_buffer_internal (XBUFFER (Vstandard_output)); + if (encodep) + insert_from_string (str, 0, 0, to, to_byte, 0); + else + { + /* We must insert the contents of STR as is without + unibyte<->multibyte conversion. */ + current_buffer->enable_multibyte_characters = Qnil; + insert_from_string (str, 0, 0, to_byte, to_byte, 0); + current_buffer->enable_multibyte_characters = Qt; + } + code_convert_region (BEGV, ZV, coding, encodep, 1); + if (encodep) + /* We must return the buffer contents as unibyte string. */ + current_buffer->enable_multibyte_characters = Qnil; + str = make_buffer_string (BEGV, ZV, 0); + set_buffer_internal (prev); + return unbind_to (count, str); + } + + if (! encodep && CODING_REQUIRE_DETECTION (coding)) + { + /* See the comments in code_convert_region. */ + if (coding->type == coding_type_undecided) + { + detect_coding (coding, XSTRING (str)->data, to_byte); + if (coding->type == coding_type_undecided) + coding->type = coding_type_emacs_mule; + } + if (coding->eol_type == CODING_EOL_UNDECIDED) + { + saved_coding_symbol = coding->symbol; + detect_eol (coding, XSTRING (str)->data, to_byte); + if (coding->eol_type == CODING_EOL_UNDECIDED) + coding->eol_type = CODING_EOL_LF; + /* We had better recover the original eol format if we + encounter an inconsitent eol format while decoding. */ + coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; + } + } + + if (encodep + ? ! CODING_REQUIRE_ENCODING (coding) + : ! CODING_REQUIRE_DECODING (coding)) + from = to_byte; + else + { + /* Try to skip the heading and tailing ASCIIs. */ + if (encodep) + shrink_encoding_region (&from, &to_byte, coding, XSTRING (str)->data); + else + shrink_decoding_region (&from, &to_byte, coding, XSTRING (str)->data); + } + if (from == to_byte) + return (nocopy ? str : Fcopy_sequence (str)); + + if (encodep) + len = encoding_buffer_size (coding, to_byte - from); + else + len = decoding_buffer_size (coding, to_byte - from); + len += from + XSTRING (str)->size_byte - to_byte; + GCPRO1 (str); + buf = get_conversion_buffer (len); + UNGCPRO; + + if (from > 0) + bcopy (XSTRING (str)->data, buf, from); + result = (encodep + ? encode_coding (coding, XSTRING (str)->data + from, + buf + from, to_byte - from, len) + : decode_coding (coding, XSTRING (str)->data + from, + buf + from, to - from, len)); + if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL) + { + /* We simple try to decode the whole string again but without + eol-conversion this time. */ + coding->eol_type = CODING_EOL_LF; + coding->symbol = saved_coding_symbol; + return code_convert_string (str, coding, encodep, nocopy); + } + + bcopy (XSTRING (str)->data + to_byte, buf + from + coding->produced, + XSTRING (str)->size_byte - to_byte); + + len = from + XSTRING (str)->size_byte - to_byte; + if (encodep) + str = make_unibyte_string (buf, len + coding->produced); + else + str = make_multibyte_string (buf, len + coding->produced_char, + len + coding->produced); + return str; +} + #ifdef emacs /*** 7. Emacs Lisp library functions ***/ @@ -3187,465 +4236,173 @@ Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil)); } -DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region, - 2, 2, 0, - "Detect coding system of the text in the region between START and END.\n\ -Return a list of possible coding systems ordered by priority.\n\ -If only ASCII characters are found, it returns `undecided'\n\ - or its subsidiary coding system according to a detected end-of-line format.") - (b, e) - Lisp_Object b, e; +Lisp_Object +detect_coding_system (src, src_bytes, highest) + unsigned char *src; + int src_bytes, highest; { int coding_mask, eol_type; - Lisp_Object val; - int beg, end; - int beg_byte, end_byte; - - validate_region (&b, &e); - beg = XINT (b), end = XINT (e); - beg_byte = CHAR_TO_BYTE (beg); - end_byte = CHAR_TO_BYTE (end); - - if (beg < GPT && end >= GPT) - move_gap_both (end, end_byte); - - coding_mask = detect_coding_mask (BYTE_POS_ADDR (beg_byte), - end_byte - beg_byte); - eol_type = detect_eol_type (BYTE_POS_ADDR (beg_byte), end_byte - beg_byte); - - if (coding_mask == CODING_CATEGORY_MASK_ANY) + Lisp_Object val, tmp; + int dummy; + + coding_mask = detect_coding_mask (src, src_bytes, NULL, &dummy); + eol_type = detect_eol_type (src, src_bytes, &dummy); + if (eol_type == CODING_EOL_INCONSISTENT) + eol_type == CODING_EOL_UNDECIDED; + + if (!coding_mask) { val = Qundecided; - if (eol_type != CODING_EOL_UNDECIDED - && eol_type != CODING_EOL_INCONSISTENT) + if (eol_type != CODING_EOL_UNDECIDED) { Lisp_Object val2; val2 = Fget (Qundecided, Qeol_type); if (VECTORP (val2)) val = XVECTOR (val2)->contents[eol_type]; } + return val; } - else + + /* At first, gather possible coding systems in VAL. */ + val = Qnil; + for (tmp = Vcoding_category_list; !NILP (tmp); tmp = XCONS (tmp)->cdr) { - Lisp_Object val2; - - /* At first, gather possible coding-systems in VAL in a reverse - order. */ - val = Qnil; - for (val2 = Vcoding_category_list; - !NILP (val2); - val2 = XCONS (val2)->cdr) + int idx + = XFASTINT (Fget (XCONS (tmp)->car, Qcoding_category_index)); + if (coding_mask & (1 << idx)) { - int idx - = XFASTINT (Fget (XCONS (val2)->car, Qcoding_category_index)); - if (coding_mask & (1 << idx)) - { -#if 0 - /* This code is suppressed until we find a better way to - distinguish raw text file and binary file. */ - - if (idx == CODING_CATEGORY_IDX_RAW_TEXT - && eol_type == CODING_EOL_INCONSISTENT) - val = Fcons (Qno_conversion, val); - else -#endif /* 0 */ - val = Fcons (Fsymbol_value (XCONS (val2)->car), val); - } - } - - /* Then, change the order of the list, while getting subsidiary - coding-systems. */ - val2 = val; - val = Qnil; - if (eol_type == CODING_EOL_INCONSISTENT) - eol_type == CODING_EOL_UNDECIDED; - for (; !NILP (val2); val2 = XCONS (val2)->cdr) - { - if (eol_type == CODING_EOL_UNDECIDED) - val = Fcons (XCONS (val2)->car, val); - else - { - Lisp_Object val3; - val3 = Fget (XCONS (val2)->car, Qeol_type); - if (VECTORP (val3)) - val = Fcons (XVECTOR (val3)->contents[eol_type], val); - else - val = Fcons (XCONS (val2)->car, val); - } + val = Fcons (Fsymbol_value (XCONS (tmp)->car), val); + if (highest) + break; } } - - return val; -} - -/* Scan text in the region between *BEGP and *ENDP, skip characters - which we never have to encode to (iff ENCODEP is 1) or decode from - coding system CODING at the head and tail, then set BEGP and ENDP - to the addresses of start and end of the text we actually convert. */ - -void -shrink_conversion_area (begp, endp, coding, encodep) - unsigned char **begp, **endp; - struct coding_system *coding; - int encodep; -{ - register unsigned char *beg_addr = *begp, *end_addr = *endp; - - if (coding->eol_type != CODING_EOL_LF - && coding->eol_type != CODING_EOL_UNDECIDED) - /* Since we anyway have to convert end-of-line format, it is not - worth skipping at most 100 bytes or so. */ - return; - - if (encodep) /* for encoding */ + if (!highest) + val = Fnreverse (val); + + /* Then, substitute the elements by subsidiary coding systems. */ + for (tmp = val; !NILP (tmp); tmp = XCONS (tmp)->cdr) { - switch (coding->type) + if (eol_type != CODING_EOL_UNDECIDED) { - case coding_type_no_conversion: - case coding_type_emacs_mule: - case coding_type_undecided: - case coding_type_raw_text: - /* We need no conversion. */ - *begp = *endp; - return; - case coding_type_ccl: - /* We can't skip any data. */ - return; - case coding_type_iso2022: - if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL) - { - unsigned char *bol = beg_addr; - while (beg_addr < end_addr && *beg_addr < 0x80) - { - beg_addr++; - if (*(beg_addr - 1) == '\n') - bol = beg_addr; - } - beg_addr = bol; - goto label_skip_tail; - } - /* fall down ... */ - default: - /* We can skip all ASCII characters at the head and tail. */ - while (beg_addr < end_addr && *beg_addr < 0x80) beg_addr++; - label_skip_tail: - while (beg_addr < end_addr && *(end_addr - 1) < 0x80) end_addr--; - break; + Lisp_Object eol; + eol = Fget (XCONS (tmp)->car, Qeol_type); + if (VECTORP (eol)) + XCONS (tmp)->car = XVECTOR (eol)->contents[eol_type]; } } - else /* for decoding */ - { - switch (coding->type) - { - case coding_type_no_conversion: - /* We need no conversion. */ - *begp = *endp; - return; - case coding_type_emacs_mule: - case coding_type_raw_text: - if (coding->eol_type == CODING_EOL_LF) - { - /* We need no conversion. */ - *begp = *endp; - return; - } - /* We can skip all but carriage-return. */ - while (beg_addr < end_addr && *beg_addr != '\r') beg_addr++; - while (beg_addr < end_addr && *(end_addr - 1) != '\r') end_addr--; - break; - case coding_type_sjis: - case coding_type_big5: - /* We can skip all ASCII characters at the head. */ - while (beg_addr < end_addr && *beg_addr < 0x80) beg_addr++; - /* We can skip all ASCII characters at the tail except for - the second byte of SJIS or BIG5 code. */ - while (beg_addr < end_addr && *(end_addr - 1) < 0x80) end_addr--; - if (end_addr != *endp) - end_addr++; - break; - case coding_type_ccl: - /* We can't skip any data. */ - return; - default: /* i.e. case coding_type_iso2022: */ - { - unsigned char c; - - /* We can skip all ASCII characters except for a few - control codes at the head. */ - while (beg_addr < end_addr && (c = *beg_addr) < 0x80 - && c != ISO_CODE_CR && c != ISO_CODE_SO - && c != ISO_CODE_SI && c != ISO_CODE_ESC) - beg_addr++; - } - break; - } - } - *begp = beg_addr; - *endp = end_addr; - return; -} - -/* Encode into or decode from (according to ENCODEP) coding system CODING - the text between char positions B and E. */ - -Lisp_Object -code_convert_region (b, e, coding, encodep) - Lisp_Object b, e; - struct coding_system *coding; - int encodep; + return (highest ? XCONS (val)->car : val); +} + +DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region, + 2, 3, 0, + "Detect coding system of the text in the region between START and END.\n\ +Return a list of possible coding systems ordered by priority.\n\ +\n\ +If only ASCII characters are found, it returns `undecided'\n\ +or its subsidiary coding system according to a detected end-of-line format.\n\ +\n\ +If optional argument HIGHEST is non-nil, return the coding system of\n\ +highest priority.") + (start, end, highest) + Lisp_Object start, end, highest; { - int beg, end, len, consumed, produced; - char *buf; - unsigned char *begp, *endp; - int opoint = PT, opoint_byte = PT_BYTE; - int beg_byte, end_byte, len_byte; - int zv_before = ZV; - int zv_byte_before = ZV_BYTE; - - validate_region (&b, &e); - beg = XINT (b), end = XINT (e); - beg_byte = CHAR_TO_BYTE (beg); - end_byte = CHAR_TO_BYTE (end); - - if (beg < GPT && end >= GPT) - move_gap_both (end, end_byte); - - if (encodep && !NILP (coding->pre_write_conversion)) - { - /* We must call a pre-conversion function which may put a new - text to be converted in a new buffer. */ - struct buffer *old = current_buffer, *new; - - TEMP_SET_PT_BOTH (beg, beg_byte); - call2 (coding->pre_write_conversion, b, e); - if (old != current_buffer) - { - /* Replace the original text by the text just generated. */ - len = ZV - BEGV; - len_byte = ZV_BYTE - BEGV_BYTE; - new = current_buffer; - set_buffer_internal (old); - del_range_both (beg, end, beg_byte, end_byte, 1); - insert_from_buffer (new, 1, len, 0); - end = beg + len; - end_byte = len_byte; - } - } - - /* We may be able to shrink the conversion region. */ - begp = BYTE_POS_ADDR (beg_byte); - endp = begp + (end_byte - beg_byte); - shrink_conversion_area (&begp, &endp, coding, encodep); - - if (begp == endp) - /* We need no conversion. */ - len = end - beg; - else - { - int shrunk_beg_byte, shrunk_end_byte; - int shrunk_beg; - int shrunk_len_byte; - int new_len_byte; - int buflen; - - shrunk_beg_byte = PTR_BYTE_POS (begp); - shrunk_beg = BYTE_TO_CHAR (shrunk_beg_byte); - shrunk_end_byte = PTR_BYTE_POS (endp); - shrunk_len_byte = shrunk_end_byte - shrunk_beg_byte; - - if (encodep) - buflen = encoding_buffer_size (coding, shrunk_len_byte); - else - buflen = decoding_buffer_size (coding, shrunk_len_byte); - buf = get_conversion_buffer (buflen); - - coding->last_block = 1; - produced = (encodep - ? encode_coding (coding, begp, buf, shrunk_len_byte, buflen, - &consumed) - : decode_coding (coding, begp, buf, shrunk_len_byte, buflen, - &consumed)); - - TEMP_SET_PT_BOTH (shrunk_beg, shrunk_beg_byte); - - /* We let the number of characters in the result - be computed in accord with enable-multilibyte-characters - even when encoding. Otherwise the buffer contents - will be inconsistent. */ - insert (buf, produced); - - del_range_byte (PT_BYTE, PT_BYTE + shrunk_len_byte, 1); - - if (opoint >= end) - { - opoint += ZV - zv_before; - opoint_byte += ZV_BYTE - zv_byte_before; - } - else if (opoint > beg) - { - opoint = beg; - opoint_byte = beg_byte; - } - TEMP_SET_PT_BOTH (opoint, opoint_byte); - - end += ZV - zv_before; - } - - if (!encodep && !NILP (coding->post_read_conversion)) - { - Lisp_Object insval; - - /* We must call a post-conversion function which may alter - the text just converted. */ - zv_before = ZV; - zv_byte_before = ZV_BYTE; - - TEMP_SET_PT_BOTH (beg, beg_byte); - insval = call1 (coding->post_read_conversion, make_number (end - beg)); - CHECK_NUMBER (insval, 0); - - if (opoint >= beg + ZV - zv_before) - { - opoint += ZV - zv_before; - opoint_byte += ZV_BYTE - zv_byte_before; - } - else if (opoint > beg) - { - opoint = beg; - opoint_byte = beg_byte; - } - TEMP_SET_PT_BOTH (opoint, opoint_byte); - len = XINT (insval); - } - - return make_number (len); + int from, to; + int from_byte, to_byte; + + CHECK_NUMBER_COERCE_MARKER (start, 0); + CHECK_NUMBER_COERCE_MARKER (end, 1); + + validate_region (&start, &end); + from = XINT (start), to = XINT (end); + from_byte = CHAR_TO_BYTE (from); + to_byte = CHAR_TO_BYTE (to); + + if (from < GPT && to >= GPT) + move_gap_both (to, to_byte); + + return detect_coding_system (BYTE_POS_ADDR (from_byte), + to_byte - from_byte, + !NILP (highest)); +} + +DEFUN ("detect-coding-string", Fdetect_coding_string, Sdetect_coding_string, + 1, 2, 0, + "Detect coding system of the text in STRING.\n\ +Return a list of possible coding systems ordered by priority.\n\ +\n\ +If only ASCII characters are found, it returns `undecided'\n\ +or its subsidiary coding system according to a detected end-of-line format.\n\ +\n\ +If optional argument HIGHEST is non-nil, return the coding system of\n\ +highest priority.") + (string, highest) + Lisp_Object string, highest; +{ + CHECK_STRING (string, 0); + + return detect_coding_system (XSTRING (string)->data, + XSTRING (string)->size_byte, + !NILP (highest)); } DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region, 3, 3, "r\nzCoding system: ", - "Decode current region by specified coding system.\n\ + "Decode the current region by specified coding system.\n\ When called from a program, takes three arguments:\n\ -START, END, and CODING-SYSTEM. START END are buffer positions.\n\ +START, END, and CODING-SYSTEM. START and END are buffer positions.\n\ Return length of decoded text.") - (b, e, coding_system) - Lisp_Object b, e, coding_system; + (start, end, coding_system) + Lisp_Object start, end, coding_system; { struct coding_system coding; - - CHECK_NUMBER_COERCE_MARKER (b, 0); - CHECK_NUMBER_COERCE_MARKER (e, 1); + int from, to; + + CHECK_NUMBER_COERCE_MARKER (start, 0); + CHECK_NUMBER_COERCE_MARKER (end, 1); CHECK_SYMBOL (coding_system, 2); + validate_region (&start, &end); + from = XFASTINT (start); + to = XFASTINT (end); + if (NILP (coding_system)) - return make_number (XFASTINT (e) - XFASTINT (b)); + return make_number (to - from); + if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) - error ("Invalid coding-system: %s", XSYMBOL (coding_system)->name->data); - - return code_convert_region (b, e, &coding, 0); + error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data); + + coding.mode |= CODING_MODE_LAST_BLOCK; + return code_convert_region (from, to, &coding, 0, 1); } DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region, 3, 3, "r\nzCoding system: ", - "Encode current region by specified coding system.\n\ + "Encode the current region by specified coding system.\n\ When called from a program, takes three arguments:\n\ -START, END, and CODING-SYSTEM. START END are buffer positions.\n\ +START, END, and CODING-SYSTEM. START and END are buffer positions.\n\ Return length of encoded text.") - (b, e, coding_system) - Lisp_Object b, e, coding_system; + (start, end, coding_system) + Lisp_Object start, end, coding_system; { struct coding_system coding; - - CHECK_NUMBER_COERCE_MARKER (b, 0); - CHECK_NUMBER_COERCE_MARKER (e, 1); + int from, to; + + CHECK_NUMBER_COERCE_MARKER (start, 0); + CHECK_NUMBER_COERCE_MARKER (end, 1); CHECK_SYMBOL (coding_system, 2); + validate_region (&start, &end); + from = XFASTINT (start); + to = XFASTINT (end); + if (NILP (coding_system)) - return make_number (XFASTINT (e) - XFASTINT (b)); + return make_number (to - from); + if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) - error ("Invalid coding-system: %s", XSYMBOL (coding_system)->name->data); - - return code_convert_region (b, e, &coding, 1); -} - -/* Encode or decode (according to ENCODEP) the text of string STR - using coding CODING. If NOCOPY is nil, we never return STR - itself, but always a copy. If NOCOPY is non-nil, we return STR - if no change is needed. */ - -Lisp_Object -code_convert_string (str, coding, encodep, nocopy) - Lisp_Object str, nocopy; - struct coding_system *coding; - int encodep; -{ - int len, consumed, produced; - char *buf; - unsigned char *begp, *endp; - int head_skip, tail_skip; - struct gcpro gcpro1; - - if (encodep && !NILP (coding->pre_write_conversion) - || !encodep && !NILP (coding->post_read_conversion)) - { - /* Since we have to call Lisp functions which assume target text - is in a buffer, after setting a temporary buffer, call - code_convert_region. */ - int count = specpdl_ptr - specpdl; - int len = XSTRING (str)->size_byte; - Lisp_Object result; - struct buffer *old = current_buffer; - - record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); - temp_output_buffer_setup (" *code-converting-work*"); - set_buffer_internal (XBUFFER (Vstandard_output)); - insert_from_string (str, 0, 0, XSTRING (str)->size, len, 0); - code_convert_region (make_number (BEGV), make_number (ZV), - coding, encodep); - result = make_buffer_string (BEGV, ZV, 0); - set_buffer_internal (old); - return unbind_to (count, result); - } - - /* We may be able to shrink the conversion region. */ - begp = XSTRING (str)->data; - endp = begp + XSTRING (str)->size_byte; - shrink_conversion_area (&begp, &endp, coding, encodep); - - if (begp == endp) - /* We need no conversion. */ - return (NILP (nocopy) ? Fcopy_sequence (str) : str); - - /* We assume that head_skip and tail_skip count single-byte characters. */ - head_skip = begp - XSTRING (str)->data; - tail_skip = XSTRING (str)->size_byte - head_skip - (endp - begp); - - GCPRO1 (str); - - if (encodep) - len = encoding_buffer_size (coding, endp - begp); - else - len = decoding_buffer_size (coding, endp - begp); - buf = get_conversion_buffer (len + head_skip + tail_skip); - - bcopy (XSTRING (str)->data, buf, head_skip); - coding->last_block = 1; - produced = (encodep - ? encode_coding (coding, XSTRING (str)->data + head_skip, - buf + head_skip, endp - begp, len, &consumed) - : decode_coding (coding, XSTRING (str)->data + head_skip, - buf + head_skip, endp - begp, len, &consumed)); - bcopy (XSTRING (str)->data + head_skip + (endp - begp), - buf + head_skip + produced, - tail_skip); - - UNGCPRO; - - if (encodep) - /* When encoding, the result is all single-byte characters. */ - return make_unibyte_string (buf, head_skip + produced + tail_skip); - - /* When decoding, count properly the number of chars in the string. */ - return make_string (buf, head_skip + produced + tail_skip); + error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data); + + coding.mode |= CODING_MODE_LAST_BLOCK; + return code_convert_region (from, to, &coding, 1, 1); } DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, @@ -3663,10 +4420,12 @@ if (NILP (coding_system)) return (NILP (nocopy) ? Fcopy_sequence (string) : string); + if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) - error ("Invalid coding-system: %s", XSYMBOL (coding_system)->name->data); - - return code_convert_string (string, &coding, 0, nocopy); + error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data); + + coding.mode |= CODING_MODE_LAST_BLOCK; + return code_convert_string (string, &coding, 0, !NILP (nocopy)); } DEFUN ("encode-coding-string", Fencode_coding_string, Sencode_coding_string, @@ -3684,10 +4443,12 @@ if (NILP (coding_system)) return (NILP (nocopy) ? Fcopy_sequence (string) : string); + if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) - error ("Invalid coding-system: %s", XSYMBOL (coding_system)->name->data); - - return code_convert_string (string, &coding, 1, nocopy); + error ("Invalid coding system: %s", XSYMBOL (coding_system)->name->data); + + coding.mode |= CODING_MODE_LAST_BLOCK; + return code_convert_string (string, &coding, 1, !NILP (nocopy)); } DEFUN ("decode-sjis-char", Fdecode_sjis_char, Sdecode_sjis_char, 1, 1, 0, @@ -3708,7 +4469,7 @@ } DEFUN ("encode-sjis-char", Fencode_sjis_char, Sencode_sjis_char, 1, 1, 0, - "Encode a JISX0208 character CHAR to SJIS coding-system.\n\ + "Encode a JISX0208 character CHAR to SJIS coding system.\n\ Return the corresponding character code in SJIS.") (ch) Lisp_Object ch; @@ -3729,7 +4490,7 @@ } DEFUN ("decode-big5-char", Fdecode_big5_char, Sdecode_big5_char, 1, 1, 0, - "Decode a Big5 character CODE of BIG5 coding-system.\n\ + "Decode a Big5 character CODE of BIG5 coding system.\n\ CODE is the character code in BIG5.\n\ Return the corresponding character.") (code) @@ -3747,7 +4508,7 @@ } DEFUN ("encode-big5-char", Fencode_big5_char, Sencode_big5_char, 1, 1, 0, - "Encode the Big5 character CHAR to BIG5 coding-system.\n\ + "Encode the Big5 character CHAR to BIG5 coding system.\n\ Return the corresponding character code in Big5.") (ch) Lisp_Object ch; @@ -3915,6 +4676,31 @@ return Qnil; } +DEFUN ("update-iso-coding-systems", Fupdate_iso_coding_systems, + Supdate_iso_coding_systems, 0, 0, 0, + "Update internal database for ISO2022 based coding systems.\n\ +When values of the following coding categories are changed, you must\n\ +call this function:\n\ + coding-category-iso-7, coding-category-iso-7-tight,\n\ + coding-category-iso-8-1, coding-category-iso-8-2,\n\ + coding-category-iso-7-else, coding-category-iso-8-else") + () +{ + int i; + + for (i = CODING_CATEGORY_IDX_ISO_7; i <= CODING_CATEGORY_IDX_ISO_8_ELSE; + i++) + { + if (! coding_system_table[i]) + coding_system_table[i] + = (struct coding_system *) xmalloc (sizeof (struct coding_system)); + setup_coding_system + (XSYMBOL (XVECTOR (Vcoding_category_table)->contents[i])->value, + coding_system_table[i]); + } + return Qnil; +} + #endif /* emacs */ @@ -3967,6 +4753,8 @@ setup_coding_system (Qnil, &terminal_coding); setup_coding_system (Qnil, &safe_terminal_coding); + bzero (coding_system_table, sizeof coding_system_table); + #if defined (MSDOS) || defined (WINDOWSNT) system_eol_type = CODING_EOL_CRLF; #else @@ -4042,17 +4830,22 @@ Fput (Qcoding_system_error, Qerror_message, build_string ("Invalid coding system")); + Qcoding_category = intern ("coding-category"); + staticpro (&Qcoding_category); Qcoding_category_index = intern ("coding-category-index"); staticpro (&Qcoding_category_index); + Vcoding_category_table + = Fmake_vector (make_number (CODING_CATEGORY_IDX_MAX), Qnil); + staticpro (&Vcoding_category_table); { int i; for (i = 0; i < CODING_CATEGORY_IDX_MAX; i++) { - coding_category_table[i] = intern (coding_category_name[i]); - staticpro (&coding_category_table[i]); - Fput (coding_category_table[i], Qcoding_category_index, - make_number (i)); + XVECTOR (Vcoding_category_table)->contents[i] + = intern (coding_category_name[i]); + Fput (XVECTOR (Vcoding_category_table)->contents[i], + Qcoding_category_index, make_number (i)); } } @@ -4075,11 +4868,15 @@ Qemacs_mule = intern ("emacs-mule"); staticpro (&Qemacs_mule); + Qraw_text = intern ("raw-text"); + staticpro (&Qraw_text); + defsubr (&Scoding_system_p); defsubr (&Sread_coding_system); defsubr (&Sread_non_nil_coding_system); defsubr (&Scheck_coding_system); defsubr (&Sdetect_coding_region); + defsubr (&Sdetect_coding_string); defsubr (&Sdecode_coding_region); defsubr (&Sencode_coding_region); defsubr (&Sdecode_coding_string); @@ -4094,6 +4891,7 @@ defsubr (&Sset_keyboard_coding_system_internal); defsubr (&Skeyboard_coding_system); defsubr (&Sfind_operation_coding_system); + defsubr (&Supdate_iso_coding_systems); DEFVAR_LISP ("coding-system-list", &Vcoding_system_list, "List of coding systems.\n\ @@ -4121,7 +4919,8 @@ Vcoding_category_list = Qnil; for (i = CODING_CATEGORY_IDX_MAX - 1; i >= 0; i--) Vcoding_category_list - = Fcons (coding_category_table[i], Vcoding_category_list); + = Fcons (XVECTOR (Vcoding_category_table)->contents[i], + Vcoding_category_list); } DEFVAR_LISP ("coding-system-for-read", &Vcoding_system_for_read, @@ -4249,6 +5048,18 @@ or reading output of a subprocess.\n\ Only 128th through 159th elements has a meaning."); Vlatin_extra_code_table = Fmake_vector (make_number (256), Qnil); + + DEFVAR_LISP ("select-safe-coding-system-function", + &Vselect_safe_coding_system_function, + "Function to call to select safe coding system for encoding a text.\n\ +\n\ +If set, this function is called to force a user to select a proper\n\ +coding system which can encode the text in the case that a default\n\ +coding system used in each operation can't encode the text.\n\ +\n\ +The default value is `select-safe-codign-system' (which see)."); + Vselect_safe_coding_system_function = Qnil; + } #endif /* emacs */