category.c 15.5 KB
Newer Older
Karl Heuer's avatar
Karl Heuer committed
1
/* GNU Emacs routines to deal with category tables.
2

Paul Eggert's avatar
Paul Eggert committed
3
Copyright (C) 1998, 2001-2020 Free Software Foundation, Inc.
4 5 6 7 8 9 10
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
  2005, 2006, 2007, 2008, 2009, 2010, 2011
  National Institute of Advanced Industrial Science and Technology (AIST)
  Registration Number H14PRO021
Copyright (C) 2003
  National Institute of Advanced Industrial Science and Technology (AIST)
  Registration Number H13PRO009
Karl Heuer's avatar
Karl Heuer committed
11 12 13

This file is part of GNU Emacs.

14
GNU Emacs is free software: you can redistribute it and/or modify
Karl Heuer's avatar
Karl Heuer committed
15
it under the terms of the GNU General Public License as published by
16 17
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
Karl Heuer's avatar
Karl Heuer committed
18 19 20 21 22 23 24

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
25
along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
Karl Heuer's avatar
Karl Heuer committed
26 27 28 29 30 31


/* Here we handle three objects: category, category set, and category
   table.  Read comments in the file category.h to understand them.  */

#include <config.h>
32

Karl Heuer's avatar
Karl Heuer committed
33
#include "lisp.h"
Kenichi Handa's avatar
Kenichi Handa committed
34
#include "character.h"
35
#include "buffer.h"
Karl Heuer's avatar
Karl Heuer committed
36 37
#include "category.h"

Paul Eggert's avatar
Paul Eggert committed
38
/* This setter is used only in this file, so it can be private.  */
39
static void
Paul Eggert's avatar
Paul Eggert committed
40 41
bset_category_table (struct buffer *b, Lisp_Object val)
{
42
  b->category_table_ = val;
Paul Eggert's avatar
Paul Eggert committed
43 44
}

Karl Heuer's avatar
Karl Heuer committed
45 46 47

/* Category set staff.  */

48
static Lisp_Object
49
hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
50 51
{
  if (NILP (XCHAR_TABLE (table)->extras[1]))
52
    set_char_table_extras
53
      (table, 1,
54 55
       make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
			DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
56
			Qnil, false));
57 58 59
  struct Lisp_Hash_Table *h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
  Lisp_Object hash;
  ptrdiff_t i = hash_lookup (h, category_set, &hash);
60 61 62 63 64 65
  if (i >= 0)
    return HASH_KEY (h, i);
  hash_put (h, category_set, Qnil, hash);
  return category_set;
}

66 67 68 69 70 71 72
/* Make CATEGORY_SET include (if VAL) or exclude (if !VAL) CATEGORY.  */

static void
set_category_set (Lisp_Object category_set, EMACS_INT category, bool val)
{
  bool_vector_set (category_set, category, val);
}
73

Karl Heuer's avatar
Karl Heuer committed
74
DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0,
75 76 77 78
       doc: /* Return a newly created category-set which contains CATEGORIES.
CATEGORIES is a string of category mnemonics.
The value is a bool-vector which has t at the indices corresponding to
those categories.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
79
  (Lisp_Object categories)
Karl Heuer's avatar
Karl Heuer committed
80 81
{
  Lisp_Object val;
82
  ptrdiff_t len;
Karl Heuer's avatar
Karl Heuer committed
83

84
  CHECK_STRING (categories);
Karl Heuer's avatar
Karl Heuer committed
85 86
  val = MAKE_CATEGORY_SET;

87
  if (STRING_MULTIBYTE (categories))
88
    error ("Multibyte string in `make-category-set'");
89

90
  len = SCHARS (categories);
Karl Heuer's avatar
Karl Heuer committed
91 92
  while (--len >= 0)
    {
93
      unsigned char cat = SREF (categories, len);
94
      Lisp_Object category = make_fixnum (cat);
Karl Heuer's avatar
Karl Heuer committed
95

96
      CHECK_CATEGORY (category);
97
      set_category_set (val, cat, 1);
Karl Heuer's avatar
Karl Heuer committed
98 99 100 101 102 103 104
    }
  return val;
}


/* Category staff.  */

105
static Lisp_Object check_category_table (Lisp_Object table);
Karl Heuer's avatar
Karl Heuer committed
106 107

