]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libedit/emacs.c
Make linux_ptrace() use linux_msg() instead of printf().
[FreeBSD/FreeBSD.git] / lib / libedit / emacs.c
1 /*      $NetBSD: emacs.c,v 1.32 2016/02/16 22:53:14 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.32 2016/02/16 22:53:14 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 /*
47  * emacs.c: Emacs functions
48  */
49 #include <ctype.h>
50
51 #include "el.h"
52 #include "emacs.h"
53
54 /* em_delete_or_list():
55  *      Delete character under cursor or list completions if at end of line
56  *      [^D]
57  */
58 protected el_action_t
59 /*ARGSUSED*/
60 em_delete_or_list(EditLine *el, wint_t c)
61 {
62
63         if (el->el_line.cursor == el->el_line.lastchar) {
64                                         /* if I'm at the end */
65                 if (el->el_line.cursor == el->el_line.buffer) {
66                                         /* and the beginning */
67                         terminal_writec(el, c); /* then do an EOF */
68                         return CC_EOF;
69                 } else {
70                         /*
71                          * Here we could list completions, but it is an
72                          * error right now
73                          */
74                         terminal_beep(el);
75                         return CC_ERROR;
76                 }
77         } else {
78                 if (el->el_state.doingarg)
79                         c_delafter(el, el->el_state.argument);
80                 else
81                         c_delafter1(el);
82                 if (el->el_line.cursor > el->el_line.lastchar)
83                         el->el_line.cursor = el->el_line.lastchar;
84                                 /* bounds check */
85                 return CC_REFRESH;
86         }
87 }
88
89
90 /* em_delete_next_word():
91  *      Cut from cursor to end of current word
92  *      [M-d]
93  */
94 protected el_action_t
95 /*ARGSUSED*/
96 em_delete_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
97 {
98         Char *cp, *p, *kp;
99
100         if (el->el_line.cursor == el->el_line.lastchar)
101                 return CC_ERROR;
102
103         cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
104             el->el_state.argument, ce__isword);
105
106         for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
107                                 /* save the text */
108                 *kp++ = *p;
109         el->el_chared.c_kill.last = kp;
110
111         c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */
112         if (el->el_line.cursor > el->el_line.lastchar)
113                 el->el_line.cursor = el->el_line.lastchar;
114                                 /* bounds check */
115         return CC_REFRESH;
116 }
117
118
119 /* em_yank():
120  *      Paste cut buffer at cursor position
121  *      [^Y]
122  */
123 protected el_action_t
124 /*ARGSUSED*/
125 em_yank(EditLine *el, wint_t c __attribute__((__unused__)))
126 {
127         Char *kp, *cp;
128
129         if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
130                 return CC_NORM;
131
132         if (el->el_line.lastchar +
133             (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
134             el->el_line.limit)
135                 return CC_ERROR;
136
137         el->el_chared.c_kill.mark = el->el_line.cursor;
138         cp = el->el_line.cursor;
139
140         /* open the space, */
141         c_insert(el,
142             (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
143         /* copy the chars */
144         for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
145                 *cp++ = *kp;
146
147         /* if an arg, cursor at beginning else cursor at end */
148         if (el->el_state.argument == 1)
149                 el->el_line.cursor = cp;
150
151         return CC_REFRESH;
152 }
153
154
155 /* em_kill_line():
156  *      Cut the entire line and save in cut buffer
157  *      [^U]
158  */
159 protected el_action_t
160 /*ARGSUSED*/
161 em_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
162 {
163         Char *kp, *cp;
164
165         cp = el->el_line.buffer;
166         kp = el->el_chared.c_kill.buf;
167         while (cp < el->el_line.lastchar)
168                 *kp++ = *cp++;  /* copy it */
169         el->el_chared.c_kill.last = kp;
170                                 /* zap! -- delete all of it */
171         el->el_line.lastchar = el->el_line.buffer;
172         el->el_line.cursor = el->el_line.buffer;
173         return CC_REFRESH;
174 }
175
176
177 /* em_kill_region():
178  *      Cut area between mark and cursor and save in cut buffer
179  *      [^W]
180  */
181 protected el_action_t
182 /*ARGSUSED*/
183 em_kill_region(EditLine *el, wint_t c __attribute__((__unused__)))
184 {
185         Char *kp, *cp;
186
187         if (!el->el_chared.c_kill.mark)
188                 return CC_ERROR;
189
190         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
191                 cp = el->el_line.cursor;
192                 kp = el->el_chared.c_kill.buf;
193                 while (cp < el->el_chared.c_kill.mark)
194                         *kp++ = *cp++;  /* copy it */
195                 el->el_chared.c_kill.last = kp;
196                 c_delafter(el, (int)(cp - el->el_line.cursor));
197         } else {                /* mark is before cursor */
198                 cp = el->el_chared.c_kill.mark;
199                 kp = el->el_chared.c_kill.buf;
200                 while (cp < el->el_line.cursor)
201                         *kp++ = *cp++;  /* copy it */
202                 el->el_chared.c_kill.last = kp;
203                 c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
204                 el->el_line.cursor = el->el_chared.c_kill.mark;
205         }
206         return CC_REFRESH;
207 }
208
209
210 /* em_copy_region():
211  *      Copy area between mark and cursor to cut buffer
212  *      [M-W]
213  */
214 protected el_action_t
215 /*ARGSUSED*/
216 em_copy_region(EditLine *el, wint_t c __attribute__((__unused__)))
217 {
218         Char *kp, *cp;
219
220         if (!el->el_chared.c_kill.mark)
221                 return CC_ERROR;
222
223         if (el->el_chared.c_kill.mark > el->el_line.cursor) {
224                 cp = el->el_line.cursor;
225                 kp = el->el_chared.c_kill.buf;
226                 while (cp < el->el_chared.c_kill.mark)
227                         *kp++ = *cp++;  /* copy it */
228                 el->el_chared.c_kill.last = kp;
229         } else {
230                 cp = el->el_chared.c_kill.mark;
231                 kp = el->el_chared.c_kill.buf;
232                 while (cp < el->el_line.cursor)
233                         *kp++ = *cp++;  /* copy it */
234                 el->el_chared.c_kill.last = kp;
235         }
236         return CC_NORM;
237 }
238
239
240 /* em_gosmacs_transpose():
241  *      Exchange the two characters before the cursor
242  *      Gosling emacs transpose chars [^T]
243  */
244 protected el_action_t
245 em_gosmacs_transpose(EditLine *el, wint_t c)
246 {
247
248         if (el->el_line.cursor > &el->el_line.buffer[1]) {
249                 /* must have at least two chars entered */
250                 c = el->el_line.cursor[-2];
251                 el->el_line.cursor[-2] = el->el_line.cursor[-1];
252                 el->el_line.cursor[-1] = (Char)c;
253                 return CC_REFRESH;
254         } else
255                 return CC_ERROR;
256 }
257
258
259 /* em_next_word():
260  *      Move next to end of current word
261  *      [M-f]
262  */
263 protected el_action_t
264 /*ARGSUSED*/
265 em_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
266 {
267         if (el->el_line.cursor == el->el_line.lastchar)
268                 return CC_ERROR;
269
270         el->el_line.cursor = c__next_word(el->el_line.cursor,
271             el->el_line.lastchar,
272             el->el_state.argument,
273             ce__isword);
274
275         if (el->el_map.type == MAP_VI)
276                 if (el->el_chared.c_vcmd.action != NOP) {
277                         cv_delfini(el);
278                         return CC_REFRESH;
279                 }
280         return CC_CURSOR;
281 }
282
283
284 /* em_upper_case():
285  *      Uppercase the characters from cursor to end of current word
286  *      [M-u]
287  */
288 protected el_action_t
289 /*ARGSUSED*/
290 em_upper_case(EditLine *el, wint_t c __attribute__((__unused__)))
291 {
292         Char *cp, *ep;
293
294         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
295             el->el_state.argument, ce__isword);
296
297         for (cp = el->el_line.cursor; cp < ep; cp++)
298                 if (Islower(*cp))
299                         *cp = Toupper(*cp);
300
301         el->el_line.cursor = ep;
302         if (el->el_line.cursor > el->el_line.lastchar)
303                 el->el_line.cursor = el->el_line.lastchar;
304         return CC_REFRESH;
305 }
306
307
308 /* em_capitol_case():
309  *      Capitalize the characters from cursor to end of current word
310  *      [M-c]
311  */
312 protected el_action_t
313 /*ARGSUSED*/
314 em_capitol_case(EditLine *el, wint_t c __attribute__((__unused__)))
315 {
316         Char *cp, *ep;
317
318         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
319             el->el_state.argument, ce__isword);
320
321         for (cp = el->el_line.cursor; cp < ep; cp++) {
322                 if (Isalpha(*cp)) {
323                         if (Islower(*cp))
324                                 *cp = Toupper(*cp);
325                         cp++;
326                         break;
327                 }
328         }
329         for (; cp < ep; cp++)
330                 if (Isupper(*cp))
331                         *cp = Tolower(*cp);
332
333         el->el_line.cursor = ep;
334         if (el->el_line.cursor > el->el_line.lastchar)
335                 el->el_line.cursor = el->el_line.lastchar;
336         return CC_REFRESH;
337 }
338
339
340 /* em_lower_case():
341  *      Lowercase the characters from cursor to end of current word
342  *      [M-l]
343  */
344 protected el_action_t
345 /*ARGSUSED*/
346 em_lower_case(EditLine *el, wint_t c __attribute__((__unused__)))
347 {
348         Char *cp, *ep;
349
350         ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
351             el->el_state.argument, ce__isword);
352
353         for (cp = el->el_line.cursor; cp < ep; cp++)
354                 if (Isupper(*cp))
355                         *cp = Tolower(*cp);
356
357         el->el_line.cursor = ep;
358         if (el->el_line.cursor > el->el_line.lastchar)
359                 el->el_line.cursor = el->el_line.lastchar;
360         return CC_REFRESH;
361 }
362
363
364 /* em_set_mark():
365  *      Set the mark at cursor
366  *      [^@]
367  */
368 protected el_action_t
369 /*ARGSUSED*/
370 em_set_mark(EditLine *el, wint_t c __attribute__((__unused__)))
371 {
372
373         el->el_chared.c_kill.mark = el->el_line.cursor;
374         return CC_NORM;
375 }
376
377
378 /* em_exchange_mark():
379  *      Exchange the cursor and mark
380  *      [^X^X]
381  */
382 protected el_action_t
383 /*ARGSUSED*/
384 em_exchange_mark(EditLine *el, wint_t c __attribute__((__unused__)))
385 {
386         Char *cp;
387
388         cp = el->el_line.cursor;
389         el->el_line.cursor = el->el_chared.c_kill.mark;
390         el->el_chared.c_kill.mark = cp;
391         return CC_CURSOR;
392 }
393
394
395 /* em_universal_argument():
396  *      Universal argument (argument times 4)
397  *      [^U]
398  */
399 protected el_action_t
400 /*ARGSUSED*/
401 em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__)))
402 {                               /* multiply current argument by 4 */
403
404         if (el->el_state.argument > 1000000)
405                 return CC_ERROR;
406         el->el_state.doingarg = 1;
407         el->el_state.argument *= 4;
408         return CC_ARGHACK;
409 }
410
411
412 /* em_meta_next():
413  *      Add 8th bit to next character typed
414  *      [<ESC>]
415  */
416 protected el_action_t
417 /*ARGSUSED*/
418 em_meta_next(EditLine *el, wint_t c __attribute__((__unused__)))
419 {
420
421         el->el_state.metanext = 1;
422         return CC_ARGHACK;
423 }
424
425
426 /* em_toggle_overwrite():
427  *      Switch from insert to overwrite mode or vice versa
428  */
429 protected el_action_t
430 /*ARGSUSED*/
431 em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__)))
432 {
433
434         el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
435             MODE_REPLACE : MODE_INSERT;
436         return CC_NORM;
437 }
438
439
440 /* em_copy_prev_word():
441  *      Copy current word to cursor
442  */
443 protected el_action_t
444 /*ARGSUSED*/
445 em_copy_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
446 {
447         Char *cp, *oldc, *dp;
448
449         if (el->el_line.cursor == el->el_line.buffer)
450                 return CC_ERROR;
451
452         oldc = el->el_line.cursor;
453         /* does a bounds check */
454         cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
455             el->el_state.argument, ce__isword);
456
457         c_insert(el, (int)(oldc - cp));
458         for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
459                 *dp++ = *cp;
460
461         el->el_line.cursor = dp;/* put cursor at end */
462
463         return CC_REFRESH;
464 }
465
466
467 /* em_inc_search_next():
468  *      Emacs incremental next search
469  */
470 protected el_action_t
471 /*ARGSUSED*/
472 em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
473 {
474
475         el->el_search.patlen = 0;
476         return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
477 }
478
479
480 /* em_inc_search_prev():
481  *      Emacs incremental reverse search
482  */
483 protected el_action_t
484 /*ARGSUSED*/
485 em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
486 {
487
488         el->el_search.patlen = 0;
489         return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
490 }
491
492
493 /* em_delete_prev_char():
494  *      Delete the character to the left of the cursor
495  *      [^?]
496  */
497 protected el_action_t
498 /*ARGSUSED*/
499 em_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
500 {
501
502         if (el->el_line.cursor <= el->el_line.buffer)
503                 return CC_ERROR;
504
505         if (el->el_state.doingarg)
506                 c_delbefore(el, el->el_state.argument);
507         else
508                 c_delbefore1(el);
509         el->el_line.cursor -= el->el_state.argument;
510         if (el->el_line.cursor < el->el_line.buffer)
511                 el->el_line.cursor = el->el_line.buffer;
512         return CC_REFRESH;
513 }