Mercurial > emacs
comparison src/editfns.c @ 54213:29d4d158e5eb
(Ftranslate_region): Handle multibyte chars in the arg
TABLE correctly.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Mon, 01 Mar 2004 06:19:10 +0000 |
parents | a3fe35a8b56b |
children | a2f5ab3b6d1b |
comparison
equal
deleted
inserted
replaced
54212:ba850aa09d2d | 54213:29d4d158e5eb |
---|---|
2739 | 2739 |
2740 DEFUN ("translate-region", Ftranslate_region, Stranslate_region, 3, 3, 0, | 2740 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; |
2748 Lisp_Object end; | 2747 Lisp_Object end; |
2749 register Lisp_Object table; | 2748 register Lisp_Object table; |
2753 register int nc; /* New character. */ | 2752 register int nc; /* New character. */ |
2754 int cnt; /* Number of changes made. */ | 2753 int cnt; /* Number of changes made. */ |
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)); |
2766 stop = CHAR_TO_BYTE (XINT (end)); | 2772 stop = CHAR_TO_BYTE (XINT (end)); |
2767 modify_region (current_buffer, XINT (start), XINT (end)); | 2773 modify_region (current_buffer, XINT (start), XINT (end)); |
2769 | 2775 |
2770 cnt = 0; | 2776 cnt = 0; |
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 |
2778 if (multibyte) | 2785 if (multibyte) |
2779 oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len); | 2786 oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len); |
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, |
2802 1, 0, 1); | 2814 1, 0, 1); |
2803 pos_byte_next = CHAR_TO_BYTE (pos); | 2815 pos_byte_next = CHAR_TO_BYTE (pos); |
2810 INC_POS (pos_byte_next); | 2822 INC_POS (pos_byte_next); |
2811 } | 2823 } |
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 } |
2819 ++cnt; | 2832 ++cnt; |
2820 } | 2833 } |