Mercurial > hg > xemacs-beta
comparison src/casefiddle.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 8de8e3f6228a |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* XEmacs case conversion functions. | |
2 Copyright (C) 1985, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; 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 /* Synched up with: FSF 19.34, but substantially rewritten by Martin. */ | |
22 | |
23 #include <config.h> | |
24 #include "lisp.h" | |
25 | |
26 #include "buffer.h" | |
27 #include "insdel.h" | |
28 #include "syntax.h" | |
29 | |
30 enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; | |
31 | |
32 static Lisp_Object | |
33 casify_object (enum case_action flag, Lisp_Object obj, Lisp_Object buffer) | |
34 { | |
35 struct buffer *buf = decode_buffer (buffer, 0); | |
36 | |
37 retry: | |
38 | |
39 if (CHAR_OR_CHAR_INTP (obj)) | |
40 { | |
41 Emchar c; | |
42 CHECK_CHAR_COERCE_INT (obj); | |
43 c = XCHAR (obj); | |
44 c = (flag == CASE_DOWN) ? DOWNCASE (buf, c) : UPCASE (buf, c); | |
45 return make_char (c); | |
46 } | |
47 | |
48 if (STRINGP (obj)) | |
49 { | |
50 struct Lisp_Char_Table *syntax_table = | |
51 XCHAR_TABLE (buf->mirror_syntax_table); | |
52 Bufbyte *storage = | |
53 alloca_array (Bufbyte, XSTRING_LENGTH (obj) * MAX_EMCHAR_LEN); | |
54 Bufbyte *newp = storage; | |
55 Bufbyte *oldp = XSTRING_DATA (obj); | |
56 int wordp = 0, wordp_prev; | |
57 | |
58 while (*oldp) | |
59 { | |
60 Emchar c = charptr_emchar (oldp); | |
61 switch (flag) | |
62 { | |
63 case CASE_UP: | |
64 c = UPCASE (buf, c); | |
65 break; | |
66 case CASE_DOWN: | |
67 c = DOWNCASE (buf, c); | |
68 break; | |
69 case CASE_CAPITALIZE: | |
70 case CASE_CAPITALIZE_UP: | |
71 wordp_prev = wordp; | |
72 wordp = WORD_SYNTAX_P (syntax_table, c); | |
73 if (!wordp) break; | |
74 if (wordp_prev) | |
75 { | |
76 if (flag == CASE_CAPITALIZE) | |
77 c = DOWNCASE (buf, c); | |
78 } | |
79 else | |
80 c = UPCASE (buf, c); | |
81 break; | |
82 } | |
83 | |
84 newp += set_charptr_emchar (newp, c); | |
85 INC_CHARPTR (oldp); | |
86 } | |
87 | |
88 return make_string (storage, newp - storage); | |
89 } | |
90 | |
91 obj = wrong_type_argument (Qchar_or_string_p, obj); | |
92 goto retry; | |
93 } | |
94 | |
95 DEFUN ("upcase", Fupcase, 1, 2, 0, /* | |
96 Convert OBJECT to upper case and return that. | |
97 OBJECT may be a character or string. The result has the same type. | |
98 OBJECT is not altered--the value is a copy. | |
99 See also `capitalize', `downcase' and `upcase-initials'. | |
100 Optional second arg BUFFER specifies which buffer's case tables to use, | |
101 and defaults to the current buffer. | |
102 */ | |
103 (object, buffer)) | |
104 { | |
105 return casify_object (CASE_UP, object, buffer); | |
106 } | |
107 | |
108 DEFUN ("downcase", Fdowncase, 1, 2, 0, /* | |
109 Convert OBJECT to lower case and return that. | |
110 OBJECT may be a character or string. The result has the same type. | |
111 OBJECT is not altered--the value is a copy. | |
112 Optional second arg BUFFER specifies which buffer's case tables to use, | |
113 and defaults to the current buffer. | |
114 */ | |
115 (object, buffer)) | |
116 { | |
117 return casify_object (CASE_DOWN, object, buffer); | |
118 } | |
119 | |
120 DEFUN ("capitalize", Fcapitalize, 1, 2, 0, /* | |
121 Convert OBJECT to capitalized form and return that. | |
122 This means that each word's first character is upper case | |
123 and the rest is lower case. | |
124 OBJECT may be a character or string. The result has the same type. | |
125 OBJECT is not altered--the value is a copy. | |
126 Optional second arg BUFFER specifies which buffer's case tables to use, | |
127 and defaults to the current buffer. | |
128 */ | |
129 (object, buffer)) | |
130 { | |
131 return casify_object (CASE_CAPITALIZE, object, buffer); | |
132 } | |
133 | |
134 /* Like Fcapitalize but change only the initial characters. */ | |
135 | |
136 DEFUN ("upcase-initials", Fupcase_initials, 1, 2, 0, /* | |
137 Convert the initial of each word in OBJECT to upper case. | |
138 Do not change the other letters of each word. | |
139 OBJECT may be a character or string. The result has the same type. | |
140 OBJECT is not altered--the value is a copy. | |
141 Optional second arg BUFFER specifies which buffer's case tables to use, | |
142 and defaults to the current buffer. | |
143 */ | |
144 (object, buffer)) | |
145 { | |
146 return casify_object (CASE_CAPITALIZE_UP, object, buffer); | |
147 } | |
148 | |
149 /* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP. | |
150 b and e specify range of buffer to operate on. */ | |
151 | |
152 static void | |
153 casify_region_internal (enum case_action flag, Lisp_Object b, Lisp_Object e, | |
154 struct buffer *buf) | |
155 { | |
156 /* This function can GC */ | |
157 REGISTER Bufpos i; | |
158 Bufpos start, end; | |
159 struct Lisp_Char_Table *syntax_table = XCHAR_TABLE (buf->mirror_syntax_table); | |
160 int mccount; | |
161 Emchar oldc, c; | |
162 int wordp = 0, wordp_prev; | |
163 | |
164 if (EQ (b, e)) | |
165 /* Not modifying because nothing marked */ | |
166 return; | |
167 | |
168 get_buffer_range_char (buf, b, e, &start, &end, 0); | |
169 | |
170 mccount = begin_multiple_change (buf, start, end); | |
171 record_change (buf, start, end - start); | |
172 | |
173 for (i = start; i < end; i++) | |
174 { | |
175 c = oldc = BUF_FETCH_CHAR (buf, i); | |
176 | |
177 switch (flag) | |
178 { | |
179 case CASE_UP: | |
180 c = UPCASE (buf, oldc); | |
181 break; | |
182 case CASE_DOWN: | |
183 c = DOWNCASE (buf, oldc); | |
184 break; | |
185 case CASE_CAPITALIZE: | |
186 case CASE_CAPITALIZE_UP: | |
187 /* !!#### need to revalidate the start and end pointers in case | |
188 the buffer was changed */ | |
189 wordp_prev = wordp; | |
190 wordp = WORD_SYNTAX_P (syntax_table, c); | |
191 if (!wordp) continue; | |
192 if (wordp_prev) | |
193 { | |
194 if (flag == CASE_CAPITALIZE) | |
195 c = DOWNCASE (buf, c); | |
196 } | |
197 else | |
198 c = UPCASE (buf, c); | |
199 break; | |
200 } | |
201 | |
202 if (oldc == c) continue; | |
203 buffer_replace_char (buf, i, c, 1, (i == start)); | |
204 BUF_MODIFF (buf)++; | |
205 } | |
206 | |
207 end_multiple_change (buf, mccount); | |
208 } | |
209 | |
210 static Lisp_Object | |
211 casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e, | |
212 Lisp_Object buffer) | |
213 { | |
214 casify_region_internal (flag, b, e, decode_buffer (buffer, 1)); | |
215 return Qnil; | |
216 } | |
217 | |
218 DEFUN ("upcase-region", Fupcase_region, 2, 3, "r", /* | |
219 Convert the region to upper case. In programs, wants two arguments. | |
220 These arguments specify the starting and ending character numbers of | |
221 the region to operate on. When used as a command, the text between | |
222 point and the mark is operated on. | |
223 See also `capitalize-region'. | |
224 Optional third arg BUFFER defaults to the current buffer. | |
225 */ | |
226 (b, e, buffer)) | |
227 { | |
228 /* This function can GC */ | |
229 return casify_region (CASE_UP, b, e, buffer); | |
230 } | |
231 | |
232 DEFUN ("downcase-region", Fdowncase_region, 2, 3, "r", /* | |
233 Convert the region to lower case. In programs, wants two arguments. | |
234 These arguments specify the starting and ending character numbers of | |
235 the region to operate on. When used as a command, the text between | |
236 point and the mark is operated on. | |
237 Optional third arg BUFFER defaults to the current buffer. | |
238 */ | |
239 (b, e, buffer)) | |
240 { | |
241 /* This function can GC */ | |
242 return casify_region (CASE_DOWN, b, e, buffer); | |
243 } | |
244 | |
245 DEFUN ("capitalize-region", Fcapitalize_region, 2, 3, "r", /* | |
246 Convert the region to capitalized form. | |
247 Capitalized form means each word's first character is upper case | |
248 and the rest of it is lower case. | |
249 In programs, give two arguments, the starting and ending | |
250 character positions to operate on. | |
251 Optional third arg BUFFER defaults to the current buffer. | |
252 */ | |
253 (b, e, buffer)) | |
254 { | |
255 /* This function can GC */ | |
256 return casify_region (CASE_CAPITALIZE, b, e, buffer); | |
257 } | |
258 | |
259 /* Like Fcapitalize_region but change only the initials. */ | |
260 | |
261 DEFUN ("upcase-initials-region", Fupcase_initials_region, 2, 3, "r", /* | |
262 Upcase the initial of each word in the region. | |
263 Subsequent letters of each word are not changed. | |
264 In programs, give two arguments, the starting and ending | |
265 character positions to operate on. | |
266 Optional third arg BUFFER defaults to the current buffer. | |
267 */ | |
268 (b, e, buffer)) | |
269 { | |
270 return casify_region (CASE_CAPITALIZE_UP, b, e, buffer); | |
271 } | |
272 | |
273 | |
274 static Lisp_Object | |
275 casify_word (enum case_action flag, Lisp_Object arg, Lisp_Object buffer) | |
276 { | |
277 Bufpos farend; | |
278 struct buffer *buf = decode_buffer (buffer, 1); | |
279 | |
280 CHECK_INT (arg); | |
281 | |
282 farend = scan_words (buf, BUF_PT (buf), XINT (arg)); | |
283 if (!farend) | |
284 farend = XINT (arg) > 0 ? BUF_ZV (buf) : BUF_BEGV (buf); | |
285 | |
286 casify_region_internal (flag, make_int (BUF_PT (buf)), make_int (farend), buf); | |
287 BUF_SET_PT (buf, max (BUF_PT (buf), farend)); | |
288 return Qnil; | |
289 } | |
290 | |
291 DEFUN ("upcase-word", Fupcase_word, 1, 2, "p", /* | |
292 Convert following word (or N words) to upper case, moving over. | |
293 With negative argument, convert previous words but do not move. | |
294 See also `capitalize-word'. | |
295 Optional second arg BUFFER defaults to the current buffer. | |
296 */ | |
297 (n, buffer)) | |
298 { | |
299 /* This function can GC */ | |
300 return casify_word (CASE_UP, n, buffer); | |
301 } | |
302 | |
303 DEFUN ("downcase-word", Fdowncase_word, 1, 2, "p", /* | |
304 Convert following word (or N words) to lower case, moving over. | |
305 With negative argument, convert previous words but do not move. | |
306 Optional second arg BUFFER defaults to the current buffer. | |
307 */ | |
308 (n, buffer)) | |
309 { | |
310 /* This function can GC */ | |
311 return casify_word (CASE_DOWN, n, buffer); | |
312 } | |
313 | |
314 DEFUN ("capitalize-word", Fcapitalize_word, 1, 2, "p", /* | |
315 Capitalize the following word (or N words), moving over. | |
316 This gives the word(s) a first character in upper case | |
317 and the rest lower case. | |
318 With negative argument, capitalize previous words but do not move. | |
319 Optional second arg BUFFER defaults to the current buffer. | |
320 */ | |
321 (n, buffer)) | |
322 { | |
323 /* This function can GC */ | |
324 return casify_word (CASE_CAPITALIZE, n, buffer); | |
325 } | |
326 | |
327 | |
328 void | |
329 syms_of_casefiddle (void) | |
330 { | |
331 DEFSUBR (Fupcase); | |
332 DEFSUBR (Fdowncase); | |
333 DEFSUBR (Fcapitalize); | |
334 DEFSUBR (Fupcase_initials); | |
335 DEFSUBR (Fupcase_region); | |
336 DEFSUBR (Fdowncase_region); | |
337 DEFSUBR (Fcapitalize_region); | |
338 DEFSUBR (Fupcase_initials_region); | |
339 DEFSUBR (Fupcase_word); | |
340 DEFSUBR (Fdowncase_word); | |
341 DEFSUBR (Fcapitalize_word); | |
342 } |