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
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
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 $
40 * emacs.c: Emacs functions
44 /* em_delete_or_list():
45 * Delete character under cursor or list completions if at end of line
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 */
61 * Here we could list completions, but it is an
68 if (el
->el_state
.doingarg
)
69 c_delafter(el
, el
->el_state
.argument
);
72 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
73 el
->el_line
.cursor
= el
->el_line
.lastchar
;
80 /* em_delete_next_word():
81 * Cut from cursor to end of current word
86 em_delete_next_word(EditLine
*el
, int c
__attribute__((__unused__
)))
90 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
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
++)
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
;
110 * Paste cut buffer at cursor position
113 protected el_action_t
115 em_yank(EditLine
*el
, int c
__attribute__((__unused__
)))
119 if (el
->el_chared
.c_kill
.last
== el
->el_chared
.c_kill
.buf
)
122 if (el
->el_line
.lastchar
+
123 (el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
) >=
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
);
133 for (kp
= el
->el_chared
.c_kill
.buf
; kp
< el
->el_chared
.c_kill
.last
; 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
;
145 * Cut the entire line and save in cut buffer
148 protected el_action_t
150 em_kill_line(EditLine
*el
, int c
__attribute__((__unused__
)))
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
;
167 * Cut area between mark and cursor and save in cut buffer
170 protected el_action_t
172 em_kill_region(EditLine
*el
, int c
__attribute__((__unused__
)))
176 if (!el
->el_chared
.c_kill
.mark
)
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
;
200 * Copy area between mark and cursor to cut buffer
203 protected el_action_t
205 em_copy_region(EditLine
*el
, int c
__attribute__((__unused__
)))
209 if (!el
->el_chared
.c_kill
.mark
)
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
;
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
;
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
;
249 * Move next to end of current word
252 protected el_action_t
254 em_next_word(EditLine
*el
, int c
__attribute__((__unused__
)))
256 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
259 el
->el_line
.cursor
= c__next_word(el
->el_line
.cursor
,
260 el
->el_line
.lastchar
,
261 el
->el_state
.argument
,
264 if (el
->el_map
.type
== MAP_VI
)
265 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
274 * Uppercase the characters from cursor to end of current word
277 protected el_action_t
279 em_upper_case(EditLine
*el
, int c
__attribute__((__unused__
)))
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
;
297 /* em_capitol_case():
298 * Capitalize the characters from cursor to end of current word
301 protected el_action_t
303 em_capitol_case(EditLine
*el
, int c
__attribute__((__unused__
)))
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
);
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
;
330 * Lowercase the characters from cursor to end of current word
333 protected el_action_t
335 em_lower_case(EditLine
*el
, int c
__attribute__((__unused__
)))
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
;
354 * Set the mark at cursor
357 protected el_action_t
359 em_set_mark(EditLine
*el
, int c
__attribute__((__unused__
)))
362 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
367 /* em_exchange_mark():
368 * Exchange the cursor and mark
371 protected el_action_t
373 em_exchange_mark(EditLine
*el
, int c
__attribute__((__unused__
)))
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
;
384 /* em_universal_argument():
385 * Universal argument (argument times 4)
388 protected el_action_t
390 em_universal_argument(EditLine
*el
, int c
__attribute__((__unused__
)))
391 { /* multiply current argument by 4 */
393 if (el
->el_state
.argument
> 1000000)
395 el
->el_state
.doingarg
= 1;
396 el
->el_state
.argument
*= 4;
402 * Add 8th bit to next character typed
405 protected el_action_t
407 em_meta_next(EditLine
*el
, int c
__attribute__((__unused__
)))
410 el
->el_state
.metanext
= 1;
415 /* em_toggle_overwrite():
416 * Switch from insert to overwrite mode or vice versa
418 protected el_action_t
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
;
429 /* em_copy_prev_word():
430 * Copy current word to cursor
432 protected el_action_t
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
)
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
++)
450 el
->el_line
.cursor
= dp
;/* put cursor at end */
456 /* em_inc_search_next():
457 * Emacs incremental next search
459 protected el_action_t
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
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
486 protected el_action_t
488 em_delete_prev_char(EditLine
*el
, int c
__attribute__((__unused__
)))
491 if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
494 if (el
->el_state
.doingarg
)
495 c_delbefore(el
, el
->el_state
.argument
);
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
;