diff options
| -rw-r--r-- | src/category.c | 213 |
1 files changed, 61 insertions, 152 deletions
diff --git a/src/category.c b/src/category.c index bbd4686ed86..cc9be2a0c86 100644 --- a/src/category.c +++ b/src/category.c | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | /* GNU Emacs routines to deal with category tables. | 1 | /* GNU Emacs routines to deal with category tables. |
| 2 | Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. | 2 | Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN. |
| 3 | Licensed to the Free Software Foundation. | 3 | Licensed to the Free Software Foundation. |
| 4 | Copyright (C) 2001, 2002 | ||
| 5 | National Institute of Advanced Industrial Science and Technology (AIST) | ||
| 6 | Registration Number H13PRO009 | ||
| 4 | 7 | ||
| 5 | This file is part of GNU Emacs. | 8 | This file is part of GNU Emacs. |
| 6 | 9 | ||
| @@ -27,6 +30,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 27 | #include <ctype.h> | 30 | #include <ctype.h> |
| 28 | #include "lisp.h" | 31 | #include "lisp.h" |
| 29 | #include "buffer.h" | 32 | #include "buffer.h" |
| 33 | #include "character.h" | ||
| 30 | #include "charset.h" | 34 | #include "charset.h" |
| 31 | #include "category.h" | 35 | #include "category.h" |
| 32 | #include "keymap.h" | 36 | #include "keymap.h" |
| @@ -186,6 +190,15 @@ This is the one used for new buffers. */) | |||
| 186 | return Vstandard_category_table; | 190 | return Vstandard_category_table; |
| 187 | } | 191 | } |
| 188 | 192 | ||
| 193 | |||
| 194 | static void | ||
| 195 | copy_category_entry (table, range, val) | ||
| 196 | Lisp_Object table, range, val; | ||
| 197 | { | ||
| 198 | char_table_set_range (table, XINT (XCAR (range)), XINT (XCDR (range)), | ||
| 199 | Fcopy_sequence (val)); | ||
| 200 | } | ||
| 201 | |||
| 189 | /* Return a copy of category table TABLE. We can't simply use the | 202 | /* Return a copy of category table TABLE. We can't simply use the |
| 190 | function copy-sequence because no contents should be shared between | 203 | function copy-sequence because no contents should be shared between |
| 191 | the original and the copy. This function is called recursively by | 204 | the original and the copy. This function is called recursively by |
| @@ -195,44 +208,15 @@ Lisp_Object | |||
| 195 | copy_category_table (table) | 208 | copy_category_table (table) |
| 196 | Lisp_Object table; | 209 | Lisp_Object table; |
| 197 | { | 210 | { |
| 198 | Lisp_Object tmp; | 211 | table = copy_char_table (table); |
| 199 | int i, to; | ||
| 200 | 212 | ||
| 201 | if (!NILP (XCHAR_TABLE (table)->top)) | 213 | if (! NILP (XCHAR_TABLE (table)->defalt)) |
| 202 | { | 214 | XCHAR_TABLE (table)->defalt |
| 203 | /* TABLE is a top level char table. | 215 | = Fcopy_sequence (XCHAR_TABLE (table)->defalt); |
| 204 | At first, make a copy of tree structure of the table. */ | 216 | XCHAR_TABLE (table)->extras[0] |
| 205 | table = Fcopy_sequence (table); | 217 | = Fcopy_sequence (XCHAR_TABLE (table)->extras[0]); |
| 206 | |||
| 207 | /* Then, copy elements for single byte characters one by one. */ | ||
| 208 | for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++) | ||
| 209 | if (!NILP (tmp = XCHAR_TABLE (table)->contents[i])) | ||
| 210 | XCHAR_TABLE (table)->contents[i] = Fcopy_sequence (tmp); | ||
| 211 | to = CHAR_TABLE_ORDINARY_SLOTS; | ||
| 212 | |||
| 213 | /* Also copy the first (and sole) extra slot. It is a vector | ||
| 214 | containing docstring of each category. */ | ||
| 215 | Fset_char_table_extra_slot | ||
| 216 | (table, make_number (0), | ||
| 217 | Fcopy_sequence (Fchar_table_extra_slot (table, make_number (0)))); | ||
| 218 | } | ||
| 219 | else | ||
| 220 | { | ||
| 221 | i = 32; | ||
| 222 | to = SUB_CHAR_TABLE_ORDINARY_SLOTS; | ||
| 223 | } | ||
| 224 | |||
| 225 | /* If the table has non-nil default value, copy it. */ | ||
| 226 | if (!NILP (tmp = XCHAR_TABLE (table)->defalt)) | ||
| 227 | XCHAR_TABLE (table)->defalt = Fcopy_sequence (tmp); | ||
| 228 | 218 | ||
| 229 | /* At last, copy the remaining elements while paying attention to a | 219 | map_char_table (copy_category_entry, Qnil, table, table, 0, NULL); |
| 230 | sub char table. */ | ||
| 231 | for (; i < to; i++) | ||
| 232 | if (!NILP (tmp = XCHAR_TABLE (table)->contents[i])) | ||
| 233 | XCHAR_TABLE (table)->contents[i] | ||
| 234 | = (SUB_CHAR_TABLE_P (tmp) | ||
| 235 | ? copy_category_table (tmp) : Fcopy_sequence (tmp)); | ||
| 236 | 220 | ||
| 237 | return table; | 221 | return table; |
| 238 | } | 222 | } |
| @@ -258,9 +242,12 @@ DEFUN ("make-category-table", Fmake_category_table, Smake_category_table, | |||
| 258 | () | 242 | () |
| 259 | { | 243 | { |
| 260 | Lisp_Object val; | 244 | Lisp_Object val; |
| 245 | int i; | ||
| 261 | 246 | ||
| 262 | val = Fmake_char_table (Qcategory_table, Qnil); | 247 | val = Fmake_char_table (Qcategory_table, Qnil); |
| 263 | XCHAR_TABLE (val)->defalt = MAKE_CATEGORY_SET; | 248 | XCHAR_TABLE (val)->defalt = MAKE_CATEGORY_SET; |
| 249 | for (i = 0; i < (1 << CHARTAB_SIZE_BITS_0); i++) | ||
| 250 | XCHAR_TABLE (val)->contents[i] = MAKE_CATEGORY_SET; | ||
| 264 | Fset_char_table_extra_slot (val, make_number (0), | 251 | Fset_char_table_extra_slot (val, make_number (0), |
| 265 | Fmake_vector (make_number (95), Qnil)); | 252 | Fmake_vector (make_number (95), Qnil)); |
| 266 | return val; | 253 | return val; |
| @@ -281,6 +268,13 @@ DEFUN ("set-category-table", Fset_category_table, Sset_category_table, 1, 1, 0, | |||
| 281 | } | 268 | } |
| 282 | 269 | ||
| 283 | 270 | ||
| 271 | Lisp_Object | ||
| 272 | char_category_set (c) | ||
| 273 | int c; | ||
| 274 | { | ||
| 275 | return CHAR_TABLE_REF (current_buffer->category_table, c); | ||
| 276 | } | ||
| 277 | |||
| 284 | DEFUN ("char-category-set", Fchar_category_set, Schar_category_set, 1, 1, 0, | 278 | DEFUN ("char-category-set", Fchar_category_set, Schar_category_set, 1, 1, 0, |
| 285 | doc: /* Return the category set of CHAR. */) | 279 | doc: /* Return the category set of CHAR. */) |
| 286 | (ch) | 280 | (ch) |
| @@ -313,34 +307,6 @@ The return value is a string containing those same categories. */) | |||
| 313 | return build_string (str); | 307 | return build_string (str); |
| 314 | } | 308 | } |
| 315 | 309 | ||
| 316 | /* Modify all category sets stored under sub char-table TABLE so that | ||
| 317 | they contain (SET_VALUE is t) or don't contain (SET_VALUE is nil) | ||
| 318 | CATEGORY. */ | ||
| 319 | |||
| 320 | void | ||
| 321 | modify_lower_category_set (table, category, set_value) | ||
| 322 | Lisp_Object table, category, set_value; | ||
| 323 | { | ||
| 324 | Lisp_Object val; | ||
| 325 | int i; | ||
| 326 | |||
| 327 | val = XCHAR_TABLE (table)->defalt; | ||
| 328 | if (!CATEGORY_SET_P (val)) | ||
| 329 | val = MAKE_CATEGORY_SET; | ||
| 330 | SET_CATEGORY_SET (val, category, set_value); | ||
| 331 | XCHAR_TABLE (table)->defalt = val; | ||
| 332 | |||
| 333 | for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++) | ||
| 334 | { | ||
| 335 | val = XCHAR_TABLE (table)->contents[i]; | ||
| 336 | |||
| 337 | if (CATEGORY_SET_P (val)) | ||
| 338 | SET_CATEGORY_SET (val, category, set_value); | ||
| 339 | else if (SUB_CHAR_TABLE_P (val)) | ||
| 340 | modify_lower_category_set (val, category, set_value); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | void | 310 | void |
| 345 | set_category_set (category_set, category, val) | 311 | set_category_set (category_set, category, val) |
| 346 | Lisp_Object category_set, category, val; | 312 | Lisp_Object category_set, category, val; |
| @@ -369,9 +335,23 @@ then delete CATEGORY from the category set instead of adding it. */) | |||
| 369 | int c, charset, c1, c2; | 335 | int c, charset, c1, c2; |
| 370 | Lisp_Object set_value; /* Actual value to be set in category sets. */ | 336 | Lisp_Object set_value; /* Actual value to be set in category sets. */ |
| 371 | Lisp_Object val, category_set; | 337 | Lisp_Object val, category_set; |
| 338 | int start, end; | ||
| 339 | int from, to; | ||
| 340 | |||
| 341 | if (INTEGERP (character)) | ||
| 342 | { | ||
| 343 | CHECK_CHARACTER (character); | ||
| 344 | start = end = XFASTINT (character); | ||
| 345 | } | ||
| 346 | else | ||
| 347 | { | ||
| 348 | CHECK_CONS (character); | ||
| 349 | CHECK_CHARACTER (XCAR (character)); | ||
| 350 | CHECK_CHARACTER (XCDR (character)); | ||
| 351 | start = XFASTINT (XCAR (character)); | ||
| 352 | end = XFASTINT (XCDR (character)); | ||
| 353 | } | ||
| 372 | 354 | ||
| 373 | CHECK_NUMBER (character); | ||
| 374 | c = XINT (character); | ||
| 375 | CHECK_CATEGORY (category); | 355 | CHECK_CATEGORY (category); |
| 376 | table = check_category_table (table); | 356 | table = check_category_table (table); |
| 377 | 357 | ||
| @@ -380,94 +360,23 @@ then delete CATEGORY from the category set instead of adding it. */) | |||
| 380 | 360 | ||
| 381 | set_value = NILP (reset) ? Qt : Qnil; | 361 | set_value = NILP (reset) ? Qt : Qnil; |
| 382 | 362 | ||
| 383 | if (c < CHAR_TABLE_SINGLE_BYTE_SLOTS) | 363 | while (start <= end) |
| 384 | { | ||
| 385 | val = XCHAR_TABLE (table)->contents[c]; | ||
| 386 | if (!CATEGORY_SET_P (val)) | ||
| 387 | XCHAR_TABLE (table)->contents[c] = (val = MAKE_CATEGORY_SET); | ||
| 388 | SET_CATEGORY_SET (val, category, set_value); | ||
| 389 | return Qnil; | ||
| 390 | } | ||
| 391 | |||
| 392 | SPLIT_CHAR (c, charset, c1, c2); | ||
| 393 | |||
| 394 | /* The top level table. */ | ||
| 395 | val = XCHAR_TABLE (table)->contents[charset + 128]; | ||
| 396 | if (CATEGORY_SET_P (val)) | ||
| 397 | category_set = val; | ||
| 398 | else if (!SUB_CHAR_TABLE_P (val)) | ||
| 399 | { | 364 | { |
| 400 | category_set = val = MAKE_CATEGORY_SET; | 365 | category_set = char_table_ref_and_range (table, start, &from, &to); |
| 401 | XCHAR_TABLE (table)->contents[charset + 128] = category_set; | 366 | if (from < start || to > end) |
| 367 | category_set = Fcopy_sequence (category_set); | ||
| 368 | SET_CATEGORY_SET (category_set, category, set_value); | ||
| 369 | if (from < start) | ||
| 370 | { | ||
| 371 | if (to > end) | ||
| 372 | char_table_set_range (table, start, end, category_set); | ||
| 373 | else | ||
| 374 | char_table_set_range (table, start, to, category_set); | ||
| 375 | } | ||
| 376 | else if (to > end) | ||
| 377 | char_table_set_range (table, start, end, category_set); | ||
| 378 | start = to + 1; | ||
| 402 | } | 379 | } |
| 403 | |||
| 404 | if (c1 <= 0) | ||
| 405 | { | ||
| 406 | /* Only a charset is specified. */ | ||
| 407 | if (SUB_CHAR_TABLE_P (val)) | ||
| 408 | /* All characters in CHARSET should be the same as for having | ||
| 409 | CATEGORY or not. */ | ||
| 410 | modify_lower_category_set (val, category, set_value); | ||
| 411 | else | ||
| 412 | SET_CATEGORY_SET (category_set, category, set_value); | ||
| 413 | return Qnil; | ||
| 414 | } | ||
| 415 | |||
| 416 | /* The second level table. */ | ||
| 417 | if (!SUB_CHAR_TABLE_P (val)) | ||
| 418 | { | ||
| 419 | val = make_sub_char_table (Qnil); | ||
| 420 | XCHAR_TABLE (table)->contents[charset + 128] = val; | ||
| 421 | /* We must set default category set of CHARSET in `defalt' slot. */ | ||
| 422 | XCHAR_TABLE (val)->defalt = category_set; | ||
| 423 | } | ||
| 424 | table = val; | ||
| 425 | |||
| 426 | val = XCHAR_TABLE (table)->contents[c1]; | ||
| 427 | if (CATEGORY_SET_P (val)) | ||
| 428 | category_set = val; | ||
| 429 | else if (!SUB_CHAR_TABLE_P (val)) | ||
| 430 | { | ||
| 431 | category_set = val = Fcopy_sequence (XCHAR_TABLE (table)->defalt); | ||
| 432 | XCHAR_TABLE (table)->contents[c1] = category_set; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (c2 <= 0) | ||
| 436 | { | ||
| 437 | if (SUB_CHAR_TABLE_P (val)) | ||
| 438 | /* All characters in C1 group of CHARSET should be the same as | ||
| 439 | for CATEGORY. */ | ||
| 440 | modify_lower_category_set (val, category, set_value); | ||
| 441 | else | ||
| 442 | SET_CATEGORY_SET (category_set, category, set_value); | ||
| 443 | return Qnil; | ||
| 444 | } | ||
| 445 | |||
| 446 | /* The third (bottom) level table. */ | ||
| 447 | if (!SUB_CHAR_TABLE_P (val)) | ||
| 448 | { | ||
| 449 | val = make_sub_char_table (Qnil); | ||
| 450 | XCHAR_TABLE (table)->contents[c1] = val; | ||
| 451 | /* We must set default category set of CHARSET and C1 in | ||
| 452 | `defalt' slot. */ | ||
| 453 | XCHAR_TABLE (val)->defalt = category_set; | ||
| 454 | } | ||
| 455 | table = val; | ||
| 456 | |||
| 457 | val = XCHAR_TABLE (table)->contents[c2]; | ||
| 458 | if (CATEGORY_SET_P (val)) | ||
| 459 | category_set = val; | ||
| 460 | else if (!SUB_CHAR_TABLE_P (val)) | ||
| 461 | { | ||
| 462 | category_set = Fcopy_sequence (XCHAR_TABLE (table)->defalt); | ||
| 463 | XCHAR_TABLE (table)->contents[c2] = category_set; | ||
| 464 | } | ||
| 465 | else | ||
| 466 | /* This should never happen. */ | ||
| 467 | error ("Invalid category table"); | ||
| 468 | |||
| 469 | SET_CATEGORY_SET (category_set, category, set_value); | ||
| 470 | |||
| 471 | return Qnil; | 380 | return Qnil; |
| 472 | } | 381 | } |
| 473 | 382 | ||