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