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