1 /* $NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $ */
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
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
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid
[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
40 __RCSID("$NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $");
42 #endif /* not lint && not SCCSID */
45 * emacs.c: Emacs functions
49 /* em_delete_or_list():
50 * Delete character under cursor or list completions if at end of line
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 terminal_writec(el
, c
); /* then do an EOF */
66 * Here we could list completions, but it is an
73 if (el
->el_state
.doingarg
)
74 c_delafter(el
, el
->el_state
.argument
);
77 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
78 el
->el_line
.cursor
= el
->el_line
.lastchar
;
85 /* em_delete_next_word():
86 * Cut from cursor to end of current word
91 em_delete_next_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
95 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
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
++)
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
;
115 * Paste cut buffer at cursor position
118 protected el_action_t
120 em_yank(EditLine
*el
, Int c
__attribute__((__unused__
)))
124 if (el
->el_chared
.c_kill
.last
== el
->el_chared
.c_kill
.buf
)
127 if (el
->el_line
.lastchar
+
128 (el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
) >=
132 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
133 cp
= el
->el_line
.cursor
;
135 /* open the space, */
137 (int)(el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
));
139 for (kp
= el
->el_chared
.c_kill
.buf
; kp
< el
->el_chared
.c_kill
.last
; 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
;
151 * Cut the entire line and save in cut buffer
154 protected el_action_t
156 em_kill_line(EditLine
*el
, Int c
__attribute__((__unused__
)))
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
;
173 * Cut area between mark and cursor and save in cut buffer
176 protected el_action_t
178 em_kill_region(EditLine
*el
, Int c
__attribute__((__unused__
)))
182 if (!el
->el_chared
.c_kill
.mark
)
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
;
206 * Copy area between mark and cursor to cut buffer
209 protected el_action_t
211 em_copy_region(EditLine
*el
, Int c
__attribute__((__unused__
)))
215 if (!el
->el_chared
.c_kill
.mark
)
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
;
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
;
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
;
255 * Move next to end of current word
258 protected el_action_t
260 em_next_word(EditLine
*el
, Int c
__attribute__((__unused__
)))
262 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
265 el
->el_line
.cursor
= c__next_word(el
->el_line
.cursor
,
266 el
->el_line
.lastchar
,
267 el
->el_state
.argument
,
270 if (el
->el_map
.type
== MAP_VI
)
271 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
280 * Uppercase the characters from cursor to end of current word
283 protected el_action_t
285 em_upper_case(EditLine
*el
, Int c
__attribute__((__unused__
)))
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
++)
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
;
303 /* em_capitol_case():
304 * Capitalize the characters from cursor to end of current word
307 protected el_action_t
309 em_capitol_case(EditLine
*el
, Int c
__attribute__((__unused__
)))
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
++) {
324 for (; cp
< ep
; 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
;
336 * Lowercase the characters from cursor to end of current word
339 protected el_action_t
341 em_lower_case(EditLine
*el
, Int c
__attribute__((__unused__
)))
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
++)
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
;
360 * Set the mark at cursor
363 protected el_action_t
365 em_set_mark(EditLine
*el
, Int c
__attribute__((__unused__
)))
368 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
373 /* em_exchange_mark():
374 * Exchange the cursor and mark
377 protected el_action_t
379 em_exchange_mark(EditLine
*el
, Int c
__attribute__((__unused__
)))
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
;
390 /* em_universal_argument():
391 * Universal argument (argument times 4)
394 protected el_action_t
396 em_universal_argument(EditLine
*el
, Int c
__attribute__((__unused__
)))
397 { /* multiply current argument by 4 */
399 if (el
->el_state
.argument
> 1000000)
401 el
->el_state
.doingarg
= 1;
402 el
->el_state
.argument
*= 4;
408 * Add 8th bit to next character typed
411 protected el_action_t
413 em_meta_next(EditLine
*el
, Int c
__attribute__((__unused__
)))
416 el
->el_state
.metanext
= 1;
421 /* em_toggle_overwrite():
422 * Switch from insert to overwrite mode or vice versa
424 protected el_action_t
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
;
435 /* em_copy_prev_word():
436 * Copy current word to cursor
438 protected el_action_t
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
)
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
++)
456 el
->el_line
.cursor
= dp
;/* put cursor at end */
462 /* em_inc_search_next():
463 * Emacs incremental next search
465 protected el_action_t
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
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
492 protected el_action_t
494 em_delete_prev_char(EditLine
*el
, Int c
__attribute__((__unused__
)))
497 if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
500 if (el
->el_state
.doingarg
)
501 c_delbefore(el
, el
->el_state
.argument
);
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
;