diff options
| author | Kenichi Handa | 2003-09-08 12:53:41 +0000 |
|---|---|---|
| committer | Kenichi Handa | 2003-09-08 12:53:41 +0000 |
| commit | 8f924df7df019cce90537647de2627581043b5c4 (patch) | |
| tree | 6c40bd05679425e710d6b2e5649eae3da5e40a52 /src/casefiddle.c | |
| parent | 463f5630a5e7cbe7f042bc1175d1fa1c4e98860f (diff) | |
| parent | 9d4807432a01f9b3cc519fcfa3ea92a70ffa7f43 (diff) | |
| download | emacs-8f924df7df019cce90537647de2627581043b5c4.tar.gz emacs-8f924df7df019cce90537647de2627581043b5c4.zip | |
*** empty log message ***
Diffstat (limited to 'src/casefiddle.c')
| -rw-r--r-- | src/casefiddle.c | 201 |
1 files changed, 84 insertions, 117 deletions
diff --git a/src/casefiddle.c b/src/casefiddle.c index 8b92d39cbb3..1e502af9c02 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c | |||
| @@ -22,7 +22,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 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" |
| @@ -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,18 @@ 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 | MAKE_CHAR_MULTIBYTE (c1); |
| 58 | else if (c == (XFASTINT (obj) & ~flagbits)) | 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; |
| @@ -66,66 +71,43 @@ casify_object (flag, obj) | |||
| 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 | } |
| @@ -187,13 +169,14 @@ 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 */ |
| @@ -211,82 +194,66 @@ casify_region (flag, b, e) | |||
| 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; | ||
| 227 | if (c != c2) | ||
| 228 | changed = 1; | ||
| 229 | if ((int) flag >= (int) CASE_CAPITALIZE) | 218 | if ((int) flag >= (int) CASE_CAPITALIZE) |
| 230 | inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c)); | 219 | inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c))); |
| 231 | } | 220 | 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 | { | 221 | { |
| 242 | if ((c = FETCH_BYTE (i)) >= 0x80) | 222 | changed = 1; |
| 243 | c = FETCH_MULTIBYTE_CHAR (i); | 223 | if (! multibyte) |
| 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 | { | 224 | { |
| 252 | int fromlen, tolen, j; | 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; | ||
| 253 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 233 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 254 | 234 | ||
| 255 | changed = 1; | 235 | CHAR_STRING (c, str); |
| 256 | /* Handle the most likely case */ | 236 | for (j = 0; j < len; ++j) |
| 257 | if (c < 0400 && c2 < 0400) | 237 | FETCH_BYTE (start_byte + j) = str[j]; |
| 258 | FETCH_BYTE (i) = c2; | 238 | } |
| 259 | else if (fromlen = CHAR_STRING (c, str), | 239 | else |
| 260 | tolen = CHAR_STRING (c2, str), | 240 | { |
| 261 | fromlen == tolen) | 241 | TEMP_SET_PT_BOTH (start, start_byte); |
| 262 | { | 242 | del_range_2 (start, start_byte, start + 1, start_byte + len, 0); |
| 263 | for (j = 0; j < tolen; ++j) | 243 | insert_char (c); |
| 264 | FETCH_BYTE (i + j) = str[j]; | 244 | len = CHAR_BYTES (c); |
| 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 | } | 245 | } |
| 280 | if ((int) flag >= (int) CASE_CAPITALIZE) | ||
| 281 | inword = SYNTAX (c2) == Sword; | ||
| 282 | INC_BOTH (start, i); | ||
| 283 | } | 246 | } |
| 284 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | 247 | start++; |
| 248 | start_byte += len; | ||
| 285 | } | 249 | } |
| 286 | 250 | ||
| 287 | start = XFASTINT (b); | 251 | if (PT != opoint) |
| 252 | TEMP_SET_PT_BOTH (opoint, opoint_byte); | ||
| 253 | |||
| 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 | } |