X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/9aecacd08a93bffb529cee59d74477890ce96f37..0e2501ed344f5c8e251bcdca981f5d81dd78f663:/src/casefiddle.c diff --git a/src/casefiddle.c b/src/casefiddle.c index 0e9e1ba2c3..650e046a26 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c @@ -1,6 +1,6 @@ /* GNU Emacs case conversion functions. Copyright (C) 1985, 1994, 1997, 1998, 1999, 2001, 2002, 2003, 2004, - 2005, 2006, 2007 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -23,7 +23,7 @@ Boston, MA 02110-1301, USA. */ #include #include "lisp.h" #include "buffer.h" -#include "charset.h" +#include "character.h" #include "commands.h" #include "syntax.h" #include "composite.h" @@ -38,7 +38,7 @@ casify_object (flag, obj) enum case_action flag; Lisp_Object obj; { - register int i, c, len; + register int c, c1; register int inword = flag == CASE_DOWN; /* If the case table is flagged as modified, rescan it. */ @@ -50,6 +50,7 @@ casify_object (flag, obj) int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER | CHAR_SHIFT | CHAR_CTL | CHAR_META); int flags = XINT (obj) & flagbits; + int multibyte = ! NILP (current_buffer->enable_multibyte_characters); /* If the character has higher bits set above the flags, return it unchanged. @@ -57,12 +58,18 @@ casify_object (flag, obj) if ((unsigned) XFASTINT (obj) > (unsigned) flagbits) return obj; - c = DOWNCASE (XFASTINT (obj) & ~flagbits); + c1 = XFASTINT (obj) & ~flagbits; + if (! multibyte) + MAKE_CHAR_MULTIBYTE (c1); + c = DOWNCASE (c1); if (inword) XSETFASTINT (obj, c | flags); else if (c == (XFASTINT (obj) & ~flagbits)) { - c = UPCASE1 ((XFASTINT (obj) & ~flagbits)); + if (! inword) + c = UPCASE1 (c1); + if (! multibyte) + MAKE_CHAR_UNIBYTE (c); XSETFASTINT (obj, c | flags); } return obj; @@ -71,42 +78,43 @@ casify_object (flag, obj) if (STRINGP (obj)) { int multibyte = STRING_MULTIBYTE (obj); - int n; + int i, i_byte, len; + int size = SCHARS (obj); obj = Fcopy_sequence (obj); - len = SBYTES (obj); - - /* I counts bytes, and N counts chars. */ - for (i = n = 0; i < len; n++) + for (i = i_byte = 0; i < size; i++, i_byte += len) { - int from_len = 1, to_len = 1; - - c = SREF (obj, i); - - if (multibyte && c >= 0x80) - c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i, len -i, from_len); + if (multibyte) + c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len); + else + { + c = SREF (obj, i_byte); + len = 1; + MAKE_CHAR_MULTIBYTE (c); + } + c1 = c; if (inword && flag != CASE_CAPITALIZE_UP) c = DOWNCASE (c); else if (!UPPERCASEP (c) && (!inword || flag != CASE_CAPITALIZE_UP)) - c = UPCASE1 (c); - if ((ASCII_BYTE_P (c) && from_len == 1) - || (! multibyte && SINGLE_BYTE_CHAR_P (c))) - SSET (obj, i, c); - else + c = UPCASE1 (c1); + if ((int) flag >= (int) CASE_CAPITALIZE) + inword = (SYNTAX (c) == Sword); + if (c != c1) { - to_len = CHAR_BYTES (c); - if (from_len == to_len) - CHAR_STRING (c, SDATA (obj) + i); + if (! multibyte) + { + MAKE_CHAR_UNIBYTE (c); + SSET (obj, i_byte, c); + } + else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c)) + SSET (obj, i_byte, c); else { - Faset (obj, make_number (n), make_number (c)); - len += to_len - from_len; + Faset (obj, make_number (i), make_number (c)); + i_byte += CHAR_BYTES (c) - len; } } - if ((int) flag >= (int) CASE_CAPITALIZE) - inword = SYNTAX (c) == Sword; - i += to_len; } return obj; } @@ -168,13 +176,14 @@ casify_region (flag, b, e) enum case_action flag; Lisp_Object b, e; { - register int i; register int c; register int inword = flag == CASE_DOWN; register int multibyte = !NILP (current_buffer->enable_multibyte_characters); - int start, end; - int start_byte, end_byte; - int changed = 0; + EMACS_INT start, end; + EMACS_INT start_byte, end_byte; + EMACS_INT first = -1, last; /* Position of first and last changes. */ + EMACS_INT opoint = PT; + EMACS_INT opoint_byte = PT_BYTE; if (EQ (b, e)) /* Not modifying because nothing marked */ @@ -192,87 +201,78 @@ casify_region (flag, b, e) start_byte = CHAR_TO_BYTE (start); end_byte = CHAR_TO_BYTE (end); - for (i = start_byte; i < end_byte; i++, start++) + while (start < end) { - int c2; - c = c2 = FETCH_BYTE (i); - if (multibyte && c >= 0x80) - /* A multibyte character can't be handled in this simple loop. */ - break; + int c2, len; + + if (multibyte) + { + c = FETCH_MULTIBYTE_CHAR (start_byte); + len = CHAR_BYTES (c); + } + else + { + c = FETCH_BYTE (start_byte); + MAKE_CHAR_MULTIBYTE (c); + len = 1; + } + c2 = c; if (inword && flag != CASE_CAPITALIZE_UP) c = DOWNCASE (c); else if (!UPPERCASEP (c) && (!inword || flag != CASE_CAPITALIZE_UP)) c = UPCASE1 (c); - if (multibyte && c >= 0x80) - /* A multibyte result character can't be handled in this - simple loop. */ - break; - FETCH_BYTE (i) = c; - if (c != c2) - changed = 1; if ((int) flag >= (int) CASE_CAPITALIZE) - inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c)); - } - 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 (start < end) + inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c))); + if (c != c2) { - if ((c = FETCH_BYTE (i)) >= 0x80) - c = FETCH_MULTIBYTE_CHAR (i); - c2 = c; - if (inword && flag != CASE_CAPITALIZE_UP) - c2 = DOWNCASE (c); - else if (!UPPERCASEP (c) - && (!inword || flag != CASE_CAPITALIZE_UP)) - c2 = UPCASE1 (c); - if (c != c2) + last = start; + if (first < 0) + first = start; + + if (! multibyte) + { + MAKE_CHAR_UNIBYTE (c); + FETCH_BYTE (start_byte) = c; + } + else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c)) + FETCH_BYTE (start_byte) = c; + else { - int fromlen, tolen, j; + int tolen = CHAR_BYTES (c); + int j; unsigned char str[MAX_MULTIBYTE_LENGTH]; - changed = 1; - /* Handle the most likely case */ - if (c < 0400 && c2 < 0400) - FETCH_BYTE (i) = c2; - else if (fromlen = CHAR_STRING (c, str), - tolen = CHAR_STRING (c2, str), - fromlen == tolen) + CHAR_STRING (c, str); + if (len == tolen) { /* Length is unchanged. */ - for (j = 0; j < tolen; ++j) - FETCH_BYTE (i + j) = str[j]; + for (j = 0; j < len; ++j) + FETCH_BYTE (start_byte + j) = str[j]; } else { /* Replace one character with the other, keeping text properties the same. */ - replace_range_2 (start, i, - start + 1, i + fromlen, + replace_range_2 (start, start_byte, + start + 1, start_byte + len, str, 1, tolen, - 1); - if (opoint > start) - opoint_byte += tolen - fromlen; + 0); + len = tolen; } } - if ((int) flag >= (int) CASE_CAPITALIZE) - inword = SYNTAX (c2) == Sword; - INC_BOTH (start, i); } - TEMP_SET_PT_BOTH (opoint, opoint_byte); + start++; + start_byte += len; } - start = XFASTINT (b); - if (changed) + if (PT != opoint) + TEMP_SET_PT_BOTH (opoint, opoint_byte); + + if (first >= 0) { - signal_after_change (start, end - start, end - start); - update_compositions (start, end, CHECK_ALL); + signal_after_change (first, last + 1 - first, last + 1 - first); + update_compositions (first, last + 1, CHECK_ALL); } }