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 * $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $
35 #if !defined(lint) && !defined(SCCSID)
36 static char sccsid
[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
37 #endif /* not lint && not SCCSID */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
42 * emacs.c: Emacs functions
47 /* em_delete_or_list():
48 * Delete character under cursor or list completions if at end of line
53 em_delete_or_list(EditLine
*el
, int c
)
56 if (el
->el_line
.cursor
== el
->el_line
.lastchar
) {
57 /* if I'm at the end */
58 if (el
->el_line
.cursor
== el
->el_line
.buffer
) {
59 /* and the beginning */
60 term_writec(el
, c
); /* then do an EOF */
64 * Here we could list completions, but it is an
71 if (el
->el_state
.doingarg
)
72 c_delafter(el
, el
->el_state
.argument
);
75 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
76 el
->el_line
.cursor
= el
->el_line
.lastchar
;
83 /* em_delete_next_word():
84 * Cut from cursor to end of current word
89 em_delete_next_word(EditLine
*el
, int c __unused
)
93 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
96 cp
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
97 el
->el_state
.argument
, ce__isword
);
99 for (p
= el
->el_line
.cursor
, kp
= el
->el_chared
.c_kill
.buf
; p
< cp
; p
++)
102 el
->el_chared
.c_kill
.last
= kp
;
104 c_delafter(el
, cp
- el
->el_line
.cursor
); /* delete after dot */
105 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
106 el
->el_line
.cursor
= el
->el_line
.lastchar
;
113 * Paste cut buffer at cursor position
116 protected el_action_t
118 em_yank(EditLine
*el
, int c __unused
)
122 if (el
->el_chared
.c_kill
.last
== el
->el_chared
.c_kill
.buf
)
125 if (el
->el_line
.lastchar
+
126 (el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
) >=
130 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
131 cp
= el
->el_line
.cursor
;
133 /* open the space, */
134 c_insert(el
, el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
);
136 for (kp
= el
->el_chared
.c_kill
.buf
; kp
< el
->el_chared
.c_kill
.last
; kp
++)
139 /* if an arg, cursor at beginning else cursor at end */
140 if (el
->el_state
.argument
== 1)
141 el
->el_line
.cursor
= cp
;
148 * Cut the entire line and save in cut buffer
151 protected el_action_t
153 em_kill_line(EditLine
*el
, int c __unused
)
157 cp
= el
->el_line
.buffer
;
158 kp
= el
->el_chared
.c_kill
.buf
;
159 while (cp
< el
->el_line
.lastchar
)
160 *kp
++ = *cp
++; /* copy it */
161 el
->el_chared
.c_kill
.last
= kp
;
162 /* zap! -- delete all of it */
163 el
->el_line
.lastchar
= el
->el_line
.buffer
;
164 el
->el_line
.cursor
= el
->el_line
.buffer
;
170 * Cut area between mark and cursor and save in cut buffer
173 protected el_action_t
175 em_kill_region(EditLine
*el
, int c __unused
)
179 if (!el
->el_chared
.c_kill
.mark
)
182 if (el
->el_chared
.c_kill
.mark
> el
->el_line
.cursor
) {
183 cp
= el
->el_line
.cursor
;
184 kp
= el
->el_chared
.c_kill
.buf
;
185 while (cp
< el
->el_chared
.c_kill
.mark
)
186 *kp
++ = *cp
++; /* copy it */
187 el
->el_chared
.c_kill
.last
= kp
;
188 c_delafter(el
, cp
- el
->el_line
.cursor
);
189 } else { /* mark is before cursor */
190 cp
= el
->el_chared
.c_kill
.mark
;
191 kp
= el
->el_chared
.c_kill
.buf
;
192 while (cp
< el
->el_line
.cursor
)
193 *kp
++ = *cp
++; /* copy it */
194 el
->el_chared
.c_kill
.last
= kp
;
195 c_delbefore(el
, cp
- el
->el_chared
.c_kill
.mark
);
196 el
->el_line
.cursor
= el
->el_chared
.c_kill
.mark
;
203 * Copy area between mark and cursor to cut buffer
206 protected el_action_t
208 em_copy_region(EditLine
*el
, int c __unused
)
212 if (!el
->el_chared
.c_kill
.mark
)
215 if (el
->el_chared
.c_kill
.mark
> el
->el_line
.cursor
) {
216 cp
= el
->el_line
.cursor
;
217 kp
= el
->el_chared
.c_kill
.buf
;
218 while (cp
< el
->el_chared
.c_kill
.mark
)
219 *kp
++ = *cp
++; /* copy it */
220 el
->el_chared
.c_kill
.last
= kp
;
222 cp
= el
->el_chared
.c_kill
.mark
;
223 kp
= el
->el_chared
.c_kill
.buf
;
224 while (cp
< el
->el_line
.cursor
)
225 *kp
++ = *cp
++; /* copy it */
226 el
->el_chared
.c_kill
.last
= kp
;
232 /* em_gosmacs_transpose():
233 * Exchange the two characters before the cursor
234 * Gosling emacs transpose chars [^T]
236 protected el_action_t
237 em_gosmacs_transpose(EditLine
*el
, int c
)
240 if (el
->el_line
.cursor
> &el
->el_line
.buffer
[1]) {
241 /* must have at least two chars entered */
242 c
= el
->el_line
.cursor
[-2];
243 el
->el_line
.cursor
[-2] = el
->el_line
.cursor
[-1];
244 el
->el_line
.cursor
[-1] = c
;
252 * Move next to end of current word
255 protected el_action_t
257 em_next_word(EditLine
*el
, int c __unused
)
259 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
262 el
->el_line
.cursor
= c__next_word(el
->el_line
.cursor
,
263 el
->el_line
.lastchar
,
264 el
->el_state
.argument
,
267 if (el
->el_map
.type
== MAP_VI
)
268 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
277 * Uppercase the characters from cursor to end of current word
280 protected el_action_t
282 em_upper_case(EditLine
*el
, int c __unused
)
286 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
287 el
->el_state
.argument
, ce__isword
);
289 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++)
290 if (islower((unsigned char)*cp
))
291 *cp
= toupper((unsigned char)*cp
);
293 el
->el_line
.cursor
= ep
;
294 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
295 el
->el_line
.cursor
= el
->el_line
.lastchar
;
300 /* em_capitol_case():
301 * Capitalize the characters from cursor to end of current word
304 protected el_action_t
306 em_capitol_case(EditLine
*el
, int c __unused
)
310 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
311 el
->el_state
.argument
, ce__isword
);
313 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++) {
314 if (isalpha((unsigned char)*cp
)) {
315 if (islower((unsigned char)*cp
))
316 *cp
= toupper((unsigned char)*cp
);
321 for (; cp
< ep
; cp
++)
322 if (isupper((unsigned char)*cp
))
323 *cp
= tolower((unsigned char)*cp
);
325 el
->el_line
.cursor
= ep
;
326 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
327 el
->el_line
.cursor
= el
->el_line
.lastchar
;
333 * Lowercase the characters from cursor to end of current word
336 protected el_action_t
338 em_lower_case(EditLine
*el
, int c __unused
)
342 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
343 el
->el_state
.argument
, ce__isword
);
345 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++)
346 if (isupper((unsigned char)*cp
))
347 *cp
= tolower((unsigned char)*cp
);
349 el
->el_line
.cursor
= ep
;
350 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
351 el
->el_line
.cursor
= el
->el_line
.lastchar
;
357 * Set the mark at cursor
360 protected el_action_t
362 em_set_mark(EditLine
*el
, int c __unused
)
365 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
370 /* em_exchange_mark():
371 * Exchange the cursor and mark
374 protected el_action_t
376 em_exchange_mark(EditLine
*el
, int c __unused
)
380 cp
= el
->el_line
.cursor
;
381 el
->el_line
.cursor
= el
->el_chared
.c_kill
.mark
;
382 el
->el_chared
.c_kill
.mark
= cp
;
387 /* em_universal_argument():
388 * Universal argument (argument times 4)
391 protected el_action_t
393 em_universal_argument(EditLine
*el
, int c __unused
)
394 { /* multiply current argument by 4 */
396 if (el
->el_state
.argument
> 1000000)
398 el
->el_state
.doingarg
= 1;
399 el
->el_state
.argument
*= 4;
405 * Add 8th bit to next character typed
408 protected el_action_t
410 em_meta_next(EditLine
*el
, int c __unused
)
413 el
->el_state
.metanext
= 1;
418 /* em_toggle_overwrite():
419 * Switch from insert to overwrite mode or vice versa
421 protected el_action_t
423 em_toggle_overwrite(EditLine
*el
, int c __unused
)
426 el
->el_state
.inputmode
= (el
->el_state
.inputmode
== MODE_INSERT
) ?
427 MODE_REPLACE
: MODE_INSERT
;
432 /* em_copy_prev_word():
433 * Copy current word to cursor
435 protected el_action_t
437 em_copy_prev_word(EditLine
*el
, int c __unused
)
439 char *cp
, *oldc
, *dp
;
441 if (el
->el_line
.cursor
== el
->el_line
.buffer
)
444 oldc
= el
->el_line
.cursor
;
445 /* does a bounds check */
446 cp
= c__prev_word(el
->el_line
.cursor
, el
->el_line
.buffer
,
447 el
->el_state
.argument
, ce__isword
);
449 c_insert(el
, oldc
- cp
);
450 for (dp
= oldc
; cp
< oldc
&& dp
< el
->el_line
.lastchar
; cp
++)
453 el
->el_line
.cursor
= dp
;/* put cursor at end */
459 /* em_inc_search_next():
460 * Emacs incremental next search
462 protected el_action_t
464 em_inc_search_next(EditLine
*el
, int c __unused
)
467 el
->el_search
.patlen
= 0;
468 return (ce_inc_search(el
, ED_SEARCH_NEXT_HISTORY
));
472 /* em_inc_search_prev():
473 * Emacs incremental reverse search
475 protected el_action_t
477 em_inc_search_prev(EditLine
*el
, int c __unused
)
480 el
->el_search
.patlen
= 0;
481 return (ce_inc_search(el
, ED_SEARCH_PREV_HISTORY
));
485 /* em_delete_prev_char():
486 * Delete the character to the left of the cursor
489 protected el_action_t
491 em_delete_prev_char(EditLine
*el
, int c __unused
)
494 if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
497 if (el
->el_state
.doingarg
)
498 c_delbefore(el
, el
->el_state
.argument
);
501 el
->el_line
.cursor
-= el
->el_state
.argument
;
502 if (el
->el_line
.cursor
< el
->el_line
.buffer
)
503 el
->el_line
.cursor
= el
->el_line
.buffer
;