* alloc.c (pure_bytes_used_lisp, pure_bytes_used_non_lisp):
[bpt/emacs.git] / src / casefiddle.c
CommitLineData
dcfdbac7 1/* GNU Emacs case conversion functions.
95df8112
GM
2
3Copyright (C) 1985, 1994, 1997-1999, 2001-2011 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 34\f
181aa2be 35static Lisp_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 41 /* If the case table is flagged as modified, rescan it. */
4b4deea2
TT
42 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1]))
43 Fset_case_table (BVAR (current_buffer, downcase_table));
bd47bd35 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;
4b4deea2 50 int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters));
0d64f689
KH
51
52 /* If the character has higher bits set
53 above the flags, return it unchanged.
54 It is not a real character. */
ea204efb 55 if (UNSIGNED_CMP (XFASTINT (obj), >, flagbits))
0d64f689
KH
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);
5da9919f 67 c = downcase (c1);
0d64f689
KH
68 if (inword)
69 XSETFASTINT (obj, c | flags);
70 else if (c == (XFASTINT (obj) & ~flagbits))
dcfdbac7 71 {
0d64f689 72 if (! inword)
5da9919f 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 {
d311d28c
PE
85 ptrdiff_t i;
86 ptrdiff_t 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)
5da9919f
PE
95 c = downcase (c);
96 else if (!uppercasep (c)
0d64f689 97 && (!inword || flag != CASE_CAPITALIZE_UP))
5da9919f 98 c = upcase1 (c1);
0d64f689
KH
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 {
d311d28c 114 ptrdiff_t i, i_byte, size = SCHARS (obj);
994b75e0 115 int len;
438eba3c
SM
116 USE_SAFE_ALLOCA;
117 unsigned char *dst, *o;
d311d28c
PE
118 ptrdiff_t o_size = (size < STRING_BYTES_BOUND / MAX_MULTIBYTE_LENGTH
119 ? size * MAX_MULTIBYTE_LENGTH
120 : STRING_BYTES_BOUND);
438eba3c
SM
121 SAFE_ALLOCA (dst, void *, o_size);
122 o = dst;
123
124 for (i = i_byte = 0; i < size; i++, i_byte += len)
125 {
d311d28c
PE
126 if (o_size - (o - dst) < MAX_MULTIBYTE_LENGTH)
127 string_overflow ();
62a6e103 128 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
438eba3c 129 if (inword && flag != CASE_CAPITALIZE_UP)
5da9919f
PE
130 c = downcase (c);
131 else if (!uppercasep (c)
438eba3c 132 && (!inword || flag != CASE_CAPITALIZE_UP))
5da9919f 133 c = upcase1 (c);
438eba3c
SM
134 if ((int) flag >= (int) CASE_CAPITALIZE)
135 inword = (SYNTAX (c) == Sword);
136 o += CHAR_STRING (c, o);
dcfdbac7 137 }
438eba3c 138 eassert (o - dst <= o_size);
47ce90e4 139 obj = make_multibyte_string ((char *) dst, size, o - dst);
438eba3c 140 SAFE_FREE ();
0d64f689 141 return obj;
dcfdbac7
JB
142 }
143}
144
a7ca3326 145DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
fdb82f93
PJ
146 doc: /* Convert argument to upper case and return that.
147The argument may be a character or string. The result has the same type.
148The argument object is not altered--the value is a copy.
149See also `capitalize', `downcase' and `upcase-initials'. */)
5842a27b 150 (Lisp_Object obj)
dcfdbac7
JB
151{
152 return casify_object (CASE_UP, obj);
153}
154
a7ca3326 155DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0,
fdb82f93
PJ
156 doc: /* Convert argument to lower case and return that.
157The argument may be a character or string. The result has the same type.
158The argument object is not altered--the value is a copy. */)
5842a27b 159 (Lisp_Object obj)
dcfdbac7
JB
160{
161 return casify_object (CASE_DOWN, obj);
162}
163
164DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
fdb82f93
PJ
165 doc: /* Convert argument to capitalized form and return that.
166This means that each word's first character is upper case
167and the rest is lower case.
168The argument may be a character or string. The result has the same type.
169The argument object is not altered--the value is a copy. */)
5842a27b 170 (Lisp_Object obj)
dcfdbac7
JB
171{
172 return casify_object (CASE_CAPITALIZE, obj);
173}
96927ba4 174
2371fad4
KH
175/* Like Fcapitalize but change only the initials. */
176
a7ca3326 177DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
fdb82f93
PJ
178 doc: /* Convert the initial of each word in the argument to upper case.
179Do not change the other letters of each word.
180The argument may be a character or string. The result has the same type.
181The argument object is not altered--the value is a copy. */)
5842a27b 182 (Lisp_Object obj)
8cef1f78
RS
183{
184 return casify_object (CASE_CAPITALIZE_UP, obj);
185}
dcfdbac7
JB
186\f
187/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
188 b and e specify range of buffer to operate on. */
189
181aa2be 190static void
971de7fb 191casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e)
dcfdbac7 192{
dcfdbac7
JB
193 register int c;
194 register int inword = flag == CASE_DOWN;
4b4deea2 195 register int multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
d311d28c
PE
196 ptrdiff_t start, end;
197 ptrdiff_t start_byte;
e45a141a
PE
198
199 /* Position of first and last changes. */
d311d28c 200 ptrdiff_t first = -1, last IF_LINT (= 0);
e45a141a 201
d311d28c
PE
202 ptrdiff_t opoint = PT;
203 ptrdiff_t opoint_byte = PT_BYTE;
dcfdbac7
JB
204
205 if (EQ (b, e))
206 /* Not modifying because nothing marked */
207 return;
208
bd47bd35 209 /* If the case table is flagged as modified, rescan it. */
4b4deea2
TT
210 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1]))
211 Fset_case_table (BVAR (current_buffer, downcase_table));
bd47bd35 212
dcfdbac7 213 validate_region (&b, &e);
2371fad4
KH
214 start = XFASTINT (b);
215 end = XFASTINT (e);
3e145152 216 modify_region (current_buffer, start, end, 0);
2371fad4 217 record_change (start, end - start);
4c7b7eab 218 start_byte = CHAR_TO_BYTE (start);
dcfdbac7 219
5e617bc2 220 SETUP_BUFFER_SYNTAX_TABLE (); /* For syntax_prefix_flag_p. */
c785836d 221
2422e50a 222 while (start < end)
a04538da 223 {
2422e50a
KH
224 int c2, len;
225
226 if (multibyte)
227 {
228 c = FETCH_MULTIBYTE_CHAR (start_byte);
229 len = CHAR_BYTES (c);
230 }
231 else
232 {
233 c = FETCH_BYTE (start_byte);
234 MAKE_CHAR_MULTIBYTE (c);
235 len = 1;
236 }
237 c2 = c;
a0615d90 238 if (inword && flag != CASE_CAPITALIZE_UP)
5da9919f
PE
239 c = downcase (c);
240 else if (!uppercasep (c)
a0615d90 241 && (!inword || flag != CASE_CAPITALIZE_UP))
5da9919f 242 c = upcase1 (c);
a0615d90 243 if ((int) flag >= (int) CASE_CAPITALIZE)
c5683ceb
SM
244 inword = ((SYNTAX (c) == Sword)
245 && (inword || !syntax_prefix_flag_p (c)));
2422e50a 246 if (c != c2)
a04538da 247 {
7927d8e3
SM
248 last = start;
249 if (first < 0)
250 first = start;
251
2422e50a
KH
252 if (! multibyte)
253 {
254 MAKE_CHAR_UNIBYTE (c);
255 FETCH_BYTE (start_byte) = c;
256 }
257 else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c))
258 FETCH_BYTE (start_byte) = c;
08588bfa 259 else
a04538da 260 {
08588bfa 261 int tolen = CHAR_BYTES (c);
2422e50a 262 int j;
66da2880 263 unsigned char str[MAX_MULTIBYTE_LENGTH];
a04538da 264
2422e50a 265 CHAR_STRING (c, str);
08588bfa
KH
266 if (len == tolen)
267 {
268 /* Length is unchanged. */
269 for (j = 0; j < len; ++j)
270 FETCH_BYTE (start_byte + j) = str[j];
271 }
272 else
273 {
274 /* Replace one character with the other,
275 keeping text properties the same. */
276 replace_range_2 (start, start_byte,
277 start + 1, start_byte + len,
47ce90e4 278 (char *) str, 1, tolen,
08588bfa
KH
279 0);
280 len = tolen;
281 }
a04538da 282 }
a04538da 283 }
2422e50a
KH
284 start++;
285 start_byte += len;
dcfdbac7
JB
286 }
287
8f924df7
KH
288 if (PT != opoint)
289 TEMP_SET_PT_BOTH (opoint, opoint_byte);
290
7927d8e3 291 if (first >= 0)
66da2880 292 {
7927d8e3
SM
293 signal_after_change (first, last + 1 - first, last + 1 - first);
294 update_compositions (first, last + 1, CHECK_ALL);
66da2880 295 }
dcfdbac7
JB
296}
297
a7ca3326 298DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
fdb82f93
PJ
299 doc: /* Convert the region to upper case. In programs, wants two arguments.
300These arguments specify the starting and ending character numbers of
301the region to operate on. When used as a command, the text between
302point and the mark is operated on.
303See also `capitalize-region'. */)
5842a27b 304 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 305{
8c22d56c 306 casify_region (CASE_UP, beg, end);
dcfdbac7
JB
307 return Qnil;
308}
309
310DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
fdb82f93
PJ
311 doc: /* Convert the region to lower case. In programs, wants two arguments.
312These arguments specify the starting and ending character numbers of
313the region to operate on. When used as a command, the text between
314point and the mark is operated on. */)
5842a27b 315 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 316{
8c22d56c 317 casify_region (CASE_DOWN, beg, end);
dcfdbac7
JB
318 return Qnil;
319}
320
321DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
fdb82f93
PJ
322 doc: /* Convert the region to capitalized form.
323Capitalized form means each word's first character is upper case
324and the rest of it is lower case.
325In programs, give two arguments, the starting and ending
326character positions to operate on. */)
5842a27b 327 (Lisp_Object beg, Lisp_Object end)
dcfdbac7 328{
8c22d56c 329 casify_region (CASE_CAPITALIZE, beg, end);
dcfdbac7
JB
330 return Qnil;
331}
332
2371fad4
KH
333/* Like Fcapitalize_region but change only the initials. */
334
a7ca3326 335DEFUN ("upcase-initials-region", Fupcase_initials_region,
8cef1f78 336 Supcase_initials_region, 2, 2, "r",
fdb82f93
PJ
337 doc: /* Upcase the initial of each word in the region.
338Subsequent letters of each word are not changed.
339In programs, give two arguments, the starting and ending
340character positions to operate on. */)
5842a27b 341 (Lisp_Object beg, Lisp_Object end)
8cef1f78 342{
8c22d56c 343 casify_region (CASE_CAPITALIZE_UP, beg, end);
8cef1f78
RS
344 return Qnil;
345}
dcfdbac7 346\f
438eba3c 347static Lisp_Object
d311d28c 348operate_on_word (Lisp_Object arg, ptrdiff_t *newpoint)
dcfdbac7 349{
39fb55ff 350 Lisp_Object val;
d311d28c 351 ptrdiff_t farend;
4f3a2f8d 352 EMACS_INT iarg;
dcfdbac7 353
b7826503 354 CHECK_NUMBER (arg);
2371fad4 355 iarg = XINT (arg);
6ec8bbd2 356 farend = scan_words (PT, iarg);
dcfdbac7 357 if (!farend)
2371fad4 358 farend = iarg > 0 ? ZV : BEGV;
dcfdbac7 359
6ec8bbd2 360 *newpoint = PT > farend ? PT : farend;
18e23fd0 361 XSETFASTINT (val, farend);
dcfdbac7
JB
362
363 return val;
364}
365
366DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p",
fdb82f93
PJ
367 doc: /* Convert following word (or ARG words) to upper case, moving over.
368With negative argument, convert previous words but do not move.
369See also `capitalize-word'. */)
5842a27b 370 (Lisp_Object arg)
dcfdbac7 371{
34628a90 372 Lisp_Object beg, end;
d311d28c 373 ptrdiff_t newpoint;
6ec8bbd2 374 XSETFASTINT (beg, PT);
34628a90
RS
375 end = operate_on_word (arg, &newpoint);
376 casify_region (CASE_UP, beg, end);
377 SET_PT (newpoint);
dcfdbac7
JB
378 return Qnil;
379}
380
381DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p",
fdb82f93
PJ
382 doc: /* Convert following word (or ARG words) to lower case, moving over.
383With negative argument, convert previous words but do not move. */)
5842a27b 384 (Lisp_Object arg)
dcfdbac7 385{
34628a90 386 Lisp_Object beg, end;
d311d28c 387 ptrdiff_t newpoint;
6ec8bbd2 388 XSETFASTINT (beg, PT);
34628a90
RS
389 end = operate_on_word (arg, &newpoint);
390 casify_region (CASE_DOWN, beg, end);
391 SET_PT (newpoint);
dcfdbac7
JB
392 return Qnil;
393}
394
395DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p",
fdb82f93
PJ
396 doc: /* Capitalize the following word (or ARG words), moving over.
397This gives the word(s) a first character in upper case
398and the rest lower case.
399With negative argument, capitalize previous words but do not move. */)
5842a27b 400 (Lisp_Object arg)
dcfdbac7 401{
34628a90 402 Lisp_Object beg, end;
d311d28c 403 ptrdiff_t newpoint;
6ec8bbd2 404 XSETFASTINT (beg, PT);
34628a90
RS
405 end = operate_on_word (arg, &newpoint);
406 casify_region (CASE_CAPITALIZE, beg, end);
407 SET_PT (newpoint);
dcfdbac7
JB
408 return Qnil;
409}
410\f
dfcf069d 411void
971de7fb 412syms_of_casefiddle (void)
dcfdbac7 413{
cd3520a4 414 DEFSYM (Qidentity, "identity");
dcfdbac7
JB
415 defsubr (&Supcase);
416 defsubr (&Sdowncase);
417 defsubr (&Scapitalize);
8cef1f78 418 defsubr (&Supcase_initials);
dcfdbac7
JB
419 defsubr (&Supcase_region);
420 defsubr (&Sdowncase_region);
421 defsubr (&Scapitalize_region);
8cef1f78 422 defsubr (&Supcase_initials_region);
dcfdbac7
JB
423 defsubr (&Supcase_word);
424 defsubr (&Sdowncase_word);
425 defsubr (&Scapitalize_word);
426}
427
dfcf069d 428void
971de7fb 429keys_of_casefiddle (void)
dcfdbac7 430{
5e617bc2 431 initial_define_key (control_x_map, Ctl ('U'), "upcase-region");
d427b66a 432 Fput (intern ("upcase-region"), Qdisabled, Qt);
5e617bc2 433 initial_define_key (control_x_map, Ctl ('L'), "downcase-region");
d427b66a
JB
434 Fput (intern ("downcase-region"), Qdisabled, Qt);
435
dcfdbac7
JB
436 initial_define_key (meta_map, 'u', "upcase-word");
437 initial_define_key (meta_map, 'l', "downcase-word");
438 initial_define_key (meta_map, 'c', "capitalize-word");
439}