DEFUN ("define-category", Fdefine_category, Sdefine_category, 2, 3, 0,
Kenichi Handa's avatar
Kenichi Handa committed
108 109
       doc: /* Define CATEGORY as a category which is described by DOCSTRING.
CATEGORY should be an ASCII printing character in the range ` ' to `~'.
110 111 112
DOCSTRING is the documentation string of the category.  The first line
should be a terse text (preferably less than 16 characters),
and the rest lines should be the full description.
113
The category is defined only in category table TABLE, which defaults to
Kenichi Handa's avatar
Kenichi Handa committed
114
the current buffer's category table.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
115
  (Lisp_Object category, Lisp_Object docstring, Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
116
{
117 118
  CHECK_CATEGORY (category);
  CHECK_STRING (docstring);
Karl Heuer's avatar
Karl Heuer committed
119 120
  table = check_category_table (table);

Tom Tromey's avatar
Tom Tromey committed
121 122
  if (!NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category))))
    error ("Category `%c' is already defined", (int) XFIXNAT (category));
123 124
  if (!NILP (Vpurify_flag))
    docstring = Fpurecopy (docstring);
Tom Tromey's avatar
Tom Tromey committed
125
  SET_CATEGORY_DOCSTRING (table, XFIXNAT (category), docstring);
Karl Heuer's avatar
Karl Heuer committed
126 127 128 129 130

  return Qnil;
}

DEFUN ("category-docstring", Fcategory_docstring, Scategory_docstring, 1, 2, 0,
Kenichi Handa's avatar
Kenichi Handa committed
131 132 133
       doc: /* Return the documentation string of CATEGORY, as defined in TABLE.
TABLE should be a category table and defaults to the current buffer's
category table.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
134
  (Lisp_Object category, Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
135
{
136
  CHECK_CATEGORY (category);
Karl Heuer's avatar
Karl Heuer committed
137 138
  table = check_category_table (table);

Tom Tromey's avatar
Tom Tromey committed
139
  return CATEGORY_DOCSTRING (table, XFIXNAT (category));
Karl Heuer's avatar
Karl Heuer committed
140 141 142 143
}

DEFUN ("get-unused-category", Fget_unused_category, Sget_unused_category,
       0, 1, 0,
Kenichi Handa's avatar
Kenichi Handa committed
144
       doc: /* Return a category which is not yet defined in TABLE.
145
If no category remains available, return nil.
Kenichi Handa's avatar
Kenichi Handa committed
146
The optional argument TABLE specifies which category table to modify;
147
it defaults to the current buffer's category table.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
148
  (Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
149 150 151 152 153 154 155
{
  int i;

  table = check_category_table (table);

  for (i = ' '; i <= '~'; i++)
    if (NILP (CATEGORY_DOCSTRING (table, i)))
156
      return make_fixnum (i);
Karl Heuer's avatar
Karl Heuer committed
157 158 159 160 161 162 163 164

  return Qnil;
}


/* Category-table staff.  */

DEFUN ("category-table-p", Fcategory_table_p, Scategory_table_p, 1, 1, 0,
165
       doc: /* Return t if ARG is a category table.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
166
  (Lisp_Object arg)
Karl Heuer's avatar
Karl Heuer committed
167 168
{
  if (CHAR_TABLE_P (arg)
169
      && EQ (XCHAR_TABLE (arg)->purpose, Qcategory_table))
Karl Heuer's avatar
Karl Heuer committed
170 171 172 173 174 175 176 177 178
    return Qt;
  return Qnil;
}

/* If TABLE is nil, return the current category table.  If TABLE is
   not nil, check the validity of TABLE as a category table.  If
   valid, return TABLE itself, but if not valid, signal an error of
   wrong-type-argument.  */

179
static Lisp_Object
180
check_category_table (Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
181 182
{
  if (NILP (table))
Tom Tromey's avatar
Tom Tromey committed
183
    return BVAR (current_buffer, category_table);
184
  CHECK_TYPE (!NILP (Fcategory_table_p (table)), Qcategory_table_p, table);
Karl Heuer's avatar
Karl Heuer committed
185
  return table;
186
}
Karl Heuer's avatar
Karl Heuer committed
187 188

DEFUN ("category-table", Fcategory_table, Scategory_table, 0, 0, 0,
189 190
       doc: /* Return the current category table.
This is the one specified by the current buffer.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
191
  (void)
Karl Heuer's avatar
Karl Heuer committed
192
{
Tom Tromey's avatar
Tom Tromey committed
193
  return BVAR (current_buffer, category_table);
Karl Heuer's avatar
Karl Heuer committed
194 195 196 197
}

DEFUN ("standard-category-table", Fstandard_category_table,
   Sstandard_category_table, 0, 0, 0,
198 199
       doc: /* Return the standard category table.
This is the one used for new buffers.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
200
  (void)
Karl Heuer's avatar
Karl Heuer committed
201 202 203 204
{
  return Vstandard_category_table;
}

Kenichi Handa's avatar
Kenichi Handa committed
205 206

static void
207
copy_category_entry (Lisp_Object table, Lisp_Object c, Lisp_Object val)
Kenichi Handa's avatar
Kenichi Handa committed
208
{
209
  val = Fcopy_sequence (val);
Kenichi Handa's avatar
Kenichi Handa committed
210
  if (CONSP (c))
Tom Tromey's avatar
Tom Tromey committed
211
    char_table_set_range (table, XFIXNUM (XCAR (c)), XFIXNUM (XCDR (c)), val);
212
  else
Tom Tromey's avatar
Tom Tromey committed
213
    char_table_set (table, XFIXNUM (c), val);
Kenichi Handa's avatar
Kenichi Handa committed
214 215
}

Karl Heuer's avatar
Karl Heuer committed
216 217
/* Return a copy of category table TABLE.  We can't simply use the
   function copy-sequence because no contents should be shared between
218
   the original and the copy.  This function is called recursively by
219
   binding TABLE to a sub char table.  */
Karl Heuer's avatar
Karl Heuer committed
220

221
static Lisp_Object
222
copy_category_table (Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
223
{
Kenichi Handa's avatar
Kenichi Handa committed
224
  table = copy_char_table (table);
Karl Heuer's avatar
Karl Heuer committed
225

Kenichi Handa's avatar
Kenichi Handa committed
226
  if (! NILP (XCHAR_TABLE (table)->defalt))
Paul Eggert's avatar
Paul Eggert committed
227 228
    set_char_table_defalt (table,
			   Fcopy_sequence (XCHAR_TABLE (table)->defalt));
229
  set_char_table_extras
230
    (table, 0, Fcopy_sequence (XCHAR_TABLE (table)->extras[0]));
Kenichi Handa's avatar
Kenichi Handa committed
231
  map_char_table (copy_category_entry, Qnil, table, table);
232

Karl Heuer's avatar
Karl Heuer committed
233 234 235 236 237
  return table;
}

DEFUN ("copy-category-table", Fcopy_category_table, Scopy_category_table,
       0, 1, 0,
238 239
       doc: /* Construct a new category table and return it.
It is a copy of the TABLE, which defaults to the standard category table.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
240
  (Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
241 242 243 244 245 246
{
  if (!NILP (table))
    check_category_table (table);
  else
    table = Vstandard_category_table;

247
  return copy_category_table (table);
Karl Heuer's avatar
Karl Heuer committed
248 249
}

250 251
DEFUN ("make-category-table", Fmake_category_table, Smake_category_table,
       0, 0, 0,
252
       doc: /* Construct a new and empty category table and return it.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
253
  (void)
254 255
{
  Lisp_Object val;
Kenichi Handa's avatar
Kenichi Handa committed
256
  int i;
257 258

  val = Fmake_char_table (Qcategory_table, Qnil);
Paul Eggert's avatar
Paul Eggert committed
259
  set_char_table_defalt (val, MAKE_CATEGORY_SET);
Kenichi Handa's avatar
Kenichi Handa committed
260
  for (i = 0; i < (1 << CHARTAB_SIZE_BITS_0); i++)
261
    set_char_table_contents (val, i, MAKE_CATEGORY_SET);
262
  Fset_char_table_extra_slot (val, make_fixnum (0), make_nil_vector (95));
263 264 265
  return val;
}

Karl Heuer's avatar
Karl Heuer committed
266
DEFUN ("set-category-table", Fset_category_table, Sset_category_table, 1, 1, 0,
Kenichi Handa's avatar
Kenichi Handa committed
267 268
       doc: /* Specify TABLE as the category table for the current buffer.
Return TABLE.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
269
  (Lisp_Object table)
Karl Heuer's avatar
Karl Heuer committed
270
{
271
  int idx;
Karl Heuer's avatar
Karl Heuer committed
272
  table = check_category_table (table);
Paul Eggert's avatar
Paul Eggert committed
273
  bset_category_table (current_buffer, table);
Karl Heuer's avatar
Karl Heuer committed
274
  /* Indicate that this buffer now has a specified category table.  */
Gerd Moellmann's avatar
Gerd Moellmann committed
275 276
  idx = PER_BUFFER_VAR_IDX (category_table);
  SET_PER_BUFFER_VALUE_P (current_buffer, idx, 1);
Karl Heuer's avatar
Karl Heuer committed
277 278 279 280
  return table;
}


Kenichi Handa's avatar
Kenichi Handa committed
281
Lisp_Object
282
char_category_set (int c)
Kenichi Handa's avatar
Kenichi Handa committed
283
{
Tom Tromey's avatar
Tom Tromey committed
284
  return CHAR_TABLE_REF (BVAR (current_buffer, category_table), c);
Kenichi Handa's avatar
Kenichi Handa committed
285 286
}

Karl Heuer's avatar
Karl Heuer committed
287
DEFUN ("char-category-set", Fchar_category_set, Schar_category_set, 1, 1, 0,
288 289
       doc: /* Return the category set of CHAR.
usage: (char-category-set CHAR)  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
290
  (Lisp_Object ch)
Karl Heuer's avatar
Karl Heuer committed
291
{
292
  CHECK_CHARACTER (ch);
Tom Tromey's avatar
Tom Tromey committed
293
  return CATEGORY_SET (XFIXNAT (ch));
Karl Heuer's avatar
Karl Heuer committed
294 295 296 297
}

DEFUN ("category-set-mnemonics", Fcategory_set_mnemonics,
       Scategory_set_mnemonics, 1, 1, 0,
298 299
       doc: /* Return a string containing mnemonics of the categories in CATEGORY-SET.
CATEGORY-SET is a bool-vector, and the categories \"in\" it are those
Kenichi Handa's avatar
Kenichi Handa committed
300
that are indexes where t occurs in the bool-vector.
301
The return value is a string containing those same categories.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
302
  (Lisp_Object category_set)
Karl Heuer's avatar
Karl Heuer committed
303 304 305 306
{
  int i, j;
  char str[96];

307
  CHECK_CATEGORY_SET (category_set);
Karl Heuer's avatar
Karl Heuer committed
308 309 310 311 312 313 314 315 316 317 318 319

  j = 0;
  for (i = 32; i < 127; i++)
    if (CATEGORY_MEMBER (i, category_set))
      str[j++] = i;
  str[j] = '\0';

  return build_string (str);
}

DEFUN ("modify-category-entry", Fmodify_category_entry,
       Smodify_category_entry, 2, 4, 0,
320 321
       doc: /* Modify the category set of CHARACTER by adding CATEGORY to it.
The category is changed only for table TABLE, which defaults to
322 323 324
the current buffer's category table.
CHARACTER can be either a single character or a cons representing the
lower and upper ends of an inclusive character range to modify.
325 326
CATEGORY must be a category name (a character between ` ' and `~').
Use `describe-categories' to see existing category names.
327 328
If optional fourth argument RESET is non-nil,
then delete CATEGORY from the category set instead of adding it.  */)
Dan Nicolaescu's avatar
Dan Nicolaescu committed
329
  (Lisp_Object character, Lisp_Object category, Lisp_Object table, Lisp_Object reset)
Karl Heuer's avatar
Karl Heuer committed
330
{
331
  bool set_value;	/* Actual value to be set in category sets.  */
332
  Lisp_Object category_set;
Kenichi Handa's avatar
Kenichi Handa committed
333 334
  int start, end;
  int from, to;
Karl Heuer's avatar
Karl Heuer committed
335

336
  if (FIXNUMP (character))
Karl Heuer's avatar
Karl Heuer committed
337
    {
Kenichi Handa's avatar
Kenichi Handa committed
338
      CHECK_CHARACTER (character);
Tom Tromey's avatar
Tom Tromey committed
339
      start = end = XFIXNAT (character);
Karl Heuer's avatar
Karl Heuer committed
340
    }
Kenichi Handa's avatar
Kenichi Handa committed
341
  else
Karl Heuer's avatar
Karl Heuer committed
342
    {
Kenichi Handa's avatar
Kenichi Handa committed
343
      CHECK_CONS (character);
Kenichi Handa's avatar
Kenichi Handa committed
344 345
      CHECK_CHARACTER_CAR (character);
      CHECK_CHARACTER_CDR (character);
Tom Tromey's avatar
Tom Tromey committed
346 347
      start = XFIXNAT (XCAR (character));
      end = XFIXNAT (XCDR (character));
Karl Heuer's avatar
Karl Heuer committed
348 349
    }

350
  CHECK_CATEGORY (category);
Karl Heuer's avatar
Karl Heuer committed
351 352
  table = check_category_table (table);

Tom Tromey's avatar
Tom Tromey committed
353 354
  if (NILP (CATEGORY_DOCSTRING (table, XFIXNAT (category))))
    error ("Undefined category: %c", (int) XFIXNAT (category));
Karl Heuer's avatar
Karl Heuer committed
355

356
  set_value = NILP (reset);
Karl Heuer's avatar
Karl Heuer committed
357

Kenichi Handa's avatar
Kenichi Handa committed
358
  while (start <= end)
Karl Heuer's avatar
Karl Heuer committed
359
    {
360
      from = start, to = end;
Kenichi Handa's avatar
Kenichi Handa committed
361
      category_set = char_table_ref_and_range (table, start, &from, &to);
Tom Tromey's avatar
Tom Tromey committed
362
      if (CATEGORY_MEMBER (XFIXNAT (category), category_set) != NILP (reset))
Kenichi Handa's avatar
Kenichi Handa committed
363
	{
364
	  category_set = Fcopy_sequence (category_set);
Tom Tromey's avatar
Tom Tromey committed
365
	  set_category_set (category_set, XFIXNAT (category), set_value);
366 367
	  category_set = hash_get_category_set (table, category_set);
	  char_table_set_range (table, start, to, category_set);
Kenichi Handa's avatar
Kenichi Handa committed
368 369
	}
      start = to + 1;
Karl Heuer's avatar
Karl Heuer committed
370 371 372 373 374
    }

  return Qnil;
}

375 376
/* Return true if there is a word boundary between two word-constituent
   characters C1 and C2 if they appear in this order.
Karl Heuer's avatar
Karl Heuer committed
377 378 379
   Use the macro WORD_BOUNDARY_P instead of calling this function
   directly.  */

380
bool
381
word_boundary_p (int c1, int c2)
Karl Heuer's avatar
Karl Heuer committed
382 383 384
{
  Lisp_Object category_set1, category_set2;
  Lisp_Object tail;
385
  bool default_result;
Karl Heuer's avatar
Karl Heuer committed
386

387 388
  if (EQ (CHAR_TABLE_REF (Vchar_script_table, c1),
	  CHAR_TABLE_REF (Vchar_script_table, c2)))
Karl Heuer's avatar
Karl Heuer committed
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
    {
      tail = Vword_separating_categories;
      default_result = 0;
    }
  else
    {
      tail = Vword_combining_categories;
      default_result = 1;
    }

  category_set1 = CATEGORY_SET (c1);
  if (NILP (category_set1))
    return default_result;
  category_set2 = CATEGORY_SET (c2);
  if (NILP (category_set2))
    return default_result;

406
  for (; CONSP (tail); tail = XCDR (tail))
Karl Heuer's avatar
Karl Heuer committed
407
    {
408
      Lisp_Object elt = XCAR (tail);
Karl Heuer's avatar
Karl Heuer committed
409 410

      if (CONSP (elt)
411 412
	  && (NILP (XCAR (elt))
	      || (CATEGORYP (XCAR (elt))
Tom Tromey's avatar
Tom Tromey committed
413 414
		  && CATEGORY_MEMBER (XFIXNAT (XCAR (elt)), category_set1)
		  && ! CATEGORY_MEMBER (XFIXNAT (XCAR (elt)), category_set2)))
415 416
	  && (NILP (XCDR (elt))
	      || (CATEGORYP (XCDR (elt))
Tom Tromey's avatar
Tom Tromey committed
417 418
		  && ! CATEGORY_MEMBER (XFIXNAT (XCDR (elt)), category_set1)
		  && CATEGORY_MEMBER (XFIXNAT (XCDR (elt)), category_set2))))
Karl Heuer's avatar
Karl Heuer committed
419 420 421 422 423 424
	return !default_result;
    }
  return default_result;
}


Andreas Schwab's avatar
Andreas Schwab committed
425
void
426
init_category_once (void)
Karl Heuer's avatar
Karl Heuer committed
427 428
{
  /* This has to be done here, before we call Fmake_char_table.  */
429
  DEFSYM (Qcategory_table, "category-table");
430
  Fput (Qcategory_table, Qchar_table_extra_slots, make_fixnum (2));
Karl Heuer's avatar
Karl Heuer committed
431 432

  Vstandard_category_table = Fmake_char_table (Qcategory_table, Qnil);
433
  /* Set a category set which contains nothing to the default.  */
Paul Eggert's avatar
Paul Eggert committed
434
  set_char_table_defalt (Vstandard_category_table, MAKE_CATEGORY_SET);
435
  Fset_char_table_extra_slot (Vstandard_category_table, make_fixnum (0),
436
			      make_nil_vector (95));
Karl Heuer's avatar
Karl Heuer committed
437 438
}

Andreas Schwab's avatar
Andreas Schwab committed
439
void
440
syms_of_category (void)
Karl Heuer's avatar
Karl Heuer committed
441
{
442 443 444
  DEFSYM (Qcategoryp, "categoryp");
  DEFSYM (Qcategorysetp, "categorysetp");
  DEFSYM (Qcategory_table_p, "category-table-p");
Karl Heuer's avatar
Karl Heuer committed
445

446
  DEFVAR_LISP ("word-combining-categories", Vword_combining_categories,
447 448 449
	       doc: /* List of pair (cons) of categories to determine word boundary.

Emacs treats a sequence of word constituent characters as a single
Glenn Morris's avatar
Glenn Morris committed
450
word (i.e. finds no word boundary between them) only if they belong to
451
the same script.  But, exceptions are allowed in the following cases.
452

453
\(1) The case that characters are in different scripts is controlled
454 455
by the variable `word-combining-categories'.

456
Emacs finds no word boundary between characters of different scripts
457 458 459 460 461 462
if they have categories matching some element of this list.

More precisely, if an element of this list is a cons of category CAT1
and CAT2, and a multibyte character C1 which has CAT1 is followed by
C2 which has CAT2, there's no word boundary between C1 and C2.

463 464 465
For instance, to tell that Han characters followed by Hiragana
characters can form a single word, the element `(?C . ?H)' should be
in this list.
466

467
\(2) The case that character are in the same script is controlled by
468 469
the variable `word-separating-categories'.

470
Emacs finds a word boundary between characters of the same script
471 472 473
if they have categories matching some element of this list.

More precisely, if an element of this list is a cons of category CAT1
474 475 476
and CAT2, and a multibyte character C1 which has CAT1 but not CAT2 is
followed by C2 which has CAT2 but not CAT1, there's a word boundary
between C1 and C2.
477

478 479
For instance, to tell that there's a word boundary between Hiragana
and Katakana (both are in the same script `kana'),
Paul Eggert's avatar
Paul Eggert committed
480
the element `(?H . ?K)' should be in this list.  */);
Karl Heuer's avatar
Karl Heuer committed
481 482 483

  Vword_combining_categories = Qnil;

484
  DEFVAR_LISP ("word-separating-categories", Vword_separating_categories,
485 486
	       doc: /* List of pair (cons) of categories to determine word boundary.
See the documentation of the variable `word-combining-categories'.  */);
Karl Heuer's avatar
Karl Heuer committed
487 488 489 490 491 492 493 494 495 496 497

  Vword_separating_categories = Qnil;

  defsubr (&Smake_category_set);
  defsubr (&Sdefine_category);
  defsubr (&Scategory_docstring);
  defsubr (&Sget_unused_category);
  defsubr (&Scategory_table_p);
  defsubr (&Scategory_table);
  defsubr (&Sstandard_category_table);
  defsubr (&Scopy_category_table);
498
  defsubr (&Smake_category_table);
Karl Heuer's avatar
Karl Heuer committed
499 500 501 502 503
  defsubr (&Sset_category_table);
  defsubr (&Schar_category_set);
  defsubr (&Scategory_set_mnemonics);
  defsubr (&Smodify_category_entry);
}