Commit | Line | Data |
---|---|---|
dcfdbac7 | 1 | /* GNU Emacs case conversion functions. |
3a22ee35 | 2 | Copyright (C) 1985, 1994 Free Software Foundation, Inc. |
dcfdbac7 JB |
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 | |
7c938215 | 8 | the Free Software Foundation; either version 2, or (at your option) |
dcfdbac7 JB |
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 | |
3b7ad313 EN |
18 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 | Boston, 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 | ||
28 | enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; | |
29 | \f | |
30 | Lisp_Object | |
31 | casify_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 | ||
78 | DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, | |
79 | "Convert argument to upper case and return that.\n\ | |
80 | The argument may be a character or string. The result has the same type.\n\ | |
8cef1f78 RS |
81 | The argument object is not altered--the value is a copy.\n\ |
82 | See also `capitalize', `downcase' and `upcase-initials'.") | |
dcfdbac7 JB |
83 | (obj) |
84 | Lisp_Object obj; | |
85 | { | |
86 | return casify_object (CASE_UP, obj); | |
87 | } | |
88 | ||
89 | DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0, | |
90 | "Convert argument to lower case and return that.\n\ | |
91 | The argument may be a character or string. The result has the same type.\n\ | |
8cef1f78 | 92 | The 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 | ||
99 | DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0, | |
100 | "Convert argument to capitalized form and return that.\n\ | |
101 | This means that each word's first character is upper case\n\ | |
102 | and the rest is lower case.\n\ | |
103 | The argument may be a character or string. The result has the same type.\n\ | |
8cef1f78 | 104 | The 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 |
113 | DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0, |
114 | "Convert the initial of each word in the argument to upper case.\n\ | |
115 | Do not change the other letters of each word.\n\ | |
116 | The argument may be a character or string. The result has the same type.\n\ | |
117 | The 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 | ||
127 | casify_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 | 151 | { |
fc44dfab | 152 | c = FETCH_BYTE (i); |
dcfdbac7 JB |
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); | |
fc44dfab | 158 | FETCH_BYTE (i) = c; |
dcfdbac7 JB |
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 | ||
166 | DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r", | |
167 | "Convert the region to upper case. In programs, wants two arguments.\n\ | |
168 | These arguments specify the starting and ending character numbers of\n\ | |
169 | the region to operate on. When used as a command, the text between\n\ | |
170 | point and the mark is operated on.\n\ | |
171 | See 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 | ||
179 | DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r", | |
180 | "Convert the region to lower case. In programs, wants two arguments.\n\ | |
181 | These arguments specify the starting and ending character numbers of\n\ | |
182 | the region to operate on. When used as a command, the text between\n\ | |
183 | point 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 | ||
191 | DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r", | |
192 | "Convert the region to capitalized form.\n\ | |
193 | Capitalized form means each word's first character is upper case\n\ | |
194 | and the rest of it is lower case.\n\ | |
195 | In programs, give two arguments, the starting and ending\n\ | |
196 | character 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 |
206 | DEFUN ("upcase-initials-region", Fupcase_initials_region, |
207 | Supcase_initials_region, 2, 2, "r", | |
208 | "Upcase the initial of each word in the region.\n\ | |
209 | Subsequent letters of each word are not changed.\n\ | |
210 | In programs, give two arguments, the starting and ending\n\ | |
211 | character 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 |
219 | Lisp_Object | |
34628a90 | 220 | operate_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 | 229 | iarg = XINT (arg); |
6ec8bbd2 | 230 | farend = scan_words (PT, iarg); |
dcfdbac7 | 231 | if (!farend) |
2371fad4 | 232 | farend = iarg > 0 ? ZV : BEGV; |
dcfdbac7 | 233 | |
6ec8bbd2 | 234 | *newpoint = PT > farend ? PT : farend; |
18e23fd0 | 235 | XSETFASTINT (val, farend); |
dcfdbac7 JB |
236 | |
237 | return val; | |
238 | } | |
239 | ||
240 | DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p", | |
241 | "Convert following word (or ARG words) to upper case, moving over.\n\ | |
242 | With negative argument, convert previous words but do not move.\n\ | |
243 | See also `capitalize-word'.") | |
244 | (arg) | |
245 | Lisp_Object arg; | |
246 | { | |
34628a90 RS |
247 | Lisp_Object beg, end; |
248 | int newpoint; | |
6ec8bbd2 | 249 | XSETFASTINT (beg, PT); |
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 | ||
256 | DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p", | |
257 | "Convert following word (or ARG words) to lower case, moving over.\n\ | |
258 | With 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; | |
6ec8bbd2 | 264 | XSETFASTINT (beg, PT); |
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 | ||
271 | DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p", | |
272 | "Capitalize the following word (or ARG words), moving over.\n\ | |
273 | This gives the word(s) a first character in upper case\n\ | |
274 | and the rest lower case.\n\ | |
275 | With 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; | |
6ec8bbd2 | 281 | XSETFASTINT (beg, PT); |
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 | |
288 | syms_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 | ||
303 | keys_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 | } |