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