1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <config.h>
24: #include "lisp.h"
25: #include "buffer.h"
26: #include "charset.h"
27: #include "commands.h"
28: #include "syntax.h"
29: #include "composite.h"
30: #include "keymap.h"
31:
32: enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
33:
34: Lisp_Object Qidentity;
35: ^L
36: Lisp_Object
37: casify_object (flag, obj)
38: enum case_action flag;
39: Lisp_Object obj;
40: {
41: register int i, c, len;
42: register int inword = flag == CASE_DOWN;
43:
44:
45: if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
46: Fset_case_table (current_buffer->downcase_table);
47:
48: if (INTEGERP (obj))
49: {
50: int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
51: | CHAR_SHIFT | CHAR_CTL | CHAR_META);
52: int flags = XINT (obj) & flagbits;
53:
54:
55:
56:
57: if ((unsigned) XFASTINT (obj) > (unsigned) flagbits)
58: return obj;
59:
60: c = DOWNCASE (XFASTINT (obj) & ~flagbits);
61: if (inword)
62: XSETFASTINT (obj, c | flags);
63: else if (c == (XFASTINT (obj) & ~flagbits))
64: {
65: c = UPCASE1 ((XFASTINT (obj) & ~flagbits));
66: XSETFASTINT (obj, c | flags);
67: }
68: return obj;
69: }
70:
71: if (STRINGP (obj))
72: {
73: int multibyte = STRING_MULTIBYTE (obj);
74: int n;
75:
76: obj = Fcopy_sequence (obj);
77: len = SBYTES (obj);
78:
79:
80: for (i = n = 0; i < len; n++)
81: {
82: int from_len = 1, to_len = 1;
83:
84: c = SREF (obj, i);
85:
86: if (multibyte && c >= 0x80)
87: c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i, len -i, from_len);
88: if (inword && flag != CASE_CAPITALIZE_UP)
89: c = DOWNCASE (c);
90: else if (!UPPERCASEP (c)
91: && (!inword || flag != CASE_CAPITALIZE_UP))
92: c = UPCASE1 (c);
93: if ((ASCII_BYTE_P (c) && from_len == 1)
94: || (! multibyte && SINGLE_BYTE_CHAR_P (c)))
95: SSET (obj, i, c);
96: else
97: {
98: to_len = CHAR_BYTES (c);
99: if (from_len == to_len)
100: CHAR_STRING (c, SDATA (obj) + i);
101: else
102: {
103: Faset (obj, make_number (n), make_number (c));
104: len += to_len - from_len;
105: }
106: }
107: if ((int) flag >= (int) CASE_CAPITALIZE)
108: inword = SYNTAX (c) == Sword;
109: i += to_len;
110: }
111: return obj;
112: }
113:
114: wrong_type_argument (Qchar_or_string_p, obj);
115: }
116:
117: DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
118: doc:
119:
120:
121: )
122: (obj)
123: Lisp_Object obj;
124: {
125: return casify_object (CASE_UP, obj);
126: }
127:
128: DEFUN ("downcase", Fdowncase, Sdowncase, 1, 1, 0,
129: doc:
130:
131: )
132: (obj)
133: Lisp_Object obj;
134: {
135: return casify_object (CASE_DOWN, obj);
136: }
137:
138: DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
139: doc:
140:
141:
142:
143: )
144: (obj)
145: Lisp_Object obj;
146: {
147: return casify_object (CASE_CAPITALIZE, obj);
148: }
149:
150:
151:
152: DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
153: doc:
154:
155:
156: )
157: (obj)
158: Lisp_Object obj;
159: {
160: return casify_object (CASE_CAPITALIZE_UP, obj);
161: }
162: ^L
163:
164:
165:
166: void
167: casify_region (flag, b, e)
168: enum case_action flag;
169: Lisp_Object b, e;
170: {
171: register int i;
172: register int c;
173: register int inword = flag == CASE_DOWN;
174: register int multibyte = !NILP (current_buffer->enable_multibyte_characters);
175: int start, end;
176: int start_byte, end_byte;
177: int changed = 0;
178:
179: if (EQ (b, e))
180:
181: return;
182:
183:
184: if (NILP (XCHAR_TABLE (current_buffer->downcase_table)->extras[1]))
185: Fset_case_table (current_buffer->downcase_table);
186:
187: validate_region (&b, &e);
188: start = XFASTINT (b);
189: end = XFASTINT (e);
190: modify_region (current_buffer, start, end, 0);
191: record_change (start, end - start);
192: start_byte = CHAR_TO_BYTE (start);
193: end_byte = CHAR_TO_BYTE (end);
194:
195: for (i = start_byte; i < end_byte; i++, start++)
196: {
197: int c2;
198: c = c2 = FETCH_BYTE (i);
199: if (multibyte && c >= 0x80)
200:
201: break;
202: if (inword && flag != CASE_CAPITALIZE_UP)
203: c = DOWNCASE (c);
204: else if (!UPPERCASEP (c)
205: && (!inword || flag != CASE_CAPITALIZE_UP))
206: c = UPCASE1 (c);
207: if (multibyte && c >= 0x80)
208:
209:
210: break;
211: FETCH_BYTE (i) = c;
212: if (c != c2)
213: changed = 1;
214: if ((int) flag >= (int) CASE_CAPITALIZE)
215: inword = SYNTAX (c) == Sword && (inword || !SYNTAX_PREFIX (c));
216: }
217: if (i < end_byte)
218: {
219:
220:
221: int opoint = PT;
222: int opoint_byte = PT_BYTE;
223: int c2;
224:
225: while (start < end)
226: {
227: if ((c = FETCH_BYTE (i)) >= 0x80)
228: c = FETCH_MULTIBYTE_CHAR (i);
229: c2 = c;
230: if (inword && flag != CASE_CAPITALIZE_UP)
231: c2 = DOWNCASE (c);
232: else if (!UPPERCASEP (c)
233: && (!inword || flag != CASE_CAPITALIZE_UP))
234: c2 = UPCASE1 (c);
235: if (c != c2)
236: {
237: int fromlen, tolen, j;
238: unsigned char str[MAX_MULTIBYTE_LENGTH];
239:
240: changed = 1;
241:
242: if (c < 0400 && c2 < 0400)
243: FETCH_BYTE (i) = c2;
244: else if (fromlen = CHAR_STRING (c, str),
245: tolen = CHAR_STRING (c2, str),
246: fromlen == tolen)
247: {
248:
249: for (j = 0; j < tolen; ++j)
250: FETCH_BYTE (i + j) = str[j];
251: }
252: else
253: {
254:
255:
256: replace_range_2 (start, i,
257: start + 1, i + fromlen,
258: str, 1, tolen,
259: 1);
260: if (opoint > start)
261: opoint_byte += tolen - fromlen;
262: }
263: }
264: if ((int) flag >= (int) CASE_CAPITALIZE)
265: inword = SYNTAX (c2) == Sword;
266: INC_BOTH (start, i);
267: }
268: TEMP_SET_PT_BOTH (opoint, opoint_byte);
269: }
270:
271: start = XFASTINT (b);
272: if (changed)
273: {
274: signal_after_change (start, end - start, end - start);
275: update_compositions (start, end, CHECK_ALL);
276: }
277: }
278:
279: DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 2, "r",
280: doc:
281:
282:
283:
284: )
285: (beg, end)
286: Lisp_Object beg, end;
287: {
288: casify_region (CASE_UP, beg, end);
289: return Qnil;
290: }
291:
292: DEFUN ("downcase-region", Fdowncase_region, Sdowncase_region, 2, 2, "r",
293: doc:
294:
295:
296: )
297: (beg, end)
298: Lisp_Object beg, end;
299: {
300: casify_region (CASE_DOWN, beg, end);
301: return Qnil;
302: }
303:
304: DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
305: doc:
306:
307:
308:
309: )
310: (beg, end)
311: Lisp_Object beg, end;
312: {
313: casify_region (CASE_CAPITALIZE, beg, end);
314: return Qnil;
315: }
316:
317:
318:
319: DEFUN ("upcase-initials-region", Fupcase_initials_region,
320: Supcase_initials_region, 2, 2, "r",
321: doc:
322:
323:
324: )
325: (beg, end)
326: Lisp_Object beg, end;
327: {
328: casify_region (CASE_CAPITALIZE_UP, beg, end);
329: return Qnil;
330: }
331: ^L
332: Lisp_Object
333: operate_on_word (arg, newpoint)
334: Lisp_Object arg;
335: int *newpoint;
336: {
337: Lisp_Object val;
338: int farend;
339: int iarg;
340:
341: CHECK_NUMBER (arg);
342: iarg = XINT (arg);
343: farend = scan_words (PT, iarg);
344: if (!farend)
345: farend = iarg > 0 ? ZV : BEGV;
346:
347: *newpoint = PT > farend ? PT : farend;
348: XSETFASTINT (val, farend);
349:
350: return val;
351: }
352:
353: DEFUN ("upcase-word", Fupcase_word, Supcase_word, 1, 1, "p",
354: doc:
355:
356: )
357: (arg)
358: Lisp_Object arg;
359: {
360: Lisp_Object beg, end;
361: int newpoint;
362: XSETFASTINT (beg, PT);
363: end = operate_on_word (arg, &newpoint);
364: casify_region (CASE_UP, beg, end);
365: SET_PT (newpoint);
366: return Qnil;
367: }
368:
369: DEFUN ("downcase-word", Fdowncase_word, Sdowncase_word, 1, 1, "p",
370: doc:
371: )
372: (arg)
373: Lisp_Object arg;
374: {
375: Lisp_Object beg, end;
376: int newpoint;
377: XSETFASTINT (beg, PT);
378: end = operate_on_word (arg, &newpoint);
379: casify_region (CASE_DOWN, beg, end);
380: SET_PT (newpoint);
381: return Qnil;
382: }
383:
384: DEFUN ("capitalize-word", Fcapitalize_word, Scapitalize_word, 1, 1, "p",
385: doc:
386:
387:
388: )
389: (arg)
390: Lisp_Object arg;
391: {
392: Lisp_Object beg, end;
393: int newpoint;
394: XSETFASTINT (beg, PT);
395: end = operate_on_word (arg, &newpoint);
396: casify_region (CASE_CAPITALIZE, beg, end);
397: SET_PT (newpoint);
398: return Qnil;
399: }
400: ^L
401: void
402: syms_of_casefiddle ()
403: {
404: Qidentity = intern ("identity");
405: staticpro (&Qidentity);
406: defsubr (&Supcase);
407: defsubr (&Sdowncase);
408: defsubr (&Scapitalize);
409: defsubr (&Supcase_initials);
410: defsubr (&Supcase_region);
411: defsubr (&Sdowncase_region);
412: defsubr (&Scapitalize_region);
413: defsubr (&Supcase_initials_region);
414: defsubr (&Supcase_word);
415: defsubr (&Sdowncase_word);
416: defsubr (&Scapitalize_word);
417: }
418:
419: void
420: keys_of_casefiddle ()
421: {
422: initial_define_key (control_x_map, Ctl('U'), "upcase-region");
423: Fput (intern ("upcase-region"), Qdisabled, Qt);
424: initial_define_key (control_x_map, Ctl('L'), "downcase-region");
425: Fput (intern ("downcase-region"), Qdisabled, Qt);
426:
427: initial_define_key (meta_map, 'u', "upcase-word");
428: initial_define_key (meta_map, 'l', "downcase-word");
429: initial_define_key (meta_map, 'c', "capitalize-word");
430: }
431:
432:
433: