]> code.delx.au - gnu-emacs/blob - src/casefiddle.c
(Fwin32_has_winsock, Fwin32_unload_winsock) [HAVE_SOCKETS]: New functions.
[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 2, 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
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
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
42 while (1)
43 {
44 if (INTEGERP (obj))
45 {
46 c = XINT (obj);
47 if (c >= 0 && c <= 0400)
48 {
49 if (inword)
50 XSETFASTINT (obj, DOWNCASE (c));
51 else if (!UPPERCASEP (c))
52 XSETFASTINT (obj, UPCASE1 (c));
53 }
54 return obj;
55 }
56 if (STRINGP (obj))
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];
63 if (inword && flag != CASE_CAPITALIZE_UP)
64 c = DOWNCASE (c);
65 else if (!UPPERCASEP (c)
66 && (!inword || flag != CASE_CAPITALIZE_UP))
67 c = UPCASE1 (c);
68 XSTRING (obj)->data[i] = c;
69 if ((int) flag >= (int) CASE_CAPITALIZE)
70 inword = SYNTAX (c) == Sword;
71 }
72 return obj;
73 }
74 obj = wrong_type_argument (Qchar_or_string_p, obj);
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\
81 The argument object is not altered--the value is a copy.\n\
82 See also `capitalize', `downcase' and `upcase-initials'.")
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\
92 The argument object is not altered--the value is a copy.")
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\
104 The argument object is not altered--the value is a copy.")
105 (obj)
106 Lisp_Object obj;
107 {
108 return casify_object (CASE_CAPITALIZE, obj);
109 }
110
111 /* Like Fcapitalize but change only the initials. */
112
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 }
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;
134 int start, end;
135
136 if (EQ (b, e))
137 /* Not modifying because nothing marked */
138 return;
139
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
144 validate_region (&b, &e);
145 start = XFASTINT (b);
146 end = XFASTINT (e);
147 modify_region (current_buffer, start, end);
148 record_change (start, end - start);
149
150 for (i = start; i < end; i++)
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
163 signal_after_change (start, end - start, end - start);
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'.")
172 (beg, end)
173 Lisp_Object beg, end;
174 {
175 casify_region (CASE_UP, beg, end);
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.")
184 (beg, end)
185 Lisp_Object beg, end;
186 {
187 casify_region (CASE_DOWN, beg, end);
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.")
197 (beg, end)
198 Lisp_Object beg, end;
199 {
200 casify_region (CASE_CAPITALIZE, beg, end);
201 return Qnil;
202 }
203
204 /* Like Fcapitalize_region but change only the initials. */
205
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.")
212 (beg, end)
213 Lisp_Object beg, end;
214 {
215 casify_region (CASE_CAPITALIZE_UP, beg, end);
216 return Qnil;
217 }
218 \f
219 Lisp_Object
220 operate_on_word (arg, newpoint)
221 Lisp_Object arg;
222 int *newpoint;
223 {
224 Lisp_Object val;
225 int farend;
226 int iarg;
227
228 CHECK_NUMBER (arg, 0);
229 iarg = XINT (arg);
230 farend = scan_words (point, iarg);
231 if (!farend)
232 farend = iarg > 0 ? ZV : BEGV;
233
234 *newpoint = point > farend ? point : farend;
235 XSETFASTINT (val, farend);
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 {
247 Lisp_Object beg, end;
248 int newpoint;
249 XSETFASTINT (beg, point);
250 end = operate_on_word (arg, &newpoint);
251 casify_region (CASE_UP, beg, end);
252 SET_PT (newpoint);
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 {
262 Lisp_Object beg, end;
263 int newpoint;
264 XSETFASTINT (beg, point);
265 end = operate_on_word (arg, &newpoint);
266 casify_region (CASE_DOWN, beg, end);
267 SET_PT (newpoint);
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 {
279 Lisp_Object beg, end;
280 int newpoint;
281 XSETFASTINT (beg, point);
282 end = operate_on_word (arg, &newpoint);
283 casify_region (CASE_CAPITALIZE, beg, end);
284 SET_PT (newpoint);
285 return Qnil;
286 }
287 \f
288 syms_of_casefiddle ()
289 {
290 defsubr (&Supcase);
291 defsubr (&Sdowncase);
292 defsubr (&Scapitalize);
293 defsubr (&Supcase_initials);
294 defsubr (&Supcase_region);
295 defsubr (&Sdowncase_region);
296 defsubr (&Scapitalize_region);
297 defsubr (&Supcase_initials_region);
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");
306 Fput (intern ("upcase-region"), Qdisabled, Qt);
307 initial_define_key (control_x_map, Ctl('L'), "downcase-region");
308 Fput (intern ("downcase-region"), Qdisabled, Qt);
309
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 }