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) 2003 |
6 |
|
National Institute of Advanced Industrial Science and Technology (AIST) |
7 |
|
Registration Number H13PRO009 |
8 |
|
|
9 |
This file is part of GNU Emacs. |
This file is part of GNU Emacs. |
10 |
|
|
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. */ |
|
|
|
|
|
#ifdef emacs |
|
26 |
#include <config.h> |
#include <config.h> |
|
#endif |
|
27 |
|
|
28 |
#include <stdio.h> |
#include <stdio.h> |
29 |
|
#include <unistd.h> |
30 |
#ifdef emacs |
#include <ctype.h> |
|
|
|
31 |
#include <sys/types.h> |
#include <sys/types.h> |
32 |
#include "lisp.h" |
#include "lisp.h" |
33 |
#include "buffer.h" |
#include "character.h" |
34 |
#include "charset.h" |
#include "charset.h" |
|
#include "composite.h" |
|
35 |
#include "coding.h" |
#include "coding.h" |
36 |
#include "disptab.h" |
#include "disptab.h" |
37 |
|
#include "buffer.h" |
38 |
|
|
39 |
#else /* not emacs */ |
/*** GENERAL NOTES on CODED CHARACTER SETS (CHARSETS) *** |
40 |
|
|
41 |
#include "mulelib.h" |
A coded character set ("charset" hereafter) is a meaningful |
42 |
|
collection (i.e. language, culture, functionality, etc.) of |
43 |
|
characters. Emacs handles multiple charsets at once. In Emacs Lisp |
44 |
|
code, a charset is represented by a symbol. In C code, a charset is |
45 |
|
represented by its ID number or by a pointer to a struct charset. |
46 |
|
|
47 |
|
The actual information about each charset is stored in two places. |
48 |
|
Lispy information is stored in the hash table Vcharset_hash_table as |
49 |
|
a vector (charset attributes). The other information is stored in |
50 |
|
charset_table as a struct charset. |
51 |
|
|
52 |
#endif /* emacs */ |
*/ |
53 |
|
|
54 |
Lisp_Object Qcharset, Qascii, Qeight_bit_control, Qeight_bit_graphic; |
/* List of all charsets. This variable is used only from Emacs |
55 |
Lisp_Object Qunknown; |
Lisp. */ |
56 |
|
Lisp_Object Vcharset_list; |
57 |
|
|
58 |
/* Declaration of special leading-codes. */ |
/* Hash table that contains attributes of each charset. Keys are |
59 |
EMACS_INT leading_code_private_11; /* for private DIMENSION1 of 1-column */ |
charset symbols, and values are vectors of charset attributes. */ |
60 |
EMACS_INT leading_code_private_12; /* for private DIMENSION1 of 2-column */ |
Lisp_Object Vcharset_hash_table; |
|
EMACS_INT leading_code_private_21; /* for private DIMENSION2 of 1-column */ |
|
|
EMACS_INT leading_code_private_22; /* for private DIMENSION2 of 2-column */ |
|
|
|
|
|
/* Declaration of special charsets. The values are set by |
|
|
Fsetup_special_charsets. */ |
|
|
int charset_latin_iso8859_1; /* ISO8859-1 (Latin-1) */ |
|
|
int charset_jisx0208_1978; /* JISX0208.1978 (Japanese Kanji old set) */ |
|
|
int charset_jisx0208; /* JISX0208.1983 (Japanese Kanji) */ |
|
|
int charset_katakana_jisx0201; /* JISX0201.Kana (Japanese Katakana) */ |
|
|
int charset_latin_jisx0201; /* JISX0201.Roman (Japanese Roman) */ |
|
|
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; |
|
61 |
|
|
62 |
/* A list of charset symbols ever defined. */ |
/* Table of struct charset. */ |
63 |
Lisp_Object Vcharset_list; |
struct charset *charset_table; |
64 |
|
|
65 |
|
static int charset_table_size; |
66 |
|
int charset_table_used; |
67 |
|
|
68 |
|
Lisp_Object Qcharsetp; |
69 |
|
|
70 |
|
/* Special charset symbols. */ |
71 |
|
Lisp_Object Qascii; |
72 |
|
Lisp_Object Qeight_bit; |
73 |
|
Lisp_Object Qiso_8859_1; |
74 |
|
Lisp_Object Qunicode; |
75 |
|
|
76 |
|
/* The corresponding charsets. */ |
77 |
|
int charset_ascii; |
78 |
|
int charset_eight_bit; |
79 |
|
int charset_iso_8859_1; |
80 |
|
int charset_unicode; |
81 |
|
|
82 |
|
/* The other special charsets. */ |
83 |
|
int charset_jisx0201_roman; |
84 |
|
int charset_jisx0208_1978; |
85 |
|
int charset_jisx0208; |
86 |
|
|
87 |
|
/* Value of charset attribute `charset-iso-plane'. */ |
88 |
|
Lisp_Object Qgl, Qgr; |
89 |
|
|
90 |
|
/* Charset of unibyte characters. */ |
91 |
|
int charset_unibyte; |
92 |
|
|
93 |
|
/* List of charsets ordered by the priority. */ |
94 |
|
Lisp_Object Vcharset_ordered_list; |
95 |
|
|
96 |
|
/* Incremented everytime we change Vcharset_ordered_list. This is |
97 |
|
unsigned short so that it fits in Lisp_Int and never matches |
98 |
|
-1. */ |
99 |
|
unsigned short charset_ordered_list_tick; |
100 |
|
|
101 |
/* Vector of translation table ever defined. |
/* List of iso-2022 charsets. */ |
102 |
ID of a translation table is used to index this vector. */ |
Lisp_Object Viso_2022_charset_list; |
103 |
Lisp_Object Vtranslation_table_vector; |
|
104 |
|
/* List of emacs-mule charsets. */ |
105 |
/* A char-table for characters which may invoke auto-filling. */ |
Lisp_Object Vemacs_mule_charset_list; |
106 |
Lisp_Object Vauto_fill_chars; |
|
107 |
|
struct charset *emacs_mule_charset[256]; |
|
Lisp_Object Qauto_fill_chars; |
|
|
|
|
|
/* Tables used by macros BYTES_BY_CHAR_HEAD and WIDTH_BY_CHAR_HEAD. */ |
|
|
int bytes_by_char_head[256]; |
|
|
int width_by_char_head[256]; |
|
108 |
|
|
109 |
/* Mapping table from ISO2022's charset (specified by DIMENSION, |
/* Mapping table from ISO2022's charset (specified by DIMENSION, |
110 |
CHARS, and FINAL-CHAR) to Emacs' charset. */ |
CHARS, and FINAL-CHAR) to Emacs' charset. */ |
111 |
int iso_charset_table[2][2][128]; |
int iso_charset_table[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL]; |
112 |
|
|
113 |
/* 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; |
|
114 |
|
|
115 |
/* Offset to add to a non-ASCII value when inserting it. */ |
Lisp_Object Vchar_unified_charset_table; |
|
EMACS_INT nonascii_insert_offset; |
|
116 |
|
|
117 |
/* Translation table for converting non-ASCII unibyte characters |
/* Defined in chartab.c */ |
118 |
to multibyte codes, or nil. */ |
extern void |
119 |
Lisp_Object Vnonascii_translation_table; |
map_char_table_for_charset P_ ((void (*c_function) (Lisp_Object, Lisp_Object), |
120 |
|
Lisp_Object function, Lisp_Object table, |
121 |
|
Lisp_Object arg, struct charset *charset, |
122 |
|
unsigned from, unsigned to)); |
123 |
|
|
124 |
|
#define CODE_POINT_TO_INDEX(charset, code) \ |
125 |
|
((charset)->code_linear_p \ |
126 |
|
? (code) - (charset)->min_code \ |
127 |
|
: (((charset)->code_space_mask[(code) >> 24] & 0x8) \ |
128 |
|
&& ((charset)->code_space_mask[((code) >> 16) & 0xFF] & 0x4) \ |
129 |
|
&& ((charset)->code_space_mask[((code) >> 8) & 0xFF] & 0x2) \ |
130 |
|
&& ((charset)->code_space_mask[(code) & 0xFF] & 0x1)) \ |
131 |
|
? (((((code) >> 24) - (charset)->code_space[12]) \ |
132 |
|
* (charset)->code_space[11]) \ |
133 |
|
+ (((((code) >> 16) & 0xFF) - (charset)->code_space[8]) \ |
134 |
|
* (charset)->code_space[7]) \ |
135 |
|
+ (((((code) >> 8) & 0xFF) - (charset)->code_space[4]) \ |
136 |
|
* (charset)->code_space[3]) \ |
137 |
|
+ (((code) & 0xFF) - (charset)->code_space[0]) \ |
138 |
|
- ((charset)->char_index_offset)) \ |
139 |
|
: -1) |
140 |
|
|
141 |
|
|
142 |
|
/* Convert the character index IDX to code-point CODE for CHARSET. |
143 |
|
It is assumed that IDX is in a valid range. */ |
144 |
|
|
145 |
|
#define INDEX_TO_CODE_POINT(charset, idx) \ |
146 |
|
((charset)->code_linear_p \ |
147 |
|
? (idx) + (charset)->min_code \ |
148 |
|
: (idx += (charset)->char_index_offset, \ |
149 |
|
(((charset)->code_space[0] + (idx) % (charset)->code_space[2]) \ |
150 |
|
| (((charset)->code_space[4] \ |
151 |
|
+ ((idx) / (charset)->code_space[3] % (charset)->code_space[6])) \ |
152 |
|
<< 8) \ |
153 |
|
| (((charset)->code_space[8] \ |
154 |
|
+ ((idx) / (charset)->code_space[7] % (charset)->code_space[10])) \ |
155 |
|
<< 16) \ |
156 |
|
| (((charset)->code_space[12] + ((idx) / (charset)->code_space[11])) \ |
157 |
|
<< 24)))) |
158 |
|
|
|
/* List of all possible generic characters. */ |
|
|
Lisp_Object Vgeneric_character_list; |
|
159 |
|
|
160 |
|
|
|
void |
|
|
invalid_character (c) |
|
|
int c; |
|
|
{ |
|
|
error ("Invalid character: 0%o, %d, 0x%x", c, c, c); |
|
|
} |
|
161 |
|
|
162 |
/* Parse string STR of length LENGTH and fetch information of a |
/* Set to 1 to warn that a charset map is loaded and thus a buffer |
163 |
character at STR. Set BYTES to the byte length the character |
text and a string data may be relocated. */ |
164 |
occupies, CHARSET, C1, C2 to proper values of the character. */ |
int charset_map_loaded; |
165 |
|
|
166 |
#define SPLIT_MULTIBYTE_SEQ(str, length, bytes, charset, c1, c2) \ |
struct charset_map_entries |
167 |
do { \ |
{ |
168 |
(c1) = *(str); \ |
struct { |
169 |
(bytes) = BYTES_BY_CHAR_HEAD (c1); \ |
unsigned from, to; |
170 |
if ((bytes) == 1) \ |
int c; |
171 |
(charset) = ASCII_BYTE_P (c1) ? CHARSET_ASCII : CHARSET_8_BIT_GRAPHIC; \ |
} entry[0x10000]; |
172 |
else if ((bytes) == 2) \ |
struct charset_map_entries *next; |
173 |
{ \ |
}; |
174 |
if ((c1) == LEADING_CODE_8_BIT_CONTROL) \ |
|
175 |
(charset) = CHARSET_8_BIT_CONTROL, (c1) = (str)[1] - 0x20; \ |
/* Load the mapping information for CHARSET from ENTRIES. |
176 |
else \ |
|
177 |
(charset) = (c1), (c1) = (str)[1] & 0x7F; \ |
If CONTROL_FLAG is 0, setup CHARSET->min_char and CHARSET->max_char. |
178 |
} \ |
|
179 |
else if ((bytes) == 3) \ |
If CONTROL_FLAG is 1, setup CHARSET->min_char, CHARSET->max_char, |
180 |
{ \ |
CHARSET->decoder, and CHARSET->encoder. |
181 |
if ((c1) < LEADING_CODE_PRIVATE_11) \ |
|
182 |
(charset) = (c1), (c1) = (str)[1] & 0x7F, (c2) = (str)[2] & 0x7F; \ |
If CONTROL_FLAG is 2, setup CHARSET->deunifier and |
183 |
else \ |
Vchar_unify_table. If Vchar_unified_charset_table is non-nil, |
184 |
(charset) = (str)[1], (c1) = (str)[2] & 0x7F; \ |
setup it too. */ |
185 |
} \ |
|
186 |
else \ |
static void |
187 |
(charset) = (str)[1], (c1) = (str)[2] & 0x7F, (c2) = (str)[3] & 0x7F; \ |
load_charset_map (charset, entries, n_entries, control_flag) |
188 |
} while (0) |
struct charset *charset; |
189 |
|
struct charset_map_entries *entries; |
190 |
/* 1 if CHARSET, C1, and C2 compose a valid character, else 0. |
int n_entries; |
191 |
Note that this intentionally allows invalid components, such |
int control_flag; |
192 |
as 0xA0 0xA0, because there exist many files that contain |
{ |
193 |
such invalid byte sequences, especially in EUC-GB. */ |
Lisp_Object vec, table; |
194 |
#define CHAR_COMPONENTS_VALID_P(charset, c1, c2) \ |
unsigned max_code = CHARSET_MAX_CODE (charset); |
195 |
((charset) == CHARSET_ASCII \ |
int ascii_compatible_p = charset->ascii_compatible_p; |
196 |
? ((c1) >= 0 && (c1) <= 0x7F) \ |
int min_char, max_char, nonascii_min_char; |
197 |
: ((charset) == CHARSET_8_BIT_CONTROL \ |
int i; |
198 |
? ((c1) >= 0x80 && (c1) <= 0x9F) \ |
unsigned char *fast_map = charset->fast_map; |
|
: ((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. */ |
|
199 |
|
|
200 |
int |
if (n_entries <= 0) |
201 |
char_to_string_1 (c, str) |
return; |
|
int c; |
|
|
unsigned char *str; |
|
|
{ |
|
|
unsigned char *p = str; |
|
202 |
|
|
203 |
if (c & CHAR_MODIFIER_MASK) /* This includes the case C is negative. */ |
if (control_flag > 0) |
204 |
{ |
{ |
205 |
/* Multibyte character can't have a modifier bit. */ |
int n = CODE_POINT_TO_INDEX (charset, max_code) + 1; |
206 |
if (! SINGLE_BYTE_CHAR_P ((c & ~CHAR_MODIFIER_MASK))) |
|
207 |
return -1; |
table = Fmake_char_table (Qnil, Qnil); |
208 |
|
if (control_flag == 1) |
209 |
|
vec = Fmake_vector (make_number (n), make_number (-1)); |
210 |
|
else if (! CHAR_TABLE_P (Vchar_unify_table)) |
211 |
|
Vchar_unify_table = Fmake_char_table (Qnil, Qnil); |
212 |
|
|
213 |
|
charset_map_loaded = 1; |
214 |
|
} |
215 |
|
|
216 |
/* For Meta, Shift, and Control modifiers, we need special care. */ |
min_char = max_char = entries->entry[0].c; |
217 |
if (c & CHAR_META) |
nonascii_min_char = MAX_CHAR; |
218 |
|
for (i = 0; i < n_entries; i++) |
219 |
|
{ |
220 |
|
unsigned from, to; |
221 |
|
int from_index, to_index; |
222 |
|
int from_c, to_c; |
223 |
|
int idx = i % 0x10000; |
224 |
|
|
225 |
|
if (i > 0 && idx == 0) |
226 |
|
entries = entries->next; |
227 |
|
from = entries->entry[idx].from; |
228 |
|
to = entries->entry[idx].to; |
229 |
|
from_c = entries->entry[idx].c; |
230 |
|
from_index = CODE_POINT_TO_INDEX (charset, from); |
231 |
|
if (from == to) |
232 |
{ |
{ |
233 |
/* Move the meta bit to the right place for a string. */ |
to_index = from_index; |
234 |
c = (c & ~CHAR_META) | 0x80; |
to_c = from_c; |
235 |
} |
} |
236 |
if (c & CHAR_SHIFT) |
else |
237 |
{ |
{ |
238 |
/* Shift modifier is valid only with [A-Za-z]. */ |
to_index = CODE_POINT_TO_INDEX (charset, to); |
239 |
if ((c & 0377) >= 'A' && (c & 0377) <= 'Z') |
to_c = from_c + (to_index - from_index); |
|
c &= ~CHAR_SHIFT; |
|
|
else if ((c & 0377) >= 'a' && (c & 0377) <= 'z') |
|
|
c = (c & ~CHAR_SHIFT) - ('a' - 'A'); |
|
240 |
} |
} |
241 |
if (c & CHAR_CTL) |
if (from_index < 0 || to_index < 0) |
242 |
|
continue; |
243 |
|
|
244 |
|
if (control_flag < 2) |
245 |
{ |
{ |
246 |
/* Simulate the code in lread.c. */ |
int c; |
|
/* Allow `\C- ' and `\C-?'. */ |
|
|
if (c == (CHAR_CTL | ' ')) |
|
|
c = 0; |
|
|
else if (c == (CHAR_CTL | '?')) |
|
|
c = 127; |
|
|
/* ASCII control chars are made from letters (both cases), |
|
|
as well as the non-letters within 0100...0137. */ |
|
|
else if ((c & 0137) >= 0101 && (c & 0137) <= 0132) |
|
|
c &= (037 | (~0177 & ~CHAR_CTL)); |
|
|
else if ((c & 0177) >= 0100 && (c & 0177) <= 0137) |
|
|
c &= (037 | (~0177 & ~CHAR_CTL)); |
|
|
} |
|
247 |
|
|
248 |
/* If C still has any modifier bits, just ignore it. */ |
if (to_c > max_char) |
249 |
c &= ~CHAR_MODIFIER_MASK; |
max_char = to_c; |
250 |
} |
else if (from_c < min_char) |
251 |
|
min_char = from_c; |
252 |
|
if (ascii_compatible_p) |
253 |
|
{ |
254 |
|
if (! ASCII_BYTE_P (from_c)) |
255 |
|
{ |
256 |
|
if (from_c < nonascii_min_char) |
257 |
|
nonascii_min_char = from_c; |
258 |
|
} |
259 |
|
else if (! ASCII_BYTE_P (to_c)) |
260 |
|
{ |
261 |
|
nonascii_min_char = 0x80; |
262 |
|
} |
263 |
|
} |
264 |
|
|
265 |
if (SINGLE_BYTE_CHAR_P (c)) |
for (c = from_c; c <= to_c; c++) |
266 |
{ |
CHARSET_FAST_MAP_SET (c, fast_map); |
267 |
if (ASCII_BYTE_P (c) || c >= 0xA0) |
|
268 |
*p++ = c; |
if (control_flag == 1) |
269 |
|
{ |
270 |
|
unsigned code = from; |
271 |
|
|
272 |
|
if (CHARSET_COMPACT_CODES_P (charset)) |
273 |
|
while (1) |
274 |
|
{ |
275 |
|
ASET (vec, from_index, make_number (from_c)); |
276 |
|
if (NILP (CHAR_TABLE_REF (table, from_c))) |
277 |
|
CHAR_TABLE_SET (table, from_c, make_number (code)); |
278 |
|
if (from_index == to_index) |
279 |
|
break; |
280 |
|
from_index++, from_c++; |
281 |
|
code = INDEX_TO_CODE_POINT (charset, from_index); |
282 |
|
} |
283 |
|
else |
284 |
|
for (; from_index <= to_index; from_index++, from_c++) |
285 |
|
{ |
286 |
|
ASET (vec, from_index, make_number (from_c)); |
287 |
|
if (NILP (CHAR_TABLE_REF (table, from_c))) |
288 |
|
CHAR_TABLE_SET (table, from_c, make_number (from_index)); |
289 |
|
} |
290 |
|
} |
291 |
|
} |
292 |
else |
else |
293 |
{ |
{ |
294 |
*p++ = LEADING_CODE_8_BIT_CONTROL; |
unsigned code = from; |
295 |
*p++ = c + 0x20; |
|
296 |
|
while (1) |
297 |
|
{ |
298 |
|
int c1 = DECODE_CHAR (charset, code); |
299 |
|
|
300 |
|
if (c1 >= 0) |
301 |
|
{ |
302 |
|
CHAR_TABLE_SET (table, from_c, make_number (c1)); |
303 |
|
CHAR_TABLE_SET (Vchar_unify_table, c1, make_number (from_c)); |
304 |
|
if (CHAR_TABLE_P (Vchar_unified_charset_table)) |
305 |
|
CHAR_TABLE_SET (Vchar_unified_charset_table, c1, |
306 |
|
CHARSET_NAME (charset)); |
307 |
|
} |
308 |
|
if (from_index == to_index) |
309 |
|
break; |
310 |
|
from_index++, from_c++; |
311 |
|
code = INDEX_TO_CODE_POINT (charset, from_index); |
312 |
|
} |
313 |
} |
} |
314 |
} |
} |
|
else if (CHAR_VALID_P (c, 0)) |
|
|
{ |
|
|
int charset, c1, c2; |
|
315 |
|
|
316 |
SPLIT_CHAR (c, charset, c1, c2); |
if (control_flag < 2) |
317 |
|
{ |
318 |
if (charset >= LEADING_CODE_EXT_11) |
CHARSET_MIN_CHAR (charset) = (ascii_compatible_p |
319 |
*p++ = (charset < LEADING_CODE_EXT_12 |
? nonascii_min_char : min_char); |
320 |
? LEADING_CODE_PRIVATE_11 |
CHARSET_MAX_CHAR (charset) = max_char; |
321 |
: (charset < LEADING_CODE_EXT_21 |
if (control_flag == 1) |
|
? LEADING_CODE_PRIVATE_12 |
|
|
: (charset < LEADING_CODE_EXT_22 |
|
|
? LEADING_CODE_PRIVATE_21 |
|
|
: LEADING_CODE_PRIVATE_22))); |
|
|
*p++ = charset; |
|
|
if ((c1 > 0 && c1 < 32) || (c2 > 0 && c2 < 32)) |
|
|
return -1; |
|
|
if (c1) |
|
322 |
{ |
{ |
323 |
*p++ = c1 | 0x80; |
CHARSET_DECODER (charset) = vec; |
324 |
if (c2 > 0) |
CHARSET_ENCODER (charset) = table; |
|
*p++ = c2 | 0x80; |
|
325 |
} |
} |
326 |
} |
} |
327 |
else |
else |
328 |
return -1; |
CHARSET_DEUNIFIER (charset) = table; |
|
|
|
|
return (p - str); |
|
329 |
} |
} |
330 |
|
|
331 |
|
|
332 |
/* 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 |
333 |
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. */ |
|
334 |
|
|
335 |
int |
static INLINE unsigned |
336 |
char_to_string (c, str) |
read_hex (fp, eof) |
337 |
int c; |
FILE *fp; |
338 |
unsigned char *str; |
int *eof; |
339 |
{ |
{ |
340 |
int len; |
int c; |
341 |
len = char_to_string_1 (c, str); |
unsigned n; |
342 |
if (len == -1) |
|
343 |
invalid_character (c); |
while ((c = getc (fp)) != EOF) |
344 |
return len; |
{ |
345 |
|
if (c == '#') |
346 |
|
{ |
347 |
|
while ((c = getc (fp)) != EOF && c != '\n'); |
348 |
|
} |
349 |
|
else if (c == '0') |
350 |
|
{ |
351 |
|
if ((c = getc (fp)) == EOF || c == 'x') |
352 |
|
break; |
353 |
|
} |
354 |
|
} |
355 |
|
if (c == EOF) |
356 |
|
{ |
357 |
|
*eof = 1; |
358 |
|
return 0; |
359 |
|
} |
360 |
|
*eof = 0; |
361 |
|
n = 0; |
362 |
|
if (c == 'x') |
363 |
|
while ((c = getc (fp)) != EOF && isxdigit (c)) |
364 |
|
n = ((n << 4) |
365 |
|
| (c <= '9' ? c - '0' : c <= 'F' ? c - 'A' + 10 : c - 'a' + 10)); |
366 |
|
else |
367 |
|
while ((c = getc (fp)) != EOF && isdigit (c)) |
368 |
|
n = (n * 10) + c - '0'; |
369 |
|
if (c != EOF) |
370 |
|
ungetc (c, fp); |
371 |
|
return n; |
372 |
} |
} |
373 |
|
|
374 |
|
|
375 |
/* Return the non-ASCII character corresponding to multi-byte form at |
/* Return a mapping vector for CHARSET loaded from MAPFILE. |
376 |
STR of length LEN. If ACTUAL_LEN is not NULL, store the byte |
Each line of MAPFILE has this form |
377 |
length of the multibyte form in *ACTUAL_LEN. |
0xAAAA 0xCCCC |
378 |
|
where 0xAAAA is a code-point and 0xCCCC is the corresponding |
379 |
|
character code, or this form |
380 |
|
0xAAAA-0xBBBB 0xCCCC |
381 |
|
where 0xAAAA and 0xBBBB are code-points specifying a range, and |
382 |
|
0xCCCC is the first character code of the range. |
383 |
|
|
384 |
|
The returned vector has this form: |
385 |
|
[ CODE1 CHAR1 CODE2 CHAR2 .... ] |
386 |
|
where CODE1 is a code-point or a cons of code-points specifying a |
387 |
|
range. */ |
388 |
|
|
389 |
|
extern void add_to_log P_ ((char *, Lisp_Object, Lisp_Object)); |
390 |
|
|
391 |
|
static void |
392 |
|
load_charset_map_from_file (charset, mapfile, control_flag) |
393 |
|
struct charset *charset; |
394 |
|
Lisp_Object mapfile; |
395 |
|
int control_flag; |
396 |
|
{ |
397 |
|
unsigned min_code = CHARSET_MIN_CODE (charset); |
398 |
|
unsigned max_code = CHARSET_MAX_CODE (charset); |
399 |
|
int fd; |
400 |
|
FILE *fp; |
401 |
|
int eof; |
402 |
|
Lisp_Object suffixes; |
403 |
|
struct charset_map_entries *head, *entries; |
404 |
|
int n_entries; |
405 |
|
|
406 |
|
suffixes = Fcons (build_string (".map"), |
407 |
|
Fcons (build_string (".TXT"), Qnil)); |
408 |
|
|
409 |
|
fd = openp (Fcons (Vcharset_map_directory, Qnil), mapfile, suffixes, |
410 |
|
NULL, Qnil); |
411 |
|
if (fd < 0 |
412 |
|
|| ! (fp = fdopen (fd, "r"))) |
413 |
|
{ |
414 |
|
add_to_log ("Failure in loading charset map: %S", mapfile, Qnil); |
415 |
|
return; |
416 |
|
} |
417 |
|
|
418 |
|
head = entries = ((struct charset_map_entries *) |
419 |
|
alloca (sizeof (struct charset_map_entries))); |
420 |
|
n_entries = 0; |
421 |
|
eof = 0; |
422 |
|
while (1) |
423 |
|
{ |
424 |
|
unsigned from, to; |
425 |
|
int c; |
426 |
|
int idx; |
427 |
|
|
428 |
|
from = read_hex (fp, &eof); |
429 |
|
if (eof) |
430 |
|
break; |
431 |
|
if (getc (fp) == '-') |
432 |
|
to = read_hex (fp, &eof); |
433 |
|
else |
434 |
|
to = from; |
435 |
|
c = (int) read_hex (fp, &eof); |
436 |
|
|
437 |
Use macros STRING_CHAR or STRING_CHAR_AND_LENGTH instead of calling |
if (from < min_code || to > max_code || from > to || c > MAX_CHAR) |
438 |
this function directly if you want ot handle ASCII characters as |
continue; |
|
well. */ |
|
439 |
|
|
440 |
int |
if (n_entries > 0 && (n_entries % 0x10000) == 0) |
441 |
string_to_char (str, len, actual_len) |
{ |
442 |
const unsigned char *str; |
entries->next = ((struct charset_map_entries *) |
443 |
int len, *actual_len; |
alloca (sizeof (struct charset_map_entries))); |
444 |
{ |
entries = entries->next; |
445 |
int c, bytes, charset, c1, c2; |
} |
446 |
|
idx = n_entries % 0x10000; |
447 |
SPLIT_MULTIBYTE_SEQ (str, len, bytes, charset, c1, c2); |
entries->entry[idx].from = from; |
448 |
c = MAKE_CHAR (charset, c1, c2); |
entries->entry[idx].to = to; |
449 |
if (actual_len) |
entries->entry[idx].c = c; |
450 |
*actual_len = bytes; |
n_entries++; |
451 |
return c; |
} |
452 |
|
fclose (fp); |
453 |
|
close (fd); |
454 |
|
|
455 |
|
load_charset_map (charset, head, n_entries, control_flag); |
456 |
} |
} |
457 |
|
|
458 |
/* Return the length of the multi-byte form at string STR of length LEN. |
static void |
459 |
Use the macro MULTIBYTE_FORM_LENGTH instead. */ |
load_charset_map_from_vector (charset, vec, control_flag) |
460 |
int |
struct charset *charset; |
461 |
multibyte_form_length (str, len) |
Lisp_Object vec; |
462 |
const unsigned char *str; |
int control_flag; |
|
int len; |
|
463 |
{ |
{ |
464 |
int bytes; |
unsigned min_code = CHARSET_MIN_CODE (charset); |
465 |
|
unsigned max_code = CHARSET_MAX_CODE (charset); |
466 |
|
struct charset_map_entries *head, *entries; |
467 |
|
int n_entries; |
468 |
|
int len = ASIZE (vec); |
469 |
|
int i; |
470 |
|
|
471 |
PARSE_MULTIBYTE_SEQ (str, len, bytes); |
if (len % 2 == 1) |
472 |
return bytes; |
{ |
473 |
} |
add_to_log ("Failure in loading charset map: %V", vec, Qnil); |
474 |
|
return; |
475 |
|
} |
476 |
|
|
477 |
/* Check multibyte form at string STR of length LEN and set variables |
head = entries = ((struct charset_map_entries *) |
478 |
pointed by CHARSET, C1, and C2 to charset and position codes of the |
alloca (sizeof (struct charset_map_entries))); |
479 |
character at STR, and return 0. If there's no multibyte character, |
n_entries = 0; |
480 |
return -1. This should be used only in the macro SPLIT_STRING |
for (i = 0; i < len; i += 2) |
481 |
which checks range of STR in advance. */ |
{ |
482 |
|
Lisp_Object val, val2; |
483 |
|
unsigned from, to; |
484 |
|
int c; |
485 |
|
int idx; |
486 |
|
|
487 |
|
val = AREF (vec, i); |
488 |
|
if (CONSP (val)) |
489 |
|
{ |
490 |
|
val2 = XCDR (val); |
491 |
|
val = XCAR (val); |
492 |
|
CHECK_NATNUM (val); |
493 |
|
CHECK_NATNUM (val2); |
494 |
|
from = XFASTINT (val); |
495 |
|
to = XFASTINT (val2); |
496 |
|
} |
497 |
|
else |
498 |
|
{ |
499 |
|
CHECK_NATNUM (val); |
500 |
|
from = to = XFASTINT (val); |
501 |
|
} |
502 |
|
val = AREF (vec, i + 1); |
503 |
|
CHECK_NATNUM (val); |
504 |
|
c = XFASTINT (val); |
505 |
|
|
506 |
int |
if (from < min_code || to > max_code || from > to || c > MAX_CHAR) |
507 |
split_string (str, len, charset, c1, c2) |
continue; |
|
const unsigned char *str; |
|
|
unsigned char *c1, *c2; |
|
|
int len, *charset; |
|
|
{ |
|
|
register int bytes, cs, code1, code2 = -1; |
|
508 |
|
|
509 |
SPLIT_MULTIBYTE_SEQ (str, len, bytes, cs, code1, code2); |
if ((n_entries % 0x10000) == 0) |
510 |
if (cs == CHARSET_ASCII) |
{ |
511 |
return -1; |
entries->next = ((struct charset_map_entries *) |
512 |
*charset = cs; |
alloca (sizeof (struct charset_map_entries))); |
513 |
*c1 = code1; |
entries = entries->next; |
514 |
*c2 = code2; |
} |
515 |
return 0; |
idx = n_entries % 0x10000; |
516 |
|
entries->entry[idx].from = from; |
517 |
|
entries->entry[idx].to = to; |
518 |
|
entries->entry[idx].c = c; |
519 |
|
n_entries++; |
520 |
|
} |
521 |
|
|
522 |
|
load_charset_map (charset, head, n_entries, control_flag); |
523 |
} |
} |
524 |
|
|
525 |
/* Return 1 iff character C has valid printable glyph. |
static void |
526 |
Use the macro CHAR_PRINTABLE_P instead. */ |
load_charset (charset) |
527 |
int |
struct charset *charset; |
|
char_printable_p (c) |
|
|
int c; |
|
528 |
{ |
{ |
529 |
int charset, c1, c2; |
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED) |
530 |
|
{ |
531 |
if (ASCII_BYTE_P (c)) |
Lisp_Object map; |
|
return 1; |
|
|
else if (SINGLE_BYTE_CHAR_P (c)) |
|
|
return 0; |
|
|
else if (c >= MAX_CHAR) |
|
|
return 0; |
|
532 |
|
|
533 |
SPLIT_CHAR (c, charset, c1, c2); |
map = CHARSET_MAP (charset); |
534 |
if (! CHARSET_DEFINED_P (charset)) |
if (STRINGP (map)) |
535 |
return 0; |
load_charset_map_from_file (charset, map, 1); |
536 |
if (CHARSET_CHARS (charset) == 94 |
else |
537 |
? c1 <= 32 || c1 >= 127 |
load_charset_map_from_vector (charset, map, 1); |
538 |
: c1 < 32) |
CHARSET_METHOD (charset) = CHARSET_METHOD_MAP; |
539 |
return 0; |
} |
|
if (CHARSET_DIMENSION (charset) == 2 |
|
|
&& (CHARSET_CHARS (charset) == 94 |
|
|
? c2 <= 32 || c2 >= 127 |
|
|
: c2 < 32)) |
|
|
return 0; |
|
|
return 1; |
|
540 |
} |
} |
541 |
|
|
542 |
/* Translate character C by translation table TABLE. If C |
|
543 |
is negative, translate a character specified by CHARSET, C1, and C2 |
DEFUN ("charsetp", Fcharsetp, Scharsetp, 1, 1, 0, |
544 |
(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.*/) |
545 |
found in TABLE, return C. */ |
(object) |
546 |
int |
Lisp_Object object; |
|
translate_char (table, c, charset, c1, c2) |
|
|
Lisp_Object table; |
|
|
int c, charset, c1, c2; |
|
547 |
{ |
{ |
548 |
Lisp_Object ch; |
return (CHARSETP (object) ? Qt : Qnil); |
549 |
int alt_charset, alt_c1, alt_c2, dimension; |
} |
550 |
|
|
|
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. */ |
|
551 |
|
|
552 |
int |
void |
553 |
unibyte_char_to_multibyte (c) |
map_charset_chars (c_function, function, arg, |
554 |
int c; |
charset, from, to) |
555 |
|
void (*c_function) P_ ((Lisp_Object, Lisp_Object)); |
556 |
|
Lisp_Object function, arg; |
557 |
|
struct charset *charset; |
558 |
|
unsigned from, to; |
559 |
{ |
{ |
560 |
if (c < 0400 && c >= 0200) |
Lisp_Object range; |
561 |
|
int partial; |
562 |
|
|
563 |
|
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP_DEFERRED) |
564 |
|
load_charset (charset); |
565 |
|
|
566 |
|
partial = (from > CHARSET_MIN_CODE (charset) |
567 |
|
|| to < CHARSET_MAX_CODE (charset)); |
568 |
|
|
569 |
|
if (CHARSET_UNIFIED_P (charset) |
570 |
|
&& CHAR_TABLE_P (CHARSET_DEUNIFIER (charset))) |
571 |
|
{ |
572 |
|
map_char_table_for_charset (c_function, function, |
573 |
|
CHARSET_DEUNIFIER (charset), arg, |
574 |
|
partial ? charset : NULL, from, to); |
575 |
|
} |
576 |
|
|
577 |
|
if (CHARSET_METHOD (charset) == CHARSET_METHOD_OFFSET) |
578 |
{ |
{ |
579 |
int c_save = c; |
int from_idx = CODE_POINT_TO_INDEX (charset, from); |
580 |
|
int to_idx = CODE_POINT_TO_INDEX (charset, to); |
581 |
|
int from_c = from_idx + CHARSET_CODE_OFFSET (charset); |
582 |
|
int to_c = to_idx + CHARSET_CODE_OFFSET (charset); |
583 |
|
|
584 |
if (! NILP (Vnonascii_translation_table)) |
range = Fcons (make_number (from_c), make_number (to_c)); |
585 |
|
if (NILP (function)) |
586 |
|
(*c_function) (range, arg); |
587 |
|
else |
588 |
|
call2 (function, range, arg); |
589 |
|
} |
590 |
|
else if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP) |
591 |
|
{ |
592 |
|
if (! CHAR_TABLE_P (CHARSET_ENCODER (charset))) |
593 |
|
return; |
594 |
|
if (CHARSET_ASCII_COMPATIBLE_P (charset) && from <= 127) |
595 |
{ |
{ |
596 |
c = XINT (Faref (Vnonascii_translation_table, make_number (c))); |
range = Fcons (make_number (from), make_number (to)); |
597 |
if (c >= 0400 && ! char_valid_p (c, 0)) |
if (to >= 128) |
598 |
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
XSETCAR (range, make_number (127)); |
599 |
|
|
600 |
|
if (NILP (function)) |
601 |
|
(*c_function) (range, arg); |
602 |
|
else |
603 |
|
call2 (function, range, arg); |
604 |
} |
} |
605 |
else if (c >= 0240 && nonascii_insert_offset > 0) |
map_char_table_for_charset (c_function, function, |
606 |
|
CHARSET_ENCODER (charset), arg, |
607 |
|
partial ? charset : NULL, from, to); |
608 |
|
} |
609 |
|
else if (CHARSET_METHOD (charset) == CHARSET_METHOD_SUBSET) |
610 |
|
{ |
611 |
|
Lisp_Object subset_info; |
612 |
|
int offset; |
613 |
|
|
614 |
|
subset_info = CHARSET_SUBSET (charset); |
615 |
|
charset = CHARSET_FROM_ID (XFASTINT (AREF (subset_info, 0))); |
616 |
|
offset = XINT (AREF (subset_info, 3)); |
617 |
|
from -= offset; |
618 |
|
if (from < XFASTINT (AREF (subset_info, 1))) |
619 |
|
from = XFASTINT (AREF (subset_info, 1)); |
620 |
|
to -= offset; |
621 |
|
if (to > XFASTINT (AREF (subset_info, 2))) |
622 |
|
to = XFASTINT (AREF (subset_info, 2)); |
623 |
|
map_charset_chars (c_function, function, arg, charset, from, to); |
624 |
|
} |
625 |
|
else /* i.e. CHARSET_METHOD_SUPERSET */ |
626 |
|
{ |
627 |
|
Lisp_Object parents; |
628 |
|
|
629 |
|
for (parents = CHARSET_SUPERSET (charset); CONSP (parents); |
630 |
|
parents = XCDR (parents)) |
631 |
{ |
{ |
632 |
c += nonascii_insert_offset; |
int offset; |
633 |
if (c < 0400 || ! char_valid_p (c, 0)) |
unsigned this_from, this_to; |
634 |
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
|
635 |
|
charset = CHARSET_FROM_ID (XFASTINT (XCAR (XCAR (parents)))); |
636 |
|
offset = XINT (XCDR (XCAR (parents))); |
637 |
|
this_from = from - offset; |
638 |
|
this_to = to - offset; |
639 |
|
if (this_from < CHARSET_MIN_CODE (charset)) |
640 |
|
this_from = CHARSET_MIN_CODE (charset); |
641 |
|
if (this_to > CHARSET_MAX_CODE (charset)) |
642 |
|
this_to = CHARSET_MAX_CODE (charset); |
643 |
|
map_charset_chars (c_function, function, arg, charset, from, to); |
644 |
} |
} |
|
else if (c >= 0240) |
|
|
c = c_save + DEFAULT_NONASCII_INSERT_OFFSET; |
|
645 |
} |
} |
|
return c; |
|
646 |
} |
} |
647 |
|
|
648 |
|
DEFUN ("map-charset-chars", Fmap_charset_chars, Smap_charset_chars, 2, 5, 0, |
649 |
|
doc: /* Call FUNCTION for all characters in CHARSET. |
650 |
|
FUNCTION is called with an argument RANGE and the optional 3rd |
651 |
|
argument ARG. |
652 |
|
|
653 |
/* Convert the multibyte character C to unibyte 8-bit character based |
RANGE is a cons (FROM . TO), where FROM and TO indicate a range of |
654 |
on Vnonascii_translation_table or nonascii_insert_offset. If |
characters contained in CHARSET. |
|
REV_TBL is non-nil, it should be a reverse table of |
|
|
Vnonascii_translation_table, i.e. what given by: |
|
|
Fchar_table_extra_slot (Vnonascii_translation_table, make_number (0)) */ |
|
655 |
|
|
656 |
int |
The optional 4th and 5th arguments FROM-CODE and TO-CODE specify the |
657 |
multibyte_char_to_unibyte (c, rev_tbl) |
range of code points of target characters. */) |
658 |
int c; |
(function, charset, arg, from_code, to_code) |
659 |
Lisp_Object rev_tbl; |
Lisp_Object function, charset, arg, from_code, to_code; |
660 |
|
{ |
661 |
|
struct charset *cs; |
662 |
|
unsigned from, to; |
663 |
|
|
664 |
|
CHECK_CHARSET_GET_CHARSET (charset, cs); |
665 |
|
if (NILP (from_code)) |
666 |
|
from = CHARSET_MIN_CODE (cs); |
667 |
|
else |
668 |
|
{ |
669 |
|
CHECK_NATNUM (from_code); |
670 |
|
from = XINT (from_code); |
671 |
|
if (from < CHARSET_MIN_CODE (cs)) |
672 |
|
from = CHARSET_MIN_CODE (cs); |
673 |
|
} |
674 |
|
if (NILP (to_code)) |
675 |
|
to = CHARSET_MAX_CODE (cs); |
676 |
|
else |
677 |
|
{ |
678 |
|
CHECK_NATNUM (to_code); |
679 |
|
to = XINT (to_code); |
680 |
|
if (to > CHARSET_MAX_CODE (cs)) |
681 |
|
to = CHARSET_MAX_CODE (cs); |
682 |
|
} |
683 |
|
map_charset_chars (NULL, function, arg, cs, from, to); |
684 |
|
return Qnil; |
685 |
|
} |
686 |
|
|
687 |
|
|
688 |
|
/* Define a charset according to the arguments. The Nth argument is |
689 |
|
the Nth attribute of the charset (the last attribute `charset-id' |
690 |
|
is not included). See the docstring of `define-charset' for the |
691 |
|
detail. */ |
692 |
|
|
693 |
|
DEFUN ("define-charset-internal", Fdefine_charset_internal, |
694 |
|
Sdefine_charset_internal, charset_arg_max, MANY, 0, |
695 |
|
doc: /* For internal use only. |
696 |
|
usage: (define-charset-internal ...) */) |
697 |
|
(nargs, args) |
698 |
|
int nargs; |
699 |
|
Lisp_Object *args; |
700 |
{ |
{ |
701 |
if (!SINGLE_BYTE_CHAR_P (c)) |
/* Charset attr vector. */ |
702 |
|
Lisp_Object attrs; |
703 |
|
Lisp_Object val; |
704 |
|
unsigned hash_code; |
705 |
|
struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table); |
706 |
|
int i, j; |
707 |
|
struct charset charset; |
708 |
|
int id; |
709 |
|
int dimension; |
710 |
|
int new_definition_p; |
711 |
|
int nchars; |
712 |
|
|
713 |
|
if (nargs != charset_arg_max) |
714 |
|
return Fsignal (Qwrong_number_of_arguments, |
715 |
|
Fcons (intern ("define-charset-internal"), |
716 |
|
make_number (nargs))); |
717 |
|
|
718 |
|
attrs = Fmake_vector (make_number (charset_attr_max), Qnil); |
719 |
|
|
720 |
|
CHECK_SYMBOL (args[charset_arg_name]); |
721 |
|
ASET (attrs, charset_name, args[charset_arg_name]); |
722 |
|
|
723 |
|
val = args[charset_arg_code_space]; |
724 |
|
for (i = 0, dimension = 0, nchars = 1; i < 4; i++) |
725 |
|
{ |
726 |
|
int min_byte, max_byte; |
727 |
|
|
728 |
|
min_byte = XINT (Faref (val, make_number (i * 2))); |
729 |
|
max_byte = XINT (Faref (val, make_number (i * 2 + 1))); |
730 |
|
if (min_byte < 0 || min_byte > max_byte || max_byte >= 256) |
731 |
|
error ("Invalid :code-space value"); |
732 |
|
charset.code_space[i * 4] = min_byte; |
733 |
|
charset.code_space[i * 4 + 1] = max_byte; |
734 |
|
charset.code_space[i * 4 + 2] = max_byte - min_byte + 1; |
735 |
|
nchars *= charset.code_space[i * 4 + 2]; |
736 |
|
charset.code_space[i * 4 + 3] = nchars; |
737 |
|
if (max_byte > 0) |
738 |
|
dimension = i + 1; |
739 |
|
} |
740 |
|
|
741 |
|
val = args[charset_arg_dimension]; |
742 |
|
if (NILP (val)) |
743 |
|
charset.dimension = dimension; |
744 |
|
else |
745 |
{ |
{ |
746 |
int c_save = c; |
CHECK_NATNUM (val); |
747 |
|
charset.dimension = XINT (val); |
748 |
|
if (charset.dimension < 1 || charset.dimension > 4) |
749 |
|
args_out_of_range_3 (val, make_number (1), make_number (4)); |
750 |
|
} |
751 |
|
|
752 |
|
charset.code_linear_p |
753 |
|
= (charset.dimension == 1 |
754 |
|
|| (charset.code_space[2] == 256 |
755 |
|
&& (charset.dimension == 2 |
756 |
|
|| (charset.code_space[6] == 256 |
757 |
|
&& (charset.dimension == 3 |
758 |
|
|| charset.code_space[10] == 256))))); |
759 |
|
|
760 |
|
if (! charset.code_linear_p) |
761 |
|
{ |
762 |
|
charset.code_space_mask = (unsigned char *) xmalloc (256); |
763 |
|
bzero (charset.code_space_mask, 256); |
764 |
|
for (i = 0; i < 4; i++) |
765 |
|
for (j = charset.code_space[i * 4]; j <= charset.code_space[i * 4 + 1]; |
766 |
|
j++) |
767 |
|
charset.code_space_mask[j] |= (1 << i); |
768 |
|
} |
769 |
|
|
770 |
|
charset.iso_chars_96 = charset.code_space[2] == 96; |
771 |
|
|
772 |
|
charset.min_code = (charset.code_space[0] |
773 |
|
| (charset.code_space[4] << 8) |
774 |
|
| (charset.code_space[8] << 16) |
775 |
|
| (charset.code_space[12] << 24)); |
776 |
|
charset.max_code = (charset.code_space[1] |
777 |
|
| (charset.code_space[5] << 8) |
778 |
|
| (charset.code_space[9] << 16) |
779 |
|
| (charset.code_space[13] << 24)); |
780 |
|
charset.char_index_offset = 0; |
781 |
|
|
782 |
if (! CHAR_TABLE_P (rev_tbl) |
val = args[charset_arg_min_code]; |
783 |
&& CHAR_TABLE_P (Vnonascii_translation_table)) |
if (! NILP (val)) |
784 |
rev_tbl = Fchar_table_extra_slot (Vnonascii_translation_table, |
{ |
785 |
make_number (0)); |
unsigned code; |
786 |
if (CHAR_TABLE_P (rev_tbl)) |
|
787 |
{ |
if (INTEGERP (val)) |
788 |
Lisp_Object temp; |
code = XINT (val); |
|
temp = Faref (rev_tbl, make_number (c)); |
|
|
if (INTEGERP (temp)) |
|
|
c = XINT (temp); |
|
|
if (c >= 256) |
|
|
c = (c_save & 0177) + 0200; |
|
|
} |
|
789 |
else |
else |
790 |
{ |
{ |
791 |
if (nonascii_insert_offset > 0) |
CHECK_CONS (val); |
792 |
c -= nonascii_insert_offset; |
CHECK_NUMBER_CAR (val); |
793 |
if (c < 128 || c >= 256) |
CHECK_NUMBER_CDR (val); |
794 |
c = (c_save & 0177) + 0200; |
code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val))); |
795 |
|
} |
796 |
|
if (code < charset.min_code |
797 |
|
|| code > charset.max_code) |
798 |
|
args_out_of_range_3 (make_number (charset.min_code), |
799 |
|
make_number (charset.max_code), val); |
800 |
|
charset.char_index_offset = CODE_POINT_TO_INDEX (&charset, code); |
801 |
|
charset.min_code = code; |
802 |
|
} |
803 |
|
|
804 |
|
val = args[charset_arg_max_code]; |
805 |
|
if (! NILP (val)) |
806 |
|
{ |
807 |
|
unsigned code; |
808 |
|
|
809 |
|
if (INTEGERP (val)) |
810 |
|
code = XINT (val); |
811 |
|
else |
812 |
|
{ |
813 |
|
CHECK_CONS (val); |
814 |
|
CHECK_NUMBER_CAR (val); |
815 |
|
CHECK_NUMBER_CDR (val); |
816 |
|
code = (XINT (XCAR (val)) << 16) | (XINT (XCDR (val))); |
817 |
} |
} |
818 |
|
if (code < charset.min_code |
819 |
|
|| code > charset.max_code) |
820 |
|
args_out_of_range_3 (make_number (charset.min_code), |
821 |
|
make_number (charset.max_code), val); |
822 |
|
charset.max_code = code; |
823 |
} |
} |
824 |
|
|
825 |
return c; |
charset.compact_codes_p = charset.max_code < 0x1000000; |
|
} |
|
826 |
|
|
827 |
|
val = args[charset_arg_invalid_code]; |
828 |
/* Update the table Vcharset_table with the given arguments (see the |
if (NILP (val)) |
829 |
document of `define-charset' for the meaning of each argument). |
{ |
830 |
Several other table contents are also updated. The caller should |
if (charset.min_code > 0) |
831 |
check the validity of CHARSET-ID and the remaining arguments in |
charset.invalid_code = 0; |
832 |
advance. */ |
else |
833 |
|
{ |
834 |
|
XSETINT (val, charset.max_code + 1); |
835 |
|
if (XINT (val) == charset.max_code + 1) |
836 |
|
charset.invalid_code = charset.max_code + 1; |
837 |
|
else |
838 |
|
error ("Attribute :invalid-code must be specified"); |
839 |
|
} |
840 |
|
} |
841 |
|
else |
842 |
|
{ |
843 |
|
CHECK_NATNUM (val); |
844 |
|
charset.invalid_code = XFASTINT (val); |
845 |
|
} |
846 |
|
|
847 |
void |
val = args[charset_arg_iso_final]; |
848 |
update_charset_table (charset_id, dimension, chars, width, direction, |
if (NILP (val)) |
849 |
iso_final_char, iso_graphic_plane, |
charset.iso_final = -1; |
850 |
short_name, long_name, description) |
else |
851 |
Lisp_Object charset_id, dimension, chars, width, direction; |
{ |
852 |
Lisp_Object iso_final_char, iso_graphic_plane; |
CHECK_NUMBER (val); |
853 |
Lisp_Object short_name, long_name, description; |
if (XINT (val) < '0' || XINT (val) > 127) |
854 |
{ |
error ("Invalid iso-final-char: %d", XINT (val)); |
855 |
int charset = XINT (charset_id); |
charset.iso_final = XINT (val); |
|
int bytes; |
|
|
unsigned char leading_code_base, leading_code_ext; |
|
|
|
|
|
if (NILP (CHARSET_TABLE_ENTRY (charset))) |
|
|
CHARSET_TABLE_ENTRY (charset) |
|
|
= Fmake_vector (make_number (CHARSET_MAX_IDX), Qnil); |
|
|
|
|
|
if (NILP (long_name)) |
|
|
long_name = short_name; |
|
|
if (NILP (description)) |
|
|
description = long_name; |
|
|
|
|
|
/* Get byte length of multibyte form, base leading-code, and |
|
|
extended leading-code of the charset. See the comment under the |
|
|
title "GENERAL NOTE on CHARACTER SET (CHARSET)" in charset.h. */ |
|
|
bytes = XINT (dimension); |
|
|
if (charset < MIN_CHARSET_PRIVATE_DIMENSION1) |
|
|
{ |
|
|
/* Official charset, it doesn't have an extended leading-code. */ |
|
|
if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC) |
|
|
bytes += 1; /* For a base leading-code. */ |
|
|
leading_code_base = charset; |
|
|
leading_code_ext = 0; |
|
856 |
} |
} |
857 |
|
|
858 |
|
val = args[charset_arg_iso_revision]; |
859 |
|
if (NILP (val)) |
860 |
|
charset.iso_revision = -1; |
861 |
else |
else |
862 |
{ |
{ |
863 |
/* Private charset. */ |
CHECK_NUMBER (val); |
864 |
bytes += 2; /* For base and extended leading-codes. */ |
if (XINT (val) > 63) |
865 |
leading_code_base |
args_out_of_range (make_number (63), val); |
866 |
= (charset < LEADING_CODE_EXT_12 |
charset.iso_revision = XINT (val); |
867 |
? LEADING_CODE_PRIVATE_11 |
} |
|
: (charset < LEADING_CODE_EXT_21 |
|
|
? LEADING_CODE_PRIVATE_12 |
|
|
: (charset < LEADING_CODE_EXT_22 |
|
|
? LEADING_CODE_PRIVATE_21 |
|
|
: LEADING_CODE_PRIVATE_22))); |
|
|
leading_code_ext = charset; |
|
|
if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes) |
|
|
error ("Invalid dimension for the charset-ID %d", charset); |
|
|
} |
|
|
|
|
|
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; |
|
868 |
|
|
869 |
{ |
val = args[charset_arg_emacs_mule_id]; |
870 |
/* If we have already defined a charset which has the same |
if (NILP (val)) |
871 |
DIMENSION, CHARS and ISO-FINAL-CHAR but the different |
charset.emacs_mule_id = -1; |
872 |
DIRECTION, we must update the entry REVERSE-CHARSET of both |
else |
873 |
charsets. If there's no such charset, the value of the entry |
{ |
874 |
is set to nil. */ |
CHECK_NATNUM (val); |
875 |
int i; |
if ((XINT (val) > 0 && XINT (val) <= 128) || XINT (val) >= 256) |
876 |
|
error ("Invalid emacs-mule-id: %d", XINT (val)); |
877 |
for (i = 0; i <= MAX_CHARSET; i++) |
charset.emacs_mule_id = XINT (val); |
878 |
if (!NILP (CHARSET_TABLE_ENTRY (i))) |
} |
879 |
{ |
|
880 |
if (CHARSET_DIMENSION (i) == XINT (dimension) |
charset.ascii_compatible_p = ! NILP (args[charset_arg_ascii_compatible_p]); |
881 |
&& CHARSET_CHARS (i) == XINT (chars) |
|
882 |
&& CHARSET_ISO_FINAL_CHAR (i) == XINT (iso_final_char) |
charset.supplementary_p = ! NILP (args[charset_arg_supplementary_p]); |
883 |
&& CHARSET_DIRECTION (i) != XINT (direction)) |
|
884 |
|
charset.unified_p = 0; |
885 |
|
|
886 |
|
bzero (charset.fast_map, sizeof (charset.fast_map)); |
887 |
|
|
888 |
|
if (! NILP (args[charset_arg_code_offset])) |
889 |
|
{ |
890 |
|
val = args[charset_arg_code_offset]; |
891 |
|
CHECK_NUMBER (val); |
892 |
|
|
893 |
|
charset.method = CHARSET_METHOD_OFFSET; |
894 |
|
charset.code_offset = XINT (val); |
895 |
|
|
896 |
|
i = CODE_POINT_TO_INDEX (&charset, charset.min_code); |
897 |
|
charset.min_char = i + charset.code_offset; |
898 |
|
i = CODE_POINT_TO_INDEX (&charset, charset.max_code); |
899 |
|
charset.max_char = i + charset.code_offset; |
900 |
|
if (charset.max_char > MAX_CHAR) |
901 |
|
error ("Unsupported max char: %d", charset.max_char); |
902 |
|
|
903 |
|
i = (charset.min_char >> 7) << 7; |
904 |
|
for (; i < 0x10000 && i <= charset.max_char; i += 128) |
905 |
|
CHARSET_FAST_MAP_SET (i, charset.fast_map); |
906 |
|
i = (i >> 12) << 12; |
907 |
|
for (; i <= charset.max_char; i += 0x1000) |
908 |
|
CHARSET_FAST_MAP_SET (i, charset.fast_map); |
909 |
|
} |
910 |
|
else if (! NILP (args[charset_arg_map])) |
911 |
|
{ |
912 |
|
val = args[charset_arg_map]; |
913 |
|
ASET (attrs, charset_map, val); |
914 |
|
if (STRINGP (val)) |
915 |
|
load_charset_map_from_file (&charset, val, 0); |
916 |
|
else |
917 |
|
load_charset_map_from_vector (&charset, val, 0); |
918 |
|
charset.method = CHARSET_METHOD_MAP_DEFERRED; |
919 |
|
} |
920 |
|
else if (! NILP (args[charset_arg_subset])) |
921 |
|
{ |
922 |
|
Lisp_Object parent; |
923 |
|
Lisp_Object parent_min_code, parent_max_code, parent_code_offset; |
924 |
|
struct charset *parent_charset; |
925 |
|
|
926 |
|
val = args[charset_arg_subset]; |
927 |
|
parent = Fcar (val); |
928 |
|
CHECK_CHARSET_GET_CHARSET (parent, parent_charset); |
929 |
|
parent_min_code = Fnth (make_number (1), val); |
930 |
|
CHECK_NATNUM (parent_min_code); |
931 |
|
parent_max_code = Fnth (make_number (2), val); |
932 |
|
CHECK_NATNUM (parent_max_code); |
933 |
|
parent_code_offset = Fnth (make_number (3), val); |
934 |
|
CHECK_NUMBER (parent_code_offset); |
935 |
|
val = Fmake_vector (make_number (4), Qnil); |
936 |
|
ASET (val, 0, make_number (parent_charset->id)); |
937 |
|
ASET (val, 1, parent_min_code); |
938 |
|
ASET (val, 2, parent_max_code); |
939 |
|
ASET (val, 3, parent_code_offset); |
940 |
|
ASET (attrs, charset_subset, val); |
941 |
|
|
942 |
|
charset.method = CHARSET_METHOD_SUBSET; |
943 |
|
/* Here, we just copy the parent's fast_map. It's not accurate, |
944 |
|
but at least it works for quickly detecting which character |
945 |
|
DOESN'T belong to this charset. */ |
946 |
|
for (i = 0; i < 190; i++) |
947 |
|
charset.fast_map[i] = parent_charset->fast_map[i]; |
948 |
|
|
949 |
|
/* We also copy these for parents. */ |
950 |
|
charset.min_char = parent_charset->min_char; |
951 |
|
charset.max_char = parent_charset->max_char; |
952 |
|
} |
953 |
|
else if (! NILP (args[charset_arg_superset])) |
954 |
|
{ |
955 |
|
val = args[charset_arg_superset]; |
956 |
|
charset.method = CHARSET_METHOD_SUPERSET; |
957 |
|
val = Fcopy_sequence (val); |
958 |
|
ASET (attrs, charset_superset, val); |
959 |
|
|
960 |
|
charset.min_char = MAX_CHAR; |
961 |
|
charset.max_char = 0; |
962 |
|
for (; ! NILP (val); val = Fcdr (val)) |
963 |
|
{ |
964 |
|
Lisp_Object elt, car_part, cdr_part; |
965 |
|
int this_id, offset; |
966 |
|
struct charset *this_charset; |
967 |
|
|
968 |
|
elt = Fcar (val); |
969 |
|
if (CONSP (elt)) |
970 |
|
{ |
971 |
|
car_part = XCAR (elt); |
972 |
|
cdr_part = XCDR (elt); |
973 |
|
CHECK_CHARSET_GET_ID (car_part, this_id); |
974 |
|
CHECK_NUMBER (cdr_part); |
975 |
|
offset = XINT (cdr_part); |
976 |
|
} |
977 |
|
else |
978 |
{ |
{ |
979 |
CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX) |
CHECK_CHARSET_GET_ID (elt, this_id); |
980 |
= make_number (i); |
offset = 0; |
|
CHARSET_TABLE_INFO (i, CHARSET_REVERSE_CHARSET_IDX) = charset_id; |
|
|
break; |
|
981 |
} |
} |
982 |
|
XSETCAR (val, Fcons (make_number (this_id), make_number (offset))); |
983 |
|
|
984 |
|
this_charset = CHARSET_FROM_ID (this_id); |
985 |
|
if (charset.min_char > this_charset->min_char) |
986 |
|
charset.min_char = this_charset->min_char; |
987 |
|
if (charset.max_char < this_charset->max_char) |
988 |
|
charset.max_char = this_charset->max_char; |
989 |
|
for (i = 0; i < 190; i++) |
990 |
|
charset.fast_map[i] |= this_charset->fast_map[i]; |
991 |
} |
} |
992 |
if (i > MAX_CHARSET) |
} |
993 |
/* No such a charset. */ |
else |
994 |
CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX) |
error ("None of :code-offset, :map, :parents are specified"); |
|
= make_number (-1); |
|
|
} |
|
995 |
|
|
996 |
if (charset != CHARSET_ASCII && charset != CHARSET_8_BIT_GRAPHIC |
val = args[charset_arg_unify_map]; |
997 |
&& charset < MIN_CHARSET_PRIVATE_DIMENSION1) |
if (! NILP (val) && !STRINGP (val)) |
998 |
|
CHECK_VECTOR (val); |
999 |
|
ASET (attrs, charset_unify_map, val); |
1000 |
|
|
1001 |
|
CHECK_LIST (args[charset_arg_plist]); |
1002 |
|
ASET (attrs, charset_plist, args[charset_arg_plist]); |
1003 |
|
|
1004 |
|
charset.hash_index = hash_lookup (hash_table, args[charset_arg_name], |
1005 |
|
&hash_code); |
1006 |
|
if (charset.hash_index >= 0) |
1007 |
|
{ |
1008 |
|
new_definition_p = 0; |
1009 |
|
id = XFASTINT (CHARSET_SYMBOL_ID (args[charset_arg_name])); |
1010 |
|
HASH_VALUE (hash_table, charset.hash_index) = attrs; |
1011 |
|
} |
1012 |
|
else |
1013 |
{ |
{ |
1014 |
bytes_by_char_head[leading_code_base] = bytes; |
charset.hash_index = hash_put (hash_table, args[charset_arg_name], attrs, |
1015 |
width_by_char_head[leading_code_base] = XINT (width); |
hash_code); |
1016 |
|
if (charset_table_used == charset_table_size) |
1017 |
|
{ |
1018 |
|
struct charset *new_table |
1019 |
|
= (struct charset *) xmalloc (sizeof (struct charset) |
1020 |
|
* (charset_table_size + 16)); |
1021 |
|
bcopy (charset_table, new_table, |
1022 |
|
sizeof (struct charset) * charset_table_size); |
1023 |
|
charset_table_size += 16; |
1024 |
|
charset_table = new_table; |
1025 |
|
} |
1026 |
|
id = charset_table_used++; |
1027 |
|
new_definition_p = 1; |
1028 |
|
} |
1029 |
|
|
1030 |
|
ASET (attrs, charset_id, make_number (id)); |
1031 |
|
charset.id = id; |
1032 |
|
charset_table[id] = charset; |
1033 |
|
|
1034 |
|
if (charset.iso_final >= 0) |
1035 |
|
{ |
1036 |
|
ISO_CHARSET_TABLE (charset.dimension, charset.iso_chars_96, |
1037 |
|
charset.iso_final) = id; |
1038 |
|
if (new_definition_p) |
1039 |
|
Viso_2022_charset_list = nconc2 (Viso_2022_charset_list, |
1040 |
|
Fcons (make_number (id), Qnil)); |
1041 |
|
if (ISO_CHARSET_TABLE (1, 0, 'J') == id) |
1042 |
|
charset_jisx0201_roman = id; |
1043 |
|
else if (ISO_CHARSET_TABLE (2, 0, '@') == id) |
1044 |
|
charset_jisx0208_1978 = id; |
1045 |
|
else if (ISO_CHARSET_TABLE (2, 0, 'B') == id) |
1046 |
|
charset_jisx0208 = id; |
1047 |
|
} |
1048 |
|
|
1049 |
|
if (charset.emacs_mule_id >= 0) |
1050 |
|
{ |
1051 |
|
emacs_mule_charset[charset.emacs_mule_id] = CHARSET_FROM_ID (id); |
1052 |
|
if (charset.emacs_mule_id < 0xA0) |
1053 |
|
emacs_mule_bytes[charset.emacs_mule_id] = charset.dimension + 1; |
1054 |
|
if (new_definition_p) |
1055 |
|
Vemacs_mule_charset_list = nconc2 (Vemacs_mule_charset_list, |
1056 |
|
Fcons (make_number (id), Qnil)); |
1057 |
|
} |
1058 |
|
|
1059 |
|
if (new_definition_p) |
1060 |
|
{ |
1061 |
|
Vcharset_list = Fcons (args[charset_arg_name], Vcharset_list); |
1062 |
|
Vcharset_ordered_list = nconc2 (Vcharset_ordered_list, |
1063 |
|
Fcons (make_number (id), Qnil)); |
1064 |
|
charset_ordered_list_tick++; |
1065 |
|
} |
1066 |
|
|
1067 |
/* Update table emacs_code_class. */ |
return Qnil; |
|
emacs_code_class[charset] = (bytes == 2 |
|
|
? EMACS_leading_code_2 |
|
|
: (bytes == 3 |
|
|
? EMACS_leading_code_3 |
|
|
: EMACS_leading_code_4)); |
|
|
} |
|
|
|
|
|
/* Update table iso_charset_table. */ |
|
|
if (XINT (iso_final_char) >= 0 |
|
|
&& ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0) |
|
|
ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset; |
|
1068 |
} |
} |
1069 |
|
|
|
#ifdef emacs |
|
1070 |
|
|
1071 |
/* Return charset id of CHARSET_SYMBOL, or return -1 if CHARSET_SYMBOL |
/* Same as Fdefine_charset_internal but arguments are more convenient |
1072 |
is invalid. */ |
to call from C (typically in syms_of_charset). This can define a |
1073 |
int |
charset of `offset' method only. Return the ID of the new |
1074 |
get_charset_id (charset_symbol) |
charset. */ |
1075 |
Lisp_Object charset_symbol; |
|
1076 |
|
static int |
1077 |
|
define_charset_internal (name, dimension, code_space, min_code, max_code, |
1078 |
|
iso_final, iso_revision, emacs_mule_id, |
1079 |
|
ascii_compatible, supplementary, |
1080 |
|
code_offset) |
1081 |
|
Lisp_Object name; |
1082 |
|
int dimension; |
1083 |
|
unsigned char *code_space; |
1084 |
|
unsigned min_code, max_code; |
1085 |
|
int iso_final, iso_revision, emacs_mule_id; |
1086 |
|
int ascii_compatible, supplementary; |
1087 |
|
int code_offset; |
1088 |
{ |
{ |
1089 |
|
Lisp_Object args[charset_arg_max]; |
1090 |
|
Lisp_Object plist[14]; |
1091 |
Lisp_Object val; |
Lisp_Object val; |
1092 |
int charset; |
int i; |
1093 |
|
|
1094 |
/* This originally used a ?: operator, but reportedly the HP-UX |
args[charset_arg_name] = name; |
1095 |
compiler version HP92453-01 A.10.32.22 miscompiles that. */ |
args[charset_arg_dimension] = make_number (dimension); |
1096 |
if (SYMBOLP (charset_symbol) |
val = Fmake_vector (make_number (8), make_number (0)); |
1097 |
&& VECTORP (val = Fget (charset_symbol, Qcharset)) |
for (i = 0; i < 8; i++) |
1098 |
&& CHARSET_VALID_P (charset = |
ASET (val, i, make_number (code_space[i])); |
1099 |
XINT (XVECTOR (val)->contents[CHARSET_ID_IDX]))) |
args[charset_arg_code_space] = val; |
1100 |
return charset; |
args[charset_arg_min_code] = make_number (min_code); |
1101 |
else |
args[charset_arg_max_code] = make_number (max_code); |
1102 |
return -1; |
args[charset_arg_iso_final] |
1103 |
|
= (iso_final < 0 ? Qnil : make_number (iso_final)); |
1104 |
|
args[charset_arg_iso_revision] = make_number (iso_revision); |
1105 |
|
args[charset_arg_emacs_mule_id] |
1106 |
|
= (emacs_mule_id < 0 ? Qnil : make_number (emacs_mule_id)); |
1107 |
|
args[charset_arg_ascii_compatible_p] = ascii_compatible ? Qt : Qnil; |
1108 |
|
args[charset_arg_supplementary_p] = supplementary ? Qt : Qnil; |
1109 |
|
args[charset_arg_invalid_code] = Qnil; |
1110 |
|
args[charset_arg_code_offset] = make_number (code_offset); |
1111 |
|
args[charset_arg_map] = Qnil; |
1112 |
|
args[charset_arg_subset] = Qnil; |
1113 |
|
args[charset_arg_superset] = Qnil; |
1114 |
|
args[charset_arg_unify_map] = Qnil; |
1115 |
|
|
1116 |
|
plist[0] = intern (":name"); |
1117 |
|
plist[1] = args[charset_arg_name]; |
1118 |
|
plist[2] = intern (":dimension"); |
1119 |
|
plist[3] = args[charset_arg_dimension]; |
1120 |
|
plist[4] = intern (":code-space"); |
1121 |
|
plist[5] = args[charset_arg_code_space]; |
1122 |
|
plist[6] = intern (":iso-final-char"); |
1123 |
|
plist[7] = args[charset_arg_iso_final]; |
1124 |
|
plist[8] = intern (":emacs-mule-id"); |
1125 |
|
plist[9] = args[charset_arg_emacs_mule_id]; |
1126 |
|
plist[10] = intern (":ascii-compatible-p"); |
1127 |
|
plist[11] = args[charset_arg_ascii_compatible_p]; |
1128 |
|
plist[12] = intern (":code-offset"); |
1129 |
|
plist[13] = args[charset_arg_code_offset]; |
1130 |
|
|
1131 |
|
args[charset_arg_plist] = Flist (14, plist); |
1132 |
|
Fdefine_charset_internal (charset_arg_max, args); |
1133 |
|
|
1134 |
|
return XINT (CHARSET_SYMBOL_ID (name)); |
1135 |
|
} |
1136 |
|
|
1137 |
|
|
1138 |
|
DEFUN ("define-charset-alias", Fdefine_charset_alias, |
1139 |
|
Sdefine_charset_alias, 2, 2, 0, |
1140 |
|
doc: /* Define ALIAS as an alias for charset CHARSET. */) |
1141 |
|
(alias, charset) |
1142 |
|
Lisp_Object alias, charset; |
1143 |
|
{ |
1144 |
|
Lisp_Object attr; |
1145 |
|
|
1146 |
|
CHECK_CHARSET_GET_ATTR (charset, attr); |
1147 |
|
Fputhash (alias, attr, Vcharset_hash_table); |
1148 |
|
Vcharset_list = Fcons (alias, Vcharset_list); |
1149 |
|
return Qnil; |
1150 |
} |
} |
1151 |
|
|
1152 |
/* Return an identification number for a new private charset of |
|
1153 |
DIMENSION and WIDTH. If there's no more room for the new charset, |
DEFUN ("unibyte-charset", Funibyte_charset, Sunibyte_charset, 0, 0, 0, |
1154 |
return 0. */ |
doc: /* Return the unibyte charset (set by `set-unibyte-charset'). */) |
1155 |
Lisp_Object |
() |
|
get_new_private_charset_id (dimension, width) |
|
|
int dimension, width; |
|
1156 |
{ |
{ |
1157 |
int charset, from, to; |
return CHARSET_NAME (CHARSET_FROM_ID (charset_unibyte)); |
1158 |
|
} |
1159 |
|
|
1160 |
if (dimension == 1) |
|
1161 |
{ |
DEFUN ("set-unibyte-charset", Fset_unibyte_charset, Sset_unibyte_charset, |
1162 |
from = LEADING_CODE_EXT_11; |
1, 1, 0, |
1163 |
to = LEADING_CODE_EXT_21; |
doc: /* Set the unibyte charset to CHARSET. |
1164 |
} |
This determines how unibyte/multibyte conversion is done. See also |
1165 |
else |
function `unibyte-charset'. */) |
1166 |
|
(charset) |
1167 |
|
Lisp_Object charset; |
1168 |
|
{ |
1169 |
|
struct charset *cs; |
1170 |
|
int i, c; |
1171 |
|
|
1172 |
|
CHECK_CHARSET_GET_CHARSET (charset, cs); |
1173 |
|
if (! cs->ascii_compatible_p |
1174 |
|
|| cs->dimension != 1) |
1175 |
|
error ("Inappropriate unibyte charset: %s", SDATA (SYMBOL_NAME (charset))); |
1176 |
|
charset_unibyte = cs->id; |
1177 |
|
for (i = 128; i < 256; i++) |
1178 |
{ |
{ |
1179 |
from = LEADING_CODE_EXT_21; |
c = DECODE_CHAR (cs, i); |
1180 |
to = LEADING_CODE_EXT_MAX + 1; |
unibyte_to_multibyte_table[i] = (c < 0 ? BYTE8_TO_CHAR (i) : c); |
1181 |
} |
} |
1182 |
|
|
1183 |
for (charset = from; charset < to; charset++) |
return Qnil; |
1184 |
if (!CHARSET_DEFINED_P (charset)) break; |
} |
1185 |
|
|
1186 |
|
|
1187 |
return make_number (charset < to ? charset : 0); |
DEFUN ("charset-plist", Fcharset_plist, Scharset_plist, 1, 1, 0, |
1188 |
|
doc: /* Return the property list of CHARSET. */) |
1189 |
|
(charset) |
1190 |
|
Lisp_Object charset; |
1191 |
|
{ |
1192 |
|
Lisp_Object attrs; |
1193 |
|
|
1194 |
|
CHECK_CHARSET_GET_ATTR (charset, attrs); |
1195 |
|
return CHARSET_ATTR_PLIST (attrs); |
1196 |
} |
} |
1197 |
|
|
1198 |
DEFUN ("define-charset", Fdefine_charset, Sdefine_charset, 3, 3, 0, |
|
1199 |
doc: /* Define CHARSET-ID as the identification number of CHARSET with INFO-VECTOR. |
DEFUN ("set-charset-plist", Fset_charset_plist, Sset_charset_plist, 2, 2, 0, |
1200 |
If CHARSET-ID is nil, it is decided automatically, which means CHARSET is |
doc: /* Set CHARSET's property list to PLIST. */) |
1201 |
treated as a private charset. |
(charset, plist) |
1202 |
INFO-VECTOR is a vector of the format: |
Lisp_Object charset, plist; |
1203 |
[DIMENSION CHARS WIDTH DIRECTION ISO-FINAL-CHAR ISO-GRAPHIC-PLANE |
{ |
1204 |
SHORT-NAME LONG-NAME DESCRIPTION] |
Lisp_Object attrs; |
1205 |
The meanings of each elements is as follows: |
|
1206 |
DIMENSION (integer) is the number of bytes to represent a character: 1 or 2. |
CHECK_CHARSET_GET_ATTR (charset, attrs); |
1207 |
CHARS (integer) is the number of characters in a dimension: 94 or 96. |
CHARSET_ATTR_PLIST (attrs) = plist; |
1208 |
WIDTH (integer) is the number of columns a character in the charset |
return plist; |
|
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", |
|
|
SDATA (SYMBOL_NAME (charset_symbol))); |
|
|
|
|
|
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", |
|
|
SDATA (SYMBOL_NAME (charset_symbol))); |
|
|
} |
|
|
|
|
|
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; |
|
1209 |
} |
} |
1210 |
|
|
1211 |
DEFUN ("generic-character-list", Fgeneric_character_list, |
|
1212 |
Sgeneric_character_list, 0, 0, 0, |
DEFUN ("unify-charset", Funify_charset, Sunify_charset, 1, 3, 0, |
1213 |
doc: /* Return a list of all possible generic characters. |
doc: /* Unify characters of CHARSET with Unicode. |
1214 |
It includes a generic character for a charset not yet defined. */) |
This means reading the relevant file and installing the table defined |
1215 |
() |
by CHARSET's `:unify-map' property. |
1216 |
|
|
1217 |
|
Optional second arg UNIFY-MAP is a file name string or a vector. It has |
1218 |
|
the same meaning as the `:unify-map' attribute in the function |
1219 |
|
`define-charset' (which see). |
1220 |
|
|
1221 |
|
Optional third argument DEUNIFY, if non-nil, means to de-unify CHARSET. */) |
1222 |
|
(charset, unify_map, deunify) |
1223 |
|
Lisp_Object charset, unify_map, deunify; |
1224 |
{ |
{ |
1225 |
return Vgeneric_character_list; |
int id; |
1226 |
|
struct charset *cs; |
1227 |
|
|
1228 |
|
CHECK_CHARSET_GET_ID (charset, id); |
1229 |
|
cs = CHARSET_FROM_ID (id); |
1230 |
|
if (CHARSET_METHOD (cs) == CHARSET_METHOD_MAP_DEFERRED) |
1231 |
|
load_charset (cs); |
1232 |
|
if (NILP (deunify) |
1233 |
|
? CHARSET_UNIFIED_P (cs) && ! NILP (CHARSET_DEUNIFIER (cs)) |
1234 |
|
: ! CHARSET_UNIFIED_P (cs)) |
1235 |
|
return Qnil; |
1236 |
|
|
1237 |
|
CHARSET_UNIFIED_P (cs) = 0; |
1238 |
|
if (NILP (deunify)) |
1239 |
|
{ |
1240 |
|
if (CHARSET_METHOD (cs) != CHARSET_METHOD_OFFSET) |
1241 |
|
error ("Can't unify charset: %s", SDATA (SYMBOL_NAME (charset))); |
1242 |
|
if (NILP (unify_map)) |
1243 |
|
unify_map = CHARSET_UNIFY_MAP (cs); |
1244 |
|
if (STRINGP (unify_map)) |
1245 |
|
load_charset_map_from_file (cs, unify_map, 2); |
1246 |
|
else if (VECTORP (unify_map)) |
1247 |
|
load_charset_map_from_vector (cs, unify_map, 2); |
1248 |
|
else if (NILP (unify_map)) |
1249 |
|
error ("No unify-map for charset"); |
1250 |
|
else |
1251 |
|
error ("Bad unify-map arg"); |
1252 |
|
CHARSET_UNIFIED_P (cs) = 1; |
1253 |
|
} |
1254 |
|
else if (CHAR_TABLE_P (Vchar_unify_table)) |
1255 |
|
{ |
1256 |
|
int min_code = CHARSET_MIN_CODE (cs); |
1257 |
|
int max_code = CHARSET_MAX_CODE (cs); |
1258 |
|
int min_char = DECODE_CHAR (cs, min_code); |
1259 |
|
int max_char = DECODE_CHAR (cs, max_code); |
1260 |
|
|
1261 |
|
char_table_set_range (Vchar_unify_table, min_char, max_char, Qnil); |
1262 |
|
} |
1263 |
|
|
1264 |
|
return Qnil; |
1265 |
} |
} |
1266 |
|
|
1267 |
DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char, |
DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char, |
1268 |
Sget_unused_iso_final_char, 2, 2, 0, |
Sget_unused_iso_final_char, 2, 2, 0, |
1269 |
doc: /* Return an unsed ISO's final char for a charset of DIMENISION and CHARS. |
doc: /* |
1270 |
|
Return an unsed ISO final char for a charset of DIMENISION and CHARS. |
1271 |
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. |
1272 |
CHARS is the number of characters in a dimension: 94 or 96. |
CHARS is the number of characters in a dimension: 94 or 96. |
1273 |
|
|
1281 |
|
|
1282 |
CHECK_NUMBER (dimension); |
CHECK_NUMBER (dimension); |
1283 |
CHECK_NUMBER (chars); |
CHECK_NUMBER (chars); |
1284 |
if (XINT (dimension) != 1 && XINT (dimension) != 2) |
if (XINT (dimension) != 1 && XINT (dimension) != 2 && XINT (dimension) != 3) |
1285 |
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)); |
|
1286 |
if (XINT (chars) != 94 && XINT (chars) != 96) |
if (XINT (chars) != 94 && XINT (chars) != 96) |
1287 |
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)); |
|
1288 |
for (final_char = '0'; final_char <= '?'; final_char++) |
for (final_char = '0'; final_char <= '?'; final_char++) |
1289 |
{ |
if (ISO_CHARSET_TABLE (XINT (dimension), XINT (chars), final_char) < 0) |
1290 |
if (ISO_CHARSET_TABLE (dimension, chars, make_number (final_char)) < 0) |
break; |
|
break; |
|
|
} |
|
1291 |
return (final_char <= '?' ? make_number (final_char) : Qnil); |
return (final_char <= '?' ? make_number (final_char) : Qnil); |
1292 |
} |
} |
1293 |
|
|
1294 |
DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset, |
static void |
1295 |
4, 4, 0, |
check_iso_charset_parameter (dimension, chars, final_char) |
1296 |
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; |
|
1297 |
{ |
{ |
1298 |
int charset; |
CHECK_NATNUM (dimension); |
1299 |
|
CHECK_NATNUM (chars); |
1300 |
|
CHECK_NATNUM (final_char); |
1301 |
|
|
1302 |
CHECK_NUMBER (dimension); |
if (XINT (dimension) > 3) |
1303 |
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)); |
|
1304 |
if (XINT (chars) != 94 && XINT (chars) != 96) |
if (XINT (chars) != 94 && XINT (chars) != 96) |
1305 |
error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars)); |
error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars)); |
1306 |
if (XINT (final_char) < '0' || XFASTINT (final_char) > '~') |
if (XINT (final_char) < '0' || XINT (final_char) > '~') |
1307 |
error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars)); |
error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars)); |
1308 |
if ((charset = get_charset_id (charset_symbol)) < 0) |
} |
1309 |
error ("Invalid charset %s", SDATA (SYMBOL_NAME (charset_symbol))); |
|
1310 |
|
|
1311 |
|
DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset, |
1312 |
|
4, 4, 0, |
1313 |
|
doc: /* |
1314 |
|
Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET. |
1315 |
|
CHARSET should be defined by `define-charset' in advance. */) |
1316 |
|
(dimension, chars, final_char, charset) |
1317 |
|
Lisp_Object dimension, chars, final_char, charset; |
1318 |
|
{ |
1319 |
|
int id; |
1320 |
|
|
1321 |
ISO_CHARSET_TABLE (dimension, chars, final_char) = charset; |
CHECK_CHARSET_GET_ID (charset, id); |
1322 |
|
check_iso_charset_parameter (dimension, chars, final_char); |
1323 |
|
|
1324 |
|
ISO_CHARSET_TABLE (XINT (dimension), XINT (chars), XINT (final_char)) = id; |
1325 |
return Qnil; |
return Qnil; |
1326 |
} |
} |
1327 |
|
|
1328 |
|
|
1329 |
/* Return information about charsets in the text at PTR of NBYTES |
/* Return information about charsets in the text at PTR of NBYTES |
1330 |
bytes, which are NCHARS characters. The value is: |
bytes, which are NCHARS characters. The value is: |
1331 |
|
|
1332 |
0: Each character is represented by one byte. This is always |
0: Each character is represented by one byte. This is always |
1333 |
true for unibyte text. |
true for a unibyte string. For a multibyte string, true if |
1334 |
1: No charsets other than ascii eight-bit-control, |
it contains only ASCII characters. |
|
eight-bit-graphic, and latin-1 are found. |
|
|
2: Otherwise. |
|
1335 |
|
|
1336 |
In addition, if CHARSETS is nonzero, for each found charset N, set |
1: No charsets other than ascii, control-1, and latin-1 are |
1337 |
CHARSETS[N] to 1. For that, callers should allocate CHARSETS |
found. |
1338 |
(MAX_CHARSET + 1 elements) in advance. It may lookup a translation |
|
1339 |
table TABLE if supplied. For invalid charsets, set CHARSETS[1] to |
2: Otherwise. |
1340 |
1 (note that there's no charset whose ID is 1). */ |
*/ |
1341 |
|
|
1342 |
int |
int |
1343 |
find_charset_in_text (ptr, nchars, nbytes, charsets, table) |
string_xstring_p (string) |
1344 |
const unsigned char *ptr; |
Lisp_Object string; |
|
int nchars, nbytes, *charsets; |
|
|
Lisp_Object table; |
|
1345 |
{ |
{ |
1346 |
if (nchars == nbytes) |
const unsigned char *p = SDATA (string); |
1347 |
{ |
const unsigned char *endp = p + SBYTES (string); |
1348 |
if (charsets && nbytes > 0) |
struct charset *charset; |
|
{ |
|
|
const unsigned char *endp = ptr + nbytes; |
|
|
int maskbits = 0; |
|
1349 |
|
|
1350 |
while (ptr < endp && maskbits != 7) |
if (SCHARS (string) == SBYTES (string)) |
1351 |
{ |
return 0; |
|
maskbits |= (*ptr < 0x80 ? 1 : *ptr < 0xA0 ? 2 : 4); |
|
|
ptr++; |
|
|
} |
|
1352 |
|
|
1353 |
if (maskbits & 1) |
charset = CHARSET_FROM_ID (charset_iso_8859_1); |
1354 |
charsets[CHARSET_ASCII] = 1; |
while (p < endp) |
|
if (maskbits & 2) |
|
|
charsets[CHARSET_8_BIT_CONTROL] = 1; |
|
|
if (maskbits & 4) |
|
|
charsets[CHARSET_8_BIT_GRAPHIC] = 1; |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
else |
|
1355 |
{ |
{ |
1356 |
int return_val = 1; |
int c = STRING_CHAR_ADVANCE (p); |
|
int bytes, charset, c1, c2; |
|
1357 |
|
|
1358 |
if (! CHAR_TABLE_P (table)) |
/* Fixme: comparison of unsigned expression < 0 is always false */ |
1359 |
table = Qnil; |
if (ENCODE_CHAR (charset, c) < 0) |
1360 |
|
return 2; |
1361 |
|
} |
1362 |
|
return 1; |
1363 |
|
} |
1364 |
|
|
|
while (nchars-- > 0) |
|
|
{ |
|
|
SPLIT_MULTIBYTE_SEQ (ptr, len, bytes, charset, c1, c2); |
|
|
ptr += bytes; |
|
1365 |
|
|
1366 |
if (!CHARSET_DEFINED_P (charset)) |
/* Find charsets in the string at PTR of NCHARS and NBYTES. |
1367 |
charset = 1; |
|
1368 |
else if (! NILP (table)) |
CHARSETS is a vector. Each element is a cons of CHARSET and |
1369 |
|
FOUND-FLAG. CHARSET is a charset id, and FOUND-FLAG is nil or t. |
1370 |
|
FOUND-FLAG t (or nil) means that the corresponding charset is |
1371 |
|
already found (or not yet found). |
1372 |
|
|
1373 |
|
It may lookup a translation table TABLE if supplied. */ |
1374 |
|
|
1375 |
|
static void |
1376 |
|
find_charsets_in_text (ptr, nchars, nbytes, charsets, table) |
1377 |
|
const unsigned char *ptr; |
1378 |
|
int nchars, nbytes; |
1379 |
|
Lisp_Object charsets, table; |
1380 |
|
{ |
1381 |
|
const unsigned char *pend = ptr + nbytes; |
1382 |
|
int ncharsets = ASIZE (charsets); |
1383 |
|
|
1384 |
|
if (nchars == nbytes) |
1385 |
|
return; |
1386 |
|
|
1387 |
|
while (ptr < pend) |
1388 |
|
{ |
1389 |
|
int c = STRING_CHAR_ADVANCE (ptr); |
1390 |
|
int i; |
1391 |
|
int all_found = 1; |
1392 |
|
Lisp_Object elt; |
1393 |
|
|
1394 |
|
if (!NILP (table)) |
1395 |
|
c = translate_char (table, c); |
1396 |
|
for (i = 0; i < ncharsets; i++) |
1397 |
|
{ |
1398 |
|
elt = AREF (charsets, i); |
1399 |
|
if (NILP (XCDR (elt))) |
1400 |
{ |
{ |
1401 |
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); |
|
|
} |
|
1402 |
|
|
1403 |
if (return_val == 1 |
if (ENCODE_CHAR (charset, c) != CHARSET_INVALID_CODE (charset)) |
1404 |
&& charset != CHARSET_ASCII |
XSETCDR (elt, Qt); |
1405 |
&& charset != CHARSET_8_BIT_CONTROL |
else |
1406 |
&& charset != CHARSET_8_BIT_GRAPHIC |
all_found = 0; |
1407 |
&& charset != charset_latin_iso8859_1) |
} |
|
return_val = 2; |
|
|
|
|
|
if (charsets) |
|
|
charsets[charset] = 1; |
|
|
else if (return_val == 2) |
|
|
break; |
|
1408 |
} |
} |
1409 |
return return_val; |
if (all_found) |
1410 |
|
break; |
1411 |
} |
} |
1412 |
} |
} |
1413 |
|
|
1414 |
|
/* Fixme: returns nil for unibyte. */ |
1415 |
DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region, |
DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region, |
1416 |
2, 3, 0, |
2, 3, 0, |
1417 |
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. |
1418 |
BEG and END are buffer positions. |
BEG and END are buffer positions. |
1419 |
Optional arg TABLE if non-nil is a translation table to look up. |
Optional arg TABLE if non-nil is a translation table to look up. |
1420 |
|
|
|
If the region contains invalid multibyte characters, |
|
|
`unknown' is included in the returned list. |
|
|
|
|
1421 |
If the current buffer is unibyte, the returned list may contain |
If the current buffer is unibyte, the returned list may contain |
1422 |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
1423 |
(beg, end, table) |
(beg, end, table) |
1424 |
Lisp_Object beg, end, table; |
Lisp_Object beg, end, table; |
1425 |
{ |
{ |
1426 |
int charsets[MAX_CHARSET + 1]; |
Lisp_Object charsets; |
1427 |
int from, from_byte, to, stop, stop_byte, i; |
int from, from_byte, to, stop, stop_byte, i; |
1428 |
Lisp_Object val; |
Lisp_Object val; |
1429 |
|
|
1441 |
|
|
1442 |
from_byte = CHAR_TO_BYTE (from); |
from_byte = CHAR_TO_BYTE (from); |
1443 |
|
|
1444 |
bzero (charsets, (MAX_CHARSET + 1) * sizeof (int)); |
charsets = Fmake_vector (make_number (charset_table_used), Qnil); |
1445 |
|
for (i = 0; i < charset_table_used; i++) |
1446 |
|
ASET (charsets, i, Fcons (make_number (i), Qnil)); |
1447 |
|
|
1448 |
while (1) |
while (1) |
1449 |
{ |
{ |
1450 |
find_charset_in_text (BYTE_POS_ADDR (from_byte), stop - from, |
find_charsets_in_text (BYTE_POS_ADDR (from_byte), stop - from, |
1451 |
stop_byte - from_byte, charsets, table); |
stop_byte - from_byte, charsets, table); |
1452 |
if (stop < to) |
if (stop < to) |
1453 |
{ |
{ |
1454 |
from = stop, from_byte = stop_byte; |
from = stop, from_byte = stop_byte; |
1459 |
} |
} |
1460 |
|
|
1461 |
val = Qnil; |
val = Qnil; |
1462 |
if (charsets[1]) |
for (i = charset_table_used - 1; i >= 0; i--) |
1463 |
val = Fcons (Qunknown, val); |
if (!NILP (XCDR (AREF (charsets, i)))) |
1464 |
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); |
|
1465 |
return val; |
return val; |
1466 |
} |
} |
1467 |
|
|
1468 |
|
/* Fixme: returns nil for unibyte. */ |
1469 |
DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string, |
DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string, |
1470 |
1, 2, 0, |
1, 2, 0, |
1471 |
doc: /* Return a list of charsets in STR. |
doc: /* Return a list of charsets in STR. |
1472 |
Optional arg TABLE if non-nil is a translation table to look up. |
Optional arg TABLE if non-nil is a translation table to look up. |
1473 |
|
|
|
If the string contains invalid multibyte characters, |
|
|
`unknown' is included in the returned list. |
|
|
|
|
1474 |
If STR is unibyte, the returned list may contain |
If STR is unibyte, the returned list may contain |
1475 |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
only `ascii', `eight-bit-control', and `eight-bit-graphic'. */) |
1476 |
(str, table) |
(str, table) |
1477 |
Lisp_Object str, table; |
Lisp_Object str, table; |
1478 |
{ |
{ |
1479 |
int charsets[MAX_CHARSET + 1]; |
Lisp_Object charsets; |
1480 |
int i; |
int i; |
1481 |
Lisp_Object val; |
Lisp_Object val; |
1482 |
|
|
1483 |
CHECK_STRING (str); |
CHECK_STRING (str); |
1484 |
|
|
1485 |
bzero (charsets, (MAX_CHARSET + 1) * sizeof (int)); |
charsets = Fmake_vector (make_number (charset_table_used), Qnil); |
1486 |
find_charset_in_text (SDATA (str), SCHARS (str), |
for (i = 0; i < charset_table_used; i++) |
1487 |
SBYTES (str), charsets, table); |
ASET (charsets, i, Fcons (make_number (i), Qnil)); |
1488 |
|
find_charsets_in_text (SDATA (str), SCHARS (str), SBYTES (str), |
1489 |
|
charsets, table); |
1490 |
|
|
1491 |
val = Qnil; |
val = Qnil; |
1492 |
if (charsets[1]) |
for (i = charset_table_used - 1; i >= 0; i--) |
1493 |
val = Fcons (Qunknown, val); |
if (!NILP (XCDR (AREF (charsets, i)))) |
1494 |
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); |
|
1495 |
return val; |
return val; |
1496 |
} |
} |
1497 |
|
|
1498 |
|
|
|
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)); |
|
1499 |
|
|
1500 |
if (NILP (code1)) |
/* Return a character correponding to the code-point CODE of |
1501 |
c1 = 0; |
CHARSET. */ |
1502 |
else |
|
1503 |
{ |
int |
1504 |
CHECK_NUMBER (code1); |
decode_char (charset, code) |
1505 |
c1 = XINT (code1); |
struct charset *charset; |
1506 |
} |
unsigned code; |
1507 |
if (NILP (code2)) |
{ |
1508 |
c2 = 0; |
int c, char_index; |
1509 |
else |
enum charset_method method = CHARSET_METHOD (charset); |
1510 |
|
|
1511 |
|
if (code < CHARSET_MIN_CODE (charset) || code > CHARSET_MAX_CODE (charset)) |
1512 |
|
return -1; |
1513 |
|
|
1514 |
|
if (method == CHARSET_METHOD_MAP_DEFERRED) |
1515 |
{ |
{ |
1516 |
CHECK_NUMBER (code2); |
load_charset (charset); |
1517 |
c2 = XINT (code2); |
method = CHARSET_METHOD (charset); |
1518 |
} |
} |
1519 |
|
|
1520 |
if (charset_id == CHARSET_ASCII) |
if (method == CHARSET_METHOD_SUBSET) |
1521 |
{ |
{ |
1522 |
if (c1 < 0 || c1 > 0x7F) |
Lisp_Object subset_info; |
|
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)); |
|
1523 |
|
|
1524 |
invalid_code_posints: |
subset_info = CHARSET_SUBSET (charset); |
1525 |
error ("Invalid code points for charset ID %d: %d %d", charset_id, c1, c2); |
charset = CHARSET_FROM_ID (XFASTINT (AREF (subset_info, 0))); |
1526 |
} |
code -= XINT (AREF (subset_info, 3)); |
1527 |
|
if (code < XFASTINT (AREF (subset_info, 1)) |
1528 |
|
|| code > XFASTINT (AREF (subset_info, 2))) |
1529 |
|
c = -1; |
1530 |
|
else |
1531 |
|
c = DECODE_CHAR (charset, code); |
1532 |
|
} |
1533 |
|
else if (method == CHARSET_METHOD_SUPERSET) |
1534 |
|
{ |
1535 |
|
Lisp_Object parents; |
1536 |
|
|
1537 |
DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0, |
parents = CHARSET_SUPERSET (charset); |
1538 |
doc: /* Return list of charset and one or two position-codes of CHAR. |
c = -1; |
1539 |
If CHAR is invalid as a character code, |
for (; CONSP (parents); parents = XCDR (parents)) |
1540 |
return a list of symbol `unknown' and CHAR. */) |
{ |
1541 |
(ch) |
int id = XINT (XCAR (XCAR (parents))); |
1542 |
Lisp_Object ch; |
int code_offset = XINT (XCDR (XCAR (parents))); |
1543 |
{ |
unsigned this_code = code - code_offset; |
|
int c, charset, c1, c2; |
|
1544 |
|
|
1545 |
CHECK_NUMBER (ch); |
charset = CHARSET_FROM_ID (id); |
1546 |
c = XFASTINT (ch); |
if ((c = DECODE_CHAR (charset, this_code)) >= 0) |
1547 |
if (!CHAR_VALID_P (c, 1)) |
break; |
1548 |
return Fcons (Qunknown, Fcons (ch, Qnil)); |
} |
1549 |
SPLIT_CHAR (XFASTINT (ch), charset, c1, c2); |
} |
1550 |
return (c2 >= 0 |
else |
1551 |
? Fcons (CHARSET_SYMBOL (charset), |
{ |
1552 |
Fcons (make_number (c1), Fcons (make_number (c2), Qnil))) |
char_index = CODE_POINT_TO_INDEX (charset, code); |
1553 |
: Fcons (CHARSET_SYMBOL (charset), Fcons (make_number (c1), Qnil))); |
if (char_index < 0) |
1554 |
} |
return -1; |
1555 |
|
|
1556 |
DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0, |
if (method == CHARSET_METHOD_MAP) |
1557 |
doc: /* Return charset of CHAR. */) |
{ |
1558 |
(ch) |
Lisp_Object decoder; |
|
Lisp_Object ch; |
|
|
{ |
|
|
CHECK_NUMBER (ch); |
|
1559 |
|
|
1560 |
return CHARSET_SYMBOL (CHAR_CHARSET (XINT (ch))); |
decoder = CHARSET_DECODER (charset); |
1561 |
} |
if (! VECTORP (decoder)) |
1562 |
|
return -1; |
1563 |
|
c = XINT (AREF (decoder, char_index)); |
1564 |
|
} |
1565 |
|
else |
1566 |
|
{ |
1567 |
|
c = char_index + CHARSET_CODE_OFFSET (charset); |
1568 |
|
} |
1569 |
|
} |
1570 |
|
|
1571 |
DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0, |
if (CHARSET_UNIFIED_P (charset) |
1572 |
doc: /* Return charset of a character in the current buffer at position POS. |
&& c >= 0) |
1573 |
If POS is nil, it defauls to the current point. |
{ |
1574 |
If POS is out of range, the value is nil. */) |
MAYBE_UNIFY_CHAR (c); |
1575 |
(pos) |
} |
|
Lisp_Object pos; |
|
|
{ |
|
|
Lisp_Object ch; |
|
|
int charset; |
|
1576 |
|
|
1577 |
ch = Fchar_after (pos); |
return c; |
|
if (! INTEGERP (ch)) |
|
|
return ch; |
|
|
charset = CHAR_CHARSET (XINT (ch)); |
|
|
return CHARSET_SYMBOL (charset); |
|
1578 |
} |
} |
1579 |
|
|
1580 |
DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0, |
/* Variable used temporarily by the macro ENCODE_CHAR. */ |
1581 |
doc: /* Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR. |
Lisp_Object charset_work; |
|
|
|
|
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); |
|
|
|
|
|
if ((charset = ISO_CHARSET_TABLE (dimension, chars, final_char)) < 0) |
|
|
return Qnil; |
|
|
return CHARSET_SYMBOL (charset); |
|
|
} |
|
1582 |
|
|
1583 |
/* If GENERICP is nonzero, return nonzero iff C is a valid normal or |
/* Return a code-point of CHAR in CHARSET. If CHAR doesn't belong to |
1584 |
generic character. If GENERICP is zero, return nonzero iff C is a |
CHARSET, return CHARSET_INVALID_CODE (CHARSET). If STRICT is true, |
1585 |
valid normal character. Do not call this function directly, |
use CHARSET's strict_max_char instead of max_char. */ |
1586 |
instead use macro CHAR_VALID_P. */ |
|
1587 |
int |
unsigned |
1588 |
char_valid_p (c, genericp) |
encode_char (charset, c) |
1589 |
int c, genericp; |
struct charset *charset; |
1590 |
|
int c; |
1591 |
{ |
{ |
1592 |
int charset, c1, c2; |
unsigned code; |
1593 |
|
enum charset_method method = CHARSET_METHOD (charset); |
1594 |
|
|
1595 |
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) |
|
1596 |
{ |
{ |
1597 |
if (c1) |
Lisp_Object deunifier, deunified; |
1598 |
{ |
|
1599 |
if (c2 <= 0) c2 = 0x20; |
deunifier = CHARSET_DEUNIFIER (charset); |
1600 |
} |
if (! CHAR_TABLE_P (deunifier)) |
|
else |
|
1601 |
{ |
{ |
1602 |
if (c2 <= 0) c1 = c2 = 0x20; |
Funify_charset (CHARSET_NAME (charset), Qnil, Qnil); |
1603 |
|
deunifier = CHARSET_DEUNIFIER (charset); |
1604 |
} |
} |
1605 |
|
deunified = CHAR_TABLE_REF (deunifier, c); |
1606 |
|
if (! NILP (deunified)) |
1607 |
|
c = XINT (deunified); |
1608 |
} |
} |
|
return (CHARSET_DEFINED_P (charset) |
|
|
&& CHAR_COMPONENTS_VALID_P (charset, c1, c2)); |
|
|
} |
|
1609 |
|
|
1610 |
DEFUN ("char-valid-p", Fchar_valid_p, Schar_valid_p, 1, 2, 0, |
if (method == CHARSET_METHOD_SUBSET) |
1611 |
doc: /* Return t if OBJECT is a valid normal character. |
{ |
1612 |
If optional arg GENERICP is non-nil, also return t if OBJECT is |
Lisp_Object subset_info; |
1613 |
a valid generic character. */) |
struct charset *this_charset; |
|
(object, genericp) |
|
|
Lisp_Object object, genericp; |
|
|
{ |
|
|
if (! NATNUMP (object)) |
|
|
return Qnil; |
|
|
return (CHAR_VALID_P (XFASTINT (object), !NILP (genericp)) ? Qt : Qnil); |
|
|
} |
|
1614 |
|
|
1615 |
DEFUN ("unibyte-char-to-multibyte", Funibyte_char_to_multibyte, |
subset_info = CHARSET_SUBSET (charset); |
1616 |
Sunibyte_char_to_multibyte, 1, 1, 0, |
this_charset = CHARSET_FROM_ID (XFASTINT (AREF (subset_info, 0))); |
1617 |
doc: /* Convert the unibyte character CH to multibyte character. |
code = ENCODE_CHAR (this_charset, c); |
1618 |
The conversion is done based on `nonascii-translation-table' (which see) |
if (code == CHARSET_INVALID_CODE (this_charset) |
1619 |
or `nonascii-insert-offset' (which see). */) |
|| code < XFASTINT (AREF (subset_info, 1)) |
1620 |
(ch) |
|| code > XFASTINT (AREF (subset_info, 2))) |
1621 |
Lisp_Object ch; |
return CHARSET_INVALID_CODE (charset); |
1622 |
{ |
code += XINT (AREF (subset_info, 3)); |
1623 |
int c; |
return code; |
1624 |
|
} |
1625 |
|
|
1626 |
CHECK_NUMBER (ch); |
if (method == CHARSET_METHOD_SUPERSET) |
1627 |
c = XINT (ch); |
{ |
1628 |
if (c < 0 || c >= 0400) |
Lisp_Object parents; |
|
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); |
|
|
} |
|
1629 |
|
|
1630 |
DEFUN ("multibyte-char-to-unibyte", Fmultibyte_char_to_unibyte, |
parents = CHARSET_SUPERSET (charset); |
1631 |
Smultibyte_char_to_unibyte, 1, 1, 0, |
for (; CONSP (parents); parents = XCDR (parents)) |
1632 |
doc: /* Convert the multibyte character CH to unibyte character. |
{ |
1633 |
The conversion is done based on `nonascii-translation-table' (which see) |
int id = XINT (XCAR (XCAR (parents))); |
1634 |
or `nonascii-insert-offset' (which see). */) |
int code_offset = XINT (XCDR (XCAR (parents))); |
1635 |
(ch) |
struct charset *this_charset = CHARSET_FROM_ID (id); |
|
Lisp_Object ch; |
|
|
{ |
|
|
int c; |
|
1636 |
|
|
1637 |
CHECK_NUMBER (ch); |
code = ENCODE_CHAR (this_charset, c); |
1638 |
c = XINT (ch); |
if (code != CHARSET_INVALID_CODE (this_charset)) |
1639 |
if (! CHAR_VALID_P (c, 0)) |
return code + code_offset; |
1640 |
error ("Invalid multibyte character: %d", c); |
} |
1641 |
c = multibyte_char_to_unibyte (c, Qnil); |
return CHARSET_INVALID_CODE (charset); |
1642 |
if (c < 0) |
} |
|
error ("Can't convert to unibyte character: %d", XINT (ch)); |
|
|
return make_number (c); |
|
|
} |
|
1643 |
|
|
1644 |
DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0, |
if (! CHARSET_FAST_MAP_REF ((c), charset->fast_map) |
1645 |
doc: /* Return 1 regardless of the argument CHAR. */) |
|| c < CHARSET_MIN_CHAR (charset) || c > CHARSET_MAX_CHAR (charset)) |
1646 |
(ch) |
return CHARSET_INVALID_CODE (charset); |
|
Lisp_Object ch; |
|
|
{ |
|
|
CHECK_NUMBER (ch); |
|
|
return make_number (1); |
|
|
} |
|
1647 |
|
|
1648 |
/* Return how many bytes C will occupy in a multibyte buffer. |
if (method == CHARSET_METHOD_MAP_DEFERRED) |
1649 |
Don't call this function directly, instead use macro CHAR_BYTES. */ |
{ |
1650 |
int |
load_charset (charset); |
1651 |
char_bytes (c) |
method = CHARSET_METHOD (charset); |
1652 |
int c; |
} |
|
{ |
|
|
int charset; |
|
1653 |
|
|
1654 |
if (ASCII_BYTE_P (c) || (c & ~((1 << CHARACTERBITS) -1))) |
if (method == CHARSET_METHOD_MAP) |
1655 |
return 1; |
{ |
1656 |
if (SINGLE_BYTE_CHAR_P (c) && c >= 0xA0) |
Lisp_Object encoder; |
1657 |
return 1; |
Lisp_Object val; |
1658 |
|
|
1659 |
charset = CHAR_CHARSET (c); |
encoder = CHARSET_ENCODER (charset); |
1660 |
return (CHARSET_DEFINED_P (charset) ? CHARSET_BYTES (charset) : 1); |
if (! CHAR_TABLE_P (CHARSET_ENCODER (charset))) |
1661 |
|
return CHARSET_INVALID_CODE (charset); |
1662 |
|
val = CHAR_TABLE_REF (encoder, c); |
1663 |
|
if (NILP (val)) |
1664 |
|
return CHARSET_INVALID_CODE (charset); |
1665 |
|
code = XINT (val); |
1666 |
|
if (! CHARSET_COMPACT_CODES_P (charset)) |
1667 |
|
code = INDEX_TO_CODE_POINT (charset, code); |
1668 |
|
} |
1669 |
|
else /* method == CHARSET_METHOD_OFFSET */ |
1670 |
|
{ |
1671 |
|
code = c - CHARSET_CODE_OFFSET (charset); |
1672 |
|
code = INDEX_TO_CODE_POINT (charset, code); |
1673 |
|
} |
1674 |
|
|
1675 |
|
return code; |
1676 |
} |
} |
1677 |
|
|
|
/* 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 (); |
|
1678 |
|
|
1679 |
CHECK_NUMBER (ch); |
DEFUN ("decode-char", Fdecode_char, Sdecode_char, 2, 3, 0, |
1680 |
|
doc: /* Decode the pair of CHARSET and CODE-POINT into a character. |
1681 |
|
Return nil if CODE-POINT is not valid in CHARSET. |
1682 |
|
|
1683 |
c = XINT (ch); |
CODE-POINT may be a cons (HIGHER-16-BIT-VALUE . LOWER-16-BIT-VALUE). |
1684 |
|
|
1685 |
/* Get the way the display table would display it. */ |
Optional argument RESTRICTION specifies a way to map the pair of CCS |
1686 |
disp = dp ? DISP_CHAR_VECTOR (dp, c) : Qnil; |
and CODE-POINT to a chracter. Currently not supported and just ignored. */) |
1687 |
|
(charset, code_point, restriction) |
1688 |
|
Lisp_Object charset, code_point, restriction; |
1689 |
|
{ |
1690 |
|
int c, id; |
1691 |
|
unsigned code; |
1692 |
|
struct charset *charsetp; |
1693 |
|
|
1694 |
if (VECTORP (disp)) |
CHECK_CHARSET_GET_ID (charset, id); |
1695 |
XSETINT (val, XVECTOR (disp)->size); |
if (CONSP (code_point)) |
1696 |
else if (SINGLE_BYTE_CHAR_P (c)) |
{ |
1697 |
XSETINT (val, ONE_BYTE_CHAR_WIDTH (c)); |
CHECK_NATNUM_CAR (code_point); |
1698 |
|
CHECK_NATNUM_CDR (code_point); |
1699 |
|
code = (XINT (XCAR (code_point)) << 16) | (XINT (XCDR (code_point))); |
1700 |
|
} |
1701 |
else |
else |
1702 |
{ |
{ |
1703 |
int charset = CHAR_CHARSET (c); |
CHECK_NATNUM (code_point); |
1704 |
|
code = XINT (code_point); |
|
XSETFASTINT (val, CHARSET_WIDTH (charset)); |
|
1705 |
} |
} |
1706 |
return val; |
charsetp = CHARSET_FROM_ID (id); |
1707 |
|
c = DECODE_CHAR (charsetp, code); |
1708 |
|
return (c >= 0 ? make_number (c) : Qnil); |
1709 |
} |
} |
1710 |
|
|
|
/* 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. */ |
|
1711 |
|
|
1712 |
int |
DEFUN ("encode-char", Fencode_char, Sencode_char, 2, 3, 0, |
1713 |
strwidth (str, len) |
doc: /* Encode the character CH into a code-point of CHARSET. |
1714 |
unsigned char *str; |
Return nil if CHARSET doesn't include CH. |
1715 |
int len; |
|
1716 |
{ |
Optional argument RESTRICTION specifies a way to map CHAR to a |
1717 |
return c_string_width (str, len, -1, NULL, NULL); |
code-point in CCS. Currently not supported and just ignored. */) |
1718 |
|
(ch, charset, restriction) |
1719 |
|
Lisp_Object ch, charset, restriction; |
1720 |
|
{ |
1721 |
|
int id; |
1722 |
|
unsigned code; |
1723 |
|
struct charset *charsetp; |
1724 |
|
|
1725 |
|
CHECK_CHARSET_GET_ID (charset, id); |
1726 |
|
CHECK_NATNUM (ch); |
1727 |
|
charsetp = CHARSET_FROM_ID (id); |
1728 |
|
code = ENCODE_CHAR (charsetp, XINT (ch)); |
1729 |
|
if (code == CHARSET_INVALID_CODE (charsetp)) |
1730 |
|
return Qnil; |
1731 |
|
if (code > 0x7FFFFFF) |
1732 |
|
return Fcons (make_number (code >> 16), make_number (code & 0xFFFF)); |
1733 |
|
return make_number (code); |
1734 |
} |
} |
1735 |
|
|
|
/* 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. */ |
|
1736 |
|
|
1737 |
int |
DEFUN ("make-char", Fmake_char, Smake_char, 1, 5, 0, |
1738 |
c_string_width (str, len, precision, nchars, nbytes) |
doc: |
1739 |
const unsigned char *str; |
/* Return a character of CHARSET whose position codes are CODEn. |
|
int len, precision, *nchars, *nbytes; |
|
|
{ |
|
|
int i = 0, i_byte = 0; |
|
|
int width = 0; |
|
|
int chars; |
|
|
struct Lisp_Char_Table *dp = buffer_display_table (); |
|
1740 |
|
|
1741 |
while (i_byte < len) |
CODE1 through CODE4 are optional, but if you don't supply sufficient |
1742 |
{ |
position codes, it is assumed that the minimum code in each dimension |
1743 |
int bytes, thiswidth; |
is specified. */) |
1744 |
Lisp_Object val; |
(charset, code1, code2, code3, code4) |
1745 |
|
Lisp_Object charset, code1, code2, code3, code4; |
1746 |
|
{ |
1747 |
|
int id, dimension; |
1748 |
|
struct charset *charsetp; |
1749 |
|
unsigned code; |
1750 |
|
int c; |
1751 |
|
|
1752 |
if (dp) |
CHECK_CHARSET_GET_ID (charset, id); |
1753 |
{ |
charsetp = CHARSET_FROM_ID (id); |
|
int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes); |
|
1754 |
|
|
1755 |
chars = 1; |
dimension = CHARSET_DIMENSION (charsetp); |
1756 |
val = DISP_CHAR_VECTOR (dp, c); |
if (NILP (code1)) |
1757 |
if (VECTORP (val)) |
code = (CHARSET_ASCII_COMPATIBLE_P (charsetp) |
1758 |
thiswidth = XVECTOR (val)->size; |
? 0 : CHARSET_MIN_CODE (charsetp)); |
1759 |
|
else |
1760 |
|
{ |
1761 |
|
CHECK_NATNUM (code1); |
1762 |
|
if (XFASTINT (code1) >= 0x100) |
1763 |
|
args_out_of_range (make_number (0xFF), code1); |
1764 |
|
code = XFASTINT (code1); |
1765 |
|
|
1766 |
|
if (dimension > 1) |
1767 |
|
{ |
1768 |
|
code <<= 8; |
1769 |
|
if (NILP (code2)) |
1770 |
|
code |= charsetp->code_space[(dimension - 2) * 4]; |
1771 |
else |
else |
1772 |
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
{ |
1773 |
} |
CHECK_NATNUM (code2); |
1774 |
else |
if (XFASTINT (code2) >= 0x100) |
1775 |
{ |
args_out_of_range (make_number (0xFF), code2); |
1776 |
chars = 1; |
code |= XFASTINT (code2); |
1777 |
PARSE_MULTIBYTE_SEQ (str + i_byte, len - i_byte, bytes); |
} |
|
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
|
|
} |
|
1778 |
|
|
1779 |
if (precision > 0 |
if (dimension > 2) |
1780 |
&& (width + thiswidth > precision)) |
{ |
1781 |
{ |
code <<= 8; |
1782 |
*nchars = i; |
if (NILP (code3)) |
1783 |
*nbytes = i_byte; |
code |= charsetp->code_space[(dimension - 3) * 4]; |
1784 |
return width; |
else |
1785 |
|
{ |
1786 |
|
CHECK_NATNUM (code3); |
1787 |
|
if (XFASTINT (code3) >= 0x100) |
1788 |
|
args_out_of_range (make_number (0xFF), code3); |
1789 |
|
code |= XFASTINT (code3); |
1790 |
|
} |
1791 |
|
|
1792 |
|
if (dimension > 3) |
1793 |
|
{ |
1794 |
|
code <<= 8; |
1795 |
|
if (NILP (code4)) |
1796 |
|
code |= charsetp->code_space[0]; |
1797 |
|
else |
1798 |
|
{ |
1799 |
|
CHECK_NATNUM (code4); |
1800 |
|
if (XFASTINT (code4) >= 0x100) |
1801 |
|
args_out_of_range (make_number (0xFF), code4); |
1802 |
|
code |= XFASTINT (code4); |
1803 |
|
} |
1804 |
|
} |
1805 |
|
} |
1806 |
} |
} |
|
i++; |
|
|
i_byte += bytes; |
|
|
width += thiswidth; |
|
|
} |
|
|
|
|
|
if (precision > 0) |
|
|
{ |
|
|
*nchars = i; |
|
|
*nbytes = i_byte; |
|
1807 |
} |
} |
1808 |
|
|
1809 |
return width; |
if (CHARSET_ISO_FINAL (charsetp) >= 0) |
1810 |
|
code &= 0x7F7F7F7F; |
1811 |
|
c = DECODE_CHAR (charsetp, code); |
1812 |
|
if (c < 0) |
1813 |
|
error ("Invalid code(s)"); |
1814 |
|
return make_number (c); |
1815 |
} |
} |
1816 |
|
|
|
/* 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. */ |
|
1817 |
|
|
1818 |
int |
/* Return the first charset in CHARSET_LIST that contains C. |
1819 |
lisp_string_width (string, precision, nchars, nbytes) |
CHARSET_LIST is a list of charset IDs. If it is nil, use |
1820 |
Lisp_Object string; |
Vcharset_ordered_list. */ |
1821 |
int precision, *nchars, *nbytes; |
|
1822 |
|
struct charset * |
1823 |
|
char_charset (c, charset_list, code_return) |
1824 |
|
int c; |
1825 |
|
Lisp_Object charset_list; |
1826 |
|
unsigned *code_return; |
1827 |
{ |
{ |
1828 |
int len = SCHARS (string); |
if (NILP (charset_list)) |
1829 |
int len_byte = SBYTES (string); |
charset_list = Vcharset_ordered_list; |
|
const unsigned char *str = SDATA (string); |
|
|
int i = 0, i_byte = 0; |
|
|
int width = 0; |
|
|
struct Lisp_Char_Table *dp = buffer_display_table (); |
|
1830 |
|
|
1831 |
while (i < len) |
while (CONSP (charset_list)) |
1832 |
{ |
{ |
1833 |
int chars, bytes, thiswidth; |
struct charset *charset = CHARSET_FROM_ID (XINT (XCAR (charset_list))); |
1834 |
Lisp_Object val; |
unsigned code = ENCODE_CHAR (charset, c); |
|
int cmp_id; |
|
|
int ignore, end; |
|
|
|
|
|
if (find_composition (i, -1, &ignore, &end, &val, string) |
|
|
&& ((cmp_id = get_composition_id (i, i_byte, end - i, val, string)) |
|
|
>= 0)) |
|
|
{ |
|
|
thiswidth = composition_table[cmp_id]->width; |
|
|
chars = end - i; |
|
|
bytes = string_char_to_byte (string, end) - i_byte; |
|
|
} |
|
|
else if (dp) |
|
|
{ |
|
|
int c = STRING_CHAR_AND_LENGTH (str + i_byte, len - i_byte, bytes); |
|
1835 |
|
|
1836 |
chars = 1; |
if (code != CHARSET_INVALID_CODE (charset)) |
|
val = DISP_CHAR_VECTOR (dp, c); |
|
|
if (VECTORP (val)) |
|
|
thiswidth = XVECTOR (val)->size; |
|
|
else |
|
|
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
|
|
} |
|
|
else |
|
1837 |
{ |
{ |
1838 |
chars = 1; |
if (code_return) |
1839 |
PARSE_MULTIBYTE_SEQ (str + i_byte, len_byte - i_byte, bytes); |
*code_return = code; |
1840 |
thiswidth = ONE_BYTE_CHAR_WIDTH (str[i_byte]); |
return charset; |
1841 |
} |
} |
1842 |
|
charset_list = XCDR (charset_list); |
|
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; |
|
1843 |
} |
} |
1844 |
|
return NULL; |
|
return width; |
|
1845 |
} |
} |
1846 |
|
|
|
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; |
|
|
} |
|
1847 |
|
|
1848 |
DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0, |
/* Fixme: `unknown' can't happen now? */ |
1849 |
doc: /* Return the direction of CHAR. |
DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0, |
1850 |
The returned value is 0 for left-to-right and 1 for right-to-left. */) |
doc: /*Return list of charset and one to three position-codes of CHAR. |
1851 |
|
If CHAR is invalid as a character code, return a list `(unknown CHAR)'. */) |
1852 |
(ch) |
(ch) |
1853 |
Lisp_Object ch; |
Lisp_Object ch; |
1854 |
{ |
{ |
1855 |
int charset; |
struct charset *charset; |
1856 |
|
int c, dimension; |
1857 |
CHECK_NUMBER (ch); |
unsigned code; |
1858 |
charset = CHAR_CHARSET (XFASTINT (ch)); |
Lisp_Object val; |
|
if (!CHARSET_DEFINED_P (charset)) |
|
|
invalid_character (XINT (ch)); |
|
|
return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX); |
|
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
CHECK_NUMBER_COERCE_MARKER (beg); |
|
|
CHECK_NUMBER_COERCE_MARKER (end); |
|
1859 |
|
|
1860 |
from = min (XFASTINT (beg), XFASTINT (end)); |
CHECK_CHARACTER (ch); |
1861 |
to = max (XFASTINT (beg), XFASTINT (end)); |
c = XFASTINT (ch); |
1862 |
|
charset = CHAR_CHARSET (c); |
1863 |
|
if (! charset) |
1864 |
|
return Fcons (intern ("unknown"), Fcons (ch, Qnil)); |
1865 |
|
|
1866 |
return make_number (to - from); |
code = ENCODE_CHAR (charset, c); |
1867 |
|
if (code == CHARSET_INVALID_CODE (charset)) |
1868 |
|
abort (); |
1869 |
|
dimension = CHARSET_DIMENSION (charset); |
1870 |
|
val = (dimension == 1 ? Fcons (make_number (code), Qnil) |
1871 |
|
: dimension == 2 ? Fcons (make_number (code >> 8), |
1872 |
|
Fcons (make_number (code & 0xFF), Qnil)) |
1873 |
|
: Fcons (make_number (code >> 16), |
1874 |
|
Fcons (make_number ((code >> 8) & 0xFF), |
1875 |
|
Fcons (make_number (code & 0xFF), Qnil)))); |
1876 |
|
return Fcons (CHARSET_NAME (charset), val); |
1877 |
} |
} |
1878 |
|
|
|
/* 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. */ |
|
1879 |
|
|
1880 |
int |
DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0, |
1881 |
chars_in_text (ptr, nbytes) |
doc: /* Return the charset of highest priority that contains CHAR. */) |
1882 |
const unsigned char *ptr; |
(ch) |
1883 |
int nbytes; |
Lisp_Object ch; |
1884 |
{ |
{ |
1885 |
/* current_buffer is null at early stages of Emacs initialization. */ |
struct charset *charset; |
|
if (current_buffer == 0 |
|
|
|| NILP (current_buffer->enable_multibyte_characters)) |
|
|
return nbytes; |
|
1886 |
|
|
1887 |
return multibyte_chars_in_text (ptr, nbytes); |
CHECK_CHARACTER (ch); |
1888 |
|
charset = CHAR_CHARSET (XINT (ch)); |
1889 |
|
return (CHARSET_NAME (charset)); |
1890 |
} |
} |
1891 |
|
|
|
/* 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. */ |
|
1892 |
|
|
1893 |
int |
DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0, |
1894 |
multibyte_chars_in_text (ptr, nbytes) |
doc: /* |
1895 |
const unsigned char *ptr; |
Return charset of a character in the current buffer at position POS. |
1896 |
int nbytes; |
If POS is nil, it defauls to the current point. |
1897 |
|
If POS is out of range, the value is nil. */) |
1898 |
|
(pos) |
1899 |
|
Lisp_Object pos; |
1900 |
{ |
{ |
1901 |
const unsigned char *endp; |
Lisp_Object ch; |
1902 |
int chars, bytes; |
struct charset *charset; |
1903 |
|
|
1904 |
endp = ptr + nbytes; |
ch = Fchar_after (pos); |
1905 |
chars = 0; |
if (! INTEGERP (ch)) |
1906 |
|
return ch; |
1907 |
|
charset = CHAR_CHARSET (XINT (ch)); |
1908 |
|
return (CHARSET_NAME (charset)); |
1909 |
|
} |
1910 |
|
|
|
while (ptr < endp) |
|
|
{ |
|
|
PARSE_MULTIBYTE_SEQ (ptr, endp - ptr, bytes); |
|
|
ptr += bytes; |
|
|
chars++; |
|
|
} |
|
1911 |
|
|
1912 |
return chars; |
DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0, |
1913 |
} |
doc: /* |
1914 |
|
Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR. |
1915 |
|
|
1916 |
/* Parse unibyte text at STR of LEN bytes as multibyte text, and |
ISO 2022's designation sequence (escape sequence) distinguishes charsets |
1917 |
count the numbers of characters and bytes in it. On counting |
by their DIMENSION, CHARS, and FINAL-CHAR, |
1918 |
bytes, pay attention to the fact that 8-bit characters in the range |
where as Emacs distinguishes them by charset symbol. |
1919 |
0x80..0x9F are represented by 2 bytes in multibyte text. */ |
See the documentation of the function `charset-info' for the meanings of |
1920 |
void |
DIMENSION, CHARS, and FINAL-CHAR. */) |
1921 |
parse_str_as_multibyte (str, len, nchars, nbytes) |
(dimension, chars, final_char) |
1922 |
const unsigned char *str; |
Lisp_Object dimension, chars, final_char; |
|
int len, *nchars, *nbytes; |
|
1923 |
{ |
{ |
1924 |
const unsigned char *endp = str + len; |
int id; |
|
int n, chars = 0, bytes = 0; |
|
1925 |
|
|
1926 |
while (str < endp) |
check_iso_charset_parameter (dimension, chars, final_char); |
1927 |
{ |
id = ISO_CHARSET_TABLE (XFASTINT (dimension), XFASTINT (chars), |
1928 |
if (UNIBYTE_STR_AS_MULTIBYTE_P (str, endp - str, n)) |
XFASTINT (final_char)); |
1929 |
str += n, bytes += n; |
return (id >= 0 ? CHARSET_NAME (CHARSET_FROM_ID (id)) : Qnil); |
|
else |
|
|
str++, bytes += 2; |
|
|
chars++; |
|
|
} |
|
|
*nchars = chars; |
|
|
*nbytes = bytes; |
|
|
return; |
|
1930 |
} |
} |
1931 |
|
|
|
/* Arrange unibyte text at STR of NBYTES bytes as multibyte text. |
|
|
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. */ |
|
1932 |
|
|
1933 |
int |
DEFUN ("clear-charset-maps", Fclear_charset_maps, Sclear_charset_maps, |
1934 |
str_as_multibyte (str, len, nbytes, nchars) |
0, 0, 0, |
1935 |
unsigned char *str; |
doc: /* |
1936 |
int len, nbytes, *nchars; |
Clear encoder and decoder of charsets that are loaded from mapfiles. */) |
1937 |
{ |
() |
1938 |
unsigned char *p = str, *endp = str + nbytes; |
{ |
1939 |
unsigned char *to; |
int i; |
1940 |
int chars = 0; |
struct charset *charset; |
1941 |
int n; |
Lisp_Object attrs; |
1942 |
|
|
1943 |
while (p < endp && UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n)) |
for (i = 0; i < charset_table_used; i++) |
|
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) |
|
1944 |
{ |
{ |
1945 |
if (UNIBYTE_STR_AS_MULTIBYTE_P (p, endp - p, n)) |
charset = CHARSET_FROM_ID (i); |
1946 |
{ |
attrs = CHARSET_ATTRIBUTES (charset); |
1947 |
while (n--) |
|
1948 |
*to++ = *p++; |
if (CHARSET_METHOD (charset) == CHARSET_METHOD_MAP) |
|
} |
|
|
else |
|
1949 |
{ |
{ |
1950 |
*to++ = LEADING_CODE_8_BIT_CONTROL; |
CHARSET_ATTR_DECODER (attrs) = Qnil; |
1951 |
*to++ = *p++ + 0x20; |
CHARSET_ATTR_ENCODER (attrs) = Qnil; |
1952 |
|
CHARSET_METHOD (charset) = CHARSET_METHOD_MAP_DEFERRED; |
1953 |
} |
} |
|
chars++; |
|
|
} |
|
|
if (nchars) |
|
|
*nchars = chars; |
|
|
return (to - str); |
|
|
} |
|
1954 |
|
|
1955 |
/* Parse unibyte string at STR of LEN bytes, and return the number of |
if (CHARSET_UNIFIED_P (charset)) |
1956 |
bytes it may ocupy when converted to multibyte string by |
CHARSET_ATTR_DEUNIFIER (attrs) = Qnil; |
1957 |
`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. */ |
|
1958 |
|
|
1959 |
int |
if (CHAR_TABLE_P (Vchar_unified_charset_table)) |
|
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) |
|
1960 |
{ |
{ |
1961 |
if (*p < 0x80 || *p >= 0xA0) |
Foptimize_char_table (Vchar_unified_charset_table); |
1962 |
*to++ = *p++; |
Vchar_unify_table = Vchar_unified_charset_table; |
1963 |
else |
Vchar_unified_charset_table = Qnil; |
|
*to++ = LEADING_CODE_8_BIT_CONTROL, *to++ = *p++ + 0x20; |
|
1964 |
} |
} |
|
return (to - str); |
|
|
} |
|
1965 |
|
|
1966 |
/* Arrange multibyte text at STR of LEN bytes as a unibyte text. It |
return Qnil; |
1967 |
actually converts only 8-bit characters in the range 0x80..0x9F to |
} |
|
unibyte forms. */ |
|
1968 |
|
|
1969 |
int |
DEFUN ("charset-priority-list", Fcharset_priority_list, |
1970 |
str_as_unibyte (str, bytes) |
Scharset_priority_list, 0, 1, 0, |
1971 |
unsigned char *str; |
doc: /* Return the list of charsets ordered by priority. |
1972 |
int bytes; |
HIGHESTP non-nil means just return the highest priority one. */) |
1973 |
|
(highestp) |
1974 |
|
Lisp_Object highestp; |
1975 |
{ |
{ |
1976 |
unsigned char *p = str, *endp = str + bytes; |
Lisp_Object val = Qnil, list = Vcharset_ordered_list; |
|
unsigned char *to = str; |
|
1977 |
|
|
1978 |
while (p < endp && *p != LEADING_CODE_8_BIT_CONTROL) p++; |
if (!NILP (highestp)) |
1979 |
to = p; |
return CHARSET_NAME (CHARSET_FROM_ID (XINT (Fcar (list)))); |
1980 |
while (p < endp) |
|
1981 |
|
while (!NILP (list)) |
1982 |
{ |
{ |
1983 |
if (*p == LEADING_CODE_8_BIT_CONTROL) |
val = Fcons (CHARSET_NAME (CHARSET_FROM_ID (XINT (XCAR (list)))), val); |
1984 |
*to++ = *(p + 1) - 0x20, p += 2; |
list = XCDR (list); |
|
else |
|
|
*to++ = *p++; |
|
1985 |
} |
} |
1986 |
return (to - str); |
return Fnreverse (val); |
1987 |
} |
} |
1988 |
|
|
1989 |
|
DEFUN ("set-charset-priority", Fset_charset_priority, Sset_charset_priority, |
1990 |
DEFUN ("string", Fstring, Sstring, 0, MANY, 0, |
1, MANY, 0, |
1991 |
doc: /* Concatenate all the argument characters and make the result a string. |
doc: /* Assign higher priority to the charsets given as arguments. |
1992 |
usage: (string &rest CHARACTERS) */) |
usage: (set-charset-priority &rest charsets) */) |
1993 |
(n, args) |
(nargs, args) |
1994 |
int n; |
int nargs; |
1995 |
Lisp_Object *args; |
Lisp_Object *args; |
1996 |
{ |
{ |
1997 |
int i; |
Lisp_Object new_head, old_list, arglist[2]; |
1998 |
unsigned char *buf = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH * n); |
int i, id; |
|
unsigned char *p = buf; |
|
|
int c; |
|
|
int multibyte = 0; |
|
1999 |
|
|
2000 |
for (i = 0; i < n; i++) |
old_list = Fcopy_sequence (Vcharset_ordered_list); |
2001 |
|
new_head = Qnil; |
2002 |
|
for (i = 0; i < nargs; i++) |
2003 |
{ |
{ |
2004 |
CHECK_NUMBER (args[i]); |
CHECK_CHARSET_GET_ID (args[i], id); |
2005 |
if (!multibyte && !SINGLE_BYTE_CHAR_P (XFASTINT (args[i]))) |
if (! NILP (Fmemq (make_number (id), old_list))) |
2006 |
multibyte = 1; |
{ |
2007 |
|
old_list = Fdelq (make_number (id), old_list); |
2008 |
|
new_head = Fcons (make_number (id), new_head); |
2009 |
|
} |
2010 |
} |
} |
2011 |
|
arglist[0] = Fnreverse (new_head); |
2012 |
|
arglist[1] = old_list; |
2013 |
|
Vcharset_ordered_list = Fnconc (2, arglist); |
2014 |
|
charset_ordered_list_tick++; |
2015 |
|
|
2016 |
for (i = 0; i < n; i++) |
for (old_list = Vcharset_ordered_list, new_head = Qnil; |
2017 |
|
CONSP (old_list); old_list = XCDR (old_list)) |
2018 |
{ |
{ |
2019 |
c = XINT (args[i]); |
if (! NILP (Fmemq (XCAR (old_list), Viso_2022_charset_list))) |
2020 |
if (multibyte) |
new_head = Fcons (XCAR (old_list), new_head); |
|
p += CHAR_STRING (c, p); |
|
|
else |
|
|
*p++ = c; |
|
2021 |
} |
} |
2022 |
|
Viso_2022_charset_list = Fnreverse (new_head); |
2023 |
|
|
2024 |
return make_string_from_bytes (buf, n, p - buf); |
return Qnil; |
2025 |
} |
} |
2026 |
|
|
2027 |
#endif /* emacs */ |
DEFUN ("charset-id-internal", Fcharset_id_internal, Scharset_id_internal, |
2028 |
|
0, 1, 0, |
2029 |
int |
doc: /* Internal use only. |
2030 |
charset_id_internal (charset_name) |
Return charset identification number of CHARSET. */) |
2031 |
char *charset_name; |
(charset) |
2032 |
|
Lisp_Object charset; |
2033 |
{ |
{ |
2034 |
Lisp_Object val; |
int id; |
|
|
|
|
val= Fget (intern (charset_name), Qcharset); |
|
|
if (!VECTORP (val)) |
|
|
error ("Charset %s is not defined", charset_name); |
|
2035 |
|
|
2036 |
return (XINT (XVECTOR (val)->contents[0])); |
CHECK_CHARSET_GET_ID (charset, id); |
2037 |
|
return make_number (id); |
2038 |
} |
} |
2039 |
|
|
2040 |
DEFUN ("setup-special-charsets", Fsetup_special_charsets, |
|
2041 |
Ssetup_special_charsets, 0, 0, 0, doc: /* Internal use only. */) |
void |
2042 |
() |
init_charset () |
2043 |
{ |
{ |
2044 |
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; |
|
2045 |
} |
} |
2046 |
|
|
2047 |
|
|
2048 |
void |
void |
2049 |
init_charset_once () |
init_charset_once () |
2050 |
{ |
{ |
2051 |
int i, j, k; |
int i, j, k; |
2052 |
|
|
2053 |
staticpro (&Vcharset_table); |
for (i = 0; i < ISO_MAX_DIMENSION; i++) |
2054 |
staticpro (&Vcharset_symbol_table); |
for (j = 0; j < ISO_MAX_CHARS; j++) |
2055 |
staticpro (&Vgeneric_character_list); |
for (k = 0; k < ISO_MAX_FINAL; k++) |
2056 |
|
iso_charset_table[i][j][k] = -1; |
|
/* This has to be done here, before we call Fmake_char_table. */ |
|
|
Qcharset_table = intern ("charset-table"); |
|
|
staticpro (&Qcharset_table); |
|
|
|
|
|
/* Intern this now in case it isn't already done. |
|
|
Setting this variable twice is harmless. |
|
|
But don't staticpro it here--that is done in alloc.c. */ |
|
|
Qchar_table_extra_slots = intern ("char-table-extra-slots"); |
|
|
|
|
|
/* Now we are ready to set up this property, so we can |
|
|
create the charset table. */ |
|
|
Fput (Qcharset_table, Qchar_table_extra_slots, make_number (0)); |
|
|
Vcharset_table = Fmake_char_table (Qcharset_table, Qnil); |
|
|
|
|
|
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; |
|
2057 |
|
|
2058 |
for (i = 0; i < 256; i++) |
for (i = 0; i < 256; i++) |
2059 |
bytes_by_char_head[i] = 1; |
emacs_mule_charset[i] = NULL; |
2060 |
bytes_by_char_head[LEADING_CODE_PRIVATE_11] = 3; |
|
2061 |
bytes_by_char_head[LEADING_CODE_PRIVATE_12] = 3; |
charset_jisx0201_roman = -1; |
2062 |
bytes_by_char_head[LEADING_CODE_PRIVATE_21] = 4; |
charset_jisx0208_1978 = -1; |
2063 |
bytes_by_char_head[LEADING_CODE_PRIVATE_22] = 4; |
charset_jisx0208 = -1; |
2064 |
|
|
2065 |
for (i = 0; i < 128; i++) |
for (i = 0; i < 128; i++) |
2066 |
width_by_char_head[i] = 1; |
unibyte_to_multibyte_table[i] = i; |
2067 |
for (; i < 256; i++) |
for (; i < 256; i++) |
2068 |
width_by_char_head[i] = 4; |
unibyte_to_multibyte_table[i] = BYTE8_TO_CHAR (i); |
|
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; |
|
2069 |
} |
} |
2070 |
|
|
2071 |
#ifdef emacs |
#ifdef emacs |
2073 |
void |
void |
2074 |
syms_of_charset () |
syms_of_charset () |
2075 |
{ |
{ |
2076 |
Qcharset = intern ("charset"); |
char *p; |
2077 |
staticpro (&Qcharset); |
|
2078 |
|
DEFSYM (Qcharsetp, "charsetp"); |
2079 |
|
|
2080 |
|
DEFSYM (Qascii, "ascii"); |
2081 |
|
DEFSYM (Qunicode, "unicode"); |
2082 |
|
DEFSYM (Qeight_bit, "eight-bit"); |
2083 |
|
DEFSYM (Qiso_8859_1, "iso-8859-1"); |
2084 |
|
|
2085 |
|
DEFSYM (Qgl, "gl"); |
2086 |
|
DEFSYM (Qgr, "gr"); |
2087 |
|
|
2088 |
|
p = (char *) xmalloc (30000); |
2089 |
|
|
2090 |
Qascii = intern ("ascii"); |
staticpro (&Vcharset_ordered_list); |
2091 |
staticpro (&Qascii); |
Vcharset_ordered_list = Qnil; |
2092 |
|
|
2093 |
Qeight_bit_control = intern ("eight-bit-control"); |
staticpro (&Viso_2022_charset_list); |
2094 |
staticpro (&Qeight_bit_control); |
Viso_2022_charset_list = Qnil; |
2095 |
|
|
2096 |
Qeight_bit_graphic = intern ("eight-bit-graphic"); |
staticpro (&Vemacs_mule_charset_list); |
2097 |
staticpro (&Qeight_bit_graphic); |
Vemacs_mule_charset_list = Qnil; |
|
|
|
|
/* Define special charsets ascii, eight-bit-control, and |
|
|
eight-bit-graphic. */ |
|
|
update_charset_table (make_number (CHARSET_ASCII), |
|
|
make_number (1), make_number (94), |
|
|
make_number (1), |
|
|
make_number (0), |
|
|
make_number ('B'), |
|
|
make_number (0), |
|
|
build_string ("ASCII"), |
|
|
Qnil, /* same as above */ |
|
|
build_string ("ASCII (ISO646 IRV)")); |
|
|
CHARSET_SYMBOL (CHARSET_ASCII) = Qascii; |
|
|
Fput (Qascii, Qcharset, CHARSET_TABLE_ENTRY (CHARSET_ASCII)); |
|
|
|
|
|
update_charset_table (make_number (CHARSET_8_BIT_CONTROL), |
|
|
make_number (1), make_number (96), |
|
|
make_number (4), |
|
|
make_number (0), |
|
|
make_number (-1), |
|
|
make_number (-1), |
|
|
build_string ("8-bit control code (0x80..0x9F)"), |
|
|
Qnil, /* same as above */ |
|
|
Qnil); /* same as above */ |
|
|
CHARSET_SYMBOL (CHARSET_8_BIT_CONTROL) = Qeight_bit_control; |
|
|
Fput (Qeight_bit_control, Qcharset, |
|
|
CHARSET_TABLE_ENTRY (CHARSET_8_BIT_CONTROL)); |
|
|
|
|
|
update_charset_table (make_number (CHARSET_8_BIT_GRAPHIC), |
|
|
make_number (1), make_number (96), |
|
|
make_number (4), |
|
|
make_number (0), |
|
|
make_number (-1), |
|
|
make_number (-1), |
|
|
build_string ("8-bit graphic char (0xA0..0xFF)"), |
|
|
Qnil, /* same as above */ |
|
|
Qnil); /* same as above */ |
|
|
CHARSET_SYMBOL (CHARSET_8_BIT_GRAPHIC) = Qeight_bit_graphic; |
|
|
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)); |
|
2098 |
|
|
2099 |
defsubr (&Sdefine_charset); |
staticpro (&Vcharset_hash_table); |
2100 |
defsubr (&Sgeneric_character_list); |
{ |
2101 |
|
Lisp_Object args[2]; |
2102 |
|
args[0] = QCtest; |
2103 |
|
args[1] = Qeq; |
2104 |
|
Vcharset_hash_table = Fmake_hash_table (2, args); |
2105 |
|
} |
2106 |
|
|
2107 |
|
charset_table_size = 128; |
2108 |
|
charset_table = ((struct charset *) |
2109 |
|
xmalloc (sizeof (struct charset) * charset_table_size)); |
2110 |
|
charset_table_used = 0; |
2111 |
|
|
2112 |
|
staticpro (&Vchar_unified_charset_table); |
2113 |
|
Vchar_unified_charset_table = Fmake_char_table (Qnil, make_number (-1)); |
2114 |
|
|
2115 |
|
defsubr (&Scharsetp); |
2116 |
|
defsubr (&Smap_charset_chars); |
2117 |
|
defsubr (&Sdefine_charset_internal); |
2118 |
|
defsubr (&Sdefine_charset_alias); |
2119 |
|
defsubr (&Sunibyte_charset); |
2120 |
|
defsubr (&Sset_unibyte_charset); |
2121 |
|
defsubr (&Scharset_plist); |
2122 |
|
defsubr (&Sset_charset_plist); |
2123 |
|
defsubr (&Sunify_charset); |
2124 |
defsubr (&Sget_unused_iso_final_char); |
defsubr (&Sget_unused_iso_final_char); |
2125 |
defsubr (&Sdeclare_equiv_charset); |
defsubr (&Sdeclare_equiv_charset); |
2126 |
defsubr (&Sfind_charset_region); |
defsubr (&Sfind_charset_region); |
2127 |
defsubr (&Sfind_charset_string); |
defsubr (&Sfind_charset_string); |
2128 |
defsubr (&Smake_char_internal); |
defsubr (&Sdecode_char); |
2129 |
|
defsubr (&Sencode_char); |
2130 |
defsubr (&Ssplit_char); |
defsubr (&Ssplit_char); |
2131 |
|
defsubr (&Smake_char); |
2132 |
defsubr (&Schar_charset); |
defsubr (&Schar_charset); |
2133 |
defsubr (&Scharset_after); |
defsubr (&Scharset_after); |
2134 |
defsubr (&Siso_charset); |
defsubr (&Siso_charset); |
2135 |
defsubr (&Schar_valid_p); |
defsubr (&Sclear_charset_maps); |
2136 |
defsubr (&Sunibyte_char_to_multibyte); |
defsubr (&Scharset_priority_list); |
2137 |
defsubr (&Smultibyte_char_to_unibyte); |
defsubr (&Sset_charset_priority); |
2138 |
defsubr (&Schar_bytes); |
defsubr (&Scharset_id_internal); |
2139 |
defsubr (&Schar_width); |
|
2140 |
defsubr (&Sstring_width); |
DEFVAR_LISP ("charset-map-directory", &Vcharset_map_directory, |
2141 |
defsubr (&Schar_direction); |
doc: /* Directory of charset map files that come with GNU Emacs. |
2142 |
defsubr (&Schars_in_region); |
The default value is sub-directory "charsets" of `data-directory'. */); |
2143 |
defsubr (&Sstring); |
Vcharset_map_directory = Fexpand_file_name (build_string ("charsets"), |
2144 |
defsubr (&Ssetup_special_charsets); |
Vdata_directory); |
2145 |
|
|
2146 |
DEFVAR_LISP ("charset-list", &Vcharset_list, |
DEFVAR_LISP ("charset-list", &Vcharset_list, |
2147 |
doc: /* List of charsets ever defined. */); |
doc: /* List of all charsets ever defined. */); |
2148 |
Vcharset_list = Fcons (Qascii, Fcons (Qeight_bit_control, |
Vcharset_list = Qnil; |
2149 |
Fcons (Qeight_bit_graphic, Qnil))); |
|
2150 |
|
charset_ascii |
2151 |
DEFVAR_LISP ("translation-table-vector", &Vtranslation_table_vector, |
= define_charset_internal (Qascii, 1, "\x00\x7F\x00\x00\x00\x00", |
2152 |
doc: /* Vector of cons cell of a symbol and translation table ever defined. |
0, 127, 'B', -1, 0, 1, 0, 0); |
2153 |
An ID of a translation table is an index of this vector. */); |
charset_iso_8859_1 |
2154 |
Vtranslation_table_vector = Fmake_vector (make_number (16), Qnil); |
= define_charset_internal (Qiso_8859_1, 1, "\x00\xFF\x00\x00\x00\x00", |
2155 |
|
0, 255, -1, -1, -1, 1, 0, 0); |
2156 |
DEFVAR_INT ("leading-code-private-11", &leading_code_private_11, |
charset_unicode |
2157 |
doc: /* Leading-code of private TYPE9N charset of column-width 1. */); |
= define_charset_internal (Qunicode, 3, "\x00\xFF\x00\xFF\x00\x10", |
2158 |
leading_code_private_11 = LEADING_CODE_PRIVATE_11; |
0, MAX_UNICODE_CHAR, -1, 0, -1, 1, 0, 0); |
2159 |
|
charset_eight_bit |
2160 |
DEFVAR_INT ("leading-code-private-12", &leading_code_private_12, |
= define_charset_internal (Qeight_bit, 1, "\x80\xFF\x00\x00\x00\x00", |
2161 |
doc: /* Leading-code of private TYPE9N charset of column-width 2. */); |
128, 255, -1, 0, -1, 0, 0, |
2162 |
leading_code_private_12 = LEADING_CODE_PRIVATE_12; |
MAX_5_BYTE_CHAR + 1); |
|
|
|
|
DEFVAR_INT ("leading-code-private-21", &leading_code_private_21, |
|
|
doc: /* Leading-code of private TYPE9Nx9N charset of column-width 1. */); |
|
|
leading_code_private_21 = LEADING_CODE_PRIVATE_21; |
|
|
|
|
|
DEFVAR_INT ("leading-code-private-22", &leading_code_private_22, |
|
|
doc: /* Leading-code of private TYPE9Nx9N charset of column-width 2. */); |
|
|
leading_code_private_22 = LEADING_CODE_PRIVATE_22; |
|
|
|
|
|
DEFVAR_INT ("nonascii-insert-offset", &nonascii_insert_offset, |
|
|
doc: /* Offset for converting non-ASCII unibyte codes 0240...0377 to multibyte. |
|
|
This is used for converting unibyte text to multibyte, |
|
|
and for inserting character codes specified by number. |
|
|
|
|
|
This serves to convert a Latin-1 or similar 8-bit character code |
|
|
to the corresponding Emacs multibyte character code. |
|
|
Typically the value should be (- (make-char CHARSET 0) 128), |
|
|
for your choice of character set. |
|
|
If `nonascii-translation-table' is non-nil, it overrides this variable. */); |
|
|
nonascii_insert_offset = 0; |
|
|
|
|
|
DEFVAR_LISP ("nonascii-translation-table", &Vnonascii_translation_table, |
|
|
doc: /* Translation table to convert non-ASCII unibyte codes to multibyte. |
|
|
This is used for converting unibyte text to multibyte, |
|
|
and for inserting character codes specified by number. |
|
|
|
|
|
Conversion is performed only when multibyte characters are enabled, |
|
|
and it serves to convert a Latin-1 or similar 8-bit character code |
|
|
to the corresponding Emacs character code. |
|
|
|
|
|
If this is nil, `nonascii-insert-offset' is used instead. |
|
|
See also the docstring of `make-translation-table'. */); |
|
|
Vnonascii_translation_table = Qnil; |
|
|
|
|
|
DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars, |
|
|
doc: /* A char-table for characters which invoke auto-filling. |
|
|
Such characters have value t in this table. */); |
|
|
Vauto_fill_chars = Fmake_char_table (Qauto_fill_chars, Qnil); |
|
|
CHAR_TABLE_SET (Vauto_fill_chars, make_number (' '), Qt); |
|
|
CHAR_TABLE_SET (Vauto_fill_chars, make_number ('\n'), Qt); |
|
2163 |
} |
} |
2164 |
|
|
2165 |
#endif /* emacs */ |
#endif /* emacs */ |