37 |
enum case_action flag; |
enum case_action flag; |
38 |
Lisp_Object obj; |
Lisp_Object obj; |
39 |
{ |
{ |
40 |
register int i, c, len; |
register int c, c1; |
41 |
register int inword = flag == CASE_DOWN; |
register int inword = flag == CASE_DOWN; |
42 |
|
|
43 |
/* If the case table is flagged as modified, rescan it. */ |
/* If the case table is flagged as modified, rescan it. */ |
51 |
int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER |
int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER |
52 |
| CHAR_SHIFT | CHAR_CTL | CHAR_META); |
| CHAR_SHIFT | CHAR_CTL | CHAR_META); |
53 |
int flags = XINT (obj) & flagbits; |
int flags = XINT (obj) & flagbits; |
54 |
|
int multibyte = ! NILP (current_buffer->enable_multibyte_characters); |
55 |
|
|
56 |
c = DOWNCASE (XFASTINT (obj) & ~flagbits); |
c1 = XFASTINT (obj) & ~flagbits; |
57 |
if (inword) |
if (! multibyte) |
|
XSETFASTINT (obj, c | flags); |
|
|
else if (c == (XFASTINT (obj) & ~flagbits)) |
|
58 |
{ |
{ |
59 |
c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); |
MAKE_CHAR_UNIBYTE (c1); |
60 |
|
} |
61 |
|
c = DOWNCASE (c1); |
62 |
|
if (inword || c == c1) |
63 |
|
{ |
64 |
|
if (! inword) |
65 |
|
c = UPCASE1 (c1); |
66 |
|
if (! multibyte) |
67 |
|
{ |
68 |
|
MAKE_CHAR_MULTIBYTE (c); |
69 |
|
} |
70 |
XSETFASTINT (obj, c | flags); |
XSETFASTINT (obj, c | flags); |
71 |
} |
} |
72 |
return obj; |
return obj; |
75 |
if (STRINGP (obj)) |
if (STRINGP (obj)) |
76 |
{ |
{ |
77 |
int multibyte = STRING_MULTIBYTE (obj); |
int multibyte = STRING_MULTIBYTE (obj); |
78 |
|
int i, i_byte, len; |
79 |
|
int size = XSTRING (obj)->size; |
80 |
|
|
81 |
obj = Fcopy_sequence (obj); |
obj = Fcopy_sequence (obj); |
82 |
len = STRING_BYTES (XSTRING (obj)); |
for (i = i_byte = 0; i < size; i++, i_byte += len) |
|
|
|
|
/* Scan all single-byte characters from start of string. */ |
|
|
for (i = 0; i < len;) |
|
83 |
{ |
{ |
84 |
c = XSTRING (obj)->data[i]; |
if (multibyte) |
85 |
|
c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i_byte, |
86 |
if (multibyte && c >= 0x80) |
0, len); |
87 |
/* A multibyte character can't be handled in this |
else |
88 |
simple loop. */ |
{ |
89 |
break; |
c = XSTRING (obj)->data[i_byte]; |
90 |
|
len = 1; |
91 |
|
MAKE_CHAR_MULTIBYTE (c); |
92 |
|
} |
93 |
|
c1 = c; |
94 |
if (inword && flag != CASE_CAPITALIZE_UP) |
if (inword && flag != CASE_CAPITALIZE_UP) |
95 |
c = DOWNCASE (c); |
c = DOWNCASE (c); |
96 |
else if (!UPPERCASEP (c) |
else if (!UPPERCASEP (c) |
97 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
98 |
c = UPCASE1 (c); |
c = UPCASE1 (c1); |
|
/* If this char won't fit in a single-byte string. |
|
|
fall out to the multibyte case. */ |
|
|
if (multibyte ? ! ASCII_BYTE_P (c) |
|
|
: ! SINGLE_BYTE_CHAR_P (c)) |
|
|
break; |
|
|
|
|
|
XSTRING (obj)->data[i] = c; |
|
99 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
if ((int) flag >= (int) CASE_CAPITALIZE) |
100 |
inword = SYNTAX (c) == Sword; |
inword = SYNTAX (c) == Sword; |
101 |
i++; |
if (c != c1) |
|
} |
|
|
|
|
|
/* If we didn't do the whole string as single-byte, |
|
|
scan the rest in a more complex way. */ |
|
|
if (i < len) |
|
|
{ |
|
|
/* The work is not yet finished because of a multibyte |
|
|
character just encountered. */ |
|
|
int fromlen, j_byte = i; |
|
|
char *buf |
|
|
= (char *) alloca ((len - i) * MAX_MULTIBYTE_LENGTH + i); |
|
|
|
|
|
/* Copy data already handled. */ |
|
|
bcopy (XSTRING (obj)->data, buf, i); |
|
|
|
|
|
/* From now on, I counts bytes. */ |
|
|
while (i < len) |
|
102 |
{ |
{ |
103 |
c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i, |
if (! multibyte) |
104 |
len - i, fromlen); |
{ |
105 |
if (inword && flag != CASE_CAPITALIZE_UP) |
MAKE_CHAR_UNIBYTE (c); |
106 |
c = DOWNCASE (c); |
XSTRING (obj)->data[i_byte] = c; |
107 |
else if (!UPPERCASEP (c) |
} |
108 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c)) |
109 |
c = UPCASE1 (c); |
XSTRING (obj)->data[i_byte] = c; |
110 |
i += fromlen; |
else |
111 |
j_byte += CHAR_STRING (c, buf + j_byte); |
{ |
112 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
Faset (obj, make_number (i), make_number (c)); |
113 |
inword = SYNTAX (c) == Sword; |
i_byte += CHAR_BYTES (c) - len; |
114 |
|
} |
115 |
} |
} |
|
obj = make_multibyte_string (buf, XSTRING (obj)->size, |
|
|
j_byte); |
|
116 |
} |
} |
117 |
return obj; |
return obj; |
118 |
} |
} |
181 |
int start, end; |
int start, end; |
182 |
int start_byte, end_byte; |
int start_byte, end_byte; |
183 |
int changed = 0; |
int changed = 0; |
184 |
|
int opoint = PT; |
185 |
|
int opoint_byte = PT_BYTE; |
186 |
|
|
187 |
if (EQ (b, e)) |
if (EQ (b, e)) |
188 |
/* Not modifying because nothing marked */ |
/* Not modifying because nothing marked */ |
200 |
start_byte = CHAR_TO_BYTE (start); |
start_byte = CHAR_TO_BYTE (start); |
201 |
end_byte = CHAR_TO_BYTE (end); |
end_byte = CHAR_TO_BYTE (end); |
202 |
|
|
203 |
for (i = start_byte; i < end_byte; i++, start++) |
while (start < end) |
204 |
{ |
{ |
205 |
int c2; |
int c2, len; |
206 |
c = c2 = FETCH_BYTE (i); |
|
207 |
if (multibyte && c >= 0x80) |
if (multibyte) |
208 |
/* A multibyte character can't be handled in this simple loop. */ |
{ |
209 |
break; |
c = FETCH_MULTIBYTE_CHAR (start_byte); |
210 |
|
len = CHAR_BYTES (c); |
211 |
|
} |
212 |
|
else |
213 |
|
{ |
214 |
|
c = FETCH_BYTE (start_byte); |
215 |
|
MAKE_CHAR_MULTIBYTE (c); |
216 |
|
len = 1; |
217 |
|
} |
218 |
|
c2 = c; |
219 |
if (inword && flag != CASE_CAPITALIZE_UP) |
if (inword && flag != CASE_CAPITALIZE_UP) |
220 |
c = DOWNCASE (c); |
c = DOWNCASE (c); |
221 |
else if (!UPPERCASEP (c) |
else if (!UPPERCASEP (c) |
222 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
223 |
c = UPCASE1 (c); |
c = UPCASE1 (c); |
|
FETCH_BYTE (i) = c; |
|
|
if (c != c2) |
|
|
changed = 1; |
|
224 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
if ((int) flag >= (int) CASE_CAPITALIZE) |
225 |
inword = SYNTAX (c) == Sword; |
inword = SYNTAX (c) == Sword; |
226 |
} |
if (c != c2) |
|
if (i < end_byte) |
|
|
{ |
|
|
/* The work is not yet finished because of a multibyte character |
|
|
just encountered. */ |
|
|
int opoint = PT; |
|
|
int opoint_byte = PT_BYTE; |
|
|
int c2; |
|
|
|
|
|
while (i < end_byte) |
|
227 |
{ |
{ |
228 |
if ((c = FETCH_BYTE (i)) >= 0x80) |
changed = 1; |
229 |
c = FETCH_MULTIBYTE_CHAR (i); |
if (! multibyte) |
230 |
c2 = c; |
{ |
231 |
if (inword && flag != CASE_CAPITALIZE_UP) |
MAKE_CHAR_UNIBYTE (c); |
232 |
c2 = DOWNCASE (c); |
FETCH_BYTE (start_byte) = c; |
233 |
else if (!UPPERCASEP (c) |
} |
234 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c)) |
235 |
c2 = UPCASE1 (c); |
FETCH_BYTE (start_byte) = c; |
236 |
if (c != c2) |
else if (len == CHAR_BYTES (c)) |
237 |
{ |
{ |
238 |
int fromlen, tolen, j; |
int j; |
239 |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
240 |
|
|
241 |
changed = 1; |
CHAR_STRING (c, str); |
242 |
/* Handle the most likely case */ |
for (j = 0; j < len; ++j) |
243 |
if (multibyte ? (c < 0200 && c2 < 0200) |
FETCH_BYTE (start_byte + j) = str[j]; |
244 |
: (c < 0400 && c2 < 0400)) |
} |
245 |
FETCH_BYTE (i) = c2; |
else |
246 |
else if (fromlen = CHAR_STRING (c, str), |
{ |
247 |
tolen = CHAR_STRING (c2, str), |
TEMP_SET_PT_BOTH (start, start_byte); |
248 |
fromlen == tolen) |
del_range_2 (start, start_byte, start + 1, start_byte + len, 0); |
249 |
{ |
insert_char (c); |
250 |
for (j = 0; j < tolen; ++j) |
len = CHAR_BYTES (c); |
|
FETCH_BYTE (i + j) = str[j]; |
|
|
} |
|
|
else |
|
|
{ |
|
|
error ("Can't casify letters that change length"); |
|
|
#if 0 /* This is approximately what we'd like to be able to do here */ |
|
|
if (tolen < fromlen) |
|
|
del_range_1 (i + tolen, i + fromlen, 0, 0); |
|
|
else if (tolen > fromlen) |
|
|
{ |
|
|
TEMP_SET_PT (i + fromlen); |
|
|
insert_1 (str + fromlen, tolen - fromlen, 1, 0, 0); |
|
|
} |
|
|
#endif |
|
|
} |
|
251 |
} |
} |
|
if ((int) flag >= (int) CASE_CAPITALIZE) |
|
|
inword = SYNTAX (c2) == Sword; |
|
|
INC_BOTH (start, i); |
|
252 |
} |
} |
253 |
TEMP_SET_PT_BOTH (opoint, opoint_byte); |
start++; |
254 |
|
start_byte += len; |
255 |
} |
} |
256 |
|
|
|
start = XFASTINT (b); |
|
257 |
if (changed) |
if (changed) |
258 |
{ |
{ |
259 |
|
start = XFASTINT (b); |
260 |
signal_after_change (start, end - start, end - start); |
signal_after_change (start, end - start, end - start); |
261 |
update_compositions (start, end, CHECK_ALL); |
update_compositions (start, end, CHECK_ALL); |
262 |
} |
} |