1 |
/* Coding system handler (conversion, detection, and etc). |
/* Coding system handler (conversion, detection, etc). |
2 |
Copyright (C) 1995,97,1998,2002,2003 Electrotechnical Laboratory, JAPAN. |
Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN. |
3 |
Licensed to the Free Software Foundation. |
Licensed to the Free Software Foundation. |
4 |
Copyright (C) 2001,2002,2003 Free Software Foundation, Inc. |
Copyright (C) 2001, 2002 Free Software Foundation, Inc. |
5 |
|
Copyright (C) 2003 |
6 |
|
National Institute of Advanced Industrial Science and Technology (AIST) |
7 |
|
Registration Number H13PRO009 |
8 |
|
|
9 |
This file is part of GNU Emacs. |
This file is part of GNU Emacs. |
10 |
|
|
27 |
|
|
28 |
0. General comments |
0. General comments |
29 |
1. Preamble |
1. Preamble |
30 |
2. Emacs' internal format (emacs-mule) handlers |
2. Emacs' internal format (emacs-utf-8) handlers |
31 |
3. ISO2022 handlers |
3. UTF-8 handlers |
32 |
4. Shift-JIS and BIG5 handlers |
4. UTF-16 handlers |
33 |
5. CCL handlers |
5. Charset-base coding systems handlers |
34 |
6. End-of-line handlers |
6. emacs-mule (old Emacs' internal format) handlers |
35 |
7. C library functions |
7. ISO2022 handlers |
36 |
8. Emacs Lisp library functions |
8. Shift-JIS and BIG5 handlers |
37 |
9. Post-amble |
9. CCL handlers |
38 |
|
10. C library functions |
39 |
|
11. Emacs Lisp library functions |
40 |
|
12. Postamble |
41 |
|
|
42 |
*/ |
*/ |
43 |
|
|
44 |
/*** 0. General comments ***/ |
/*** 0. General comments *** |
45 |
|
|
46 |
|
|
47 |
/*** GENERAL NOTE on CODING SYSTEMS *** |
CODING SYSTEM |
48 |
|
|
49 |
A coding system is an encoding mechanism for one or more character |
A coding system is an object for an encoding mechanism that contains |
50 |
sets. Here's a list of coding systems which Emacs can handle. When |
information about how to convert byte sequences to character |
51 |
we say "decode", it means converting some other coding system to |
sequences and vice versa. When we say "decode", it means converting |
52 |
Emacs' internal format (emacs-mule), and when we say "encode", |
a byte sequence of a specific coding system into a character |
53 |
it means converting the coding system emacs-mule to some other |
sequence that is represented by Emacs' internal coding system |
54 |
|
`emacs-utf-8', and when we say "encode", it means converting a |
55 |
|
character sequence of emacs-utf-8 to a byte sequence of a specific |
56 |
coding system. |
coding system. |
57 |
|
|
58 |
0. Emacs' internal format (emacs-mule) |
In Emacs Lisp, a coding system is represented by a Lisp symbol. In |
59 |
|
C level, a coding system is represented by a vector of attributes |
60 |
|
stored in the hash table Vcharset_hash_table. The conversion from |
61 |
|
coding system symbol to attributes vector is done by looking up |
62 |
|
Vcharset_hash_table by the symbol. |
63 |
|
|
64 |
Emacs itself holds a multi-lingual character in buffers and strings |
Coding systems are classified into the following types depending on |
65 |
in a special format. Details are described in section 2. |
the encoding mechanism. Here's a brief description of the types. |
66 |
|
|
67 |
1. ISO2022 |
o UTF-8 |
68 |
|
|
69 |
|
o UTF-16 |
70 |
|
|
71 |
|
o Charset-base coding system |
72 |
|
|
73 |
|
A coding system defined by one or more (coded) character sets. |
74 |
|
Decoding and encoding are done by a code converter defined for each |
75 |
|
character set. |
76 |
|
|
77 |
|
o Old Emacs internal format (emacs-mule) |
78 |
|
|
79 |
|
The coding system adopted by old versions of Emacs (20 and 21). |
80 |
|
|
81 |
|
o ISO2022-base coding system |
82 |
|
|
83 |
The most famous coding system for multiple character sets. X's |
The most famous coding system for multiple character sets. X's |
84 |
Compound Text, various EUCs (Extended Unix Code), and coding |
Compound Text, various EUCs (Extended Unix Code), and coding systems |
85 |
systems used in Internet communication such as ISO-2022-JP are |
used in the Internet communication such as ISO-2022-JP are all |
86 |
all variants of ISO2022. Details are described in section 3. |
variants of ISO2022. |
87 |
|
|
88 |
2. SJIS (or Shift-JIS or MS-Kanji-Code) |
o SJIS (or Shift-JIS or MS-Kanji-Code) |
89 |
|
|
90 |
A coding system to encode character sets: ASCII, JISX0201, and |
A coding system to encode character sets: ASCII, JISX0201, and |
91 |
JISX0208. Widely used for PC's in Japan. Details are described in |
JISX0208. Widely used for PC's in Japan. Details are described in |
92 |
section 4. |
section 8. |
93 |
|
|
94 |
3. BIG5 |
o BIG5 |
95 |
|
|
96 |
A coding system to encode the character sets ASCII and Big5. Widely |
A coding system to encode character sets: ASCII and Big5. Widely |
97 |
used for Chinese (mainly in Taiwan and Hong Kong). Details are |
used for Chinese (mainly in Taiwan and Hong Kong). Details are |
98 |
described in section 4. In this file, when we write "BIG5" |
described in section 8. In this file, when we write "big5" (all |
99 |
(all uppercase), we mean the coding system, and when we write |
lowercase), we mean the coding system, and when we write "Big5" |
100 |
"Big5" (capitalized), we mean the character set. |
(capitalized), we mean the character set. |
|
|
|
|
4. Raw text |
|
|
|
|
|
A coding system for text containing random 8-bit code. Emacs does |
|
|
no code conversion on such text except for end-of-line format. |
|
|
|
|
|
5. Other |
|
|
|
|
|
If a user wants to read/write text encoded in a coding system not |
|
|
listed above, he can supply a decoder and an encoder for it as CCL |
|
|
(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 |
|
|
information about it is set in a structure of type `struct |
|
|
coding_system' for rapid processing. See section 6 for more details. |
|
101 |
|
|
102 |
*/ |
o CCL |
103 |
|
|
104 |
|
If a user wants to decode/encode text encoded in a coding system |
105 |
|
not listed above, he can supply a decoder and an encoder for it in |
106 |
|
CCL (Code Conversion Language) programs. Emacs executes the CCL |
107 |
|
program while decoding/encoding. |
108 |
|
|
109 |
|
o Raw-text |
110 |
|
|
111 |
|
A coding system for text containing raw eight-bit data. Emacs |
112 |
|
treats each byte of source text as a character (except for |
113 |
|
end-of-line conversion). |
114 |
|
|
115 |
|
o No-conversion |
116 |
|
|
117 |
/*** GENERAL NOTES on END-OF-LINE FORMAT *** |
Like raw text, but don't do end-of-line conversion. |
118 |
|
|
119 |
How end-of-line of text is encoded depends on the operating system. |
|
120 |
For instance, Unix's format is just one byte of `line-feed' code, |
END-OF-LINE FORMAT |
121 |
|
|
122 |
|
How text end-of-line is encoded depends on operating system. For |
123 |
|
instance, Unix's format is just one byte of LF (line-feed) code, |
124 |
whereas DOS's format is two-byte sequence of `carriage-return' and |
whereas DOS's format is two-byte sequence of `carriage-return' and |
125 |
`line-feed' codes. MacOS's format is usually one byte of |
`line-feed' codes. MacOS's format is usually one byte of |
126 |
`carriage-return'. |
`carriage-return'. |
127 |
|
|
128 |
Since text character encoding and end-of-line encoding are |
Since text character encoding and end-of-line encoding are |
129 |
independent, any coding system described above can have any |
independent, any coding system described above can take any format |
130 |
end-of-line format. So Emacs has information about end-of-line |
of end-of-line (except for no-conversion). |
131 |
format in each coding-system. See section 6 for more details. |
|
132 |
|
STRUCT CODING_SYSTEM |
133 |
|
|
134 |
|
Before using a coding system for code conversion (i.e. decoding and |
135 |
|
encoding), we setup a structure of type `struct coding_system'. |
136 |
|
This structure keeps various information about a specific code |
137 |
|
conversion (e.g. the location of source and destination data). |
138 |
|
|
139 |
*/ |
*/ |
140 |
|
|
141 |
|
/* COMMON MACROS */ |
142 |
|
|
143 |
|
|
144 |
/*** GENERAL NOTES on `detect_coding_XXX ()' functions *** |
/*** GENERAL NOTES on `detect_coding_XXX ()' functions *** |
145 |
|
|
146 |
These functions check if a text between SRC and SRC_END is encoded |
These functions check if a byte sequence specified as a source in |
147 |
in the coding system category XXX. Each returns an integer value in |
CODING conforms to the format of XXX, and update the members of |
148 |
which appropriate flag bits for the category XXX are set. The flag |
DETECT_INFO. |
149 |
bits are defined in macros CODING_CATEGORY_MASK_XXX. Below is the |
|
150 |
template for these functions. If MULTIBYTEP is nonzero, 8-bit codes |
Return 1 if the byte sequence conforms to XXX, otherwise return 0. |
151 |
of the range 0x80..0x9F are in multibyte form. */ |
|
152 |
|
Below is the template of these functions. */ |
153 |
|
|
154 |
#if 0 |
#if 0 |
155 |
int |
static int |
156 |
detect_coding_emacs_mule (src, src_end, multibytep) |
detect_coding_XXX (coding, detect_info) |
157 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
158 |
int multibytep; |
struct coding_detection_info *detect_info; |
159 |
{ |
{ |
160 |
... |
unsigned char *src = coding->source; |
161 |
|
unsigned char *src_end = coding->source + coding->src_bytes; |
162 |
|
int multibytep = coding->src_multibyte; |
163 |
|
int consumed_chars = 0; |
164 |
|
int found = 0; |
165 |
|
...; |
166 |
|
|
167 |
|
while (1) |
168 |
|
{ |
169 |
|
/* Get one byte from the source. If the souce is exausted, jump |
170 |
|
to no_more_source:. */ |
171 |
|
ONE_MORE_BYTE (c); |
172 |
|
|
173 |
|
if (! __C_conforms_to_XXX___ (c)) |
174 |
|
break; |
175 |
|
if (! __C_strongly_suggests_XXX__ (c)) |
176 |
|
found = CATEGORY_MASK_XXX; |
177 |
|
} |
178 |
|
/* The byte sequence is invalid for XXX. */ |
179 |
|
detect_info->rejected |= CATEGORY_MASK_XXX; |
180 |
|
return 0; |
181 |
|
|
182 |
|
no_more_source: |
183 |
|
/* The source exausted successfully. */ |
184 |
|
detect_info->found |= found; |
185 |
|
return 1; |
186 |
} |
} |
187 |
#endif |
#endif |
188 |
|
|
189 |
/*** GENERAL NOTES on `decode_coding_XXX ()' functions *** |
/*** GENERAL NOTES on `decode_coding_XXX ()' functions *** |
190 |
|
|
191 |
These functions decode SRC_BYTES length of unibyte text at SOURCE |
These functions decode a byte sequence specified as a source by |
192 |
encoded in CODING to Emacs' internal format. The resulting |
CODING. The resulting multibyte text goes to a place pointed to by |
193 |
multibyte text goes to a place pointed to by DESTINATION, the length |
CODING->charbuf, the length of which should not exceed |
194 |
of which should not exceed DST_BYTES. |
CODING->charbuf_size; |
195 |
|
|
196 |
These functions set the information about original and decoded texts |
These functions set the information of original and decoded texts in |
197 |
in the members `produced', `produced_char', `consumed', and |
CODING->consumed, CODING->consumed_char, and CODING->charbuf_used. |
198 |
`consumed_char' of the structure *CODING. They also set the member |
They also set CODING->result to one of CODING_RESULT_XXX indicating |
199 |
`result' to one of CODING_FINISH_XXX indicating how the decoding |
how the decoding is finished. |
200 |
finished. |
|
201 |
|
Below is the template of these functions. */ |
|
DST_BYTES zero means that the source area and destination area are |
|
|
overlapped, which means that we can produce a decoded text until it |
|
|
reaches the head of the not-yet-decoded source text. |
|
202 |
|
|
|
Below is a template for these functions. */ |
|
203 |
#if 0 |
#if 0 |
204 |
static void |
static void |
205 |
decode_coding_XXX (coding, source, destination, src_bytes, dst_bytes) |
decode_coding_XXXX (coding) |
206 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
207 |
{ |
{ |
208 |
... |
unsigned char *src = coding->source + coding->consumed; |
209 |
|
unsigned char *src_end = coding->source + coding->src_bytes; |
210 |
|
/* SRC_BASE remembers the start position in source in each loop. |
211 |
|
The loop will be exited when there's not enough source code, or |
212 |
|
when there's no room in CHARBUF for a decoded character. */ |
213 |
|
unsigned char *src_base; |
214 |
|
/* A buffer to produce decoded characters. */ |
215 |
|
int *charbuf = coding->charbuf; |
216 |
|
int *charbuf_end = charbuf + coding->charbuf_size; |
217 |
|
int multibytep = coding->src_multibyte; |
218 |
|
|
219 |
|
while (1) |
220 |
|
{ |
221 |
|
src_base = src; |
222 |
|
if (charbuf < charbuf_end) |
223 |
|
/* No more room to produce a decoded character. */ |
224 |
|
break; |
225 |
|
ONE_MORE_BYTE (c); |
226 |
|
/* Decode it. */ |
227 |
|
} |
228 |
|
|
229 |
|
no_more_source: |
230 |
|
if (src_base < src_end |
231 |
|
&& coding->mode & CODING_MODE_LAST_BLOCK) |
232 |
|
/* If the source ends by partial bytes to construct a character, |
233 |
|
treat them as eight-bit raw data. */ |
234 |
|
while (src_base < src_end && charbuf < charbuf_end) |
235 |
|
*charbuf++ = *src_base++; |
236 |
|
/* Remember how many bytes and characters we consumed. If the |
237 |
|
source is multibyte, the bytes and chars are not identical. */ |
238 |
|
coding->consumed = coding->consumed_char = src_base - coding->source; |
239 |
|
/* Remember how many characters we produced. */ |
240 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
241 |
} |
} |
242 |
#endif |
#endif |
243 |
|
|
244 |
/*** GENERAL NOTES on `encode_coding_XXX ()' functions *** |
/*** GENERAL NOTES on `encode_coding_XXX ()' functions *** |
245 |
|
|
246 |
These functions encode SRC_BYTES length text at SOURCE from Emacs' |
These functions encode SRC_BYTES length text at SOURCE of Emacs' |
247 |
internal multibyte format to CODING. The resulting unibyte text |
internal multibyte format by CODING. The resulting byte sequence |
248 |
goes to a place pointed to by DESTINATION, the length of which |
goes to a place pointed to by DESTINATION, the length of which |
249 |
should not exceed DST_BYTES. |
should not exceed DST_BYTES. |
250 |
|
|
251 |
These functions set the information about original and encoded texts |
These functions set the information of original and encoded texts in |
252 |
in the members `produced', `produced_char', `consumed', and |
the members produced, produced_char, consumed, and consumed_char of |
253 |
`consumed_char' of the structure *CODING. They also set the member |
the structure *CODING. They also set the member result to one of |
254 |
`result' to one of CODING_FINISH_XXX indicating how the encoding |
CODING_RESULT_XXX indicating how the encoding finished. |
255 |
finished. |
|
256 |
|
DST_BYTES zero means that source area and destination area are |
257 |
DST_BYTES zero means that the source area and destination area are |
overlapped, which means that we can produce a encoded text until it |
258 |
overlapped, which means that we can produce encoded text until it |
reaches at the head of not-yet-encoded source text. |
|
reaches at the head of the not-yet-encoded source text. |
|
259 |
|
|
260 |
Below is a template for these functions. */ |
Below is a template of these functions. */ |
261 |
#if 0 |
#if 0 |
262 |
static void |
static void |
263 |
encode_coding_XXX (coding, source, destination, src_bytes, dst_bytes) |
encode_coding_XXX (coding) |
264 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
265 |
{ |
{ |
266 |
... |
int multibytep = coding->dst_multibyte; |
267 |
|
int *charbuf = coding->charbuf; |
268 |
|
int *charbuf_end = charbuf->charbuf + coding->charbuf_used; |
269 |
|
unsigned char *dst = coding->destination + coding->produced; |
270 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
271 |
|
unsigned char *adjusted_dst_end = dst_end - _MAX_BYTES_PRODUCED_IN_LOOP_; |
272 |
|
int produced_chars = 0; |
273 |
|
|
274 |
|
for (; charbuf < charbuf_end && dst < adjusted_dst_end; charbuf++) |
275 |
|
{ |
276 |
|
int c = *charbuf; |
277 |
|
/* Encode C into DST, and increment DST. */ |
278 |
|
} |
279 |
|
label_no_more_destination: |
280 |
|
/* How many chars and bytes we produced. */ |
281 |
|
coding->produced_char += produced_chars; |
282 |
|
coding->produced = dst - coding->destination; |
283 |
} |
} |
284 |
#endif |
#endif |
285 |
|
|
|
/*** COMMONLY USED MACROS ***/ |
|
|
|
|
|
/* The following two macros ONE_MORE_BYTE and TWO_MORE_BYTES safely |
|
|
get one, two, and three bytes from the source text respectively. |
|
|
If there are not enough bytes in the source, they jump to |
|
|
`label_end_of_loop'. The caller should set variables `coding', |
|
|
`src' and `src_end' to appropriate pointer in advance. These |
|
|
macros are called from decoding routines `decode_coding_XXX', thus |
|
|
it is assumed that the source text is unibyte. */ |
|
|
|
|
|
#define ONE_MORE_BYTE(c1) \ |
|
|
do { \ |
|
|
if (src >= src_end) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_SRC; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
c1 = *src++; \ |
|
|
} while (0) |
|
|
|
|
|
#define TWO_MORE_BYTES(c1, c2) \ |
|
|
do { \ |
|
|
if (src + 1 >= src_end) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_SRC; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
c1 = *src++; \ |
|
|
c2 = *src++; \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* Like ONE_MORE_BYTE, but 8-bit bytes of data at SRC are in multibyte |
|
|
form if MULTIBYTEP is nonzero. */ |
|
|
|
|
|
#define ONE_MORE_BYTE_CHECK_MULTIBYTE(c1, multibytep) \ |
|
|
do { \ |
|
|
if (src >= src_end) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_SRC; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
c1 = *src++; \ |
|
|
if (multibytep && c1 == LEADING_CODE_8_BIT_CONTROL) \ |
|
|
c1 = *src++ - 0x20; \ |
|
|
} while (0) |
|
|
|
|
|
/* Set C to the next character at the source text pointed by `src'. |
|
|
If there are not enough characters in the source, jump to |
|
|
`label_end_of_loop'. The caller should set variables `coding' |
|
|
`src', `src_end', and `translation_table' to appropriate pointers |
|
|
in advance. This macro is used in encoding routines |
|
|
`encode_coding_XXX', thus it assumes that the source text is in |
|
|
multibyte form except for 8-bit characters. 8-bit characters are |
|
|
in multibyte form if coding->src_multibyte is nonzero, else they |
|
|
are represented by a single byte. */ |
|
|
|
|
|
#define ONE_MORE_CHAR(c) \ |
|
|
do { \ |
|
|
int len = src_end - src; \ |
|
|
int bytes; \ |
|
|
if (len <= 0) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_SRC; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
if (coding->src_multibyte \ |
|
|
|| UNIBYTE_STR_AS_MULTIBYTE_P (src, len, bytes)) \ |
|
|
c = STRING_CHAR_AND_LENGTH (src, len, bytes); \ |
|
|
else \ |
|
|
c = *src, bytes = 1; \ |
|
|
if (!NILP (translation_table)) \ |
|
|
c = translate_char (translation_table, c, -1, 0, 0); \ |
|
|
src += bytes; \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* Produce a multibyte form of character C to `dst'. Jump to |
|
|
`label_end_of_loop' if there's not enough space at `dst'. |
|
|
|
|
|
If we are now in the middle of a composition sequence, the decoded |
|
|
character may be ALTCHAR (for the current composition). In that |
|
|
case, the character goes to coding->cmp_data->data instead of |
|
|
`dst'. |
|
|
|
|
|
This macro is used in decoding routines. */ |
|
|
|
|
|
#define EMIT_CHAR(c) \ |
|
|
do { \ |
|
|
if (! COMPOSING_P (coding) \ |
|
|
|| coding->composing == COMPOSITION_RELATIVE \ |
|
|
|| coding->composing == COMPOSITION_WITH_RULE) \ |
|
|
{ \ |
|
|
int bytes = CHAR_BYTES (c); \ |
|
|
if ((dst + bytes) > (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
dst += CHAR_STRING (c, dst); \ |
|
|
coding->produced_char++; \ |
|
|
} \ |
|
|
\ |
|
|
if (COMPOSING_P (coding) \ |
|
|
&& coding->composing != COMPOSITION_RELATIVE) \ |
|
|
{ \ |
|
|
CODING_ADD_COMPOSITION_COMPONENT (coding, c); \ |
|
|
coding->composition_rule_follows \ |
|
|
= coding->composing != COMPOSITION_WITH_ALTCHARS; \ |
|
|
} \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
#define EMIT_ONE_BYTE(c) \ |
|
|
do { \ |
|
|
if (dst >= (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
*dst++ = c; \ |
|
|
} while (0) |
|
|
|
|
|
#define EMIT_TWO_BYTES(c1, c2) \ |
|
|
do { \ |
|
|
if (dst + 2 > (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
*dst++ = c1, *dst++ = c2; \ |
|
|
} while (0) |
|
|
|
|
|
#define EMIT_BYTES(from, to) \ |
|
|
do { \ |
|
|
if (dst + (to - from) > (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
while (from < to) \ |
|
|
*dst++ = *from++; \ |
|
|
} while (0) |
|
|
|
|
286 |
|
|
287 |
/*** 1. Preamble ***/ |
/*** 1. Preamble ***/ |
288 |
|
|
|
#ifdef emacs |
|
289 |
#include <config.h> |
#include <config.h> |
|
#endif |
|
|
|
|
290 |
#include <stdio.h> |
#include <stdio.h> |
291 |
|
|
|
#ifdef emacs |
|
|
|
|
292 |
#include "lisp.h" |
#include "lisp.h" |
293 |
#include "buffer.h" |
#include "buffer.h" |
294 |
|
#include "character.h" |
295 |
#include "charset.h" |
#include "charset.h" |
|
#include "composite.h" |
|
296 |
#include "ccl.h" |
#include "ccl.h" |
297 |
|
#include "composite.h" |
298 |
#include "coding.h" |
#include "coding.h" |
299 |
#include "window.h" |
#include "window.h" |
|
#include "intervals.h" |
|
|
|
|
|
#else /* not emacs */ |
|
|
|
|
|
#include "mulelib.h" |
|
300 |
|
|
301 |
#endif /* not emacs */ |
Lisp_Object Vcoding_system_hash_table; |
302 |
|
|
303 |
Lisp_Object Qcoding_system, Qeol_type; |
Lisp_Object Qcoding_system, Qcoding_aliases, Qeol_type; |
304 |
|
Lisp_Object Qunix, Qdos; |
305 |
|
extern Lisp_Object Qmac; /* frame.c */ |
306 |
Lisp_Object Qbuffer_file_coding_system; |
Lisp_Object Qbuffer_file_coding_system; |
307 |
Lisp_Object Qpost_read_conversion, Qpre_write_conversion; |
Lisp_Object Qpost_read_conversion, Qpre_write_conversion; |
308 |
|
Lisp_Object Qdefault_char; |
309 |
Lisp_Object Qno_conversion, Qundecided; |
Lisp_Object Qno_conversion, Qundecided; |
310 |
|
Lisp_Object Qcharset, Qiso_2022, Qutf_8, Qutf_16, Qshift_jis, Qbig5; |
311 |
|
Lisp_Object Qbig, Qlittle; |
312 |
Lisp_Object Qcoding_system_history; |
Lisp_Object Qcoding_system_history; |
|
Lisp_Object Qsafe_chars; |
|
313 |
Lisp_Object Qvalid_codes; |
Lisp_Object Qvalid_codes; |
314 |
|
Lisp_Object QCcategory; |
315 |
|
|
316 |
extern Lisp_Object Qinsert_file_contents, Qwrite_region; |
extern Lisp_Object Qinsert_file_contents, Qwrite_region; |
317 |
Lisp_Object Qcall_process, Qcall_process_region, Qprocess_argument; |
Lisp_Object Qcall_process, Qcall_process_region, Qprocess_argument; |
318 |
Lisp_Object Qstart_process, Qopen_network_stream; |
Lisp_Object Qstart_process, Qopen_network_stream; |
319 |
Lisp_Object Qtarget_idx; |
Lisp_Object Qtarget_idx; |
320 |
|
|
|
Lisp_Object Vselect_safe_coding_system_function; |
|
|
|
|
321 |
int coding_system_require_warning; |
int coding_system_require_warning; |
322 |
|
|
323 |
|
Lisp_Object Vselect_safe_coding_system_function; |
324 |
|
|
325 |
/* Mnemonic string for each format of end-of-line. */ |
/* Mnemonic string for each format of end-of-line. */ |
326 |
Lisp_Object eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac; |
Lisp_Object eol_mnemonic_unix, eol_mnemonic_dos, eol_mnemonic_mac; |
327 |
/* Mnemonic string to indicate format of end-of-line is not yet |
/* Mnemonic string to indicate format of end-of-line is not yet |
328 |
decided. */ |
decided. */ |
329 |
Lisp_Object eol_mnemonic_undecided; |
Lisp_Object eol_mnemonic_undecided; |
330 |
|
|
|
/* Format of end-of-line decided by system. This is CODING_EOL_LF on |
|
|
Unix, CODING_EOL_CRLF on DOS/Windows, and CODING_EOL_CR on Mac. */ |
|
|
int system_eol_type; |
|
|
|
|
331 |
#ifdef emacs |
#ifdef emacs |
332 |
|
|
|
/* Information about which coding system is safe for which chars. |
|
|
The value has the form (GENERIC-LIST . NON-GENERIC-ALIST). |
|
|
|
|
|
GENERIC-LIST is a list of generic coding systems which can encode |
|
|
any characters. |
|
|
|
|
|
NON-GENERIC-ALIST is an alist of non generic coding systems vs the |
|
|
corresponding char table that contains safe chars. */ |
|
|
Lisp_Object Vcoding_system_safe_chars; |
|
|
|
|
333 |
Lisp_Object Vcoding_system_list, Vcoding_system_alist; |
Lisp_Object Vcoding_system_list, Vcoding_system_alist; |
334 |
|
|
335 |
Lisp_Object Qcoding_system_p, Qcoding_system_error; |
Lisp_Object Qcoding_system_p, Qcoding_system_error; |
337 |
/* Coding system emacs-mule and raw-text are for converting only |
/* Coding system emacs-mule and raw-text are for converting only |
338 |
end-of-line format. */ |
end-of-line format. */ |
339 |
Lisp_Object Qemacs_mule, Qraw_text; |
Lisp_Object Qemacs_mule, Qraw_text; |
340 |
|
Lisp_Object Qutf_8_emacs; |
|
Lisp_Object Qutf_8; |
|
341 |
|
|
342 |
/* Coding-systems are handed between Emacs Lisp programs and C internal |
/* Coding-systems are handed between Emacs Lisp programs and C internal |
343 |
routines by the following three variables. */ |
routines by the following three variables. */ |
371 |
/* Coding system of what is sent from terminal keyboard. */ |
/* Coding system of what is sent from terminal keyboard. */ |
372 |
struct coding_system keyboard_coding; |
struct coding_system keyboard_coding; |
373 |
|
|
|
/* Default coding system to be used to write a file. */ |
|
|
struct coding_system default_buffer_file_coding; |
|
|
|
|
374 |
Lisp_Object Vfile_coding_system_alist; |
Lisp_Object Vfile_coding_system_alist; |
375 |
Lisp_Object Vprocess_coding_system_alist; |
Lisp_Object Vprocess_coding_system_alist; |
376 |
Lisp_Object Vnetwork_coding_system_alist; |
Lisp_Object Vnetwork_coding_system_alist; |
379 |
|
|
380 |
#endif /* emacs */ |
#endif /* emacs */ |
381 |
|
|
|
Lisp_Object Qcoding_category, Qcoding_category_index; |
|
|
|
|
|
/* List of symbols `coding-category-xxx' ordered by priority. */ |
|
|
Lisp_Object Vcoding_category_list; |
|
|
|
|
|
/* 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", |
|
|
"coding-category-iso-8-else", |
|
|
"coding-category-ccl", |
|
|
"coding-category-big5", |
|
|
"coding-category-utf-8", |
|
|
"coding-category-utf-16-be", |
|
|
"coding-category-utf-16-le", |
|
|
"coding-category-raw-text", |
|
|
"coding-category-binary" |
|
|
}; |
|
|
|
|
|
/* Table of pointers to coding systems corresponding to each coding |
|
|
categories. */ |
|
|
struct coding_system *coding_system_table[CODING_CATEGORY_IDX_MAX]; |
|
|
|
|
|
/* Table of coding category masks. Nth element is a mask for a coding |
|
|
category of which priority is Nth. */ |
|
|
static |
|
|
int coding_priorities[CODING_CATEGORY_IDX_MAX]; |
|
|
|
|
382 |
/* Flag to tell if we look up translation table on character code |
/* Flag to tell if we look up translation table on character code |
383 |
conversion. */ |
conversion. */ |
384 |
Lisp_Object Venable_character_translation; |
Lisp_Object Venable_character_translation; |
393 |
Lisp_Object Qtranslation_table_for_encode; |
Lisp_Object Qtranslation_table_for_encode; |
394 |
|
|
395 |
/* Alist of charsets vs revision number. */ |
/* Alist of charsets vs revision number. */ |
396 |
Lisp_Object Vcharset_revision_alist; |
static Lisp_Object Vcharset_revision_table; |
397 |
|
|
398 |
/* Default coding systems used for process I/O. */ |
/* Default coding systems used for process I/O. */ |
399 |
Lisp_Object Vdefault_process_coding_system; |
Lisp_Object Vdefault_process_coding_system; |
407 |
to avoid infinite recursive call. */ |
to avoid infinite recursive call. */ |
408 |
static int inhibit_pre_post_conversion; |
static int inhibit_pre_post_conversion; |
409 |
|
|
410 |
Lisp_Object Qchar_coding_system; |
/* Two special coding systems. */ |
411 |
|
Lisp_Object Vsjis_coding_system; |
412 |
|
Lisp_Object Vbig5_coding_system; |
413 |
|
|
414 |
|
|
415 |
|
static int detect_coding_utf_8 P_ ((struct coding_system *, |
416 |
|
struct coding_detection_info *info)); |
417 |
|
static void decode_coding_utf_8 P_ ((struct coding_system *)); |
418 |
|
static int encode_coding_utf_8 P_ ((struct coding_system *)); |
419 |
|
|
420 |
|
static int detect_coding_utf_16 P_ ((struct coding_system *, |
421 |
|
struct coding_detection_info *info)); |
422 |
|
static void decode_coding_utf_16 P_ ((struct coding_system *)); |
423 |
|
static int encode_coding_utf_16 P_ ((struct coding_system *)); |
424 |
|
|
425 |
|
static int detect_coding_iso_2022 P_ ((struct coding_system *, |
426 |
|
struct coding_detection_info *info)); |
427 |
|
static void decode_coding_iso_2022 P_ ((struct coding_system *)); |
428 |
|
static int encode_coding_iso_2022 P_ ((struct coding_system *)); |
429 |
|
|
430 |
|
static int detect_coding_emacs_mule P_ ((struct coding_system *, |
431 |
|
struct coding_detection_info *info)); |
432 |
|
static void decode_coding_emacs_mule P_ ((struct coding_system *)); |
433 |
|
static int encode_coding_emacs_mule P_ ((struct coding_system *)); |
434 |
|
|
435 |
|
static int detect_coding_sjis P_ ((struct coding_system *, |
436 |
|
struct coding_detection_info *info)); |
437 |
|
static void decode_coding_sjis P_ ((struct coding_system *)); |
438 |
|
static int encode_coding_sjis P_ ((struct coding_system *)); |
439 |
|
|
440 |
|
static int detect_coding_big5 P_ ((struct coding_system *, |
441 |
|
struct coding_detection_info *info)); |
442 |
|
static void decode_coding_big5 P_ ((struct coding_system *)); |
443 |
|
static int encode_coding_big5 P_ ((struct coding_system *)); |
444 |
|
|
445 |
|
static int detect_coding_ccl P_ ((struct coding_system *, |
446 |
|
struct coding_detection_info *info)); |
447 |
|
static void decode_coding_ccl P_ ((struct coding_system *)); |
448 |
|
static int encode_coding_ccl P_ ((struct coding_system *)); |
449 |
|
|
450 |
|
static void decode_coding_raw_text P_ ((struct coding_system *)); |
451 |
|
static int encode_coding_raw_text P_ ((struct coding_system *)); |
452 |
|
|
453 |
|
|
454 |
|
/* ISO2022 section */ |
455 |
|
|
456 |
|
#define CODING_ISO_INITIAL(coding, reg) \ |
457 |
|
(XINT (AREF (AREF (CODING_ID_ATTRS ((coding)->id), \ |
458 |
|
coding_attr_iso_initial), \ |
459 |
|
reg))) |
460 |
|
|
461 |
|
|
462 |
|
#define CODING_ISO_REQUEST(coding, charset_id) \ |
463 |
|
((charset_id <= (coding)->max_charset_id \ |
464 |
|
? (coding)->safe_charsets[charset_id] \ |
465 |
|
: -1)) |
466 |
|
|
467 |
|
|
468 |
|
#define CODING_ISO_FLAGS(coding) \ |
469 |
|
((coding)->spec.iso_2022.flags) |
470 |
|
#define CODING_ISO_DESIGNATION(coding, reg) \ |
471 |
|
((coding)->spec.iso_2022.current_designation[reg]) |
472 |
|
#define CODING_ISO_INVOCATION(coding, plane) \ |
473 |
|
((coding)->spec.iso_2022.current_invocation[plane]) |
474 |
|
#define CODING_ISO_SINGLE_SHIFTING(coding) \ |
475 |
|
((coding)->spec.iso_2022.single_shifting) |
476 |
|
#define CODING_ISO_BOL(coding) \ |
477 |
|
((coding)->spec.iso_2022.bol) |
478 |
|
#define CODING_ISO_INVOKED_CHARSET(coding, plane) \ |
479 |
|
CODING_ISO_DESIGNATION ((coding), CODING_ISO_INVOCATION ((coding), (plane))) |
480 |
|
|
481 |
|
/* Control characters of ISO2022. */ |
482 |
|
/* code */ /* function */ |
483 |
|
#define ISO_CODE_LF 0x0A /* line-feed */ |
484 |
|
#define ISO_CODE_CR 0x0D /* carriage-return */ |
485 |
|
#define ISO_CODE_SO 0x0E /* shift-out */ |
486 |
|
#define ISO_CODE_SI 0x0F /* shift-in */ |
487 |
|
#define ISO_CODE_SS2_7 0x19 /* single-shift-2 for 7-bit code */ |
488 |
|
#define ISO_CODE_ESC 0x1B /* escape */ |
489 |
|
#define ISO_CODE_SS2 0x8E /* single-shift-2 */ |
490 |
|
#define ISO_CODE_SS3 0x8F /* single-shift-3 */ |
491 |
|
#define ISO_CODE_CSI 0x9B /* control-sequence-introducer */ |
492 |
|
|
493 |
|
/* All code (1-byte) of ISO2022 is classified into one of the |
494 |
|
followings. */ |
495 |
|
enum iso_code_class_type |
496 |
|
{ |
497 |
|
ISO_control_0, /* Control codes in the range |
498 |
|
0x00..0x1F and 0x7F, except for the |
499 |
|
following 5 codes. */ |
500 |
|
ISO_carriage_return, /* ISO_CODE_CR (0x0D) */ |
501 |
|
ISO_shift_out, /* ISO_CODE_SO (0x0E) */ |
502 |
|
ISO_shift_in, /* ISO_CODE_SI (0x0F) */ |
503 |
|
ISO_single_shift_2_7, /* ISO_CODE_SS2_7 (0x19) */ |
504 |
|
ISO_escape, /* ISO_CODE_SO (0x1B) */ |
505 |
|
ISO_control_1, /* Control codes in the range |
506 |
|
0x80..0x9F, except for the |
507 |
|
following 3 codes. */ |
508 |
|
ISO_single_shift_2, /* ISO_CODE_SS2 (0x8E) */ |
509 |
|
ISO_single_shift_3, /* ISO_CODE_SS3 (0x8F) */ |
510 |
|
ISO_control_sequence_introducer, /* ISO_CODE_CSI (0x9B) */ |
511 |
|
ISO_0x20_or_0x7F, /* Codes of the values 0x20 or 0x7F. */ |
512 |
|
ISO_graphic_plane_0, /* Graphic codes in the range 0x21..0x7E. */ |
513 |
|
ISO_0xA0_or_0xFF, /* Codes of the values 0xA0 or 0xFF. */ |
514 |
|
ISO_graphic_plane_1 /* Graphic codes in the range 0xA1..0xFE. */ |
515 |
|
}; |
516 |
|
|
517 |
/* Return `safe-chars' property of CODING_SYSTEM (symbol). Don't check |
/** The macros CODING_ISO_FLAG_XXX defines a flag bit of the |
518 |
its validity. */ |
`iso-flags' attribute of an iso2022 coding system. */ |
519 |
|
|
520 |
Lisp_Object |
/* If set, produce long-form designation sequence (e.g. ESC $ ( A) |
521 |
coding_safe_chars (coding_system) |
instead of the correct short-form sequence (e.g. ESC $ A). */ |
522 |
Lisp_Object coding_system; |
#define CODING_ISO_FLAG_LONG_FORM 0x0001 |
523 |
|
|
524 |
|
/* If set, reset graphic planes and registers at end-of-line to the |
525 |
|
initial state. */ |
526 |
|
#define CODING_ISO_FLAG_RESET_AT_EOL 0x0002 |
527 |
|
|
528 |
|
/* If set, reset graphic planes and registers before any control |
529 |
|
characters to the initial state. */ |
530 |
|
#define CODING_ISO_FLAG_RESET_AT_CNTL 0x0004 |
531 |
|
|
532 |
|
/* If set, encode by 7-bit environment. */ |
533 |
|
#define CODING_ISO_FLAG_SEVEN_BITS 0x0008 |
534 |
|
|
535 |
|
/* If set, use locking-shift function. */ |
536 |
|
#define CODING_ISO_FLAG_LOCKING_SHIFT 0x0010 |
537 |
|
|
538 |
|
/* If set, use single-shift function. Overwrite |
539 |
|
CODING_ISO_FLAG_LOCKING_SHIFT. */ |
540 |
|
#define CODING_ISO_FLAG_SINGLE_SHIFT 0x0020 |
541 |
|
|
542 |
|
/* If set, use designation escape sequence. */ |
543 |
|
#define CODING_ISO_FLAG_DESIGNATION 0x0040 |
544 |
|
|
545 |
|
/* If set, produce revision number sequence. */ |
546 |
|
#define CODING_ISO_FLAG_REVISION 0x0080 |
547 |
|
|
548 |
|
/* If set, produce ISO6429's direction specifying sequence. */ |
549 |
|
#define CODING_ISO_FLAG_DIRECTION 0x0100 |
550 |
|
|
551 |
|
/* If set, assume designation states are reset at beginning of line on |
552 |
|
output. */ |
553 |
|
#define CODING_ISO_FLAG_INIT_AT_BOL 0x0200 |
554 |
|
|
555 |
|
/* If set, designation sequence should be placed at beginning of line |
556 |
|
on output. */ |
557 |
|
#define CODING_ISO_FLAG_DESIGNATE_AT_BOL 0x0400 |
558 |
|
|
559 |
|
/* If set, do not encode unsafe charactes on output. */ |
560 |
|
#define CODING_ISO_FLAG_SAFE 0x0800 |
561 |
|
|
562 |
|
/* If set, extra latin codes (128..159) are accepted as a valid code |
563 |
|
on input. */ |
564 |
|
#define CODING_ISO_FLAG_LATIN_EXTRA 0x1000 |
565 |
|
|
566 |
|
#define CODING_ISO_FLAG_COMPOSITION 0x2000 |
567 |
|
|
568 |
|
#define CODING_ISO_FLAG_EUC_TW_SHIFT 0x4000 |
569 |
|
|
570 |
|
#define CODING_ISO_FLAG_USE_ROMAN 0x8000 |
571 |
|
|
572 |
|
#define CODING_ISO_FLAG_USE_OLDJIS 0x10000 |
573 |
|
|
574 |
|
#define CODING_ISO_FLAG_FULL_SUPPORT 0x100000 |
575 |
|
|
576 |
|
/* A character to be produced on output if encoding of the original |
577 |
|
character is prohibited by CODING_ISO_FLAG_SAFE. */ |
578 |
|
#define CODING_INHIBIT_CHARACTER_SUBSTITUTION '?' |
579 |
|
|
580 |
|
|
581 |
|
/* UTF-16 section */ |
582 |
|
#define CODING_UTF_16_BOM(coding) \ |
583 |
|
((coding)->spec.utf_16.bom) |
584 |
|
|
585 |
|
#define CODING_UTF_16_ENDIAN(coding) \ |
586 |
|
((coding)->spec.utf_16.endian) |
587 |
|
|
588 |
|
#define CODING_UTF_16_SURROGATE(coding) \ |
589 |
|
((coding)->spec.utf_16.surrogate) |
590 |
|
|
591 |
|
|
592 |
|
/* CCL section */ |
593 |
|
#define CODING_CCL_DECODER(coding) \ |
594 |
|
AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_decoder) |
595 |
|
#define CODING_CCL_ENCODER(coding) \ |
596 |
|
AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_encoder) |
597 |
|
#define CODING_CCL_VALIDS(coding) \ |
598 |
|
(SDATA (AREF (CODING_ID_ATTRS ((coding)->id), coding_attr_ccl_valids))) |
599 |
|
|
600 |
|
/* Index for each coding category in `coding_categories' */ |
601 |
|
|
602 |
|
enum coding_category |
603 |
|
{ |
604 |
|
coding_category_iso_7, |
605 |
|
coding_category_iso_7_tight, |
606 |
|
coding_category_iso_8_1, |
607 |
|
coding_category_iso_8_2, |
608 |
|
coding_category_iso_7_else, |
609 |
|
coding_category_iso_8_else, |
610 |
|
coding_category_utf_8, |
611 |
|
coding_category_utf_16_auto, |
612 |
|
coding_category_utf_16_be, |
613 |
|
coding_category_utf_16_le, |
614 |
|
coding_category_utf_16_be_nosig, |
615 |
|
coding_category_utf_16_le_nosig, |
616 |
|
coding_category_charset, |
617 |
|
coding_category_sjis, |
618 |
|
coding_category_big5, |
619 |
|
coding_category_ccl, |
620 |
|
coding_category_emacs_mule, |
621 |
|
/* All above are targets of code detection. */ |
622 |
|
coding_category_raw_text, |
623 |
|
coding_category_undecided, |
624 |
|
coding_category_max |
625 |
|
}; |
626 |
|
|
627 |
|
/* Definitions of flag bits used in detect_coding_XXXX. */ |
628 |
|
#define CATEGORY_MASK_ISO_7 (1 << coding_category_iso_7) |
629 |
|
#define CATEGORY_MASK_ISO_7_TIGHT (1 << coding_category_iso_7_tight) |
630 |
|
#define CATEGORY_MASK_ISO_8_1 (1 << coding_category_iso_8_1) |
631 |
|
#define CATEGORY_MASK_ISO_8_2 (1 << coding_category_iso_8_2) |
632 |
|
#define CATEGORY_MASK_ISO_7_ELSE (1 << coding_category_iso_7_else) |
633 |
|
#define CATEGORY_MASK_ISO_8_ELSE (1 << coding_category_iso_8_else) |
634 |
|
#define CATEGORY_MASK_UTF_8 (1 << coding_category_utf_8) |
635 |
|
#define CATEGORY_MASK_UTF_16_AUTO (1 << coding_category_utf_16_auto) |
636 |
|
#define CATEGORY_MASK_UTF_16_BE (1 << coding_category_utf_16_be) |
637 |
|
#define CATEGORY_MASK_UTF_16_LE (1 << coding_category_utf_16_le) |
638 |
|
#define CATEGORY_MASK_UTF_16_BE_NOSIG (1 << coding_category_utf_16_be_nosig) |
639 |
|
#define CATEGORY_MASK_UTF_16_LE_NOSIG (1 << coding_category_utf_16_le_nosig) |
640 |
|
#define CATEGORY_MASK_CHARSET (1 << coding_category_charset) |
641 |
|
#define CATEGORY_MASK_SJIS (1 << coding_category_sjis) |
642 |
|
#define CATEGORY_MASK_BIG5 (1 << coding_category_big5) |
643 |
|
#define CATEGORY_MASK_CCL (1 << coding_category_ccl) |
644 |
|
#define CATEGORY_MASK_EMACS_MULE (1 << coding_category_emacs_mule) |
645 |
|
#define CATEGORY_MASK_RAW_TEXT (1 << coding_category_raw_text) |
646 |
|
|
647 |
|
/* This value is returned if detect_coding_mask () find nothing other |
648 |
|
than ASCII characters. */ |
649 |
|
#define CATEGORY_MASK_ANY \ |
650 |
|
(CATEGORY_MASK_ISO_7 \ |
651 |
|
| CATEGORY_MASK_ISO_7_TIGHT \ |
652 |
|
| CATEGORY_MASK_ISO_8_1 \ |
653 |
|
| CATEGORY_MASK_ISO_8_2 \ |
654 |
|
| CATEGORY_MASK_ISO_7_ELSE \ |
655 |
|
| CATEGORY_MASK_ISO_8_ELSE \ |
656 |
|
| CATEGORY_MASK_UTF_8 \ |
657 |
|
| CATEGORY_MASK_UTF_16_BE \ |
658 |
|
| CATEGORY_MASK_UTF_16_LE \ |
659 |
|
| CATEGORY_MASK_UTF_16_BE_NOSIG \ |
660 |
|
| CATEGORY_MASK_UTF_16_LE_NOSIG \ |
661 |
|
| CATEGORY_MASK_CHARSET \ |
662 |
|
| CATEGORY_MASK_SJIS \ |
663 |
|
| CATEGORY_MASK_BIG5 \ |
664 |
|
| CATEGORY_MASK_CCL \ |
665 |
|
| CATEGORY_MASK_EMACS_MULE) |
666 |
|
|
667 |
|
|
668 |
|
#define CATEGORY_MASK_ISO_7BIT \ |
669 |
|
(CATEGORY_MASK_ISO_7 | CATEGORY_MASK_ISO_7_TIGHT) |
670 |
|
|
671 |
|
#define CATEGORY_MASK_ISO_8BIT \ |
672 |
|
(CATEGORY_MASK_ISO_8_1 | CATEGORY_MASK_ISO_8_2) |
673 |
|
|
674 |
|
#define CATEGORY_MASK_ISO_ELSE \ |
675 |
|
(CATEGORY_MASK_ISO_7_ELSE | CATEGORY_MASK_ISO_8_ELSE) |
676 |
|
|
677 |
|
#define CATEGORY_MASK_ISO_ESCAPE \ |
678 |
|
(CATEGORY_MASK_ISO_7 \ |
679 |
|
| CATEGORY_MASK_ISO_7_TIGHT \ |
680 |
|
| CATEGORY_MASK_ISO_7_ELSE \ |
681 |
|
| CATEGORY_MASK_ISO_8_ELSE) |
682 |
|
|
683 |
|
#define CATEGORY_MASK_ISO \ |
684 |
|
( CATEGORY_MASK_ISO_7BIT \ |
685 |
|
| CATEGORY_MASK_ISO_8BIT \ |
686 |
|
| CATEGORY_MASK_ISO_ELSE) |
687 |
|
|
688 |
|
#define CATEGORY_MASK_UTF_16 \ |
689 |
|
(CATEGORY_MASK_UTF_16_BE \ |
690 |
|
| CATEGORY_MASK_UTF_16_LE \ |
691 |
|
| CATEGORY_MASK_UTF_16_BE_NOSIG \ |
692 |
|
| CATEGORY_MASK_UTF_16_LE_NOSIG) |
693 |
|
|
694 |
|
|
695 |
|
/* List of symbols `coding-category-xxx' ordered by priority. This |
696 |
|
variable is exposed to Emacs Lisp. */ |
697 |
|
static Lisp_Object Vcoding_category_list; |
698 |
|
|
699 |
|
/* Table of coding categories (Lisp symbols). This variable is for |
700 |
|
internal use oly. */ |
701 |
|
static Lisp_Object Vcoding_category_table; |
702 |
|
|
703 |
|
/* Table of coding-categories ordered by priority. */ |
704 |
|
static enum coding_category coding_priorities[coding_category_max]; |
705 |
|
|
706 |
|
/* Nth element is a coding context for the coding system bound to the |
707 |
|
Nth coding category. */ |
708 |
|
static struct coding_system coding_categories[coding_category_max]; |
709 |
|
|
710 |
|
/*** Commonly used macros and functions ***/ |
711 |
|
|
712 |
|
#ifndef min |
713 |
|
#define min(a, b) ((a) < (b) ? (a) : (b)) |
714 |
|
#endif |
715 |
|
#ifndef max |
716 |
|
#define max(a, b) ((a) > (b) ? (a) : (b)) |
717 |
|
#endif |
718 |
|
|
719 |
|
#define CODING_GET_INFO(coding, attrs, eol_type, charset_list) \ |
720 |
|
do { \ |
721 |
|
attrs = CODING_ID_ATTRS (coding->id); \ |
722 |
|
eol_type = CODING_ID_EOL_TYPE (coding->id); \ |
723 |
|
if (VECTORP (eol_type)) \ |
724 |
|
eol_type = Qunix; \ |
725 |
|
charset_list = CODING_ATTR_CHARSET_LIST (attrs); \ |
726 |
|
} while (0) |
727 |
|
|
728 |
|
|
729 |
|
/* Safely get one byte from the source text pointed by SRC which ends |
730 |
|
at SRC_END, and set C to that byte. If there are not enough bytes |
731 |
|
in the source, it jumps to `no_more_source'. The caller |
732 |
|
should declare and set these variables appropriately in advance: |
733 |
|
src, src_end, multibytep |
734 |
|
*/ |
735 |
|
|
736 |
|
#define ONE_MORE_BYTE(c) \ |
737 |
|
do { \ |
738 |
|
if (src == src_end) \ |
739 |
|
{ \ |
740 |
|
if (src_base < src) \ |
741 |
|
coding->result = CODING_RESULT_INSUFFICIENT_SRC; \ |
742 |
|
goto no_more_source; \ |
743 |
|
} \ |
744 |
|
c = *src++; \ |
745 |
|
if (multibytep && (c & 0x80)) \ |
746 |
|
{ \ |
747 |
|
if ((c & 0xFE) != 0xC0) \ |
748 |
|
error ("Undecodable char found"); \ |
749 |
|
c = ((c & 1) << 6) | *src++; \ |
750 |
|
} \ |
751 |
|
consumed_chars++; \ |
752 |
|
} while (0) |
753 |
|
|
754 |
|
|
755 |
|
#define ONE_MORE_BYTE_NO_CHECK(c) \ |
756 |
|
do { \ |
757 |
|
c = *src++; \ |
758 |
|
if (multibytep && (c & 0x80)) \ |
759 |
|
{ \ |
760 |
|
if ((c & 0xFE) != 0xC0) \ |
761 |
|
error ("Undecodable char found"); \ |
762 |
|
c = ((c & 1) << 6) | *src++; \ |
763 |
|
} \ |
764 |
|
consumed_chars++; \ |
765 |
|
} while (0) |
766 |
|
|
767 |
|
|
768 |
|
/* Store a byte C in the place pointed by DST and increment DST to the |
769 |
|
next free point, and increment PRODUCED_CHARS. The caller should |
770 |
|
assure that C is 0..127, and declare and set the variable `dst' |
771 |
|
appropriately in advance. |
772 |
|
*/ |
773 |
|
|
774 |
|
|
775 |
|
#define EMIT_ONE_ASCII_BYTE(c) \ |
776 |
|
do { \ |
777 |
|
produced_chars++; \ |
778 |
|
*dst++ = (c); \ |
779 |
|
} while (0) |
780 |
|
|
781 |
|
|
782 |
|
/* Like EMIT_ONE_ASCII_BYTE byt store two bytes; C1 and C2. */ |
783 |
|
|
784 |
|
#define EMIT_TWO_ASCII_BYTES(c1, c2) \ |
785 |
|
do { \ |
786 |
|
produced_chars += 2; \ |
787 |
|
*dst++ = (c1), *dst++ = (c2); \ |
788 |
|
} while (0) |
789 |
|
|
790 |
|
|
791 |
|
/* Store a byte C in the place pointed by DST and increment DST to the |
792 |
|
next free point, and increment PRODUCED_CHARS. If MULTIBYTEP is |
793 |
|
nonzero, store in an appropriate multibyte from. The caller should |
794 |
|
declare and set the variables `dst' and `multibytep' appropriately |
795 |
|
in advance. */ |
796 |
|
|
797 |
|
#define EMIT_ONE_BYTE(c) \ |
798 |
|
do { \ |
799 |
|
produced_chars++; \ |
800 |
|
if (multibytep) \ |
801 |
|
{ \ |
802 |
|
int ch = (c); \ |
803 |
|
if (ch >= 0x80) \ |
804 |
|
ch = BYTE8_TO_CHAR (ch); \ |
805 |
|
CHAR_STRING_ADVANCE (ch, dst); \ |
806 |
|
} \ |
807 |
|
else \ |
808 |
|
*dst++ = (c); \ |
809 |
|
} while (0) |
810 |
|
|
811 |
|
|
812 |
|
/* Like EMIT_ONE_BYTE, but emit two bytes; C1 and C2. */ |
813 |
|
|
814 |
|
#define EMIT_TWO_BYTES(c1, c2) \ |
815 |
|
do { \ |
816 |
|
produced_chars += 2; \ |
817 |
|
if (multibytep) \ |
818 |
|
{ \ |
819 |
|
int ch; \ |
820 |
|
\ |
821 |
|
ch = (c1); \ |
822 |
|
if (ch >= 0x80) \ |
823 |
|
ch = BYTE8_TO_CHAR (ch); \ |
824 |
|
CHAR_STRING_ADVANCE (ch, dst); \ |
825 |
|
ch = (c2); \ |
826 |
|
if (ch >= 0x80) \ |
827 |
|
ch = BYTE8_TO_CHAR (ch); \ |
828 |
|
CHAR_STRING_ADVANCE (ch, dst); \ |
829 |
|
} \ |
830 |
|
else \ |
831 |
|
{ \ |
832 |
|
*dst++ = (c1); \ |
833 |
|
*dst++ = (c2); \ |
834 |
|
} \ |
835 |
|
} while (0) |
836 |
|
|
837 |
|
|
838 |
|
#define EMIT_THREE_BYTES(c1, c2, c3) \ |
839 |
|
do { \ |
840 |
|
EMIT_ONE_BYTE (c1); \ |
841 |
|
EMIT_TWO_BYTES (c2, c3); \ |
842 |
|
} while (0) |
843 |
|
|
844 |
|
|
845 |
|
#define EMIT_FOUR_BYTES(c1, c2, c3, c4) \ |
846 |
|
do { \ |
847 |
|
EMIT_TWO_BYTES (c1, c2); \ |
848 |
|
EMIT_TWO_BYTES (c3, c4); \ |
849 |
|
} while (0) |
850 |
|
|
851 |
|
|
852 |
|
#define CODING_DECODE_CHAR(coding, src, src_base, src_end, charset, code, c) \ |
853 |
|
do { \ |
854 |
|
charset_map_loaded = 0; \ |
855 |
|
c = DECODE_CHAR (charset, code); \ |
856 |
|
if (charset_map_loaded) \ |
857 |
|
{ \ |
858 |
|
const unsigned char *orig = coding->source; \ |
859 |
|
EMACS_INT offset; \ |
860 |
|
\ |
861 |
|
coding_set_source (coding); \ |
862 |
|
offset = coding->source - orig; \ |
863 |
|
src += offset; \ |
864 |
|
src_base += offset; \ |
865 |
|
src_end += offset; \ |
866 |
|
} \ |
867 |
|
} while (0) |
868 |
|
|
869 |
|
|
870 |
|
#define ASSURE_DESTINATION(bytes) \ |
871 |
|
do { \ |
872 |
|
if (dst + (bytes) >= dst_end) \ |
873 |
|
{ \ |
874 |
|
int more_bytes = charbuf_end - charbuf + (bytes); \ |
875 |
|
\ |
876 |
|
dst = alloc_destination (coding, more_bytes, dst); \ |
877 |
|
dst_end = coding->destination + coding->dst_bytes; \ |
878 |
|
} \ |
879 |
|
} while (0) |
880 |
|
|
881 |
|
|
882 |
|
|
883 |
|
static void |
884 |
|
coding_set_source (coding) |
885 |
|
struct coding_system *coding; |
886 |
|
{ |
887 |
|
if (BUFFERP (coding->src_object)) |
888 |
|
{ |
889 |
|
struct buffer *buf = XBUFFER (coding->src_object); |
890 |
|
|
891 |
|
if (coding->src_pos < 0) |
892 |
|
coding->source = BUF_GAP_END_ADDR (buf) + coding->src_pos_byte; |
893 |
|
else |
894 |
|
coding->source = BUF_BYTE_ADDRESS (buf, coding->src_pos_byte); |
895 |
|
} |
896 |
|
else if (STRINGP (coding->src_object)) |
897 |
|
{ |
898 |
|
coding->source = SDATA (coding->src_object) + coding->src_pos_byte; |
899 |
|
} |
900 |
|
else |
901 |
|
/* Otherwise, the source is C string and is never relocated |
902 |
|
automatically. Thus we don't have to update anything. */ |
903 |
|
; |
904 |
|
} |
905 |
|
|
906 |
|
static void |
907 |
|
coding_set_destination (coding) |
908 |
|
struct coding_system *coding; |
909 |
|
{ |
910 |
|
if (BUFFERP (coding->dst_object)) |
911 |
|
{ |
912 |
|
if (coding->src_pos < 0) |
913 |
|
{ |
914 |
|
coding->destination = BEG_ADDR + coding->dst_pos_byte - 1; |
915 |
|
coding->dst_bytes = (GAP_END_ADDR |
916 |
|
- (coding->src_bytes - coding->consumed) |
917 |
|
- coding->destination); |
918 |
|
} |
919 |
|
else |
920 |
|
{ |
921 |
|
/* We are sure that coding->dst_pos_byte is before the gap |
922 |
|
of the buffer. */ |
923 |
|
coding->destination = (BUF_BEG_ADDR (XBUFFER (coding->dst_object)) |
924 |
|
+ coding->dst_pos_byte - 1); |
925 |
|
coding->dst_bytes = (BUF_GAP_END_ADDR (XBUFFER (coding->dst_object)) |
926 |
|
- coding->destination); |
927 |
|
} |
928 |
|
} |
929 |
|
else |
930 |
|
/* Otherwise, the destination is C string and is never relocated |
931 |
|
automatically. Thus we don't have to update anything. */ |
932 |
|
; |
933 |
|
} |
934 |
|
|
935 |
|
|
936 |
|
static void |
937 |
|
coding_alloc_by_realloc (coding, bytes) |
938 |
|
struct coding_system *coding; |
939 |
|
EMACS_INT bytes; |
940 |
|
{ |
941 |
|
coding->destination = (unsigned char *) xrealloc (coding->destination, |
942 |
|
coding->dst_bytes + bytes); |
943 |
|
coding->dst_bytes += bytes; |
944 |
|
} |
945 |
|
|
946 |
|
static void |
947 |
|
coding_alloc_by_making_gap (coding, bytes) |
948 |
|
struct coding_system *coding; |
949 |
|
EMACS_INT bytes; |
950 |
|
{ |
951 |
|
if (BUFFERP (coding->dst_object) |
952 |
|
&& EQ (coding->src_object, coding->dst_object)) |
953 |
|
{ |
954 |
|
EMACS_INT add = coding->src_bytes - coding->consumed; |
955 |
|
|
956 |
|
GAP_SIZE -= add; ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add; |
957 |
|
make_gap (bytes); |
958 |
|
GAP_SIZE += add; ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add; |
959 |
|
} |
960 |
|
else |
961 |
|
{ |
962 |
|
Lisp_Object this_buffer; |
963 |
|
|
964 |
|
this_buffer = Fcurrent_buffer (); |
965 |
|
set_buffer_internal (XBUFFER (coding->dst_object)); |
966 |
|
make_gap (bytes); |
967 |
|
set_buffer_internal (XBUFFER (this_buffer)); |
968 |
|
} |
969 |
|
} |
970 |
|
|
971 |
|
|
972 |
|
static unsigned char * |
973 |
|
alloc_destination (coding, nbytes, dst) |
974 |
|
struct coding_system *coding; |
975 |
|
int nbytes; |
976 |
|
unsigned char *dst; |
977 |
|
{ |
978 |
|
EMACS_INT offset = dst - coding->destination; |
979 |
|
|
980 |
|
if (BUFFERP (coding->dst_object)) |
981 |
|
coding_alloc_by_making_gap (coding, nbytes); |
982 |
|
else |
983 |
|
coding_alloc_by_realloc (coding, nbytes); |
984 |
|
coding->result = CODING_RESULT_SUCCESS; |
985 |
|
coding_set_destination (coding); |
986 |
|
dst = coding->destination + offset; |
987 |
|
return dst; |
988 |
|
} |
989 |
|
|
990 |
|
/** Macros for annotations. */ |
991 |
|
|
992 |
|
/* Maximum length of annotation data (sum of annotations for |
993 |
|
composition and charset). */ |
994 |
|
#define MAX_ANNOTATION_LENGTH (5 + (MAX_COMPOSITION_COMPONENTS * 2) - 1 + 5) |
995 |
|
|
996 |
|
/* An annotation data is stored in the array coding->charbuf in this |
997 |
|
format: |
998 |
|
[ -LENGTH ANNOTATION_MASK FROM TO ... ] |
999 |
|
LENGTH is the number of elements in the annotation. |
1000 |
|
ANNOTATION_MASK is one of CODING_ANNOTATE_XXX_MASK. |
1001 |
|
FROM and TO specify the range of text annotated. They are relative |
1002 |
|
to coding->src_pos (on encoding) or coding->dst_pos (on decoding). |
1003 |
|
|
1004 |
|
The format of the following elements depend on ANNOTATION_MASK. |
1005 |
|
|
1006 |
|
In the case of CODING_ANNOTATE_COMPOSITION_MASK, these elements |
1007 |
|
follows: |
1008 |
|
... METHOD [ COMPOSITION-COMPONENTS ... ] |
1009 |
|
METHOD is one of enum composition_method. |
1010 |
|
Optionnal COMPOSITION-COMPONENTS are characters and composition |
1011 |
|
rules. |
1012 |
|
|
1013 |
|
In the case of CODING_ANNOTATE_CHARSET_MASK, one element CHARSET-ID |
1014 |
|
follows. */ |
1015 |
|
|
1016 |
|
#define ADD_ANNOTATION_DATA(buf, len, mask, from, to) \ |
1017 |
|
do { \ |
1018 |
|
*(buf)++ = -(len); \ |
1019 |
|
*(buf)++ = (mask); \ |
1020 |
|
*(buf)++ = (from); \ |
1021 |
|
*(buf)++ = (to); \ |
1022 |
|
coding->annotated = 1; \ |
1023 |
|
} while (0); |
1024 |
|
|
1025 |
|
#define ADD_COMPOSITION_DATA(buf, from, to, method) \ |
1026 |
|
do { \ |
1027 |
|
ADD_ANNOTATION_DATA (buf, 5, CODING_ANNOTATE_COMPOSITION_MASK, from, to); \ |
1028 |
|
*buf++ = method; \ |
1029 |
|
} while (0) |
1030 |
|
|
1031 |
|
|
1032 |
|
#define ADD_CHARSET_DATA(buf, from, to, id) \ |
1033 |
|
do { \ |
1034 |
|
ADD_ANNOTATION_DATA (buf, 5, CODING_ANNOTATE_CHARSET_MASK, from, to); \ |
1035 |
|
*buf++ = id; \ |
1036 |
|
} while (0) |
1037 |
|
|
1038 |
|
|
1039 |
|
/*** 2. Emacs' internal format (emacs-utf-8) ***/ |
1040 |
|
|
1041 |
|
|
1042 |
|
|
1043 |
|
|
1044 |
|
/*** 3. UTF-8 ***/ |
1045 |
|
|
1046 |
|
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
1047 |
|
Check if a text is encoded in UTF-8. If it is, return 1, else |
1048 |
|
return 0. */ |
1049 |
|
|
1050 |
|
#define UTF_8_1_OCTET_P(c) ((c) < 0x80) |
1051 |
|
#define UTF_8_EXTRA_OCTET_P(c) (((c) & 0xC0) == 0x80) |
1052 |
|
#define UTF_8_2_OCTET_LEADING_P(c) (((c) & 0xE0) == 0xC0) |
1053 |
|
#define UTF_8_3_OCTET_LEADING_P(c) (((c) & 0xF0) == 0xE0) |
1054 |
|
#define UTF_8_4_OCTET_LEADING_P(c) (((c) & 0xF8) == 0xF0) |
1055 |
|
#define UTF_8_5_OCTET_LEADING_P(c) (((c) & 0xFC) == 0xF8) |
1056 |
|
|
1057 |
|
static int |
1058 |
|
detect_coding_utf_8 (coding, detect_info) |
1059 |
|
struct coding_system *coding; |
1060 |
|
struct coding_detection_info *detect_info; |
1061 |
|
{ |
1062 |
|
const unsigned char *src = coding->source, *src_base = src; |
1063 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
1064 |
|
int multibytep = coding->src_multibyte; |
1065 |
|
int consumed_chars = 0; |
1066 |
|
int found = 0; |
1067 |
|
int incomplete; |
1068 |
|
|
1069 |
|
detect_info->checked |= CATEGORY_MASK_UTF_8; |
1070 |
|
/* A coding system of this category is always ASCII compatible. */ |
1071 |
|
src += coding->head_ascii; |
1072 |
|
|
1073 |
|
while (1) |
1074 |
|
{ |
1075 |
|
int c, c1, c2, c3, c4; |
1076 |
|
|
1077 |
|
incomplete = 0; |
1078 |
|
ONE_MORE_BYTE (c); |
1079 |
|
if (UTF_8_1_OCTET_P (c)) |
1080 |
|
continue; |
1081 |
|
incomplete = 1; |
1082 |
|
ONE_MORE_BYTE (c1); |
1083 |
|
if (! UTF_8_EXTRA_OCTET_P (c1)) |
1084 |
|
break; |
1085 |
|
if (UTF_8_2_OCTET_LEADING_P (c)) |
1086 |
|
{ |
1087 |
|
found = CATEGORY_MASK_UTF_8; |
1088 |
|
continue; |
1089 |
|
} |
1090 |
|
ONE_MORE_BYTE (c2); |
1091 |
|
if (! UTF_8_EXTRA_OCTET_P (c2)) |
1092 |
|
break; |
1093 |
|
if (UTF_8_3_OCTET_LEADING_P (c)) |
1094 |
|
{ |
1095 |
|
found = CATEGORY_MASK_UTF_8; |
1096 |
|
continue; |
1097 |
|
} |
1098 |
|
ONE_MORE_BYTE (c3); |
1099 |
|
if (! UTF_8_EXTRA_OCTET_P (c3)) |
1100 |
|
break; |
1101 |
|
if (UTF_8_4_OCTET_LEADING_P (c)) |
1102 |
|
{ |
1103 |
|
found = CATEGORY_MASK_UTF_8; |
1104 |
|
continue; |
1105 |
|
} |
1106 |
|
ONE_MORE_BYTE (c4); |
1107 |
|
if (! UTF_8_EXTRA_OCTET_P (c4)) |
1108 |
|
break; |
1109 |
|
if (UTF_8_5_OCTET_LEADING_P (c)) |
1110 |
|
{ |
1111 |
|
found = CATEGORY_MASK_UTF_8; |
1112 |
|
continue; |
1113 |
|
} |
1114 |
|
break; |
1115 |
|
} |
1116 |
|
detect_info->rejected |= CATEGORY_MASK_UTF_8; |
1117 |
|
return 0; |
1118 |
|
|
1119 |
|
no_more_source: |
1120 |
|
if (incomplete && coding->mode & CODING_MODE_LAST_BLOCK) |
1121 |
|
{ |
1122 |
|
detect_info->rejected |= CATEGORY_MASK_UTF_8; |
1123 |
|
return 0; |
1124 |
|
} |
1125 |
|
detect_info->found |= found; |
1126 |
|
return 1; |
1127 |
|
} |
1128 |
|
|
1129 |
|
|
1130 |
|
static void |
1131 |
|
decode_coding_utf_8 (coding) |
1132 |
|
struct coding_system *coding; |
1133 |
|
{ |
1134 |
|
const unsigned char *src = coding->source + coding->consumed; |
1135 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
1136 |
|
const unsigned char *src_base; |
1137 |
|
int *charbuf = coding->charbuf; |
1138 |
|
int *charbuf_end = charbuf + coding->charbuf_size; |
1139 |
|
int consumed_chars = 0, consumed_chars_base; |
1140 |
|
int multibytep = coding->src_multibyte; |
1141 |
|
Lisp_Object attr, eol_type, charset_list; |
1142 |
|
|
1143 |
|
CODING_GET_INFO (coding, attr, eol_type, charset_list); |
1144 |
|
|
1145 |
|
while (1) |
1146 |
|
{ |
1147 |
|
int c, c1, c2, c3, c4, c5; |
1148 |
|
|
1149 |
|
src_base = src; |
1150 |
|
consumed_chars_base = consumed_chars; |
1151 |
|
|
1152 |
|
if (charbuf >= charbuf_end) |
1153 |
|
break; |
1154 |
|
|
1155 |
|
ONE_MORE_BYTE (c1); |
1156 |
|
if (UTF_8_1_OCTET_P(c1)) |
1157 |
|
{ |
1158 |
|
c = c1; |
1159 |
|
if (c == '\r') |
1160 |
|
{ |
1161 |
|
if (EQ (eol_type, Qdos)) |
1162 |
|
{ |
1163 |
|
if (src == src_end) |
1164 |
|
{ |
1165 |
|
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
1166 |
|
goto no_more_source; |
1167 |
|
} |
1168 |
|
if (*src == '\n') |
1169 |
|
ONE_MORE_BYTE (c); |
1170 |
|
} |
1171 |
|
else if (EQ (eol_type, Qmac)) |
1172 |
|
c = '\n'; |
1173 |
|
} |
1174 |
|
} |
1175 |
|
else |
1176 |
|
{ |
1177 |
|
ONE_MORE_BYTE (c2); |
1178 |
|
if (! UTF_8_EXTRA_OCTET_P (c2)) |
1179 |
|
goto invalid_code; |
1180 |
|
if (UTF_8_2_OCTET_LEADING_P (c1)) |
1181 |
|
{ |
1182 |
|
c = ((c1 & 0x1F) << 6) | (c2 & 0x3F); |
1183 |
|
/* Reject overlong sequences here and below. Encoders |
1184 |
|
producing them are incorrect, they can be misleading, |
1185 |
|
and they mess up read/write invariance. */ |
1186 |
|
if (c < 128) |
1187 |
|
goto invalid_code; |
1188 |
|
} |
1189 |
|
else |
1190 |
|
{ |
1191 |
|
ONE_MORE_BYTE (c3); |
1192 |
|
if (! UTF_8_EXTRA_OCTET_P (c3)) |
1193 |
|
goto invalid_code; |
1194 |
|
if (UTF_8_3_OCTET_LEADING_P (c1)) |
1195 |
|
{ |
1196 |
|
c = (((c1 & 0xF) << 12) |
1197 |
|
| ((c2 & 0x3F) << 6) | (c3 & 0x3F)); |
1198 |
|
if (c < 0x800 |
1199 |
|
|| (c >= 0xd800 && c < 0xe000)) /* surrogates (invalid) */ |
1200 |
|
goto invalid_code; |
1201 |
|
} |
1202 |
|
else |
1203 |
|
{ |
1204 |
|
ONE_MORE_BYTE (c4); |
1205 |
|
if (! UTF_8_EXTRA_OCTET_P (c4)) |
1206 |
|
goto invalid_code; |
1207 |
|
if (UTF_8_4_OCTET_LEADING_P (c1)) |
1208 |
|
{ |
1209 |
|
c = (((c1 & 0x7) << 18) | ((c2 & 0x3F) << 12) |
1210 |
|
| ((c3 & 0x3F) << 6) | (c4 & 0x3F)); |
1211 |
|
if (c < 0x10000) |
1212 |
|
goto invalid_code; |
1213 |
|
} |
1214 |
|
else |
1215 |
|
{ |
1216 |
|
ONE_MORE_BYTE (c5); |
1217 |
|
if (! UTF_8_EXTRA_OCTET_P (c5)) |
1218 |
|
goto invalid_code; |
1219 |
|
if (UTF_8_5_OCTET_LEADING_P (c1)) |
1220 |
|
{ |
1221 |
|
c = (((c1 & 0x3) << 24) | ((c2 & 0x3F) << 18) |
1222 |
|
| ((c3 & 0x3F) << 12) | ((c4 & 0x3F) << 6) |
1223 |
|
| (c5 & 0x3F)); |
1224 |
|
if ((c > MAX_CHAR) || (c < 0x200000)) |
1225 |
|
goto invalid_code; |
1226 |
|
} |
1227 |
|
else |
1228 |
|
goto invalid_code; |
1229 |
|
} |
1230 |
|
} |
1231 |
|
} |
1232 |
|
} |
1233 |
|
|
1234 |
|
*charbuf++ = c; |
1235 |
|
continue; |
1236 |
|
|
1237 |
|
invalid_code: |
1238 |
|
src = src_base; |
1239 |
|
consumed_chars = consumed_chars_base; |
1240 |
|
ONE_MORE_BYTE (c); |
1241 |
|
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
1242 |
|
coding->errors++; |
1243 |
|
} |
1244 |
|
|
1245 |
|
no_more_source: |
1246 |
|
coding->consumed_char += consumed_chars_base; |
1247 |
|
coding->consumed = src_base - coding->source; |
1248 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
1249 |
|
} |
1250 |
|
|
1251 |
|
|
1252 |
|
static int |
1253 |
|
encode_coding_utf_8 (coding) |
1254 |
|
struct coding_system *coding; |
1255 |
|
{ |
1256 |
|
int multibytep = coding->dst_multibyte; |
1257 |
|
int *charbuf = coding->charbuf; |
1258 |
|
int *charbuf_end = charbuf + coding->charbuf_used; |
1259 |
|
unsigned char *dst = coding->destination + coding->produced; |
1260 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
1261 |
|
int produced_chars = 0; |
1262 |
|
int c; |
1263 |
|
|
1264 |
|
if (multibytep) |
1265 |
|
{ |
1266 |
|
int safe_room = MAX_MULTIBYTE_LENGTH * 2; |
1267 |
|
|
1268 |
|
while (charbuf < charbuf_end) |
1269 |
|
{ |
1270 |
|
unsigned char str[MAX_MULTIBYTE_LENGTH], *p, *pend = str; |
1271 |
|
|
1272 |
|
ASSURE_DESTINATION (safe_room); |
1273 |
|
c = *charbuf++; |
1274 |
|
if (CHAR_BYTE8_P (c)) |
1275 |
|
{ |
1276 |
|
c = CHAR_TO_BYTE8 (c); |
1277 |
|
EMIT_ONE_BYTE (c); |
1278 |
|
} |
1279 |
|
else |
1280 |
|
{ |
1281 |
|
CHAR_STRING_ADVANCE (c, pend); |
1282 |
|
for (p = str; p < pend; p++) |
1283 |
|
EMIT_ONE_BYTE (*p); |
1284 |
|
} |
1285 |
|
} |
1286 |
|
} |
1287 |
|
else |
1288 |
|
{ |
1289 |
|
int safe_room = MAX_MULTIBYTE_LENGTH; |
1290 |
|
|
1291 |
|
while (charbuf < charbuf_end) |
1292 |
|
{ |
1293 |
|
ASSURE_DESTINATION (safe_room); |
1294 |
|
c = *charbuf++; |
1295 |
|
dst += CHAR_STRING (c, dst); |
1296 |
|
produced_chars++; |
1297 |
|
} |
1298 |
|
} |
1299 |
|
coding->result = CODING_RESULT_SUCCESS; |
1300 |
|
coding->produced_char += produced_chars; |
1301 |
|
coding->produced = dst - coding->destination; |
1302 |
|
return 0; |
1303 |
|
} |
1304 |
|
|
1305 |
|
|
1306 |
|
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
1307 |
|
Check if a text is encoded in one of UTF-16 based coding systems. |
1308 |
|
If it is, return 1, else return 0. */ |
1309 |
|
|
1310 |
|
#define UTF_16_HIGH_SURROGATE_P(val) \ |
1311 |
|
(((val) & 0xFC00) == 0xD800) |
1312 |
|
|
1313 |
|
#define UTF_16_LOW_SURROGATE_P(val) \ |
1314 |
|
(((val) & 0xFC00) == 0xDC00) |
1315 |
|
|
1316 |
|
#define UTF_16_INVALID_P(val) \ |
1317 |
|
(((val) == 0xFFFE) \ |
1318 |
|
|| ((val) == 0xFFFF) \ |
1319 |
|
|| UTF_16_LOW_SURROGATE_P (val)) |
1320 |
|
|
1321 |
|
|
1322 |
|
static int |
1323 |
|
detect_coding_utf_16 (coding, detect_info) |
1324 |
|
struct coding_system *coding; |
1325 |
|
struct coding_detection_info *detect_info; |
1326 |
|
{ |
1327 |
|
const unsigned char *src = coding->source, *src_base = src; |
1328 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
1329 |
|
int multibytep = coding->src_multibyte; |
1330 |
|
int consumed_chars = 0; |
1331 |
|
int c1, c2; |
1332 |
|
|
1333 |
|
detect_info->checked |= CATEGORY_MASK_UTF_16; |
1334 |
|
|
1335 |
|
if (coding->mode & CODING_MODE_LAST_BLOCK |
1336 |
|
&& (coding->src_bytes & 1)) |
1337 |
|
{ |
1338 |
|
detect_info->rejected |= CATEGORY_MASK_UTF_16; |
1339 |
|
return 0; |
1340 |
|
} |
1341 |
|
ONE_MORE_BYTE (c1); |
1342 |
|
ONE_MORE_BYTE (c2); |
1343 |
|
|
1344 |
|
if ((c1 == 0xFF) && (c2 == 0xFE)) |
1345 |
|
{ |
1346 |
|
detect_info->found |= (CATEGORY_MASK_UTF_16_LE |
1347 |
|
| CATEGORY_MASK_UTF_16_AUTO); |
1348 |
|
detect_info->rejected |= CATEGORY_MASK_UTF_16_BE; |
1349 |
|
} |
1350 |
|
else if ((c1 == 0xFE) && (c2 == 0xFF)) |
1351 |
|
{ |
1352 |
|
detect_info->found |= (CATEGORY_MASK_UTF_16_BE |
1353 |
|
| CATEGORY_MASK_UTF_16_AUTO); |
1354 |
|
detect_info->rejected |= CATEGORY_MASK_UTF_16_LE; |
1355 |
|
} |
1356 |
|
no_more_source: |
1357 |
|
return 1; |
1358 |
|
} |
1359 |
|
|
1360 |
|
static void |
1361 |
|
decode_coding_utf_16 (coding) |
1362 |
|
struct coding_system *coding; |
1363 |
{ |
{ |
1364 |
Lisp_Object coding_spec, plist, safe_chars; |
const unsigned char *src = coding->source + coding->consumed; |
1365 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
1366 |
|
const unsigned char *src_base; |
1367 |
|
int *charbuf = coding->charbuf; |
1368 |
|
int *charbuf_end = charbuf + coding->charbuf_size; |
1369 |
|
int consumed_chars = 0, consumed_chars_base; |
1370 |
|
int multibytep = coding->src_multibyte; |
1371 |
|
enum utf_16_bom_type bom = CODING_UTF_16_BOM (coding); |
1372 |
|
enum utf_16_endian_type endian = CODING_UTF_16_ENDIAN (coding); |
1373 |
|
int surrogate = CODING_UTF_16_SURROGATE (coding); |
1374 |
|
Lisp_Object attr, eol_type, charset_list; |
1375 |
|
|
1376 |
|
CODING_GET_INFO (coding, attr, eol_type, charset_list); |
1377 |
|
|
1378 |
coding_spec = Fget (coding_system, Qcoding_system); |
if (bom == utf_16_with_bom) |
1379 |
plist = XVECTOR (coding_spec)->contents[3]; |
{ |
1380 |
safe_chars = Fplist_get (XVECTOR (coding_spec)->contents[3], Qsafe_chars); |
int c, c1, c2; |
1381 |
return (CHAR_TABLE_P (safe_chars) ? safe_chars : Qt); |
|
1382 |
|
src_base = src; |
1383 |
|
ONE_MORE_BYTE (c1); |
1384 |
|
ONE_MORE_BYTE (c2); |
1385 |
|
c = (c1 << 8) | c2; |
1386 |
|
|
1387 |
|
if (endian == utf_16_big_endian |
1388 |
|
? c != 0xFEFF : c != 0xFFFE) |
1389 |
|
{ |
1390 |
|
/* The first two bytes are not BOM. Treat them as bytes |
1391 |
|
for a normal character. */ |
1392 |
|
src = src_base; |
1393 |
|
coding->errors++; |
1394 |
|
} |
1395 |
|
CODING_UTF_16_BOM (coding) = utf_16_without_bom; |
1396 |
|
} |
1397 |
|
else if (bom == utf_16_detect_bom) |
1398 |
|
{ |
1399 |
|
/* We have already tried to detect BOM and failed in |
1400 |
|
detect_coding. */ |
1401 |
|
CODING_UTF_16_BOM (coding) = utf_16_without_bom; |
1402 |
|
} |
1403 |
|
|
1404 |
|
while (1) |
1405 |
|
{ |
1406 |
|
int c, c1, c2; |
1407 |
|
|
1408 |
|
src_base = src; |
1409 |
|
consumed_chars_base = consumed_chars; |
1410 |
|
|
1411 |
|
if (charbuf + 2 >= charbuf_end) |
1412 |
|
break; |
1413 |
|
|
1414 |
|
ONE_MORE_BYTE (c1); |
1415 |
|
ONE_MORE_BYTE (c2); |
1416 |
|
c = (endian == utf_16_big_endian |
1417 |
|
? ((c1 << 8) | c2) : ((c2 << 8) | c1)); |
1418 |
|
if (surrogate) |
1419 |
|
{ |
1420 |
|
if (! UTF_16_LOW_SURROGATE_P (c)) |
1421 |
|
{ |
1422 |
|
if (endian == utf_16_big_endian) |
1423 |
|
c1 = surrogate >> 8, c2 = surrogate & 0xFF; |
1424 |
|
else |
1425 |
|
c1 = surrogate & 0xFF, c2 = surrogate >> 8; |
1426 |
|
*charbuf++ = c1; |
1427 |
|
*charbuf++ = c2; |
1428 |
|
coding->errors++; |
1429 |
|
if (UTF_16_HIGH_SURROGATE_P (c)) |
1430 |
|
CODING_UTF_16_SURROGATE (coding) = surrogate = c; |
1431 |
|
else |
1432 |
|
*charbuf++ = c; |
1433 |
|
} |
1434 |
|
else |
1435 |
|
{ |
1436 |
|
c = ((surrogate - 0xD800) << 10) | (c - 0xDC00); |
1437 |
|
CODING_UTF_16_SURROGATE (coding) = surrogate = 0; |
1438 |
|
*charbuf++ = c; |
1439 |
|
} |
1440 |
|
} |
1441 |
|
else |
1442 |
|
{ |
1443 |
|
if (UTF_16_HIGH_SURROGATE_P (c)) |
1444 |
|
CODING_UTF_16_SURROGATE (coding) = surrogate = c; |
1445 |
|
else |
1446 |
|
*charbuf++ = c; |
1447 |
|
} |
1448 |
|
} |
1449 |
|
|
1450 |
|
no_more_source: |
1451 |
|
coding->consumed_char += consumed_chars_base; |
1452 |
|
coding->consumed = src_base - coding->source; |
1453 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
1454 |
} |
} |
1455 |
|
|
1456 |
#define CODING_SAFE_CHAR_P(safe_chars, c) \ |
static int |
1457 |
(EQ (safe_chars, Qt) || !NILP (CHAR_TABLE_REF (safe_chars, c))) |
encode_coding_utf_16 (coding) |
1458 |
|
struct coding_system *coding; |
1459 |
|
{ |
1460 |
|
int multibytep = coding->dst_multibyte; |
1461 |
|
int *charbuf = coding->charbuf; |
1462 |
|
int *charbuf_end = charbuf + coding->charbuf_used; |
1463 |
|
unsigned char *dst = coding->destination + coding->produced; |
1464 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
1465 |
|
int safe_room = 8; |
1466 |
|
enum utf_16_bom_type bom = CODING_UTF_16_BOM (coding); |
1467 |
|
int big_endian = CODING_UTF_16_ENDIAN (coding) == utf_16_big_endian; |
1468 |
|
int produced_chars = 0; |
1469 |
|
Lisp_Object attrs, eol_type, charset_list; |
1470 |
|
int c; |
1471 |
|
|
1472 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
1473 |
|
|
1474 |
|
if (bom != utf_16_without_bom) |
1475 |
|
{ |
1476 |
|
ASSURE_DESTINATION (safe_room); |
1477 |
|
if (big_endian) |
1478 |
|
EMIT_TWO_BYTES (0xFE, 0xFF); |
1479 |
|
else |
1480 |
|
EMIT_TWO_BYTES (0xFF, 0xFE); |
1481 |
|
CODING_UTF_16_BOM (coding) = utf_16_without_bom; |
1482 |
|
} |
1483 |
|
|
1484 |
|
while (charbuf < charbuf_end) |
1485 |
|
{ |
1486 |
|
ASSURE_DESTINATION (safe_room); |
1487 |
|
c = *charbuf++; |
1488 |
|
if (c >= MAX_UNICODE_CHAR) |
1489 |
|
c = coding->default_char; |
1490 |
|
|
1491 |
|
if (c < 0x10000) |
1492 |
|
{ |
1493 |
|
if (big_endian) |
1494 |
|
EMIT_TWO_BYTES (c >> 8, c & 0xFF); |
1495 |
|
else |
1496 |
|
EMIT_TWO_BYTES (c & 0xFF, c >> 8); |
1497 |
|
} |
1498 |
|
else |
1499 |
|
{ |
1500 |
|
int c1, c2; |
1501 |
|
|
1502 |
|
c -= 0x10000; |
1503 |
|
c1 = (c >> 10) + 0xD800; |
1504 |
|
c2 = (c & 0x3FF) + 0xDC00; |
1505 |
|
if (big_endian) |
1506 |
|
EMIT_FOUR_BYTES (c1 >> 8, c1 & 0xFF, c2 >> 8, c2 & 0xFF); |
1507 |
|
else |
1508 |
|
EMIT_FOUR_BYTES (c1 & 0xFF, c1 >> 8, c2 & 0xFF, c2 >> 8); |
1509 |
|
} |
1510 |
|
} |
1511 |
|
coding->result = CODING_RESULT_SUCCESS; |
1512 |
|
coding->produced = dst - coding->destination; |
1513 |
|
coding->produced_char += produced_chars; |
1514 |
|
return 0; |
1515 |
|
} |
1516 |
|
|
1517 |
|
|
1518 |
/*** 2. Emacs internal format (emacs-mule) handlers ***/ |
/*** 6. Old Emacs' internal format (emacs-mule) ***/ |
1519 |
|
|
1520 |
/* Emacs' internal format for representation of multiple character |
/* Emacs' internal format for representation of multiple character |
1521 |
sets is a kind of multi-byte encoding, i.e. characters are |
sets is a kind of multi-byte encoding, i.e. characters are |
1557 |
In that case, a sequence of one-byte codes has a slightly different |
In that case, a sequence of one-byte codes has a slightly different |
1558 |
form. |
form. |
1559 |
|
|
1560 |
Firstly, all characters in eight-bit-control are represented by |
At first, all characters in eight-bit-control are represented by |
1561 |
one-byte sequences which are their 8-bit code. |
one-byte sequences which are their 8-bit code. |
1562 |
|
|
1563 |
Next, character composition data are represented by the byte |
Next, character composition data are represented by the byte |
1566 |
METHOD is 0xF0 plus one of composition method (enum |
METHOD is 0xF0 plus one of composition method (enum |
1567 |
composition_method), |
composition_method), |
1568 |
|
|
1569 |
BYTES is 0xA0 plus the byte length of these composition data, |
BYTES is 0xA0 plus a byte length of this composition data, |
1570 |
|
|
1571 |
CHARS is 0xA0 plus the number of characters composed by these |
CHARS is 0x20 plus a number of characters composed by this |
1572 |
data, |
data, |
1573 |
|
|
1574 |
COMPONENTs are characters of multibyte form or composition |
COMPONENTs are characters of multibye form or composition |
1575 |
rules encoded by two-byte of ASCII codes. |
rules encoded by two-byte of ASCII codes. |
1576 |
|
|
1577 |
In addition, for backward compatibility, the following formats are |
In addition, for backward compatibility, the following formats are |
1588 |
represents a composition rule. |
represents a composition rule. |
1589 |
*/ |
*/ |
1590 |
|
|
1591 |
enum emacs_code_class_type emacs_code_class[256]; |
char emacs_mule_bytes[256]; |
1592 |
|
|
1593 |
|
int |
1594 |
|
emacs_mule_char (coding, src, nbytes, nchars, id) |
1595 |
|
struct coding_system *coding; |
1596 |
|
unsigned char *src; |
1597 |
|
int *nbytes, *nchars, *id; |
1598 |
|
{ |
1599 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
1600 |
|
const unsigned char *src_base = src; |
1601 |
|
int multibytep = coding->src_multibyte; |
1602 |
|
struct charset *charset; |
1603 |
|
unsigned code; |
1604 |
|
int c; |
1605 |
|
int consumed_chars = 0; |
1606 |
|
|
1607 |
|
ONE_MORE_BYTE (c); |
1608 |
|
switch (emacs_mule_bytes[c]) |
1609 |
|
{ |
1610 |
|
case 2: |
1611 |
|
if (! (charset = emacs_mule_charset[c])) |
1612 |
|
goto invalid_code; |
1613 |
|
ONE_MORE_BYTE (c); |
1614 |
|
code = c & 0x7F; |
1615 |
|
break; |
1616 |
|
|
1617 |
|
case 3: |
1618 |
|
if (c == EMACS_MULE_LEADING_CODE_PRIVATE_11 |
1619 |
|
|| c == EMACS_MULE_LEADING_CODE_PRIVATE_12) |
1620 |
|
{ |
1621 |
|
ONE_MORE_BYTE (c); |
1622 |
|
if (! (charset = emacs_mule_charset[c])) |
1623 |
|
goto invalid_code; |
1624 |
|
ONE_MORE_BYTE (c); |
1625 |
|
code = c & 0x7F; |
1626 |
|
} |
1627 |
|
else |
1628 |
|
{ |
1629 |
|
if (! (charset = emacs_mule_charset[c])) |
1630 |
|
goto invalid_code; |
1631 |
|
ONE_MORE_BYTE (c); |
1632 |
|
code = (c & 0x7F) << 8; |
1633 |
|
ONE_MORE_BYTE (c); |
1634 |
|
code |= c & 0x7F; |
1635 |
|
} |
1636 |
|
break; |
1637 |
|
|
1638 |
|
case 4: |
1639 |
|
ONE_MORE_BYTE (c); |
1640 |
|
if (! (charset = emacs_mule_charset[c])) |
1641 |
|
goto invalid_code; |
1642 |
|
ONE_MORE_BYTE (c); |
1643 |
|
code = (c & 0x7F) << 8; |
1644 |
|
ONE_MORE_BYTE (c); |
1645 |
|
code |= c & 0x7F; |
1646 |
|
break; |
1647 |
|
|
1648 |
|
case 1: |
1649 |
|
code = c; |
1650 |
|
charset = CHARSET_FROM_ID (ASCII_BYTE_P (code) |
1651 |
|
? charset_ascii : charset_eight_bit); |
1652 |
|
break; |
1653 |
|
|
1654 |
|
default: |
1655 |
|
abort (); |
1656 |
|
} |
1657 |
|
c = DECODE_CHAR (charset, code); |
1658 |
|
if (c < 0) |
1659 |
|
goto invalid_code; |
1660 |
|
*nbytes = src - src_base; |
1661 |
|
*nchars = consumed_chars; |
1662 |
|
if (id) |
1663 |
|
*id = charset->id; |
1664 |
|
return c; |
1665 |
|
|
1666 |
|
no_more_source: |
1667 |
|
return -2; |
1668 |
|
|
1669 |
|
invalid_code: |
1670 |
|
return -1; |
1671 |
|
} |
1672 |
|
|
1673 |
|
|
1674 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
1675 |
Check if a text is encoded in Emacs' internal format. If it is, |
Check if a text is encoded in `emacs-mule'. If it is, return 1, |
1676 |
return CODING_CATEGORY_MASK_EMACS_MULE, else return 0. */ |
else return 0. */ |
1677 |
|
|
1678 |
static int |
static int |
1679 |
detect_coding_emacs_mule (src, src_end, multibytep) |
detect_coding_emacs_mule (coding, detect_info) |
1680 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
1681 |
int multibytep; |
struct coding_detection_info *detect_info; |
1682 |
{ |
{ |
1683 |
unsigned char c; |
const unsigned char *src = coding->source, *src_base = src; |
1684 |
int composing = 0; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
1685 |
/* Dummy for ONE_MORE_BYTE. */ |
int multibytep = coding->src_multibyte; |
1686 |
struct coding_system dummy_coding; |
int consumed_chars = 0; |
1687 |
struct coding_system *coding = &dummy_coding; |
int c; |
1688 |
|
int found = 0; |
1689 |
|
int incomplete; |
1690 |
|
|
1691 |
|
detect_info->checked |= CATEGORY_MASK_EMACS_MULE; |
1692 |
|
/* A coding system of this category is always ASCII compatible. */ |
1693 |
|
src += coding->head_ascii; |
1694 |
|
|
1695 |
while (1) |
while (1) |
1696 |
{ |
{ |
1697 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
incomplete = 0; |
1698 |
|
ONE_MORE_BYTE (c); |
1699 |
|
incomplete = 1; |
1700 |
|
|
1701 |
if (composing) |
if (c == 0x80) |
1702 |
{ |
{ |
1703 |
if (c < 0xA0) |
/* Perhaps the start of composite character. We simple skip |
1704 |
composing = 0; |
it because analyzing it is too heavy for detecting. But, |
1705 |
else if (c == 0xA0) |
at least, we check that the composite character |
1706 |
|
constitues of more than 4 bytes. */ |
1707 |
|
const unsigned char *src_base; |
1708 |
|
|
1709 |
|
repeat: |
1710 |
|
src_base = src; |
1711 |
|
do |
1712 |
{ |
{ |
1713 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
|
c &= 0x7F; |
|
1714 |
} |
} |
1715 |
else |
while (c >= 0xA0); |
1716 |
c -= 0x20; |
|
1717 |
|
if (src - src_base <= 4) |
1718 |
|
break; |
1719 |
|
found = CATEGORY_MASK_EMACS_MULE; |
1720 |
|
if (c == 0x80) |
1721 |
|
goto repeat; |
1722 |
} |
} |
1723 |
|
|
1724 |
if (c < 0x20) |
if (c < 0x80) |
1725 |
{ |
{ |
1726 |
if (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO) |
if (c < 0x20 |
1727 |
return 0; |
&& (c == ISO_CODE_ESC || c == ISO_CODE_SI || c == ISO_CODE_SO)) |
1728 |
|
break; |
1729 |
} |
} |
1730 |
else if (c >= 0x80 && c < 0xA0) |
else |
1731 |
{ |
{ |
1732 |
if (c == 0x80) |
const unsigned char *src_base = src - 1; |
|
/* Old leading code for a composite character. */ |
|
|
composing = 1; |
|
|
else |
|
|
{ |
|
|
unsigned char *src_base = src - 1; |
|
|
int bytes; |
|
1733 |
|
|
1734 |
if (!UNIBYTE_STR_AS_MULTIBYTE_P (src_base, src_end - src_base, |
do |
1735 |
bytes)) |
{ |
1736 |
return 0; |
ONE_MORE_BYTE (c); |
|
src = src_base + bytes; |
|
1737 |
} |
} |
1738 |
|
while (c >= 0xA0); |
1739 |
|
if (src - src_base != emacs_mule_bytes[*src_base]) |
1740 |
|
break; |
1741 |
|
found = CATEGORY_MASK_EMACS_MULE; |
1742 |
} |
} |
1743 |
} |
} |
1744 |
label_end_of_loop: |
detect_info->rejected |= CATEGORY_MASK_EMACS_MULE; |
1745 |
return CODING_CATEGORY_MASK_EMACS_MULE; |
return 0; |
1746 |
|
|
1747 |
|
no_more_source: |
1748 |
|
if (incomplete && coding->mode & CODING_MODE_LAST_BLOCK) |
1749 |
|
{ |
1750 |
|
detect_info->rejected |= CATEGORY_MASK_EMACS_MULE; |
1751 |
|
return 0; |
1752 |
|
} |
1753 |
|
detect_info->found |= found; |
1754 |
|
return 1; |
1755 |
} |
} |
1756 |
|
|
1757 |
|
|
1758 |
/* Record the starting position START and METHOD of one composition. */ |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
1759 |
|
|
1760 |
#define CODING_ADD_COMPOSITION_START(coding, start, method) \ |
/* Decode a character represented as a component of composition |
1761 |
do { \ |
sequence of Emacs 20/21 style at SRC. Set C to that character and |
1762 |
struct composition_data *cmp_data = coding->cmp_data; \ |
update SRC to the head of next character (or an encoded composition |
1763 |
int *data = cmp_data->data + cmp_data->used; \ |
rule). If SRC doesn't points a composition component, set C to -1. |
1764 |
coding->cmp_data_start = cmp_data->used; \ |
If SRC points an invalid byte sequence, global exit by a return |
1765 |
data[0] = -1; \ |
value 0. */ |
1766 |
data[1] = cmp_data->char_offset + start; \ |
|
1767 |
data[3] = (int) method; \ |
#define DECODE_EMACS_MULE_COMPOSITION_CHAR(buf) \ |
1768 |
cmp_data->used += 4; \ |
if (1) \ |
1769 |
|
{ \ |
1770 |
|
int c; \ |
1771 |
|
int nbytes, nchars; \ |
1772 |
|
\ |
1773 |
|
if (src == src_end) \ |
1774 |
|
break; \ |
1775 |
|
c = emacs_mule_char (coding, src, &nbytes, &nchars, NULL);\ |
1776 |
|
if (c < 0) \ |
1777 |
|
{ \ |
1778 |
|
if (c == -2) \ |
1779 |
|
break; \ |
1780 |
|
goto invalid_code; \ |
1781 |
|
} \ |
1782 |
|
*buf++ = c; \ |
1783 |
|
src += nbytes; \ |
1784 |
|
consumed_chars += nchars; \ |
1785 |
|
} \ |
1786 |
|
else |
1787 |
|
|
1788 |
|
|
1789 |
|
/* Decode a composition rule represented as a component of composition |
1790 |
|
sequence of Emacs 20 style at SRC. Store the decoded rule in *BUF, |
1791 |
|
and increment BUF. If SRC points an invalid byte sequence, set C |
1792 |
|
to -1. */ |
1793 |
|
|
1794 |
|
#define DECODE_EMACS_MULE_COMPOSITION_RULE_20(buf) \ |
1795 |
|
do { \ |
1796 |
|
int c, gref, nref; \ |
1797 |
|
\ |
1798 |
|
if (src >= src_end) \ |
1799 |
|
goto invalid_code; \ |
1800 |
|
ONE_MORE_BYTE_NO_CHECK (c); \ |
1801 |
|
c -= 0x20; \ |
1802 |
|
if (c < 0 || c >= 81) \ |
1803 |
|
goto invalid_code; \ |
1804 |
|
\ |
1805 |
|
gref = c / 9, nref = c % 9; \ |
1806 |
|
*buf++ = COMPOSITION_ENCODE_RULE (gref, nref); \ |
1807 |
} while (0) |
} while (0) |
1808 |
|
|
|
/* Record the ending position END of the current composition. */ |
|
1809 |
|
|
1810 |
#define CODING_ADD_COMPOSITION_END(coding, end) \ |
/* Decode a composition rule represented as a component of composition |
1811 |
do { \ |
sequence of Emacs 21 style at SRC. Store the decoded rule in *BUF, |
1812 |
struct composition_data *cmp_data = coding->cmp_data; \ |
and increment BUF. If SRC points an invalid byte sequence, set C |
1813 |
int *data = cmp_data->data + coding->cmp_data_start; \ |
to -1. */ |
1814 |
data[0] = cmp_data->used - coding->cmp_data_start; \ |
|
1815 |
data[2] = cmp_data->char_offset + end; \ |
#define DECODE_EMACS_MULE_COMPOSITION_RULE_21(buf) \ |
1816 |
|
do { \ |
1817 |
|
int gref, nref; \ |
1818 |
|
\ |
1819 |
|
if (src + 1>= src_end) \ |
1820 |
|
goto invalid_code; \ |
1821 |
|
ONE_MORE_BYTE_NO_CHECK (gref); \ |
1822 |
|
gref -= 0x20; \ |
1823 |
|
ONE_MORE_BYTE_NO_CHECK (nref); \ |
1824 |
|
nref -= 0x20; \ |
1825 |
|
if (gref < 0 || gref >= 81 \ |
1826 |
|
|| nref < 0 || nref >= 81) \ |
1827 |
|
goto invalid_code; \ |
1828 |
|
*buf++ = COMPOSITION_ENCODE_RULE (gref, nref); \ |
1829 |
} while (0) |
} while (0) |
1830 |
|
|
|
/* Record one COMPONENT (alternate character or composition rule). */ |
|
1831 |
|
|
1832 |
#define CODING_ADD_COMPOSITION_COMPONENT(coding, component) \ |
#define DECODE_EMACS_MULE_21_COMPOSITION(c) \ |
1833 |
do { \ |
do { \ |
1834 |
coding->cmp_data->data[coding->cmp_data->used++] = component; \ |
/* Emacs 21 style format. The first three bytes at SRC are \ |
1835 |
if (coding->cmp_data->used - coding->cmp_data_start \ |
(METHOD - 0xF2), (BYTES - 0xA0), (CHARS - 0xA0), where BYTES is \ |
1836 |
== COMPOSITION_DATA_MAX_BUNCH_LENGTH) \ |
the byte length of this composition information, CHARS is the \ |
1837 |
|
number of characters composed by this composition. */ \ |
1838 |
|
enum composition_method method = c - 0xF2; \ |
1839 |
|
int *charbuf_base = charbuf; \ |
1840 |
|
int from, to; \ |
1841 |
|
int consumed_chars_limit; \ |
1842 |
|
int nbytes, nchars; \ |
1843 |
|
\ |
1844 |
|
ONE_MORE_BYTE (c); \ |
1845 |
|
nbytes = c - 0xA0; \ |
1846 |
|
if (nbytes < 3) \ |
1847 |
|
goto invalid_code; \ |
1848 |
|
ONE_MORE_BYTE (c); \ |
1849 |
|
nchars = c - 0xA0; \ |
1850 |
|
from = coding->produced + char_offset; \ |
1851 |
|
to = from + nchars; \ |
1852 |
|
ADD_COMPOSITION_DATA (charbuf, from, to, method); \ |
1853 |
|
consumed_chars_limit = consumed_chars_base + nbytes; \ |
1854 |
|
if (method != COMPOSITION_RELATIVE) \ |
1855 |
{ \ |
{ \ |
1856 |
CODING_ADD_COMPOSITION_END (coding, coding->produced_char); \ |
int i = 0; \ |
1857 |
coding->composing = COMPOSITION_NO; \ |
while (consumed_chars < consumed_chars_limit) \ |
1858 |
|
{ \ |
1859 |
|
if (i % 2 && method != COMPOSITION_WITH_ALTCHARS) \ |
1860 |
|
DECODE_EMACS_MULE_COMPOSITION_RULE_21 (charbuf); \ |
1861 |
|
else \ |
1862 |
|
DECODE_EMACS_MULE_COMPOSITION_CHAR (charbuf); \ |
1863 |
|
i++; \ |
1864 |
|
} \ |
1865 |
|
if (consumed_chars < consumed_chars_limit) \ |
1866 |
|
goto invalid_code; \ |
1867 |
|
charbuf_base[0] -= i; \ |
1868 |
} \ |
} \ |
1869 |
} while (0) |
} while (0) |
1870 |
|
|
1871 |
|
|
1872 |
/* Get one byte from a data pointed by SRC and increment SRC. If SRC |
#define DECODE_EMACS_MULE_20_RELATIVE_COMPOSITION(c) \ |
1873 |
is not less than SRC_END, return -1 without incrementing Src. */ |
do { \ |
1874 |
|
/* Emacs 20 style format for relative composition. */ \ |
1875 |
#define SAFE_ONE_MORE_BYTE() (src >= src_end ? -1 : *src++) |
/* Store multibyte form of characters to be composed. */ \ |
1876 |
|
enum composition_method method = COMPOSITION_RELATIVE; \ |
1877 |
|
int components[MAX_COMPOSITION_COMPONENTS * 2 - 1]; \ |
1878 |
|
int *buf = components; \ |
1879 |
|
int i, j; \ |
1880 |
|
int from, to; \ |
1881 |
|
\ |
1882 |
|
src = src_base; \ |
1883 |
|
ONE_MORE_BYTE (c); /* skip 0x80 */ \ |
1884 |
|
for (i = 0; i < MAX_COMPOSITION_COMPONENTS; i++) \ |
1885 |
|
DECODE_EMACS_MULE_COMPOSITION_CHAR (buf); \ |
1886 |
|
if (i < 2) \ |
1887 |
|
goto invalid_code; \ |
1888 |
|
from = coding->produced_char + char_offset; \ |
1889 |
|
to = from + i; \ |
1890 |
|
ADD_COMPOSITION_DATA (charbuf, from, to, method); \ |
1891 |
|
for (j = 0; j < i; j++) \ |
1892 |
|
*charbuf++ = components[j]; \ |
1893 |
|
} while (0) |
1894 |
|
|
1895 |
|
|
1896 |
/* Decode a character represented as a component of composition |
#define DECODE_EMACS_MULE_20_RULEBASE_COMPOSITION(c) \ |
|
sequence of Emacs 20 style at SRC. Set C to that character, store |
|
|
its multibyte form sequence at P, and set P to the end of that |
|
|
sequence. If no valid character is found, set C to -1. */ |
|
|
|
|
|
#define DECODE_EMACS_MULE_COMPOSITION_CHAR(c, p) \ |
|
1897 |
do { \ |
do { \ |
1898 |
int bytes; \ |
/* Emacs 20 style format for rule-base composition. */ \ |
1899 |
|
/* Store multibyte form of characters to be composed. */ \ |
1900 |
|
enum composition_method method = COMPOSITION_WITH_RULE; \ |
1901 |
|
int components[MAX_COMPOSITION_COMPONENTS * 2 - 1]; \ |
1902 |
|
int *buf = components; \ |
1903 |
|
int i, j; \ |
1904 |
|
int from, to; \ |
1905 |
\ |
\ |
1906 |
c = SAFE_ONE_MORE_BYTE (); \ |
DECODE_EMACS_MULE_COMPOSITION_CHAR (buf); \ |
1907 |
if (c < 0) \ |
for (i = 0; i < MAX_COMPOSITION_COMPONENTS; i++) \ |
|
break; \ |
|
|
if (CHAR_HEAD_P (c)) \ |
|
|
c = -1; \ |
|
|
else if (c == 0xA0) \ |
|
1908 |
{ \ |
{ \ |
1909 |
c = SAFE_ONE_MORE_BYTE (); \ |
DECODE_EMACS_MULE_COMPOSITION_RULE_20 (buf); \ |
1910 |
if (c < 0xA0) \ |
DECODE_EMACS_MULE_COMPOSITION_CHAR (buf); \ |
|
c = -1; \ |
|
|
else \ |
|
|
{ \ |
|
|
c -= 0xA0; \ |
|
|
*p++ = c; \ |
|
|
} \ |
|
|
} \ |
|
|
else if (BASE_LEADING_CODE_P (c - 0x20)) \ |
|
|
{ \ |
|
|
unsigned char *p0 = p; \ |
|
|
\ |
|
|
c -= 0x20; \ |
|
|
*p++ = c; \ |
|
|
bytes = BYTES_BY_CHAR_HEAD (c); \ |
|
|
while (--bytes) \ |
|
|
{ \ |
|
|
c = SAFE_ONE_MORE_BYTE (); \ |
|
|
if (c < 0) \ |
|
|
break; \ |
|
|
*p++ = c; \ |
|
|
} \ |
|
|
if (UNIBYTE_STR_AS_MULTIBYTE_P (p0, p - p0, bytes) \ |
|
|
|| (coding->flags /* We are recovering a file. */ \ |
|
|
&& p0[0] == LEADING_CODE_8_BIT_CONTROL \ |
|
|
&& ! CHAR_HEAD_P (p0[1]))) \ |
|
|
c = STRING_CHAR (p0, bytes); \ |
|
|
else \ |
|
|
c = -1; \ |
|
1911 |
} \ |
} \ |
1912 |
else \ |
if (i < 1 || (buf - components) % 2 == 0) \ |
1913 |
c = -1; \ |
goto invalid_code; \ |
1914 |
|
if (charbuf + i + (i / 2) + 1 < charbuf_end) \ |
1915 |
|
goto no_more_source; \ |
1916 |
|
from = coding->produced_char + char_offset; \ |
1917 |
|
to = from + i; \ |
1918 |
|
ADD_COMPOSITION_DATA (buf, from, to, method); \ |
1919 |
|
for (j = 0; j < i; j++) \ |
1920 |
|
*charbuf++ = components[j]; \ |
1921 |
|
for (j = 0; j < i; j += 2) \ |
1922 |
|
*charbuf++ = components[j]; \ |
1923 |
} while (0) |
} while (0) |
1924 |
|
|
1925 |
|
|
1926 |
/* Decode a composition rule represented as a component of composition |
static void |
1927 |
sequence of Emacs 20 style at SRC. Set C to the rule. If not |
decode_coding_emacs_mule (coding) |
|
valid rule is found, set C to -1. */ |
|
|
|
|
|
#define DECODE_EMACS_MULE_COMPOSITION_RULE(c) \ |
|
|
do { \ |
|
|
c = SAFE_ONE_MORE_BYTE (); \ |
|
|
c -= 0xA0; \ |
|
|
if (c < 0 || c >= 81) \ |
|
|
c = -1; \ |
|
|
else \ |
|
|
{ \ |
|
|
gref = c / 9, nref = c % 9; \ |
|
|
c = COMPOSITION_ENCODE_RULE (gref, nref); \ |
|
|
} \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* Decode composition sequence encoded by `emacs-mule' at the source |
|
|
pointed by SRC. SRC_END is the end of source. Store information |
|
|
of the composition in CODING->cmp_data. |
|
|
|
|
|
For backward compatibility, decode also a composition sequence of |
|
|
Emacs 20 style. In that case, the composition sequence contains |
|
|
characters that should be extracted into a buffer or string. Store |
|
|
those characters at *DESTINATION in multibyte form. |
|
|
|
|
|
If we encounter an invalid byte sequence, return 0. |
|
|
If we encounter an insufficient source or destination, or |
|
|
insufficient space in CODING->cmp_data, return 1. |
|
|
Otherwise, return consumed bytes in the source. |
|
|
|
|
|
*/ |
|
|
static INLINE int |
|
|
decode_composition_emacs_mule (coding, src, src_end, |
|
|
destination, dst_end, dst_bytes) |
|
1928 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *src, *src_end, **destination, *dst_end; |
|
|
int dst_bytes; |
|
1929 |
{ |
{ |
1930 |
unsigned char *dst = *destination; |
const unsigned char *src = coding->source + coding->consumed; |
1931 |
int method, data_len, nchars; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
1932 |
unsigned char *src_base = src++; |
const unsigned char *src_base; |
1933 |
/* Store components of composition. */ |
int *charbuf = coding->charbuf; |
1934 |
int component[COMPOSITION_DATA_MAX_BUNCH_LENGTH]; |
int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH; |
1935 |
int ncomponent; |
int consumed_chars = 0, consumed_chars_base; |
1936 |
/* Store multibyte form of characters to be composed. This is for |
int multibytep = coding->src_multibyte; |
1937 |
Emacs 20 style composition sequence. */ |
Lisp_Object attrs, eol_type, charset_list; |
1938 |
unsigned char buf[MAX_COMPOSITION_COMPONENTS * MAX_MULTIBYTE_LENGTH]; |
int char_offset = coding->produced_char; |
1939 |
unsigned char *bufp = buf; |
int last_offset = char_offset; |
1940 |
int c, i, gref, nref; |
int last_id = charset_ascii; |
1941 |
|
|
1942 |
if (coding->cmp_data->used + COMPOSITION_DATA_MAX_BUNCH_LENGTH |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
|
>= COMPOSITION_DATA_SIZE) |
|
|
{ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_CMP; |
|
|
return -1; |
|
|
} |
|
1943 |
|
|
1944 |
ONE_MORE_BYTE (c); |
while (1) |
|
if (c - 0xF0 >= COMPOSITION_RELATIVE |
|
|
&& c - 0xF0 <= COMPOSITION_WITH_RULE_ALTCHARS) |
|
1945 |
{ |
{ |
1946 |
int with_rule; |
int c; |
1947 |
|
|
1948 |
|
src_base = src; |
1949 |
|
consumed_chars_base = consumed_chars; |
1950 |
|
|
1951 |
|
if (charbuf >= charbuf_end) |
1952 |
|
break; |
1953 |
|
|
|
method = c - 0xF0; |
|
|
with_rule = (method == COMPOSITION_WITH_RULE |
|
|
|| method == COMPOSITION_WITH_RULE_ALTCHARS); |
|
|
ONE_MORE_BYTE (c); |
|
|
data_len = c - 0xA0; |
|
|
if (data_len < 4 |
|
|
|| src_base + data_len > src_end) |
|
|
return 0; |
|
1954 |
ONE_MORE_BYTE (c); |
ONE_MORE_BYTE (c); |
|
nchars = c - 0xA0; |
|
|
if (c < 1) |
|
|
return 0; |
|
|
for (ncomponent = 0; src < src_base + data_len; ncomponent++) |
|
|
{ |
|
|
/* If it is longer than this, it can't be valid. */ |
|
|
if (ncomponent >= COMPOSITION_DATA_MAX_BUNCH_LENGTH) |
|
|
return 0; |
|
1955 |
|
|
1956 |
if (ncomponent % 2 && with_rule) |
if (c < 0x80) |
1957 |
{ |
{ |
1958 |
ONE_MORE_BYTE (gref); |
if (c == '\r') |
|
gref -= 32; |
|
|
ONE_MORE_BYTE (nref); |
|
|
nref -= 32; |
|
|
c = COMPOSITION_ENCODE_RULE (gref, nref); |
|
|
} |
|
|
else |
|
1959 |
{ |
{ |
1960 |
int bytes; |
if (EQ (eol_type, Qdos)) |
1961 |
if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes) |
{ |
1962 |
|| (coding->flags /* We are recovering a file. */ |
if (src == src_end) |
1963 |
&& src[0] == LEADING_CODE_8_BIT_CONTROL |
{ |
1964 |
&& ! CHAR_HEAD_P (src[1]))) |
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
1965 |
c = STRING_CHAR (src, bytes); |
goto no_more_source; |
1966 |
else |
} |
1967 |
c = *src, bytes = 1; |
if (*src == '\n') |
1968 |
src += bytes; |
ONE_MORE_BYTE (c); |
1969 |
|
} |
1970 |
|
else if (EQ (eol_type, Qmac)) |
1971 |
|
c = '\n'; |
1972 |
} |
} |
1973 |
component[ncomponent] = c; |
*charbuf++ = c; |
1974 |
|
char_offset++; |
1975 |
} |
} |
1976 |
} |
else if (c == 0x80) |
|
else |
|
|
{ |
|
|
/* This may be an old Emacs 20 style format. See the comment at |
|
|
the section 2 of this file. */ |
|
|
while (src < src_end && !CHAR_HEAD_P (*src)) src++; |
|
|
if (src == src_end |
|
|
&& !(coding->mode & CODING_MODE_LAST_BLOCK)) |
|
|
goto label_end_of_loop; |
|
|
|
|
|
src_end = src; |
|
|
src = src_base + 1; |
|
|
if (c < 0xC0) |
|
1977 |
{ |
{ |
1978 |
method = COMPOSITION_RELATIVE; |
ONE_MORE_BYTE (c); |
1979 |
for (ncomponent = 0; ncomponent < MAX_COMPOSITION_COMPONENTS;) |
if (c - 0xF2 >= COMPOSITION_RELATIVE |
1980 |
{ |
&& c - 0xF2 <= COMPOSITION_WITH_RULE_ALTCHARS) |
1981 |
DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp); |
DECODE_EMACS_MULE_21_COMPOSITION (c); |
1982 |
if (c < 0) |
else if (c < 0xC0) |
1983 |
break; |
DECODE_EMACS_MULE_20_RELATIVE_COMPOSITION (c); |
1984 |
component[ncomponent++] = c; |
else if (c == 0xFF) |
1985 |
} |
DECODE_EMACS_MULE_20_RULEBASE_COMPOSITION (c); |
1986 |
if (ncomponent < 2) |
else |
1987 |
return 0; |
goto invalid_code; |
|
nchars = ncomponent; |
|
1988 |
} |
} |
1989 |
else if (c == 0xFF) |
else if (c < 0xA0 && emacs_mule_bytes[c] > 1) |
1990 |
{ |
{ |
1991 |
method = COMPOSITION_WITH_RULE; |
int nbytes, nchars; |
1992 |
src++; |
int id; |
1993 |
DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp); |
|
1994 |
|
src = src_base; |
1995 |
|
consumed_chars = consumed_chars_base; |
1996 |
|
c = emacs_mule_char (coding, src, &nbytes, &nchars, &id); |
1997 |
if (c < 0) |
if (c < 0) |
|
return 0; |
|
|
component[0] = c; |
|
|
for (ncomponent = 1; |
|
|
ncomponent < MAX_COMPOSITION_COMPONENTS * 2 - 1;) |
|
1998 |
{ |
{ |
1999 |
DECODE_EMACS_MULE_COMPOSITION_RULE (c); |
if (c == -2) |
|
if (c < 0) |
|
|
break; |
|
|
component[ncomponent++] = c; |
|
|
DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp); |
|
|
if (c < 0) |
|
2000 |
break; |
break; |
2001 |
component[ncomponent++] = c; |
goto invalid_code; |
2002 |
} |
} |
2003 |
if (ncomponent < 3) |
if (last_id != id) |
2004 |
return 0; |
{ |
2005 |
nchars = (ncomponent + 1) / 2; |
if (last_id != charset_ascii) |
2006 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
2007 |
|
last_id = id; |
2008 |
|
last_offset = char_offset; |
2009 |
|
} |
2010 |
|
*charbuf++ = c; |
2011 |
|
src += nbytes; |
2012 |
|
consumed_chars += nchars; |
2013 |
|
char_offset++; |
2014 |
} |
} |
2015 |
else |
continue; |
|
return 0; |
|
|
} |
|
2016 |
|
|
2017 |
if (buf == bufp || dst + (bufp - buf) <= (dst_bytes ? dst_end : src)) |
invalid_code: |
2018 |
{ |
src = src_base; |
2019 |
CODING_ADD_COMPOSITION_START (coding, coding->produced_char, method); |
consumed_chars = consumed_chars_base; |
2020 |
for (i = 0; i < ncomponent; i++) |
ONE_MORE_BYTE (c); |
2021 |
CODING_ADD_COMPOSITION_COMPONENT (coding, component[i]); |
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
2022 |
CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars); |
char_offset++; |
2023 |
if (buf < bufp) |
coding->errors++; |
|
{ |
|
|
unsigned char *p = buf; |
|
|
EMIT_BYTES (p, bufp); |
|
|
*destination += bufp - buf; |
|
|
coding->produced_char += nchars; |
|
|
} |
|
|
return (src - src_base); |
|
2024 |
} |
} |
2025 |
label_end_of_loop: |
|
2026 |
return -1; |
no_more_source: |
2027 |
|
if (last_id != charset_ascii) |
2028 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
2029 |
|
coding->consumed_char += consumed_chars_base; |
2030 |
|
coding->consumed = src_base - coding->source; |
2031 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
2032 |
} |
} |
2033 |
|
|
|
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
|
2034 |
|
|
2035 |
static void |
#define EMACS_MULE_LEADING_CODES(id, codes) \ |
2036 |
decode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes) |
do { \ |
2037 |
|
if (id < 0xA0) \ |
2038 |
|
codes[0] = id, codes[1] = 0; \ |
2039 |
|
else if (id < 0xE0) \ |
2040 |
|
codes[0] = 0x9A, codes[1] = id; \ |
2041 |
|
else if (id < 0xF0) \ |
2042 |
|
codes[0] = 0x9B, codes[1] = id; \ |
2043 |
|
else if (id < 0xF5) \ |
2044 |
|
codes[0] = 0x9C, codes[1] = id; \ |
2045 |
|
else \ |
2046 |
|
codes[0] = 0x9D, codes[1] = id; \ |
2047 |
|
} while (0); |
2048 |
|
|
2049 |
|
|
2050 |
|
static int |
2051 |
|
encode_coding_emacs_mule (coding) |
2052 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
2053 |
{ |
{ |
2054 |
unsigned char *src = source; |
int multibytep = coding->dst_multibyte; |
2055 |
unsigned char *src_end = source + src_bytes; |
int *charbuf = coding->charbuf; |
2056 |
unsigned char *dst = destination; |
int *charbuf_end = charbuf + coding->charbuf_used; |
2057 |
unsigned char *dst_end = destination + dst_bytes; |
unsigned char *dst = coding->destination + coding->produced; |
2058 |
/* SRC_BASE remembers the start position in source in each loop. |
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
2059 |
The loop will be exited when there's not enough source code, or |
int safe_room = 8; |
2060 |
when there's not enough destination area to produce a |
int produced_chars = 0; |
2061 |
character. */ |
Lisp_Object attrs, eol_type, charset_list; |
2062 |
unsigned char *src_base; |
int c; |
2063 |
|
int preferred_charset_id = -1; |
2064 |
|
|
2065 |
coding->produced_char = 0; |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
|
while ((src_base = src) < src_end) |
|
|
{ |
|
|
unsigned char tmp[MAX_MULTIBYTE_LENGTH], *p; |
|
|
int bytes; |
|
2066 |
|
|
2067 |
if (*src == '\r') |
while (charbuf < charbuf_end) |
2068 |
{ |
{ |
2069 |
int c = *src++; |
ASSURE_DESTINATION (safe_room); |
2070 |
|
c = *charbuf++; |
2071 |
|
|
2072 |
if (coding->eol_type == CODING_EOL_CR) |
if (c < 0) |
|
c = '\n'; |
|
|
else if (coding->eol_type == CODING_EOL_CRLF) |
|
|
{ |
|
|
ONE_MORE_BYTE (c); |
|
|
if (c != '\n') |
|
|
{ |
|
|
src--; |
|
|
c = '\r'; |
|
|
} |
|
|
} |
|
|
*dst++ = c; |
|
|
coding->produced_char++; |
|
|
continue; |
|
|
} |
|
|
else if (*src == '\n') |
|
2073 |
{ |
{ |
2074 |
if ((coding->eol_type == CODING_EOL_CR |
/* Handle an annotation. */ |
2075 |
|| coding->eol_type == CODING_EOL_CRLF) |
switch (*charbuf) |
|
&& coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
|
2076 |
{ |
{ |
2077 |
coding->result = CODING_FINISH_INCONSISTENT_EOL; |
case CODING_ANNOTATE_COMPOSITION_MASK: |
2078 |
goto label_end_of_loop; |
/* Not yet implemented. */ |
2079 |
|
break; |
2080 |
|
case CODING_ANNOTATE_CHARSET_MASK: |
2081 |
|
preferred_charset_id = charbuf[3]; |
2082 |
|
if (preferred_charset_id >= 0 |
2083 |
|
&& NILP (Fmemq (make_number (preferred_charset_id), |
2084 |
|
charset_list))) |
2085 |
|
preferred_charset_id = -1; |
2086 |
|
break; |
2087 |
|
default: |
2088 |
|
abort (); |
2089 |
} |
} |
2090 |
*dst++ = *src++; |
charbuf += -c - 1; |
|
coding->produced_char++; |
|
2091 |
continue; |
continue; |
2092 |
} |
} |
2093 |
else if (*src == 0x80 && coding->cmp_data) |
|
2094 |
{ |
if (ASCII_CHAR_P (c)) |
2095 |
/* Start of composition data. */ |
EMIT_ONE_ASCII_BYTE (c); |
2096 |
int consumed = decode_composition_emacs_mule (coding, src, src_end, |
else if (CHAR_BYTE8_P (c)) |
|
&dst, dst_end, |
|
|
dst_bytes); |
|
|
if (consumed < 0) |
|
|
goto label_end_of_loop; |
|
|
else if (consumed > 0) |
|
|
{ |
|
|
src += consumed; |
|
|
continue; |
|
|
} |
|
|
bytes = CHAR_STRING (*src, tmp); |
|
|
p = tmp; |
|
|
src++; |
|
|
} |
|
|
else if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes) |
|
|
|| (coding->flags /* We are recovering a file. */ |
|
|
&& src[0] == LEADING_CODE_8_BIT_CONTROL |
|
|
&& ! CHAR_HEAD_P (src[1]))) |
|
2097 |
{ |
{ |
2098 |
p = src; |
c = CHAR_TO_BYTE8 (c); |
2099 |
src += bytes; |
EMIT_ONE_BYTE (c); |
2100 |
} |
} |
2101 |
else |
else |
2102 |
{ |
{ |
2103 |
bytes = CHAR_STRING (*src, tmp); |
struct charset *charset; |
2104 |
p = tmp; |
unsigned code; |
2105 |
src++; |
int dimension; |
2106 |
} |
int emacs_mule_id; |
2107 |
if (dst + bytes >= (dst_bytes ? dst_end : src)) |
unsigned char leading_codes[2]; |
2108 |
{ |
|
2109 |
coding->result = CODING_FINISH_INSUFFICIENT_DST; |
if (preferred_charset_id >= 0) |
2110 |
break; |
{ |
2111 |
} |
charset = CHARSET_FROM_ID (preferred_charset_id); |
2112 |
while (bytes--) *dst++ = *p++; |
if (! CHAR_CHARSET_P (c, charset)) |
2113 |
coding->produced_char++; |
charset = char_charset (c, charset_list, NULL); |
2114 |
} |
} |
|
label_end_of_loop: |
|
|
coding->consumed = coding->consumed_char = src_base - source; |
|
|
coding->produced = dst - destination; |
|
|
} |
|
|
|
|
|
|
|
|
/* Encode composition data stored at DATA into a special byte sequence |
|
|
starting by 0x80. Update CODING->cmp_data_start and maybe |
|
|
CODING->cmp_data for the next call. */ |
|
|
|
|
|
#define ENCODE_COMPOSITION_EMACS_MULE(coding, data) \ |
|
|
do { \ |
|
|
unsigned char buf[1024], *p0 = buf, *p; \ |
|
|
int len = data[0]; \ |
|
|
int i; \ |
|
|
\ |
|
|
buf[0] = 0x80; \ |
|
|
buf[1] = 0xF0 + data[3]; /* METHOD */ \ |
|
|
buf[3] = 0xA0 + (data[2] - data[1]); /* COMPOSED-CHARS */ \ |
|
|
p = buf + 4; \ |
|
|
if (data[3] == COMPOSITION_WITH_RULE \ |
|
|
|| data[3] == COMPOSITION_WITH_RULE_ALTCHARS) \ |
|
|
{ \ |
|
|
p += CHAR_STRING (data[4], p); \ |
|
|
for (i = 5; i < len; i += 2) \ |
|
|
{ \ |
|
|
int gref, nref; \ |
|
|
COMPOSITION_DECODE_RULE (data[i], gref, nref); \ |
|
|
*p++ = 0x20 + gref; \ |
|
|
*p++ = 0x20 + nref; \ |
|
|
p += CHAR_STRING (data[i + 1], p); \ |
|
|
} \ |
|
|
} \ |
|
|
else \ |
|
|
{ \ |
|
|
for (i = 4; i < len; i++) \ |
|
|
p += CHAR_STRING (data[i], p); \ |
|
|
} \ |
|
|
buf[2] = 0xA0 + (p - buf); /* COMPONENTS-BYTES */ \ |
|
|
\ |
|
|
if (dst + (p - buf) + 4 > (dst_bytes ? dst_end : src)) \ |
|
|
{ \ |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; \ |
|
|
goto label_end_of_loop; \ |
|
|
} \ |
|
|
while (p0 < p) \ |
|
|
*dst++ = *p0++; \ |
|
|
coding->cmp_data_start += data[0]; \ |
|
|
if (coding->cmp_data_start == coding->cmp_data->used \ |
|
|
&& coding->cmp_data->next) \ |
|
|
{ \ |
|
|
coding->cmp_data = coding->cmp_data->next; \ |
|
|
coding->cmp_data_start = 0; \ |
|
|
} \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
static void encode_eol P_ ((struct coding_system *, const unsigned char *, |
|
|
unsigned char *, int, int)); |
|
|
|
|
|
static void |
|
|
encode_coding_emacs_mule (coding, source, destination, src_bytes, dst_bytes) |
|
|
struct coding_system *coding; |
|
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
|
{ |
|
|
unsigned char *src = source; |
|
|
unsigned char *src_end = source + src_bytes; |
|
|
unsigned char *dst = destination; |
|
|
unsigned char *dst_end = destination + dst_bytes; |
|
|
unsigned char *src_base; |
|
|
int c; |
|
|
int char_offset; |
|
|
int *data; |
|
|
|
|
|
Lisp_Object translation_table; |
|
|
|
|
|
translation_table = Qnil; |
|
|
|
|
|
/* Optimization for the case that there's no composition. */ |
|
|
if (!coding->cmp_data || coding->cmp_data->used == 0) |
|
|
{ |
|
|
encode_eol (coding, source, destination, src_bytes, dst_bytes); |
|
|
return; |
|
|
} |
|
|
|
|
|
char_offset = coding->cmp_data->char_offset; |
|
|
data = coding->cmp_data->data + coding->cmp_data_start; |
|
|
while (1) |
|
|
{ |
|
|
src_base = src; |
|
|
|
|
|
/* If SRC starts a composition, encode the information about the |
|
|
composition in advance. */ |
|
|
if (coding->cmp_data_start < coding->cmp_data->used |
|
|
&& char_offset + coding->consumed_char == data[1]) |
|
|
{ |
|
|
ENCODE_COMPOSITION_EMACS_MULE (coding, data); |
|
|
char_offset = coding->cmp_data->char_offset; |
|
|
data = coding->cmp_data->data + coding->cmp_data_start; |
|
|
} |
|
|
|
|
|
ONE_MORE_CHAR (c); |
|
|
if (c == '\n' && (coding->eol_type == CODING_EOL_CRLF |
|
|
|| coding->eol_type == CODING_EOL_CR)) |
|
|
{ |
|
|
if (coding->eol_type == CODING_EOL_CRLF) |
|
|
EMIT_TWO_BYTES ('\r', c); |
|
2115 |
else |
else |
2116 |
EMIT_ONE_BYTE ('\r'); |
charset = char_charset (c, charset_list, &code); |
2117 |
} |
if (! charset) |
|
else if (SINGLE_BYTE_CHAR_P (c)) |
|
|
{ |
|
|
if (coding->flags && ! ASCII_BYTE_P (c)) |
|
2118 |
{ |
{ |
2119 |
/* As we are auto saving, retain the multibyte form for |
c = coding->default_char; |
2120 |
8-bit chars. */ |
if (ASCII_CHAR_P (c)) |
2121 |
unsigned char buf[MAX_MULTIBYTE_LENGTH]; |
{ |
2122 |
int bytes = CHAR_STRING (c, buf); |
EMIT_ONE_ASCII_BYTE (c); |
2123 |
|
continue; |
2124 |
if (bytes == 1) |
} |
2125 |
EMIT_ONE_BYTE (buf[0]); |
charset = char_charset (c, charset_list, &code); |
|
else |
|
|
EMIT_TWO_BYTES (buf[0], buf[1]); |
|
2126 |
} |
} |
2127 |
|
dimension = CHARSET_DIMENSION (charset); |
2128 |
|
emacs_mule_id = CHARSET_EMACS_MULE_ID (charset); |
2129 |
|
EMACS_MULE_LEADING_CODES (emacs_mule_id, leading_codes); |
2130 |
|
EMIT_ONE_BYTE (leading_codes[0]); |
2131 |
|
if (leading_codes[1]) |
2132 |
|
EMIT_ONE_BYTE (leading_codes[1]); |
2133 |
|
if (dimension == 1) |
2134 |
|
EMIT_ONE_BYTE (code); |
2135 |
else |
else |
2136 |
EMIT_ONE_BYTE (c); |
{ |
2137 |
|
EMIT_ONE_BYTE (code >> 8); |
2138 |
|
EMIT_ONE_BYTE (code & 0xFF); |
2139 |
|
} |
2140 |
} |
} |
|
else |
|
|
EMIT_BYTES (src_base, src); |
|
|
coding->consumed_char++; |
|
2141 |
} |
} |
2142 |
label_end_of_loop: |
coding->result = CODING_RESULT_SUCCESS; |
2143 |
coding->consumed = src_base - source; |
coding->produced_char += produced_chars; |
2144 |
coding->produced = coding->produced_char = dst - destination; |
coding->produced = dst - coding->destination; |
2145 |
return; |
return 0; |
2146 |
} |
} |
2147 |
|
|
2148 |
|
|
2149 |
/*** 3. ISO2022 handlers ***/ |
/*** 7. ISO2022 handlers ***/ |
2150 |
|
|
2151 |
/* The following note describes the coding system ISO2022 briefly. |
/* The following note describes the coding system ISO2022 briefly. |
2152 |
Since the intention of this note is to help understand the |
Since the intention of this note is to help understand the |
2276 |
7-bit environment, non-locking-shift, and non-single-shift. |
7-bit environment, non-locking-shift, and non-single-shift. |
2277 |
|
|
2278 |
Note (**): If <F> is '@', 'A', or 'B', the intermediate character |
Note (**): If <F> is '@', 'A', or 'B', the intermediate character |
2279 |
'(' can be omitted. We refer to this as "short-form" hereafter. |
'(' must be omitted. We refer to this as "short-form" hereafter. |
2280 |
|
|
2281 |
Now you may notice that there are a lot of ways of encoding the |
Now you may notice that there are a lot of ways of encoding the |
2282 |
same multilingual text in ISO2022. Actually, there exist many |
same multilingual text in ISO2022. Actually, there exist many |
2306 |
Since these are not standard escape sequences of any ISO standard, |
Since these are not standard escape sequences of any ISO standard, |
2307 |
the use of them with these meanings is restricted to Emacs only. |
the use of them with these meanings is restricted to Emacs only. |
2308 |
|
|
2309 |
(*) This form is used only in Emacs 20.5 and older versions, |
(*) This form is used only in Emacs 20.7 and older versions, |
2310 |
but the newer versions can safely decode it. |
but newer versions can safely decode it. |
2311 |
(**) This form is used only in Emacs 21.1 and newer versions, |
(**) This form is used only in Emacs 21.1 and newer versions, |
2312 |
and the older versions can't decode it. |
and older versions can't decode it. |
2313 |
|
|
2314 |
Here's a list of example usages of these composition escape |
Here's a list of example usages of these composition escape |
2315 |
sequences (categorized by `enum composition_method'). |
sequences (categorized by `enum composition_method'). |
2325 |
|
|
2326 |
enum iso_code_class_type iso_code_class[256]; |
enum iso_code_class_type iso_code_class[256]; |
2327 |
|
|
2328 |
#define CHARSET_OK(idx, charset, c) \ |
#define SAFE_CHARSET_P(coding, id) \ |
2329 |
(coding_system_table[idx] \ |
((id) <= (coding)->max_charset_id \ |
2330 |
&& (charset == CHARSET_ASCII \ |
&& (coding)->safe_charsets[id] >= 0) |
2331 |
|| (safe_chars = coding_safe_chars (coding_system_table[idx]->symbol), \ |
|
2332 |
CODING_SAFE_CHAR_P (safe_chars, c))) \ |
|
2333 |
&& (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding_system_table[idx], \ |
#define SHIFT_OUT_OK(category) \ |
2334 |
charset) \ |
(CODING_ISO_INITIAL (&coding_categories[category], 1) >= 0) |
2335 |
!= CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)) |
|
2336 |
|
static void |
2337 |
|
setup_iso_safe_charsets (attrs) |
2338 |
|
Lisp_Object attrs; |
2339 |
|
{ |
2340 |
|
Lisp_Object charset_list, safe_charsets; |
2341 |
|
Lisp_Object request; |
2342 |
|
Lisp_Object reg_usage; |
2343 |
|
Lisp_Object tail; |
2344 |
|
int reg94, reg96; |
2345 |
|
int flags = XINT (AREF (attrs, coding_attr_iso_flags)); |
2346 |
|
int max_charset_id; |
2347 |
|
|
2348 |
|
charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
2349 |
|
if ((flags & CODING_ISO_FLAG_FULL_SUPPORT) |
2350 |
|
&& ! EQ (charset_list, Viso_2022_charset_list)) |
2351 |
|
{ |
2352 |
|
CODING_ATTR_CHARSET_LIST (attrs) |
2353 |
|
= charset_list = Viso_2022_charset_list; |
2354 |
|
ASET (attrs, coding_attr_safe_charsets, Qnil); |
2355 |
|
} |
2356 |
|
|
2357 |
|
if (STRINGP (AREF (attrs, coding_attr_safe_charsets))) |
2358 |
|
return; |
2359 |
|
|
2360 |
#define SHIFT_OUT_OK(idx) \ |
max_charset_id = 0; |
2361 |
(CODING_SPEC_ISO_INITIAL_DESIGNATION (coding_system_table[idx], 1) >= 0) |
for (tail = charset_list; CONSP (tail); tail = XCDR (tail)) |
2362 |
|
{ |
2363 |
|
int id = XINT (XCAR (tail)); |
2364 |
|
if (max_charset_id < id) |
2365 |
|
max_charset_id = id; |
2366 |
|
} |
2367 |
|
|
2368 |
|
safe_charsets = Fmake_string (make_number (max_charset_id + 1), |
2369 |
|
make_number (255)); |
2370 |
|
request = AREF (attrs, coding_attr_iso_request); |
2371 |
|
reg_usage = AREF (attrs, coding_attr_iso_usage); |
2372 |
|
reg94 = XINT (XCAR (reg_usage)); |
2373 |
|
reg96 = XINT (XCDR (reg_usage)); |
2374 |
|
|
2375 |
|
for (tail = charset_list; CONSP (tail); tail = XCDR (tail)) |
2376 |
|
{ |
2377 |
|
Lisp_Object id; |
2378 |
|
Lisp_Object reg; |
2379 |
|
struct charset *charset; |
2380 |
|
|
2381 |
|
id = XCAR (tail); |
2382 |
|
charset = CHARSET_FROM_ID (XINT (id)); |
2383 |
|
reg = Fcdr (Fassq (id, request)); |
2384 |
|
if (! NILP (reg)) |
2385 |
|
SSET (safe_charsets, XINT (id), XINT (reg)); |
2386 |
|
else if (charset->iso_chars_96) |
2387 |
|
{ |
2388 |
|
if (reg96 < 4) |
2389 |
|
SSET (safe_charsets, XINT (id), reg96); |
2390 |
|
} |
2391 |
|
else |
2392 |
|
{ |
2393 |
|
if (reg94 < 4) |
2394 |
|
SSET (safe_charsets, XINT (id), reg94); |
2395 |
|
} |
2396 |
|
} |
2397 |
|
ASET (attrs, coding_attr_safe_charsets, safe_charsets); |
2398 |
|
} |
2399 |
|
|
|
#define COMPOSITION_OK(idx) \ |
|
|
(coding_system_table[idx]->composing != COMPOSITION_DISABLED) |
|
2400 |
|
|
2401 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
2402 |
Check if a text is encoded in ISO2022. If it is, return an |
Check if a text is encoded in one of ISO-2022 based codig systems. |
2403 |
integer in which appropriate flag bits any of: |
If it is, return 1, else return 0. */ |
|
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 |
|
|
CODING_CATEGORY_MASK_ISO_8_ELSE |
|
|
are set. If a code which should never appear in ISO2022 is found, |
|
|
returns 0. */ |
|
2404 |
|
|
2405 |
static int |
static int |
2406 |
detect_coding_iso2022 (src, src_end, multibytep) |
detect_coding_iso_2022 (coding, detect_info) |
2407 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
2408 |
int multibytep; |
struct coding_detection_info *detect_info; |
2409 |
{ |
{ |
2410 |
int mask = CODING_CATEGORY_MASK_ISO; |
const unsigned char *src = coding->source, *src_base = src; |
2411 |
int mask_found = 0; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
2412 |
int reg[4], shift_out = 0, single_shifting = 0; |
int multibytep = coding->src_multibyte; |
2413 |
int c, c1, charset; |
int single_shifting = 0; |
2414 |
/* Dummy for ONE_MORE_BYTE. */ |
int id; |
2415 |
struct coding_system dummy_coding; |
int c, c1; |
2416 |
struct coding_system *coding = &dummy_coding; |
int consumed_chars = 0; |
2417 |
Lisp_Object safe_chars; |
int i; |
2418 |
|
int rejected = 0; |
2419 |
|
int found = 0; |
2420 |
|
|
2421 |
reg[0] = CHARSET_ASCII, reg[1] = reg[2] = reg[3] = -1; |
detect_info->checked |= CATEGORY_MASK_ISO; |
2422 |
while (mask && src < src_end) |
|
2423 |
|
for (i = coding_category_iso_7; i <= coding_category_iso_8_else; i++) |
2424 |
{ |
{ |
2425 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
struct coding_system *this = &(coding_categories[i]); |
2426 |
retry: |
Lisp_Object attrs, val; |
2427 |
|
|
2428 |
|
attrs = CODING_ID_ATTRS (this->id); |
2429 |
|
if (CODING_ISO_FLAGS (this) & CODING_ISO_FLAG_FULL_SUPPORT |
2430 |
|
&& ! EQ (CODING_ATTR_SAFE_CHARSETS (attrs), Viso_2022_charset_list)) |
2431 |
|
setup_iso_safe_charsets (attrs); |
2432 |
|
val = CODING_ATTR_SAFE_CHARSETS (attrs); |
2433 |
|
this->max_charset_id = SCHARS (val) - 1; |
2434 |
|
this->safe_charsets = (char *) SDATA (val); |
2435 |
|
} |
2436 |
|
|
2437 |
|
/* A coding system of this category is always ASCII compatible. */ |
2438 |
|
src += coding->head_ascii; |
2439 |
|
|
2440 |
|
while (rejected != CATEGORY_MASK_ISO) |
2441 |
|
{ |
2442 |
|
ONE_MORE_BYTE (c); |
2443 |
switch (c) |
switch (c) |
2444 |
{ |
{ |
2445 |
case ISO_CODE_ESC: |
case ISO_CODE_ESC: |
2446 |
if (inhibit_iso_escape_detection) |
if (inhibit_iso_escape_detection) |
2447 |
break; |
break; |
2448 |
single_shifting = 0; |
single_shifting = 0; |
2449 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
2450 |
if (c >= '(' && c <= '/') |
if (c >= '(' && c <= '/') |
2451 |
{ |
{ |
2452 |
/* Designation sequence for a charset of dimension 1. */ |
/* Designation sequence for a charset of dimension 1. */ |
2453 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c1, multibytep); |
ONE_MORE_BYTE (c1); |
2454 |
if (c1 < ' ' || c1 >= 0x80 |
if (c1 < ' ' || c1 >= 0x80 |
2455 |
|| (charset = iso_charset_table[0][c >= ','][c1]) < 0) |
|| (id = iso_charset_table[0][c >= ','][c1]) < 0) |
2456 |
/* Invalid designation sequence. Just ignore. */ |
/* Invalid designation sequence. Just ignore. */ |
2457 |
break; |
break; |
|
reg[(c - '(') % 4] = charset; |
|
2458 |
} |
} |
2459 |
else if (c == '$') |
else if (c == '$') |
2460 |
{ |
{ |
2461 |
/* Designation sequence for a charset of dimension 2. */ |
/* Designation sequence for a charset of dimension 2. */ |
2462 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
2463 |
if (c >= '@' && c <= 'B') |
if (c >= '@' && c <= 'B') |
2464 |
/* Designation for JISX0208.1978, GB2312, or JISX0208. */ |
/* Designation for JISX0208.1978, GB2312, or JISX0208. */ |
2465 |
reg[0] = charset = iso_charset_table[1][0][c]; |
id = iso_charset_table[1][0][c]; |
2466 |
else if (c >= '(' && c <= '/') |
else if (c >= '(' && c <= '/') |
2467 |
{ |
{ |
2468 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c1, multibytep); |
ONE_MORE_BYTE (c1); |
2469 |
if (c1 < ' ' || c1 >= 0x80 |
if (c1 < ' ' || c1 >= 0x80 |
2470 |
|| (charset = iso_charset_table[1][c >= ','][c1]) < 0) |
|| (id = iso_charset_table[1][c >= ','][c1]) < 0) |
2471 |
/* Invalid designation sequence. Just ignore. */ |
/* Invalid designation sequence. Just ignore. */ |
2472 |
break; |
break; |
|
reg[(c - '(') % 4] = charset; |
|
2473 |
} |
} |
2474 |
else |
else |
2475 |
/* Invalid designation sequence. Just ignore. */ |
/* Invalid designation sequence. Just ignore it. */ |
2476 |
break; |
break; |
2477 |
} |
} |
2478 |
else if (c == 'N' || c == 'O') |
else if (c == 'N' || c == 'O') |
2479 |
{ |
{ |
2480 |
/* ESC <Fe> for SS2 or SS3. */ |
/* ESC <Fe> for SS2 or SS3. */ |
2481 |
mask &= CODING_CATEGORY_MASK_ISO_7_ELSE; |
single_shifting = 1; |
2482 |
|
rejected |= CATEGORY_MASK_ISO_7BIT | CATEGORY_MASK_ISO_8BIT; |
2483 |
break; |
break; |
2484 |
} |
} |
2485 |
else if (c >= '0' && c <= '4') |
else if (c >= '0' && c <= '4') |
2486 |
{ |
{ |
2487 |
/* ESC <Fp> for start/end composition. */ |
/* ESC <Fp> for start/end composition. */ |
2488 |
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7)) |
found |= CATEGORY_MASK_ISO; |
|
mask_found |= CODING_CATEGORY_MASK_ISO_7; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_7; |
|
|
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7_TIGHT)) |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_7_TIGHT; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_7_TIGHT; |
|
|
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_1)) |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_8_1; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_8_1; |
|
|
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_2)) |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_8_2; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_8_2; |
|
|
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_7_ELSE)) |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_7_ELSE; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_7_ELSE; |
|
|
if (COMPOSITION_OK (CODING_CATEGORY_IDX_ISO_8_ELSE)) |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_8_ELSE; |
|
|
else |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_8_ELSE; |
|
2489 |
break; |
break; |
2490 |
} |
} |
2491 |
else |
else |
2492 |
/* Invalid escape sequence. Just ignore. */ |
{ |
2493 |
break; |
/* Invalid escape sequence. Just ignore it. */ |
2494 |
|
break; |
2495 |
|
} |
2496 |
|
|
2497 |
/* We found a valid designation sequence for CHARSET. */ |
/* We found a valid designation sequence for CHARSET. */ |
2498 |
mask &= ~CODING_CATEGORY_MASK_ISO_8BIT; |
rejected |= CATEGORY_MASK_ISO_8BIT; |
2499 |
c = MAKE_CHAR (charset, 0, 0); |
if (SAFE_CHARSET_P (&coding_categories[coding_category_iso_7], |
2500 |
if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_7, charset, c)) |
id)) |
2501 |
mask_found |= CODING_CATEGORY_MASK_ISO_7; |
found |= CATEGORY_MASK_ISO_7; |
2502 |
else |
else |
2503 |
mask &= ~CODING_CATEGORY_MASK_ISO_7; |
rejected |= CATEGORY_MASK_ISO_7; |
2504 |
if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_7_TIGHT, charset, c)) |
if (SAFE_CHARSET_P (&coding_categories[coding_category_iso_7_tight], |
2505 |
mask_found |= CODING_CATEGORY_MASK_ISO_7_TIGHT; |
id)) |
2506 |
|
found |= CATEGORY_MASK_ISO_7_TIGHT; |
2507 |
else |
else |
2508 |
mask &= ~CODING_CATEGORY_MASK_ISO_7_TIGHT; |
rejected |= CATEGORY_MASK_ISO_7_TIGHT; |
2509 |
if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_7_ELSE, charset, c)) |
if (SAFE_CHARSET_P (&coding_categories[coding_category_iso_7_else], |
2510 |
mask_found |= CODING_CATEGORY_MASK_ISO_7_ELSE; |
id)) |
2511 |
|
found |= CATEGORY_MASK_ISO_7_ELSE; |
2512 |
else |
else |
2513 |
mask &= ~CODING_CATEGORY_MASK_ISO_7_ELSE; |
rejected |= CATEGORY_MASK_ISO_7_ELSE; |
2514 |
if (CHARSET_OK (CODING_CATEGORY_IDX_ISO_8_ELSE, charset, c)) |
if (SAFE_CHARSET_P (&coding_categories[coding_category_iso_8_else], |
2515 |
mask_found |= CODING_CATEGORY_MASK_ISO_8_ELSE; |
id)) |
2516 |
|
found |= CATEGORY_MASK_ISO_8_ELSE; |
2517 |
else |
else |
2518 |
mask &= ~CODING_CATEGORY_MASK_ISO_8_ELSE; |
rejected |= CATEGORY_MASK_ISO_8_ELSE; |
2519 |
break; |
break; |
2520 |
|
|
2521 |
case ISO_CODE_SO: |
case ISO_CODE_SO: |
|
if (inhibit_iso_escape_detection) |
|
|
break; |
|
|
single_shifting = 0; |
|
|
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; |
|
|
|
|
2522 |
case ISO_CODE_SI: |
case ISO_CODE_SI: |
2523 |
|
/* Locking shift out/in. */ |
2524 |
if (inhibit_iso_escape_detection) |
if (inhibit_iso_escape_detection) |
2525 |
break; |
break; |
2526 |
single_shifting = 0; |
single_shifting = 0; |
2527 |
if (shift_out == 1) |
rejected |= CATEGORY_MASK_ISO_7BIT | CATEGORY_MASK_ISO_8BIT; |
2528 |
{ |
found |= CATEGORY_MASK_ISO_ELSE; |
|
/* Locking shift in. */ |
|
|
mask &= ~CODING_CATEGORY_MASK_ISO_7BIT; |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_SHIFT; |
|
|
} |
|
2529 |
break; |
break; |
2530 |
|
|
2531 |
case ISO_CODE_CSI: |
case ISO_CODE_CSI: |
2532 |
|
/* Control sequence introducer. */ |
2533 |
single_shifting = 0; |
single_shifting = 0; |
2534 |
|
rejected |= CATEGORY_MASK_ISO_7BIT | CATEGORY_MASK_ISO_7_ELSE; |
2535 |
|
found |= CATEGORY_MASK_ISO_8_ELSE; |
2536 |
|
goto check_extra_latin; |
2537 |
|
|
2538 |
|
|
2539 |
case ISO_CODE_SS2: |
case ISO_CODE_SS2: |
2540 |
case ISO_CODE_SS3: |
case ISO_CODE_SS3: |
2541 |
{ |
/* Single shift. */ |
2542 |
int newmask = CODING_CATEGORY_MASK_ISO_8_ELSE; |
if (inhibit_iso_escape_detection) |
2543 |
|
break; |
2544 |
if (inhibit_iso_escape_detection) |
single_shifting = 1; |
2545 |
break; |
rejected |= CATEGORY_MASK_ISO_7BIT; |
2546 |
if (c != ISO_CODE_CSI) |
if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1]) |
2547 |
{ |
& CODING_ISO_FLAG_SINGLE_SHIFT) |
2548 |
if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_1]->flags |
found |= CATEGORY_MASK_ISO_8_1; |
2549 |
& CODING_FLAG_ISO_SINGLE_SHIFT) |
if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_2]) |
2550 |
newmask |= CODING_CATEGORY_MASK_ISO_8_1; |
& CODING_ISO_FLAG_SINGLE_SHIFT) |
2551 |
if (coding_system_table[CODING_CATEGORY_IDX_ISO_8_2]->flags |
found |= CATEGORY_MASK_ISO_8_2; |
2552 |
& CODING_FLAG_ISO_SINGLE_SHIFT) |
goto check_extra_latin; |
|
newmask |= CODING_CATEGORY_MASK_ISO_8_2; |
|
|
single_shifting = 1; |
|
|
} |
|
|
if (VECTORP (Vlatin_extra_code_table) |
|
|
&& !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) |
|
|
{ |
|
|
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_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; |
|
2553 |
|
|
2554 |
default: |
default: |
2555 |
if (c < 0x80) |
if (c < 0x80) |
2557 |
single_shifting = 0; |
single_shifting = 0; |
2558 |
break; |
break; |
2559 |
} |
} |
2560 |
else if (c < 0xA0) |
if (c >= 0xA0) |
2561 |
{ |
{ |
2562 |
single_shifting = 0; |
rejected |= CATEGORY_MASK_ISO_7BIT | CATEGORY_MASK_ISO_7_ELSE; |
2563 |
if (VECTORP (Vlatin_extra_code_table) |
found |= CATEGORY_MASK_ISO_8_1; |
|
&& !NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) |
|
|
{ |
|
|
int newmask = 0; |
|
|
|
|
|
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_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; |
|
|
} |
|
|
else |
|
|
{ |
|
|
mask &= ~(CODING_CATEGORY_MASK_ISO_7BIT |
|
|
| CODING_CATEGORY_MASK_ISO_7_ELSE); |
|
|
mask_found |= CODING_CATEGORY_MASK_ISO_8_1; |
|
2564 |
/* Check the length of succeeding codes of the range |
/* Check the length of succeeding codes of the range |
2565 |
0xA0..0FF. If the byte length is odd, we exclude |
0xA0..0FF. If the byte length is even, we include |
2566 |
CODING_CATEGORY_MASK_ISO_8_2. We can check this only |
CATEGORY_MASK_ISO_8_2 in `found'. We can check this |
2567 |
when we are not single shifting. */ |
only when we are not single shifting. */ |
2568 |
if (!single_shifting |
if (! single_shifting |
2569 |
&& mask & CODING_CATEGORY_MASK_ISO_8_2) |
&& ! (rejected & CATEGORY_MASK_ISO_8_2)) |
2570 |
{ |
{ |
2571 |
int i = 1; |
int i = 1; |
|
|
|
|
c = -1; |
|
2572 |
while (src < src_end) |
while (src < src_end) |
2573 |
{ |
{ |
2574 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
2575 |
if (c < 0xA0) |
if (c < 0xA0) |
2576 |
break; |
break; |
2577 |
i++; |
i++; |
2578 |
} |
} |
2579 |
|
|
2580 |
if (i & 1 && src < src_end) |
if (i & 1 && src < src_end) |
2581 |
mask &= ~CODING_CATEGORY_MASK_ISO_8_2; |
rejected |= CATEGORY_MASK_ISO_8_2; |
2582 |
else |
else |
2583 |
mask_found |= CODING_CATEGORY_MASK_ISO_8_2; |
found |= CATEGORY_MASK_ISO_8_2; |
|
if (c >= 0) |
|
|
/* This means that we have read one extra byte. */ |
|
|
goto retry; |
|
2584 |
} |
} |
2585 |
|
break; |
2586 |
} |
} |
2587 |
break; |
check_extra_latin: |
2588 |
|
single_shifting = 0; |
2589 |
|
if (! VECTORP (Vlatin_extra_code_table) |
2590 |
|
|| NILP (XVECTOR (Vlatin_extra_code_table)->contents[c])) |
2591 |
|
{ |
2592 |
|
rejected = CATEGORY_MASK_ISO; |
2593 |
|
break; |
2594 |
|
} |
2595 |
|
if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_1]) |
2596 |
|
& CODING_ISO_FLAG_LATIN_EXTRA) |
2597 |
|
found |= CATEGORY_MASK_ISO_8_1; |
2598 |
|
else |
2599 |
|
rejected |= CATEGORY_MASK_ISO_8_1; |
2600 |
|
if (CODING_ISO_FLAGS (&coding_categories[coding_category_iso_8_2]) |
2601 |
|
& CODING_ISO_FLAG_LATIN_EXTRA) |
2602 |
|
found |= CATEGORY_MASK_ISO_8_2; |
2603 |
|
else |
2604 |
|
rejected |= CATEGORY_MASK_ISO_8_2; |
2605 |
} |
} |
2606 |
} |
} |
2607 |
label_end_of_loop: |
detect_info->rejected |= CATEGORY_MASK_ISO; |
2608 |
return (mask & mask_found); |
return 0; |
2609 |
|
|
2610 |
|
no_more_source: |
2611 |
|
detect_info->rejected |= rejected; |
2612 |
|
detect_info->found |= (found & ~rejected); |
2613 |
|
return 1; |
2614 |
} |
} |
2615 |
|
|
|
/* Decode a character of which charset is CHARSET, the 1st position |
|
|
code is C1, the 2nd position code is C2, and return the decoded |
|
|
character code. If the variable `translation_table' is non-nil, |
|
|
returned the translated code. */ |
|
|
|
|
|
#define DECODE_ISO_CHARACTER(charset, c1, c2) \ |
|
|
(NILP (translation_table) \ |
|
|
? MAKE_CHAR (charset, c1, c2) \ |
|
|
: translate_char (translation_table, -1, charset, c1, c2)) |
|
2616 |
|
|
2617 |
/* Set designation state into CODING. */ |
/* Set designation state into CODING. */ |
2618 |
#define DECODE_DESIGNATION(reg, dimension, chars, final_char) \ |
#define DECODE_DESIGNATION(reg, dim, chars_96, final) \ |
2619 |
do { \ |
do { \ |
2620 |
int charset, c; \ |
int id, prev; \ |
2621 |
\ |
\ |
2622 |
if (final_char < '0' || final_char >= 128) \ |
if (final < '0' || final >= 128 \ |
2623 |
goto label_invalid_code; \ |
|| ((id = ISO_CHARSET_TABLE (dim, chars_96, final)) < 0) \ |
2624 |
charset = ISO_CHARSET_TABLE (make_number (dimension), \ |
|| !SAFE_CHARSET_P (coding, id)) \ |
2625 |
make_number (chars), \ |
{ \ |
2626 |
make_number (final_char)); \ |
CODING_ISO_DESIGNATION (coding, reg) = -2; \ |
2627 |
c = MAKE_CHAR (charset, 0, 0); \ |
goto invalid_code; \ |
2628 |
if (charset >= 0 \ |
} \ |
2629 |
&& (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) == reg \ |
prev = CODING_ISO_DESIGNATION (coding, reg); \ |
2630 |
|| CODING_SAFE_CHAR_P (safe_chars, c))) \ |
if (id == charset_jisx0201_roman) \ |
2631 |
{ \ |
{ \ |
2632 |
if (coding->spec.iso2022.last_invalid_designation_register == 0 \ |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_USE_ROMAN) \ |
2633 |
&& reg == 0 \ |
id = charset_ascii; \ |
2634 |
&& charset == CHARSET_ASCII) \ |
} \ |
2635 |
{ \ |
else if (id == charset_jisx0208_1978) \ |
2636 |
/* We should insert this designation sequence as is so \ |
{ \ |
2637 |
that it is surely written back to a file. */ \ |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_USE_OLDJIS) \ |
2638 |
coding->spec.iso2022.last_invalid_designation_register = -1; \ |
id = charset_jisx0208; \ |
2639 |
goto label_invalid_code; \ |
} \ |
2640 |
} \ |
CODING_ISO_DESIGNATION (coding, reg) = id; \ |
2641 |
coding->spec.iso2022.last_invalid_designation_register = -1; \ |
/* If there was an invalid designation to REG previously, and this \ |
2642 |
if ((coding->mode & CODING_MODE_DIRECTION) \ |
designation is ASCII to REG, we should keep this designation \ |
2643 |
&& CHARSET_REVERSE_CHARSET (charset) >= 0) \ |
sequence. */ \ |
2644 |
charset = CHARSET_REVERSE_CHARSET (charset); \ |
if (prev == -2 && id == charset_ascii) \ |
2645 |
CODING_SPEC_ISO_DESIGNATION (coding, reg) = charset; \ |
goto invalid_code; \ |
|
} \ |
|
|
else \ |
|
|
{ \ |
|
|
coding->spec.iso2022.last_invalid_designation_register = reg; \ |
|
|
goto label_invalid_code; \ |
|
|
} \ |
|
2646 |
} while (0) |
} while (0) |
2647 |
|
|
|
/* Allocate a memory block for storing information about compositions. |
|
|
The block is chained to the already allocated blocks. */ |
|
2648 |
|
|
2649 |
void |
#define MAYBE_FINISH_COMPOSITION() \ |
2650 |
coding_allocate_composition_data (coding, char_offset) |
do { \ |
2651 |
struct coding_system *coding; |
int i; \ |
2652 |
int char_offset; |
if (composition_state == COMPOSING_NO) \ |
2653 |
{ |
break; \ |
2654 |
struct composition_data *cmp_data |
/* It is assured that we have enough room for producing \ |
2655 |
= (struct composition_data *) xmalloc (sizeof *cmp_data); |
characters stored in the table `components'. */ \ |
2656 |
|
if (charbuf + component_idx > charbuf_end) \ |
2657 |
|
goto no_more_source; \ |
2658 |
|
composition_state = COMPOSING_NO; \ |
2659 |
|
if (method == COMPOSITION_RELATIVE \ |
2660 |
|
|| method == COMPOSITION_WITH_ALTCHARS) \ |
2661 |
|
{ \ |
2662 |
|
for (i = 0; i < component_idx; i++) \ |
2663 |
|
*charbuf++ = components[i]; \ |
2664 |
|
char_offset += component_idx; \ |
2665 |
|
} \ |
2666 |
|
else \ |
2667 |
|
{ \ |
2668 |
|
for (i = 0; i < component_idx; i += 2) \ |
2669 |
|
*charbuf++ = components[i]; \ |
2670 |
|
char_offset += (component_idx / 2) + 1; \ |
2671 |
|
} \ |
2672 |
|
} while (0) |
2673 |
|
|
|
cmp_data->char_offset = char_offset; |
|
|
cmp_data->used = 0; |
|
|
cmp_data->prev = coding->cmp_data; |
|
|
cmp_data->next = NULL; |
|
|
if (coding->cmp_data) |
|
|
coding->cmp_data->next = cmp_data; |
|
|
coding->cmp_data = cmp_data; |
|
|
coding->cmp_data_start = 0; |
|
|
} |
|
2674 |
|
|
2675 |
/* Handle composition start sequence ESC 0, ESC 2, ESC 3, or ESC 4. |
/* Handle composition start sequence ESC 0, ESC 2, ESC 3, or ESC 4. |
2676 |
ESC 0 : relative composition : ESC 0 CHAR ... ESC 1 |
ESC 0 : relative composition : ESC 0 CHAR ... ESC 1 |
2677 |
ESC 2 : rulebase composition : ESC 2 CHAR RULE CHAR RULE ... CHAR ESC 1 |
ESC 2 : rulebase composition : ESC 2 CHAR RULE CHAR RULE ... CHAR ESC 1 |
2678 |
ESC 3 : altchar composition : ESC 3 ALT ... ESC 0 CHAR ... ESC 1 |
ESC 3 : altchar composition : ESC 3 CHAR ... ESC 0 CHAR ... ESC 1 |
2679 |
ESC 4 : alt&rule composition : ESC 4 ALT RULE .. ALT ESC 0 CHAR ... ESC 1 |
ESC 4 : alt&rule composition : ESC 4 CHAR RULE ... CHAR ESC 0 CHAR ... ESC 1 |
2680 |
*/ |
*/ |
2681 |
|
|
2682 |
#define DECODE_COMPOSITION_START(c1) \ |
#define DECODE_COMPOSITION_START(c1) \ |
2683 |
do { \ |
do { \ |
2684 |
if (coding->composing == COMPOSITION_DISABLED) \ |
if (c1 == '0' \ |
2685 |
{ \ |
&& composition_state == COMPOSING_COMPONENT_RULE) \ |
2686 |
*dst++ = ISO_CODE_ESC; \ |
{ \ |
2687 |
*dst++ = c1 & 0x7f; \ |
component_len = component_idx; \ |
2688 |
coding->produced_char += 2; \ |
composition_state = COMPOSING_CHAR; \ |
2689 |
} \ |
} \ |
2690 |
else if (!COMPOSING_P (coding)) \ |
else \ |
2691 |
{ \ |
{ \ |
2692 |
/* This is surely the start of a composition. We must be sure \ |
const unsigned char *p; \ |
2693 |
that coding->cmp_data has enough space to store the \ |
\ |
2694 |
information about the composition. If not, terminate the \ |
MAYBE_FINISH_COMPOSITION (); \ |
2695 |
current decoding loop, allocate one more memory block for \ |
if (charbuf + MAX_COMPOSITION_COMPONENTS > charbuf_end) \ |
2696 |
coding->cmp_data in the caller, then start the decoding \ |
goto no_more_source; \ |
2697 |
loop again. We can't allocate memory here directly because \ |
for (p = src; p < src_end - 1; p++) \ |
2698 |
it may cause buffer/string relocation. */ \ |
if (*p == ISO_CODE_ESC && p[1] == '1') \ |
2699 |
if (!coding->cmp_data \ |
break; \ |
2700 |
|| (coding->cmp_data->used + COMPOSITION_DATA_MAX_BUNCH_LENGTH \ |
if (p == src_end - 1) \ |
2701 |
>= COMPOSITION_DATA_SIZE)) \ |
{ \ |
2702 |
{ \ |
if (coding->mode & CODING_MODE_LAST_BLOCK) \ |
2703 |
coding->result = CODING_FINISH_INSUFFICIENT_CMP; \ |
goto invalid_code; \ |
2704 |
goto label_end_of_loop; \ |
goto no_more_source; \ |
2705 |
} \ |
} \ |
2706 |
coding->composing = (c1 == '0' ? COMPOSITION_RELATIVE \ |
\ |
2707 |
: c1 == '2' ? COMPOSITION_WITH_RULE \ |
/* This is surely the start of a composition. */ \ |
2708 |
: c1 == '3' ? COMPOSITION_WITH_ALTCHARS \ |
method = (c1 == '0' ? COMPOSITION_RELATIVE \ |
2709 |
: COMPOSITION_WITH_RULE_ALTCHARS); \ |
: c1 == '2' ? COMPOSITION_WITH_RULE \ |
2710 |
CODING_ADD_COMPOSITION_START (coding, coding->produced_char, \ |
: c1 == '3' ? COMPOSITION_WITH_ALTCHARS \ |
2711 |
coding->composing); \ |
: COMPOSITION_WITH_RULE_ALTCHARS); \ |
2712 |
coding->composition_rule_follows = 0; \ |
composition_state = (c1 <= '2' ? COMPOSING_CHAR \ |
2713 |
} \ |
: COMPOSING_COMPONENT_CHAR); \ |
2714 |
else \ |
component_idx = component_len = 0; \ |
2715 |
{ \ |
} \ |
|
/* We are already handling a composition. If the method is \ |
|
|
the following two, the codes following the current escape \ |
|
|
sequence are actual characters stored in a buffer. */ \ |
|
|
if (coding->composing == COMPOSITION_WITH_ALTCHARS \ |
|
|
|| coding->composing == COMPOSITION_WITH_RULE_ALTCHARS) \ |
|
|
{ \ |
|
|
coding->composing = COMPOSITION_RELATIVE; \ |
|
|
coding->composition_rule_follows = 0; \ |
|
|
} \ |
|
|
} \ |
|
2716 |
} while (0) |
} while (0) |
2717 |
|
|
|
/* Handle composition end sequence ESC 1. */ |
|
2718 |
|
|
2719 |
#define DECODE_COMPOSITION_END(c1) \ |
/* Handle compositoin end sequence ESC 1. */ |
2720 |
|
|
2721 |
|
#define DECODE_COMPOSITION_END() \ |
2722 |
do { \ |
do { \ |
2723 |
if (! COMPOSING_P (coding)) \ |
int nchars = (component_len > 0 ? component_idx - component_len \ |
2724 |
|
: method == COMPOSITION_RELATIVE ? component_idx \ |
2725 |
|
: (component_idx + 1) / 2); \ |
2726 |
|
int i; \ |
2727 |
|
int *saved_charbuf = charbuf; \ |
2728 |
|
int from = char_offset; \ |
2729 |
|
int to = from + nchars; \ |
2730 |
|
\ |
2731 |
|
ADD_COMPOSITION_DATA (charbuf, from, to, method); \ |
2732 |
|
if (method != COMPOSITION_RELATIVE) \ |
2733 |
{ \ |
{ \ |
2734 |
*dst++ = ISO_CODE_ESC; \ |
if (component_len == 0) \ |
2735 |
*dst++ = c1; \ |
for (i = 0; i < component_idx; i++) \ |
2736 |
coding->produced_char += 2; \ |
*charbuf++ = components[i]; \ |
2737 |
|
else \ |
2738 |
|
for (i = 0; i < component_len; i++) \ |
2739 |
|
*charbuf++ = components[i]; \ |
2740 |
|
*saved_charbuf = saved_charbuf - charbuf; \ |
2741 |
} \ |
} \ |
2742 |
|
if (method == COMPOSITION_WITH_RULE) \ |
2743 |
|
for (i = 0; i < component_idx; i += 2, char_offset++) \ |
2744 |
|
*charbuf++ = components[i]; \ |
2745 |
else \ |
else \ |
2746 |
{ \ |
for (i = component_len; i < component_idx; i++, char_offset++) \ |
2747 |
CODING_ADD_COMPOSITION_END (coding, coding->produced_char); \ |
*charbuf++ = components[i]; \ |
2748 |
coding->composing = COMPOSITION_NO; \ |
coding->annotated = 1; \ |
2749 |
} \ |
composition_state = COMPOSING_NO; \ |
2750 |
} while (0) |
} while (0) |
2751 |
|
|
2752 |
|
|
2753 |
/* Decode a composition rule from the byte C1 (and maybe one more byte |
/* Decode a composition rule from the byte C1 (and maybe one more byte |
2754 |
from SRC) and store one encoded composition rule in |
from SRC) and store one encoded composition rule in |
2755 |
coding->cmp_data. */ |
coding->cmp_data. */ |
2756 |
|
|
2757 |
#define DECODE_COMPOSITION_RULE(c1) \ |
#define DECODE_COMPOSITION_RULE(c1) \ |
2758 |
do { \ |
do { \ |
|
int rule = 0; \ |
|
2759 |
(c1) -= 32; \ |
(c1) -= 32; \ |
2760 |
if (c1 < 81) /* old format (before ver.21) */ \ |
if (c1 < 81) /* old format (before ver.21) */ \ |
2761 |
{ \ |
{ \ |
2763 |
int nref = (c1) % 9; \ |
int nref = (c1) % 9; \ |
2764 |
if (gref == 4) gref = 10; \ |
if (gref == 4) gref = 10; \ |
2765 |
if (nref == 4) nref = 10; \ |
if (nref == 4) nref = 10; \ |
2766 |
rule = COMPOSITION_ENCODE_RULE (gref, nref); \ |
c1 = COMPOSITION_ENCODE_RULE (gref, nref); \ |
2767 |
} \ |
} \ |
2768 |
else if (c1 < 93) /* new format (after ver.21) */ \ |
else if (c1 < 93) /* new format (after ver.21) */ \ |
2769 |
{ \ |
{ \ |
2770 |
ONE_MORE_BYTE (c2); \ |
ONE_MORE_BYTE (c2); \ |
2771 |
rule = COMPOSITION_ENCODE_RULE (c1 - 81, c2 - 32); \ |
c1 = COMPOSITION_ENCODE_RULE (c1 - 81, c2 - 32); \ |
2772 |
} \ |
} \ |
2773 |
CODING_ADD_COMPOSITION_COMPONENT (coding, rule); \ |
else \ |
2774 |
coding->composition_rule_follows = 0; \ |
c1 = 0; \ |
2775 |
} while (0) |
} while (0) |
2776 |
|
|
2777 |
|
|
2778 |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
2779 |
|
|
2780 |
static void |
static void |
2781 |
decode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes) |
decode_coding_iso_2022 (coding) |
2782 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
2783 |
{ |
{ |
2784 |
unsigned char *src = source; |
const unsigned char *src = coding->source + coding->consumed; |
2785 |
unsigned char *src_end = source + src_bytes; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
2786 |
unsigned char *dst = destination; |
const unsigned char *src_base; |
2787 |
unsigned char *dst_end = destination + dst_bytes; |
int *charbuf = coding->charbuf; |
2788 |
|
int *charbuf_end |
2789 |
|
= charbuf + coding->charbuf_size - 4 - MAX_ANNOTATION_LENGTH; |
2790 |
|
int consumed_chars = 0, consumed_chars_base; |
2791 |
|
int multibytep = coding->src_multibyte; |
2792 |
/* Charsets invoked to graphic plane 0 and 1 respectively. */ |
/* Charsets invoked to graphic plane 0 and 1 respectively. */ |
2793 |
int charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
int charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
2794 |
int charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1); |
int charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1); |
2795 |
/* SRC_BASE remembers the start position in source in each loop. |
struct charset *charset; |
2796 |
The loop will be exited when there's not enough source code |
int c; |
2797 |
(within macro ONE_MORE_BYTE), or when there's not enough |
/* For handling composition sequence. */ |
2798 |
destination area to produce a character (within macro |
#define COMPOSING_NO 0 |
2799 |
EMIT_CHAR). */ |
#define COMPOSING_CHAR 1 |
2800 |
unsigned char *src_base; |
#define COMPOSING_RULE 2 |
2801 |
int c, charset; |
#define COMPOSING_COMPONENT_CHAR 3 |
2802 |
Lisp_Object translation_table; |
#define COMPOSING_COMPONENT_RULE 4 |
2803 |
Lisp_Object safe_chars; |
|
2804 |
|
int composition_state = COMPOSING_NO; |
2805 |
safe_chars = coding_safe_chars (coding->symbol); |
enum composition_method method; |
2806 |
|
int components[MAX_COMPOSITION_COMPONENTS * 2 + 1]; |
2807 |
if (NILP (Venable_character_translation)) |
int component_idx; |
2808 |
translation_table = Qnil; |
int component_len; |
2809 |
else |
Lisp_Object attrs, eol_type, charset_list; |
2810 |
{ |
int char_offset = coding->produced_char; |
2811 |
translation_table = coding->translation_table_for_decode; |
int last_offset = char_offset; |
2812 |
if (NILP (translation_table)) |
int last_id = charset_ascii; |
|
translation_table = Vstandard_translation_table_for_decode; |
|
|
} |
|
2813 |
|
|
2814 |
coding->result = CODING_FINISH_NORMAL; |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
2815 |
|
setup_iso_safe_charsets (attrs); |
2816 |
|
|
2817 |
while (1) |
while (1) |
2818 |
{ |
{ |
2819 |
int c1, c2; |
int c1, c2; |
2820 |
|
|
2821 |
src_base = src; |
src_base = src; |
2822 |
|
consumed_chars_base = consumed_chars; |
2823 |
|
|
2824 |
|
if (charbuf >= charbuf_end) |
2825 |
|
break; |
2826 |
|
|
2827 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2828 |
|
|
2829 |
/* We produce no character or one character. */ |
/* We produce at most one character. */ |
2830 |
switch (iso_code_class [c1]) |
switch (iso_code_class [c1]) |
2831 |
{ |
{ |
2832 |
case ISO_0x20_or_0x7F: |
case ISO_0x20_or_0x7F: |
2833 |
if (COMPOSING_P (coding) && coding->composition_rule_follows) |
if (composition_state != COMPOSING_NO) |
2834 |
{ |
{ |
2835 |
DECODE_COMPOSITION_RULE (c1); |
if (composition_state == COMPOSING_RULE |
2836 |
continue; |
|| composition_state == COMPOSING_COMPONENT_RULE) |
2837 |
} |
{ |
2838 |
if (charset0 < 0 || CHARSET_CHARS (charset0) == 94) |
DECODE_COMPOSITION_RULE (c1); |
2839 |
{ |
components[component_idx++] = c1; |
2840 |
/* This is SPACE or DEL. */ |
composition_state--; |
2841 |
charset = CHARSET_ASCII; |
continue; |
2842 |
break; |
} |
2843 |
} |
} |
2844 |
/* This is a graphic character, we fall down ... */ |
if (charset_id_0 < 0 |
2845 |
|
|| ! CHARSET_ISO_CHARS_96 (CHARSET_FROM_ID (charset_id_0))) |
2846 |
|
/* This is SPACE or DEL. */ |
2847 |
|
charset = CHARSET_FROM_ID (charset_ascii); |
2848 |
|
else |
2849 |
|
charset = CHARSET_FROM_ID (charset_id_0); |
2850 |
|
break; |
2851 |
|
|
2852 |
case ISO_graphic_plane_0: |
case ISO_graphic_plane_0: |
2853 |
if (COMPOSING_P (coding) && coding->composition_rule_follows) |
if (composition_state != COMPOSING_NO) |
2854 |
{ |
{ |
2855 |
DECODE_COMPOSITION_RULE (c1); |
if (composition_state == COMPOSING_RULE |
2856 |
continue; |
|| composition_state == COMPOSING_COMPONENT_RULE) |
2857 |
|
{ |
2858 |
|
DECODE_COMPOSITION_RULE (c1); |
2859 |
|
components[component_idx++] = c1; |
2860 |
|
composition_state--; |
2861 |
|
continue; |
2862 |
|
} |
2863 |
} |
} |
2864 |
charset = charset0; |
charset = CHARSET_FROM_ID (charset_id_0); |
2865 |
break; |
break; |
2866 |
|
|
2867 |
case ISO_0xA0_or_0xFF: |
case ISO_0xA0_or_0xFF: |
2868 |
if (charset1 < 0 || CHARSET_CHARS (charset1) == 94 |
if (charset_id_1 < 0 |
2869 |
|| coding->flags & CODING_FLAG_ISO_SEVEN_BITS) |
|| ! CHARSET_ISO_CHARS_96 (CHARSET_FROM_ID (charset_id_1)) |
2870 |
goto label_invalid_code; |
|| CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) |
2871 |
|
goto invalid_code; |
2872 |
/* This is a graphic character, we fall down ... */ |
/* This is a graphic character, we fall down ... */ |
2873 |
|
|
2874 |
case ISO_graphic_plane_1: |
case ISO_graphic_plane_1: |
2875 |
if (charset1 < 0) |
if (charset_id_1 < 0) |
2876 |
goto label_invalid_code; |
goto invalid_code; |
2877 |
charset = charset1; |
charset = CHARSET_FROM_ID (charset_id_1); |
|
break; |
|
|
|
|
|
case ISO_control_0: |
|
|
if (COMPOSING_P (coding)) |
|
|
DECODE_COMPOSITION_END ('1'); |
|
|
|
|
|
/* 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)) |
|
|
{ |
|
|
coding->result = CODING_FINISH_INCONSISTENT_EOL; |
|
|
goto label_end_of_loop; |
|
|
} |
|
|
charset = CHARSET_ASCII; |
|
2878 |
break; |
break; |
2879 |
|
|
|
case ISO_control_1: |
|
|
if (COMPOSING_P (coding)) |
|
|
DECODE_COMPOSITION_END ('1'); |
|
|
goto label_invalid_code; |
|
|
|
|
2880 |
case ISO_carriage_return: |
case ISO_carriage_return: |
2881 |
if (COMPOSING_P (coding)) |
if (c1 == '\r') |
|
DECODE_COMPOSITION_END ('1'); |
|
|
|
|
|
if (coding->eol_type == CODING_EOL_CR) |
|
|
c1 = '\n'; |
|
|
else if (coding->eol_type == CODING_EOL_CRLF) |
|
2882 |
{ |
{ |
2883 |
ONE_MORE_BYTE (c1); |
if (EQ (eol_type, Qdos)) |
|
if (c1 != ISO_CODE_LF) |
|
2884 |
{ |
{ |
2885 |
src--; |
if (src == src_end) |
2886 |
c1 = '\r'; |
{ |
2887 |
|
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
2888 |
|
goto no_more_source; |
2889 |
|
} |
2890 |
|
if (*src == '\n') |
2891 |
|
ONE_MORE_BYTE (c1); |
2892 |
} |
} |
2893 |
|
else if (EQ (eol_type, Qmac)) |
2894 |
|
c1 = '\n'; |
2895 |
} |
} |
2896 |
charset = CHARSET_ASCII; |
/* fall through */ |
2897 |
|
|
2898 |
|
case ISO_control_0: |
2899 |
|
MAYBE_FINISH_COMPOSITION (); |
2900 |
|
charset = CHARSET_FROM_ID (charset_ascii); |
2901 |
break; |
break; |
2902 |
|
|
2903 |
|
case ISO_control_1: |
2904 |
|
MAYBE_FINISH_COMPOSITION (); |
2905 |
|
goto invalid_code; |
2906 |
|
|
2907 |
case ISO_shift_out: |
case ISO_shift_out: |
2908 |
if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_LOCKING_SHIFT) |
2909 |
|| CODING_SPEC_ISO_DESIGNATION (coding, 1) < 0) |
|| CODING_ISO_DESIGNATION (coding, 1) < 0) |
2910 |
goto label_invalid_code; |
goto invalid_code; |
2911 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 1; |
CODING_ISO_INVOCATION (coding, 0) = 1; |
2912 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
2913 |
continue; |
continue; |
2914 |
|
|
2915 |
case ISO_shift_in: |
case ISO_shift_in: |
2916 |
if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT)) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_LOCKING_SHIFT)) |
2917 |
goto label_invalid_code; |
goto invalid_code; |
2918 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 0; |
CODING_ISO_INVOCATION (coding, 0) = 0; |
2919 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
2920 |
continue; |
continue; |
2921 |
|
|
2922 |
case ISO_single_shift_2_7: |
case ISO_single_shift_2_7: |
2923 |
case ISO_single_shift_2: |
case ISO_single_shift_2: |
2924 |
if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT)) |
2925 |
goto label_invalid_code; |
goto invalid_code; |
2926 |
/* SS2 is handled as an escape sequence of ESC 'N' */ |
/* SS2 is handled as an escape sequence of ESC 'N' */ |
2927 |
c1 = 'N'; |
c1 = 'N'; |
2928 |
goto label_escape_sequence; |
goto label_escape_sequence; |
2929 |
|
|
2930 |
case ISO_single_shift_3: |
case ISO_single_shift_3: |
2931 |
if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT)) |
2932 |
goto label_invalid_code; |
goto invalid_code; |
2933 |
/* SS2 is handled as an escape sequence of ESC 'O' */ |
/* SS2 is handled as an escape sequence of ESC 'O' */ |
2934 |
c1 = 'O'; |
c1 = 'O'; |
2935 |
goto label_escape_sequence; |
goto label_escape_sequence; |
2942 |
case ISO_escape: |
case ISO_escape: |
2943 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2944 |
label_escape_sequence: |
label_escape_sequence: |
2945 |
/* Escape sequences handled by Emacs are invocation, |
/* Escape sequences handled here are invocation, |
2946 |
designation, direction specification, and character |
designation, direction specification, and character |
2947 |
composition specification. */ |
composition specification. */ |
2948 |
switch (c1) |
switch (c1) |
2950 |
case '&': /* revision of following character set */ |
case '&': /* revision of following character set */ |
2951 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2952 |
if (!(c1 >= '@' && c1 <= '~')) |
if (!(c1 >= '@' && c1 <= '~')) |
2953 |
goto label_invalid_code; |
goto invalid_code; |
2954 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2955 |
if (c1 != ISO_CODE_ESC) |
if (c1 != ISO_CODE_ESC) |
2956 |
goto label_invalid_code; |
goto invalid_code; |
2957 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2958 |
goto label_escape_sequence; |
goto label_escape_sequence; |
2959 |
|
|
2960 |
case '$': /* designation of 2-byte character set */ |
case '$': /* designation of 2-byte character set */ |
2961 |
if (! (coding->flags & CODING_FLAG_ISO_DESIGNATION)) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATION)) |
2962 |
goto label_invalid_code; |
goto invalid_code; |
2963 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
2964 |
if (c1 >= '@' && c1 <= 'B') |
if (c1 >= '@' && c1 <= 'B') |
2965 |
{ /* designation of JISX0208.1978, GB2312.1980, |
{ /* designation of JISX0208.1978, GB2312.1980, |
2966 |
or JISX0208.1980 */ |
or JISX0208.1980 */ |
2967 |
DECODE_DESIGNATION (0, 2, 94, c1); |
DECODE_DESIGNATION (0, 2, 0, c1); |
2968 |
} |
} |
2969 |
else if (c1 >= 0x28 && c1 <= 0x2B) |
else if (c1 >= 0x28 && c1 <= 0x2B) |
2970 |
{ /* designation of DIMENSION2_CHARS94 character set */ |
{ /* designation of DIMENSION2_CHARS94 character set */ |
2971 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c2); |
2972 |
DECODE_DESIGNATION (c1 - 0x28, 2, 94, c2); |
DECODE_DESIGNATION (c1 - 0x28, 2, 0, c2); |
2973 |
} |
} |
2974 |
else if (c1 >= 0x2C && c1 <= 0x2F) |
else if (c1 >= 0x2C && c1 <= 0x2F) |
2975 |
{ /* designation of DIMENSION2_CHARS96 character set */ |
{ /* designation of DIMENSION2_CHARS96 character set */ |
2976 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c2); |
2977 |
DECODE_DESIGNATION (c1 - 0x2C, 2, 96, c2); |
DECODE_DESIGNATION (c1 - 0x2C, 2, 1, c2); |
2978 |
} |
} |
2979 |
else |
else |
2980 |
goto label_invalid_code; |
goto invalid_code; |
2981 |
/* We must update these variables now. */ |
/* We must update these variables now. */ |
2982 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
2983 |
charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1); |
charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1); |
2984 |
continue; |
continue; |
2985 |
|
|
2986 |
case 'n': /* invocation of locking-shift-2 */ |
case 'n': /* invocation of locking-shift-2 */ |
2987 |
if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_LOCKING_SHIFT) |
2988 |
|| CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) |
|| CODING_ISO_DESIGNATION (coding, 2) < 0) |
2989 |
goto label_invalid_code; |
goto invalid_code; |
2990 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 2; |
CODING_ISO_INVOCATION (coding, 0) = 2; |
2991 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
2992 |
continue; |
continue; |
2993 |
|
|
2994 |
case 'o': /* invocation of locking-shift-3 */ |
case 'o': /* invocation of locking-shift-3 */ |
2995 |
if (! (coding->flags & CODING_FLAG_ISO_LOCKING_SHIFT) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_LOCKING_SHIFT) |
2996 |
|| CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) |
|| CODING_ISO_DESIGNATION (coding, 3) < 0) |
2997 |
goto label_invalid_code; |
goto invalid_code; |
2998 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 3; |
CODING_ISO_INVOCATION (coding, 0) = 3; |
2999 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
3000 |
continue; |
continue; |
3001 |
|
|
3002 |
case 'N': /* invocation of single-shift-2 */ |
case 'N': /* invocation of single-shift-2 */ |
3003 |
if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT) |
3004 |
|| CODING_SPEC_ISO_DESIGNATION (coding, 2) < 0) |
|| CODING_ISO_DESIGNATION (coding, 2) < 0) |
3005 |
goto label_invalid_code; |
goto invalid_code; |
3006 |
charset = CODING_SPEC_ISO_DESIGNATION (coding, 2); |
charset = CHARSET_FROM_ID (CODING_ISO_DESIGNATION (coding, 2)); |
3007 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3008 |
if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) |
if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) |
3009 |
goto label_invalid_code; |
goto invalid_code; |
3010 |
break; |
break; |
3011 |
|
|
3012 |
case 'O': /* invocation of single-shift-3 */ |
case 'O': /* invocation of single-shift-3 */ |
3013 |
if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT) |
3014 |
|| CODING_SPEC_ISO_DESIGNATION (coding, 3) < 0) |
|| CODING_ISO_DESIGNATION (coding, 3) < 0) |
3015 |
goto label_invalid_code; |
goto invalid_code; |
3016 |
charset = CODING_SPEC_ISO_DESIGNATION (coding, 3); |
charset = CHARSET_FROM_ID (CODING_ISO_DESIGNATION (coding, 3)); |
3017 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3018 |
if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) |
if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) |
3019 |
goto label_invalid_code; |
goto invalid_code; |
3020 |
break; |
break; |
3021 |
|
|
3022 |
case '0': case '2': case '3': case '4': /* start composition */ |
case '0': case '2': case '3': case '4': /* start composition */ |
3023 |
|
if (! (coding->common_flags & CODING_ANNOTATE_COMPOSITION_MASK)) |
3024 |
|
goto invalid_code; |
3025 |
DECODE_COMPOSITION_START (c1); |
DECODE_COMPOSITION_START (c1); |
3026 |
continue; |
continue; |
3027 |
|
|
3028 |
case '1': /* end composition */ |
case '1': /* end composition */ |
3029 |
DECODE_COMPOSITION_END (c1); |
if (composition_state == COMPOSING_NO) |
3030 |
|
goto invalid_code; |
3031 |
|
DECODE_COMPOSITION_END (); |
3032 |
continue; |
continue; |
3033 |
|
|
3034 |
case '[': /* specification of direction */ |
case '[': /* specification of direction */ |
3035 |
if (coding->flags & CODING_FLAG_ISO_NO_DIRECTION) |
if (! CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DIRECTION) |
3036 |
goto label_invalid_code; |
goto invalid_code; |
3037 |
/* For the moment, nested direction is not supported. |
/* For the moment, nested direction is not supported. |
3038 |
So, `coding->mode & CODING_MODE_DIRECTION' zero means |
So, `coding->mode & CODING_MODE_DIRECTION' zero means |
3039 |
left-to-right, and nonzero means right-to-left. */ |
left-to-right, and nozero means right-to-left. */ |
3040 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3041 |
switch (c1) |
switch (c1) |
3042 |
{ |
{ |
3049 |
if (c1 == ']') |
if (c1 == ']') |
3050 |
coding->mode &= ~CODING_MODE_DIRECTION; |
coding->mode &= ~CODING_MODE_DIRECTION; |
3051 |
else |
else |
3052 |
goto label_invalid_code; |
goto invalid_code; |
3053 |
break; |
break; |
3054 |
|
|
3055 |
case '2': /* start of right-to-left direction */ |
case '2': /* start of right-to-left direction */ |
3057 |
if (c1 == ']') |
if (c1 == ']') |
3058 |
coding->mode |= CODING_MODE_DIRECTION; |
coding->mode |= CODING_MODE_DIRECTION; |
3059 |
else |
else |
3060 |
goto label_invalid_code; |
goto invalid_code; |
3061 |
break; |
break; |
3062 |
|
|
3063 |
default: |
default: |
3064 |
goto label_invalid_code; |
goto invalid_code; |
3065 |
} |
} |
3066 |
continue; |
continue; |
3067 |
|
|
3068 |
case '%': |
case '%': |
|
if (COMPOSING_P (coding)) |
|
|
DECODE_COMPOSITION_END ('1'); |
|
3069 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3070 |
if (c1 == '/') |
if (c1 == '/') |
3071 |
{ |
{ |
3074 |
We keep these bytes as is for the moment. |
We keep these bytes as is for the moment. |
3075 |
They may be decoded by post-read-conversion. */ |
They may be decoded by post-read-conversion. */ |
3076 |
int dim, M, L; |
int dim, M, L; |
3077 |
int size, required; |
int size; |
3078 |
int produced_chars; |
|
|
|
|
3079 |
ONE_MORE_BYTE (dim); |
ONE_MORE_BYTE (dim); |
3080 |
ONE_MORE_BYTE (M); |
ONE_MORE_BYTE (M); |
3081 |
ONE_MORE_BYTE (L); |
ONE_MORE_BYTE (L); |
3082 |
size = ((M - 128) * 128) + (L - 128); |
size = ((M - 128) * 128) + (L - 128); |
3083 |
required = 8 + size * 2; |
if (charbuf + 8 + size > charbuf_end) |
3084 |
if (dst + required > (dst_bytes ? dst_end : src)) |
goto break_loop; |
3085 |
goto label_end_of_loop; |
*charbuf++ = ISO_CODE_ESC; |
3086 |
*dst++ = ISO_CODE_ESC; |
*charbuf++ = '%'; |
3087 |
*dst++ = '%'; |
*charbuf++ = '/'; |
3088 |
*dst++ = '/'; |
*charbuf++ = dim; |
3089 |
*dst++ = dim; |
*charbuf++ = BYTE8_TO_CHAR (M); |
3090 |
produced_chars = 4; |
*charbuf++ = BYTE8_TO_CHAR (L); |
|
dst += CHAR_STRING (M, dst), produced_chars++; |
|
|
dst += CHAR_STRING (L, dst), produced_chars++; |
|
3091 |
while (size-- > 0) |
while (size-- > 0) |
3092 |
{ |
{ |
3093 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3094 |
dst += CHAR_STRING (c1, dst), produced_chars++; |
*charbuf++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1); |
3095 |
} |
} |
|
coding->produced_char += produced_chars; |
|
3096 |
} |
} |
3097 |
else if (c1 == 'G') |
else if (c1 == 'G') |
3098 |
{ |
{ |
|
unsigned char *d = dst; |
|
|
int produced_chars; |
|
|
|
|
3099 |
/* XFree86 extension for embedding UTF-8 in CTEXT: |
/* XFree86 extension for embedding UTF-8 in CTEXT: |
3100 |
ESC % G --UTF-8-BYTES-- ESC % @ |
ESC % G --UTF-8-BYTES-- ESC % @ |
3101 |
We keep these bytes as is for the moment. |
We keep these bytes as is for the moment. |
3102 |
They may be decoded by post-read-conversion. */ |
They may be decoded by post-read-conversion. */ |
3103 |
if (d + 6 > (dst_bytes ? dst_end : src)) |
int *p = charbuf; |
3104 |
goto label_end_of_loop; |
|
3105 |
*d++ = ISO_CODE_ESC; |
if (p + 6 > charbuf_end) |
3106 |
*d++ = '%'; |
goto break_loop; |
3107 |
*d++ = 'G'; |
*p++ = ISO_CODE_ESC; |
3108 |
produced_chars = 3; |
*p++ = '%'; |
3109 |
while (d + 1 < (dst_bytes ? dst_end : src)) |
*p++ = 'G'; |
3110 |
|
while (p < charbuf_end) |
3111 |
{ |
{ |
3112 |
ONE_MORE_BYTE (c1); |
ONE_MORE_BYTE (c1); |
3113 |
if (c1 == ISO_CODE_ESC |
if (c1 == ISO_CODE_ESC |
3115 |
&& src[0] == '%' |
&& src[0] == '%' |
3116 |
&& src[1] == '@') |
&& src[1] == '@') |
3117 |
break; |
break; |
3118 |
d += CHAR_STRING (c1, d), produced_chars++; |
*p++ = ASCII_BYTE_P (c1) ? c1 : BYTE8_TO_CHAR (c1); |
3119 |
} |
} |
3120 |
if (d + 3 > (dst_bytes ? dst_end : src)) |
if (p + 3 > charbuf_end) |
3121 |
goto label_end_of_loop; |
goto break_loop; |
3122 |
*d++ = ISO_CODE_ESC; |
*p++ = ISO_CODE_ESC; |
3123 |
*d++ = '%'; |
*p++ = '%'; |
3124 |
*d++ = '@'; |
*p++ = '@'; |
3125 |
dst = d; |
charbuf = p; |
|
coding->produced_char += produced_chars + 3; |
|
3126 |
} |
} |
3127 |
else |
else |
3128 |
goto label_invalid_code; |
goto invalid_code; |
3129 |
continue; |
continue; |
3130 |
|
break; |
3131 |
|
|
3132 |
default: |
default: |
3133 |
if (! (coding->flags & CODING_FLAG_ISO_DESIGNATION)) |
if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATION)) |
3134 |
goto label_invalid_code; |
goto invalid_code; |
3135 |
if (c1 >= 0x28 && c1 <= 0x2B) |
if (c1 >= 0x28 && c1 <= 0x2B) |
3136 |
{ /* designation of DIMENSION1_CHARS94 character set */ |
{ /* designation of DIMENSION1_CHARS94 character set */ |
3137 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c2); |
3138 |
DECODE_DESIGNATION (c1 - 0x28, 1, 94, c2); |
DECODE_DESIGNATION (c1 - 0x28, 1, 0, c2); |
3139 |
} |
} |
3140 |
else if (c1 >= 0x2C && c1 <= 0x2F) |
else if (c1 >= 0x2C && c1 <= 0x2F) |
3141 |
{ /* designation of DIMENSION1_CHARS96 character set */ |
{ /* designation of DIMENSION1_CHARS96 character set */ |
3142 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c2); |
3143 |
DECODE_DESIGNATION (c1 - 0x2C, 1, 96, c2); |
DECODE_DESIGNATION (c1 - 0x2C, 1, 1, c2); |
3144 |
} |
} |
3145 |
else |
else |
3146 |
goto label_invalid_code; |
goto invalid_code; |
3147 |
/* We must update these variables now. */ |
/* We must update these variables now. */ |
3148 |
charset0 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 0); |
charset_id_0 = CODING_ISO_INVOKED_CHARSET (coding, 0); |
3149 |
charset1 = CODING_SPEC_ISO_PLANE_CHARSET (coding, 1); |
charset_id_1 = CODING_ISO_INVOKED_CHARSET (coding, 1); |
3150 |
continue; |
continue; |
3151 |
} |
} |
3152 |
} |
} |
3153 |
|
|
3154 |
|
if (charset->id != charset_ascii |
3155 |
|
&& last_id != charset->id) |
3156 |
|
{ |
3157 |
|
if (last_id != charset_ascii) |
3158 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
3159 |
|
last_id = charset->id; |
3160 |
|
last_offset = char_offset; |
3161 |
|
} |
3162 |
|
|
3163 |
/* Now we know CHARSET and 1st position code C1 of a character. |
/* Now we know CHARSET and 1st position code C1 of a character. |
3164 |
Produce a multibyte sequence for that character while getting |
Produce a decoded character while getting 2nd position code |
3165 |
2nd position code C2 if necessary. */ |
C2 if necessary. */ |
3166 |
if (CHARSET_DIMENSION (charset) == 2) |
c1 &= 0x7F; |
3167 |
|
if (CHARSET_DIMENSION (charset) > 1) |
3168 |
{ |
{ |
3169 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c2); |
3170 |
if (c1 < 0x80 ? c2 < 0x20 || c2 >= 0x80 : c2 < 0xA0) |
if (c2 < 0x20 || (c2 >= 0x80 && c2 < 0xA0)) |
3171 |
/* C2 is not in a valid range. */ |
/* C2 is not in a valid range. */ |
3172 |
goto label_invalid_code; |
goto invalid_code; |
3173 |
|
c1 = (c1 << 8) | (c2 & 0x7F); |
3174 |
|
if (CHARSET_DIMENSION (charset) > 2) |
3175 |
|
{ |
3176 |
|
ONE_MORE_BYTE (c2); |
3177 |
|
if (c2 < 0x20 || (c2 >= 0x80 && c2 < 0xA0)) |
3178 |
|
/* C2 is not in a valid range. */ |
3179 |
|
goto invalid_code; |
3180 |
|
c1 = (c1 << 8) | (c2 & 0x7F); |
3181 |
|
} |
3182 |
|
} |
3183 |
|
|
3184 |
|
CODING_DECODE_CHAR (coding, src, src_base, src_end, charset, c1, c); |
3185 |
|
if (c < 0) |
3186 |
|
{ |
3187 |
|
MAYBE_FINISH_COMPOSITION (); |
3188 |
|
for (; src_base < src; src_base++, char_offset++) |
3189 |
|
{ |
3190 |
|
if (ASCII_BYTE_P (*src_base)) |
3191 |
|
*charbuf++ = *src_base; |
3192 |
|
else |
3193 |
|
*charbuf++ = BYTE8_TO_CHAR (*src_base); |
3194 |
|
} |
3195 |
|
} |
3196 |
|
else if (composition_state == COMPOSING_NO) |
3197 |
|
{ |
3198 |
|
*charbuf++ = c; |
3199 |
|
char_offset++; |
3200 |
|
} |
3201 |
|
else |
3202 |
|
{ |
3203 |
|
components[component_idx++] = c; |
3204 |
|
if (method == COMPOSITION_WITH_RULE |
3205 |
|
|| (method == COMPOSITION_WITH_RULE_ALTCHARS |
3206 |
|
&& composition_state == COMPOSING_COMPONENT_CHAR)) |
3207 |
|
composition_state++; |
3208 |
} |
} |
|
c = DECODE_ISO_CHARACTER (charset, c1, c2); |
|
|
EMIT_CHAR (c); |
|
3209 |
continue; |
continue; |
3210 |
|
|
3211 |
label_invalid_code: |
invalid_code: |
3212 |
coding->errors++; |
MAYBE_FINISH_COMPOSITION (); |
|
if (COMPOSING_P (coding)) |
|
|
DECODE_COMPOSITION_END ('1'); |
|
3213 |
src = src_base; |
src = src_base; |
3214 |
c = *src++; |
consumed_chars = consumed_chars_base; |
3215 |
EMIT_CHAR (c); |
ONE_MORE_BYTE (c); |
3216 |
|
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
3217 |
|
char_offset++; |
3218 |
|
coding->errors++; |
3219 |
|
continue; |
3220 |
|
|
3221 |
|
break_loop: |
3222 |
|
break; |
3223 |
} |
} |
3224 |
|
|
3225 |
label_end_of_loop: |
no_more_source: |
3226 |
coding->consumed = coding->consumed_char = src_base - source; |
if (last_id != charset_ascii) |
3227 |
coding->produced = dst - destination; |
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
3228 |
return; |
coding->consumed_char += consumed_chars_base; |
3229 |
|
coding->consumed = src_base - coding->source; |
3230 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
3231 |
} |
} |
3232 |
|
|
3233 |
|
|
3235 |
|
|
3236 |
/* |
/* |
3237 |
It is not enough to say just "ISO2022" on encoding, we have to |
It is not enough to say just "ISO2022" on encoding, we have to |
3238 |
specify more details. In Emacs, each ISO2022 coding system |
specify more details. In Emacs, each coding system of ISO2022 |
3239 |
variant has the following specifications: |
variant has the following specifications: |
3240 |
1. Initial designation to G0 through G3. |
1. Initial designation to G0 thru G3. |
3241 |
2. Allows short-form designation? |
2. Allows short-form designation? |
3242 |
3. ASCII should be designated to G0 before control characters? |
3. ASCII should be designated to G0 before control characters? |
3243 |
4. ASCII should be designated to G0 at end of line? |
4. ASCII should be designated to G0 at end of line? |
3247 |
And the following two are only for Japanese: |
And the following two are only for Japanese: |
3248 |
8. Use ASCII in place of JIS0201-1976-Roman? |
8. Use ASCII in place of JIS0201-1976-Roman? |
3249 |
9. Use JISX0208-1983 in place of JISX0208-1978? |
9. Use JISX0208-1983 in place of JISX0208-1978? |
3250 |
These specifications are encoded in `coding->flags' as flag bits |
These specifications are encoded in CODING_ISO_FLAGS (coding) as flag bits |
3251 |
defined by macros CODING_FLAG_ISO_XXX. See `coding.h' for more |
defined by macros CODING_ISO_FLAG_XXX. See `coding.h' for more |
3252 |
details. |
details. |
3253 |
*/ |
*/ |
3254 |
|
|
3259 |
|
|
3260 |
#define ENCODE_DESIGNATION(charset, reg, coding) \ |
#define ENCODE_DESIGNATION(charset, reg, coding) \ |
3261 |
do { \ |
do { \ |
3262 |
unsigned char final_char = CHARSET_ISO_FINAL_CHAR (charset); \ |
unsigned char final_char = CHARSET_ISO_FINAL (charset); \ |
3263 |
char *intermediate_char_94 = "()*+"; \ |
char *intermediate_char_94 = "()*+"; \ |
3264 |
char *intermediate_char_96 = ",-./"; \ |
char *intermediate_char_96 = ",-./"; \ |
3265 |
int revision = CODING_SPEC_ISO_REVISION_NUMBER(coding, charset); \ |
int revision = -1; \ |
3266 |
\ |
int c; \ |
3267 |
if (revision < 255) \ |
\ |
3268 |
|
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_REVISION) \ |
3269 |
|
revision = CHARSET_ISO_REVISION (charset); \ |
3270 |
|
\ |
3271 |
|
if (revision >= 0) \ |
3272 |
{ \ |
{ \ |
3273 |
*dst++ = ISO_CODE_ESC; \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, '&'); \ |
3274 |
*dst++ = '&'; \ |
EMIT_ONE_BYTE ('@' + revision); \ |
|
*dst++ = '@' + revision; \ |
|
3275 |
} \ |
} \ |
3276 |
*dst++ = ISO_CODE_ESC; \ |
EMIT_ONE_ASCII_BYTE (ISO_CODE_ESC); \ |
3277 |
if (CHARSET_DIMENSION (charset) == 1) \ |
if (CHARSET_DIMENSION (charset) == 1) \ |
3278 |
{ \ |
{ \ |
3279 |
if (CHARSET_CHARS (charset) == 94) \ |
if (! CHARSET_ISO_CHARS_96 (charset)) \ |
3280 |
*dst++ = (unsigned char) (intermediate_char_94[reg]); \ |
c = intermediate_char_94[reg]; \ |
3281 |
else \ |
else \ |
3282 |
*dst++ = (unsigned char) (intermediate_char_96[reg]); \ |
c = intermediate_char_96[reg]; \ |
3283 |
|
EMIT_ONE_ASCII_BYTE (c); \ |
3284 |
} \ |
} \ |
3285 |
else \ |
else \ |
3286 |
{ \ |
{ \ |
3287 |
*dst++ = '$'; \ |
EMIT_ONE_ASCII_BYTE ('$'); \ |
3288 |
if (CHARSET_CHARS (charset) == 94) \ |
if (! CHARSET_ISO_CHARS_96 (charset)) \ |
3289 |
{ \ |
{ \ |
3290 |
if (! (coding->flags & CODING_FLAG_ISO_SHORT_FORM) \ |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_LONG_FORM \ |
3291 |
|| reg != 0 \ |
|| reg != 0 \ |
3292 |
|| final_char < '@' || final_char > 'B') \ |
|| final_char < '@' || final_char > 'B') \ |
3293 |
*dst++ = (unsigned char) (intermediate_char_94[reg]); \ |
EMIT_ONE_ASCII_BYTE (intermediate_char_94[reg]); \ |
3294 |
} \ |
} \ |
3295 |
else \ |
else \ |
3296 |
*dst++ = (unsigned char) (intermediate_char_96[reg]); \ |
EMIT_ONE_ASCII_BYTE (intermediate_char_96[reg]); \ |
3297 |
} \ |
} \ |
3298 |
*dst++ = final_char; \ |
EMIT_ONE_ASCII_BYTE (final_char); \ |
3299 |
CODING_SPEC_ISO_DESIGNATION (coding, reg) = charset; \ |
\ |
3300 |
|
CODING_ISO_DESIGNATION (coding, reg) = CHARSET_ID (charset); \ |
3301 |
} while (0) |
} while (0) |
3302 |
|
|
3303 |
|
|
3304 |
/* The following two macros produce codes (control character or escape |
/* The following two macros produce codes (control character or escape |
3305 |
sequence) for ISO2022 single-shift functions (single-shift-2 and |
sequence) for ISO2022 single-shift functions (single-shift-2 and |
3306 |
single-shift-3). */ |
single-shift-3). */ |
3307 |
|
|
3308 |
#define ENCODE_SINGLE_SHIFT_2 \ |
#define ENCODE_SINGLE_SHIFT_2 \ |
3309 |
do { \ |
do { \ |
3310 |
if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) \ |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) \ |
3311 |
*dst++ = ISO_CODE_ESC, *dst++ = 'N'; \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, 'N'); \ |
3312 |
else \ |
else \ |
3313 |
*dst++ = ISO_CODE_SS2; \ |
EMIT_ONE_BYTE (ISO_CODE_SS2); \ |
3314 |
CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 1; \ |
CODING_ISO_SINGLE_SHIFTING (coding) = 1; \ |
3315 |
} while (0) |
} while (0) |
3316 |
|
|
3317 |
#define ENCODE_SINGLE_SHIFT_3 \ |
|
3318 |
do { \ |
#define ENCODE_SINGLE_SHIFT_3 \ |
3319 |
if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) \ |
do { \ |
3320 |
*dst++ = ISO_CODE_ESC, *dst++ = 'O'; \ |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) \ |
3321 |
else \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, 'O'); \ |
3322 |
*dst++ = ISO_CODE_SS3; \ |
else \ |
3323 |
CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 1; \ |
EMIT_ONE_BYTE (ISO_CODE_SS3); \ |
3324 |
|
CODING_ISO_SINGLE_SHIFTING (coding) = 1; \ |
3325 |
} while (0) |
} while (0) |
3326 |
|
|
3327 |
|
|
3328 |
/* The following four macros produce codes (control character or |
/* The following four macros produce codes (control character or |
3329 |
escape sequence) for ISO2022 locking-shift functions (shift-in, |
escape sequence) for ISO2022 locking-shift functions (shift-in, |
3330 |
shift-out, locking-shift-2, and locking-shift-3). */ |
shift-out, locking-shift-2, and locking-shift-3). */ |
3331 |
|
|
3332 |
#define ENCODE_SHIFT_IN \ |
#define ENCODE_SHIFT_IN \ |
3333 |
do { \ |
do { \ |
3334 |
*dst++ = ISO_CODE_SI; \ |
EMIT_ONE_ASCII_BYTE (ISO_CODE_SI); \ |
3335 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 0; \ |
CODING_ISO_INVOCATION (coding, 0) = 0; \ |
3336 |
} while (0) |
} while (0) |
3337 |
|
|
3338 |
#define ENCODE_SHIFT_OUT \ |
|
3339 |
do { \ |
#define ENCODE_SHIFT_OUT \ |
3340 |
*dst++ = ISO_CODE_SO; \ |
do { \ |
3341 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 1; \ |
EMIT_ONE_ASCII_BYTE (ISO_CODE_SO); \ |
3342 |
|
CODING_ISO_INVOCATION (coding, 0) = 1; \ |
3343 |
} while (0) |
} while (0) |
3344 |
|
|
3345 |
#define ENCODE_LOCKING_SHIFT_2 \ |
|
3346 |
do { \ |
#define ENCODE_LOCKING_SHIFT_2 \ |
3347 |
*dst++ = ISO_CODE_ESC, *dst++ = 'n'; \ |
do { \ |
3348 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 2; \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, 'n'); \ |
3349 |
|
CODING_ISO_INVOCATION (coding, 0) = 2; \ |
3350 |
} while (0) |
} while (0) |
3351 |
|
|
3352 |
#define ENCODE_LOCKING_SHIFT_3 \ |
|
3353 |
do { \ |
#define ENCODE_LOCKING_SHIFT_3 \ |
3354 |
*dst++ = ISO_CODE_ESC, *dst++ = 'o'; \ |
do { \ |
3355 |
CODING_SPEC_ISO_INVOCATION (coding, 0) = 3; \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, 'n'); \ |
3356 |
|
CODING_ISO_INVOCATION (coding, 0) = 3; \ |
3357 |
} while (0) |
} while (0) |
3358 |
|
|
3359 |
|
|
3360 |
/* Produce codes for a DIMENSION1 character whose character set is |
/* Produce codes for a DIMENSION1 character whose character set is |
3361 |
CHARSET and whose position-code is C1. Designation and invocation |
CHARSET and whose position-code is C1. Designation and invocation |
3362 |
sequences are also produced in advance if necessary. */ |
sequences are also produced in advance if necessary. */ |
3363 |
|
|
3364 |
#define ENCODE_ISO_CHARACTER_DIMENSION1(charset, c1) \ |
#define ENCODE_ISO_CHARACTER_DIMENSION1(charset, c1) \ |
3365 |
do { \ |
do { \ |
3366 |
if (CODING_SPEC_ISO_SINGLE_SHIFTING (coding)) \ |
int id = CHARSET_ID (charset); \ |
3367 |
|
\ |
3368 |
|
if ((CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_USE_ROMAN) \ |
3369 |
|
&& id == charset_ascii) \ |
3370 |
{ \ |
{ \ |
3371 |
if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) \ |
id = charset_jisx0201_roman; \ |
3372 |
*dst++ = c1 & 0x7F; \ |
charset = CHARSET_FROM_ID (id); \ |
3373 |
|
} \ |
3374 |
|
\ |
3375 |
|
if (CODING_ISO_SINGLE_SHIFTING (coding)) \ |
3376 |
|
{ \ |
3377 |
|
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) \ |
3378 |
|
EMIT_ONE_ASCII_BYTE (c1 & 0x7F); \ |
3379 |
else \ |
else \ |
3380 |
*dst++ = c1 | 0x80; \ |
EMIT_ONE_BYTE (c1 | 0x80); \ |
3381 |
CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 0; \ |
CODING_ISO_SINGLE_SHIFTING (coding) = 0; \ |
3382 |
break; \ |
break; \ |
3383 |
} \ |
} \ |
3384 |
else if (charset == CODING_SPEC_ISO_PLANE_CHARSET (coding, 0)) \ |
else if (id == CODING_ISO_INVOKED_CHARSET (coding, 0)) \ |
3385 |
{ \ |
{ \ |
3386 |
*dst++ = c1 & 0x7F; \ |
EMIT_ONE_ASCII_BYTE (c1 & 0x7F); \ |
3387 |
break; \ |
break; \ |
3388 |
} \ |
} \ |
3389 |
else if (charset == CODING_SPEC_ISO_PLANE_CHARSET (coding, 1)) \ |
else if (id == CODING_ISO_INVOKED_CHARSET (coding, 1)) \ |
3390 |
{ \ |
{ \ |
3391 |
*dst++ = c1 | 0x80; \ |
EMIT_ONE_BYTE (c1 | 0x80); \ |
3392 |
break; \ |
break; \ |
3393 |
} \ |
} \ |
3394 |
else \ |
else \ |
3396 |
must invoke it, or, at first, designate it to some graphic \ |
must invoke it, or, at first, designate it to some graphic \ |
3397 |
register. Then repeat the loop to actually produce the \ |
register. Then repeat the loop to actually produce the \ |
3398 |
character. */ \ |
character. */ \ |
3399 |
dst = encode_invocation_designation (charset, coding, dst); \ |
dst = encode_invocation_designation (charset, coding, dst, \ |
3400 |
|
&produced_chars); \ |
3401 |
} while (1) |
} while (1) |
3402 |
|
|
3403 |
|
|
3404 |
/* Produce codes for a DIMENSION2 character whose character set is |
/* Produce codes for a DIMENSION2 character whose character set is |
3405 |
CHARSET and whose position-codes are C1 and C2. Designation and |
CHARSET and whose position-codes are C1 and C2. Designation and |
3406 |
invocation codes are also produced in advance if necessary. */ |
invocation codes are also produced in advance if necessary. */ |
3407 |
|
|
3408 |
#define ENCODE_ISO_CHARACTER_DIMENSION2(charset, c1, c2) \ |
#define ENCODE_ISO_CHARACTER_DIMENSION2(charset, c1, c2) \ |
3409 |
do { \ |
do { \ |
3410 |
if (CODING_SPEC_ISO_SINGLE_SHIFTING (coding)) \ |
int id = CHARSET_ID (charset); \ |
3411 |
|
\ |
3412 |
|
if ((CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_USE_OLDJIS) \ |
3413 |
|
&& id == charset_jisx0208) \ |
3414 |
{ \ |
{ \ |
3415 |
if (coding->flags & CODING_FLAG_ISO_SEVEN_BITS) \ |
id = charset_jisx0208_1978; \ |
3416 |
*dst++ = c1 & 0x7F, *dst++ = c2 & 0x7F; \ |
charset = CHARSET_FROM_ID (id); \ |
3417 |
|
} \ |
3418 |
|
\ |
3419 |
|
if (CODING_ISO_SINGLE_SHIFTING (coding)) \ |
3420 |
|
{ \ |
3421 |
|
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) \ |
3422 |
|
EMIT_TWO_ASCII_BYTES ((c1) & 0x7F, (c2) & 0x7F); \ |
3423 |
else \ |
else \ |
3424 |
*dst++ = c1 | 0x80, *dst++ = c2 | 0x80; \ |
EMIT_TWO_BYTES ((c1) | 0x80, (c2) | 0x80); \ |
3425 |
CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 0; \ |
CODING_ISO_SINGLE_SHIFTING (coding) = 0; \ |
3426 |
break; \ |
break; \ |
3427 |
} \ |
} \ |
3428 |
else if (charset == CODING_SPEC_ISO_PLANE_CHARSET (coding, 0)) \ |
else if (id == CODING_ISO_INVOKED_CHARSET (coding, 0)) \ |
3429 |
{ \ |
{ \ |
3430 |
*dst++ = c1 & 0x7F, *dst++= c2 & 0x7F; \ |
EMIT_TWO_ASCII_BYTES ((c1) & 0x7F, (c2) & 0x7F); \ |
3431 |
break; \ |
break; \ |
3432 |
} \ |
} \ |
3433 |
else if (charset == CODING_SPEC_ISO_PLANE_CHARSET (coding, 1)) \ |
else if (id == CODING_ISO_INVOKED_CHARSET (coding, 1)) \ |
3434 |
{ \ |
{ \ |
3435 |
*dst++ = c1 | 0x80, *dst++= c2 | 0x80; \ |
EMIT_TWO_BYTES ((c1) | 0x80, (c2) | 0x80); \ |
3436 |
break; \ |
break; \ |
3437 |
} \ |
} \ |
3438 |
else \ |
else \ |
3440 |
must invoke it, or, at first, designate it to some graphic \ |
must invoke it, or, at first, designate it to some graphic \ |
3441 |
register. Then repeat the loop to actually produce the \ |
register. Then repeat the loop to actually produce the \ |
3442 |
character. */ \ |
character. */ \ |
3443 |
dst = encode_invocation_designation (charset, coding, dst); \ |
dst = encode_invocation_designation (charset, coding, dst, \ |
3444 |
|
&produced_chars); \ |
3445 |
} while (1) |
} while (1) |
3446 |
|
|
|
#define ENCODE_ISO_CHARACTER(c) \ |
|
|
do { \ |
|
|
int charset, c1, c2; \ |
|
|
\ |
|
|
SPLIT_CHAR (c, charset, c1, c2); \ |
|
|
if (CHARSET_DEFINED_P (charset)) \ |
|
|
{ \ |
|
|
if (CHARSET_DIMENSION (charset) == 1) \ |
|
|
{ \ |
|
|
if (charset == CHARSET_ASCII \ |
|
|
&& coding->flags & CODING_FLAG_ISO_USE_ROMAN) \ |
|
|
charset = charset_latin_jisx0201; \ |
|
|
ENCODE_ISO_CHARACTER_DIMENSION1 (charset, c1); \ |
|
|
} \ |
|
|
else \ |
|
|
{ \ |
|
|
if (charset == charset_jisx0208 \ |
|
|
&& coding->flags & CODING_FLAG_ISO_USE_OLDJIS) \ |
|
|
charset = charset_jisx0208_1978; \ |
|
|
ENCODE_ISO_CHARACTER_DIMENSION2 (charset, c1, c2); \ |
|
|
} \ |
|
|
} \ |
|
|
else \ |
|
|
{ \ |
|
|
*dst++ = c1; \ |
|
|
if (c2 >= 0) \ |
|
|
*dst++ = c2; \ |
|
|
} \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
/* Instead of encoding character C, produce one or two `?'s. */ |
|
3447 |
|
|
3448 |
#define ENCODE_UNSAFE_CHARACTER(c) \ |
#define ENCODE_ISO_CHARACTER(charset, c) \ |
3449 |
do { \ |
do { \ |
3450 |
ENCODE_ISO_CHARACTER (CODING_REPLACEMENT_CHARACTER); \ |
int code = ENCODE_CHAR ((charset),(c)); \ |
3451 |
if (CHARSET_WIDTH (CHAR_CHARSET (c)) > 1) \ |
\ |
3452 |
ENCODE_ISO_CHARACTER (CODING_REPLACEMENT_CHARACTER); \ |
if (CHARSET_DIMENSION (charset) == 1) \ |
3453 |
|
ENCODE_ISO_CHARACTER_DIMENSION1 ((charset), code); \ |
3454 |
|
else \ |
3455 |
|
ENCODE_ISO_CHARACTER_DIMENSION2 ((charset), code >> 8, code & 0xFF); \ |
3456 |
} while (0) |
} while (0) |
3457 |
|
|
3458 |
|
|
3459 |
/* Produce designation and invocation codes at a place pointed by DST |
/* Produce designation and invocation codes at a place pointed by DST |
3460 |
to use CHARSET. The element `spec.iso2022' of *CODING is updated. |
to use CHARSET. The element `spec.iso_2022' of *CODING is updated. |
3461 |
Return new DST. */ |
Return new DST. */ |
3462 |
|
|
3463 |
unsigned char * |
unsigned char * |
3464 |
encode_invocation_designation (charset, coding, dst) |
encode_invocation_designation (charset, coding, dst, p_nchars) |
3465 |
int charset; |
struct charset *charset; |
3466 |
struct coding_system *coding; |
struct coding_system *coding; |
3467 |
unsigned char *dst; |
unsigned char *dst; |
3468 |
|
int *p_nchars; |
3469 |
{ |
{ |
3470 |
|
int multibytep = coding->dst_multibyte; |
3471 |
|
int produced_chars = *p_nchars; |
3472 |
int reg; /* graphic register number */ |
int reg; /* graphic register number */ |
3473 |
|
int id = CHARSET_ID (charset); |
3474 |
|
|
3475 |
/* At first, check designations. */ |
/* At first, check designations. */ |
3476 |
for (reg = 0; reg < 4; reg++) |
for (reg = 0; reg < 4; reg++) |
3477 |
if (charset == CODING_SPEC_ISO_DESIGNATION (coding, reg)) |
if (id == CODING_ISO_DESIGNATION (coding, reg)) |
3478 |
break; |
break; |
3479 |
|
|
3480 |
if (reg >= 4) |
if (reg >= 4) |
3481 |
{ |
{ |
3482 |
/* CHARSET is not yet designated to any graphic registers. */ |
/* CHARSET is not yet designated to any graphic registers. */ |
3483 |
/* At first check the requested designation. */ |
/* At first check the requested designation. */ |
3484 |
reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset); |
reg = CODING_ISO_REQUEST (coding, id); |
3485 |
if (reg == CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION) |
if (reg < 0) |
3486 |
/* Since CHARSET requests no special designation, designate it |
/* Since CHARSET requests no special designation, designate it |
3487 |
to graphic register 0. */ |
to graphic register 0. */ |
3488 |
reg = 0; |
reg = 0; |
3490 |
ENCODE_DESIGNATION (charset, reg, coding); |
ENCODE_DESIGNATION (charset, reg, coding); |
3491 |
} |
} |
3492 |
|
|
3493 |
if (CODING_SPEC_ISO_INVOCATION (coding, 0) != reg |
if (CODING_ISO_INVOCATION (coding, 0) != reg |
3494 |
&& CODING_SPEC_ISO_INVOCATION (coding, 1) != reg) |
&& CODING_ISO_INVOCATION (coding, 1) != reg) |
3495 |
{ |
{ |
3496 |
/* Since the graphic register REG is not invoked to any graphic |
/* Since the graphic register REG is not invoked to any graphic |
3497 |
planes, invoke it to graphic plane 0. */ |
planes, invoke it to graphic plane 0. */ |
3506 |
break; |
break; |
3507 |
|
|
3508 |
case 2: /* graphic register 2 */ |
case 2: /* graphic register 2 */ |
3509 |
if (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT) |
3510 |
ENCODE_SINGLE_SHIFT_2; |
ENCODE_SINGLE_SHIFT_2; |
3511 |
else |
else |
3512 |
ENCODE_LOCKING_SHIFT_2; |
ENCODE_LOCKING_SHIFT_2; |
3513 |
break; |
break; |
3514 |
|
|
3515 |
case 3: /* graphic register 3 */ |
case 3: /* graphic register 3 */ |
3516 |
if (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT) |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT) |
3517 |
ENCODE_SINGLE_SHIFT_3; |
ENCODE_SINGLE_SHIFT_3; |
3518 |
else |
else |
3519 |
ENCODE_LOCKING_SHIFT_3; |
ENCODE_LOCKING_SHIFT_3; |
3521 |
} |
} |
3522 |
} |
} |
3523 |
|
|
3524 |
|
*p_nchars = produced_chars; |
3525 |
return dst; |
return dst; |
3526 |
} |
} |
3527 |
|
|
3528 |
/* Produce 2-byte codes for encoded composition rule RULE. */ |
/* The following three macros produce codes for indicating direction |
3529 |
|
of text. */ |
3530 |
#define ENCODE_COMPOSITION_RULE(rule) \ |
#define ENCODE_CONTROL_SEQUENCE_INTRODUCER \ |
|
do { \ |
|
|
int gref, nref; \ |
|
|
COMPOSITION_DECODE_RULE (rule, gref, nref); \ |
|
|
*dst++ = 32 + 81 + gref; \ |
|
|
*dst++ = 32 + nref; \ |
|
|
} while (0) |
|
|
|
|
|
/* Produce codes for indicating the start of a composition sequence |
|
|
(ESC 0, ESC 3, or ESC 4). DATA points to an array of integers |
|
|
which specify information about the composition. See the comment |
|
|
in coding.h for the format of DATA. */ |
|
|
|
|
|
#define ENCODE_COMPOSITION_START(coding, data) \ |
|
3531 |
do { \ |
do { \ |
3532 |
coding->composing = data[3]; \ |
if (CODING_ISO_FLAGS (coding) == CODING_ISO_FLAG_SEVEN_BITS) \ |
3533 |
*dst++ = ISO_CODE_ESC; \ |
EMIT_TWO_ASCII_BYTES (ISO_CODE_ESC, '['); \ |
|
if (coding->composing == COMPOSITION_RELATIVE) \ |
|
|
*dst++ = '0'; \ |
|
3534 |
else \ |
else \ |
3535 |
{ \ |
EMIT_ONE_BYTE (ISO_CODE_CSI); \ |
|
*dst++ = (coding->composing == COMPOSITION_WITH_ALTCHARS \ |
|
|
? '3' : '4'); \ |
|
|
coding->cmp_data_index = coding->cmp_data_start + 4; \ |
|
|
coding->composition_rule_follows = 0; \ |
|
|
} \ |
|
3536 |
} while (0) |
} while (0) |
3537 |
|
|
|
/* Produce codes for indicating the end of the current composition. */ |
|
3538 |
|
|
3539 |
#define ENCODE_COMPOSITION_END(coding, data) \ |
#define ENCODE_DIRECTION_R2L() \ |
3540 |
do { \ |
do { \ |
3541 |
*dst++ = ISO_CODE_ESC; \ |
ENCODE_CONTROL_SEQUENCE_INTRODUCER (dst); \ |
3542 |
*dst++ = '1'; \ |
EMIT_TWO_ASCII_BYTES ('2', ']'); \ |
|
coding->cmp_data_start += data[0]; \ |
|
|
coding->composing = COMPOSITION_NO; \ |
|
|
if (coding->cmp_data_start == coding->cmp_data->used \ |
|
|
&& coding->cmp_data->next) \ |
|
|
{ \ |
|
|
coding->cmp_data = coding->cmp_data->next; \ |
|
|
coding->cmp_data_start = 0; \ |
|
|
} \ |
|
3543 |
} while (0) |
} while (0) |
3544 |
|
|
|
/* Produce composition start sequence ESC 0. Here, this sequence |
|
|
doesn't mean the start of a new composition but means that we have |
|
|
just produced components (alternate chars and composition rules) of |
|
|
the composition and the actual text follows in SRC. */ |
|
3545 |
|
|
3546 |
#define ENCODE_COMPOSITION_FAKE_START(coding) \ |
#define ENCODE_DIRECTION_L2R() \ |
3547 |
do { \ |
do { \ |
3548 |
*dst++ = ISO_CODE_ESC; \ |
ENCODE_CONTROL_SEQUENCE_INTRODUCER (dst); \ |
3549 |
*dst++ = '0'; \ |
EMIT_TWO_ASCII_BYTES ('0', ']'); \ |
|
coding->composing = COMPOSITION_RELATIVE; \ |
|
3550 |
} while (0) |
} while (0) |
3551 |
|
|
|
/* The following three macros produce codes for indicating direction |
|
|
of text. */ |
|
|
#define ENCODE_CONTROL_SEQUENCE_INTRODUCER \ |
|
|
do { \ |
|
|
if (coding->flags == CODING_FLAG_ISO_SEVEN_BITS) \ |
|
|
*dst++ = ISO_CODE_ESC, *dst++ = '['; \ |
|
|
else \ |
|
|
*dst++ = ISO_CODE_CSI; \ |
|
|
} while (0) |
|
|
|
|
|
#define ENCODE_DIRECTION_R2L \ |
|
|
ENCODE_CONTROL_SEQUENCE_INTRODUCER (dst), *dst++ = '2', *dst++ = ']' |
|
|
|
|
|
#define ENCODE_DIRECTION_L2R \ |
|
|
ENCODE_CONTROL_SEQUENCE_INTRODUCER (dst), *dst++ = '0', *dst++ = ']' |
|
3552 |
|
|
3553 |
/* Produce codes for designation and invocation to reset the graphic |
/* Produce codes for designation and invocation to reset the graphic |
3554 |
planes and registers to initial state. */ |
planes and registers to initial state. */ |
3555 |
#define ENCODE_RESET_PLANE_AND_REGISTER \ |
#define ENCODE_RESET_PLANE_AND_REGISTER() \ |
3556 |
do { \ |
do { \ |
3557 |
int reg; \ |
int reg; \ |
3558 |
if (CODING_SPEC_ISO_INVOCATION (coding, 0) != 0) \ |
struct charset *charset; \ |
3559 |
ENCODE_SHIFT_IN; \ |
\ |
3560 |
for (reg = 0; reg < 4; reg++) \ |
if (CODING_ISO_INVOCATION (coding, 0) != 0) \ |
3561 |
if (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, reg) >= 0 \ |
ENCODE_SHIFT_IN; \ |
3562 |
&& (CODING_SPEC_ISO_DESIGNATION (coding, reg) \ |
for (reg = 0; reg < 4; reg++) \ |
3563 |
!= CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, reg))) \ |
if (CODING_ISO_INITIAL (coding, reg) >= 0 \ |
3564 |
ENCODE_DESIGNATION \ |
&& (CODING_ISO_DESIGNATION (coding, reg) \ |
3565 |
(CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, reg), reg, coding); \ |
!= CODING_ISO_INITIAL (coding, reg))) \ |
3566 |
|
{ \ |
3567 |
|
charset = CHARSET_FROM_ID (CODING_ISO_INITIAL (coding, reg)); \ |
3568 |
|
ENCODE_DESIGNATION (charset, reg, coding); \ |
3569 |
|
} \ |
3570 |
} while (0) |
} while (0) |
3571 |
|
|
3572 |
|
|
3573 |
/* Produce designation sequences of charsets in the line started from |
/* Produce designation sequences of charsets in the line started from |
3574 |
SRC to a place pointed by DST, and return updated DST. |
SRC to a place pointed by DST, and return updated DST. |
3575 |
|
|
3577 |
find all the necessary designations. */ |
find all the necessary designations. */ |
3578 |
|
|
3579 |
static unsigned char * |
static unsigned char * |
3580 |
encode_designation_at_bol (coding, translation_table, src, src_end, dst) |
encode_designation_at_bol (coding, charbuf, charbuf_end, dst) |
3581 |
struct coding_system *coding; |
struct coding_system *coding; |
3582 |
Lisp_Object translation_table; |
int *charbuf, *charbuf_end; |
3583 |
unsigned char *src, *src_end, *dst; |
unsigned char *dst; |
3584 |
{ |
{ |
3585 |
int charset, c, found = 0, reg; |
struct charset *charset; |
3586 |
/* Table of charsets to be designated to each graphic register. */ |
/* Table of charsets to be designated to each graphic register. */ |
3587 |
int r[4]; |
int r[4]; |
3588 |
|
int c, found = 0, reg; |
3589 |
|
int produced_chars = 0; |
3590 |
|
int multibytep = coding->dst_multibyte; |
3591 |
|
Lisp_Object attrs; |
3592 |
|
Lisp_Object charset_list; |
3593 |
|
|
3594 |
|
attrs = CODING_ID_ATTRS (coding->id); |
3595 |
|
charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
3596 |
|
if (EQ (charset_list, Qiso_2022)) |
3597 |
|
charset_list = Viso_2022_charset_list; |
3598 |
|
|
3599 |
for (reg = 0; reg < 4; reg++) |
for (reg = 0; reg < 4; reg++) |
3600 |
r[reg] = -1; |
r[reg] = -1; |
3601 |
|
|
3602 |
while (found < 4) |
while (found < 4) |
3603 |
{ |
{ |
3604 |
ONE_MORE_CHAR (c); |
int id; |
3605 |
|
|
3606 |
|
c = *charbuf++; |
3607 |
if (c == '\n') |
if (c == '\n') |
3608 |
break; |
break; |
3609 |
|
charset = char_charset (c, charset_list, NULL); |
3610 |
charset = CHAR_CHARSET (c); |
id = CHARSET_ID (charset); |
3611 |
reg = CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset); |
reg = CODING_ISO_REQUEST (coding, id); |
3612 |
if (reg != CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION && r[reg] < 0) |
if (reg >= 0 && r[reg] < 0) |
3613 |
{ |
{ |
3614 |
found++; |
found++; |
3615 |
r[reg] = charset; |
r[reg] = id; |
3616 |
} |
} |
3617 |
} |
} |
3618 |
|
|
|
label_end_of_loop: |
|
3619 |
if (found) |
if (found) |
3620 |
{ |
{ |
3621 |
for (reg = 0; reg < 4; reg++) |
for (reg = 0; reg < 4; reg++) |
3622 |
if (r[reg] >= 0 |
if (r[reg] >= 0 |
3623 |
&& CODING_SPEC_ISO_DESIGNATION (coding, reg) != r[reg]) |
&& CODING_ISO_DESIGNATION (coding, reg) != r[reg]) |
3624 |
ENCODE_DESIGNATION (r[reg], reg, coding); |
ENCODE_DESIGNATION (CHARSET_FROM_ID (r[reg]), reg, coding); |
3625 |
} |
} |
3626 |
|
|
3627 |
return dst; |
return dst; |
3629 |
|
|
3630 |
/* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". */ |
/* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". */ |
3631 |
|
|
3632 |
static void |
static int |
3633 |
encode_coding_iso2022 (coding, source, destination, src_bytes, dst_bytes) |
encode_coding_iso_2022 (coding) |
3634 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
3635 |
{ |
{ |
3636 |
unsigned char *src = source; |
int multibytep = coding->dst_multibyte; |
3637 |
unsigned char *src_end = source + src_bytes; |
int *charbuf = coding->charbuf; |
3638 |
unsigned char *dst = destination; |
int *charbuf_end = charbuf + coding->charbuf_used; |
3639 |
unsigned char *dst_end = destination + dst_bytes; |
unsigned char *dst = coding->destination + coding->produced; |
3640 |
/* Since the maximum bytes produced by each loop is 20, we subtract 19 |
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
3641 |
from DST_END to assure overflow checking is necessary only at the |
int safe_room = 16; |
3642 |
head of loop. */ |
int bol_designation |
3643 |
unsigned char *adjusted_dst_end = dst_end - 19; |
= (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATE_AT_BOL |
3644 |
/* SRC_BASE remembers the start position in source in each loop. |
&& CODING_ISO_BOL (coding)); |
3645 |
The loop will be exited when there's not enough source text to |
int produced_chars = 0; |
3646 |
analyze multi-byte codes (within macro ONE_MORE_CHAR), or when |
Lisp_Object attrs, eol_type, charset_list; |
3647 |
there's not enough destination area to produce encoded codes |
int ascii_compatible; |
|
(within macro EMIT_BYTES). */ |
|
|
unsigned char *src_base; |
|
3648 |
int c; |
int c; |
3649 |
Lisp_Object translation_table; |
int preferred_charset_id = -1; |
|
Lisp_Object safe_chars; |
|
3650 |
|
|
3651 |
if (coding->flags & CODING_FLAG_ISO_SAFE) |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
3652 |
coding->mode |= CODING_MODE_INHIBIT_UNENCODABLE_CHAR; |
setup_iso_safe_charsets (attrs); |
3653 |
|
/* Charset list may have been changed. */ |
3654 |
|
charset_list = CODING_ATTR_CHARSET_LIST (attrs); \ |
3655 |
|
coding->safe_charsets = (char *) SDATA (CODING_ATTR_SAFE_CHARSETS(attrs)); |
3656 |
|
|
3657 |
safe_chars = coding_safe_chars (coding->symbol); |
ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)); |
|
|
|
|
if (NILP (Venable_character_translation)) |
|
|
translation_table = Qnil; |
|
|
else |
|
|
{ |
|
|
translation_table = coding->translation_table_for_encode; |
|
|
if (NILP (translation_table)) |
|
|
translation_table = Vstandard_translation_table_for_encode; |
|
|
} |
|
3658 |
|
|
3659 |
coding->consumed_char = 0; |
while (charbuf < charbuf_end) |
|
coding->errors = 0; |
|
|
while (1) |
|
3660 |
{ |
{ |
3661 |
src_base = src; |
ASSURE_DESTINATION (safe_room); |
3662 |
|
|
3663 |
if (dst >= (dst_bytes ? adjusted_dst_end : (src - 19))) |
if (bol_designation) |
3664 |
{ |
{ |
3665 |
coding->result = CODING_FINISH_INSUFFICIENT_DST; |
unsigned char *dst_prev = dst; |
|
break; |
|
|
} |
|
3666 |
|
|
|
if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL |
|
|
&& CODING_SPEC_ISO_BOL (coding)) |
|
|
{ |
|
3667 |
/* We have to produce designation sequences if any now. */ |
/* We have to produce designation sequences if any now. */ |
3668 |
dst = encode_designation_at_bol (coding, translation_table, |
dst = encode_designation_at_bol (coding, charbuf, charbuf_end, dst); |
3669 |
src, src_end, dst); |
bol_designation = 0; |
3670 |
CODING_SPEC_ISO_BOL (coding) = 0; |
/* We are sure that designation sequences are all ASCII bytes. */ |
3671 |
|
produced_chars += dst - dst_prev; |
3672 |
} |
} |
3673 |
|
|
3674 |
/* Check composition start and end. */ |
c = *charbuf++; |
|
if (coding->composing != COMPOSITION_DISABLED |
|
|
&& coding->cmp_data_start < coding->cmp_data->used) |
|
|
{ |
|
|
struct composition_data *cmp_data = coding->cmp_data; |
|
|
int *data = cmp_data->data + coding->cmp_data_start; |
|
|
int this_pos = cmp_data->char_offset + coding->consumed_char; |
|
3675 |
|
|
3676 |
if (coding->composing == COMPOSITION_RELATIVE) |
if (c < 0) |
3677 |
{ |
{ |
3678 |
if (this_pos == data[2]) |
/* Handle an annotation. */ |
3679 |
{ |
switch (*charbuf) |
|
ENCODE_COMPOSITION_END (coding, data); |
|
|
cmp_data = coding->cmp_data; |
|
|
data = cmp_data->data + coding->cmp_data_start; |
|
|
} |
|
|
} |
|
|
else if (COMPOSING_P (coding)) |
|
|
{ |
|
|
/* COMPOSITION_WITH_ALTCHARS or COMPOSITION_WITH_RULE_ALTCHAR */ |
|
|
if (coding->cmp_data_index == coding->cmp_data_start + data[0]) |
|
|
/* We have consumed components of the composition. |
|
|
What follows in SRC is the composition's base |
|
|
text. */ |
|
|
ENCODE_COMPOSITION_FAKE_START (coding); |
|
|
else |
|
|
{ |
|
|
int c = cmp_data->data[coding->cmp_data_index++]; |
|
|
if (coding->composition_rule_follows) |
|
|
{ |
|
|
ENCODE_COMPOSITION_RULE (c); |
|
|
coding->composition_rule_follows = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR |
|
|
&& ! CODING_SAFE_CHAR_P (safe_chars, c)) |
|
|
ENCODE_UNSAFE_CHARACTER (c); |
|
|
else |
|
|
ENCODE_ISO_CHARACTER (c); |
|
|
if (coding->composing == COMPOSITION_WITH_RULE_ALTCHARS) |
|
|
coding->composition_rule_follows = 1; |
|
|
} |
|
|
continue; |
|
|
} |
|
|
} |
|
|
if (!COMPOSING_P (coding)) |
|
3680 |
{ |
{ |
3681 |
if (this_pos == data[1]) |
case CODING_ANNOTATE_COMPOSITION_MASK: |
3682 |
{ |
/* Not yet implemented. */ |
3683 |
ENCODE_COMPOSITION_START (coding, data); |
break; |
3684 |
continue; |
case CODING_ANNOTATE_CHARSET_MASK: |
3685 |
} |
preferred_charset_id = charbuf[3]; |
3686 |
|
if (preferred_charset_id >= 0 |
3687 |
|
&& NILP (Fmemq (make_number (preferred_charset_id), |
3688 |
|
charset_list))) |
3689 |
|
preferred_charset_id = -1; |
3690 |
|
break; |
3691 |
|
default: |
3692 |
|
abort (); |
3693 |
} |
} |
3694 |
|
charbuf += -c - 1; |
3695 |
|
continue; |
3696 |
} |
} |
3697 |
|
|
|
ONE_MORE_CHAR (c); |
|
|
|
|
3698 |
/* Now encode the character C. */ |
/* Now encode the character C. */ |
3699 |
if (c < 0x20 || c == 0x7F) |
if (c < 0x20 || c == 0x7F) |
3700 |
{ |
{ |
3701 |
if (c == '\r') |
if (c == '\n' |
3702 |
|
|| (c == '\r' && EQ (eol_type, Qmac))) |
3703 |
{ |
{ |
3704 |
if (! (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)) |
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_RESET_AT_EOL) |
3705 |
|
ENCODE_RESET_PLANE_AND_REGISTER (); |
3706 |
|
if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_INIT_AT_BOL) |
3707 |
{ |
{ |
3708 |
if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL) |
int i; |
3709 |
ENCODE_RESET_PLANE_AND_REGISTER; |
|
3710 |
*dst++ = c; |
for (i = 0; i < 4; i++) |
3711 |
continue; |
CODING_ISO_DESIGNATION (coding, i) |
3712 |
|
= CODING_ISO_INITIAL (coding, i); |
3713 |
} |
} |
3714 |
/* fall down to treat '\r' as '\n' ... */ |
bol_designation |
3715 |
c = '\n'; |
= CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_DESIGNATE_AT_BOL; |
|
} |
|
|
if (c == '\n') |
|
|
{ |
|
|
if (coding->flags & CODING_FLAG_ISO_RESET_AT_EOL) |
|
|
ENCODE_RESET_PLANE_AND_REGISTER; |
|
|
if (coding->flags & CODING_FLAG_ISO_INIT_AT_BOL) |
|
|
bcopy (coding->spec.iso2022.initial_designation, |
|
|
coding->spec.iso2022.current_designation, |
|
|
sizeof coding->spec.iso2022.initial_designation); |
|
|
if (coding->eol_type == CODING_EOL_LF |
|
|
|| coding->eol_type == CODING_EOL_UNDECIDED) |
|
|
*dst++ = ISO_CODE_LF; |
|
|
else if (coding->eol_type == CODING_EOL_CRLF) |
|
|
*dst++ = ISO_CODE_CR, *dst++ = ISO_CODE_LF; |
|
|
else |
|
|
*dst++ = ISO_CODE_CR; |
|
|
CODING_SPEC_ISO_BOL (coding) = 1; |
|
3716 |
} |
} |
3717 |
|
else if (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_RESET_AT_CNTL) |
3718 |
|
ENCODE_RESET_PLANE_AND_REGISTER (); |
3719 |
|
EMIT_ONE_ASCII_BYTE (c); |
3720 |
|
} |
3721 |
|
else if (ASCII_CHAR_P (c)) |
3722 |
|
{ |
3723 |
|
if (ascii_compatible) |
3724 |
|
EMIT_ONE_ASCII_BYTE (c); |
3725 |
else |
else |
3726 |
{ |
{ |
3727 |
if (coding->flags & CODING_FLAG_ISO_RESET_AT_CNTL) |
struct charset *charset = CHARSET_FROM_ID (charset_ascii); |
3728 |
ENCODE_RESET_PLANE_AND_REGISTER; |
ENCODE_ISO_CHARACTER (charset, c); |
|
*dst++ = c; |
|
3729 |
} |
} |
3730 |
} |
} |
3731 |
else if (ASCII_BYTE_P (c)) |
else if (CHAR_BYTE8_P (c)) |
|
ENCODE_ISO_CHARACTER (c); |
|
|
else if (SINGLE_BYTE_CHAR_P (c)) |
|
3732 |
{ |
{ |
3733 |
*dst++ = c; |
c = CHAR_TO_BYTE8 (c); |
3734 |
coding->errors++; |
EMIT_ONE_BYTE (c); |
3735 |
} |
} |
|
else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR |
|
|
&& ! CODING_SAFE_CHAR_P (safe_chars, c)) |
|
|
ENCODE_UNSAFE_CHARACTER (c); |
|
3736 |
else |
else |
3737 |
ENCODE_ISO_CHARACTER (c); |
{ |
3738 |
|
struct charset *charset; |
3739 |
|
|
3740 |
coding->consumed_char++; |
if (preferred_charset_id >= 0) |
3741 |
|
{ |
3742 |
|
charset = CHARSET_FROM_ID (preferred_charset_id); |
3743 |
|
if (! CHAR_CHARSET_P (c, charset)) |
3744 |
|
charset = char_charset (c, charset_list, NULL); |
3745 |
|
} |
3746 |
|
else |
3747 |
|
charset = char_charset (c, charset_list, NULL); |
3748 |
|
if (!charset) |
3749 |
|
{ |
3750 |
|
if (coding->mode & CODING_MODE_SAFE_ENCODING) |
3751 |
|
{ |
3752 |
|
c = CODING_INHIBIT_CHARACTER_SUBSTITUTION; |
3753 |
|
charset = CHARSET_FROM_ID (charset_ascii); |
3754 |
|
} |
3755 |
|
else |
3756 |
|
{ |
3757 |
|
c = coding->default_char; |
3758 |
|
charset = char_charset (c, charset_list, NULL); |
3759 |
|
} |
3760 |
|
} |
3761 |
|
ENCODE_ISO_CHARACTER (charset, c); |
3762 |
|
} |
3763 |
} |
} |
3764 |
|
|
3765 |
label_end_of_loop: |
if (coding->mode & CODING_MODE_LAST_BLOCK |
3766 |
coding->consumed = src_base - source; |
&& CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_RESET_AT_EOL) |
3767 |
coding->produced = coding->produced_char = dst - destination; |
{ |
3768 |
|
ASSURE_DESTINATION (safe_room); |
3769 |
|
ENCODE_RESET_PLANE_AND_REGISTER (); |
3770 |
|
} |
3771 |
|
coding->result = CODING_RESULT_SUCCESS; |
3772 |
|
CODING_ISO_BOL (coding) = bol_designation; |
3773 |
|
coding->produced_char += produced_chars; |
3774 |
|
coding->produced = dst - coding->destination; |
3775 |
|
return 0; |
3776 |
} |
} |
3777 |
|
|
3778 |
|
|
3779 |
/*** 4. SJIS and BIG5 handlers ***/ |
/*** 8,9. SJIS and BIG5 handlers ***/ |
3780 |
|
|
3781 |
/* Although SJIS and BIG5 are not ISO coding systems, they are used |
/* Although SJIS and BIG5 are not ISO's coding system, they are used |
3782 |
quite widely. So, for the moment, Emacs supports them in the bare |
quite widely. So, for the moment, Emacs supports them in the bare |
3783 |
C code. But, in the future, they may be supported only by CCL. */ |
C code. But, in the future, they may be supported only by CCL. */ |
3784 |
|
|
3787 |
as is. A character of charset katakana-jisx0201 is encoded by |
as is. A character of charset katakana-jisx0201 is encoded by |
3788 |
"position-code + 0x80". A character of charset japanese-jisx0208 |
"position-code + 0x80". A character of charset japanese-jisx0208 |
3789 |
is encoded in 2-byte but two position-codes are divided and shifted |
is encoded in 2-byte but two position-codes are divided and shifted |
3790 |
so that it fits in the range below. |
so that it fit in the range below. |
3791 |
|
|
3792 |
--- CODE RANGE of SJIS --- |
--- CODE RANGE of SJIS --- |
3793 |
(character set) (range) |
(character set) (range) |
3794 |
ASCII 0x00 .. 0x7F |
ASCII 0x00 .. 0x7F |
3795 |
KATAKANA-JISX0201 0xA1 .. 0xDF |
KATAKANA-JISX0201 0xA0 .. 0xDF |
3796 |
JISX0208 (1st byte) 0x81 .. 0x9F and 0xE0 .. 0xEF |
JISX0208 (1st byte) 0x81 .. 0x9F and 0xE0 .. 0xEF |
3797 |
(2nd byte) 0x40 .. 0x7E and 0x80 .. 0xFC |
(2nd byte) 0x40 .. 0x7E and 0x80 .. 0xFC |
3798 |
------------------------------- |
------------------------------- |
3801 |
|
|
3802 |
/* BIG5 is a coding system encoding two character sets: ASCII and |
/* BIG5 is a coding system encoding two character sets: ASCII and |
3803 |
Big5. An ASCII character is encoded as is. Big5 is a two-byte |
Big5. An ASCII character is encoded as is. Big5 is a two-byte |
3804 |
character set and is encoded in two bytes. |
character set and is encoded in two-byte. |
3805 |
|
|
3806 |
--- CODE RANGE of BIG5 --- |
--- CODE RANGE of BIG5 --- |
3807 |
(character set) (range) |
(character set) (range) |
3810 |
(2nd byte) 0x40 .. 0x7E and 0xA1 .. 0xFE |
(2nd byte) 0x40 .. 0x7E and 0xA1 .. 0xFE |
3811 |
-------------------------- |
-------------------------- |
3812 |
|
|
3813 |
Since the number of characters in Big5 is larger than maximum |
*/ |
|
characters in Emacs' charset (96x96), it can't be handled as one |
|
|
charset. So, in Emacs, Big5 is divided into two: `charset-big5-1' |
|
|
and `charset-big5-2'. Both are DIMENSION2 and CHARS94. The former |
|
|
contains frequently used characters and the latter contains less |
|
|
frequently used characters. */ |
|
|
|
|
|
/* Macros to decode or encode a character of Big5 in BIG5. B1 and B2 |
|
|
are the 1st and 2nd position-codes of Big5 in BIG5 coding system. |
|
|
C1 and C2 are the 1st and 2nd position-codes of Emacs' internal |
|
|
format. CHARSET is `charset_big5_1' or `charset_big5_2'. */ |
|
|
|
|
|
/* Number of Big5 characters which have the same code in 1st byte. */ |
|
|
#define BIG5_SAME_ROW (0xFF - 0xA1 + 0x7F - 0x40) |
|
|
|
|
|
#define DECODE_BIG5(b1, b2, charset, c1, c2) \ |
|
|
do { \ |
|
|
unsigned int temp \ |
|
|
= (b1 - 0xA1) * BIG5_SAME_ROW + b2 - (b2 < 0x7F ? 0x40 : 0x62); \ |
|
|
if (b1 < 0xC9) \ |
|
|
charset = charset_big5_1; \ |
|
|
else \ |
|
|
{ \ |
|
|
charset = charset_big5_2; \ |
|
|
temp -= (0xC9 - 0xA1) * BIG5_SAME_ROW; \ |
|
|
} \ |
|
|
c1 = temp / (0xFF - 0xA1) + 0x21; \ |
|
|
c2 = temp % (0xFF - 0xA1) + 0x21; \ |
|
|
} while (0) |
|
|
|
|
|
#define ENCODE_BIG5(charset, c1, c2, b1, b2) \ |
|
|
do { \ |
|
|
unsigned int temp = (c1 - 0x21) * (0xFF - 0xA1) + (c2 - 0x21); \ |
|
|
if (charset == charset_big5_2) \ |
|
|
temp += BIG5_SAME_ROW * (0xC9 - 0xA1); \ |
|
|
b1 = temp / BIG5_SAME_ROW + 0xA1; \ |
|
|
b2 = temp % BIG5_SAME_ROW; \ |
|
|
b2 += b2 < 0x3F ? 0x40 : 0x62; \ |
|
|
} while (0) |
|
3814 |
|
|
3815 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
3816 |
Check if a text is encoded in SJIS. If it is, return |
Check if a text is encoded in SJIS. If it is, return |
3817 |
CODING_CATEGORY_MASK_SJIS, else return 0. */ |
CATEGORY_MASK_SJIS, else return 0. */ |
3818 |
|
|
3819 |
static int |
static int |
3820 |
detect_coding_sjis (src, src_end, multibytep) |
detect_coding_sjis (coding, detect_info) |
3821 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
3822 |
int multibytep; |
struct coding_detection_info *detect_info; |
3823 |
{ |
{ |
3824 |
|
const unsigned char *src = coding->source, *src_base = src; |
3825 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
3826 |
|
int multibytep = coding->src_multibyte; |
3827 |
|
int consumed_chars = 0; |
3828 |
|
int found = 0; |
3829 |
int c; |
int c; |
3830 |
/* Dummy for ONE_MORE_BYTE. */ |
int incomplete; |
3831 |
struct coding_system dummy_coding; |
|
3832 |
struct coding_system *coding = &dummy_coding; |
detect_info->checked |= CATEGORY_MASK_SJIS; |
3833 |
|
/* A coding system of this category is always ASCII compatible. */ |
3834 |
|
src += coding->head_ascii; |
3835 |
|
|
3836 |
while (1) |
while (1) |
3837 |
{ |
{ |
3838 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
incomplete = 0; |
3839 |
|
ONE_MORE_BYTE (c); |
3840 |
|
incomplete = 1; |
3841 |
if (c < 0x80) |
if (c < 0x80) |
3842 |
continue; |
continue; |
3843 |
if (c == 0x80 || c == 0xA0 || c > 0xEF) |
if ((c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xEF)) |
|
return 0; |
|
|
if (c <= 0x9F || c >= 0xE0) |
|
3844 |
{ |
{ |
3845 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
3846 |
if (c < 0x40 || c == 0x7F || c > 0xFC) |
if (c < 0x40 || c == 0x7F || c > 0xFC) |
3847 |
return 0; |
break; |
3848 |
|
found = CATEGORY_MASK_SJIS; |
3849 |
} |
} |
3850 |
|
else if (c >= 0xA0 && c < 0xE0) |
3851 |
|
found = CATEGORY_MASK_SJIS; |
3852 |
|
else |
3853 |
|
break; |
3854 |
|
} |
3855 |
|
detect_info->rejected |= CATEGORY_MASK_SJIS; |
3856 |
|
return 0; |
3857 |
|
|
3858 |
|
no_more_source: |
3859 |
|
if (incomplete && coding->mode & CODING_MODE_LAST_BLOCK) |
3860 |
|
{ |
3861 |
|
detect_info->rejected |= CATEGORY_MASK_SJIS; |
3862 |
|
return 0; |
3863 |
} |
} |
3864 |
label_end_of_loop: |
detect_info->found |= found; |
3865 |
return CODING_CATEGORY_MASK_SJIS; |
return 1; |
3866 |
} |
} |
3867 |
|
|
3868 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
3869 |
Check if a text is encoded in BIG5. If it is, return |
Check if a text is encoded in BIG5. If it is, return |
3870 |
CODING_CATEGORY_MASK_BIG5, else return 0. */ |
CATEGORY_MASK_BIG5, else return 0. */ |
3871 |
|
|
3872 |
static int |
static int |
3873 |
detect_coding_big5 (src, src_end, multibytep) |
detect_coding_big5 (coding, detect_info) |
3874 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
3875 |
int multibytep; |
struct coding_detection_info *detect_info; |
3876 |
{ |
{ |
3877 |
|
const unsigned char *src = coding->source, *src_base = src; |
3878 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
3879 |
|
int multibytep = coding->src_multibyte; |
3880 |
|
int consumed_chars = 0; |
3881 |
|
int found = 0; |
3882 |
int c; |
int c; |
3883 |
/* Dummy for ONE_MORE_BYTE. */ |
int incomplete; |
3884 |
struct coding_system dummy_coding; |
|
3885 |
struct coding_system *coding = &dummy_coding; |
detect_info->checked |= CATEGORY_MASK_BIG5; |
3886 |
|
/* A coding system of this category is always ASCII compatible. */ |
3887 |
|
src += coding->head_ascii; |
3888 |
|
|
3889 |
while (1) |
while (1) |
3890 |
{ |
{ |
3891 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
incomplete = 0; |
3892 |
|
ONE_MORE_BYTE (c); |
3893 |
|
incomplete = 1; |
3894 |
if (c < 0x80) |
if (c < 0x80) |
3895 |
continue; |
continue; |
3896 |
if (c < 0xA1 || c > 0xFE) |
if (c >= 0xA1) |
3897 |
return 0; |
{ |
3898 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
ONE_MORE_BYTE (c); |
3899 |
if (c < 0x40 || (c > 0x7F && c < 0xA1) || c > 0xFE) |
if (c < 0x40 || (c >= 0x7F && c <= 0xA0)) |
3900 |
return 0; |
return 0; |
3901 |
|
found = CATEGORY_MASK_BIG5; |
3902 |
|
} |
3903 |
|
else |
3904 |
|
break; |
3905 |
} |
} |
3906 |
label_end_of_loop: |
detect_info->rejected |= CATEGORY_MASK_BIG5; |
3907 |
return CODING_CATEGORY_MASK_BIG5; |
return 0; |
|
} |
|
3908 |
|
|
3909 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
no_more_source: |
3910 |
Check if a text is encoded in UTF-8. If it is, return |
if (incomplete && coding->mode & CODING_MODE_LAST_BLOCK) |
3911 |
CODING_CATEGORY_MASK_UTF_8, else return 0. */ |
{ |
3912 |
|
detect_info->rejected |= CATEGORY_MASK_BIG5; |
3913 |
|
return 0; |
3914 |
|
} |
3915 |
|
detect_info->found |= found; |
3916 |
|
return 1; |
3917 |
|
} |
3918 |
|
|
3919 |
#define UTF_8_1_OCTET_P(c) ((c) < 0x80) |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". |
3920 |
#define UTF_8_EXTRA_OCTET_P(c) (((c) & 0xC0) == 0x80) |
If SJIS_P is 1, decode SJIS text, else decode BIG5 test. */ |
|
#define UTF_8_2_OCTET_LEADING_P(c) (((c) & 0xE0) == 0xC0) |
|
|
#define UTF_8_3_OCTET_LEADING_P(c) (((c) & 0xF0) == 0xE0) |
|
|
#define UTF_8_4_OCTET_LEADING_P(c) (((c) & 0xF8) == 0xF0) |
|
|
#define UTF_8_5_OCTET_LEADING_P(c) (((c) & 0xFC) == 0xF8) |
|
|
#define UTF_8_6_OCTET_LEADING_P(c) (((c) & 0xFE) == 0xFC) |
|
3921 |
|
|
3922 |
static int |
static void |
3923 |
detect_coding_utf_8 (src, src_end, multibytep) |
decode_coding_sjis (coding) |
3924 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
|
int multibytep; |
|
3925 |
{ |
{ |
3926 |
unsigned char c; |
const unsigned char *src = coding->source + coding->consumed; |
3927 |
int seq_maybe_bytes; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
3928 |
/* Dummy for ONE_MORE_BYTE. */ |
const unsigned char *src_base; |
3929 |
struct coding_system dummy_coding; |
int *charbuf = coding->charbuf; |
3930 |
struct coding_system *coding = &dummy_coding; |
int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH; |
3931 |
|
int consumed_chars = 0, consumed_chars_base; |
3932 |
|
int multibytep = coding->src_multibyte; |
3933 |
|
struct charset *charset_roman, *charset_kanji, *charset_kana; |
3934 |
|
Lisp_Object attrs, eol_type, charset_list, val; |
3935 |
|
int char_offset = coding->produced_char; |
3936 |
|
int last_offset = char_offset; |
3937 |
|
int last_id = charset_ascii; |
3938 |
|
|
3939 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
3940 |
|
|
3941 |
|
val = charset_list; |
3942 |
|
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
3943 |
|
charset_kana = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
3944 |
|
charset_kanji = CHARSET_FROM_ID (XINT (XCAR (val))); |
3945 |
|
|
3946 |
while (1) |
while (1) |
3947 |
{ |
{ |
3948 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
int c, c1; |
|
if (UTF_8_1_OCTET_P (c)) |
|
|
continue; |
|
|
else if (UTF_8_2_OCTET_LEADING_P (c)) |
|
|
seq_maybe_bytes = 1; |
|
|
else if (UTF_8_3_OCTET_LEADING_P (c)) |
|
|
seq_maybe_bytes = 2; |
|
|
else if (UTF_8_4_OCTET_LEADING_P (c)) |
|
|
seq_maybe_bytes = 3; |
|
|
else if (UTF_8_5_OCTET_LEADING_P (c)) |
|
|
seq_maybe_bytes = 4; |
|
|
else if (UTF_8_6_OCTET_LEADING_P (c)) |
|
|
seq_maybe_bytes = 5; |
|
|
else |
|
|
return 0; |
|
|
|
|
|
do |
|
|
{ |
|
|
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
|
|
if (!UTF_8_EXTRA_OCTET_P (c)) |
|
|
return 0; |
|
|
seq_maybe_bytes--; |
|
|
} |
|
|
while (seq_maybe_bytes > 0); |
|
|
} |
|
|
|
|
|
label_end_of_loop: |
|
|
return CODING_CATEGORY_MASK_UTF_8; |
|
|
} |
|
|
|
|
|
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
|
|
Check if a text is encoded in UTF-16 Big Endian (endian == 1) or |
|
|
Little Endian (otherwise). If it is, return |
|
|
CODING_CATEGORY_MASK_UTF_16_BE or CODING_CATEGORY_MASK_UTF_16_LE, |
|
|
else return 0. */ |
|
3949 |
|
|
3950 |
#define UTF_16_INVALID_P(val) \ |
src_base = src; |
3951 |
(((val) == 0xFFFE) \ |
consumed_chars_base = consumed_chars; |
|
|| ((val) == 0xFFFF)) |
|
3952 |
|
|
3953 |
#define UTF_16_HIGH_SURROGATE_P(val) \ |
if (charbuf >= charbuf_end) |
3954 |
(((val) & 0xD800) == 0xD800) |
break; |
3955 |
|
|
3956 |
#define UTF_16_LOW_SURROGATE_P(val) \ |
ONE_MORE_BYTE (c); |
|
(((val) & 0xDC00) == 0xDC00) |
|
3957 |
|
|
3958 |
static int |
if (c == '\r') |
3959 |
detect_coding_utf_16 (src, src_end, multibytep) |
{ |
3960 |
unsigned char *src, *src_end; |
if (EQ (eol_type, Qdos)) |
3961 |
int multibytep; |
{ |
3962 |
{ |
if (src == src_end) |
3963 |
unsigned char c1, c2; |
{ |
3964 |
/* Dummy for ONE_MORE_BYTE_CHECK_MULTIBYTE. */ |
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
3965 |
struct coding_system dummy_coding; |
goto no_more_source; |
3966 |
struct coding_system *coding = &dummy_coding; |
} |
3967 |
|
if (*src == '\n') |
3968 |
|
ONE_MORE_BYTE (c); |
3969 |
|
} |
3970 |
|
else if (EQ (eol_type, Qmac)) |
3971 |
|
c = '\n'; |
3972 |
|
} |
3973 |
|
else |
3974 |
|
{ |
3975 |
|
struct charset *charset; |
3976 |
|
|
3977 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c1, multibytep); |
if (c < 0x80) |
3978 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c2, multibytep); |
charset = charset_roman; |
3979 |
|
else |
3980 |
|
{ |
3981 |
|
if (c >= 0xF0) |
3982 |
|
goto invalid_code; |
3983 |
|
if (c < 0xA0 || c >= 0xE0) |
3984 |
|
{ |
3985 |
|
/* SJIS -> JISX0208 */ |
3986 |
|
ONE_MORE_BYTE (c1); |
3987 |
|
if (c1 < 0x40 || c1 == 0x7F || c1 > 0xFC) |
3988 |
|
goto invalid_code; |
3989 |
|
c = (c << 8) | c1; |
3990 |
|
SJIS_TO_JIS (c); |
3991 |
|
charset = charset_kanji; |
3992 |
|
} |
3993 |
|
else if (c > 0xA0) |
3994 |
|
{ |
3995 |
|
/* SJIS -> JISX0201-Kana */ |
3996 |
|
c &= 0x7F; |
3997 |
|
charset = charset_kana; |
3998 |
|
} |
3999 |
|
else |
4000 |
|
goto invalid_code; |
4001 |
|
} |
4002 |
|
if (charset->id != charset_ascii |
4003 |
|
&& last_id != charset->id) |
4004 |
|
{ |
4005 |
|
if (last_id != charset_ascii) |
4006 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4007 |
|
last_id = charset->id; |
4008 |
|
last_offset = char_offset; |
4009 |
|
} |
4010 |
|
CODING_DECODE_CHAR (coding, src, src_base, src_end, charset, c, c); |
4011 |
|
} |
4012 |
|
*charbuf++ = c; |
4013 |
|
char_offset++; |
4014 |
|
continue; |
4015 |
|
|
4016 |
if ((c1 == 0xFF) && (c2 == 0xFE)) |
invalid_code: |
4017 |
return CODING_CATEGORY_MASK_UTF_16_LE; |
src = src_base; |
4018 |
else if ((c1 == 0xFE) && (c2 == 0xFF)) |
consumed_chars = consumed_chars_base; |
4019 |
return CODING_CATEGORY_MASK_UTF_16_BE; |
ONE_MORE_BYTE (c); |
4020 |
|
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
4021 |
|
char_offset++; |
4022 |
|
coding->errors++; |
4023 |
|
} |
4024 |
|
|
4025 |
label_end_of_loop: |
no_more_source: |
4026 |
return 0; |
if (last_id != charset_ascii) |
4027 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4028 |
|
coding->consumed_char += consumed_chars_base; |
4029 |
|
coding->consumed = src_base - coding->source; |
4030 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
4031 |
} |
} |
4032 |
|
|
|
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". |
|
|
If SJIS_P is 1, decode SJIS text, else decode BIG5 test. */ |
|
|
|
|
4033 |
static void |
static void |
4034 |
decode_coding_sjis_big5 (coding, source, destination, |
decode_coding_big5 (coding) |
|
src_bytes, dst_bytes, sjis_p) |
|
4035 |
struct coding_system *coding; |
struct coding_system *coding; |
4036 |
unsigned char *source, *destination; |
{ |
4037 |
int src_bytes, dst_bytes; |
const unsigned char *src = coding->source + coding->consumed; |
4038 |
int sjis_p; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
4039 |
{ |
const unsigned char *src_base; |
4040 |
unsigned char *src = source; |
int *charbuf = coding->charbuf; |
4041 |
unsigned char *src_end = source + src_bytes; |
int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH; |
4042 |
unsigned char *dst = destination; |
int consumed_chars = 0, consumed_chars_base; |
4043 |
unsigned char *dst_end = destination + dst_bytes; |
int multibytep = coding->src_multibyte; |
4044 |
/* SRC_BASE remembers the start position in source in each loop. |
struct charset *charset_roman, *charset_big5; |
4045 |
The loop will be exited when there's not enough source code |
Lisp_Object attrs, eol_type, charset_list, val; |
4046 |
(within macro ONE_MORE_BYTE), or when there's not enough |
int char_offset = coding->produced_char; |
4047 |
destination area to produce a character (within macro |
int last_offset = char_offset; |
4048 |
EMIT_CHAR). */ |
int last_id = charset_ascii; |
4049 |
unsigned char *src_base; |
|
4050 |
Lisp_Object translation_table; |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4051 |
|
val = charset_list; |
4052 |
if (NILP (Venable_character_translation)) |
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
4053 |
translation_table = Qnil; |
charset_big5 = CHARSET_FROM_ID (XINT (XCAR (val))); |
|
else |
|
|
{ |
|
|
translation_table = coding->translation_table_for_decode; |
|
|
if (NILP (translation_table)) |
|
|
translation_table = Vstandard_translation_table_for_decode; |
|
|
} |
|
4054 |
|
|
|
coding->produced_char = 0; |
|
4055 |
while (1) |
while (1) |
4056 |
{ |
{ |
4057 |
int c, charset, c1, c2; |
int c, c1; |
4058 |
|
|
4059 |
src_base = src; |
src_base = src; |
4060 |
ONE_MORE_BYTE (c1); |
consumed_chars_base = consumed_chars; |
4061 |
|
|
4062 |
|
if (charbuf >= charbuf_end) |
4063 |
|
break; |
4064 |
|
|
4065 |
|
ONE_MORE_BYTE (c); |
4066 |
|
|
4067 |
if (c1 < 0x80) |
if (c == '\r') |
4068 |
{ |
{ |
4069 |
charset = CHARSET_ASCII; |
if (EQ (eol_type, Qdos)) |
|
if (c1 < 0x20) |
|
4070 |
{ |
{ |
4071 |
if (c1 == '\r') |
if (src == src_end) |
|
{ |
|
|
if (coding->eol_type == CODING_EOL_CRLF) |
|
|
{ |
|
|
ONE_MORE_BYTE (c2); |
|
|
if (c2 == '\n') |
|
|
c1 = c2; |
|
|
else |
|
|
/* To process C2 again, SRC is subtracted by 1. */ |
|
|
src--; |
|
|
} |
|
|
else if (coding->eol_type == CODING_EOL_CR) |
|
|
c1 = '\n'; |
|
|
} |
|
|
else if (c1 == '\n' |
|
|
&& (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
|
|
&& (coding->eol_type == CODING_EOL_CR |
|
|
|| coding->eol_type == CODING_EOL_CRLF)) |
|
4072 |
{ |
{ |
4073 |
coding->result = CODING_FINISH_INCONSISTENT_EOL; |
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
4074 |
goto label_end_of_loop; |
goto no_more_source; |
4075 |
} |
} |
4076 |
|
if (*src == '\n') |
4077 |
|
ONE_MORE_BYTE (c); |
4078 |
} |
} |
4079 |
|
else if (EQ (eol_type, Qmac)) |
4080 |
|
c = '\n'; |
4081 |
} |
} |
4082 |
else |
else |
4083 |
{ |
{ |
4084 |
if (sjis_p) |
struct charset *charset; |
4085 |
{ |
if (c < 0x80) |
4086 |
if (c1 == 0x80 || c1 == 0xA0 || c1 > 0xEF) |
charset = charset_roman; |
|
goto label_invalid_code; |
|
|
if (c1 <= 0x9F || c1 >= 0xE0) |
|
|
{ |
|
|
/* SJIS -> JISX0208 */ |
|
|
ONE_MORE_BYTE (c2); |
|
|
if (c2 < 0x40 || c2 == 0x7F || c2 > 0xFC) |
|
|
goto label_invalid_code; |
|
|
DECODE_SJIS (c1, c2, c1, c2); |
|
|
charset = charset_jisx0208; |
|
|
} |
|
|
else |
|
|
/* SJIS -> JISX0201-Kana */ |
|
|
charset = charset_katakana_jisx0201; |
|
|
} |
|
4087 |
else |
else |
4088 |
{ |
{ |
4089 |
/* BIG5 -> Big5 */ |
/* BIG5 -> Big5 */ |
4090 |
if (c1 < 0xA0 || c1 > 0xFE) |
if (c < 0xA1 || c > 0xFE) |
4091 |
goto label_invalid_code; |
goto invalid_code; |
4092 |
ONE_MORE_BYTE (c2); |
ONE_MORE_BYTE (c1); |
4093 |
if (c2 < 0x40 || (c2 > 0x7E && c2 < 0xA1) || c2 > 0xFE) |
if (c1 < 0x40 || (c1 > 0x7E && c1 < 0xA1) || c1 > 0xFE) |
4094 |
goto label_invalid_code; |
goto invalid_code; |
4095 |
DECODE_BIG5 (c1, c2, charset, c1, c2); |
c = c << 8 | c1; |
4096 |
|
charset = charset_big5; |
4097 |
|
} |
4098 |
|
if (charset->id != charset_ascii |
4099 |
|
&& last_id != charset->id) |
4100 |
|
{ |
4101 |
|
if (last_id != charset_ascii) |
4102 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4103 |
|
last_id = charset->id; |
4104 |
|
last_offset = char_offset; |
4105 |
} |
} |
4106 |
|
CODING_DECODE_CHAR (coding, src, src_base, src_end, charset, c, c); |
4107 |
} |
} |
4108 |
|
|
4109 |
c = DECODE_ISO_CHARACTER (charset, c1, c2); |
*charbuf++ = c; |
4110 |
EMIT_CHAR (c); |
char_offset++; |
4111 |
continue; |
continue; |
4112 |
|
|
4113 |
label_invalid_code: |
invalid_code: |
|
coding->errors++; |
|
4114 |
src = src_base; |
src = src_base; |
4115 |
c = *src++; |
consumed_chars = consumed_chars_base; |
4116 |
EMIT_CHAR (c); |
ONE_MORE_BYTE (c); |
4117 |
|
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
4118 |
|
char_offset++; |
4119 |
|
coding->errors++; |
4120 |
} |
} |
4121 |
|
|
4122 |
label_end_of_loop: |
no_more_source: |
4123 |
coding->consumed = coding->consumed_char = src_base - source; |
if (last_id != charset_ascii) |
4124 |
coding->produced = dst - destination; |
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4125 |
return; |
coding->consumed_char += consumed_chars_base; |
4126 |
|
coding->consumed = src_base - coding->source; |
4127 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
4128 |
} |
} |
4129 |
|
|
4130 |
/* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `encode_coding_XXX ()' functions". |
4135 |
charsets are produced without any encoding. If SJIS_P is 1, encode |
charsets are produced without any encoding. If SJIS_P is 1, encode |
4136 |
SJIS text, else encode BIG5 text. */ |
SJIS text, else encode BIG5 text. */ |
4137 |
|
|
4138 |
static void |
static int |
4139 |
encode_coding_sjis_big5 (coding, source, destination, |
encode_coding_sjis (coding) |
|
src_bytes, dst_bytes, sjis_p) |
|
4140 |
struct coding_system *coding; |
struct coding_system *coding; |
4141 |
unsigned char *source, *destination; |
{ |
4142 |
int src_bytes, dst_bytes; |
int multibytep = coding->dst_multibyte; |
4143 |
int sjis_p; |
int *charbuf = coding->charbuf; |
4144 |
{ |
int *charbuf_end = charbuf + coding->charbuf_used; |
4145 |
unsigned char *src = source; |
unsigned char *dst = coding->destination + coding->produced; |
4146 |
unsigned char *src_end = source + src_bytes; |
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
4147 |
unsigned char *dst = destination; |
int safe_room = 4; |
4148 |
unsigned char *dst_end = destination + dst_bytes; |
int produced_chars = 0; |
4149 |
/* SRC_BASE remembers the start position in source in each loop. |
Lisp_Object attrs, eol_type, charset_list, val; |
4150 |
The loop will be exited when there's not enough source text to |
int ascii_compatible; |
4151 |
analyze multi-byte codes (within macro ONE_MORE_CHAR), or when |
struct charset *charset_roman, *charset_kanji, *charset_kana; |
4152 |
there's not enough destination area to produce encoded codes |
int c; |
|
(within macro EMIT_BYTES). */ |
|
|
unsigned char *src_base; |
|
|
Lisp_Object translation_table; |
|
4153 |
|
|
4154 |
if (NILP (Venable_character_translation)) |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4155 |
translation_table = Qnil; |
val = charset_list; |
4156 |
else |
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
4157 |
{ |
charset_kana = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
4158 |
translation_table = coding->translation_table_for_encode; |
charset_kanji = CHARSET_FROM_ID (XINT (XCAR (val))); |
|
if (NILP (translation_table)) |
|
|
translation_table = Vstandard_translation_table_for_encode; |
|
|
} |
|
4159 |
|
|
4160 |
while (1) |
ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)); |
|
{ |
|
|
int c, charset, c1, c2; |
|
|
|
|
|
src_base = src; |
|
|
ONE_MORE_CHAR (c); |
|
4161 |
|
|
4162 |
|
while (charbuf < charbuf_end) |
4163 |
|
{ |
4164 |
|
ASSURE_DESTINATION (safe_room); |
4165 |
|
c = *charbuf++; |
4166 |
/* Now encode the character C. */ |
/* Now encode the character C. */ |
4167 |
if (SINGLE_BYTE_CHAR_P (c)) |
if (ASCII_CHAR_P (c) && ascii_compatible) |
4168 |
|
EMIT_ONE_ASCII_BYTE (c); |
4169 |
|
else if (CHAR_BYTE8_P (c)) |
4170 |
{ |
{ |
4171 |
switch (c) |
c = CHAR_TO_BYTE8 (c); |
4172 |
|
EMIT_ONE_BYTE (c); |
4173 |
|
} |
4174 |
|
else |
4175 |
|
{ |
4176 |
|
unsigned code; |
4177 |
|
struct charset *charset = char_charset (c, charset_list, &code); |
4178 |
|
|
4179 |
|
if (!charset) |
4180 |
{ |
{ |
4181 |
case '\r': |
if (coding->mode & CODING_MODE_SAFE_ENCODING) |
|
if (!(coding->mode & CODING_MODE_SELECTIVE_DISPLAY)) |
|
4182 |
{ |
{ |
4183 |
EMIT_ONE_BYTE (c); |
code = CODING_INHIBIT_CHARACTER_SUBSTITUTION; |
4184 |
break; |
charset = CHARSET_FROM_ID (charset_ascii); |
4185 |
} |
} |
4186 |
c = '\n'; |
else |
|
case '\n': |
|
|
if (coding->eol_type == CODING_EOL_CRLF) |
|
4187 |
{ |
{ |
4188 |
EMIT_TWO_BYTES ('\r', c); |
c = coding->default_char; |
4189 |
break; |
charset = char_charset (c, charset_list, &code); |
4190 |
} |
} |
|
else if (coding->eol_type == CODING_EOL_CR) |
|
|
c = '\r'; |
|
|
default: |
|
|
EMIT_ONE_BYTE (c); |
|
4191 |
} |
} |
4192 |
|
if (code == CHARSET_INVALID_CODE (charset)) |
4193 |
|
abort (); |
4194 |
|
if (charset == charset_kanji) |
4195 |
|
{ |
4196 |
|
int c1, c2; |
4197 |
|
JIS_TO_SJIS (code); |
4198 |
|
c1 = code >> 8, c2 = code & 0xFF; |
4199 |
|
EMIT_TWO_BYTES (c1, c2); |
4200 |
|
} |
4201 |
|
else if (charset == charset_kana) |
4202 |
|
EMIT_ONE_BYTE (code | 0x80); |
4203 |
|
else |
4204 |
|
EMIT_ONE_ASCII_BYTE (code & 0x7F); |
4205 |
|
} |
4206 |
|
} |
4207 |
|
coding->result = CODING_RESULT_SUCCESS; |
4208 |
|
coding->produced_char += produced_chars; |
4209 |
|
coding->produced = dst - coding->destination; |
4210 |
|
return 0; |
4211 |
|
} |
4212 |
|
|
4213 |
|
static int |
4214 |
|
encode_coding_big5 (coding) |
4215 |
|
struct coding_system *coding; |
4216 |
|
{ |
4217 |
|
int multibytep = coding->dst_multibyte; |
4218 |
|
int *charbuf = coding->charbuf; |
4219 |
|
int *charbuf_end = charbuf + coding->charbuf_used; |
4220 |
|
unsigned char *dst = coding->destination + coding->produced; |
4221 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
4222 |
|
int safe_room = 4; |
4223 |
|
int produced_chars = 0; |
4224 |
|
Lisp_Object attrs, eol_type, charset_list, val; |
4225 |
|
int ascii_compatible; |
4226 |
|
struct charset *charset_roman, *charset_big5; |
4227 |
|
int c; |
4228 |
|
|
4229 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4230 |
|
val = charset_list; |
4231 |
|
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
4232 |
|
charset_big5 = CHARSET_FROM_ID (XINT (XCAR (val))); |
4233 |
|
ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)); |
4234 |
|
|
4235 |
|
while (charbuf < charbuf_end) |
4236 |
|
{ |
4237 |
|
ASSURE_DESTINATION (safe_room); |
4238 |
|
c = *charbuf++; |
4239 |
|
/* Now encode the character C. */ |
4240 |
|
if (ASCII_CHAR_P (c) && ascii_compatible) |
4241 |
|
EMIT_ONE_ASCII_BYTE (c); |
4242 |
|
else if (CHAR_BYTE8_P (c)) |
4243 |
|
{ |
4244 |
|
c = CHAR_TO_BYTE8 (c); |
4245 |
|
EMIT_ONE_BYTE (c); |
4246 |
} |
} |
4247 |
else |
else |
4248 |
{ |
{ |
4249 |
SPLIT_CHAR (c, charset, c1, c2); |
unsigned code; |
4250 |
if (sjis_p) |
struct charset *charset = char_charset (c, charset_list, &code); |
4251 |
|
|
4252 |
|
if (! charset) |
4253 |
{ |
{ |
4254 |
if (charset == charset_jisx0208 |
if (coding->mode & CODING_MODE_SAFE_ENCODING) |
|
|| charset == charset_jisx0208_1978) |
|
4255 |
{ |
{ |
4256 |
ENCODE_SJIS (c1, c2, c1, c2); |
code = CODING_INHIBIT_CHARACTER_SUBSTITUTION; |
4257 |
EMIT_TWO_BYTES (c1, c2); |
charset = CHARSET_FROM_ID (charset_ascii); |
|
} |
|
|
else if (charset == charset_katakana_jisx0201) |
|
|
EMIT_ONE_BYTE (c1 | 0x80); |
|
|
else if (charset == charset_latin_jisx0201) |
|
|
EMIT_ONE_BYTE (c1); |
|
|
else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR) |
|
|
{ |
|
|
EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER); |
|
|
if (CHARSET_WIDTH (charset) > 1) |
|
|
EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER); |
|
4258 |
} |
} |
4259 |
else |
else |
|
/* There's no way other than producing the internal |
|
|
codes as is. */ |
|
|
EMIT_BYTES (src_base, src); |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (charset == charset_big5_1 || charset == charset_big5_2) |
|
|
{ |
|
|
ENCODE_BIG5 (charset, c1, c2, c1, c2); |
|
|
EMIT_TWO_BYTES (c1, c2); |
|
|
} |
|
|
else if (coding->mode & CODING_MODE_INHIBIT_UNENCODABLE_CHAR) |
|
4260 |
{ |
{ |
4261 |
EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER); |
c = coding->default_char; |
4262 |
if (CHARSET_WIDTH (charset) > 1) |
charset = char_charset (c, charset_list, &code); |
|
EMIT_ONE_BYTE (CODING_REPLACEMENT_CHARACTER); |
|
4263 |
} |
} |
|
else |
|
|
/* There's no way other than producing the internal |
|
|
codes as is. */ |
|
|
EMIT_BYTES (src_base, src); |
|
4264 |
} |
} |
4265 |
|
if (code == CHARSET_INVALID_CODE (charset)) |
4266 |
|
abort (); |
4267 |
|
if (charset == charset_big5) |
4268 |
|
{ |
4269 |
|
int c1, c2; |
4270 |
|
|
4271 |
|
c1 = code >> 8, c2 = code & 0xFF; |
4272 |
|
EMIT_TWO_BYTES (c1, c2); |
4273 |
|
} |
4274 |
|
else |
4275 |
|
EMIT_ONE_ASCII_BYTE (code & 0x7F); |
4276 |
} |
} |
|
coding->consumed_char++; |
|
4277 |
} |
} |
4278 |
|
coding->result = CODING_RESULT_SUCCESS; |
4279 |
label_end_of_loop: |
coding->produced_char += produced_chars; |
4280 |
coding->consumed = src_base - source; |
coding->produced = dst - coding->destination; |
4281 |
coding->produced = coding->produced_char = dst - destination; |
return 0; |
4282 |
} |
} |
4283 |
|
|
4284 |
|
|
4285 |
/*** 5. CCL handlers ***/ |
/*** 10. CCL handlers ***/ |
4286 |
|
|
4287 |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
4288 |
Check if a text is encoded in a coding system of which |
Check if a text is encoded in a coding system of which |
4289 |
encoder/decoder are written in CCL program. If it is, return |
encoder/decoder are written in CCL program. If it is, return |
4290 |
CODING_CATEGORY_MASK_CCL, else return 0. */ |
CATEGORY_MASK_CCL, else return 0. */ |
4291 |
|
|
4292 |
static int |
static int |
4293 |
detect_coding_ccl (src, src_end, multibytep) |
detect_coding_ccl (coding, detect_info) |
4294 |
unsigned char *src, *src_end; |
struct coding_system *coding; |
4295 |
int multibytep; |
struct coding_detection_info *detect_info; |
4296 |
{ |
{ |
4297 |
unsigned char *valid; |
const unsigned char *src = coding->source, *src_base = src; |
4298 |
int c; |
const unsigned char *src_end = coding->source + coding->src_bytes; |
4299 |
/* Dummy for ONE_MORE_BYTE. */ |
int multibytep = coding->src_multibyte; |
4300 |
struct coding_system dummy_coding; |
int consumed_chars = 0; |
4301 |
struct coding_system *coding = &dummy_coding; |
int found = 0; |
4302 |
|
unsigned char *valids = CODING_CCL_VALIDS (coding); |
4303 |
/* No coding system is assigned to coding-category-ccl. */ |
int head_ascii = coding->head_ascii; |
4304 |
if (!coding_system_table[CODING_CATEGORY_IDX_CCL]) |
Lisp_Object attrs; |
4305 |
return 0; |
|
4306 |
|
detect_info->checked |= CATEGORY_MASK_CCL; |
4307 |
|
|
4308 |
|
coding = &coding_categories[coding_category_ccl]; |
4309 |
|
attrs = CODING_ID_ATTRS (coding->id); |
4310 |
|
if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
4311 |
|
src += head_ascii; |
4312 |
|
|
|
valid = coding_system_table[CODING_CATEGORY_IDX_CCL]->spec.ccl.valid_codes; |
|
4313 |
while (1) |
while (1) |
4314 |
{ |
{ |
4315 |
ONE_MORE_BYTE_CHECK_MULTIBYTE (c, multibytep); |
int c; |
4316 |
if (! valid[c]) |
ONE_MORE_BYTE (c); |
4317 |
return 0; |
if (! valids[c]) |
4318 |
|
break; |
4319 |
|
if ((valids[c] > 1)) |
4320 |
|
found = CATEGORY_MASK_CCL; |
4321 |
|
} |
4322 |
|
detect_info->rejected |= CATEGORY_MASK_CCL; |
4323 |
|
return 0; |
4324 |
|
|
4325 |
|
no_more_source: |
4326 |
|
detect_info->found |= found; |
4327 |
|
return 1; |
4328 |
|
} |
4329 |
|
|
4330 |
|
static void |
4331 |
|
decode_coding_ccl (coding) |
4332 |
|
struct coding_system *coding; |
4333 |
|
{ |
4334 |
|
const unsigned char *src = coding->source + coding->consumed; |
4335 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
4336 |
|
int *charbuf = coding->charbuf; |
4337 |
|
int *charbuf_end = charbuf + coding->charbuf_size; |
4338 |
|
int consumed_chars = 0; |
4339 |
|
int multibytep = coding->src_multibyte; |
4340 |
|
struct ccl_program ccl; |
4341 |
|
int source_charbuf[1024]; |
4342 |
|
int source_byteidx[1024]; |
4343 |
|
Lisp_Object attrs, eol_type, charset_list; |
4344 |
|
|
4345 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4346 |
|
setup_ccl_program (&ccl, CODING_CCL_DECODER (coding)); |
4347 |
|
|
4348 |
|
while (src < src_end) |
4349 |
|
{ |
4350 |
|
const unsigned char *p = src; |
4351 |
|
int *source, *source_end; |
4352 |
|
int i = 0; |
4353 |
|
|
4354 |
|
if (multibytep) |
4355 |
|
while (i < 1024 && p < src_end) |
4356 |
|
{ |
4357 |
|
source_byteidx[i] = p - src; |
4358 |
|
source_charbuf[i++] = STRING_CHAR_ADVANCE (p); |
4359 |
|
} |
4360 |
|
else |
4361 |
|
while (i < 1024 && p < src_end) |
4362 |
|
source_charbuf[i++] = *p++; |
4363 |
|
|
4364 |
|
if (p == src_end && coding->mode & CODING_MODE_LAST_BLOCK) |
4365 |
|
ccl.last_block = 1; |
4366 |
|
|
4367 |
|
source = source_charbuf; |
4368 |
|
source_end = source + i; |
4369 |
|
while (source < source_end) |
4370 |
|
{ |
4371 |
|
ccl_driver (&ccl, source, charbuf, |
4372 |
|
source_end - source, charbuf_end - charbuf, |
4373 |
|
charset_list); |
4374 |
|
source += ccl.consumed; |
4375 |
|
charbuf += ccl.produced; |
4376 |
|
if (ccl.status != CCL_STAT_SUSPEND_BY_DST) |
4377 |
|
break; |
4378 |
|
} |
4379 |
|
if (source < source_end) |
4380 |
|
src += source_byteidx[source - source_charbuf]; |
4381 |
|
else |
4382 |
|
src = p; |
4383 |
|
consumed_chars += source - source_charbuf; |
4384 |
|
|
4385 |
|
if (ccl.status != CCL_STAT_SUSPEND_BY_SRC |
4386 |
|
&& ccl.status != CODING_RESULT_INSUFFICIENT_SRC) |
4387 |
|
break; |
4388 |
|
} |
4389 |
|
|
4390 |
|
switch (ccl.status) |
4391 |
|
{ |
4392 |
|
case CCL_STAT_SUSPEND_BY_SRC: |
4393 |
|
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
4394 |
|
break; |
4395 |
|
case CCL_STAT_SUSPEND_BY_DST: |
4396 |
|
break; |
4397 |
|
case CCL_STAT_QUIT: |
4398 |
|
case CCL_STAT_INVALID_CMD: |
4399 |
|
coding->result = CODING_RESULT_INTERRUPT; |
4400 |
|
break; |
4401 |
|
default: |
4402 |
|
coding->result = CODING_RESULT_SUCCESS; |
4403 |
|
break; |
4404 |
} |
} |
4405 |
label_end_of_loop: |
coding->consumed_char += consumed_chars; |
4406 |
return CODING_CATEGORY_MASK_CCL; |
coding->consumed = src - coding->source; |
4407 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
4408 |
} |
} |
4409 |
|
|
4410 |
|
static int |
4411 |
|
encode_coding_ccl (coding) |
4412 |
|
struct coding_system *coding; |
4413 |
|
{ |
4414 |
|
struct ccl_program ccl; |
4415 |
|
int multibytep = coding->dst_multibyte; |
4416 |
|
int *charbuf = coding->charbuf; |
4417 |
|
int *charbuf_end = charbuf + coding->charbuf_used; |
4418 |
|
unsigned char *dst = coding->destination + coding->produced; |
4419 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
4420 |
|
unsigned char *adjusted_dst_end = dst_end - 1; |
4421 |
|
int destination_charbuf[1024]; |
4422 |
|
int i, produced_chars = 0; |
4423 |
|
Lisp_Object attrs, eol_type, charset_list; |
4424 |
|
|
4425 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4426 |
|
setup_ccl_program (&ccl, CODING_CCL_ENCODER (coding)); |
4427 |
|
|
4428 |
|
ccl.last_block = coding->mode & CODING_MODE_LAST_BLOCK; |
4429 |
|
ccl.dst_multibyte = coding->dst_multibyte; |
4430 |
|
|
4431 |
|
while (charbuf < charbuf_end && dst < adjusted_dst_end) |
4432 |
|
{ |
4433 |
|
int dst_bytes = dst_end - dst; |
4434 |
|
if (dst_bytes > 1024) |
4435 |
|
dst_bytes = 1024; |
4436 |
|
|
4437 |
|
ccl_driver (&ccl, charbuf, destination_charbuf, |
4438 |
|
charbuf_end - charbuf, dst_bytes, charset_list); |
4439 |
|
charbuf += ccl.consumed; |
4440 |
|
if (multibytep) |
4441 |
|
for (i = 0; i < ccl.produced; i++) |
4442 |
|
EMIT_ONE_BYTE (destination_charbuf[i] & 0xFF); |
4443 |
|
else |
4444 |
|
{ |
4445 |
|
for (i = 0; i < ccl.produced; i++) |
4446 |
|
*dst++ = destination_charbuf[i] & 0xFF; |
4447 |
|
produced_chars += ccl.produced; |
4448 |
|
} |
4449 |
|
} |
4450 |
|
|
4451 |
|
switch (ccl.status) |
4452 |
|
{ |
4453 |
|
case CCL_STAT_SUSPEND_BY_SRC: |
4454 |
|
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
4455 |
|
break; |
4456 |
|
case CCL_STAT_SUSPEND_BY_DST: |
4457 |
|
coding->result = CODING_RESULT_INSUFFICIENT_DST; |
4458 |
|
break; |
4459 |
|
case CCL_STAT_QUIT: |
4460 |
|
case CCL_STAT_INVALID_CMD: |
4461 |
|
coding->result = CODING_RESULT_INTERRUPT; |
4462 |
|
break; |
4463 |
|
default: |
4464 |
|
coding->result = CODING_RESULT_SUCCESS; |
4465 |
|
break; |
4466 |
|
} |
4467 |
|
|
4468 |
|
coding->produced_char += produced_chars; |
4469 |
|
coding->produced = dst - coding->destination; |
4470 |
|
return 0; |
4471 |
|
} |
4472 |
|
|
4473 |
|
|
4474 |
|
|
4475 |
/*** 6. End-of-line handlers ***/ |
/*** 10, 11. no-conversion handlers ***/ |
4476 |
|
|
4477 |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
/* See the above "GENERAL NOTES on `decode_coding_XXX ()' functions". */ |
4478 |
|
|
4479 |
static void |
static void |
4480 |
decode_eol (coding, source, destination, src_bytes, dst_bytes) |
decode_coding_raw_text (coding) |
4481 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes; |
|
4482 |
{ |
{ |
4483 |
unsigned char *src = source; |
coding->chars_at_source = 1; |
4484 |
unsigned char *dst = destination; |
coding->consumed_char = 0; |
4485 |
unsigned char *src_end = src + src_bytes; |
coding->consumed = 0; |
4486 |
unsigned char *dst_end = dst + dst_bytes; |
coding->result = CODING_RESULT_SUCCESS; |
4487 |
Lisp_Object translation_table; |
} |
4488 |
/* SRC_BASE remembers the start position in source in each loop. |
|
4489 |
The loop will be exited when there's not enough source code |
static int |
4490 |
(within macro ONE_MORE_BYTE), or when there's not enough |
encode_coding_raw_text (coding) |
4491 |
destination area to produce a character (within macro |
struct coding_system *coding; |
4492 |
EMIT_CHAR). */ |
{ |
4493 |
unsigned char *src_base; |
int multibytep = coding->dst_multibyte; |
4494 |
|
int *charbuf = coding->charbuf; |
4495 |
|
int *charbuf_end = coding->charbuf + coding->charbuf_used; |
4496 |
|
unsigned char *dst = coding->destination + coding->produced; |
4497 |
|
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
4498 |
|
int produced_chars = 0; |
4499 |
int c; |
int c; |
4500 |
|
|
4501 |
translation_table = Qnil; |
if (multibytep) |
4502 |
switch (coding->eol_type) |
{ |
4503 |
|
int safe_room = MAX_MULTIBYTE_LENGTH * 2; |
4504 |
|
|
4505 |
|
if (coding->src_multibyte) |
4506 |
|
while (charbuf < charbuf_end) |
4507 |
|
{ |
4508 |
|
ASSURE_DESTINATION (safe_room); |
4509 |
|
c = *charbuf++; |
4510 |
|
if (ASCII_CHAR_P (c)) |
4511 |
|
EMIT_ONE_ASCII_BYTE (c); |
4512 |
|
else if (CHAR_BYTE8_P (c)) |
4513 |
|
{ |
4514 |
|
c = CHAR_TO_BYTE8 (c); |
4515 |
|
EMIT_ONE_BYTE (c); |
4516 |
|
} |
4517 |
|
else |
4518 |
|
{ |
4519 |
|
unsigned char str[MAX_MULTIBYTE_LENGTH], *p0 = str, *p1 = str; |
4520 |
|
|
4521 |
|
CHAR_STRING_ADVANCE (c, p1); |
4522 |
|
while (p0 < p1) |
4523 |
|
{ |
4524 |
|
EMIT_ONE_BYTE (*p0); |
4525 |
|
p0++; |
4526 |
|
} |
4527 |
|
} |
4528 |
|
} |
4529 |
|
else |
4530 |
|
while (charbuf < charbuf_end) |
4531 |
|
{ |
4532 |
|
ASSURE_DESTINATION (safe_room); |
4533 |
|
c = *charbuf++; |
4534 |
|
EMIT_ONE_BYTE (c); |
4535 |
|
} |
4536 |
|
} |
4537 |
|
else |
4538 |
{ |
{ |
4539 |
case CODING_EOL_CRLF: |
if (coding->src_multibyte) |
|
while (1) |
|
4540 |
{ |
{ |
4541 |
src_base = src; |
int safe_room = MAX_MULTIBYTE_LENGTH; |
4542 |
ONE_MORE_BYTE (c); |
|
4543 |
if (c == '\r') |
while (charbuf < charbuf_end) |
|
{ |
|
|
ONE_MORE_BYTE (c); |
|
|
if (c != '\n') |
|
|
{ |
|
|
src--; |
|
|
c = '\r'; |
|
|
} |
|
|
} |
|
|
else if (c == '\n' |
|
|
&& (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL)) |
|
4544 |
{ |
{ |
4545 |
coding->result = CODING_FINISH_INCONSISTENT_EOL; |
ASSURE_DESTINATION (safe_room); |
4546 |
goto label_end_of_loop; |
c = *charbuf++; |
4547 |
|
if (ASCII_CHAR_P (c)) |
4548 |
|
*dst++ = c; |
4549 |
|
else if (CHAR_BYTE8_P (c)) |
4550 |
|
*dst++ = CHAR_TO_BYTE8 (c); |
4551 |
|
else |
4552 |
|
CHAR_STRING_ADVANCE (c, dst); |
4553 |
|
produced_chars++; |
4554 |
} |
} |
|
EMIT_CHAR (c); |
|
4555 |
} |
} |
4556 |
break; |
else |
4557 |
|
{ |
4558 |
|
ASSURE_DESTINATION (charbuf_end - charbuf); |
4559 |
|
while (charbuf < charbuf_end && dst < dst_end) |
4560 |
|
*dst++ = *charbuf++; |
4561 |
|
produced_chars = dst - (coding->destination + coding->dst_bytes); |
4562 |
|
} |
4563 |
|
} |
4564 |
|
coding->result = CODING_RESULT_SUCCESS; |
4565 |
|
coding->produced_char += produced_chars; |
4566 |
|
coding->produced = dst - coding->destination; |
4567 |
|
return 0; |
4568 |
|
} |
4569 |
|
|
4570 |
|
/* See the above "GENERAL NOTES on `detect_coding_XXX ()' functions". |
4571 |
|
Check if a text is encoded in a charset-based coding system. If it |
4572 |
|
is, return 1, else return 0. */ |
4573 |
|
|
4574 |
|
static int |
4575 |
|
detect_coding_charset (coding, detect_info) |
4576 |
|
struct coding_system *coding; |
4577 |
|
struct coding_detection_info *detect_info; |
4578 |
|
{ |
4579 |
|
const unsigned char *src = coding->source, *src_base = src; |
4580 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
4581 |
|
int multibytep = coding->src_multibyte; |
4582 |
|
int consumed_chars = 0; |
4583 |
|
Lisp_Object attrs, valids; |
4584 |
|
int found = 0; |
4585 |
|
|
4586 |
|
detect_info->checked |= CATEGORY_MASK_CHARSET; |
4587 |
|
|
4588 |
|
coding = &coding_categories[coding_category_charset]; |
4589 |
|
attrs = CODING_ID_ATTRS (coding->id); |
4590 |
|
valids = AREF (attrs, coding_attr_charset_valids); |
4591 |
|
|
4592 |
|
if (! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
4593 |
|
src += coding->head_ascii; |
4594 |
|
|
4595 |
|
while (1) |
4596 |
|
{ |
4597 |
|
int c; |
4598 |
|
|
4599 |
case CODING_EOL_CR: |
ONE_MORE_BYTE (c); |
4600 |
while (1) |
if (NILP (AREF (valids, c))) |
4601 |
|
break; |
4602 |
|
if (c >= 0x80) |
4603 |
|
found = CATEGORY_MASK_CHARSET; |
4604 |
|
} |
4605 |
|
detect_info->rejected |= CATEGORY_MASK_CHARSET; |
4606 |
|
return 0; |
4607 |
|
|
4608 |
|
no_more_source: |
4609 |
|
detect_info->found |= found; |
4610 |
|
return 1; |
4611 |
|
} |
4612 |
|
|
4613 |
|
static void |
4614 |
|
decode_coding_charset (coding) |
4615 |
|
struct coding_system *coding; |
4616 |
|
{ |
4617 |
|
const unsigned char *src = coding->source + coding->consumed; |
4618 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
4619 |
|
const unsigned char *src_base; |
4620 |
|
int *charbuf = coding->charbuf; |
4621 |
|
int *charbuf_end = charbuf + coding->charbuf_size - MAX_ANNOTATION_LENGTH; |
4622 |
|
int consumed_chars = 0, consumed_chars_base; |
4623 |
|
int multibytep = coding->src_multibyte; |
4624 |
|
Lisp_Object attrs, eol_type, charset_list, valids; |
4625 |
|
int char_offset = coding->produced_char; |
4626 |
|
int last_offset = char_offset; |
4627 |
|
int last_id = charset_ascii; |
4628 |
|
|
4629 |
|
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4630 |
|
valids = AREF (attrs, coding_attr_charset_valids); |
4631 |
|
|
4632 |
|
while (1) |
4633 |
|
{ |
4634 |
|
int c; |
4635 |
|
|
4636 |
|
src_base = src; |
4637 |
|
consumed_chars_base = consumed_chars; |
4638 |
|
|
4639 |
|
if (charbuf >= charbuf_end) |
4640 |
|
break; |
4641 |
|
|
4642 |
|
ONE_MORE_BYTE (c); |
4643 |
|
if (c == '\r') |
4644 |
{ |
{ |
4645 |
src_base = src; |
/* Here we assume that no charset maps '\r' to something |
4646 |
ONE_MORE_BYTE (c); |
else. */ |
4647 |
if (c == '\n') |
if (EQ (eol_type, Qdos)) |
4648 |
{ |
{ |
4649 |
if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
if (src == src_end) |
4650 |
{ |
{ |
4651 |
coding->result = CODING_FINISH_INCONSISTENT_EOL; |
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
4652 |
goto label_end_of_loop; |
goto no_more_source; |
4653 |
} |
} |
4654 |
|
if (*src == '\n') |
4655 |
|
ONE_MORE_BYTE (c); |
4656 |
} |
} |
4657 |
else if (c == '\r') |
else if (EQ (eol_type, Qmac)) |
4658 |
c = '\n'; |
c = '\n'; |
|
EMIT_CHAR (c); |
|
4659 |
} |
} |
4660 |
break; |
else |
|
|
|
|
default: /* no need for EOL handling */ |
|
|
while (1) |
|
4661 |
{ |
{ |
4662 |
src_base = src; |
Lisp_Object val; |
4663 |
ONE_MORE_BYTE (c); |
struct charset *charset; |
4664 |
EMIT_CHAR (c); |
int dim; |
4665 |
|
int len = 1; |
4666 |
|
unsigned code = c; |
4667 |
|
|
4668 |
|
val = AREF (valids, c); |
4669 |
|
if (NILP (val)) |
4670 |
|
goto invalid_code; |
4671 |
|
if (INTEGERP (val)) |
4672 |
|
{ |
4673 |
|
charset = CHARSET_FROM_ID (XFASTINT (val)); |
4674 |
|
dim = CHARSET_DIMENSION (charset); |
4675 |
|
while (len < dim) |
4676 |
|
{ |
4677 |
|
ONE_MORE_BYTE (c); |
4678 |
|
code = (code << 8) | c; |
4679 |
|
len++; |
4680 |
|
} |
4681 |
|
CODING_DECODE_CHAR (coding, src, src_base, src_end, |
4682 |
|
charset, code, c); |
4683 |
|
} |
4684 |
|
else |
4685 |
|
{ |
4686 |
|
/* VAL is a list of charset IDs. It is assured that the |
4687 |
|
list is sorted by charset dimensions (smaller one |
4688 |
|
comes first). */ |
4689 |
|
while (CONSP (val)) |
4690 |
|
{ |
4691 |
|
charset = CHARSET_FROM_ID (XFASTINT (XCAR (val))); |
4692 |
|
dim = CHARSET_DIMENSION (charset); |
4693 |
|
while (len < dim) |
4694 |
|
{ |
4695 |
|
ONE_MORE_BYTE (c); |
4696 |
|
code = (code << 8) | c; |
4697 |
|
len++; |
4698 |
|
} |
4699 |
|
CODING_DECODE_CHAR (coding, src, src_base, |
4700 |
|
src_end, charset, code, c); |
4701 |
|
if (c >= 0) |
4702 |
|
break; |
4703 |
|
val = XCDR (val); |
4704 |
|
} |
4705 |
|
} |
4706 |
|
if (c < 0) |
4707 |
|
goto invalid_code; |
4708 |
|
if (charset->id != charset_ascii |
4709 |
|
&& last_id != charset->id) |
4710 |
|
{ |
4711 |
|
if (last_id != charset_ascii) |
4712 |
|
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4713 |
|
last_id = charset->id; |
4714 |
|
last_offset = char_offset; |
4715 |
|
} |
4716 |
} |
} |
4717 |
|
*charbuf++ = c; |
4718 |
|
char_offset++; |
4719 |
|
continue; |
4720 |
|
|
4721 |
|
invalid_code: |
4722 |
|
src = src_base; |
4723 |
|
consumed_chars = consumed_chars_base; |
4724 |
|
ONE_MORE_BYTE (c); |
4725 |
|
*charbuf++ = ASCII_BYTE_P (c) ? c : BYTE8_TO_CHAR (c); |
4726 |
|
char_offset++; |
4727 |
|
coding->errors++; |
4728 |
} |
} |
4729 |
|
|
4730 |
label_end_of_loop: |
no_more_source: |
4731 |
coding->consumed = coding->consumed_char = src_base - source; |
if (last_id != charset_ascii) |
4732 |
coding->produced = dst - destination; |
ADD_CHARSET_DATA (charbuf, last_offset, char_offset, last_id); |
4733 |
return; |
coding->consumed_char += consumed_chars_base; |
4734 |
|
coding->consumed = src_base - coding->source; |
4735 |
|
coding->charbuf_used = charbuf - coding->charbuf; |
4736 |
} |
} |
4737 |
|
|
4738 |
/* See "GENERAL NOTES about `encode_coding_XXX ()' functions". Encode |
static int |
4739 |
format of end-of-line according to `coding->eol_type'. It also |
encode_coding_charset (coding) |
|
convert multibyte form 8-bit characters to unibyte if |
|
|
CODING->src_multibyte is nonzero. If `coding->mode & |
|
|
CODING_MODE_SELECTIVE_DISPLAY' is nonzero, code '\r' in source text |
|
|
also means end-of-line. */ |
|
|
|
|
|
static void |
|
|
encode_eol (coding, source, destination, src_bytes, dst_bytes) |
|
4740 |
struct coding_system *coding; |
struct coding_system *coding; |
|
const unsigned char *source; |
|
|
unsigned char *destination; |
|
|
int src_bytes, dst_bytes; |
|
4741 |
{ |
{ |
4742 |
const unsigned char *src = source; |
int multibytep = coding->dst_multibyte; |
4743 |
unsigned char *dst = destination; |
int *charbuf = coding->charbuf; |
4744 |
const unsigned char *src_end = src + src_bytes; |
int *charbuf_end = charbuf + coding->charbuf_used; |
4745 |
unsigned char *dst_end = dst + dst_bytes; |
unsigned char *dst = coding->destination + coding->produced; |
4746 |
Lisp_Object translation_table; |
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
4747 |
/* SRC_BASE remembers the start position in source in each loop. |
int safe_room = MAX_MULTIBYTE_LENGTH; |
4748 |
The loop will be exited when there's not enough source text to |
int produced_chars = 0; |
4749 |
analyze multi-byte codes (within macro ONE_MORE_CHAR), or when |
Lisp_Object attrs, eol_type, charset_list; |
4750 |
there's not enough destination area to produce encoded codes |
int ascii_compatible; |
|
(within macro EMIT_BYTES). */ |
|
|
const unsigned char *src_base; |
|
|
unsigned char *tmp; |
|
4751 |
int c; |
int c; |
|
int selective_display = coding->mode & CODING_MODE_SELECTIVE_DISPLAY; |
|
4752 |
|
|
4753 |
translation_table = Qnil; |
CODING_GET_INFO (coding, attrs, eol_type, charset_list); |
4754 |
if (coding->src_multibyte |
ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)); |
|
&& *(src_end - 1) == LEADING_CODE_8_BIT_CONTROL) |
|
|
{ |
|
|
src_end--; |
|
|
src_bytes--; |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_SRC; |
|
|
} |
|
4755 |
|
|
4756 |
if (coding->eol_type == CODING_EOL_CRLF) |
while (charbuf < charbuf_end) |
|
{ |
|
|
while (src < src_end) |
|
|
{ |
|
|
src_base = src; |
|
|
c = *src++; |
|
|
if (c >= 0x20) |
|
|
EMIT_ONE_BYTE (c); |
|
|
else if (c == '\n' || (c == '\r' && selective_display)) |
|
|
EMIT_TWO_BYTES ('\r', '\n'); |
|
|
else |
|
|
EMIT_ONE_BYTE (c); |
|
|
} |
|
|
src_base = src; |
|
|
label_end_of_loop: |
|
|
; |
|
|
} |
|
|
else |
|
4757 |
{ |
{ |
4758 |
if (!dst_bytes || src_bytes <= dst_bytes) |
struct charset *charset; |
4759 |
|
unsigned code; |
4760 |
|
|
4761 |
|
ASSURE_DESTINATION (safe_room); |
4762 |
|
c = *charbuf++; |
4763 |
|
if (ascii_compatible && ASCII_CHAR_P (c)) |
4764 |
|
EMIT_ONE_ASCII_BYTE (c); |
4765 |
|
else if (CHAR_BYTE8_P (c)) |
4766 |
{ |
{ |
4767 |
safe_bcopy (src, dst, src_bytes); |
c = CHAR_TO_BYTE8 (c); |
4768 |
src_base = src_end; |
EMIT_ONE_BYTE (c); |
|
dst += src_bytes; |
|
4769 |
} |
} |
4770 |
else |
else |
4771 |
{ |
{ |
4772 |
if (coding->src_multibyte |
charset = char_charset (c, charset_list, &code); |
4773 |
&& *(src + dst_bytes - 1) == LEADING_CODE_8_BIT_CONTROL) |
if (charset) |
4774 |
dst_bytes--; |
{ |
4775 |
safe_bcopy (src, dst, dst_bytes); |
if (CHARSET_DIMENSION (charset) == 1) |
4776 |
src_base = src + dst_bytes; |
EMIT_ONE_BYTE (code); |
4777 |
dst = destination + dst_bytes; |
else if (CHARSET_DIMENSION (charset) == 2) |
4778 |
coding->result = CODING_FINISH_INSUFFICIENT_DST; |
EMIT_TWO_BYTES (code >> 8, code & 0xFF); |
4779 |
} |
else if (CHARSET_DIMENSION (charset) == 3) |
4780 |
if (coding->eol_type == CODING_EOL_CR) |
EMIT_THREE_BYTES (code >> 16, (code >> 8) & 0xFF, code & 0xFF); |
4781 |
{ |
else |
4782 |
for (tmp = destination; tmp < dst; tmp++) |
EMIT_FOUR_BYTES (code >> 24, (code >> 16) & 0xFF, |
4783 |
if (*tmp == '\n') *tmp = '\r'; |
(code >> 8) & 0xFF, code & 0xFF); |
4784 |
} |
} |
4785 |
else if (selective_display) |
else |
4786 |
{ |
{ |
4787 |
for (tmp = destination; tmp < dst; tmp++) |
if (coding->mode & CODING_MODE_SAFE_ENCODING) |
4788 |
if (*tmp == '\r') *tmp = '\n'; |
c = CODING_INHIBIT_CHARACTER_SUBSTITUTION; |
4789 |
|
else |
4790 |
|
c = coding->default_char; |
4791 |
|
EMIT_ONE_BYTE (c); |
4792 |
|
} |
4793 |
} |
} |
4794 |
} |
} |
|
if (coding->src_multibyte) |
|
|
dst = destination + str_as_unibyte (destination, dst - destination); |
|
4795 |
|
|
4796 |
coding->consumed = src_base - source; |
coding->result = CODING_RESULT_SUCCESS; |
4797 |
coding->produced = dst - destination; |
coding->produced_char += produced_chars; |
4798 |
coding->produced_char = coding->produced; |
coding->produced = dst - coding->destination; |
4799 |
|
return 0; |
4800 |
} |
} |
4801 |
|
|
4802 |
|
|
4803 |
/*** 7. C library functions ***/ |
/*** 7. C library functions ***/ |
4804 |
|
|
4805 |
/* In Emacs Lisp, a coding system is represented by a Lisp symbol which |
/* Setup coding context CODING from information about CODING_SYSTEM. |
4806 |
has a property `coding-system'. The value of this property is a |
If CODING_SYSTEM is nil, `no-conversion' is assumed. If |
4807 |
vector of length 5 (called the coding-vector). Among elements of |
CODING_SYSTEM is invalid, signal an error. */ |
|
this vector, the first (element[0]) and the fifth (element[4]) |
|
|
carry important information for decoding/encoding. Before |
|
|
decoding/encoding, this information should be set in fields of a |
|
|
structure of type `coding_system'. |
|
|
|
|
|
The value of the property `coding-system' can be a symbol of another |
|
|
subsidiary coding-system. In that case, Emacs gets coding-vector |
|
|
from that symbol. |
|
|
|
|
|
`element[0]' contains information to be set in `coding->type'. The |
|
|
value and its meaning is as follows: |
|
|
|
|
|
0 -- coding_type_emacs_mule |
|
|
1 -- coding_type_sjis |
|
|
2 -- coding_type_iso2022 |
|
|
3 -- coding_type_big5 |
|
|
4 -- coding_type_ccl encoder/decoder written in CCL |
|
|
nil -- coding_type_no_conversion |
|
|
t -- coding_type_undecided (automatic conversion on decoding, |
|
|
no-conversion on encoding) |
|
|
|
|
|
`element[4]' contains information to be set in `coding->flags' and |
|
|
`coding->spec'. The meaning varies by `coding->type'. |
|
|
|
|
|
If `coding->type' is `coding_type_iso2022', element[4] is a vector |
|
|
of length 32 (of which the first 13 sub-elements are used now). |
|
|
Meanings of these sub-elements are: |
|
|
|
|
|
sub-element[N] where N is 0 through 3: to be set in `coding->spec.iso2022' |
|
|
If the value is an integer of valid charset, the charset is |
|
|
assumed to be designated to graphic register N initially. |
|
|
|
|
|
If the value is minus, it is a minus value of charset which |
|
|
reserves graphic register N, which means that the charset is |
|
|
not designated initially but should be designated to graphic |
|
|
register N just before encoding a character in that charset. |
|
|
|
|
|
If the value is nil, graphic register N is never used on |
|
|
encoding. |
|
|
|
|
|
sub-element[N] where N is 4 through 11: to be set in `coding->flags' |
|
|
Each value takes t or nil. See the section ISO2022 of |
|
|
`coding.h' for more information. |
|
|
|
|
|
If `coding->type' is `coding_type_big5', element[4] is t to denote |
|
|
BIG5-ETen or nil to denote BIG5-HKU. |
|
|
|
|
|
If `coding->type' takes the other value, element[4] is ignored. |
|
|
|
|
|
Emacs Lisp's coding systems also carry information about format of |
|
|
end-of-line in a value of property `eol-type'. If the value is |
|
|
integer, 0 means CODING_EOL_LF, 1 means CODING_EOL_CRLF, and 2 |
|
|
means CODING_EOL_CR. If it is not integer, it should be a vector |
|
|
of subsidiary coding systems of which property `eol-type' has one |
|
|
of the above values. |
|
4808 |
|
|
4809 |
*/ |
void |
|
|
|
|
/* Extract information for decoding/encoding from CODING_SYSTEM_SYMBOL |
|
|
and set it in CODING. If CODING_SYSTEM_SYMBOL is invalid, CODING |
|
|
is setup so that no conversion is necessary and return -1, else |
|
|
return 0. */ |
|
|
|
|
|
int |
|
4810 |
setup_coding_system (coding_system, coding) |
setup_coding_system (coding_system, coding) |
4811 |
Lisp_Object coding_system; |
Lisp_Object coding_system; |
4812 |
struct coding_system *coding; |
struct coding_system *coding; |
4813 |
{ |
{ |
4814 |
Lisp_Object coding_spec, coding_type, eol_type, plist; |
Lisp_Object attrs; |
4815 |
|
Lisp_Object eol_type; |
4816 |
|
Lisp_Object coding_type; |
4817 |
Lisp_Object val; |
Lisp_Object val; |
4818 |
|
|
|
/* At first, zero clear all members. */ |
|
|
bzero (coding, sizeof (struct coding_system)); |
|
|
|
|
|
/* Initialize some fields required for all kinds of coding systems. */ |
|
|
coding->symbol = coding_system; |
|
|
coding->heading_ascii = -1; |
|
|
coding->post_read_conversion = coding->pre_write_conversion = Qnil; |
|
|
coding->composing = COMPOSITION_DISABLED; |
|
|
coding->cmp_data = NULL; |
|
|
|
|
4819 |
if (NILP (coding_system)) |
if (NILP (coding_system)) |
4820 |
goto label_invalid_coding_system; |
coding_system = Qno_conversion; |
4821 |
|
|
4822 |
coding_spec = Fget (coding_system, Qcoding_system); |
CHECK_CODING_SYSTEM_GET_ID (coding_system, coding->id); |
4823 |
|
|
4824 |
if (!VECTORP (coding_spec) |
attrs = CODING_ID_ATTRS (coding->id); |
4825 |
|| XVECTOR (coding_spec)->size != 5 |
eol_type = CODING_ID_EOL_TYPE (coding->id); |
|
|| !CONSP (XVECTOR (coding_spec)->contents[3])) |
|
|
goto label_invalid_coding_system; |
|
4826 |
|
|
4827 |
eol_type = inhibit_eol_conversion ? Qnil : Fget (coding_system, Qeol_type); |
coding->mode = 0; |
4828 |
if (VECTORP (eol_type)) |
coding->head_ascii = -1; |
4829 |
{ |
coding->common_flags |
4830 |
coding->eol_type = CODING_EOL_UNDECIDED; |
= (VECTORP (eol_type) ? CODING_REQUIRE_DETECTION_MASK : 0); |
4831 |
coding->common_flags = CODING_REQUIRE_DETECTION_MASK; |
if (! NILP (CODING_ATTR_POST_READ (attrs))) |
4832 |
|
coding->common_flags |= CODING_REQUIRE_DECODING_MASK; |
4833 |
|
if (! NILP (CODING_ATTR_PRE_WRITE (attrs))) |
4834 |
|
coding->common_flags |= CODING_REQUIRE_ENCODING_MASK; |
4835 |
|
if (! NILP (CODING_ATTR_FOR_UNIBYTE (attrs))) |
4836 |
|
coding->common_flags |= CODING_FOR_UNIBYTE_MASK; |
4837 |
|
|
4838 |
|
val = CODING_ATTR_SAFE_CHARSETS (attrs); |
4839 |
|
coding->max_charset_id = SCHARS (val) - 1; |
4840 |
|
coding->safe_charsets = (char *) SDATA (val); |
4841 |
|
coding->default_char = XINT (CODING_ATTR_DEFAULT_CHAR (attrs)); |
4842 |
|
|
4843 |
|
coding_type = CODING_ATTR_TYPE (attrs); |
4844 |
|
if (EQ (coding_type, Qundecided)) |
4845 |
|
{ |
4846 |
|
coding->detector = NULL; |
4847 |
|
coding->decoder = decode_coding_raw_text; |
4848 |
|
coding->encoder = encode_coding_raw_text; |
4849 |
|
coding->common_flags |= CODING_REQUIRE_DETECTION_MASK; |
4850 |
} |
} |
4851 |
else if (XFASTINT (eol_type) == 1) |
else if (EQ (coding_type, Qiso_2022)) |
4852 |
{ |
{ |
4853 |
coding->eol_type = CODING_EOL_CRLF; |
int i; |
4854 |
|
int flags = XINT (AREF (attrs, coding_attr_iso_flags)); |
4855 |
|
|
4856 |
|
/* Invoke graphic register 0 to plane 0. */ |
4857 |
|
CODING_ISO_INVOCATION (coding, 0) = 0; |
4858 |
|
/* Invoke graphic register 1 to plane 1 if we can use 8-bit. */ |
4859 |
|
CODING_ISO_INVOCATION (coding, 1) |
4860 |
|
= (flags & CODING_ISO_FLAG_SEVEN_BITS ? -1 : 1); |
4861 |
|
/* Setup the initial status of designation. */ |
4862 |
|
for (i = 0; i < 4; i++) |
4863 |
|
CODING_ISO_DESIGNATION (coding, i) = CODING_ISO_INITIAL (coding, i); |
4864 |
|
/* Not single shifting initially. */ |
4865 |
|
CODING_ISO_SINGLE_SHIFTING (coding) = 0; |
4866 |
|
/* Beginning of buffer should also be regarded as bol. */ |
4867 |
|
CODING_ISO_BOL (coding) = 1; |
4868 |
|
coding->detector = detect_coding_iso_2022; |
4869 |
|
coding->decoder = decode_coding_iso_2022; |
4870 |
|
coding->encoder = encode_coding_iso_2022; |
4871 |
|
if (flags & CODING_ISO_FLAG_SAFE) |
4872 |
|
coding->mode |= CODING_MODE_SAFE_ENCODING; |
4873 |
coding->common_flags |
coding->common_flags |
4874 |
= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK |
4875 |
} |
| CODING_REQUIRE_FLUSHING_MASK); |
4876 |
else if (XFASTINT (eol_type) == 2) |
if (flags & CODING_ISO_FLAG_COMPOSITION) |
4877 |
{ |
coding->common_flags |= CODING_ANNOTATE_COMPOSITION_MASK; |
4878 |
coding->eol_type = CODING_EOL_CR; |
if (flags & CODING_ISO_FLAG_DESIGNATION) |
4879 |
|
coding->common_flags |= CODING_ANNOTATE_CHARSET_MASK; |
4880 |
|
if (flags & CODING_ISO_FLAG_FULL_SUPPORT) |
4881 |
|
{ |
4882 |
|
setup_iso_safe_charsets (attrs); |
4883 |
|
val = CODING_ATTR_SAFE_CHARSETS (attrs); |
4884 |
|
coding->max_charset_id = SCHARS (val) - 1; |
4885 |
|
coding->safe_charsets = (char *) SDATA (val); |
4886 |
|
} |
4887 |
|
CODING_ISO_FLAGS (coding) = flags; |
4888 |
|
} |
4889 |
|
else if (EQ (coding_type, Qcharset)) |
4890 |
|
{ |
4891 |
|
coding->detector = detect_coding_charset; |
4892 |
|
coding->decoder = decode_coding_charset; |
4893 |
|
coding->encoder = encode_coding_charset; |
4894 |
coding->common_flags |
coding->common_flags |
4895 |
= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
4896 |
} |
} |
4897 |
else |
else if (EQ (coding_type, Qutf_8)) |
|
coding->eol_type = CODING_EOL_LF; |
|
|
|
|
|
coding_type = XVECTOR (coding_spec)->contents[0]; |
|
|
/* Try short cut. */ |
|
|
if (SYMBOLP (coding_type)) |
|
4898 |
{ |
{ |
4899 |
if (EQ (coding_type, Qt)) |
coding->detector = detect_coding_utf_8; |
4900 |
{ |
coding->decoder = decode_coding_utf_8; |
4901 |
coding->type = coding_type_undecided; |
coding->encoder = encode_coding_utf_8; |
4902 |
coding->common_flags |= CODING_REQUIRE_DETECTION_MASK; |
coding->common_flags |
4903 |
} |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
|
else |
|
|
coding->type = coding_type_no_conversion; |
|
|
/* Initialize this member. Any thing other than |
|
|
CODING_CATEGORY_IDX_UTF_16_BE and |
|
|
CODING_CATEGORY_IDX_UTF_16_LE are ok because they have |
|
|
special treatment in detect_eol. */ |
|
|
coding->category_idx = CODING_CATEGORY_IDX_EMACS_MULE; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
/* Get values of coding system properties: |
|
|
`post-read-conversion', `pre-write-conversion', |
|
|
`translation-table-for-decode', `translation-table-for-encode'. */ |
|
|
plist = XVECTOR (coding_spec)->contents[3]; |
|
|
/* Pre & post conversion functions should be disabled if |
|
|
inhibit_eol_conversion is nonzero. This is the case that a code |
|
|
conversion function is called while those functions are running. */ |
|
|
if (! inhibit_pre_post_conversion) |
|
|
{ |
|
|
coding->post_read_conversion = Fplist_get (plist, Qpost_read_conversion); |
|
|
coding->pre_write_conversion = Fplist_get (plist, Qpre_write_conversion); |
|
|
} |
|
|
val = Fplist_get (plist, Qtranslation_table_for_decode); |
|
|
if (SYMBOLP (val)) |
|
|
val = Fget (val, Qtranslation_table_for_decode); |
|
|
coding->translation_table_for_decode = CHAR_TABLE_P (val) ? val : Qnil; |
|
|
val = Fplist_get (plist, Qtranslation_table_for_encode); |
|
|
if (SYMBOLP (val)) |
|
|
val = Fget (val, Qtranslation_table_for_encode); |
|
|
coding->translation_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; |
|
4904 |
} |
} |
4905 |
else |
else if (EQ (coding_type, Qutf_16)) |
|
goto label_invalid_coding_system; |
|
|
|
|
|
/* If the coding system has non-nil `composition' property, enable |
|
|
composition handling. */ |
|
|
val = Fplist_get (plist, Qcomposition); |
|
|
if (!NILP (val)) |
|
|
coding->composing = COMPOSITION_NO; |
|
|
|
|
|
switch (XFASTINT (coding_type)) |
|
4906 |
{ |
{ |
4907 |
case 0: |
val = AREF (attrs, coding_attr_utf_16_bom); |
4908 |
coding->type = coding_type_emacs_mule; |
CODING_UTF_16_BOM (coding) = (CONSP (val) ? utf_16_detect_bom |
4909 |
|
: EQ (val, Qt) ? utf_16_with_bom |
4910 |
|
: utf_16_without_bom); |
4911 |
|
val = AREF (attrs, coding_attr_utf_16_endian); |
4912 |
|
CODING_UTF_16_ENDIAN (coding) = (EQ (val, Qbig) ? utf_16_big_endian |
4913 |
|
: utf_16_little_endian); |
4914 |
|
CODING_UTF_16_SURROGATE (coding) = 0; |
4915 |
|
coding->detector = detect_coding_utf_16; |
4916 |
|
coding->decoder = decode_coding_utf_16; |
4917 |
|
coding->encoder = encode_coding_utf_16; |
4918 |
coding->common_flags |
coding->common_flags |
4919 |
|= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
4920 |
if (!NILP (coding->post_read_conversion)) |
if (CODING_UTF_16_BOM (coding) == utf_16_detect_bom) |
4921 |
coding->common_flags |= CODING_REQUIRE_DECODING_MASK; |
coding->common_flags |= CODING_REQUIRE_DETECTION_MASK; |
4922 |
if (!NILP (coding->pre_write_conversion)) |
} |
4923 |
coding->common_flags |= CODING_REQUIRE_ENCODING_MASK; |
else if (EQ (coding_type, Qccl)) |
4924 |
break; |
{ |
4925 |
|
coding->detector = detect_coding_ccl; |
4926 |
case 1: |
coding->decoder = decode_coding_ccl; |
4927 |
coding->type = coding_type_sjis; |
coding->encoder = encode_coding_ccl; |
4928 |
coding->common_flags |
coding->common_flags |
4929 |
|= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK |
4930 |
break; |
| CODING_REQUIRE_FLUSHING_MASK); |
4931 |
|
} |
4932 |
case 2: |
else if (EQ (coding_type, Qemacs_mule)) |
4933 |
coding->type = coding_type_iso2022; |
{ |
4934 |
|
coding->detector = detect_coding_emacs_mule; |
4935 |
|
coding->decoder = decode_coding_emacs_mule; |
4936 |
|
coding->encoder = encode_coding_emacs_mule; |
4937 |
coding->common_flags |
coding->common_flags |
4938 |
|= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
4939 |
{ |
if (! NILP (AREF (attrs, coding_attr_emacs_mule_full)) |
4940 |
Lisp_Object val, temp; |
&& ! EQ (CODING_ATTR_CHARSET_LIST (attrs), Vemacs_mule_charset_list)) |
4941 |
Lisp_Object *flags; |
{ |
4942 |
int i, charset, reg_bits = 0; |
Lisp_Object tail, safe_charsets; |
4943 |
|
int max_charset_id = 0; |
4944 |
val = XVECTOR (coding_spec)->contents[4]; |
|
4945 |
|
for (tail = Vemacs_mule_charset_list; CONSP (tail); |
4946 |
if (!VECTORP (val) || XVECTOR (val)->size != 32) |
tail = XCDR (tail)) |
4947 |
goto label_invalid_coding_system; |
if (max_charset_id < XFASTINT (XCAR (tail))) |
4948 |
|
max_charset_id = XFASTINT (XCAR (tail)); |
4949 |
flags = XVECTOR (val)->contents; |
safe_charsets = Fmake_string (make_number (max_charset_id + 1), |
4950 |
coding->flags |
make_number (255)); |
4951 |
= ((NILP (flags[4]) ? 0 : CODING_FLAG_ISO_SHORT_FORM) |
for (tail = Vemacs_mule_charset_list; CONSP (tail); |
4952 |
| (NILP (flags[5]) ? 0 : CODING_FLAG_ISO_RESET_AT_EOL) |
tail = XCDR (tail)) |
4953 |
| (NILP (flags[6]) ? 0 : CODING_FLAG_ISO_RESET_AT_CNTL) |
SSET (safe_charsets, XFASTINT (XCAR (tail)), 0); |
4954 |
| (NILP (flags[7]) ? 0 : CODING_FLAG_ISO_SEVEN_BITS) |
coding->max_charset_id = max_charset_id; |
4955 |
| (NILP (flags[8]) ? 0 : CODING_FLAG_ISO_LOCKING_SHIFT) |
coding->safe_charsets = (char *) SDATA (safe_charsets); |
4956 |
| (NILP (flags[9]) ? 0 : CODING_FLAG_ISO_SINGLE_SHIFT) |
} |
4957 |
| (NILP (flags[10]) ? 0 : CODING_FLAG_ISO_USE_ROMAN) |
} |
4958 |
| (NILP (flags[11]) ? 0 : CODING_FLAG_ISO_USE_OLDJIS) |
else if (EQ (coding_type, Qshift_jis)) |
4959 |
| (NILP (flags[12]) ? 0 : CODING_FLAG_ISO_NO_DIRECTION) |
{ |
4960 |
| (NILP (flags[13]) ? 0 : CODING_FLAG_ISO_INIT_AT_BOL) |
coding->detector = detect_coding_sjis; |
4961 |
| (NILP (flags[14]) ? 0 : CODING_FLAG_ISO_DESIGNATE_AT_BOL) |
coding->decoder = decode_coding_sjis; |
4962 |
| (NILP (flags[15]) ? 0 : CODING_FLAG_ISO_SAFE) |
coding->encoder = encode_coding_sjis; |
|
| (NILP (flags[16]) ? 0 : CODING_FLAG_ISO_LATIN_EXTRA) |
|
|
); |
|
|
|
|
|
/* Invoke graphic register 0 to plane 0. */ |
|
|
CODING_SPEC_ISO_INVOCATION (coding, 0) = 0; |
|
|
/* Invoke graphic register 1 to plane 1 if we can use full 8-bit. */ |
|
|
CODING_SPEC_ISO_INVOCATION (coding, 1) |
|
|
= (coding->flags & CODING_FLAG_ISO_SEVEN_BITS ? -1 : 1); |
|
|
/* Not single shifting at first. */ |
|
|
CODING_SPEC_ISO_SINGLE_SHIFTING (coding) = 0; |
|
|
/* Beginning of buffer should also be regarded as bol. */ |
|
|
CODING_SPEC_ISO_BOL (coding) = 1; |
|
|
|
|
|
for (charset = 0; charset <= MAX_CHARSET; charset++) |
|
|
CODING_SPEC_ISO_REVISION_NUMBER (coding, charset) = 255; |
|
|
val = Vcharset_revision_alist; |
|
|
while (CONSP (val)) |
|
|
{ |
|
|
charset = get_charset_id (Fcar_safe (XCAR (val))); |
|
|
if (charset >= 0 |
|
|
&& (temp = Fcdr_safe (XCAR (val)), INTEGERP (temp)) |
|
|
&& (i = XINT (temp), (i >= 0 && (i + '@') < 128))) |
|
|
CODING_SPEC_ISO_REVISION_NUMBER (coding, charset) = i; |
|
|
val = XCDR (val); |
|
|
} |
|
|
|
|
|
/* Checks FLAGS[REG] (REG = 0, 1, 2 3) and decide designations. |
|
|
FLAGS[REG] can be one of below: |
|
|
integer CHARSET: CHARSET occupies register I, |
|
|
t: designate nothing to REG initially, but can be used |
|
|
by any charsets, |
|
|
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 charsets, |
|
|
nil: REG is never used. */ |
|
|
for (charset = 0; charset <= MAX_CHARSET; charset++) |
|
|
CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) |
|
|
= CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION; |
|
|
for (i = 0; i < 4; i++) |
|
|
{ |
|
|
if ((INTEGERP (flags[i]) |
|
|
&& (charset = XINT (flags[i]), CHARSET_VALID_P (charset))) |
|
|
|| (charset = get_charset_id (flags[i])) >= 0) |
|
|
{ |
|
|
CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset; |
|
|
CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) = i; |
|
|
} |
|
|
else if (EQ (flags[i], Qt)) |
|
|
{ |
|
|
CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1; |
|
|
reg_bits |= 1 << i; |
|
|
coding->flags |= CODING_FLAG_ISO_DESIGNATION; |
|
|
} |
|
|
else if (CONSP (flags[i])) |
|
|
{ |
|
|
Lisp_Object tail; |
|
|
tail = flags[i]; |
|
|
|
|
|
coding->flags |= CODING_FLAG_ISO_DESIGNATION; |
|
|
if ((INTEGERP (XCAR (tail)) |
|
|
&& (charset = XINT (XCAR (tail)), |
|
|
CHARSET_VALID_P (charset))) |
|
|
|| (charset = get_charset_id (XCAR (tail))) >= 0) |
|
|
{ |
|
|
CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = charset; |
|
|
CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) =i; |
|
|
} |
|
|
else |
|
|
CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1; |
|
|
tail = XCDR (tail); |
|
|
while (CONSP (tail)) |
|
|
{ |
|
|
if ((INTEGERP (XCAR (tail)) |
|
|
&& (charset = XINT (XCAR (tail)), |
|
|
CHARSET_VALID_P (charset))) |
|
|
|| (charset = get_charset_id (XCAR (tail))) >= 0) |
|
|
CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) |
|
|
= i; |
|
|
else if (EQ (XCAR (tail), Qt)) |
|
|
reg_bits |= 1 << i; |
|
|
tail = XCDR (tail); |
|
|
} |
|
|
} |
|
|
else |
|
|
CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i) = -1; |
|
|
|
|
|
CODING_SPEC_ISO_DESIGNATION (coding, i) |
|
|
= CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, i); |
|
|
} |
|
|
|
|
|
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) |
|
|
reg_bits &= ~2; |
|
|
if (! (coding->flags & CODING_FLAG_ISO_SINGLE_SHIFT)) |
|
|
/* Without any shifting, only REG 0 and 1 can be used. */ |
|
|
reg_bits &= 3; |
|
|
} |
|
|
|
|
|
if (reg_bits) |
|
|
for (charset = 0; charset <= MAX_CHARSET; charset++) |
|
|
{ |
|
|
if (CHARSET_DEFINED_P (charset) |
|
|
&& (CODING_SPEC_ISO_REQUESTED_DESIGNATION (coding, charset) |
|
|
== CODING_SPEC_ISO_NO_REQUESTED_DESIGNATION)) |
|
|
{ |
|
|
/* There exist some default graphic registers to be |
|
|
used by 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: |
|
|
coding->type = coding_type_big5; |
|
4963 |
coding->common_flags |
coding->common_flags |
4964 |
|= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
4965 |
coding->flags |
} |
4966 |
= (NILP (XVECTOR (coding_spec)->contents[4]) |
else if (EQ (coding_type, Qbig5)) |
4967 |
? CODING_FLAG_BIG5_HKU |
{ |
4968 |
: CODING_FLAG_BIG5_ETEN); |
coding->detector = detect_coding_big5; |
4969 |
break; |
coding->decoder = decode_coding_big5; |
4970 |
|
coding->encoder = encode_coding_big5; |
|
case 4: |
|
|
coding->type = coding_type_ccl; |
|
4971 |
coding->common_flags |
coding->common_flags |
4972 |
|= CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK; |
|= (CODING_REQUIRE_DECODING_MASK | CODING_REQUIRE_ENCODING_MASK); |
4973 |
{ |
} |
4974 |
val = XVECTOR (coding_spec)->contents[4]; |
else /* EQ (coding_type, Qraw_text) */ |
4975 |
if (! CONSP (val) |
{ |
4976 |
|| setup_ccl_program (&(coding->spec.ccl.decoder), |
coding->detector = NULL; |
4977 |
XCAR (val)) < 0 |
coding->decoder = decode_coding_raw_text; |
4978 |
|| setup_ccl_program (&(coding->spec.ccl.encoder), |
coding->encoder = encode_coding_raw_text; |
|
XCDR (val)) < 0) |
|
|
goto label_invalid_coding_system; |
|
|
|
|
|
bzero (coding->spec.ccl.valid_codes, 256); |
|
|
val = Fplist_get (plist, Qvalid_codes); |
|
|
if (CONSP (val)) |
|
|
{ |
|
|
Lisp_Object this; |
|
|
|
|
|
for (; CONSP (val); val = XCDR (val)) |
|
|
{ |
|
|
this = XCAR (val); |
|
|
if (INTEGERP (this) |
|
|
&& XINT (this) >= 0 && XINT (this) < 256) |
|
|
coding->spec.ccl.valid_codes[XINT (this)] = 1; |
|
|
else if (CONSP (this) |
|
|
&& INTEGERP (XCAR (this)) |
|
|
&& INTEGERP (XCDR (this))) |
|
|
{ |
|
|
int start = XINT (XCAR (this)); |
|
|
int end = XINT (XCDR (this)); |
|
|
|
|
|
if (start >= 0 && start <= end && end < 256) |
|
|
while (start <= end) |
|
|
coding->spec.ccl.valid_codes[start++] = 1; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
coding->common_flags |= CODING_REQUIRE_FLUSHING_MASK; |
|
|
coding->spec.ccl.cr_carryover = 0; |
|
|
coding->spec.ccl.eight_bit_carryover[0] = 0; |
|
|
break; |
|
|
|
|
|
case 5: |
|
|
coding->type = coding_type_raw_text; |
|
|
break; |
|
|
|
|
|
default: |
|
|
goto label_invalid_coding_system; |
|
4979 |
} |
} |
|
return 0; |
|
4980 |
|
|
4981 |
label_invalid_coding_system: |
return; |
|
coding->type = coding_type_no_conversion; |
|
|
coding->category_idx = CODING_CATEGORY_IDX_BINARY; |
|
|
coding->common_flags = 0; |
|
|
coding->eol_type = CODING_EOL_LF; |
|
|
coding->pre_write_conversion = coding->post_read_conversion = Qnil; |
|
|
return -1; |
|
4982 |
} |
} |
4983 |
|
|
4984 |
/* Free memory blocks allocated for storing composition information. */ |
/* Return raw-text or one of its subsidiaries that has the same |
4985 |
|
eol_type as CODING-SYSTEM. */ |
4986 |
|
|
4987 |
void |
Lisp_Object |
4988 |
coding_free_composition_data (coding) |
raw_text_coding_system (coding_system) |
4989 |
struct coding_system *coding; |
Lisp_Object coding_system; |
4990 |
{ |
{ |
4991 |
struct composition_data *cmp_data = coding->cmp_data, *next; |
Lisp_Object spec, attrs; |
4992 |
|
Lisp_Object eol_type, raw_text_eol_type; |
4993 |
|
|
4994 |
if (!cmp_data) |
if (NILP (coding_system)) |
4995 |
return; |
return Qraw_text; |
4996 |
/* Memory blocks are chained. At first, rewind to the first, then, |
spec = CODING_SYSTEM_SPEC (coding_system); |
4997 |
free blocks one by one. */ |
attrs = AREF (spec, 0); |
|
while (cmp_data->prev) |
|
|
cmp_data = cmp_data->prev; |
|
|
while (cmp_data) |
|
|
{ |
|
|
next = cmp_data->next; |
|
|
xfree (cmp_data); |
|
|
cmp_data = next; |
|
|
} |
|
|
coding->cmp_data = NULL; |
|
|
} |
|
|
|
|
|
/* Set `char_offset' member of all memory blocks pointed by |
|
|
coding->cmp_data to POS. */ |
|
4998 |
|
|
4999 |
void |
if (EQ (CODING_ATTR_TYPE (attrs), Qraw_text)) |
5000 |
coding_adjust_composition_offset (coding, pos) |
return coding_system; |
|
struct coding_system *coding; |
|
|
int pos; |
|
|
{ |
|
|
struct composition_data *cmp_data; |
|
5001 |
|
|
5002 |
for (cmp_data = coding->cmp_data; cmp_data; cmp_data = cmp_data->next) |
eol_type = AREF (spec, 2); |
5003 |
cmp_data->char_offset = pos; |
if (VECTORP (eol_type)) |
5004 |
|
return Qraw_text; |
5005 |
|
spec = CODING_SYSTEM_SPEC (Qraw_text); |
5006 |
|
raw_text_eol_type = AREF (spec, 2); |
5007 |
|
return (EQ (eol_type, Qunix) ? AREF (raw_text_eol_type, 0) |
5008 |
|
: EQ (eol_type, Qdos) ? AREF (raw_text_eol_type, 1) |
5009 |
|
: AREF (raw_text_eol_type, 2)); |
5010 |
} |
} |
5011 |
|
|
|
/* Setup raw-text or one of its subsidiaries in the structure |
|
|
coding_system CODING according to the already setup value eol_type |
|
|
in CODING. CODING should be setup for some coding system in |
|
|
advance. */ |
|
5012 |
|
|
5013 |
void |
/* If CODING_SYSTEM doesn't specify end-of-line format but PARENT |
5014 |
setup_raw_text_coding_system (coding) |
does, return one of the subsidiary that has the same eol-spec as |
5015 |
struct coding_system *coding; |
PARENT. Otherwise, return CODING_SYSTEM. */ |
5016 |
|
|
5017 |
|
Lisp_Object |
5018 |
|
coding_inherit_eol_type (coding_system, parent) |
5019 |
|
Lisp_Object coding_system, parent; |
5020 |
{ |
{ |
5021 |
if (coding->type != coding_type_raw_text) |
Lisp_Object spec, attrs, eol_type; |
|
{ |
|
|
coding->symbol = Qraw_text; |
|
|
coding->type = coding_type_raw_text; |
|
|
if (coding->eol_type != CODING_EOL_UNDECIDED) |
|
|
{ |
|
|
Lisp_Object subsidiaries; |
|
|
subsidiaries = Fget (Qraw_text, Qeol_type); |
|
5022 |
|
|
5023 |
if (VECTORP (subsidiaries) |
if (NILP (coding_system)) |
5024 |
&& XVECTOR (subsidiaries)->size == 3) |
coding_system = Qraw_text; |
5025 |
coding->symbol |
spec = CODING_SYSTEM_SPEC (coding_system); |
5026 |
= XVECTOR (subsidiaries)->contents[coding->eol_type]; |
attrs = AREF (spec, 0); |
5027 |
} |
eol_type = AREF (spec, 2); |
5028 |
setup_coding_system (coding->symbol, coding); |
if (VECTORP (eol_type) |
5029 |
|
&& ! NILP (parent)) |
5030 |
|
{ |
5031 |
|
Lisp_Object parent_spec; |
5032 |
|
Lisp_Object parent_eol_type; |
5033 |
|
|
5034 |
|
parent_spec |
5035 |
|
= CODING_SYSTEM_SPEC (buffer_defaults.buffer_file_coding_system); |
5036 |
|
parent_eol_type = AREF (parent_spec, 2); |
5037 |
|
if (EQ (parent_eol_type, Qunix)) |
5038 |
|
coding_system = AREF (eol_type, 0); |
5039 |
|
else if (EQ (parent_eol_type, Qdos)) |
5040 |
|
coding_system = AREF (eol_type, 1); |
5041 |
|
else if (EQ (parent_eol_type, Qmac)) |
5042 |
|
coding_system = AREF (eol_type, 2); |
5043 |
} |
} |
5044 |
return; |
return coding_system; |
5045 |
} |
} |
5046 |
|
|
5047 |
/* Emacs has a mechanism to automatically detect a coding system if it |
/* Emacs has a mechanism to automatically detect a coding system if it |
5094 |
o coding-category-iso-7-else |
o coding-category-iso-7-else |
5095 |
|
|
5096 |
The category for a coding system which has the same code range |
The category for a coding system which has the same code range |
5097 |
as ISO2022 of 7-bit environment but uses locking shift or |
as ISO2022 of 7-bit environemnt but uses locking shift or |
5098 |
single shift functions. Assigned the coding-system (Lisp |
single shift functions. Assigned the coding-system (Lisp |
5099 |
symbol) `iso-2022-7bit-lock' by default. |
symbol) `iso-2022-7bit-lock' by default. |
5100 |
|
|
5101 |
o coding-category-iso-8-else |
o coding-category-iso-8-else |
5102 |
|
|
5103 |
The category for a coding system which has the same code range |
The category for a coding system which has the same code range |
5104 |
as ISO2022 of 8-bit environment but uses locking shift or |
as ISO2022 of 8-bit environemnt but uses locking shift or |
5105 |
single shift functions. Assigned the coding-system (Lisp |
single shift functions. Assigned the coding-system (Lisp |
5106 |
symbol) `iso-2022-8bit-ss2' by default. |
symbol) `iso-2022-8bit-ss2' by default. |
5107 |
|
|
5144 |
`no-conversion' by default. |
`no-conversion' by default. |
5145 |
|
|
5146 |
Each of them is a Lisp symbol and the value is an actual |
Each of them is a Lisp symbol and the value is an actual |
5147 |
`coding-system' (this is also a Lisp symbol) assigned by a user. |
`coding-system's (this is also a Lisp symbol) assigned by a user. |
5148 |
What Emacs does actually is to detect a category of coding system. |
What Emacs does actually is to detect a category of coding system. |
5149 |
Then, it uses a `coding-system' assigned to it. If Emacs can't |
Then, it uses a `coding-system' assigned to it. If Emacs can't |
5150 |
decide a single possible category, it selects a category of the |
decide only one possible category, it selects a category of the |
5151 |
highest priority. Priorities of categories are also specified by a |
highest priority. Priorities of categories are also specified by a |
5152 |
user in a Lisp variable `coding-category-list'. |
user in a Lisp variable `coding-category-list'. |
5153 |
|
|
5154 |
*/ |
*/ |
5155 |
|
|
5156 |
static |
#define EOL_SEEN_NONE 0 |
5157 |
int ascii_skip_code[256]; |
#define EOL_SEEN_LF 1 |
5158 |
|
#define EOL_SEEN_CR 2 |
5159 |
|
#define EOL_SEEN_CRLF 4 |
5160 |
|
|
5161 |
|
/* Detect how end-of-line of a text of length SRC_BYTES pointed by |
5162 |
|
SOURCE is encoded. If CATEGORY is one of |
5163 |
|
coding_category_utf_16_XXXX, assume that CR and LF are encoded by |
5164 |
|
two-byte, else they are encoded by one-byte. |
5165 |
|
|
5166 |
/* Detect how a text of length SRC_BYTES pointed by SOURCE is encoded. |
Return one of EOL_SEEN_XXX. */ |
|
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'. If PRIORITIES is non-NULL, |
|
|
it should point the table `coding_priorities'. In that case, only |
|
|
the flag bit for a coding system of the highest priority is set in |
|
|
the returned value. If MULTIBYTEP is nonzero, 8-bit codes of the |
|
|
range 0x80..0x9F are in multibyte form. |
|
5167 |
|
|
5168 |
How many ASCII characters are at the head is returned as *SKIP. */ |
#define MAX_EOL_CHECK_COUNT 3 |
5169 |
|
|
5170 |
static int |
static int |
5171 |
detect_coding_mask (source, src_bytes, priorities, skip, multibytep) |
detect_eol (source, src_bytes, category) |
5172 |
unsigned char *source; |
unsigned char *source; |
5173 |
int src_bytes, *priorities, *skip; |
EMACS_INT src_bytes; |
5174 |
int multibytep; |
enum coding_category category; |
5175 |
{ |
{ |
5176 |
register unsigned char c; |
unsigned char *src = source, *src_end = src + src_bytes; |
5177 |
unsigned char *src = source, *src_end = source + src_bytes; |
unsigned char c; |
5178 |
unsigned int mask, utf16_examined_p, iso2022_examined_p; |
int total = 0; |
5179 |
int i; |
int eol_seen = EOL_SEEN_NONE; |
5180 |
|
|
5181 |
/* At first, skip all ASCII characters and control characters except |
if ((1 << category) & CATEGORY_MASK_UTF_16) |
5182 |
for three ISO2022 specific control characters. */ |
{ |
5183 |
ascii_skip_code[ISO_CODE_SO] = 0; |
int msb, lsb; |
5184 |
ascii_skip_code[ISO_CODE_SI] = 0; |
|
5185 |
ascii_skip_code[ISO_CODE_ESC] = 0; |
msb = category == (coding_category_utf_16_le |
5186 |
|
| coding_category_utf_16_le_nosig); |
5187 |
label_loop_detect_coding: |
lsb = 1 - msb; |
5188 |
while (src < src_end && ascii_skip_code[*src]) src++; |
|
5189 |
*skip = src - source; |
while (src + 1 < src_end) |
|
|
|
|
if (src >= src_end) |
|
|
/* We found nothing other than ASCII. There's nothing to do. */ |
|
|
return 0; |
|
|
|
|
|
c = *src; |
|
|
/* The text seems to be encoded in some multilingual coding system. |
|
|
Now, try to find in which coding system the text is encoded. */ |
|
|
if (c < 0x80) |
|
|
{ |
|
|
/* 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, multibytep); |
|
|
if (mask == 0) |
|
|
{ |
|
|
/* No valid ISO2022 code follows C. Try again. */ |
|
|
src++; |
|
|
if (c == ISO_CODE_ESC) |
|
|
ascii_skip_code[ISO_CODE_ESC] = 1; |
|
|
else |
|
|
ascii_skip_code[ISO_CODE_SO] = ascii_skip_code[ISO_CODE_SI] = 1; |
|
|
goto label_loop_detect_coding; |
|
|
} |
|
|
if (priorities) |
|
5190 |
{ |
{ |
5191 |
for (i = 0; i < CODING_CATEGORY_IDX_MAX; i++) |
c = src[lsb]; |
5192 |
|
if (src[msb] == 0 && (c == '\n' || c == '\r')) |
5193 |
{ |
{ |
5194 |
if (mask & priorities[i]) |
int this_eol; |
5195 |
return priorities[i]; |
|
5196 |
|
if (c == '\n') |
5197 |
|
this_eol = EOL_SEEN_LF; |
5198 |
|
else if (src + 3 >= src_end |
5199 |
|
|| src[msb + 2] != 0 |
5200 |
|
|| src[lsb + 2] != '\n') |
5201 |
|
this_eol = EOL_SEEN_CR; |
5202 |
|
else |
5203 |
|
this_eol = EOL_SEEN_CRLF; |
5204 |
|
|
5205 |
|
if (eol_seen == EOL_SEEN_NONE) |
5206 |
|
/* This is the first end-of-line. */ |
5207 |
|
eol_seen = this_eol; |
5208 |
|
else if (eol_seen != this_eol) |
5209 |
|
{ |
5210 |
|
/* The found type is different from what found before. */ |
5211 |
|
eol_seen = EOL_SEEN_LF; |
5212 |
|
break; |
5213 |
|
} |
5214 |
|
if (++total == MAX_EOL_CHECK_COUNT) |
5215 |
|
break; |
5216 |
} |
} |
5217 |
return CODING_CATEGORY_MASK_RAW_TEXT; |
src += 2; |
5218 |
} |
} |
5219 |
} |
} |
5220 |
else |
else |
5221 |
{ |
{ |
5222 |
int try; |
while (src < src_end) |
5223 |
|
{ |
5224 |
|
c = *src++; |
5225 |
|
if (c == '\n' || c == '\r') |
5226 |
|
{ |
5227 |
|
int this_eol; |
5228 |
|
|
5229 |
if (multibytep && c == LEADING_CODE_8_BIT_CONTROL) |
if (c == '\n') |
5230 |
c = src[1] - 0x20; |
this_eol = EOL_SEEN_LF; |
5231 |
|
else if (src >= src_end || *src != '\n') |
5232 |
|
this_eol = EOL_SEEN_CR; |
5233 |
|
else |
5234 |
|
this_eol = EOL_SEEN_CRLF, src++; |
5235 |
|
|
5236 |
if (c < 0xA0) |
if (eol_seen == EOL_SEEN_NONE) |
5237 |
{ |
/* This is the first end-of-line. */ |
5238 |
/* C is the first byte of SJIS character code, |
eol_seen = this_eol; |
5239 |
or a leading-code of Emacs' internal format (emacs-mule), |
else if (eol_seen != this_eol) |
5240 |
or the first byte of UTF-16. */ |
{ |
5241 |
try = (CODING_CATEGORY_MASK_SJIS |
/* The found type is different from what found before. */ |
5242 |
| CODING_CATEGORY_MASK_EMACS_MULE |
eol_seen = EOL_SEEN_LF; |
5243 |
| CODING_CATEGORY_MASK_UTF_16_BE |
break; |
5244 |
| CODING_CATEGORY_MASK_UTF_16_LE); |
} |
5245 |
|
if (++total == MAX_EOL_CHECK_COUNT) |
5246 |
/* Or, if C is a special latin extra code, |
break; |
5247 |
or is an ISO2022 specific control code of C1 (SS2 or SS3), |
} |
5248 |
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, |
|
|
or the first byte of UTF-8/16. */ |
|
|
try = (CODING_CATEGORY_MASK_ISO_8_ELSE |
|
|
| CODING_CATEGORY_MASK_ISO_8BIT |
|
|
| CODING_CATEGORY_MASK_SJIS |
|
|
| CODING_CATEGORY_MASK_BIG5 |
|
|
| CODING_CATEGORY_MASK_UTF_8 |
|
|
| CODING_CATEGORY_MASK_UTF_16_BE |
|
|
| CODING_CATEGORY_MASK_UTF_16_LE); |
|
|
|
|
|
/* Or, we may have to consider the possibility of CCL. */ |
|
|
if (coding_system_table[CODING_CATEGORY_IDX_CCL] |
|
|
&& (coding_system_table[CODING_CATEGORY_IDX_CCL] |
|
|
->spec.ccl.valid_codes)[c]) |
|
|
try |= CODING_CATEGORY_MASK_CCL; |
|
|
|
|
|
mask = 0; |
|
|
utf16_examined_p = iso2022_examined_p = 0; |
|
|
if (priorities) |
|
|
{ |
|
|
for (i = 0; i < CODING_CATEGORY_IDX_MAX; i++) |
|
|
{ |
|
|
if (!iso2022_examined_p |
|
|
&& (priorities[i] & try & CODING_CATEGORY_MASK_ISO)) |
|
|
{ |
|
|
mask |= detect_coding_iso2022 (src, src_end, multibytep); |
|
|
iso2022_examined_p = 1; |
|
|
} |
|
|
else if (priorities[i] & try & CODING_CATEGORY_MASK_SJIS) |
|
|
mask |= detect_coding_sjis (src, src_end, multibytep); |
|
|
else if (priorities[i] & try & CODING_CATEGORY_MASK_UTF_8) |
|
|
mask |= detect_coding_utf_8 (src, src_end, multibytep); |
|
|
else if (!utf16_examined_p |
|
|
&& (priorities[i] & try & |
|
|
CODING_CATEGORY_MASK_UTF_16_BE_LE)) |
|
|
{ |
|
|
mask |= detect_coding_utf_16 (src, src_end, multibytep); |
|
|
utf16_examined_p = 1; |
|
|
} |
|
|
else if (priorities[i] & try & CODING_CATEGORY_MASK_BIG5) |
|
|
mask |= detect_coding_big5 (src, src_end, multibytep); |
|
|
else if (priorities[i] & try & CODING_CATEGORY_MASK_EMACS_MULE) |
|
|
mask |= detect_coding_emacs_mule (src, src_end, multibytep); |
|
|
else if (priorities[i] & try & CODING_CATEGORY_MASK_CCL) |
|
|
mask |= detect_coding_ccl (src, src_end, multibytep); |
|
|
else if (priorities[i] & CODING_CATEGORY_MASK_RAW_TEXT) |
|
|
mask |= CODING_CATEGORY_MASK_RAW_TEXT; |
|
|
else if (priorities[i] & CODING_CATEGORY_MASK_BINARY) |
|
|
mask |= CODING_CATEGORY_MASK_BINARY; |
|
|
if (mask & priorities[i]) |
|
|
return priorities[i]; |
|
|
} |
|
|
return CODING_CATEGORY_MASK_RAW_TEXT; |
|
|
} |
|
|
if (try & CODING_CATEGORY_MASK_ISO) |
|
|
mask |= detect_coding_iso2022 (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_SJIS) |
|
|
mask |= detect_coding_sjis (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_BIG5) |
|
|
mask |= detect_coding_big5 (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_UTF_8) |
|
|
mask |= detect_coding_utf_8 (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_UTF_16_BE_LE) |
|
|
mask |= detect_coding_utf_16 (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_EMACS_MULE) |
|
|
mask |= detect_coding_emacs_mule (src, src_end, multibytep); |
|
|
if (try & CODING_CATEGORY_MASK_CCL) |
|
|
mask |= detect_coding_ccl (src, src_end, multibytep); |
|
5249 |
} |
} |
5250 |
return (mask | CODING_CATEGORY_MASK_RAW_TEXT | CODING_CATEGORY_MASK_BINARY); |
return eol_seen; |
5251 |
} |
} |
5252 |
|
|
|
/* Detect how a text of length SRC_BYTES pointed by SRC is encoded. |
|
|
The information of the detected coding system is set in CODING. */ |
|
5253 |
|
|
5254 |
void |
static void |
5255 |
detect_coding (coding, src, src_bytes) |
adjust_coding_eol_type (coding, eol_seen) |
5256 |
struct coding_system *coding; |
struct coding_system *coding; |
5257 |
const unsigned char *src; |
int eol_seen; |
|
int src_bytes; |
|
5258 |
{ |
{ |
5259 |
unsigned int idx; |
Lisp_Object eol_type; |
|
int skip, mask; |
|
|
Lisp_Object val; |
|
5260 |
|
|
5261 |
val = Vcoding_category_list; |
eol_type = CODING_ID_EOL_TYPE (coding->id); |
5262 |
mask = detect_coding_mask (src, src_bytes, coding_priorities, &skip, |
if (eol_seen & EOL_SEEN_LF) |
5263 |
coding->src_multibyte); |
coding->id = CODING_SYSTEM_ID (AREF (eol_type, 0)); |
5264 |
coding->heading_ascii = skip; |
else if (eol_seen & EOL_SEEN_CRLF) |
5265 |
|
coding->id = CODING_SYSTEM_ID (AREF (eol_type, 1)); |
5266 |
|
else if (eol_seen & EOL_SEEN_CR) |
5267 |
|
coding->id = CODING_SYSTEM_ID (AREF (eol_type, 2)); |
5268 |
|
} |
5269 |
|
|
5270 |
|
/* Detect how a text specified in CODING is encoded. If a coding |
5271 |
|
system is detected, update fields of CODING by the detected coding |
5272 |
|
system. */ |
5273 |
|
|
5274 |
if (!mask) return; |
void |
5275 |
|
detect_coding (coding) |
5276 |
|
struct coding_system *coding; |
5277 |
|
{ |
5278 |
|
const unsigned char *src, *src_end; |
5279 |
|
Lisp_Object attrs, coding_type; |
5280 |
|
|
5281 |
/* We found a single coding system of the highest priority in MASK. */ |
coding->consumed = coding->consumed_char = 0; |
5282 |
idx = 0; |
coding->produced = coding->produced_char = 0; |
5283 |
while (mask && ! (mask & 1)) mask >>= 1, idx++; |
coding_set_source (coding); |
|
if (! mask) |
|
|
idx = CODING_CATEGORY_IDX_RAW_TEXT; |
|
5284 |
|
|
5285 |
val = SYMBOL_VALUE (XVECTOR (Vcoding_category_table)->contents[idx]); |
src_end = coding->source + coding->src_bytes; |
5286 |
|
|
5287 |
if (coding->eol_type != CODING_EOL_UNDECIDED) |
/* If we have not yet decided the text encoding type, detect it |
5288 |
|
now. */ |
5289 |
|
if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qundecided)) |
5290 |
{ |
{ |
5291 |
Lisp_Object tmp; |
int c, i; |
|
|
|
|
tmp = Fget (val, Qeol_type); |
|
|
if (VECTORP (tmp)) |
|
|
val = XVECTOR (tmp)->contents[coding->eol_type]; |
|
|
} |
|
|
|
|
|
/* Setup this new coding system while preserving some slots. */ |
|
|
{ |
|
|
int src_multibyte = coding->src_multibyte; |
|
|
int dst_multibyte = coding->dst_multibyte; |
|
|
|
|
|
setup_coding_system (val, coding); |
|
|
coding->src_multibyte = src_multibyte; |
|
|
coding->dst_multibyte = dst_multibyte; |
|
|
coding->heading_ascii = skip; |
|
|
} |
|
|
} |
|
|
|
|
|
/* 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 |
|
|
|
|
|
static int |
|
|
detect_eol_type (source, src_bytes, skip) |
|
|
unsigned char *source; |
|
|
int src_bytes, *skip; |
|
|
{ |
|
|
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; |
|
5292 |
|
|
5293 |
while (src < src_end && total < MAX_EOL_CHECK_COUNT) |
for (src = coding->source; src < src_end; src++) |
|
{ |
|
|
c = *src++; |
|
|
if (c == '\n' || c == '\r') |
|
5294 |
{ |
{ |
5295 |
if (*skip == 0) |
c = *src; |
5296 |
*skip = src - 1 - source; |
if (c & 0x80 || (c < 0x20 && (c == ISO_CODE_ESC |
5297 |
total++; |
|| c == ISO_CODE_SI |
5298 |
if (c == '\n') |
|| c == ISO_CODE_SO))) |
5299 |
this_eol_type = CODING_EOL_LF; |
break; |
|
else if (src >= src_end || *src != '\n') |
|
|
this_eol_type = CODING_EOL_CR; |
|
|
else |
|
|
this_eol_type = CODING_EOL_CRLF, src++; |
|
|
|
|
|
if (eol_type == CODING_EOL_UNDECIDED) |
|
|
/* 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. */ |
|
|
eol_type = CODING_EOL_INCONSISTENT; |
|
|
break; |
|
|
} |
|
5300 |
} |
} |
5301 |
} |
coding->head_ascii = src - (coding->source + coding->consumed); |
|
|
|
|
if (*skip == 0) |
|
|
*skip = src_end - source; |
|
|
return eol_type; |
|
|
} |
|
|
|
|
|
/* Like detect_eol_type, but detect EOL type in 2-octet |
|
|
big-endian/little-endian format for coding systems utf-16-be and |
|
|
utf-16-le. */ |
|
|
|
|
|
static int |
|
|
detect_eol_type_in_2_octet_form (source, src_bytes, skip, big_endian_p) |
|
|
unsigned char *source; |
|
|
int src_bytes, *skip, big_endian_p; |
|
|
{ |
|
|
unsigned char *src = source, *src_end = src + src_bytes; |
|
|
unsigned int c1, c2; |
|
|
int total = 0; /* How many end-of-lines are found so far. */ |
|
|
int eol_type = CODING_EOL_UNDECIDED; |
|
|
int this_eol_type; |
|
|
int msb, lsb; |
|
|
|
|
|
if (big_endian_p) |
|
|
msb = 0, lsb = 1; |
|
|
else |
|
|
msb = 1, lsb = 0; |
|
|
|
|
|
*skip = 0; |
|
|
|
|
|
while ((src + 1) < src_end && total < MAX_EOL_CHECK_COUNT) |
|
|
{ |
|
|
c1 = (src[msb] << 8) | (src[lsb]); |
|
|
src += 2; |
|
5302 |
|
|
5303 |
if (c1 == '\n' || c1 == '\r') |
if (coding->head_ascii < coding->src_bytes) |
5304 |
{ |
{ |
5305 |
if (*skip == 0) |
struct coding_detection_info detect_info; |
5306 |
*skip = src - 2 - source; |
enum coding_category category; |
5307 |
total++; |
struct coding_system *this; |
5308 |
if (c1 == '\n') |
|
5309 |
{ |
detect_info.checked = detect_info.found = detect_info.rejected = 0; |
5310 |
this_eol_type = CODING_EOL_LF; |
for (i = 0; i < coding_category_raw_text; i++) |
|
} |
|
|
else |
|
5311 |
{ |
{ |
5312 |
if ((src + 1) >= src_end) |
category = coding_priorities[i]; |
5313 |
|
this = coding_categories + category; |
5314 |
|
if (this->id < 0) |
5315 |
{ |
{ |
5316 |
this_eol_type = CODING_EOL_CR; |
/* No coding system of this category is defined. */ |
5317 |
|
detect_info.rejected |= (1 << category); |
5318 |
} |
} |
5319 |
else |
else if (category >= coding_category_raw_text) |
5320 |
|
continue; |
5321 |
|
else if (detect_info.checked & (1 << category)) |
5322 |
{ |
{ |
5323 |
c2 = (src[msb] << 8) | (src[lsb]); |
if (detect_info.found & (1 << category)) |
5324 |
if (c2 == '\n') |
break; |
|
this_eol_type = CODING_EOL_CRLF, src += 2; |
|
|
else |
|
|
this_eol_type = CODING_EOL_CR; |
|
5325 |
} |
} |
5326 |
|
else if ((*(this->detector)) (coding, &detect_info) |
5327 |
|
&& detect_info.found & (1 << category)) |
5328 |
|
break; |
5329 |
} |
} |
5330 |
|
if (i < coding_category_raw_text) |
5331 |
if (eol_type == CODING_EOL_UNDECIDED) |
setup_coding_system (CODING_ID_NAME (this->id), coding); |
5332 |
/* This is the first end-of-line. */ |
else if (detect_info.rejected == CATEGORY_MASK_ANY) |
5333 |
eol_type = this_eol_type; |
setup_coding_system (Qraw_text, coding); |
5334 |
else if (eol_type != this_eol_type) |
else if (detect_info.rejected) |
5335 |
{ |
for (i = 0; i < coding_category_raw_text; i++) |
5336 |
/* The found type is different from what found before. */ |
if (! (detect_info.rejected & (1 << coding_priorities[i]))) |
5337 |
eol_type = CODING_EOL_INCONSISTENT; |
{ |
5338 |
break; |
this = coding_categories + coding_priorities[i]; |
5339 |
} |
setup_coding_system (CODING_ID_NAME (this->id), coding); |
5340 |
|
break; |
5341 |
|
} |
5342 |
} |
} |
5343 |
} |
} |
5344 |
|
else if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qutf_16)) |
|
if (*skip == 0) |
|
|
*skip = src_end - source; |
|
|
return eol_type; |
|
|
} |
|
|
|
|
|
/* Detect how end-of-line of a text of length SRC_BYTES pointed by SRC |
|
|
is encoded. If it detects an appropriate format of end-of-line, it |
|
|
sets the information in *CODING. */ |
|
|
|
|
|
void |
|
|
detect_eol (coding, src, src_bytes) |
|
|
struct coding_system *coding; |
|
|
const unsigned char *src; |
|
|
int src_bytes; |
|
|
{ |
|
|
Lisp_Object val; |
|
|
int skip; |
|
|
int eol_type; |
|
|
|
|
|
switch (coding->category_idx) |
|
|
{ |
|
|
case CODING_CATEGORY_IDX_UTF_16_BE: |
|
|
eol_type = detect_eol_type_in_2_octet_form (src, src_bytes, &skip, 1); |
|
|
break; |
|
|
case CODING_CATEGORY_IDX_UTF_16_LE: |
|
|
eol_type = detect_eol_type_in_2_octet_form (src, src_bytes, &skip, 0); |
|
|
break; |
|
|
default: |
|
|
eol_type = detect_eol_type (src, src_bytes, &skip); |
|
|
break; |
|
|
} |
|
|
|
|
|
if (coding->heading_ascii > skip) |
|
|
coding->heading_ascii = skip; |
|
|
else |
|
|
skip = coding->heading_ascii; |
|
|
|
|
|
if (eol_type == CODING_EOL_UNDECIDED) |
|
|
return; |
|
|
if (eol_type == CODING_EOL_INCONSISTENT) |
|
5345 |
{ |
{ |
5346 |
#if 0 |
Lisp_Object coding_systems; |
5347 |
/* This code is suppressed until we find a better way to |
struct coding_detection_info detect_info; |
|
distinguish raw text file and binary file. */ |
|
5348 |
|
|
5349 |
/* If we have already detected that the coding is raw-text, the |
coding_systems |
5350 |
coding should actually be no-conversion. */ |
= AREF (CODING_ID_ATTRS (coding->id), coding_attr_utf_16_bom); |
5351 |
if (coding->type == coding_type_raw_text) |
detect_info.found = detect_info.rejected = 0; |
5352 |
|
if (CONSP (coding_systems) |
5353 |
|
&& detect_coding_utf_16 (coding, &detect_info) |
5354 |
|
&& (detect_info.found & (CATEGORY_MASK_UTF_16_LE |
5355 |
|
| CATEGORY_MASK_UTF_16_BE))) |
5356 |
{ |
{ |
5357 |
setup_coding_system (Qno_conversion, coding); |
if (detect_info.found & CATEGORY_MASK_UTF_16_LE) |
5358 |
return; |
setup_coding_system (XCAR (coding_systems), coding); |
5359 |
|
else |
5360 |
|
setup_coding_system (XCDR (coding_systems), coding); |
5361 |
} |
} |
|
/* Else, let's decode only text code anyway. */ |
|
|
#endif /* 0 */ |
|
|
eol_type = CODING_EOL_LF; |
|
5362 |
} |
} |
5363 |
|
|
5364 |
val = Fget (coding->symbol, Qeol_type); |
attrs = CODING_ID_ATTRS (coding->id); |
5365 |
if (VECTORP (val) && XVECTOR (val)->size == 3) |
coding_type = CODING_ATTR_TYPE (attrs); |
5366 |
|
|
5367 |
|
/* If we have not yet decided the EOL type, detect it now. But, the |
5368 |
|
detection is impossible for a CCL based coding system, in which |
5369 |
|
case, we detct the EOL type after decoding. */ |
5370 |
|
if (VECTORP (CODING_ID_EOL_TYPE (coding->id)) |
5371 |
|
&& ! EQ (coding_type, Qccl)) |
5372 |
{ |
{ |
5373 |
int src_multibyte = coding->src_multibyte; |
int eol_seen = detect_eol (coding->source, coding->src_bytes, |
5374 |
int dst_multibyte = coding->dst_multibyte; |
XINT (CODING_ATTR_CATEGORY (attrs))); |
|
struct composition_data *cmp_data = coding->cmp_data; |
|
5375 |
|
|
5376 |
setup_coding_system (XVECTOR (val)->contents[eol_type], coding); |
if (eol_seen != EOL_SEEN_NONE) |
5377 |
coding->src_multibyte = src_multibyte; |
adjust_coding_eol_type (coding, eol_seen); |
|
coding->dst_multibyte = dst_multibyte; |
|
|
coding->heading_ascii = skip; |
|
|
coding->cmp_data = cmp_data; |
|
5378 |
} |
} |
5379 |
} |
} |
5380 |
|
|
|
#define CONVERSION_BUFFER_EXTRA_ROOM 256 |
|
5381 |
|
|
5382 |
#define DECODING_BUFFER_MAG(coding) \ |
static void |
5383 |
(coding->type == coding_type_iso2022 \ |
decode_eol (coding) |
|
? 3 \ |
|
|
: (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. */ |
|
|
|
|
|
int |
|
|
decoding_buffer_size (coding, src_bytes) |
|
5384 |
struct coding_system *coding; |
struct coding_system *coding; |
|
int src_bytes; |
|
5385 |
{ |
{ |
5386 |
return (src_bytes * DECODING_BUFFER_MAG (coding) |
if (VECTORP (CODING_ID_EOL_TYPE (coding->id))) |
5387 |
+ CONVERSION_BUFFER_EXTRA_ROOM); |
{ |
5388 |
} |
unsigned char *p = CHAR_POS_ADDR (coding->dst_pos); |
5389 |
|
unsigned char *pend = p + coding->produced; |
5390 |
/* Return maximum size (bytes) of a buffer enough for encoding |
int eol_seen = EOL_SEEN_NONE; |
|
SRC_BYTES of text to CODING. */ |
|
5391 |
|
|
5392 |
int |
for (; p < pend; p++) |
5393 |
encoding_buffer_size (coding, src_bytes) |
{ |
5394 |
struct coding_system *coding; |
if (*p == '\n') |
5395 |
int src_bytes; |
eol_seen |= EOL_SEEN_LF; |
5396 |
{ |
else if (*p == '\r') |
5397 |
int magnification; |
{ |
5398 |
|
if (p + 1 < pend && *(p + 1) == '\n') |
5399 |
|
{ |
5400 |
|
eol_seen |= EOL_SEEN_CRLF; |
5401 |
|
p++; |
5402 |
|
} |
5403 |
|
else |
5404 |
|
eol_seen |= EOL_SEEN_CR; |
5405 |
|
} |
5406 |
|
} |
5407 |
|
if (eol_seen != EOL_SEEN_NONE) |
5408 |
|
adjust_coding_eol_type (coding, eol_seen); |
5409 |
|
} |
5410 |
|
|
5411 |
if (coding->type == coding_type_ccl) |
if (EQ (CODING_ID_EOL_TYPE (coding->id), Qmac)) |
5412 |
{ |
{ |
5413 |
magnification = coding->spec.ccl.encoder.buf_magnification; |
unsigned char *p = CHAR_POS_ADDR (coding->dst_pos); |
5414 |
if (coding->eol_type == CODING_EOL_CRLF) |
unsigned char *pend = p + coding->produced; |
5415 |
magnification *= 2; |
|
5416 |
|
for (; p < pend; p++) |
5417 |
|
if (*p == '\r') |
5418 |
|
*p = '\n'; |
5419 |
} |
} |
5420 |
else if (CODING_REQUIRE_ENCODING (coding)) |
else if (EQ (CODING_ID_EOL_TYPE (coding->id), Qdos)) |
5421 |
magnification = 3; |
{ |
5422 |
else |
unsigned char *p, *pbeg, *pend; |
5423 |
magnification = 1; |
Lisp_Object undo_list; |
5424 |
|
|
5425 |
|
move_gap_both (coding->dst_pos + coding->produced_char, |
5426 |
|
coding->dst_pos_byte + coding->produced); |
5427 |
|
undo_list = current_buffer->undo_list; |
5428 |
|
current_buffer->undo_list = Qt; |
5429 |
|
del_range_2 (coding->dst_pos, coding->dst_pos_byte, GPT, GPT_BYTE, 0); |
5430 |
|
current_buffer->undo_list = undo_list; |
5431 |
|
pbeg = GPT_ADDR; |
5432 |
|
pend = pbeg + coding->produced; |
5433 |
|
|
5434 |
return (src_bytes * magnification + CONVERSION_BUFFER_EXTRA_ROOM); |
for (p = pend - 1; p >= pbeg; p--) |
5435 |
|
if (*p == '\r') |
5436 |
|
{ |
5437 |
|
safe_bcopy ((char *) (p + 1), (char *) p, pend - p - 1); |
5438 |
|
pend--; |
5439 |
|
} |
5440 |
|
coding->produced_char -= coding->produced - (pend - pbeg); |
5441 |
|
coding->produced = pend - pbeg; |
5442 |
|
insert_from_gap (coding->produced_char, coding->produced); |
5443 |
|
} |
5444 |
} |
} |
5445 |
|
|
5446 |
/* Working buffer for code conversion. */ |
static void |
5447 |
struct conversion_buffer |
translate_chars (coding, table) |
5448 |
|
struct coding_system *coding; |
5449 |
|
Lisp_Object table; |
5450 |
{ |
{ |
5451 |
int size; /* size of data. */ |
int *charbuf = coding->charbuf; |
5452 |
int on_stack; /* 1 if allocated by alloca. */ |
int *charbuf_end = charbuf + coding->charbuf_used; |
5453 |
unsigned char *data; |
int c; |
|
}; |
|
|
|
|
|
/* Don't use alloca for allocating memory space larger than this, lest |
|
|
we overflow their stack. */ |
|
|
#define MAX_ALLOCA 16*1024 |
|
5454 |
|
|
5455 |
/* Allocate LEN bytes of memory for BUF (struct conversion_buffer). */ |
if (coding->chars_at_source) |
5456 |
#define allocate_conversion_buffer(buf, len) \ |
return; |
|
do { \ |
|
|
if (len < MAX_ALLOCA) \ |
|
|
{ \ |
|
|
buf.data = (unsigned char *) alloca (len); \ |
|
|
buf.on_stack = 1; \ |
|
|
} \ |
|
|
else \ |
|
|
{ \ |
|
|
buf.data = (unsigned char *) xmalloc (len); \ |
|
|
buf.on_stack = 0; \ |
|
|
} \ |
|
|
buf.size = len; \ |
|
|
} while (0) |
|
5457 |
|
|
5458 |
/* Double the allocated memory for *BUF. */ |
while (charbuf < charbuf_end) |
|
static void |
|
|
extend_conversion_buffer (buf) |
|
|
struct conversion_buffer *buf; |
|
|
{ |
|
|
if (buf->on_stack) |
|
|
{ |
|
|
unsigned char *save = buf->data; |
|
|
buf->data = (unsigned char *) xmalloc (buf->size * 2); |
|
|
bcopy (save, buf->data, buf->size); |
|
|
buf->on_stack = 0; |
|
|
} |
|
|
else |
|
5459 |
{ |
{ |
5460 |
buf->data = (unsigned char *) xrealloc (buf->data, buf->size * 2); |
c = *charbuf; |
5461 |
|
if (c < 0) |
5462 |
|
charbuf += c; |
5463 |
|
else |
5464 |
|
*charbuf++ = translate_char (table, c); |
5465 |
} |
} |
|
buf->size *= 2; |
|
5466 |
} |
} |
5467 |
|
|
5468 |
/* Free the allocated memory for BUF if it is not on stack. */ |
static int |
5469 |
static void |
produce_chars (coding) |
|
free_conversion_buffer (buf) |
|
|
struct conversion_buffer *buf; |
|
|
{ |
|
|
if (!buf->on_stack) |
|
|
xfree (buf->data); |
|
|
} |
|
|
|
|
|
int |
|
|
ccl_coding_driver (coding, source, destination, src_bytes, dst_bytes, encodep) |
|
5470 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *source, *destination; |
|
|
int src_bytes, dst_bytes, encodep; |
|
5471 |
{ |
{ |
5472 |
struct ccl_program *ccl |
unsigned char *dst = coding->destination + coding->produced; |
5473 |
= encodep ? &coding->spec.ccl.encoder : &coding->spec.ccl.decoder; |
unsigned char *dst_end = coding->destination + coding->dst_bytes; |
5474 |
unsigned char *dst = destination; |
int produced; |
5475 |
|
int produced_chars = 0; |
5476 |
|
|
5477 |
ccl->suppress_error = coding->suppress_error; |
if (! coding->chars_at_source) |
|
ccl->last_block = coding->mode & CODING_MODE_LAST_BLOCK; |
|
|
if (encodep) |
|
5478 |
{ |
{ |
5479 |
/* On encoding, EOL format is converted within ccl_driver. For |
/* Characters are in coding->charbuf. */ |
5480 |
that, setup proper information in the structure CCL. */ |
int *buf = coding->charbuf; |
5481 |
ccl->eol_type = coding->eol_type; |
int *buf_end = buf + coding->charbuf_used; |
5482 |
if (ccl->eol_type ==CODING_EOL_UNDECIDED) |
unsigned char *adjusted_dst_end; |
|
ccl->eol_type = CODING_EOL_LF; |
|
|
ccl->cr_consumed = coding->spec.ccl.cr_carryover; |
|
|
ccl->eight_bit_control = coding->dst_multibyte; |
|
|
} |
|
|
else |
|
|
ccl->eight_bit_control = 1; |
|
|
ccl->multibyte = coding->src_multibyte; |
|
|
if (coding->spec.ccl.eight_bit_carryover[0] != 0) |
|
|
{ |
|
|
/* Move carryover bytes to DESTINATION. */ |
|
|
unsigned char *p = coding->spec.ccl.eight_bit_carryover; |
|
|
while (*p) |
|
|
*dst++ = *p++; |
|
|
coding->spec.ccl.eight_bit_carryover[0] = 0; |
|
|
if (dst_bytes) |
|
|
dst_bytes -= dst - destination; |
|
|
} |
|
|
|
|
|
coding->produced = (ccl_driver (ccl, source, dst, src_bytes, dst_bytes, |
|
|
&(coding->consumed)) |
|
|
+ dst - destination); |
|
5483 |
|
|
5484 |
if (encodep) |
if (BUFFERP (coding->src_object) |
5485 |
{ |
&& EQ (coding->src_object, coding->dst_object)) |
5486 |
coding->produced_char = coding->produced; |
dst_end = ((unsigned char *) coding->source) + coding->consumed; |
5487 |
coding->spec.ccl.cr_carryover = ccl->cr_consumed; |
adjusted_dst_end = dst_end - MAX_MULTIBYTE_LENGTH; |
|
} |
|
|
else if (!ccl->eight_bit_control) |
|
|
{ |
|
|
/* The produced bytes forms a valid multibyte sequence. */ |
|
|
coding->produced_char |
|
|
= multibyte_chars_in_text (destination, coding->produced); |
|
|
coding->spec.ccl.eight_bit_carryover[0] = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* On decoding, the destination should always multibyte. But, |
|
|
CCL program might have been generated an invalid multibyte |
|
|
sequence. Here we make such a sequence valid as |
|
|
multibyte. */ |
|
|
int bytes |
|
|
= dst_bytes ? dst_bytes : source + coding->consumed - destination; |
|
5488 |
|
|
5489 |
if ((coding->consumed < src_bytes |
while (buf < buf_end) |
|
|| !ccl->last_block) |
|
|
&& coding->produced >= 1 |
|
|
&& destination[coding->produced - 1] >= 0x80) |
|
5490 |
{ |
{ |
5491 |
/* We should not convert the tailing 8-bit codes to |
int c = *buf++; |
|
multibyte form even if they doesn't form a valid |
|
|
multibyte sequence. They may form a valid sequence in |
|
|
the next call. */ |
|
|
int carryover = 0; |
|
5492 |
|
|
5493 |
if (destination[coding->produced - 1] < 0xA0) |
if (dst >= adjusted_dst_end) |
|
carryover = 1; |
|
|
else if (coding->produced >= 2) |
|
5494 |
{ |
{ |
5495 |
if (destination[coding->produced - 2] >= 0x80) |
dst = alloc_destination (coding, |
5496 |
{ |
buf_end - buf + MAX_MULTIBYTE_LENGTH, |
5497 |
if (destination[coding->produced - 2] < 0xA0) |
dst); |
5498 |
carryover = 2; |
dst_end = coding->destination + coding->dst_bytes; |
5499 |
else if (coding->produced >= 3 |
adjusted_dst_end = dst_end - MAX_MULTIBYTE_LENGTH; |
|
&& destination[coding->produced - 3] >= 0x80 |
|
|
&& destination[coding->produced - 3] < 0xA0) |
|
|
carryover = 3; |
|
|
} |
|
5500 |
} |
} |
5501 |
if (carryover > 0) |
if (c >= 0) |
5502 |
{ |
{ |
5503 |
BCOPY_SHORT (destination + coding->produced - carryover, |
if (coding->dst_multibyte |
5504 |
coding->spec.ccl.eight_bit_carryover, |
|| ! CHAR_BYTE8_P (c)) |
5505 |
carryover); |
CHAR_STRING_ADVANCE (c, dst); |
5506 |
coding->spec.ccl.eight_bit_carryover[carryover] = 0; |
else |
5507 |
coding->produced -= carryover; |
*dst++ = CHAR_TO_BYTE8 (c); |
5508 |
|
produced_chars++; |
5509 |
} |
} |
5510 |
|
else |
5511 |
|
/* This is an annotation datum. (-C) is the length of |
5512 |
|
it. */ |
5513 |
|
buf += -c - 1; |
5514 |
} |
} |
|
coding->produced = str_as_multibyte (destination, bytes, |
|
|
coding->produced, |
|
|
&(coding->produced_char)); |
|
5515 |
} |
} |
5516 |
|
else |
|
switch (ccl->status) |
|
5517 |
{ |
{ |
5518 |
case CCL_STAT_SUSPEND_BY_SRC: |
const unsigned char *src = coding->source; |
5519 |
coding->result = CODING_FINISH_INSUFFICIENT_SRC; |
const unsigned char *src_end = src + coding->src_bytes; |
5520 |
break; |
Lisp_Object eol_type; |
|
case CCL_STAT_SUSPEND_BY_DST: |
|
|
coding->result = CODING_FINISH_INSUFFICIENT_DST; |
|
|
break; |
|
|
case CCL_STAT_QUIT: |
|
|
case CCL_STAT_INVALID_CMD: |
|
|
coding->result = CODING_FINISH_INTERRUPT; |
|
|
break; |
|
|
default: |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
|
break; |
|
|
} |
|
|
return coding->result; |
|
|
} |
|
5521 |
|
|
5522 |
/* Decode EOL format of the text at PTR of BYTES length destructively |
eol_type = CODING_ID_EOL_TYPE (coding->id); |
|
according to CODING->eol_type. This is called after the CCL |
|
|
program produced a decoded text at PTR. If we do CRLF->LF |
|
|
conversion, update CODING->produced and CODING->produced_char. */ |
|
5523 |
|
|
5524 |
static void |
if (coding->src_multibyte != coding->dst_multibyte) |
5525 |
decode_eol_post_ccl (coding, ptr, bytes) |
{ |
5526 |
struct coding_system *coding; |
if (coding->src_multibyte) |
5527 |
unsigned char *ptr; |
{ |
5528 |
int bytes; |
int multibytep = 1; |
5529 |
{ |
int consumed_chars; |
|
Lisp_Object val, saved_coding_symbol; |
|
|
unsigned char *pend = ptr + bytes; |
|
|
int dummy; |
|
5530 |
|
|
5531 |
/* Remember the current coding system symbol. We set it back when |
while (1) |
5532 |
an inconsistent EOL is found so that `last-coding-system-used' is |
{ |
5533 |
set to the coding system that doesn't specify EOL conversion. */ |
const unsigned char *src_base = src; |
5534 |
saved_coding_symbol = coding->symbol; |
int c; |
5535 |
|
|
5536 |
coding->spec.ccl.cr_carryover = 0; |
ONE_MORE_BYTE (c); |
5537 |
if (coding->eol_type == CODING_EOL_UNDECIDED) |
if (c == '\r') |
5538 |
{ |
{ |
5539 |
/* Here, to avoid the call of setup_coding_system, we directly |
if (EQ (eol_type, Qdos)) |
5540 |
call detect_eol_type. */ |
{ |
5541 |
coding->eol_type = detect_eol_type (ptr, bytes, &dummy); |
if (src == src_end) |
5542 |
if (coding->eol_type == CODING_EOL_INCONSISTENT) |
{ |
5543 |
coding->eol_type = CODING_EOL_LF; |
coding->result = CODING_RESULT_INSUFFICIENT_SRC; |
5544 |
if (coding->eol_type != CODING_EOL_UNDECIDED) |
goto no_more_source; |
5545 |
{ |
} |
5546 |
val = Fget (coding->symbol, Qeol_type); |
if (*src == '\n') |
5547 |
if (VECTORP (val) && XVECTOR (val)->size == 3) |
c = *src++; |
5548 |
coding->symbol = XVECTOR (val)->contents[coding->eol_type]; |
} |
5549 |
} |
else if (EQ (eol_type, Qmac)) |
5550 |
coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; |
c = '\n'; |
5551 |
} |
} |
5552 |
|
if (dst == dst_end) |
5553 |
|
{ |
5554 |
|
coding->consumed = src - coding->source; |
5555 |
|
|
5556 |
if (coding->eol_type == CODING_EOL_LF |
if (EQ (coding->src_object, coding->dst_object)) |
5557 |
|| coding->eol_type == CODING_EOL_UNDECIDED) |
dst_end = (unsigned char *) src; |
5558 |
{ |
if (dst == dst_end) |
5559 |
/* We have nothing to do. */ |
{ |
5560 |
ptr = pend; |
dst = alloc_destination (coding, src_end - src + 1, |
5561 |
} |
dst); |
5562 |
else if (coding->eol_type == CODING_EOL_CRLF) |
dst_end = coding->destination + coding->dst_bytes; |
5563 |
{ |
coding_set_source (coding); |
5564 |
unsigned char *pstart = ptr, *p = ptr; |
src = coding->source + coding->consumed; |
5565 |
|
src_end = coding->source + coding->src_bytes; |
5566 |
|
} |
5567 |
|
} |
5568 |
|
*dst++ = c; |
5569 |
|
produced_chars++; |
5570 |
|
} |
5571 |
|
no_more_source: |
5572 |
|
; |
5573 |
|
} |
5574 |
|
else |
5575 |
|
while (src < src_end) |
5576 |
|
{ |
5577 |
|
int multibytep = 1; |
5578 |
|
int c = *src++; |
5579 |
|
|
5580 |
if (! (coding->mode & CODING_MODE_LAST_BLOCK) |
if (c == '\r') |
5581 |
&& *(pend - 1) == '\r') |
{ |
5582 |
{ |
if (EQ (eol_type, Qdos)) |
5583 |
/* If the last character is CR, we can't handle it here |
{ |
5584 |
because LF will be in the not-yet-decoded source text. |
if (src < src_end |
5585 |
Record that the CR is not yet processed. */ |
&& *src == '\n') |
5586 |
coding->spec.ccl.cr_carryover = 1; |
c = *src++; |
5587 |
coding->produced--; |
} |
5588 |
coding->produced_char--; |
else if (EQ (eol_type, Qmac)) |
5589 |
pend--; |
c = '\n'; |
5590 |
|
} |
5591 |
|
if (dst >= dst_end - 1) |
5592 |
|
{ |
5593 |
|
coding->consumed = src - coding->source; |
5594 |
|
|
5595 |
|
if (EQ (coding->src_object, coding->dst_object)) |
5596 |
|
dst_end = (unsigned char *) src; |
5597 |
|
if (dst >= dst_end - 1) |
5598 |
|
{ |
5599 |
|
dst = alloc_destination (coding, src_end - src + 2, |
5600 |
|
dst); |
5601 |
|
dst_end = coding->destination + coding->dst_bytes; |
5602 |
|
coding_set_source (coding); |
5603 |
|
src = coding->source + coding->consumed; |
5604 |
|
src_end = coding->source + coding->src_bytes; |
5605 |
|
} |
5606 |
|
} |
5607 |
|
EMIT_ONE_BYTE (c); |
5608 |
|
} |
5609 |
} |
} |
5610 |
while (ptr < pend) |
else |
5611 |
{ |
{ |
5612 |
if (*ptr == '\r') |
if (!EQ (coding->src_object, coding->dst_object)) |
5613 |
{ |
{ |
5614 |
if (ptr + 1 < pend && *(ptr + 1) == '\n') |
int require = coding->src_bytes - coding->dst_bytes; |
5615 |
{ |
|
5616 |
*p++ = '\n'; |
if (require > 0) |
|
ptr += 2; |
|
|
} |
|
|
else |
|
5617 |
{ |
{ |
5618 |
if (coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
EMACS_INT offset = src - coding->source; |
|
goto undo_eol_conversion; |
|
|
*p++ = *ptr++; |
|
|
} |
|
|
} |
|
|
else if (*ptr == '\n' |
|
|
&& coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
|
|
goto undo_eol_conversion; |
|
|
else |
|
|
*p++ = *ptr++; |
|
|
continue; |
|
5619 |
|
|
5620 |
undo_eol_conversion: |
dst = alloc_destination (coding, require, dst); |
5621 |
/* We have faced with inconsistent EOL format at PTR. |
coding_set_source (coding); |
5622 |
Convert all LFs before PTR back to CRLFs. */ |
src = coding->source + offset; |
5623 |
for (p--, ptr--; p >= pstart; p--) |
src_end = coding->source + coding->src_bytes; |
5624 |
{ |
} |
|
if (*p == '\n') |
|
|
*ptr-- = '\n', *ptr-- = '\r'; |
|
|
else |
|
|
*ptr-- = *p; |
|
5625 |
} |
} |
5626 |
/* If carryover is recorded, cancel it because we don't |
produced_chars = coding->src_chars; |
5627 |
convert CRLF anymore. */ |
while (src < src_end) |
|
if (coding->spec.ccl.cr_carryover) |
|
5628 |
{ |
{ |
5629 |
coding->spec.ccl.cr_carryover = 0; |
int c = *src++; |
|
coding->produced++; |
|
|
coding->produced_char++; |
|
|
pend++; |
|
|
} |
|
|
p = ptr = pend; |
|
|
coding->eol_type = CODING_EOL_LF; |
|
|
coding->symbol = saved_coding_symbol; |
|
|
} |
|
|
if (p < pend) |
|
|
{ |
|
|
/* As each two-byte sequence CRLF was converted to LF, (PEND |
|
|
- P) is the number of deleted characters. */ |
|
|
coding->produced -= pend - p; |
|
|
coding->produced_char -= pend - p; |
|
|
} |
|
|
} |
|
|
else /* i.e. coding->eol_type == CODING_EOL_CR */ |
|
|
{ |
|
|
unsigned char *p = ptr; |
|
5630 |
|
|
5631 |
for (; ptr < pend; ptr++) |
if (c == '\r') |
|
{ |
|
|
if (*ptr == '\r') |
|
|
*ptr = '\n'; |
|
|
else if (*ptr == '\n' |
|
|
&& coding->mode & CODING_MODE_INHIBIT_INCONSISTENT_EOL) |
|
|
{ |
|
|
for (; p < ptr; p++) |
|
5632 |
{ |
{ |
5633 |
if (*p == '\n') |
if (EQ (eol_type, Qdos)) |
5634 |
*p = '\r'; |
{ |
5635 |
|
if (src < src_end |
5636 |
|
&& *src == '\n') |
5637 |
|
c = *src++; |
5638 |
|
produced_chars--; |
5639 |
|
} |
5640 |
|
else if (EQ (eol_type, Qmac)) |
5641 |
|
c = '\n'; |
5642 |
} |
} |
5643 |
ptr = pend; |
*dst++ = c; |
|
coding->eol_type = CODING_EOL_LF; |
|
|
coding->symbol = saved_coding_symbol; |
|
5644 |
} |
} |
5645 |
} |
} |
5646 |
|
coding->consumed = coding->src_bytes; |
5647 |
|
coding->consumed_char = coding->src_chars; |
5648 |
} |
} |
5649 |
|
|
5650 |
|
produced = dst - (coding->destination + coding->produced); |
5651 |
|
if (BUFFERP (coding->dst_object)) |
5652 |
|
insert_from_gap (produced_chars, produced); |
5653 |
|
coding->produced += produced; |
5654 |
|
coding->produced_char += produced_chars; |
5655 |
|
return produced_chars; |
5656 |
} |
} |
5657 |
|
|
5658 |
/* See "GENERAL NOTES about `decode_coding_XXX ()' functions". Before |
/* Compose text in CODING->object according to the annotation data at |
5659 |
decoding, it may detect coding system and format of end-of-line if |
CHARBUF. CHARBUF is an array: |
5660 |
those are not yet decided. The source should be unibyte, the |
[ -LENGTH ANNOTATION_MASK FROM TO METHOD COMP_LEN [ COMPONENTS... ] ] |
5661 |
result is multibyte if CODING->dst_multibyte is nonzero, else |
*/ |
|
unibyte. */ |
|
5662 |
|
|
5663 |
int |
static INLINE void |
5664 |
decode_coding (coding, source, destination, src_bytes, dst_bytes) |
produce_composition (coding, charbuf) |
5665 |
struct coding_system *coding; |
struct coding_system *coding; |
5666 |
const unsigned char *source; |
int *charbuf; |
|
unsigned char *destination; |
|
|
int src_bytes, dst_bytes; |
|
5667 |
{ |
{ |
5668 |
int extra = 0; |
int len; |
5669 |
|
EMACS_INT from, to; |
5670 |
if (coding->type == coding_type_undecided) |
enum composition_method method; |
5671 |
detect_coding (coding, source, src_bytes); |
Lisp_Object components; |
5672 |
|
|
5673 |
|
len = -charbuf[0]; |
5674 |
|
from = coding->dst_pos + charbuf[2]; |
5675 |
|
to = coding->dst_pos + charbuf[3]; |
5676 |
|
method = (enum composition_method) (charbuf[4]); |
5677 |
|
|
5678 |
if (coding->eol_type == CODING_EOL_UNDECIDED |
if (method == COMPOSITION_RELATIVE) |
5679 |
&& coding->type != coding_type_ccl) |
components = Qnil; |
5680 |
|
else |
5681 |
{ |
{ |
5682 |
detect_eol (coding, source, src_bytes); |
Lisp_Object args[MAX_COMPOSITION_COMPONENTS * 2 - 1]; |
5683 |
/* We had better recover the original eol format if we |
int i; |
5684 |
encounter an inconsistent eol format while decoding. */ |
|
5685 |
coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; |
len -= 5; |
5686 |
|
charbuf += 5; |
5687 |
|
for (i = 0; i < len; i++) |
5688 |
|
args[i] = make_number (charbuf[i]); |
5689 |
|
components = (method == COMPOSITION_WITH_ALTCHARS |
5690 |
|
? Fstring (len, args) : Fvector (len, args)); |
5691 |
} |
} |
5692 |
|
compose_text (from, to, components, Qnil, coding->dst_object); |
5693 |
|
} |
5694 |
|
|
|
coding->produced = coding->produced_char = 0; |
|
|
coding->consumed = coding->consumed_char = 0; |
|
|
coding->errors = 0; |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
5695 |
|
|
5696 |
switch (coding->type) |
/* Put `charset' property on text in CODING->object according to |
5697 |
{ |
the annotation data at CHARBUF. CHARBUF is an array: |
5698 |
case coding_type_sjis: |
[ -LENGTH ANNOTATION_MASK FROM TO CHARSET-ID ] |
5699 |
decode_coding_sjis_big5 (coding, source, destination, |
*/ |
|
src_bytes, dst_bytes, 1); |
|
|
break; |
|
5700 |
|
|
5701 |
case coding_type_iso2022: |
static INLINE void |
5702 |
decode_coding_iso2022 (coding, source, destination, |
produce_charset (coding, charbuf) |
5703 |
src_bytes, dst_bytes); |
struct coding_system *coding; |
5704 |
break; |
int *charbuf; |
5705 |
|
{ |
5706 |
|
EMACS_INT from = coding->dst_pos + charbuf[2]; |
5707 |
|
EMACS_INT to = coding->dst_pos + charbuf[3]; |
5708 |
|
struct charset *charset = CHARSET_FROM_ID (charbuf[4]); |
5709 |
|
|
5710 |
case coding_type_big5: |
Fput_text_property (make_number (from), make_number (to), |
5711 |
decode_coding_sjis_big5 (coding, source, destination, |
Qcharset, CHARSET_NAME (charset), |
5712 |
src_bytes, dst_bytes, 0); |
coding->dst_object); |
5713 |
break; |
} |
5714 |
|
|
|
case coding_type_emacs_mule: |
|
|
decode_coding_emacs_mule (coding, source, destination, |
|
|
src_bytes, dst_bytes); |
|
|
break; |
|
5715 |
|
|
5716 |
case coding_type_ccl: |
#define CHARBUF_SIZE 0x4000 |
|
if (coding->spec.ccl.cr_carryover) |
|
|
{ |
|
|
/* Put the CR which was not processed by the previous call |
|
|
of decode_eol_post_ccl in DESTINATION. It will be |
|
|
decoded together with the following LF by the call to |
|
|
decode_eol_post_ccl below. */ |
|
|
*destination = '\r'; |
|
|
coding->produced++; |
|
|
coding->produced_char++; |
|
|
dst_bytes--; |
|
|
extra = coding->spec.ccl.cr_carryover; |
|
|
} |
|
|
ccl_coding_driver (coding, source, destination + extra, |
|
|
src_bytes, dst_bytes, 0); |
|
|
if (coding->eol_type != CODING_EOL_LF) |
|
|
{ |
|
|
coding->produced += extra; |
|
|
coding->produced_char += extra; |
|
|
decode_eol_post_ccl (coding, destination, coding->produced); |
|
|
} |
|
|
break; |
|
5717 |
|
|
5718 |
default: |
#define ALLOC_CONVERSION_WORK_AREA(coding) \ |
5719 |
decode_eol (coding, source, destination, src_bytes, dst_bytes); |
do { \ |
5720 |
} |
int size = CHARBUF_SIZE;; \ |
5721 |
|
\ |
5722 |
|
coding->charbuf = NULL; \ |
5723 |
|
while (size > 1024) \ |
5724 |
|
{ \ |
5725 |
|
coding->charbuf = (int *) alloca (sizeof (int) * size); \ |
5726 |
|
if (coding->charbuf) \ |
5727 |
|
break; \ |
5728 |
|
size >>= 1; \ |
5729 |
|
} \ |
5730 |
|
if (! coding->charbuf) \ |
5731 |
|
{ \ |
5732 |
|
coding->result = CODING_RESULT_INSUFFICIENT_MEM; \ |
5733 |
|
return coding->result; \ |
5734 |
|
} \ |
5735 |
|
coding->charbuf_size = size; \ |
5736 |
|
} while (0) |
5737 |
|
|
|
if (coding->result == CODING_FINISH_INSUFFICIENT_SRC |
|
|
&& coding->mode & CODING_MODE_LAST_BLOCK |
|
|
&& coding->consumed == src_bytes) |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
5738 |
|
|
5739 |
if (coding->mode & CODING_MODE_LAST_BLOCK |
static void |
5740 |
&& coding->result == CODING_FINISH_INSUFFICIENT_SRC) |
produce_annotation (coding) |
5741 |
{ |
struct coding_system *coding; |
5742 |
const unsigned char *src = source + coding->consumed; |
{ |
5743 |
unsigned char *dst = destination + coding->produced; |
int *charbuf = coding->charbuf; |
5744 |
|
int *charbuf_end = charbuf + coding->charbuf_used; |
5745 |
|
|
5746 |
src_bytes -= coding->consumed; |
if (NILP (coding->dst_object)) |
5747 |
coding->errors++; |
return; |
5748 |
if (COMPOSING_P (coding)) |
|
5749 |
DECODE_COMPOSITION_END ('1'); |
while (charbuf < charbuf_end) |
5750 |
while (src_bytes--) |
{ |
5751 |
|
if (*charbuf >= 0) |
5752 |
|
charbuf++; |
5753 |
|
else |
5754 |
{ |
{ |
5755 |
int c = *src++; |
int len = -*charbuf; |
5756 |
dst += CHAR_STRING (c, dst); |
switch (charbuf[1]) |
5757 |
coding->produced_char++; |
{ |
5758 |
|
case CODING_ANNOTATE_COMPOSITION_MASK: |
5759 |
|
produce_composition (coding, charbuf); |
5760 |
|
break; |
5761 |
|
case CODING_ANNOTATE_CHARSET_MASK: |
5762 |
|
produce_charset (coding, charbuf); |
5763 |
|
break; |
5764 |
|
default: |
5765 |
|
abort (); |
5766 |
|
} |
5767 |
|
charbuf += len; |
5768 |
} |
} |
|
coding->consumed = coding->consumed_char = src - source; |
|
|
coding->produced = dst - destination; |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
5769 |
} |
} |
5770 |
|
} |
5771 |
|
|
5772 |
if (!coding->dst_multibyte) |
/* Decode the data at CODING->src_object into CODING->dst_object. |
5773 |
{ |
CODING->src_object is a buffer, a string, or nil. |
5774 |
coding->produced = str_as_unibyte (destination, coding->produced); |
CODING->dst_object is a buffer. |
|
coding->produced_char = coding->produced; |
|
|
} |
|
5775 |
|
|
5776 |
return coding->result; |
If CODING->src_object is a buffer, it must be the current buffer. |
5777 |
} |
In this case, if CODING->src_pos is positive, it is a position of |
5778 |
|
the source text in the buffer, otherwise, the source text is in the |
5779 |
|
gap area of the buffer, and CODING->src_pos specifies the offset of |
5780 |
|
the text from GPT (which must be the same as PT). If this is the |
5781 |
|
same buffer as CODING->dst_object, CODING->src_pos must be |
5782 |
|
negative. |
5783 |
|
|
5784 |
/* See "GENERAL NOTES about `encode_coding_XXX ()' functions". The |
If CODING->src_object is a string, CODING->src_pos in an index to |
5785 |
multibyteness of the source is CODING->src_multibyte, the |
that string. |
|
multibyteness of the result is always unibyte. */ |
|
5786 |
|
|
5787 |
int |
If CODING->src_object is nil, CODING->source must already point to |
5788 |
encode_coding (coding, source, destination, src_bytes, dst_bytes) |
the non-relocatable memory area. In this case, CODING->src_pos is |
5789 |
struct coding_system *coding; |
an offset from CODING->source. |
|
const unsigned char *source; |
|
|
unsigned char *destination; |
|
|
int src_bytes, dst_bytes; |
|
|
{ |
|
|
coding->produced = coding->produced_char = 0; |
|
|
coding->consumed = coding->consumed_char = 0; |
|
|
coding->errors = 0; |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
5790 |
|
|
5791 |
switch (coding->type) |
The decoded data is inserted at the current point of the buffer |
5792 |
{ |
CODING->dst_object. |
5793 |
case coding_type_sjis: |
*/ |
|
encode_coding_sjis_big5 (coding, source, destination, |
|
|
src_bytes, dst_bytes, 1); |
|
|
break; |
|
5794 |
|
|
5795 |
case coding_type_iso2022: |
static int |
5796 |
encode_coding_iso2022 (coding, source, destination, |
decode_coding (coding) |
5797 |
src_bytes, dst_bytes); |
struct coding_system *coding; |
5798 |
break; |
{ |
5799 |
|
Lisp_Object attrs; |
5800 |
|
|
5801 |
case coding_type_big5: |
if (BUFFERP (coding->src_object) |
5802 |
encode_coding_sjis_big5 (coding, source, destination, |
&& coding->src_pos > 0 |
5803 |
src_bytes, dst_bytes, 0); |
&& coding->src_pos < GPT |
5804 |
break; |
&& coding->src_pos + coding->src_chars > GPT) |
5805 |
|
move_gap_both (coding->src_pos, coding->src_pos_byte); |
5806 |
|
|
5807 |
|
if (BUFFERP (coding->dst_object)) |
5808 |
|
{ |
5809 |
|
if (current_buffer != XBUFFER (coding->dst_object)) |
5810 |
|
set_buffer_internal (XBUFFER (coding->dst_object)); |
5811 |
|
if (GPT != PT) |
5812 |
|
move_gap_both (PT, PT_BYTE); |
5813 |
|
} |
5814 |
|
|
5815 |
case coding_type_emacs_mule: |
coding->consumed = coding->consumed_char = 0; |
5816 |
encode_coding_emacs_mule (coding, source, destination, |
coding->produced = coding->produced_char = 0; |
5817 |
src_bytes, dst_bytes); |
coding->chars_at_source = 0; |
5818 |
break; |
coding->result = CODING_RESULT_SUCCESS; |
5819 |
|
coding->errors = 0; |
5820 |
|
|
5821 |
case coding_type_ccl: |
ALLOC_CONVERSION_WORK_AREA (coding); |
|
ccl_coding_driver (coding, source, destination, |
|
|
src_bytes, dst_bytes, 1); |
|
|
break; |
|
5822 |
|
|
5823 |
default: |
attrs = CODING_ID_ATTRS (coding->id); |
|
encode_eol (coding, source, destination, src_bytes, dst_bytes); |
|
|
} |
|
5824 |
|
|
5825 |
if (coding->mode & CODING_MODE_LAST_BLOCK |
do |
|
&& coding->result == CODING_FINISH_INSUFFICIENT_SRC) |
|
5826 |
{ |
{ |
5827 |
const unsigned char *src = source + coding->consumed; |
coding_set_source (coding); |
5828 |
unsigned char *dst = destination + coding->produced; |
coding->annotated = 0; |
5829 |
|
(*(coding->decoder)) (coding); |
5830 |
|
if (!NILP (CODING_ATTR_DECODE_TBL (attrs))) |
5831 |
|
translate_chars (coding, CODING_ATTR_DECODE_TBL (attrs)); |
5832 |
|
else if (!NILP (Vstandard_translation_table_for_decode)) |
5833 |
|
translate_chars (coding, Vstandard_translation_table_for_decode); |
5834 |
|
coding_set_destination (coding); |
5835 |
|
produce_chars (coding); |
5836 |
|
if (coding->annotated) |
5837 |
|
produce_annotation (coding); |
5838 |
|
} |
5839 |
|
while (coding->consumed < coding->src_bytes |
5840 |
|
&& ! coding->result); |
5841 |
|
|
5842 |
|
if (EQ (CODING_ATTR_TYPE (CODING_ID_ATTRS (coding->id)), Qccl) |
5843 |
|
&& SYMBOLP (CODING_ID_EOL_TYPE (coding->id)) |
5844 |
|
&& ! EQ (CODING_ID_EOL_TYPE (coding->id), Qunix)) |
5845 |
|
decode_eol (coding); |
5846 |
|
|
5847 |
|
coding->carryover_bytes = 0; |
5848 |
|
if (coding->consumed < coding->src_bytes) |
5849 |
|
{ |
5850 |
|
int nbytes = coding->src_bytes - coding->consumed; |
5851 |
|
const unsigned char *src; |
5852 |
|
|
5853 |
|
coding_set_source (coding); |
5854 |
|
coding_set_destination (coding); |
5855 |
|
src = coding->source + coding->consumed; |
5856 |
|
|
5857 |
|
if (coding->mode & CODING_MODE_LAST_BLOCK) |
5858 |
|
{ |
5859 |
|
/* Flush out unprocessed data as binary chars. We are sure |
5860 |
|
that the number of data is less than the size of |
5861 |
|
coding->charbuf. */ |
5862 |
|
while (nbytes-- > 0) |
5863 |
|
{ |
5864 |
|
int c = *src++; |
5865 |
|
|
5866 |
if (coding->type == coding_type_iso2022) |
coding->charbuf[coding->charbuf_used++] = (c & 0x80 ? - c : c); |
5867 |
ENCODE_RESET_PLANE_AND_REGISTER; |
} |
5868 |
if (COMPOSING_P (coding)) |
produce_chars (coding); |
5869 |
*dst++ = ISO_CODE_ESC, *dst++ = '1'; |
} |
5870 |
if (coding->consumed < src_bytes) |
else |
5871 |
{ |
{ |
5872 |
int len = src_bytes - coding->consumed; |
/* Record unprocessed bytes in coding->carryover. We are |
5873 |
|
sure that the number of data is less than the size of |
5874 |
BCOPY_SHORT (src, dst, len); |
coding->carryover. */ |
5875 |
if (coding->src_multibyte) |
unsigned char *p = coding->carryover; |
5876 |
len = str_as_unibyte (dst, len); |
|
5877 |
dst += len; |
coding->carryover_bytes = nbytes; |
5878 |
coding->consumed = src_bytes; |
while (nbytes-- > 0) |
5879 |
|
*p++ = *src++; |
5880 |
} |
} |
5881 |
coding->produced = coding->produced_char = dst - destination; |
coding->consumed = coding->src_bytes; |
|
coding->result = CODING_FINISH_NORMAL; |
|
5882 |
} |
} |
5883 |
|
|
|
if (coding->result == CODING_FINISH_INSUFFICIENT_SRC |
|
|
&& coding->consumed == src_bytes) |
|
|
coding->result = CODING_FINISH_NORMAL; |
|
|
|
|
5884 |
return coding->result; |
return coding->result; |
5885 |
} |
} |
5886 |
|
|
|
/* Scan text in the region between *BEG and *END (byte positions), |
|
|
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. The caller should move |
|
|
the gap out of the region in advance if the region is from a |
|
|
buffer. |
|
5887 |
|
|
5888 |
If STR is not NULL, *BEG and *END are indices into STR. */ |
/* Extract an annotation datum from a composition starting at POS and |
5889 |
|
ending before LIMIT of CODING->src_object (buffer or string), store |
5890 |
static void |
the data in BUF, set *STOP to a starting position of the next |
5891 |
shrink_decoding_region (beg, end, coding, str) |
composition (if any) or to LIMIT, and return the address of the |
5892 |
int *beg, *end; |
next element of BUF. |
5893 |
|
|
5894 |
|
If such an annotation is not found, set *STOP to a starting |
5895 |
|
position of a composition after POS (if any) or to LIMIT, and |
5896 |
|
return BUF. */ |
5897 |
|
|
5898 |
|
static INLINE int * |
5899 |
|
handle_composition_annotation (pos, limit, coding, buf, stop) |
5900 |
|
EMACS_INT pos, limit; |
5901 |
struct coding_system *coding; |
struct coding_system *coding; |
5902 |
unsigned char *str; |
int *buf; |
5903 |
|
EMACS_INT *stop; |
5904 |
{ |
{ |
5905 |
unsigned char *begp_orig, *begp, *endp_orig, *endp, c; |
EMACS_INT start, end; |
5906 |
int eol_conversion; |
Lisp_Object prop; |
|
Lisp_Object translation_table; |
|
|
|
|
|
if (coding->type == coding_type_ccl |
|
|
|| coding->type == coding_type_undecided |
|
|
|| coding->eol_type != CODING_EOL_LF |
|
|
|| !NILP (coding->post_read_conversion) |
|
|
|| coding->composing != COMPOSITION_DISABLED) |
|
|
{ |
|
|
/* We can't skip any data. */ |
|
|
return; |
|
|
} |
|
|
if (coding->type == coding_type_no_conversion |
|
|
|| coding->type == coding_type_raw_text |
|
|
|| coding->type == coding_type_emacs_mule) |
|
|
{ |
|
|
/* We need no conversion, but don't have to skip any data here. |
|
|
Decoding routine handles them effectively anyway. */ |
|
|
return; |
|
|
} |
|
|
|
|
|
translation_table = coding->translation_table_for_decode; |
|
|
if (NILP (translation_table) && !NILP (Venable_character_translation)) |
|
|
translation_table = Vstandard_translation_table_for_decode; |
|
|
if (CHAR_TABLE_P (translation_table)) |
|
|
{ |
|
|
int i; |
|
|
for (i = 0; i < 128; i++) |
|
|
if (!NILP (CHAR_TABLE_REF (translation_table, i))) |
|
|
break; |
|
|
if (i < 128) |
|
|
/* Some ASCII character should be translated. We give up |
|
|
shrinking. */ |
|
|
return; |
|
|
} |
|
|
|
|
|
if (coding->heading_ascii >= 0) |
|
|
/* Detection routine has already found how much we can skip at the |
|
|
head. */ |
|
|
*beg += coding->heading_ascii; |
|
5907 |
|
|
5908 |
if (str) |
if (! find_composition (pos, limit, &start, &end, &prop, coding->src_object) |
5909 |
{ |
|| end > limit) |
5910 |
begp_orig = begp = str + *beg; |
*stop = limit; |
5911 |
endp_orig = endp = str + *end; |
else if (start > pos) |
5912 |
} |
*stop = start; |
5913 |
else |
else |
5914 |
{ |
{ |
5915 |
begp_orig = begp = BYTE_POS_ADDR (*beg); |
if (start == pos) |
|
endp_orig = endp = begp + *end - *beg; |
|
|
} |
|
|
|
|
|
eol_conversion = (coding->eol_type == CODING_EOL_CR |
|
|
|| coding->eol_type == CODING_EOL_CRLF); |
|
|
|
|
|
switch (coding->type) |
|
|
{ |
|
|
case coding_type_sjis: |
|
|
case coding_type_big5: |
|
|
/* We can skip all ASCII characters at the head. */ |
|
|
if (coding->heading_ascii < 0) |
|
5916 |
{ |
{ |
5917 |
if (eol_conversion) |
/* We found a composition. Store the corresponding |
5918 |
while (begp < endp && *begp < 0x80 && *begp != '\r') begp++; |
annotation data in BUF. */ |
5919 |
else |
int *head = buf; |
5920 |
while (begp < endp && *begp < 0x80) begp++; |
enum composition_method method = COMPOSITION_METHOD (prop); |
5921 |
} |
int nchars = COMPOSITION_LENGTH (prop); |
|
/* 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] != '\r') endp--; |
|
|
else |
|
|
while (begp < endp && endp[-1] < 0x80) endp--; |
|
|
/* Do not consider LF as ascii if preceded by CR, since that |
|
|
confuses eol decoding. */ |
|
|
if (begp < endp && endp < endp_orig && endp[-1] == '\r' && endp[0] == '\n') |
|
|
endp++; |
|
|
if (begp < endp && endp < endp_orig && endp[-1] >= 0x80) |
|
|
endp++; |
|
|
break; |
|
5922 |
|
|
5923 |
case coding_type_iso2022: |
ADD_COMPOSITION_DATA (buf, 0, nchars, method); |
5924 |
if (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, 0) != CHARSET_ASCII) |
if (method != COMPOSITION_RELATIVE) |
5925 |
/* We can't skip any data. */ |
{ |
5926 |
break; |
Lisp_Object components; |
5927 |
if (coding->heading_ascii < 0) |
int len, i, i_byte; |
|
{ |
|
|
/* 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 && (c = endp[-1]) < 0x80 && c != '\r') endp--; |
|
|
else |
|
|
while (begp < endp && endp[-1] < 0x80) endp--; |
|
|
/* Do not consider LF as ascii if preceded by CR, since that |
|
|
confuses eol decoding. */ |
|
|
if (begp < endp && endp < endp_orig && endp[-1] == '\r' && endp[0] == '\n') |
|
|
endp++; |
|
|
break; |
|
5928 |
|
|
5929 |
case CODING_CATEGORY_IDX_ISO_7: |
components = COMPOSITION_COMPONENTS (prop); |
5930 |
case CODING_CATEGORY_IDX_ISO_7_TIGHT: |
if (VECTORP (components)) |
|
{ |
|
|
/* We can skip all characters at the tail except for 8-bit |
|
|
codes and ESC and the following 2-byte at the tail. */ |
|
|
unsigned char *eight_bit = NULL; |
|
|
|
|
|
if (eol_conversion) |
|
|
while (begp < endp |
|
|
&& (c = endp[-1]) != ISO_CODE_ESC && c != '\r') |
|
5931 |
{ |
{ |
5932 |
if (!eight_bit && c & 0x80) eight_bit = endp; |
len = XVECTOR (components)->size; |
5933 |
endp--; |
for (i = 0; i < len; i++) |
5934 |
|
*buf++ = XINT (AREF (components, i)); |
5935 |
} |
} |
5936 |
else |
else if (STRINGP (components)) |
|
while (begp < endp |
|
|
&& (c = endp[-1]) != ISO_CODE_ESC) |
|
5937 |
{ |
{ |
5938 |
if (!eight_bit && c & 0x80) eight_bit = endp; |
len = SCHARS (components); |
5939 |
endp--; |
i = i_byte = 0; |
5940 |
|
while (i < len) |
5941 |
|
{ |
5942 |
|
FETCH_STRING_CHAR_ADVANCE (*buf, components, i, i_byte); |
5943 |
|
buf++; |
5944 |
|
} |
5945 |
} |
} |
5946 |
/* Do not consider LF as ascii if preceded by CR, since that |
else if (INTEGERP (components)) |
5947 |
confuses eol decoding. */ |
{ |
5948 |
if (begp < endp && endp < endp_orig |
len = 1; |
5949 |
&& endp[-1] == '\r' && endp[0] == '\n') |
*buf++ = XINT (components); |
5950 |
endp++; |
} |
5951 |
if (begp < endp && endp[-1] == ISO_CODE_ESC) |
else if (CONSP (components)) |
5952 |
{ |
{ |
5953 |
if (endp + 1 < endp_orig && end[0] == '(' && end[1] == 'B') |
for (len = 0; CONSP (components); |
5954 |
/* This is an ASCII designation sequence. We can |
len++, components = XCDR (components)) |
5955 |
surely skip the tail. But, if we have |
*buf++ = XINT (XCAR (components)); |
5956 |
encountered an 8-bit code, skip only the codes |
} |
5957 |
after that. */ |
else |
5958 |
endp = eight_bit ? eight_bit : endp + 2; |
abort (); |
5959 |
else |
*head -= len; |
5960 |
/* Hmmm, we can't skip the tail. */ |
} |
|
endp = endp_orig; |
|
|
} |
|
|
else if (eight_bit) |
|
|
endp = eight_bit; |
|
|
} |
|
5961 |
} |
} |
|
break; |
|
5962 |
|
|
5963 |
default: |
if (find_composition (end, limit, &start, &end, &prop, |
5964 |
abort (); |
coding->src_object) |
5965 |
|
&& end <= limit) |
5966 |
|
*stop = start; |
5967 |
|
else |
5968 |
|
*stop = limit; |
5969 |
} |
} |
5970 |
*beg += begp - begp_orig; |
return buf; |
5971 |
*end += endp - endp_orig; |
} |
5972 |
return; |
|
5973 |
|
|
5974 |
|
/* Extract an annotation datum from a text property `charset' at POS of |
5975 |
|
CODING->src_object (buffer of string), store the data in BUF, set |
5976 |
|
*STOP to the position where the value of `charset' property changes |
5977 |
|
(limiting by LIMIT), and return the address of the next element of |
5978 |
|
BUF. |
5979 |
|
|
5980 |
|
If the property value is nil, set *STOP to the position where the |
5981 |
|
property value is non-nil (limiting by LIMIT), and return BUF. */ |
5982 |
|
|
5983 |
|
static INLINE int * |
5984 |
|
handle_charset_annotation (pos, limit, coding, buf, stop) |
5985 |
|
EMACS_INT pos, limit; |
5986 |
|
struct coding_system *coding; |
5987 |
|
int *buf; |
5988 |
|
EMACS_INT *stop; |
5989 |
|
{ |
5990 |
|
Lisp_Object val, next; |
5991 |
|
int id; |
5992 |
|
|
5993 |
|
val = Fget_text_property (make_number (pos), Qcharset, coding->src_object); |
5994 |
|
if (! NILP (val) && CHARSETP (val)) |
5995 |
|
id = XINT (CHARSET_SYMBOL_ID (val)); |
5996 |
|
else |
5997 |
|
id = -1; |
5998 |
|
ADD_CHARSET_DATA (buf, 0, 0, id); |
5999 |
|
next = Fnext_single_property_change (make_number (pos), Qcharset, |
6000 |
|
coding->src_object, |
6001 |
|
make_number (limit)); |
6002 |
|
*stop = XINT (next); |
6003 |
|
return buf; |
6004 |
} |
} |
6005 |
|
|
|
/* Like shrink_decoding_region but for encoding. */ |
|
6006 |
|
|
6007 |
static void |
static void |
6008 |
shrink_encoding_region (beg, end, coding, str) |
consume_chars (coding) |
|
int *beg, *end; |
|
6009 |
struct coding_system *coding; |
struct coding_system *coding; |
|
unsigned char *str; |
|
6010 |
{ |
{ |
6011 |
unsigned char *begp_orig, *begp, *endp_orig, *endp; |
int *buf = coding->charbuf; |
6012 |
int eol_conversion; |
int *buf_end = coding->charbuf + coding->charbuf_size; |
6013 |
Lisp_Object translation_table; |
const unsigned char *src = coding->source + coding->consumed; |
6014 |
|
const unsigned char *src_end = coding->source + coding->src_bytes; |
6015 |
|
EMACS_INT pos = coding->src_pos + coding->consumed_char; |
6016 |
|
EMACS_INT end_pos = coding->src_pos + coding->src_chars; |
6017 |
|
int multibytep = coding->src_multibyte; |
6018 |
|
Lisp_Object eol_type; |
6019 |
|
int c; |
6020 |
|
EMACS_INT stop, stop_composition, stop_charset; |
6021 |
|
|
6022 |
if (coding->type == coding_type_ccl |
eol_type = CODING_ID_EOL_TYPE (coding->id); |
6023 |
|| coding->eol_type == CODING_EOL_CRLF |
if (VECTORP (eol_type)) |
6024 |
|| coding->eol_type == CODING_EOL_CR |
eol_type = Qunix; |
|
|| (coding->cmp_data && coding->cmp_data->used > 0)) |
|
|
{ |
|
|
/* We can't skip any data. */ |
|
|
return; |
|
|
} |
|
|
if (coding->type == coding_type_no_conversion |
|
|
|| coding->type == coding_type_raw_text |
|
|
|| coding->type == coding_type_emacs_mule |
|
|
|| coding->type == coding_type_undecided) |
|
|
{ |
|
|
/* We need no conversion, but don't have to skip any data here. |
|
|
Encoding routine handles them effectively anyway. */ |
|
|
return; |
|
|
} |
|
6025 |
|
|
6026 |
translation_table = coding->translation_table_for_encode; |
/* Note: composition handling is not yet implemented. */ |
6027 |
if (NILP (translation_table) && !NILP (Venable_character_translation)) |
coding->common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK; |
|
translation_table = Vstandard_translation_table_for_encode; |
|
|
if (CHAR_TABLE_P (translation_table)) |
|
|
{ |
|
|
int i; |
|
|
for (i = 0; i < 128; i++) |
|
|
if (!NILP (CHAR_TABLE_REF (translation_table, i))) |
|
|
break; |
|
|
if (i < 128) |
|
|
/* Some ASCII character should be translated. We give up |
|
|
shrinking. */ |
|
|
return; |
|
|
} |
|
6028 |
|
|
6029 |
if (str) |
if (coding->common_flags & CODING_ANNOTATE_COMPOSITION_MASK) |
6030 |
{ |
stop = stop_composition = pos; |
|
begp_orig = begp = str + *beg; |
|
|
endp_orig = endp = str + *end; |
|
|
} |
|
6031 |
else |
else |
6032 |
{ |
stop = stop_composition = end_pos; |
6033 |
begp_orig = begp = BYTE_POS_ADDR (*beg); |
if (coding->common_flags & CODING_ANNOTATE_CHARSET_MASK) |
6034 |
endp_orig = endp = begp + *end - *beg; |
stop = stop_charset = pos; |
6035 |
} |
else |
6036 |
|
stop_charset = end_pos; |
|
eol_conversion = (coding->eol_type == CODING_EOL_CR |
|
|
|| coding->eol_type == CODING_EOL_CRLF); |
|
6037 |
|
|
6038 |
/* Here, we don't have to check coding->pre_write_conversion because |
/* Compensate for CRLF and annotation. */ |
6039 |
the caller is expected to have handled it already. */ |
buf_end -= 1 + MAX_ANNOTATION_LENGTH; |
6040 |
switch (coding->type) |
while (buf < buf_end) |
6041 |
{ |
{ |
6042 |
case coding_type_iso2022: |
if (pos == stop) |
6043 |
if (CODING_SPEC_ISO_INITIAL_DESIGNATION (coding, 0) != CHARSET_ASCII) |
{ |
6044 |
/* We can't skip any data. */ |
if (pos == end_pos) |
6045 |
break; |
break; |
6046 |
if (coding->flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL) |
if (pos == stop_composition) |
6047 |
|
buf = handle_composition_annotation (pos, end_pos, coding, |
6048 |
|
buf, &stop_composition); |
6049 |
|
if (pos == stop_charset) |
6050 |
|
buf = handle_charset_annotation (pos, end_pos, coding, |
6051 |
|
buf, &stop_charset); |
6052 |
|
stop = (stop_composition < stop_charset |
6053 |
|
? stop_composition : stop_charset); |
6054 |
|
} |
6055 |
|
|
6056 |
|
if (! multibytep) |
6057 |
|
{ |
6058 |
|
EMACS_INT bytes; |
6059 |
|
|
6060 |
|
if (! CODING_FOR_UNIBYTE (coding) |
6061 |
|
&& (bytes = MULTIBYTE_LENGTH (src, src_end)) > 0) |
6062 |
|
c = STRING_CHAR_ADVANCE (src), pos += bytes; |
6063 |
|
else |
6064 |
|
c = *src++, pos++; |
6065 |
|
} |
6066 |
|
else |
6067 |
|
c = STRING_CHAR_ADVANCE (src), pos++; |
6068 |
|
if ((c == '\r') && (coding->mode & CODING_MODE_SELECTIVE_DISPLAY)) |
6069 |
|
c = '\n'; |
6070 |
|
if (! EQ (eol_type, Qunix)) |
6071 |
{ |
{ |
6072 |
unsigned char *bol = begp; |
if (c == '\n') |
|
while (begp < endp && *begp < 0x80) |
|
6073 |
{ |
{ |
6074 |
begp++; |
if (EQ (eol_type, Qdos)) |
6075 |
if (begp[-1] == '\n') |
*buf++ = '\r'; |
6076 |
bol = begp; |
else |
6077 |
|
c = '\r'; |
6078 |
} |
} |
|
begp = bol; |
|
|
goto label_skip_tail; |
|
6079 |
} |
} |
6080 |
/* fall down ... */ |
*buf++ = c; |
|
|
|
|
case coding_type_sjis: |
|
|
case coding_type_big5: |
|
|
/* 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; |
|
|
|
|
|
default: |
|
|
abort (); |
|
6081 |
} |
} |
6082 |
|
|
6083 |
*beg += begp - begp_orig; |
coding->consumed = src - coding->source; |
6084 |
*end += endp - endp_orig; |
coding->consumed_char = pos - coding->src_pos; |
6085 |
return; |
coding->charbuf_used = buf - coding->charbuf; |
6086 |
|
coding->chars_at_source = 0; |
6087 |
} |
} |
6088 |
|
|
|
/* As shrinking conversion region requires some overhead, we don't try |
|
|
shrinking if the length of conversion region is less than this |
|
|
value. */ |
|
|
static int shrink_conversion_region_threshhold = 1024; |
|
6089 |
|
|
6090 |
#define SHRINK_CONVERSION_REGION(beg, end, coding, str, encodep) \ |
/* Encode the text at CODING->src_object into CODING->dst_object. |
6091 |
do { \ |
CODING->src_object is a buffer or a string. |
6092 |
if (*(end) - *(beg) > shrink_conversion_region_threshhold) \ |
CODING->dst_object is a buffer or nil. |
|
{ \ |
|
|
if (encodep) shrink_encoding_region (beg, end, coding, str); \ |
|
|
else shrink_decoding_region (beg, end, coding, str); \ |
|
|
} \ |
|
|
} while (0) |
|
6093 |
|
|
6094 |
static Lisp_Object |
If CODING->src_object is a buffer, it must be the current buffer. |
6095 |
code_convert_region_unwind (arg) |
In this case, if CODING->src_pos is positive, it is a position of |
6096 |
Lisp_Object arg; |
the source text in the buffer, otherwise. the source text is in the |
6097 |
{ |
gap area of the buffer, and coding->src_pos specifies the offset of |
6098 |
inhibit_pre_post_conversion = 0; |
the text from GPT (which must be the same as PT). If this is the |
6099 |
Vlast_coding_system_used = arg; |
same buffer as CODING->dst_object, CODING->src_pos must be |
6100 |
return Qnil; |
negative and CODING should not have `pre-write-conversion'. |
|
} |
|
6101 |
|
|
6102 |
/* Store information about all compositions in the range FROM and TO |
If CODING->src_object is a string, CODING should not have |
6103 |
of OBJ in memory blocks pointed by CODING->cmp_data. OBJ is a |
`pre-write-conversion'. |
|
buffer or a string, defaults to the current buffer. */ |
|
6104 |
|
|
6105 |
void |
If CODING->dst_object is a buffer, the encoded data is inserted at |
6106 |
coding_save_composition (coding, from, to, obj) |
the current point of that buffer. |
6107 |
|
|
6108 |
|
If CODING->dst_object is nil, the encoded data is placed at the |
6109 |
|
memory area specified by CODING->destination. */ |
6110 |
|
|
6111 |
|
static int |
6112 |
|
encode_coding (coding) |
6113 |
struct coding_system *coding; |
struct coding_system *coding; |
|
int from, to; |
|
|
Lisp_Object obj; |
|
6114 |
{ |
{ |
6115 |
Lisp_Object prop; |
Lisp_Object attrs; |
|
int start, end; |
|
6116 |
|
|
6117 |
if (coding->composing == COMPOSITION_DISABLED) |
attrs = CODING_ID_ATTRS (coding->id); |
|
return; |
|
|
if (!coding->cmp_data) |
|
|
coding_allocate_composition_data (coding, from); |
|
|
if (!find_composition (from, to, &start, &end, &prop, obj) |
|
|
|| end > to) |
|
|
return; |
|
|
if (start < from |
|
|
&& (!find_composition (end, to, &start, &end, &prop, obj) |
|
|
|| end > to)) |
|
|
return; |
|
|
coding->composing = COMPOSITION_NO; |
|
|
do |
|
|
{ |
|
|
if (COMPOSITION_VALID_P (start, end, prop)) |
|
|
{ |
|
|
enum composition_method method = COMPOSITION_METHOD (prop); |
|
|
if (coding->cmp_data->used + COMPOSITION_DATA_MAX_BUNCH_LENGTH |
|
|
>= COMPOSITION_DATA_SIZE) |
|
|
coding_allocate_composition_data (coding, from); |
|
|
/* For relative composition, we remember start and end |
|
|
positions, for the other compositions, we also remember |
|
|
components. */ |
|
|
CODING_ADD_COMPOSITION_START (coding, start - from, method); |
|
|
if (method != COMPOSITION_RELATIVE) |
|
|
{ |
|
|
/* We must store a*/ |
|
|
Lisp_Object val, ch; |
|
6118 |
|
|
6119 |
val = COMPOSITION_COMPONENTS (prop); |
if (BUFFERP (coding->dst_object)) |
6120 |
if (CONSP (val)) |
{ |
6121 |
while (CONSP (val)) |
set_buffer_internal (XBUFFER (coding->dst_object)); |
6122 |
{ |
coding->dst_multibyte |
6123 |
ch = XCAR (val), val = XCDR (val); |
= ! NILP (current_buffer->enable_multibyte_characters); |
|
CODING_ADD_COMPOSITION_COMPONENT (coding, XINT (ch)); |
|
|
} |
|
|
else if (VECTORP (val) || STRINGP (val)) |
|
|
{ |
|
|
int len = (VECTORP (val) |
|
|
? XVECTOR (val)->size : SCHARS (val)); |
|
|
int i; |
|
|
for (i = 0; i < len; i++) |
|
|
{ |
|
|
ch = (STRINGP (val) |
|
|
? Faref (val, make_number (i)) |
|
|
: XVECTOR (val)->contents[i]); |
|
|
CODING_ADD_COMPOSITION_COMPONENT (coding, XINT (ch)); |
|
|
} |
|
|
} |
|
|
else /* INTEGERP (val) */ |
|
|
CODING_ADD_COMPOSITION_COMPONENT (coding, XINT (val)); |
|
|
} |
|
|
CODING_ADD_COMPOSITION_END (coding, end - from); |
|
|
} |
|
|
start = end; |
|
6124 |
} |
} |
|
while (start < to |
|
|
&& find_composition (start, to, &start, &end, &prop, obj) |
|
|
&& end <= to); |
|
6125 |
|
|
6126 |
/* Make coding->cmp_data point to the first memory block. */ |
coding->consumed = coding->consumed_char = 0; |
6127 |
while (coding->cmp_data->prev) |
coding->produced = coding->produced_char = 0; |
6128 |
coding->cmp_data = coding->cmp_data->prev; |
coding->result = CODING_RESULT_SUCCESS; |
6129 |
coding->cmp_data_start = 0; |
coding->errors = 0; |
|
} |
|
|
|
|
|
/* Reflect the saved information about compositions to OBJ. |
|
|
CODING->cmp_data points to a memory block for the information. OBJ |
|
|
is a buffer or a string, defaults to the current buffer. */ |
|
|
|
|
|
void |
|
|
coding_restore_composition (coding, obj) |
|
|
struct coding_system *coding; |
|
|
Lisp_Object obj; |
|
|
{ |
|
|
struct composition_data *cmp_data = coding->cmp_data; |
|
6130 |
|
|
6131 |
if (!cmp_data) |
ALLOC_CONVERSION_WORK_AREA (coding); |
|
return; |
|
6132 |
|
|
6133 |
while (cmp_data->prev) |
do { |
6134 |
cmp_data = cmp_data->prev; |
coding_set_source (coding); |
6135 |
|
consume_chars (coding); |
6136 |
|
|
6137 |
while (cmp_data) |
if (!NILP (CODING_ATTR_ENCODE_TBL (attrs))) |
6138 |
{ |
translate_chars (coding, CODING_ATTR_ENCODE_TBL (attrs)); |
6139 |
int i; |
else if (!NILP (Vstandard_translation_table_for_encode)) |
6140 |
|
translate_chars (coding, Vstandard_translation_table_for_encode); |
6141 |
|
|
6142 |
for (i = 0; i < cmp_data->used && cmp_data->data[i] > 0; |
coding_set_destination (coding); |
6143 |
i += cmp_data->data[i]) |
(*(coding->encoder)) (coding); |
6144 |
{ |
} while (coding->consumed_char < coding->src_chars); |
|
int *data = cmp_data->data + i; |
|
|
enum composition_method method = (enum composition_method) data[3]; |
|
|
Lisp_Object components; |
|
6145 |
|
|
6146 |
if (method == COMPOSITION_RELATIVE) |
if (BUFFERP (coding->dst_object)) |
6147 |
components = Qnil; |
insert_from_gap (coding->produced_char, coding->produced); |
|
else |
|
|
{ |
|
|
int len = data[0] - 4, j; |
|
|
Lisp_Object args[MAX_COMPOSITION_COMPONENTS * 2 - 1]; |
|
6148 |
|
|
6149 |
if (method == COMPOSITION_WITH_RULE_ALTCHARS |
return (coding->result); |
|
&& len % 2 == 0) |
|
|
len --; |
|
|
for (j = 0; j < len; j++) |
|
|
args[j] = make_number (data[4 + j]); |
|
|
components = (method == COMPOSITION_WITH_ALTCHARS |
|
|
? Fstring (len, args) : Fvector (len, args)); |
|
|
} |
|
|
compose_text (data[1], data[2], components, Qnil, obj); |
|
|
} |
|
|
cmp_data = cmp_data->next; |
|
|
} |
|
6150 |
} |
} |
6151 |
|
|
|
/* Decode (if ENCODEP is zero) or encode (if ENCODEP is nonzero) the |
|
|
text from FROM to TO (byte positions are FROM_BYTE and TO_BYTE) by |
|
|
coding system CODING, and return the status code of code conversion |
|
|
(currently, this value has no meaning). |
|
6152 |
|
|
6153 |
How many characters (and bytes) are converted to how many |
/* Stack of working buffers used in code conversion. An nil element |
6154 |
characters (and bytes) are recorded in members of the structure |
means that the code conversion of that level is not using a working |
6155 |
CODING. |
buffer. */ |
6156 |
|
Lisp_Object Vcode_conversion_work_buf_list; |
6157 |
|
|
6158 |
If REPLACE is nonzero, we do various things as if the original text |
/* A working buffer used by the top level conversion. */ |
6159 |
is deleted and a new text is inserted. See the comments in |
Lisp_Object Vcode_conversion_reused_work_buf; |
|
replace_range (insdel.c) to know what we are doing. |
|
6160 |
|
|
|
If REPLACE is zero, it is assumed that the source text is unibyte. |
|
|
Otherwise, it is assumed that the source text is multibyte. */ |
|
6161 |
|
|
6162 |
int |
/* Return a working buffer that can be freely used by the following |
6163 |
code_convert_region (from, from_byte, to, to_byte, coding, encodep, replace) |
code conversion. MULTIBYTEP specifies the multibyteness of the |
6164 |
int from, from_byte, to, to_byte, encodep, replace; |
buffer. */ |
|
struct coding_system *coding; |
|
|
{ |
|
|
int len = to - from, len_byte = to_byte - from_byte; |
|
|
int nchars_del = 0, nbytes_del = 0; |
|
|
int require, inserted, inserted_byte; |
|
|
int head_skip, tail_skip, total_skip = 0; |
|
|
Lisp_Object saved_coding_symbol; |
|
|
int first = 1; |
|
|
unsigned char *src, *dst; |
|
|
Lisp_Object deletion; |
|
|
int orig_point = PT, orig_len = len; |
|
|
int prev_Z; |
|
|
int multibyte_p = !NILP (current_buffer->enable_multibyte_characters); |
|
6165 |
|
|
6166 |
deletion = Qnil; |
Lisp_Object |
6167 |
saved_coding_symbol = coding->symbol; |
make_conversion_work_buffer (multibytep, depth) |
6168 |
|
int multibytep, depth; |
6169 |
|
{ |
6170 |
|
struct buffer *current = current_buffer; |
6171 |
|
Lisp_Object buf, name; |
6172 |
|
|
6173 |
if (from < PT && PT < to) |
if (depth == 0) |
6174 |
{ |
{ |
6175 |
TEMP_SET_PT_BOTH (from, from_byte); |
if (NILP (Vcode_conversion_reused_work_buf)) |
6176 |
orig_point = from; |
Vcode_conversion_reused_work_buf |
6177 |
|
= Fget_buffer_create (build_string (" *code-converting-work<0>*")); |
6178 |
|
buf = Vcode_conversion_reused_work_buf; |
6179 |
} |
} |
6180 |
|
else |
|
if (replace) |
|
6181 |
{ |
{ |
6182 |
int saved_from = from; |
if (depth < 0) |
|
int saved_inhibit_modification_hooks; |
|
|
|
|
|
prepare_to_modify_buffer (from, to, &from); |
|
|
if (saved_from != from) |
|
6183 |
{ |
{ |
6184 |
to = from + len; |
name = build_string (" *code-converting-work*"); |
6185 |
from_byte = CHAR_TO_BYTE (from), to_byte = CHAR_TO_BYTE (to); |
name = Fgenerate_new_buffer_name (name, Qnil); |
|
len_byte = to_byte - from_byte; |
|
6186 |
} |
} |
6187 |
|
else |
|
/* The code conversion routine can not preserve text properties |
|
|
for now. So, we must remove all text properties in the |
|
|
region. Here, we must suppress all modification hooks. */ |
|
|
saved_inhibit_modification_hooks = inhibit_modification_hooks; |
|
|
inhibit_modification_hooks = 1; |
|
|
Fset_text_properties (make_number (from), make_number (to), Qnil, Qnil); |
|
|
inhibit_modification_hooks = saved_inhibit_modification_hooks; |
|
|
} |
|
|
|
|
|
if (! encodep && CODING_REQUIRE_DETECTION (coding)) |
|
|
{ |
|
|
/* We must detect encoding of text and eol format. */ |
|
|
|
|
|
if (from < GPT && to > GPT) |
|
|
move_gap_both (from, from_byte); |
|
|
if (coding->type == coding_type_undecided) |
|
6188 |
{ |
{ |
6189 |
detect_coding (coding, BYTE_POS_ADDR (from_byte), len_byte); |
char str[128]; |
|
if (coding->type == coding_type_undecided) |
|
|
{ |
|
|
/* It seems that the text contains only ASCII, but we |
|
|
should not leave it undecided because the deeper |
|
|
decoding routine (decode_coding) tries to detect the |
|
|
encodings again in vain. */ |
|
|
coding->type = coding_type_emacs_mule; |
|
|
coding->category_idx = CODING_CATEGORY_IDX_EMACS_MULE; |
|
|
/* As emacs-mule decoder will handle composition, we |
|
|
need this setting to allocate coding->cmp_data |
|
|
later. */ |
|
|
coding->composing = COMPOSITION_NO; |
|
|
} |
|
|
} |
|
|
if (coding->eol_type == CODING_EOL_UNDECIDED |
|
|
&& coding->type != coding_type_ccl) |
|
|
{ |
|
|
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 inconsistent eol format while decoding. */ |
|
|
coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; |
|
|
} |
|
|
} |
|
6190 |
|
|
6191 |
/* Now we convert the text. */ |
sprintf (str, " *code-converting-work*<%d>", depth); |
6192 |
|
name = build_string (str); |
|
/* For encoding, we must process pre-write-conversion in advance. */ |
|
|
if (! inhibit_pre_post_conversion |
|
|
&& encodep |
|
|
&& SYMBOLP (coding->pre_write_conversion) |
|
|
&& ! NILP (Ffboundp (coding->pre_write_conversion))) |
|
|
{ |
|
|
/* The function in pre-write-conversion may put a new text in a |
|
|
new buffer. */ |
|
|
struct buffer *prev = current_buffer; |
|
|
Lisp_Object new; |
|
|
|
|
|
record_unwind_protect (code_convert_region_unwind, |
|
|
Vlast_coding_system_used); |
|
|
/* We should not call any more pre-write/post-read-conversion |
|
|
functions while this pre-write-conversion is running. */ |
|
|
inhibit_pre_post_conversion = 1; |
|
|
call2 (coding->pre_write_conversion, |
|
|
make_number (from), make_number (to)); |
|
|
inhibit_pre_post_conversion = 0; |
|
|
/* Discard the unwind protect. */ |
|
|
specpdl_ptr--; |
|
|
|
|
|
if (current_buffer != prev) |
|
|
{ |
|
|
len = ZV - BEGV; |
|
|
new = Fcurrent_buffer (); |
|
|
set_buffer_internal_1 (prev); |
|
|
del_range_2 (from, from_byte, to, to_byte, 0); |
|
|
TEMP_SET_PT_BOTH (from, from_byte); |
|
|
insert_from_buffer (XBUFFER (new), 1, len, 0); |
|
|
Fkill_buffer (new); |
|
|
if (orig_point >= to) |
|
|
orig_point += len - orig_len; |
|
|
else if (orig_point > from) |
|
|
orig_point = from; |
|
|
orig_len = len; |
|
|
to = from + len; |
|
|
from_byte = CHAR_TO_BYTE (from); |
|
|
to_byte = CHAR_TO_BYTE (to); |
|
|
len_byte = to_byte - from_byte; |
|
|
TEMP_SET_PT_BOTH (from, from_byte); |
|
6193 |
} |
} |
6194 |
|
buf = Fget_buffer_create (name); |
6195 |
} |
} |
6196 |
|
set_buffer_internal (XBUFFER (buf)); |
6197 |
|
current_buffer->undo_list = Qt; |
6198 |
|
Ferase_buffer (); |
6199 |
|
Fset_buffer_multibyte (multibytep ? Qt : Qnil); |
6200 |
|
set_buffer_internal (current); |
6201 |
|
return buf; |
6202 |
|
} |
6203 |
|
|
6204 |
if (replace) |
static Lisp_Object |
6205 |
{ |
code_conversion_restore (buffer) |
6206 |
if (! EQ (current_buffer->undo_list, Qt)) |
Lisp_Object buffer; |
6207 |
deletion = make_buffer_string_both (from, from_byte, to, to_byte, 1); |
{ |
6208 |
else |
Lisp_Object workbuf; |
|
{ |
|
|
nchars_del = to - from; |
|
|
nbytes_del = to_byte - from_byte; |
|
|
} |
|
|
} |
|
6209 |
|
|
6210 |
if (coding->composing != COMPOSITION_DISABLED) |
workbuf = XCAR (Vcode_conversion_work_buf_list); |
6211 |
{ |
if (! NILP (workbuf) |
6212 |
if (encodep) |
&& ! EQ (workbuf, Vcode_conversion_reused_work_buf) |
6213 |
coding_save_composition (coding, from, to, Fcurrent_buffer ()); |
&& ! NILP (Fbuffer_live_p (workbuf))) |
6214 |
else |
Fkill_buffer (workbuf); |
6215 |
coding_allocate_composition_data (coding, from); |
Vcode_conversion_work_buf_list = XCDR (Vcode_conversion_work_buf_list); |
6216 |
} |
set_buffer_internal (XBUFFER (buffer)); |
6217 |
|
return Qnil; |
6218 |
|
} |
6219 |
|
|
6220 |
/* Try to skip the heading and tailing ASCIIs. */ |
static Lisp_Object |
6221 |
if (coding->type != coding_type_ccl) |
code_conversion_save (buffer, with_work_buf, multibyte) |
6222 |
{ |
Lisp_Object buffer; |
6223 |
int from_byte_orig = from_byte, to_byte_orig = to_byte; |
int with_work_buf, multibyte; |
6224 |
|
{ |
6225 |
|
Lisp_Object workbuf; |
6226 |
|
|
6227 |
if (from < GPT && GPT < to) |
if (with_work_buf) |
6228 |
move_gap_both (from, from_byte); |
{ |
6229 |
SHRINK_CONVERSION_REGION (&from_byte, &to_byte, coding, NULL, encodep); |
int depth = XINT (Flength (Vcode_conversion_work_buf_list)); |
|
if (from_byte == to_byte |
|
|
&& (encodep || NILP (coding->post_read_conversion)) |
|
|
&& ! CODING_REQUIRE_FLUSHING (coding)) |
|
|
{ |
|
|
coding->produced = len_byte; |
|
|
coding->produced_char = len; |
|
|
if (!replace) |
|
|
/* We must record and adjust for this new text now. */ |
|
|
adjust_after_insert (from, from_byte_orig, to, to_byte_orig, len); |
|
|
return 0; |
|
|
} |
|
6230 |
|
|
6231 |
head_skip = from_byte - from_byte_orig; |
workbuf = make_conversion_work_buffer (multibyte, depth); |
|
tail_skip = to_byte_orig - to_byte; |
|
|
total_skip = head_skip + tail_skip; |
|
|
from += head_skip; |
|
|
to -= tail_skip; |
|
|
len -= total_skip; len_byte -= total_skip; |
|
6232 |
} |
} |
6233 |
|
else |
6234 |
|
workbuf = Qnil; |
6235 |
|
Vcode_conversion_work_buf_list |
6236 |
|
= Fcons (workbuf, Vcode_conversion_work_buf_list); |
6237 |
|
record_unwind_protect (code_conversion_restore, buffer); |
6238 |
|
return workbuf; |
6239 |
|
} |
6240 |
|
|
6241 |
/* For conversion, we must put the gap before the text in addition to |
int |
6242 |
making the gap larger for efficient decoding. The required gap |
decode_coding_gap (coding, chars, bytes) |
6243 |
size starts from 2000 which is the magic number used in make_gap. |
struct coding_system *coding; |
6244 |
But, after one batch of conversion, it will be incremented if we |
EMACS_INT chars, bytes; |
6245 |
find that it is not enough . */ |
{ |
6246 |
require = 2000; |
int count = specpdl_ptr - specpdl; |
6247 |
|
Lisp_Object attrs; |
6248 |
|
Lisp_Object buffer; |
6249 |
|
|
6250 |
if (GAP_SIZE < require) |
buffer = Fcurrent_buffer (); |
6251 |
make_gap (require - GAP_SIZE); |
code_conversion_save (buffer, 0, 0); |
|
move_gap_both (from, from_byte); |
|
6252 |
|
|
6253 |
inserted = inserted_byte = 0; |
coding->src_object = buffer; |
6254 |
|
coding->src_chars = chars; |
6255 |
|
coding->src_bytes = bytes; |
6256 |
|
coding->src_pos = -chars; |
6257 |
|
coding->src_pos_byte = -bytes; |
6258 |
|
coding->src_multibyte = chars < bytes; |
6259 |
|
coding->dst_object = buffer; |
6260 |
|
coding->dst_pos = PT; |
6261 |
|
coding->dst_pos_byte = PT_BYTE; |
6262 |
|
coding->dst_multibyte = ! NILP (current_buffer->enable_multibyte_characters); |
6263 |
|
coding->mode |= CODING_MODE_LAST_BLOCK; |
6264 |
|
|
6265 |
GAP_SIZE += len_byte; |
if (CODING_REQUIRE_DETECTION (coding)) |
6266 |
ZV -= len; |
detect_coding (coding); |
|
Z -= len; |
|
|
ZV_BYTE -= len_byte; |
|
|
Z_BYTE -= len_byte; |
|
6267 |
|
|
6268 |
if (GPT - BEG < BEG_UNCHANGED) |
decode_coding (coding); |
|
BEG_UNCHANGED = GPT - BEG; |
|
|
if (Z - GPT < END_UNCHANGED) |
|
|
END_UNCHANGED = Z - GPT; |
|
6269 |
|
|
6270 |
if (!encodep && coding->src_multibyte) |
attrs = CODING_ID_ATTRS (coding->id); |
6271 |
|
if (! NILP (CODING_ATTR_POST_READ (attrs))) |
6272 |
{ |
{ |
6273 |
/* Decoding routines expects that the source text is unibyte. |
EMACS_INT prev_Z = Z, prev_Z_BYTE = Z_BYTE; |
6274 |
We must convert 8-bit characters of multibyte form to |
Lisp_Object val; |
6275 |
unibyte. */ |
|
6276 |
int len_byte_orig = len_byte; |
TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte); |
6277 |
len_byte = str_as_unibyte (GAP_END_ADDR - len_byte, len_byte); |
val = call1 (CODING_ATTR_POST_READ (attrs), |
6278 |
if (len_byte < len_byte_orig) |
make_number (coding->produced_char)); |
6279 |
safe_bcopy (GAP_END_ADDR - len_byte_orig, GAP_END_ADDR - len_byte, |
CHECK_NATNUM (val); |
6280 |
len_byte); |
coding->produced_char += Z - prev_Z; |
6281 |
coding->src_multibyte = 0; |
coding->produced += Z_BYTE - prev_Z_BYTE; |
6282 |
} |
} |
6283 |
|
|
6284 |
for (;;) |
unbind_to (count, Qnil); |
6285 |
{ |
return coding->result; |
6286 |
int result; |
} |
6287 |
|
|
6288 |
/* The buffer memory is now: |
int |
6289 |
+--------+converted-text+---------+-------original-text-------+---+ |
encode_coding_gap (coding, chars, bytes) |
6290 |
|<-from->|<--inserted-->|---------|<--------len_byte--------->|---| |
struct coding_system *coding; |
6291 |
|<---------------------- GAP ----------------------->| */ |
EMACS_INT chars, bytes; |
6292 |
src = GAP_END_ADDR - len_byte; |
{ |
6293 |
dst = GPT_ADDR + inserted_byte; |
int count = specpdl_ptr - specpdl; |
6294 |
|
Lisp_Object buffer; |
6295 |
|
|
6296 |
if (encodep) |
buffer = Fcurrent_buffer (); |
6297 |
result = encode_coding (coding, src, dst, len_byte, 0); |
code_conversion_save (buffer, 0, 0); |
|
else |
|
|
{ |
|
|
if (coding->composing != COMPOSITION_DISABLED) |
|
|
coding->cmp_data->char_offset = from + inserted; |
|
|
result = decode_coding (coding, src, dst, len_byte, 0); |
|
|
} |
|
6298 |
|
|
6299 |
/* The buffer memory is now: |
coding->src_object = buffer; |
6300 |
+--------+-------converted-text----+--+------original-text----+---+ |
coding->src_chars = chars; |
6301 |
|<-from->|<-inserted->|<-produced->|--|<-(len_byte-consumed)->|---| |
coding->src_bytes = bytes; |
6302 |
|<---------------------- GAP ----------------------->| */ |
coding->src_pos = -chars; |
6303 |
|
coding->src_pos_byte = -bytes; |
6304 |
|
coding->src_multibyte = chars < bytes; |
6305 |
|
coding->dst_object = coding->src_object; |
6306 |
|
coding->dst_pos = PT; |
6307 |
|
coding->dst_pos_byte = PT_BYTE; |
6308 |
|
|
6309 |
inserted += coding->produced_char; |
encode_coding (coding); |
|
inserted_byte += coding->produced; |
|
|
len_byte -= coding->consumed; |
|
6310 |
|
|
6311 |
if (result == CODING_FINISH_INSUFFICIENT_CMP) |
unbind_to (count, Qnil); |
6312 |
{ |
return coding->result; |
6313 |
coding_allocate_composition_data (coding, from + inserted); |
} |
|
continue; |
|
|
} |
|
6314 |
|
|
|
src += coding->consumed; |
|
|
dst += coding->produced; |
|
6315 |
|
|
6316 |
if (result == CODING_FINISH_NORMAL) |
/* Decode the text in the range FROM/FROM_BYTE and TO/TO_BYTE in |
6317 |
{ |
SRC_OBJECT into DST_OBJECT by coding context CODING. |
|
src += len_byte; |
|
|
break; |
|
|
} |
|
|
if (! encodep && result == CODING_FINISH_INCONSISTENT_EOL) |
|
|
{ |
|
|
unsigned char *pend = dst, *p = pend - inserted_byte; |
|
|
Lisp_Object eol_type; |
|
6318 |
|
|
6319 |
/* Encode LFs back to the original eol format (CR or CRLF). */ |
SRC_OBJECT is a buffer, a string, or Qnil. |
|
if (coding->eol_type == CODING_EOL_CR) |
|
|
{ |
|
|
while (p < pend) if (*p++ == '\n') p[-1] = '\r'; |
|
|
} |
|
|
else |
|
|
{ |
|
|
int count = 0; |
|
6320 |
|
|
6321 |
while (p < pend) if (*p++ == '\n') count++; |
If it is a buffer, the text is at point of the buffer. FROM and TO |
6322 |
if (src - dst < count) |
are positions in the buffer. |
|
{ |
|
|
/* We don't have sufficient room for encoding LFs |
|
|
back to CRLF. We must record converted and |
|
|
not-yet-converted text back to the buffer |
|
|
content, enlarge the gap, then record them out of |
|
|
the buffer contents again. */ |
|
|
int add = len_byte + inserted_byte; |
|
|
|
|
|
GAP_SIZE -= add; |
|
|
ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add; |
|
|
GPT += inserted_byte; GPT_BYTE += inserted_byte; |
|
|
make_gap (count - GAP_SIZE); |
|
|
GAP_SIZE += add; |
|
|
ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add; |
|
|
GPT -= inserted_byte; GPT_BYTE -= inserted_byte; |
|
|
/* Don't forget to update SRC, DST, and PEND. */ |
|
|
src = GAP_END_ADDR - len_byte; |
|
|
dst = GPT_ADDR + inserted_byte; |
|
|
pend = dst; |
|
|
} |
|
|
inserted += count; |
|
|
inserted_byte += count; |
|
|
coding->produced += count; |
|
|
p = dst = pend + count; |
|
|
while (count) |
|
|
{ |
|
|
*--p = *--pend; |
|
|
if (*p == '\n') count--, *--p = '\r'; |
|
|
} |
|
|
} |
|
6323 |
|
|
6324 |
/* Suppress eol-format conversion in the further conversion. */ |
If it is a string, the text is at the beginning of the string. |
6325 |
coding->eol_type = CODING_EOL_LF; |
FROM and TO are indices to the string. |
|
|
|
|
/* Set the coding system symbol to that for Unix-like EOL. */ |
|
|
eol_type = Fget (saved_coding_symbol, Qeol_type); |
|
|
if (VECTORP (eol_type) |
|
|
&& XVECTOR (eol_type)->size == 3 |
|
|
&& SYMBOLP (XVECTOR (eol_type)->contents[CODING_EOL_LF])) |
|
|
coding->symbol = XVECTOR (eol_type)->contents[CODING_EOL_LF]; |
|
|
else |
|
|
coding->symbol = saved_coding_symbol; |
|
6326 |
|
|
6327 |
continue; |
If it is nil, the text is at coding->source. FROM and TO are |
6328 |
} |
indices to coding->source. |
|
if (len_byte <= 0) |
|
|
{ |
|
|
if (coding->type != coding_type_ccl |
|
|
|| coding->mode & CODING_MODE_LAST_BLOCK) |
|
|
break; |
|
|
coding->mode |= CODING_MODE_LAST_BLOCK; |
|
|
continue; |
|
|
} |
|
|
if (result == CODING_FINISH_INSUFFICIENT_SRC) |
|
|
{ |
|
|
/* The source text ends in invalid codes. Let's just |
|
|
make them valid buffer contents, and finish conversion. */ |
|
|
if (multibyte_p) |
|
|
{ |
|
|
unsigned char *start = dst; |
|
6329 |
|
|
6330 |
inserted += len_byte; |
DST_OBJECT is a buffer, Qt, or Qnil. |
|
while (len_byte--) |
|
|
{ |
|
|
int c = *src++; |
|
|
dst += CHAR_STRING (c, dst); |
|
|
} |
|
6331 |
|
|
6332 |
inserted_byte += dst - start; |
If it is a buffer, the decoded text is inserted at point of the |
6333 |
} |
buffer. If the buffer is the same as SRC_OBJECT, the source text |
6334 |
else |
is deleted. |
|
{ |
|
|
inserted += len_byte; |
|
|
inserted_byte += len_byte; |
|
|
while (len_byte--) |
|
|
*dst++ = *src++; |
|
|
} |
|
|
break; |
|
|
} |
|
|
if (result == CODING_FINISH_INTERRUPT) |
|
|
{ |
|
|
/* The conversion procedure was interrupted by a user. */ |
|
|
break; |
|
|
} |
|
|
/* Now RESULT == CODING_FINISH_INSUFFICIENT_DST */ |
|
|
if (coding->consumed < 1) |
|
|
{ |
|
|
/* It's quite strange to require more memory without |
|
|
consuming any bytes. Perhaps CCL program bug. */ |
|
|
break; |
|
|
} |
|
|
if (first) |
|
|
{ |
|
|
/* We have just done the first batch of conversion which was |
|
|
stopped because of insufficient gap. Let's reconsider the |
|
|
required gap size (i.e. SRT - DST) now. |
|
|
|
|
|
We have converted ORIG bytes (== coding->consumed) into |
|
|
NEW bytes (coding->produced). To convert the remaining |
|
|
LEN bytes, we may need REQUIRE bytes of gap, where: |
|
|
REQUIRE + LEN_BYTE = LEN_BYTE * (NEW / ORIG) |
|
|
REQUIRE = LEN_BYTE * (NEW - ORIG) / ORIG |
|
|
Here, we are sure that NEW >= ORIG. */ |
|
|
float ratio; |
|
|
|
|
|
if (coding->produced <= coding->consumed) |
|
|
{ |
|
|
/* This happens because of CCL-based coding system with |
|
|
eol-type CRLF. */ |
|
|
require = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
ratio = (coding->produced - coding->consumed) / coding->consumed; |
|
|
require = len_byte * ratio; |
|
|
} |
|
|
first = 0; |
|
|
} |
|
|
if ((src - dst) < (require + 2000)) |
|
|
{ |
|
|
/* See the comment above the previous call of make_gap. */ |
|
|
int add = len_byte + inserted_byte; |
|
6335 |
|
|
6336 |
GAP_SIZE -= add; |
If it is Qt, a string is made from the decoded text, and |
6337 |
ZV += add; Z += add; ZV_BYTE += add; Z_BYTE += add; |
set in CODING->dst_object. |
6338 |
GPT += inserted_byte; GPT_BYTE += inserted_byte; |
|
6339 |
make_gap (require + 2000); |
If it is Qnil, the decoded text is stored at CODING->destination. |
6340 |
GAP_SIZE += add; |
The caller must allocate CODING->dst_bytes bytes at |
6341 |
ZV -= add; Z -= add; ZV_BYTE -= add; Z_BYTE -= add; |
CODING->destination by xmalloc. If the decoded text is longer than |
6342 |
GPT -= inserted_byte; GPT_BYTE -= inserted_byte; |
CODING->dst_bytes, CODING->destination is relocated by xrealloc. |
6343 |
} |
*/ |
6344 |
|
|
6345 |
|
void |
6346 |
|
decode_coding_object (coding, src_object, from, from_byte, to, to_byte, |
6347 |
|
dst_object) |
6348 |
|
struct coding_system *coding; |
6349 |
|
Lisp_Object src_object; |
6350 |
|
EMACS_INT from, from_byte, to, to_byte; |
6351 |
|
Lisp_Object dst_object; |
6352 |
|
{ |
6353 |
|
int count = specpdl_ptr - specpdl; |
6354 |
|
unsigned char *destination; |
6355 |
|
EMACS_INT dst_bytes; |
6356 |
|
EMACS_INT chars = to - from; |
6357 |
|
EMACS_INT bytes = to_byte - from_byte; |
6358 |
|
Lisp_Object attrs; |
6359 |
|
Lisp_Object buffer; |
6360 |
|
int saved_pt = -1, saved_pt_byte; |
6361 |
|
|
6362 |
|
buffer = Fcurrent_buffer (); |
6363 |
|
|
6364 |
|
if (NILP (dst_object)) |
6365 |
|
{ |
6366 |
|
destination = coding->destination; |
6367 |
|
dst_bytes = coding->dst_bytes; |
6368 |
} |
} |
|
if (src - dst > 0) *dst = 0; /* Put an anchor. */ |
|
6369 |
|
|
6370 |
if (encodep && coding->dst_multibyte) |
coding->src_object = src_object; |
6371 |
|
coding->src_chars = chars; |
6372 |
|
coding->src_bytes = bytes; |
6373 |
|
coding->src_multibyte = chars < bytes; |
6374 |
|
|
6375 |
|
if (STRINGP (src_object)) |
6376 |
|
{ |
6377 |
|
coding->src_pos = from; |
6378 |
|
coding->src_pos_byte = from_byte; |
6379 |
|
} |
6380 |
|
else if (BUFFERP (src_object)) |
6381 |
{ |
{ |
6382 |
/* The output is unibyte. We must convert 8-bit characters to |
set_buffer_internal (XBUFFER (src_object)); |
6383 |
multibyte form. */ |
if (from != GPT) |
6384 |
if (inserted_byte * 2 > GAP_SIZE) |
move_gap_both (from, from_byte); |
6385 |
|
if (EQ (src_object, dst_object)) |
6386 |
|
{ |
6387 |
|
saved_pt = PT, saved_pt_byte = PT_BYTE; |
6388 |
|
TEMP_SET_PT_BOTH (from, from_byte); |
6389 |
|
del_range_both (from, from_byte, to, to_byte, 1); |
6390 |
|
coding->src_pos = -chars; |
6391 |
|
coding->src_pos_byte = -bytes; |
6392 |
|
} |
6393 |
|
else |
6394 |
{ |
{ |
6395 |
GAP_SIZE -= inserted_byte; |
coding->src_pos = from; |
6396 |
ZV += inserted_byte; Z += inserted_byte; |
coding->src_pos_byte = from_byte; |
|
ZV_BYTE += inserted_byte; Z_BYTE += inserted_byte; |
|
|
GPT += inserted_byte; GPT_BYTE += inserted_byte; |
|
|
make_gap (inserted_byte - GAP_SIZE); |
|
|
GAP_SIZE += inserted_byte; |
|
|
ZV -= inserted_byte; Z -= inserted_byte; |
|
|
ZV_BYTE -= inserted_byte; Z_BYTE -= inserted_byte; |
|
|
GPT -= inserted_byte; GPT_BYTE -= inserted_byte; |
|
6397 |
} |
} |
|
inserted_byte = str_to_multibyte (GPT_ADDR, GAP_SIZE, inserted_byte); |
|
6398 |
} |
} |
6399 |
|
|
6400 |
/* If we shrank the conversion area, adjust it now. */ |
if (CODING_REQUIRE_DETECTION (coding)) |
6401 |
if (total_skip > 0) |
detect_coding (coding); |
6402 |
|
attrs = CODING_ID_ATTRS (coding->id); |
6403 |
|
|
6404 |
|
if (EQ (dst_object, Qt) |
6405 |
|
|| (! NILP (CODING_ATTR_POST_READ (attrs)) |
6406 |
|
&& NILP (dst_object))) |
6407 |
|
{ |
6408 |
|
coding->dst_object = code_conversion_save (buffer, 1, 1); |
6409 |
|
coding->dst_pos = BEG; |
6410 |
|
coding->dst_pos_byte = BEG_BYTE; |
6411 |
|
coding->dst_multibyte = 1; |
6412 |
|
} |
6413 |
|
else if (BUFFERP (dst_object)) |
6414 |
|
{ |
6415 |
|
code_conversion_save (buffer, 0, 0); |
6416 |
|
coding->dst_object = dst_object; |
6417 |
|
coding->dst_pos = BUF_PT (XBUFFER (dst_object)); |
6418 |
|
coding->dst_pos_byte = BUF_PT_BYTE (XBUFFER (dst_object)); |
6419 |
|
coding->dst_multibyte |
6420 |
|
= ! NILP (XBUFFER (dst_object)->enable_multibyte_characters); |
6421 |
|
} |
6422 |
|
else |
6423 |
{ |
{ |
6424 |
if (tail_skip > 0) |
code_conversion_save (buffer, 0, 0); |
6425 |
safe_bcopy (GAP_END_ADDR, GPT_ADDR + inserted_byte, tail_skip); |
coding->dst_object = Qnil; |
6426 |
inserted += total_skip; inserted_byte += total_skip; |
coding->dst_multibyte = 1; |
|
GAP_SIZE += total_skip; |
|
|
GPT -= head_skip; GPT_BYTE -= head_skip; |
|
|
ZV -= total_skip; ZV_BYTE -= total_skip; |
|
|
Z -= total_skip; Z_BYTE -= total_skip; |
|
|
from -= head_skip; from_byte -= head_skip; |
|
|
to += tail_skip; to_byte += tail_skip; |
|
6427 |
} |
} |
6428 |
|
|
6429 |
prev_Z = Z; |
decode_coding (coding); |
|
if (! EQ (current_buffer->undo_list, Qt)) |
|
|
adjust_after_replace (from, from_byte, deletion, inserted, inserted_byte); |
|
|
else |
|
|
adjust_after_replace_noundo (from, from_byte, nchars_del, nbytes_del, |
|
|
inserted, inserted_byte); |
|
|
inserted = Z - prev_Z; |
|
|
|
|
|
if (!encodep && coding->cmp_data && coding->cmp_data->used) |
|
|
coding_restore_composition (coding, Fcurrent_buffer ()); |
|
|
coding_free_composition_data (coding); |
|
6430 |
|
|
6431 |
if (! inhibit_pre_post_conversion |
if (BUFFERP (coding->dst_object)) |
6432 |
&& ! encodep && ! NILP (coding->post_read_conversion)) |
set_buffer_internal (XBUFFER (coding->dst_object)); |
6433 |
|
|
6434 |
|
if (! NILP (CODING_ATTR_POST_READ (attrs))) |
6435 |
{ |
{ |
6436 |
|
struct gcpro gcpro1, gcpro2; |
6437 |
|
EMACS_INT prev_Z = Z, prev_Z_BYTE = Z_BYTE; |
6438 |
Lisp_Object val; |
Lisp_Object val; |
|
Lisp_Object saved_coding_system; |
|
6439 |
|
|
6440 |
if (from != PT) |
TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte); |
6441 |
TEMP_SET_PT_BOTH (from, from_byte); |
GCPRO2 (coding->src_object, coding->dst_object); |
6442 |
prev_Z = Z; |
val = call1 (CODING_ATTR_POST_READ (attrs), |
6443 |
record_unwind_protect (code_convert_region_unwind, |
make_number (coding->produced_char)); |
6444 |
Vlast_coding_system_used); |
UNGCPRO; |
6445 |
saved_coding_system = Vlast_coding_system_used; |
CHECK_NATNUM (val); |
6446 |
Vlast_coding_system_used = coding->symbol; |
coding->produced_char += Z - prev_Z; |
6447 |
/* We should not call any more pre-write/post-read-conversion |
coding->produced += Z_BYTE - prev_Z_BYTE; |
|
functions while this post-read-conversion is running. */ |
|
|
inhibit_pre_post_conversion = 1; |
|
|
val = call1 (coding->post_read_conversion, make_number (inserted)); |
|
|
inhibit_pre_post_conversion = 0; |
|
|
coding->symbol = Vlast_coding_system_used; |
|
|
Vlast_coding_system_used = saved_coding_system; |
|
|
/* Discard the unwind protect. */ |
|
|
specpdl_ptr--; |
|
|
CHECK_NUMBER (val); |
|
|
inserted += Z - prev_Z; |
|
|
} |
|
|
|
|
|
if (orig_point >= from) |
|
|
{ |
|
|
if (orig_point >= from + orig_len) |
|
|
orig_point += inserted - orig_len; |
|
|
else |
|
|
orig_point = from; |
|
|
TEMP_SET_PT (orig_point); |
|
6448 |
} |
} |
6449 |
|
|
6450 |
if (replace) |
if (EQ (dst_object, Qt)) |
6451 |
{ |
{ |
6452 |
signal_after_change (from, to - from, inserted); |
coding->dst_object = Fbuffer_string (); |
6453 |
update_compositions (from, from + inserted, CHECK_BORDER); |
} |
6454 |
|
else if (NILP (dst_object) && BUFFERP (coding->dst_object)) |
6455 |
|
{ |
6456 |
|
set_buffer_internal (XBUFFER (coding->dst_object)); |
6457 |
|
if (dst_bytes < coding->produced) |
6458 |
|
{ |
6459 |
|
destination |
6460 |
|
= (unsigned char *) xrealloc (destination, coding->produced); |
6461 |
|
if (! destination) |
6462 |
|
{ |
6463 |
|
coding->result = CODING_RESULT_INSUFFICIENT_DST; |
6464 |
|
unbind_to (count, Qnil); |
6465 |
|
return; |
6466 |
|
} |
6467 |
|
if (BEGV < GPT && GPT < BEGV + coding->produced_char) |
6468 |
|
move_gap_both (BEGV, BEGV_BYTE); |
6469 |
|
bcopy (BEGV_ADDR, destination, coding->produced); |
6470 |
|
coding->destination = destination; |
6471 |
|
} |
6472 |
} |
} |
6473 |
|
|
6474 |
{ |
if (saved_pt >= 0) |
6475 |
coding->consumed = to_byte - from_byte; |
{ |
6476 |
coding->consumed_char = to - from; |
/* This is the case of: |
6477 |
coding->produced = inserted_byte; |
(BUFFERP (src_object) && EQ (src_object, dst_object)) |
6478 |
coding->produced_char = inserted; |
As we have moved PT while replacing the original buffer |
6479 |
} |
contents, we must recover it now. */ |
6480 |
|
set_buffer_internal (XBUFFER (src_object)); |
6481 |
|
if (saved_pt < from) |
6482 |
|
TEMP_SET_PT_BOTH (saved_pt, saved_pt_byte); |
6483 |
|
else if (saved_pt < from + chars) |
6484 |
|
TEMP_SET_PT_BOTH (from, from_byte); |
6485 |
|
else if (! NILP (current_buffer->enable_multibyte_characters)) |
6486 |
|
TEMP_SET_PT_BOTH (saved_pt + (coding->produced_char - chars), |
6487 |
|
saved_pt_byte + (coding->produced - bytes)); |
6488 |
|
else |
6489 |
|
TEMP_SET_PT_BOTH (saved_pt + (coding->produced - bytes), |
6490 |
|
saved_pt_byte + (coding->produced - bytes)); |
6491 |
|
} |
6492 |
|
|
6493 |
return 0; |
unbind_to (count, Qnil); |
6494 |
} |
} |
6495 |
|
|
6496 |
Lisp_Object |
|
6497 |
run_pre_post_conversion_on_str (str, coding, encodep) |
void |
6498 |
Lisp_Object str; |
encode_coding_object (coding, src_object, from, from_byte, to, to_byte, |
6499 |
|
dst_object) |
6500 |
struct coding_system *coding; |
struct coding_system *coding; |
6501 |
int encodep; |
Lisp_Object src_object; |
6502 |
{ |
EMACS_INT from, from_byte, to, to_byte; |
6503 |
int count = SPECPDL_INDEX (); |
Lisp_Object dst_object; |
6504 |
struct gcpro gcpro1, gcpro2; |
{ |
6505 |
int multibyte = STRING_MULTIBYTE (str); |
int count = specpdl_ptr - specpdl; |
6506 |
|
EMACS_INT chars = to - from; |
6507 |
|
EMACS_INT bytes = to_byte - from_byte; |
6508 |
|
Lisp_Object attrs; |
6509 |
Lisp_Object buffer; |
Lisp_Object buffer; |
6510 |
struct buffer *buf; |
int saved_pt = -1, saved_pt_byte; |
|
Lisp_Object old_deactivate_mark; |
|
6511 |
|
|
6512 |
record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); |
buffer = Fcurrent_buffer (); |
|
record_unwind_protect (code_convert_region_unwind, |
|
|
Vlast_coding_system_used); |
|
|
/* It is not crucial to specbind this. */ |
|
|
old_deactivate_mark = Vdeactivate_mark; |
|
|
GCPRO2 (str, old_deactivate_mark); |
|
|
|
|
|
buffer = Fget_buffer_create (build_string (" *code-converting-work*")); |
|
|
buf = XBUFFER (buffer); |
|
|
|
|
|
delete_all_overlays (buf); |
|
|
buf->directory = current_buffer->directory; |
|
|
buf->read_only = Qnil; |
|
|
buf->filename = Qnil; |
|
|
buf->undo_list = Qt; |
|
|
eassert (buf->overlays_before == NULL); |
|
|
eassert (buf->overlays_after == NULL); |
|
|
|
|
|
set_buffer_internal (buf); |
|
|
/* We must insert the contents of STR as is without |
|
|
unibyte<->multibyte conversion. For that, we adjust the |
|
|
multibyteness of the working buffer to that of STR. */ |
|
|
Ferase_buffer (); |
|
|
buf->enable_multibyte_characters = multibyte ? Qt : Qnil; |
|
6513 |
|
|
6514 |
insert_from_string (str, 0, 0, |
coding->src_object = src_object; |
6515 |
SCHARS (str), SBYTES (str), 0); |
coding->src_chars = chars; |
6516 |
UNGCPRO; |
coding->src_bytes = bytes; |
6517 |
inhibit_pre_post_conversion = 1; |
coding->src_multibyte = chars < bytes; |
6518 |
if (encodep) |
|
6519 |
call2 (coding->pre_write_conversion, make_number (BEG), make_number (Z)); |
attrs = CODING_ID_ATTRS (coding->id); |
6520 |
else |
|
6521 |
{ |
if (! NILP (CODING_ATTR_PRE_WRITE (attrs))) |
6522 |
Vlast_coding_system_used = coding->symbol; |
{ |
6523 |
TEMP_SET_PT_BOTH (BEG, BEG_BYTE); |
coding->src_object = code_conversion_save (buffer, 1, |
6524 |
call1 (coding->post_read_conversion, make_number (Z - BEG)); |
coding->src_multibyte); |
6525 |
coding->symbol = Vlast_coding_system_used; |
set_buffer_internal (XBUFFER (coding->src_object)); |
6526 |
} |
if (STRINGP (src_object)) |
6527 |
inhibit_pre_post_conversion = 0; |
insert_from_string (src_object, from, from_byte, chars, bytes, 0); |
6528 |
Vdeactivate_mark = old_deactivate_mark; |
else if (BUFFERP (src_object)) |
6529 |
str = make_buffer_string (BEG, Z, 1); |
insert_from_buffer (XBUFFER (src_object), from, chars, 0); |
6530 |
return unbind_to (count, str); |
else |
6531 |
} |
insert_1_both (coding->source + from, chars, bytes, 0, 0, 0); |
6532 |
|
|
6533 |
Lisp_Object |
if (EQ (src_object, dst_object)) |
|
decode_coding_string (str, coding, nocopy) |
|
|
Lisp_Object str; |
|
|
struct coding_system *coding; |
|
|
int nocopy; |
|
|
{ |
|
|
int len; |
|
|
struct conversion_buffer buf; |
|
|
int from, to_byte; |
|
|
Lisp_Object saved_coding_symbol; |
|
|
int result; |
|
|
int require_decoding; |
|
|
int shrinked_bytes = 0; |
|
|
Lisp_Object newstr; |
|
|
int consumed, consumed_char, produced, produced_char; |
|
|
|
|
|
from = 0; |
|
|
to_byte = SBYTES (str); |
|
|
|
|
|
saved_coding_symbol = coding->symbol; |
|
|
coding->src_multibyte = STRING_MULTIBYTE (str); |
|
|
coding->dst_multibyte = 1; |
|
|
if (CODING_REQUIRE_DETECTION (coding)) |
|
|
{ |
|
|
/* See the comments in code_convert_region. */ |
|
|
if (coding->type == coding_type_undecided) |
|
6534 |
{ |
{ |
6535 |
detect_coding (coding, SDATA (str), to_byte); |
set_buffer_internal (XBUFFER (src_object)); |
6536 |
if (coding->type == coding_type_undecided) |
saved_pt = PT, saved_pt_byte = PT_BYTE; |
6537 |
{ |
del_range_both (from, from_byte, to, to_byte, 1); |
6538 |
coding->type = coding_type_emacs_mule; |
set_buffer_internal (XBUFFER (coding->src_object)); |
6539 |
coding->category_idx = CODING_CATEGORY_IDX_EMACS_MULE; |
} |
6540 |
/* As emacs-mule decoder will handle composition, we |
|
6541 |
need this setting to allocate coding->cmp_data |
call2 (CODING_ATTR_PRE_WRITE (attrs), |
6542 |
later. */ |
make_number (BEG), make_number (Z)); |
6543 |
coding->composing = COMPOSITION_NO; |
coding->src_object = Fcurrent_buffer (); |
6544 |
} |
if (BEG != GPT) |
6545 |
|
move_gap_both (BEG, BEG_BYTE); |
6546 |
|
coding->src_chars = Z - BEG; |
6547 |
|
coding->src_bytes = Z_BYTE - BEG_BYTE; |
6548 |
|
coding->src_pos = BEG; |
6549 |
|
coding->src_pos_byte = BEG_BYTE; |
6550 |
|
coding->src_multibyte = Z < Z_BYTE; |
6551 |
|
} |
6552 |
|
else if (STRINGP (src_object)) |
6553 |
|
{ |
6554 |
|
code_conversion_save (buffer, 0, 0); |
6555 |
|
coding->src_pos = from; |
6556 |
|
coding->src_pos_byte = from_byte; |
6557 |
|
} |
6558 |
|
else if (BUFFERP (src_object)) |
6559 |
|
{ |
6560 |
|
code_conversion_save (buffer, 0, 0); |
6561 |
|
set_buffer_internal (XBUFFER (src_object)); |
6562 |
|
if (EQ (src_object, dst_object)) |
6563 |
|
{ |
6564 |
|
saved_pt = PT, saved_pt_byte = PT_BYTE; |
6565 |
|
coding->src_object = del_range_1 (from, to, 1, 1); |
6566 |
|
coding->src_pos = 0; |
6567 |
|
coding->src_pos_byte = 0; |
6568 |
} |
} |
6569 |
if (coding->eol_type == CODING_EOL_UNDECIDED |
else |
|
&& coding->type != coding_type_ccl) |
|
6570 |
{ |
{ |
6571 |
saved_coding_symbol = coding->symbol; |
if (from < GPT && to >= GPT) |
6572 |
detect_eol (coding, SDATA (str), to_byte); |
move_gap_both (from, from_byte); |
6573 |
if (coding->eol_type == CODING_EOL_UNDECIDED) |
coding->src_pos = from; |
6574 |
coding->eol_type = CODING_EOL_LF; |
coding->src_pos_byte = from_byte; |
|
/* We had better recover the original eol format if we |
|
|
encounter an inconsistent eol format while decoding. */ |
|
|
coding->mode |= CODING_MODE_INHIBIT_INCONSISTENT_EOL; |
|
6575 |
} |
} |
6576 |
} |
} |
6577 |
|
else |
6578 |
|
code_conversion_save (buffer, 0, 0); |
6579 |
|
|
6580 |
if (coding->type == coding_type_no_conversion |
if (BUFFERP (dst_object)) |
|
|| coding->type == coding_type_raw_text) |
|
|
coding->dst_multibyte = 0; |
|
|
|
|
|
require_decoding = CODING_REQUIRE_DECODING (coding); |
|
|
|
|
|
if (STRING_MULTIBYTE (str)) |
|
|
{ |
|
|
/* Decoding routines expect the source text to be unibyte. */ |
|
|
str = Fstring_as_unibyte (str); |
|
|
to_byte = SBYTES (str); |
|
|
nocopy = 1; |
|
|
coding->src_multibyte = 0; |
|
|
} |
|
|
|
|
|
/* Try to skip the heading and tailing ASCIIs. */ |
|
|
if (require_decoding && coding->type != coding_type_ccl) |
|
|
{ |
|
|
SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str), |
|
|
0); |
|
|
if (from == to_byte) |
|
|
require_decoding = 0; |
|
|
shrinked_bytes = from + (SBYTES (str) - to_byte); |
|
|
} |
|
|
|
|
|
if (!require_decoding |
|
|
&& !(SYMBOLP (coding->post_read_conversion) |
|
|
&& !NILP (Ffboundp (coding->post_read_conversion)))) |
|
6581 |
{ |
{ |
6582 |
coding->consumed = SBYTES (str); |
coding->dst_object = dst_object; |
6583 |
coding->consumed_char = SCHARS (str); |
if (EQ (src_object, dst_object)) |
6584 |
if (coding->dst_multibyte) |
{ |
6585 |
|
coding->dst_pos = from; |
6586 |
|
coding->dst_pos_byte = from_byte; |
6587 |
|
} |
6588 |
|
else |
6589 |
{ |
{ |
6590 |
str = Fstring_as_multibyte (str); |
coding->dst_pos = BUF_PT (XBUFFER (dst_object)); |
6591 |
nocopy = 1; |
coding->dst_pos_byte = BUF_PT_BYTE (XBUFFER (dst_object)); |
6592 |
} |
} |
6593 |
coding->produced = SBYTES (str); |
coding->dst_multibyte |
6594 |
coding->produced_char = SCHARS (str); |
= ! NILP (XBUFFER (dst_object)->enable_multibyte_characters); |
|
return (nocopy ? str : Fcopy_sequence (str)); |
|
6595 |
} |
} |
6596 |
|
else if (EQ (dst_object, Qt)) |
|
if (coding->composing != COMPOSITION_DISABLED) |
|
|
coding_allocate_composition_data (coding, from); |
|
|
len = decoding_buffer_size (coding, to_byte - from); |
|
|
allocate_conversion_buffer (buf, len); |
|
|
|
|
|
consumed = consumed_char = produced = produced_char = 0; |
|
|
while (1) |
|
6597 |
{ |
{ |
6598 |
result = decode_coding (coding, SDATA (str) + from + consumed, |
coding->dst_object = Qnil; |
6599 |
buf.data + produced, to_byte - from - consumed, |
coding->dst_bytes = coding->src_chars; |
6600 |
buf.size - produced); |
if (coding->dst_bytes == 0) |
6601 |
consumed += coding->consumed; |
coding->dst_bytes = 1; |
6602 |
consumed_char += coding->consumed_char; |
coding->destination = (unsigned char *) xmalloc (coding->dst_bytes); |
6603 |
produced += coding->produced; |
coding->dst_multibyte = 0; |
|
produced_char += coding->produced_char; |
|
|
if (result == CODING_FINISH_NORMAL |
|
|
|| (result == CODING_FINISH_INSUFFICIENT_SRC |
|
|
&& coding->consumed == 0)) |
|
|
break; |
|
|
if (result == CODING_FINISH_INSUFFICIENT_CMP) |
|
|
coding_allocate_composition_data (coding, from + produced_char); |
|
|
else if (result == CODING_FINISH_INSUFFICIENT_DST) |
|
|
extend_conversion_buffer (&buf); |
|
|
else if (result == CODING_FINISH_INCONSISTENT_EOL) |
|
|
{ |
|
|
Lisp_Object eol_type; |
|
|
|
|
|
/* Recover the original EOL format. */ |
|
|
if (coding->eol_type == CODING_EOL_CR) |
|
|
{ |
|
|
unsigned char *p; |
|
|
for (p = buf.data; p < buf.data + produced; p++) |
|
|
if (*p == '\n') *p = '\r'; |
|
|
} |
|
|
else if (coding->eol_type == CODING_EOL_CRLF) |
|
|
{ |
|
|
int num_eol = 0; |
|
|
unsigned char *p0, *p1; |
|
|
for (p0 = buf.data, p1 = p0 + produced; p0 < p1; p0++) |
|
|
if (*p0 == '\n') num_eol++; |
|
|
if (produced + num_eol >= buf.size) |
|
|
extend_conversion_buffer (&buf); |
|
|
for (p0 = buf.data + produced, p1 = p0 + num_eol; p0 > buf.data;) |
|
|
{ |
|
|
*--p1 = *--p0; |
|
|
if (*p0 == '\n') *--p1 = '\r'; |
|
|
} |
|
|
produced += num_eol; |
|
|
produced_char += num_eol; |
|
|
} |
|
|
/* Suppress eol-format conversion in the further conversion. */ |
|
|
coding->eol_type = CODING_EOL_LF; |
|
|
|
|
|
/* Set the coding system symbol to that for Unix-like EOL. */ |
|
|
eol_type = Fget (saved_coding_symbol, Qeol_type); |
|
|
if (VECTORP (eol_type) |
|
|
&& XVECTOR (eol_type)->size == 3 |
|
|
&& SYMBOLP (XVECTOR (eol_type)->contents[CODING_EOL_LF])) |
|
|
coding->symbol = XVECTOR (eol_type)->contents[CODING_EOL_LF]; |
|
|
else |
|
|
coding->symbol = saved_coding_symbol; |
|
|
|
|
|
|
|
|
} |
|
6604 |
} |
} |
|
|
|
|
coding->consumed = consumed; |
|
|
coding->consumed_char = consumed_char; |
|
|
coding->produced = produced; |
|
|
coding->produced_char = produced_char; |
|
|
|
|
|
if (coding->dst_multibyte) |
|
|
newstr = make_uninit_multibyte_string (produced_char + shrinked_bytes, |
|
|
produced + shrinked_bytes); |
|
6605 |
else |
else |
6606 |
newstr = make_uninit_string (produced + shrinked_bytes); |
{ |
6607 |
if (from > 0) |
coding->dst_object = Qnil; |
6608 |
STRING_COPYIN (newstr, 0, SDATA (str), from); |
coding->dst_multibyte = 0; |
6609 |
STRING_COPYIN (newstr, from, buf.data, produced); |
} |
|
if (shrinked_bytes > from) |
|
|
STRING_COPYIN (newstr, from + produced, |
|
|
SDATA (str) + to_byte, |
|
|
shrinked_bytes - from); |
|
|
free_conversion_buffer (&buf); |
|
|
|
|
|
if (coding->cmp_data && coding->cmp_data->used) |
|
|
coding_restore_composition (coding, newstr); |
|
|
coding_free_composition_data (coding); |
|
|
|
|
|
if (SYMBOLP (coding->post_read_conversion) |
|
|
&& !NILP (Ffboundp (coding->post_read_conversion))) |
|
|
newstr = run_pre_post_conversion_on_str (newstr, coding, 0); |
|
|
|
|
|
return newstr; |
|
|
} |
|
|
|
|
|
Lisp_Object |
|
|
encode_coding_string (str, coding, nocopy) |
|
|
Lisp_Object str; |
|
|
struct coding_system *coding; |
|
|
int nocopy; |
|
|
{ |
|
|
int len; |
|
|
struct conversion_buffer buf; |
|
|
int from, to, to_byte; |
|
|
int result; |
|
|
int shrinked_bytes = 0; |
|
|
Lisp_Object newstr; |
|
|
int consumed, consumed_char, produced, produced_char; |
|
|
|
|
|
if (SYMBOLP (coding->pre_write_conversion) |
|
|
&& !NILP (Ffboundp (coding->pre_write_conversion))) |
|
|
str = run_pre_post_conversion_on_str (str, coding, 1); |
|
6610 |
|
|
6611 |
from = 0; |
encode_coding (coding); |
|
to = SCHARS (str); |
|
|
to_byte = SBYTES (str); |
|
6612 |
|
|
6613 |
/* Encoding routines determine the multibyteness of the source text |
if (EQ (dst_object, Qt)) |
|
by coding->src_multibyte. */ |
|
|
coding->src_multibyte = STRING_MULTIBYTE (str); |
|
|
coding->dst_multibyte = 0; |
|
|
if (! CODING_REQUIRE_ENCODING (coding)) |
|
6614 |
{ |
{ |
6615 |
coding->consumed = SBYTES (str); |
if (BUFFERP (coding->dst_object)) |
6616 |
coding->consumed_char = SCHARS (str); |
coding->dst_object = Fbuffer_string (); |
6617 |
if (STRING_MULTIBYTE (str)) |
else |
6618 |
{ |
{ |
6619 |
str = Fstring_as_unibyte (str); |
coding->dst_object |
6620 |
nocopy = 1; |
= make_unibyte_string ((char *) coding->destination, |
6621 |
|
coding->produced); |
6622 |
|
xfree (coding->destination); |
6623 |
} |
} |
|
coding->produced = SBYTES (str); |
|
|
coding->produced_char = SCHARS (str); |
|
|
return (nocopy ? str : Fcopy_sequence (str)); |
|
6624 |
} |
} |
6625 |
|
|
6626 |
if (coding->composing != COMPOSITION_DISABLED) |
if (saved_pt >= 0) |
6627 |
coding_save_composition (coding, from, to, str); |
{ |
6628 |
|
/* This is the case of: |
6629 |
/* Try to skip the heading and tailing ASCIIs. */ |
(BUFFERP (src_object) && EQ (src_object, dst_object)) |
6630 |
if (coding->type != coding_type_ccl) |
As we have moved PT while replacing the original buffer |
6631 |
{ |
contents, we must recover it now. */ |
6632 |
SHRINK_CONVERSION_REGION (&from, &to_byte, coding, SDATA (str), |
set_buffer_internal (XBUFFER (src_object)); |
6633 |
1); |
if (saved_pt < from) |
6634 |
if (from == to_byte) |
TEMP_SET_PT_BOTH (saved_pt, saved_pt_byte); |
6635 |
return (nocopy ? str : Fcopy_sequence (str)); |
else if (saved_pt < from + chars) |
6636 |
shrinked_bytes = from + (SBYTES (str) - to_byte); |
TEMP_SET_PT_BOTH (from, from_byte); |
6637 |
|
else if (! NILP (current_buffer->enable_multibyte_characters)) |
6638 |
|
TEMP_SET_PT_BOTH (saved_pt + (coding->produced_char - chars), |
6639 |
|
saved_pt_byte + (coding->produced - bytes)); |
6640 |
|
else |
6641 |
|
TEMP_SET_PT_BOTH (saved_pt + (coding->produced - bytes), |
6642 |
|
saved_pt_byte + (coding->produced - bytes)); |
6643 |
} |
} |
6644 |
|
|
6645 |
len = encoding_buffer_size (coding, to_byte - from); |
unbind_to (count, Qnil); |
6646 |
allocate_conversion_buffer (buf, len); |
} |
|
|
|
|
consumed = consumed_char = produced = produced_char = 0; |
|
|
while (1) |
|
|
{ |
|
|
result = encode_coding (coding, SDATA (str) + from + consumed, |
|
|
buf.data + produced, to_byte - from - consumed, |
|
|
buf.size - produced); |
|
|
consumed += coding->consumed; |
|
|
consumed_char += coding->consumed_char; |
|
|
produced += coding->produced; |
|
|
produced_char += coding->produced_char; |
|
|
if (result == CODING_FINISH_NORMAL |
|
|
|| (result == CODING_FINISH_INSUFFICIENT_SRC |
|
|
&& coding->consumed == 0)) |
|
|
break; |
|
|
/* Now result should be CODING_FINISH_INSUFFICIENT_DST. */ |
|
|
extend_conversion_buffer (&buf); |
|
|
} |
|
6647 |
|
|
|
coding->consumed = consumed; |
|
|
coding->consumed_char = consumed_char; |
|
|
coding->produced = produced; |
|
|
coding->produced_char = produced_char; |
|
|
|
|
|
newstr = make_uninit_string (produced + shrinked_bytes); |
|
|
if (from > 0) |
|
|
STRING_COPYIN (newstr, 0, SDATA (str), from); |
|
|
STRING_COPYIN (newstr, from, buf.data, produced); |
|
|
if (shrinked_bytes > from) |
|
|
STRING_COPYIN (newstr, from + produced, |
|
|
SDATA (str) + to_byte, |
|
|
shrinked_bytes - from); |
|
6648 |
|
|
6649 |
free_conversion_buffer (&buf); |
Lisp_Object |
6650 |
coding_free_composition_data (coding); |
preferred_coding_system () |
6651 |
|
{ |
6652 |
|
int id = coding_categories[coding_priorities[0]].id; |
6653 |
|
|
6654 |
return newstr; |
return CODING_ID_NAME (id); |
6655 |
} |
} |
6656 |
|
|
6657 |
|
|
6660 |
|
|
6661 |
DEFUN ("coding-system-p", Fcoding_system_p, Scoding_system_p, 1, 1, 0, |
DEFUN ("coding-system-p", Fcoding_system_p, Scoding_system_p, 1, 1, 0, |
6662 |
doc: /* Return t if OBJECT is nil or a coding-system. |
doc: /* Return t if OBJECT is nil or a coding-system. |
6663 |
See the documentation of `make-coding-system' for information |
See the documentation of `define-coding-system' for information |
6664 |
about coding-system objects. */) |
about coding-system objects. */) |
6665 |
(obj) |
(obj) |
6666 |
Lisp_Object obj; |
Lisp_Object obj; |
6667 |
{ |
{ |
6668 |
if (NILP (obj)) |
return ((NILP (obj) || CODING_SYSTEM_P (obj)) ? Qt : Qnil); |
|
return Qt; |
|
|
if (!SYMBOLP (obj)) |
|
|
return Qnil; |
|
|
/* Get coding-spec vector for OBJ. */ |
|
|
obj = Fget (obj, Qcoding_system); |
|
|
return ((VECTORP (obj) && XVECTOR (obj)->size == 5) |
|
|
? Qt : Qnil); |
|
6669 |
} |
} |
6670 |
|
|
6671 |
DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system, |
DEFUN ("read-non-nil-coding-system", Fread_non_nil_coding_system, |
6692 |
{ |
{ |
6693 |
Lisp_Object val; |
Lisp_Object val; |
6694 |
if (SYMBOLP (default_coding_system)) |
if (SYMBOLP (default_coding_system)) |
6695 |
default_coding_system = SYMBOL_NAME (default_coding_system); |
XSETSTRING (default_coding_system, SYMBOL_NAME (default_coding_system)); |
6696 |
val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil, |
val = Fcompleting_read (prompt, Vcoding_system_alist, Qnil, |
6697 |
Qt, Qnil, Qcoding_system_history, |
Qt, Qnil, Qcoding_system_history, |
6698 |
default_coding_system, Qnil); |
default_coding_system, Qnil); |
6702 |
DEFUN ("check-coding-system", Fcheck_coding_system, Scheck_coding_system, |
DEFUN ("check-coding-system", Fcheck_coding_system, Scheck_coding_system, |
6703 |
1, 1, 0, |
1, 1, 0, |
6704 |
doc: /* Check validity of CODING-SYSTEM. |
doc: /* Check validity of CODING-SYSTEM. |
6705 |
If valid, return CODING-SYSTEM, else signal a `coding-system-error' error. |
If valid, return CODING-SYSTEM, else signal a `coding-system-error' error. */) |
6706 |
It is valid if it is a symbol with a non-nil `coding-system' property. |
(coding_system) |
|
The value of property should be a vector of length 5. */) |
|
|
(coding_system) |
|
6707 |
Lisp_Object coding_system; |
Lisp_Object coding_system; |
6708 |
{ |
{ |
6709 |
CHECK_SYMBOL (coding_system); |
CHECK_SYMBOL (coding_system); |
6712 |
while (1) |
while (1) |
6713 |
Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil)); |
Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil)); |
6714 |
} |
} |
6715 |
|
|
6716 |
|
|
6717 |
|
/* Detect how the bytes at SRC of length SRC_BYTES are encoded. If |
6718 |
|
HIGHEST is nonzero, return the coding system of the highest |
6719 |
|
priority among the detected coding systems. Otherwize return a |
6720 |
|
list of detected coding systems sorted by their priorities. If |
6721 |
|
MULTIBYTEP is nonzero, it is assumed that the bytes are in correct |
6722 |
|
multibyte form but contains only ASCII and eight-bit chars. |
6723 |
|
Otherwise, the bytes are raw bytes. |
6724 |
|
|
6725 |
|
CODING-SYSTEM controls the detection as below: |
6726 |
|
|
6727 |
|
If it is nil, detect both text-format and eol-format. If the |
6728 |
|
text-format part of CODING-SYSTEM is already specified |
6729 |
|
(e.g. `iso-latin-1'), detect only eol-format. If the eol-format |
6730 |
|
part of CODING-SYSTEM is already specified (e.g. `undecided-unix'), |
6731 |
|
detect only text-format. */ |
6732 |
|
|
6733 |
Lisp_Object |
Lisp_Object |
6734 |
detect_coding_system (src, src_bytes, highest, multibytep) |
detect_coding_system (src, src_bytes, highest, multibytep, coding_system) |
6735 |
const unsigned char *src; |
const unsigned char *src; |
6736 |
int src_bytes, highest; |
int src_bytes, highest; |
6737 |
int multibytep; |
int multibytep; |
6738 |
|
Lisp_Object coding_system; |
6739 |
{ |
{ |
6740 |
int coding_mask, eol_type; |
const unsigned char *src_end = src + src_bytes; |
6741 |
Lisp_Object val, tmp; |
Lisp_Object attrs, eol_type; |
6742 |
int dummy; |
Lisp_Object val; |
6743 |
|
struct coding_system coding; |
6744 |
|
int id; |
6745 |
|
struct coding_detection_info detect_info; |
6746 |
|
|
6747 |
|
if (NILP (coding_system)) |
6748 |
|
coding_system = Qundecided; |
6749 |
|
setup_coding_system (coding_system, &coding); |
6750 |
|
attrs = CODING_ID_ATTRS (coding.id); |
6751 |
|
eol_type = CODING_ID_EOL_TYPE (coding.id); |
6752 |
|
coding_system = CODING_ATTR_BASE_NAME (attrs); |
6753 |
|
|
6754 |
|
coding.source = src; |
6755 |
|
coding.src_bytes = src_bytes; |
6756 |
|
coding.src_multibyte = multibytep; |
6757 |
|
coding.consumed = 0; |
6758 |
|
coding.mode |= CODING_MODE_LAST_BLOCK; |
6759 |
|
|
6760 |
coding_mask = detect_coding_mask (src, src_bytes, NULL, &dummy, multibytep); |
detect_info.checked = detect_info.found = detect_info.rejected = 0; |
|
eol_type = detect_eol_type (src, src_bytes, &dummy); |
|
|
if (eol_type == CODING_EOL_INCONSISTENT) |
|
|
eol_type = CODING_EOL_UNDECIDED; |
|
6761 |
|
|
6762 |
if (!coding_mask) |
/* At first, detect text-format if necessary. */ |
6763 |
|
if (XINT (CODING_ATTR_CATEGORY (attrs)) == coding_category_undecided) |
6764 |
{ |
{ |
6765 |
val = Qundecided; |
enum coding_category category; |
6766 |
if (eol_type != CODING_EOL_UNDECIDED) |
struct coding_system *this; |
6767 |
{ |
int c, i; |
6768 |
Lisp_Object val2; |
|
6769 |
val2 = Fget (Qundecided, Qeol_type); |
for (; src < src_end; src++) |
6770 |
if (VECTORP (val2)) |
{ |
6771 |
val = XVECTOR (val2)->contents[eol_type]; |
c = *src; |
6772 |
|
if (c & 0x80 |
6773 |
|
|| (c < 0x20 && (c == ISO_CODE_ESC |
6774 |
|
|| c == ISO_CODE_SI |
6775 |
|
|| c == ISO_CODE_SO))) |
6776 |
|
break; |
6777 |
} |
} |
6778 |
return (highest ? val : Fcons (val, Qnil)); |
coding.head_ascii = src - coding.source; |
|
} |
|
6779 |
|
|
6780 |
/* At first, gather possible coding systems in VAL. */ |
if (src < src_end) |
6781 |
val = Qnil; |
for (i = 0; i < coding_category_raw_text; i++) |
6782 |
for (tmp = Vcoding_category_list; CONSP (tmp); tmp = XCDR (tmp)) |
{ |
6783 |
{ |
category = coding_priorities[i]; |
6784 |
Lisp_Object category_val, category_index; |
this = coding_categories + category; |
6785 |
|
|
6786 |
category_index = Fget (XCAR (tmp), Qcoding_category_index); |
if (this->id < 0) |
6787 |
category_val = Fsymbol_value (XCAR (tmp)); |
{ |
6788 |
if (!NILP (category_val) |
/* No coding system of this category is defined. */ |
6789 |
&& NATNUMP (category_index) |
detect_info.rejected |= (1 << category); |
6790 |
&& (coding_mask & (1 << XFASTINT (category_index)))) |
} |
6791 |
|
else if (category >= coding_category_raw_text) |
6792 |
|
continue; |
6793 |
|
else if (detect_info.checked & (1 << category)) |
6794 |
|
{ |
6795 |
|
if (highest |
6796 |
|
&& (detect_info.found & (1 << category))) |
6797 |
|
break; |
6798 |
|
} |
6799 |
|
else |
6800 |
|
{ |
6801 |
|
if ((*(this->detector)) (&coding, &detect_info) |
6802 |
|
&& highest |
6803 |
|
&& (detect_info.found & (1 << category))) |
6804 |
|
break; |
6805 |
|
} |
6806 |
|
} |
6807 |
|
|
6808 |
|
|
6809 |
|
if (detect_info.rejected == CATEGORY_MASK_ANY) |
6810 |
{ |
{ |
6811 |
val = Fcons (category_val, val); |
detect_info.found = CATEGORY_MASK_RAW_TEXT; |
6812 |
if (highest) |
id = coding_categories[coding_category_raw_text].id; |
6813 |
break; |
val = Fcons (make_number (id), Qnil); |
6814 |
} |
} |
6815 |
} |
else if (! detect_info.rejected && ! detect_info.found) |
6816 |
if (!highest) |
{ |
6817 |
val = Fnreverse (val); |
detect_info.found = CATEGORY_MASK_ANY; |
6818 |
|
id = coding_categories[coding_category_undecided].id; |
6819 |
/* Then, replace the elements with subsidiary coding systems. */ |
val = Fcons (make_number (id), Qnil); |
6820 |
for (tmp = val; CONSP (tmp); tmp = XCDR (tmp)) |
} |
6821 |
{ |
else if (highest) |
6822 |
if (eol_type != CODING_EOL_UNDECIDED |
{ |
6823 |
&& eol_type != CODING_EOL_INCONSISTENT) |
if (detect_info.found) |
6824 |
|
{ |
6825 |
|
detect_info.found = 1 << category; |
6826 |
|
val = Fcons (make_number (this->id), Qnil); |
6827 |
|
} |
6828 |
|
else |
6829 |
|
for (i = 0; i < coding_category_raw_text; i++) |
6830 |
|
if (! (detect_info.rejected & (1 << coding_priorities[i]))) |
6831 |
|
{ |
6832 |
|
detect_info.found = 1 << coding_priorities[i]; |
6833 |
|
id = coding_categories[coding_priorities[i]].id; |
6834 |
|
val = Fcons (make_number (id), Qnil); |
6835 |
|
break; |
6836 |
|
} |
6837 |
|
} |
6838 |
|
else |
6839 |
{ |
{ |
6840 |
Lisp_Object eol; |
int mask = detect_info.rejected | detect_info.found; |
6841 |
eol = Fget (XCAR (tmp), Qeol_type); |
int found = 0; |
6842 |
if (VECTORP (eol)) |
val = Qnil; |
6843 |
XSETCAR (tmp, XVECTOR (eol)->contents[eol_type]); |
|
6844 |
|
for (i = coding_category_raw_text - 1; i >= 0; i--) |
6845 |
|
{ |
6846 |
|
category = coding_priorities[i]; |
6847 |
|
if (! (mask & (1 << category))) |
6848 |
|
{ |
6849 |
|
found |= 1 << category; |
6850 |
|
id = coding_categories[category].id; |
6851 |
|
val = Fcons (make_number (id), val); |
6852 |
|
} |
6853 |
|
} |
6854 |
|
for (i = coding_category_raw_text - 1; i >= 0; i--) |
6855 |
|
{ |
6856 |
|
category = coding_priorities[i]; |
6857 |
|
if (detect_info.found & (1 << category)) |
6858 |
|
{ |
6859 |
|
id = coding_categories[category].id; |
6860 |
|
val = Fcons (make_number (id), val); |
6861 |
|
} |
6862 |
|
} |
6863 |
|
detect_info.found |= found; |
6864 |
} |
} |
6865 |
} |
} |
6866 |
|
else |
6867 |
|
{ |
6868 |
|
detect_info.found = 1 << XINT (CODING_ATTR_CATEGORY (attrs)); |
6869 |
|
val = Fcons (make_number (coding.id), Qnil); |
6870 |
|
} |
6871 |
|
|
6872 |
|
/* Then, detect eol-format if necessary. */ |
6873 |
|
{ |
6874 |
|
int normal_eol = -1, utf_16_be_eol = -1, utf_16_le_eol; |
6875 |
|
Lisp_Object tail; |
6876 |
|
|
6877 |
|
if (VECTORP (eol_type)) |
6878 |
|
{ |
6879 |
|
if (detect_info.found & ~CATEGORY_MASK_UTF_16) |
6880 |
|
normal_eol = detect_eol (coding.source, src_bytes, |
6881 |
|
coding_category_raw_text); |
6882 |
|
if (detect_info.found & (CATEGORY_MASK_UTF_16_BE |
6883 |
|
| CATEGORY_MASK_UTF_16_BE_NOSIG)) |
6884 |
|
utf_16_be_eol = detect_eol (coding.source, src_bytes, |
6885 |
|
coding_category_utf_16_be); |
6886 |
|
if (detect_info.found & (CATEGORY_MASK_UTF_16_LE |
6887 |
|
| CATEGORY_MASK_UTF_16_LE_NOSIG)) |
6888 |
|
utf_16_le_eol = detect_eol (coding.source, src_bytes, |
6889 |
|
coding_category_utf_16_le); |
6890 |
|
} |
6891 |
|
else |
6892 |
|
{ |
6893 |
|
if (EQ (eol_type, Qunix)) |
6894 |
|
normal_eol = utf_16_be_eol = utf_16_le_eol = EOL_SEEN_LF; |
6895 |
|
else if (EQ (eol_type, Qdos)) |
6896 |
|
normal_eol = utf_16_be_eol = utf_16_le_eol = EOL_SEEN_CRLF; |
6897 |
|
else |
6898 |
|
normal_eol = utf_16_be_eol = utf_16_le_eol = EOL_SEEN_CR; |
6899 |
|
} |
6900 |
|
|
6901 |
|
for (tail = val; CONSP (tail); tail = XCDR (tail)) |
6902 |
|
{ |
6903 |
|
enum coding_category category; |
6904 |
|
int this_eol; |
6905 |
|
|
6906 |
|
id = XINT (XCAR (tail)); |
6907 |
|
attrs = CODING_ID_ATTRS (id); |
6908 |
|
category = XINT (CODING_ATTR_CATEGORY (attrs)); |
6909 |
|
eol_type = CODING_ID_EOL_TYPE (id); |
6910 |
|
if (VECTORP (eol_type)) |
6911 |
|
{ |
6912 |
|
if (category == coding_category_utf_16_be |
6913 |
|
|| category == coding_category_utf_16_be_nosig) |
6914 |
|
this_eol = utf_16_be_eol; |
6915 |
|
else if (category == coding_category_utf_16_le |
6916 |
|
|| category == coding_category_utf_16_le_nosig) |
6917 |
|
this_eol = utf_16_le_eol; |
6918 |
|
else |
6919 |
|
this_eol = normal_eol; |
6920 |
|
|
6921 |
|
if (this_eol == EOL_SEEN_LF) |
6922 |
|
XSETCAR (tail, AREF (eol_type, 0)); |
6923 |
|
else if (this_eol == EOL_SEEN_CRLF) |
6924 |
|
XSETCAR (tail, AREF (eol_type, 1)); |
6925 |
|
else if (this_eol == EOL_SEEN_CR) |
6926 |
|
XSETCAR (tail, AREF (eol_type, 2)); |
6927 |
|
else |
6928 |
|
XSETCAR (tail, CODING_ID_NAME (id)); |
6929 |
|
} |
6930 |
|
else |
6931 |
|
XSETCAR (tail, CODING_ID_NAME (id)); |
6932 |
|
} |
6933 |
|
} |
6934 |
|
|
6935 |
return (highest ? XCAR (val) : val); |
return (highest ? XCAR (val) : val); |
6936 |
} |
} |
6937 |
|
|
6938 |
|
|
6939 |
DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region, |
DEFUN ("detect-coding-region", Fdetect_coding_region, Sdetect_coding_region, |
6940 |
2, 3, 0, |
2, 3, 0, |
6941 |
doc: /* Detect how the byte sequence in the region is encoded. |
doc: /* Detect coding system of the text in the region between START and END. |
6942 |
Return a list of possible coding systems used on decoding a byte |
Return a list of possible coding systems ordered by priority. |
|
sequence containing the bytes in the region between START and END when |
|
|
the coding system `undecided' is specified. The list is ordered by |
|
|
priority decided in the current language environment. |
|
6943 |
|
|
6944 |
If only ASCII characters are found, it returns a list of single element |
If only ASCII characters are found, it returns a list of single element |
6945 |
`undecided' or its subsidiary coding system according to a detected |
`undecided' or its subsidiary coding system according to a detected |
6952 |
{ |
{ |
6953 |
int from, to; |
int from, to; |
6954 |
int from_byte, to_byte; |
int from_byte, to_byte; |
|
int include_anchor_byte = 0; |
|
6955 |
|
|
6956 |
CHECK_NUMBER_COERCE_MARKER (start); |
CHECK_NUMBER_COERCE_MARKER (start); |
6957 |
CHECK_NUMBER_COERCE_MARKER (end); |
CHECK_NUMBER_COERCE_MARKER (end); |
6963 |
|
|
6964 |
if (from < GPT && to >= GPT) |
if (from < GPT && to >= GPT) |
6965 |
move_gap_both (to, to_byte); |
move_gap_both (to, to_byte); |
|
/* If we an anchor byte `\0' follows the region, we include it in |
|
|
the detecting source. Then code detectors can handle the tailing |
|
|
byte sequence more accurately. |
|
6966 |
|
|
|
Fix me: This is not a perfect solution. It is better that we |
|
|
add one more argument, say LAST_BLOCK, to all detect_coding_XXX. |
|
|
*/ |
|
|
if (to == Z || (to == GPT && GAP_SIZE > 0)) |
|
|
include_anchor_byte = 1; |
|
6967 |
return detect_coding_system (BYTE_POS_ADDR (from_byte), |
return detect_coding_system (BYTE_POS_ADDR (from_byte), |
6968 |
to_byte - from_byte + include_anchor_byte, |
to_byte - from_byte, |
6969 |
!NILP (highest), |
!NILP (highest), |
6970 |
!NILP (current_buffer |
!NILP (current_buffer |
6971 |
->enable_multibyte_characters)); |
->enable_multibyte_characters), |
6972 |
|
Qnil); |
6973 |
} |
} |
6974 |
|
|
6975 |
DEFUN ("detect-coding-string", Fdetect_coding_string, Sdetect_coding_string, |
DEFUN ("detect-coding-string", Fdetect_coding_string, Sdetect_coding_string, |
6976 |
1, 2, 0, |
1, 2, 0, |
6977 |
doc: /* Detect how the byte sequence in STRING is encoded. |
doc: /* Detect coding system of the text in STRING. |
6978 |
Return a list of possible coding systems used on decoding a byte |
Return a list of possible coding systems ordered by priority. |
|
sequence containing the bytes in STRING when the coding system |
|
|
`undecided' is specified. The list is ordered by priority decided in |
|
|
the current language environment. |
|
6979 |
|
|
6980 |
If only ASCII characters are found, it returns a list of single element |
If only ASCII characters are found, it returns a list of single element |
6981 |
`undecided' or its subsidiary coding system according to a detected |
`undecided' or its subsidiary coding system according to a detected |
6988 |
{ |
{ |
6989 |
CHECK_STRING (string); |
CHECK_STRING (string); |
6990 |
|
|
6991 |
return detect_coding_system (SDATA (string), |
return detect_coding_system (SDATA (string), SBYTES (string), |
6992 |
/* "+ 1" is to include the anchor byte |
!NILP (highest), STRING_MULTIBYTE (string), |
6993 |
`\0'. With this, code detectors can |
Qnil); |
|
handle the tailing bytes more |
|
|
accurately. */ |
|
|
SBYTES (string) + 1, |
|
|
!NILP (highest), |
|
|
STRING_MULTIBYTE (string)); |
|
6994 |
} |
} |
6995 |
|
|
|
/* Subroutine for Fsafe_coding_systems_region_internal. |
|
6996 |
|
|
6997 |
Return a list of coding systems that safely encode the multibyte |
static INLINE int |
6998 |
text between P and PEND. SAFE_CODINGS, if non-nil, is an alist of |
char_encodable_p (c, attrs) |
6999 |
possible coding systems. If it is nil, it means that we have not |
int c; |
7000 |
yet found any coding systems. |
Lisp_Object attrs; |
7001 |
|
{ |
7002 |
WORK_TABLE is a copy of the char-table Vchar_coding_system_table. An |
Lisp_Object tail; |
7003 |
element of WORK_TABLE is set to t once the element is looked up. |
struct charset *charset; |
|
|
|
|
If a non-ASCII single byte char is found, set |
|
|
*single_byte_char_found to 1. */ |
|
|
|
|
|
static Lisp_Object |
|
|
find_safe_codings (p, pend, safe_codings, work_table, single_byte_char_found) |
|
|
unsigned char *p, *pend; |
|
|
Lisp_Object safe_codings, work_table; |
|
|
int *single_byte_char_found; |
|
|
{ |
|
|
int c, len; |
|
|
Lisp_Object val, ch; |
|
|
Lisp_Object prev, tail; |
|
7004 |
|
|
7005 |
while (p < pend) |
for (tail = CODING_ATTR_CHARSET_LIST (attrs); |
7006 |
|
CONSP (tail); tail = XCDR (tail)) |
7007 |
{ |
{ |
7008 |
c = STRING_CHAR_AND_LENGTH (p, pend - p, len); |
charset = CHARSET_FROM_ID (XINT (XCAR (tail))); |
7009 |
p += len; |
if (CHAR_CHARSET_P (c, charset)) |
7010 |
if (ASCII_BYTE_P (c)) |
break; |
|
/* We can ignore ASCII characters here. */ |
|
|
continue; |
|
|
if (SINGLE_BYTE_CHAR_P (c)) |
|
|
*single_byte_char_found = 1; |
|
|
if (NILP (safe_codings)) |
|
|
/* Already all coding systems are excluded. But, we can't |
|
|
terminate the loop here because non-ASCII single-byte char |
|
|
must be found. */ |
|
|
continue; |
|
|
/* Check the safe coding systems for C. */ |
|
|
ch = make_number (c); |
|
|
val = Faref (work_table, ch); |
|
|
if (EQ (val, Qt)) |
|
|
/* This element was already checked. Ignore it. */ |
|
|
continue; |
|
|
/* Remember that we checked this element. */ |
|
|
Faset (work_table, ch, Qt); |
|
|
|
|
|
for (prev = tail = safe_codings; CONSP (tail); tail = XCDR (tail)) |
|
|
{ |
|
|
Lisp_Object elt, translation_table, hash_table, accept_latin_extra; |
|
|
int encodable; |
|
|
|
|
|
elt = XCAR (tail); |
|
|
if (CONSP (XCDR (elt))) |
|
|
{ |
|
|
/* This entry has this format now: |
|
|
( CODING SAFE-CHARS TRANSLATION-TABLE HASH-TABLE |
|
|
ACCEPT-LATIN-EXTRA ) */ |
|
|
val = XCDR (elt); |
|
|
encodable = ! NILP (Faref (XCAR (val), ch)); |
|
|
if (! encodable) |
|
|
{ |
|
|
val = XCDR (val); |
|
|
translation_table = XCAR (val); |
|
|
hash_table = XCAR (XCDR (val)); |
|
|
accept_latin_extra = XCAR (XCDR (XCDR (val))); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* This entry has this format now: ( CODING . SAFE-CHARS) */ |
|
|
encodable = ! NILP (Faref (XCDR (elt), ch)); |
|
|
if (! encodable) |
|
|
{ |
|
|
/* Transform the format to: |
|
|
( CODING SAFE-CHARS TRANSLATION-TABLE HASH-TABLE |
|
|
ACCEPT-LATIN-EXTRA ) */ |
|
|
val = Fget (XCAR (elt), Qcoding_system); |
|
|
translation_table |
|
|
= Fplist_get (AREF (val, 3), |
|
|
Qtranslation_table_for_encode); |
|
|
if (SYMBOLP (translation_table)) |
|
|
translation_table = Fget (translation_table, |
|
|
Qtranslation_table); |
|
|
hash_table |
|
|
= (CHAR_TABLE_P (translation_table) |
|
|
? XCHAR_TABLE (translation_table)->extras[1] |
|
|
: Qnil); |
|
|
accept_latin_extra |
|
|
= ((EQ (AREF (val, 0), make_number (2)) |
|
|
&& VECTORP (AREF (val, 4))) |
|
|
? AREF (AREF (val, 4), 16) |
|
|
: Qnil); |
|
|
XSETCAR (tail, list5 (XCAR (elt), XCDR (elt), |
|
|
translation_table, hash_table, |
|
|
accept_latin_extra)); |
|
|
} |
|
|
} |
|
|
|
|
|
if (! encodable |
|
|
&& ((CHAR_TABLE_P (translation_table) |
|
|
&& ! NILP (Faref (translation_table, ch))) |
|
|
|| (HASH_TABLE_P (hash_table) |
|
|
&& ! NILP (Fgethash (ch, hash_table, Qnil))) |
|
|
|| (SINGLE_BYTE_CHAR_P (c) |
|
|
&& ! NILP (accept_latin_extra) |
|
|
&& VECTORP (Vlatin_extra_code_table) |
|
|
&& ! NILP (AREF (Vlatin_extra_code_table, c))))) |
|
|
encodable = 1; |
|
|
if (encodable) |
|
|
prev = tail; |
|
|
else |
|
|
{ |
|
|
/* Exclude this coding system from SAFE_CODINGS. */ |
|
|
if (EQ (tail, safe_codings)) |
|
|
safe_codings = XCDR (safe_codings); |
|
|
else |
|
|
XSETCDR (prev, XCDR (tail)); |
|
|
} |
|
|
} |
|
7011 |
} |
} |
7012 |
return safe_codings; |
return (! NILP (tail)); |
7013 |
} |
} |
7014 |
|
|
7015 |
|
|
7016 |
|
/* Return a list of coding systems that safely encode the text between |
7017 |
|
START and END. If EXCLUDE is non-nil, it is a list of coding |
7018 |
|
systems not to check. The returned list doesn't contain any such |
7019 |
|
coding systems. In any case, if the text contains only ASCII or is |
7020 |
|
unibyte, return t. */ |
7021 |
|
|
7022 |
DEFUN ("find-coding-systems-region-internal", |
DEFUN ("find-coding-systems-region-internal", |
7023 |
Ffind_coding_systems_region_internal, |
Ffind_coding_systems_region_internal, |
7024 |
Sfind_coding_systems_region_internal, 2, 2, 0, |
Sfind_coding_systems_region_internal, 2, 3, 0, |
7025 |
doc: /* Internal use only. */) |
doc: /* Internal use only. */) |
7026 |
(start, end) |
(start, end, exclude) |
7027 |
Lisp_Object start, end; |
Lisp_Object start, end, exclude; |
7028 |
{ |
{ |
7029 |
Lisp_Object work_table, safe_codings; |
Lisp_Object coding_attrs_list, safe_codings; |
7030 |
int non_ascii_p = 0; |
EMACS_INT start_byte, end_byte; |
7031 |
int single_byte_char_found = 0; |
const unsigned char *p, *pbeg, *pend; |
7032 |
const unsigned char *p1, *p1end, *p2, *p2end, *p; |
int c; |
7033 |
|
Lisp_Object tail, elt; |
7034 |
|
|
7035 |
if (STRINGP (start)) |
if (STRINGP (start)) |
7036 |
{ |
{ |
7037 |
if (!STRING_MULTIBYTE (start)) |
if (!STRING_MULTIBYTE (start) |
7038 |
|
|| SCHARS (start) == SBYTES (start)) |
7039 |
return Qt; |
return Qt; |
7040 |
p1 = SDATA (start), p1end = p1 + SBYTES (start); |
start_byte = 0; |
7041 |
p2 = p2end = p1end; |
end_byte = SBYTES (start); |
|
if (SCHARS (start) != SBYTES (start)) |
|
|
non_ascii_p = 1; |
|
7042 |
} |
} |
7043 |
else |
else |
7044 |
{ |
{ |
|
int from, to, stop; |
|
|
|
|
7045 |
CHECK_NUMBER_COERCE_MARKER (start); |
CHECK_NUMBER_COERCE_MARKER (start); |
7046 |
CHECK_NUMBER_COERCE_MARKER (end); |
CHECK_NUMBER_COERCE_MARKER (end); |
7047 |
if (XINT (start) < BEG || XINT (end) > Z || XINT (start) > XINT (end)) |
if (XINT (start) < BEG || XINT (end) > Z || XINT (start) > XINT (end)) |
7048 |
args_out_of_range (start, end); |
args_out_of_range (start, end); |
7049 |
if (NILP (current_buffer->enable_multibyte_characters)) |
if (NILP (current_buffer->enable_multibyte_characters)) |
7050 |
return Qt; |
return Qt; |
7051 |
from = CHAR_TO_BYTE (XINT (start)); |
start_byte = CHAR_TO_BYTE (XINT (start)); |
7052 |
to = CHAR_TO_BYTE (XINT (end)); |
end_byte = CHAR_TO_BYTE (XINT (end)); |
7053 |
stop = from < GPT_BYTE && GPT_BYTE < to ? GPT_BYTE : to; |
if (XINT (end) - XINT (start) == end_byte - start_byte) |
7054 |
p1 = BYTE_POS_ADDR (from), p1end = p1 + (stop - from); |
return Qt; |
|
if (stop == to) |
|
|
p2 = p2end = p1end; |
|
|
else |
|
|
p2 = BYTE_POS_ADDR (stop), p2end = p2 + (to - stop); |
|
|
if (XINT (end) - XINT (start) != to - from) |
|
|
non_ascii_p = 1; |
|
|
} |
|
7055 |
|
|
7056 |
if (!non_ascii_p) |
if (XINT (start) < GPT && XINT (end) > GPT) |
|
{ |
|
|
/* We are sure that the text contains no multibyte character. |
|
|
Check if it contains eight-bit-graphic. */ |
|
|
p = p1; |
|
|
for (p = p1; p < p1end && ASCII_BYTE_P (*p); p++); |
|
|
if (p == p1end) |
|
7057 |
{ |
{ |
7058 |
for (p = p2; p < p2end && ASCII_BYTE_P (*p); p++); |
if ((GPT - XINT (start)) < (XINT (end) - GPT)) |
7059 |
if (p == p2end) |
move_gap_both (XINT (start), start_byte); |
7060 |
return Qt; |
else |
7061 |
|
move_gap_both (XINT (end), end_byte); |
7062 |
} |
} |
7063 |
} |
} |
7064 |
|
|
7065 |
/* The text contains non-ASCII characters. */ |
coding_attrs_list = Qnil; |
7066 |
|
for (tail = Vcoding_system_list; CONSP (tail); tail = XCDR (tail)) |
7067 |
|
if (NILP (exclude) |
7068 |
|
|| NILP (Fmemq (XCAR (tail), exclude))) |
7069 |
|
{ |
7070 |
|
Lisp_Object attrs; |
7071 |
|
|
7072 |
work_table = Fmake_char_table (Qchar_coding_system, Qnil); |
attrs = AREF (CODING_SYSTEM_SPEC (XCAR (tail)), 0); |
7073 |
safe_codings = Fcopy_sequence (XCDR (Vcoding_system_safe_chars)); |
if (EQ (XCAR (tail), CODING_ATTR_BASE_NAME (attrs)) |
7074 |
|
&& ! EQ (CODING_ATTR_TYPE (attrs), Qundecided)) |
7075 |
|
coding_attrs_list = Fcons (attrs, coding_attrs_list); |
7076 |
|
} |
7077 |
|
|
7078 |
safe_codings = find_safe_codings (p1, p1end, safe_codings, work_table, |
if (STRINGP (start)) |
7079 |
&single_byte_char_found); |
p = pbeg = SDATA (start); |
|
if (p2 < p2end) |
|
|
safe_codings = find_safe_codings (p2, p2end, safe_codings, work_table, |
|
|
&single_byte_char_found); |
|
|
if (EQ (safe_codings, XCDR (Vcoding_system_safe_chars))) |
|
|
safe_codings = Qt; |
|
7080 |
else |
else |
7081 |
{ |
p = pbeg = BYTE_POS_ADDR (start_byte); |
7082 |
/* Turn safe_codings to a list of coding systems... */ |
pend = p + (end_byte - start_byte); |
|
Lisp_Object val; |
|
|
|
|
|
if (single_byte_char_found) |
|
|
/* ... and append these for eight-bit chars. */ |
|
|
val = Fcons (Qraw_text, |
|
|
Fcons (Qemacs_mule, Fcons (Qno_conversion, Qnil))); |
|
|
else |
|
|
/* ... and append generic coding systems. */ |
|
|
val = Fcopy_sequence (XCAR (Vcoding_system_safe_chars)); |
|
|
|
|
|
for (; CONSP (safe_codings); safe_codings = XCDR (safe_codings)) |
|
|
val = Fcons (XCAR (XCAR (safe_codings)), val); |
|
|
safe_codings = val; |
|
|
} |
|
|
|
|
|
return safe_codings; |
|
|
} |
|
|
|
|
|
|
|
|
/* Search from position POS for such characters that are unencodable |
|
|
accoding to SAFE_CHARS, and return a list of their positions. P |
|
|
points where in the memory the character at POS exists. Limit the |
|
|
search at PEND or when Nth unencodable characters are found. |
|
|
|
|
|
If SAFE_CHARS is a char table, an element for an unencodable |
|
|
character is nil. |
|
|
|
|
|
If SAFE_CHARS is nil, all non-ASCII characters are unencodable. |
|
7083 |
|
|
7084 |
Otherwise, SAFE_CHARS is t, and only eight-bit-contrl and |
while (p < pend && ASCII_BYTE_P (*p)) p++; |
7085 |
eight-bit-graphic characters are unencodable. */ |
while (p < pend && ASCII_BYTE_P (*(pend - 1))) pend--; |
7086 |
|
|
|
static Lisp_Object |
|
|
unencodable_char_position (safe_chars, pos, p, pend, n) |
|
|
Lisp_Object safe_chars; |
|
|
int pos; |
|
|
unsigned char *p, *pend; |
|
|
int n; |
|
|
{ |
|
|
Lisp_Object pos_list; |
|
|
|
|
|
pos_list = Qnil; |
|
7087 |
while (p < pend) |
while (p < pend) |
7088 |
{ |
{ |
7089 |
int len; |
if (ASCII_BYTE_P (*p)) |
7090 |
int c = STRING_CHAR_AND_LENGTH (p, MAX_MULTIBYTE_LENGTH, len); |
p++; |
7091 |
|
else |
|
if (c >= 128 |
|
|
&& (CHAR_TABLE_P (safe_chars) |
|
|
? NILP (CHAR_TABLE_REF (safe_chars, c)) |
|
|
: (NILP (safe_chars) || c < 256))) |
|
7092 |
{ |
{ |
7093 |
pos_list = Fcons (make_number (pos), pos_list); |
c = STRING_CHAR_ADVANCE (p); |
7094 |
if (--n <= 0) |
|
7095 |
break; |
charset_map_loaded = 0; |
7096 |
|
for (tail = coding_attrs_list; CONSP (tail);) |
7097 |
|
{ |
7098 |
|
elt = XCAR (tail); |
7099 |
|
if (NILP (elt)) |
7100 |
|
tail = XCDR (tail); |
7101 |
|
else if (char_encodable_p (c, elt)) |
7102 |
|
tail = XCDR (tail); |
7103 |
|
else if (CONSP (XCDR (tail))) |
7104 |
|
{ |
7105 |
|
XSETCAR (tail, XCAR (XCDR (tail))); |
7106 |
|
XSETCDR (tail, XCDR (XCDR (tail))); |
7107 |
|
} |
7108 |
|
else |
7109 |
|
{ |
7110 |
|
XSETCAR (tail, Qnil); |
7111 |
|
tail = XCDR (tail); |
7112 |
|
} |
7113 |
|
} |
7114 |
|
if (charset_map_loaded) |
7115 |
|
{ |
7116 |
|
EMACS_INT p_offset = p - pbeg, pend_offset = pend - pbeg; |
7117 |
|
|
7118 |
|
if (STRINGP (start)) |
7119 |
|
pbeg = SDATA (start); |
7120 |
|
else |
7121 |
|
pbeg = BYTE_POS_ADDR (start_byte); |
7122 |
|
p = pbeg + p_offset; |
7123 |
|
pend = pbeg + pend_offset; |
7124 |
|
} |
7125 |
} |
} |
|
pos++; |
|
|
p += len; |
|
7126 |
} |
} |
7127 |
return Fnreverse (pos_list); |
|
7128 |
|
safe_codings = Qnil; |
7129 |
|
for (tail = coding_attrs_list; CONSP (tail); tail = XCDR (tail)) |
7130 |
|
if (! NILP (XCAR (tail))) |
7131 |
|
safe_codings = Fcons (CODING_ATTR_BASE_NAME (XCAR (tail)), safe_codings); |
7132 |
|
|
7133 |
|
return safe_codings; |
7134 |
} |
} |
7135 |
|
|
7136 |
|
|
7152 |
Lisp_Object start, end, coding_system, count, string; |
Lisp_Object start, end, coding_system, count, string; |
7153 |
{ |
{ |
7154 |
int n; |
int n; |
|
Lisp_Object safe_chars; |
|
7155 |
struct coding_system coding; |
struct coding_system coding; |
7156 |
|
Lisp_Object attrs, charset_list; |
7157 |
Lisp_Object positions; |
Lisp_Object positions; |
7158 |
int from, to; |
int from, to; |
7159 |
unsigned char *p, *pend; |
const unsigned char *p, *stop, *pend; |
7160 |
|
int ascii_compatible; |
7161 |
|
|
7162 |
|
setup_coding_system (Fcheck_coding_system (coding_system), &coding); |
7163 |
|
attrs = CODING_ID_ATTRS (coding.id); |
7164 |
|
if (EQ (CODING_ATTR_TYPE (attrs), Qraw_text)) |
7165 |
|
return Qnil; |
7166 |
|
ascii_compatible = ! NILP (CODING_ATTR_ASCII_COMPAT (attrs)); |
7167 |
|
charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
7168 |
|
|
7169 |
if (NILP (string)) |
if (NILP (string)) |
7170 |
{ |
{ |
7171 |
validate_region (&start, &end); |
validate_region (&start, &end); |
7172 |
from = XINT (start); |
from = XINT (start); |
7173 |
to = XINT (end); |
to = XINT (end); |
7174 |
if (NILP (current_buffer->enable_multibyte_characters)) |
if (NILP (current_buffer->enable_multibyte_characters) |
7175 |
|
|| (ascii_compatible |
7176 |
|
&& (to - from) == (CHAR_TO_BYTE (to) - (CHAR_TO_BYTE (from))))) |
7177 |
return Qnil; |
return Qnil; |
7178 |
p = CHAR_POS_ADDR (from); |
p = CHAR_POS_ADDR (from); |
7179 |
if (to == GPT) |
pend = CHAR_POS_ADDR (to); |
7180 |
pend = GPT_ADDR; |
if (from < GPT && to >= GPT) |
7181 |
|
stop = GPT_ADDR; |
7182 |
else |
else |
7183 |
pend = CHAR_POS_ADDR (to); |
stop = pend; |
7184 |
} |
} |
7185 |
else |
else |
7186 |
{ |
{ |
7195 |
if (! STRING_MULTIBYTE (string)) |
if (! STRING_MULTIBYTE (string)) |
7196 |
return Qnil; |
return Qnil; |
7197 |
p = SDATA (string) + string_char_to_byte (string, from); |
p = SDATA (string) + string_char_to_byte (string, from); |
7198 |
pend = SDATA (string) + string_char_to_byte (string, to); |
stop = pend = SDATA (string) + string_char_to_byte (string, to); |
7199 |
|
if (ascii_compatible && (to - from) == (pend - p)) |
7200 |
|
return Qnil; |
7201 |
} |
} |
7202 |
|
|
|
setup_coding_system (Fcheck_coding_system (coding_system), &coding); |
|
|
|
|
7203 |
if (NILP (count)) |
if (NILP (count)) |
7204 |
n = 1; |
n = 1; |
7205 |
else |
else |
7208 |
n = XINT (count); |
n = XINT (count); |
7209 |
} |
} |
7210 |
|
|
7211 |
if (coding.type == coding_type_no_conversion |
positions = Qnil; |
7212 |
|| coding.type == coding_type_raw_text) |
while (1) |
7213 |
return Qnil; |
{ |
7214 |
|
int c; |
7215 |
|
|
7216 |
if (coding.type == coding_type_undecided) |
if (ascii_compatible) |
7217 |
safe_chars = Qnil; |
while (p < stop && ASCII_BYTE_P (*p)) |
7218 |
else |
p++, from++; |
7219 |
safe_chars = coding_safe_chars (coding_system); |
if (p >= stop) |
7220 |
|
{ |
7221 |
|
if (p >= pend) |
7222 |
|
break; |
7223 |
|
stop = pend; |
7224 |
|
p = GAP_END_ADDR; |
7225 |
|
} |
7226 |
|
|
7227 |
|
c = STRING_CHAR_ADVANCE (p); |
7228 |
|
if (! (ASCII_CHAR_P (c) && ascii_compatible) |
7229 |
|
&& ! char_charset (c, charset_list, NULL)) |
7230 |
|
{ |
7231 |
|
positions = Fcons (make_number (from), positions); |
7232 |
|
n--; |
7233 |
|
if (n == 0) |
7234 |
|
break; |
7235 |
|
} |
7236 |
|
|
7237 |
|
from++; |
7238 |
|
} |
7239 |
|
|
7240 |
if (STRINGP (string) |
return (NILP (count) ? Fcar (positions) : Fnreverse (positions)); |
7241 |
|| from >= GPT || to <= GPT) |
} |
7242 |
positions = unencodable_char_position (safe_chars, from, p, pend, n); |
|
7243 |
|
|
7244 |
|
DEFUN ("check-coding-systems-region", Fcheck_coding_systems_region, |
7245 |
|
Scheck_coding_systems_region, 3, 3, 0, |
7246 |
|
doc: /* Check if the region is encodable by coding systems. |
7247 |
|
|
7248 |
|
START and END are buffer positions specifying the region. |
7249 |
|
CODING-SYSTEM-LIST is a list of coding systems to check. |
7250 |
|
|
7251 |
|
The value is an alist ((CODING-SYSTEM POS0 POS1 ...) ...), where |
7252 |
|
CODING-SYSTEM is a member of CODING-SYSTEM-LIst and can't encode the |
7253 |
|
whole region, POS0, POS1, ... are buffer positions where non-encodable |
7254 |
|
characters are found. |
7255 |
|
|
7256 |
|
If all coding systems in CODING-SYSTEM-LIST can encode the region, the |
7257 |
|
value is nil. |
7258 |
|
|
7259 |
|
START may be a string. In that case, check if the string is |
7260 |
|
encodable, and the value contains indices to the string instead of |
7261 |
|
buffer positions. END is ignored. */) |
7262 |
|
(start, end, coding_system_list) |
7263 |
|
Lisp_Object start, end, coding_system_list; |
7264 |
|
{ |
7265 |
|
Lisp_Object list; |
7266 |
|
EMACS_INT start_byte, end_byte; |
7267 |
|
int pos; |
7268 |
|
const unsigned char *p, *pbeg, *pend; |
7269 |
|
int c; |
7270 |
|
Lisp_Object tail, elt; |
7271 |
|
|
7272 |
|
if (STRINGP (start)) |
7273 |
|
{ |
7274 |
|
if (!STRING_MULTIBYTE (start) |
7275 |
|
&& SCHARS (start) != SBYTES (start)) |
7276 |
|
return Qnil; |
7277 |
|
start_byte = 0; |
7278 |
|
end_byte = SBYTES (start); |
7279 |
|
pos = 0; |
7280 |
|
} |
7281 |
else |
else |
7282 |
{ |
{ |
7283 |
Lisp_Object args[2]; |
CHECK_NUMBER_COERCE_MARKER (start); |
7284 |
|
CHECK_NUMBER_COERCE_MARKER (end); |
7285 |
|
if (XINT (start) < BEG || XINT (end) > Z || XINT (start) > XINT (end)) |
7286 |
|
args_out_of_range (start, end); |
7287 |
|
if (NILP (current_buffer->enable_multibyte_characters)) |
7288 |
|
return Qnil; |
7289 |
|
start_byte = CHAR_TO_BYTE (XINT (start)); |
7290 |
|
end_byte = CHAR_TO_BYTE (XINT (end)); |
7291 |
|
if (XINT (end) - XINT (start) == end_byte - start_byte) |
7292 |
|
return Qt; |
7293 |
|
|
7294 |
|
if (XINT (start) < GPT && XINT (end) > GPT) |
7295 |
|
{ |
7296 |
|
if ((GPT - XINT (start)) < (XINT (end) - GPT)) |
7297 |
|
move_gap_both (XINT (start), start_byte); |
7298 |
|
else |
7299 |
|
move_gap_both (XINT (end), end_byte); |
7300 |
|
} |
7301 |
|
pos = XINT (start); |
7302 |
|
} |
7303 |
|
|
7304 |
|
list = Qnil; |
7305 |
|
for (tail = coding_system_list; CONSP (tail); tail = XCDR (tail)) |
7306 |
|
{ |
7307 |
|
elt = XCAR (tail); |
7308 |
|
list = Fcons (Fcons (elt, Fcons (AREF (CODING_SYSTEM_SPEC (elt), 0), |
7309 |
|
Qnil)), |
7310 |
|
list); |
7311 |
|
} |
7312 |
|
|
7313 |
|
if (STRINGP (start)) |
7314 |
|
p = pbeg = SDATA (start); |
7315 |
|
else |
7316 |
|
p = pbeg = BYTE_POS_ADDR (start_byte); |
7317 |
|
pend = p + (end_byte - start_byte); |
7318 |
|
|
7319 |
args[0] = unencodable_char_position (safe_chars, from, p, GPT_ADDR, n); |
while (p < pend && ASCII_BYTE_P (*p)) p++, pos++; |
7320 |
n -= XINT (Flength (args[0])); |
while (p < pend && ASCII_BYTE_P (*(pend - 1))) pend--; |
7321 |
if (n <= 0) |
|
7322 |
positions = args[0]; |
while (p < pend) |
7323 |
|
{ |
7324 |
|
if (ASCII_BYTE_P (*p)) |
7325 |
|
p++; |
7326 |
else |
else |
7327 |
{ |
{ |
7328 |
args[1] = unencodable_char_position (safe_chars, GPT, GAP_END_ADDR, |
c = STRING_CHAR_ADVANCE (p); |
7329 |
pend, n); |
|
7330 |
positions = Fappend (2, args); |
charset_map_loaded = 0; |
7331 |
|
for (tail = list; CONSP (tail); tail = XCDR (tail)) |
7332 |
|
{ |
7333 |
|
elt = XCDR (XCAR (tail)); |
7334 |
|
if (! char_encodable_p (c, XCAR (elt))) |
7335 |
|
XSETCDR (elt, Fcons (make_number (pos), XCDR (elt))); |
7336 |
|
} |
7337 |
|
if (charset_map_loaded) |
7338 |
|
{ |
7339 |
|
EMACS_INT p_offset = p - pbeg, pend_offset = pend - pbeg; |
7340 |
|
|
7341 |
|
if (STRINGP (start)) |
7342 |
|
pbeg = SDATA (start); |
7343 |
|
else |
7344 |
|
pbeg = BYTE_POS_ADDR (start_byte); |
7345 |
|
p = pbeg + p_offset; |
7346 |
|
pend = pbeg + pend_offset; |
7347 |
|
} |
7348 |
} |
} |
7349 |
|
pos++; |
7350 |
} |
} |
7351 |
|
|
7352 |
return (NILP (count) ? Fcar (positions) : positions); |
tail = list; |
7353 |
|
list = Qnil; |
7354 |
|
for (; CONSP (tail); tail = XCDR (tail)) |
7355 |
|
{ |
7356 |
|
elt = XCAR (tail); |
7357 |
|
if (CONSP (XCDR (XCDR (elt)))) |
7358 |
|
list = Fcons (Fcons (XCAR (elt), Fnreverse (XCDR (XCDR (elt)))), |
7359 |
|
list); |
7360 |
|
} |
7361 |
|
|
7362 |
|
return list; |
7363 |
} |
} |
7364 |
|
|
7365 |
|
|
7366 |
|
|
7367 |
Lisp_Object |
Lisp_Object |
7368 |
code_convert_region1 (start, end, coding_system, encodep) |
code_convert_region (start, end, coding_system, dst_object, encodep, norecord) |
7369 |
Lisp_Object start, end, coding_system; |
Lisp_Object start, end, coding_system, dst_object; |
7370 |
int encodep; |
int encodep, norecord; |
7371 |
{ |
{ |
7372 |
struct coding_system coding; |
struct coding_system coding; |
7373 |
int from, to; |
EMACS_INT from, from_byte, to, to_byte; |
7374 |
|
Lisp_Object src_object; |
7375 |
|
|
7376 |
CHECK_NUMBER_COERCE_MARKER (start); |
CHECK_NUMBER_COERCE_MARKER (start); |
7377 |
CHECK_NUMBER_COERCE_MARKER (end); |
CHECK_NUMBER_COERCE_MARKER (end); |
7378 |
CHECK_SYMBOL (coding_system); |
if (NILP (coding_system)) |
7379 |
|
coding_system = Qno_conversion; |
7380 |
|
else |
7381 |
|
CHECK_CODING_SYSTEM (coding_system); |
7382 |
|
src_object = Fcurrent_buffer (); |
7383 |
|
if (NILP (dst_object)) |
7384 |
|
dst_object = src_object; |
7385 |
|
else if (! EQ (dst_object, Qt)) |
7386 |
|
CHECK_BUFFER (dst_object); |
7387 |
|
|
7388 |
validate_region (&start, &end); |
validate_region (&start, &end); |
7389 |
from = XFASTINT (start); |
from = XFASTINT (start); |
7390 |
|
from_byte = CHAR_TO_BYTE (from); |
7391 |
to = XFASTINT (end); |
to = XFASTINT (end); |
7392 |
|
to_byte = CHAR_TO_BYTE (to); |
7393 |
|
|
7394 |
if (NILP (coding_system)) |
setup_coding_system (coding_system, &coding); |
|
return make_number (to - from); |
|
|
|
|
|
if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) |
|
|
error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system))); |
|
|
|
|
7395 |
coding.mode |= CODING_MODE_LAST_BLOCK; |
coding.mode |= CODING_MODE_LAST_BLOCK; |
7396 |
coding.src_multibyte = coding.dst_multibyte |
|
7397 |
= !NILP (current_buffer->enable_multibyte_characters); |
if (encodep) |
7398 |
code_convert_region (from, CHAR_TO_BYTE (from), to, CHAR_TO_BYTE (to), |
encode_coding_object (&coding, src_object, from, from_byte, to, to_byte, |
7399 |
&coding, encodep, 1); |
dst_object); |
7400 |
Vlast_coding_system_used = coding.symbol; |
else |
7401 |
return make_number (coding.produced_char); |
decode_coding_object (&coding, src_object, from, from_byte, to, to_byte, |
7402 |
|
dst_object); |
7403 |
|
if (! norecord) |
7404 |
|
Vlast_coding_system_used = CODING_ID_NAME (coding.id); |
7405 |
|
|
7406 |
|
if (coding.result != CODING_RESULT_SUCCESS) |
7407 |
|
error ("Code conversion error: %d", coding.result); |
7408 |
|
|
7409 |
|
return (BUFFERP (dst_object) |
7410 |
|
? make_number (coding.produced_char) |
7411 |
|
: coding.dst_object); |
7412 |
} |
} |
7413 |
|
|
7414 |
|
|
7415 |
DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region, |
DEFUN ("decode-coding-region", Fdecode_coding_region, Sdecode_coding_region, |
7416 |
3, 3, "r\nzCoding system: ", |
3, 4, "r\nzCoding system: ", |
7417 |
doc: /* Decode the current region from the specified coding system. |
doc: /* Decode the current region from the specified coding system. |
7418 |
When called from a program, takes three arguments: |
When called from a program, takes four arguments: |
7419 |
START, END, and CODING-SYSTEM. START and END are buffer positions. |
START, END, CODING-SYSTEM, and DESTINATION. |
7420 |
|
START and END are buffer positions. |
7421 |
|
|
7422 |
|
Optional 4th arguments DESTINATION specifies where the decoded text goes. |
7423 |
|
If nil, the region between START and END is replace by the decoded text. |
7424 |
|
If buffer, the decoded text is inserted in the buffer. |
7425 |
|
If t, the decoded text is returned. |
7426 |
|
|
7427 |
This function sets `last-coding-system-used' to the precise coding system |
This function sets `last-coding-system-used' to the precise coding system |
7428 |
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
7429 |
not fully specified.) |
not fully specified.) |
7430 |
It returns the length of the decoded text. */) |
It returns the length of the decoded text. */) |
7431 |
(start, end, coding_system) |
(start, end, coding_system, destination) |
7432 |
Lisp_Object start, end, coding_system; |
Lisp_Object start, end, coding_system, destination; |
7433 |
{ |
{ |
7434 |
return code_convert_region1 (start, end, coding_system, 0); |
return code_convert_region (start, end, coding_system, destination, 0, 0); |
7435 |
} |
} |
7436 |
|
|
7437 |
DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region, |
DEFUN ("encode-coding-region", Fencode_coding_region, Sencode_coding_region, |
7438 |
3, 3, "r\nzCoding system: ", |
3, 4, "r\nzCoding system: ", |
7439 |
doc: /* Encode the current region into the specified coding system. |
doc: /* Encode the current region by specified coding system. |
7440 |
When called from a program, takes three arguments: |
When called from a program, takes three arguments: |
7441 |
START, END, and CODING-SYSTEM. START and END are buffer positions. |
START, END, and CODING-SYSTEM. START and END are buffer positions. |
7442 |
|
|
7443 |
|
Optional 4th arguments DESTINATION specifies where the encoded text goes. |
7444 |
|
If nil, the region between START and END is replace by the encoded text. |
7445 |
|
If buffer, the encoded text is inserted in the buffer. |
7446 |
|
If t, the encoded text is returned. |
7447 |
|
|
7448 |
This function sets `last-coding-system-used' to the precise coding system |
This function sets `last-coding-system-used' to the precise coding system |
7449 |
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
7450 |
not fully specified.) |
not fully specified.) |
7451 |
It returns the length of the encoded text. */) |
It returns the length of the encoded text. */) |
7452 |
(start, end, coding_system) |
(start, end, coding_system, destination) |
7453 |
Lisp_Object start, end, coding_system; |
Lisp_Object start, end, coding_system, destination; |
7454 |
{ |
{ |
7455 |
return code_convert_region1 (start, end, coding_system, 1); |
return code_convert_region (start, end, coding_system, destination, 1, 0); |
7456 |
} |
} |
7457 |
|
|
7458 |
Lisp_Object |
Lisp_Object |
7459 |
code_convert_string1 (string, coding_system, nocopy, encodep) |
code_convert_string (string, coding_system, dst_object, |
7460 |
Lisp_Object string, coding_system, nocopy; |
encodep, nocopy, norecord) |
7461 |
int encodep; |
Lisp_Object string, coding_system, dst_object; |
7462 |
|
int encodep, nocopy, norecord; |
7463 |
{ |
{ |
7464 |
struct coding_system coding; |
struct coding_system coding; |
7465 |
|
EMACS_INT chars, bytes; |
7466 |
|
|
7467 |
CHECK_STRING (string); |
CHECK_STRING (string); |
|
CHECK_SYMBOL (coding_system); |
|
|
|
|
7468 |
if (NILP (coding_system)) |
if (NILP (coding_system)) |
7469 |
return (NILP (nocopy) ? Fcopy_sequence (string) : string); |
{ |
7470 |
|
if (! norecord) |
7471 |
|
Vlast_coding_system_used = Qno_conversion; |
7472 |
|
if (NILP (dst_object)) |
7473 |
|
return (nocopy ? Fcopy_sequence (string) : string); |
7474 |
|
} |
7475 |
|
|
7476 |
if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) |
if (NILP (coding_system)) |
7477 |
error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system))); |
coding_system = Qno_conversion; |
7478 |
|
else |
7479 |
|
CHECK_CODING_SYSTEM (coding_system); |
7480 |
|
if (NILP (dst_object)) |
7481 |
|
dst_object = Qt; |
7482 |
|
else if (! EQ (dst_object, Qt)) |
7483 |
|
CHECK_BUFFER (dst_object); |
7484 |
|
|
7485 |
|
setup_coding_system (coding_system, &coding); |
7486 |
coding.mode |= CODING_MODE_LAST_BLOCK; |
coding.mode |= CODING_MODE_LAST_BLOCK; |
7487 |
string = (encodep |
chars = SCHARS (string); |
7488 |
? encode_coding_string (string, &coding, !NILP (nocopy)) |
bytes = SBYTES (string); |
7489 |
: decode_coding_string (string, &coding, !NILP (nocopy))); |
if (encodep) |
7490 |
Vlast_coding_system_used = coding.symbol; |
encode_coding_object (&coding, string, 0, 0, chars, bytes, dst_object); |
7491 |
|
else |
7492 |
return string; |
decode_coding_object (&coding, string, 0, 0, chars, bytes, dst_object); |
7493 |
} |
if (! norecord) |
7494 |
|
Vlast_coding_system_used = CODING_ID_NAME (coding.id); |
7495 |
DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, |
|
7496 |
2, 3, 0, |
if (coding.result != CODING_RESULT_SUCCESS) |
7497 |
doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result. |
error ("Code conversion error: %d", coding.result); |
7498 |
Optional arg NOCOPY non-nil means it is OK to return STRING itself |
|
7499 |
if the decoding operation is trivial. |
return (BUFFERP (dst_object) |
7500 |
This function sets `last-coding-system-used' to the precise coding system |
? make_number (coding.produced_char) |
7501 |
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
: coding.dst_object); |
|
not fully specified.) */) |
|
|
(string, coding_system, nocopy) |
|
|
Lisp_Object string, coding_system, nocopy; |
|
|
{ |
|
|
return code_convert_string1 (string, coding_system, nocopy, 0); |
|
7502 |
} |
} |
7503 |
|
|
|
DEFUN ("encode-coding-string", Fencode_coding_string, Sencode_coding_string, |
|
|
2, 3, 0, |
|
|
doc: /* Encode STRING to CODING-SYSTEM, and return the result. |
|
|
Optional arg NOCOPY non-nil means it is OK to return STRING itself |
|
|
if the encoding operation is trivial. |
|
|
This function sets `last-coding-system-used' to the precise coding system |
|
|
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
|
|
not fully specified.) */) |
|
|
(string, coding_system, nocopy) |
|
|
Lisp_Object string, coding_system, nocopy; |
|
|
{ |
|
|
return code_convert_string1 (string, coding_system, nocopy, 1); |
|
|
} |
|
7504 |
|
|
7505 |
/* Encode or decode STRING according to CODING_SYSTEM. |
/* Encode or decode STRING according to CODING_SYSTEM. |
7506 |
Do not set Vlast_coding_system_used. |
Do not set Vlast_coding_system_used. |
7513 |
Lisp_Object string, coding_system; |
Lisp_Object string, coding_system; |
7514 |
int encodep; |
int encodep; |
7515 |
{ |
{ |
7516 |
struct coding_system coding; |
return code_convert_string (string, coding_system, Qt, encodep, 0, 1); |
7517 |
|
} |
7518 |
|
|
|
CHECK_STRING (string); |
|
|
CHECK_SYMBOL (coding_system); |
|
7519 |
|
|
7520 |
if (NILP (coding_system)) |
DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, |
7521 |
return string; |
2, 4, 0, |
7522 |
|
doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result. |
7523 |
|
|
7524 |
if (setup_coding_system (Fcheck_coding_system (coding_system), &coding) < 0) |
Optional third arg NOCOPY non-nil means it is OK to return STRING itself |
7525 |
error ("Invalid coding system: %s", SDATA (SYMBOL_NAME (coding_system))); |
if the decoding operation is trivial. |
7526 |
|
|
7527 |
coding.composing = COMPOSITION_DISABLED; |
Optional fourth arg BUFFER non-nil meant that the decoded text is |
7528 |
coding.mode |= CODING_MODE_LAST_BLOCK; |
inserted in BUFFER instead of returned as a string. In this case, |
7529 |
return (encodep |
the return value is BUFFER. |
7530 |
? encode_coding_string (string, &coding, 1) |
|
7531 |
: decode_coding_string (string, &coding, 1)); |
This function sets `last-coding-system-used' to the precise coding system |
7532 |
|
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
7533 |
|
not fully specified. */) |
7534 |
|
(string, coding_system, nocopy, buffer) |
7535 |
|
Lisp_Object string, coding_system, nocopy, buffer; |
7536 |
|
{ |
7537 |
|
return code_convert_string (string, coding_system, buffer, |
7538 |
|
0, ! NILP (nocopy), 0); |
7539 |
|
} |
7540 |
|
|
7541 |
|
DEFUN ("encode-coding-string", Fencode_coding_string, Sencode_coding_string, |
7542 |
|
2, 4, 0, |
7543 |
|
doc: /* Encode STRING to CODING-SYSTEM, and return the result. |
7544 |
|
|
7545 |
|
Optional third arg NOCOPY non-nil means it is OK to return STRING |
7546 |
|
itself if the encoding operation is trivial. |
7547 |
|
|
7548 |
|
Optional fourth arg BUFFER non-nil meant that the encoded text is |
7549 |
|
inserted in BUFFER instead of returned as a string. In this case, |
7550 |
|
the return value is BUFFER. |
7551 |
|
|
7552 |
|
This function sets `last-coding-system-used' to the precise coding system |
7553 |
|
used (which may be different from CODING-SYSTEM if CODING-SYSTEM is |
7554 |
|
not fully specified.) */) |
7555 |
|
(string, coding_system, nocopy, buffer) |
7556 |
|
Lisp_Object string, coding_system, nocopy, buffer; |
7557 |
|
{ |
7558 |
|
return code_convert_string (string, coding_system, buffer, |
7559 |
|
1, ! NILP (nocopy), 1); |
7560 |
} |
} |
7561 |
|
|
7562 |
|
|
7563 |
DEFUN ("decode-sjis-char", Fdecode_sjis_char, Sdecode_sjis_char, 1, 1, 0, |
DEFUN ("decode-sjis-char", Fdecode_sjis_char, Sdecode_sjis_char, 1, 1, 0, |
7564 |
doc: /* Decode a Japanese character which has CODE in shift_jis encoding. |
doc: /* Decode a Japanese character which has CODE in shift_jis encoding. |
7566 |
(code) |
(code) |
7567 |
Lisp_Object code; |
Lisp_Object code; |
7568 |
{ |
{ |
7569 |
unsigned char c1, c2, s1, s2; |
Lisp_Object spec, attrs, val; |
7570 |
Lisp_Object val; |
struct charset *charset_roman, *charset_kanji, *charset_kana, *charset; |
7571 |
|
int c; |
7572 |
|
|
7573 |
CHECK_NUMBER (code); |
CHECK_NATNUM (code); |
7574 |
s1 = (XFASTINT (code)) >> 8, s2 = (XFASTINT (code)) & 0xFF; |
c = XFASTINT (code); |
7575 |
if (s1 == 0) |
CHECK_CODING_SYSTEM_GET_SPEC (Vsjis_coding_system, spec); |
7576 |
{ |
attrs = AREF (spec, 0); |
7577 |
if (s2 < 0x80) |
|
7578 |
XSETFASTINT (val, s2); |
if (ASCII_BYTE_P (c) |
7579 |
else if (s2 >= 0xA0 || s2 <= 0xDF) |
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
7580 |
XSETFASTINT (val, MAKE_CHAR (charset_katakana_jisx0201, s2, 0)); |
return code; |
7581 |
else |
|
7582 |
error ("Invalid Shift JIS code: %x", XFASTINT (code)); |
val = CODING_ATTR_CHARSET_LIST (attrs); |
7583 |
|
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
7584 |
|
charset_kana = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
7585 |
|
charset_kanji = CHARSET_FROM_ID (XINT (XCAR (val))); |
7586 |
|
|
7587 |
|
if (c <= 0x7F) |
7588 |
|
charset = charset_roman; |
7589 |
|
else if (c >= 0xA0 && c < 0xDF) |
7590 |
|
{ |
7591 |
|
charset = charset_kana; |
7592 |
|
c -= 0x80; |
7593 |
} |
} |
7594 |
else |
else |
7595 |
{ |
{ |
7596 |
if ((s1 < 0x80 || (s1 > 0x9F && s1 < 0xE0) || s1 > 0xEF) |
int s1 = c >> 8, s2 = c & 0xFF; |
7597 |
|| (s2 < 0x40 || s2 == 0x7F || s2 > 0xFC)) |
|
7598 |
error ("Invalid Shift JIS code: %x", XFASTINT (code)); |
if (s1 < 0x81 || (s1 > 0x9F && s1 < 0xE0) || s1 > 0xEF |
7599 |
DECODE_SJIS (s1, s2, c1, c2); |
|| s2 < 0x40 || s2 == 0x7F || s2 > 0xFC) |
7600 |
XSETFASTINT (val, MAKE_CHAR (charset_jisx0208, c1, c2)); |
error ("Invalid code: %d", code); |
7601 |
} |
SJIS_TO_JIS (c); |
7602 |
return val; |
charset = charset_kanji; |
7603 |
|
} |
7604 |
|
c = DECODE_CHAR (charset, c); |
7605 |
|
if (c < 0) |
7606 |
|
error ("Invalid code: %d", code); |
7607 |
|
return make_number (c); |
7608 |
} |
} |
7609 |
|
|
7610 |
|
|
7611 |
DEFUN ("encode-sjis-char", Fencode_sjis_char, Sencode_sjis_char, 1, 1, 0, |
DEFUN ("encode-sjis-char", Fencode_sjis_char, Sencode_sjis_char, 1, 1, 0, |
7612 |
doc: /* Encode a Japanese character CHAR to shift_jis encoding. |
doc: /* Encode a Japanese character CHAR to shift_jis encoding. |
7613 |
Return the corresponding code in SJIS. */) |
Return the corresponding code in SJIS. */) |
7614 |
(ch) |
(ch) |
7615 |
Lisp_Object ch; |
Lisp_Object ch; |
7616 |
{ |
{ |
7617 |
int charset, c1, c2, s1, s2; |
Lisp_Object spec, attrs, charset_list; |
7618 |
Lisp_Object val; |
int c; |
7619 |
|
struct charset *charset; |
7620 |
|
unsigned code; |
7621 |
|
|
7622 |
CHECK_NUMBER (ch); |
CHECK_CHARACTER (ch); |
7623 |
SPLIT_CHAR (XFASTINT (ch), charset, c1, c2); |
c = XFASTINT (ch); |
7624 |
if (charset == CHARSET_ASCII) |
CHECK_CODING_SYSTEM_GET_SPEC (Vsjis_coding_system, spec); |
7625 |
{ |
attrs = AREF (spec, 0); |
7626 |
val = ch; |
|
7627 |
} |
if (ASCII_CHAR_P (c) |
7628 |
else if (charset == charset_jisx0208 |
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
7629 |
&& c1 > 0x20 && c1 < 0x7F && c2 > 0x20 && c2 < 0x7F) |
return ch; |
7630 |
{ |
|
7631 |
ENCODE_SJIS (c1, c2, s1, s2); |
charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
7632 |
XSETFASTINT (val, (s1 << 8) | s2); |
charset = char_charset (c, charset_list, &code); |
7633 |
} |
if (code == CHARSET_INVALID_CODE (charset)) |
7634 |
else if (charset == charset_katakana_jisx0201 |
error ("Can't encode by shift_jis encoding: %d", c); |
7635 |
&& c1 > 0x20 && c2 < 0xE0) |
JIS_TO_SJIS (code); |
7636 |
{ |
|
7637 |
XSETFASTINT (val, c1 | 0x80); |
return make_number (code); |
|
} |
|
|
else |
|
|
error ("Can't encode to shift_jis: %d", XFASTINT (ch)); |
|
|
return val; |
|
7638 |
} |
} |
7639 |
|
|
7640 |
DEFUN ("decode-big5-char", Fdecode_big5_char, Sdecode_big5_char, 1, 1, 0, |
DEFUN ("decode-big5-char", Fdecode_big5_char, Sdecode_big5_char, 1, 1, 0, |
7643 |
(code) |
(code) |
7644 |
Lisp_Object code; |
Lisp_Object code; |
7645 |
{ |
{ |
7646 |
int charset; |
Lisp_Object spec, attrs, val; |
7647 |
unsigned char b1, b2, c1, c2; |
struct charset *charset_roman, *charset_big5, *charset; |
7648 |
Lisp_Object val; |
int c; |
7649 |
|
|
7650 |
CHECK_NUMBER (code); |
CHECK_NATNUM (code); |
7651 |
b1 = (XFASTINT (code)) >> 8, b2 = (XFASTINT (code)) & 0xFF; |
c = XFASTINT (code); |
7652 |
if (b1 == 0) |
CHECK_CODING_SYSTEM_GET_SPEC (Vbig5_coding_system, spec); |
7653 |
{ |
attrs = AREF (spec, 0); |
7654 |
if (b2 >= 0x80) |
|
7655 |
error ("Invalid BIG5 code: %x", XFASTINT (code)); |
if (ASCII_BYTE_P (c) |
7656 |
val = code; |
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
7657 |
} |
return code; |
7658 |
|
|
7659 |
|
val = CODING_ATTR_CHARSET_LIST (attrs); |
7660 |
|
charset_roman = CHARSET_FROM_ID (XINT (XCAR (val))), val = XCDR (val); |
7661 |
|
charset_big5 = CHARSET_FROM_ID (XINT (XCAR (val))); |
7662 |
|
|
7663 |
|
if (c <= 0x7F) |
7664 |
|
charset = charset_roman; |
7665 |
else |
else |
7666 |
{ |
{ |
7667 |
if ((b1 < 0xA1 || b1 > 0xFE) |
int b1 = c >> 8, b2 = c & 0x7F; |
7668 |
|| (b2 < 0x40 || (b2 > 0x7E && b2 < 0xA1) || b2 > 0xFE)) |
if (b1 < 0xA1 || b1 > 0xFE |
7669 |
error ("Invalid BIG5 code: %x", XFASTINT (code)); |
|| b2 < 0x40 || (b2 > 0x7E && b2 < 0xA1) || b2 > 0xFE) |
7670 |
DECODE_BIG5 (b1, b2, charset, c1, c2); |
error ("Invalid code: %d", code); |
7671 |
XSETFASTINT (val, MAKE_CHAR (charset, c1, c2)); |
charset = charset_big5; |
7672 |
} |
} |
7673 |
return val; |
c = DECODE_CHAR (charset, (unsigned )c); |
7674 |
|
if (c < 0) |
7675 |
|
error ("Invalid code: %d", code); |
7676 |
|
return make_number (c); |
7677 |
} |
} |
7678 |
|
|
7679 |
DEFUN ("encode-big5-char", Fencode_big5_char, Sencode_big5_char, 1, 1, 0, |
DEFUN ("encode-big5-char", Fencode_big5_char, Sencode_big5_char, 1, 1, 0, |
7682 |
(ch) |
(ch) |
7683 |
Lisp_Object ch; |
Lisp_Object ch; |
7684 |
{ |
{ |
7685 |
int charset, c1, c2, b1, b2; |
Lisp_Object spec, attrs, charset_list; |
7686 |
Lisp_Object val; |
struct charset *charset; |
7687 |
|
int c; |
7688 |
|
unsigned code; |
7689 |
|
|
7690 |
CHECK_NUMBER (ch); |
CHECK_CHARACTER (ch); |
7691 |
SPLIT_CHAR (XFASTINT (ch), charset, c1, c2); |
c = XFASTINT (ch); |
7692 |
if (charset == CHARSET_ASCII) |
CHECK_CODING_SYSTEM_GET_SPEC (Vbig5_coding_system, spec); |
7693 |
{ |
attrs = AREF (spec, 0); |
7694 |
val = ch; |
if (ASCII_CHAR_P (c) |
7695 |
} |
&& ! NILP (CODING_ATTR_ASCII_COMPAT (attrs))) |
7696 |
else if ((charset == charset_big5_1 |
return ch; |
7697 |
&& (XFASTINT (ch) >= 0x250a1 && XFASTINT (ch) <= 0x271ec)) |
|
7698 |
|| (charset == charset_big5_2 |
charset_list = CODING_ATTR_CHARSET_LIST (attrs); |
7699 |
&& XFASTINT (ch) >= 0x290a1 && XFASTINT (ch) <= 0x2bdb2)) |
charset = char_charset (c, charset_list, &code); |
7700 |
{ |
if (code == CHARSET_INVALID_CODE (charset)) |
7701 |
ENCODE_BIG5 (charset, c1, c2, b1, b2); |
error ("Can't encode by Big5 encoding: %d", c); |
7702 |
XSETFASTINT (val, (b1 << 8) | b2); |
|
7703 |
} |
return make_number (code); |
|
else |
|
|
error ("Can't encode to Big5: %d", XFASTINT (ch)); |
|
|
return val; |
|
7704 |
} |
} |
7705 |
|
|
7706 |
|
|
7707 |
DEFUN ("set-terminal-coding-system-internal", Fset_terminal_coding_system_internal, |
DEFUN ("set-terminal-coding-system-internal", |
7708 |
|
Fset_terminal_coding_system_internal, |
7709 |
Sset_terminal_coding_system_internal, 1, 1, 0, |
Sset_terminal_coding_system_internal, 1, 1, 0, |
7710 |
doc: /* Internal use only. */) |
doc: /* Internal use only. */) |
7711 |
(coding_system) |
(coding_system) |
7712 |
Lisp_Object coding_system; |
Lisp_Object coding_system; |
7713 |
{ |
{ |
7714 |
CHECK_SYMBOL (coding_system); |
CHECK_SYMBOL (coding_system); |
7715 |
setup_coding_system (Fcheck_coding_system (coding_system), &terminal_coding); |
setup_coding_system (Fcheck_coding_system (coding_system), |
7716 |
|
&terminal_coding); |
7717 |
|
|
7718 |
/* We had better not send unsafe characters to terminal. */ |
/* We had better not send unsafe characters to terminal. */ |
7719 |
terminal_coding.mode |= CODING_MODE_INHIBIT_UNENCODABLE_CHAR; |
terminal_coding.mode |= CODING_MODE_SAFE_ENCODING; |
7720 |
/* Character composition should be disabled. */ |
/* Characer composition should be disabled. */ |
7721 |
terminal_coding.composing = COMPOSITION_DISABLED; |
terminal_coding.common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK; |
|
/* Error notification should be suppressed. */ |
|
|
terminal_coding.suppress_error = 1; |
|
7722 |
terminal_coding.src_multibyte = 1; |
terminal_coding.src_multibyte = 1; |
7723 |
terminal_coding.dst_multibyte = 0; |
terminal_coding.dst_multibyte = 0; |
7724 |
return Qnil; |
return Qnil; |
7725 |
} |
} |
7726 |
|
|
7727 |
DEFUN ("set-safe-terminal-coding-system-internal", Fset_safe_terminal_coding_system_internal, |
DEFUN ("set-safe-terminal-coding-system-internal", |
7728 |
|
Fset_safe_terminal_coding_system_internal, |
7729 |
Sset_safe_terminal_coding_system_internal, 1, 1, 0, |
Sset_safe_terminal_coding_system_internal, 1, 1, 0, |
7730 |
doc: /* Internal use only. */) |
doc: /* Internal use only. */) |
7731 |
(coding_system) |
(coding_system) |
7734 |
CHECK_SYMBOL (coding_system); |
CHECK_SYMBOL (coding_system); |
7735 |
setup_coding_system (Fcheck_coding_system (coding_system), |
setup_coding_system (Fcheck_coding_system (coding_system), |
7736 |
&safe_terminal_coding); |
&safe_terminal_coding); |
7737 |
/* Character composition should be disabled. */ |
/* Characer composition should be disabled. */ |
7738 |
safe_terminal_coding.composing = COMPOSITION_DISABLED; |
safe_terminal_coding.common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK; |
|
/* Error notification should be suppressed. */ |
|
|
terminal_coding.suppress_error = 1; |
|
7739 |
safe_terminal_coding.src_multibyte = 1; |
safe_terminal_coding.src_multibyte = 1; |
7740 |
safe_terminal_coding.dst_multibyte = 0; |
safe_terminal_coding.dst_multibyte = 0; |
7741 |
return Qnil; |
return Qnil; |
7742 |
} |
} |
7743 |
|
|
7744 |
DEFUN ("terminal-coding-system", Fterminal_coding_system, |
DEFUN ("terminal-coding-system", |
7745 |
Sterminal_coding_system, 0, 0, 0, |
Fterminal_coding_system, Sterminal_coding_system, 0, 0, 0, |
7746 |
doc: /* Return coding system specified for terminal output. */) |
doc: /* Return coding system specified for terminal output. */) |
7747 |
() |
() |
7748 |
{ |
{ |
7749 |
return terminal_coding.symbol; |
return CODING_ID_NAME (terminal_coding.id); |
7750 |
} |
} |
7751 |
|
|
7752 |
DEFUN ("set-keyboard-coding-system-internal", Fset_keyboard_coding_system_internal, |
DEFUN ("set-keyboard-coding-system-internal", |
7753 |
|
Fset_keyboard_coding_system_internal, |
7754 |
Sset_keyboard_coding_system_internal, 1, 1, 0, |
Sset_keyboard_coding_system_internal, 1, 1, 0, |
7755 |
doc: /* Internal use only. */) |
doc: /* Internal use only. */) |
7756 |
(coding_system) |
(coding_system) |
7757 |
Lisp_Object coding_system; |
Lisp_Object coding_system; |
7758 |
{ |
{ |
7759 |
CHECK_SYMBOL (coding_system); |
CHECK_SYMBOL (coding_system); |
7760 |
setup_coding_system (Fcheck_coding_system (coding_system), &keyboard_coding); |
setup_coding_system (Fcheck_coding_system (coding_system), |
7761 |
/* Character composition should be disabled. */ |
&keyboard_coding); |
7762 |
keyboard_coding.composing = COMPOSITION_DISABLED; |
/* Characer composition should be disabled. */ |
7763 |
|
keyboard_coding.common_flags &= ~CODING_ANNOTATE_COMPOSITION_MASK; |
7764 |
return Qnil; |
return Qnil; |
7765 |
} |
} |
7766 |
|
|
7767 |
DEFUN ("keyboard-coding-system", Fkeyboard_coding_system, |
DEFUN ("keyboard-coding-system", |
7768 |
Skeyboard_coding_system, 0, 0, 0, |
Fkeyboard_coding_system, Skeyboard_coding_system, 0, 0, 0, |
7769 |
doc: /* Return coding system specified for decoding keyboard input. */) |
doc: /* Return coding system specified for decoding keyboard input. */) |
7770 |
() |
() |
7771 |
{ |
{ |
7772 |
return keyboard_coding.symbol; |
return CODING_ID_NAME (keyboard_coding.id); |
7773 |
} |
} |
7774 |
|
|
7775 |
|
|
7817 |
operation = args[0]; |
operation = args[0]; |
7818 |
if (!SYMBOLP (operation) |
if (!SYMBOLP (operation) |
7819 |
|| !INTEGERP (target_idx = Fget (operation, Qtarget_idx))) |
|| !INTEGERP (target_idx = Fget (operation, Qtarget_idx))) |
7820 |
error ("Invalid first argument"); |
error ("Invalid first arguement"); |
7821 |
if (nargs < 1 + XINT (target_idx)) |
if (nargs < 1 + XINT (target_idx)) |
7822 |
error ("Too few arguments for operation: %s", |
error ("Too few arguments for operation: %s", |
7823 |
SDATA (SYMBOL_NAME (operation))); |
SDATA (SYMBOL_NAME (operation))); |
|
/* For write-region, if the 6th argument (i.e. VISIT, the 5th |
|
|
argument to write-region) is string, it must be treated as a |
|
|
target file name. */ |
|
|
if (EQ (operation, Qwrite_region) |
|
|
&& nargs > 5 |
|
|
&& STRINGP (args[5])) |
|
|
target_idx = make_number (4); |
|
7824 |
target = args[XINT (target_idx) + 1]; |
target = args[XINT (target_idx) + 1]; |
7825 |
if (!(STRINGP (target) |
if (!(STRINGP (target) |
7826 |
|| (EQ (operation, Qopen_network_stream) && INTEGERP (target)))) |
|| (EQ (operation, Qopen_network_stream) && INTEGERP (target)))) |
7827 |
error ("Invalid argument %d", XINT (target_idx) + 1); |
error ("Invalid %dth argument", XINT (target_idx) + 1); |
7828 |
|
|
7829 |
chain = ((EQ (operation, Qinsert_file_contents) |
chain = ((EQ (operation, Qinsert_file_contents) |
7830 |
|| EQ (operation, Qwrite_region)) |
|| EQ (operation, Qwrite_region)) |
7838 |
for (; CONSP (chain); chain = XCDR (chain)) |
for (; CONSP (chain); chain = XCDR (chain)) |
7839 |
{ |
{ |
7840 |
Lisp_Object elt; |
Lisp_Object elt; |
|
elt = XCAR (chain); |
|
7841 |
|
|
7842 |
|
elt = XCAR (chain); |
7843 |
if (CONSP (elt) |
if (CONSP (elt) |
7844 |
&& ((STRINGP (target) |
&& ((STRINGP (target) |
7845 |
&& STRINGP (XCAR (elt)) |
&& STRINGP (XCAR (elt)) |
7869 |
return Qnil; |
return Qnil; |
7870 |
} |
} |
7871 |
|
|
7872 |
DEFUN ("update-coding-systems-internal", Fupdate_coding_systems_internal, |
DEFUN ("set-coding-system-priority", Fset_coding_system_priority, |
7873 |
Supdate_coding_systems_internal, 0, 0, 0, |
Sset_coding_system_priority, 0, MANY, 0, |
7874 |
doc: /* Update internal database for ISO2022 and CCL based coding systems. |
doc: /* Assign higher priority to the coding systems given as arguments. |
7875 |
When values of any coding categories are changed, you must |
If multiple coding systems belongs to the same category, |
7876 |
call this function. */) |
all but the first one are ignored. */) |
7877 |
() |
(nargs, args) |
7878 |
|
int nargs; |
7879 |
|
Lisp_Object *args; |
7880 |
|
{ |
7881 |
|
int i, j; |
7882 |
|
int changed[coding_category_max]; |
7883 |
|
enum coding_category priorities[coding_category_max]; |
7884 |
|
|
7885 |
|
bzero (changed, sizeof changed); |
7886 |
|
|
7887 |
|
for (i = j = 0; i < nargs; i++) |
7888 |
|
{ |
7889 |
|
enum coding_category category; |
7890 |
|
Lisp_Object spec, attrs; |
7891 |
|
|
7892 |
|
CHECK_CODING_SYSTEM_GET_SPEC (args[i], spec); |
7893 |
|
attrs = AREF (spec, 0); |
7894 |
|
category = XINT (CODING_ATTR_CATEGORY (attrs)); |
7895 |
|
if (changed[category]) |
7896 |
|
/* Ignore this coding system because a coding system of the |
7897 |
|
same category already had a higher priority. */ |
7898 |
|
continue; |
7899 |
|
changed[category] = 1; |
7900 |
|
priorities[j++] = category; |
7901 |
|
if (coding_categories[category].id >= 0 |
7902 |
|
&& ! EQ (args[i], CODING_ID_NAME (coding_categories[category].id))) |
7903 |
|
setup_coding_system (args[i], &coding_categories[category]); |
7904 |
|
Fset (AREF (Vcoding_category_table, category), args[i]); |
7905 |
|
} |
7906 |
|
|
7907 |
|
/* Now we have decided top J priorities. Reflect the order of the |
7908 |
|
original priorities to the remaining priorities. */ |
7909 |
|
|
7910 |
|
for (i = j, j = 0; i < coding_category_max; i++, j++) |
7911 |
|
{ |
7912 |
|
while (j < coding_category_max |
7913 |
|
&& changed[coding_priorities[j]]) |
7914 |
|
j++; |
7915 |
|
if (j == coding_category_max) |
7916 |
|
abort (); |
7917 |
|
priorities[i] = coding_priorities[j]; |
7918 |
|
} |
7919 |
|
|
7920 |
|
bcopy (priorities, coding_priorities, sizeof priorities); |
7921 |
|
|
7922 |
|
/* Update `coding-category-list'. */ |
7923 |
|
Vcoding_category_list = Qnil; |
7924 |
|
for (i = coding_category_max - 1; i >= 0; i--) |
7925 |
|
Vcoding_category_list |
7926 |
|
= Fcons (AREF (Vcoding_category_table, priorities[i]), |
7927 |
|
Vcoding_category_list); |
7928 |
|
|
7929 |
|
return Qnil; |
7930 |
|
} |
7931 |
|
|
7932 |
|
DEFUN ("coding-system-priority-list", Fcoding_system_priority_list, |
7933 |
|
Scoding_system_priority_list, 0, 1, 0, |
7934 |
|
doc: /* Return a list of coding systems ordered by their priorities. |
7935 |
|
HIGHESTP non-nil means just return the highest priority one. */) |
7936 |
|
(highestp) |
7937 |
|
Lisp_Object highestp; |
7938 |
{ |
{ |
7939 |
int i; |
int i; |
7940 |
|
Lisp_Object val; |
7941 |
|
|
7942 |
for (i = CODING_CATEGORY_IDX_EMACS_MULE; i < CODING_CATEGORY_IDX_MAX; i++) |
for (i = 0, val = Qnil; i < coding_category_max; i++) |
7943 |
{ |
{ |
7944 |
Lisp_Object val; |
enum coding_category category = coding_priorities[i]; |
7945 |
|
int id = coding_categories[category].id; |
7946 |
|
Lisp_Object attrs; |
7947 |
|
|
7948 |
|
if (id < 0) |
7949 |
|
continue; |
7950 |
|
attrs = CODING_ID_ATTRS (id); |
7951 |
|
if (! NILP (highestp)) |
7952 |
|
return CODING_ATTR_BASE_NAME (attrs); |
7953 |
|
val = Fcons (CODING_ATTR_BASE_NAME (attrs), val); |
7954 |
|
} |
7955 |
|
return Fnreverse (val); |
7956 |
|
} |
7957 |
|
|
7958 |
|
static char *suffixes[] = { "-unix", "-dos", "-mac" }; |
7959 |
|
|
7960 |
|
static Lisp_Object |
7961 |
|
make_subsidiaries (base) |
7962 |
|
Lisp_Object base; |
7963 |
|
{ |
7964 |
|
Lisp_Object subsidiaries; |
7965 |
|
int base_name_len = SBYTES (SYMBOL_NAME (base)); |
7966 |
|
char *buf = (char *) alloca (base_name_len + 6); |
7967 |
|
int i; |
7968 |
|
|
7969 |
val = SYMBOL_VALUE (XVECTOR (Vcoding_category_table)->contents[i]); |
bcopy (SDATA (SYMBOL_NAME (base)), buf, base_name_len); |
7970 |
if (!NILP (val)) |
subsidiaries = Fmake_vector (make_number (3), Qnil); |
7971 |
|
for (i = 0; i < 3; i++) |
7972 |
|
{ |
7973 |
|
bcopy (suffixes[i], buf + base_name_len, strlen (suffixes[i]) + 1); |
7974 |
|
ASET (subsidiaries, i, intern (buf)); |
7975 |
|
} |
7976 |
|
return subsidiaries; |
7977 |
|
} |
7978 |
|
|
7979 |
|
|
7980 |
|
DEFUN ("define-coding-system-internal", Fdefine_coding_system_internal, |
7981 |
|
Sdefine_coding_system_internal, coding_arg_max, MANY, 0, |
7982 |
|
doc: /* For internal use only. |
7983 |
|
usage: (define-coding-system-internal ...) */) |
7984 |
|
(nargs, args) |
7985 |
|
int nargs; |
7986 |
|
Lisp_Object *args; |
7987 |
|
{ |
7988 |
|
Lisp_Object name; |
7989 |
|
Lisp_Object spec_vec; /* [ ATTRS ALIASE EOL_TYPE ] */ |
7990 |
|
Lisp_Object attrs; /* Vector of attributes. */ |
7991 |
|
Lisp_Object eol_type; |
7992 |
|
Lisp_Object aliases; |
7993 |
|
Lisp_Object coding_type, charset_list, safe_charsets; |
7994 |
|
enum coding_category category; |
7995 |
|
Lisp_Object tail, val; |
7996 |
|
int max_charset_id = 0; |
7997 |
|
int i; |
7998 |
|
|
7999 |
|
if (nargs < coding_arg_max) |
8000 |
|
goto short_args; |
8001 |
|
|
8002 |
|
attrs = Fmake_vector (make_number (coding_attr_last_index), Qnil); |
8003 |
|
|
8004 |
|
name = args[coding_arg_name]; |
8005 |
|
CHECK_SYMBOL (name); |
8006 |
|
CODING_ATTR_BASE_NAME (attrs) = name; |
8007 |
|
|
8008 |
|
val = args[coding_arg_mnemonic]; |
8009 |
|
if (! STRINGP (val)) |
8010 |
|
CHECK_CHARACTER (val); |
8011 |
|
CODING_ATTR_MNEMONIC (attrs) = val; |
8012 |
|
|
8013 |
|
coding_type = args[coding_arg_coding_type]; |
8014 |
|
CHECK_SYMBOL (coding_type); |
8015 |
|
CODING_ATTR_TYPE (attrs) = coding_type; |
8016 |
|
|
8017 |
|
charset_list = args[coding_arg_charset_list]; |
8018 |
|
if (SYMBOLP (charset_list)) |
8019 |
|
{ |
8020 |
|
if (EQ (charset_list, Qiso_2022)) |
8021 |
{ |
{ |
8022 |
if (! coding_system_table[i]) |
if (! EQ (coding_type, Qiso_2022)) |
8023 |
coding_system_table[i] = ((struct coding_system *) |
error ("Invalid charset-list"); |
8024 |
xmalloc (sizeof (struct coding_system))); |
charset_list = Viso_2022_charset_list; |
|
setup_coding_system (val, coding_system_table[i]); |
|
8025 |
} |
} |
8026 |
else if (coding_system_table[i]) |
else if (EQ (charset_list, Qemacs_mule)) |
8027 |
{ |
{ |
8028 |
xfree (coding_system_table[i]); |
if (! EQ (coding_type, Qemacs_mule)) |
8029 |
coding_system_table[i] = NULL; |
error ("Invalid charset-list"); |
8030 |
|
charset_list = Vemacs_mule_charset_list; |
8031 |
} |
} |
8032 |
|
for (tail = charset_list; CONSP (tail); tail = XCDR (tail)) |
8033 |
|
if (max_charset_id < XFASTINT (XCAR (tail))) |
8034 |
|
max_charset_id = XFASTINT (XCAR (tail)); |
8035 |
} |
} |
8036 |
|
else |
8037 |
|
{ |
8038 |
|
charset_list = Fcopy_sequence (charset_list); |
8039 |
|
for (tail = charset_list; !NILP (tail); tail = Fcdr (tail)) |
8040 |
|
{ |
8041 |
|
struct charset *charset; |
8042 |
|
|
8043 |
return Qnil; |
val = Fcar (tail); |
8044 |
} |
CHECK_CHARSET_GET_CHARSET (val, charset); |
8045 |
|
if (EQ (coding_type, Qiso_2022) |
8046 |
|
? CHARSET_ISO_FINAL (charset) < 0 |
8047 |
|
: EQ (coding_type, Qemacs_mule) |
8048 |
|
? CHARSET_EMACS_MULE_ID (charset) < 0 |
8049 |
|
: 0) |
8050 |
|
error ("Can't handle charset `%s'", |
8051 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8052 |
|
|
8053 |
|
XSETCAR (tail, make_number (charset->id)); |
8054 |
|
if (max_charset_id < charset->id) |
8055 |
|
max_charset_id = charset->id; |
8056 |
|
} |
8057 |
|
} |
8058 |
|
CODING_ATTR_CHARSET_LIST (attrs) = charset_list; |
8059 |
|
|
8060 |
|
safe_charsets = Fmake_string (make_number (max_charset_id + 1), |
8061 |
|
make_number (255)); |
8062 |
|
for (tail = charset_list; CONSP (tail); tail = XCDR (tail)) |
8063 |
|
SSET (safe_charsets, XFASTINT (XCAR (tail)), 0); |
8064 |
|
CODING_ATTR_SAFE_CHARSETS (attrs) = safe_charsets; |
8065 |
|
|
8066 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = args[coding_arg_ascii_compatible_p]; |
8067 |
|
|
8068 |
|
val = args[coding_arg_decode_translation_table]; |
8069 |
|
if (! NILP (val)) |
8070 |
|
CHECK_CHAR_TABLE (val); |
8071 |
|
CODING_ATTR_DECODE_TBL (attrs) = val; |
8072 |
|
|
8073 |
|
val = args[coding_arg_encode_translation_table]; |
8074 |
|
if (! NILP (val)) |
8075 |
|
CHECK_CHAR_TABLE (val); |
8076 |
|
CODING_ATTR_ENCODE_TBL (attrs) = val; |
8077 |
|
|
8078 |
|
val = args[coding_arg_post_read_conversion]; |
8079 |
|
CHECK_SYMBOL (val); |
8080 |
|
CODING_ATTR_POST_READ (attrs) = val; |
8081 |
|
|
8082 |
|
val = args[coding_arg_pre_write_conversion]; |
8083 |
|
CHECK_SYMBOL (val); |
8084 |
|
CODING_ATTR_PRE_WRITE (attrs) = val; |
8085 |
|
|
8086 |
|
val = args[coding_arg_default_char]; |
8087 |
|
if (NILP (val)) |
8088 |
|
CODING_ATTR_DEFAULT_CHAR (attrs) = make_number (' '); |
8089 |
|
else |
8090 |
|
{ |
8091 |
|
CHECK_CHARACTER (val); |
8092 |
|
CODING_ATTR_DEFAULT_CHAR (attrs) = val; |
8093 |
|
} |
8094 |
|
|
8095 |
DEFUN ("set-coding-priority-internal", Fset_coding_priority_internal, |
val = args[coding_arg_for_unibyte]; |
8096 |
Sset_coding_priority_internal, 0, 0, 0, |
CODING_ATTR_FOR_UNIBYTE (attrs) = NILP (val) ? Qnil : Qt; |
|
doc: /* Update internal database for the current value of `coding-category-list'. |
|
|
This function is internal use only. */) |
|
|
() |
|
|
{ |
|
|
int i = 0, idx; |
|
|
Lisp_Object val; |
|
8097 |
|
|
8098 |
val = Vcoding_category_list; |
val = args[coding_arg_plist]; |
8099 |
|
CHECK_LIST (val); |
8100 |
|
CODING_ATTR_PLIST (attrs) = val; |
8101 |
|
|
8102 |
while (CONSP (val) && i < CODING_CATEGORY_IDX_MAX) |
if (EQ (coding_type, Qcharset)) |
8103 |
{ |
{ |
8104 |
if (! SYMBOLP (XCAR (val))) |
Lisp_Object list; |
8105 |
break; |
/* Generate a lisp vector of 256 elements. Each element is nil, |
8106 |
idx = XFASTINT (Fget (XCAR (val), Qcoding_category_index)); |
integer, or a list of charset IDs. |
8107 |
if (idx >= CODING_CATEGORY_IDX_MAX) |
|
8108 |
break; |
If Nth element is nil, the byte code N is invalid in this |
8109 |
coding_priorities[i++] = (1 << idx); |
coding system. |
8110 |
val = XCDR (val); |
|
8111 |
|
If Nth element is a number NUM, N is the first byte of a |
8112 |
|
charset whose ID is NUM. |
8113 |
|
|
8114 |
|
If Nth element is a list of charset IDs, N is the first byte |
8115 |
|
of one of them. The list is sorted by dimensions of the |
8116 |
|
charsets. A charset of smaller dimension comes firtst. |
8117 |
|
*/ |
8118 |
|
for (list = Qnil, tail = charset_list; CONSP (tail); tail = XCDR (tail)) |
8119 |
|
{ |
8120 |
|
struct charset *charset = CHARSET_FROM_ID (XFASTINT (XCAR (tail))); |
8121 |
|
|
8122 |
|
if (charset->method == CHARSET_METHOD_SUPERSET) |
8123 |
|
{ |
8124 |
|
val = CHARSET_SUPERSET (charset); |
8125 |
|
for (; CONSP (val); val = XCDR (val)) |
8126 |
|
list = Fcons (XCAR (XCAR (val)), list); |
8127 |
|
} |
8128 |
|
else |
8129 |
|
list = Fcons (XCAR (tail), list); |
8130 |
|
} |
8131 |
|
|
8132 |
|
val = Fmake_vector (make_number (256), Qnil); |
8133 |
|
|
8134 |
|
for (tail = Fnreverse (list); CONSP (tail); tail = XCDR (tail)) |
8135 |
|
{ |
8136 |
|
struct charset *charset = CHARSET_FROM_ID (XFASTINT (XCAR (tail))); |
8137 |
|
int dim = CHARSET_DIMENSION (charset); |
8138 |
|
int idx = (dim - 1) * 4; |
8139 |
|
|
8140 |
|
if (CHARSET_ASCII_COMPATIBLE_P (charset)) |
8141 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8142 |
|
|
8143 |
|
for (i = charset->code_space[idx]; |
8144 |
|
i <= charset->code_space[idx + 1]; i++) |
8145 |
|
{ |
8146 |
|
Lisp_Object tmp, tmp2; |
8147 |
|
int dim2; |
8148 |
|
|
8149 |
|
tmp = AREF (val, i); |
8150 |
|
if (NILP (tmp)) |
8151 |
|
tmp = XCAR (tail); |
8152 |
|
else if (NUMBERP (tmp)) |
8153 |
|
{ |
8154 |
|
dim2 = CHARSET_DIMENSION (CHARSET_FROM_ID (XFASTINT (tmp))); |
8155 |
|
if (dim < dim2) |
8156 |
|
tmp = Fcons (XCAR (tail), Fcons (tmp, Qnil)); |
8157 |
|
else |
8158 |
|
tmp = Fcons (tmp, Fcons (XCAR (tail), Qnil)); |
8159 |
|
} |
8160 |
|
else |
8161 |
|
{ |
8162 |
|
for (tmp2 = tmp; CONSP (tmp2); tmp2 = XCDR (tmp2)) |
8163 |
|
{ |
8164 |
|
dim2 = CHARSET_DIMENSION (CHARSET_FROM_ID (XFASTINT (XCAR (tmp2)))); |
8165 |
|
if (dim < dim2) |
8166 |
|
break; |
8167 |
|
} |
8168 |
|
if (NILP (tmp2)) |
8169 |
|
tmp = nconc2 (tmp, Fcons (XCAR (tail), Qnil)); |
8170 |
|
else |
8171 |
|
{ |
8172 |
|
XSETCDR (tmp2, Fcons (XCAR (tmp2), XCDR (tmp2))); |
8173 |
|
XSETCAR (tmp2, XCAR (tail)); |
8174 |
|
} |
8175 |
|
} |
8176 |
|
ASET (val, i, tmp); |
8177 |
|
} |
8178 |
|
} |
8179 |
|
ASET (attrs, coding_attr_charset_valids, val); |
8180 |
|
category = coding_category_charset; |
8181 |
} |
} |
8182 |
/* If coding-category-list is valid and contains all coding |
else if (EQ (coding_type, Qccl)) |
8183 |
categories, `i' should be CODING_CATEGORY_IDX_MAX now. If not, |
{ |
8184 |
the following code saves Emacs from crashing. */ |
Lisp_Object valids; |
|
while (i < CODING_CATEGORY_IDX_MAX) |
|
|
coding_priorities[i++] = CODING_CATEGORY_MASK_RAW_TEXT; |
|
8185 |
|
|
8186 |
return Qnil; |
if (nargs < coding_arg_ccl_max) |
8187 |
} |
goto short_args; |
8188 |
|
|
8189 |
DEFUN ("define-coding-system-internal", Fdefine_coding_system_internal, |
val = args[coding_arg_ccl_decoder]; |
8190 |
Sdefine_coding_system_internal, 1, 1, 0, |
CHECK_CCL_PROGRAM (val); |
8191 |
doc: /* Register CODING-SYSTEM as a base coding system. |
if (VECTORP (val)) |
8192 |
This function is internal use only. */) |
val = Fcopy_sequence (val); |
8193 |
(coding_system) |
ASET (attrs, coding_attr_ccl_decoder, val); |
|
Lisp_Object coding_system; |
|
|
{ |
|
|
Lisp_Object safe_chars, slot; |
|
8194 |
|
|
8195 |
if (NILP (Fcheck_coding_system (coding_system))) |
val = args[coding_arg_ccl_encoder]; |
8196 |
Fsignal (Qcoding_system_error, Fcons (coding_system, Qnil)); |
CHECK_CCL_PROGRAM (val); |
8197 |
safe_chars = coding_safe_chars (coding_system); |
if (VECTORP (val)) |
8198 |
if (! EQ (safe_chars, Qt) && ! CHAR_TABLE_P (safe_chars)) |
val = Fcopy_sequence (val); |
8199 |
error ("No valid safe-chars property for %s", |
ASET (attrs, coding_attr_ccl_encoder, val); |
8200 |
SDATA (SYMBOL_NAME (coding_system))); |
|
8201 |
if (EQ (safe_chars, Qt)) |
val = args[coding_arg_ccl_valids]; |
8202 |
{ |
valids = Fmake_string (make_number (256), make_number (0)); |
8203 |
if (NILP (Fmemq (coding_system, XCAR (Vcoding_system_safe_chars)))) |
for (tail = val; !NILP (tail); tail = Fcdr (tail)) |
8204 |
XSETCAR (Vcoding_system_safe_chars, |
{ |
8205 |
Fcons (coding_system, XCAR (Vcoding_system_safe_chars))); |
int from, to; |
8206 |
|
|
8207 |
|
val = Fcar (tail); |
8208 |
|
if (INTEGERP (val)) |
8209 |
|
{ |
8210 |
|
from = to = XINT (val); |
8211 |
|
if (from < 0 || from > 255) |
8212 |
|
args_out_of_range_3 (val, make_number (0), make_number (255)); |
8213 |
|
} |
8214 |
|
else |
8215 |
|
{ |
8216 |
|
CHECK_CONS (val); |
8217 |
|
CHECK_NATNUM_CAR (val); |
8218 |
|
CHECK_NATNUM_CDR (val); |
8219 |
|
from = XINT (XCAR (val)); |
8220 |
|
if (from > 255) |
8221 |
|
args_out_of_range_3 (XCAR (val), |
8222 |
|
make_number (0), make_number (255)); |
8223 |
|
to = XINT (XCDR (val)); |
8224 |
|
if (to < from || to > 255) |
8225 |
|
args_out_of_range_3 (XCDR (val), |
8226 |
|
XCAR (val), make_number (255)); |
8227 |
|
} |
8228 |
|
for (i = from; i <= to; i++) |
8229 |
|
SSET (valids, i, 1); |
8230 |
|
} |
8231 |
|
ASET (attrs, coding_attr_ccl_valids, valids); |
8232 |
|
|
8233 |
|
category = coding_category_ccl; |
8234 |
|
} |
8235 |
|
else if (EQ (coding_type, Qutf_16)) |
8236 |
|
{ |
8237 |
|
Lisp_Object bom, endian; |
8238 |
|
|
8239 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qnil; |
8240 |
|
|
8241 |
|
if (nargs < coding_arg_utf16_max) |
8242 |
|
goto short_args; |
8243 |
|
|
8244 |
|
bom = args[coding_arg_utf16_bom]; |
8245 |
|
if (! NILP (bom) && ! EQ (bom, Qt)) |
8246 |
|
{ |
8247 |
|
CHECK_CONS (bom); |
8248 |
|
val = XCAR (bom); |
8249 |
|
CHECK_CODING_SYSTEM (val); |
8250 |
|
val = XCDR (bom); |
8251 |
|
CHECK_CODING_SYSTEM (val); |
8252 |
|
} |
8253 |
|
ASET (attrs, coding_attr_utf_16_bom, bom); |
8254 |
|
|
8255 |
|
endian = args[coding_arg_utf16_endian]; |
8256 |
|
CHECK_SYMBOL (endian); |
8257 |
|
if (NILP (endian)) |
8258 |
|
endian = Qbig; |
8259 |
|
else if (! EQ (endian, Qbig) && ! EQ (endian, Qlittle)) |
8260 |
|
error ("Invalid endian: %s", SDATA (SYMBOL_NAME (endian))); |
8261 |
|
ASET (attrs, coding_attr_utf_16_endian, endian); |
8262 |
|
|
8263 |
|
category = (CONSP (bom) |
8264 |
|
? coding_category_utf_16_auto |
8265 |
|
: NILP (bom) |
8266 |
|
? (EQ (endian, Qbig) |
8267 |
|
? coding_category_utf_16_be_nosig |
8268 |
|
: coding_category_utf_16_le_nosig) |
8269 |
|
: (EQ (endian, Qbig) |
8270 |
|
? coding_category_utf_16_be |
8271 |
|
: coding_category_utf_16_le)); |
8272 |
} |
} |
8273 |
else |
else if (EQ (coding_type, Qiso_2022)) |
8274 |
{ |
{ |
8275 |
slot = Fassq (coding_system, XCDR (Vcoding_system_safe_chars)); |
Lisp_Object initial, reg_usage, request, flags; |
8276 |
if (NILP (slot)) |
int i; |
8277 |
XSETCDR (Vcoding_system_safe_chars, |
|
8278 |
nconc2 (XCDR (Vcoding_system_safe_chars), |
if (nargs < coding_arg_iso2022_max) |
8279 |
Fcons (Fcons (coding_system, safe_chars), Qnil))); |
goto short_args; |
8280 |
|
|
8281 |
|
initial = Fcopy_sequence (args[coding_arg_iso2022_initial]); |
8282 |
|
CHECK_VECTOR (initial); |
8283 |
|
for (i = 0; i < 4; i++) |
8284 |
|
{ |
8285 |
|
val = Faref (initial, make_number (i)); |
8286 |
|
if (! NILP (val)) |
8287 |
|
{ |
8288 |
|
struct charset *charset; |
8289 |
|
|
8290 |
|
CHECK_CHARSET_GET_CHARSET (val, charset); |
8291 |
|
ASET (initial, i, make_number (CHARSET_ID (charset))); |
8292 |
|
if (i == 0 && CHARSET_ASCII_COMPATIBLE_P (charset)) |
8293 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8294 |
|
} |
8295 |
|
else |
8296 |
|
ASET (initial, i, make_number (-1)); |
8297 |
|
} |
8298 |
|
|
8299 |
|
reg_usage = args[coding_arg_iso2022_reg_usage]; |
8300 |
|
CHECK_CONS (reg_usage); |
8301 |
|
CHECK_NUMBER_CAR (reg_usage); |
8302 |
|
CHECK_NUMBER_CDR (reg_usage); |
8303 |
|
|
8304 |
|
request = Fcopy_sequence (args[coding_arg_iso2022_request]); |
8305 |
|
for (tail = request; ! NILP (tail); tail = Fcdr (tail)) |
8306 |
|
{ |
8307 |
|
int id; |
8308 |
|
Lisp_Object tmp; |
8309 |
|
|
8310 |
|
val = Fcar (tail); |
8311 |
|
CHECK_CONS (val); |
8312 |
|
tmp = XCAR (val); |
8313 |
|
CHECK_CHARSET_GET_ID (tmp, id); |
8314 |
|
CHECK_NATNUM_CDR (val); |
8315 |
|
if (XINT (XCDR (val)) >= 4) |
8316 |
|
error ("Invalid graphic register number: %d", XINT (XCDR (val))); |
8317 |
|
XSETCAR (val, make_number (id)); |
8318 |
|
} |
8319 |
|
|
8320 |
|
flags = args[coding_arg_iso2022_flags]; |
8321 |
|
CHECK_NATNUM (flags); |
8322 |
|
i = XINT (flags); |
8323 |
|
if (EQ (args[coding_arg_charset_list], Qiso_2022)) |
8324 |
|
flags = make_number (i | CODING_ISO_FLAG_FULL_SUPPORT); |
8325 |
|
|
8326 |
|
ASET (attrs, coding_attr_iso_initial, initial); |
8327 |
|
ASET (attrs, coding_attr_iso_usage, reg_usage); |
8328 |
|
ASET (attrs, coding_attr_iso_request, request); |
8329 |
|
ASET (attrs, coding_attr_iso_flags, flags); |
8330 |
|
setup_iso_safe_charsets (attrs); |
8331 |
|
|
8332 |
|
if (i & CODING_ISO_FLAG_SEVEN_BITS) |
8333 |
|
category = ((i & (CODING_ISO_FLAG_LOCKING_SHIFT |
8334 |
|
| CODING_ISO_FLAG_SINGLE_SHIFT)) |
8335 |
|
? coding_category_iso_7_else |
8336 |
|
: EQ (args[coding_arg_charset_list], Qiso_2022) |
8337 |
|
? coding_category_iso_7 |
8338 |
|
: coding_category_iso_7_tight); |
8339 |
else |
else |
8340 |
XSETCDR (slot, safe_chars); |
{ |
8341 |
|
int id = XINT (AREF (initial, 1)); |
8342 |
|
|
8343 |
|
category = (((i & CODING_ISO_FLAG_LOCKING_SHIFT) |
8344 |
|
|| EQ (args[coding_arg_charset_list], Qiso_2022) |
8345 |
|
|| id < 0) |
8346 |
|
? coding_category_iso_8_else |
8347 |
|
: (CHARSET_DIMENSION (CHARSET_FROM_ID (id)) == 1) |
8348 |
|
? coding_category_iso_8_1 |
8349 |
|
: coding_category_iso_8_2); |
8350 |
|
} |
8351 |
|
if (category != coding_category_iso_8_1 |
8352 |
|
&& category != coding_category_iso_8_2) |
8353 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qnil; |
8354 |
|
} |
8355 |
|
else if (EQ (coding_type, Qemacs_mule)) |
8356 |
|
{ |
8357 |
|
if (EQ (args[coding_arg_charset_list], Qemacs_mule)) |
8358 |
|
ASET (attrs, coding_attr_emacs_mule_full, Qt); |
8359 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8360 |
|
category = coding_category_emacs_mule; |
8361 |
|
} |
8362 |
|
else if (EQ (coding_type, Qshift_jis)) |
8363 |
|
{ |
8364 |
|
|
8365 |
|
struct charset *charset; |
8366 |
|
|
8367 |
|
if (XINT (Flength (charset_list)) != 3) |
8368 |
|
error ("There should be just three charsets"); |
8369 |
|
|
8370 |
|
charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
8371 |
|
if (CHARSET_DIMENSION (charset) != 1) |
8372 |
|
error ("Dimension of charset %s is not one", |
8373 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8374 |
|
if (CHARSET_ASCII_COMPATIBLE_P (charset)) |
8375 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8376 |
|
|
8377 |
|
charset_list = XCDR (charset_list); |
8378 |
|
charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
8379 |
|
if (CHARSET_DIMENSION (charset) != 1) |
8380 |
|
error ("Dimension of charset %s is not one", |
8381 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8382 |
|
|
8383 |
|
charset_list = XCDR (charset_list); |
8384 |
|
charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
8385 |
|
if (CHARSET_DIMENSION (charset) != 2) |
8386 |
|
error ("Dimension of charset %s is not two", |
8387 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8388 |
|
|
8389 |
|
category = coding_category_sjis; |
8390 |
|
Vsjis_coding_system = name; |
8391 |
|
} |
8392 |
|
else if (EQ (coding_type, Qbig5)) |
8393 |
|
{ |
8394 |
|
struct charset *charset; |
8395 |
|
|
8396 |
|
if (XINT (Flength (charset_list)) != 2) |
8397 |
|
error ("There should be just two charsets"); |
8398 |
|
|
8399 |
|
charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
8400 |
|
if (CHARSET_DIMENSION (charset) != 1) |
8401 |
|
error ("Dimension of charset %s is not one", |
8402 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8403 |
|
if (CHARSET_ASCII_COMPATIBLE_P (charset)) |
8404 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8405 |
|
|
8406 |
|
charset_list = XCDR (charset_list); |
8407 |
|
charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
8408 |
|
if (CHARSET_DIMENSION (charset) != 2) |
8409 |
|
error ("Dimension of charset %s is not two", |
8410 |
|
SDATA (SYMBOL_NAME (CHARSET_NAME (charset)))); |
8411 |
|
|
8412 |
|
category = coding_category_big5; |
8413 |
|
Vbig5_coding_system = name; |
8414 |
|
} |
8415 |
|
else if (EQ (coding_type, Qraw_text)) |
8416 |
|
{ |
8417 |
|
category = coding_category_raw_text; |
8418 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8419 |
|
} |
8420 |
|
else if (EQ (coding_type, Qutf_8)) |
8421 |
|
{ |
8422 |
|
category = coding_category_utf_8; |
8423 |
|
CODING_ATTR_ASCII_COMPAT (attrs) = Qt; |
8424 |
|
} |
8425 |
|
else if (EQ (coding_type, Qundecided)) |
8426 |
|
category = coding_category_undecided; |
8427 |
|
else |
8428 |
|
error ("Invalid coding system type: %s", |
8429 |
|
SDATA (SYMBOL_NAME (coding_type))); |
8430 |
|
|
8431 |
|
CODING_ATTR_CATEGORY (attrs) = make_number (category); |
8432 |
|
CODING_ATTR_PLIST (attrs) |
8433 |
|
= Fcons (QCcategory, Fcons (AREF (Vcoding_category_table, category), |
8434 |
|
CODING_ATTR_PLIST (attrs))); |
8435 |
|
|
8436 |
|
eol_type = args[coding_arg_eol_type]; |
8437 |
|
if (! NILP (eol_type) |
8438 |
|
&& ! EQ (eol_type, Qunix) |
8439 |
|
&& ! EQ (eol_type, Qdos) |
8440 |
|
&& ! EQ (eol_type, Qmac)) |
8441 |
|
error ("Invalid eol-type"); |
8442 |
|
|
8443 |
|
aliases = Fcons (name, Qnil); |
8444 |
|
|
8445 |
|
if (NILP (eol_type)) |
8446 |
|
{ |
8447 |
|
eol_type = make_subsidiaries (name); |
8448 |
|
for (i = 0; i < 3; i++) |
8449 |
|
{ |
8450 |
|
Lisp_Object this_spec, this_name, this_aliases, this_eol_type; |
8451 |
|
|
8452 |
|
this_name = AREF (eol_type, i); |
8453 |
|
this_aliases = Fcons (this_name, Qnil); |
8454 |
|
this_eol_type = (i == 0 ? Qunix : i == 1 ? Qdos : Qmac); |
8455 |
|
this_spec = Fmake_vector (make_number (3), attrs); |
8456 |
|
ASET (this_spec, 1, this_aliases); |
8457 |
|
ASET (this_spec, 2, this_eol_type); |
8458 |
|
Fputhash (this_name, this_spec, Vcoding_system_hash_table); |
8459 |
|
Vcoding_system_list = Fcons (this_name, Vcoding_system_list); |
8460 |
|
Vcoding_system_alist = Fcons (Fcons (Fsymbol_name (this_name), Qnil), |
8461 |
|
Vcoding_system_alist); |
8462 |
|
} |
8463 |
} |
} |
8464 |
|
|
8465 |
|
spec_vec = Fmake_vector (make_number (3), attrs); |
8466 |
|
ASET (spec_vec, 1, aliases); |
8467 |
|
ASET (spec_vec, 2, eol_type); |
8468 |
|
|
8469 |
|
Fputhash (name, spec_vec, Vcoding_system_hash_table); |
8470 |
|
Vcoding_system_list = Fcons (name, Vcoding_system_list); |
8471 |
|
Vcoding_system_alist = Fcons (Fcons (Fsymbol_name (name), Qnil), |
8472 |
|
Vcoding_system_alist); |
8473 |
|
|
8474 |
|
{ |
8475 |
|
int id = coding_categories[category].id; |
8476 |
|
|
8477 |
|
if (id < 0 || EQ (name, CODING_ID_NAME (id))) |
8478 |
|
setup_coding_system (name, &coding_categories[category]); |
8479 |
|
} |
8480 |
|
|
8481 |
return Qnil; |
return Qnil; |
8482 |
|
|
8483 |
|
short_args: |
8484 |
|
return Fsignal (Qwrong_number_of_arguments, |
8485 |
|
Fcons (intern ("define-coding-system-internal"), |
8486 |
|
make_number (nargs))); |
8487 |
|
} |
8488 |
|
|
8489 |
|
/* Fixme: should this record the alias relationships for |
8490 |
|
diagnostics? Should it update coding-system-list? */ |
8491 |
|
DEFUN ("define-coding-system-alias", Fdefine_coding_system_alias, |
8492 |
|
Sdefine_coding_system_alias, 2, 2, 0, |
8493 |
|
doc: /* Define ALIAS as an alias for CODING-SYSTEM. */) |
8494 |
|
(alias, coding_system) |
8495 |
|
Lisp_Object alias, coding_system; |
8496 |
|
{ |
8497 |
|
Lisp_Object spec, aliases, eol_type; |
8498 |
|
|
8499 |
|
CHECK_SYMBOL (alias); |
8500 |
|
CHECK_CODING_SYSTEM_GET_SPEC (coding_system, spec); |
8501 |
|
aliases = AREF (spec, 1); |
8502 |
|
while (!NILP (XCDR (aliases))) |
8503 |
|
aliases = XCDR (aliases); |
8504 |
|
XSETCDR (aliases, Fcons (alias, Qnil)); |
8505 |
|
|
8506 |
|
eol_type = AREF (spec, 2); |
8507 |
|
if (VECTORP (eol_type)) |
8508 |
|
{ |
8509 |
|
Lisp_Object subsidiaries; |
8510 |
|
int i; |
8511 |
|
|
8512 |
|
subsidiaries = make_subsidiaries (alias); |
8513 |
|
for (i = 0; i < 3; i++) |
8514 |
|
Fdefine_coding_system_alias (AREF (subsidiaries, i), |
8515 |
|
AREF (eol_type, i)); |
8516 |
|
|
8517 |
|
ASET (spec, 2, subsidiaries); |
8518 |
|
} |
8519 |
|
|
8520 |
|
Fputhash (alias, spec, Vcoding_system_hash_table); |
8521 |
|
Vcoding_system_alist = Fcons (Fcons (Fsymbol_name (alias), Qnil), |
8522 |
|
Vcoding_system_alist); |
8523 |
|
|
8524 |
|
return Qnil; |
8525 |
|
} |
8526 |
|
|
8527 |
|
DEFUN ("coding-system-base", Fcoding_system_base, Scoding_system_base, |
8528 |
|
1, 1, 0, |
8529 |
|
doc: /* Return the base of CODING-SYSTEM. |
8530 |
|
Any alias or subsidiary coding system is not a base coding system. */) |
8531 |
|
(coding_system) |
8532 |
|
Lisp_Object coding_system; |
8533 |
|
{ |
8534 |
|
Lisp_Object spec, attrs; |
8535 |
|
|
8536 |
|
if (NILP (coding_system)) |
8537 |
|
return (Qno_conversion); |
8538 |
|
CHECK_CODING_SYSTEM_GET_SPEC (coding_system, spec); |
8539 |
|
attrs = AREF (spec, 0); |
8540 |
|
return CODING_ATTR_BASE_NAME (attrs); |
8541 |
|
} |
8542 |
|
|
8543 |
|
DEFUN ("coding-system-plist", Fcoding_system_plist, Scoding_system_plist, |
8544 |
|
1, 1, 0, |
8545 |
|
doc: "Return the property list of CODING-SYSTEM.") |
8546 |
|
(coding_system) |
8547 |
|
Lisp_Object coding_system; |
8548 |
|
{ |
8549 |
|
Lisp_Object spec, attrs; |
8550 |
|
|
8551 |
|
if (NILP (coding_system)) |
8552 |
|
coding_system = Qno_conversion; |
8553 |
|
CHECK_CODING_SYSTEM_GET_SPEC (coding_system, spec); |
8554 |
|
attrs = AREF (spec, 0); |
8555 |
|
return CODING_ATTR_PLIST (attrs); |
8556 |
|
} |
8557 |
|
|
8558 |
|
|
8559 |
|
DEFUN ("coding-system-aliases", Fcoding_system_aliases, Scoding_system_aliases, |
8560 |
|
1, 1, 0, |
8561 |
|
doc: /* Return the list of aliases of CODING-SYSTEM. */) |
8562 |
|
(coding_system) |
8563 |
|
Lisp_Object coding_system; |
8564 |
|
{ |
8565 |
|
Lisp_Object spec; |
8566 |
|
|
8567 |
|
if (NILP (coding_system)) |
8568 |
|
coding_system = Qno_conversion; |
8569 |
|
CHECK_CODING_SYSTEM_GET_SPEC (coding_system, spec); |
8570 |
|
return AREF (spec, 1); |
8571 |
|
} |
8572 |
|
|
8573 |
|
DEFUN ("coding-system-eol-type", Fcoding_system_eol_type, |
8574 |
|
Scoding_system_eol_type, 1, 1, 0, |
8575 |
|
doc: /* Return eol-type of CODING-SYSTEM. |
8576 |
|
An eol-type is integer 0, 1, 2, or a vector of coding systems. |
8577 |
|
|
8578 |
|
Integer values 0, 1, and 2 indicate a format of end-of-line; LF, CRLF, |
8579 |
|
and CR respectively. |
8580 |
|
|
8581 |
|
A vector value indicates that a format of end-of-line should be |
8582 |
|
detected automatically. Nth element of the vector is the subsidiary |
8583 |
|
coding system whose eol-type is N. */) |
8584 |
|
(coding_system) |
8585 |
|
Lisp_Object coding_system; |
8586 |
|
{ |
8587 |
|
Lisp_Object spec, eol_type; |
8588 |
|
int n; |
8589 |
|
|
8590 |
|
if (NILP (coding_system)) |
8591 |
|
coding_system = Qno_conversion; |
8592 |
|
if (! CODING_SYSTEM_P (coding_system)) |
8593 |
|
return Qnil; |
8594 |
|
spec = CODING_SYSTEM_SPEC (coding_system); |
8595 |
|
eol_type = AREF (spec, 2); |
8596 |
|
if (VECTORP (eol_type)) |
8597 |
|
return Fcopy_sequence (eol_type); |
8598 |
|
n = EQ (eol_type, Qunix) ? 0 : EQ (eol_type, Qdos) ? 1 : 2; |
8599 |
|
return make_number (n); |
8600 |
} |
} |
8601 |
|
|
8602 |
#endif /* emacs */ |
#endif /* emacs */ |
8609 |
{ |
{ |
8610 |
int i; |
int i; |
8611 |
|
|
8612 |
/* Emacs' internal format specific initialize routine. */ |
for (i = 0; i < coding_category_max; i++) |
8613 |
for (i = 0; i <= 0x20; i++) |
{ |
8614 |
emacs_code_class[i] = EMACS_control_code; |
coding_categories[i].id = -1; |
8615 |
emacs_code_class[0x0A] = EMACS_linefeed_code; |
coding_priorities[i] = i; |
8616 |
emacs_code_class[0x0D] = EMACS_carriage_return_code; |
} |
|
for (i = 0x21 ; i < 0x7F; i++) |
|
|
emacs_code_class[i] = EMACS_ascii_code; |
|
|
emacs_code_class[0x7F] = EMACS_control_code; |
|
|
for (i = 0x80; i < 0xFF; i++) |
|
|
emacs_code_class[i] = EMACS_invalid_code; |
|
|
emacs_code_class[LEADING_CODE_PRIVATE_11] = EMACS_leading_code_3; |
|
|
emacs_code_class[LEADING_CODE_PRIVATE_12] = EMACS_leading_code_3; |
|
|
emacs_code_class[LEADING_CODE_PRIVATE_21] = EMACS_leading_code_4; |
|
|
emacs_code_class[LEADING_CODE_PRIVATE_22] = EMACS_leading_code_4; |
|
8617 |
|
|
8618 |
/* ISO2022 specific initialize routine. */ |
/* ISO2022 specific initialize routine. */ |
8619 |
for (i = 0; i < 0x20; i++) |
for (i = 0; i < 0x20; i++) |
8635 |
iso_code_class[ISO_CODE_SS3] = ISO_single_shift_3; |
iso_code_class[ISO_CODE_SS3] = ISO_single_shift_3; |
8636 |
iso_code_class[ISO_CODE_CSI] = ISO_control_sequence_introducer; |
iso_code_class[ISO_CODE_CSI] = ISO_control_sequence_introducer; |
8637 |
|
|
|
setup_coding_system (Qnil, &keyboard_coding); |
|
|
setup_coding_system (Qnil, &terminal_coding); |
|
|
setup_coding_system (Qnil, &safe_terminal_coding); |
|
|
setup_coding_system (Qnil, &default_buffer_file_coding); |
|
|
|
|
|
bzero (coding_system_table, sizeof coding_system_table); |
|
|
|
|
|
bzero (ascii_skip_code, sizeof ascii_skip_code); |
|
|
for (i = 0; i < 128; i++) |
|
|
ascii_skip_code[i] = 1; |
|
|
|
|
|
#if defined (MSDOS) || defined (WINDOWSNT) |
|
|
system_eol_type = CODING_EOL_CRLF; |
|
|
#else |
|
|
system_eol_type = CODING_EOL_LF; |
|
|
#endif |
|
|
|
|
8638 |
inhibit_pre_post_conversion = 0; |
inhibit_pre_post_conversion = 0; |
8639 |
|
|
8640 |
|
for (i = 0; i < 256; i++) |
8641 |
|
{ |
8642 |
|
emacs_mule_bytes[i] = 1; |
8643 |
|
} |
8644 |
|
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_11] = 3; |
8645 |
|
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_12] = 3; |
8646 |
|
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_21] = 4; |
8647 |
|
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_22] = 4; |
8648 |
} |
} |
8649 |
|
|
8650 |
#ifdef emacs |
#ifdef emacs |
8652 |
void |
void |
8653 |
syms_of_coding () |
syms_of_coding () |
8654 |
{ |
{ |
8655 |
Qtarget_idx = intern ("target-idx"); |
staticpro (&Vcoding_system_hash_table); |
8656 |
staticpro (&Qtarget_idx); |
{ |
8657 |
|
Lisp_Object args[2]; |
8658 |
|
args[0] = QCtest; |
8659 |
|
args[1] = Qeq; |
8660 |
|
Vcoding_system_hash_table = Fmake_hash_table (2, args); |
8661 |
|
} |
8662 |
|
|
8663 |
|
staticpro (&Vsjis_coding_system); |
8664 |
|
Vsjis_coding_system = Qnil; |
8665 |
|
|
8666 |
Qcoding_system_history = intern ("coding-system-history"); |
staticpro (&Vbig5_coding_system); |
8667 |
staticpro (&Qcoding_system_history); |
Vbig5_coding_system = Qnil; |
8668 |
|
|
8669 |
|
staticpro (&Vcode_conversion_work_buf_list); |
8670 |
|
Vcode_conversion_work_buf_list = Qnil; |
8671 |
|
|
8672 |
|
staticpro (&Vcode_conversion_reused_work_buf); |
8673 |
|
Vcode_conversion_reused_work_buf = Qnil; |
8674 |
|
|
8675 |
|
DEFSYM (Qcharset, "charset"); |
8676 |
|
DEFSYM (Qtarget_idx, "target-idx"); |
8677 |
|
DEFSYM (Qcoding_system_history, "coding-system-history"); |
8678 |
Fset (Qcoding_system_history, Qnil); |
Fset (Qcoding_system_history, Qnil); |
8679 |
|
|
8680 |
/* Target FILENAME is the first argument. */ |
/* Target FILENAME is the first argument. */ |
8682 |
/* Target FILENAME is the third argument. */ |
/* Target FILENAME is the third argument. */ |
8683 |
Fput (Qwrite_region, Qtarget_idx, make_number (2)); |
Fput (Qwrite_region, Qtarget_idx, make_number (2)); |
8684 |
|
|
8685 |
Qcall_process = intern ("call-process"); |
DEFSYM (Qcall_process, "call-process"); |
|
staticpro (&Qcall_process); |
|
8686 |
/* Target PROGRAM is the first argument. */ |
/* Target PROGRAM is the first argument. */ |
8687 |
Fput (Qcall_process, Qtarget_idx, make_number (0)); |
Fput (Qcall_process, Qtarget_idx, make_number (0)); |
8688 |
|
|
8689 |
Qcall_process_region = intern ("call-process-region"); |
DEFSYM (Qcall_process_region, "call-process-region"); |
|
staticpro (&Qcall_process_region); |
|
8690 |
/* Target PROGRAM is the third argument. */ |
/* Target PROGRAM is the third argument. */ |
8691 |
Fput (Qcall_process_region, Qtarget_idx, make_number (2)); |
Fput (Qcall_process_region, Qtarget_idx, make_number (2)); |
8692 |
|
|
8693 |
Qstart_process = intern ("start-process"); |
DEFSYM (Qstart_process, "start-process"); |
|
staticpro (&Qstart_process); |
|
8694 |
/* Target PROGRAM is the third argument. */ |
/* Target PROGRAM is the third argument. */ |
8695 |
Fput (Qstart_process, Qtarget_idx, make_number (2)); |
Fput (Qstart_process, Qtarget_idx, make_number (2)); |
8696 |
|
|
8697 |
Qopen_network_stream = intern ("open-network-stream"); |
DEFSYM (Qopen_network_stream, "open-network-stream"); |
|
staticpro (&Qopen_network_stream); |
|
8698 |
/* Target SERVICE is the fourth argument. */ |
/* Target SERVICE is the fourth argument. */ |
8699 |
Fput (Qopen_network_stream, Qtarget_idx, make_number (3)); |
Fput (Qopen_network_stream, Qtarget_idx, make_number (3)); |
8700 |
|
|
8701 |
Qcoding_system = intern ("coding-system"); |
DEFSYM (Qcoding_system, "coding-system"); |
8702 |
staticpro (&Qcoding_system); |
DEFSYM (Qcoding_aliases, "coding-aliases"); |
8703 |
|
|
8704 |
Qeol_type = intern ("eol-type"); |
DEFSYM (Qeol_type, "eol-type"); |
8705 |
staticpro (&Qeol_type); |
DEFSYM (Qunix, "unix"); |
8706 |
|
DEFSYM (Qdos, "dos"); |
8707 |
|
|
8708 |
Qbuffer_file_coding_system = intern ("buffer-file-coding-system"); |
DEFSYM (Qbuffer_file_coding_system, "buffer-file-coding-system"); |
8709 |
staticpro (&Qbuffer_file_coding_system); |
DEFSYM (Qpost_read_conversion, "post-read-conversion"); |
8710 |
|
DEFSYM (Qpre_write_conversion, "pre-write-conversion"); |
8711 |
|
DEFSYM (Qdefault_char, "default-char"); |
8712 |
|
DEFSYM (Qundecided, "undecided"); |
8713 |
|
DEFSYM (Qno_conversion, "no-conversion"); |
8714 |
|
DEFSYM (Qraw_text, "raw-text"); |
8715 |
|
|
8716 |
Qpost_read_conversion = intern ("post-read-conversion"); |
DEFSYM (Qiso_2022, "iso-2022"); |
|
staticpro (&Qpost_read_conversion); |
|
8717 |
|
|
8718 |
Qpre_write_conversion = intern ("pre-write-conversion"); |
DEFSYM (Qutf_8, "utf-8"); |
8719 |
staticpro (&Qpre_write_conversion); |
DEFSYM (Qutf_8_emacs, "utf-8-emacs"); |
8720 |
|
|
8721 |
Qno_conversion = intern ("no-conversion"); |
DEFSYM (Qutf_16, "utf-16"); |
8722 |
staticpro (&Qno_conversion); |
DEFSYM (Qbig, "big"); |
8723 |
|
DEFSYM (Qlittle, "little"); |
8724 |
|
|
8725 |
Qundecided = intern ("undecided"); |
DEFSYM (Qshift_jis, "shift-jis"); |
8726 |
staticpro (&Qundecided); |
DEFSYM (Qbig5, "big5"); |
8727 |
|
|
8728 |
Qcoding_system_p = intern ("coding-system-p"); |
DEFSYM (Qcoding_system_p, "coding-system-p"); |
|
staticpro (&Qcoding_system_p); |
|
|
|
|
|
Qcoding_system_error = intern ("coding-system-error"); |
|
|
staticpro (&Qcoding_system_error); |
|
8729 |
|
|
8730 |
|
DEFSYM (Qcoding_system_error, "coding-system-error"); |
8731 |
Fput (Qcoding_system_error, Qerror_conditions, |
Fput (Qcoding_system_error, Qerror_conditions, |
8732 |
Fcons (Qcoding_system_error, Fcons (Qerror, Qnil))); |
Fcons (Qcoding_system_error, Fcons (Qerror, Qnil))); |
8733 |
Fput (Qcoding_system_error, Qerror_message, |
Fput (Qcoding_system_error, Qerror_message, |
8734 |
build_string ("Invalid coding system")); |
build_string ("Invalid coding system")); |
8735 |
|
|
|
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++) |
|
|
{ |
|
|
XVECTOR (Vcoding_category_table)->contents[i] |
|
|
= intern (coding_category_name[i]); |
|
|
Fput (XVECTOR (Vcoding_category_table)->contents[i], |
|
|
Qcoding_category_index, make_number (i)); |
|
|
} |
|
|
} |
|
|
|
|
|
Vcoding_system_safe_chars = Fcons (Qnil, Qnil); |
|
|
staticpro (&Vcoding_system_safe_chars); |
|
|
|
|
|
Qtranslation_table = intern ("translation-table"); |
|
|
staticpro (&Qtranslation_table); |
|
|
Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (2)); |
|
|
|
|
|
Qtranslation_table_id = intern ("translation-table-id"); |
|
|
staticpro (&Qtranslation_table_id); |
|
|
|
|
|
Qtranslation_table_for_decode = intern ("translation-table-for-decode"); |
|
|
staticpro (&Qtranslation_table_for_decode); |
|
|
|
|
|
Qtranslation_table_for_encode = intern ("translation-table-for-encode"); |
|
|
staticpro (&Qtranslation_table_for_encode); |
|
|
|
|
|
Qsafe_chars = intern ("safe-chars"); |
|
|
staticpro (&Qsafe_chars); |
|
|
|
|
|
Qchar_coding_system = intern ("char-coding-system"); |
|
|
staticpro (&Qchar_coding_system); |
|
|
|
|
8736 |
/* Intern this now in case it isn't already done. |
/* Intern this now in case it isn't already done. |
8737 |
Setting this variable twice is harmless. |
Setting this variable twice is harmless. |
8738 |
But don't staticpro it here--that is done in alloc.c. */ |
But don't staticpro it here--that is done in alloc.c. */ |
8739 |
Qchar_table_extra_slots = intern ("char-table-extra-slots"); |
Qchar_table_extra_slots = intern ("char-table-extra-slots"); |
|
Fput (Qsafe_chars, Qchar_table_extra_slots, make_number (0)); |
|
|
Fput (Qchar_coding_system, Qchar_table_extra_slots, make_number (0)); |
|
8740 |
|
|
8741 |
Qvalid_codes = intern ("valid-codes"); |
DEFSYM (Qtranslation_table, "translation-table"); |
8742 |
staticpro (&Qvalid_codes); |
Fput (Qtranslation_table, Qchar_table_extra_slots, make_number (1)); |
8743 |
|
DEFSYM (Qtranslation_table_id, "translation-table-id"); |
8744 |
|
DEFSYM (Qtranslation_table_for_decode, "translation-table-for-decode"); |
8745 |
|
DEFSYM (Qtranslation_table_for_encode, "translation-table-for-encode"); |
8746 |
|
|
8747 |
Qemacs_mule = intern ("emacs-mule"); |
DEFSYM (Qvalid_codes, "valid-codes"); |
|
staticpro (&Qemacs_mule); |
|
8748 |
|
|
8749 |
Qraw_text = intern ("raw-text"); |
DEFSYM (Qemacs_mule, "emacs-mule"); |
|
staticpro (&Qraw_text); |
|
8750 |
|
|
8751 |
Qutf_8 = intern ("utf-8"); |
DEFSYM (QCcategory, ":category"); |
8752 |
staticpro (&Qutf_8); |
|
8753 |
|
Vcoding_category_table |
8754 |
|
= Fmake_vector (make_number (coding_category_max), Qnil); |
8755 |
|
staticpro (&Vcoding_category_table); |
8756 |
|
/* Followings are target of code detection. */ |
8757 |
|
ASET (Vcoding_category_table, coding_category_iso_7, |
8758 |
|
intern ("coding-category-iso-7")); |
8759 |
|
ASET (Vcoding_category_table, coding_category_iso_7_tight, |
8760 |
|
intern ("coding-category-iso-7-tight")); |
8761 |
|
ASET (Vcoding_category_table, coding_category_iso_8_1, |
8762 |
|
intern ("coding-category-iso-8-1")); |
8763 |
|
ASET (Vcoding_category_table, coding_category_iso_8_2, |
8764 |
|
intern ("coding-category-iso-8-2")); |
8765 |
|
ASET (Vcoding_category_table, coding_category_iso_7_else, |
8766 |
|
intern ("coding-category-iso-7-else")); |
8767 |
|
ASET (Vcoding_category_table, coding_category_iso_8_else, |
8768 |
|
intern ("coding-category-iso-8-else")); |
8769 |
|
ASET (Vcoding_category_table, coding_category_utf_8, |
8770 |
|
intern ("coding-category-utf-8")); |
8771 |
|
ASET (Vcoding_category_table, coding_category_utf_16_be, |
8772 |
|
intern ("coding-category-utf-16-be")); |
8773 |
|
ASET (Vcoding_category_table, coding_category_utf_16_auto, |
8774 |
|
intern ("coding-category-utf-16-auto")); |
8775 |
|
ASET (Vcoding_category_table, coding_category_utf_16_le, |
8776 |
|
intern ("coding-category-utf-16-le")); |
8777 |
|
ASET (Vcoding_category_table, coding_category_utf_16_be_nosig, |
8778 |
|
intern ("coding-category-utf-16-be-nosig")); |
8779 |
|
ASET (Vcoding_category_table, coding_category_utf_16_le_nosig, |
8780 |
|
intern ("coding-category-utf-16-le-nosig")); |
8781 |
|
ASET (Vcoding_category_table, coding_category_charset, |
8782 |
|
intern ("coding-category-charset")); |
8783 |
|
ASET (Vcoding_category_table, coding_category_sjis, |
8784 |
|
intern ("coding-category-sjis")); |
8785 |
|
ASET (Vcoding_category_table, coding_category_big5, |
8786 |
|
intern ("coding-category-big5")); |
8787 |
|
ASET (Vcoding_category_table, coding_category_ccl, |
8788 |
|
intern ("coding-category-ccl")); |
8789 |
|
ASET (Vcoding_category_table, coding_category_emacs_mule, |
8790 |
|
intern ("coding-category-emacs-mule")); |
8791 |
|
/* Followings are NOT target of code detection. */ |
8792 |
|
ASET (Vcoding_category_table, coding_category_raw_text, |
8793 |
|
intern ("coding-category-raw-text")); |
8794 |
|
ASET (Vcoding_category_table, coding_category_undecided, |
8795 |
|
intern ("coding-category-undecided")); |
8796 |
|
|
8797 |
defsubr (&Scoding_system_p); |
defsubr (&Scoding_system_p); |
8798 |
defsubr (&Sread_coding_system); |
defsubr (&Sread_coding_system); |
8802 |
defsubr (&Sdetect_coding_string); |
defsubr (&Sdetect_coding_string); |
8803 |
defsubr (&Sfind_coding_systems_region_internal); |
defsubr (&Sfind_coding_systems_region_internal); |
8804 |
defsubr (&Sunencodable_char_position); |
defsubr (&Sunencodable_char_position); |
8805 |
|
defsubr (&Scheck_coding_systems_region); |
8806 |
defsubr (&Sdecode_coding_region); |
defsubr (&Sdecode_coding_region); |
8807 |
defsubr (&Sencode_coding_region); |
defsubr (&Sencode_coding_region); |
8808 |
defsubr (&Sdecode_coding_string); |
defsubr (&Sdecode_coding_string); |
8817 |
defsubr (&Sset_keyboard_coding_system_internal); |
defsubr (&Sset_keyboard_coding_system_internal); |
8818 |
defsubr (&Skeyboard_coding_system); |
defsubr (&Skeyboard_coding_system); |
8819 |
defsubr (&Sfind_operation_coding_system); |
defsubr (&Sfind_operation_coding_system); |
8820 |
defsubr (&Supdate_coding_systems_internal); |
defsubr (&Sset_coding_system_priority); |
|
defsubr (&Sset_coding_priority_internal); |
|
8821 |
defsubr (&Sdefine_coding_system_internal); |
defsubr (&Sdefine_coding_system_internal); |
8822 |
|
defsubr (&Sdefine_coding_system_alias); |
8823 |
|
defsubr (&Scoding_system_base); |
8824 |
|
defsubr (&Scoding_system_plist); |
8825 |
|
defsubr (&Scoding_system_aliases); |
8826 |
|
defsubr (&Scoding_system_eol_type); |
8827 |
|
defsubr (&Scoding_system_priority_list); |
8828 |
|
|
8829 |
DEFVAR_LISP ("coding-system-list", &Vcoding_system_list, |
DEFVAR_LISP ("coding-system-list", &Vcoding_system_list, |
8830 |
doc: /* List of coding systems. |
doc: /* List of coding systems. |
8831 |
|
|
8832 |
Do not alter the value of this variable manually. This variable should be |
Do not alter the value of this variable manually. This variable should be |
8833 |
updated by the functions `make-coding-system' and |
updated by the functions `define-coding-system' and |
8834 |
`define-coding-system-alias'. */); |
`define-coding-system-alias'. */); |
8835 |
Vcoding_system_list = Qnil; |
Vcoding_system_list = Qnil; |
8836 |
|
|
8855 |
int i; |
int i; |
8856 |
|
|
8857 |
Vcoding_category_list = Qnil; |
Vcoding_category_list = Qnil; |
8858 |
for (i = CODING_CATEGORY_IDX_MAX - 1; i >= 0; i--) |
for (i = coding_category_max - 1; i >= 0; i--) |
8859 |
Vcoding_category_list |
Vcoding_category_list |
8860 |
= Fcons (XVECTOR (Vcoding_category_table)->contents[i], |
= Fcons (XVECTOR (Vcoding_category_table)->contents[i], |
8861 |
Vcoding_category_list); |
Vcoding_category_list); |
8885 |
Vcoding_system_for_write = Qnil; |
Vcoding_system_for_write = Qnil; |
8886 |
|
|
8887 |
DEFVAR_LISP ("last-coding-system-used", &Vlast_coding_system_used, |
DEFVAR_LISP ("last-coding-system-used", &Vlast_coding_system_used, |
8888 |
doc: /* Coding system used in the latest file or process I/O. |
doc: /* |
8889 |
Also set by `encode-coding-region', `decode-coding-region', |
Coding system used in the latest file or process I/O. */); |
|
`encode-coding-string' and `decode-coding-string'. */); |
|
8890 |
Vlast_coding_system_used = Qnil; |
Vlast_coding_system_used = Qnil; |
8891 |
|
|
8892 |
DEFVAR_BOOL ("inhibit-eol-conversion", &inhibit_eol_conversion, |
DEFVAR_BOOL ("inhibit-eol-conversion", &inhibit_eol_conversion, |
8893 |
doc: /* *Non-nil means always inhibit code conversion of end-of-line format. |
doc: /* |
8894 |
|
*Non-nil means always inhibit code conversion of end-of-line format. |
8895 |
See info node `Coding Systems' and info node `Text and Binary' concerning |
See info node `Coding Systems' and info node `Text and Binary' concerning |
8896 |
such conversion. */); |
such conversion. */); |
8897 |
inhibit_eol_conversion = 0; |
inhibit_eol_conversion = 0; |
8898 |
|
|
8899 |
DEFVAR_BOOL ("inherit-process-coding-system", &inherit_process_coding_system, |
DEFVAR_BOOL ("inherit-process-coding-system", &inherit_process_coding_system, |
8900 |
doc: /* Non-nil means process buffer inherits coding system of process output. |
doc: /* |
8901 |
|
Non-nil means process buffer inherits coding system of process output. |
8902 |
Bind it to t if the process output is to be treated as if it were a file |
Bind it to t if the process output is to be treated as if it were a file |
8903 |
read from some filesystem. */); |
read from some filesystem. */); |
8904 |
inherit_process_coding_system = 0; |
inherit_process_coding_system = 0; |
8905 |
|
|
8906 |
DEFVAR_LISP ("file-coding-system-alist", &Vfile_coding_system_alist, |
DEFVAR_LISP ("file-coding-system-alist", &Vfile_coding_system_alist, |
8907 |
doc: /* Alist to decide a coding system to use for a file I/O operation. |
doc: /* |
8908 |
|
Alist to decide a coding system to use for a file I/O operation. |
8909 |
The format is ((PATTERN . VAL) ...), |
The format is ((PATTERN . VAL) ...), |
8910 |
where PATTERN is a regular expression matching a file name, |
where PATTERN is a regular expression matching a file name, |
8911 |
VAL is a coding system, a cons of coding systems, or a function symbol. |
VAL is a coding system, a cons of coding systems, or a function symbol. |
8915 |
and the cdr part is used for encoding. |
and the cdr part is used for encoding. |
8916 |
If VAL is a function symbol, the function must return a coding system |
If VAL is a function symbol, the function must return a coding system |
8917 |
or a cons of coding systems which are used as above. The function gets |
or a cons of coding systems which are used as above. The function gets |
8918 |
the arguments with which `find-operation-coding-system' was called. |
the arguments with which `find-operation-coding-systems' was called. |
8919 |
|
|
8920 |
See also the function `find-operation-coding-system' |
See also the function `find-operation-coding-system' |
8921 |
and the variable `auto-coding-alist'. */); |
and the variable `auto-coding-alist'. */); |
8922 |
Vfile_coding_system_alist = Qnil; |
Vfile_coding_system_alist = Qnil; |
8923 |
|
|
8924 |
DEFVAR_LISP ("process-coding-system-alist", &Vprocess_coding_system_alist, |
DEFVAR_LISP ("process-coding-system-alist", &Vprocess_coding_system_alist, |
8925 |
doc: /* Alist to decide a coding system to use for a process I/O operation. |
doc: /* |
8926 |
|
Alist to decide a coding system to use for a process I/O operation. |
8927 |
The format is ((PATTERN . VAL) ...), |
The format is ((PATTERN . VAL) ...), |
8928 |
where PATTERN is a regular expression matching a program name, |
where PATTERN is a regular expression matching a program name, |
8929 |
VAL is a coding system, a cons of coding systems, or a function symbol. |
VAL is a coding system, a cons of coding systems, or a function symbol. |
8938 |
Vprocess_coding_system_alist = Qnil; |
Vprocess_coding_system_alist = Qnil; |
8939 |
|
|
8940 |
DEFVAR_LISP ("network-coding-system-alist", &Vnetwork_coding_system_alist, |
DEFVAR_LISP ("network-coding-system-alist", &Vnetwork_coding_system_alist, |
8941 |
doc: /* Alist to decide a coding system to use for a network I/O operation. |
doc: /* |
8942 |
|
Alist to decide a coding system to use for a network I/O operation. |
8943 |
The format is ((PATTERN . VAL) ...), |
The format is ((PATTERN . VAL) ...), |
8944 |
where PATTERN is a regular expression matching a network service name |
where PATTERN is a regular expression matching a network service name |
8945 |
or is a port number to connect to, |
or is a port number to connect to, |
8961 |
|
|
8962 |
/* The eol mnemonics are reset in startup.el system-dependently. */ |
/* The eol mnemonics are reset in startup.el system-dependently. */ |
8963 |
DEFVAR_LISP ("eol-mnemonic-unix", &eol_mnemonic_unix, |
DEFVAR_LISP ("eol-mnemonic-unix", &eol_mnemonic_unix, |
8964 |
doc: /* *String displayed in mode line for UNIX-like (LF) end-of-line format. */); |
doc: /* |
8965 |
|
*String displayed in mode line for UNIX-like (LF) end-of-line format. */); |
8966 |
eol_mnemonic_unix = build_string (":"); |
eol_mnemonic_unix = build_string (":"); |
8967 |
|
|
8968 |
DEFVAR_LISP ("eol-mnemonic-dos", &eol_mnemonic_dos, |
DEFVAR_LISP ("eol-mnemonic-dos", &eol_mnemonic_dos, |
8969 |
doc: /* *String displayed in mode line for DOS-like (CRLF) end-of-line format. */); |
doc: /* |
8970 |
|
*String displayed in mode line for DOS-like (CRLF) end-of-line format. */); |
8971 |
eol_mnemonic_dos = build_string ("\\"); |
eol_mnemonic_dos = build_string ("\\"); |
8972 |
|
|
8973 |
DEFVAR_LISP ("eol-mnemonic-mac", &eol_mnemonic_mac, |
DEFVAR_LISP ("eol-mnemonic-mac", &eol_mnemonic_mac, |
8974 |
doc: /* *String displayed in mode line for MAC-like (CR) end-of-line format. */); |
doc: /* |
8975 |
|
*String displayed in mode line for MAC-like (CR) end-of-line format. */); |
8976 |
eol_mnemonic_mac = build_string ("/"); |
eol_mnemonic_mac = build_string ("/"); |
8977 |
|
|
8978 |
DEFVAR_LISP ("eol-mnemonic-undecided", &eol_mnemonic_undecided, |
DEFVAR_LISP ("eol-mnemonic-undecided", &eol_mnemonic_undecided, |
8979 |
doc: /* *String displayed in mode line when end-of-line format is not yet determined. */); |
doc: /* |
8980 |
|
*String displayed in mode line when end-of-line format is not yet determined. */); |
8981 |
eol_mnemonic_undecided = build_string (":"); |
eol_mnemonic_undecided = build_string (":"); |
8982 |
|
|
8983 |
DEFVAR_LISP ("enable-character-translation", &Venable_character_translation, |
DEFVAR_LISP ("enable-character-translation", &Venable_character_translation, |
8984 |
doc: /* *Non-nil enables character translation while encoding and decoding. */); |
doc: /* |
8985 |
|
*Non-nil enables character translation while encoding and decoding. */); |
8986 |
Venable_character_translation = Qt; |
Venable_character_translation = Qt; |
8987 |
|
|
8988 |
DEFVAR_LISP ("standard-translation-table-for-decode", |
DEFVAR_LISP ("standard-translation-table-for-decode", |
8995 |
doc: /* Table for translating characters while encoding. */); |
doc: /* Table for translating characters while encoding. */); |
8996 |
Vstandard_translation_table_for_encode = Qnil; |
Vstandard_translation_table_for_encode = Qnil; |
8997 |
|
|
8998 |
DEFVAR_LISP ("charset-revision-table", &Vcharset_revision_alist, |
DEFVAR_LISP ("charset-revision-table", &Vcharset_revision_table, |
8999 |
doc: /* Alist of charsets vs revision numbers. |
doc: /* Alist of charsets vs revision numbers. |
9000 |
While encoding, if a charset (car part of an element) is found, |
While encoding, if a charset (car part of an element) is found, |
9001 |
designate it with the escape sequence identifying revision (cdr part of the element). */); |
designate it with the escape sequence identifying revision (cdr part |
9002 |
Vcharset_revision_alist = Qnil; |
of the element). */); |
9003 |
|
Vcharset_revision_table = Qnil; |
9004 |
|
|
9005 |
DEFVAR_LISP ("default-process-coding-system", |
DEFVAR_LISP ("default-process-coding-system", |
9006 |
&Vdefault_process_coding_system, |
&Vdefault_process_coding_system, |
9010 |
Vdefault_process_coding_system = Qnil; |
Vdefault_process_coding_system = Qnil; |
9011 |
|
|
9012 |
DEFVAR_LISP ("latin-extra-code-table", &Vlatin_extra_code_table, |
DEFVAR_LISP ("latin-extra-code-table", &Vlatin_extra_code_table, |
9013 |
doc: /* Table of extra Latin codes in the range 128..159 (inclusive). |
doc: /* |
9014 |
|
Table of extra Latin codes in the range 128..159 (inclusive). |
9015 |
This is a vector of length 256. |
This is a vector of length 256. |
9016 |
If Nth element is non-nil, the existence of code N in a file |
If Nth element is non-nil, the existence of code N in a file |
9017 |
\(or output of subprocess) doesn't prevent it to be detected as |
\(or output of subprocess) doesn't prevent it to be detected as |
9023 |
|
|
9024 |
DEFVAR_LISP ("select-safe-coding-system-function", |
DEFVAR_LISP ("select-safe-coding-system-function", |
9025 |
&Vselect_safe_coding_system_function, |
&Vselect_safe_coding_system_function, |
9026 |
doc: /* Function to call to select safe coding system for encoding a text. |
doc: /* |
9027 |
|
Function to call to select safe coding system for encoding a text. |
9028 |
|
|
9029 |
If set, this function is called to force a user to select a proper |
If set, this function is called to force a user to select a proper |
9030 |
coding system which can encode the text in the case that a default |
coding system which can encode the text in the case that a default |
9044 |
|
|
9045 |
DEFVAR_BOOL ("inhibit-iso-escape-detection", |
DEFVAR_BOOL ("inhibit-iso-escape-detection", |
9046 |
&inhibit_iso_escape_detection, |
&inhibit_iso_escape_detection, |
9047 |
doc: /* If non-nil, Emacs ignores ISO2022's escape sequence on code detection. |
doc: /* |
9048 |
|
If non-nil, Emacs ignores ISO2022's escape sequence on code detection. |
9049 |
|
|
9050 |
By default, on reading a file, Emacs tries to detect how the text is |
By default, on reading a file, Emacs tries to detect how the text is |
9051 |
encoded. This code detection is sensitive to escape sequences. If |
encoded. This code detection is sensitive to escape sequences. If |
9075 |
This is applied to the result of input methods, not their input. See also |
This is applied to the result of input methods, not their input. See also |
9076 |
`keyboard-translate-table'. */); |
`keyboard-translate-table'. */); |
9077 |
Vtranslation_table_for_input = Qnil; |
Vtranslation_table_for_input = Qnil; |
9078 |
|
|
9079 |
|
{ |
9080 |
|
Lisp_Object args[coding_arg_max]; |
9081 |
|
Lisp_Object plist[16]; |
9082 |
|
int i; |
9083 |
|
|
9084 |
|
for (i = 0; i < coding_arg_max; i++) |
9085 |
|
args[i] = Qnil; |
9086 |
|
|
9087 |
|
plist[0] = intern (":name"); |
9088 |
|
plist[1] = args[coding_arg_name] = Qno_conversion; |
9089 |
|
plist[2] = intern (":mnemonic"); |
9090 |
|
plist[3] = args[coding_arg_mnemonic] = make_number ('='); |
9091 |
|
plist[4] = intern (":coding-type"); |
9092 |
|
plist[5] = args[coding_arg_coding_type] = Qraw_text; |
9093 |
|
plist[6] = intern (":ascii-compatible-p"); |
9094 |
|
plist[7] = args[coding_arg_ascii_compatible_p] = Qt; |
9095 |
|
plist[8] = intern (":default-char"); |
9096 |
|
plist[9] = args[coding_arg_default_char] = make_number (0); |
9097 |
|
plist[10] = intern (":for-unibyte"); |
9098 |
|
plist[11] = args[coding_arg_for_unibyte] = Qt; |
9099 |
|
plist[12] = intern (":docstring"); |
9100 |
|
plist[13] = build_string ("Do no conversion.\n\ |
9101 |
|
\n\ |
9102 |
|
When you visit a file with this coding, the file is read into a\n\ |
9103 |
|
unibyte buffer as is, thus each byte of a file is treated as a\n\ |
9104 |
|
character."); |
9105 |
|
plist[14] = intern (":eol-type"); |
9106 |
|
plist[15] = args[coding_arg_eol_type] = Qunix; |
9107 |
|
args[coding_arg_plist] = Flist (16, plist); |
9108 |
|
Fdefine_coding_system_internal (coding_arg_max, args); |
9109 |
|
} |
9110 |
|
|
9111 |
|
setup_coding_system (Qno_conversion, &keyboard_coding); |
9112 |
|
setup_coding_system (Qno_conversion, &terminal_coding); |
9113 |
|
setup_coding_system (Qno_conversion, &safe_terminal_coding); |
9114 |
|
|
9115 |
|
{ |
9116 |
|
int i; |
9117 |
|
|
9118 |
|
for (i = 0; i < coding_category_max; i++) |
9119 |
|
Fset (AREF (Vcoding_category_table, i), Qno_conversion); |
9120 |
|
} |
9121 |
} |
} |
9122 |
|
|
9123 |
char * |
char * |
9141 |
} |
} |
9142 |
|
|
9143 |
#endif /* emacs */ |
#endif /* emacs */ |
|
|
|