Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / lib / libedit / emacs.c
blob0867756644d39270b1fea998fa170e584e12a36a
1 /* $NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $ */
3 /*-
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
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.
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.
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.22 2009/02/15 21:55:23 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
45 * emacs.c: Emacs functions
47 #include "el.h"
49 /* em_delete_or_list():
50 * Delete character under cursor or list completions if at end of line
51 * [^D]
53 protected el_action_t
54 /*ARGSUSED*/
55 em_delete_or_list(EditLine *el, Int c)
58 if (el->el_line.cursor == el->el_line.lastchar) {
59 /* if I'm at the end */
60 if (el->el_line.cursor == el->el_line.buffer) {
61 /* and the beginning */
62 term_writec(el, c); /* then do an EOF */
63 return (CC_EOF);
64 } else {
66 * Here we could list completions, but it is an
67 * error right now
69 term_beep(el);
70 return (CC_ERROR);
72 } else {
73 if (el->el_state.doingarg)
74 c_delafter(el, el->el_state.argument);
75 else
76 c_delafter1(el);
77 if (el->el_line.cursor > el->el_line.lastchar)
78 el->el_line.cursor = el->el_line.lastchar;
79 /* bounds check */
80 return (CC_REFRESH);
85 /* em_delete_next_word():
86 * Cut from cursor to end of current word
87 * [M-d]
89 protected el_action_t
90 /*ARGSUSED*/
91 em_delete_next_word(EditLine *el, Int c __attribute__((__unused__)))
93 Char *cp, *p, *kp;
95 if (el->el_line.cursor == el->el_line.lastchar)
96 return (CC_ERROR);
98 cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
99 el->el_state.argument, ce__isword);
101 for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
102 /* save the text */
103 *kp++ = *p;
104 el->el_chared.c_kill.last = kp;
106 c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */
107 if (el->el_line.cursor > el->el_line.lastchar)
108 el->el_line.cursor = el->el_line.lastchar;
109 /* bounds check */
110 return (CC_REFRESH);
114 /* em_yank():
115 * Paste cut buffer at cursor position
116 * [^Y]
118 protected el_action_t
119 /*ARGSUSED*/
120 em_yank(EditLine *el, Int c __attribute__((__unused__)))
122 Char *kp, *cp;
124 if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
125 return (CC_NORM);
127 if (el->el_line.lastchar +
128 (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
129 el->el_line.limit)
130 return (CC_ERROR);
132 el->el_chared.c_kill.mark = el->el_line.cursor;
133 cp = el->el_line.cursor;
135 /* open the space, */
136 c_insert(el,
137 (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
138 /* copy the chars */
139 for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
140 *cp++ = *kp;
142 /* if an arg, cursor at beginning else cursor at end */
143 if (el->el_state.argument == 1)
144 el->el_line.cursor = cp;
146 return (CC_REFRESH);
150 /* em_kill_line():
151 * Cut the entire line and save in cut buffer
152 * [^U]
154 protected el_action_t
155 /*ARGSUSED*/
156 em_kill_line(EditLine *el, Int c __attribute__((__unused__)))
158 Char *kp, *cp;
160 cp = el->el_line.buffer;
161 kp = el->el_chared.c_kill.buf;
162 while (cp < el->el_line.lastchar)
163 *kp++ = *cp++; /* copy it */
164 el->el_chared.c_kill.last = kp;
165 /* zap! -- delete all of it */
166 el->el_line.lastchar = el->el_line.buffer;
167 el->el_line.cursor = el->el_line.buffer;
168 return (CC_REFRESH);
172 /* em_kill_region():
173 * Cut area between mark and cursor and save in cut buffer
174 * [^W]
176 protected el_action_t
177 /*ARGSUSED*/
178 em_kill_region(EditLine *el, Int c __attribute__((__unused__)))
180 Char *kp, *cp;
182 if (!el->el_chared.c_kill.mark)
183 return (CC_ERROR);
185 if (el->el_chared.c_kill.mark > el->el_line.cursor) {
186 cp = el->el_line.cursor;
187 kp = el->el_chared.c_kill.buf;
188 while (cp < el->el_chared.c_kill.mark)
189 *kp++ = *cp++; /* copy it */
190 el->el_chared.c_kill.last = kp;
191 c_delafter(el, (int)(cp - el->el_line.cursor));
192 } else { /* mark is before cursor */
193 cp = el->el_chared.c_kill.mark;
194 kp = el->el_chared.c_kill.buf;
195 while (cp < el->el_line.cursor)
196 *kp++ = *cp++; /* copy it */
197 el->el_chared.c_kill.last = kp;
198 c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
199 el->el_line.cursor = el->el_chared.c_kill.mark;
201 return (CC_REFRESH);
205 /* em_copy_region():
206 * Copy area between mark and cursor to cut buffer
207 * [M-W]
209 protected el_action_t
210 /*ARGSUSED*/
211 em_copy_region(EditLine *el, Int c __attribute__((__unused__)))
213 Char *kp, *cp;
215 if (!el->el_chared.c_kill.mark)
216 return (CC_ERROR);
218 if (el->el_chared.c_kill.mark > el->el_line.cursor) {
219 cp = el->el_line.cursor;
220 kp = el->el_chared.c_kill.buf;
221 while (cp < el->el_chared.c_kill.mark)
222 *kp++ = *cp++; /* copy it */
223 el->el_chared.c_kill.last = kp;
224 } else {
225 cp = el->el_chared.c_kill.mark;
226 kp = el->el_chared.c_kill.buf;
227 while (cp < el->el_line.cursor)
228 *kp++ = *cp++; /* copy it */
229 el->el_chared.c_kill.last = kp;
231 return (CC_NORM);
235 /* em_gosmacs_transpose():
236 * Exchange the two characters before the cursor
237 * Gosling emacs transpose chars [^T]
239 protected el_action_t
240 em_gosmacs_transpose(EditLine *el, Int c)
243 if (el->el_line.cursor > &el->el_line.buffer[1]) {
244 /* must have at least two chars entered */
245 c = el->el_line.cursor[-2];
246 el->el_line.cursor[-2] = el->el_line.cursor[-1];
247 el->el_line.cursor[-1] = c;
248 return (CC_REFRESH);
249 } else
250 return (CC_ERROR);
254 /* em_next_word():
255 * Move next to end of current word
256 * [M-f]
258 protected el_action_t
259 /*ARGSUSED*/
260 em_next_word(EditLine *el, Int c __attribute__((__unused__)))
262 if (el->el_line.cursor == el->el_line.lastchar)
263 return (CC_ERROR);
265 el->el_line.cursor = c__next_word(el->el_line.cursor,
266 el->el_line.lastchar,
267 el->el_state.argument,
268 ce__isword);
270 if (el->el_map.type == MAP_VI)
271 if (el->el_chared.c_vcmd.action != NOP) {
272 cv_delfini(el);
273 return (CC_REFRESH);
275 return (CC_CURSOR);
279 /* em_upper_case():
280 * Uppercase the characters from cursor to end of current word
281 * [M-u]
283 protected el_action_t
284 /*ARGSUSED*/
285 em_upper_case(EditLine *el, Int c __attribute__((__unused__)))
287 Char *cp, *ep;
289 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
290 el->el_state.argument, ce__isword);
292 for (cp = el->el_line.cursor; cp < ep; cp++)
293 if (Islower(*cp))
294 *cp = Toupper(*cp);
296 el->el_line.cursor = ep;
297 if (el->el_line.cursor > el->el_line.lastchar)
298 el->el_line.cursor = el->el_line.lastchar;
299 return (CC_REFRESH);
303 /* em_capitol_case():
304 * Capitalize the characters from cursor to end of current word
305 * [M-c]
307 protected el_action_t
308 /*ARGSUSED*/
309 em_capitol_case(EditLine *el, Int c __attribute__((__unused__)))
311 Char *cp, *ep;
313 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
314 el->el_state.argument, ce__isword);
316 for (cp = el->el_line.cursor; cp < ep; cp++) {
317 if (Isalpha(*cp)) {
318 if (Islower(*cp))
319 *cp = Toupper(*cp);
320 cp++;
321 break;
324 for (; cp < ep; cp++)
325 if (Isupper(*cp))
326 *cp = Tolower(*cp);
328 el->el_line.cursor = ep;
329 if (el->el_line.cursor > el->el_line.lastchar)
330 el->el_line.cursor = el->el_line.lastchar;
331 return (CC_REFRESH);
335 /* em_lower_case():
336 * Lowercase the characters from cursor to end of current word
337 * [M-l]
339 protected el_action_t
340 /*ARGSUSED*/
341 em_lower_case(EditLine *el, Int c __attribute__((__unused__)))
343 Char *cp, *ep;
345 ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
346 el->el_state.argument, ce__isword);
348 for (cp = el->el_line.cursor; cp < ep; cp++)
349 if (Isupper(*cp))
350 *cp = Tolower(*cp);
352 el->el_line.cursor = ep;
353 if (el->el_line.cursor > el->el_line.lastchar)
354 el->el_line.cursor = el->el_line.lastchar;
355 return (CC_REFRESH);
359 /* em_set_mark():
360 * Set the mark at cursor
361 * [^@]
363 protected el_action_t
364 /*ARGSUSED*/
365 em_set_mark(EditLine *el, Int c __attribute__((__unused__)))
368 el->el_chared.c_kill.mark = el->el_line.cursor;
369 return (CC_NORM);
373 /* em_exchange_mark():
374 * Exchange the cursor and mark
375 * [^X^X]
377 protected el_action_t
378 /*ARGSUSED*/
379 em_exchange_mark(EditLine *el, Int c __attribute__((__unused__)))
381 Char *cp;
383 cp = el->el_line.cursor;
384 el->el_line.cursor = el->el_chared.c_kill.mark;
385 el->el_chared.c_kill.mark = cp;
386 return (CC_CURSOR);
390 /* em_universal_argument():
391 * Universal argument (argument times 4)
392 * [^U]
394 protected el_action_t
395 /*ARGSUSED*/
396 em_universal_argument(EditLine *el, Int c __attribute__((__unused__)))
397 { /* multiply current argument by 4 */
399 if (el->el_state.argument > 1000000)
400 return (CC_ERROR);
401 el->el_state.doingarg = 1;
402 el->el_state.argument *= 4;
403 return (CC_ARGHACK);
407 /* em_meta_next():
408 * Add 8th bit to next character typed
409 * [<ESC>]
411 protected el_action_t
412 /*ARGSUSED*/
413 em_meta_next(EditLine *el, Int c __attribute__((__unused__)))
416 el->el_state.metanext = 1;
417 return (CC_ARGHACK);
421 /* em_toggle_overwrite():
422 * Switch from insert to overwrite mode or vice versa
424 protected el_action_t
425 /*ARGSUSED*/
426 em_toggle_overwrite(EditLine *el, Int c __attribute__((__unused__)))
429 el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
430 MODE_REPLACE : MODE_INSERT;
431 return (CC_NORM);
435 /* em_copy_prev_word():
436 * Copy current word to cursor
438 protected el_action_t
439 /*ARGSUSED*/
440 em_copy_prev_word(EditLine *el, Int c __attribute__((__unused__)))
442 Char *cp, *oldc, *dp;
444 if (el->el_line.cursor == el->el_line.buffer)
445 return (CC_ERROR);
447 oldc = el->el_line.cursor;
448 /* does a bounds check */
449 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
450 el->el_state.argument, ce__isword);
452 c_insert(el, (int)(oldc - cp));
453 for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
454 *dp++ = *cp;
456 el->el_line.cursor = dp;/* put cursor at end */
458 return (CC_REFRESH);
462 /* em_inc_search_next():
463 * Emacs incremental next search
465 protected el_action_t
466 /*ARGSUSED*/
467 em_inc_search_next(EditLine *el, Int c __attribute__((__unused__)))
470 el->el_search.patlen = 0;
471 return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
475 /* em_inc_search_prev():
476 * Emacs incremental reverse search
478 protected el_action_t
479 /*ARGSUSED*/
480 em_inc_search_prev(EditLine *el, Int c __attribute__((__unused__)))
483 el->el_search.patlen = 0;
484 return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
488 /* em_delete_prev_char():
489 * Delete the character to the left of the cursor
490 * [^?]
492 protected el_action_t
493 /*ARGSUSED*/
494 em_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
497 if (el->el_line.cursor <= el->el_line.buffer)
498 return (CC_ERROR);
500 if (el->el_state.doingarg)
501 c_delbefore(el, el->el_state.argument);
502 else
503 c_delbefore1(el);
504 el->el_line.cursor -= el->el_state.argument;
505 if (el->el_line.cursor < el->el_line.buffer)
506 el->el_line.cursor = el->el_line.buffer;
507 return (CC_REFRESH);