]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - lib/libedit/emacs.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.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.22 2009/02/15 21:55:23 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, (int)(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,
135             (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
136         /* copy the chars */
137         for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
138                 *cp++ = *kp;
139
140         /* if an arg, cursor at beginning else cursor at end */
141         if (el->el_state.argument == 1)
142                 el->el_line.cursor = cp;
143
144         return (CC_REFRESH);
145 }
146
147
148 /* em_kill_line():
149  *      Cut the entire line and save in cut buffer
150  *      [^U]
151  */
152 protected el_action_t
153 /*ARGSUSED*/
154 em_kill_line(EditLine *el, int c __unused)
155 {
156         char *kp, *cp;
157
158         cp = el->el_line.buffer;
159         kp = el->el_chared.c_kill.buf;
160         while (cp < el->el_line.lastchar)
161                 *kp++ = *cp++;  /* copy it */
162         el->el_chared.c_kill.last = kp;
163                                 /* zap! -- delete all of it */
164         el->el_line.lastchar = el->el_line.buffer;
165         el->el_line.cursor = el->el_line.buffer;
166         return (CC_REFRESH);
167 }
168
169
170 /* em_kill_region():
171  *      Cut area between mark and cursor and save in cut buffer
172  *      [^W]
173  */
174 protected el_action_t
175 /*ARGSUSED*/
176 em_kill_region(EditLine *el, int c __unused)
177 {
178         char *kp, *cp;
179
180         if (!el->el_chared.c_kill.mark)
181                 return (CC_ERROR);
182
183         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
184                 cp = el->el_line.cursor;
185                 kp = el->el_chared.c_kill.buf;
186                 while (cp < el->el_chared.c_kill.mark)
187                         *kp++ = *cp++;  /* copy it */
188                 el->el_chared.c_kill.last = kp;
189                 c_delafter(el, (int)(cp - el->el_line.cursor));
190         } else {                /* mark is before cursor */
191                 cp = el->el_chared.c_kill.mark;
192                 kp = el->el_chared.c_kill.buf;
193                 while (cp < el->el_line.cursor)
194                         *kp++ = *cp++;  /* copy it */
195                 el->el_chared.c_kill.last = kp;
196                 c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
197                 el->el_line.cursor = el->el_chared.c_kill.mark;
198         }
199         return (CC_REFRESH);
200 }
201
202
203 /* em_copy_region():
204  *      Copy area between mark and cursor to cut buffer
205  *      [M-W]
206  */
207 protected el_action_t
208 /*ARGSUSED*/
209 em_copy_region(EditLine *el, int c __unused)
210 {
211         char *kp, *cp;
212
213         if (!el->el_chared.c_kill.mark)
214                 return (CC_ERROR);
215
216         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
217                 cp = el->el_line.cursor;
218                 kp = el->el_chared.c_kill.buf;
219                 while (cp < el->el_chared.c_kill.mark)
220                         *kp++ = *cp++;  /* copy it */
221                 el->el_chared.c_kill.last = kp;
222         } else {
223                 cp = el->el_chared.c_kill.mark;
224                 kp = el->el_chared.c_kill.buf;
225                 while (cp < el->el_line.cursor)
226                         *kp++ = *cp++;  /* copy it */
227                 el->el_chared.c_kill.last = kp;
228         }
229         return (CC_NORM);
230 }
231
232
233 /* em_gosmacs_transpose():
234  *      Exchange the two characters before the cursor
235  *      Gosling emacs transpose chars [^T]
236  */
237 protected el_action_t
238 em_gosmacs_transpose(EditLine *el, int c)
239 {
240
241         if (el->el_line.cursor > &el->el_line.buffer[1]) {
242                 /* must have at least two chars entered */
243                 c = el->el_line.cursor[-2];
244                 el->el_line.cursor[-2] = el->el_line.cursor[-1];
245                 el->el_line.cursor[-1] = c;
246                 return (CC_REFRESH);
247         } else
248                 return (CC_ERROR);
249 }
250
251
252 /* em_next_word():
253  *      Move next to end of current word
254  *      [M-f]
255  */
256 protected el_action_t
257 /*ARGSUSED*/
258 em_next_word(EditLine *el, int c __unused)
259 {
260         if (el->el_line.cursor == el->el_line.lastchar)
261                 return (CC_ERROR);
262
263         el->el_line.cursor = c__next_word(el->el_line.cursor,
264             el->el_line.lastchar,
265             el->el_state.argument,
266             ce__isword);
267
268         if (el->el_map.type == MAP_VI)
269                 if (el->el_chared.c_vcmd.action != NOP) {
270                         cv_delfini(el);
271                         return (CC_REFRESH);
272                 }
273         return (CC_CURSOR);
274 }
275
276
277 /* em_upper_case():
278  *      Uppercase the characters from cursor to end of current word
279  *      [M-u]
280  */
281 protected el_action_t
282 /*ARGSUSED*/
283 em_upper_case(EditLine *el, int c __unused)
284 {
285         char *cp, *ep;
286
287         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
288             el->el_state.argument, ce__isword);
289
290         for (cp = el->el_line.cursor; cp < ep; cp++)
291                 if (islower((unsigned char)*cp))
292                         *cp = toupper((unsigned char)*cp);
293
294         el->el_line.cursor = ep;
295         if (el->el_line.cursor > el->el_line.lastchar)
296                 el->el_line.cursor = el->el_line.lastchar;
297         return (CC_REFRESH);
298 }
299
300
301 /* em_capitol_case():
302  *      Capitalize the characters from cursor to end of current word
303  *      [M-c]
304  */
305 protected el_action_t
306 /*ARGSUSED*/
307 em_capitol_case(EditLine *el, int c __unused)
308 {
309         char *cp, *ep;
310
311         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
312             el->el_state.argument, ce__isword);
313
314         for (cp = el->el_line.cursor; cp < ep; cp++) {
315                 if (isalpha((unsigned char)*cp)) {
316                         if (islower((unsigned char)*cp))
317                                 *cp = toupper((unsigned char)*cp);
318                         cp++;
319                         break;
320                 }
321         }
322         for (; cp < ep; cp++)
323                 if (isupper((unsigned char)*cp))
324                         *cp = tolower((unsigned char)*cp);
325
326         el->el_line.cursor = ep;
327         if (el->el_line.cursor > el->el_line.lastchar)
328                 el->el_line.cursor = el->el_line.lastchar;
329         return (CC_REFRESH);
330 }
331
332
333 /* em_lower_case():
334  *      Lowercase the characters from cursor to end of current word
335  *      [M-l]
336  */
337 protected el_action_t
338 /*ARGSUSED*/
339 em_lower_case(EditLine *el, int c __unused)
340 {
341         char *cp, *ep;
342
343         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
344             el->el_state.argument, ce__isword);
345
346         for (cp = el->el_line.cursor; cp < ep; cp++)
347                 if (isupper((unsigned char)*cp))
348                         *cp = tolower((unsigned char)*cp);
349
350         el->el_line.cursor = ep;
351         if (el->el_line.cursor > el->el_line.lastchar)
352                 el->el_line.cursor = el->el_line.lastchar;
353         return (CC_REFRESH);
354 }
355
356
357 /* em_set_mark():
358  *      Set the mark at cursor
359  *      [^@]
360  */
361 protected el_action_t
362 /*ARGSUSED*/
363 em_set_mark(EditLine *el, int c __unused)
364 {
365
366         el->el_chared.c_kill.mark = el->el_line.cursor;
367         return (CC_NORM);
368 }
369
370
371 /* em_exchange_mark():
372  *      Exchange the cursor and mark
373  *      [^X^X]
374  */
375 protected el_action_t
376 /*ARGSUSED*/
377 em_exchange_mark(EditLine *el, int c __unused)
378 {
379         char *cp;
380
381         cp = el->el_line.cursor;
382         el->el_line.cursor = el->el_chared.c_kill.mark;
383         el->el_chared.c_kill.mark = cp;
384         return (CC_CURSOR);
385 }
386
387
388 /* em_universal_argument():
389  *      Universal argument (argument times 4)
390  *      [^U]
391  */
392 protected el_action_t
393 /*ARGSUSED*/
394 em_universal_argument(EditLine *el, int c __unused)
395 {                               /* multiply current argument by 4 */
396
397         if (el->el_state.argument > 1000000)
398                 return (CC_ERROR);
399         el->el_state.doingarg = 1;
400         el->el_state.argument *= 4;
401         return (CC_ARGHACK);
402 }
403
404
405 /* em_meta_next():
406  *      Add 8th bit to next character typed
407  *      [<ESC>]
408  */
409 protected el_action_t
410 /*ARGSUSED*/
411 em_meta_next(EditLine *el, int c __unused)
412 {
413
414         el->el_state.metanext = 1;
415         return (CC_ARGHACK);
416 }
417
418
419 /* em_toggle_overwrite():
420  *      Switch from insert to overwrite mode or vice versa
421  */
422 protected el_action_t
423 /*ARGSUSED*/
424 em_toggle_overwrite(EditLine *el, int c __unused)
425 {
426
427         el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
428             MODE_REPLACE : MODE_INSERT;
429         return (CC_NORM);
430 }
431
432
433 /* em_copy_prev_word():
434  *      Copy current word to cursor
435  */
436 protected el_action_t
437 /*ARGSUSED*/
438 em_copy_prev_word(EditLine *el, int c __unused)
439 {
440         char *cp, *oldc, *dp;
441
442         if (el->el_line.cursor == el->el_line.buffer)
443                 return (CC_ERROR);
444
445         oldc = el->el_line.cursor;
446         /* does a bounds check */
447         cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
448             el->el_state.argument, ce__isword);
449
450         c_insert(el, (int)(oldc - cp));
451         for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
452                 *dp++ = *cp;
453
454         el->el_line.cursor = dp;/* put cursor at end */
455
456         return (CC_REFRESH);
457 }
458
459
460 /* em_inc_search_next():
461  *      Emacs incremental next search
462  */
463 protected el_action_t
464 /*ARGSUSED*/
465 em_inc_search_next(EditLine *el, int c __unused)
466 {
467
468         el->el_search.patlen = 0;
469         return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
470 }
471
472
473 /* em_inc_search_prev():
474  *      Emacs incremental reverse search
475  */
476 protected el_action_t
477 /*ARGSUSED*/
478 em_inc_search_prev(EditLine *el, int c __unused)
479 {
480
481         el->el_search.patlen = 0;
482         return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
483 }
484
485
486 /* em_delete_prev_char():
487  *      Delete the character to the left of the cursor
488  *      [^?]
489  */
490 protected el_action_t
491 /*ARGSUSED*/
492 em_delete_prev_char(EditLine *el, int c __unused)
493 {
494
495         if (el->el_line.cursor <= el->el_line.buffer)
496                 return (CC_ERROR);
497
498         if (el->el_state.doingarg)
499                 c_delbefore(el, el->el_state.argument);
500         else
501                 c_delbefore1(el);
502         el->el_line.cursor -= el->el_state.argument;
503         if (el->el_line.cursor < el->el_line.buffer)
504                 el->el_line.cursor = el->el_line.buffer;
505         return (CC_REFRESH);
506 }