1 |
/* Basic multilingual character support. |
/* Basic character set support. |
2 |
Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN. |
Copyright (C) 1995, 97, 98, 2000, 2001 Electrotechnical Laboratory, JAPAN. |
3 |
Licensed to the Free Software Foundation. |
Licensed to the Free Software Foundation. |
4 |
Copyright (C) 2001 Free Software Foundation, Inc. |
Copyright (C) 2001 Free Software Foundation, Inc. |
5 |
|
Copyright (C) 2001, 2002 |
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 |
|
|
23 |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
24 |
Boston, MA 02111-1307, USA. */ |
Boston, MA 02111-1307, USA. */ |
25 |
|
|
|
/* At first, see the document in `charset.h' to understand the code in |
|
|
this file. */ |
|
|
|
|
26 |
#ifdef emacs |
#ifdef emacs |
27 |
#include <config.h> |
#include <config.h> |
28 |
#endif |
#endif |
29 |
|
|
30 |
#include <stdio.h> |
#include <stdio.h> |
31 |
|
#include <unistd.h> |
32 |
|
#include <ctype.h> |
33 |
|
|
34 |
#ifdef emacs |
#ifdef emacs |
35 |
|
|
36 |
#include <sys/types.h> |
#include <sys/types.h> |
37 |
#include "lisp.h" |
#include "lisp.h" |
38 |
#include "buffer.h" |
#include "character.h" |
39 |
#include "charset.h" |
#include "charset.h" |
|
#include "composite.h" |
|
40 |
#include "coding.h" |
#include "coding.h" |
41 |
#include "disptab.h" |
#include "disptab.h" |
42 |
|
#include "buffer.h" |
43 |
|
|
44 |
#else /* not emacs */ |
#else /* not emacs */ |
45 |
|
|
47 |
|
|
48 |
#endif /* emacs */ |
#endif /* emacs */ |
49 |
|
|
|
Lisp_Object Qcharset, Qascii, Qeight_bit_control, Qeight_bit_graphic; |
|
|
Lisp_Object Qunknown; |
|
50 |
|
|
51 |
/* Declaration of special leading-codes. */ |
/*** GENERAL NOTE on CODED CHARACTER SET (CHARSET) *** |
52 |
int leading_code_private_11; /* for private DIMENSION1 of 1-column */ |
|
53 |
int leading_code_private_12; /* for private DIMENSION1 of 2-column */ |
A coded character set ("charset" hereafter) is a meaningful |
54 |
int leading_code_private_21; /* for private DIMENSION2 of 1-column */ |
collection (i.e. language, culture, functionality, etc) of |
55 |
int leading_code_private_22; /* for private DIMENSION2 of 2-column */ |
characters. Emacs handles multiple charsets at once. In Emacs Lisp |
56 |
|
code, a charset is represented by symbol. In C code, a charset is |
57 |
/* Declaration of special charsets. The values are set by |
represented by its ID number or by a pointer the struct charset. |
58 |
Fsetup_special_charsets. */ |
|
59 |
int charset_latin_iso8859_1; /* ISO8859-1 (Latin-1) */ |
The actual information about each charset is stored in two places. |
60 |
int charset_jisx0208_1978; /* JISX0208.1978 (Japanese Kanji old set) */ |
Lispy information is stored in the hash table Vcharset_hash_table as |
61 |
int charset_jisx0208; /* JISX0208.1983 (Japanese Kanji) */ |
a vector (charset attributes). The other information is stored in |
62 |
int charset_katakana_jisx0201; /* JISX0201.Kana (Japanese Katakana) */ |
charset_table as struct charset. |
63 |
int charset_latin_jisx0201; /* JISX0201.Roman (Japanese Roman) */ |
|
64 |
int charset_big5_1; /* Big5 Level 1 (Chinese Traditional) */ |
*/ |
|
int charset_big5_2; /* Big5 Level 2 (Chinese Traditional) */ |
|
|
|
|
|
Lisp_Object Qcharset_table; |
|
|
|
|
|
/* A char-table containing information of each character set. */ |
|
|
Lisp_Object Vcharset_table; |
|
|
|
|
|
/* A vector of charset symbol indexed by charset-id. This is used |
|
|
only for returning charset symbol from C functions. */ |
|
|
Lisp_Object Vcharset_symbol_table; |
|
65 |
|
|
66 |
/* A list of charset symbols ever defined. */ |
/* List of all charsets. This variable is used only from Emacs |
67 |
|
Lisp. */ |
68 |
Lisp_Object Vcharset_list; |
Lisp_Object Vcharset_list; |
69 |
|
|
70 |
/* Vector of translation table ever defined. |
/* Hash table that contains attributes of each charset. Keys are |
71 |
ID of a translation table is used to index this vector. */ |
charset symbols, and values are vectors of charset attributes. */ |
72 |
Lisp_Object Vtranslation_table_vector; |
Lisp_Object Vcharset_hash_table; |
73 |
|
|
74 |
/* A char-table for characters which may invoke auto-filling. */ |
/* Table of struct charset. */ |
75 |
Lisp_Object Vauto_fill_chars; |
struct charset *charset_table; |
76 |
|
|
77 |
Lisp_Object Qauto_fill_chars; |
static int charset_table_size; |
78 |
|
int charset_table_used; |
79 |
/* Tables used by macros BYTES_BY_CHAR_HEAD and WIDTH_BY_CHAR_HEAD. */ |
|
80 |
int bytes_by_char_head[256]; |
Lisp_Object Qcharsetp; |
81 |
int width_by_char_head[256]; |
|
82 |
|
/* Special charset symbols. */ |
83 |
|
Lisp_Object Qascii; |
84 |
|
Lisp_Object Qeight_bit_control; |
85 |
|
Lisp_Object Qeight_bit_graphic; |
86 |
|
Lisp_Object Qiso_8859_1; |
87 |
|
Lisp_Object Qunicode; |
88 |
|
|
89 |
|
/* The corresponding charsets. */ |
90 |
|
int charset_ascii; |
91 |
|
int charset_8_bit_control; |
92 |
|
int charset_8_bit_graphic; |
93 |
|
int charset_iso_8859_1; |
94 |
|
int charset_unicode; |
95 |
|
|
96 |
|
/* Value of charset attribute `charset-iso-plane'. */ |
97 |
|
Lisp_Object Qgl, Qgr; |
98 |
|
|
99 |
|
/* The primary charset. It is a charset of unibyte characters. */ |
100 |
|
int charset_primary; |
101 |
|
|
102 |
|
/* List of charsets ordered by the priority. */ |
103 |
|
Lisp_Object Vcharset_ordered_list; |
104 |
|
|
105 |
|
/* List of iso-2022 charsets. */ |
106 |
|
Lisp_Object Viso_2022_charset_list; |
107 |
|
|
108 |
|
/* List of emacs-mule charsets. */ |
109 |
|
Lisp_Object Vemacs_mule_charset_list; |
110 |
|
|
111 |
|
struct charset *emacs_mule_charset[256]; |
112 |
|
|
113 |
/* Mapping table from ISO2022's charset (specified by DIMENSION, |
/* Mapping table from ISO2022's charset (specified by DIMENSION, |
114 |
CHARS, and FINAL-CHAR) to Emacs' charset. */ |
CHARS, and FINAL-CHAR) to Emacs' charset. */ |
115 |
int iso_charset_table[2][2][128]; |
int iso_charset_table[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL]; |
116 |
|
|
117 |
/* Variables used locally in the macro FETCH_MULTIBYTE_CHAR. */ |
Lisp_Object Vcharset_map_directory; |
|
unsigned char *_fetch_multibyte_char_p; |
|
|
int _fetch_multibyte_char_len; |
|
118 |
|
|
119 |
/* Offset to add to a non-ASCII value when inserting it. */ |
Lisp_Object Vchar_unified_charset_table; |
|
int nonascii_insert_offset; |
|
120 |
|
|
121 |
/* Translation table for converting non-ASCII unibyte characters |
#define CODE_POINT_TO_INDEX(charset, code) \ |
122 |
to multibyte codes, or nil. */ |
((charset)->code_linear_p \ |
123 |
Lisp_Object Vnonascii_translation_table; |
? (code) - (charset)->min_code \ |
124 |
|
: ((((code) >> 24) <= (charset)->code_space[13]) \ |
125 |
/* List of all possible generic characters. */ |
&& ((((code) >> 16) & 0xFF) <= (charset)->code_space[9]) \ |
126 |
Lisp_Object Vgeneric_character_list; |
&& ((((code) >> 8) & 0xFF) <= (charset)->code_space[5]) \ |
127 |
|
&& (((code) & 0xFF) <= (charset)->code_space[1])) \ |
128 |
|
? (((((code) >> 24) - (charset)->code_space[12]) \ |
129 |
|
* (charset)->code_space[11]) \ |
130 |
|
+ (((((code) >> 16) & 0xFF) - (charset)->code_space[8]) \ |
131 |
|
* (charset)->code_space[7]) \ |
132 |
|
+ (((((code) >> 8) & 0xFF) - (charset)->code_space[4]) \ |
133 |
|
* (charset)->code_space[3]) \ |
134 |
|
+ (((code) & 0xFF) - (charset)->code_space[0])) \ |
135 |
|
: -1) |
136 |
|
|
137 |
|
|
138 |
|
/* Convert the character index IDX to code-point CODE for CHARSET. |
139 |
|
It is assumed that IDX is in a valid range. */ |
140 |
|
|
141 |
|
#define INDEX_TO_CODE_POINT(charset, idx) \ |
142 |
|
((charset)->code_linear_p \ |
143 |
|
? (idx) + (charset)->min_code \ |
144 |
|
: (((charset)->code_space[0] + (idx) % (charset)->code_space[2]) \ |
145 |
|
| (((charset)->code_space[4] \ |
146 |
|
+ ((idx) / (charset)->code_space[3] % (charset)->code_space[6])) \ |
147 |
|
<< 8) \ |
148 |
|
| (((charset)->code_space[8] \ |
149 |
|
+ ((idx) / (charset)->code_space[7] % (charset)->code_space[10])) \ |
150 |
|
<< 16) \ |
151 |
|
| (((charset)->code_space[12] + ((idx) / (charset)->code_space[11])) \ |
152 |
|
<< 24))) |
153 |
|
|
154 |
|
|
|
void |
|
|
invalid_character (c) |
|
|
int c; |
|
|
{ |
|
|
error ("Invalid character: 0%o, %d, 0x%x", c, c, c); |
|
|
} |
|
155 |
|
|
156 |
/* Parse string STR of length LENGTH and fetch information of a |
/* Set to 1 when a charset map is loaded to warn that a buffer text |
157 |
character at STR. Set BYTES to the byte length the character |
and a string data may be relocated. */ |
158 |
occupies, CHARSET, C1, C2 to proper values of the character. */ |
int charset_map_loaded; |
159 |
|
|
160 |
#define SPLIT_MULTIBYTE_SEQ(str, length, bytes, charset, c1, c2) \ |
/* Parse the mapping vector MAP which has this form: |
161 |
do { \ |
[CODE0 CHAR0 CODE1 CHAR1 ... ] |
162 |
(c1) = *(str); \ |
|
163 |
(bytes) = BYTES_BY_CHAR_HEAD (c1); \ |
If CONTROL_FLAG is 0, setup CHARSET->min_char and CHARSET->max_char. |
164 |
if ((bytes) == 1) \ |
|
165 |
(charset) = ASCII_BYTE_P (c1) ? CHARSET_ASCII : CHARSET_8_BIT_GRAPHIC; \ |
If CONTROL_FLAG is 1, setup CHARSET->min_char, CHARSET->max_char, |
166 |
else if ((bytes) == 2) \ |
CHARSET->decoder, and CHARSET->encoder. |
167 |
{ \ |
|
168 |
if ((c1) == LEADING_CODE_8_BIT_CONTROL) \ |
If CONTROL_FLAG is 2, setup CHARSET->deunifier and |
169 |
(charset) = CHARSET_8_BIT_CONTROL, (c1) = (str)[1] - 0x20; \ |
Vchar_unify_table. If Vchar_unified_charset_table is non-nil, |
170 |
else \ |
setup it too. */ |
171 |
(charset) = (c1), (c1) = (str)[1] & 0x7F; \ |
|
172 |
} \ |
static void |
173 |
else if ((bytes) == 3) \ |
parse_charset_map (charset, map, control_flag) |
174 |
{ \ |
struct charset *charset; |
175 |
if ((c1) < LEADING_CODE_PRIVATE_11) \ |
Lisp_Object map; |
176 |
(charset) = (c1), (c1) = (str)[1] & 0x7F, (c2) = (str)[2] & 0x7F; \ |
int control_flag; |
177 |
else \ |
{ |
178 |
(charset) = (str)[1], (c1) = (str)[2] & 0x7F; \ |
Lisp_Object vec, table; |
179 |
} \ |
unsigned min_code = CHARSET_MIN_CODE (charset); |
180 |
else \ |
unsigned max_code = CHARSET_MAX_CODE (charset); |
181 |
(charset) = (str)[1], (c1) = (str)[2] & 0x7F, (c2) = (str)[3] & 0x7F; \ |
int ascii_compatible_p = charset->ascii_compatible_p; |
182 |
} while (0) |
int min_char, max_char, nonascii_min_char; |
183 |
|
int size; |
184 |
/* 1 if CHARSET, C1, and C2 compose a valid character, else 0. */ |
int i; |
185 |
#define CHAR_COMPONENTS_VALID_P(charset, c1, c2) \ |
int first; |
186 |
((charset) == CHARSET_ASCII \ |
unsigned char *fast_map = charset->fast_map; |
|
? ((c1) >= 0 && (c1) <= 0x7F) \ |
|
|
: ((charset) == CHARSET_8_BIT_CONTROL \ |
|
|
? ((c1) >= 0x80 && (c1) <= 0x9F) \ |
|
|
: ((charset) == CHARSET_8_BIT_GRAPHIC \ |
|
|
? ((c1) >= 0x80 && (c1) <= 0xFF) \ |
|
|
: (CHARSET_DIMENSION (charset) == 1 \ |
|
|
? ((c1) >= 0x20 && (c1) <= 0x7F) \ |
|
|
: ((c1) >= 0x20 && (c1) <= 0x7F \ |
|
|
&& (c2) >= 0x20 && (c2) <= 0x7F))))) |
|
|
|
|
|
/* Store multi-byte form of the character C in STR. The caller should |
|
|
allocate at least 4-byte area at STR in advance. Returns the |
|
|
length of the multi-byte form. If C is an invalid character code, |
|
|
return -1. */ |
|
187 |
|
|
188 |
int |
if (control_flag) |
189 |
char_to_string_1 (c, str) |
{ |
190 |
int c; |
int n = CODE_POINT_TO_INDEX (charset, max_code) + 1; |
191 |
unsigned char *str; |
unsigned invalid_code = CHARSET_INVALID_CODE (charset); |
192 |
{ |
|
193 |
unsigned char *p = str; |
table = Fmake_char_table (Qnil, make_number (invalid_code)); |
194 |
|
if (control_flag == 1) |
195 |
|
vec = Fmake_vector (make_number (n), make_number (-1)); |
196 |
|
else if (! CHAR_TABLE_P (Vchar_unify_table)) |
197 |
|
Vchar_unify_table = Fmake_char_table (Qnil, make_number (-1)); |
198 |
|
|
199 |
if (c & CHAR_MODIFIER_MASK) /* This includes the case C is negative. */ |
charset_map_loaded = 1; |
200 |
|
} |
201 |
|
|
202 |
|
size = ASIZE (map); |
203 |
|
nonascii_min_char = MAX_CHAR; |
204 |
|
CHARSET_COMPACT_CODES_P (charset) = 1; |
205 |
|
for (first = 1, i = 0; i < size; i += 2) |
206 |
{ |
{ |
207 |
/* Multibyte character can't have a modifier bit. */ |
Lisp_Object val; |
208 |
if (! SINGLE_BYTE_CHAR_P ((c & ~CHAR_MODIFIER_MASK))) |
unsigned code, temp; |
209 |
return -1; |
int c, char_index; |
210 |
|
|
211 |
/* For Meta, Shift, and Control modifiers, we need special care. */ |
val = AREF (map, i); |
212 |
if (c & CHAR_META) |
CHECK_NATNUM (val); |
213 |
{ |
code = XFASTINT (val); |
214 |
/* Move the meta bit to the right place for a string. */ |
val = AREF (map, i + 1); |
215 |
c = (c & ~CHAR_META) | 0x80; |
CHECK_NATNUM (val); |
216 |
} |
c = XFASTINT (val); |
217 |
if (c & CHAR_SHIFT) |
|
218 |
{ |
if (code < min_code || code > max_code) |
219 |
/* Shift modifier is valid only with [A-Za-z]. */ |
continue; |
220 |
if ((c & 0377) >= 'A' && (c & 0377) <= 'Z') |
char_index = CODE_POINT_TO_INDEX (charset, code); |
221 |
c &= ~CHAR_SHIFT; |
if (char_index < 0 |
222 |
else if ((c & 0377) >= 'a' && (c & 0377) <= 'z') |
|| c > MAX_CHAR) |
223 |
c = (c & ~CHAR_SHIFT) - ('a' - 'A'); |
continue; |
224 |
} |
|
225 |
if (c & CHAR_CTL) |
if (control_flag < 2) |
226 |
{ |
{ |
227 |
/* Simulate the code in lread.c. */ |
if (first) |
228 |
/* Allow `\C- ' and `\C-?'. */ |
{ |
229 |
if (c == (CHAR_CTL | ' ')) |
min_char = max_char = c; |
230 |
c = 0; |
first = 0; |
231 |
else if (c == (CHAR_CTL | '?')) |
} |
232 |
c = 127; |
else if (c > max_char) |
233 |
/* ASCII control chars are made from letters (both cases), |
max_char = c; |
234 |
as well as the non-letters within 0100...0137. */ |
else if (c < min_char) |
235 |
else if ((c & 0137) >= 0101 && (c & 0137) <= 0132) |
min_char = c; |
236 |
c &= (037 | (~0177 & ~CHAR_CTL)); |
if (ascii_compatible_p && ! ASCII_BYTE_P (c) |
237 |
else if ((c & 0177) >= 0100 && (c & 0177) <= 0137) |
&& c < nonascii_min_char) |
238 |
c &= (037 | (~0177 & ~CHAR_CTL)); |
nonascii_min_char = c; |
239 |
|
|
240 |
|
CHARSET_FAST_MAP_SET (c, fast_map); |
241 |
} |
} |
242 |
|
|
243 |
/* If C still has any modifier bits, just ignore it. */ |
if (control_flag) |
|
c &= ~CHAR_MODIFIER_MASK; |
|
|
} |
|
|
|
|
|
if (SINGLE_BYTE_CHAR_P (c)) |
|
|
{ |
|
|
if (ASCII_BYTE_P (c) || c >= 0xA0) |
|
|
*p++ = c; |
|
|
else |
|
244 |
{ |
{ |
245 |
*p++ = LEADING_CODE_8_BIT_CONTROL; |
if (control_flag == 1) |
246 |
*p++ = c + 0x20; |
{ |
247 |
|
if (char_index >= ASIZE (vec)) |
248 |
|
abort (); |
249 |
|
ASET (vec, char_index, make_number (c)); |
250 |
|
if (code > 0x7FFFFFF) |
251 |
|
{ |
252 |
|
CHAR_TABLE_SET (table, c, |
253 |
|
Fcons (make_number (code >> 16), |
254 |
|
make_number (code & 0xFFFF))); |
255 |
|
CHARSET_COMPACT_CODES_P (charset) = 0; |
256 |
|
} |
257 |
|
else |
258 |
|
CHAR_TABLE_SET (table, c, make_number (code)); |
259 |
|
} |
260 |
|
else |
261 |
|
{ |
262 |
|
int c1 = DECODE_CHAR (charset, code); |
263 |
|
if (c1 >= 0) |
264 |
|
{ |
265 |
|
CHAR_TABLE_SET (table, c, make_number (c1)); |
266 |
|
CHAR_TABLE_SET (Vchar_unify_table, c1, c); |
267 |
|
if (CHAR_TABLE_P (Vchar_unified_charset_table)) |
268 |
|
CHAR_TABLE_SET (Vchar_unified_charset_table, c1, |
269 |
|
CHARSET_NAME (charset)); |
270 |
|
} |
271 |
|
} |
272 |
} |
} |
273 |
} |
} |
|
else if (CHAR_VALID_P (c, 0)) |
|
|
{ |
|
|
int charset, c1, c2; |
|
274 |
|
|
275 |
SPLIT_CHAR (c, charset, c1, c2); |
if (control_flag < 2) |
276 |
|
{ |
277 |
if (charset >= LEADING_CODE_EXT_11) |
CHARSET_MIN_CHAR (charset) = (ascii_compatible_p |
278 |
*p++ = (charset < LEADING_CODE_EXT_12 |
? nonascii_min_char : min_char); |
279 |
? LEADING_CODE_PRIVATE_11 |
CHARSET_MAX_CHAR (charset) = max_char; |
280 |
: (charset < LEADING_CODE_EXT_21 |
if (control_flag) |
281 |
? LEADING_CODE_PRIVATE_12 |
{ |
282 |
: (charset < LEADING_CODE_EXT_22 |
CHARSET_DECODER (charset) = vec; |
283 |
? LEADING_CODE_PRIVATE_21 |
CHARSET_ENCODER (charset) = table; |
|
: LEADING_CODE_PRIVATE_22))); |
|
|
*p++ = charset; |
|
|
if ((c1 > 0 && c1 < 32) || (c2 > 0 && c2 < 32)) |
|
|
return -1; |
|
|
if (c1) |
|
|
{ |
|
|
*p++ = c1 | 0x80; |
|
|
if (c2 > 0) |
|
|
*p++ = c2 | 0x80; |
|
284 |
} |
} |
285 |
} |
} |
286 |
else |
else |
287 |
return -1; |
CHARSET_DEUNIFIER (charset) = table; |
|
|
|
|
return (p - str); |
|
288 |
} |
} |
289 |
|
|
290 |
|
|
291 |
/* Store multi-byte form of the character C in STR. The caller should |
/* Read a hexadecimal number (preceded by "0x") from the file FP while |
292 |
allocate at least 4-byte area at STR in advance. Returns the |
paying attention to comment charcter '#'. */ |
|
length of the multi-byte form. If C is an invalid character code, |
|
|
signal an error. |
|
|
|
|
|
Use macro `CHAR_STRING (C, STR)' instead of calling this function |
|
|
directly if C can be an ASCII character. */ |
|
293 |
|
|
294 |
int |
static INLINE unsigned |
295 |
char_to_string (c, str) |
read_hex (fp, eof) |
296 |
int c; |
FILE *fp; |
297 |
unsigned char *str; |
int *eof; |
298 |
{ |
{ |
299 |
int len; |
int c; |
300 |
len = char_to_string_1 (c, str); |
unsigned n; |
301 |
if (len == -1) |
|
302 |
invalid_character (c); |
while ((c = getc (fp)) != EOF) |
303 |
return len; |
{ |
304 |
|
if (c == '#' || c == ' ') |
305 |
|
{ |
306 |
|
while ((c = getc (fp)) != EOF && c != '\n'); |
307 |
|
} |
308 |
|
else if (c == '0') |
309 |
|
{ |
310 |
|
if ((c = getc (fp)) == EOF || c == 'x') |
311 |
|
break; |
312 |
|
} |
313 |
|
} |
314 |
|
if (c == EOF) |
315 |
|
{ |
316 |
|
*eof = 1; |
317 |
|
return 0; |
318 |
|
} |
319 |
|
*eof = 0; |
320 |
|
n = 0; |
321 |
|
if (c == 'x') |
322 |
|
while ((c = getc (fp)) != EOF && isxdigit (c)) |
323 |
|
n = ((n << 4) |
324 |
|
| (c <= '9' ? c - '0' : c <= 'F' ? c - 'A' + 10 : c - 'a' + 10)); |
325 |
|
else |
326 |
|
while ((c = getc (fp)) != EOF && isdigit (c)) |
327 |
|
n = (n * 10) + c - '0'; |
328 |
|
return n; |
329 |
} |
} |
330 |
|
|
331 |
|
|
332 |
/* Return the non-ASCII character corresponding to multi-byte form at |
/* Return a mapping vector for CHARSET loaded from MAPFILE. |
333 |
STR of length LEN. If ACTUAL_LEN is not NULL, store the byte |
Each line of MAPFILE has this form: |
334 |
length of the multibyte form in *ACTUAL_LEN. |
0xAAAA 0xBBBB |
335 |
|
where 0xAAAA is a code-point and 0xBBBB is the corresponding |
336 |
|
character code. |
337 |
|
The returned vector has this form: |
338 |
|
[ CODE1 CHAR1 CODE2 CHAR2 .... ] |
339 |
|
*/ |
340 |
|
|
341 |
|
static Lisp_Object |
342 |
|
load_charset_map (charset, mapfile) |
343 |
|
struct charset *charset; |
344 |
|
Lisp_Object mapfile; |
345 |
|
{ |
346 |
|
int fd; |
347 |
|
FILE *fp; |
348 |
|
int num; |
349 |
|
unsigned *numbers_table[256]; |
350 |
|
int numbers_table_used; |
351 |
|
unsigned *numbers; |
352 |
|
int eof; |
353 |
|
Lisp_Object suffixes; |
354 |
|
Lisp_Object vec; |
355 |
|
int i; |
356 |
|
|
357 |
Use macros STRING_CHAR or STRING_CHAR_AND_LENGTH instead of calling |
suffixes = Fcons (build_string (".map"), |
358 |
this function directly if you want ot handle ASCII characters as |
Fcons (build_string (".TXT"), Qnil)); |
|
well. */ |
|
359 |
|
|
360 |
int |
fd = openp (Fcons (Vcharset_map_directory, Qnil), mapfile, suffixes, |
361 |
string_to_char (str, len, actual_len) |
NULL, 0); |
362 |
const unsigned char *str; |
if (fd < 0 |
363 |
int len, *actual_len; |
|| ! (fp = fdopen (fd, "r"))) |
364 |
{ |
{ |
365 |
int c, bytes, charset, c1, c2; |
add_to_log ("Failure in loading charset map: %S", mapfile, Qnil); |
366 |
|
return Qnil; |
367 |
SPLIT_MULTIBYTE_SEQ (str, len, bytes, charset, c1, c2); |
} |
|
c = MAKE_CHAR (charset, c1, c2); |
|
|
if (actual_len) |
|
|
*actual_len = bytes; |
|
|
return c; |
|
|
} |
|
368 |
|
|
369 |
/* Return the length of the multi-byte form at string STR of length LEN. |
numbers_table_used = 0; |
370 |
Use the macro MULTIBYTE_FORM_LENGTH instead. */ |
num = 0; |
371 |
int |
eof = 0; |
372 |
multibyte_form_length (str, len) |
while (1) |
373 |
const unsigned char *str; |
{ |
374 |
int len; |
unsigned n = read_hex (fp, &eof); |
|
{ |
|
|
int bytes; |
|
375 |
|
|
376 |
PARSE_MULTIBYTE_SEQ (str, len, bytes); |
if (eof) |
377 |
return bytes; |
break; |
378 |
} |
if ((num % 0x10000) == 0) |
379 |
|
{ |
380 |
|
if (numbers_table_used == 256) |
381 |
|
break; |
382 |
|
numbers = (unsigned *) alloca (sizeof (unsigned) * 0x10000); |
383 |
|
numbers_table[numbers_table_used++] = numbers; |
384 |
|
} |
385 |
|
*numbers++ = n; |
386 |
|
num++; |
387 |
|
} |
388 |
|
fclose (fp); |
389 |
|
close (fd); |
390 |
|
|
391 |
/* Check multibyte form at string STR of length LEN and set variables |
vec = Fmake_vector (make_number (num), Qnil); |
392 |
pointed by CHARSET, C1, and C2 to charset and position codes of the |
for (i = 0; i < num; i++, numbers++) |
393 |
character at STR, and return 0. If there's no multibyte character, |
{ |
394 |
return -1. This should be used only in the macro SPLIT_STRING |
if ((i % 0x10000) == 0) |
395 |
which checks range of STR in advance. */ |
numbers = numbers_table[i / 0x10000]; |
396 |
|
ASET (vec, i, make_number (*numbers)); |
397 |
|
} |
398 |
|
|
399 |
int |
charset_map_loaded = 1; |
|
split_string (str, len, charset, c1, c2) |
|
|
const unsigned char *str; |
|
|
unsigned char *c1, *c2; |
|
|
int len, *charset; |
|
|
{ |
|
|
register int bytes, cs, code1, code2 = -1; |
|
400 |
|
|
401 |
SPLIT_MULTIBYTE_SEQ (str, len, bytes, cs, code1, code2); |
return vec; |
|
if (cs == CHARSET_ASCII) |
|
|
return -1; |
|
|
*charset = cs; |
|
|
*c1 = code1; |
|
|
*c2 = code2; |
|
|
return 0; |
|
402 |
} |
} |
403 |
|
|
404 |
/* Return 1 iff character C has valid printable glyph. |
static void |
405 |
Use the macro CHAR_PRINTABLE_P instead. */ |
load_charset (charset) |
406 |
int |
struct charset *charset; |
|
char_printable_p (c) |
|
|
int c; |
|
407 |
{ |
{ |
408 |
int charset, c1, c2; |
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED) |
409 |
|
{ |
410 |
|
Lisp_Object map; |
411 |
|
|
412 |
if (ASCII_BYTE_P (c)) |
map = CHARSET_MAP (charset); |
413 |
return 1; |
if (STRINGP (map)) |
414 |
else if (SINGLE_BYTE_CHAR_P (c)) |
map = load_charset_map (charset, map); |
415 |
return 0; |
parse_charset_map (charset, map, 1); |
416 |
else if (c >= MAX_CHAR) |
CHARSET_METHOD (charset) = CHARSET_METHOD_MAP; |
417 |
return 0; |
} |
|
|
|
|
SPLIT_CHAR (c, charset, c1, c2); |
|
|
if (! CHARSET_DEFINED_P (charset)) |
|
|
return 0; |
|
|
if (CHARSET_CHARS (charset) == 94 |
|
|
? c1 <= 32 || c1 >= 127 |
|
|
: c1 < 32) |
|
|
return 0; |
|
|
if (CHARSET_DIMENSION (charset) == 2 |
|
|
&& (CHARSET_CHARS (charset) == 94 |
|
|
? c2 <= 32 || c2 >= 127 |
|
|
: c2 < 32)) |
|
|
return 0; |
|
|
return 1; |
|
418 |
} |
} |
419 |
|
|
420 |
/* Translate character C by translation table TABLE. If C |
|
421 |
is negative, translate a character specified by CHARSET, C1, and C2 |
DEFUN ("charsetp", Fcharsetp, Scharsetp, 1, 1, 0, |
422 |
(C1 and C2 are code points of the character). If no translation is |
doc: /* Return non-nil if and only if OBJECT is a charset.*/) |
423 |
found in TABLE, return C. */ |
(object) |
424 |
int |
Lisp_Object object; |
|
translate_char (table, c, charset, c1, c2) |
|
|
Lisp_Object table; |
|
|
int c, charset, c1, c2; |
|
425 |
{ |
{ |
426 |
Lisp_Object ch; |
return (CHARSETP (object) ? Qt : Qnil); |
427 |
int alt_charset, alt_c1, alt_c2, dimension; |
} |
428 |
|
|
|
if (c < 0) c = MAKE_CHAR (charset, (c1 & 0x7F) , (c2 & 0x7F)); |
|
|
if (!CHAR_TABLE_P (table) |
|
|
|| (ch = Faref (table, make_number (c)), !NATNUMP (ch))) |
|
|
return c; |
|
|
|
|
|
SPLIT_CHAR (XFASTINT (ch), alt_charset, alt_c1, alt_c2); |
|
|
dimension = CHARSET_DIMENSION (alt_charset); |
|
|
if ((dimension == 1 && alt_c1 > 0) || (dimension == 2 && alt_c2 > 0)) |
|
|
/* CH is not a generic character, just return it. */ |
|
|
return XFASTINT (ch); |
|
|
|
|
|
/* Since CH is a generic character, we must return a specific |
|
|
charater which has the same position codes as C from CH. */ |
|
|
if (charset < 0) |
|
|
SPLIT_CHAR (c, charset, c1, c2); |
|
|
if (dimension != CHARSET_DIMENSION (charset)) |
|
|
/* We can't make such a character because of dimension mismatch. */ |
|
|
return c; |
|
|
return MAKE_CHAR (alt_charset, c1, c2); |
|
|
} |
|
|
|
|
|
/* Convert the unibyte character C to multibyte based on |
|
|
Vnonascii_translation_table or nonascii_insert_offset. If they can't |
|
|
convert C to a valid multibyte character, convert it based on |
|
|
DEFAULT_NONASCII_INSERT_OFFSET which makes C a Latin-1 character. */ |
|
429 |
|
|
430 |
int |
void |
431 |
unibyte_char_to_multibyte (c) |
map_charset_chars (c_function, function, charset_symbol, arg) |
432 |
int c; |
void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object); |
433 |
{ |
Lisp_Object function, charset_symbol, arg; |
434 |
if (c < 0400 && c >= 0200) |
{ |
435 |
|
int id; |
436 |
|
struct charset *charset; |
437 |
|
Lisp_Object range; |
438 |
|
|
439 |
|
CHECK_CHARSET_GET_ID (charset_symbol, id); |
440 |
|
charset = CHARSET_FROM_ID (id); |
441 |
|
|
442 |
|
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED) |
443 |
|
load_charset (charset); |
444 |
|
|
445 |
|
if (CHARSET_METHOD (charset) == CHARSET_METHOD_OFFSET) |
446 |
|
{ |
447 |
|
range = Fcons (make_number (CHARSET_MIN_CHAR (charset)), |
448 |
|
make_number (CHARSET_MAX_CHAR (charset))); |
449 |
|
if (NILP (function)) |
450 |
|
(*c_function) (arg, range, Qnil); |
451 |
|
else |
452 |
|
call2 (function, range, arg); |
453 |
|
} |
454 |
|
else if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP) |
455 |
{ |
{ |
456 |
int c_save = c; |
if (! CHAR_TABLE_P (CHARSET_ENCODER (charset))) |
457 |
|
return; |
458 |
if (! NILP (Vnonascii_translation_table)) |
if (CHARSET_ASCII_COMPATIBLE_P (charset)) |
459 |
{ |
{ |
460 |
c = XINT (Faref (Vnonascii_translation_table, make_number (c))); |
range = Fcons (make_number (0), make_number (127)); |
461 |
if (c >= 0400 && ! char_valid_p (c, 0)) |
if (NILP (function)) |
462 |
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
(*c_function) (arg, range, Qnil); |
463 |
|
else |
464 |
|
call2 (function, range, arg); |
465 |
} |
} |
466 |
else if (c >= 0240 && nonascii_insert_offset > 0) |
map_char_table (c_function, function, CHARSET_ENCODER (charset), arg, |
467 |
|
0, NULL); |
468 |
|
} |
469 |
|
else /* i.e. CHARSET_METHOD_PARENT */ |
470 |
|
{ |
471 |
|
int from, to, c; |
472 |
|
unsigned code; |
473 |
|
int i, j, k, l; |
474 |
|
int *code_space = CHARSET_CODE_SPACE (charset); |
475 |
|
Lisp_Object val; |
476 |
|
|
477 |
|
range = Fcons (Qnil, Qnil); |
478 |
|
from = to = -2; |
479 |
|
for (i = code_space[12]; i <= code_space[13]; i++) |
480 |
|
for (j = code_space[8]; j <= code_space[9]; j++) |
481 |
|
for (k = code_space[4]; k <= code_space[5]; k++) |
482 |
|
for (l = code_space[0]; l <= code_space[1]; l++) |
483 |
|
{ |
484 |
|
code = (i << 24) | (j << 16) | (k << 8) | l; |
485 |
|
c = DECODE_CHAR (charset, code); |
486 |
|
if (c == to + 1) |
487 |
|
{ |
488 |
|
to++; |
489 |
|
continue; |
490 |
|
} |
491 |
|
if (from >= 0) |
492 |
|
{ |
493 |
|
if (from < to) |
494 |
|
{ |
495 |
|
XSETCAR (range, make_number (from)); |
496 |
|
XSETCDR (range, make_number (to)); |
497 |
|
val = range; |
498 |
|
} |
499 |
|
else |
500 |
|
val = make_number (from); |
501 |
|
if (NILP (function)) |
502 |
|
(*c_function) (arg, val, Qnil); |
503 |
|
else |
504 |
|
call2 (function, val, arg); |
505 |
|
} |
506 |
|
from = to = (c < 0 ? -2 : c); |
507 |
|
} |
508 |
|
if (from >= 0) |
509 |
{ |
{ |
510 |
c += nonascii_insert_offset; |
if (from < to) |
511 |
if (c < 0400 || ! char_valid_p (c, 0)) |
{ |
512 |
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
XSETCAR (range, make_number (from)); |
513 |
|
XSETCDR (range, make_number (to)); |
514 |
|
val = range; |
515 |
|
} |
516 |
|
else |
517 |
|
val = make_number (from); |
518 |
|
if (NILP (function)) |
519 |
|
(*c_function) (arg, val, Qnil); |
520 |
|
else |
521 |
|
call2 (function, val, arg); |
522 |
} |
} |
|
else if (c >= 0240) |
|
|
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
|
523 |
} |
} |
524 |
return c; |
} |
525 |
|
|
526 |
|
DEFUN ("map-charset-chars", Fmap_charset_chars, Smap_charset_chars, 2, 3, 0, |
527 |
|
doc: /* Call FUNCTION for each characters in CHARSET. |
528 |
|
FUNCTION is called with three arguments; FROM, TO, and the 3rd optional |
529 |
|
argument ARG. |
530 |
|
FROM and TO indicates a range of character sequence that are contained |
531 |
|
in CHARSET. */) |
532 |
|
(function, charset, arg) |
533 |
|
Lisp_Object function, charset, arg; |
534 |
|
{ |
535 |
|
map_charset_chars (NULL, function, charset, arg); |
536 |
|
return Qnil; |
537 |
} |
} |
538 |
|
|
539 |
|
|
540 |
/* Convert the multibyte character C to unibyte 8-bit character based |
/* Define a charset according to the arguments. The Nth argument is |
541 |
on Vnonascii_translation_table or nonascii_insert_offset. If |
the Nth attribute of the charset (the last attribute `charset-id' |
542 |
REV_TBL is non-nil, it should be a reverse table of |
is not included). See the docstring of `define-charset' for the |
543 |
Vnonascii_translation_table, i.e. what given by: |
detail. */ |
544 |
Fchar_table_extra_slot (Vnonascii_translation_table, make_number (0)) */ |
|
545 |
|
DEFUN ("define-charset-internal", Fdefine_charset_internal, |
546 |
int |
Sdefine_charset_internal, charset_arg_max, MANY, 0, |
547 |
multibyte_char_to_unibyte (c, rev_tbl) |
doc: /* For internal use only. */) |
548 |
int c; |
(nargs, args) |
549 |
Lisp_Object rev_tbl; |
int nargs; |
550 |
|
Lisp_Object *args; |
551 |
{ |
{ |
552 |
if (!SINGLE_BYTE_CHAR_P (c)) |
/* Charset attr vector. */ |
553 |
|
Lisp_Object attrs; |
554 |
|
Lisp_Object val; |
555 |
|
unsigned hash_code; |
556 |
|
struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table); |
557 |
|
int i; |
558 |
|
struct charset charset; |
559 |
|
int id; |
560 |
|
int dimension; |
561 |
|
int new_definition_p; |
562 |
|
int nchars; |
563 |
|
|
564 |
|
if (nargs != charset_arg_max) |
565 |
|
return Fsignal (Qwrong_number_of_arguments, |
566 |
|
Fcons (intern ("define-charset-internal"), |
567 |
|
make_number (nargs))); |
568 |
|
|
569 |
|
attrs = Fmake_vector (make_number (charset_attr_max), Qnil); |
570 |
|
|
571 |
|
CHECK_SYMBOL (args[charset_arg_name]); |
572 |
|
ASET (attrs, charset_name, args[charset_arg_name]); |
573 |
|
|
574 |
|
val = args[charset_arg_code_space]; |
575 |
|
for (i = 0, dimension = 0, nchars = 1; i < 4; i++) |
576 |
|
{ |
577 |
|
int min_byte, max_byte; |
578 |
|
|
579 |
|
min_byte = XINT (Faref (val, make_number (i * 2))); |
580 |
|
max_byte = XINT (Faref (val, make_number (i * 2 + 1))); |
581 |
|
if (min_byte < 0 || min_byte > max_byte || max_byte >= 256) |
582 |
|
error ("Invalid :code-space value"); |
583 |
|
charset.code_space[i * 4] = min_byte; |
584 |
|
charset.code_space[i * 4 + 1] = max_byte; |
585 |
|
charset.code_space[i * 4 + 2] = max_byte - min_byte + 1; |
586 |
|
nchars *= charset.code_space[i * 4 + 2]; |
587 |
|
charset.code_space[i * 4 + 3] = nchars; |
588 |
|
if (max_byte > 0) |
589 |
|
dimension = i + 1; |
590 |
|
} |
591 |
|
|
592 |
|
val = args[charset_arg_dimension]; |
593 |
|
if (NILP (val)) |
594 |
|
charset.dimension = dimension; |
595 |
|
else |
596 |
{ |
{ |
597 |
int c_save = c; |
CHECK_NATNUM (val); |
598 |
|
charset.dimension = XINT (val); |
599 |
|
if (charset.dimension < 1 || charset.dimension > 4) |
600 |
|
args_out_of_range_3 (val, make_number (1), make_number (4)); |
601 |
|
} |
602 |
|
|
603 |
|
charset.code_linear_p |
604 |
|
= (charset.dimension == 1 |
605 |
|
|| (charset.code_space[2] == 256 |
606 |
|
&& (charset.dimension == 2 |
607 |
|
|| (charset.code_space[6] == 256 |
608 |
|
&& (charset.dimension == 3 |
609 |
|
|| charset.code_space[10] == 256))))); |
610 |
|
|
611 |
|
charset.iso_chars_96 = charset.code_space[2] == 96; |
612 |
|
|
613 |
|
charset.min_code = (charset.code_space[0] |
614 |
|
| (charset.code_space[4] << 8) |
615 |
|
| (charset.code_space[8] << 16) |
616 |
|
| (charset.code_space[12] << 24)); |
617 |
|
charset.max_code = (charset.code_space[1] |
618 |
|
| (charset.code_space[5] << 8) |
619 |
|
| (charset.code_space[9] << 16) |
620 |
|
| (charset.code_space[13] << 24)); |
621 |
|
|
622 |
if (! CHAR_TABLE_P (rev_tbl) |
val = args[charset_arg_invalid_code]; |
623 |
&& CHAR_TABLE_P (Vnonascii_translation_table)) |
if (NILP (val)) |
624 |
rev_tbl = Fchar_table_extra_slot (Vnonascii_translation_table, |
{ |
625 |
make_number (0)); |
if (charset.min_code > 0) |
626 |
if (CHAR_TABLE_P (rev_tbl)) |
charset.invalid_code = 0; |
|
{ |
|
|
Lisp_Object temp; |
|
|
temp = Faref (rev_tbl, make_number (c)); |
|
|
if (INTEGERP (temp)) |
|
|
c = XINT (temp); |
|
|
if (c >= 256) |
|
|
c = (c_save & 0177) + 0200; |
|
|
} |
|
627 |
else |
else |
628 |
{ |
{ |
629 |
if (nonascii_insert_offset > 0) |
XSETINT (val, charset.max_code + 1); |
630 |
c -= nonascii_insert_offset; |
if (XINT (val) == charset.max_code + 1) |
631 |
if (c < 128 || c >= 256) |
charset.invalid_code = charset.max_code + 1; |
632 |
c = (c_save & 0177) + 0200; |
else |
633 |
|
error ("Attribute :invalid-code must be specified"); |
634 |
} |
} |
635 |
} |
} |
636 |
|
else |
637 |
|
{ |
638 |
|
CHECK_NATNUM (val); |
639 |
|
charset.invalid_code = XFASTINT (val); |
640 |
|
} |
641 |
|
|
642 |
return c; |
val = args[charset_arg_iso_final]; |
643 |
} |
if (NILP (val)) |
644 |
|
charset.iso_final = -1; |
645 |
|
else |
646 |
|
{ |
647 |
|
CHECK_NUMBER (val); |
648 |
|
if (XINT (val) < '0' || XINT (val) > 127) |
649 |
|
error ("Invalid iso-final-char: %d", XINT (val)); |
650 |
|
charset.iso_final = XINT (val); |
651 |
|
} |
652 |
|
|
653 |
|
val = args[charset_arg_iso_revision]; |
654 |
|
if (NILP (val)) |
655 |
|
charset.iso_revision = -1; |
656 |
|
else |
657 |
|
{ |
658 |
|
CHECK_NUMBER (val); |
659 |
|
if (XINT (val) > 63) |
660 |
|
args_out_of_range (make_number (63), val); |
661 |
|
charset.iso_revision = XINT (val); |
662 |
|
} |
663 |
|
|
664 |
|
val = args[charset_arg_emacs_mule_id]; |
665 |
/* Update the table Vcharset_table with the given arguments (see the |
if (NILP (val)) |
666 |
document of `define-charset' for the meaning of each argument). |
charset.emacs_mule_id = -1; |
667 |
Several other table contents are also updated. The caller should |
else |
668 |
check the validity of CHARSET-ID and the remaining arguments in |
{ |
669 |
advance. */ |
CHECK_NATNUM (val); |
670 |
|
if ((XINT (val) > 0 && XINT (val) <= 128) || XINT (val) >= 256) |
671 |
|
error ("Invalid emacs-mule-id: %d", XINT (val)); |
672 |
|
charset.emacs_mule_id = XINT (val); |
673 |
|
} |
674 |
|
|
675 |
void |
charset.ascii_compatible_p = ! NILP (args[charset_arg_ascii_compatible_p]); |
676 |
update_charset_table (charset_id, dimension, chars, width, direction, |
|
677 |
iso_final_char, iso_graphic_plane, |
charset.supplementary_p = ! NILP (args[charset_arg_supplementary_p]); |
678 |
short_name, long_name, description) |
|
679 |
Lisp_Object charset_id, dimension, chars, width, direction; |
charset.unified_p = 0; |
680 |
Lisp_Object iso_final_char, iso_graphic_plane; |
|
681 |
Lisp_Object short_name, long_name, description; |
bzero (charset.fast_map, sizeof (charset.fast_map)); |
682 |
{ |
|
683 |
int charset = XINT (charset_id); |
if (! NILP (args[charset_arg_code_offset])) |
684 |
int bytes; |
{ |
685 |
unsigned char leading_code_base, leading_code_ext; |
val = args[charset_arg_code_offset]; |
686 |
|
CHECK_NUMBER (val); |
687 |
if (NILP (CHARSET_TABLE_ENTRY (charset))) |
|
688 |
CHARSET_TABLE_ENTRY (charset) |
charset.method = CHARSET_METHOD_OFFSET; |
689 |
= Fmake_vector (make_number (CHARSET_MAX_IDX), Qnil); |
charset.code_offset = XINT (val); |
690 |
|
|
691 |
if (NILP (long_name)) |
i = CODE_POINT_TO_INDEX (&charset, charset.min_code); |
692 |
long_name = short_name; |
charset.min_char = i + charset.code_offset; |
693 |
if (NILP (description)) |
i = CODE_POINT_TO_INDEX (&charset, charset.max_code); |
694 |
description = long_name; |
charset.max_char = i + charset.code_offset; |
695 |
|
if (charset.max_char > MAX_CHAR) |
696 |
/* Get byte length of multibyte form, base leading-code, and |
error ("Unsupported max char: %d", charset.max_char); |
697 |
extended leading-code of the charset. See the comment under the |
|
698 |
title "GENERAL NOTE on CHARACTER SET (CHARSET)" in charset.h. */ |
for (i = charset.min_char; i < 0x10000 && i <= charset.max_char; |
699 |
bytes = XINT (dimension); |
i += 128) |
700 |
if (charset < MIN_CHARSET_PRIVATE_DIMENSION1) |
CHARSET_FAST_MAP_SET (i, charset.fast_map); |
701 |
{ |
for (; i <= charset.max_char; i += 0x1000) |
702 |
/* Official charset, it doesn't have an extended leading-code. */ |
CHARSET_FAST_MAP_SET (i, charset.fast_map); |
|
if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC) |
|
|
bytes += 1; /* For a base leading-code. */ |
|
|
leading_code_base = charset; |
|
|
leading_code_ext = 0; |
|
703 |
} |
} |
704 |
else |
else if (! NILP (args[charset_arg_map])) |
705 |
{ |
{ |
706 |
/* Private charset. */ |
val = args[charset_arg_map]; |
707 |
bytes += 2; /* For base and extended leading-codes. */ |
ASET (attrs, charset_map, val); |
708 |
leading_code_base |
if (STRINGP (val)) |
709 |
= (charset < LEADING_CODE_EXT_12 |
val = load_charset_map (&charset, val); |
710 |
? LEADING_CODE_PRIVATE_11 |
CHECK_VECTOR (val); |
711 |
: (charset < LEADING_CODE_EXT_21 |
parse_charset_map (&charset, val, 0); |
712 |
? LEADING_CODE_PRIVATE_12 |
charset.method = CHARSET_METHOD_MAP_DEFERRED; |
713 |
: (charset < LEADING_CODE_EXT_22 |
} |
714 |
? LEADING_CODE_PRIVATE_21 |
else if (! NILP (args[charset_arg_parents])) |
715 |
: LEADING_CODE_PRIVATE_22))); |
{ |
716 |
leading_code_ext = charset; |
val = args[charset_arg_parents]; |
717 |
if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes) |
CHECK_LIST (val); |
718 |
error ("Invalid dimension for the charset-ID %d", charset); |
charset.method = CHARSET_METHOD_INHERIT; |
719 |
} |
val = Fcopy_sequence (val); |
720 |
|
ASET (attrs, charset_parents, val); |
|
CHARSET_TABLE_INFO (charset, CHARSET_ID_IDX) = charset_id; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_BYTES_IDX) = make_number (bytes); |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_DIMENSION_IDX) = dimension; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_CHARS_IDX) = chars; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_WIDTH_IDX) = width; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX) = direction; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_BASE_IDX) |
|
|
= make_number (leading_code_base); |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_EXT_IDX) |
|
|
= make_number (leading_code_ext); |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_ISO_FINAL_CHAR_IDX) = iso_final_char; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_ISO_GRAPHIC_PLANE_IDX) |
|
|
= iso_graphic_plane; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_SHORT_NAME_IDX) = short_name; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX) = long_name; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_DESCRIPTION_IDX) = description; |
|
|
CHARSET_TABLE_INFO (charset, CHARSET_PLIST_IDX) = Qnil; |
|
721 |
|
|
722 |
{ |
charset.min_char = MAX_CHAR; |
723 |
/* If we have already defined a charset which has the same |
charset.max_char = 0; |
724 |
DIMENSION, CHARS and ISO-FINAL-CHAR but the different |
for (; ! NILP (val); val = Fcdr (val)) |
725 |
DIRECTION, we must update the entry REVERSE-CHARSET of both |
{ |
726 |
charsets. If there's no such charset, the value of the entry |
Lisp_Object elt, car_part, cdr_part; |
727 |
is set to nil. */ |
int this_id, offset; |
728 |
int i; |
struct charset *this_charset; |
729 |
|
|
730 |
for (i = 0; i <= MAX_CHARSET; i++) |
elt = Fcar (val); |
731 |
if (!NILP (CHARSET_TABLE_ENTRY (i))) |
if (CONSP (elt)) |
|
{ |
|
|
if (CHARSET_DIMENSION (i) == XINT (dimension) |
|
|
&& CHARSET_CHARS (i) == XINT (chars) |
|
|
&& CHARSET_ISO_FINAL_CHAR (i) == XINT (iso_final_char) |
|
|
&& CHARSET_DIRECTION (i) != XINT (direction)) |
|
732 |
{ |
{ |
733 |
CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX) |
car_part = XCAR (elt); |
734 |
= make_number (i); |
cdr_part = XCDR (elt); |
735 |
CHARSET_TABLE_INFO (i, CHARSET_REVERSE_CHARSET_IDX) = charset_id; |
CHECK_CHARSET_GET_ID (car_part, this_id); |
736 |
break; |
CHECK_NUMBER (cdr_part); |
737 |
|
offset = XINT (cdr_part); |
738 |
} |
} |
739 |
|
else |
740 |
|
{ |
741 |
|
CHECK_CHARSET_GET_ID (elt, this_id); |
742 |
|
offset = 0; |
743 |
|
} |
744 |
|
XSETCAR (val, Fcons (make_number (this_id), make_number (offset))); |
745 |
|
|
746 |
|
this_charset = CHARSET_FROM_ID (this_id); |
747 |
|
if (charset.min_char > this_charset->min_char) |
748 |
|
charset.min_char = this_charset->min_char; |
749 |
|
if (charset.max_char < this_charset->max_char) |
750 |
|
charset.max_char = this_charset->max_char; |
751 |
|
for (i = 0; i < 190; i++) |
752 |
|
charset.fast_map[i] |= this_charset->fast_map[i]; |
753 |
} |
} |
754 |
if (i > MAX_CHARSET) |
} |
755 |
/* No such a charset. */ |
else |
756 |
CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX) |
error ("None of :code-offset, :map, :parents are specified"); |
|
= make_number (-1); |
|
|
} |
|
757 |
|
|
758 |
if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC |
val = args[charset_arg_unify_map]; |
759 |
&& charset < MIN_CHARSET_PRIVATE_DIMENSION1) |
if (! NILP (val) && !STRINGP (val)) |
760 |
|
CHECK_VECTOR (val); |
761 |
|
ASET (attrs, charset_unify_map, val); |
762 |
|
|
763 |
|
CHECK_LIST (args[charset_arg_plist]); |
764 |
|
ASET (attrs, charset_plist, args[charset_arg_plist]); |
765 |
|
|
766 |
|
charset.hash_index = hash_lookup (hash_table, args[charset_arg_name], |
767 |
|
&hash_code); |
768 |
|
if (charset.hash_index >= 0) |
769 |
|
{ |
770 |
|
new_definition_p = 0; |
771 |
|
HASH_VALUE (hash_table, charset.hash_index) = attrs; |
772 |
|
} |
773 |
|
else |
774 |
{ |
{ |
775 |
bytes_by_char_head[leading_code_base] = bytes; |
charset.hash_index = hash_put (hash_table, args[charset_arg_name], attrs, |
776 |
width_by_char_head[leading_code_base] = XINT (width); |
hash_code); |
777 |
|
if (charset_table_used == charset_table_size) |
778 |
|
{ |
779 |
|
charset_table_size += 256; |
780 |
|
charset_table |
781 |
|
= ((struct charset *) |
782 |
|
xrealloc (charset_table, |
783 |
|
sizeof (struct charset) * charset_table_size)); |
784 |
|
} |
785 |
|
id = charset_table_used++; |
786 |
|
ASET (attrs, charset_id, make_number (id)); |
787 |
|
new_definition_p = 1; |
788 |
|
} |
789 |
|
|
790 |
|
|
791 |
|
charset.id = id; |
792 |
|
charset_table[id] = charset; |
793 |
|
|
794 |
/* Update table emacs_code_class. */ |
if (charset.iso_final >= 0) |
795 |
emacs_code_class[charset] = (bytes == 2 |
{ |
796 |
? EMACS_leading_code_2 |
ISO_CHARSET_TABLE (charset.dimension, charset.iso_chars_96, |
797 |
: (bytes == 3 |
charset.iso_final) = id; |
798 |
? EMACS_leading_code_3 |
if (new_definition_p) |
799 |
: EMACS_leading_code_4)); |
Viso_2022_charset_list = nconc2 (Viso_2022_charset_list, |
800 |
} |
Fcons (make_number (id), Qnil)); |
801 |
|
} |
802 |
/* Update table iso_charset_table. */ |
|
803 |
if (XINT (iso_final_char) >= 0 |
if (charset.emacs_mule_id >= 0) |
804 |
&& ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0) |
{ |
805 |
ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset; |
emacs_mule_charset[charset.emacs_mule_id] = CHARSET_FROM_ID (id); |
806 |
|
if (new_definition_p) |
807 |
|
Vemacs_mule_charset_list = nconc2 (Vemacs_mule_charset_list, |
808 |
|
Fcons (make_number (id), Qnil)); |
809 |
|
} |
810 |
|
|
811 |
|
if (new_definition_p) |
812 |
|
{ |
813 |
|
Vcharset_list = Fcons (args[charset_arg_name], Vcharset_list); |
814 |
|
Vcharset_ordered_list = nconc2 (Vcharset_ordered_list, |
815 |
|
Fcons (make_number (id), Qnil)); |
816 |
|
} |
817 |
|
|
818 |
|
return Qnil; |
819 |
} |
} |
820 |
|
|
|
#ifdef emacs |
|
821 |
|
|
822 |
/* Return charset id of CHARSET_SYMBOL, or return -1 if CHARSET_SYMBOL |
DEFUN ("define-charset-alias", Fdefine_charset_alias, |
823 |
is invalid. */ |
Sdefine_charset_alias, 2, 2, 0, |
824 |
int |
doc: /* Define ALIAS as an alias for charset CHARSET. */) |
825 |
get_charset_id (charset_symbol) |
(alias, charset) |
826 |
Lisp_Object charset_symbol; |
Lisp_Object alias, charset; |
827 |
{ |
{ |
828 |
Lisp_Object val; |
Lisp_Object attr; |
|
int charset; |
|
829 |
|
|
830 |
/* This originally used a ?: operator, but reportedly the HP-UX |
CHECK_CHARSET_GET_ATTR (charset, attr); |
831 |
compiler version HP92453-01 A.10.32.22 miscompiles that. */ |
Fputhash (alias, attr, Vcharset_hash_table); |
832 |
if (SYMBOLP (charset_symbol) |
return Qnil; |
|
&& VECTORP (val = Fget (charset_symbol, Qcharset)) |
|
|
&& CHARSET_VALID_P (charset = |
|
|
XINT (XVECTOR (val)->contents[CHARSET_ID_IDX]))) |
|
|
return charset; |
|
|
else |
|
|
return -1; |
|
833 |
} |
} |
834 |
|
|
835 |
/* Return an identification number for a new private charset of |
|
836 |
DIMENSION and WIDTH. If there's no more room for the new charset, |
DEFUN ("primary-charset", Fprimary_charset, Sprimary_charset, 0, 0, 0, |
837 |
return 0. */ |
doc: /* Return the primary charset. */) |
838 |
Lisp_Object |
() |
|
get_new_private_charset_id (dimension, width) |
|
|
int dimension, width; |
|
839 |
{ |
{ |
840 |
int charset, from, to; |
return CHARSET_NAME (CHARSET_FROM_ID (charset_primary)); |
841 |
|
} |
842 |
|
|
|
if (dimension == 1) |
|
|
{ |
|
|
from = LEADING_CODE_EXT_11; |
|
|
to = LEADING_CODE_EXT_21; |
|
|
} |
|
|
else |
|
|
{ |
|
|
from = LEADING_CODE_EXT_21; |
|
|
to = LEADING_CODE_EXT_MAX + 1; |
|
|
} |
|
843 |
|
|
844 |
for (charset = from; charset < to; charset++) |
DEFUN ("set-primary-charset", Fset_primary_charset, Sset_primary_charset, |
845 |
if (!CHARSET_DEFINED_P (charset)) break; |
1, 1, 0, |
846 |
|
doc: /* Set the primary charset to CHARSET. */) |
847 |
|
(charset) |
848 |
|
Lisp_Object charset; |
849 |
|
{ |
850 |
|
int id; |
851 |
|
|
852 |
return make_number (charset < to ? charset : 0); |
CHECK_CHARSET_GET_ID (charset, id); |
853 |
|
charset_primary = id; |
854 |
|
return Qnil; |
855 |
} |
} |
856 |
|
|
857 |
DEFUN ("define-charset", Fdefine_charset, Sdefine_charset, 3, 3, 0, |
|
858 |
doc: /* Define CHARSET-ID as the identification number of CHARSET with INFO-VECTOR. |
DEFUN ("charset-plist", Fcharset_plist, Scharset_plist, 1, 1, 0, |
859 |
If CHARSET-ID is nil, it is decided automatically, which means CHARSET is |
doc: /* Return a property list of CHARSET. */) |
860 |
treated as a private charset. |
(charset) |
861 |
INFO-VECTOR is a vector of the format: |
Lisp_Object charset; |
862 |
[DIMENSION CHARS WIDTH DIRECTION ISO-FINAL-CHAR ISO-GRAPHIC-PLANE |
{ |
863 |
SHORT-NAME LONG-NAME DESCRIPTION] |
Lisp_Object attrs; |
864 |
The meanings of each elements is as follows: |
|
865 |
DIMENSION (integer) is the number of bytes to represent a character: 1 or 2. |
CHECK_CHARSET_GET_ATTR (charset, attrs); |
866 |
CHARS (integer) is the number of characters in a dimension: 94 or 96. |
return CHARSET_ATTR_PLIST (attrs); |
|
WIDTH (integer) is the number of columns a character in the charset |
|
|
occupies on the screen: one of 0, 1, and 2. |
|
|
|
|
|
DIRECTION (integer) is the rendering direction of characters in the |
|
|
charset when rendering. If 0, render from left to right, else |
|
|
render from right to left. |
|
|
|
|
|
ISO-FINAL-CHAR (character) is the final character of the |
|
|
corresponding ISO 2022 charset. |
|
|
It may be -1 if the charset is internal use only. |
|
|
|
|
|
ISO-GRAPHIC-PLANE (integer) is the graphic plane to be invoked |
|
|
while encoding to variants of ISO 2022 coding system, one of the |
|
|
following: 0/graphic-plane-left(GL), 1/graphic-plane-right(GR). |
|
|
It may be -1 if the charset is internal use only. |
|
|
|
|
|
SHORT-NAME (string) is the short name to refer to the charset. |
|
|
|
|
|
LONG-NAME (string) is the long name to refer to the charset. |
|
|
|
|
|
DESCRIPTION (string) is the description string of the charset. */) |
|
|
(charset_id, charset_symbol, info_vector) |
|
|
Lisp_Object charset_id, charset_symbol, info_vector; |
|
|
{ |
|
|
Lisp_Object *vec; |
|
|
|
|
|
if (!NILP (charset_id)) |
|
|
CHECK_NUMBER (charset_id); |
|
|
CHECK_SYMBOL (charset_symbol); |
|
|
CHECK_VECTOR (info_vector); |
|
|
|
|
|
if (! NILP (charset_id)) |
|
|
{ |
|
|
if (! CHARSET_VALID_P (XINT (charset_id))) |
|
|
error ("Invalid CHARSET: %d", XINT (charset_id)); |
|
|
else if (CHARSET_DEFINED_P (XINT (charset_id))) |
|
|
error ("Already defined charset: %d", XINT (charset_id)); |
|
|
} |
|
|
|
|
|
vec = XVECTOR (info_vector)->contents; |
|
|
if (XVECTOR (info_vector)->size != 9 |
|
|
|| !INTEGERP (vec[0]) || !(XINT (vec[0]) == 1 || XINT (vec[0]) == 2) |
|
|
|| !INTEGERP (vec[1]) || !(XINT (vec[1]) == 94 || XINT (vec[1]) == 96) |
|
|
|| !INTEGERP (vec[2]) || !(XINT (vec[2]) == 1 || XINT (vec[2]) == 2) |
|
|
|| !INTEGERP (vec[3]) || !(XINT (vec[3]) == 0 || XINT (vec[3]) == 1) |
|
|
|| !INTEGERP (vec[4]) |
|
|
|| !(XINT (vec[4]) == -1 || (XINT (vec[4]) >= '0' && XINT (vec[4]) <= '~')) |
|
|
|| !INTEGERP (vec[5]) |
|
|
|| !(XINT (vec[5]) == -1 || XINT (vec[5]) == 0 || XINT (vec[5]) == 1) |
|
|
|| !STRINGP (vec[6]) |
|
|
|| !STRINGP (vec[7]) |
|
|
|| !STRINGP (vec[8])) |
|
|
error ("Invalid info-vector argument for defining charset %s", |
|
|
XSYMBOL (charset_symbol)->name->data); |
|
|
|
|
|
if (NILP (charset_id)) |
|
|
{ |
|
|
charset_id = get_new_private_charset_id (XINT (vec[0]), XINT (vec[2])); |
|
|
if (XINT (charset_id) == 0) |
|
|
error ("There's no room for a new private charset %s", |
|
|
XSYMBOL (charset_symbol)->name->data); |
|
|
} |
|
|
|
|
|
update_charset_table (charset_id, vec[0], vec[1], vec[2], vec[3], |
|
|
vec[4], vec[5], vec[6], vec[7], vec[8]); |
|
|
Fput (charset_symbol, Qcharset, CHARSET_TABLE_ENTRY (XINT (charset_id))); |
|
|
CHARSET_SYMBOL (XINT (charset_id)) = charset_symbol; |
|
|
Vcharset_list = Fcons (charset_symbol, Vcharset_list); |
|
|
Fupdate_coding_systems_internal (); |
|
|
return Qnil; |
|
867 |
} |
} |
868 |
|
|
869 |
DEFUN ("generic-character-list", Fgeneric_character_list, |
|
870 |
Sgeneric_character_list, 0, 0, 0, |
DEFUN ("set-charset-plist", Fset_charset_plist, Sset_charset_plist, 2, 2, 0, |
871 |
doc: /* Return a list of all possible generic characters. |
doc: /* Set CHARSET's property list to PLIST. */) |
872 |
It includes a generic character for a charset not yet defined. */) |
(charset, plist) |
873 |
() |
Lisp_Object charset, plist; |
874 |
{ |
{ |
875 |
return Vgeneric_character_list; |
Lisp_Object attrs; |
876 |
|
|
877 |
|
CHECK_CHARSET_GET_ATTR (charset, attrs); |
878 |
|
CHARSET_ATTR_PLIST (attrs) = plist; |
879 |
|
return plist; |
880 |
|
} |
881 |
|
|
882 |
|
|
883 |
|
DEFUN ("unify-charset", Funify_charset, Sunify_charset, 1, 2, 0, |
884 |
|
doc: /* Unify characters of CHARSET with Unicode. */) |
885 |
|
(charset, unify_map) |
886 |
|
Lisp_Object charset, unify_map; |
887 |
|
{ |
888 |
|
int id; |
889 |
|
struct charset *cs; |
890 |
|
|
891 |
|
CHECK_CHARSET_GET_ID (charset, id); |
892 |
|
cs = CHARSET_FROM_ID (id); |
893 |
|
if (CHARSET_METHOD (cs) == CHARSET_METHOD_MAP_DEFERRED) |
894 |
|
load_charset (cs); |
895 |
|
if (CHARSET_UNIFIED_P (cs) |
896 |
|
&& CHAR_TABLE_P (CHARSET_DEUNIFIER (cs))) |
897 |
|
return Qnil; |
898 |
|
CHARSET_UNIFIED_P (cs) = 0; |
899 |
|
if (NILP (unify_map)) |
900 |
|
unify_map = CHARSET_UNIFY_MAP (cs); |
901 |
|
if (STRINGP (unify_map)) |
902 |
|
unify_map = load_charset_map (cs, unify_map); |
903 |
|
parse_charset_map (cs, unify_map, 2); |
904 |
|
CHARSET_UNIFIED_P (cs) = 1; |
905 |
|
return Qnil; |
906 |
} |
} |
907 |
|
|
908 |
DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char, |
DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char, |
909 |
Sget_unused_iso_final_char, 2, 2, 0, |
Sget_unused_iso_final_char, 2, 2, 0, |
910 |
doc: /* Return an unsed ISO's final char for a charset of DIMENISION and CHARS. |
doc: /* |
911 |
|
Return an unsed ISO's final char for a charset of DIMENISION and CHARS. |
912 |
DIMENSION is the number of bytes to represent a character: 1 or 2. |
DIMENSION is the number of bytes to represent a character: 1 or 2. |
913 |
CHARS is the number of characters in a dimension: 94 or 96. |
CHARS is the number of characters in a dimension: 94 or 96. |
914 |
|
|
915 |
This final char is for private use, thus the range is `0' (48) .. `?' (63). |
This final char is for private use, thus the range is `0' (48) .. `?' (63). |
916 |
If there's no unused final char for the specified kind of charset, |
If there's no unused final char for the attrified kind of charset, |
917 |
return nil. */) |
return nil. */) |
918 |
(dimension, chars) |
(dimension, chars) |
919 |
Lisp_Object dimension, chars; |
Lisp_Object dimension, chars; |
922 |
|
|
923 |
CHECK_NUMBER (dimension); |
CHECK_NUMBER (dimension); |
924 |
CHECK_NUMBER (chars); |
CHECK_NUMBER (chars); |
925 |
if (XINT (dimension) != 1 && XINT (dimension) != 2) |
if (XINT (dimension) != 1 && XINT (dimension) != 2 && XINT (dimension) != 3) |
926 |
error ("Invalid charset dimension %d, it should be 1 or 2", |
args_out_of_range_3 (dimension, make_number (1), make_number (3)); |
|
XINT (dimension)); |
|
927 |
if (XINT (chars) != 94 && XINT (chars) != 96) |
if (XINT (chars) != 94 && XINT (chars) != 96) |
928 |
error ("Invalid charset chars %d, it should be 94 or 96", |
args_out_of_range_3 (chars, make_number (94), make_number (96)); |
|
XINT (chars)); |
|
929 |
for (final_char = '0'; final_char <= '?'; final_char++) |
for (final_char = '0'; final_char <= '?'; final_char++) |
930 |
{ |
if (ISO_CHARSET_TABLE (XINT (dimension), XINT (chars), final_char) < 0) |
931 |
if (ISO_CHARSET_TABLE (dimension, chars, make_number (final_char)) < 0) |
break; |
|
break; |
|
|
} |
|
932 |
return (final_char <= '?' ? make_number (final_char) : Qnil); |
return (final_char <= '?' ? make_number (final_char) : Qnil); |
933 |
} |
} |
934 |
|
|
935 |
DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset, |
static void |
936 |
4, 4, 0, |
check_iso_charset_parameter (dimension, chars, final_char) |
937 |
doc: /* Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET. |
Lisp_Object dimension, chars, final_char; |
|
CHARSET should be defined by `defined-charset' in advance. */) |
|
|
(dimension, chars, final_char, charset_symbol) |
|
|
Lisp_Object dimension, chars, final_char, charset_symbol; |
|
938 |
{ |
{ |
939 |
int charset; |
CHECK_NATNUM (dimension); |
940 |
|
CHECK_NATNUM (chars); |
941 |
|
CHECK_NATNUM (final_char); |
942 |
|
|
943 |
CHECK_NUMBER (dimension); |
if (XINT (dimension) > 3) |
944 |
CHECK_NUMBER (chars); |
error ("Invalid DIMENSION %d, it should be 1, 2, or 3", XINT (dimension)); |
|
CHECK_NUMBER (final_char); |
|
|
CHECK_SYMBOL (charset_symbol); |
|
|
|
|
|
if (XINT (dimension) != 1 && XINT (dimension) != 2) |
|
|
error ("Invalid DIMENSION %d, it should be 1 or 2", XINT (dimension)); |
|
945 |
if (XINT (chars) != 94 && XINT (chars) != 96) |
if (XINT (chars) != 94 && XINT (chars) != 96) |
946 |
error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars)); |
error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars)); |
947 |
if (XINT (final_char) < '0' || XFASTINT (final_char) > '~') |
if (XINT (final_char) < '0' || XINT (final_char) > '~') |
948 |
error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars)); |
error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars)); |
949 |
if ((charset = get_charset_id (charset_symbol)) < 0) |
} |
950 |
error ("Invalid charset %s", XSYMBOL (charset_symbol)->name->data); |
|
951 |
|
|
952 |
ISO_CHARSET_TABLE (dimension, chars, final_char) = charset; |
DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset, |
953 |
|
4, 4, 0, |
954 |
|
doc: /* |
955 |
|
Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET. |
956 |
|
CHARSET should be defined by `defined-charset' in advance. */) |
957 |
|
(dimension, chars, final_char, charset) |
958 |
|
Lisp_Object dimension, chars, final_char, charset; |
959 |
|
{ |
960 |
|
int id; |
961 |
|
|
962 |
|
CHECK_CHARSET_GET_ID (charset, id); |
963 |
|
check_iso_charset_parameter (dimension, chars, final_char); |
964 |
|
|
965 |
|
ISO_CHARSET_TABLE (dimension, chars, final_char) = id; |
966 |
return Qnil; |
return Qnil; |
967 |
} |
} |
968 |
|
|
969 |
|
|
970 |
/* Return information about charsets in the text at PTR of NBYTES |
/* Return information about charsets in the text at PTR of NBYTES |
971 |
bytes, which are NCHARS characters. The value is: |
bytes, which are NCHARS characters. The value is: |
972 |
|
|
973 |
0: Each character is represented by one byte. This is always |
0: Each character is represented by one byte. This is always |
974 |
true for unibyte text. |
true for a unibyte string. For a multibyte string, true if |
975 |
1: No charsets other than ascii eight-bit-control, |
it contains only ASCII characters. |
|
eight-bit-graphic, and latin-1 are found. |
|
|
2: Otherwise. |
|
976 |
|
|
977 |
In addition, if CHARSETS is nonzero, for each found charset N, set |
1: No charsets other than ascii, eight-bit-control, and |
978 |
CHARSETS[N] to 1. For that, callers should allocate CHARSETS |
latin-1 are found. |
979 |
(MAX_CHARSET + 1 elements) in advance. It may lookup a translation |
|
980 |
table TABLE if supplied. For invalid charsets, set CHARSETS[1] to |
2: Otherwise. |
981 |
1 (note that there's no charset whose ID is 1). */ |
*/ |
982 |
|
|
983 |
int |
int |
984 |
find_charset_in_text (ptr, nchars, nbytes, charsets, table) |
string_xstring_p (string) |
985 |
unsigned char *ptr; |
Lisp_Object string; |
|
int nchars, nbytes, *charsets; |
|
|
Lisp_Object table; |
|
986 |
{ |
{ |
987 |
if (nchars == nbytes) |
unsigned char *p = XSTRING (string)->data; |
988 |
|
unsigned char *endp = p + STRING_BYTES (XSTRING (string)); |
989 |
|
struct charset *charset; |
990 |
|
|
991 |
|
if (XSTRING (string)->size == STRING_BYTES (XSTRING (string))) |
992 |
|
return 0; |
993 |
|
|
994 |
|
charset = CHARSET_FROM_ID (charset_iso_8859_1); |
995 |
|
while (p < endp) |
996 |
{ |
{ |
997 |
if (charsets && nbytes > 0) |
int c = STRING_CHAR_ADVANCE (p); |
|
{ |
|
|
unsigned char *endp = ptr + nbytes; |
|
|
int maskbits = 0; |
|
998 |
|
|
999 |
while (ptr < endp && maskbits != 7) |
if (ENCODE_CHAR (charset, c) < 0) |
1000 |
{ |
return 2; |
|
maskbits |= (*ptr < 0x80 ? 1 : *ptr < 0xA0 ? 2 : 4); |
|
|
ptr++; |
|
|
} |
|
|
|
|
|
if (maskbits & 1) |
|
|
charsets[CHARSET_ASCII] = 1; |
|
|
if (maskbits & 2) |
|
|
charsets[CHARSET_8_BIT_CONTROL] = 1; |
|
|
if (maskbits & 4) |
|
|
charsets[CHARSET_8_BIT_GRAPHIC] = 1; |
|
|
} |
|
|
return 0; |
|
1001 |
} |
} |
1002 |
else |
return 1; |
1003 |
{ |
} |
|
int return_val = 1; |
|
|
int bytes, charset, c1, c2; |
|
1004 |
|
|
|
if (! CHAR_TABLE_P (table)) |
|
|
table = Qnil; |
|
1005 |
|
|
1006 |
while (nchars-- > 0) |
/* Find charsets in the string at PTR of NCHARS and NBYTES. |
1007 |
{ |
|
1008 |
SPLIT_MULTIBYTE_SEQ (ptr, len, bytes, charset, c1, c2); |
CHARSETS is a vector. Each element is a cons of CHARSET and |
1009 |
ptr += bytes; |
FOUND-FLAG. CHARSET is a charset id, and FOUND-FLAG is nil or t. |
1010 |
|
FOUND-FLAG t (or nil) means that the corresponding charset is |
1011 |
|
already found (or not yet found). |
1012 |
|
|
1013 |
|
It may lookup a translation table TABLE if supplied. */ |
1014 |
|
|
1015 |
|
static void |
1016 |
|
find_charsets_in_text (ptr, nchars, nbytes, charsets, table) |
1017 |
|
unsigned char *ptr; |
1018 |
|
int nchars, nbytes; |
1019 |
|
Lisp_Object charsets, table; |
1020 |
|
{ |
1021 |
|
unsigned char *pend = ptr + nbytes; |
1022 |
|
int ncharsets = ASIZE (charsets); |
1023 |
|
|
1024 |
if (!CHARSET_DEFINED_P (charset)) |
if (nchars == nbytes) |
1025 |
charset = 1; |
return; |
1026 |
else if (! NILP (table)) |
|
1027 |
|
while (ptr < pend) |
1028 |
|
{ |
1029 |
|
int c = STRING_CHAR_ADVANCE (ptr); |
1030 |
|
int i; |
1031 |
|
int all_found = 1; |
1032 |
|
Lisp_Object elt; |
1033 |
|
|
1034 |
|
if (!NILP (table)) |
1035 |
|
c = translate_char (table, c); |
1036 |
|
for (i = 0; i < ncharsets; i++) |
1037 |
|
{ |
1038 |
|
elt = AREF (charsets, i); |
1039 |
|
if (NILP (XCDR (elt))) |
1040 |
{ |
{ |
1041 |
int c = translate_char (table, -1, charset, c1, c2); |
struct charset *charset = CHARSET_FROM_ID (XINT (XCAR (elt))); |
|
if (c >= 0) |
|
|
charset = CHAR_CHARSET (c); |
|
|
} |
|
1042 |
|
|
1043 |
if (return_val == 1 |
if (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)) |
1044 |
&& charset != CHARSET_ASCII |
XCDR (elt) = Qt; |
1045 |
&& charset != CHARSET_8_BIT_CONTROL |
else |
1046 |
&& charset != CHARSET_8_BIT_GRAPHIC |
all_found = 0; |
1047 |
&& charset != charset_latin_iso8859_1) |
} |
|
return_val = 2; |
|
|
|
|
|
if (charsets) |
|
|
charsets[charset] = 1; |
|
|
else if (return_val == 2) |
|
|
break; |
|
1048 |
} |
} |
1049 |
return return_val; |
if (all_found) |
1050 |
|
break; |
1051 |
} |
} |
1052 |
} |
} |
1053 |
|
|
1054 |
|
|
1055 |
DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region, |
DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region, |
1056 |
2, 3, 0, |
2, 3, 0, |
1057 |
doc: /* Return a list of charsets in the region between BEG and END. |
doc: /* Return a list of charsets in the region between BEG and END. |
1066 |
(beg, end, table) |
(beg, end, table) |
1067 |
Lisp_Object beg, end, table; |
Lisp_Object beg, end, table; |
1068 |
{ |
{ |
1069 |
int charsets[MAX_CHARSET + 1]; |
Lisp_Object charsets; |
1070 |
int from, from_byte, to, stop, stop_byte, i; |
int from, from_byte, to, stop, stop_byte, i; |
1071 |
Lisp_Object val; |
Lisp_Object val; |
1072 |
|
|
1084 |
|
|
1085 |
from_byte = CHAR_TO_BYTE (from); |
from_byte = CHAR_TO_BYTE (from); |
1086 |
|
|
1087 |
bzero (charsets, (MAX_CHARSET + 1) * sizeof (int)); |
charsets = Fmake_vector (make_number (charset_table_used), Qnil); |
1088 |
|
for (i = 0; i < charset_table_used; i++) |
1089 |
|
ASET (charsets, i, Fcons (make_number (i), Qnil)); |
1090 |
|
|
1091 |
while (1) |
while (1) |
1092 |
{ |
{ |
1093 |
find_charset_in_text (BYTE_POS_ADDR (from_byte), stop - from, |
find_charsets_in_text (BYTE_POS_ADDR (from_byte), stop - from, |
1094 |
stop_byte - from_byte, charsets, table); |
stop_byte - from_byte, charsets, table); |
1095 |
if (stop < to) |
if (stop < to) |
1096 |
{ |
{ |
1097 |
from = stop, from_byte = stop_byte; |
from = stop, from_byte = stop_byte; |
1102 |
} |
} |
1103 |
|
|
1104 |
val = Qnil; |
val = Qnil; |
1105 |
if (charsets[1]) |
for (i = charset_table_used - 1; i >= 0; i--) |
1106 |
val = Fcons (Qunknown, val); |
if (!NILP (XCDR (AREF (charsets, i)))) |
1107 |
for (i = MAX_CHARSET; i >= MIN_CHARSET_OFFICIAL_DIMENSION1; i--) |
val = Fcons (CHARSET_NAME (charset_table + i), val); |
|
if (charsets[i]) |
|
|
val = Fcons (CHARSET_SYMBOL (i), val); |
|
|
if (charsets[0]) |
|
|
val = Fcons (Qascii, val); |
|
1108 |
return val; |
return val; |
1109 |
} |
} |
1110 |
|
|
1117 |
`unknown' is included in the returned list. |
`unknown' is included in the returned list. |
1118 |
|
|
1119 |
If STR is unibyte, the returned list may contain |
If STR is unibyte, the returned list may contain |
1120 |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
1121 |
(str, table) |
(str, table) |
1122 |
Lisp_Object str, table; |
Lisp_Object str, table; |
1123 |
{ |
{ |
1124 |
int charsets[MAX_CHARSET + 1]; |
Lisp_Object charsets; |
1125 |
int i; |
int i; |
1126 |
Lisp_Object val; |
Lisp_Object val; |
1127 |
|
|
1128 |
CHECK_STRING (str); |
CHECK_STRING (str); |
1129 |
|
|
1130 |
bzero (charsets, (MAX_CHARSET + 1) * sizeof (int)); |
charsets = Fmake_vector (make_number (charset_table_used), Qnil); |
1131 |
find_charset_in_text (XSTRING (str)->data, XSTRING (str)->size, |
find_charsets_in_text (XSTRING (str)->data, XSTRING (str)->size, |
1132 |
STRING_BYTES (XSTRING (str)), charsets, table); |
STRING_BYTES (XSTRING (str)), charsets, table); |
1133 |
|
|
1134 |
val = Qnil; |
val = Qnil; |
1135 |
if (charsets[1]) |
for (i = charset_table_used - 1; i >= 0; i--) |
1136 |
val = Fcons (Qunknown, val); |
if (!NILP (XCDR (AREF (charsets, i)))) |
1137 |
for (i = MAX_CHARSET; i >= MIN_CHARSET_OFFICIAL_DIMENSION1; i--) |
val = Fcons (CHARSET_NAME (charset_table + i), val); |
|
if (charsets[i]) |
|
|
val = Fcons (CHARSET_SYMBOL (i), val); |
|
|
if (charsets[0]) |
|
|
val = Fcons (Qascii, val); |
|
1138 |
return val; |
return val; |
1139 |
} |
} |
1140 |
|
|
1141 |
|
|
|
DEFUN ("make-char-internal", Fmake_char_internal, Smake_char_internal, 1, 3, 0, |
|
|
doc: /* Return a character made from arguments. |
|
|
Internal use only. */) |
|
|
(charset, code1, code2) |
|
|
Lisp_Object charset, code1, code2; |
|
|
{ |
|
|
int charset_id, c1, c2; |
|
|
|
|
|
CHECK_NUMBER (charset); |
|
|
charset_id = XINT (charset); |
|
|
if (!CHARSET_DEFINED_P (charset_id)) |
|
|
error ("Invalid charset ID: %d", XINT (charset)); |
|
1142 |
|
|
1143 |
if (NILP (code1)) |
/* Return a character correponding to the code-point CODE of |
1144 |
c1 = 0; |
CHARSET. */ |
1145 |
else |
|
1146 |
{ |
int |
1147 |
CHECK_NUMBER (code1); |
decode_char (charset, code) |
1148 |
c1 = XINT (code1); |
struct charset *charset; |
1149 |
} |
unsigned code; |
1150 |
if (NILP (code2)) |
{ |
1151 |
c2 = 0; |
int c, char_index; |
1152 |
else |
enum charset_method method = CHARSET_METHOD (charset); |
1153 |
|
|
1154 |
|
if (code < CHARSET_MIN_CODE (charset) || code > CHARSET_MAX_CODE (charset)) |
1155 |
|
return -1; |
1156 |
|
|
1157 |
|
if (method == CHARSET_METHOD_MAP_DEFERRED) |
1158 |
{ |
{ |
1159 |
CHECK_NUMBER (code2); |
load_charset (charset); |
1160 |
c2 = XINT (code2); |
method = CHARSET_METHOD (charset); |
1161 |
} |
} |
1162 |
|
|
1163 |
if (charset_id == CHARSET_ASCII) |
if (method == CHARSET_METHOD_INHERIT) |
1164 |
{ |
{ |
1165 |
if (c1 < 0 || c1 > 0x7F) |
Lisp_Object parents; |
|
goto invalid_code_posints; |
|
|
return make_number (c1); |
|
|
} |
|
|
else if (charset_id == CHARSET_8_BIT_CONTROL) |
|
|
{ |
|
|
if (NILP (code1)) |
|
|
c1 = 0x80; |
|
|
else if (c1 < 0x80 || c1 > 0x9F) |
|
|
goto invalid_code_posints; |
|
|
return make_number (c1); |
|
|
} |
|
|
else if (charset_id == CHARSET_8_BIT_GRAPHIC) |
|
|
{ |
|
|
if (NILP (code1)) |
|
|
c1 = 0xA0; |
|
|
else if (c1 < 0xA0 || c1 > 0xFF) |
|
|
goto invalid_code_posints; |
|
|
return make_number (c1); |
|
|
} |
|
|
else if (c1 < 0 || c1 > 0xFF || c2 < 0 || c2 > 0xFF) |
|
|
goto invalid_code_posints; |
|
|
c1 &= 0x7F; |
|
|
c2 &= 0x7F; |
|
|
if (c1 == 0 |
|
|
? c2 != 0 |
|
|
: (c2 == 0 |
|
|
? !CHAR_COMPONENTS_VALID_P (charset_id, c1, 0x20) |
|
|
: !CHAR_COMPONENTS_VALID_P (charset_id, c1, c2))) |
|
|
goto invalid_code_posints; |
|
|
return make_number (MAKE_CHAR (charset_id, c1, c2)); |
|
1166 |
|
|
1167 |
invalid_code_posints: |
parents = CHARSET_PARENTS (charset); |
1168 |
error ("Invalid code points for charset ID %d: %d %d", charset_id, c1, c2); |
c = -1; |
1169 |
} |
for (; CONSP (parents); parents = XCDR (parents)) |
1170 |
|
{ |
1171 |
|
int id = XINT (XCAR (XCAR (parents))); |
1172 |
|
int code_offset = XINT (XCDR (XCAR (parents))); |
1173 |
|
unsigned this_code = code + code_offset; |
1174 |
|
|
1175 |
DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0, |
charset = CHARSET_FROM_ID (id); |
1176 |
doc: /* Return list of charset and one or two position-codes of CHAR. |
if ((c = DECODE_CHAR (charset, this_code)) >= 0) |
1177 |
If CHAR is invalid as a character code, |
break; |
1178 |
return a list of symbol `unknown' and CHAR. */) |
} |
1179 |
(ch) |
} |
1180 |
Lisp_Object ch; |
else |
1181 |
{ |
{ |
1182 |
int c, charset, c1, c2; |
char_index = CODE_POINT_TO_INDEX (charset, code); |
1183 |
|
|
1184 |
CHECK_NUMBER (ch); |
if (method == CHARSET_METHOD_MAP) |
1185 |
c = XFASTINT (ch); |
{ |
1186 |
if (!CHAR_VALID_P (c, 1)) |
Lisp_Object decoder; |
|
return Fcons (Qunknown, Fcons (ch, Qnil)); |
|
|
SPLIT_CHAR (XFASTINT (ch), charset, c1, c2); |
|
|
return (c2 >= 0 |
|
|
? Fcons (CHARSET_SYMBOL (charset), |
|
|
Fcons (make_number (c1), Fcons (make_number (c2), Qnil))) |
|
|
: Fcons (CHARSET_SYMBOL (charset), Fcons (make_number (c1), Qnil))); |
|
|
} |
|
1187 |
|
|
1188 |
DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0, |
decoder = CHARSET_DECODER (charset); |
1189 |
doc: /* Return charset of CHAR. */) |
if (! VECTORP (decoder)) |
1190 |
(ch) |
return -1; |
1191 |
Lisp_Object ch; |
c = XINT (AREF (decoder, char_index)); |
1192 |
{ |
} |
1193 |
CHECK_NUMBER (ch); |
else |
1194 |
|
{ |
1195 |
|
c = char_index + CHARSET_CODE_OFFSET (charset); |
1196 |
|
} |
1197 |
|
} |
1198 |
|
|
1199 |
return CHARSET_SYMBOL (CHAR_CHARSET (XINT (ch))); |
if (CHARSET_UNIFIED_P (charset) |
1200 |
} |
&& c >= 0) |
1201 |
|
MAYBE_UNIFY_CHAR (c); |
1202 |
|
|
1203 |
DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0, |
return c; |
|
doc: /* Return charset of a character in the current buffer at position POS. |
|
|
If POS is nil, it defauls to the current point. |
|
|
If POS is out of range, the value is nil. */) |
|
|
(pos) |
|
|
Lisp_Object pos; |
|
|
{ |
|
|
Lisp_Object ch; |
|
|
int charset; |
|
|
|
|
|
ch = Fchar_after (pos); |
|
|
if (! INTEGERP (ch)) |
|
|
return ch; |
|
|
charset = CHAR_CHARSET (XINT (ch)); |
|
|
return CHARSET_SYMBOL (charset); |
|
1204 |
} |
} |
1205 |
|
|
|
DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0, |
|
|
doc: /* Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR. |
|
|
|
|
|
ISO 2022's designation sequence (escape sequence) distinguishes charsets |
|
|
by their DIMENSION, CHARS, and FINAL-CHAR, |
|
|
where as Emacs distinguishes them by charset symbol. |
|
|
See the documentation of the function `charset-info' for the meanings of |
|
|
DIMENSION, CHARS, and FINAL-CHAR. */) |
|
|
(dimension, chars, final_char) |
|
|
Lisp_Object dimension, chars, final_char; |
|
|
{ |
|
|
int charset; |
|
|
|
|
|
CHECK_NUMBER (dimension); |
|
|
CHECK_NUMBER (chars); |
|
|
CHECK_NUMBER (final_char); |
|
1206 |
|
|
1207 |
if ((charset = ISO_CHARSET_TABLE (dimension, chars, final_char)) < 0) |
/* Return a code-point of CHAR in CHARSET. If CHAR doesn't belong to |
1208 |
return Qnil; |
CHARSET, return CHARSET_INVALID_CODE (CHARSET). */ |
|
return CHARSET_SYMBOL (charset); |
|
|
} |
|
1209 |
|
|
1210 |
/* If GENERICP is nonzero, return nonzero iff C is a valid normal or |
unsigned |
1211 |
generic character. If GENERICP is zero, return nonzero iff C is a |
encode_char (charset, c) |
1212 |
valid normal character. Do not call this function directly, |
struct charset *charset; |
1213 |
instead use macro CHAR_VALID_P. */ |
int c; |
|
int |
|
|
char_valid_p (c, genericp) |
|
|
int c, genericp; |
|
1214 |
{ |
{ |
1215 |
int charset, c1, c2; |
unsigned code; |
1216 |
|
enum charset_method method = CHARSET_METHOD (charset); |
1217 |
|
|
1218 |
if (c < 0 || c >= MAX_CHAR) |
if (CHARSET_UNIFIED_P (charset)) |
|
return 0; |
|
|
if (SINGLE_BYTE_CHAR_P (c)) |
|
|
return 1; |
|
|
SPLIT_CHAR (c, charset, c1, c2); |
|
|
if (genericp) |
|
1219 |
{ |
{ |
1220 |
if (c1) |
Lisp_Object deunifier; |
1221 |
{ |
int deunified; |
1222 |
if (c2 <= 0) c2 = 0x20; |
|
1223 |
} |
deunifier = CHARSET_DEUNIFIER (charset); |
1224 |
else |
if (! CHAR_TABLE_P (deunifier)) |
1225 |
{ |
{ |
1226 |
if (c2 <= 0) c1 = c2 = 0x20; |
Funify_charset (CHARSET_NAME (charset), Qnil); |
1227 |
|
deunifier = CHARSET_DEUNIFIER (charset); |
1228 |
} |
} |
1229 |
|
deunified = XINT (CHAR_TABLE_REF (deunifier, c)); |
1230 |
|
if (deunified > 0) |
1231 |
|
c = deunified; |
1232 |
} |
} |
|
return (CHARSET_DEFINED_P (charset) |
|
|
&& CHAR_COMPONENTS_VALID_P (charset, c1, c2)); |
|
|
} |
|
1233 |
|
|
1234 |
DEFUN ("char-valid-p", Fchar_valid_p, Schar_valid_p, 1, 2, 0, |
if (! CHARSET_FAST_MAP_REF ((c), charset->fast_map) |
1235 |
doc: /* Return t if OBJECT is a valid normal character. |
|| c < CHARSET_MIN_CHAR (charset) || c > CHARSET_MAX_CHAR (charset)) |
1236 |
If optional arg GENERICP is non-nil, also return t if OBJECT is |
return CHARSET_INVALID_CODE (charset); |
|
a valid generic character. */) |
|
|
(object, genericp) |
|
|
Lisp_Object object, genericp; |
|
|
{ |
|
|
if (! NATNUMP (object)) |
|
|
return Qnil; |
|
|
return (CHAR_VALID_P (XFASTINT (object), !NILP (genericp)) ? Qt : Qnil); |
|
|
} |
|
1237 |
|
|
1238 |
DEFUN ("unibyte-char-to-multibyte", Funibyte_char_to_multibyte, |
if (method == CHARSET_METHOD_INHERIT) |
1239 |
Sunibyte_char_to_multibyte, 1, 1, 0, |
{ |
1240 |
doc: /* Convert the unibyte character CH to multibyte character. |
Lisp_Object parents; |
|
The conversion is done based on `nonascii-translation-table' (which see) |
|
|
or `nonascii-insert-offset' (which see). */) |
|
|
(ch) |
|
|
Lisp_Object ch; |
|
|
{ |
|
|
int c; |
|
|
|
|
|
CHECK_NUMBER (ch); |
|
|
c = XINT (ch); |
|
|
if (c < 0 || c >= 0400) |
|
|
error ("Invalid unibyte character: %d", c); |
|
|
c = unibyte_char_to_multibyte (c); |
|
|
if (c < 0) |
|
|
error ("Can't convert to multibyte character: %d", XINT (ch)); |
|
|
return make_number (c); |
|
|
} |
|
1241 |
|
|
1242 |
DEFUN ("multibyte-char-to-unibyte", Fmultibyte_char_to_unibyte, |
parents = CHARSET_PARENTS (charset); |
1243 |
Smultibyte_char_to_unibyte, 1, 1, 0, |
for (; CONSP (parents); parents = XCDR (parents)) |
1244 |
doc: /* Convert the multibyte character CH to unibyte character. |
{ |
1245 |
The conversion is done based on `nonascii-translation-table' (which see) |
int id = XINT (XCAR (XCAR (parents))); |
1246 |
or `nonascii-insert-offset' (which see). */) |
int code_offset = XINT (XCDR (XCAR (parents))); |
1247 |
(ch) |
struct charset *this_charset = CHARSET_FROM_ID (id); |
|
Lisp_Object ch; |
|
|
{ |
|
|
int c; |
|
1248 |
|
|
1249 |
CHECK_NUMBER (ch); |
code = ENCODE_CHAR (this_charset, c); |
1250 |
c = XINT (ch); |
if (code != CHARSET_INVALID_CODE (this_charset) |
1251 |
if (! CHAR_VALID_P (c, 0)) |
&& (code_offset < 0 || code >= code_offset)) |
1252 |
error ("Invalid multibyte character: %d", c); |
{ |
1253 |
c = multibyte_char_to_unibyte (c, Qnil); |
code -= code_offset; |
1254 |
if (c < 0) |
if (CODE_POINT_TO_INDEX (charset, code) >= 0) |
1255 |
error ("Can't convert to unibyte character: %d", XINT (ch)); |
return code; |
1256 |
return make_number (c); |
} |
1257 |
} |
} |
1258 |
|
return CHARSET_INVALID_CODE (charset); |
1259 |
|
} |
1260 |
|
|
1261 |
DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0, |
if (method == CHARSET_METHOD_MAP_DEFERRED) |
1262 |
doc: /* Return 1 regardless of the argument CHAR. |
{ |
1263 |
This is now an obsolete function. We keep it just for backward compatibility. */) |
load_charset (charset); |
1264 |
(ch) |
method = CHARSET_METHOD (charset); |
1265 |
Lisp_Object ch; |
} |
|
{ |
|
|
CHECK_NUMBER (ch); |
|
|
return make_number (1); |
|
|
} |
|
1266 |
|
|
1267 |
/* Return how many bytes C will occupy in a multibyte buffer. |
if (method == CHARSET_METHOD_MAP) |
1268 |
Don't call this function directly, instead use macro CHAR_BYTES. */ |
{ |
1269 |
int |
Lisp_Object encoder; |
1270 |
char_bytes (c) |
Lisp_Object val; |
|
int c; |
|
|
{ |
|
|
int charset; |
|
1271 |
|
|
1272 |
if (ASCII_BYTE_P (c) || (c & ~((1 << CHARACTERBITS) -1))) |
encoder = CHARSET_ENCODER (charset); |
1273 |
return 1; |
if (! CHAR_TABLE_P (CHARSET_ENCODER (charset))) |
1274 |
if (SINGLE_BYTE_CHAR_P (c) && c >= 0xA0) |
return CHARSET_INVALID_CODE (charset); |
1275 |
return 1; |
val = CHAR_TABLE_REF (encoder, c); |
1276 |
|
if (CONSP (val)) |
1277 |
|
code = (XINT (XCAR (val)) << 16) | XINT (XCDR (val)); |
1278 |
|
else |
1279 |
|
code = XINT (val); |
1280 |
|
} |
1281 |
|
else |
1282 |
|
{ |
1283 |
|
code = c - CHARSET_CODE_OFFSET (charset); |
1284 |
|
code = INDEX_TO_CODE_POINT (charset, code); |
1285 |
|
} |
1286 |
|
|
1287 |
charset = CHAR_CHARSET (c); |
return code; |
|
return (CHARSET_DEFINED_P (charset) ? CHARSET_BYTES (charset) : 1); |
|
1288 |
} |
} |
1289 |
|
|
|
/* Return the width of character of which multi-byte form starts with |
|
|
C. The width is measured by how many columns occupied on the |
|
|
screen when displayed in the current buffer. */ |
|
|
|
|
|
#define ONE_BYTE_CHAR_WIDTH(c) \ |
|
|
(c < 0x20 \ |
|
|
? (c == '\t' \ |
|
|
? XFASTINT (current_buffer->tab_width) \ |
|
|
: (c == '\n' ? 0 : (NILP (current_buffer->ctl_arrow) ? 4 : 2))) \ |
|
|
: (c < 0x7f \ |
|
|
? 1 \ |
|
|
: (c == 0x7F \ |
|
|
? (NILP (current_buffer->ctl_arrow) ? 4 : 2) \ |
|
|
: ((! NILP (current_buffer->enable_multibyte_characters) \ |
|
|
&& BASE_LEADING_CODE_P (c)) \ |
|
|
? WIDTH_BY_CHAR_HEAD (c) \ |
|
|
: 4)))) |
|
|
|
|
|
DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0, |
|
|
doc: /* Return width of CHAR when displayed in the current buffer. |
|
|
The width is measured by how many columns it occupies on the screen. |
|
|
Tab is taken to occupy `tab-width' columns. */) |
|
|
(ch) |
|
|
Lisp_Object ch; |
|
|
{ |
|
|
Lisp_Object val, disp; |
|
|
int c; |
|
|
struct Lisp_Char_Table *dp = buffer_display_table (); |
|
1290 |
|
|
1291 |
CHECK_NUMBER (ch); |
DEFUN ("decode-char", Fdecode_char, Sdecode_char, 2, 3, 0, |
1292 |
|
doc: /* Decode the pair of CHARSET and CODE-POINT into a character. |
1293 |
|
Return nil if CODE-POINT is not valid in CHARSET. |
1294 |
|
|
1295 |
c = XINT (ch); |
CODE-POINT may be a cons (HIGHER-16-BIT-VALUE . LOWER-16-BIT-VALUE). |
1296 |
|
|
1297 |
/* Get the way the display table would display it. */ |
Optional argument RESTRICTION specifies a way to map the pair of CCS |
1298 |
disp = dp ? DISP_CHAR_VECTOR (dp, c) : Qnil; |
and CODE-POINT to a chracter. Currently not supported and just ignored. */) |
1299 |
|
(charset, code_point, restriction) |
1300 |
|
Lisp_Object charset, code_point, restriction; |
1301 |
|
{ |
1302 |
|
int c, id; |
1303 |
|
unsigned code; |
1304 |
|
struct charset *charsetp; |
1305 |
|
|
1306 |
if (VECTORP (disp)) |
CHECK_CHARSET_GET_ID (charset, id); |
1307 |
XSETINT (val, XVECTOR (disp)->size); |
if (CONSP (code_point)) |
1308 |
else if (SINGLE_BYTE_CHAR_P (c)) |
{ |
1309 |
XSETINT (val, ONE_BYTE_CHAR_WIDTH (c)); |
CHECK_NATNUM (XCAR (code_point)); |
1310 |
|
CHECK_NATNUM (XCDR (code_point)); |
1311 |
|
code = (XINT (XCAR (code_point)) << 16) | (XINT (XCAR (code_point))); |
1312 |
|
} |
1313 |
else |
else |
1314 |
{ |
{ |
1315 |
int charset = CHAR_CHARSET (c); |
CHECK_NATNUM (code_point); |
1316 |
|
code = XINT (code_point); |
|
XSETFASTINT (val, CHARSET_WIDTH (charset)); |
|
1317 |
} |
} |
1318 |
return val; |
charsetp = CHARSET_FROM_ID (id); |
1319 |
|
c = DECODE_CHAR (charsetp, code); |
1320 |
|
return (c >= 0 ? make_number (c) : Qnil); |
1321 |
} |
} |
1322 |
|
|
|
/* Return width of string STR of length LEN when displayed in the |
|
|
current buffer. The width is measured by how many columns it |
|
|
occupies on the screen. */ |
|
1323 |
|
|
1324 |
int |
DEFUN ("encode-char", Fencode_char, Sencode_char, 2, 3, 0, |
1325 |
strwidth (str, len) |
doc: /* Encode the character CH into a code-point of CHARSET. |
1326 |
unsigned char *str; |
Return nil if CHARSET doesn't include CH. |
1327 |
int len; |
|
1328 |
{ |
Optional argument RESTRICTION specifies a way to map CHAR to a |
1329 |
return c_string_width (str, len, -1, NULL, NULL); |
code-point in CCS. Currently not supported and just ignored. */) |
1330 |
|
(ch, charset, restriction) |
1331 |
|
Lisp_Object ch, charset, restriction; |
1332 |
|
{ |
1333 |
|
int c, id; |
1334 |
|
unsigned code; |
1335 |
|
struct charset *charsetp; |
1336 |
|
|
1337 |
|
CHECK_CHARSET_GET_ID (charset, id); |
1338 |
|
CHECK_NATNUM (ch); |
1339 |
|
c = XINT (ch); |
1340 |
|
charsetp = CHARSET_FROM_ID (id); |
1341 |
|
code = ENCODE_CHAR (charsetp, ch); |
1342 |
|
if (code == CHARSET_INVALID_CODE (charsetp)) |
1343 |
|
return Qnil; |
1344 |
|
if (code > 0x7FFFFFF) |
1345 |
|
return Fcons (make_number (code >> 16), make_number (code & 0xFFFF)); |
1346 |
|
return make_number (code); |
1347 |
} |
} |
1348 |
|
|
|
/* Return width of string STR of length LEN when displayed in the |
|
|
current buffer. The width is measured by how many columns it |
|
|
occupies on the screen. If PRECISION > 0, return the width of |
|
|
longest substring that doesn't exceed PRECISION, and set number of |
|
|
characters and bytes of the substring in *NCHARS and *NBYTES |
|
|
respectively. */ |
|
1349 |
|
|
1350 |
int |
DEFUN ("make-char", Fmake_char, Smake_char, 1, 4, 0, |
1351 |
c_string_width (str, len, precision, nchars, nbytes) |
doc: /* Return a character of CHARSET whose position code is CODE. |
|
unsigned char *str; |
|
|
int precision, *nchars, *nbytes; |
|
|
{ |
|
|
int i = 0, i_byte = 0; |
|
|
int width = 0; |
|
|
int chars; |
|
|
struct Lisp_Char_Table *dp = buffer_display_table (); |
|
1352 |
|
|
1353 |
while (i_byte < len) |
If dimension of CHARSET is two, and the third optional arg CODE2 is |
1354 |
{ |
non-nil, CODE actually specifies the first byte of the position code, |
1355 |
int bytes, thiswidth; |
and CODE2 specifies the second byte. |
|
Lisp_Object val; |
|
1356 |
|
|
1357 |
if (dp) |
If dimension of CHARSET is three, and the third optional arg CODE2 and |
1358 |
{ |
the fourth optional arg CODE3 are both non-nil, CODE actually |
1359 |
int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes); |
specifies the first byte of the position code, CODE2 the second byte, |
1360 |
|
and CODE3 the third byte. */) |
1361 |
|
(charset, code, code2, code3) |
1362 |
|
Lisp_Object charset, code, code2, code3; |
1363 |
|
{ |
1364 |
|
int id, dimension; |
1365 |
|
struct charset *charsetp; |
1366 |
|
unsigned c; |
1367 |
|
|
1368 |
chars = 1; |
CHECK_CHARSET_GET_ID (charset, id); |
1369 |
val = DISP_CHAR_VECTOR (dp, c); |
charsetp = CHARSET_FROM_ID (id); |
1370 |
if (VECTORP (val)) |
|
1371 |
thiswidth = XVECTOR (val)->size; |
if (NILP (code)) |
1372 |
else |
code = make_number (CHARSET_MIN_CODE (charsetp)); |
1373 |
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
else |
1374 |
} |
{ |
1375 |
else |
CHECK_NATNUM (code); |
1376 |
{ |
dimension = CHARSET_DIMENSION (charsetp); |
|
chars = 1; |
|
|
PARSE_MULTIBYTE_SEQ (str + i_byte, len - i_byte, bytes); |
|
|
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
|
|
} |
|
1377 |
|
|
1378 |
if (precision > 0 |
if (!NILP (code2)) |
|
&& (width + thiswidth > precision)) |
|
1379 |
{ |
{ |
1380 |
*nchars = i; |
CHECK_NATNUM (code2); |
1381 |
*nbytes = i_byte; |
if (dimension == 3) |
1382 |
return width; |
CHECK_NATNUM (code3); |
1383 |
} |
} |
|
i++; |
|
|
i_byte += bytes; |
|
|
width += thiswidth; |
|
|
} |
|
|
|
|
|
if (precision > 0) |
|
|
{ |
|
|
*nchars = i; |
|
|
*nbytes = i_byte; |
|
1384 |
} |
} |
1385 |
|
|
1386 |
return width; |
if (dimension == 1 || NILP (code2)) |
1387 |
|
c = XFASTINT (code); |
1388 |
|
else if (dimension == 2) |
1389 |
|
c = (XFASTINT (code) << 8) | XFASTINT (code2); |
1390 |
|
else if (dimension == 3) |
1391 |
|
c = (XFASTINT (code) << 16) | (XFASTINT (code2) << 8) | XFASTINT (code3); |
1392 |
|
|
1393 |
|
c = DECODE_CHAR (charsetp, c); |
1394 |
|
return make_number (c); |
1395 |
} |
} |
1396 |
|
|
|
/* Return width of Lisp string STRING when displayed in the current |
|
|
buffer. The width is measured by how many columns it occupies on |
|
|
the screen while paying attention to compositions. If PRECISION > |
|
|
0, return the width of longest substring that doesn't exceed |
|
|
PRECISION, and set number of characters and bytes of the substring |
|
|
in *NCHARS and *NBYTES respectively. */ |
|
1397 |
|
|
1398 |
int |
/* Return the first charset in CHARSET_LIST that contains C. |
1399 |
lisp_string_width (string, precision, nchars, nbytes) |
CHARSET_LIST is a list of charset IDs. If it is nil, use |
1400 |
Lisp_Object string; |
Vcharset_ordered_list. */ |
1401 |
int precision, *nchars, *nbytes; |
|
1402 |
|
struct charset * |
1403 |
|
char_charset (c, charset_list, code_return) |
1404 |
|
int c; |
1405 |
|
Lisp_Object charset_list; |
1406 |
|
unsigned *code_return; |
1407 |
{ |
{ |
1408 |
int len = XSTRING (string)->size; |
if (NILP (charset_list)) |
1409 |
int len_byte = STRING_BYTES (XSTRING (string)); |
charset_list = Vcharset_ordered_list; |
|
unsigned char *str = XSTRING (string)->data; |
|
|
int i = 0, i_byte = 0; |
|
|
int width = 0; |
|
|
struct Lisp_Char_Table *dp = buffer_display_table (); |
|
1410 |
|
|
1411 |
while (i < len) |
while (CONSP (charset_list)) |
1412 |
{ |
{ |
1413 |
int chars, bytes, thiswidth; |
struct charset *charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
1414 |
Lisp_Object val; |
unsigned code = ENCODE_CHAR (charset, c); |
|
int cmp_id; |
|
|
int ignore, end; |
|
1415 |
|
|
1416 |
if (find_composition (i, -1, &ignore, &end, &val, string) |
if (code != CHARSET_INVALID_CODE (charset)) |
|
&& ((cmp_id = get_composition_id (i, i_byte, end - i, val, string)) |
|
|
>= 0)) |
|
1417 |
{ |
{ |
1418 |
thiswidth = composition_table[cmp_id]->width; |
if (code_return) |
1419 |
chars = end - i; |
*code_return = code; |
1420 |
bytes = string_char_to_byte (string, end) - i_byte; |
return charset; |
1421 |
} |
} |
1422 |
else if (dp) |
charset_list = XCDR (charset_list); |
|
{ |
|
|
int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes); |
|
|
|
|
|
chars = 1; |
|
|
val = DISP_CHAR_VECTOR (dp, c); |
|
|
if (VECTORP (val)) |
|
|
thiswidth = XVECTOR (val)->size; |
|
|
else |
|
|
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
|
|
} |
|
|
else |
|
|
{ |
|
|
chars = 1; |
|
|
PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes); |
|
|
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
|
|
} |
|
|
|
|
|
if (precision > 0 |
|
|
&& (width + thiswidth > precision)) |
|
|
{ |
|
|
*nchars = i; |
|
|
*nbytes = i_byte; |
|
|
return width; |
|
|
} |
|
|
i += chars; |
|
|
i_byte += bytes; |
|
|
width += thiswidth; |
|
|
} |
|
|
|
|
|
if (precision > 0) |
|
|
{ |
|
|
*nchars = i; |
|
|
*nbytes = i_byte; |
|
1423 |
} |
} |
1424 |
|
return NULL; |
|
return width; |
|
1425 |
} |
} |
1426 |
|
|
|
DEFUN ("string-width", Fstring_width, Sstring_width, 1, 1, 0, |
|
|
doc: /* Return width of STRING when displayed in the current buffer. |
|
|
Width is measured by how many columns it occupies on the screen. |
|
|
When calculating width of a multibyte character in STRING, |
|
|
only the base leading-code is considered; the validity of |
|
|
the following bytes is not checked. Tabs in STRING are always |
|
|
taken to occupy `tab-width' columns. */) |
|
|
(str) |
|
|
Lisp_Object str; |
|
|
{ |
|
|
Lisp_Object val; |
|
|
|
|
|
CHECK_STRING (str); |
|
|
XSETFASTINT (val, lisp_string_width (str, -1, NULL, NULL)); |
|
|
return val; |
|
|
} |
|
1427 |
|
|
1428 |
DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0, |
DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0, |
1429 |
doc: /* Return the direction of CHAR. |
doc: /*Return list of charset and one or two position-codes of CHAR. |
1430 |
The returned value is 0 for left-to-right and 1 for right-to-left. */) |
If CHAR is invalid as a character code, |
1431 |
|
return a list of symbol `unknown' and CHAR. */) |
1432 |
(ch) |
(ch) |
1433 |
Lisp_Object ch; |
Lisp_Object ch; |
1434 |
{ |
{ |
1435 |
int charset; |
struct charset *charset; |
1436 |
|
int c, dimension; |
1437 |
|
unsigned code; |
1438 |
|
Lisp_Object val; |
1439 |
|
|
1440 |
CHECK_NUMBER (ch); |
CHECK_CHARACTER (ch); |
1441 |
charset = CHAR_CHARSET (XFASTINT (ch)); |
c = XFASTINT (ch); |
1442 |
if (!CHARSET_DEFINED_P (charset)) |
charset = CHAR_CHARSET (c); |
1443 |
invalid_character (XINT (ch)); |
if (! charset) |
1444 |
return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX); |
return Fcons (intern ("unknown"), Fcons (ch, Qnil)); |
1445 |
|
|
1446 |
|
code = ENCODE_CHAR (charset, c); |
1447 |
|
if (code == CHARSET_INVALID_CODE (charset)) |
1448 |
|
abort (); |
1449 |
|
dimension = CHARSET_DIMENSION (charset); |
1450 |
|
val = (dimension == 1 ? Fcons (make_number (code), Qnil) |
1451 |
|
: dimension == 2 ? Fcons (make_number (code >> 8), |
1452 |
|
Fcons (make_number (code & 0xFF), Qnil)) |
1453 |
|
: Fcons (make_number (code >> 16), |
1454 |
|
Fcons (make_number ((code >> 8) & 0xFF), |
1455 |
|
Fcons (make_number (code & 0xFF), Qnil)))); |
1456 |
|
return Fcons (CHARSET_NAME (charset), val); |
1457 |
} |
} |
1458 |
|
|
|
DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0, |
|
|
doc: /* Return number of characters between BEG and END. */) |
|
|
(beg, end) |
|
|
Lisp_Object beg, end; |
|
|
{ |
|
|
int from, to; |
|
1459 |
|
|
1460 |
CHECK_NUMBER_COERCE_MARKER (beg); |
DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0, |
1461 |
CHECK_NUMBER_COERCE_MARKER (end); |
doc: /* Return the charset of highest priority that contains CHAR. */) |
1462 |
|
(ch) |
1463 |
from = min (XFASTINT (beg), XFASTINT (end)); |
Lisp_Object ch; |
1464 |
to = max (XFASTINT (beg), XFASTINT (end)); |
{ |
1465 |
|
struct charset *charset; |
1466 |
|
|
1467 |
return make_number (to - from); |
CHECK_CHARACTER (ch); |
1468 |
|
charset = CHAR_CHARSET (XINT (ch)); |
1469 |
|
return (CHARSET_NAME (charset)); |
1470 |
} |
} |
1471 |
|
|
|
/* Return the number of characters in the NBYTES bytes at PTR. |
|
|
This works by looking at the contents and checking for multibyte sequences. |
|
|
However, if the current buffer has enable-multibyte-characters = nil, |
|
|
we treat each byte as a character. */ |
|
1472 |
|
|
1473 |
int |
DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0, |
1474 |
chars_in_text (ptr, nbytes) |
doc: /* |
1475 |
unsigned char *ptr; |
Return charset of a character in the current buffer at position POS. |
1476 |
int nbytes; |
If POS is nil, it defauls to the current point. |
1477 |
|
If POS is out of range, the value is nil. */) |
1478 |
|
(pos) |
1479 |
|
Lisp_Object pos; |
1480 |
{ |
{ |
1481 |
/* current_buffer is null at early stages of Emacs initialization. */ |
Lisp_Object ch; |
1482 |
if (current_buffer == 0 |
struct charset *charset; |
|
|| NILP (current_buffer->enable_multibyte_characters)) |
|
|
return nbytes; |
|
1483 |
|
|
1484 |
return multibyte_chars_in_text (ptr, nbytes); |
ch = Fchar_after (pos); |
1485 |
|
if (! INTEGERP (ch)) |
1486 |
|
return ch; |
1487 |
|
charset = CHAR_CHARSET (XINT (ch)); |
1488 |
|
return (CHARSET_NAME (charset)); |
1489 |
} |
} |
1490 |
|
|
|
/* Return the number of characters in the NBYTES bytes at PTR. |
|
|
This works by looking at the contents and checking for multibyte sequences. |
|
|
It ignores enable-multibyte-characters. */ |
|
1491 |
|
|
1492 |
int |
DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0, |
1493 |
multibyte_chars_in_text (ptr, nbytes) |
doc: /* |
1494 |
unsigned char *ptr; |
Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR. |
|
int nbytes; |
|
|
{ |
|
|
unsigned char *endp; |
|
|
int chars, bytes; |
|
|
|
|
|
endp = ptr + nbytes; |
|
|
chars = 0; |
|
1495 |
|
|
1496 |
while (ptr < endp) |
ISO 2022's designation sequence (escape sequence) distinguishes charsets |
1497 |
{ |
by their DIMENSION, CHARS, and FINAL-CHAR, |
1498 |
PARSE_MULTIBYTE_SEQ (ptr, endp - ptr, bytes); |
where as Emacs distinguishes them by charset symbol. |
1499 |
ptr += bytes; |
See the documentation of the function `charset-info' for the meanings of |
1500 |
chars++; |
DIMENSION, CHARS, and FINAL-CHAR. */) |
1501 |
} |
(dimension, chars, final_char) |
1502 |
|
Lisp_Object dimension, chars, final_char; |
1503 |
|
{ |
1504 |
|
int id; |
1505 |
|
|
1506 |
return chars; |
check_iso_charset_parameter (dimension, chars, final_char); |
1507 |
|
id = ISO_CHARSET_TABLE (XFASTINT (dimension), XFASTINT (chars), |
1508 |
|
XFASTINT (final_char)); |
1509 |
|
return (id >= 0 ? CHARSET_NAME (CHARSET_FROM_ID (id)) : Qnil); |
1510 |
} |
} |
1511 |
|
|
1512 |
/* Parse unibyte text at STR of LEN bytes as multibyte text, and |
|
1513 |
count the numbers of characters and bytes in it. On counting |
DEFUN ("clear-charset-maps", Fclear_charset_maps, Sclear_charset_maps, |
1514 |
bytes, pay attention to the fact that 8-bit characters in the range |
0, 0, 0, |
1515 |
0x80..0x9F are represented by 2 bytes in multibyte text. */ |
doc: /* |
1516 |
void |
Clear encoder and decoder of charsets that are loaded from mapfiles. */) |
1517 |
parse_str_as_multibyte (str, len, nchars, nbytes) |
() |
|
unsigned char *str; |
|
|
int len, *nchars, *nbytes; |
|
1518 |
{ |
{ |
1519 |
unsigned char *endp = str + len; |
int i; |
1520 |
int n, chars = 0, bytes = 0; |
struct charset *charset; |
1521 |
|
Lisp_Object attrs; |
1522 |
|
|
1523 |
while (str < endp) |
for (i = 0; i < charset_table_used; i++) |
1524 |
{ |
{ |
1525 |
if (UNIBYTE_STR_AS_MULTIBYTE_P (str, endp - str, n)) |
charset = CHARSET_FROM_ID (i); |
1526 |
str += n, bytes += n; |
attrs = CHARSET_ATTRIBUTES (charset); |
|
else |
|
|
str++, bytes += 2; |
|
|
chars++; |
|
|
} |
|
|
*nchars = chars; |
|
|
*nbytes = bytes; |
|
|
return; |
|
|
} |
|
1527 |
|
|
1528 |
/* Arrange unibyte text at STR of NBYTES bytes as multibyte text. |
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP) |
|
It actually converts only 8-bit characters in the range 0x80..0x9F |
|
|
that don't contruct multibyte characters to multibyte forms. If |
|
|
NCHARS is nonzero, set *NCHARS to the number of characters in the |
|
|
text. It is assured that we can use LEN bytes at STR as a work |
|
|
area and that is enough. Return the number of bytes of the |
|
|
resulting text. */ |
|
|
|
|
|
int |
|
|
str_as_multibyte (str, len, nbytes, nchars) |
|
|
unsigned char *str; |
|
|
int len, nbytes, *nchars; |
|
|
{ |
|
|
unsigned char *p = str, *endp = str + nbytes; |
|
|
unsigned char *to; |
|
|
int chars = 0; |
|
|
int n; |
|
|
|
|
|
while (p < endp && UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n)) |
|
|
p += n, chars++; |
|
|
if (nchars) |
|
|
*nchars = chars; |
|
|
if (p == endp) |
|
|
return nbytes; |
|
|
|
|
|
to = p; |
|
|
nbytes = endp - p; |
|
|
endp = str + len; |
|
|
safe_bcopy (p, endp - nbytes, nbytes); |
|
|
p = endp - nbytes; |
|
|
while (p < endp) |
|
|
{ |
|
|
if (UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n)) |
|
|
{ |
|
|
while (n--) |
|
|
*to++ = *p++; |
|
|
} |
|
|
else |
|
1529 |
{ |
{ |
1530 |
*to++ = LEADING_CODE_8_BIT_CONTROL; |
CHARSET_ATTR_DECODER (attrs) = Qnil; |
1531 |
*to++ = *p++ + 0x20; |
CHARSET_ATTR_ENCODER (attrs) = Qnil; |
1532 |
|
CHARSET_METHOD (charset) = CHARSET_METHOD_MAP_DEFERRED; |
1533 |
} |
} |
|
chars++; |
|
|
} |
|
|
if (nchars) |
|
|
*nchars = chars; |
|
|
return (to - str); |
|
|
} |
|
|
|
|
|
/* Parse unibyte string at STR of LEN bytes, and return the number of |
|
|
bytes it may ocupy when converted to multibyte string by |
|
|
`str_to_multibyte'. */ |
|
|
|
|
|
int |
|
|
parse_str_to_multibyte (str, len) |
|
|
unsigned char *str; |
|
|
int len; |
|
|
{ |
|
|
unsigned char *endp = str + len; |
|
|
int bytes; |
|
|
|
|
|
for (bytes = 0; str < endp; str++) |
|
|
bytes += (*str < 0x80 || *str >= 0xA0) ? 1 : 2; |
|
|
return bytes; |
|
|
} |
|
|
|
|
|
/* Convert unibyte text at STR of NBYTES bytes to multibyte text |
|
|
that contains the same single-byte characters. It actually |
|
|
converts all 8-bit characters to multibyte forms. It is assured |
|
|
that we can use LEN bytes at STR as a work area and that is |
|
|
enough. */ |
|
|
|
|
|
int |
|
|
str_to_multibyte (str, len, bytes) |
|
|
unsigned char *str; |
|
|
int len, bytes; |
|
|
{ |
|
|
unsigned char *p = str, *endp = str + bytes; |
|
|
unsigned char *to; |
|
|
|
|
|
while (p < endp && (*p < 0x80 || *p >= 0xA0)) p++; |
|
|
if (p == endp) |
|
|
return bytes; |
|
|
to = p; |
|
|
bytes = endp - p; |
|
|
endp = str + len; |
|
|
safe_bcopy (p, endp - bytes, bytes); |
|
|
p = endp - bytes; |
|
|
while (p < endp) |
|
|
{ |
|
|
if (*p < 0x80 || *p >= 0xA0) |
|
|
*to++ = *p++; |
|
|
else |
|
|
*to++ = LEADING_CODE_8_BIT_CONTROL, *to++ = *p++ + 0x20; |
|
|
} |
|
|
return (to - str); |
|
|
} |
|
|
|
|
|
/* Arrange multibyte text at STR of LEN bytes as a unibyte text. It |
|
|
actually converts only 8-bit characters in the range 0x80..0x9F to |
|
|
unibyte forms. */ |
|
|
|
|
|
int |
|
|
str_as_unibyte (str, bytes) |
|
|
unsigned char *str; |
|
|
int bytes; |
|
|
{ |
|
|
unsigned char *p = str, *endp = str + bytes; |
|
|
unsigned char *to = str; |
|
|
|
|
|
while (p < endp && *p != LEADING_CODE_8_BIT_CONTROL) p++; |
|
|
to = p; |
|
|
while (p < endp) |
|
|
{ |
|
|
if (*p == LEADING_CODE_8_BIT_CONTROL) |
|
|
*to++ = *(p + 1) - 0x20, p += 2; |
|
|
else |
|
|
*to++ = *p++; |
|
|
} |
|
|
return (to - str); |
|
|
} |
|
1534 |
|
|
1535 |
|
if (CHARSET_UNIFIED_P (charset)) |
1536 |
DEFUN ("string", Fstring, Sstring, 1, MANY, 0, |
CHARSET_ATTR_DEUNIFIER (attrs) = Qnil; |
|
doc: /* Concatenate all the argument characters and make the result a string. |
|
|
usage: (string &rest CHARACTERS) */) |
|
|
(n, args) |
|
|
int n; |
|
|
Lisp_Object *args; |
|
|
{ |
|
|
int i; |
|
|
unsigned char *buf = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH * n); |
|
|
unsigned char *p = buf; |
|
|
int c; |
|
|
int multibyte = 0; |
|
|
|
|
|
for (i = 0; i < n; i++) |
|
|
{ |
|
|
CHECK_NUMBER (args[i]); |
|
|
if (!multibyte && !SINGLE_BYTE_CHAR_P (XFASTINT (args[i]))) |
|
|
multibyte = 1; |
|
1537 |
} |
} |
1538 |
|
|
1539 |
for (i = 0; i < n; i++) |
if (CHAR_TABLE_P (Vchar_unified_charset_table)) |
1540 |
{ |
{ |
1541 |
c = XINT (args[i]); |
Foptimize_char_table (Vchar_unified_charset_table); |
1542 |
if (multibyte) |
Vchar_unify_table = Vchar_unified_charset_table; |
1543 |
p += CHAR_STRING (c, p); |
Vchar_unified_charset_table = Qnil; |
|
else |
|
|
*p++ = c; |
|
1544 |
} |
} |
1545 |
|
|
1546 |
return make_string_from_bytes (buf, n, p - buf); |
return Qnil; |
1547 |
} |
} |
1548 |
|
|
|
#endif /* emacs */ |
|
1549 |
|
|
1550 |
int |
void |
1551 |
charset_id_internal (charset_name) |
init_charset () |
|
char *charset_name; |
|
1552 |
{ |
{ |
|
Lisp_Object val; |
|
|
|
|
|
val= Fget (intern (charset_name), Qcharset); |
|
|
if (!VECTORP (val)) |
|
|
error ("Charset %s is not defined", charset_name); |
|
1553 |
|
|
|
return (XINT (XVECTOR (val)->contents[0])); |
|
1554 |
} |
} |
1555 |
|
|
|
DEFUN ("setup-special-charsets", Fsetup_special_charsets, |
|
|
Ssetup_special_charsets, 0, 0, 0, doc: /* Internal use only. */) |
|
|
() |
|
|
{ |
|
|
charset_latin_iso8859_1 = charset_id_internal ("latin-iso8859-1"); |
|
|
charset_jisx0208_1978 = charset_id_internal ("japanese-jisx0208-1978"); |
|
|
charset_jisx0208 = charset_id_internal ("japanese-jisx0208"); |
|
|
charset_katakana_jisx0201 = charset_id_internal ("katakana-jisx0201"); |
|
|
charset_latin_jisx0201 = charset_id_internal ("latin-jisx0201"); |
|
|
charset_big5_1 = charset_id_internal ("chinese-big5-1"); |
|
|
charset_big5_2 = charset_id_internal ("chinese-big5-2"); |
|
|
return Qnil; |
|
|
} |
|
1556 |
|
|
1557 |
void |
void |
1558 |
init_charset_once () |
init_charset_once () |
1559 |
{ |
{ |
1560 |
int i, j, k; |
int i, j, k; |
1561 |
|
|
1562 |
staticpro (&Vcharset_table); |
for (i = 0; i < ISO_MAX_DIMENSION; i++) |
1563 |
staticpro (&Vcharset_symbol_table); |
for (j = 0; j < ISO_MAX_CHARS; j++) |
1564 |
staticpro (&Vgeneric_character_list); |
for (k = 0; k < ISO_MAX_FINAL; k++) |
1565 |
|
iso_charset_table[i][j][k] = -1; |
1566 |
/* This has to be done here, before we call Fmake_char_table. */ |
|
1567 |
Qcharset_table = intern ("charset-table"); |
for (i = 0; i < 255; i++) |
1568 |
staticpro (&Qcharset_table); |
emacs_mule_charset[i] = NULL; |
1569 |
|
|
1570 |
|
#if 0 |
1571 |
|
Vchar_charset_set = Fmake_char_table (Qnil, Qnil); |
1572 |
|
CHAR_TABLE_SET (Vchar_charset_set, make_number (97), Qnil); |
1573 |
|
|
1574 |
|
DEFSYM (Qcharset_encode_table, "charset-encode-table"); |
1575 |
|
|
1576 |
/* Intern this now in case it isn't already done. |
/* Intern this now in case it isn't already done. |
1577 |
Setting this variable twice is harmless. |
Setting this variable twice is harmless. |
1578 |
But don't staticpro it here--that is done in alloc.c. */ |
But don't staticpro it here--that is done in alloc.c. */ |
1579 |
Qchar_table_extra_slots = intern ("char-table-extra-slots"); |
Qchar_table_extra_slots = intern ("char-table-extra-slots"); |
1580 |
|
|
1581 |
/* Now we are ready to set up this property, so we can |
/* Now we are ready to set up this property, so we can create syntax |
1582 |
create the charset table. */ |
tables. */ |
1583 |
Fput (Qcharset_table, Qchar_table_extra_slots, make_number (0)); |
Fput (Qcharset_encode_table, Qchar_table_extra_slots, make_number (0)); |
1584 |
Vcharset_table = Fmake_char_table (Qcharset_table, Qnil); |
#endif |
|
|
|
|
Qunknown = intern ("unknown"); |
|
|
staticpro (&Qunknown); |
|
|
Vcharset_symbol_table = Fmake_vector (make_number (MAX_CHARSET + 1), |
|
|
Qunknown); |
|
|
|
|
|
/* Setup tables. */ |
|
|
for (i = 0; i < 2; i++) |
|
|
for (j = 0; j < 2; j++) |
|
|
for (k = 0; k < 128; k++) |
|
|
iso_charset_table [i][j][k] = -1; |
|
|
|
|
|
for (i = 0; i < 256; i++) |
|
|
bytes_by_char_head[i] = 1; |
|
|
bytes_by_char_head[LEADING_CODE_PRIVATE_11] = 3; |
|
|
bytes_by_char_head[LEADING_CODE_PRIVATE_12] = 3; |
|
|
bytes_by_char_head[LEADING_CODE_PRIVATE_21] = 4; |
|
|
bytes_by_char_head[LEADING_CODE_PRIVATE_22] = 4; |
|
|
|
|
|
for (i = 0; i < 128; i++) |
|
|
width_by_char_head[i] = 1; |
|
|
for (; i < 256; i++) |
|
|
width_by_char_head[i] = 4; |
|
|
width_by_char_head[LEADING_CODE_PRIVATE_11] = 1; |
|
|
width_by_char_head[LEADING_CODE_PRIVATE_12] = 2; |
|
|
width_by_char_head[LEADING_CODE_PRIVATE_21] = 1; |
|
|
width_by_char_head[LEADING_CODE_PRIVATE_22] = 2; |
|
|
|
|
|
{ |
|
|
Lisp_Object val; |
|
|
|
|
|
val = Qnil; |
|
|
for (i = 0x81; i < 0x90; i++) |
|
|
val = Fcons (make_number ((i - 0x70) << 7), val); |
|
|
for (; i < 0x9A; i++) |
|
|
val = Fcons (make_number ((i - 0x8F) << 14), val); |
|
|
for (i = 0xA0; i < 0xF0; i++) |
|
|
val = Fcons (make_number ((i - 0x70) << 7), val); |
|
|
for (; i < 0xFF; i++) |
|
|
val = Fcons (make_number ((i - 0xE0) << 14), val); |
|
|
Vgeneric_character_list = Fnreverse (val); |
|
|
} |
|
|
|
|
|
nonascii_insert_offset = 0; |
|
|
Vnonascii_translation_table = Qnil; |
|
1585 |
} |
} |
1586 |
|
|
1587 |
#ifdef emacs |
#ifdef emacs |
1589 |
void |
void |
1590 |
syms_of_charset () |
syms_of_charset () |
1591 |
{ |
{ |
1592 |
Qcharset = intern ("charset"); |
char *p; |
|
staticpro (&Qcharset); |
|
|
|
|
|
Qascii = intern ("ascii"); |
|
|
staticpro (&Qascii); |
|
1593 |
|
|
1594 |
Qeight_bit_control = intern ("eight-bit-control"); |
DEFSYM (Qcharsetp, "charsetp"); |
|
staticpro (&Qeight_bit_control); |
|
1595 |
|
|
1596 |
Qeight_bit_graphic = intern ("eight-bit-graphic"); |
DEFSYM (Qascii, "ascii"); |
1597 |
staticpro (&Qeight_bit_graphic); |
DEFSYM (Qunicode, "unicode"); |
1598 |
|
DEFSYM (Qeight_bit_control, "eight-bit-control"); |
1599 |
/* Define special charsets ascii, eight-bit-control, and |
DEFSYM (Qeight_bit_graphic, "eight-bit-graphic"); |
1600 |
eight-bit-graphic. */ |
DEFSYM (Qiso_8859_1, "iso-8859-1"); |
1601 |
update_charset_table (make_number (CHARSET_ASCII), |
|
1602 |
make_number (1), make_number (94), |
DEFSYM (Qgl, "gl"); |
1603 |
make_number (1), |
DEFSYM (Qgr, "gr"); |
1604 |
make_number (0), |
|
1605 |
make_number ('B'), |
p = (char *) xmalloc (30000); |
1606 |
make_number (0), |
|
1607 |
build_string ("ASCII"), |
staticpro (&Vcharset_ordered_list); |
1608 |
Qnil, /* same as above */ |
Vcharset_ordered_list = Qnil; |
1609 |
build_string ("ASCII (ISO646 IRV)")); |
|
1610 |
CHARSET_SYMBOL (CHARSET_ASCII) = Qascii; |
staticpro (&Viso_2022_charset_list); |
1611 |
Fput (Qascii, Qcharset, CHARSET_TABLE_ENTRY (CHARSET_ASCII)); |
Viso_2022_charset_list = Qnil; |
1612 |
|
|
1613 |
update_charset_table (make_number (CHARSET_8_BIT_CONTROL), |
staticpro (&Vemacs_mule_charset_list); |
1614 |
make_number (1), make_number (96), |
Vemacs_mule_charset_list = Qnil; |
1615 |
make_number (4), |
|
1616 |
make_number (0), |
staticpro (&Vcharset_hash_table); |
1617 |
make_number (-1), |
Vcharset_hash_table = Fmakehash (Qeq); |
1618 |
make_number (-1), |
|
1619 |
build_string ("8-bit control code (0x80..0x9F)"), |
charset_table_size = 128; |
1620 |
Qnil, /* same as above */ |
charset_table = ((struct charset *) |
1621 |
Qnil); /* same as above */ |
xmalloc (sizeof (struct charset) * charset_table_size)); |
1622 |
CHARSET_SYMBOL (CHARSET_8_BIT_CONTROL) = Qeight_bit_control; |
charset_table_used = 0; |
1623 |
Fput (Qeight_bit_control, Qcharset, |
|
1624 |
CHARSET_TABLE_ENTRY (CHARSET_8_BIT_CONTROL)); |
staticpro (&Vchar_unified_charset_table); |
1625 |
|
Vchar_unified_charset_table = Fmake_char_table (Qnil, make_number (-1)); |
1626 |
update_charset_table (make_number (CHARSET_8_BIT_GRAPHIC), |
|
1627 |
make_number (1), make_number (96), |
defsubr (&Scharsetp); |
1628 |
make_number (4), |
defsubr (&Smap_charset_chars); |
1629 |
make_number (0), |
defsubr (&Sdefine_charset_internal); |
1630 |
make_number (-1), |
defsubr (&Sdefine_charset_alias); |
1631 |
make_number (-1), |
defsubr (&Sprimary_charset); |
1632 |
build_string ("8-bit graphic char (0xA0..0xFF)"), |
defsubr (&Sset_primary_charset); |
1633 |
Qnil, /* same as above */ |
defsubr (&Scharset_plist); |
1634 |
Qnil); /* same as above */ |
defsubr (&Sset_charset_plist); |
1635 |
CHARSET_SYMBOL (CHARSET_8_BIT_GRAPHIC) = Qeight_bit_graphic; |
defsubr (&Sunify_charset); |
|
Fput (Qeight_bit_graphic, Qcharset, |
|
|
CHARSET_TABLE_ENTRY (CHARSET_8_BIT_GRAPHIC)); |
|
|
|
|
|
Qauto_fill_chars = intern ("auto-fill-chars"); |
|
|
staticpro (&Qauto_fill_chars); |
|
|
Fput (Qauto_fill_chars, Qchar_table_extra_slots, make_number (0)); |
|
|
|
|
|
defsubr (&Sdefine_charset); |
|
|
defsubr (&Sgeneric_character_list); |
|
1636 |
defsubr (&Sget_unused_iso_final_char); |
defsubr (&Sget_unused_iso_final_char); |
1637 |
defsubr (&Sdeclare_equiv_charset); |
defsubr (&Sdeclare_equiv_charset); |
1638 |
defsubr (&Sfind_charset_region); |
defsubr (&Sfind_charset_region); |
1639 |
defsubr (&Sfind_charset_string); |
defsubr (&Sfind_charset_string); |
1640 |
defsubr (&Smake_char_internal); |
defsubr (&Sdecode_char); |
1641 |
|
defsubr (&Sencode_char); |
1642 |
defsubr (&Ssplit_char); |
defsubr (&Ssplit_char); |
1643 |
|
defsubr (&Smake_char); |
1644 |
defsubr (&Schar_charset); |
defsubr (&Schar_charset); |
1645 |
defsubr (&Scharset_after); |
defsubr (&Scharset_after); |
1646 |
defsubr (&Siso_charset); |
defsubr (&Siso_charset); |
1647 |
defsubr (&Schar_valid_p); |
defsubr (&Sclear_charset_maps); |
1648 |
defsubr (&Sunibyte_char_to_multibyte); |
|
1649 |
defsubr (&Smultibyte_char_to_unibyte); |
DEFVAR_LISP ("charset-map-directory", &Vcharset_map_directory, |
1650 |
defsubr (&Schar_bytes); |
doc: /* Directory of charset map files that come with GNU Emacs. |
1651 |
defsubr (&Schar_width); |
The default value is \"\\[data-directory]/charsets\". */); |
1652 |
defsubr (&Sstring_width); |
Vcharset_map_directory = Fexpand_file_name (build_string ("charsets"), |
1653 |
defsubr (&Schar_direction); |
Vdata_directory); |
|
defsubr (&Schars_in_region); |
|
|
defsubr (&Sstring); |
|
|
defsubr (&Ssetup_special_charsets); |
|
1654 |
|
|
1655 |
DEFVAR_LISP ("charset-list", &Vcharset_list, |
DEFVAR_LISP ("charset-list", &Vcharset_list, |
1656 |
doc: /* List of charsets ever defined. */); |
doc: /* List of charsets ever defined. */); |
1657 |
Vcharset_list = Fcons (Qascii, Fcons (Qeight_bit_control, |
Vcharset_list = Qnil; |
|
Fcons (Qeight_bit_graphic, Qnil))); |
|
1658 |
|
|
1659 |
DEFVAR_LISP ("translation-table-vector", &Vtranslation_table_vector, |
/* Make the prerequisite charset `ascii' and `unicode'. */ |
1660 |
doc: /* Vector of cons cell of a symbol and translation table ever defined. |
{ |
1661 |
An ID of a translation table is an index of this vector. */); |
Lisp_Object args[charset_arg_max]; |
1662 |
Vtranslation_table_vector = Fmake_vector (make_number (16), Qnil); |
Lisp_Object plist[14]; |
1663 |
|
Lisp_Object val; |
1664 |
DEFVAR_INT ("leading-code-private-11", &leading_code_private_11, |
|
1665 |
doc: /* Leading-code of private TYPE9N charset of column-width 1. */); |
plist[0] = intern (":name"); |
1666 |
leading_code_private_11 = LEADING_CODE_PRIVATE_11; |
plist[1] = args[charset_arg_name] = Qascii; |
1667 |
|
plist[2] = intern (":dimension"); |
1668 |
DEFVAR_INT ("leading-code-private-12", &leading_code_private_12, |
plist[3] = args[charset_arg_dimension] = make_number (1); |
1669 |
doc: /* Leading-code of private TYPE9N charset of column-width 2. */); |
val = Fmake_vector (make_number (8), make_number (0)); |
1670 |
leading_code_private_12 = LEADING_CODE_PRIVATE_12; |
ASET (val, 1, make_number (127)); |
1671 |
|
plist[4] = intern (":code-space"); |
1672 |
DEFVAR_INT ("leading-code-private-21", &leading_code_private_21, |
plist[5] = args[charset_arg_code_space] = val; |
1673 |
doc: /* Leading-code of private TYPE9Nx9N charset of column-width 1. */); |
plist[6] = intern (":iso-final-char"); |
1674 |
leading_code_private_21 = LEADING_CODE_PRIVATE_21; |
plist[7] = args[charset_arg_iso_final] = make_number ('B'); |
1675 |
|
args[charset_arg_iso_revision] = Qnil; |
1676 |
DEFVAR_INT ("leading-code-private-22", &leading_code_private_22, |
plist[8] = intern (":emacs-mule-id"); |
1677 |
doc: /* Leading-code of private TYPE9Nx9N charset of column-width 2. */); |
plist[9] = args[charset_arg_emacs_mule_id] = make_number (0); |
1678 |
leading_code_private_22 = LEADING_CODE_PRIVATE_22; |
plist[10] = intern (":ascii-compatible-p"); |
1679 |
|
plist[11] = args[charset_arg_ascii_compatible_p] = Qt; |
1680 |
DEFVAR_INT ("nonascii-insert-offset", &nonascii_insert_offset, |
args[charset_arg_supplementary_p] = Qnil; |
1681 |
doc: /* Offset for converting non-ASCII unibyte codes 0240...0377 to multibyte. |
args[charset_arg_invalid_code] = Qnil; |
1682 |
This is used for converting unibyte text to multibyte, |
plist[12] = intern (":code-offset"); |
1683 |
and for inserting character codes specified by number. |
plist[13] = args[charset_arg_code_offset] = make_number (0); |
1684 |
|
args[charset_arg_map] = Qnil; |
1685 |
This serves to convert a Latin-1 or similar 8-bit character code |
args[charset_arg_parents] = Qnil; |
1686 |
to the corresponding Emacs multibyte character code. |
args[charset_arg_unify_map] = Qnil; |
1687 |
Typically the value should be (- (make-char CHARSET 0) 128), |
/* The actual plist is set by mule-conf.el. */ |
1688 |
for your choice of character set. |
args[charset_arg_plist] = Flist (14, plist); |
1689 |
If `nonascii-translation-table' is non-nil, it overrides this variable. */); |
Fdefine_charset_internal (charset_arg_max, args); |
1690 |
nonascii_insert_offset = 0; |
charset_ascii = CHARSET_SYMBOL_ID (Qascii); |
1691 |
|
|
1692 |
DEFVAR_LISP ("nonascii-translation-table", &Vnonascii_translation_table, |
plist[1] = args[charset_arg_name] = Qunicode; |
1693 |
doc: /* Translation table to convert non-ASCII unibyte codes to multibyte. |
plist[3] = args[charset_arg_dimension] = make_number (3); |
1694 |
This is used for converting unibyte text to multibyte, |
val = Fmake_vector (make_number (8), make_number (0)); |
1695 |
and for inserting character codes specified by number. |
ASET (val, 1, make_number (255)); |
1696 |
|
ASET (val, 3, make_number (255)); |
1697 |
Conversion is performed only when multibyte characters are enabled, |
ASET (val, 5, make_number (16)); |
1698 |
and it serves to convert a Latin-1 or similar 8-bit character code |
plist[5] = args[charset_arg_code_space] = val; |
1699 |
to the corresponding Emacs character code. |
plist[7] = args[charset_arg_iso_final] = Qnil; |
1700 |
|
args[charset_arg_iso_revision] = Qnil; |
1701 |
If this is nil, `nonascii-insert-offset' is used instead. |
plist[9] = args[charset_arg_emacs_mule_id] = Qnil; |
1702 |
See also the docstring of `make-translation-table'. */); |
plist[11] = args[charset_arg_ascii_compatible_p] = Qt; |
1703 |
Vnonascii_translation_table = Qnil; |
args[charset_arg_supplementary_p] = Qnil; |
1704 |
|
args[charset_arg_invalid_code] = Qnil; |
1705 |
DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars, |
plist[13] = args[charset_arg_code_offset] = make_number (0); |
1706 |
doc: /* A char-table for characters which invoke auto-filling. |
args[charset_arg_map] = Qnil; |
1707 |
Such characters have value t in this table. */); |
args[charset_arg_parents] = Qnil; |
1708 |
Vauto_fill_chars = Fmake_char_table (Qauto_fill_chars, Qnil); |
args[charset_arg_unify_map] = Qnil; |
1709 |
CHAR_TABLE_SET (Vauto_fill_chars, make_number (' '), Qt); |
/* The actual plist is set by mule-conf.el. */ |
1710 |
CHAR_TABLE_SET (Vauto_fill_chars, make_number ('\n'), Qt); |
args[charset_arg_plist] = Flist (14, plist); |
1711 |
|
Fdefine_charset_internal (charset_arg_max, args); |
1712 |
|
charset_unicode = CHARSET_SYMBOL_ID (Qunicode); |
1713 |
|
} |
1714 |
} |
} |
1715 |
|
|
1716 |
#endif /* emacs */ |
#endif /* emacs */ |