(Fmodify_category_entry): Delete second arg in call to make_sub_char_table.
[bpt/emacs.git] / src / category.c
1 /* GNU Emacs routines to deal with category tables.
2 Ver.1.0
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; 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
24 /* Here we handle three objects: category, category set, and category
25 table. Read comments in the file category.h to understand them. */
26
27 #include <config.h>
28 #include <ctype.h>
29 #include "lisp.h"
30 #include "buffer.h"
31 #include "charset.h"
32 #include "category.h"
33
34 /* The version number of the latest category table. Each category
35 table has a unique version number. It is assigned a new number
36 also when it is modified. When a regular expression is compiled
37 into the struct re_pattern_buffer, the version number of the
38 category table (of the current buffer) at that moment is also
39 embedded in the structure.
40
41 For the moment, we are not using this feature. */
42 static int category_table_version;
43
44 Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, Qcategory_table_p;
45
46 /* Variables to determine word boundary. */
47 Lisp_Object Vword_combining_categories, Vword_separating_categories;
48
49 /* Temporary internal variable used in macro CHAR_HAS_CATEGORY. */
50 Lisp_Object _temp_category_set;
51
52 \f
53 /* Category set staff. */
54
55 DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0,
56 "Return a newly created category-set which contains CATEGORIES.\n\
57 CATEGORIES is a string of category mnemonics.")
58 (categories)
59 Lisp_Object categories;
60 {
61 Lisp_Object val;
62 int len;
63
64 CHECK_STRING (categories, 0);
65 val = MAKE_CATEGORY_SET;
66
67 len = XSTRING (categories)->size;
68 while (--len >= 0)
69 {
70 Lisp_Object category;
71
72 XSETFASTINT (category, XSTRING (categories)->data[len]);
73 CHECK_CATEGORY (category, 0);
74 SET_CATEGORY_SET (val, category, Qt);
75 }
76 return val;
77 }
78
79 \f
80 /* Category staff. */
81
82 Lisp_Object check_category_table ();
83
84 DEFUN ("define-category", Fdefine_category, Sdefine_category, 2, 3, 0,
85 "Define CHAR as a category which is described by DOCSTRING.\n\
86 CHAR should be a visible letter of ` ' thru `~'.\n\
87 DOCSTRING is a documentation string of the category.\n\
88 The category is defined only in category table TABLE, which defaults to\n\
89 the current buffer's category table.")
90 (category, docstring, table)
91 Lisp_Object category, docstring, table;
92 {
93 CHECK_CATEGORY (category, 0);
94 CHECK_STRING (docstring, 1);
95 table = check_category_table (table);
96
97 if (!NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
98 error ("Category `%c' is already defined", XFASTINT (category));
99 CATEGORY_DOCSTRING (table, XFASTINT (category)) = docstring;
100
101 return Qnil;
102 }
103
104 DEFUN ("category-docstring", Fcategory_docstring, Scategory_docstring, 1, 2, 0,
105 "Return a documentation string of CATEGORY.\n\
106 Optional second arg specifies CATEGORY-TABLE,\n\
107 which defaults to the current buffer's category table.")
108 (category, table)
109 Lisp_Object category, table;
110 {
111 Lisp_Object doc;
112
113 CHECK_CATEGORY (category, 0);
114 table = check_category_table (table);
115
116 return CATEGORY_DOCSTRING (table, XFASTINT (category));
117 }
118
119 DEFUN ("get-unused-category", Fget_unused_category, Sget_unused_category,
120 0, 1, 0,
121 "Return a category which is not yet defined.\n\
122 If total number of categories has reached the limit (95), return nil.\n\
123 Optional argument specifies CATEGORY-TABLE,\n\
124 which defaults to the current buffer's category table.")
125 (table)
126 Lisp_Object table;
127 {
128 int i;
129 Lisp_Object docstring_vector;
130
131 table = check_category_table (table);
132
133 for (i = ' '; i <= '~'; i++)
134 if (NILP (CATEGORY_DOCSTRING (table, i)))
135 return make_number (i);
136
137 return Qnil;
138 }
139
140 \f
141 /* Category-table staff. */
142
143 DEFUN ("category-table-p", Fcategory_table_p, Scategory_table_p, 1, 1, 0,
144 "Return t if ARG is a category table.")
145 (arg)
146 Lisp_Object arg;
147 {
148 if (CHAR_TABLE_P (arg)
149 && EQ (XCHAR_TABLE (arg)->purpose, Qcategory_table))
150 return Qt;
151 return Qnil;
152 }
153
154 /* If TABLE is nil, return the current category table. If TABLE is
155 not nil, check the validity of TABLE as a category table. If
156 valid, return TABLE itself, but if not valid, signal an error of
157 wrong-type-argument. */
158
159 Lisp_Object
160 check_category_table (table)
161 Lisp_Object table;
162 {
163 register Lisp_Object tem;
164 if (NILP (table))
165 return current_buffer->category_table;
166 while (tem = Fcategory_table_p (table), NILP (tem))
167 table = wrong_type_argument (Qcategory_table_p, table);
168 return table;
169 }
170
171 DEFUN ("category-table", Fcategory_table, Scategory_table, 0, 0, 0,
172 "Return the current category table.\n\
173 This is the one specified by the current buffer.")
174 ()
175 {
176 return current_buffer->category_table;
177 }
178
179 DEFUN ("standard-category-table", Fstandard_category_table,
180 Sstandard_category_table, 0, 0, 0,
181 "Return the standard category table.\n\
182 This is the one used for new buffers.")
183 ()
184 {
185 return Vstandard_category_table;
186 }
187
188 /* Return a copy of category table TABLE. We can't simply use the
189 function copy-sequence because no contents should be shared between
190 the original and the copy. This function is called recursively by
191 biding TABLE to a sub char table. */
192
193 Lisp_Object
194 copy_category_table (table)
195 Lisp_Object table;
196 {
197 Lisp_Object tmp;
198 int i, to;
199
200 if (!NILP (XCHAR_TABLE (table)->top))
201 {
202 /* TABLE is a top level char table.
203 At first, make a copy of tree structure of the table. */
204 table = Fcopy_sequence (table);
205
206 /* Then, copy elements for single byte characters one by one. */
207 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
208 if (!NILP (tmp = XCHAR_TABLE (table)->contents[i]))
209 XCHAR_TABLE (table)->contents[i] = Fcopy_sequence (tmp);
210 to = CHAR_TABLE_ORDINARY_SLOTS;
211 }
212 else
213 {
214 i = 32;
215 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
216 }
217
218 /* If the table has non-nil default value, copy it. */
219 if (!NILP (tmp = XCHAR_TABLE (table)->defalt))
220 XCHAR_TABLE (table)->defalt = Fcopy_sequence (tmp);
221
222 /* At last, copy the remaining elements while paying attention to a
223 sub char table. */
224 for (; i < to; i++)
225 if (!NILP (tmp = XCHAR_TABLE (table)->contents[i]))
226 XCHAR_TABLE (table)->contents[i]
227 = (SUB_CHAR_TABLE_P (tmp)
228 ? copy_category_table (tmp) : Fcopy_sequence (tmp));
229
230 return table;
231 }
232
233 DEFUN ("copy-category-table", Fcopy_category_table, Scopy_category_table,
234 0, 1, 0,
235 "Construct a new category table and return it.\n\
236 It is a copy of the TABLE, which defaults to the standard category table.")
237 (table)
238 Lisp_Object table;
239 {
240 if (!NILP (table))
241 check_category_table (table);
242 else
243 table = Vstandard_category_table;
244
245 return copy_category_table (table, 1);
246 }
247
248 DEFUN ("set-category-table", Fset_category_table, Sset_category_table, 1, 1, 0,
249 "Select a new category table for the current buffer.\n\
250 One argument, a category table.")
251 (table)
252 Lisp_Object table;
253 {
254 table = check_category_table (table);
255 current_buffer->category_table = table;
256 /* Indicate that this buffer now has a specified category table. */
257 current_buffer->local_var_flags
258 |= XFASTINT (buffer_local_flags.category_table);
259 return table;
260 }
261
262 \f
263 DEFUN ("char-category-set", Fchar_category_set, Schar_category_set, 1, 1, 0,
264 "Return a category set of CHAR.")
265 (ch)
266 Lisp_Object ch;
267 {
268 Lisp_Object val;
269 int charset;
270 unsigned char c1, c2;
271
272 CHECK_NUMBER (ch, 0);
273 return CATEGORY_SET (XFASTINT (ch));
274 }
275
276 DEFUN ("category-set-mnemonics", Fcategory_set_mnemonics,
277 Scategory_set_mnemonics, 1, 1, 0,
278 "Return a string of mnemonics of all categories in CATEGORY-SET.")
279 (category_set)
280 Lisp_Object category_set;
281 {
282 int i, j;
283 char str[96];
284
285 CHECK_CATEGORY_SET (category_set, 0);
286
287 j = 0;
288 for (i = 32; i < 127; i++)
289 if (CATEGORY_MEMBER (i, category_set))
290 str[j++] = i;
291 str[j] = '\0';
292
293 return build_string (str);
294 }
295
296 /* Modify all category sets stored under sub char-table TABLE so that
297 they contain (SET_VALUE is t) or don't contain (SET_VALUE is nil)
298 CATEGORY. */
299
300 void
301 modify_lower_category_set (table, category, set_value)
302 Lisp_Object table, category, set_value;
303 {
304 Lisp_Object val;
305 int i;
306
307 if (NILP (XCHAR_TABLE (table)->defalt))
308 {
309 val = MAKE_CATEGORY_SET;
310 SET_CATEGORY_SET (val, category, set_value);
311 XCHAR_TABLE (table)->defalt = val;
312 }
313
314 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
315 {
316 val = XCHAR_TABLE (table)->contents[i];
317
318 if (CATEGORY_SET_P (val))
319 SET_CATEGORY_SET (val, category, set_value);
320 else if (SUB_CHAR_TABLE_P (val))
321 modify_lower_category_set (val, category, set_value);
322 }
323 }
324
325 void
326 set_category_set (category_set, category, val)
327 Lisp_Object category_set, category, val;
328 {
329 do {
330 int idx = XINT (category) / 8;
331 unsigned char bits = 1 << (XINT (category) % 8);
332
333 if (NILP (val))
334 XCATEGORY_SET (category_set)->data[idx] &= ~bits;
335 else
336 XCATEGORY_SET (category_set)->data[idx] |= bits;
337 } while (0);
338 }
339
340 DEFUN ("modify-category-entry", Fmodify_category_entry,
341 Smodify_category_entry, 2, 4, 0,
342 "Modify the category set of CHAR by adding CATEGORY to it.\n\
343 The category is changed only for table TABLE, which defaults to\n\
344 the current buffer's category table.\n\
345 If optional forth argument RESET is non NIL,\n\
346 CATEGORY is deleted from the category set instead of being added.")
347 (ch, category, table, reset)
348 Lisp_Object ch, category, table, reset;
349 {
350 int c, charset, c1, c2;
351 Lisp_Object set_value; /* Actual value to be set in category sets. */
352 Lisp_Object val, category_set;
353
354 CHECK_NUMBER (ch, 0);
355 c = XINT (ch);
356 CHECK_CATEGORY (category, 1);
357 table = check_category_table (table);
358
359 if (NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
360 error ("Undefined category: %c", XFASTINT (category));
361
362 set_value = NILP (reset) ? Qt : Qnil;
363
364 if (c < CHAR_TABLE_SINGLE_BYTE_SLOTS)
365 {
366 val = XCHAR_TABLE (table)->contents[c];
367 if (!CATEGORY_SET_P (val))
368 XCHAR_TABLE (table)->contents[c] = (val = MAKE_CATEGORY_SET);
369 SET_CATEGORY_SET (val, category, set_value);
370 return Qnil;
371 }
372
373 SPLIT_NON_ASCII_CHAR (c, charset, c1, c2);
374
375 /* The top level table. */
376 val = XCHAR_TABLE (table)->contents[charset + 128];
377 if (CATEGORY_SET_P (val))
378 category_set = val;
379 else if (!SUB_CHAR_TABLE_P (val))
380 {
381 category_set = val = MAKE_CATEGORY_SET;
382 XCHAR_TABLE (table)->contents[charset + 128] = category_set;
383 }
384
385 if (c1 <= 0)
386 {
387 /* Only a charset is specified. */
388 if (SUB_CHAR_TABLE_P (val))
389 /* All characters in CHARSET should be the same as for having
390 CATEGORY or not. */
391 modify_lower_category_set (val, category, set_value);
392 else
393 SET_CATEGORY_SET (category_set, category, set_value);
394 return Qnil;
395 }
396
397 /* The second level table. */
398 if (!SUB_CHAR_TABLE_P (val))
399 {
400 val = make_sub_char_table (Qnil);
401 XCHAR_TABLE (table)->contents[charset + 128] = val;
402 /* We must set default category set of CHARSET in `defalt' slot. */
403 XCHAR_TABLE (val)->defalt = category_set;
404 }
405 table = val;
406
407 val = XCHAR_TABLE (table)->contents[c1];
408 if (CATEGORY_SET_P (val))
409 category_set = val;
410 else if (!SUB_CHAR_TABLE_P (val))
411 {
412 category_set = val = Fcopy_sequence (XCHAR_TABLE (table)->defalt);
413 XCHAR_TABLE (table)->contents[c1] = category_set;
414 }
415
416 if (c2 <= 0)
417 {
418 if (SUB_CHAR_TABLE_P (val))
419 /* All characters in C1 group of CHARSET should be the same as
420 for CATEGORY. */
421 modify_lower_category_set (val, category, set_value);
422 else
423 SET_CATEGORY_SET (category_set, category, set_value);
424 return Qnil;
425 }
426
427 /* The third (bottom) level table. */
428 if (!SUB_CHAR_TABLE_P (val))
429 {
430 val = make_sub_char_table (Qnil);
431 XCHAR_TABLE (table)->contents[c1] = val;
432 /* We must set default category set of CHARSET and C1 in
433 `defalt' slot. */
434 XCHAR_TABLE (val)->defalt = category_set;
435 }
436 table = val;
437
438 val = XCHAR_TABLE (table)->contents[c2];
439 if (CATEGORY_SET_P (val))
440 category_set = val;
441 else if (!SUB_CHAR_TABLE_P (val))
442 {
443 category_set = Fcopy_sequence (XCHAR_TABLE (table)->defalt);
444 XCHAR_TABLE (table)->contents[c2] = category_set;
445 }
446 else
447 /* This should never happen. */
448 error ("Invalid category table");
449
450 SET_CATEGORY_SET (category_set, category, set_value);
451
452 return Qnil;
453 }
454 \f
455 /* Dump category table to buffer in human-readable format */
456
457 static void
458 describe_category (value)
459 Lisp_Object value;
460 {
461 Lisp_Object mnemonics;
462
463 Findent_to (make_number (16), make_number (1));
464
465 if (NILP (value))
466 {
467 insert_string ("default\n");
468 return;
469 }
470
471 if (!CATEGORY_SET_P (value))
472 {
473 insert_string ("invalid\n");
474 return;
475 }
476
477 mnemonics = Fcategory_set_mnemonics (value);
478 insert_from_string (mnemonics, 0, XSTRING (mnemonics)->size, 0);
479 insert_string ("\n");
480 return;
481 }
482
483 static Lisp_Object
484 describe_category_1 (vector)
485 Lisp_Object vector;
486 {
487 struct buffer *old = current_buffer;
488 set_buffer_internal (XBUFFER (Vstandard_output));
489 describe_vector (vector, Qnil, describe_category, 0, Qnil, Qnil);
490 {
491 int i;
492 Lisp_Object docs = XCHAR_TABLE (vector)->extras[0];
493 Lisp_Object elt;
494
495 if (!VECTORP (docs) || XVECTOR (docs)->size != 95)
496 {
497 insert_string ("Invalid first extra slot in this char table\n");
498 return Qnil;
499 }
500
501 insert_string ("Meanings of mnemonice characters are:\n");
502 for (i = 0; i < 95; i++)
503 {
504 elt = XVECTOR (docs)->contents[i];
505 if (NILP (elt))
506 continue;
507
508 insert_char (i + 32);
509 insert (": ", 2);
510 insert_from_string (elt, 0, XSTRING (elt)->size, 0);
511 insert ("\n", 1);
512 }
513 }
514
515 while (! NILP (XCHAR_TABLE (vector)->parent))
516 {
517 vector = XCHAR_TABLE (vector)->parent;
518 insert_string ("\nThe parent category table is:");
519 describe_vector (vector, Qnil, describe_category, 0, Qnil, Qnil);
520 }
521
522 call0 (intern ("help-mode"));
523 set_buffer_internal (old);
524 return Qnil;
525 }
526
527 DEFUN ("describe-category", Fdescribe_category, Sdescribe_category, 0, 0, "",
528 "Describe the category specifications in the category table.\n\
529 The descriptions are inserted in a buffer, which is then displayed.")
530 ()
531 {
532 internal_with_output_to_temp_buffer
533 ("*Help*", describe_category_1, current_buffer->category_table);
534
535 return Qnil;
536 }
537 \f
538 /* Return 1 if there is a word boundary between two word-constituent
539 characters C1 and C2 if they appear in this order, else return 0.
540 Use the macro WORD_BOUNDARY_P instead of calling this function
541 directly. */
542
543 int
544 word_boundary_p (c1, c2)
545 int c1, c2;
546 {
547 Lisp_Object category_set1, category_set2;
548 Lisp_Object tail;
549 int default_result;
550
551 if (CHAR_CHARSET (c1) == CHAR_CHARSET (c2))
552 {
553 tail = Vword_separating_categories;
554 default_result = 0;
555 }
556 else
557 {
558 tail = Vword_combining_categories;
559 default_result = 1;
560 }
561
562 category_set1 = CATEGORY_SET (c1);
563 if (NILP (category_set1))
564 return default_result;
565 category_set2 = CATEGORY_SET (c2);
566 if (NILP (category_set2))
567 return default_result;
568
569 for (; CONSP (tail); tail = XCONS (tail)->cdr)
570 {
571 Lisp_Object elt = XCONS(tail)->car;
572
573 if (CONSP (elt)
574 && CATEGORYP (XCONS (elt)->car)
575 && CATEGORYP (XCONS (elt)->cdr)
576 && CATEGORY_MEMBER (XCONS (elt)->car, category_set1)
577 && CATEGORY_MEMBER (XCONS (elt)->cdr, category_set2))
578 return !default_result;
579 }
580 return default_result;
581 }
582
583 \f
584 init_category_once ()
585 {
586 /* This has to be done here, before we call Fmake_char_table. */
587 Qcategory_table = intern ("category-table");
588 staticpro (&Qcategory_table);
589
590 /* Intern this now in case it isn't already done.
591 Setting this variable twice is harmless.
592 But don't staticpro it here--that is done in alloc.c. */
593 Qchar_table_extra_slots = intern ("char-table-extra-slots");
594
595 /* Now we are ready to set up this property, so we can
596 create category tables. */
597 Fput (Qcategory_table, Qchar_table_extra_slots, make_number (2));
598
599 Vstandard_category_table = Fmake_char_table (Qcategory_table, Qnil);
600 /* Set a category set which contains nothing to the default. */
601 XCHAR_TABLE (Vstandard_category_table)->defalt = MAKE_CATEGORY_SET;
602 Fset_char_table_extra_slot (Vstandard_category_table, 0,
603 Fmake_vector (make_number (95), Qnil));
604 }
605
606 syms_of_category ()
607 {
608 Qcategoryp = intern ("categoryp");
609 staticpro (&Qcategoryp);
610 Qcategorysetp = intern ("categorysetp");
611 staticpro (&Qcategorysetp);
612 Qcategory_table_p = intern ("category-table-p");
613 staticpro (&Qcategory_table_p);
614
615 DEFVAR_LISP ("word-combining-categories", &Vword_combining_categories,
616 "List of pair (cons) of categories to determine word boundary.\n\
617 \n\
618 Emacs treats a sequence of word constituent characters as a single\n\
619 word (i.e. finds no word boundary between them) iff they belongs to\n\
620 the same charset. But, exceptions are allowed in the following cases.\n\
621 \n\
622 (1) The case that characters are in different charsets is controlled\n\
623 by the variable `word-combining-categories'.\n\
624 \n\
625 Emacs finds no word boundary between characters of different charsets\n\
626 if they have categories matching some element of this list.\n\
627 \n\
628 More precisely, if an element of this list is a cons of category CAT1\n\
629 and CAT2, and a multibyte character C1 which has CAT1 is followed by\n\
630 C2 which has CAT2, there's no word boundary between C1 and C2.\n\
631 \n\
632 For instance, to tell that ASCII characters and Latin-1 characters can\n\
633 form a single word, the element `(?l . ?l)' should be in this list\n\
634 because both characters have the category `l' (Latin characters).\n\
635 \n\
636 (2) The case that character are in the same charset is controlled by\n\
637 the variable `word-separating-categories'.\n\
638 \n\
639 Emacs find a word boundary between characters of the same charset\n\
640 if they have categories matching some element of this list.\n\
641 \n\
642 More precisely, if an element of this list is a cons of category CAT1\n\
643 and CAT2, and a multibyte character C1 which has CAT1 is followed by\n\
644 C2 which has CAT2, there's a word boundary between C1 and C2.\n\
645 \n\
646 For instance, to tell that there's a word boundary between Japanese\n\
647 Hiragana and Japanese Kanji (both are in the same charset), the\n\
648 element `(?H . ?C) should be in this list.");
649
650 Vword_combining_categories = Qnil;
651
652 DEFVAR_LISP ("word-separating-categories", &Vword_separating_categories,
653 "List of pair (cons) of categories to determine word boundary.\n\
654 See the documentation of the variable `word-combining-categories'.");
655
656 Vword_separating_categories = Qnil;
657
658 defsubr (&Smake_category_set);
659 defsubr (&Sdefine_category);
660 defsubr (&Scategory_docstring);
661 defsubr (&Sget_unused_category);
662 defsubr (&Scategory_table_p);
663 defsubr (&Scategory_table);
664 defsubr (&Sstandard_category_table);
665 defsubr (&Scopy_category_table);
666 defsubr (&Sset_category_table);
667 defsubr (&Schar_category_set);
668 defsubr (&Scategory_set_mnemonics);
669 defsubr (&Smodify_category_entry);
670 defsubr (&Sdescribe_category);
671
672 category_table_version = 0;
673 }