diff options
| author | Kenichi Handa | 2002-08-20 03:58:53 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2002-08-20 03:58:53 +0000 |
| commit | 2422e50a5174bac265f12c7888bf29366dc44a6d (patch) | |
| tree | eabcc8d2b646b280e95365a0728704c200044cf3 /src | |
| parent | 064808ae246cd108c0d410f52937a18d9417f5a6 (diff) | |
| download | emacs-2422e50a5174bac265f12c7888bf29366dc44a6d.tar.gz emacs-2422e50a5174bac265f12c7888bf29366dc44a6d.zip | |
(casify_object): Simplified. Handle the case that
the case conversion change the byte length.
(casify_region): Likewise
Diffstat (limited to 'src')
| -rw-r--r-- | src/casefiddle.c | 197 |
1 files changed, 83 insertions, 114 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c index 0f060b8a0ae..31b88d3c15d 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c | |||
| @@ -37,7 +37,7 @@ 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. */ |
| @@ -51,13 +51,22 @@ casify_object (flag, obj) | |||
| 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 | int multibyte = ! NILP (current_buffer->enable_multibyte_characters); | ||
| 54 | 55 | ||
| 55 | c = DOWNCASE (XFASTINT (obj) & ~flagbits); | 56 | c1 = XFASTINT (obj) & ~flagbits; |
| 56 | if (inword) | 57 | if (! multibyte) |
| 57 | XSETFASTINT (obj, c | flags); | ||
| 58 | else if (c == (XFASTINT (obj) & ~flagbits)) | ||
| 59 | { | 58 | { |
| 60 | c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); | 59 | 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 | } | ||
| 61 | XSETFASTINT (obj, c | flags); | 70 | XSETFASTINT (obj, c | flags); |
| 62 | } | 71 | } |
| 63 | return obj; | 72 | return obj; |
| @@ -66,66 +75,44 @@ casify_object (flag, obj) | |||
| 66 | if (STRINGP (obj)) | 75 | if (STRINGP (obj)) |
| 67 | { | 76 | { |
| 68 | int multibyte = STRING_MULTIBYTE (obj); | 77 | int multibyte = STRING_MULTIBYTE (obj); |
| 78 | int i, i_byte, len; | ||
| 79 | int size = XSTRING (obj)->size; | ||
| 69 | 80 | ||
| 70 | obj = Fcopy_sequence (obj); | 81 | obj = Fcopy_sequence (obj); |
| 71 | len = STRING_BYTES (XSTRING (obj)); | 82 | 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 | { | 83 | { |
| 76 | c = XSTRING (obj)->data[i]; | 84 | if (multibyte) |
| 77 | 85 | c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i_byte, | |
| 78 | if (multibyte && c >= 0x80) | 86 | 0, len); |
| 79 | /* A multibyte character can't be handled in this | 87 | else |
| 80 | simple loop. */ | 88 | { |
| 81 | break; | 89 | c = XSTRING (obj)->data[i_byte]; |
| 90 | len = 1; | ||
| 91 | MAKE_CHAR_MULTIBYTE (c); | ||
| 92 | } | ||
| 93 | c1 = c; | ||
| 82 | if (inword && flag != CASE_CAPITALIZE_UP) | 94 | if (inword && flag != CASE_CAPITALIZE_UP) |
| 83 | c = DOWNCASE (c); | 95 | c = DOWNCASE (c); |
| 84 | else if (!UPPERCASEP (c) | 96 | else if (!UPPERCASEP (c) |
| 85 | && (!inword || flag != CASE_CAPITALIZE_UP)) | 97 | && (!inword || flag != CASE_CAPITALIZE_UP)) |
| 86 | c = UPCASE1 (c); | 98 | 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 | XSTRING (obj)->data[i] = c; | ||
| 94 | if ((int) flag >= (int) CASE_CAPITALIZE) | 99 | if ((int) flag >= (int) CASE_CAPITALIZE) |
| 95 | inword = SYNTAX (c) == Sword; | 100 | inword = SYNTAX (c) == Sword; |
| 96 | i++; | 101 | 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 (XSTRING (obj)->data, buf, i); | ||
| 111 | |||
| 112 | /* From now on, I counts bytes. */ | ||
| 113 | while (i < len) | ||
| 114 | { | 102 | { |
| 115 | c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i, | 103 | if (! multibyte) |
| 116 | len - i, fromlen); | 104 | { |
| 117 | if (inword && flag != CASE_CAPITALIZE_UP) | 105 | MAKE_CHAR_UNIBYTE (c); |
| 118 | c = DOWNCASE (c); | 106 | XSTRING (obj)->data[i_byte] = c; |
| 119 | else if (!UPPERCASEP (c) | 107 | } |
| 120 | && (!inword || flag != CASE_CAPITALIZE_UP)) | 108 | else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c)) |
| 121 | c = UPCASE1 (c); | 109 | XSTRING (obj)->data[i_byte] = c; |
| 122 | i += fromlen; | 110 | else |
| 123 | j_byte += CHAR_STRING (c, buf + j_byte); | 111 | { |
| 124 | if ((int) flag >= (int) CASE_CAPITALIZE) | 112 | Faset (obj, make_number (i), make_number (c)); |
| 125 | inword = SYNTAX (c) == Sword; | 113 | i_byte += CHAR_BYTES (c) - len; |
| 114 | } | ||
| 126 | } | 115 | } |
| 127 | obj = make_multibyte_string (buf, XSTRING (obj)->size, | ||
| 128 | j_byte); | ||
| 129 | } | 116 | } |
| 130 | return obj; | 117 | return obj; |
| 131 | } | 118 | } |
| @@ -194,6 +181,8 @@ casify_region (flag, b, e) | |||
| 194 | int start, end; | 181 | int start, end; |
| 195 | int start_byte, end_byte; | 182 | int start_byte, end_byte; |
| 196 | int changed = 0; | 183 | int changed = 0; |
| 184 | int opoint = PT; | ||
| 185 | int opoint_byte = PT_BYTE; | ||
| 197 | 186 | ||
| 198 | if (EQ (b, e)) | 187 | if (EQ (b, e)) |
| 199 | /* Not modifying because nothing marked */ | 188 | /* Not modifying because nothing marked */ |
| @@ -211,83 +200,63 @@ casify_region (flag, b, e) | |||
| 211 | start_byte = CHAR_TO_BYTE (start); | 200 | start_byte = CHAR_TO_BYTE (start); |
| 212 | end_byte = CHAR_TO_BYTE (end); | 201 | end_byte = CHAR_TO_BYTE (end); |
| 213 | 202 | ||
| 214 | for (i = start_byte; i < end_byte; i++, start++) | 203 | while (start < end) |
| 215 | { | 204 | { |
| 216 | int c2; | 205 | int c2, len; |
| 217 | c = c2 = FETCH_BYTE (i); | 206 | |
| 218 | if (multibyte && c >= 0x80) | 207 | if (multibyte) |
| 219 | /* A multibyte character can't be handled in this simple loop. */ | 208 | { |
| 220 | break; | 209 | 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; | ||
| 221 | if (inword && flag != CASE_CAPITALIZE_UP) | 219 | if (inword && flag != CASE_CAPITALIZE_UP) |
| 222 | c = DOWNCASE (c); | 220 | c = DOWNCASE (c); |
| 223 | else if (!UPPERCASEP (c) | 221 | else if (!UPPERCASEP (c) |
| 224 | && (!inword || flag != CASE_CAPITALIZE_UP)) | 222 | && (!inword || flag != CASE_CAPITALIZE_UP)) |
| 225 | c = UPCASE1 (c); | 223 | c = UPCASE1 (c); |
| 226 | FETCH_BYTE (i) = c; | ||
| 227 | if (c != c2) | ||
| 228 | changed = 1; | ||
| 229 | if ((int) flag >= (int) CASE_CAPITALIZE) | 224 | if ((int) flag >= (int) CASE_CAPITALIZE) |
| 230 | inword = SYNTAX (c) == Sword; | 225 | inword = SYNTAX (c) == Sword; |
| 231 | } | 226 | if (c != c2) |
| 232 | if (i < end_byte) | ||
| 233 | { | ||
| 234 | /* The work is not yet finished because of a multibyte character | ||
| 235 | just encountered. */ | ||
| 236 | int opoint = PT; | ||
| 237 | int opoint_byte = PT_BYTE; | ||
| 238 | int c2; | ||
| 239 | |||
| 240 | while (i < end_byte) | ||
| 241 | { | 227 | { |
| 242 | if ((c = FETCH_BYTE (i)) >= 0x80) | 228 | changed = 1; |
| 243 | c = FETCH_MULTIBYTE_CHAR (i); | 229 | if (! multibyte) |
| 244 | c2 = c; | 230 | { |
| 245 | if (inword && flag != CASE_CAPITALIZE_UP) | 231 | MAKE_CHAR_UNIBYTE (c); |
| 246 | c2 = DOWNCASE (c); | 232 | FETCH_BYTE (start_byte) = c; |
| 247 | else if (!UPPERCASEP (c) | 233 | } |
| 248 | && (!inword || flag != CASE_CAPITALIZE_UP)) | 234 | else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c)) |
| 249 | c2 = UPCASE1 (c); | 235 | FETCH_BYTE (start_byte) = c; |
| 250 | if (c != c2) | 236 | else if (len == CHAR_BYTES (c)) |
| 251 | { | 237 | { |
| 252 | int fromlen, tolen, j; | 238 | int j; |
| 253 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 239 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 254 | 240 | ||
| 255 | changed = 1; | 241 | CHAR_STRING (c, str); |
| 256 | /* Handle the most likely case */ | 242 | for (j = 0; j < len; ++j) |
| 257 | if (multibyte ? (c < 0200 && c2 < 0200) | 243 | FETCH_BYTE (start_byte + j) = str[j]; |
| 258 | : (c < 0400 && c2 < 0400)) | 244 | } |
| 259 | FETCH_BYTE (i) = c2; | 245 | else |
| 260 | else if (fromlen = CHAR_STRING (c, str), | 246 | { |
| 261 | tolen = CHAR_STRING (c2, str), | 247 | TEMP_SET_PT_BOTH (start, start_byte); |
| 262 | fromlen == tolen) | 248 | del_range_2 (start, start_byte, start + 1, start_byte + len, 0); |
| 263 | { | 249 | insert_char (c); |
| 264 | for (j = 0; j < tolen; ++j) | 250 | len = CHAR_BYTES (c); |
| 265 | FETCH_BYTE (i + j) = str[j]; | ||
| 266 | } | ||
| 267 | else | ||
| 268 | { | ||
| 269 | error ("Can't casify letters that change length"); | ||
| 270 | #if 0 /* This is approximately what we'd like to be able to do here */ | ||
| 271 | if (tolen < fromlen) | ||
| 272 | del_range_1 (i + tolen, i + fromlen, 0, 0); | ||
| 273 | else if (tolen > fromlen) | ||
| 274 | { | ||
| 275 | TEMP_SET_PT (i + fromlen); | ||
| 276 | insert_1 (str + fromlen, tolen - fromlen, 1, 0, 0); | ||
| 277 | } | ||
| 278 | #endif | ||
| 279 | } | ||
| 280 | } | 251 | } |
| 281 | if ((int) flag >= (int) CASE_CAPITALIZE) | ||
| 282 | inword = SYNTAX (c2) == Sword; | ||
| 283 | INC_BOTH (start, i); | ||
| 284 | } | 252 | } |
| 285 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | 253 | start++; |
| 254 | start_byte += len; | ||
| 286 | } | 255 | } |
| 287 | 256 | ||
| 288 | start = XFASTINT (b); | ||
| 289 | if (changed) | 257 | if (changed) |
| 290 | { | 258 | { |
| 259 | start = XFASTINT (b); | ||
| 291 | signal_after_change (start, end - start, end - start); | 260 | signal_after_change (start, end - start, end - start); |
| 292 | update_compositions (start, end, CHECK_ALL); | 261 | update_compositions (start, end, CHECK_ALL); |
| 293 | } | 262 | } |