(add_registry): Set path for runemacs.exe to use.
[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
2422e50a 224 while (start < end)
a04538da 225 {
2422e50a
KH
226 int c2, len;
227
228 if (multibyte)
229 {
230 c = FETCH_MULTIBYTE_CHAR (start_byte);
231 len = CHAR_BYTES (c);
232 }
233 else
234 {
235 c = FETCH_BYTE (start_byte);
236 MAKE_CHAR_MULTIBYTE (c);
237 len = 1;
238 }
239 c2 = c;
a0615d90
KH
240 if (inword && flag != CASE_CAPITALIZE_UP)
241 c = DOWNCASE (c);
242 else if (!UPPERCASEP (c)
243 && (!inword || flag != CASE_CAPITALIZE_UP))
244 c = UPCASE1 (c);
a0615d90 245 if ((int) flag >= (int) CASE_CAPITALIZE)
8f924df7 246 inword = ((SYNTAX (c) == Sword) && (inword || !SYNTAX_PREFIX (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,
279 str, 1, tolen,
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
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
8cef1f78
RS
336DEFUN ("upcase-initials-region", Fupcase_initials_region,
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
971de7fb 349operate_on_word (Lisp_Object arg, EMACS_INT *newpoint)
dcfdbac7 350{
39fb55ff 351 Lisp_Object val;
34628a90 352 int farend;
2371fad4 353 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;
438eba3c 374 EMACS_INT 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;
438eba3c 388 EMACS_INT 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;
438eba3c 404 EMACS_INT 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{
d67b4f80 415 Qidentity = intern_c_string ("identity");
a04538da 416 staticpro (&Qidentity);
dcfdbac7
JB
417 defsubr (&Supcase);
418 defsubr (&Sdowncase);
419 defsubr (&Scapitalize);
8cef1f78 420 defsubr (&Supcase_initials);
dcfdbac7
JB
421 defsubr (&Supcase_region);
422 defsubr (&Sdowncase_region);
423 defsubr (&Scapitalize_region);
8cef1f78 424 defsubr (&Supcase_initials_region);
dcfdbac7
JB
425 defsubr (&Supcase_word);
426 defsubr (&Sdowncase_word);
427 defsubr (&Scapitalize_word);
428}
429
dfcf069d 430void
971de7fb 431keys_of_casefiddle (void)
dcfdbac7
JB
432{
433 initial_define_key (control_x_map, Ctl('U'), "upcase-region");
d427b66a 434 Fput (intern ("upcase-region"), Qdisabled, Qt);
dcfdbac7 435 initial_define_key (control_x_map, Ctl('L'), "downcase-region");
d427b66a
JB
436 Fput (intern ("downcase-region"), Qdisabled, Qt);
437
dcfdbac7
JB
438 initial_define_key (meta_map, 'u', "upcase-word");
439 initial_define_key (meta_map, 'l', "downcase-word");
440 initial_define_key (meta_map, 'c', "capitalize-word");
441}
6b61353c
KH
442
443/* arch-tag: 60a73c66-5489-47e7-a81f-cead4057c526
444 (do not change this comment) */