Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / lib / libedit / emacs.c
blobe54a25183d97c4d87d46dcfb883f05740b4af369
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
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.
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.
32 * @(#)emacs.c 8.1 (Berkeley) 6/4/93
33 * $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $
34 * $DragonFly: src/lib/libedit/emacs.c,v 1.6 2007/05/05 00:27:39 pavalos Exp $
37 #include "config.h"
40 * emacs.c: Emacs functions
42 #include "el.h"
44 /* em_delete_or_list():
45 * Delete character under cursor or list completions if at end of line
46 * [^D]
48 protected el_action_t
49 /*ARGSUSED*/
50 em_delete_or_list(EditLine *el, int c)
53 if (el->el_line.cursor == el->el_line.lastchar) {
54 /* if I'm at the end */
55 if (el->el_line.cursor == el->el_line.buffer) {
56 /* and the beginning */
57 term_writec(el, c); /* then do an EOF */
58 return (CC_EOF);
59 } else {
61 * Here we could list completions, but it is an
62 * error right now
64 term_beep(el);
65 return (CC_ERROR);
67 } else {
68 if (el->el_state.doingarg)
69 c_delafter(el, el->el_state.argument);
70 else
71 c_delafter1(el);
72 if (el->el_line.cursor > el->el_line.lastchar)
73 el->el_line.cursor = el->el_line.lastchar;
74 /* bounds check */
75 return (CC_REFRESH);
80 /* em_delete_next_word():
81 * Cut from cursor to end of current word
82 * [M-d]
84 protected el_action_t
85 /*ARGSUSED*/
86 em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))
88 char *cp, *p, *kp;
90 if (el->el_line.cursor == el->el_line.lastchar)
91 return (CC_ERROR);
93 cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
94 el->el_state.argument, ce__isword);
96 for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
97 /* save the text */
98 *kp++ = *p;
99 el->el_chared.c_kill.last = kp;
101 c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
102 if (el->el_line.cursor > el->el_line.lastchar)
103 el->el_line.cursor = el->el_line.lastchar;
104 /* bounds check */
105 return (CC_REFRESH);
109 /* em_yank():
110 * Paste cut buffer at cursor position
111 * [^Y]
113 protected el_action_t
114 /*ARGSUSED*/
115 em_yank(EditLine *el, int c __attribute__((__unused__)))
117 char *kp, *cp;
119 if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
120 return (CC_NORM);
122 if (el->el_line.lastchar +
123 (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
124 el->el_line.limit)
125 return (CC_ERROR);
127 el->el_chared.c_kill.mark = el->el_line.cursor;
128 cp = el->el_line.cursor;
130 /* open the space, */
131 c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
132 /* copy the chars */
133 for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
134 *cp++ = *kp;
136 /* if an arg, cursor at beginning else cursor at end */
137 if (el->el_state.argument == 1)
138 el->el_line.cursor = cp;
140 return (CC_REFRESH);
144 /* em_kill_line():
145 * Cut the entire line and save in cut buffer
146 * [^U]
148 protected el_action_t
149 /*ARGSUSED*/
150 em_kill_line(EditLine *el, int c __attribute__((__unused__)))
152 char *kp, *cp;
154 cp = el->el_line.buffer;
155 kp = el->el_chared.c_kill.buf;
156 while (cp < el->el_line.lastchar)
157 *kp++ = *cp++; /* copy it */
158 el->el_chared.c_kill.last = kp;
159 /* zap! -- delete all of it */
160 el->el_line.lastchar = el->el_line.buffer;
161 el->el_line.cursor = el->el_line.buffer;
162 return (CC_REFRESH);
166 /* em_kill_region():
167 * Cut area between mark and cursor and save in cut buffer
168 * [^W]
170 protected el_action_t
171 /*ARGSUSED*/
172 em_kill_region(EditLine *el, int c __attribute__((__unused__)))
174 char *kp, *cp;
176 if (!el->el_chared.c_kill.mark)
177 return (CC_ERROR);
179 if (el->el_chared.c_kill.mark > el->el_line.cursor) {
180 cp = el->el_line.cursor;
181 kp = el->el_chared.c_kill.buf;
182 while (cp < el->el_chared.c_kill.mark)
183 *kp++ = *cp++; /* copy it */
184 el->el_chared.c_kill.last = kp;
185 c_delafter(el, cp - el->el_line.cursor);
186 } else { /* mark is before cursor */
187 cp = el->el_chared.c_kill.mark;
188 kp = el->el_chared.c_kill.buf;
189 while (cp < el->el_line.cursor)
190 *kp++ = *cp++; /* copy it */
191 el->el_chared.c_kill.last = kp;
192 c_delbefore(el, cp - el->el_chared.c_kill.mark);
193 el->el_line.cursor = el->el_chared.c_kill.mark;
195 return (CC_REFRESH);
199 /* em_copy_region():
200 * Copy area between mark and cursor to cut buffer
201 * [M-W]
203 protected el_action_t
204 /*ARGSUSED*/
205 em_copy_region(EditLine *el, int c __attribute__((__unused__)))
207 char *kp, *cp;
209 if (!el->el_chared.c_kill.mark)
210 return (CC_ERROR);
212 if (el->el_chared.c_kill.mark > el->el_line.cursor) {
213 cp = el->el_line.cursor;
214 kp = el->el_chared.c_kill.buf;
215 while (cp < el->el_chared.c_kill.mark)
216 *kp++ = *cp++; /* copy it */
217 el->el_chared.c_kill.last = kp;
218 } else {
219 cp = el->el_chared.c_kill.mark;
220 kp = el->el_chared.c_kill.buf;
221 while (cp < el->el_line.cursor)
222 *kp++ = *cp++; /* copy it */
223 el->el_chared.c_kill.last = kp;
225 return (CC_NORM);
229 /* em_gosmacs_transpose():
230 * Exchange the two characters before the cursor
231 * Gosling emacs transpose chars [^T]
233 protected el_action_t
234 em_gosmacs_transpose(EditLine *el, int c)
237 if (el->el_line.cursor > &el->el_line.buffer[1]) {
238 /* must have at least two chars entered */
239 c = el->el_line.cursor[-2];
240 el->el_line.cursor[-2] = el->el_line.cursor[-1];
241 el->el_line.cursor[-1] = c;
242 return (CC_REFRESH);
243 } else
244 return (CC_ERROR);
248 /* em_next_word():
249 * Move next to end of current word
250 * [M-f]
252 protected el_action_t
253 /*ARGSUSED*/
254 em_next_word(EditLine *el, int c __attribute__((__unused__)))
256 if (el->el_line.cursor == el->el_line.lastchar)
257 return (CC_ERROR);
259 el->el_line.cursor = c__next_word(el->el_line.cursor,
260 el->el_line.lastchar,
261 el->el_state.argument,
262 ce__isword);
264 if (el->el_map.type == MAP_VI)
265 if (el->el_chared.c_vcmd.action != NOP) {
266 cv_delfini(el);
267 return (CC_REFRESH);
269 return (CC_CURSOR);
273 /* em_upper_case():
274 * Uppercase the characters from cursor to end of current word
275 * [M-u]
277 protected el_action_t
278 /*ARGSUSED*/
279 em_upper_case(EditLine *el, int c __attribute__((__unused__)))
281 char *cp, *ep;
283 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
284 el->el_state.argument, ce__isword);
286 for (cp = el->el_line.cursor; cp < ep; cp++)
287 if (islower((unsigned char)*cp))
288 *cp = toupper((unsigned char)*cp);
290 el->el_line.cursor = ep;
291 if (el->el_line.cursor > el->el_line.lastchar)
292 el->el_line.cursor = el->el_line.lastchar;
293 return (CC_REFRESH);
297 /* em_capitol_case():
298 * Capitalize the characters from cursor to end of current word
299 * [M-c]
301 protected el_action_t
302 /*ARGSUSED*/
303 em_capitol_case(EditLine *el, int c __attribute__((__unused__)))
305 char *cp, *ep;
307 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
308 el->el_state.argument, ce__isword);
310 for (cp = el->el_line.cursor; cp < ep; cp++) {
311 if (isalpha((unsigned char)*cp)) {
312 if (islower((unsigned char)*cp))
313 *cp = toupper((unsigned char)*cp);
314 cp++;
315 break;
318 for (; cp < ep; cp++)
319 if (isupper((unsigned char)*cp))
320 *cp = tolower((unsigned char)*cp);
322 el->el_line.cursor = ep;
323 if (el->el_line.cursor > el->el_line.lastchar)
324 el->el_line.cursor = el->el_line.lastchar;
325 return (CC_REFRESH);
329 /* em_lower_case():
330 * Lowercase the characters from cursor to end of current word
331 * [M-l]
333 protected el_action_t
334 /*ARGSUSED*/
335 em_lower_case(EditLine *el, int c __attribute__((__unused__)))
337 char *cp, *ep;
339 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
340 el->el_state.argument, ce__isword);
342 for (cp = el->el_line.cursor; cp < ep; cp++)
343 if (isupper((unsigned char)*cp))
344 *cp = tolower((unsigned char)*cp);
346 el->el_line.cursor = ep;
347 if (el->el_line.cursor > el->el_line.lastchar)
348 el->el_line.cursor = el->el_line.lastchar;
349 return (CC_REFRESH);
353 /* em_set_mark():
354 * Set the mark at cursor
355 * [^@]
357 protected el_action_t
358 /*ARGSUSED*/
359 em_set_mark(EditLine *el, int c __attribute__((__unused__)))
362 el->el_chared.c_kill.mark = el->el_line.cursor;
363 return (CC_NORM);
367 /* em_exchange_mark():
368 * Exchange the cursor and mark
369 * [^X^X]
371 protected el_action_t
372 /*ARGSUSED*/
373 em_exchange_mark(EditLine *el, int c __attribute__((__unused__)))
375 char *cp;
377 cp = el->el_line.cursor;
378 el->el_line.cursor = el->el_chared.c_kill.mark;
379 el->el_chared.c_kill.mark = cp;
380 return (CC_CURSOR);
384 /* em_universal_argument():
385 * Universal argument (argument times 4)
386 * [^U]
388 protected el_action_t
389 /*ARGSUSED*/
390 em_universal_argument(EditLine *el, int c __attribute__((__unused__)))
391 { /* multiply current argument by 4 */
393 if (el->el_state.argument > 1000000)
394 return (CC_ERROR);
395 el->el_state.doingarg = 1;
396 el->el_state.argument *= 4;
397 return (CC_ARGHACK);
401 /* em_meta_next():
402 * Add 8th bit to next character typed
403 * [<ESC>]
405 protected el_action_t
406 /*ARGSUSED*/
407 em_meta_next(EditLine *el, int c __attribute__((__unused__)))
410 el->el_state.metanext = 1;
411 return (CC_ARGHACK);
415 /* em_toggle_overwrite():
416 * Switch from insert to overwrite mode or vice versa
418 protected el_action_t
419 /*ARGSUSED*/
420 em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__)))
423 el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
424 MODE_REPLACE : MODE_INSERT;
425 return (CC_NORM);
429 /* em_copy_prev_word():
430 * Copy current word to cursor
432 protected el_action_t
433 /*ARGSUSED*/
434 em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))
436 char *cp, *oldc, *dp;
438 if (el->el_line.cursor == el->el_line.buffer)
439 return (CC_ERROR);
441 oldc = el->el_line.cursor;
442 /* does a bounds check */
443 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
444 el->el_state.argument, ce__isword);
446 c_insert(el, oldc - cp);
447 for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
448 *dp++ = *cp;
450 el->el_line.cursor = dp;/* put cursor at end */
452 return (CC_REFRESH);
456 /* em_inc_search_next():
457 * Emacs incremental next search
459 protected el_action_t
460 /*ARGSUSED*/
461 em_inc_search_next(EditLine *el, int c __attribute__((__unused__)))
464 el->el_search.patlen = 0;
465 return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
469 /* em_inc_search_prev():
470 * Emacs incremental reverse search
472 protected el_action_t
473 /*ARGSUSED*/
474 em_inc_search_prev(EditLine *el, int c __attribute__((__unused__)))
477 el->el_search.patlen = 0;
478 return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
482 /* em_delete_prev_char():
483 * Delete the character to the left of the cursor
484 * [^?]
486 protected el_action_t
487 /*ARGSUSED*/
488 em_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
491 if (el->el_line.cursor <= el->el_line.buffer)
492 return (CC_ERROR);
494 if (el->el_state.doingarg)
495 c_delbefore(el, el->el_state.argument);
496 else
497 c_delbefore1(el);
498 el->el_line.cursor -= el->el_state.argument;
499 if (el->el_line.cursor < el->el_line.buffer)
500 el->el_line.cursor = el->el_line.buffer;
501 return (CC_REFRESH);