Mercurial > emacs
comparison src/casefiddle.c @ 89483:2f877ed80fa6
*** empty log message ***
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Mon, 08 Sep 2003 12:53:41 +0000 |
parents | 375f2633d815 496be2b262c6 |
children | 68c22ea6027c |
comparison
equal
deleted
inserted
replaced
88123:375f2633d815 | 89483:2f877ed80fa6 |
---|---|
20 | 20 |
21 | 21 |
22 #include <config.h> | 22 #include <config.h> |
23 #include "lisp.h" | 23 #include "lisp.h" |
24 #include "buffer.h" | 24 #include "buffer.h" |
25 #include "charset.h" | 25 #include "character.h" |
26 #include "commands.h" | 26 #include "commands.h" |
27 #include "syntax.h" | 27 #include "syntax.h" |
28 #include "composite.h" | 28 #include "composite.h" |
29 #include "keymap.h" | 29 #include "keymap.h" |
30 | 30 |
35 Lisp_Object | 35 Lisp_Object |
36 casify_object (flag, obj) | 36 casify_object (flag, obj) |
37 enum case_action flag; | 37 enum case_action flag; |
38 Lisp_Object obj; | 38 Lisp_Object obj; |
39 { | 39 { |
40 register int i, c, len; | 40 register int c, c1; |
41 register int inword = flag == CASE_DOWN; | 41 register int inword = flag == CASE_DOWN; |
42 | 42 |
43 /* If the case table is flagged as modified, rescan it. */ | 43 /* If the case table is flagged as modified, rescan it. */ |
44 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1])) | 44 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1])) |
45 Fset_case_table (current_buffer->downcase_table); | 45 Fset_case_table (current_buffer->downcase_table); |
49 if (INTEGERP (obj)) | 49 if (INTEGERP (obj)) |
50 { | 50 { |
51 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER | 51 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER |
52 | CHAR_SHIFT | CHAR_CTL | CHAR_META); | 52 | CHAR_SHIFT | CHAR_CTL | CHAR_META); |
53 int flags = XINT (obj) & flagbits; | 53 int flags = XINT (obj) & flagbits; |
54 | 54 int multibyte = ! NILP (current_buffer->enable_multibyte_characters); |
55 c = DOWNCASE (XFASTINT (obj) & ~flagbits); | 55 |
56 if (inword) | 56 c1 = XFASTINT (obj) & ~flagbits; |
57 XSETFASTINT (obj, c | flags); | 57 if (! multibyte) |
58 else if (c == (XFASTINT (obj) & ~flagbits)) | 58 MAKE_CHAR_MULTIBYTE (c1); |
59 c = DOWNCASE (c1); | |
60 if (inword || c == c1) | |
59 { | 61 { |
60 c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); | 62 if (! inword) |
63 c = UPCASE1 (c1); | |
64 if (! multibyte) | |
65 MAKE_CHAR_UNIBYTE (c); | |
61 XSETFASTINT (obj, c | flags); | 66 XSETFASTINT (obj, c | flags); |
62 } | 67 } |
63 return obj; | 68 return obj; |
64 } | 69 } |
65 | 70 |
66 if (STRINGP (obj)) | 71 if (STRINGP (obj)) |
67 { | 72 { |
68 int multibyte = STRING_MULTIBYTE (obj); | 73 int multibyte = STRING_MULTIBYTE (obj); |
74 int i, i_byte, len; | |
75 int size = SCHARS (obj); | |
69 | 76 |
70 obj = Fcopy_sequence (obj); | 77 obj = Fcopy_sequence (obj); |
71 len = SBYTES (obj); | 78 for (i = i_byte = 0; i < size; i++, i_byte += len) |
72 | |
73 /* Scan all single-byte characters from start of string. */ | |
74 for (i = 0; i < len;) | |
75 { | 79 { |
76 c = SREF (obj, i); | 80 if (multibyte) |
77 | 81 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len); |
78 if (multibyte && c >= 0x80) | 82 else |
79 /* A multibyte character can't be handled in this | 83 { |
80 simple loop. */ | 84 c = SREF (obj, i_byte); |
81 break; | 85 len = 1; |
86 MAKE_CHAR_MULTIBYTE (c); | |
87 } | |
88 c1 = c; | |
82 if (inword && flag != CASE_CAPITALIZE_UP) | 89 if (inword && flag != CASE_CAPITALIZE_UP) |
83 c = DOWNCASE (c); | 90 c = DOWNCASE (c); |
84 else if (!UPPERCASEP (c) | 91 else if (!UPPERCASEP (c) |
85 && (!inword || flag != CASE_CAPITALIZE_UP)) | 92 && (!inword || flag != CASE_CAPITALIZE_UP)) |
86 c = UPCASE1 (c); | 93 c = UPCASE1 (c1); |
87 /* If this char won't fit in a single-byte string. | |
88 fall out to the multibyte case. */ | |
89 if (multibyte ? ! ASCII_BYTE_P (c) | |
90 : ! SINGLE_BYTE_CHAR_P (c)) | |
91 break; | |
92 | |
93 SSET (obj, i, c); | |
94 if ((int) flag >= (int) CASE_CAPITALIZE) | 94 if ((int) flag >= (int) CASE_CAPITALIZE) |
95 inword = SYNTAX (c) == Sword; | 95 inword = (SYNTAX (c) == Sword); |
96 i++; | 96 if (c != c1) |
97 } | |
98 | |
99 /* If we didn't do the whole string as single-byte, | |
100 scan the rest in a more complex way. */ | |
101 if (i < len) | |
102 { | |
103 /* The work is not yet finished because of a multibyte | |
104 character just encountered. */ | |
105 int fromlen, j_byte = i; | |
106 char *buf | |
107 = (char *) alloca ((len - i) * MAX_MULTIBYTE_LENGTH + i); | |
108 | |
109 /* Copy data already handled. */ | |
110 bcopy (SDATA (obj), buf, i); | |
111 | |
112 /* From now on, I counts bytes. */ | |
113 while (i < len) | |
114 { | 97 { |
115 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i, | 98 if (! multibyte) |
116 len - i, fromlen); | 99 { |
117 if (inword && flag != CASE_CAPITALIZE_UP) | 100 MAKE_CHAR_UNIBYTE (c); |
118 c = DOWNCASE (c); | 101 SSET (obj, i_byte, c); |
119 else if (!UPPERCASEP (c) | 102 } |
120 && (!inword || flag != CASE_CAPITALIZE_UP)) | 103 else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c)) |
121 c = UPCASE1 (c); | 104 SSET (obj, i_byte, c); |
122 i += fromlen; | 105 else |
123 j_byte += CHAR_STRING (c, buf + j_byte); | 106 { |
124 if ((int) flag >= (int) CASE_CAPITALIZE) | 107 Faset (obj, make_number (i), make_number (c)); |
125 inword = SYNTAX (c) == Sword; | 108 i_byte += CHAR_BYTES (c) - len; |
109 } | |
126 } | 110 } |
127 obj = make_multibyte_string (buf, SCHARS (obj), | |
128 j_byte); | |
129 } | 111 } |
130 return obj; | 112 return obj; |
131 } | 113 } |
132 obj = wrong_type_argument (Qchar_or_string_p, obj); | 114 obj = wrong_type_argument (Qchar_or_string_p, obj); |
133 } | 115 } |
185 void | 167 void |
186 casify_region (flag, b, e) | 168 casify_region (flag, b, e) |
187 enum case_action flag; | 169 enum case_action flag; |
188 Lisp_Object b, e; | 170 Lisp_Object b, e; |
189 { | 171 { |
190 register int i; | |
191 register int c; | 172 register int c; |
192 register int inword = flag == CASE_DOWN; | 173 register int inword = flag == CASE_DOWN; |
193 register int multibyte = !NILP (current_buffer->enable_multibyte_characters); | 174 register int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
194 int start, end; | 175 int start, end; |
195 int start_byte, end_byte; | 176 int start_byte, end_byte; |
196 int changed = 0; | 177 int changed = 0; |
178 int opoint = PT; | |
179 int opoint_byte = PT_BYTE; | |
197 | 180 |
198 if (EQ (b, e)) | 181 if (EQ (b, e)) |
199 /* Not modifying because nothing marked */ | 182 /* Not modifying because nothing marked */ |
200 return; | 183 return; |
201 | 184 |
209 modify_region (current_buffer, start, end); | 192 modify_region (current_buffer, start, end); |
210 record_change (start, end - start); | 193 record_change (start, end - start); |
211 start_byte = CHAR_TO_BYTE (start); | 194 start_byte = CHAR_TO_BYTE (start); |
212 end_byte = CHAR_TO_BYTE (end); | 195 end_byte = CHAR_TO_BYTE (end); |
213 | 196 |
214 for (i = start_byte; i < end_byte; i++, start++) | 197 while (start < end) |
215 { | 198 { |
216 int c2; | 199 int c2, len; |
217 c = c2 = FETCH_BYTE (i); | 200 |
218 if (multibyte && c >= 0x80) | 201 if (multibyte) |
219 /* A multibyte character can't be handled in this simple loop. */ | 202 { |
220 break; | 203 c = FETCH_MULTIBYTE_CHAR (start_byte); |
204 len = CHAR_BYTES (c); | |
205 } | |
206 else | |
207 { | |
208 c = FETCH_BYTE (start_byte); | |
209 MAKE_CHAR_MULTIBYTE (c); | |
210 len = 1; | |
211 } | |
212 c2 = c; | |
221 if (inword && flag != CASE_CAPITALIZE_UP) | 213 if (inword && flag != CASE_CAPITALIZE_UP) |
222 c = DOWNCASE (c); | 214 c = DOWNCASE (c); |
223 else if (!UPPERCASEP (c) | 215 else if (!UPPERCASEP (c) |
224 && (!inword || flag != CASE_CAPITALIZE_UP)) | 216 && (!inword || flag != CASE_CAPITALIZE_UP)) |
225 c = UPCASE1 (c); | 217 c = UPCASE1 (c); |
226 FETCH_BYTE (i) = c; | 218 if ((int) flag >= (int) CASE_CAPITALIZE) |
219 inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c))); | |
227 if (c != c2) | 220 if (c != c2) |
228 changed = 1; | 221 { |
229 if ((int) flag >= (int) CASE_CAPITALIZE) | 222 changed = 1; |
230 inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c)); | 223 if (! multibyte) |
224 { | |
225 MAKE_CHAR_UNIBYTE (c); | |
226 FETCH_BYTE (start_byte) = c; | |
227 } | |
228 else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c)) | |
229 FETCH_BYTE (start_byte) = c; | |
230 else if (len == CHAR_BYTES (c)) | |
231 { | |
232 int j; | |
233 unsigned char str[MAX_MULTIBYTE_LENGTH]; | |
234 | |
235 CHAR_STRING (c, str); | |
236 for (j = 0; j < len; ++j) | |
237 FETCH_BYTE (start_byte + j) = str[j]; | |
238 } | |
239 else | |
240 { | |
241 TEMP_SET_PT_BOTH (start, start_byte); | |
242 del_range_2 (start, start_byte, start + 1, start_byte + len, 0); | |
243 insert_char (c); | |
244 len = CHAR_BYTES (c); | |
245 } | |
246 } | |
247 start++; | |
248 start_byte += len; | |
231 } | 249 } |
232 if (i < end_byte) | 250 |
233 { | 251 if (PT != opoint) |
234 /* The work is not yet finished because of a multibyte character | 252 TEMP_SET_PT_BOTH (opoint, opoint_byte); |
235 just encountered. */ | 253 |
236 int opoint = PT; | |
237 int opoint_byte = PT_BYTE; | |
238 int c2; | |
239 | |
240 while (i < end_byte) | |
241 { | |
242 if ((c = FETCH_BYTE (i)) >= 0x80) | |
243 c = FETCH_MULTIBYTE_CHAR (i); | |
244 c2 = c; | |
245 if (inword && flag != CASE_CAPITALIZE_UP) | |
246 c2 = DOWNCASE (c); | |
247 else if (!UPPERCASEP (c) | |
248 && (!inword || flag != CASE_CAPITALIZE_UP)) | |
249 c2 = UPCASE1 (c); | |
250 if (c != c2) | |
251 { | |
252 int fromlen, tolen, j; | |
253 unsigned char str[MAX_MULTIBYTE_LENGTH]; | |
254 | |
255 changed = 1; | |
256 /* Handle the most likely case */ | |
257 if (c < 0400 && c2 < 0400) | |
258 FETCH_BYTE (i) = c2; | |
259 else if (fromlen = CHAR_STRING (c, str), | |
260 tolen = CHAR_STRING (c2, str), | |
261 fromlen == tolen) | |
262 { | |
263 for (j = 0; j < tolen; ++j) | |
264 FETCH_BYTE (i + j) = str[j]; | |
265 } | |
266 else | |
267 { | |
268 error ("Can't casify letters that change length"); | |
269 #if 0 /* This is approximately what we'd like to be able to do here */ | |
270 if (tolen < fromlen) | |
271 del_range_1 (i + tolen, i + fromlen, 0, 0); | |
272 else if (tolen > fromlen) | |
273 { | |
274 TEMP_SET_PT (i + fromlen); | |
275 insert_1 (str + fromlen, tolen - fromlen, 1, 0, 0); | |
276 } | |
277 #endif | |
278 } | |
279 } | |
280 if ((int) flag >= (int) CASE_CAPITALIZE) | |
281 inword = SYNTAX (c2) == Sword; | |
282 INC_BOTH (start, i); | |
283 } | |
284 TEMP_SET_PT_BOTH (opoint, opoint_byte); | |
285 } | |
286 | |
287 start = XFASTINT (b); | |
288 if (changed) | 254 if (changed) |
289 { | 255 { |
256 start = XFASTINT (b); | |
290 signal_after_change (start, end - start, end - start); | 257 signal_after_change (start, end - start, end - start); |
291 update_compositions (start, end, CHECK_ALL); | 258 update_compositions (start, end, CHECK_ALL); |
292 } | 259 } |
293 } | 260 } |
294 | 261 |