]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libedit/emacs.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libedit / emacs.c
1 /*-
2  * Copyright (c) 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Christos Zoulas of Cornell University.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $
33  */
34
35 #if !defined(lint) && !defined(SCCSID)
36 static char sccsid[] = "@(#)emacs.c     8.1 (Berkeley) 6/4/93";
37 #endif /* not lint && not SCCSID */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 /*
42  * emacs.c: Emacs functions
43  */
44 #include "sys.h"
45 #include "el.h"
46
47 /* em_delete_or_list():
48  *      Delete character under cursor or list completions if at end of line
49  *      [^D]
50  */
51 protected el_action_t
52 /*ARGSUSED*/
53 em_delete_or_list(EditLine *el, int c)
54 {
55
56         if (el->el_line.cursor == el->el_line.lastchar) {
57                                         /* if I'm at the end */
58                 if (el->el_line.cursor == el->el_line.buffer) {
59                                         /* and the beginning */
60                         term_writec(el, c);     /* then do an EOF */
61                         return (CC_EOF);
62                 } else {
63                         /*
64                          * Here we could list completions, but it is an
65                          * error right now
66                          */
67                         term_beep(el);
68                         return (CC_ERROR);
69                 }
70         } else {
71                 if (el->el_state.doingarg)
72                         c_delafter(el, el->el_state.argument);
73                 else
74                         c_delafter1(el);
75                 if (el->el_line.cursor > el->el_line.lastchar)
76                         el->el_line.cursor = el->el_line.lastchar;
77                                 /* bounds check */
78                 return (CC_REFRESH);
79         }
80 }
81
82
83 /* em_delete_next_word():
84  *      Cut from cursor to end of current word
85  *      [M-d]
86  */
87 protected el_action_t
88 /*ARGSUSED*/
89 em_delete_next_word(EditLine *el, int c __unused)
90 {
91         char *cp, *p, *kp;
92
93         if (el->el_line.cursor == el->el_line.lastchar)
94                 return (CC_ERROR);
95
96         cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
97             el->el_state.argument, ce__isword);
98
99         for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
100                                 /* save the text */
101                 *kp++ = *p;
102         el->el_chared.c_kill.last = kp;
103
104         c_delafter(el, cp - el->el_line.cursor);        /* delete after dot */
105         if (el->el_line.cursor > el->el_line.lastchar)
106                 el->el_line.cursor = el->el_line.lastchar;
107                                 /* bounds check */
108         return (CC_REFRESH);
109 }
110
111
112 /* em_yank():
113  *      Paste cut buffer at cursor position
114  *      [^Y]
115  */
116 protected el_action_t
117 /*ARGSUSED*/
118 em_yank(EditLine *el, int c __unused)
119 {
120         char *kp, *cp;
121
122         if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
123                 return (CC_NORM);
124
125         if (el->el_line.lastchar +
126             (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
127             el->el_line.limit)
128                 return (CC_ERROR);
129
130         el->el_chared.c_kill.mark = el->el_line.cursor;
131         cp = el->el_line.cursor;
132
133         /* open the space, */
134         c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
135         /* copy the chars */
136         for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
137                 *cp++ = *kp;
138
139         /* if an arg, cursor at beginning else cursor at end */
140         if (el->el_state.argument == 1)
141                 el->el_line.cursor = cp;
142
143         return (CC_REFRESH);
144 }
145
146
147 /* em_kill_line():
148  *      Cut the entire line and save in cut buffer
149  *      [^U]
150  */
151 protected el_action_t
152 /*ARGSUSED*/
153 em_kill_line(EditLine *el, int c __unused)
154 {
155         char *kp, *cp;
156
157         cp = el->el_line.buffer;
158         kp = el->el_chared.c_kill.buf;
159         while (cp < el->el_line.lastchar)
160                 *kp++ = *cp++;  /* copy it */
161         el->el_chared.c_kill.last = kp;
162                                 /* zap! -- delete all of it */
163         el->el_line.lastchar = el->el_line.buffer;
164         el->el_line.cursor = el->el_line.buffer;
165         return (CC_REFRESH);
166 }
167
168
169 /* em_kill_region():
170  *      Cut area between mark and cursor and save in cut buffer
171  *      [^W]
172  */
173 protected el_action_t
174 /*ARGSUSED*/
175 em_kill_region(EditLine *el, int c __unused)
176 {
177         char *kp, *cp;
178
179         if (!el->el_chared.c_kill.mark)
180                 return (CC_ERROR);
181
182         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
183                 cp = el->el_line.cursor;
184                 kp = el->el_chared.c_kill.buf;
185                 while (cp < el->el_chared.c_kill.mark)
186                         *kp++ = *cp++;  /* copy it */
187                 el->el_chared.c_kill.last = kp;
188                 c_delafter(el, cp - el->el_line.cursor);
189         } else {                /* mark is before cursor */
190                 cp = el->el_chared.c_kill.mark;
191                 kp = el->el_chared.c_kill.buf;
192                 while (cp < el->el_line.cursor)
193                         *kp++ = *cp++;  /* copy it */
194                 el->el_chared.c_kill.last = kp;
195                 c_delbefore(el, cp - el->el_chared.c_kill.mark);
196                 el->el_line.cursor = el->el_chared.c_kill.mark;
197         }
198         return (CC_REFRESH);
199 }
200
201
202 /* em_copy_region():
203  *      Copy area between mark and cursor to cut buffer
204  *      [M-W]
205  */
206 protected el_action_t
207 /*ARGSUSED*/
208 em_copy_region(EditLine *el, int c __unused)
209 {
210         char *kp, *cp;
211
212         if (!el->el_chared.c_kill.mark)
213                 return (CC_ERROR);
214
215         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
216                 cp = el->el_line.cursor;
217                 kp = el->el_chared.c_kill.buf;
218                 while (cp < el->el_chared.c_kill.mark)
219                         *kp++ = *cp++;  /* copy it */
220                 el->el_chared.c_kill.last = kp;
221         } else {
222                 cp = el->el_chared.c_kill.mark;
223                 kp = el->el_chared.c_kill.buf;
224                 while (cp < el->el_line.cursor)
225                         *kp++ = *cp++;  /* copy it */
226                 el->el_chared.c_kill.last = kp;
227         }
228         return (CC_NORM);
229 }
230
231
232 /* em_gosmacs_transpose():
233  *      Exchange the two characters before the cursor
234  *      Gosling emacs transpose chars [^T]
235  */
236 protected el_action_t
237 em_gosmacs_transpose(EditLine *el, int c)
238 {
239
240         if (el->el_line.cursor > &el->el_line.buffer[1]) {
241                 /* must have at least two chars entered */
242                 c = el->el_line.cursor[-2];
243                 el->el_line.cursor[-2] = el->el_line.cursor[-1];
244                 el->el_line.cursor[-1] = c;
245                 return (CC_REFRESH);
246         } else
247                 return (CC_ERROR);
248 }
249
250
251 /* em_next_word():
252  *      Move next to end of current word
253  *      [M-f]
254  */
255 protected el_action_t
256 /*ARGSUSED*/
257 em_next_word(EditLine *el, int c __unused)
258 {
259         if (el->el_line.cursor == el->el_line.lastchar)
260                 return (CC_ERROR);
261
262         el->el_line.cursor = c__next_word(el->el_line.cursor,
263             el->el_line.lastchar,
264             el->el_state.argument,
265             ce__isword);
266
267         if (el->el_map.type == MAP_VI)
268                 if (el->el_chared.c_vcmd.action != NOP) {
269                         cv_delfini(el);
270                         return (CC_REFRESH);
271                 }
272         return (CC_CURSOR);
273 }
274
275
276 /* em_upper_case():
277  *      Uppercase the characters from cursor to end of current word
278  *      [M-u]
279  */
280 protected el_action_t
281 /*ARGSUSED*/
282 em_upper_case(EditLine *el, int c __unused)
283 {
284         char *cp, *ep;
285
286         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
287             el->el_state.argument, ce__isword);
288
289         for (cp = el->el_line.cursor; cp < ep; cp++)
290                 if (islower((unsigned char)*cp))
291                         *cp = toupper((unsigned char)*cp);
292
293         el->el_line.cursor = ep;
294         if (el->el_line.cursor > el->el_line.lastchar)
295                 el->el_line.cursor = el->el_line.lastchar;
296         return (CC_REFRESH);
297 }
298
299
300 /* em_capitol_case():
301  *      Capitalize the characters from cursor to end of current word
302  *      [M-c]
303  */
304 protected el_action_t
305 /*ARGSUSED*/
306 em_capitol_case(EditLine *el, int c __unused)
307 {
308         char *cp, *ep;
309
310         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
311             el->el_state.argument, ce__isword);
312
313         for (cp = el->el_line.cursor; cp < ep; cp++) {
314                 if (isalpha((unsigned char)*cp)) {
315                         if (islower((unsigned char)*cp))
316                                 *cp = toupper((unsigned char)*cp);
317                         cp++;
318                         break;
319                 }
320         }
321         for (; cp < ep; cp++)
322                 if (isupper((unsigned char)*cp))
323                         *cp = tolower((unsigned char)*cp);
324
325         el->el_line.cursor = ep;
326         if (el->el_line.cursor > el->el_line.lastchar)
327                 el->el_line.cursor = el->el_line.lastchar;
328         return (CC_REFRESH);
329 }
330
331
332 /* em_lower_case():
333  *      Lowercase the characters from cursor to end of current word
334  *      [M-l]
335  */
336 protected el_action_t
337 /*ARGSUSED*/
338 em_lower_case(EditLine *el, int c __unused)
339 {
340         char *cp, *ep;
341
342         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
343             el->el_state.argument, ce__isword);
344
345         for (cp = el->el_line.cursor; cp < ep; cp++)
346                 if (isupper((unsigned char)*cp))
347                         *cp = tolower((unsigned char)*cp);
348
349         el->el_line.cursor = ep;
350         if (el->el_line.cursor > el->el_line.lastchar)
351                 el->el_line.cursor = el->el_line.lastchar;
352         return (CC_REFRESH);
353 }
354
355
356 /* em_set_mark():
357  *      Set the mark at cursor
358  *      [^@]
359  */
360 protected el_action_t
361 /*ARGSUSED*/
362 em_set_mark(EditLine *el, int c __unused)
363 {
364
365         el->el_chared.c_kill.mark = el->el_line.cursor;
366         return (CC_NORM);
367 }
368
369
370 /* em_exchange_mark():
371  *      Exchange the cursor and mark
372  *      [^X^X]
373  */
374 protected el_action_t
375 /*ARGSUSED*/
376 em_exchange_mark(EditLine *el, int c __unused)
377 {
378         char *cp;
379
380         cp = el->el_line.cursor;
381         el->el_line.cursor = el->el_chared.c_kill.mark;
382         el->el_chared.c_kill.mark = cp;
383         return (CC_CURSOR);
384 }
385
386
387 /* em_universal_argument():
388  *      Universal argument (argument times 4)
389  *      [^U]
390  */
391 protected el_action_t
392 /*ARGSUSED*/
393 em_universal_argument(EditLine *el, int c __unused)
394 {                               /* multiply current argument by 4 */
395
396         if (el->el_state.argument > 1000000)
397                 return (CC_ERROR);
398         el->el_state.doingarg = 1;
399         el->el_state.argument *= 4;
400         return (CC_ARGHACK);
401 }
402
403
404 /* em_meta_next():
405  *      Add 8th bit to next character typed
406  *      [<ESC>]
407  */
408 protected el_action_t
409 /*ARGSUSED*/
410 em_meta_next(EditLine *el, int c __unused)
411 {
412
413         el->el_state.metanext = 1;
414         return (CC_ARGHACK);
415 }
416
417
418 /* em_toggle_overwrite():
419  *      Switch from insert to overwrite mode or vice versa
420  */
421 protected el_action_t
422 /*ARGSUSED*/
423 em_toggle_overwrite(EditLine *el, int c __unused)
424 {
425
426         el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
427             MODE_REPLACE : MODE_INSERT;
428         return (CC_NORM);
429 }
430
431
432 /* em_copy_prev_word():
433  *      Copy current word to cursor
434  */
435 protected el_action_t
436 /*ARGSUSED*/
437 em_copy_prev_word(EditLine *el, int c __unused)
438 {
439         char *cp, *oldc, *dp;
440
441         if (el->el_line.cursor == el->el_line.buffer)
442                 return (CC_ERROR);
443
444         oldc = el->el_line.cursor;
445         /* does a bounds check */
446         cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
447             el->el_state.argument, ce__isword);
448
449         c_insert(el, oldc - cp);
450         for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
451                 *dp++ = *cp;
452
453         el->el_line.cursor = dp;/* put cursor at end */
454
455         return (CC_REFRESH);
456 }
457
458
459 /* em_inc_search_next():
460  *      Emacs incremental next search
461  */
462 protected el_action_t
463 /*ARGSUSED*/
464 em_inc_search_next(EditLine *el, int c __unused)
465 {
466
467         el->el_search.patlen = 0;
468         return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
469 }
470
471
472 /* em_inc_search_prev():
473  *      Emacs incremental reverse search
474  */
475 protected el_action_t
476 /*ARGSUSED*/
477 em_inc_search_prev(EditLine *el, int c __unused)
478 {
479
480         el->el_search.patlen = 0;
481         return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
482 }
483
484
485 /* em_delete_prev_char():
486  *      Delete the character to the left of the cursor
487  *      [^?]
488  */
489 protected el_action_t
490 /*ARGSUSED*/
491 em_delete_prev_char(EditLine *el, int c __unused)
492 {
493
494         if (el->el_line.cursor <= el->el_line.buffer)
495                 return (CC_ERROR);
496
497         if (el->el_state.doingarg)
498                 c_delbefore(el, el->el_state.argument);
499         else
500                 c_delbefore1(el);
501         el->el_line.cursor -= el->el_state.argument;
502         if (el->el_line.cursor < el->el_line.buffer)
503                 el->el_line.cursor = el->el_line.buffer;
504         return (CC_REFRESH);
505 }