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