Commit | Line | Data |
---|---|---|
dcfdbac7 JB |
1 | /* GNU Emacs case conversion functions. |
2 | Copyright (C) 1985 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) | |
59 | c = DOWNCASE (c); | |
60 | else if (!UPPERCASEP (c)) | |
61 | c = UPCASE1 (c); | |
62 | XSTRING (obj)->data[i] = c; | |
63 | if (flag == CASE_CAPITALIZE) | |
64 | inword = SYNTAX (c) == Sword; | |
65 | } | |
66 | return obj; | |
67 | } | |
68 | obj = wrong_type_argument (Qchar_or_string_p, obj, 0); | |
69 | } | |
70 | } | |
71 | ||
72 | DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, | |
73 | "Convert argument to upper case and return that.\n\ | |
74 | The argument may be a character or string. The result has the same type.\n\ | |
75 | The argument object is not altered. See also `capitalize'.") | |
76 | (obj) | |
77 | Lisp_Object obj; | |
78 | { | |
79 | return casify_object (CASE_UP, obj); | |
80 | } | |
81 | ||
82 | DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0, | |
83 | "Convert argument to lower case and return that.\n\ | |
84 | The argument may be a character or string. The result has the same type.\n\ | |
85 | The argument object is not altered.") | |
86 | (obj) | |
87 | Lisp_Object obj; | |
88 | { | |
89 | return casify_object (CASE_DOWN, obj); | |
90 | } | |
91 | ||
92 | DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0, | |
93 | "Convert argument to capitalized form and return that.\n\ | |
94 | This means that each word's first character is upper case\n\ | |
95 | and the rest is lower case.\n\ | |
96 | The argument may be a character or string. The result has the same type.\n\ | |
97 | The argument object is not altered.") | |
98 | (obj) | |
99 | Lisp_Object obj; | |
100 | { | |
101 | return casify_object (CASE_CAPITALIZE, obj); | |
102 | } | |
103 | \f | |
104 | /* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP. | |
105 | b and e specify range of buffer to operate on. */ | |
106 | ||
107 | casify_region (flag, b, e) | |
108 | enum case_action flag; | |
109 | Lisp_Object b, e; | |
110 | { | |
111 | register int i; | |
112 | register int c; | |
113 | register int inword = flag == CASE_DOWN; | |
114 | ||
115 | if (EQ (b, e)) | |
116 | /* Not modifying because nothing marked */ | |
117 | return; | |
118 | ||
119 | validate_region (&b, &e); | |
120 | modify_region (XFASTINT (b), XFASTINT (e)); | |
121 | record_change (XFASTINT (b), XFASTINT (e) - XFASTINT (b)); | |
122 | ||
123 | for (i = XFASTINT (b); i < XFASTINT (e); i++) | |
124 | { | |
125 | c = FETCH_CHAR (i); | |
126 | if (inword && flag != CASE_CAPITALIZE_UP) | |
127 | c = DOWNCASE (c); | |
128 | else if (!UPPERCASEP (c) | |
129 | && (!inword || flag != CASE_CAPITALIZE_UP)) | |
130 | c = UPCASE1 (c); | |
131 | FETCH_CHAR (i) = c; | |
132 | if ((int) flag >= (int) CASE_CAPITALIZE) | |
133 | inword = SYNTAX (c) == Sword; | |
134 | } | |
135 | ||
136 | signal_after_change (XFASTINT (b), | |
137 | XFASTINT (e) - XFASTINT (b), | |
138 | XFASTINT (e) - XFASTINT (b)); | |
139 | } | |
140 | ||
141 | DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r", | |
142 | "Convert the region to upper case. In programs, wants two arguments.\n\ | |
143 | These arguments specify the starting and ending character numbers of\n\ | |
144 | the region to operate on. When used as a command, the text between\n\ | |
145 | point and the mark is operated on.\n\ | |
146 | See also `capitalize-region'.") | |
147 | (b, e) | |
148 | Lisp_Object b, e; | |
149 | { | |
150 | casify_region (CASE_UP, b, e); | |
151 | return Qnil; | |
152 | } | |
153 | ||
154 | DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r", | |
155 | "Convert the region to lower case. In programs, wants two arguments.\n\ | |
156 | These arguments specify the starting and ending character numbers of\n\ | |
157 | the region to operate on. When used as a command, the text between\n\ | |
158 | point and the mark is operated on.") | |
159 | (b, e) | |
160 | Lisp_Object b, e; | |
161 | { | |
162 | casify_region (CASE_DOWN, b, e); | |
163 | return Qnil; | |
164 | } | |
165 | ||
166 | DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r", | |
167 | "Convert the region to capitalized form.\n\ | |
168 | Capitalized form means each word's first character is upper case\n\ | |
169 | and the rest of it is lower case.\n\ | |
170 | In programs, give two arguments, the starting and ending\n\ | |
171 | character positions to operate on.") | |
172 | (b, e) | |
173 | Lisp_Object b, e; | |
174 | { | |
175 | casify_region (CASE_CAPITALIZE, b, e); | |
176 | return Qnil; | |
177 | } | |
178 | ||
179 | /* Like Fcapitalize but change only the initials. */ | |
180 | ||
181 | Lisp_Object | |
182 | upcase_initials_region (b, e) | |
183 | Lisp_Object b, e; | |
184 | { | |
185 | casify_region (CASE_CAPITALIZE_UP, b, e); | |
186 | return Qnil; | |
187 | } | |
188 | \f | |
189 | Lisp_Object | |
190 | operate_on_word (arg) | |
191 | Lisp_Object arg; | |
192 | { | |
193 | Lisp_Object val, end; | |
194 | int farend; | |
195 | ||
196 | CHECK_NUMBER (arg, 0); | |
197 | farend = scan_words (point, XINT (arg)); | |
198 | if (!farend) | |
199 | farend = XINT (arg) > 0 ? ZV : BEGV; | |
200 | ||
201 | end = point > farend ? point : farend; | |
202 | SET_PT (end); | |
203 | XFASTINT (val) = farend; | |
204 | ||
205 | return val; | |
206 | } | |
207 | ||
208 | DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p", | |
209 | "Convert following word (or ARG words) to upper case, moving over.\n\ | |
210 | With negative argument, convert previous words but do not move.\n\ | |
211 | See also `capitalize-word'.") | |
212 | (arg) | |
213 | Lisp_Object arg; | |
214 | { | |
215 | Lisp_Object opoint; | |
216 | ||
217 | XFASTINT (opoint) = point; | |
218 | casify_region (CASE_UP, opoint, operate_on_word (arg)); | |
219 | return Qnil; | |
220 | } | |
221 | ||
222 | DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p", | |
223 | "Convert following word (or ARG words) to lower case, moving over.\n\ | |
224 | With negative argument, convert previous words but do not move.") | |
225 | (arg) | |
226 | Lisp_Object arg; | |
227 | { | |
228 | Lisp_Object opoint; | |
229 | XFASTINT (opoint) = point; | |
230 | casify_region (CASE_DOWN, opoint, operate_on_word (arg)); | |
231 | return Qnil; | |
232 | } | |
233 | ||
234 | DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p", | |
235 | "Capitalize the following word (or ARG words), moving over.\n\ | |
236 | This gives the word(s) a first character in upper case\n\ | |
237 | and the rest lower case.\n\ | |
238 | With negative argument, capitalize previous words but do not move.") | |
239 | (arg) | |
240 | Lisp_Object arg; | |
241 | { | |
242 | Lisp_Object opoint; | |
243 | XFASTINT (opoint) = point; | |
244 | casify_region (CASE_CAPITALIZE, opoint, operate_on_word (arg)); | |
245 | return Qnil; | |
246 | } | |
247 | \f | |
248 | syms_of_casefiddle () | |
249 | { | |
250 | defsubr (&Supcase); | |
251 | defsubr (&Sdowncase); | |
252 | defsubr (&Scapitalize); | |
253 | defsubr (&Supcase_region); | |
254 | defsubr (&Sdowncase_region); | |
255 | defsubr (&Scapitalize_region); | |
256 | defsubr (&Supcase_word); | |
257 | defsubr (&Sdowncase_word); | |
258 | defsubr (&Scapitalize_word); | |
259 | } | |
260 | ||
261 | keys_of_casefiddle () | |
262 | { | |
263 | initial_define_key (control_x_map, Ctl('U'), "upcase-region"); | |
d427b66a | 264 | Fput (intern ("upcase-region"), Qdisabled, Qt); |
dcfdbac7 | 265 | initial_define_key (control_x_map, Ctl('L'), "downcase-region"); |
d427b66a JB |
266 | Fput (intern ("downcase-region"), Qdisabled, Qt); |
267 | ||
dcfdbac7 JB |
268 | initial_define_key (meta_map, 'u', "upcase-word"); |
269 | initial_define_key (meta_map, 'l', "downcase-word"); | |
270 | initial_define_key (meta_map, 'c', "capitalize-word"); | |
271 | } |