diff options
| author | Kenichi Handa | 2004-03-01 06:19:10 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2004-03-01 06:19:10 +0000 |
| commit | 10475277ce0d5f813792940aabbd270ebd717f02 (patch) | |
| tree | 9556da817f047dbb8f3bb694c00c96582e0bb0a3 /src | |
| parent | 83797c58bfe922c1d39fc809722260cc99c579a9 (diff) | |
| download | emacs-10475277ce0d5f813792940aabbd270ebd717f02.tar.gz emacs-10475277ce0d5f813792940aabbd270ebd717f02.zip | |
(Ftranslate_region): Handle multibyte chars in the arg
TABLE correctly.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/editfns.c b/src/editfns.c index 9a1ce81f316..31493e3c774 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -2741,7 +2741,6 @@ DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0, | |||
| 2741 | doc: /* From START to END, translate characters according to TABLE. | 2741 | doc: /* From START to END, translate characters according to TABLE. |
| 2742 | TABLE is a string; the Nth character in it is the mapping | 2742 | TABLE is a string; the Nth character in it is the mapping |
| 2743 | for the character with code N. | 2743 | for the character with code N. |
| 2744 | This function does not alter multibyte characters. | ||
| 2745 | It returns the number of characters changed. */) | 2744 | It returns the number of characters changed. */) |
| 2746 | (start, end, table) | 2745 | (start, end, table) |
| 2747 | Lisp_Object start; | 2746 | Lisp_Object start; |
| @@ -2755,11 +2754,18 @@ It returns the number of characters changed. */) | |||
| 2755 | int size; /* Size of translate table. */ | 2754 | int size; /* Size of translate table. */ |
| 2756 | int pos; | 2755 | int pos; |
| 2757 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); | 2756 | int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
| 2757 | int string_multibyte; | ||
| 2758 | 2758 | ||
| 2759 | validate_region (&start, &end); | 2759 | validate_region (&start, &end); |
| 2760 | CHECK_STRING (table); | 2760 | CHECK_STRING (table); |
| 2761 | 2761 | ||
| 2762 | size = SBYTES (table); | 2762 | if (multibyte != (SCHARS (table) < SBYTES (table))) |
| 2763 | table = (multibyte | ||
| 2764 | ? string_make_multibyte (table) | ||
| 2765 | : string_make_unibyte (table)); | ||
| 2766 | string_multibyte = SCHARS (table) < SBYTES (table); | ||
| 2767 | |||
| 2768 | size = SCHARS (table); | ||
| 2763 | tt = SDATA (table); | 2769 | tt = SDATA (table); |
| 2764 | 2770 | ||
| 2765 | pos_byte = CHAR_TO_BYTE (XINT (start)); | 2771 | pos_byte = CHAR_TO_BYTE (XINT (start)); |
| @@ -2771,7 +2777,8 @@ It returns the number of characters changed. */) | |||
| 2771 | for (; pos_byte < stop; ) | 2777 | for (; pos_byte < stop; ) |
| 2772 | { | 2778 | { |
| 2773 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); | 2779 | register unsigned char *p = BYTE_POS_ADDR (pos_byte); |
| 2774 | int len; | 2780 | unsigned char *str; |
| 2781 | int len, str_len; | ||
| 2775 | int oc; | 2782 | int oc; |
| 2776 | int pos_byte_next; | 2783 | int pos_byte_next; |
| 2777 | 2784 | ||
| @@ -2780,22 +2787,27 @@ It returns the number of characters changed. */) | |||
| 2780 | else | 2787 | else |
| 2781 | oc = *p, len = 1; | 2788 | oc = *p, len = 1; |
| 2782 | pos_byte_next = pos_byte + len; | 2789 | pos_byte_next = pos_byte + len; |
| 2783 | if (oc < size && len == 1) | 2790 | if (oc < size) |
| 2784 | { | 2791 | { |
| 2785 | nc = tt[oc]; | 2792 | if (string_multibyte) |
| 2793 | { | ||
| 2794 | str = tt + string_char_to_byte (table, oc); | ||
| 2795 | nc = STRING_CHAR_AND_LENGTH (str, MAX_MULTIBYTE_LENGTH, str_len); | ||
| 2796 | } | ||
| 2797 | else | ||
| 2798 | { | ||
| 2799 | str = tt + oc; | ||
| 2800 | nc = tt[oc], str_len = 1; | ||
| 2801 | } | ||
| 2786 | if (nc != oc) | 2802 | if (nc != oc) |
| 2787 | { | 2803 | { |
| 2788 | /* Take care of the case where the new character | 2804 | /* Take care of the case where the new character |
| 2789 | combines with neighboring bytes. */ | 2805 | combines with neighboring bytes. */ |
| 2790 | if (!ASCII_BYTE_P (nc) | 2806 | if (len > 1 || str_len > 1) |
| 2791 | && (CHAR_HEAD_P (nc) | ||
| 2792 | ? ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1)) | ||
| 2793 | : (pos_byte > BEG_BYTE | ||
| 2794 | && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1))))) | ||
| 2795 | { | 2807 | { |
| 2796 | Lisp_Object string; | 2808 | Lisp_Object string; |
| 2797 | 2809 | ||
| 2798 | string = make_multibyte_string (tt + oc, 1, 1); | 2810 | string = make_multibyte_string (str, 1, str_len); |
| 2799 | /* This is less efficient, because it moves the gap, | 2811 | /* This is less efficient, because it moves the gap, |
| 2800 | but it handles combining correctly. */ | 2812 | but it handles combining correctly. */ |
| 2801 | replace_range (pos, pos + 1, string, | 2813 | replace_range (pos, pos + 1, string, |
| @@ -2812,7 +2824,8 @@ It returns the number of characters changed. */) | |||
| 2812 | else | 2824 | else |
| 2813 | { | 2825 | { |
| 2814 | record_change (pos, 1); | 2826 | record_change (pos, 1); |
| 2815 | *p = nc; | 2827 | while (str_len-- > 0) |
| 2828 | *p++ = *str++; | ||
| 2816 | signal_after_change (pos, 1, 1); | 2829 | signal_after_change (pos, 1, 1); |
| 2817 | update_compositions (pos, pos + 1, CHECK_BORDER); | 2830 | update_compositions (pos, pos + 1, CHECK_BORDER); |
| 2818 | } | 2831 | } |