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