X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/d29ee6b1a110cf5d170a10317a96acbbd4a1c68b..cbf21103d9fad16fe87d9affbc955c75cce657e4:/src/casefiddle.c diff --git a/src/casefiddle.c b/src/casefiddle.c index 2984201a03..bda49fb365 100644 --- a/src/casefiddle.c +++ b/src/casefiddle.c @@ -1,13 +1,13 @@ /* 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. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,9 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ #include @@ -59,6 +57,12 @@ casify_object (flag, obj) return obj; c1 = XFASTINT (obj) & ~flagbits; + /* FIXME: Even if enable-multibyte-characters is nil, we may + manipulate multibyte chars. This means we have a bug for latin-1 + chars since when we receive an int 128-255 we can't tell whether + it's an eight-bit byte or a latin-1 char. */ + if (c1 >= 256) + multibyte = 1; if (! multibyte) MAKE_CHAR_MULTIBYTE (c1); c = DOWNCASE (c1); @@ -75,23 +79,18 @@ casify_object (flag, obj) return obj; } - if (STRINGP (obj)) + if (!STRINGP (obj)) + wrong_type_argument (Qchar_or_string_p, obj); + else if (!STRING_MULTIBYTE (obj)) { - int multibyte = STRING_MULTIBYTE (obj); - int i, i_byte, len; - int size = SCHARS (obj); + EMACS_INT i; + EMACS_INT size = SCHARS (obj); obj = Fcopy_sequence (obj); - for (i = i_byte = 0; i < size; i++, i_byte += len) + for (i = 0; i < size; i++) { - if (multibyte) - c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len); - else - { - c = SREF (obj, i_byte); - len = 1; + c = SREF (obj, i); MAKE_CHAR_MULTIBYTE (c); - } c1 = c; if (inword && flag != CASE_CAPITALIZE_UP) c = DOWNCASE (c); @@ -102,24 +101,52 @@ casify_object (flag, obj) inword = (SYNTAX (c) == Sword); if (c != c1) { - 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 (i), make_number (c)); - i_byte += CHAR_BYTES (c) - len; - } + /* If the char can't be converted to a valid byte, just don't + change it. */ + if (c >= 0 && c < 256) + SSET (obj, i, c); } } return obj; } + else + { + EMACS_INT i, i_byte, size = SCHARS (obj); + int len; + USE_SAFE_ALLOCA; + unsigned char *dst, *o; + /* Over-allocate by 12%: this is a minor overhead, but should be + sufficient in 99.999% of the cases to avoid a reallocation. */ + EMACS_INT o_size = SBYTES (obj) + SBYTES (obj) / 8 + MAX_MULTIBYTE_LENGTH; + SAFE_ALLOCA (dst, void *, o_size); + o = dst; - wrong_type_argument (Qchar_or_string_p, obj); + for (i = i_byte = 0; i < size; i++, i_byte += len) + { + if ((o - dst) + MAX_MULTIBYTE_LENGTH > o_size) + { /* Not enough space for the next char: grow the destination. */ + unsigned char *old_dst = dst; + o_size += o_size; /* Probably overkill, but extremely rare. */ + SAFE_ALLOCA (dst, void *, o_size); + bcopy (old_dst, dst, o - old_dst); + o = dst + (o - old_dst); + } + c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, 0, len); + if (inword && flag != CASE_CAPITALIZE_UP) + c = DOWNCASE (c); + else if (!UPPERCASEP (c) + && (!inword || flag != CASE_CAPITALIZE_UP)) + c = UPCASE1 (c); + if ((int) flag >= (int) CASE_CAPITALIZE) + inword = (SYNTAX (c) == Sword); + o += CHAR_STRING (c, o); + } + eassert (o - dst <= o_size); + obj = make_multibyte_string (dst, size, o - dst); + SAFE_FREE (); + return obj; + } } DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, @@ -179,11 +206,11 @@ casify_region (flag, b, e) 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; - int opoint = PT; - int opoint_byte = PT_BYTE; + 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 */ @@ -226,7 +253,10 @@ casify_region (flag, b, e) inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (c))); if (c != c2) { - changed = 1; + last = start; + if (first < 0) + first = start; + if (! multibyte) { MAKE_CHAR_UNIBYTE (c); @@ -266,11 +296,10 @@ casify_region (flag, b, e) if (PT != opoint) TEMP_SET_PT_BOTH (opoint, opoint_byte); - if (changed) + if (first >= 0) { - start = XFASTINT (b); - 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); } } @@ -327,10 +356,10 @@ character positions to operate on. */) return Qnil; } -Lisp_Object +static Lisp_Object operate_on_word (arg, newpoint) Lisp_Object arg; - int *newpoint; + EMACS_INT *newpoint; { Lisp_Object val; int farend; @@ -356,7 +385,7 @@ See also `capitalize-word'. */) Lisp_Object arg; { Lisp_Object beg, end; - int newpoint; + EMACS_INT newpoint; XSETFASTINT (beg, PT); end = operate_on_word (arg, &newpoint); casify_region (CASE_UP, beg, end); @@ -371,7 +400,7 @@ With negative argument, convert previous words but do not move. */) Lisp_Object arg; { Lisp_Object beg, end; - int newpoint; + EMACS_INT newpoint; XSETFASTINT (beg, PT); end = operate_on_word (arg, &newpoint); casify_region (CASE_DOWN, beg, end); @@ -388,7 +417,7 @@ With negative argument, capitalize previous words but do not move. */) Lisp_Object arg; { Lisp_Object beg, end; - int newpoint; + EMACS_INT newpoint; XSETFASTINT (beg, PT); end = operate_on_word (arg, &newpoint); casify_region (CASE_CAPITALIZE, beg, end);