xref: /csrg-svn/lib/libedit/emacs.c (revision 61275)
154216Sbostic /*-
2*61275Sbostic  * Copyright (c) 1992, 1993
3*61275Sbostic  *	The Regents of the University of California.  All rights reserved.
454216Sbostic  *
554216Sbostic  * This code is derived from software contributed to Berkeley by
654216Sbostic  * Christos Zoulas of Cornell University.
754216Sbostic  *
854216Sbostic  * %sccs.include.redist.c%
954216Sbostic  */
1054216Sbostic 
1154624Schristos #if !defined(lint) && !defined(SCCSID)
12*61275Sbostic static char sccsid[] = "@(#)emacs.c	8.1 (Berkeley) 06/04/93";
1354624Schristos #endif /* not lint && not SCCSID */
1454216Sbostic 
1554216Sbostic /*
1654624Schristos  * emacs.c: Emacs functions
1754216Sbostic  */
1854216Sbostic #include "sys.h"
1954216Sbostic #include "el.h"
2054216Sbostic 
2154216Sbostic /* em_delete_or_list():
2254216Sbostic  *	Delete character under cursor or list completions if at end of line
2354216Sbostic  *	[^D]
2454216Sbostic  */
2554216Sbostic protected el_action_t
2654216Sbostic /*ARGSUSED*/
em_delete_or_list(el,c)2754216Sbostic em_delete_or_list(el, c)
2854216Sbostic     EditLine *el;
2954216Sbostic     int c;
3054216Sbostic {
3154216Sbostic     if (el->el_line.cursor == el->el_line.lastchar) {	/* if I'm at the end */
3254216Sbostic #ifdef notyet
3354216Sbostic 	if (el->el_line.cursor == el->el_line.buffer) {	/* and the beginning */
3454216Sbostic #endif
3554216Sbostic 	    term_overwrite(el, STReof, 4);/* then do a EOF */
3654216Sbostic 	    term__flush();
3754216Sbostic 	    return CC_EOF;
3854216Sbostic #ifdef notyet
3954216Sbostic 	}
4054216Sbostic 	else {
4154216Sbostic 	    re_goto_bottom(el);
4254216Sbostic 	    *el->el_line.lastchar = '\0';		/* just in case */
4354216Sbostic 	    return CC_LIST_CHOICES;
4454216Sbostic 	}
4554216Sbostic #endif
4654216Sbostic     }
4754216Sbostic     else {
4854216Sbostic 	c_delafter(el, el->el_state.argument);	/* delete after dot */
4954216Sbostic 	if (el->el_line.cursor > el->el_line.lastchar)
5054216Sbostic 	    el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
5154216Sbostic 	return CC_REFRESH;
5254216Sbostic     }
5354216Sbostic }
5454216Sbostic 
5554216Sbostic 
5654216Sbostic /* em_delete_next_word():
5754216Sbostic  *	Cut from cursor to end of current word
5854216Sbostic  *	[M-d]
5954216Sbostic  */
6054216Sbostic protected el_action_t
6154216Sbostic /*ARGSUSED*/
em_delete_next_word(el,c)6254216Sbostic em_delete_next_word(el, c)
6354216Sbostic     EditLine *el;
6454216Sbostic     int c;
6554216Sbostic {
6654216Sbostic     char *cp, *p, *kp;
6754216Sbostic 
6854216Sbostic     if (el->el_line.cursor == el->el_line.lastchar)
6954216Sbostic 	return CC_ERROR;
7054216Sbostic 
7154216Sbostic     cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
7254216Sbostic 		      el->el_state.argument, ce__isword);
7354216Sbostic 
7454216Sbostic     for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
7554216Sbostic 	/* save the text */
7654216Sbostic 	*kp++ = *p;
7754216Sbostic     el->el_chared.c_kill.last = kp;
7854216Sbostic 
7954216Sbostic     c_delafter(el, cp - el->el_line.cursor);		/* delete after dot */
8054216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
8154216Sbostic 	el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
8254216Sbostic     return CC_REFRESH;
8354216Sbostic }
8454216Sbostic 
8554216Sbostic 
8654216Sbostic /* em_yank():
8754216Sbostic  *	Paste cut buffer at cursor position
8854216Sbostic  *	[^Y]
8954216Sbostic  */
9054216Sbostic protected el_action_t
9154216Sbostic /*ARGSUSED*/
em_yank(el,c)9254216Sbostic em_yank(el, c)
9354216Sbostic     EditLine *el;
9454216Sbostic     int c;
9554216Sbostic {
9654216Sbostic     char *kp, *cp;
9754216Sbostic 
9854216Sbostic     if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
9954216Sbostic 	return CC_ERROR;
10054216Sbostic 
10154216Sbostic     if (el->el_line.lastchar +
10254216Sbostic 	(el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
10354216Sbostic 	el->el_line.limit)
10454216Sbostic 	return CC_ERROR;
10554216Sbostic 
10654216Sbostic     el->el_chared.c_kill.mark = el->el_line.cursor;
10754216Sbostic     cp = el->el_line.cursor;
10854216Sbostic 
10954216Sbostic     /* open the space, */
11054216Sbostic     c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
11154216Sbostic     /* copy the chars */
11254216Sbostic     for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
11354216Sbostic 	*cp++ = *kp;
11454216Sbostic 
11554216Sbostic     /* if an arg, cursor at beginning else cursor at end */
11654216Sbostic     if (el->el_state.argument == 1)
11754216Sbostic 	el->el_line.cursor = cp;
11854216Sbostic 
11954216Sbostic     return CC_REFRESH;
12054216Sbostic }
12154216Sbostic 
12254216Sbostic 
12354216Sbostic /* em_kill_line():
12454216Sbostic  *	Cut the entire line and save in cut buffer
12554216Sbostic  *	[^U]
12654216Sbostic  */
12754216Sbostic protected el_action_t
12854216Sbostic /*ARGSUSED*/
em_kill_line(el,c)12954216Sbostic em_kill_line(el, c)
13054216Sbostic     EditLine *el;
13154216Sbostic     int c;
13254216Sbostic {
13354216Sbostic     char *kp, *cp;
13454216Sbostic 
13554216Sbostic     cp = el->el_line.buffer;
13654216Sbostic     kp = el->el_chared.c_kill.buf;
13754216Sbostic     while (cp < el->el_line.lastchar)
13854216Sbostic 	*kp++ = *cp++;		/* copy it */
13954216Sbostic     el->el_chared.c_kill.last = kp;
14054216Sbostic     el->el_line.lastchar = el->el_line.buffer;	/* zap! -- delete all of it */
14154216Sbostic     el->el_line.cursor = el->el_line.buffer;
14254216Sbostic     return CC_REFRESH;
14354216Sbostic }
14454216Sbostic 
14554216Sbostic 
14654216Sbostic /* em_kill_region():
14754216Sbostic  *	Cut area between mark and cursor and save in cut buffer
14854216Sbostic  *	[^W]
14954216Sbostic  */
15054216Sbostic protected el_action_t
15154216Sbostic /*ARGSUSED*/
em_kill_region(el,c)15254216Sbostic em_kill_region(el, c)
15354216Sbostic     EditLine *el;
15454216Sbostic     int c;
15554216Sbostic {
15654216Sbostic     char *kp, *cp;
15754216Sbostic 
15854216Sbostic     if (!el->el_chared.c_kill.mark)
15954216Sbostic 	return CC_ERROR;
16054216Sbostic 
16154216Sbostic     if (el->el_chared.c_kill.mark > el->el_line.cursor) {
16254216Sbostic 	cp = el->el_line.cursor;
16354216Sbostic 	kp = el->el_chared.c_kill.buf;
16454216Sbostic 	while (cp < el->el_chared.c_kill.mark)
16554216Sbostic 	    *kp++ = *cp++;	/* copy it */
16654216Sbostic 	el->el_chared.c_kill.last = kp;
16754216Sbostic 	c_delafter(el, cp - el->el_line.cursor);
16854216Sbostic     }
16954216Sbostic     else {			/* mark is before cursor */
17054216Sbostic 	cp = el->el_chared.c_kill.mark;
17154216Sbostic 	kp = el->el_chared.c_kill.buf;
17254216Sbostic 	while (cp < el->el_line.cursor)
17354216Sbostic 	    *kp++ = *cp++;	/* copy it */
17454216Sbostic 	el->el_chared.c_kill.last = kp;
17554216Sbostic 	c_delbefore(el, cp - el->el_chared.c_kill.mark);
17654216Sbostic 	el->el_line.cursor = el->el_chared.c_kill.mark;
17754216Sbostic     }
17854216Sbostic     return CC_REFRESH;
17954216Sbostic }
18054216Sbostic 
18154216Sbostic 
18254216Sbostic /* em_copy_region():
18354216Sbostic  *	Copy area between mark and cursor to cut buffer
18454216Sbostic  *	[M-W]
18554216Sbostic  */
18654216Sbostic protected el_action_t
18754216Sbostic /*ARGSUSED*/
em_copy_region(el,c)18854216Sbostic em_copy_region(el, c)
18954216Sbostic     EditLine *el;
19054216Sbostic     int c;
19154216Sbostic {
19254216Sbostic     char *kp, *cp;
19354216Sbostic 
19454216Sbostic     if (el->el_chared.c_kill.mark)
19554216Sbostic 	return CC_ERROR;
19654216Sbostic 
19754216Sbostic     if (el->el_chared.c_kill.mark > el->el_line.cursor) {
19854216Sbostic 	cp = el->el_line.cursor;
19954216Sbostic 	kp = el->el_chared.c_kill.buf;
20054216Sbostic 	while (cp < el->el_chared.c_kill.mark)
20154216Sbostic 	    *kp++ = *cp++;	/* copy it */
20254216Sbostic 	el->el_chared.c_kill.last = kp;
20354216Sbostic     }
20454216Sbostic     else {
20554216Sbostic 	cp = el->el_chared.c_kill.mark;
20654216Sbostic 	kp = el->el_chared.c_kill.buf;
20754216Sbostic 	while (cp < el->el_line.cursor)
20854216Sbostic 	    *kp++ = *cp++;	/* copy it */
20954216Sbostic 	el->el_chared.c_kill.last = kp;
21054216Sbostic     }
21154216Sbostic     return CC_NORM;
21254216Sbostic }
21354216Sbostic 
21454216Sbostic 
21554216Sbostic /* em_gosmacs_traspose():
21654216Sbostic  *	Exchange the two characters before the cursor
21754216Sbostic  *	Gosling emacs transpose chars [^T]
21854216Sbostic  */
21954216Sbostic protected el_action_t
em_gosmacs_traspose(el,c)22054216Sbostic em_gosmacs_traspose(el, c)
22154216Sbostic     EditLine *el;
22254216Sbostic     int c;
22354216Sbostic {
22454216Sbostic 
22554216Sbostic     if (el->el_line.cursor > &el->el_line.buffer[1]) {
22654216Sbostic    	/* must have at least two chars entered */
22754216Sbostic 	c = el->el_line.cursor[-2];
22854216Sbostic 	el->el_line.cursor[-2] = el->el_line.cursor[-1];
22954216Sbostic 	el->el_line.cursor[-1] = c;
23054216Sbostic 	return CC_REFRESH;
23154216Sbostic     }
23254216Sbostic     else
23354216Sbostic 	return CC_ERROR;
23454216Sbostic }
23554216Sbostic 
23654216Sbostic 
23754216Sbostic /* em_next_word():
23854216Sbostic  *	Move next to end of current word
23954216Sbostic  *	[M-f]
24054216Sbostic  */
24154216Sbostic protected el_action_t
24254216Sbostic /*ARGSUSED*/
em_next_word(el,c)24354216Sbostic em_next_word(el, c)
24454216Sbostic     EditLine *el;
24554216Sbostic     int c;
24654216Sbostic {
24754216Sbostic     if (el->el_line.cursor == el->el_line.lastchar)
24854216Sbostic 	return CC_ERROR;
24954216Sbostic 
25054216Sbostic     el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
25154216Sbostic 				      el->el_state.argument,
25254216Sbostic 				      ce__isword);
25354216Sbostic 
25454216Sbostic     if (el->el_map.type == MAP_VI)
25554216Sbostic 	if (el->el_chared.c_vcmd.action & DELETE) {
25654216Sbostic 	    cv_delfini(el);
25754216Sbostic 	    return CC_REFRESH;
25854216Sbostic 	}
25954216Sbostic 
26054216Sbostic     return CC_CURSOR;
26154216Sbostic }
26254216Sbostic 
26354216Sbostic /* em_upper_case():
26454216Sbostic  *	Uppercase the characters from cursor to end of current word
26554216Sbostic  *	[M-u]
26654216Sbostic  */
26754216Sbostic protected el_action_t
26854216Sbostic /*ARGSUSED*/
em_upper_case(el,c)26954216Sbostic em_upper_case(el, c)
27054216Sbostic     EditLine *el;
27154216Sbostic     int c;
27254216Sbostic {
27354216Sbostic     char   *cp, *ep;
27454216Sbostic 
27554216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
27654216Sbostic 		      el->el_state.argument, ce__isword);
27754216Sbostic 
27854216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++)
27954216Sbostic 	if (islower(*cp))
28054216Sbostic 	    *cp = toupper(*cp);
28154216Sbostic 
28254216Sbostic     el->el_line.cursor = ep;
28354216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
28454216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
28554216Sbostic     return CC_REFRESH;
28654216Sbostic }
28754216Sbostic 
28854216Sbostic 
28954216Sbostic /* em_capitol_case():
29054216Sbostic  *	Capitalize the characters from cursor to end of current word
29154216Sbostic  *	[M-c]
29254216Sbostic  */
29354216Sbostic protected el_action_t
29454216Sbostic /*ARGSUSED*/
em_capitol_case(el,c)29554216Sbostic em_capitol_case(el, c)
29654216Sbostic     EditLine *el;
29754216Sbostic     int c;
29854216Sbostic {
29954216Sbostic     char   *cp, *ep;
30054216Sbostic 
30154216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
30254216Sbostic 		      el->el_state.argument, ce__isword);
30354216Sbostic 
30454216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++) {
30554216Sbostic 	if (isalpha(*cp)) {
30654216Sbostic 	    if (islower(*cp))
30754216Sbostic 		*cp = toupper(*cp);
30854216Sbostic 	    cp++;
30954216Sbostic 	    break;
31054216Sbostic 	}
31154216Sbostic     }
31254216Sbostic     for (; cp < ep; cp++)
31354216Sbostic 	if (isupper(*cp))
31454216Sbostic 	    *cp = tolower(*cp);
31554216Sbostic 
31654216Sbostic     el->el_line.cursor = ep;
31754216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
31854216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
31954216Sbostic     return CC_REFRESH;
32054216Sbostic }
32154216Sbostic 
32254216Sbostic /* em_lower_case():
32354216Sbostic  *	Lowercase the characters from cursor to end of current word
32454216Sbostic  *	[M-l]
32554216Sbostic  */
32654216Sbostic protected el_action_t
32754216Sbostic /*ARGSUSED*/
em_lower_case(el,c)32854216Sbostic em_lower_case(el, c)
32954216Sbostic     EditLine *el;
33054216Sbostic     int c;
33154216Sbostic {
33254216Sbostic     char   *cp, *ep;
33354216Sbostic 
33454216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
33554216Sbostic 		      el->el_state.argument, ce__isword);
33654216Sbostic 
33754216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++)
33854216Sbostic 	if (isupper(*cp))
33954216Sbostic 	    *cp = tolower(*cp);
34054216Sbostic 
34154216Sbostic     el->el_line.cursor = ep;
34254216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
34354216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
34454216Sbostic     return CC_REFRESH;
34554216Sbostic }
34654216Sbostic 
34754216Sbostic 
34854216Sbostic /* em_set_mark():
34954216Sbostic  *	Set the mark at cursor
35054216Sbostic  *	[^@]
35154216Sbostic  */
35254216Sbostic protected el_action_t
35354216Sbostic /*ARGSUSED*/
em_set_mark(el,c)35454216Sbostic em_set_mark(el, c)
35554216Sbostic     EditLine *el;
35654216Sbostic     int c;
35754216Sbostic {
35854216Sbostic     el->el_chared.c_kill.mark = el->el_line.cursor;
35954216Sbostic     return CC_NORM;
36054216Sbostic }
36154216Sbostic 
36254216Sbostic 
36354216Sbostic /* em_exchange_mark():
36454216Sbostic  *	Exchange the cursor and mark
36554216Sbostic  *	[^X^X]
36654216Sbostic  */
36754216Sbostic protected el_action_t
36854216Sbostic /*ARGSUSED*/
em_exchange_mark(el,c)36954216Sbostic em_exchange_mark(el, c)
37054216Sbostic     EditLine *el;
37154216Sbostic     int c;
37254216Sbostic {
37354216Sbostic     register char *cp;
37454216Sbostic 
37554216Sbostic     cp = el->el_line.cursor;
37654216Sbostic     el->el_line.cursor = el->el_chared.c_kill.mark;
37754216Sbostic     el->el_chared.c_kill.mark = cp;
37854216Sbostic     return CC_CURSOR;
37954216Sbostic }
38054216Sbostic 
38154216Sbostic /* em_universal_argument():
38254216Sbostic  *	Universal argument (argument times 4)
38354216Sbostic  *	[^U]
38454216Sbostic  */
38554216Sbostic protected el_action_t
38654216Sbostic /*ARGSUSED*/
em_universal_argument(el,c)38754216Sbostic em_universal_argument(el, c)
38854216Sbostic     EditLine *el;
38954216Sbostic     int c;
39054216Sbostic {				/* multiply current argument by 4 */
39154216Sbostic     if (el->el_state.argument > 1000000)
39254216Sbostic 	return CC_ERROR;
39354216Sbostic     el->el_state.doingarg = 1;
39454216Sbostic     el->el_state.argument *= 4;
39554216Sbostic     return CC_ARGHACK;
39654216Sbostic }
39754216Sbostic 
39854216Sbostic /* em_meta_next():
39954216Sbostic  *	Add 8th bit to next character typed
40054216Sbostic  *	[<ESC>]
40154216Sbostic  */
40254216Sbostic protected el_action_t
40354216Sbostic /*ARGSUSED*/
em_meta_next(el,c)40454216Sbostic em_meta_next(el, c)
40554216Sbostic     EditLine *el;
40654216Sbostic     int c;
40754216Sbostic {
40854216Sbostic     el->el_state.metanext = 1;
40954216Sbostic     return CC_ARGHACK;
41054216Sbostic }
41154216Sbostic 
41254216Sbostic 
41354216Sbostic /* em_toggle_overwrite():
41454216Sbostic  *	Switch from insert to overwrite mode or vice versa
41554216Sbostic  */
41654216Sbostic protected el_action_t
41754216Sbostic /*ARGSUSED*/
em_toggle_overwrite(el,c)41854216Sbostic em_toggle_overwrite(el, c)
41954216Sbostic     EditLine *el;
42054216Sbostic     int c;
42154216Sbostic {
42254216Sbostic     el->el_state.inputmode =
42354216Sbostic 	(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
42454216Sbostic     return CC_NORM;
42554216Sbostic }
42654216Sbostic 
42754216Sbostic 
42854216Sbostic /* em_copy_prev_word():
42954216Sbostic  *	Copy current word to cursor
43054216Sbostic  */
43154216Sbostic protected el_action_t
43254216Sbostic /*ARGSUSED*/
em_copy_prev_word(el,c)43354216Sbostic em_copy_prev_word(el, c)
43454216Sbostic     EditLine *el;
43554216Sbostic     int c;
43654216Sbostic {
43754216Sbostic     char *cp, *oldc, *dp;
43854216Sbostic 
43954216Sbostic     if (el->el_line.cursor == el->el_line.buffer)
44054216Sbostic 	return CC_ERROR;
44154216Sbostic 
44254216Sbostic     oldc = el->el_line.cursor;
44354216Sbostic     /* does a bounds check */
44454216Sbostic     cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
44554216Sbostic 		      el->el_state.argument, ce__isword);
44654216Sbostic 
44754216Sbostic     c_insert(el, oldc - cp);
44854216Sbostic     for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
44954216Sbostic 	*dp++ = *cp;
45054216Sbostic 
45154216Sbostic     el->el_line.cursor = dp;		/* put cursor at end */
45254216Sbostic 
45354216Sbostic     return CC_REFRESH;
45454216Sbostic }
45554216Sbostic 
45654216Sbostic 
45754216Sbostic /* em_inc_search_next():
45854216Sbostic  *	Emacs incremental next search
45954216Sbostic  */
46054216Sbostic protected el_action_t
46154216Sbostic /*ARGSUSED*/
em_inc_search_next(el,c)46254216Sbostic em_inc_search_next(el, c)
46354216Sbostic     EditLine *el;
46454216Sbostic     int c;
46554216Sbostic {
46654216Sbostic     el->el_search.patlen = 0;
46754216Sbostic     return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
46854216Sbostic }
46954216Sbostic 
47054216Sbostic 
47154216Sbostic /* em_inc_search_prev():
47254216Sbostic  *	Emacs incremental reverse search
47354216Sbostic  */
47454216Sbostic protected el_action_t
47554216Sbostic /*ARGSUSED*/
em_inc_search_prev(el,c)47654216Sbostic em_inc_search_prev(el, c)
47754216Sbostic     EditLine *el;
47854216Sbostic     int c;
47954216Sbostic {
48054216Sbostic     el->el_search.patlen = 0;
48154216Sbostic     return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
48254216Sbostic }
483