Fix EMACS_INT/int conversion in scroll.c.
[bpt/emacs.git] / src / casefiddle.c
CommitLineData
dcfdbac7 1/* GNU Emacs case conversion functions.
0b5538bd 2 Copyright (C) 1985, 1994, 1997, 1998, 1999, 2001, 2002, 2003, 2004,
114f9c96 3 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
dcfdbac7
JB
4
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
dcfdbac7 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
dcfdbac7
JB
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
dcfdbac7
JB
19
20
18160b98 21#include <config.h>
d7306fe6 22#include <setjmp.h>
dcfdbac7
JB
23#include "lisp.h"
24#include "buffer.h"
83be827a 25#include "character.h"
dcfdbac7
JB
26#include "commands.h"
27#include "syntax.h"
66da2880 28#include "composite.h"
e35f6ff7 29#include "keymap.h"
dcfdbac7
JB
30
31enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
a04538da
KH
32
33Lisp_Object Qidentity;
dcfdbac7
JB
34\f
35Lisp_Object
971de7fb 36casify_object (enum case_action flag, Lisp_Object obj)
dcfdbac7 37{
2422e50a 38 register int c, c1;
dcfdbac7
JB
39 register int inword = flag == CASE_DOWN;
40
bd47bd35
RS
41 /* If the case table is flagged as modified, rescan it. */
42 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
43 Fset_case_table (current_buffer->downcase_table);
44
0d64f689 45 if (INTEGERP (obj))
dcfdbac7 46 {
0d64f689
KH
47 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
48 | CHAR_SHIFT | CHAR_CTL | CHAR_META);
49 int flags = XINT (obj) & flagbits;
50 int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
51
52 /* If the character has higher bits set
53 above the flags, return it unchanged.
54 It is not a real character. */
55 if ((unsigned) XFASTINT (obj) > (unsigned) flagbits)
56 return obj;
57
58 c1 = XFASTINT (obj) & ~flagbits;
1fb5aad7
SM
59 /* FIXME: Even if enable-multibyte-characters is nil, we may
60 manipulate multibyte chars. This means we have a bug for latin-1
61 chars since when we receive an int 128-255 we can't tell whether
62 it's an eight-bit byte or a latin-1 char. */
63 if (c1 >= 256)
64 multibyte = 1;
0d64f689
KH
65 if (! multibyte)
66 MAKE_CHAR_MULTIBYTE (c1);
67 c = DOWNCASE (c1);
68 if (inword)
69 XSETFASTINT (obj, c | flags);
70 else if (c == (XFASTINT (obj) & ~flagbits))
dcfdbac7 71 {
0d64f689
KH
72 if (! inword)
73 c = UPCASE1 (c1);
2422e50a 74 if (! multibyte)
0d64f689
KH
75 MAKE_CHAR_UNIBYTE (c);
76 XSETFASTINT (obj, c | flags);
dcfdbac7 77 }
0d64f689
KH
78 return obj;
79 }
5245463a 80
438eba3c
SM
81 if (!STRINGP (obj))
82 wrong_type_argument (Qchar_or_string_p, obj);
83 else if (!STRING_MULTIBYTE (obj))
0d64f689 84 {
438eba3c
SM
85 EMACS_INT i;
86 EMACS_INT size = SCHARS (obj);
a0615d90 87
0d64f689 88 obj = Fcopy_sequence (obj);
438eba3c 89 for (i = 0; i < size; i++)
0d64f689 90 {
438eba3c 91 c = SREF (obj, i);
4c0354d7 92 MAKE_CHAR_MULTIBYTE (c);
0d64f689
KH
93 c1 = c;
94 if (inword && flag != CASE_CAPITALIZE_UP)
95 c = DOWNCASE (c);
96 else if (!UPPERCASEP (c)
97 && (!inword || flag != CASE_CAPITALIZE_UP))
98 c = UPCASE1 (c1);
99 if ((int) flag >= (int) CASE_CAPITALIZE)
100 inword = (SYNTAX (c) == Sword);
101 if (c != c1)
102 {
0d64f689 103 MAKE_CHAR_UNIBYTE (c);
438eba3c
SM
104 /* If the char can't be converted to a valid byte, just don't
105 change it. */
106 if (c >= 0 && c < 256)
107 SSET (obj, i, c);
108 }
109 }
110 return obj;
994b75e0
SM
111 }
112 else
113 {
114 EMACS_INT i, i_byte, size = SCHARS (obj);
115 int len;
438eba3c
SM
116 USE_SAFE_ALLOCA;
117 unsigned char *dst, *o;
118 /* Over-allocate by 12%: this is a minor overhead, but should be
119 sufficient in 99.999% of the cases to avoid a reallocation. */
120 EMACS_INT o_size = SBYTES (obj) + SBYTES (obj) / 8 + MAX_MULTIBYTE_LENGTH;
121 SAFE_ALLOCA (dst, void *, o_size);
122 o = dst;
123
124 for (i = i_byte = 0; i < size; i++, i_byte += len)
125 {
126 if ((o - dst) + MAX_MULTIBYTE_LENGTH > o_size)
127 { /* Not enough space for the next char: grow the destination. */
128 unsigned char *old_dst = dst;
129 o_size += o_size; /* Probably overkill, but extremely rare. */
130 SAFE_ALLOCA (dst, void *, o_size);
72af86bd 131 memcpy (dst, old_dst, o - old_dst);
438eba3c 132 o = dst + (o - old_dst);
a0615d90 133 }
62a6e103 134 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
438eba3c
SM
135 if (inword && flag != CASE_CAPITALIZE_UP)
136 c = DOWNCASE (c);
137 else if (!UPPERCASEP (c)
138 && (!inword || flag != CASE_CAPITALIZE_UP))
139 c = UPCASE1 (c);
140 if ((int) flag >= (int) CASE_CAPITALIZE)
141 inword = (SYNTAX (c) == Sword);
142 o += CHAR_STRING (c, o);
dcfdbac7 143 }
438eba3c
SM
144 eassert (o - dst <= o_size);
145 obj = make_multibyte_string (dst, size, o - dst);
146 SAFE_FREE ();
0d64f689 147 return obj;
dcfdbac7
JB
148 }
149}
150
151DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
fdb82f93
PJ
152 doc: /* Convert argument to upper case and return that.
153The argument may be a character or string. The result has the same type.
154The argument object is not altered--the value is a copy.
155See also `capitalize', `downcase' and `upcase-initials'. */)
5842a27b 156 (Lisp_Object obj)
dcfdbac7
JB
157{
158 return casify_object (CASE_UP, obj);
159}
160
161DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0,
fdb82f93
PJ
162 doc: /* Convert argument to lower case and return that.
163The argument may be a character or string. The result has the same type.
164The argument object is not altered--the value is a copy. */)
5842a27b 165 (Lisp_Object obj)
dcfdbac7
JB
166{
167 return casify_object (CASE_DOWN, obj);
168}
169
170DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
fdb82f93
PJ
171 doc: /* Convert argument to capitalized form and return that.
172This means that each word's first character is upper case
173and the rest is lower case.
174The argument may be a character or string. The result has the same type.
175The argument object is not altered--the value is a copy. */)
5842a27b 176 (Lisp_Object obj)
dcfdbac7
JB
177{
178 return casify_object (CASE_CAPITALIZE, obj);
179}
96927ba4 180
2371fad4
KH
181/* Like Fcapitalize but change only the initials. */
182
8cef1f78 183DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
fdb82f93
PJ
184 doc: /* Convert the initial of each word in the argument to upper case.
185Do not change the other letters of each word.
186The argument may be a character or string. The result has the same type.
187The argument object is not altered--the value is a copy. */)
5842a27b 188 (Lisp_Object obj)
8cef1f78
RS
189{
190 return casify_object (CASE_CAPITALIZE_UP, obj);
191}
dcfdbac7
JB
192\f
193/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
194 b and e specify range of buffer to operate on. */
195
dfcf069d 196void
971de7fb 197casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e)
dcfdbac7 198{
dcfdbac7
JB
199 register int c;
200 register int inword = flag == CASE_DOWN;
a0615d90 201 register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
7927d8e3
SM
202 EMACS_INT start, end;
203 EMACS_INT start_byte, end_byte;
204 EMACS_INT first = -1, last; /* Position of first and last changes. */
205 EMACS_INT opoint = PT;
206 EMACS_INT opoint_byte = PT_BYTE;
dcfdbac7
JB
207
208 if (EQ (b, e))
209 /* Not modifying because nothing marked */
210 return;
211
bd47bd35
RS
212 /* If the case table is flagged as modified, rescan it. */
213 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
214 Fset_case_table (current_buffer->downcase_table);
215
dcfdbac7 216 validate_region (&b, &e);
2371fad4
KH
217 start = XFASTINT (b);
218 end = XFASTINT (e);
3e145152 219 modify_region (current_buffer, start, end, 0);
2371fad4 220 record_change (start, end - start);
4c7b7eab
RS
221 start_byte = CHAR_TO_BYTE (start);
222 end_byte = CHAR_TO_BYTE (end);
dcfdbac7 223
c785836d
SM
224 SETUP_BUFFER_SYNTAX_TABLE(); /* For syntax_prefix_flag_p. */
225
2422e50a 226 while (start < end)
a04538da 227 {
2422e50a
KH
228 int c2, len;
229
230 if (multibyte)
231 {
232 c = FETCH_MULTIBYTE_CHAR (start_byte);
233 len = CHAR_BYTES (c);
234 }
235 else
236 {
237 c = FETCH_BYTE (start_byte);
238 MAKE_CHAR_MULTIBYTE (c);
239 len = 1;
240 }
241 c2 = c;
a0615d90
KH
242 if (inword && flag != CASE_CAPITALIZE_UP)
243 c = DOWNCASE (c);
244 else if (!UPPERCASEP (c)
245 && (!inword || flag != CASE_CAPITALIZE_UP))
246 c = UPCASE1 (c);
a0615d90 247 if ((int) flag >= (int) CASE_CAPITALIZE)
c5683ceb
SM
248 inword = ((SYNTAX (c) == Sword)
249 && (inword || !syntax_prefix_flag_p (c)));
2422e50a 250 if (c != c2)
a04538da 251 {
7927d8e3
SM
252 last = start;
253 if (first < 0)
254 first = start;
255
2422e50a
KH
256 if (! multibyte)
257 {
258 MAKE_CHAR_UNIBYTE (c);
259 FETCH_BYTE (start_byte) = c;
260 }
261 else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c))
262 FETCH_BYTE (start_byte) = c;
08588bfa 263 else
a04538da 264 {
08588bfa 265 int tolen = CHAR_BYTES (c);
2422e50a 266 int j;
66da2880 267 unsigned char str[MAX_MULTIBYTE_LENGTH];
a04538da 268
2422e50a 269 CHAR_STRING (c, str);
08588bfa
KH
270 if (len == tolen)
271 {
272 /* Length is unchanged. */
273 for (j = 0; j < len; ++j)
274 FETCH_BYTE (start_byte + j) = str[j];
275 }
276 else
277 {
278 /* Replace one character with the other,
279 keeping text properties the same. */
280 replace_range_2 (start, start_byte,
281 start + 1, start_byte + len,
282 str, 1, tolen,
283 0);
284 len = tolen;
285 }
a04538da 286 }
a04538da 287 }
2422e50a
KH
288 start++;
289 start_byte += len;
dcfdbac7
JB
290 }
291
8f924df7
KH
292 if (PT != opoint)
293 TEMP_SET_PT_BOTH (opoint, opoint_byte);
294
7927d8e3 295 if (first >= 0)
66da2880 296 {
7927d8e3
SM
297 signal_after_change (first, last + 1 - first, last + 1 - first);
298 update_compositions (first, last + 1, CHECK_ALL);
66da2880 299 }
dcfdbac7
JB
300}
301
302DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
fdb82f93
PJ
303 doc: /* Convert the region to upper case. In programs, wants two arguments.
304These arguments specify the starting and ending character numbers of
305the region to operate on. When used as a command, the text between
306point and the mark is operated on.
307See also `capitalize-region'. */)
5842a27b 308 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 309{
8c22d56c 310 casify_region (CASE_UP, beg, end);
dcfdbac7
JB
311 return Qnil;
312}
313
314DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
fdb82f93
PJ
315 doc: /* Convert the region to lower case. In programs, wants two arguments.
316These arguments specify the starting and ending character numbers of
317the region to operate on. When used as a command, the text between
318point and the mark is operated on. */)
5842a27b 319 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 320{
8c22d56c 321 casify_region (CASE_DOWN, beg, end);
dcfdbac7
JB
322 return Qnil;
323}
324
325DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
fdb82f93
PJ
326 doc: /* Convert the region to capitalized form.
327Capitalized form means each word's first character is upper case
328and the rest of it is lower case.
329In programs, give two arguments, the starting and ending
330character positions to operate on. */)
5842a27b 331 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 332{
8c22d56c 333 casify_region (CASE_CAPITALIZE, beg, end);
dcfdbac7
JB
334 return Qnil;
335}
336
2371fad4
KH
337/* Like Fcapitalize_region but change only the initials. */
338
8cef1f78
RS
339DEFUN ("upcase-initials-region", Fupcase_initials_region,
340 Supcase_initials_region, 2, 2, "r",
fdb82f93
PJ
341 doc: /* Upcase the initial of each word in the region.
342Subsequent letters of each word are not changed.
343In programs, give two arguments, the starting and ending
344character positions to operate on. */)
5842a27b 345 (Lisp_Object beg, Lisp_Object end)
8cef1f78 346{
8c22d56c 347 casify_region (CASE_CAPITALIZE_UP, beg, end);
8cef1f78
RS
348 return Qnil;
349}
dcfdbac7 350\f
438eba3c 351static Lisp_Object
971de7fb 352operate_on_word (Lisp_Object arg, EMACS_INT *newpoint)
dcfdbac7 353{
39fb55ff 354 Lisp_Object val;
34628a90 355 int farend;
2371fad4 356 int iarg;
dcfdbac7 357
b7826503 358 CHECK_NUMBER (arg);
2371fad4 359 iarg = XINT (arg);
6ec8bbd2 360 farend = scan_words (PT, iarg);
dcfdbac7 361 if (!farend)
2371fad4 362 farend = iarg > 0 ? ZV : BEGV;
dcfdbac7 363
6ec8bbd2 364 *newpoint = PT > farend ? PT : farend;
18e23fd0 365 XSETFASTINT (val, farend);
dcfdbac7
JB
366
367 return val;
368}
369
370DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p",
fdb82f93
PJ
371 doc: /* Convert following word (or ARG words) to upper case, moving over.
372With negative argument, convert previous words but do not move.
373See also `capitalize-word'. */)
5842a27b 374 (Lisp_Object arg)
dcfdbac7 375{
34628a90 376 Lisp_Object beg, end;
438eba3c 377 EMACS_INT newpoint;
6ec8bbd2 378 XSETFASTINT (beg, PT);
34628a90
RS
379 end = operate_on_word (arg, &newpoint);
380 casify_region (CASE_UP, beg, end);
381 SET_PT (newpoint);
dcfdbac7
JB
382 return Qnil;
383}
384
385DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p",
fdb82f93
PJ
386 doc: /* Convert following word (or ARG words) to lower case, moving over.
387With negative argument, convert previous words but do not move. */)
5842a27b 388 (Lisp_Object arg)
dcfdbac7 389{
34628a90 390 Lisp_Object beg, end;
438eba3c 391 EMACS_INT newpoint;
6ec8bbd2 392 XSETFASTINT (beg, PT);
34628a90
RS
393 end = operate_on_word (arg, &newpoint);
394 casify_region (CASE_DOWN, beg, end);
395 SET_PT (newpoint);
dcfdbac7
JB
396 return Qnil;
397}
398
399DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p",
fdb82f93
PJ
400 doc: /* Capitalize the following word (or ARG words), moving over.
401This gives the word(s) a first character in upper case
402and the rest lower case.
403With negative argument, capitalize previous words but do not move. */)
5842a27b 404 (Lisp_Object arg)
dcfdbac7 405{
34628a90 406 Lisp_Object beg, end;
438eba3c 407 EMACS_INT newpoint;
6ec8bbd2 408 XSETFASTINT (beg, PT);
34628a90
RS
409 end = operate_on_word (arg, &newpoint);
410 casify_region (CASE_CAPITALIZE, beg, end);
411 SET_PT (newpoint);
dcfdbac7
JB
412 return Qnil;
413}
414\f
dfcf069d 415void
971de7fb 416syms_of_casefiddle (void)
dcfdbac7 417{
d67b4f80 418 Qidentity = intern_c_string ("identity");
a04538da 419 staticpro (&Qidentity);
dcfdbac7
JB
420 defsubr (&Supcase);
421 defsubr (&Sdowncase);
422 defsubr (&Scapitalize);
8cef1f78 423 defsubr (&Supcase_initials);
dcfdbac7
JB
424 defsubr (&Supcase_region);
425 defsubr (&Sdowncase_region);
426 defsubr (&Scapitalize_region);
8cef1f78 427 defsubr (&Supcase_initials_region);
dcfdbac7
JB
428 defsubr (&Supcase_word);
429 defsubr (&Sdowncase_word);
430 defsubr (&Scapitalize_word);
431}
432
dfcf069d 433void
971de7fb 434keys_of_casefiddle (void)
dcfdbac7
JB
435{
436 initial_define_key (control_x_map, Ctl('U'), "upcase-region");
d427b66a 437 Fput (intern ("upcase-region"), Qdisabled, Qt);
dcfdbac7 438 initial_define_key (control_x_map, Ctl('L'), "downcase-region");
d427b66a
JB
439 Fput (intern ("downcase-region"), Qdisabled, Qt);
440
dcfdbac7
JB
441 initial_define_key (meta_map, 'u', "upcase-word");
442 initial_define_key (meta_map, 'l', "downcase-word");
443 initial_define_key (meta_map, 'c', "capitalize-word");
444}
6b61353c
KH
445
446/* arch-tag: 60a73c66-5489-47e7-a81f-cead4057c526
447 (do not change this comment) */