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