diff options
| author | Kenichi Handa | 2000-11-06 12:35:27 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2000-11-06 12:35:27 +0000 |
| commit | 40add26d11b5446339255f1eb99aa18e9ce1c3a7 (patch) | |
| tree | 408693afb7a28c3ee5aaf86ffe587e608e369c0f /src | |
| parent | c9a7baeea13e58584cc6a5a5848a9c10233e1665 (diff) | |
| download | emacs-40add26d11b5446339255f1eb99aa18e9ce1c3a7.tar.gz emacs-40add26d11b5446339255f1eb99aa18e9ce1c3a7.zip | |
(Vcomposition_function_table): New variable.
(Qcomposition_function_table): New variable.
(run_composition_function): Call
Vcompose_chars_after_function with three arguments.
(compose_chars_in_text): New function.
(syms_of_composite): Modified the doc-string of
Vcompose_chars_after_function. Declare composition-function-table
as a lisp variable, and initialize it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/composite.c | 156 |
1 files changed, 151 insertions, 5 deletions
diff --git a/src/composite.c b/src/composite.c index 41f89fd6024..3379d594d28 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -144,6 +144,10 @@ Lisp_Object composition_hash_table; | |||
| 144 | /* Function to call to adjust composition. */ | 144 | /* Function to call to adjust composition. */ |
| 145 | Lisp_Object Vcompose_chars_after_function; | 145 | Lisp_Object Vcompose_chars_after_function; |
| 146 | 146 | ||
| 147 | /* Char-table of patterns and functions to make a composition. */ | ||
| 148 | Lisp_Object Vcomposition_function_table; | ||
| 149 | Lisp_Object Qcomposition_function_table; | ||
| 150 | |||
| 147 | /* Temporary variable used in macros COMPOSITION_XXX. */ | 151 | /* Temporary variable used in macros COMPOSITION_XXX. */ |
| 148 | Lisp_Object composition_temp; | 152 | Lisp_Object composition_temp; |
| 149 | 153 | ||
| @@ -455,8 +459,8 @@ run_composition_function (from, to, prop) | |||
| 455 | if (!NILP (func)) | 459 | if (!NILP (func)) |
| 456 | call2 (func, make_number (from), make_number (to)); | 460 | call2 (func, make_number (from), make_number (to)); |
| 457 | else if (!NILP (Ffboundp (Vcompose_chars_after_function))) | 461 | else if (!NILP (Ffboundp (Vcompose_chars_after_function))) |
| 458 | call2 (Vcompose_chars_after_function, | 462 | call3 (Vcompose_chars_after_function, |
| 459 | make_number (from), make_number (to)); | 463 | make_number (from), make_number (to), Qnil); |
| 460 | } | 464 | } |
| 461 | 465 | ||
| 462 | /* Make invalid compositions adjacent to or inside FROM and TO valid. | 466 | /* Make invalid compositions adjacent to or inside FROM and TO valid. |
| @@ -576,6 +580,123 @@ compose_text (start, end, components, modification_func, string) | |||
| 576 | Qcomposition, prop, string); | 580 | Qcomposition, prop, string); |
| 577 | } | 581 | } |
| 578 | 582 | ||
| 583 | /* Compose sequences of characters in the region between START and END | ||
| 584 | by functions registered in Vcomposition_function_table. If STRING | ||
| 585 | is non-nil, operate on characters contained between indices START | ||
| 586 | and END in STRING. */ | ||
| 587 | |||
| 588 | void | ||
| 589 | compose_chars_in_text (start, end, string) | ||
| 590 | int start, end; | ||
| 591 | Lisp_Object string; | ||
| 592 | { | ||
| 593 | int count; | ||
| 594 | struct gcpro gcpro1; | ||
| 595 | Lisp_Object tail, elt, val, to; | ||
| 596 | /* Set to nonzero if we don't have to compose ASCII characters. */ | ||
| 597 | int skip_ascii; | ||
| 598 | int i, len, stop, c; | ||
| 599 | unsigned char *ptr, *pend; | ||
| 600 | |||
| 601 | if (! CHAR_TABLE_P (Vcomposition_function_table)) | ||
| 602 | return; | ||
| 603 | |||
| 604 | if (STRINGP (string)) | ||
| 605 | { | ||
| 606 | count = specpdl_ptr - specpdl; | ||
| 607 | GCPRO1 (string); | ||
| 608 | stop = end; | ||
| 609 | ptr = XSTRING (string)->data + string_char_to_byte (string, start); | ||
| 610 | pend = ptr + STRING_BYTES (XSTRING (string)); | ||
| 611 | } | ||
| 612 | else | ||
| 613 | { | ||
| 614 | record_unwind_protect (save_excursion_restore, save_excursion_save ()); | ||
| 615 | TEMP_SET_PT (start); | ||
| 616 | stop = (start < GPT && GPT < end ? GPT : end); | ||
| 617 | ptr = CHAR_POS_ADDR (start); | ||
| 618 | pend = CHAR_POS_ADDR (end); | ||
| 619 | } | ||
| 620 | |||
| 621 | /* Preserve the match data. */ | ||
| 622 | record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); | ||
| 623 | |||
| 624 | /* If none of ASCII characters have composition functions, we can | ||
| 625 | skip them quickly. */ | ||
| 626 | for (i = 0; i < 128; i++) | ||
| 627 | if (!NILP (CHAR_TABLE_REF (Vcomposition_function_table, i))) | ||
| 628 | break; | ||
| 629 | skip_ascii = (i == 128); | ||
| 630 | |||
| 631 | |||
| 632 | while (1) | ||
| 633 | { | ||
| 634 | if (skip_ascii) | ||
| 635 | while (start < stop && ASCII_BYTE_P (*ptr)) | ||
| 636 | start++, ptr++; | ||
| 637 | |||
| 638 | if (start >= stop) | ||
| 639 | { | ||
| 640 | if (stop == end || start >= end) | ||
| 641 | break; | ||
| 642 | stop = end; | ||
| 643 | if (STRINGP (string)) | ||
| 644 | ptr = XSTRING (string)->data + string_char_to_byte (string, start); | ||
| 645 | else | ||
| 646 | ptr = CHAR_POS_ADDR (start); | ||
| 647 | } | ||
| 648 | |||
| 649 | c = STRING_CHAR_AND_LENGTH (ptr, pend - ptr, len); | ||
| 650 | tail = CHAR_TABLE_REF (Vcomposition_function_table, c); | ||
| 651 | while (CONSP (tail)) | ||
| 652 | { | ||
| 653 | elt = XCAR (tail); | ||
| 654 | if (CONSP (elt) | ||
| 655 | && STRINGP (XCAR (elt)) | ||
| 656 | && !NILP (Ffboundp (XCDR (elt)))) | ||
| 657 | { | ||
| 658 | if (STRINGP (string)) | ||
| 659 | val = Fstring_match (XCAR (elt), string, make_number (start)); | ||
| 660 | else | ||
| 661 | { | ||
| 662 | val = Flooking_at (XCAR (elt)); | ||
| 663 | if (!NILP (val)) | ||
| 664 | val = make_number (start); | ||
| 665 | } | ||
| 666 | if (INTEGERP (val) && XFASTINT (val) == start) | ||
| 667 | { | ||
| 668 | to = Fmatch_end (make_number (0)); | ||
| 669 | val = call4 (XCDR (elt), val, to, XCAR (elt), string); | ||
| 670 | if (INTEGERP (val) && XINT (val) > 1) | ||
| 671 | { | ||
| 672 | start += XINT (val); | ||
| 673 | if (STRINGP (string)) | ||
| 674 | ptr = XSTRING (string)->data + string_char_to_byte (string, start); | ||
| 675 | else | ||
| 676 | ptr = CHAR_POS_ADDR (start); | ||
| 677 | } | ||
| 678 | else | ||
| 679 | { | ||
| 680 | start++; | ||
| 681 | ptr += len; | ||
| 682 | } | ||
| 683 | break; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | tail = XCDR (tail); | ||
| 687 | } | ||
| 688 | if (!CONSP (tail)) | ||
| 689 | { | ||
| 690 | /* No composition done. Try the next character. */ | ||
| 691 | start++; | ||
| 692 | ptr += len; | ||
| 693 | } | ||
| 694 | } | ||
| 695 | |||
| 696 | unbind_to (count, Qnil); | ||
| 697 | if (STRINGP (string)) | ||
| 698 | UNGCPRO; | ||
| 699 | } | ||
| 579 | 700 | ||
| 580 | /* Emacs Lisp APIs. */ | 701 | /* Emacs Lisp APIs. */ |
| 581 | 702 | ||
| @@ -717,16 +838,41 @@ syms_of_composite () | |||
| 717 | DEFVAR_LISP ("compose-chars-after-function", &Vcompose_chars_after_function, | 838 | DEFVAR_LISP ("compose-chars-after-function", &Vcompose_chars_after_function, |
| 718 | "Function to adjust composition of buffer text.\n\ | 839 | "Function to adjust composition of buffer text.\n\ |
| 719 | \n\ | 840 | \n\ |
| 841 | The function is called with three arguments FROM, TO, and OBJECT.\n\ | ||
| 842 | FROM and TO specify the range of text of which composition should be\n\ | ||
| 843 | adjusted. OBJECT, if non-nil, is a string that contains the text.\n\ | ||
| 844 | \n\ | ||
| 720 | This function is called after a text with `composition' property is\n\ | 845 | This function is called after a text with `composition' property is\n\ |
| 721 | inserted or deleted to keep `composition' property of buffer text\n\ | 846 | inserted or deleted to keep `composition' property of buffer text\n\ |
| 722 | valid.\n\ | 847 | valid.\n\ |
| 723 | \n\ | 848 | \n\ |
| 724 | The function is called with two arguments FROM and TO. They specify\n\ | ||
| 725 | the range of text of which composition should be adjusted.\n\ | ||
| 726 | \n\ | ||
| 727 | The default value is the function `compose-chars-after'."); | 849 | The default value is the function `compose-chars-after'."); |
| 728 | Vcompose_chars_after_function = intern ("compose-chars-after"); | 850 | Vcompose_chars_after_function = intern ("compose-chars-after"); |
| 729 | 851 | ||
| 852 | Qcomposition_function_table = intern ("composition-function-table"); | ||
| 853 | staticpro (&Qcomposition_function_table); | ||
| 854 | |||
| 855 | /* Intern this now in case it isn't already done. | ||
| 856 | Setting this variable twice is harmless. | ||
| 857 | But don't staticpro it here--that is done in alloc.c. */ | ||
| 858 | Qchar_table_extra_slots = intern ("char-table-extra-slots"); | ||
| 859 | |||
| 860 | Fput (Qcomposition_function_table, Qchar_table_extra_slots, make_number (0)); | ||
| 861 | |||
| 862 | DEFVAR_LISP ("composition-function-table", &Vcomposition_function_table, | ||
| 863 | "Char table of patterns and functions to make a composition.\n\ | ||
| 864 | \n\ | ||
| 865 | Each element is nil or an alist of PATTERNs vs FUNCs, where PATTERNs\n\ | ||
| 866 | are regular expressions and FUNCs are functions. FUNC is responsible\n\ | ||
| 867 | for composing text matching the corresponding PATTERN. FUNC is called\n\ | ||
| 868 | with three arguments FROM, TO, and PATTERN. See the function\n\ | ||
| 869 | `compose-chars-after' for more detail.\n\ | ||
| 870 | \n\ | ||
| 871 | This table is looked up by the first character of a composition when\n\ | ||
| 872 | the composition gets invalid after a change in a buffer."); | ||
| 873 | Vcomposition_function_table | ||
| 874 | = Fmake_char_table (Qcomposition_function_table, Qnil); | ||
| 875 | |||
| 730 | defsubr (&Scompose_region_internal); | 876 | defsubr (&Scompose_region_internal); |
| 731 | defsubr (&Scompose_string_internal); | 877 | defsubr (&Scompose_string_internal); |
| 732 | defsubr (&Sfind_composition_internal); | 878 | defsubr (&Sfind_composition_internal); |