comparison src/editfns.c @ 23554:e06e84c477fa

(Fsubst_char_in_region): Correctly handle the case that byte combining before happens. (Ftranslate_region): Likewise.
author Kenichi Handa <handa@m17n.org>
date Tue, 27 Oct 1998 03:54:13 +0000
parents b6d888e0dfcc
children 077655e1e014
comparison
equal deleted inserted replaced
23553:b6d888e0dfcc 23554:e06e84c477fa
1936 { 1936 {
1937 register int pos, pos_byte, stop, i, len, end_byte; 1937 register int pos, pos_byte, stop, i, len, end_byte;
1938 int changed = 0; 1938 int changed = 0;
1939 unsigned char fromwork[4], *fromstr, towork[4], *tostr, *p; 1939 unsigned char fromwork[4], *fromstr, towork[4], *tostr, *p;
1940 int count = specpdl_ptr - specpdl; 1940 int count = specpdl_ptr - specpdl;
1941 int maybe_byte_combining = 0;
1941 1942
1942 validate_region (&start, &end); 1943 validate_region (&start, &end);
1943 CHECK_NUMBER (fromchar, 2); 1944 CHECK_NUMBER (fromchar, 2);
1944 CHECK_NUMBER (tochar, 3); 1945 CHECK_NUMBER (tochar, 3);
1945 1946
1946 if (! NILP (current_buffer->enable_multibyte_characters)) 1947 if (! NILP (current_buffer->enable_multibyte_characters))
1947 { 1948 {
1948 len = CHAR_STRING (XFASTINT (fromchar), fromwork, fromstr); 1949 len = CHAR_STRING (XFASTINT (fromchar), fromwork, fromstr);
1949 if (CHAR_STRING (XFASTINT (tochar), towork, tostr) != len) 1950 if (CHAR_STRING (XFASTINT (tochar), towork, tostr) != len)
1950 error ("Characters in subst-char-in-region have different byte-lengths"); 1951 error ("Characters in subst-char-in-region have different byte-lengths");
1952 if (len == 1)
1953 /* If *TOSTR is in the range 0x80..0x9F, it may be combined
1954 with the after bytes. If it is in the range 0xA0..0xFF, it
1955 may be combined with the before bytes. */
1956 maybe_byte_combining = !ASCII_BYTE_P (*tostr);
1951 } 1957 }
1952 else 1958 else
1953 { 1959 {
1954 len = 1; 1960 len = 1;
1955 fromwork[0] = XFASTINT (fromchar), fromstr = fromwork; 1961 fromwork[0] = XFASTINT (fromchar), fromstr = fromwork;
1978 1984
1979 if (pos_byte < GPT_BYTE) 1985 if (pos_byte < GPT_BYTE)
1980 stop = min (stop, GPT_BYTE); 1986 stop = min (stop, GPT_BYTE);
1981 while (1) 1987 while (1)
1982 { 1988 {
1989 int pos_byte_next = pos_byte;
1990
1983 if (pos_byte >= stop) 1991 if (pos_byte >= stop)
1984 { 1992 {
1985 if (pos_byte >= end_byte) break; 1993 if (pos_byte >= end_byte) break;
1986 stop = end_byte; 1994 stop = end_byte;
1987 } 1995 }
1988 p = BYTE_POS_ADDR (pos_byte); 1996 p = BYTE_POS_ADDR (pos_byte);
1989 if (p[0] == fromstr[0] 1997 INC_POS (pos_byte_next);
1998 if (pos_byte_next - pos_byte == len
1999 && p[0] == fromstr[0]
1990 && (len == 1 2000 && (len == 1
1991 || (p[1] == fromstr[1] 2001 || (p[1] == fromstr[1]
1992 && (len == 2 || (p[2] == fromstr[2] 2002 && (len == 2 || (p[2] == fromstr[2]
1993 && (len == 3 || p[3] == fromstr[3])))))) 2003 && (len == 3 || p[3] == fromstr[3]))))))
1994 { 2004 {
2007 changed = 1; 2017 changed = 1;
2008 } 2018 }
2009 2019
2010 /* Take care of the case where the new character 2020 /* Take care of the case where the new character
2011 combines with neighboring bytes. */ 2021 combines with neighboring bytes. */
2012 if (len == 1 2022 if (maybe_byte_combining
2013 && ((! CHAR_HEAD_P (tostr[0]) 2023 && (CHAR_HEAD_P (*tostr)
2014 && pos_byte > BEGV_BYTE 2024 ? ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))
2015 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1))) 2025 : (pos_byte > BEGV_BYTE
2016 || 2026 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))))
2017 (! ASCII_BYTE_P (tostr[0])
2018 && pos_byte + 1 < ZV_BYTE
2019 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1)))))
2020 { 2027 {
2021 Lisp_Object tem, string; 2028 Lisp_Object tem, string;
2022 2029
2023 struct gcpro gcpro1; 2030 struct gcpro gcpro1;
2024 2031
2025 tem = current_buffer->undo_list; 2032 tem = current_buffer->undo_list;
2026 GCPRO1 (tem); 2033 GCPRO1 (tem);
2027 2034
2028 /* Make a multibyte string containing this 2035 /* Make a multibyte string containing this single-byte
2029 single-byte character. */ 2036 character. */
2030 string = Fmake_string (make_number (1), 2037 string = make_multibyte_string (tostr, 1, 1);
2031 make_number (tochar));
2032 SET_STRING_BYTES (XSTRING (string), 1);
2033 /* replace_range is less efficient, because it moves the gap, 2038 /* replace_range is less efficient, because it moves the gap,
2034 but it handles combining correctly. */ 2039 but it handles combining correctly. */
2035 replace_range (pos, pos + 1, string, 2040 replace_range (pos, pos + 1, string,
2036 0, 0, 1); 2041 0, 0, 1);
2042 pos_byte_next = CHAR_TO_BYTE (pos);
2043 if (pos_byte_next > pos_byte)
2044 /* Before combining happened. We should not increment
2045 POS because now it points the next character. */
2046 pos_byte = pos_byte_next;
2047 else
2048 {
2049 pos++;
2050 INC_POS (pos_byte_next);
2051 }
2052
2037 if (! NILP (noundo)) 2053 if (! NILP (noundo))
2038 current_buffer->undo_list = tem; 2054 current_buffer->undo_list = tem;
2039 2055
2040 UNGCPRO; 2056 UNGCPRO;
2041 } 2057 }
2042 else 2058 else
2043 { 2059 {
2044 if (NILP (noundo)) 2060 if (NILP (noundo))
2045 record_change (pos, 1); 2061 record_change (pos, 1);
2046 for (i = 0; i < len; i++) *p++ = tostr[i]; 2062 for (i = 0; i < len; i++) *p++ = tostr[i];
2063 pos_byte = pos_byte_next;
2064 pos++;
2047 } 2065 }
2048 } 2066 }
2049 INC_BOTH (pos, pos_byte); 2067 else
2068 {
2069 pos_byte = pos_byte_next;
2070 pos++;
2071 }
2050 } 2072 }
2051 2073
2052 if (changed) 2074 if (changed)
2053 signal_after_change (XINT (start), 2075 signal_after_change (XINT (start),
2054 XINT (end) - XINT (start), XINT (end) - XINT (start)); 2076 XINT (end) - XINT (start), XINT (end) - XINT (start));
2090 for (; pos_byte < stop; ) 2112 for (; pos_byte < stop; )
2091 { 2113 {
2092 register unsigned char *p = BYTE_POS_ADDR (pos_byte); 2114 register unsigned char *p = BYTE_POS_ADDR (pos_byte);
2093 int len; 2115 int len;
2094 int oc; 2116 int oc;
2117 int pos_byte_next;
2095 2118
2096 oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len); 2119 oc = STRING_CHAR_AND_LENGTH (p, stop - pos_byte, len);
2120 pos_byte_next = pos_byte + len;
2097 if (oc < size && len == 1) 2121 if (oc < size && len == 1)
2098 { 2122 {
2099 nc = tt[oc]; 2123 nc = tt[oc];
2100 if (nc != oc) 2124 if (nc != oc)
2101 { 2125 {
2102 /* Take care of the case where the new character 2126 /* Take care of the case where the new character
2103 combines with neighboring bytes. */ 2127 combines with neighboring bytes. */
2104 if ((! CHAR_HEAD_P (nc) 2128 if (!ASCII_BYTE_P (nc)
2105 && pos_byte > BEGV_BYTE 2129 && (CHAR_HEAD_P (nc)
2106 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1))) 2130 ? ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))
2107 || 2131 : (pos_byte > BEGV_BYTE
2108 (! ASCII_BYTE_P (nc) 2132 && ! ASCII_BYTE_P (FETCH_BYTE (pos_byte - 1)))))
2109 && pos_byte + 1 < ZV_BYTE
2110 && ! CHAR_HEAD_P (FETCH_BYTE (pos_byte + 1))))
2111 { 2133 {
2112 Lisp_Object string; 2134 Lisp_Object string;
2113 2135
2114 string = Fmake_string (make_number (1), 2136 string = make_multibyte_string (tt + oc, 1, 1);
2115 make_number (nc));
2116 SET_STRING_BYTES (XSTRING (string), 1);
2117
2118 /* This is less efficient, because it moves the gap, 2137 /* This is less efficient, because it moves the gap,
2119 but it handles combining correctly. */ 2138 but it handles combining correctly. */
2120 replace_range (pos, pos + 1, string, 2139 replace_range (pos, pos + 1, string,
2121 1, 0, 0); 2140 1, 0, 1);
2141 pos_byte_next = CHAR_TO_BYTE (pos);
2142 if (pos_byte_next > pos_byte)
2143 /* Before combining happened. We should not
2144 increment POS because now it points the next
2145 character. */
2146 pos_byte = pos_byte_next;
2147 else
2148 {
2149 pos++;
2150 INC_POS (pos_byte_next);
2151 }
2122 } 2152 }
2123 else 2153 else
2124 { 2154 {
2125 record_change (pos, 1); 2155 record_change (pos, 1);
2126 *p = nc; 2156 *p = nc;
2127 signal_after_change (pos, 1, 1); 2157 signal_after_change (pos, 1, 1);
2158 pos_byte++;
2159 pos++;
2128 } 2160 }
2129 ++cnt; 2161 ++cnt;
2130 } 2162 }
2163 else
2164 {
2165 pos_byte++;
2166 pos++;
2167 }
2131 } 2168 }
2132 pos_byte += len; 2169 else
2133 pos++; 2170 {
2171 pos_byte += len;
2172 pos++;
2173 }
2134 } 2174 }
2135 2175
2136 return make_number (cnt); 2176 return make_number (cnt);
2137 } 2177 }
2138 2178