/* GNU Emacs case conversion functions.
- Copyright (C) 1985, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "charset.h"
#include "commands.h"
#include "syntax.h"
+#include "composite.h"
enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
{
register int i, c, len;
register int inword = flag == CASE_DOWN;
- Lisp_Object tem;
/* If the case table is flagged as modified, rescan it. */
if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
{
if (INTEGERP (obj))
{
- c = DOWNCASE (XFASTINT (obj));
+ int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
+ | CHAR_SHIFT | CHAR_CTL | CHAR_META);
+ int flags = XINT (obj) & flagbits;
+
+ c = DOWNCASE (XFASTINT (obj) & ~flagbits);
if (inword)
- XSETFASTINT (obj, c);
- else if (c == XFASTINT (obj))
+ XSETFASTINT (obj, c | flags);
+ else if (c == (XFASTINT (obj) & ~flagbits))
{
- c = UPCASE1 (XFASTINT (obj));
- XSETFASTINT (obj, c);
+ c = UPCASE1 ((XFASTINT (obj) & ~flagbits));
+ XSETFASTINT (obj, c | flags);
}
return obj;
}
int multibyte = STRING_MULTIBYTE (obj);
obj = Fcopy_sequence (obj);
- len = XSTRING (obj)->size_byte;
+ len = STRING_BYTES (XSTRING (obj));
/* Scan all single-byte characters from start of string. */
for (i = 0; i < len;)
{
/* The work is not yet finished because of a multibyte
character just encountered. */
- int fromlen, tolen, j = i, j_byte = i;
+ int fromlen, tolen, j_byte = i;
char *buf
- = (char *) alloca ((len - i) * MAX_LENGTH_OF_MULTI_BYTE_FORM
- + i);
- unsigned char *str, workbuf[4];
+ = (char *) alloca ((len - i) * MAX_MULTIBYTE_LENGTH + i);
/* Copy data already handled. */
bcopy (XSTRING (obj)->data, buf, i);
else if (!UPPERCASEP (c)
&& (!inword || flag != CASE_CAPITALIZE_UP))
c = UPCASE1 (c);
- tolen = CHAR_STRING (c, workbuf, str);
- bcopy (str, buf + j_byte, tolen);
i += fromlen;
- j++;
- j_byte += tolen;
+ j_byte += CHAR_STRING (c, buf + j_byte);
if ((int) flag >= (int) CASE_CAPITALIZE)
inword = SYNTAX (c) == Sword;
}
- obj = make_multibyte_string (buf, j, j_byte);
+ obj = make_multibyte_string (buf, XSTRING (obj)->size,
+ j_byte);
}
return obj;
}
/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
b and e specify range of buffer to operate on. */
+void
casify_region (flag, b, e)
enum case_action flag;
Lisp_Object b, e;
register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
int start, end;
int start_byte, end_byte;
- Lisp_Object ch, downch, val;
+ int changed = 0;
if (EQ (b, e))
/* Not modifying because nothing marked */
start_byte = CHAR_TO_BYTE (start);
end_byte = CHAR_TO_BYTE (end);
- for (i = start_byte; i < end_byte; i++)
+ for (i = start_byte; i < end_byte; i++, start++)
{
- c = FETCH_BYTE (i);
+ int c2;
+ c = c2 = FETCH_BYTE (i);
if (multibyte && c >= 0x80)
/* A multibyte character can't be handled in this simple loop. */
break;
&& (!inword || flag != CASE_CAPITALIZE_UP))
c = UPCASE1 (c);
FETCH_BYTE (i) = c;
+ if (c != c2)
+ changed = 1;
if ((int) flag >= (int) CASE_CAPITALIZE)
inword = SYNTAX (c) == Sword;
}
if (c != c2)
{
int fromlen, tolen, j;
- unsigned char workbuf[4], *str;
+ 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, workbuf, str),
- tolen = CHAR_STRING (c2, workbuf, str),
+ else if (fromlen = CHAR_STRING (c, str),
+ tolen = CHAR_STRING (c2, str),
fromlen == tolen)
{
for (j = 0; j < tolen; ++j)
error ("Can't casify letters that change length");
#if 0 /* This is approximately what we'd like to be able to do here */
if (tolen < fromlen)
- del_range_1 (i + tolen, i + fromlen, 0);
+ del_range_1 (i + tolen, i + fromlen, 0, 0);
else if (tolen > fromlen)
{
TEMP_SET_PT (i + fromlen);
}
if ((int) flag >= (int) CASE_CAPITALIZE)
inword = SYNTAX (c2) == Sword;
- INC_POS (i);
+ INC_BOTH (start, i);
}
TEMP_SET_PT_BOTH (opoint, opoint_byte);
}
- signal_after_change (start, end - start, end - start);
+ start = XFASTINT (b);
+ if (changed)
+ {
+ signal_after_change (start, end - start, end - start);
+ update_compositions (start, end, CHECK_ALL);
+ }
}
DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
return Qnil;
}
\f
+void
syms_of_casefiddle ()
{
Qidentity = intern ("identity");
defsubr (&Scapitalize_word);
}
+void
keys_of_casefiddle ()
{
initial_define_key (control_x_map, Ctl('U'), "upcase-region");