22 |
#include <config.h> |
#include <config.h> |
23 |
#include "lisp.h" |
#include "lisp.h" |
24 |
#include "buffer.h" |
#include "buffer.h" |
25 |
#include "charset.h" |
#include "character.h" |
26 |
#include "commands.h" |
#include "commands.h" |
27 |
#include "syntax.h" |
#include "syntax.h" |
28 |
#include "composite.h" |
#include "composite.h" |
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) |
58 |
XSETFASTINT (obj, c | flags); |
MAKE_CHAR_MULTIBYTE (c1); |
59 |
else if (c == (XFASTINT (obj) & ~flagbits)) |
c = DOWNCASE (c1); |
60 |
|
if (inword || c == c1) |
61 |
{ |
{ |
62 |
c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); |
if (! inword) |
63 |
|
c = UPCASE1 (c1); |
64 |
|
if (! multibyte) |
65 |
|
MAKE_CHAR_UNIBYTE (c); |
66 |
XSETFASTINT (obj, c | flags); |
XSETFASTINT (obj, c | flags); |
67 |
} |
} |
68 |
return obj; |
return obj; |
71 |
if (STRINGP (obj)) |
if (STRINGP (obj)) |
72 |
{ |
{ |
73 |
int multibyte = STRING_MULTIBYTE (obj); |
int multibyte = STRING_MULTIBYTE (obj); |
74 |
|
int i, i_byte, len; |
75 |
|
int size = SCHARS (obj); |
76 |
|
|
77 |
obj = Fcopy_sequence (obj); |
obj = Fcopy_sequence (obj); |
78 |
len = SBYTES (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;) |
|
79 |
{ |
{ |
80 |
c = SREF (obj, i); |
if (multibyte) |
81 |
|
c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len); |
82 |
if (multibyte && c >= 0x80) |
else |
83 |
/* A multibyte character can't be handled in this |
{ |
84 |
simple loop. */ |
c = SREF (obj, i_byte); |
85 |
break; |
len = 1; |
86 |
|
MAKE_CHAR_MULTIBYTE (c); |
87 |
|
} |
88 |
|
c1 = c; |
89 |
if (inword && flag != CASE_CAPITALIZE_UP) |
if (inword && flag != CASE_CAPITALIZE_UP) |
90 |
c = DOWNCASE (c); |
c = DOWNCASE (c); |
91 |
else if (!UPPERCASEP (c) |
else if (!UPPERCASEP (c) |
92 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
93 |
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; |
|
|
|
|
|
SSET (obj, i, c); |
|
94 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
if ((int) flag >= (int) CASE_CAPITALIZE) |
95 |
inword = SYNTAX (c) == Sword; |
inword = (SYNTAX (c) == Sword); |
96 |
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 (SDATA (obj), buf, i); |
|
|
|
|
|
/* From now on, I counts bytes. */ |
|
|
while (i < len) |
|
97 |
{ |
{ |
98 |
c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i, |
if (! multibyte) |
99 |
len - i, fromlen); |
{ |
100 |
if (inword && flag != CASE_CAPITALIZE_UP) |
MAKE_CHAR_UNIBYTE (c); |
101 |
c = DOWNCASE (c); |
SSET (obj, i_byte, c); |
102 |
else if (!UPPERCASEP (c) |
} |
103 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c)) |
104 |
c = UPCASE1 (c); |
SSET (obj, i_byte, c); |
105 |
i += fromlen; |
else |
106 |
j_byte += CHAR_STRING (c, buf + j_byte); |
{ |
107 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
Faset (obj, make_number (i), make_number (c)); |
108 |
inword = SYNTAX (c) == Sword; |
i_byte += CHAR_BYTES (c) - len; |
109 |
|
} |
110 |
} |
} |
|
obj = make_multibyte_string (buf, SCHARS (obj), |
|
|
j_byte); |
|
111 |
} |
} |
112 |
return obj; |
return obj; |
113 |
} |
} |
169 |
enum case_action flag; |
enum case_action flag; |
170 |
Lisp_Object b, e; |
Lisp_Object b, e; |
171 |
{ |
{ |
|
register int i; |
|
172 |
register int c; |
register int c; |
173 |
register int inword = flag == CASE_DOWN; |
register int inword = flag == CASE_DOWN; |
174 |
register int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
register int multibyte = !NILP (current_buffer->enable_multibyte_characters); |
175 |
int start, end; |
int start, end; |
176 |
int start_byte, end_byte; |
int start_byte, end_byte; |
177 |
int changed = 0; |
int changed = 0; |
178 |
|
int opoint = PT; |
179 |
|
int opoint_byte = PT_BYTE; |
180 |
|
|
181 |
if (EQ (b, e)) |
if (EQ (b, e)) |
182 |
/* Not modifying because nothing marked */ |
/* Not modifying because nothing marked */ |
194 |
start_byte = CHAR_TO_BYTE (start); |
start_byte = CHAR_TO_BYTE (start); |
195 |
end_byte = CHAR_TO_BYTE (end); |
end_byte = CHAR_TO_BYTE (end); |
196 |
|
|
197 |
for (i = start_byte; i < end_byte; i++, start++) |
while (start < end) |
198 |
{ |
{ |
199 |
int c2; |
int c2, len; |
200 |
c = c2 = FETCH_BYTE (i); |
|
201 |
if (multibyte && c >= 0x80) |
if (multibyte) |
202 |
/* A multibyte character can't be handled in this simple loop. */ |
{ |
203 |
break; |
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; |
213 |
if (inword && flag != CASE_CAPITALIZE_UP) |
if (inword && flag != CASE_CAPITALIZE_UP) |
214 |
c = DOWNCASE (c); |
c = DOWNCASE (c); |
215 |
else if (!UPPERCASEP (c) |
else if (!UPPERCASEP (c) |
216 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
217 |
c = UPCASE1 (c); |
c = UPCASE1 (c); |
|
FETCH_BYTE (i) = c; |
|
|
if (c != c2) |
|
|
changed = 1; |
|
218 |
if ((int) flag >= (int) CASE_CAPITALIZE) |
if ((int) flag >= (int) CASE_CAPITALIZE) |
219 |
inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c)); |
inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c))); |
220 |
} |
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) |
|
221 |
{ |
{ |
222 |
if ((c = FETCH_BYTE (i)) >= 0x80) |
changed = 1; |
223 |
c = FETCH_MULTIBYTE_CHAR (i); |
if (! multibyte) |
224 |
c2 = c; |
{ |
225 |
if (inword && flag != CASE_CAPITALIZE_UP) |
MAKE_CHAR_UNIBYTE (c); |
226 |
c2 = DOWNCASE (c); |
FETCH_BYTE (start_byte) = c; |
227 |
else if (!UPPERCASEP (c) |
} |
228 |
&& (!inword || flag != CASE_CAPITALIZE_UP)) |
else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c)) |
229 |
c2 = UPCASE1 (c); |
FETCH_BYTE (start_byte) = c; |
230 |
if (c != c2) |
else if (len == CHAR_BYTES (c)) |
231 |
{ |
{ |
232 |
int fromlen, tolen, j; |
int j; |
233 |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
unsigned char str[MAX_MULTIBYTE_LENGTH]; |
234 |
|
|
235 |
changed = 1; |
CHAR_STRING (c, str); |
236 |
/* Handle the most likely case */ |
for (j = 0; j < len; ++j) |
237 |
if (c < 0400 && c2 < 0400) |
FETCH_BYTE (start_byte + j) = str[j]; |
238 |
FETCH_BYTE (i) = c2; |
} |
239 |
else if (fromlen = CHAR_STRING (c, str), |
else |
240 |
tolen = CHAR_STRING (c2, str), |
{ |
241 |
fromlen == tolen) |
TEMP_SET_PT_BOTH (start, start_byte); |
242 |
{ |
del_range_2 (start, start_byte, start + 1, start_byte + len, 0); |
243 |
for (j = 0; j < tolen; ++j) |
insert_char (c); |
244 |
FETCH_BYTE (i + j) = str[j]; |
len = CHAR_BYTES (c); |
|
} |
|
|
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 |
|
|
} |
|
245 |
} |
} |
|
if ((int) flag >= (int) CASE_CAPITALIZE) |
|
|
inword = SYNTAX (c2) == Sword; |
|
|
INC_BOTH (start, i); |
|
246 |
} |
} |
247 |
TEMP_SET_PT_BOTH (opoint, opoint_byte); |
start++; |
248 |
|
start_byte += len; |
249 |
} |
} |
250 |
|
|
251 |
start = XFASTINT (b); |
if (PT != opoint) |
252 |
|
TEMP_SET_PT_BOTH (opoint, opoint_byte); |
253 |
|
|
254 |
if (changed) |
if (changed) |
255 |
{ |
{ |
256 |
|
start = XFASTINT (b); |
257 |
signal_after_change (start, end - start, end - start); |
signal_after_change (start, end - start, end - start); |
258 |
update_compositions (start, end, CHECK_ALL); |
update_compositions (start, end, CHECK_ALL); |
259 |
} |
} |