aboutsummaryrefslogtreecommitdiffstats
path: root/src/casefiddle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/casefiddle.c')
-rw-r--r--src/casefiddle.c162
1 files changed, 80 insertions, 82 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 0c438d6afa9..daaa7a228ba 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -23,7 +23,7 @@ Boston, MA 02110-1301, USA. */
23#include <config.h> 23#include <config.h>
24#include "lisp.h" 24#include "lisp.h"
25#include "buffer.h" 25#include "buffer.h"
26#include "charset.h" 26#include "character.h"
27#include "commands.h" 27#include "commands.h"
28#include "syntax.h" 28#include "syntax.h"
29#include "composite.h" 29#include "composite.h"
@@ -38,7 +38,7 @@ casify_object (flag, obj)
38 enum case_action flag; 38 enum case_action flag;
39 Lisp_Object obj; 39 Lisp_Object obj;
40{ 40{
41 register int i, c, len; 41 register int c, c1;
42 register int inword = flag == CASE_DOWN; 42 register int inword = flag == CASE_DOWN;
43 43
44 /* If the case table is flagged as modified, rescan it. */ 44 /* If the case table is flagged as modified, rescan it. */
@@ -50,6 +50,7 @@ casify_object (flag, obj)
50 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER 50 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
51 | CHAR_SHIFT | CHAR_CTL | CHAR_META); 51 | CHAR_SHIFT | CHAR_CTL | CHAR_META);
52 int flags = XINT (obj) & flagbits; 52 int flags = XINT (obj) & flagbits;
53 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
53 54
54 /* If the character has higher bits set 55 /* If the character has higher bits set
55 above the flags, return it unchanged. 56 above the flags, return it unchanged.
@@ -57,12 +58,18 @@ casify_object (flag, obj)
57 if ((unsigned) XFASTINT (obj) > (unsigned) flagbits) 58 if ((unsigned) XFASTINT (obj) > (unsigned) flagbits)
58 return obj; 59 return obj;
59 60
60 c = DOWNCASE (XFASTINT (obj) & ~flagbits); 61 c1 = XFASTINT (obj) & ~flagbits;
62 if (! multibyte)
63 MAKE_CHAR_MULTIBYTE (c1);
64 c = DOWNCASE (c1);
61 if (inword) 65 if (inword)
62 XSETFASTINT (obj, c | flags); 66 XSETFASTINT (obj, c | flags);
63 else if (c == (XFASTINT (obj) & ~flagbits)) 67 else if (c == (XFASTINT (obj) & ~flagbits))
64 { 68 {
65 c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); 69 if (! inword)
70 c = UPCASE1 (c1);
71 if (! multibyte)
72 MAKE_CHAR_UNIBYTE (c);
66 XSETFASTINT (obj, c | flags); 73 XSETFASTINT (obj, c | flags);
67 } 74 }
68 return obj; 75 return obj;
@@ -71,42 +78,43 @@ casify_object (flag, obj)
71 if (STRINGP (obj)) 78 if (STRINGP (obj))
72 { 79 {
73 int multibyte = STRING_MULTIBYTE (obj); 80 int multibyte = STRING_MULTIBYTE (obj);
74 int n; 81 int i, i_byte, len;
82 int size = SCHARS (obj);
75 83
76 obj = Fcopy_sequence (obj); 84 obj = Fcopy_sequence (obj);
77 len = SBYTES (obj); 85 for (i = i_byte = 0; i < size; i++, i_byte += len)
78
79 /* I counts bytes, and N counts chars. */
80 for (i = n = 0; i < len; n++)
81 { 86 {
82 int from_len = 1, to_len = 1; 87 if (multibyte)
83 88 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len);
84 c = SREF (obj, i); 89 else
85 90 {
86 if (multibyte && c >= 0x80) 91 c = SREF (obj, i_byte);
87 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i, len -i, from_len); 92 len = 1;
93 MAKE_CHAR_MULTIBYTE (c);
94 }
95 c1 = c;
88 if (inword && flag != CASE_CAPITALIZE_UP) 96 if (inword && flag != CASE_CAPITALIZE_UP)
89 c = DOWNCASE (c); 97 c = DOWNCASE (c);
90 else if (!UPPERCASEP (c) 98 else if (!UPPERCASEP (c)
91 && (!inword || flag != CASE_CAPITALIZE_UP)) 99 && (!inword || flag != CASE_CAPITALIZE_UP))
92 c = UPCASE1 (c); 100 c = UPCASE1 (c1);
93 if ((ASCII_BYTE_P (c) && from_len == 1) 101 if ((int) flag >= (int) CASE_CAPITALIZE)
94 || (! multibyte && SINGLE_BYTE_CHAR_P (c))) 102 inword = (SYNTAX (c) == Sword);
95 SSET (obj, i, c); 103 if (c != c1)
96 else
97 { 104 {
98 to_len = CHAR_BYTES (c); 105 if (! multibyte)
99 if (from_len == to_len) 106 {
100 CHAR_STRING (c, SDATA (obj) + i); 107 MAKE_CHAR_UNIBYTE (c);
108 SSET (obj, i_byte, c);
109 }
110 else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c))
111 SSET (obj, i_byte, c);
101 else 112 else
102 { 113 {
103 Faset (obj, make_number (n), make_number (c)); 114 Faset (obj, make_number (i), make_number (c));
104 len += to_len - from_len; 115 i_byte += CHAR_BYTES (c) - len;
105 } 116 }
106 } 117 }
107 if ((int) flag >= (int) CASE_CAPITALIZE)
108 inword = SYNTAX (c) == Sword;
109 i += to_len;
110 } 118 }
111 return obj; 119 return obj;
112 } 120 }
@@ -168,13 +176,14 @@ casify_region (flag, b, e)
168 enum case_action flag; 176 enum case_action flag;
169 Lisp_Object b, e; 177 Lisp_Object b, e;
170{ 178{
171 register int i;
172 register int c; 179 register int c;
173 register int inword = flag == CASE_DOWN; 180 register int inword = flag == CASE_DOWN;
174 register int multibyte = !NILP (current_buffer->enable_multibyte_characters); 181 register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
175 int start, end; 182 int start, end;
176 int start_byte, end_byte; 183 int start_byte, end_byte;
177 int changed = 0; 184 int changed = 0;
185 int opoint = PT;
186 int opoint_byte = PT_BYTE;
178 187
179 if (EQ (b, e)) 188 if (EQ (b, e))
180 /* Not modifying because nothing marked */ 189 /* Not modifying because nothing marked */
@@ -192,85 +201,74 @@ casify_region (flag, b, e)
192 start_byte = CHAR_TO_BYTE (start); 201 start_byte = CHAR_TO_BYTE (start);
193 end_byte = CHAR_TO_BYTE (end); 202 end_byte = CHAR_TO_BYTE (end);
194 203
195 for (i = start_byte; i < end_byte; i++, start++) 204 while (start < end)
196 { 205 {
197 int c2; 206 int c2, len;
198 c = c2 = FETCH_BYTE (i); 207
199 if (multibyte && c >= 0x80) 208 if (multibyte)
200 /* A multibyte character can't be handled in this simple loop. */ 209 {
201 break; 210 c = FETCH_MULTIBYTE_CHAR (start_byte);
211 len = CHAR_BYTES (c);
212 }
213 else
214 {
215 c = FETCH_BYTE (start_byte);
216 MAKE_CHAR_MULTIBYTE (c);
217 len = 1;
218 }
219 c2 = c;
202 if (inword && flag != CASE_CAPITALIZE_UP) 220 if (inword && flag != CASE_CAPITALIZE_UP)
203 c = DOWNCASE (c); 221 c = DOWNCASE (c);
204 else if (!UPPERCASEP (c) 222 else if (!UPPERCASEP (c)
205 && (!inword || flag != CASE_CAPITALIZE_UP)) 223 && (!inword || flag != CASE_CAPITALIZE_UP))
206 c = UPCASE1 (c); 224 c = UPCASE1 (c);
207 if (multibyte && c >= 0x80)
208 /* A multibyte result character can't be handled in this
209 simple loop. */
210 break;
211 FETCH_BYTE (i) = c;
212 if (c != c2)
213 changed = 1;
214 if ((int) flag >= (int) CASE_CAPITALIZE) 225 if ((int) flag >= (int) CASE_CAPITALIZE)
215 inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c)); 226 inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c)));
216 } 227 if (c != c2)
217 if (i < end_byte)
218 {
219 /* The work is not yet finished because of a multibyte character
220 just encountered. */
221 int opoint = PT;
222 int opoint_byte = PT_BYTE;
223 int c2;
224
225 while (start < end)
226 { 228 {
227 if ((c = FETCH_BYTE (i)) >= 0x80) 229 changed = 1;
228 c = FETCH_MULTIBYTE_CHAR (i); 230 if (! multibyte)
229 c2 = c; 231 {
230 if (inword && flag != CASE_CAPITALIZE_UP) 232 MAKE_CHAR_UNIBYTE (c);
231 c2 = DOWNCASE (c); 233 FETCH_BYTE (start_byte) = c;
232 else if (!UPPERCASEP (c) 234 }
233 && (!inword || flag != CASE_CAPITALIZE_UP)) 235 else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c))
234 c2 = UPCASE1 (c); 236 FETCH_BYTE (start_byte) = c;
235 if (c != c2) 237 else
236 { 238 {
237 int fromlen, tolen, j; 239 int tolen = CHAR_BYTES (c);
240 int j;
238 unsigned char str[MAX_MULTIBYTE_LENGTH]; 241 unsigned char str[MAX_MULTIBYTE_LENGTH];
239 242
240 changed = 1; 243 CHAR_STRING (c, str);
241 /* Handle the most likely case */ 244 if (len == tolen)
242 if (c < 0400 && c2 < 0400)
243 FETCH_BYTE (i) = c2;
244 else if (fromlen = CHAR_STRING (c, str),
245 tolen = CHAR_STRING (c2, str),
246 fromlen == tolen)
247 { 245 {
248 /* Length is unchanged. */ 246 /* Length is unchanged. */
249 for (j = 0; j < tolen; ++j) 247 for (j = 0; j < len; ++j)
250 FETCH_BYTE (i + j) = str[j]; 248 FETCH_BYTE (start_byte + j) = str[j];
251 } 249 }
252 else 250 else
253 { 251 {
254 /* Replace one character with the other, 252 /* Replace one character with the other,
255 keeping text properties the same. */ 253 keeping text properties the same. */
256 replace_range_2 (start, i, 254 replace_range_2 (start, start_byte,
257 start + 1, i + fromlen, 255 start + 1, start_byte + len,
258 str, 1, tolen, 256 str, 1, tolen,
259 1); 257 0);
260 if (opoint > start) 258 len = tolen;
261 opoint_byte += tolen - fromlen;
262 } 259 }
263 } 260 }
264 if ((int) flag >= (int) CASE_CAPITALIZE)
265 inword = SYNTAX (c2) == Sword;
266 INC_BOTH (start, i);
267 } 261 }
268 TEMP_SET_PT_BOTH (opoint, opoint_byte); 262 start++;
263 start_byte += len;
269 } 264 }
270 265
271 start = XFASTINT (b); 266 if (PT != opoint)
267 TEMP_SET_PT_BOTH (opoint, opoint_byte);
268
272 if (changed) 269 if (changed)
273 { 270 {
271 start = XFASTINT (b);
274 signal_after_change (start, end - start, end - start); 272 signal_after_change (start, end - start, end - start);
275 update_compositions (start, end, CHECK_ALL); 273 update_compositions (start, end, CHECK_ALL);
276 } 274 }