1 /* $OpenBSD: emacs.c,v 1.17 2016/05/06 13:12:52 schwarze Exp $ */
2 /* $NetBSD: emacs.c,v 1.35 2016/04/18 17:01:19 christos Exp $ */
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
9 * Christos Zoulas of Cornell University.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * 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
, wint_t 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 terminal_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
, wint_t c
__attribute__((__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
, (int)(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
, wint_t c
__attribute__((__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, */
135 (int)(el
->el_chared
.c_kill
.last
- el
->el_chared
.c_kill
.buf
));
137 for (kp
= el
->el_chared
.c_kill
.buf
; kp
< el
->el_chared
.c_kill
.last
; kp
++)
140 /* if an arg, cursor at beginning else cursor at end */
141 if (el
->el_state
.argument
== 1)
142 el
->el_line
.cursor
= cp
;
149 * Cut the entire line and save in cut buffer
152 protected el_action_t
154 em_kill_line(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
158 cp
= el
->el_line
.buffer
;
159 kp
= el
->el_chared
.c_kill
.buf
;
160 while (cp
< el
->el_line
.lastchar
)
161 *kp
++ = *cp
++; /* copy it */
162 el
->el_chared
.c_kill
.last
= kp
;
163 /* zap! -- delete all of it */
164 el
->el_line
.lastchar
= el
->el_line
.buffer
;
165 el
->el_line
.cursor
= el
->el_line
.buffer
;
171 * Cut area between mark and cursor and save in cut buffer
174 protected el_action_t
176 em_kill_region(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
180 if (!el
->el_chared
.c_kill
.mark
)
183 if (el
->el_chared
.c_kill
.mark
> el
->el_line
.cursor
) {
184 cp
= el
->el_line
.cursor
;
185 kp
= el
->el_chared
.c_kill
.buf
;
186 while (cp
< el
->el_chared
.c_kill
.mark
)
187 *kp
++ = *cp
++; /* copy it */
188 el
->el_chared
.c_kill
.last
= kp
;
189 c_delafter(el
, (int)(cp
- el
->el_line
.cursor
));
190 } else { /* mark is before cursor */
191 cp
= el
->el_chared
.c_kill
.mark
;
192 kp
= el
->el_chared
.c_kill
.buf
;
193 while (cp
< el
->el_line
.cursor
)
194 *kp
++ = *cp
++; /* copy it */
195 el
->el_chared
.c_kill
.last
= kp
;
196 c_delbefore(el
, (int)(cp
- el
->el_chared
.c_kill
.mark
));
197 el
->el_line
.cursor
= el
->el_chared
.c_kill
.mark
;
204 * Copy area between mark and cursor to cut buffer
207 protected el_action_t
209 em_copy_region(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
213 if (!el
->el_chared
.c_kill
.mark
)
216 if (el
->el_chared
.c_kill
.mark
> el
->el_line
.cursor
) {
217 cp
= el
->el_line
.cursor
;
218 kp
= el
->el_chared
.c_kill
.buf
;
219 while (cp
< el
->el_chared
.c_kill
.mark
)
220 *kp
++ = *cp
++; /* copy it */
221 el
->el_chared
.c_kill
.last
= kp
;
223 cp
= el
->el_chared
.c_kill
.mark
;
224 kp
= el
->el_chared
.c_kill
.buf
;
225 while (cp
< el
->el_line
.cursor
)
226 *kp
++ = *cp
++; /* copy it */
227 el
->el_chared
.c_kill
.last
= kp
;
233 /* em_gosmacs_transpose():
234 * Exchange the two characters before the cursor
235 * Gosling emacs transpose chars [^T]
237 protected el_action_t
238 em_gosmacs_transpose(EditLine
*el
, wint_t c
)
241 if (el
->el_line
.cursor
> &el
->el_line
.buffer
[1]) {
242 /* must have at least two chars entered */
243 c
= el
->el_line
.cursor
[-2];
244 el
->el_line
.cursor
[-2] = el
->el_line
.cursor
[-1];
245 el
->el_line
.cursor
[-1] = c
;
253 * Move next to end of current word
256 protected el_action_t
258 em_next_word(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
260 if (el
->el_line
.cursor
== el
->el_line
.lastchar
)
263 el
->el_line
.cursor
= c__next_word(el
->el_line
.cursor
,
264 el
->el_line
.lastchar
,
265 el
->el_state
.argument
,
268 if (el
->el_map
.type
== MAP_VI
)
269 if (el
->el_chared
.c_vcmd
.action
!= NOP
) {
278 * Uppercase the characters from cursor to end of current word
281 protected el_action_t
283 em_upper_case(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
287 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
288 el
->el_state
.argument
, ce__isword
);
290 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++)
294 el
->el_line
.cursor
= ep
;
295 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
296 el
->el_line
.cursor
= el
->el_line
.lastchar
;
301 /* em_capitol_case():
302 * Capitalize the characters from cursor to end of current word
305 protected el_action_t
307 em_capitol_case(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
311 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
312 el
->el_state
.argument
, ce__isword
);
314 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++) {
322 for (; cp
< ep
; cp
++)
326 el
->el_line
.cursor
= ep
;
327 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
328 el
->el_line
.cursor
= el
->el_line
.lastchar
;
334 * Lowercase the characters from cursor to end of current word
337 protected el_action_t
339 em_lower_case(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
343 ep
= c__next_word(el
->el_line
.cursor
, el
->el_line
.lastchar
,
344 el
->el_state
.argument
, ce__isword
);
346 for (cp
= el
->el_line
.cursor
; cp
< ep
; cp
++)
350 el
->el_line
.cursor
= ep
;
351 if (el
->el_line
.cursor
> el
->el_line
.lastchar
)
352 el
->el_line
.cursor
= el
->el_line
.lastchar
;
358 * Set the mark at cursor
361 protected el_action_t
363 em_set_mark(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
366 el
->el_chared
.c_kill
.mark
= el
->el_line
.cursor
;
371 /* em_exchange_mark():
372 * Exchange the cursor and mark
375 protected el_action_t
377 em_exchange_mark(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
381 cp
= el
->el_line
.cursor
;
382 el
->el_line
.cursor
= el
->el_chared
.c_kill
.mark
;
383 el
->el_chared
.c_kill
.mark
= cp
;
388 /* em_universal_argument():
389 * Universal argument (argument times 4)
392 protected el_action_t
394 em_universal_argument(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
395 { /* multiply current argument by 4 */
397 if (el
->el_state
.argument
> 1000000)
399 el
->el_state
.doingarg
= 1;
400 el
->el_state
.argument
*= 4;
406 * Add 8th bit to next character typed
409 protected el_action_t
411 em_meta_next(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
414 el
->el_state
.metanext
= 1;
419 /* em_toggle_overwrite():
420 * Switch from insert to overwrite mode or vice versa
422 protected el_action_t
424 em_toggle_overwrite(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
427 el
->el_state
.inputmode
= (el
->el_state
.inputmode
== MODE_INSERT
) ?
428 MODE_REPLACE
: MODE_INSERT
;
433 /* em_copy_prev_word():
434 * Copy current word to cursor
436 protected el_action_t
438 em_copy_prev_word(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
440 wchar_t *cp
, *oldc
, *dp
;
442 if (el
->el_line
.cursor
== el
->el_line
.buffer
)
445 oldc
= el
->el_line
.cursor
;
446 /* does a bounds check */
447 cp
= c__prev_word(el
->el_line
.cursor
, el
->el_line
.buffer
,
448 el
->el_state
.argument
, ce__isword
);
450 c_insert(el
, (int)(oldc
- cp
));
451 for (dp
= oldc
; cp
< oldc
&& dp
< el
->el_line
.lastchar
; cp
++)
454 el
->el_line
.cursor
= dp
;/* put cursor at end */
460 /* em_inc_search_next():
461 * Emacs incremental next search
463 protected el_action_t
465 em_inc_search_next(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
468 el
->el_search
.patlen
= 0;
469 return ce_inc_search(el
, ED_SEARCH_NEXT_HISTORY
);
473 /* em_inc_search_prev():
474 * Emacs incremental reverse search
476 protected el_action_t
478 em_inc_search_prev(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
481 el
->el_search
.patlen
= 0;
482 return ce_inc_search(el
, ED_SEARCH_PREV_HISTORY
);
486 /* em_delete_prev_char():
487 * Delete the character to the left of the cursor
490 protected el_action_t
492 em_delete_prev_char(EditLine
*el
, wint_t c
__attribute__((__unused__
)))
495 if (el
->el_line
.cursor
<= el
->el_line
.buffer
)
498 if (el
->el_state
.doingarg
)
499 c_delbefore(el
, el
->el_state
.argument
);
502 el
->el_line
.cursor
-= el
->el_state
.argument
;
503 if (el
->el_line
.cursor
< el
->el_line
.buffer
)
504 el
->el_line
.cursor
= el
->el_line
.buffer
;