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