(vip-custom-file-name): Use convert-standard-filename.
[bpt/emacs.git] / src / casefiddle.c
CommitLineData
dcfdbac7 1/* GNU Emacs case conversion functions.
3a22ee35 2 Copyright (C) 1985, 1994 Free Software Foundation, Inc.
dcfdbac7
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
7c938215 8the Free Software Foundation; either version 2, or (at your option)
dcfdbac7
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
dcfdbac7
JB
20
21
18160b98 22#include <config.h>
dcfdbac7
JB
23#include "lisp.h"
24#include "buffer.h"
25#include "commands.h"
26#include "syntax.h"
27
28enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
29\f
30Lisp_Object
31casify_object (flag, obj)
32 enum case_action flag;
33 Lisp_Object obj;
34{
35 register int i, c, len;
36 register int inword = flag == CASE_DOWN;
37
bd47bd35
RS
38 /* If the case table is flagged as modified, rescan it. */
39 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
40 Fset_case_table (current_buffer->downcase_table);
41
dcfdbac7
JB
42 while (1)
43 {
9d05e3d4 44 if (INTEGERP (obj))
dcfdbac7
JB
45 {
46 c = XINT (obj);
47 if (c >= 0 && c <= 0400)
48 {
49 if (inword)
18e23fd0 50 XSETFASTINT (obj, DOWNCASE (c));
dcfdbac7 51 else if (!UPPERCASEP (c))
18e23fd0 52 XSETFASTINT (obj, UPCASE1 (c));
dcfdbac7
JB
53 }
54 return obj;
55 }
9d05e3d4 56 if (STRINGP (obj))
dcfdbac7
JB
57 {
58 obj = Fcopy_sequence (obj);
59 len = XSTRING (obj)->size;
60 for (i = 0; i < len; i++)
61 {
62 c = XSTRING (obj)->data[i];
96927ba4 63 if (inword && flag != CASE_CAPITALIZE_UP)
dcfdbac7 64 c = DOWNCASE (c);
96927ba4
RS
65 else if (!UPPERCASEP (c)
66 && (!inword || flag != CASE_CAPITALIZE_UP))
dcfdbac7
JB
67 c = UPCASE1 (c);
68 XSTRING (obj)->data[i] = c;
96927ba4 69 if ((int) flag >= (int) CASE_CAPITALIZE)
dcfdbac7
JB
70 inword = SYNTAX (c) == Sword;
71 }
72 return obj;
73 }
b37902c8 74 obj = wrong_type_argument (Qchar_or_string_p, obj);
dcfdbac7
JB
75 }
76}
77
78DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
79 "Convert argument to upper case and return that.\n\
80The argument may be a character or string. The result has the same type.\n\
8cef1f78
RS
81The argument object is not altered--the value is a copy.\n\
82See also `capitalize', `downcase' and `upcase-initials'.")
dcfdbac7
JB
83 (obj)
84 Lisp_Object obj;
85{
86 return casify_object (CASE_UP, obj);
87}
88
89DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0,
90 "Convert argument to lower case and return that.\n\
91The argument may be a character or string. The result has the same type.\n\
8cef1f78 92The argument object is not altered--the value is a copy.")
dcfdbac7
JB
93 (obj)
94 Lisp_Object obj;
95{
96 return casify_object (CASE_DOWN, obj);
97}
98
99DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
100 "Convert argument to capitalized form and return that.\n\
101This means that each word's first character is upper case\n\
102and the rest is lower case.\n\
103The argument may be a character or string. The result has the same type.\n\
8cef1f78 104The argument object is not altered--the value is a copy.")
dcfdbac7
JB
105 (obj)
106 Lisp_Object obj;
107{
108 return casify_object (CASE_CAPITALIZE, obj);
109}
96927ba4 110
2371fad4
KH
111/* Like Fcapitalize but change only the initials. */
112
8cef1f78
RS
113DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
114 "Convert the initial of each word in the argument to upper case.\n\
115Do not change the other letters of each word.\n\
116The argument may be a character or string. The result has the same type.\n\
117The argument object is not altered--the value is a copy.")
118 (obj)
119 Lisp_Object obj;
120{
121 return casify_object (CASE_CAPITALIZE_UP, obj);
122}
dcfdbac7
JB
123\f
124/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP.
125 b and e specify range of buffer to operate on. */
126
127casify_region (flag, b, e)
128 enum case_action flag;
129 Lisp_Object b, e;
130{
131 register int i;
132 register int c;
133 register int inword = flag == CASE_DOWN;
2371fad4 134 int start, end;
dcfdbac7
JB
135
136 if (EQ (b, e))
137 /* Not modifying because nothing marked */
138 return;
139
bd47bd35
RS
140 /* If the case table is flagged as modified, rescan it. */
141 if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
142 Fset_case_table (current_buffer->downcase_table);
143
dcfdbac7 144 validate_region (&b, &e);
2371fad4
KH
145 start = XFASTINT (b);
146 end = XFASTINT (e);
147 modify_region (current_buffer, start, end);
148 record_change (start, end - start);
dcfdbac7 149
2371fad4 150 for (i = start; i < end; i++)
dcfdbac7
JB
151 {
152 c = FETCH_CHAR (i);
153 if (inword && flag != CASE_CAPITALIZE_UP)
154 c = DOWNCASE (c);
155 else if (!UPPERCASEP (c)
156 && (!inword || flag != CASE_CAPITALIZE_UP))
157 c = UPCASE1 (c);
158 FETCH_CHAR (i) = c;
159 if ((int) flag >= (int) CASE_CAPITALIZE)
160 inword = SYNTAX (c) == Sword;
161 }
162
2371fad4 163 signal_after_change (start, end - start, end - start);
dcfdbac7
JB
164}
165
166DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
167 "Convert the region to upper case. In programs, wants two arguments.\n\
168These arguments specify the starting and ending character numbers of\n\
169the region to operate on. When used as a command, the text between\n\
170point and the mark is operated on.\n\
171See also `capitalize-region'.")
8c22d56c
EN
172 (beg, end)
173 Lisp_Object beg, end;
dcfdbac7 174{
8c22d56c 175 casify_region (CASE_UP, beg, end);
dcfdbac7
JB
176 return Qnil;
177}
178
179DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
180 "Convert the region to lower case. In programs, wants two arguments.\n\
181These arguments specify the starting and ending character numbers of\n\
182the region to operate on. When used as a command, the text between\n\
183point and the mark is operated on.")
8c22d56c
EN
184 (beg, end)
185 Lisp_Object beg, end;
dcfdbac7 186{
8c22d56c 187 casify_region (CASE_DOWN, beg, end);
dcfdbac7
JB
188 return Qnil;
189}
190
191DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
192 "Convert the region to capitalized form.\n\
193Capitalized form means each word's first character is upper case\n\
194and the rest of it is lower case.\n\
195In programs, give two arguments, the starting and ending\n\
196character positions to operate on.")
8c22d56c
EN
197 (beg, end)
198 Lisp_Object beg, end;
dcfdbac7 199{
8c22d56c 200 casify_region (CASE_CAPITALIZE, beg, end);
dcfdbac7
JB
201 return Qnil;
202}
203
2371fad4
KH
204/* Like Fcapitalize_region but change only the initials. */
205
8cef1f78
RS
206DEFUN ("upcase-initials-region", Fupcase_initials_region,
207 Supcase_initials_region, 2, 2, "r",
208 "Upcase the initial of each word in the region.\n\
209Subsequent letters of each word are not changed.\n\
210In programs, give two arguments, the starting and ending\n\
211character positions to operate on.")
8c22d56c
EN
212 (beg, end)
213 Lisp_Object beg, end;
8cef1f78 214{
8c22d56c 215 casify_region (CASE_CAPITALIZE_UP, beg, end);
8cef1f78
RS
216 return Qnil;
217}
dcfdbac7
JB
218\f
219Lisp_Object
34628a90 220operate_on_word (arg, newpoint)
dcfdbac7 221 Lisp_Object arg;
34628a90 222 int *newpoint;
dcfdbac7 223{
39fb55ff 224 Lisp_Object val;
34628a90 225 int farend;
2371fad4 226 int iarg;
dcfdbac7
JB
227
228 CHECK_NUMBER (arg, 0);
2371fad4
KH
229 iarg = XINT (arg);
230 farend = scan_words (point, iarg);
dcfdbac7 231 if (!farend)
2371fad4 232 farend = iarg > 0 ? ZV : BEGV;
dcfdbac7 233
34628a90 234 *newpoint = point > farend ? point : farend;
18e23fd0 235 XSETFASTINT (val, farend);
dcfdbac7
JB
236
237 return val;
238}
239
240DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p",
241 "Convert following word (or ARG words) to upper case, moving over.\n\
242With negative argument, convert previous words but do not move.\n\
243See also `capitalize-word'.")
244 (arg)
245 Lisp_Object arg;
246{
34628a90
RS
247 Lisp_Object beg, end;
248 int newpoint;
18e23fd0 249 XSETFASTINT (beg, point);
34628a90
RS
250 end = operate_on_word (arg, &newpoint);
251 casify_region (CASE_UP, beg, end);
252 SET_PT (newpoint);
dcfdbac7
JB
253 return Qnil;
254}
255
256DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p",
257 "Convert following word (or ARG words) to lower case, moving over.\n\
258With negative argument, convert previous words but do not move.")
259 (arg)
260 Lisp_Object arg;
261{
34628a90
RS
262 Lisp_Object beg, end;
263 int newpoint;
18e23fd0 264 XSETFASTINT (beg, point);
34628a90
RS
265 end = operate_on_word (arg, &newpoint);
266 casify_region (CASE_DOWN, beg, end);
267 SET_PT (newpoint);
dcfdbac7
JB
268 return Qnil;
269}
270
271DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p",
272 "Capitalize the following word (or ARG words), moving over.\n\
273This gives the word(s) a first character in upper case\n\
274and the rest lower case.\n\
275With negative argument, capitalize previous words but do not move.")
276 (arg)
277 Lisp_Object arg;
278{
34628a90
RS
279 Lisp_Object beg, end;
280 int newpoint;
18e23fd0 281 XSETFASTINT (beg, point);
34628a90
RS
282 end = operate_on_word (arg, &newpoint);
283 casify_region (CASE_CAPITALIZE, beg, end);
284 SET_PT (newpoint);
dcfdbac7
JB
285 return Qnil;
286}
287\f
288syms_of_casefiddle ()
289{
290 defsubr (&Supcase);
291 defsubr (&Sdowncase);
292 defsubr (&Scapitalize);
8cef1f78 293 defsubr (&Supcase_initials);
dcfdbac7
JB
294 defsubr (&Supcase_region);
295 defsubr (&Sdowncase_region);
296 defsubr (&Scapitalize_region);
8cef1f78 297 defsubr (&Supcase_initials_region);
dcfdbac7
JB
298 defsubr (&Supcase_word);
299 defsubr (&Sdowncase_word);
300 defsubr (&Scapitalize_word);
301}
302
303keys_of_casefiddle ()
304{
305 initial_define_key (control_x_map, Ctl('U'), "upcase-region");
d427b66a 306 Fput (intern ("upcase-region"), Qdisabled, Qt);
dcfdbac7 307 initial_define_key (control_x_map, Ctl('L'), "downcase-region");
d427b66a
JB
308 Fput (intern ("downcase-region"), Qdisabled, Qt);
309
dcfdbac7
JB
310 initial_define_key (meta_map, 'u', "upcase-word");
311 initial_define_key (meta_map, 'l', "downcase-word");
312 initial_define_key (meta_map, 'c', "capitalize-word");
313}