Add an EXFUN for `Fchar_feature'.
[chise/xemacs-chise.git.1] / src / chartab.h
1 /* Declarations having to do with Mule char tables.
2    Copyright (C) 1992 Free Software Foundation, Inc.
3    Copyright (C) 1995 Sun Microsystems, Inc.
4    Copyright (C) 1999,2000,2001,2002,2003,2004 MORIOKA Tomohiko
5
6 This file is part of XEmacs.
7
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
12
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING.  If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 /* Synched up with: Mule 2.3.  Not synched with FSF.
24
25    This file was written independently of the FSF implementation,
26    and is not compatible. */
27
28 #ifndef INCLUDED_chartab_h_
29 #define INCLUDED_chartab_h_
30
31
32 #ifdef UTF2000
33
34 #ifdef HAVE_CHISE
35 #  ifdef HAVE_LIBCHISE
36 #    include <chise.h>
37 #  else /* HAVE_LIBCHISE */
38 #    include "database.h"
39 #  endif /* not HAVE_LIBCHISE */
40 #endif
41
42 EXFUN (Fmake_char, 3);
43 EXFUN (Fdecode_char, 4);
44
45 EXFUN (Fput_char_attribute, 3);
46
47 EXFUN (Ffind_char, 1);
48
49 extern Lisp_Object Qdowncase, Qflippedcase, Q_lowercase, Q_uppercase;
50
51 #ifdef HAVE_LIBCHISE
52 extern CHISE_DS *default_chise_data_source;
53
54 int open_chise_data_source_maybe (void);
55 #endif
56
57 /************************************************************************/
58 /*                          Char-ID Tables                              */
59 /************************************************************************/
60
61 struct Lisp_Uint8_Byte_Table
62 {
63   struct lcrecord_header header;
64
65   unsigned char property[256];
66 };
67 typedef struct Lisp_Uint8_Byte_Table Lisp_Uint8_Byte_Table;
68
69 DECLARE_LRECORD (uint8_byte_table, Lisp_Uint8_Byte_Table);
70 #define XUINT8_BYTE_TABLE(x) \
71    XRECORD (x, uint8_byte_table, Lisp_Uint8_Byte_Table)
72 #define XSETUINT8_BYTE_TABLE(x, p) XSETRECORD (x, p, uint8_byte_table)
73 #define UINT8_BYTE_TABLE_P(x) RECORDP (x, uint8_byte_table)
74 #define GC_UINT8_BYTE_TABLE_P(x) GC_RECORDP (x, uint8_byte_table)
75 /* #define CHECK_UINT8_BYTE_TABLE(x) CHECK_RECORD (x, uint8_byte_table)
76    char table entries should never escape to Lisp */
77
78
79 struct Lisp_Uint16_Byte_Table
80 {
81   struct lcrecord_header header;
82
83   unsigned short property[256];
84 };
85 typedef struct Lisp_Uint16_Byte_Table Lisp_Uint16_Byte_Table;
86
87 DECLARE_LRECORD (uint16_byte_table, Lisp_Uint16_Byte_Table);
88 #define XUINT16_BYTE_TABLE(x) \
89    XRECORD (x, uint16_byte_table, Lisp_Uint16_Byte_Table)
90 #define XSETUINT16_BYTE_TABLE(x, p) XSETRECORD (x, p, uint16_byte_table)
91 #define UINT16_BYTE_TABLE_P(x) RECORDP (x, uint16_byte_table)
92 #define GC_UINT16_BYTE_TABLE_P(x) GC_RECORDP (x, uint16_byte_table)
93 /* #define CHECK_UINT16_BYTE_TABLE(x) CHECK_RECORD (x, uint16_byte_table)
94    char table entries should never escape to Lisp */
95
96
97 struct Lisp_Byte_Table
98 {
99   struct lcrecord_header header;
100
101   Lisp_Object property[256];
102 };
103 typedef struct Lisp_Byte_Table Lisp_Byte_Table;
104
105 DECLARE_LRECORD (byte_table, Lisp_Byte_Table);
106 #define XBYTE_TABLE(x) XRECORD (x, byte_table, Lisp_Byte_Table)
107 #define XSETBYTE_TABLE(x, p) XSETRECORD (x, p, byte_table)
108 #define BYTE_TABLE_P(x) RECORDP (x, byte_table)
109 #define GC_BYTE_TABLE_P(x) GC_RECORDP (x, byte_table)
110 /* #define CHECK_BYTE_TABLE(x) CHECK_RECORD (x, byte_table)
111    char table entries should never escape to Lisp */
112
113 Lisp_Object get_byte_table (Lisp_Object table, unsigned char idx);
114
115 Lisp_Object put_byte_table (Lisp_Object table, unsigned char idx,
116                             Lisp_Object value);
117
118
119 Lisp_Object make_char_id_table (Lisp_Object initval);
120
121 #endif
122
123
124 /************************************************************************/
125 /*                               Char Tables                            */
126 /************************************************************************/
127
128 /* Under Mule, we use a complex representation (see below).
129    When not under Mule, there are only 256 possible characters
130    so we just represent them directly. */
131
132 #if defined(MULE)&&!defined(UTF2000)
133
134 struct Lisp_Char_Table_Entry
135 {
136   struct lcrecord_header header;
137
138   /* In the interests of simplicity, we just use a fixed 96-entry
139      table.  If we felt like being smarter, we could make this
140      variable-size and add an offset value into this structure. */
141   Lisp_Object level2[96];
142 };
143 typedef struct Lisp_Char_Table_Entry Lisp_Char_Table_Entry;
144
145 DECLARE_LRECORD (char_table_entry, Lisp_Char_Table_Entry);
146 #define XCHAR_TABLE_ENTRY(x) \
147   XRECORD (x, char_table_entry, Lisp_Char_Table_Entry)
148 #define XSETCHAR_TABLE_ENTRY(x, p) XSETRECORD (x, p, char_table_entry)
149 #define CHAR_TABLE_ENTRYP(x) RECORDP (x, char_table_entry)
150 /* #define CHECK_CHAR_TABLE_ENTRY(x) CHECK_RECORD (x, char_table_entry)
151    char table entries should never escape to Lisp */
152
153 #endif /* MULE */
154
155 enum char_table_type
156 {
157   CHAR_TABLE_TYPE_GENERIC,
158 #ifdef MULE
159   CHAR_TABLE_TYPE_CATEGORY,
160 #endif
161   CHAR_TABLE_TYPE_SYNTAX,
162   CHAR_TABLE_TYPE_DISPLAY,
163   CHAR_TABLE_TYPE_CHAR
164 };
165
166 #ifndef UTF2000
167 #ifdef MULE
168 #define NUM_ASCII_CHARS 160
169 #else
170 #define NUM_ASCII_CHARS 256
171 #endif
172 #endif
173
174 struct Lisp_Char_Table
175 {
176   struct lcrecord_header header;
177
178 #ifdef UTF2000
179   Lisp_Object table;
180   Lisp_Object default_value;
181   Lisp_Object name;
182 #ifndef HAVE_LIBCHISE
183   Lisp_Object db;
184 #endif
185   unsigned char unloaded;
186 #else
187   Lisp_Object ascii[NUM_ASCII_CHARS];
188
189 #ifdef MULE
190   /* We basically duplicate the Mule vectors-of-vectors implementation.
191      We can do this because we know a great deal about the sorts of
192      things we are going to be indexing.
193
194      The current implementation is as follows:
195
196      ascii[0-159] is used for ASCII and Control-1 characters.
197
198      level1[0 .. (NUM_LEADING_BYTES-1)] indexes charsets by leading
199      byte (subtract MIN_LEADING_BYTE from the leading byte).  If the
200      value of this is not an opaque, then it specifies a value for all
201      characters in the charset.  Otherwise, it will be a
202      96-Lisp-Object opaque that we created, specifying a value for
203      each row.  If the value of this is not an opaque, then it
204      specifies a value for all characters in the row.  Otherwise, it
205      will be a 96-Lisp-Object opaque that we created, specifying a
206      value for each character.
207
208      NOTE: 1) This will fail if some C routine passes an opaque to
209               Fput_char_table().  Currently this is not a problem
210               since all char tables that are created are Lisp-visible
211               and thus no one should ever be putting an opaque in
212               a char table.  Another possibility is to consider
213               adding a type to */
214
215   Lisp_Object level1[NUM_LEADING_BYTES];
216
217 #endif /* MULE */
218 #endif /* non UTF2000 */
219
220   enum char_table_type type;
221
222 #ifndef UTF2000
223   /* stuff used for syntax tables */
224   Lisp_Object mirror_table;
225 #endif
226   Lisp_Object next_table; /* DO NOT mark through this. */
227 };
228 typedef struct Lisp_Char_Table Lisp_Char_Table;
229
230 DECLARE_LRECORD (char_table, Lisp_Char_Table);
231 #define XCHAR_TABLE(x) XRECORD (x, char_table, Lisp_Char_Table)
232 #define XSETCHAR_TABLE(x, p) XSETRECORD (x, p, char_table)
233 #define CHAR_TABLEP(x) RECORDP (x, char_table)
234 #define CHECK_CHAR_TABLE(x) CHECK_RECORD (x, char_table)
235 #define CONCHECK_CHAR_TABLE(x) CONCHECK_RECORD (x, char_table)
236
237 #define CHAR_TABLE_TYPE(ct) ((ct)->type)
238 #define XCHAR_TABLE_TYPE(ct) CHAR_TABLE_TYPE (XCHAR_TABLE (ct))
239
240 #ifdef UTF2000
241
242 #define CHAR_TABLE_NAME(ct) ((ct)->name)
243 #define XCHAR_TABLE_NAME(ct) CHAR_TABLE_NAME (XCHAR_TABLE (ct))
244
245 #define CHAR_TABLE_UNLOADED(ct) ((ct)->unloaded)
246 #define XCHAR_TABLE_UNLOADED(ct) CHAR_TABLE_UNLOADED (XCHAR_TABLE (ct))
247
248 INLINE_HEADER Lisp_Object
249 CHAR_TABLE_VALUE_UNSAFE (Lisp_Char_Table *ct, Emchar ch);
250 INLINE_HEADER Lisp_Object
251 CHAR_TABLE_VALUE_UNSAFE (Lisp_Char_Table *ct, Emchar ch)
252 {
253   Lisp_Object val = get_byte_table (get_byte_table
254                                     (get_byte_table
255                                      (get_byte_table
256                                       (ct->table,
257                                        (unsigned char)(ch >> 24)),
258                                       (unsigned char) (ch >> 16)),
259                                      (unsigned char)  (ch >> 8)),
260                                     (unsigned char)    ch);
261   if (UNBOUNDP (val))
262     return ct->default_value;
263   else
264     return val;
265 }
266
267 #elif defined(MULE)
268
269 Lisp_Object get_non_ascii_char_table_value (Lisp_Char_Table *ct,
270                                             Charset_ID leading_byte,
271                                             Emchar c);
272
273 INLINE_HEADER Lisp_Object
274 CHAR_TABLE_NON_ASCII_VALUE_UNSAFE (Lisp_Char_Table *ct, Emchar ch);
275 INLINE_HEADER Lisp_Object
276 CHAR_TABLE_NON_ASCII_VALUE_UNSAFE (Lisp_Char_Table *ct, Emchar ch)
277 {
278 #ifdef UTF2000
279   Charset_ID lb = CHAR_CHARSET_ID (ch);
280 #else
281   Charset_ID lb = CHAR_LEADING_BYTE (ch);
282 #endif
283   if (!CHAR_TABLE_ENTRYP ((ct)->level1[lb - MIN_LEADING_BYTE]))
284     return (ct)->level1[lb - MIN_LEADING_BYTE];
285   else
286     return get_non_ascii_char_table_value (ct, lb, ch);
287 }
288
289 #define CHAR_TABLE_VALUE_UNSAFE(ct, ch)         \
290   ((ch) < NUM_ASCII_CHARS                       \
291    ? (ct)->ascii[ch]                            \
292    : CHAR_TABLE_NON_ASCII_VALUE_UNSAFE (ct, ch))
293
294 #else /* not MULE */
295
296 #define CHAR_TABLE_VALUE_UNSAFE(ct, ch) ((ct)->ascii[(unsigned char) (ch)])
297
298 #endif /* not MULE */
299
300 #define XCHAR_TABLE_VALUE_UNSAFE(ct, ch) \
301   CHAR_TABLE_VALUE_UNSAFE (XCHAR_TABLE (ct), ch)
302
303 enum chartab_range_type
304 {
305   CHARTAB_RANGE_ALL,
306 #ifdef UTF2000
307   CHARTAB_RANGE_DEFAULT,
308 #endif
309 #ifdef MULE
310   CHARTAB_RANGE_CHARSET,
311   CHARTAB_RANGE_ROW,
312 #endif
313   CHARTAB_RANGE_CHAR
314 };
315
316 struct chartab_range
317 {
318   enum chartab_range_type type;
319   Emchar ch;
320   Lisp_Object charset;
321   int row;
322 };
323
324 void fill_char_table (Lisp_Char_Table *ct, Lisp_Object value);
325 void put_char_table (Lisp_Char_Table *ct, struct chartab_range *range,
326                      Lisp_Object val);
327 Lisp_Object get_char_table (Emchar, Lisp_Char_Table *);
328 int map_char_table (Lisp_Char_Table *ct,
329                     struct chartab_range *range,
330                     int (*fn) (struct chartab_range *range,
331                                Lisp_Object val, void *arg),
332                     void *arg);
333 void prune_syntax_tables (void);
334
335 EXFUN (Fcopy_char_table, 1);
336 EXFUN (Fmake_char_table, 1);
337 EXFUN (Fput_char_table, 3);
338 EXFUN (Fget_char_table, 2);
339
340 extern Lisp_Object Vall_syntax_tables;
341
342 \f
343 #ifdef UTF2000
344
345 INLINE_HEADER void
346 put_char_id_table_0 (Lisp_Char_Table* cit, Emchar code, Lisp_Object value);
347 INLINE_HEADER void
348 put_char_id_table_0 (Lisp_Char_Table* cit, Emchar code, Lisp_Object value)
349 {
350   Lisp_Object table1, table2, table3, table4;
351         
352   table1 = cit->table;
353   table2 = get_byte_table (table1, (unsigned char)(code >> 24));
354   table3 = get_byte_table (table2, (unsigned char)(code >> 16));
355   table4 = get_byte_table (table3, (unsigned char)(code >>  8));
356
357   table4     = put_byte_table (table4, (unsigned char) code, value);
358   table3     = put_byte_table (table3, (unsigned char)(code >>  8), table4);
359   table2     = put_byte_table (table2, (unsigned char)(code >> 16), table3);
360   cit->table = put_byte_table (table1, (unsigned char)(code >> 24), table2);
361 }
362
363 #ifdef HAVE_CHISE
364 Lisp_Object load_char_attribute_maybe (Lisp_Char_Table* cit, Emchar ch);
365
366 #ifndef HAVE_LIBCHISE
367 extern Lisp_Object Qsystem_char_id;
368
369 Lisp_Object
370 char_attribute_system_db_file (Lisp_Object key_type, Lisp_Object attribute,
371                                int writing_mode);
372 #endif /* not HAVE_LIBCHISE */
373 #endif /* HAVE_CHISE */
374
375 INLINE_HEADER Lisp_Object
376 get_char_id_table_0 (Lisp_Char_Table* cit, Emchar ch);
377 INLINE_HEADER Lisp_Object
378 get_char_id_table_0 (Lisp_Char_Table* cit, Emchar ch)
379 {
380   return get_byte_table (get_byte_table
381                          (get_byte_table
382                           (get_byte_table
383                            (cit->table,
384                             (unsigned char)(ch >> 24)),
385                            (unsigned char) (ch >> 16)),
386                           (unsigned char)  (ch >> 8)),
387                          (unsigned char)    ch);
388 }
389
390 INLINE_HEADER Lisp_Object
391 get_char_id_table (Lisp_Char_Table* cit, Emchar ch);
392 INLINE_HEADER Lisp_Object
393 get_char_id_table (Lisp_Char_Table* cit, Emchar ch)
394 {
395   Lisp_Object val = get_char_id_table_0 (cit, ch);
396
397 #ifdef HAVE_CHISE
398   if (EQ (val, Qunloaded))
399     {
400       val = load_char_attribute_maybe (cit, ch);
401       put_char_id_table_0 (cit, ch, val);
402     }
403 #endif /* HAVE_CHISE */
404   if (UNBOUNDP (val))
405     return cit->default_value;
406   else
407     return val;
408 }
409
410 void
411 decode_char_table_range (Lisp_Object range, struct chartab_range *outrange);
412
413 INLINE_HEADER void
414 put_char_id_table (Lisp_Char_Table* table,
415                    Lisp_Object character, Lisp_Object value);
416 INLINE_HEADER void
417 put_char_id_table (Lisp_Char_Table* table,
418                    Lisp_Object character, Lisp_Object value)
419 {
420   struct chartab_range range;
421
422   decode_char_table_range (character, &range);
423   put_char_table (table, &range, value);
424 }
425
426
427 EXFUN (Fget_char_attribute, 3);
428 EXFUN (Fchar_feature, 5);
429
430 #endif
431 \f
432
433 #ifdef MULE
434 int check_category_char(Emchar ch, Lisp_Object ctbl,
435                         unsigned int designator, unsigned int not_p);
436
437 extern Lisp_Object Vstandard_category_table;
438
439 #define CATEGORY_DESIGNATORP(x) \
440  (CHARP (x) && XCHAR (x) >= 32 && XCHAR (x) <= 126)
441
442 #define CHECK_CATEGORY_DESIGNATOR(x) do {                       \
443   if (!CATEGORY_DESIGNATORP (x))                                \
444     dead_wrong_type_argument (Qcategory_designator_p, x);       \
445 } while (0)
446
447 #define CONCHECK_CATEGORY_DESIGNATOR(x) do {                    \
448   if (!CATEGORY_DESIGNATORP (x))                                \
449     x = wrong_type_argument (Qcategory_designator_p, x);        \
450 } while (0)
451
452 #define CATEGORY_TABLE_VALUEP(x) \
453  (NILP (x) || (BIT_VECTORP (x) && (bit_vector_length (XBIT_VECTOR (x)) == 95)))
454
455 #define CHECK_CATEGORY_TABLE_VALUE(x) do {                      \
456   if (!CATEGORY_TABLE_VALUEP (x))                               \
457     dead_wrong_type_argument (Qcategory_table_value_p, x);      \
458 } while (0)
459
460 #define CONCHECK_CATEGORY_TABLE_VALUE(x) do {                   \
461   if (!CATEGORY_TABLE_VALUEP (x))                               \
462     x = wrong_type_argument (Qcategory_table_value_p, x);       \
463 } while (0)
464
465 #endif /* MULE */
466
467 #endif /* INCLUDED_chartab_h_ */