(Fexpand_abbrev): Remove unused variables.
[bpt/emacs.git] / src / charset.c
CommitLineData
75c8c592 1/* Basic multilingual character support.
35e623fb 2 Copyright (C) 1995, 1997, 1998 Electrotechnical Laboratory, JAPAN.
75c8c592 3 Licensed to the Free Software Foundation.
4ed46869 4
369314dc
KH
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
4ed46869 11
369314dc
KH
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
4ed46869 16
369314dc
KH
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
4ed46869
KH
21
22/* At first, see the document in `charset.h' to understand the code in
23 this file. */
24
25#include <stdio.h>
26
27#ifdef emacs
28
29#include <sys/types.h>
30#include <config.h>
31#include "lisp.h"
32#include "buffer.h"
33#include "charset.h"
34#include "coding.h"
fc6b09bf 35#include "disptab.h"
4ed46869
KH
36
37#else /* not emacs */
38
39#include "mulelib.h"
40
41#endif /* emacs */
42
43Lisp_Object Qcharset, Qascii, Qcomposition;
0282eb69 44Lisp_Object Qunknown;
4ed46869
KH
45
46/* Declaration of special leading-codes. */
47int leading_code_composition; /* for composite characters */
48int leading_code_private_11; /* for private DIMENSION1 of 1-column */
49int leading_code_private_12; /* for private DIMENSION1 of 2-column */
50int leading_code_private_21; /* for private DIMENSION2 of 1-column */
51int leading_code_private_22; /* for private DIMENSION2 of 2-column */
52
53/* Declaration of special charsets. */
54int charset_ascii; /* ASCII */
55int charset_composition; /* for a composite character */
56int charset_latin_iso8859_1; /* ISO8859-1 (Latin-1) */
57int charset_jisx0208_1978; /* JISX0208.1978 (Japanese Kanji old set) */
58int charset_jisx0208; /* JISX0208.1983 (Japanese Kanji) */
59int charset_katakana_jisx0201; /* JISX0201.Kana (Japanese Katakana) */
60int charset_latin_jisx0201; /* JISX0201.Roman (Japanese Roman) */
61int charset_big5_1; /* Big5 Level 1 (Chinese Traditional) */
62int charset_big5_2; /* Big5 Level 2 (Chinese Traditional) */
63
b0e3cf2b
KH
64int min_composite_char;
65
4ed46869
KH
66Lisp_Object Qcharset_table;
67
68/* A char-table containing information of each character set. */
69Lisp_Object Vcharset_table;
70
71/* A vector of charset symbol indexed by charset-id. This is used
72 only for returning charset symbol from C functions. */
73Lisp_Object Vcharset_symbol_table;
74
75/* A list of charset symbols ever defined. */
76Lisp_Object Vcharset_list;
77
537efd8d
KH
78/* Vector of translation table ever defined.
79 ID of a translation table is used to index this vector. */
80Lisp_Object Vtranslation_table_vector;
b0e3cf2b 81
c1a08b4c
KH
82/* A char-table for characters which may invoke auto-filling. */
83Lisp_Object Vauto_fill_chars;
84
85Lisp_Object Qauto_fill_chars;
86
4ed46869
KH
87/* Tables used by macros BYTES_BY_CHAR_HEAD and WIDTH_BY_CHAR_HEAD. */
88int bytes_by_char_head[256];
89int width_by_char_head[256];
90
91/* Mapping table from ISO2022's charset (specified by DIMENSION,
92 CHARS, and FINAL-CHAR) to Emacs' charset. */
93int iso_charset_table[2][2][128];
94
513ee442
KH
95/* Table of pointers to the structure `cmpchar_info' indexed by
96 CMPCHAR-ID. */
97struct cmpchar_info **cmpchar_table;
98/* The current size of `cmpchar_table'. */
99static int cmpchar_table_size;
100/* Number of the current composite characters. */
101int n_cmpchars;
102
4ed46869
KH
103/* Variables used locally in the macro FETCH_MULTIBYTE_CHAR. */
104unsigned char *_fetch_multibyte_char_p;
105int _fetch_multibyte_char_len;
106
35e623fb
RS
107/* Offset to add to a non-ASCII value when inserting it. */
108int nonascii_insert_offset;
109
4cf9710d
RS
110/* Translation table for converting non-ASCII unibyte characters
111 to multibyte codes, or nil. */
b4e9dd77 112Lisp_Object Vnonascii_translation_table;
4cf9710d 113
8a73a704
KH
114/* List of all possible generic characters. */
115Lisp_Object Vgeneric_character_list;
116
046b1f03
RS
117#define min(X, Y) ((X) < (Y) ? (X) : (Y))
118#define max(X, Y) ((X) > (Y) ? (X) : (Y))
119\f
93bcb785
KH
120void
121invalid_character (c)
122 int c;
123{
ba7434e5 124 error ("Invalid character: 0%o, %d, 0x%x", c, c, c);
93bcb785
KH
125}
126
44c6492d
KH
127/* Parse composite character string STR of length LENGTH (>= 2) and
128 set BYTES, CHARSET, C1, and C2 as below.
129
130 It is assumed that *STR is LEADING_CODE_COMPOSITION and the
131 following (LENGTH - 1) bytes satisfy !CHAR_HEAD_P.
132
133 If there is a valid composite character, set CHARSET, C1, and C2 to
134 such values that MAKE_CHAR can make the composite character from
135 them. Otherwise, set CHARSET to CHARSET_COMPOSITION, set C1 to the
136 second byte of the sequence, C2 to -1 so that MAKE_CHAR can make
137 the invalid multibyte character whose string representation is two
138 bytes of STR[0] and STR[1]. In any case, set BYTES to LENGTH.
139
140 This macro should be called only from SPLIT_MULTIBYTE_SEQ. */
ac4137cc
KH
141
142#define SPLIT_COMPOSITE_SEQ(str, length, bytes, charset, c1, c2) \
143 do { \
144 int cmpchar_id = str_cmpchar_id ((str), (length)); \
145 \
146 (charset) = CHARSET_COMPOSITION; \
147 (bytes) = (length); \
148 if (cmpchar_id >= 0) \
149 { \
150 (c1) = CHAR_FIELD2 (cmpchar_id); \
151 (c2) = CHAR_FIELD3 (cmpchar_id); \
152 } \
153 else \
154 { \
155 (c1) = (str)[1] & 0x7F; \
156 (c2) = -1; \
157 } \
158 } while (0)
159
44c6492d
KH
160/* Parse non-composite multibyte character string STR of length LENGTH
161 (>= 2) and set BYTES to the length of actual multibyte sequence,
162 CHARSET, C1, and C2 to such values that MAKE_CHAR can make the
163 multibyte character from them.
164
165 It is assumed that *STR is one of base leading codes (excluding
166 LEADING_CODE_COMPOSITION) and the following (LENGTH - 1) bytes
167 satisfy !CHAR_HEAD_P.
168
169 This macro should be called only from SPLIT_MULTIBYTE_SEQ. */
ac4137cc
KH
170
171#define SPLIT_CHARACTER_SEQ(str, length, bytes, charset, c1, c2) \
172 do { \
173 (bytes) = 1; \
174 (charset) = (str)[0]; \
175 if ((charset) >= LEADING_CODE_PRIVATE_11 \
176 && (charset) <= LEADING_CODE_PRIVATE_22) \
177 (charset) = (str)[(bytes)++]; \
178 if ((bytes) < (length)) \
179 { \
180 (c1) = (str)[(bytes)++] & 0x7F; \
181 if ((bytes) < (length)) \
182 (c2) = (str)[(bytes)++] & 0x7F; \
183 else \
184 (c2) = -1; \
185 } \
186 else \
187 (c1) = (c2) = -1; \
188 } while (0)
189
190/* Parse string STR of length LENGTH and check if a multibyte
191 characters is at STR. set BYTES to the actual length, CHARSET, C1,
192 C2 to proper values for that character. */
193
194#define SPLIT_MULTIBYTE_SEQ(str, length, bytes, charset, c1, c2) \
195 do { \
196 int i; \
44c6492d
KH
197 if (ASCII_BYTE_P ((str)[0])) \
198 i = 1; \
199 else \
200 for (i = 1; i < (length) && ! CHAR_HEAD_P ((str)[i]); i++); \
ac4137cc
KH
201 if (i == 1) \
202 (bytes) = 1, (charset) = CHARSET_ASCII, (c1) = (str)[0] ; \
203 else if ((str)[0] == LEADING_CODE_COMPOSITION) \
204 SPLIT_COMPOSITE_SEQ (str, i, bytes, charset, c1, c2); \
205 else \
206 { \
207 if (i > BYTES_BY_CHAR_HEAD ((str)[0])) \
208 i = BYTES_BY_CHAR_HEAD ((str)[0]); \
209 SPLIT_CHARACTER_SEQ (str, i, bytes, charset, c1, c2); \
210 } \
211 } while (0)
212
213/* 1 if CHARSET, C1, and C2 compose a valid character, else 0. */
44c6492d 214#define CHAR_COMPONENTS_VALID_P(charset, c1, c2) \
63f4d579
KH
215 (charset == CHARSET_ASCII \
216 ? ((c1) >= 0 && (c1) <= 0x7F) \
217 : (CHARSET_DIMENSION (charset) == 1 \
218 ? ((c1) >= 0x20 && (c1) <= 0x7F) \
219 : ((c1) >= 0x20 && (c1) <= 0x7F && (c2) >= 0x20 && (c2) <= 0x7F)))
93bcb785 220
4ed46869
KH
221/* Set STR a pointer to the multi-byte form of the character C. If C
222 is not a composite character, the multi-byte form is set in WORKBUF
223 and STR points WORKBUF. The caller should allocate at least 4-byte
224 area at WORKBUF in advance. Returns the length of the multi-byte
ac4137cc
KH
225 form. If C is an invalid character, store (C & 0xFF) in WORKBUF[0]
226 and return 1.
4ed46869
KH
227
228 Use macro `CHAR_STRING (C, WORKBUF, STR)' instead of calling this
229 function directly if C can be an ASCII character. */
230
231int
232non_ascii_char_to_string (c, workbuf, str)
233 int c;
234 unsigned char *workbuf, **str;
235{
6662e69b 236 if (c & CHAR_MODIFIER_MASK) /* This includes the case C is negative. */
8ac5a9cc 237 {
6662e69b
KH
238 /* Multibyte character can't have a modifier bit. */
239 if (! SINGLE_BYTE_CHAR_P ((c & ~CHAR_MODIFIER_MASK)))
240 invalid_character (c);
241
242 /* For Meta, Shift, and Control modifiers, we need special care. */
8ac5a9cc 243 if (c & CHAR_META)
6662e69b
KH
244 {
245 /* Move the meta bit to the right place for a string. */
246 c = (c & ~CHAR_META) | 0x80;
247 }
248 if (c & CHAR_SHIFT)
249 {
250 /* Shift modifier is valid only with [A-Za-z]. */
251 if ((c & 0377) >= 'A' && (c & 0377) <= 'Z')
252 c &= ~CHAR_SHIFT;
253 else if ((c & 0377) >= 'a' && (c & 0377) <= 'z')
254 c = (c & ~CHAR_SHIFT) - ('a' - 'A');
255 }
8ac5a9cc 256 if (c & CHAR_CTL)
6662e69b
KH
257 {
258 /* Simulate the code in lread.c. */
259 /* Allow `\C- ' and `\C-?'. */
260 if (c == (CHAR_CTL | ' '))
261 c = 0;
262 else if (c == (CHAR_CTL | '?'))
263 c = 127;
264 /* ASCII control chars are made from letters (both cases),
265 as well as the non-letters within 0100...0137. */
266 else if ((c & 0137) >= 0101 && (c & 0137) <= 0132)
267 c &= (037 | (~0177 & ~CHAR_CTL));
268 else if ((c & 0177) >= 0100 && (c & 0177) <= 0137)
269 c &= (037 | (~0177 & ~CHAR_CTL));
270 }
271
272 /* If C still has any modifier bits, it is an invalid character. */
273 if (c & CHAR_MODIFIER_MASK)
274 invalid_character (c);
275
8ac5a9cc 276 *str = workbuf;
ac4137cc 277 *workbuf++ = c;
8ac5a9cc 278 }
ac4137cc 279 else
4ed46869 280 {
ac4137cc 281 int charset, c1, c2;
4ed46869 282
ac4137cc
KH
283 SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
284 if (charset == CHARSET_COMPOSITION)
4ed46869 285 {
ac4137cc
KH
286 if (c >= MAX_CHAR)
287 invalid_character (c);
288 if (c >= MIN_CHAR_COMPOSITION)
289 {
290 /* Valid composite character. */
291 *str = cmpchar_table[COMPOSITE_CHAR_ID (c)]->data;
292 workbuf = *str + cmpchar_table[COMPOSITE_CHAR_ID (c)]->len;
293 }
294 else
295 {
296 /* Invalid but can have multibyte form. */
297 *str = workbuf;
298 *workbuf++ = LEADING_CODE_COMPOSITION;
299 *workbuf++ = c1 | 0x80;
300 }
4ed46869 301 }
ac4137cc 302 else if (charset > CHARSET_COMPOSITION)
4ed46869 303 {
ac4137cc
KH
304 *str = workbuf;
305 if (charset >= LEADING_CODE_EXT_11)
306 *workbuf++ = (charset < LEADING_CODE_EXT_12
307 ? LEADING_CODE_PRIVATE_11
308 : (charset < LEADING_CODE_EXT_21
309 ? LEADING_CODE_PRIVATE_12
310 : (charset < LEADING_CODE_EXT_22
311 ? LEADING_CODE_PRIVATE_21
312 : LEADING_CODE_PRIVATE_22)));
313 *workbuf++ = charset;
314 if (c1 > 0 && c1 < 32 || c2 > 0 && c2 < 32)
315 invalid_character (c);
316 if (c1)
317 {
318 *workbuf++ = c1 | 0x80;
319 if (c2 > 0)
320 *workbuf++ = c2 | 0x80;
321 }
4ed46869 322 }
ac4137cc
KH
323 else if (charset == CHARSET_ASCII)
324 *workbuf++= c & 0x7F;
325 else
326 invalid_character (c);
4ed46869
KH
327 }
328
4ed46869
KH
329 return (workbuf - *str);
330}
331
44c6492d
KH
332/* Return the non-ASCII character corresponding to multi-byte form at
333 STR of length LEN. If ACTUAL_LEN is not NULL, store the byte
334 length of the multibyte form in *ACTUAL_LEN.
537efd8d 335
4ed46869 336 Use macro `STRING_CHAR (STR, LEN)' instead of calling this function
44c6492d 337 directly if you want ot handle ASCII characters as well. */
4ed46869 338
dfcf069d 339int
ac4137cc 340string_to_non_ascii_char (str, len, actual_len)
8867de67 341 const unsigned char *str;
ac4137cc 342 int len, *actual_len;
4ed46869 343{
ac4137cc 344 int c, bytes, charset, c1, c2;
4ed46869 345
ac4137cc
KH
346 SPLIT_MULTIBYTE_SEQ (str, len, bytes, charset, c1, c2);
347 c = MAKE_CHAR (charset, c1, c2);
4ed46869 348 if (actual_len)
ac4137cc 349 *actual_len = bytes;
4ed46869
KH
350 return c;
351}
352
44c6492d
KH
353/* Return the length of the multi-byte form at string STR of length LEN.
354 Use the macro MULTIBYTE_FORM_LENGTH instead. */
4ed46869
KH
355int
356multibyte_form_length (str, len)
8867de67 357 const unsigned char *str;
4ed46869
KH
358 int len;
359{
ac4137cc 360 int bytes;
4ed46869 361
ac4137cc 362 PARSE_MULTIBYTE_SEQ (str, len, bytes);
90d7b74e 363 return bytes;
4ed46869
KH
364}
365
ac4137cc
KH
366/* Check multibyte form at string STR of length LEN and set variables
367 pointed by CHARSET, C1, and C2 to charset and position codes of the
368 character at STR, and return 0. If there's no multibyte character,
4ed46869
KH
369 return -1. This should be used only in the macro SPLIT_STRING
370 which checks range of STR in advance. */
371
dfcf069d 372int
4ed46869 373split_non_ascii_string (str, len, charset, c1, c2)
ac4137cc
KH
374 const unsigned char *str;
375 unsigned char *c1, *c2;
376 int len, *charset;
4ed46869 377{
ac4137cc 378 register int bytes, cs, code1, code2 = -1;
4ed46869 379
ac4137cc
KH
380 SPLIT_MULTIBYTE_SEQ (str, len, bytes, cs, code1, code2);
381 if (cs == CHARSET_ASCII)
4ed46869 382 return -1;
ac4137cc
KH
383 *charset = cs;
384 *c1 = code1;
385 *c2 = code2;
386}
387
44c6492d
KH
388/* Return 1 iff character C has valid printable glyph.
389 Use the macro CHAR_PRINTABLE_P instead. */
ac4137cc
KH
390int
391char_printable_p (c)
392 int c;
393{
394 int charset, c1, c2, chars;
395
396 if (SINGLE_BYTE_CHAR_P (c))
397 return 1;
398 if (c >= MIN_CHAR_COMPOSITION)
399 return (c < MAX_CHAR);
400
401 SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
402 if (! CHARSET_DEFINED_P (charset))
403 return 0;
404 if (CHARSET_CHARS (charset) == 94
405 ? c1 <= 32 || c1 >= 127
406 : c1 < 32)
407 return 0;
408 if (CHARSET_DIMENSION (charset) == 2
409 && (CHARSET_CHARS (charset) == 94
410 ? c2 <= 32 || c2 >= 127
411 : c2 < 32))
412 return 0;
413 return 1;
4ed46869
KH
414}
415
537efd8d 416/* Translate character C by translation table TABLE. If C
b4e9dd77
KH
417 is negative, translate a character specified by CHARSET, C1, and C2
418 (C1 and C2 are code points of the character). If no translation is
419 found in TABLE, return C. */
dfcf069d 420int
b4e9dd77 421translate_char (table, c, charset, c1, c2)
23d2a7f1
KH
422 Lisp_Object table;
423 int c, charset, c1, c2;
424{
425 Lisp_Object ch;
426 int alt_charset, alt_c1, alt_c2, dimension;
427
0ad3f83d 428 if (c < 0) c = MAKE_CHAR (charset, (c1 & 0x7F) , (c2 & 0x7F));
23d2a7f1 429 if (!CHAR_TABLE_P (table)
ac4137cc 430 || (ch = Faref (table, make_number (c)), !NATNUMP (ch)))
23d2a7f1
KH
431 return c;
432
433 SPLIT_CHAR (XFASTINT (ch), alt_charset, alt_c1, alt_c2);
434 dimension = CHARSET_DIMENSION (alt_charset);
435 if (dimension == 1 && alt_c1 > 0 || dimension == 2 && alt_c2 > 0)
436 /* CH is not a generic character, just return it. */
437 return XFASTINT (ch);
438
439 /* Since CH is a generic character, we must return a specific
440 charater which has the same position codes as C from CH. */
441 if (charset < 0)
442 SPLIT_CHAR (c, charset, c1, c2);
443 if (dimension != CHARSET_DIMENSION (charset))
444 /* We can't make such a character because of dimension mismatch. */
445 return c;
23d2a7f1
KH
446 return MAKE_CHAR (alt_charset, c1, c2);
447}
448
d2665018 449/* Convert the unibyte character C to multibyte based on
b4e9dd77 450 Vnonascii_translation_table or nonascii_insert_offset. If they can't
d2665018
KH
451 convert C to a valid multibyte character, convert it based on
452 DEFAULT_NONASCII_INSERT_OFFSET which makes C a Latin-1 character. */
35e623fb 453
dfcf069d 454int
35e623fb
RS
455unibyte_char_to_multibyte (c)
456 int c;
457{
543b4f61 458 if (c < 0400 && c >= 0200)
35e623fb 459 {
d2665018
KH
460 int c_save = c;
461
b4e9dd77 462 if (! NILP (Vnonascii_translation_table))
bbf12bb3
KH
463 {
464 c = XINT (Faref (Vnonascii_translation_table, make_number (c)));
ac4137cc 465 if (c >= 0400 && ! char_valid_p (c, 0))
bbf12bb3
KH
466 c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
467 }
468 else if (c >= 0240 && nonascii_insert_offset > 0)
469 {
470 c += nonascii_insert_offset;
ac4137cc 471 if (c < 0400 || ! char_valid_p (c, 0))
bbf12bb3
KH
472 c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
473 }
474 else if (c >= 0240)
d2665018 475 c = c_save + DEFAULT_NONASCII_INSERT_OFFSET;
35e623fb
RS
476 }
477 return c;
478}
76d7b829
KH
479
480
481/* Convert the multibyte character C to unibyte 8-bit character based
482 on Vnonascii_translation_table or nonascii_insert_offset. If
483 REV_TBL is non-nil, it should be a reverse table of
484 Vnonascii_translation_table, i.e. what given by:
485 Fchar_table_extra_slot (Vnonascii_translation_table, make_number (0)) */
486
487int
488multibyte_char_to_unibyte (c, rev_tbl)
489 int c;
490 Lisp_Object rev_tbl;
491{
492 if (!SINGLE_BYTE_CHAR_P (c))
493 {
494 int c_save = c;
495
496 if (! CHAR_TABLE_P (rev_tbl)
497 && CHAR_TABLE_P (Vnonascii_translation_table))
498 rev_tbl = Fchar_table_extra_slot (Vnonascii_translation_table,
499 make_number (0));
500 if (CHAR_TABLE_P (rev_tbl))
501 {
502 Lisp_Object temp;
503 temp = Faref (rev_tbl, make_number (c));
504 if (INTEGERP (temp))
505 c = XINT (temp);
bbf12bb3
KH
506 if (c >= 256)
507 c = (c_save & 0177) + 0200;
508 }
509 else
510 {
511 if (nonascii_insert_offset > 0)
512 c -= nonascii_insert_offset;
513 if (c < 128 || c >= 256)
514 c = (c_save & 0177) + 0200;
76d7b829 515 }
76d7b829
KH
516 }
517
518 return c;
519}
520
35e623fb 521\f
4ed46869
KH
522/* Update the table Vcharset_table with the given arguments (see the
523 document of `define-charset' for the meaning of each argument).
524 Several other table contents are also updated. The caller should
525 check the validity of CHARSET-ID and the remaining arguments in
526 advance. */
527
528void
529update_charset_table (charset_id, dimension, chars, width, direction,
530 iso_final_char, iso_graphic_plane,
531 short_name, long_name, description)
532 Lisp_Object charset_id, dimension, chars, width, direction;
533 Lisp_Object iso_final_char, iso_graphic_plane;
534 Lisp_Object short_name, long_name, description;
535{
536 int charset = XINT (charset_id);
537 int bytes;
538 unsigned char leading_code_base, leading_code_ext;
539
6dc0722d
KH
540 if (NILP (CHARSET_TABLE_ENTRY (charset)))
541 CHARSET_TABLE_ENTRY (charset)
542 = Fmake_vector (make_number (CHARSET_MAX_IDX), Qnil);
4ed46869
KH
543
544 /* Get byte length of multibyte form, base leading-code, and
545 extended leading-code of the charset. See the comment under the
546 title "GENERAL NOTE on CHARACTER SET (CHARSET)" in charset.h. */
547 bytes = XINT (dimension);
548 if (charset < MIN_CHARSET_PRIVATE_DIMENSION1)
549 {
550 /* Official charset, it doesn't have an extended leading-code. */
551 if (charset != CHARSET_ASCII)
552 bytes += 1; /* For a base leading-code. */
553 leading_code_base = charset;
554 leading_code_ext = 0;
555 }
556 else
557 {
558 /* Private charset. */
559 bytes += 2; /* For base and extended leading-codes. */
560 leading_code_base
561 = (charset < LEADING_CODE_EXT_12
562 ? LEADING_CODE_PRIVATE_11
563 : (charset < LEADING_CODE_EXT_21
564 ? LEADING_CODE_PRIVATE_12
565 : (charset < LEADING_CODE_EXT_22
566 ? LEADING_CODE_PRIVATE_21
567 : LEADING_CODE_PRIVATE_22)));
568 leading_code_ext = charset;
569 }
570
6ef23ebb
KH
571 if (BYTES_BY_CHAR_HEAD (leading_code_base) != bytes)
572 error ("Invalid dimension for the charset-ID %d", charset);
573
4ed46869
KH
574 CHARSET_TABLE_INFO (charset, CHARSET_ID_IDX) = charset_id;
575 CHARSET_TABLE_INFO (charset, CHARSET_BYTES_IDX) = make_number (bytes);
576 CHARSET_TABLE_INFO (charset, CHARSET_DIMENSION_IDX) = dimension;
577 CHARSET_TABLE_INFO (charset, CHARSET_CHARS_IDX) = chars;
578 CHARSET_TABLE_INFO (charset, CHARSET_WIDTH_IDX) = width;
579 CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX) = direction;
580 CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_BASE_IDX)
581 = make_number (leading_code_base);
582 CHARSET_TABLE_INFO (charset, CHARSET_LEADING_CODE_EXT_IDX)
583 = make_number (leading_code_ext);
584 CHARSET_TABLE_INFO (charset, CHARSET_ISO_FINAL_CHAR_IDX) = iso_final_char;
585 CHARSET_TABLE_INFO (charset, CHARSET_ISO_GRAPHIC_PLANE_IDX)
586 = iso_graphic_plane;
587 CHARSET_TABLE_INFO (charset, CHARSET_SHORT_NAME_IDX) = short_name;
588 CHARSET_TABLE_INFO (charset, CHARSET_LONG_NAME_IDX) = long_name;
589 CHARSET_TABLE_INFO (charset, CHARSET_DESCRIPTION_IDX) = description;
590 CHARSET_TABLE_INFO (charset, CHARSET_PLIST_IDX) = Qnil;
591
592 {
593 /* If we have already defined a charset which has the same
594 DIMENSION, CHARS and ISO-FINAL-CHAR but the different
595 DIRECTION, we must update the entry REVERSE-CHARSET of both
596 charsets. If there's no such charset, the value of the entry
597 is set to nil. */
598 int i;
599
513ee442 600 for (i = 0; i <= MAX_CHARSET; i++)
4ed46869
KH
601 if (!NILP (CHARSET_TABLE_ENTRY (i)))
602 {
603 if (CHARSET_DIMENSION (i) == XINT (dimension)
604 && CHARSET_CHARS (i) == XINT (chars)
605 && CHARSET_ISO_FINAL_CHAR (i) == XINT (iso_final_char)
606 && CHARSET_DIRECTION (i) != XINT (direction))
607 {
608 CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX)
609 = make_number (i);
610 CHARSET_TABLE_INFO (i, CHARSET_REVERSE_CHARSET_IDX) = charset_id;
611 break;
612 }
613 }
513ee442 614 if (i > MAX_CHARSET)
4ed46869
KH
615 /* No such a charset. */
616 CHARSET_TABLE_INFO (charset, CHARSET_REVERSE_CHARSET_IDX)
617 = make_number (-1);
618 }
619
620 if (charset != CHARSET_ASCII
621 && charset < MIN_CHARSET_PRIVATE_DIMENSION1)
622 {
4ed46869
KH
623 width_by_char_head[leading_code_base] = XINT (width);
624
625 /* Update table emacs_code_class. */
626 emacs_code_class[charset] = (bytes == 2
627 ? EMACS_leading_code_2
628 : (bytes == 3
629 ? EMACS_leading_code_3
630 : EMACS_leading_code_4));
631 }
632
633 /* Update table iso_charset_table. */
634 if (ISO_CHARSET_TABLE (dimension, chars, iso_final_char) < 0)
635 ISO_CHARSET_TABLE (dimension, chars, iso_final_char) = charset;
636}
637
638#ifdef emacs
639
640/* Return charset id of CHARSET_SYMBOL, or return -1 if CHARSET_SYMBOL
641 is invalid. */
642int
643get_charset_id (charset_symbol)
644 Lisp_Object charset_symbol;
645{
646 Lisp_Object val;
647 int charset;
648
649 return ((SYMBOLP (charset_symbol)
650 && (val = Fget (charset_symbol, Qcharset), VECTORP (val))
651 && (charset = XINT (XVECTOR (val)->contents[CHARSET_ID_IDX]),
652 CHARSET_VALID_P (charset)))
653 ? charset : -1);
654}
655
656/* Return an identification number for a new private charset of
657 DIMENSION and WIDTH. If there's no more room for the new charset,
658 return 0. */
659Lisp_Object
660get_new_private_charset_id (dimension, width)
661 int dimension, width;
662{
663 int charset, from, to;
664
665 if (dimension == 1)
666 {
667 if (width == 1)
668 from = LEADING_CODE_EXT_11, to = LEADING_CODE_EXT_12;
669 else
670 from = LEADING_CODE_EXT_12, to = LEADING_CODE_EXT_21;
671 }
672 else
673 {
674 if (width == 1)
675 from = LEADING_CODE_EXT_21, to = LEADING_CODE_EXT_22;
676 else
b0e3cf2b 677 from = LEADING_CODE_EXT_22, to = LEADING_CODE_EXT_MAX + 1;
4ed46869
KH
678 }
679
680 for (charset = from; charset < to; charset++)
681 if (!CHARSET_DEFINED_P (charset)) break;
682
683 return make_number (charset < to ? charset : 0);
684}
685
686DEFUN ("define-charset", Fdefine_charset, Sdefine_charset, 3, 3, 0,
687 "Define CHARSET-ID as the identification number of CHARSET with INFO-VECTOR.\n\
23d2a7f1 688If CHARSET-ID is nil, it is decided automatically, which means CHARSET is\n\
4ed46869
KH
689 treated as a private charset.\n\
690INFO-VECTOR is a vector of the format:\n\
691 [DIMENSION CHARS WIDTH DIRECTION ISO-FINAL-CHAR ISO-GRAPHIC-PLANE\n\
692 SHORT-NAME LONG-NAME DESCRIPTION]\n\
693The meanings of each elements is as follows:\n\
694DIMENSION (integer) is the number of bytes to represent a character: 1 or 2.\n\
695CHARS (integer) is the number of characters in a dimension: 94 or 96.\n\
696WIDTH (integer) is the number of columns a character in the charset\n\
697occupies on the screen: one of 0, 1, and 2.\n\
698\n\
699DIRECTION (integer) is the rendering direction of characters in the\n\
277576f6
KH
700charset when rendering. If 0, render from left to right, else\n\
701render from right to left.\n\
4ed46869
KH
702\n\
703ISO-FINAL-CHAR (character) is the final character of the\n\
704corresponding ISO 2022 charset.\n\
705\n\
706ISO-GRAPHIC-PLANE (integer) is the graphic plane to be invoked\n\
707while encoding to variants of ISO 2022 coding system, one of the\n\
708following: 0/graphic-plane-left(GL), 1/graphic-plane-right(GR).\n\
709\n\
710SHORT-NAME (string) is the short name to refer to the charset.\n\
711\n\
712LONG-NAME (string) is the long name to refer to the charset.\n\
713\n\
714DESCRIPTION (string) is the description string of the charset.")
715 (charset_id, charset_symbol, info_vector)
716 Lisp_Object charset_id, charset_symbol, info_vector;
717{
718 Lisp_Object *vec;
719
720 if (!NILP (charset_id))
721 CHECK_NUMBER (charset_id, 0);
722 CHECK_SYMBOL (charset_symbol, 1);
723 CHECK_VECTOR (info_vector, 2);
724
725 if (! NILP (charset_id))
726 {
727 if (! CHARSET_VALID_P (XINT (charset_id)))
728 error ("Invalid CHARSET: %d", XINT (charset_id));
729 else if (CHARSET_DEFINED_P (XINT (charset_id)))
730 error ("Already defined charset: %d", XINT (charset_id));
731 }
732
733 vec = XVECTOR (info_vector)->contents;
734 if (XVECTOR (info_vector)->size != 9
735 || !INTEGERP (vec[0]) || !(XINT (vec[0]) == 1 || XINT (vec[0]) == 2)
736 || !INTEGERP (vec[1]) || !(XINT (vec[1]) == 94 || XINT (vec[1]) == 96)
737 || !INTEGERP (vec[2]) || !(XINT (vec[2]) == 1 || XINT (vec[2]) == 2)
738 || !INTEGERP (vec[3]) || !(XINT (vec[3]) == 0 || XINT (vec[3]) == 1)
739 || !INTEGERP (vec[4]) || !(XINT (vec[4]) >= '0' && XINT (vec[4]) <= '~')
740 || !INTEGERP (vec[5]) || !(XINT (vec[5]) == 0 || XINT (vec[5]) == 1)
741 || !STRINGP (vec[6])
742 || !STRINGP (vec[7])
743 || !STRINGP (vec[8]))
744 error ("Invalid info-vector argument for defining charset %s",
745 XSYMBOL (charset_symbol)->name->data);
746
747 if (NILP (charset_id))
748 {
749 charset_id = get_new_private_charset_id (XINT (vec[0]), XINT (vec[2]));
750 if (XINT (charset_id) == 0)
751 error ("There's no room for a new private charset %s",
752 XSYMBOL (charset_symbol)->name->data);
753 }
754
755 update_charset_table (charset_id, vec[0], vec[1], vec[2], vec[3],
756 vec[4], vec[5], vec[6], vec[7], vec[8]);
6dc0722d 757 Fput (charset_symbol, Qcharset, CHARSET_TABLE_ENTRY (XINT (charset_id)));
4ed46869
KH
758 CHARSET_SYMBOL (XINT (charset_id)) = charset_symbol;
759 Vcharset_list = Fcons (charset_symbol, Vcharset_list);
760 return Qnil;
761}
762
8a73a704
KH
763DEFUN ("generic-character-list", Fgeneric_character_list,
764 Sgeneric_character_list, 0, 0, 0,
765 "Return a list of all possible generic characters.\n\
766It includes a generic character for a charset not yet defined.")
767 ()
768{
769 return Vgeneric_character_list;
770}
771
3fac5a51
KH
772DEFUN ("get-unused-iso-final-char", Fget_unused_iso_final_char,
773 Sget_unused_iso_final_char, 2, 2, 0,
774 "Return an unsed ISO's final char for a charset of DIMENISION and CHARS.\n\
775DIMENSION is the number of bytes to represent a character: 1 or 2.\n\
776CHARS is the number of characters in a dimension: 94 or 96.\n\
777\n\
778This final char is for private use, thus the range is `0' (48) .. `?' (63).\n\
779If there's no unused final char for the specified kind of charset,\n\
780return nil.")
781 (dimension, chars)
782 Lisp_Object dimension, chars;
783{
784 int final_char;
785
786 CHECK_NUMBER (dimension, 0);
787 CHECK_NUMBER (chars, 1);
788 if (XINT (dimension) != 1 && XINT (dimension) != 2)
789 error ("Invalid charset dimension %d, it should be 1 or 2",
790 XINT (dimension));
791 if (XINT (chars) != 94 && XINT (chars) != 96)
792 error ("Invalid charset chars %d, it should be 94 or 96",
793 XINT (chars));
794 for (final_char = '0'; final_char <= '?'; final_char++)
795 {
796 if (ISO_CHARSET_TABLE (dimension, chars, make_number (final_char)) < 0)
797 break;
798 }
799 return (final_char <= '?' ? make_number (final_char) : Qnil);
800}
801
4ed46869
KH
802DEFUN ("declare-equiv-charset", Fdeclare_equiv_charset, Sdeclare_equiv_charset,
803 4, 4, 0,
804 "Declare a charset of DIMENSION, CHARS, FINAL-CHAR is the same as CHARSET.\n\
805CHARSET should be defined by `defined-charset' in advance.")
806 (dimension, chars, final_char, charset_symbol)
807 Lisp_Object dimension, chars, final_char, charset_symbol;
808{
809 int charset;
810
811 CHECK_NUMBER (dimension, 0);
812 CHECK_NUMBER (chars, 1);
813 CHECK_NUMBER (final_char, 2);
814 CHECK_SYMBOL (charset_symbol, 3);
815
816 if (XINT (dimension) != 1 && XINT (dimension) != 2)
817 error ("Invalid DIMENSION %d, it should be 1 or 2", XINT (dimension));
818 if (XINT (chars) != 94 && XINT (chars) != 96)
819 error ("Invalid CHARS %d, it should be 94 or 96", XINT (chars));
820 if (XINT (final_char) < '0' || XFASTINT (final_char) > '~')
821 error ("Invalid FINAL-CHAR %c, it should be `0'..`~'", XINT (chars));
822 if ((charset = get_charset_id (charset_symbol)) < 0)
823 error ("Invalid charset %s", XSYMBOL (charset_symbol)->name->data);
824
825 ISO_CHARSET_TABLE (dimension, chars, final_char) = charset;
826 return Qnil;
827}
828
829/* Return number of different charsets in STR of length LEN. In
830 addition, for each found charset N, CHARSETS[N] is set 1. The
a29e3b1b 831 caller should allocate CHARSETS (MAX_CHARSET + 1 elements) in advance.
1d67c29b
KH
832 It may lookup a translation table TABLE if supplied.
833
834 If CMPCHARP is nonzero and some composite character is found,
835 CHARSETS[128] is also set 1 and the returned number is incremented
0282eb69
KH
836 by 1.
837
838 If MULTIBYTE is zero, do not check multibyte characters, i.e. if
839 any ASCII codes (7-bit) are found, CHARSET[0] is set to 1, if any
840 8-bit codes are found CHARSET[1] is set to 1. */
4ed46869
KH
841
842int
0282eb69 843find_charset_in_str (str, len, charsets, table, cmpcharp, multibyte)
028d516b
KH
844 unsigned char *str;
845 int len, *charsets;
23d2a7f1 846 Lisp_Object table;
1d67c29b 847 int cmpcharp;
0282eb69 848 int multibyte;
4ed46869 849{
733eafd8 850 register int num = 0, c;
4ed46869 851
0282eb69
KH
852 if (! multibyte)
853 {
854 unsigned char *endp = str + len;
855 int maskbits = 0;
856
857 while (str < endp && maskbits != 3)
858 maskbits |= (*str++ < 0x80 ? 1 : 2);
859 if (maskbits & 1)
860 {
861 charsets[0] = 1;
862 num++;
863 }
864 if (maskbits & 2)
865 {
866 charsets[1] = 1;
867 num++;
868 }
869 return num;
870 }
871
23d2a7f1
KH
872 if (! CHAR_TABLE_P (table))
873 table = Qnil;
874
4ed46869
KH
875 while (len > 0)
876 {
05505664 877 int bytes, charset;
733eafd8 878 c = *str;
23d2a7f1 879
733eafd8 880 if (c == LEADING_CODE_COMPOSITION)
05505664 881 {
733eafd8
KH
882 int cmpchar_id = str_cmpchar_id (str, len);
883 GLYPH *glyph;
05505664 884
1d67c29b 885 if (cmpchar_id >= 0)
05505664 886 {
020da460 887 struct cmpchar_info *cmp_p = cmpchar_table[cmpchar_id];
733eafd8
KH
888 int i;
889
020da460 890 for (i = 0; i < cmp_p->glyph_len; i++)
733eafd8 891 {
020da460 892 c = cmp_p->glyph[i];
733eafd8
KH
893 if (!NILP (table))
894 {
b4e9dd77 895 if ((c = translate_char (table, c, 0, 0, 0)) < 0)
020da460 896 c = cmp_p->glyph[i];
733eafd8
KH
897 }
898 if ((charset = CHAR_CHARSET (c)) < 0)
899 charset = CHARSET_ASCII;
900 if (!charsets[charset])
901 {
902 charsets[charset] = 1;
903 num += 1;
904 }
905 }
020da460
KH
906 str += cmp_p->len;
907 len -= cmp_p->len;
908 if (cmpcharp && !charsets[CHARSET_COMPOSITION])
909 {
910 charsets[CHARSET_COMPOSITION] = 1;
911 num += 1;
912 }
733eafd8 913 continue;
05505664 914 }
05505664 915
0282eb69 916 charset = 1; /* This leads to `unknown' charset. */
733eafd8
KH
917 bytes = 1;
918 }
23d2a7f1
KH
919 else
920 {
733eafd8
KH
921 c = STRING_CHAR_AND_LENGTH (str, len, bytes);
922 if (! NILP (table))
923 {
b4e9dd77 924 int c1 = translate_char (table, c, 0, 0, 0);
733eafd8
KH
925 if (c1 >= 0)
926 c = c1;
927 }
928 charset = CHAR_CHARSET (c);
23d2a7f1 929 }
4ed46869
KH
930
931 if (!charsets[charset])
932 {
933 charsets[charset] = 1;
934 num += 1;
935 }
936 str += bytes;
937 len -= bytes;
938 }
939 return num;
940}
941
942DEFUN ("find-charset-region", Ffind_charset_region, Sfind_charset_region,
23d2a7f1 943 2, 3, 0,
4ed46869 944 "Return a list of charsets in the region between BEG and END.\n\
23d2a7f1 945BEG and END are buffer positions.\n\
020da460
KH
946If the region contains any composite character,\n\
947`composition' is included in the returned list.\n\
0282eb69
KH
948Optional arg TABLE if non-nil is a translation table to look up.\n\
949\n\
950If the region contains invalid multiybte characters,\n\
38f02ede 951`unknown' is included in the returned list.\n\
0282eb69
KH
952\n\
953If the current buffer is unibyte, the returned list contains\n\
954`ascii' if any 7-bit characters are found,\n\
955and `unknown' if any 8-bit characters are found.")
23d2a7f1
KH
956 (beg, end, table)
957 Lisp_Object beg, end, table;
4ed46869 958{
028d516b 959 int charsets[MAX_CHARSET + 1];
6ae1f27e 960 int from, from_byte, to, stop, stop_byte, i;
4ed46869 961 Lisp_Object val;
0282eb69
KH
962 int undefined;
963 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
4ed46869
KH
964
965 validate_region (&beg, &end);
966 from = XFASTINT (beg);
967 stop = to = XFASTINT (end);
6ae1f27e 968
4ed46869 969 if (from < GPT && GPT < to)
6ae1f27e
RS
970 {
971 stop = GPT;
972 stop_byte = GPT_BYTE;
973 }
974 else
975 stop_byte = CHAR_TO_BYTE (stop);
976
977 from_byte = CHAR_TO_BYTE (from);
978
028d516b 979 bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
4ed46869
KH
980 while (1)
981 {
6ae1f27e 982 find_charset_in_str (BYTE_POS_ADDR (from_byte), stop_byte - from_byte,
0282eb69 983 charsets, table, 1, multibyte);
4ed46869 984 if (stop < to)
6ae1f27e
RS
985 {
986 from = stop, from_byte = stop_byte;
987 stop = to, stop_byte = CHAR_TO_BYTE (stop);
988 }
4ed46869
KH
989 else
990 break;
991 }
6ae1f27e 992
4ed46869 993 val = Qnil;
0282eb69
KH
994 undefined = 0;
995 for (i = (multibyte ? MAX_CHARSET : 1); i >= 0; i--)
4ed46869 996 if (charsets[i])
0282eb69
KH
997 {
998 if (CHARSET_DEFINED_P (i) || i == CHARSET_COMPOSITION)
999 val = Fcons (CHARSET_SYMBOL (i), val);
1000 else
1001 undefined = 1;
1002 }
1003 if (undefined)
1004 val = Fcons (Qunknown, val);
4ed46869
KH
1005 return val;
1006}
1007
1008DEFUN ("find-charset-string", Ffind_charset_string, Sfind_charset_string,
23d2a7f1
KH
1009 1, 2, 0,
1010 "Return a list of charsets in STR.\n\
020da460
KH
1011If the string contains any composite characters,\n\
1012`composition' is included in the returned list.\n\
0282eb69
KH
1013Optional arg TABLE if non-nil is a translation table to look up.\n\
1014\n\
1015If the region contains invalid multiybte characters,\n\
1016`unknown' is included in the returned list.\n\
1017\n\
1018If STR is unibyte, the returned list contains\n\
1019`ascii' if any 7-bit characters are found,\n\
1020and `unknown' if any 8-bit characters are found.")
23d2a7f1
KH
1021 (str, table)
1022 Lisp_Object str, table;
4ed46869 1023{
a29e3b1b 1024 int charsets[MAX_CHARSET + 1];
4ed46869
KH
1025 int i;
1026 Lisp_Object val;
0282eb69
KH
1027 int undefined;
1028 int multibyte;
4ed46869
KH
1029
1030 CHECK_STRING (str, 0);
0282eb69 1031 multibyte = STRING_MULTIBYTE (str);
87b089ad 1032
a29e3b1b 1033 bzero (charsets, (MAX_CHARSET + 1) * sizeof (int));
fc932ac6 1034 find_charset_in_str (XSTRING (str)->data, STRING_BYTES (XSTRING (str)),
0282eb69 1035 charsets, table, 1, multibyte);
4ed46869 1036 val = Qnil;
0282eb69
KH
1037 undefined = 0;
1038 for (i = (multibyte ? MAX_CHARSET : 1); i >= 0; i--)
4ed46869 1039 if (charsets[i])
0282eb69
KH
1040 {
1041 if (CHARSET_DEFINED_P (i) || i == CHARSET_COMPOSITION)
1042 val = Fcons (CHARSET_SYMBOL (i), val);
1043 else
1044 undefined = 1;
1045 }
1046 if (undefined)
1047 val = Fcons (Qunknown, val);
4ed46869
KH
1048 return val;
1049}
1050\f
1051DEFUN ("make-char-internal", Fmake_char_internal, Smake_char_internal, 1, 3, 0,
513ee442 1052 "")
4ed46869
KH
1053 (charset, code1, code2)
1054 Lisp_Object charset, code1, code2;
1055{
ac4137cc
KH
1056 int charset_id, c1, c2;
1057
4ed46869 1058 CHECK_NUMBER (charset, 0);
ac4137cc
KH
1059 charset_id = XINT (charset);
1060 if (!CHARSET_DEFINED_P (charset_id))
1061 error ("Invalid charset ID: %d", XINT (charset));
4ed46869
KH
1062
1063 if (NILP (code1))
ac4137cc 1064 c1 = 0;
4ed46869 1065 else
ac4137cc
KH
1066 {
1067 CHECK_NUMBER (code1, 1);
1068 c1 = XINT (code1);
1069 }
4ed46869 1070 if (NILP (code2))
ac4137cc 1071 c2 = 0;
4ed46869 1072 else
ac4137cc
KH
1073 {
1074 CHECK_NUMBER (code2, 2);
1075 c2 = XINT (code2);
1076 }
4ed46869 1077
ac4137cc
KH
1078 if (c1 < 0 || c1 > 0xFF || c2 < 0 || c2 > 0xFF)
1079 error ("Invalid code points: %d %d", c1, c2);
1080 c1 &= 0x7F;
1081 c2 &= 0x7F;
1082 if (c1 == 0
1083 ? c2 != 0
1084 : (c2 == 0
44c6492d
KH
1085 ? !CHAR_COMPONENTS_VALID_P (charset, c1, 0x20)
1086 : !CHAR_COMPONENTS_VALID_P (charset, c1, c2)))
ac4137cc
KH
1087 error ("Invalid code points: %d %d", c1, c2);
1088
1089 return make_number (MAKE_CHAR (charset_id, c1, c2));
4ed46869
KH
1090}
1091
1092DEFUN ("split-char", Fsplit_char, Ssplit_char, 1, 1, 0,
0282eb69
KH
1093 "Return list of charset and one or two position-codes of CHAR.\n\
1094If CHAR is invalid as a character code,\n\
1095return a list of symbol `unknown' and CHAR.")
4ed46869
KH
1096 (ch)
1097 Lisp_Object ch;
1098{
1099 Lisp_Object val;
0282eb69 1100 int c, charset, c1, c2;
4ed46869
KH
1101
1102 CHECK_NUMBER (ch, 0);
0282eb69
KH
1103 c = XFASTINT (ch);
1104 if (!CHAR_VALID_P (c, 1))
1105 return Fcons (Qunknown, Fcons (ch, Qnil));
4ed46869 1106 SPLIT_CHAR (XFASTINT (ch), charset, c1, c2);
6dc0722d 1107 return (c2 >= 0
4ed46869
KH
1108 ? Fcons (CHARSET_SYMBOL (charset),
1109 Fcons (make_number (c1), Fcons (make_number (c2), Qnil)))
1110 : Fcons (CHARSET_SYMBOL (charset), Fcons (make_number (c1), Qnil)));
1111}
1112
1113DEFUN ("char-charset", Fchar_charset, Schar_charset, 1, 1, 0,
1114 "Return charset of CHAR.")
1115 (ch)
1116 Lisp_Object ch;
1117{
1118 CHECK_NUMBER (ch, 0);
1119
1120 return CHARSET_SYMBOL (CHAR_CHARSET (XINT (ch)));
1121}
1122
90d7b74e 1123DEFUN ("charset-after", Fcharset_after, Scharset_after, 0, 1, 0,
ac4137cc 1124 "Return charset of a character in the current buffer at position POS.\n\
e6e114f2
KH
1125If POS is nil, it defauls to the current point.\n\
1126If POS is out of range, the value is nil.")
90d7b74e
KH
1127 (pos)
1128 Lisp_Object pos;
1129{
ac4137cc 1130 register int pos_byte, bytes, charset, c1, c2;
90d7b74e
KH
1131 register unsigned char *p;
1132
1133 if (NILP (pos))
1134 pos_byte = PT_BYTE;
1135 else if (MARKERP (pos))
e6e114f2
KH
1136 {
1137 pos_byte = marker_byte_position (pos);
1138 if (pos_byte < BEGV_BYTE || pos_byte >= ZV_BYTE)
1139 return Qnil;
1140 }
90d7b74e
KH
1141 else
1142 {
1143 CHECK_NUMBER (pos, 0);
e6e114f2
KH
1144 if (XINT (pos) < BEGV || XINT (pos) >= ZV)
1145 return Qnil;
90d7b74e
KH
1146 pos_byte = CHAR_TO_BYTE (XINT (pos));
1147 }
1148 p = BYTE_POS_ADDR (pos_byte);
ac4137cc
KH
1149 if (BASE_LEADING_CODE_P (*p))
1150 {
1151 SPLIT_MULTIBYTE_SEQ (p, Z_BYTE - pos_byte, bytes, charset, c1, c2);
1152 if (charset < 0)
1153 charset = 1;
1154 }
1155 else
1156 charset = CHARSET_ASCII;
1157
90d7b74e
KH
1158 return CHARSET_SYMBOL (charset);
1159}
1160
4ed46869 1161DEFUN ("iso-charset", Fiso_charset, Siso_charset, 3, 3, 0,
2b71bb78
KH
1162 "Return charset of ISO's specification DIMENSION, CHARS, and FINAL-CHAR.\n\
1163\n\
1164ISO 2022's designation sequence (escape sequence) distinguishes charsets\n\
1165by their DIMENSION, CHARS, and FINAL-CHAR,\n\
1166where as Emacs distinguishes them by charset symbol.\n\
1167See the documentation of the function `charset-info' for the meanings of\n\
1168DIMENSION, CHARS, and FINAL-CHAR.")
4ed46869
KH
1169 (dimension, chars, final_char)
1170 Lisp_Object dimension, chars, final_char;
1171{
1172 int charset;
1173
1174 CHECK_NUMBER (dimension, 0);
1175 CHECK_NUMBER (chars, 1);
1176 CHECK_NUMBER (final_char, 2);
1177
1178 if ((charset = ISO_CHARSET_TABLE (dimension, chars, final_char)) < 0)
1179 return Qnil;
1180 return CHARSET_SYMBOL (charset);
1181}
1182
9d3d8cba
KH
1183/* If GENERICP is nonzero, return nonzero iff C is a valid normal or
1184 generic character. If GENERICP is zero, return nonzero iff C is a
1185 valid normal character. Do not call this function directly,
1186 instead use macro CHAR_VALID_P. */
1187int
1188char_valid_p (c, genericp)
1189 int c, genericp;
1190{
1191 int charset, c1, c2;
1192
1193 if (c < 0)
1194 return 0;
1195 if (SINGLE_BYTE_CHAR_P (c))
1196 return 1;
1197 SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
ac4137cc
KH
1198 if (charset == CHARSET_COMPOSITION)
1199 return ((c >= MIN_CHAR_COMPOSITION
1200 && c < MIN_CHAR_COMPOSITION + n_cmpchars)
1201 || (genericp && c == GENERIC_COMPOSITION_CHAR));
1202 if (genericp)
1203 {
1204 if (c1)
1205 {
1206 if (c2 <= 0) c2 = 0x20;
1207 }
1208 else
1209 {
1210 if (c2 <= 0) c1 = c2 = 0x20;
1211 }
1212 }
1213 return (CHARSET_DEFINED_P (charset)
44c6492d 1214 && CHAR_COMPONENTS_VALID_P (charset, c1, c2));
9d3d8cba
KH
1215}
1216
1217DEFUN ("char-valid-p", Fchar_valid_p, Schar_valid_p, 1, 2, 0,
a9d02884
DL
1218 "Return t if OBJECT is a valid normal character.\n\
1219If optional arg GENERICP is non-nil, also return t if OBJECT is\n\
9d3d8cba
KH
1220a valid generic character.")
1221 (object, genericp)
1222 Lisp_Object object, genericp;
1223{
1224 if (! NATNUMP (object))
1225 return Qnil;
1226 return (CHAR_VALID_P (XFASTINT (object), !NILP (genericp)) ? Qt : Qnil);
1227}
1228
d2665018
KH
1229DEFUN ("unibyte-char-to-multibyte", Funibyte_char_to_multibyte,
1230 Sunibyte_char_to_multibyte, 1, 1, 0,
1231 "Convert the unibyte character CH to multibyte character.\n\
537efd8d 1232The conversion is done based on `nonascii-translation-table' (which see)\n\
340b8d58 1233 or `nonascii-insert-offset' (which see).")
d2665018
KH
1234 (ch)
1235 Lisp_Object ch;
1236{
1237 int c;
1238
1239 CHECK_NUMBER (ch, 0);
1240 c = XINT (ch);
1241 if (c < 0 || c >= 0400)
1242 error ("Invalid unibyte character: %d", c);
1243 c = unibyte_char_to_multibyte (c);
1244 if (c < 0)
1245 error ("Can't convert to multibyte character: %d", XINT (ch));
1246 return make_number (c);
1247}
1248
1bcc1567
RS
1249DEFUN ("multibyte-char-to-unibyte", Fmultibyte_char_to_unibyte,
1250 Smultibyte_char_to_unibyte, 1, 1, 0,
1251 "Convert the multibyte character CH to unibyte character.\n\
1252The conversion is done based on `nonascii-translation-table' (which see)\n\
1253 or `nonascii-insert-offset' (which see).")
1254 (ch)
1255 Lisp_Object ch;
1256{
1257 int c;
1258
1259 CHECK_NUMBER (ch, 0);
1260 c = XINT (ch);
ac4137cc 1261 if (! CHAR_VALID_P (c, 0))
1bcc1567
RS
1262 error ("Invalid multibyte character: %d", c);
1263 c = multibyte_char_to_unibyte (c, Qnil);
1264 if (c < 0)
1265 error ("Can't convert to unibyte character: %d", XINT (ch));
1266 return make_number (c);
1267}
1268
4ed46869 1269DEFUN ("char-bytes", Fchar_bytes, Schar_bytes, 1, 1, 0,
f78643ef 1270 "Return 1 regardless of the argument CHAR.\n\
60022cb7 1271This is now an obsolete function. We keep it just for backward compatibility.")
4ed46869
KH
1272 (ch)
1273 Lisp_Object ch;
1274{
1275 Lisp_Object val;
4ed46869
KH
1276
1277 CHECK_NUMBER (ch, 0);
9b6a601f
KH
1278 return make_number (1);
1279}
1280
1281/* Return how many bytes C will occupy in a multibyte buffer.
1282 Don't call this function directly, instead use macro CHAR_BYTES. */
1283int
1284char_bytes (c)
1285 int c;
1286{
1287 int bytes;
1288
8ac5a9cc
KH
1289 if (SINGLE_BYTE_CHAR_P (c) || (c & ~GLYPH_MASK_CHAR))
1290 return 1;
1291
9b6a601f 1292 if (COMPOSITE_CHAR_P (c))
4ed46869 1293 {
9b6a601f 1294 unsigned int id = COMPOSITE_CHAR_ID (c);
4ed46869
KH
1295
1296 bytes = (id < n_cmpchars ? cmpchar_table[id]->len : 1);
1297 }
1298 else
1299 {
9b6a601f 1300 int charset = CHAR_CHARSET (c);
4ed46869
KH
1301
1302 bytes = CHARSET_DEFINED_P (charset) ? CHARSET_BYTES (charset) : 1;
1303 }
1304
60022cb7 1305 return bytes;
4ed46869
KH
1306}
1307
1308/* Return the width of character of which multi-byte form starts with
1309 C. The width is measured by how many columns occupied on the
1310 screen when displayed in the current buffer. */
1311
1312#define ONE_BYTE_CHAR_WIDTH(c) \
1313 (c < 0x20 \
1314 ? (c == '\t' \
53316e55 1315 ? XFASTINT (current_buffer->tab_width) \
4ed46869
KH
1316 : (c == '\n' ? 0 : (NILP (current_buffer->ctl_arrow) ? 4 : 2))) \
1317 : (c < 0x7f \
1318 ? 1 \
1319 : (c == 0x7F \
1320 ? (NILP (current_buffer->ctl_arrow) ? 4 : 2) \
1321 : ((! NILP (current_buffer->enable_multibyte_characters) \
1322 && BASE_LEADING_CODE_P (c)) \
1323 ? WIDTH_BY_CHAR_HEAD (c) \
b4e9dd77 1324 : 4))))
4ed46869
KH
1325
1326DEFUN ("char-width", Fchar_width, Schar_width, 1, 1, 0,
1327 "Return width of CHAR when displayed in the current buffer.\n\
1328The width is measured by how many columns it occupies on the screen.")
1329 (ch)
1330 Lisp_Object ch;
1331{
859f2b3c 1332 Lisp_Object val, disp;
4ed46869 1333 int c;
51c4025f 1334 struct Lisp_Char_Table *dp = buffer_display_table ();
4ed46869
KH
1335
1336 CHECK_NUMBER (ch, 0);
1337
859f2b3c
RS
1338 c = XINT (ch);
1339
1340 /* Get the way the display table would display it. */
51c4025f 1341 disp = dp ? DISP_CHAR_VECTOR (dp, c) : Qnil;
859f2b3c
RS
1342
1343 if (VECTORP (disp))
1344 XSETINT (val, XVECTOR (disp)->size);
1345 else if (SINGLE_BYTE_CHAR_P (c))
1346 XSETINT (val, ONE_BYTE_CHAR_WIDTH (c));
4ed46869
KH
1347 else if (COMPOSITE_CHAR_P (c))
1348 {
1349 int id = COMPOSITE_CHAR_ID (XFASTINT (ch));
0282eb69 1350 XSETFASTINT (val, (id < n_cmpchars ? cmpchar_table[id]->width : 1));
4ed46869
KH
1351 }
1352 else
1353 {
1354 int charset = CHAR_CHARSET (c);
1355
1356 XSETFASTINT (val, CHARSET_WIDTH (charset));
1357 }
1358 return val;
1359}
1360
1361/* Return width of string STR of length LEN when displayed in the
1362 current buffer. The width is measured by how many columns it
1363 occupies on the screen. */
859f2b3c 1364
4ed46869
KH
1365int
1366strwidth (str, len)
1367 unsigned char *str;
1368 int len;
1369{
1370 unsigned char *endp = str + len;
1371 int width = 0;
c4a4e28f 1372 struct Lisp_Char_Table *dp = buffer_display_table ();
4ed46869 1373
859f2b3c
RS
1374 while (str < endp)
1375 {
1376 if (*str == LEADING_CODE_COMPOSITION)
1377 {
1378 int id = str_cmpchar_id (str, endp - str);
1379
1380 if (id < 0)
1381 {
1382 width += 4;
1383 str++;
1384 }
1385 else
1386 {
1387 width += cmpchar_table[id]->width;
1388 str += cmpchar_table[id]->len;
1389 }
1390 }
1391 else
1392 {
1393 Lisp_Object disp;
e515b0a9
KH
1394 int thislen;
1395 int c = STRING_CHAR_AND_LENGTH (str, endp - str, thislen);
859f2b3c
RS
1396
1397 /* Get the way the display table would display it. */
acc35c36
RS
1398 if (dp)
1399 disp = DISP_CHAR_VECTOR (dp, c);
1400 else
1401 disp = Qnil;
859f2b3c
RS
1402
1403 if (VECTORP (disp))
e515b0a9 1404 width += XVECTOR (disp)->size;
859f2b3c 1405 else
e515b0a9 1406 width += ONE_BYTE_CHAR_WIDTH (*str);
859f2b3c 1407
e515b0a9 1408 str += thislen;
859f2b3c
RS
1409 }
1410 }
4ed46869
KH
1411 return width;
1412}
1413
1414DEFUN ("string-width", Fstring_width, Sstring_width, 1, 1, 0,
1415 "Return width of STRING when displayed in the current buffer.\n\
1416Width is measured by how many columns it occupies on the screen.\n\
046b1f03
RS
1417When calculating width of a multibyte character in STRING,\n\
1418only the base leading-code is considered; the validity of\n\
1419the following bytes is not checked.")
4ed46869
KH
1420 (str)
1421 Lisp_Object str;
1422{
1423 Lisp_Object val;
1424
1425 CHECK_STRING (str, 0);
fc932ac6
RS
1426 XSETFASTINT (val, strwidth (XSTRING (str)->data,
1427 STRING_BYTES (XSTRING (str))));
4ed46869
KH
1428 return val;
1429}
1430
1431DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0,
1432 "Return the direction of CHAR.\n\
1433The returned value is 0 for left-to-right and 1 for right-to-left.")
1434 (ch)
1435 Lisp_Object ch;
1436{
1437 int charset;
1438
1439 CHECK_NUMBER (ch, 0);
1440 charset = CHAR_CHARSET (XFASTINT (ch));
1441 if (!CHARSET_DEFINED_P (charset))
93bcb785 1442 invalid_character (XINT (ch));
4ed46869
KH
1443 return CHARSET_TABLE_INFO (charset, CHARSET_DIRECTION_IDX);
1444}
1445
af4fecb4 1446DEFUN ("chars-in-region", Fchars_in_region, Schars_in_region, 2, 2, 0,
6ae1f27e 1447 "Return number of characters between BEG and END.")
046b1f03
RS
1448 (beg, end)
1449 Lisp_Object beg, end;
1450{
6ae1f27e 1451 int from, to;
046b1f03 1452
17e7ef1b
RS
1453 CHECK_NUMBER_COERCE_MARKER (beg, 0);
1454 CHECK_NUMBER_COERCE_MARKER (end, 1);
1455
046b1f03 1456 from = min (XFASTINT (beg), XFASTINT (end));
a8a35e61 1457 to = max (XFASTINT (beg), XFASTINT (end));
046b1f03 1458
a8c21066 1459 return make_number (to - from);
6ae1f27e 1460}
9036eb45 1461
87b089ad
RS
1462/* Return the number of characters in the NBYTES bytes at PTR.
1463 This works by looking at the contents and checking for multibyte sequences.
1464 However, if the current buffer has enable-multibyte-characters = nil,
1465 we treat each byte as a character. */
1466
6ae1f27e
RS
1467int
1468chars_in_text (ptr, nbytes)
1469 unsigned char *ptr;
1470 int nbytes;
1471{
87b089ad
RS
1472 /* current_buffer is null at early stages of Emacs initialization. */
1473 if (current_buffer == 0
1474 || NILP (current_buffer->enable_multibyte_characters))
6ae1f27e 1475 return nbytes;
a8a35e61 1476
ac4137cc 1477 return multibyte_chars_in_text (ptr, nbytes);
046b1f03
RS
1478}
1479
87b089ad
RS
1480/* Return the number of characters in the NBYTES bytes at PTR.
1481 This works by looking at the contents and checking for multibyte sequences.
1482 It ignores enable-multibyte-characters. */
1483
1484int
1485multibyte_chars_in_text (ptr, nbytes)
1486 unsigned char *ptr;
1487 int nbytes;
1488{
ac4137cc
KH
1489 unsigned char *endp;
1490 int chars, bytes;
87b089ad
RS
1491
1492 endp = ptr + nbytes;
1493 chars = 0;
1494
1495 while (ptr < endp)
1496 {
ac4137cc
KH
1497 if (BASE_LEADING_CODE_P (*ptr))
1498 {
1499 PARSE_MULTIBYTE_SEQ (ptr, nbytes, bytes);
1500 ptr += bytes;
1501 nbytes -= bytes;
1502 }
1503 else
1504 {
1505 ptr++;
1506 nbytes--;
1507 }
87b089ad
RS
1508 chars++;
1509 }
1510
1511 return chars;
1512}
1513
1514DEFUN ("string", Fstring, Sstring, 1, MANY, 0,
4ed46869 1515 "Concatenate all the argument characters and make the result a string.")
53316e55
KH
1516 (n, args)
1517 int n;
4ed46869
KH
1518 Lisp_Object *args;
1519{
53316e55 1520 int i;
4ed46869 1521 unsigned char *buf
bd4c6dd0 1522 = (unsigned char *) alloca (MAX_LENGTH_OF_MULTI_BYTE_FORM * n);
4ed46869
KH
1523 unsigned char *p = buf;
1524 Lisp_Object val;
1525
1526 for (i = 0; i < n; i++)
1527 {
1528 int c, len;
1529 unsigned char *str;
1530
1531 if (!INTEGERP (args[i]))
b0e3cf2b 1532 CHECK_NUMBER (args[i], 0);
4ed46869
KH
1533 c = XINT (args[i]);
1534 len = CHAR_STRING (c, p, str);
1535 if (p != str)
1536 /* C is a composite character. */
1537 bcopy (str, p, len);
1538 p += len;
1539 }
1540
020da460
KH
1541 /* Here, we can't use make_string_from_bytes because of byte
1542 combining problem. */
1543 val = make_string (buf, p - buf);
4ed46869
KH
1544 return val;
1545}
1546
1547#endif /* emacs */
1548\f
1549/*** Composite characters staffs ***/
1550
1551/* Each composite character is identified by CMPCHAR-ID which is
1552 assigned when Emacs needs the character code of the composite
1553 character (e.g. when displaying it on the screen). See the
1554 document "GENERAL NOTE on COMPOSITE CHARACTER" in `charset.h' how a
1555 composite character is represented in Emacs. */
1556
1557/* If `static' is defined, it means that it is defined to null string. */
1558#ifndef static
1559/* The following function is copied from lread.c. */
1560static int
1561hash_string (ptr, len)
1562 unsigned char *ptr;
1563 int len;
1564{
1565 register unsigned char *p = ptr;
1566 register unsigned char *end = p + len;
1567 register unsigned char c;
1568 register int hash = 0;
1569
1570 while (p != end)
1571 {
1572 c = *p++;
1573 if (c >= 0140) c -= 40;
1574 hash = ((hash<<3) + (hash>>28) + c);
1575 }
1576 return hash & 07777777777;
1577}
1578#endif
1579
4ed46869
KH
1580#define CMPCHAR_HASH_TABLE_SIZE 0xFFF
1581
1582static int *cmpchar_hash_table[CMPCHAR_HASH_TABLE_SIZE];
1583
1584/* Each element of `cmpchar_hash_table' is a pointer to an array of
1585 integer, where the 1st element is the size of the array, the 2nd
1586 element is how many elements are actually used in the array, and
1587 the remaining elements are CMPCHAR-IDs of composite characters of
1588 the same hash value. */
1589#define CMPCHAR_HASH_SIZE(table) table[0]
1590#define CMPCHAR_HASH_USED(table) table[1]
1591#define CMPCHAR_HASH_CMPCHAR_ID(table, i) table[i]
1592
1593/* Return CMPCHAR-ID of the composite character in STR of the length
1594 LEN. If the composite character has not yet been registered,
1595 register it in `cmpchar_table' and assign new CMPCHAR-ID. This
1596 is the sole function for assigning CMPCHAR-ID. */
1597int
1598str_cmpchar_id (str, len)
8867de67 1599 const unsigned char *str;
4ed46869
KH
1600 int len;
1601{
1602 int hash_idx, *hashp;
1603 unsigned char *buf;
1604 int embedded_rule; /* 1 if composition rule is embedded. */
1605 int chars; /* number of components. */
1606 int i;
1607 struct cmpchar_info *cmpcharp;
1608
ac4137cc 1609 /* The second byte 0xFF means COMPOSITION rule is embedded. */
4ed46869
KH
1610 embedded_rule = (str[1] == 0xFF);
1611
1612 /* At first, get the actual length of the composite character. */
1613 {
8867de67 1614 const unsigned char *p, *endp = str + 1, *lastp = str + len;
4ed46869
KH
1615 int bytes;
1616
6ae1f27e 1617 while (endp < lastp && ! CHAR_HEAD_P (*endp)) endp++;
93bcb785
KH
1618 if (endp - str < 5)
1619 /* Any composite char have at least 5-byte length. */
1620 return -1;
1621
4ed46869 1622 chars = 0;
93bcb785 1623 p = str + 1;
4ed46869
KH
1624 while (p < endp)
1625 {
9b4d1fe6
KH
1626 if (embedded_rule)
1627 {
1628 p++;
1629 if (p >= endp)
1630 return -1;
1631 }
4ed46869 1632 /* No need of checking if *P is 0xA0 because
93bcb785
KH
1633 BYTES_BY_CHAR_HEAD (0x80) surely returns 2. */
1634 p += BYTES_BY_CHAR_HEAD (*p - 0x20);
4ed46869
KH
1635 chars++;
1636 }
93bcb785
KH
1637 if (p > endp || chars < 2 || chars > MAX_COMPONENT_COUNT)
1638 /* Invalid components. */
4ed46869 1639 return -1;
93bcb785 1640 len = p - str;
4ed46869
KH
1641 }
1642 hash_idx = hash_string (str, len) % CMPCHAR_HASH_TABLE_SIZE;
1643 hashp = cmpchar_hash_table[hash_idx];
1644
1645 /* Then, look into the hash table. */
1646 if (hashp != NULL)
1647 /* Find the correct one among composite characters of the same
1648 hash value. */
1649 for (i = 2; i < CMPCHAR_HASH_USED (hashp); i++)
1650 {
1651 cmpcharp = cmpchar_table[CMPCHAR_HASH_CMPCHAR_ID (hashp, i)];
1652 if (len == cmpcharp->len
1653 && ! bcmp (str, cmpcharp->data, len))
1654 return CMPCHAR_HASH_CMPCHAR_ID (hashp, i);
1655 }
1656
1657 /* We have to register the composite character in cmpchar_table. */
0282eb69 1658 if (n_cmpchars >= (CHAR_FIELD2_MASK | CHAR_FIELD3_MASK))
513ee442
KH
1659 /* No, we have no more room for a new composite character. */
1660 return -1;
1661
4ed46869
KH
1662 /* Make the entry in hash table. */
1663 if (hashp == NULL)
1664 {
1665 /* Make a table for 8 composite characters initially. */
1666 hashp = (cmpchar_hash_table[hash_idx]
1667 = (int *) xmalloc (sizeof (int) * (2 + 8)));
1668 CMPCHAR_HASH_SIZE (hashp) = 10;
1669 CMPCHAR_HASH_USED (hashp) = 2;
1670 }
1671 else if (CMPCHAR_HASH_USED (hashp) >= CMPCHAR_HASH_SIZE (hashp))
1672 {
1673 CMPCHAR_HASH_SIZE (hashp) += 8;
1674 hashp = (cmpchar_hash_table[hash_idx]
1675 = (int *) xrealloc (hashp,
1676 sizeof (int) * CMPCHAR_HASH_SIZE (hashp)));
1677 }
1678 CMPCHAR_HASH_CMPCHAR_ID (hashp, CMPCHAR_HASH_USED (hashp)) = n_cmpchars;
1679 CMPCHAR_HASH_USED (hashp)++;
1680
1681 /* Set information of the composite character in cmpchar_table. */
1682 if (cmpchar_table_size == 0)
1683 {
1684 /* This is the first composite character to be registered. */
1685 cmpchar_table_size = 256;
1686 cmpchar_table
1687 = (struct cmpchar_info **) xmalloc (sizeof (cmpchar_table[0])
1688 * cmpchar_table_size);
1689 }
1690 else if (cmpchar_table_size <= n_cmpchars)
1691 {
1692 cmpchar_table_size += 256;
1693 cmpchar_table
1694 = (struct cmpchar_info **) xrealloc (cmpchar_table,
1695 sizeof (cmpchar_table[0])
1696 * cmpchar_table_size);
1697 }
1698
1699 cmpcharp = (struct cmpchar_info *) xmalloc (sizeof (struct cmpchar_info));
1700
1701 cmpcharp->len = len;
1702 cmpcharp->data = (unsigned char *) xmalloc (len + 1);
1703 bcopy (str, cmpcharp->data, len);
1704 cmpcharp->data[len] = 0;
1705 cmpcharp->glyph_len = chars;
1706 cmpcharp->glyph = (GLYPH *) xmalloc (sizeof (GLYPH) * chars);
1707 if (embedded_rule)
1708 {
1709 cmpcharp->cmp_rule = (unsigned char *) xmalloc (chars);
1710 cmpcharp->col_offset = (float *) xmalloc (sizeof (float) * chars);
1711 }
1712 else
1713 {
1714 cmpcharp->cmp_rule = NULL;
1715 cmpcharp->col_offset = NULL;
1716 }
1717
1718 /* Setup GLYPH data and composition rules (if any) so as not to make
1719 them every time on displaying. */
1720 {
1721 unsigned char *bufp;
1722 int width;
1723 float leftmost = 0.0, rightmost = 1.0;
1724
1725 if (embedded_rule)
1726 /* At first, col_offset[N] is set to relative to col_offset[0]. */
1727 cmpcharp->col_offset[0] = 0;
1728
1729 for (i = 0, bufp = cmpcharp->data + 1; i < chars; i++)
1730 {
1731 if (embedded_rule)
1732 cmpcharp->cmp_rule[i] = *bufp++;
1733
1734 if (*bufp == 0xA0) /* This is an ASCII character. */
1735 {
1736 cmpcharp->glyph[i] = FAST_MAKE_GLYPH ((*++bufp & 0x7F), 0);
1737 width = 1;
1738 bufp++;
1739 }
1740 else /* Multibyte character. */
1741 {
1742 /* Make `bufp' point normal multi-byte form temporally. */
1743 *bufp -= 0x20;
1744 cmpcharp->glyph[i]
ac4137cc 1745 = FAST_MAKE_GLYPH (string_to_non_ascii_char (bufp, 4, 0), 0);
4ed46869
KH
1746 width = WIDTH_BY_CHAR_HEAD (*bufp);
1747 *bufp += 0x20;
1748 bufp += BYTES_BY_CHAR_HEAD (*bufp - 0x20);
1749 }
1750
1751 if (embedded_rule && i > 0)
1752 {
1753 /* Reference points (global_ref and new_ref) are
1754 encoded as below:
1755
1756 0--1--2 -- ascent
1757 | |
1758 | |
1759 | 4 -+--- center
1760 -- 3 5 -- baseline
1761 | |
1762 6--7--8 -- descent
1763
1764 Now, we calculate the column offset of the new glyph
1765 from the left edge of the first glyph. This can avoid
1766 the same calculation everytime displaying this
1767 composite character. */
1768
1769 /* Reference points of global glyph and new glyph. */
1770 int global_ref = (cmpcharp->cmp_rule[i] - 0xA0) / 9;
1771 int new_ref = (cmpcharp->cmp_rule[i] - 0xA0) % 9;
1772 /* Column offset relative to the first glyph. */
1773 float left = (leftmost
1774 + (global_ref % 3) * (rightmost - leftmost) / 2.0
1775 - (new_ref % 3) * width / 2.0);
1776
1777 cmpcharp->col_offset[i] = left;
1778 if (left < leftmost)
1779 leftmost = left;
1780 if (left + width > rightmost)
1781 rightmost = left + width;
1782 }
1783 else
1784 {
1785 if (width > rightmost)
1786 rightmost = width;
1787 }
1788 }
1789 if (embedded_rule)
1790 {
1791 /* Now col_offset[N] are relative to the left edge of the
1792 first component. Make them relative to the left edge of
1793 overall glyph. */
1794 for (i = 0; i < chars; i++)
1795 cmpcharp->col_offset[i] -= leftmost;
1796 /* Make rightmost holds width of overall glyph. */
1797 rightmost -= leftmost;
1798 }
1799
1800 cmpcharp->width = rightmost;
1801 if (cmpcharp->width < rightmost)
1802 /* To get a ceiling integer value. */
1803 cmpcharp->width++;
1804 }
1805
1806 cmpchar_table[n_cmpchars] = cmpcharp;
1807
1808 return n_cmpchars++;
1809}
1810
de54b0d5
KH
1811/* Return the Nth element of the composite character C. If NOERROR is
1812 nonzero, return 0 on error condition (C is an invalid composite
1813 charcter, or N is out of range). */
4ed46869 1814int
de54b0d5
KH
1815cmpchar_component (c, n, noerror)
1816 int c, n, noerror;
4ed46869
KH
1817{
1818 int id = COMPOSITE_CHAR_ID (c);
1819
de54b0d5
KH
1820 if (id < 0 || id >= n_cmpchars)
1821 {
1822 /* C is not a valid composite character. */
1823 if (noerror) return 0;
1824 error ("Invalid composite character: %d", c) ;
1825 }
1826 if (n >= cmpchar_table[id]->glyph_len)
1827 {
1828 /* No such component. */
1829 if (noerror) return 0;
1830 args_out_of_range (make_number (c), make_number (n));
1831 }
4ed46869
KH
1832 /* No face data is stored in glyph code. */
1833 return ((int) (cmpchar_table[id]->glyph[n]));
1834}
1835
1836DEFUN ("cmpcharp", Fcmpcharp, Scmpcharp, 1, 1, 0,
1837 "T if CHAR is a composite character.")
1838 (ch)
1839 Lisp_Object ch;
1840{
1841 CHECK_NUMBER (ch, 0);
1842 return (COMPOSITE_CHAR_P (XINT (ch)) ? Qt : Qnil);
1843}
1844
1845DEFUN ("composite-char-component", Fcmpchar_component, Scmpchar_component,
1846 2, 2, 0,
de54b0d5
KH
1847 "Return the Nth component character of composite character CHARACTER.")
1848 (character, n)
1849 Lisp_Object character, n;
4ed46869 1850{
de54b0d5 1851 int id;
4ed46869
KH
1852
1853 CHECK_NUMBER (character, 0);
de54b0d5 1854 CHECK_NUMBER (n, 1);
4ed46869 1855
de54b0d5 1856 return (make_number (cmpchar_component (XINT (character), XINT (n), 0)));
4ed46869
KH
1857}
1858
1859DEFUN ("composite-char-composition-rule", Fcmpchar_cmp_rule, Scmpchar_cmp_rule,
1860 2, 2, 0,
de54b0d5 1861 "Return the Nth composition rule of composite character CHARACTER.\n\
55001746 1862The returned rule is for composing the Nth component\n\
de54b0d5
KH
1863on the (N-1)th component.\n\
1864If CHARACTER should be composed relatively or N is 0, return 255.")
55001746
KH
1865 (character, n)
1866 Lisp_Object character, n;
4ed46869 1867{
de54b0d5 1868 int id;
4ed46869
KH
1869
1870 CHECK_NUMBER (character, 0);
55001746 1871 CHECK_NUMBER (n, 1);
4ed46869
KH
1872
1873 id = COMPOSITE_CHAR_ID (XINT (character));
1874 if (id < 0 || id >= n_cmpchars)
1875 error ("Invalid composite character: %d", XINT (character));
de54b0d5 1876 if (XINT (n) < 0 || XINT (n) >= cmpchar_table[id]->glyph_len)
55001746 1877 args_out_of_range (character, n);
4ed46869 1878
de54b0d5
KH
1879 return make_number (cmpchar_table[id]->cmp_rule
1880 ? cmpchar_table[id]->cmp_rule[XINT (n)]
1881 : 255);
4ed46869
KH
1882}
1883
1884DEFUN ("composite-char-composition-rule-p", Fcmpchar_cmp_rule_p,
1885 Scmpchar_cmp_rule_p, 1, 1, 0,
1886 "Return non-nil if composite character CHARACTER contains a embedded rule.")
1887 (character)
1888 Lisp_Object character;
1889{
1890 int id;
1891
1892 CHECK_NUMBER (character, 0);
1893 id = COMPOSITE_CHAR_ID (XINT (character));
1894 if (id < 0 || id >= n_cmpchars)
1895 error ("Invalid composite character: %d", XINT (character));
1896
1897 return (cmpchar_table[id]->cmp_rule ? Qt : Qnil);
1898}
1899
1900DEFUN ("composite-char-component-count", Fcmpchar_cmp_count,
1901 Scmpchar_cmp_count, 1, 1, 0,
1902 "Return number of compoents of composite character CHARACTER.")
1903 (character)
1904 Lisp_Object character;
1905{
1906 int id;
1907
1908 CHECK_NUMBER (character, 0);
1909 id = COMPOSITE_CHAR_ID (XINT (character));
1910 if (id < 0 || id >= n_cmpchars)
1911 error ("Invalid composite character: %d", XINT (character));
1912
1913 return (make_number (cmpchar_table[id]->glyph_len));
1914}
1915
1916DEFUN ("compose-string", Fcompose_string, Scompose_string,
1917 1, 1, 0,
1918 "Return one char string composed from all characters in STRING.")
1919 (str)
1920 Lisp_Object str;
1921{
1922 unsigned char buf[MAX_LENGTH_OF_MULTI_BYTE_FORM], *p, *pend, *ptemp;
1923 int len, i;
1924
1925 CHECK_STRING (str, 0);
1926
1927 buf[0] = LEADING_CODE_COMPOSITION;
1928 p = XSTRING (str)->data;
fc932ac6 1929 pend = p + STRING_BYTES (XSTRING (str));
4ed46869
KH
1930 i = 1;
1931 while (p < pend)
1932 {
9b4d1fe6 1933 if (*p < 0x20) /* control code */
4ed46869
KH
1934 error ("Invalid component character: %d", *p);
1935 else if (*p < 0x80) /* ASCII */
1936 {
1937 if (i + 2 >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
1938 error ("Too long string to be composed: %s", XSTRING (str)->data);
1939 /* Prepend an ASCII charset indicator 0xA0, set MSB of the
1940 code itself. */
1941 buf[i++] = 0xA0;
1942 buf[i++] = *p++ + 0x80;
1943 }
1944 else if (*p == LEADING_CODE_COMPOSITION) /* composite char */
1945 {
1946 /* Already composed. Eliminate the heading
1947 LEADING_CODE_COMPOSITION, keep the remaining bytes
1948 unchanged. */
1949 p++;
de54b0d5
KH
1950 if (*p == 255)
1951 error ("Can't compose a rule-based composition character");
4ed46869 1952 ptemp = p;
6ae1f27e 1953 while (! CHAR_HEAD_P (*p)) p++;
9b4d1fe6
KH
1954 if (str_cmpchar_id (ptemp - 1, p - ptemp + 1) < 0)
1955 error ("Can't compose an invalid composition character");
4ed46869
KH
1956 if (i + (p - ptemp) >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
1957 error ("Too long string to be composed: %s", XSTRING (str)->data);
1958 bcopy (ptemp, buf + i, p - ptemp);
1959 i += p - ptemp;
1960 }
1961 else /* multibyte char */
1962 {
1963 /* Add 0x20 to the base leading-code, keep the remaining
1964 bytes unchanged. */
ac4137cc 1965 int c = STRING_CHAR_AND_LENGTH (p, pend - p, len);
9b4d1fe6
KH
1966
1967 if (len <= 1 || ! CHAR_VALID_P (c, 0))
1968 error ("Can't compose an invalid character");
4ed46869
KH
1969 if (i + len >= MAX_LENGTH_OF_MULTI_BYTE_FORM)
1970 error ("Too long string to be composed: %s", XSTRING (str)->data);
1971 bcopy (p, buf + i, len);
1972 buf[i] += 0x20;
1973 p += len, i += len;
1974 }
1975 }
1976
1977 if (i < 5)
1978 /* STR contains only one character, which can't be composed. */
1979 error ("Too short string to be composed: %s", XSTRING (str)->data);
1980
27802600 1981 return make_string_from_bytes (buf, 1, i);
4ed46869
KH
1982}
1983
1984\f
dfcf069d 1985int
4ed46869
KH
1986charset_id_internal (charset_name)
1987 char *charset_name;
1988{
76d7b829 1989 Lisp_Object val;
4ed46869 1990
76d7b829 1991 val= Fget (intern (charset_name), Qcharset);
4ed46869
KH
1992 if (!VECTORP (val))
1993 error ("Charset %s is not defined", charset_name);
1994
1995 return (XINT (XVECTOR (val)->contents[0]));
1996}
1997
1998DEFUN ("setup-special-charsets", Fsetup_special_charsets,
1999 Ssetup_special_charsets, 0, 0, 0, "Internal use only.")
2000 ()
2001{
2002 charset_latin_iso8859_1 = charset_id_internal ("latin-iso8859-1");
2003 charset_jisx0208_1978 = charset_id_internal ("japanese-jisx0208-1978");
2004 charset_jisx0208 = charset_id_internal ("japanese-jisx0208");
2005 charset_katakana_jisx0201 = charset_id_internal ("katakana-jisx0201");
2006 charset_latin_jisx0201 = charset_id_internal ("latin-jisx0201");
2007 charset_big5_1 = charset_id_internal ("chinese-big5-1");
2008 charset_big5_2 = charset_id_internal ("chinese-big5-2");
2009 return Qnil;
2010}
2011
dfcf069d 2012void
4ed46869
KH
2013init_charset_once ()
2014{
2015 int i, j, k;
2016
2017 staticpro (&Vcharset_table);
2018 staticpro (&Vcharset_symbol_table);
8a73a704 2019 staticpro (&Vgeneric_character_list);
4ed46869
KH
2020
2021 /* This has to be done here, before we call Fmake_char_table. */
2022 Qcharset_table = intern ("charset-table");
2023 staticpro (&Qcharset_table);
2024
2025 /* Intern this now in case it isn't already done.
2026 Setting this variable twice is harmless.
2027 But don't staticpro it here--that is done in alloc.c. */
2028 Qchar_table_extra_slots = intern ("char-table-extra-slots");
2029
2030 /* Now we are ready to set up this property, so we can
2031 create the charset table. */
2032 Fput (Qcharset_table, Qchar_table_extra_slots, make_number (0));
2033 Vcharset_table = Fmake_char_table (Qcharset_table, Qnil);
2034
0282eb69
KH
2035 Qunknown = intern ("unknown");
2036 staticpro (&Qunknown);
2037 Vcharset_symbol_table = Fmake_vector (make_number (MAX_CHARSET + 1),
2038 Qunknown);
4ed46869
KH
2039
2040 /* Setup tables. */
2041 for (i = 0; i < 2; i++)
2042 for (j = 0; j < 2; j++)
2043 for (k = 0; k < 128; k++)
2044 iso_charset_table [i][j][k] = -1;
2045
2046 bzero (cmpchar_hash_table, sizeof cmpchar_hash_table);
2047 cmpchar_table_size = n_cmpchars = 0;
2048
60383934 2049 for (i = 0; i < 256; i++)
4ed46869 2050 BYTES_BY_CHAR_HEAD (i) = 1;
6ef23ebb
KH
2051 for (i = MIN_CHARSET_OFFICIAL_DIMENSION1;
2052 i <= MAX_CHARSET_OFFICIAL_DIMENSION1; i++)
2053 BYTES_BY_CHAR_HEAD (i) = 2;
2054 for (i = MIN_CHARSET_OFFICIAL_DIMENSION2;
2055 i <= MAX_CHARSET_OFFICIAL_DIMENSION2; i++)
2056 BYTES_BY_CHAR_HEAD (i) = 3;
4ed46869
KH
2057 BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_11) = 3;
2058 BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_12) = 3;
2059 BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_21) = 4;
2060 BYTES_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_22) = 4;
6ef23ebb 2061 /* The followings don't reflect the actual bytes, but just to tell
4ed46869
KH
2062 that it is a start of a multibyte character. */
2063 BYTES_BY_CHAR_HEAD (LEADING_CODE_COMPOSITION) = 2;
6ef23ebb
KH
2064 BYTES_BY_CHAR_HEAD (0x9E) = 2;
2065 BYTES_BY_CHAR_HEAD (0x9F) = 2;
4ed46869
KH
2066
2067 for (i = 0; i < 128; i++)
2068 WIDTH_BY_CHAR_HEAD (i) = 1;
2069 for (; i < 256; i++)
2070 WIDTH_BY_CHAR_HEAD (i) = 4;
2071 WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_11) = 1;
2072 WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_12) = 2;
2073 WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_21) = 1;
2074 WIDTH_BY_CHAR_HEAD (LEADING_CODE_PRIVATE_22) = 2;
8a73a704
KH
2075
2076 {
76d7b829 2077 Lisp_Object val;
8a73a704 2078
76d7b829 2079 val = Qnil;
8a73a704
KH
2080 for (i = 0x81; i < 0x90; i++)
2081 val = Fcons (make_number ((i - 0x70) << 7), val);
2082 for (; i < 0x9A; i++)
2083 val = Fcons (make_number ((i - 0x8F) << 14), val);
2084 for (i = 0xA0; i < 0xF0; i++)
2085 val = Fcons (make_number ((i - 0x70) << 7), val);
2086 for (; i < 0xFF; i++)
2087 val = Fcons (make_number ((i - 0xE0) << 14), val);
2088 val = Fcons (make_number (GENERIC_COMPOSITION_CHAR), val);
2089 Vgeneric_character_list = Fnreverse (val);
2090 }
bbf12bb3
KH
2091
2092 nonascii_insert_offset = 0;
2093 Vnonascii_translation_table = Qnil;
4ed46869
KH
2094}
2095
2096#ifdef emacs
2097
dfcf069d 2098void
4ed46869
KH
2099syms_of_charset ()
2100{
2101 Qascii = intern ("ascii");
2102 staticpro (&Qascii);
2103
2104 Qcharset = intern ("charset");
2105 staticpro (&Qcharset);
2106
2107 /* Define ASCII charset now. */
2108 update_charset_table (make_number (CHARSET_ASCII),
2109 make_number (1), make_number (94),
2110 make_number (1),
2111 make_number (0),
2112 make_number ('B'),
2113 make_number (0),
2114 build_string ("ASCII"),
2115 build_string ("ASCII"),
2116 build_string ("ASCII (ISO646 IRV)"));
2117 CHARSET_SYMBOL (CHARSET_ASCII) = Qascii;
2118 Fput (Qascii, Qcharset, CHARSET_TABLE_ENTRY (CHARSET_ASCII));
2119
2120 Qcomposition = intern ("composition");
2121 staticpro (&Qcomposition);
2122 CHARSET_SYMBOL (CHARSET_COMPOSITION) = Qcomposition;
2123
c1a08b4c
KH
2124 Qauto_fill_chars = intern ("auto-fill-chars");
2125 staticpro (&Qauto_fill_chars);
2126 Fput (Qauto_fill_chars, Qchar_table_extra_slots, make_number (0));
2127
4ed46869 2128 defsubr (&Sdefine_charset);
8a73a704 2129 defsubr (&Sgeneric_character_list);
3fac5a51 2130 defsubr (&Sget_unused_iso_final_char);
4ed46869
KH
2131 defsubr (&Sdeclare_equiv_charset);
2132 defsubr (&Sfind_charset_region);
2133 defsubr (&Sfind_charset_string);
2134 defsubr (&Smake_char_internal);
2135 defsubr (&Ssplit_char);
2136 defsubr (&Schar_charset);
90d7b74e 2137 defsubr (&Scharset_after);
4ed46869 2138 defsubr (&Siso_charset);
9d3d8cba 2139 defsubr (&Schar_valid_p);
d2665018 2140 defsubr (&Sunibyte_char_to_multibyte);
1bcc1567 2141 defsubr (&Smultibyte_char_to_unibyte);
4ed46869
KH
2142 defsubr (&Schar_bytes);
2143 defsubr (&Schar_width);
2144 defsubr (&Sstring_width);
2145 defsubr (&Schar_direction);
af4fecb4 2146 defsubr (&Schars_in_region);
87b089ad 2147 defsubr (&Sstring);
4ed46869
KH
2148 defsubr (&Scmpcharp);
2149 defsubr (&Scmpchar_component);
2150 defsubr (&Scmpchar_cmp_rule);
2151 defsubr (&Scmpchar_cmp_rule_p);
2152 defsubr (&Scmpchar_cmp_count);
2153 defsubr (&Scompose_string);
2154 defsubr (&Ssetup_special_charsets);
2155
2156 DEFVAR_LISP ("charset-list", &Vcharset_list,
2157 "List of charsets ever defined.");
2158 Vcharset_list = Fcons (Qascii, Qnil);
2159
537efd8d 2160 DEFVAR_LISP ("translation-table-vector", &Vtranslation_table_vector,
b4e9dd77
KH
2161 "Vector of cons cell of a symbol and translation table ever defined.\n\
2162An ID of a translation table is an index of this vector.");
537efd8d 2163 Vtranslation_table_vector = Fmake_vector (make_number (16), Qnil);
b0e3cf2b 2164
4ed46869
KH
2165 DEFVAR_INT ("leading-code-composition", &leading_code_composition,
2166 "Leading-code of composite characters.");
2167 leading_code_composition = LEADING_CODE_COMPOSITION;
2168
2169 DEFVAR_INT ("leading-code-private-11", &leading_code_private_11,
2170 "Leading-code of private TYPE9N charset of column-width 1.");
2171 leading_code_private_11 = LEADING_CODE_PRIVATE_11;
2172
2173 DEFVAR_INT ("leading-code-private-12", &leading_code_private_12,
2174 "Leading-code of private TYPE9N charset of column-width 2.");
2175 leading_code_private_12 = LEADING_CODE_PRIVATE_12;
2176
2177 DEFVAR_INT ("leading-code-private-21", &leading_code_private_21,
2178 "Leading-code of private TYPE9Nx9N charset of column-width 1.");
2179 leading_code_private_21 = LEADING_CODE_PRIVATE_21;
2180
2181 DEFVAR_INT ("leading-code-private-22", &leading_code_private_22,
2182 "Leading-code of private TYPE9Nx9N charset of column-width 2.");
2183 leading_code_private_22 = LEADING_CODE_PRIVATE_22;
35e623fb
RS
2184
2185 DEFVAR_INT ("nonascii-insert-offset", &nonascii_insert_offset,
d2665018 2186 "Offset for converting non-ASCII unibyte codes 0240...0377 to multibyte.\n\
4cf9710d
RS
2187This is used for converting unibyte text to multibyte,\n\
2188and for inserting character codes specified by number.\n\n\
3e8ceaac
RS
2189This serves to convert a Latin-1 or similar 8-bit character code\n\
2190to the corresponding Emacs multibyte character code.\n\
2191Typically the value should be (- (make-char CHARSET 0) 128),\n\
2192for your choice of character set.\n\
537efd8d 2193If `nonascii-translation-table' is non-nil, it overrides this variable.");
35e623fb 2194 nonascii_insert_offset = 0;
b0e3cf2b 2195
b4e9dd77 2196 DEFVAR_LISP ("nonascii-translation-table", &Vnonascii_translation_table,
537efd8d 2197 "Translation table to convert non-ASCII unibyte codes to multibyte.\n\
4cf9710d
RS
2198This is used for converting unibyte text to multibyte,\n\
2199and for inserting character codes specified by number.\n\n\
2200Conversion is performed only when multibyte characters are enabled,\n\
2201and it serves to convert a Latin-1 or similar 8-bit character code\n\
2202to the corresponding Emacs character code.\n\n\
da4d65af 2203If this is nil, `nonascii-insert-offset' is used instead.\n\
b4e9dd77
KH
2204See also the docstring of `make-translation-table'.");
2205 Vnonascii_translation_table = Qnil;
4cf9710d 2206
b0e3cf2b
KH
2207 DEFVAR_INT ("min-composite-char", &min_composite_char,
2208 "Minimum character code of a composite character.");
2209 min_composite_char = MIN_CHAR_COMPOSITION;
c1a08b4c
KH
2210
2211 DEFVAR_LISP ("auto-fill-chars", &Vauto_fill_chars,
2212 "A char-table for characters which invoke auto-filling.\n\
2213Such characters has value t in this table.");
2214 Vauto_fill_chars = Fmake_char_table (Qauto_fill_chars, Qnil);
60022cb7
AS
2215 CHAR_TABLE_SET (Vauto_fill_chars, make_number (' '), Qt);
2216 CHAR_TABLE_SET (Vauto_fill_chars, make_number ('\n'), Qt);
4ed46869
KH
2217}
2218
2219#endif /* emacs */