emacs.c revision 268782
121526Sdavidn/*-
225901Sgpalmer * Copyright (c) 1992, 1993
321526Sdavidn *	The Regents of the University of California.  All rights reserved.
421526Sdavidn *
521526Sdavidn * This code is derived from software contributed to Berkeley by
621526Sdavidn * Christos Zoulas of Cornell University.
721526Sdavidn *
821526Sdavidn * Redistribution and use in source and binary forms, with or without
921526Sdavidn * modification, are permitted provided that the following conditions
1021526Sdavidn * are met:
1121526Sdavidn * 1. Redistributions of source code must retain the above copyright
1243220Sdg *    notice, this list of conditions and the following disclaimer.
1321526Sdavidn * 2. Redistributions in binary form must reproduce the above copyright
1421526Sdavidn *    notice, this list of conditions and the following disclaimer in the
1539375Smsmith *    documentation and/or other materials provided with the distribution.
1639375Smsmith * 3. Neither the name of the University nor the names of its contributors
1721526Sdavidn *    may be used to endorse or promote products derived from this software
1842149Shoek *    without specific prior written permission.
1921526Sdavidn *
2021526Sdavidn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2121526Sdavidn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2221526Sdavidn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2321526Sdavidn * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2421526Sdavidn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2543220Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2621526Sdavidn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2742515Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2839375Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2939375Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3039375Smsmith * SUCH DAMAGE.
3139375Smsmith *
3239375Smsmith *	$NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $
3339375Smsmith */
3439375Smsmith
3539375Smsmith#if !defined(lint) && !defined(SCCSID)
3639375Smsmithstatic char sccsid[] = "@(#)emacs.c	8.1 (Berkeley) 6/4/93";
3721538Sdavidn#endif /* not lint && not SCCSID */
3821526Sdavidn#include <sys/cdefs.h>
3939375Smsmith__FBSDID("$FreeBSD: stable/10/lib/libedit/emacs.c 268782 2014-07-17 02:14:25Z pfg $");
4021526Sdavidn
4121943Sdavidn/*
4221538Sdavidn * emacs.c: Emacs functions
4339375Smsmith */
4439375Smsmith#include "sys.h"
4539375Smsmith#include "el.h"
4621538Sdavidn
4739375Smsmith/* em_delete_or_list():
4839375Smsmith *	Delete character under cursor or list completions if at end of line
4921538Sdavidn *	[^D]
5039375Smsmith */
5121526Sdavidnprotected el_action_t
5239375Smsmith/*ARGSUSED*/
5339375Smsmithem_delete_or_list(EditLine *el, int c)
5439424Sdt{
5539375Smsmith
5639375Smsmith	if (el->el_line.cursor == el->el_line.lastchar) {
5739375Smsmith					/* if I'm at the end */
5839375Smsmith		if (el->el_line.cursor == el->el_line.buffer) {
5921526Sdavidn					/* and the beginning */
6021526Sdavidn			term_writec(el, c);	/* then do an EOF */
6139375Smsmith			return (CC_EOF);
6221526Sdavidn		} else {
6321526Sdavidn			/*
6439375Smsmith			 * Here we could list completions, but it is an
6539375Smsmith			 * error right now
6621526Sdavidn			 */
6721526Sdavidn			term_beep(el);
6839375Smsmith			return (CC_ERROR);
6921526Sdavidn		}
7039375Smsmith	} else {
7139375Smsmith		if (el->el_state.doingarg)
7239375Smsmith			c_delafter(el, el->el_state.argument);
7321526Sdavidn		else
7421526Sdavidn			c_delafter1(el);
7521526Sdavidn		if (el->el_line.cursor > el->el_line.lastchar)
7639375Smsmith			el->el_line.cursor = el->el_line.lastchar;
7739375Smsmith				/* bounds check */
7839375Smsmith		return (CC_REFRESH);
7939375Smsmith	}
8039375Smsmith}
8139375Smsmith
8239375Smsmith
8339375Smsmith/* em_delete_next_word():
8439375Smsmith *	Cut from cursor to end of current word
8539375Smsmith *	[M-d]
8639375Smsmith */
8721526Sdavidnprotected el_action_t
8839375Smsmith/*ARGSUSED*/
8939375Smsmithem_delete_next_word(EditLine *el, int c __unused)
9021526Sdavidn{
9139375Smsmith	char *cp, *p, *kp;
9239375Smsmith
9339375Smsmith	if (el->el_line.cursor == el->el_line.lastchar)
9421526Sdavidn		return (CC_ERROR);
9539375Smsmith
9639375Smsmith	cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
9721526Sdavidn	    el->el_state.argument, ce__isword);
9821526Sdavidn
9939375Smsmith	for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
10039375Smsmith				/* save the text */
10139375Smsmith		*kp++ = *p;
10221526Sdavidn	el->el_chared.c_kill.last = kp;
10339375Smsmith
10439375Smsmith	c_delafter(el, (int)(cp - el->el_line.cursor));	/* delete after dot */
10539375Smsmith	if (el->el_line.cursor > el->el_line.lastchar)
10639375Smsmith		el->el_line.cursor = el->el_line.lastchar;
10739375Smsmith				/* bounds check */
10839375Smsmith	return (CC_REFRESH);
10939375Smsmith}
11039375Smsmith
11139375Smsmith
11239375Smsmith/* em_yank():
11339375Smsmith *	Paste cut buffer at cursor position
11439375Smsmith *	[^Y]
11539375Smsmith */
11639375Smsmithprotected el_action_t
11721526Sdavidn/*ARGSUSED*/
11821526Sdavidnem_yank(EditLine *el, int c __unused)
11939375Smsmith{
12039375Smsmith	char *kp, *cp;
12139375Smsmith
12239375Smsmith	if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
12339375Smsmith		return (CC_NORM);
12439375Smsmith
12543220Sdg	if (el->el_line.lastchar +
12639375Smsmith	    (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
12739375Smsmith	    el->el_line.limit)
12842587Sasami		return (CC_ERROR);
12939375Smsmith
13039375Smsmith	el->el_chared.c_kill.mark = el->el_line.cursor;
13139375Smsmith	cp = el->el_line.cursor;
13239375Smsmith
13339375Smsmith	/* open the space, */
13439375Smsmith	c_insert(el,
13539375Smsmith	    (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
13639375Smsmith	/* copy the chars */
13739375Smsmith	for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
13839375Smsmith		*cp++ = *kp;
13939375Smsmith
14039375Smsmith	/* if an arg, cursor at beginning else cursor at end */
14139375Smsmith	if (el->el_state.argument == 1)
14239375Smsmith		el->el_line.cursor = cp;
14339375Smsmith
14421526Sdavidn	return (CC_REFRESH);
14521526Sdavidn}
14639375Smsmith
14739375Smsmith
14839375Smsmith/* em_kill_line():
14939375Smsmith *	Cut the entire line and save in cut buffer
15039375Smsmith *	[^U]
15139375Smsmith */
15239375Smsmithprotected el_action_t
15339375Smsmith/*ARGSUSED*/
15439375Smsmithem_kill_line(EditLine *el, int c __unused)
15539375Smsmith{
15639375Smsmith	char *kp, *cp;
15739375Smsmith
15839375Smsmith	cp = el->el_line.buffer;
15925369Sache	kp = el->el_chared.c_kill.buf;
16025369Sache	while (cp < el->el_line.lastchar)
16139375Smsmith		*kp++ = *cp++;	/* copy it */
16239375Smsmith	el->el_chared.c_kill.last = kp;
16339375Smsmith				/* zap! -- delete all of it */
16439375Smsmith	el->el_line.lastchar = el->el_line.buffer;
16539375Smsmith	el->el_line.cursor = el->el_line.buffer;
16639375Smsmith	return (CC_REFRESH);
16739375Smsmith}
16839375Smsmith
16939375Smsmith
17039375Smsmith/* em_kill_region():
17139375Smsmith *	Cut area between mark and cursor and save in cut buffer
17239375Smsmith *	[^W]
17339375Smsmith */
17439375Smsmithprotected el_action_t
17539375Smsmith/*ARGSUSED*/
17639375Smsmithem_kill_region(EditLine *el, int c __unused)
17739375Smsmith{
17839375Smsmith	char *kp, *cp;
17939375Smsmith
18039375Smsmith	if (!el->el_chared.c_kill.mark)
18139375Smsmith		return (CC_ERROR);
18239375Smsmith
18339375Smsmith	if (el->el_chared.c_kill.mark > el->el_line.cursor) {
18439375Smsmith		cp = el->el_line.cursor;
18539375Smsmith		kp = el->el_chared.c_kill.buf;
18639375Smsmith		while (cp < el->el_chared.c_kill.mark)
18739375Smsmith			*kp++ = *cp++;	/* copy it */
18839375Smsmith		el->el_chared.c_kill.last = kp;
18939375Smsmith		c_delafter(el, (int)(cp - el->el_line.cursor));
19039375Smsmith	} else {		/* mark is before cursor */
19139375Smsmith		cp = el->el_chared.c_kill.mark;
19239375Smsmith		kp = el->el_chared.c_kill.buf;
19339375Smsmith		while (cp < el->el_line.cursor)
19439375Smsmith			*kp++ = *cp++;	/* copy it */
19539375Smsmith		el->el_chared.c_kill.last = kp;
19639375Smsmith		c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
19739375Smsmith		el->el_line.cursor = el->el_chared.c_kill.mark;
19839375Smsmith	}
19939375Smsmith	return (CC_REFRESH);
20039375Smsmith}
20139375Smsmith
20239375Smsmith
20339375Smsmith/* em_copy_region():
20439375Smsmith *	Copy area between mark and cursor to cut buffer
20539375Smsmith *	[M-W]
20639375Smsmith */
20739375Smsmithprotected el_action_t
20839375Smsmith/*ARGSUSED*/
20939375Smsmithem_copy_region(EditLine *el, int c __unused)
21039375Smsmith{
21139375Smsmith	char *kp, *cp;
21239375Smsmith
21339375Smsmith	if (!el->el_chared.c_kill.mark)
21439375Smsmith		return (CC_ERROR);
21539375Smsmith
21639375Smsmith	if (el->el_chared.c_kill.mark > el->el_line.cursor) {
21739375Smsmith		cp = el->el_line.cursor;
21839375Smsmith		kp = el->el_chared.c_kill.buf;
21939375Smsmith		while (cp < el->el_chared.c_kill.mark)
22039375Smsmith			*kp++ = *cp++;	/* copy it */
22139375Smsmith		el->el_chared.c_kill.last = kp;
22239375Smsmith	} else {
22339375Smsmith		cp = el->el_chared.c_kill.mark;
22439375Smsmith		kp = el->el_chared.c_kill.buf;
22539375Smsmith		while (cp < el->el_line.cursor)
22639375Smsmith			*kp++ = *cp++;	/* copy it */
22739375Smsmith		el->el_chared.c_kill.last = kp;
22839375Smsmith	}
22939375Smsmith	return (CC_NORM);
23039375Smsmith}
23139375Smsmith
23239375Smsmith
23339375Smsmith/* em_gosmacs_transpose():
23439375Smsmith *	Exchange the two characters before the cursor
23539375Smsmith *	Gosling emacs transpose chars [^T]
23639375Smsmith */
23739375Smsmithprotected el_action_t
23839375Smsmithem_gosmacs_transpose(EditLine *el, int c)
23939375Smsmith{
24039375Smsmith
24139375Smsmith	if (el->el_line.cursor > &el->el_line.buffer[1]) {
24239375Smsmith		/* must have at least two chars entered */
24339375Smsmith		c = el->el_line.cursor[-2];
24439375Smsmith		el->el_line.cursor[-2] = el->el_line.cursor[-1];
24539375Smsmith		el->el_line.cursor[-1] = c;
24639375Smsmith		return (CC_REFRESH);
24739375Smsmith	} else
24839375Smsmith		return (CC_ERROR);
24939375Smsmith}
25039375Smsmith
25139375Smsmith
25239375Smsmith/* em_next_word():
25339375Smsmith *	Move next to end of current word
25439375Smsmith *	[M-f]
25539375Smsmith */
25639375Smsmithprotected el_action_t
25739375Smsmith/*ARGSUSED*/
25839375Smsmithem_next_word(EditLine *el, int c __unused)
25939375Smsmith{
26039375Smsmith	if (el->el_line.cursor == el->el_line.lastchar)
26139375Smsmith		return (CC_ERROR);
26239375Smsmith
26339375Smsmith	el->el_line.cursor = c__next_word(el->el_line.cursor,
26439375Smsmith	    el->el_line.lastchar,
26539375Smsmith	    el->el_state.argument,
26639375Smsmith	    ce__isword);
26739375Smsmith
26839375Smsmith	if (el->el_map.type == MAP_VI)
26939375Smsmith		if (el->el_chared.c_vcmd.action != NOP) {
27039375Smsmith			cv_delfini(el);
27139375Smsmith			return (CC_REFRESH);
27239375Smsmith		}
27339375Smsmith	return (CC_CURSOR);
27439375Smsmith}
27539375Smsmith
27639375Smsmith
27739375Smsmith/* em_upper_case():
27839375Smsmith *	Uppercase the characters from cursor to end of current word
27939375Smsmith *	[M-u]
28039375Smsmith */
28139375Smsmithprotected el_action_t
28239375Smsmith/*ARGSUSED*/
28339375Smsmithem_upper_case(EditLine *el, int c __unused)
28439375Smsmith{
28539375Smsmith	char *cp, *ep;
28639375Smsmith
28739375Smsmith	ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
28839375Smsmith	    el->el_state.argument, ce__isword);
28939375Smsmith
29039375Smsmith	for (cp = el->el_line.cursor; cp < ep; cp++)
29139375Smsmith		if (islower((unsigned char)*cp))
29239375Smsmith			*cp = toupper((unsigned char)*cp);
29339375Smsmith
29439375Smsmith	el->el_line.cursor = ep;
29539375Smsmith	if (el->el_line.cursor > el->el_line.lastchar)
29639375Smsmith		el->el_line.cursor = el->el_line.lastchar;
29739375Smsmith	return (CC_REFRESH);
29839375Smsmith}
29939375Smsmith
30039375Smsmith
30139375Smsmith/* em_capitol_case():
30239375Smsmith *	Capitalize the characters from cursor to end of current word
30339375Smsmith *	[M-c]
30439375Smsmith */
30539375Smsmithprotected el_action_t
30639375Smsmith/*ARGSUSED*/
30739375Smsmithem_capitol_case(EditLine *el, int c __unused)
30839375Smsmith{
30939375Smsmith	char *cp, *ep;
31039375Smsmith
31139375Smsmith	ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
31239375Smsmith	    el->el_state.argument, ce__isword);
31339375Smsmith
31439375Smsmith	for (cp = el->el_line.cursor; cp < ep; cp++) {
31539375Smsmith		if (isalpha((unsigned char)*cp)) {
31639375Smsmith			if (islower((unsigned char)*cp))
31739375Smsmith				*cp = toupper((unsigned char)*cp);
31839375Smsmith			cp++;
31939375Smsmith			break;
32039375Smsmith		}
32139375Smsmith	}
32239375Smsmith	for (; cp < ep; cp++)
32339375Smsmith		if (isupper((unsigned char)*cp))
32439375Smsmith			*cp = tolower((unsigned char)*cp);
32539375Smsmith
32639375Smsmith	el->el_line.cursor = ep;
32742113Scwt	if (el->el_line.cursor > el->el_line.lastchar)
328		el->el_line.cursor = el->el_line.lastchar;
329	return (CC_REFRESH);
330}
331
332
333/* em_lower_case():
334 *	Lowercase the characters from cursor to end of current word
335 *	[M-l]
336 */
337protected el_action_t
338/*ARGSUSED*/
339em_lower_case(EditLine *el, int c __unused)
340{
341	char *cp, *ep;
342
343	ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
344	    el->el_state.argument, ce__isword);
345
346	for (cp = el->el_line.cursor; cp < ep; cp++)
347		if (isupper((unsigned char)*cp))
348			*cp = tolower((unsigned char)*cp);
349
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;
353	return (CC_REFRESH);
354}
355
356
357/* em_set_mark():
358 *	Set the mark at cursor
359 *	[^@]
360 */
361protected el_action_t
362/*ARGSUSED*/
363em_set_mark(EditLine *el, int c __unused)
364{
365
366	el->el_chared.c_kill.mark = el->el_line.cursor;
367	return (CC_NORM);
368}
369
370
371/* em_exchange_mark():
372 *	Exchange the cursor and mark
373 *	[^X^X]
374 */
375protected el_action_t
376/*ARGSUSED*/
377em_exchange_mark(EditLine *el, int c __unused)
378{
379	char *cp;
380
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;
384	return (CC_CURSOR);
385}
386
387
388/* em_universal_argument():
389 *	Universal argument (argument times 4)
390 *	[^U]
391 */
392protected el_action_t
393/*ARGSUSED*/
394em_universal_argument(EditLine *el, int c __unused)
395{				/* multiply current argument by 4 */
396
397	if (el->el_state.argument > 1000000)
398		return (CC_ERROR);
399	el->el_state.doingarg = 1;
400	el->el_state.argument *= 4;
401	return (CC_ARGHACK);
402}
403
404
405/* em_meta_next():
406 *	Add 8th bit to next character typed
407 *	[<ESC>]
408 */
409protected el_action_t
410/*ARGSUSED*/
411em_meta_next(EditLine *el, int c __unused)
412{
413
414	el->el_state.metanext = 1;
415	return (CC_ARGHACK);
416}
417
418
419/* em_toggle_overwrite():
420 *	Switch from insert to overwrite mode or vice versa
421 */
422protected el_action_t
423/*ARGSUSED*/
424em_toggle_overwrite(EditLine *el, int c __unused)
425{
426
427	el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
428	    MODE_REPLACE : MODE_INSERT;
429	return (CC_NORM);
430}
431
432
433/* em_copy_prev_word():
434 *	Copy current word to cursor
435 */
436protected el_action_t
437/*ARGSUSED*/
438em_copy_prev_word(EditLine *el, int c __unused)
439{
440	char *cp, *oldc, *dp;
441
442	if (el->el_line.cursor == el->el_line.buffer)
443		return (CC_ERROR);
444
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);
449
450	c_insert(el, (int)(oldc - cp));
451	for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
452		*dp++ = *cp;
453
454	el->el_line.cursor = dp;/* put cursor at end */
455
456	return (CC_REFRESH);
457}
458
459
460/* em_inc_search_next():
461 *	Emacs incremental next search
462 */
463protected el_action_t
464/*ARGSUSED*/
465em_inc_search_next(EditLine *el, int c __unused)
466{
467
468	el->el_search.patlen = 0;
469	return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
470}
471
472
473/* em_inc_search_prev():
474 *	Emacs incremental reverse search
475 */
476protected el_action_t
477/*ARGSUSED*/
478em_inc_search_prev(EditLine *el, int c __unused)
479{
480
481	el->el_search.patlen = 0;
482	return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
483}
484
485
486/* em_delete_prev_char():
487 *	Delete the character to the left of the cursor
488 *	[^?]
489 */
490protected el_action_t
491/*ARGSUSED*/
492em_delete_prev_char(EditLine *el, int c __unused)
493{
494
495	if (el->el_line.cursor <= el->el_line.buffer)
496		return (CC_ERROR);
497
498	if (el->el_state.doingarg)
499		c_delbefore(el, el->el_state.argument);
500	else
501		c_delbefore1(el);
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;
505	return (CC_REFRESH);
506}
507