xref: /csrg-svn/lib/libedit/emacs.c (revision 54216)
1*54216Sbostic /*-
2*54216Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*54216Sbostic  * All rights reserved.
4*54216Sbostic  *
5*54216Sbostic  * This code is derived from software contributed to Berkeley by
6*54216Sbostic  * Christos Zoulas of Cornell University.
7*54216Sbostic  *
8*54216Sbostic  * %sccs.include.redist.c%
9*54216Sbostic  */
10*54216Sbostic 
11*54216Sbostic #ifndef lint
12*54216Sbostic static char sccsid[] = "@(#)emacs.c	5.1 (Berkeley) 06/22/92";
13*54216Sbostic #endif /* not lint */
14*54216Sbostic 
15*54216Sbostic /*
16*54216Sbostic  * el.emacs.c: Emacs functions
17*54216Sbostic  */
18*54216Sbostic #include "sys.h"
19*54216Sbostic #include "el.h"
20*54216Sbostic 
21*54216Sbostic /* em_delete_or_list():
22*54216Sbostic  *	Delete character under cursor or list completions if at end of line
23*54216Sbostic  *	[^D]
24*54216Sbostic  */
25*54216Sbostic protected el_action_t
26*54216Sbostic /*ARGSUSED*/
27*54216Sbostic em_delete_or_list(el, c)
28*54216Sbostic     EditLine *el;
29*54216Sbostic     int c;
30*54216Sbostic {
31*54216Sbostic     if (el->el_line.cursor == el->el_line.lastchar) {	/* if I'm at the end */
32*54216Sbostic #ifdef notyet
33*54216Sbostic 	if (el->el_line.cursor == el->el_line.buffer) {	/* and the beginning */
34*54216Sbostic #endif
35*54216Sbostic 	    term_overwrite(el, STReof, 4);/* then do a EOF */
36*54216Sbostic 	    term__flush();
37*54216Sbostic 	    return CC_EOF;
38*54216Sbostic #ifdef notyet
39*54216Sbostic 	}
40*54216Sbostic 	else {
41*54216Sbostic 	    re_goto_bottom(el);
42*54216Sbostic 	    *el->el_line.lastchar = '\0';		/* just in case */
43*54216Sbostic 	    return CC_LIST_CHOICES;
44*54216Sbostic 	}
45*54216Sbostic #endif
46*54216Sbostic     }
47*54216Sbostic     else {
48*54216Sbostic 	c_delafter(el, el->el_state.argument);	/* delete after dot */
49*54216Sbostic 	if (el->el_line.cursor > el->el_line.lastchar)
50*54216Sbostic 	    el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
51*54216Sbostic 	return CC_REFRESH;
52*54216Sbostic     }
53*54216Sbostic }
54*54216Sbostic 
55*54216Sbostic 
56*54216Sbostic /* em_delete_next_word():
57*54216Sbostic  *	Cut from cursor to end of current word
58*54216Sbostic  *	[M-d]
59*54216Sbostic  */
60*54216Sbostic protected el_action_t
61*54216Sbostic /*ARGSUSED*/
62*54216Sbostic em_delete_next_word(el, c)
63*54216Sbostic     EditLine *el;
64*54216Sbostic     int c;
65*54216Sbostic {
66*54216Sbostic     char *cp, *p, *kp;
67*54216Sbostic 
68*54216Sbostic     if (el->el_line.cursor == el->el_line.lastchar)
69*54216Sbostic 	return CC_ERROR;
70*54216Sbostic 
71*54216Sbostic     cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
72*54216Sbostic 		      el->el_state.argument, ce__isword);
73*54216Sbostic 
74*54216Sbostic     for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
75*54216Sbostic 	/* save the text */
76*54216Sbostic 	*kp++ = *p;
77*54216Sbostic     el->el_chared.c_kill.last = kp;
78*54216Sbostic 
79*54216Sbostic     c_delafter(el, cp - el->el_line.cursor);		/* delete after dot */
80*54216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
81*54216Sbostic 	el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
82*54216Sbostic     return CC_REFRESH;
83*54216Sbostic }
84*54216Sbostic 
85*54216Sbostic 
86*54216Sbostic /* em_yank():
87*54216Sbostic  *	Paste cut buffer at cursor position
88*54216Sbostic  *	[^Y]
89*54216Sbostic  */
90*54216Sbostic protected el_action_t
91*54216Sbostic /*ARGSUSED*/
92*54216Sbostic em_yank(el, c)
93*54216Sbostic     EditLine *el;
94*54216Sbostic     int c;
95*54216Sbostic {
96*54216Sbostic     char *kp, *cp;
97*54216Sbostic 
98*54216Sbostic     if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
99*54216Sbostic 	return CC_ERROR;
100*54216Sbostic 
101*54216Sbostic     if (el->el_line.lastchar +
102*54216Sbostic 	(el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
103*54216Sbostic 	el->el_line.limit)
104*54216Sbostic 	return CC_ERROR;
105*54216Sbostic 
106*54216Sbostic     el->el_chared.c_kill.mark = el->el_line.cursor;
107*54216Sbostic     cp = el->el_line.cursor;
108*54216Sbostic 
109*54216Sbostic     /* open the space, */
110*54216Sbostic     c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
111*54216Sbostic     /* copy the chars */
112*54216Sbostic     for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
113*54216Sbostic 	*cp++ = *kp;
114*54216Sbostic 
115*54216Sbostic     /* if an arg, cursor at beginning else cursor at end */
116*54216Sbostic     if (el->el_state.argument == 1)
117*54216Sbostic 	el->el_line.cursor = cp;
118*54216Sbostic 
119*54216Sbostic     return CC_REFRESH;
120*54216Sbostic }
121*54216Sbostic 
122*54216Sbostic 
123*54216Sbostic /* em_kill_line():
124*54216Sbostic  *	Cut the entire line and save in cut buffer
125*54216Sbostic  *	[^U]
126*54216Sbostic  */
127*54216Sbostic protected el_action_t
128*54216Sbostic /*ARGSUSED*/
129*54216Sbostic em_kill_line(el, c)
130*54216Sbostic     EditLine *el;
131*54216Sbostic     int c;
132*54216Sbostic {
133*54216Sbostic     char *kp, *cp;
134*54216Sbostic 
135*54216Sbostic     cp = el->el_line.buffer;
136*54216Sbostic     kp = el->el_chared.c_kill.buf;
137*54216Sbostic     while (cp < el->el_line.lastchar)
138*54216Sbostic 	*kp++ = *cp++;		/* copy it */
139*54216Sbostic     el->el_chared.c_kill.last = kp;
140*54216Sbostic     el->el_line.lastchar = el->el_line.buffer;	/* zap! -- delete all of it */
141*54216Sbostic     el->el_line.cursor = el->el_line.buffer;
142*54216Sbostic     return CC_REFRESH;
143*54216Sbostic }
144*54216Sbostic 
145*54216Sbostic 
146*54216Sbostic /* em_kill_region():
147*54216Sbostic  *	Cut area between mark and cursor and save in cut buffer
148*54216Sbostic  *	[^W]
149*54216Sbostic  */
150*54216Sbostic protected el_action_t
151*54216Sbostic /*ARGSUSED*/
152*54216Sbostic em_kill_region(el, c)
153*54216Sbostic     EditLine *el;
154*54216Sbostic     int c;
155*54216Sbostic {
156*54216Sbostic     char *kp, *cp;
157*54216Sbostic 
158*54216Sbostic     if (!el->el_chared.c_kill.mark)
159*54216Sbostic 	return CC_ERROR;
160*54216Sbostic 
161*54216Sbostic     if (el->el_chared.c_kill.mark > el->el_line.cursor) {
162*54216Sbostic 	cp = el->el_line.cursor;
163*54216Sbostic 	kp = el->el_chared.c_kill.buf;
164*54216Sbostic 	while (cp < el->el_chared.c_kill.mark)
165*54216Sbostic 	    *kp++ = *cp++;	/* copy it */
166*54216Sbostic 	el->el_chared.c_kill.last = kp;
167*54216Sbostic 	c_delafter(el, cp - el->el_line.cursor);
168*54216Sbostic     }
169*54216Sbostic     else {			/* mark is before cursor */
170*54216Sbostic 	cp = el->el_chared.c_kill.mark;
171*54216Sbostic 	kp = el->el_chared.c_kill.buf;
172*54216Sbostic 	while (cp < el->el_line.cursor)
173*54216Sbostic 	    *kp++ = *cp++;	/* copy it */
174*54216Sbostic 	el->el_chared.c_kill.last = kp;
175*54216Sbostic 	c_delbefore(el, cp - el->el_chared.c_kill.mark);
176*54216Sbostic 	el->el_line.cursor = el->el_chared.c_kill.mark;
177*54216Sbostic     }
178*54216Sbostic     return CC_REFRESH;
179*54216Sbostic }
180*54216Sbostic 
181*54216Sbostic 
182*54216Sbostic /* em_copy_region():
183*54216Sbostic  *	Copy area between mark and cursor to cut buffer
184*54216Sbostic  *	[M-W]
185*54216Sbostic  */
186*54216Sbostic protected el_action_t
187*54216Sbostic /*ARGSUSED*/
188*54216Sbostic em_copy_region(el, c)
189*54216Sbostic     EditLine *el;
190*54216Sbostic     int c;
191*54216Sbostic {
192*54216Sbostic     char *kp, *cp;
193*54216Sbostic 
194*54216Sbostic     if (el->el_chared.c_kill.mark)
195*54216Sbostic 	return CC_ERROR;
196*54216Sbostic 
197*54216Sbostic     if (el->el_chared.c_kill.mark > el->el_line.cursor) {
198*54216Sbostic 	cp = el->el_line.cursor;
199*54216Sbostic 	kp = el->el_chared.c_kill.buf;
200*54216Sbostic 	while (cp < el->el_chared.c_kill.mark)
201*54216Sbostic 	    *kp++ = *cp++;	/* copy it */
202*54216Sbostic 	el->el_chared.c_kill.last = kp;
203*54216Sbostic     }
204*54216Sbostic     else {
205*54216Sbostic 	cp = el->el_chared.c_kill.mark;
206*54216Sbostic 	kp = el->el_chared.c_kill.buf;
207*54216Sbostic 	while (cp < el->el_line.cursor)
208*54216Sbostic 	    *kp++ = *cp++;	/* copy it */
209*54216Sbostic 	el->el_chared.c_kill.last = kp;
210*54216Sbostic     }
211*54216Sbostic     return CC_NORM;
212*54216Sbostic }
213*54216Sbostic 
214*54216Sbostic 
215*54216Sbostic /* em_gosmacs_traspose():
216*54216Sbostic  *	Exchange the two characters before the cursor
217*54216Sbostic  *	Gosling emacs transpose chars [^T]
218*54216Sbostic  */
219*54216Sbostic protected el_action_t
220*54216Sbostic em_gosmacs_traspose(el, c)
221*54216Sbostic     EditLine *el;
222*54216Sbostic     int c;
223*54216Sbostic {
224*54216Sbostic 
225*54216Sbostic     if (el->el_line.cursor > &el->el_line.buffer[1]) {
226*54216Sbostic    	/* must have at least two chars entered */
227*54216Sbostic 	c = el->el_line.cursor[-2];
228*54216Sbostic 	el->el_line.cursor[-2] = el->el_line.cursor[-1];
229*54216Sbostic 	el->el_line.cursor[-1] = c;
230*54216Sbostic 	return CC_REFRESH;
231*54216Sbostic     }
232*54216Sbostic     else
233*54216Sbostic 	return CC_ERROR;
234*54216Sbostic }
235*54216Sbostic 
236*54216Sbostic 
237*54216Sbostic /* em_next_word():
238*54216Sbostic  *	Move next to end of current word
239*54216Sbostic  *	[M-f]
240*54216Sbostic  */
241*54216Sbostic protected el_action_t
242*54216Sbostic /*ARGSUSED*/
243*54216Sbostic em_next_word(el, c)
244*54216Sbostic     EditLine *el;
245*54216Sbostic     int c;
246*54216Sbostic {
247*54216Sbostic     if (el->el_line.cursor == el->el_line.lastchar)
248*54216Sbostic 	return CC_ERROR;
249*54216Sbostic 
250*54216Sbostic     el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
251*54216Sbostic 				      el->el_state.argument,
252*54216Sbostic 				      ce__isword);
253*54216Sbostic 
254*54216Sbostic     if (el->el_map.type == MAP_VI)
255*54216Sbostic 	if (el->el_chared.c_vcmd.action & DELETE) {
256*54216Sbostic 	    cv_delfini(el);
257*54216Sbostic 	    return CC_REFRESH;
258*54216Sbostic 	}
259*54216Sbostic 
260*54216Sbostic     return CC_CURSOR;
261*54216Sbostic }
262*54216Sbostic 
263*54216Sbostic /* em_upper_case():
264*54216Sbostic  *	Uppercase the characters from cursor to end of current word
265*54216Sbostic  *	[M-u]
266*54216Sbostic  */
267*54216Sbostic protected el_action_t
268*54216Sbostic /*ARGSUSED*/
269*54216Sbostic em_upper_case(el, c)
270*54216Sbostic     EditLine *el;
271*54216Sbostic     int c;
272*54216Sbostic {
273*54216Sbostic     char   *cp, *ep;
274*54216Sbostic 
275*54216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
276*54216Sbostic 		      el->el_state.argument, ce__isword);
277*54216Sbostic 
278*54216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++)
279*54216Sbostic 	if (islower(*cp))
280*54216Sbostic 	    *cp = toupper(*cp);
281*54216Sbostic 
282*54216Sbostic     el->el_line.cursor = ep;
283*54216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
284*54216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
285*54216Sbostic     return CC_REFRESH;
286*54216Sbostic }
287*54216Sbostic 
288*54216Sbostic 
289*54216Sbostic /* em_capitol_case():
290*54216Sbostic  *	Capitalize the characters from cursor to end of current word
291*54216Sbostic  *	[M-c]
292*54216Sbostic  */
293*54216Sbostic protected el_action_t
294*54216Sbostic /*ARGSUSED*/
295*54216Sbostic em_capitol_case(el, c)
296*54216Sbostic     EditLine *el;
297*54216Sbostic     int c;
298*54216Sbostic {
299*54216Sbostic     char   *cp, *ep;
300*54216Sbostic 
301*54216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
302*54216Sbostic 		      el->el_state.argument, ce__isword);
303*54216Sbostic 
304*54216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++) {
305*54216Sbostic 	if (isalpha(*cp)) {
306*54216Sbostic 	    if (islower(*cp))
307*54216Sbostic 		*cp = toupper(*cp);
308*54216Sbostic 	    cp++;
309*54216Sbostic 	    break;
310*54216Sbostic 	}
311*54216Sbostic     }
312*54216Sbostic     for (; cp < ep; cp++)
313*54216Sbostic 	if (isupper(*cp))
314*54216Sbostic 	    *cp = tolower(*cp);
315*54216Sbostic 
316*54216Sbostic     el->el_line.cursor = ep;
317*54216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
318*54216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
319*54216Sbostic     return CC_REFRESH;
320*54216Sbostic }
321*54216Sbostic 
322*54216Sbostic /* em_lower_case():
323*54216Sbostic  *	Lowercase the characters from cursor to end of current word
324*54216Sbostic  *	[M-l]
325*54216Sbostic  */
326*54216Sbostic protected el_action_t
327*54216Sbostic /*ARGSUSED*/
328*54216Sbostic em_lower_case(el, c)
329*54216Sbostic     EditLine *el;
330*54216Sbostic     int c;
331*54216Sbostic {
332*54216Sbostic     char   *cp, *ep;
333*54216Sbostic 
334*54216Sbostic     ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
335*54216Sbostic 		      el->el_state.argument, ce__isword);
336*54216Sbostic 
337*54216Sbostic     for (cp = el->el_line.cursor; cp < ep; cp++)
338*54216Sbostic 	if (isupper(*cp))
339*54216Sbostic 	    *cp = tolower(*cp);
340*54216Sbostic 
341*54216Sbostic     el->el_line.cursor = ep;
342*54216Sbostic     if (el->el_line.cursor > el->el_line.lastchar)
343*54216Sbostic 	el->el_line.cursor = el->el_line.lastchar;
344*54216Sbostic     return CC_REFRESH;
345*54216Sbostic }
346*54216Sbostic 
347*54216Sbostic 
348*54216Sbostic /* em_set_mark():
349*54216Sbostic  *	Set the mark at cursor
350*54216Sbostic  *	[^@]
351*54216Sbostic  */
352*54216Sbostic protected el_action_t
353*54216Sbostic /*ARGSUSED*/
354*54216Sbostic em_set_mark(el, c)
355*54216Sbostic     EditLine *el;
356*54216Sbostic     int c;
357*54216Sbostic {
358*54216Sbostic     el->el_chared.c_kill.mark = el->el_line.cursor;
359*54216Sbostic     return CC_NORM;
360*54216Sbostic }
361*54216Sbostic 
362*54216Sbostic 
363*54216Sbostic /* em_exchange_mark():
364*54216Sbostic  *	Exchange the cursor and mark
365*54216Sbostic  *	[^X^X]
366*54216Sbostic  */
367*54216Sbostic protected el_action_t
368*54216Sbostic /*ARGSUSED*/
369*54216Sbostic em_exchange_mark(el, c)
370*54216Sbostic     EditLine *el;
371*54216Sbostic     int c;
372*54216Sbostic {
373*54216Sbostic     register char *cp;
374*54216Sbostic 
375*54216Sbostic     cp = el->el_line.cursor;
376*54216Sbostic     el->el_line.cursor = el->el_chared.c_kill.mark;
377*54216Sbostic     el->el_chared.c_kill.mark = cp;
378*54216Sbostic     return CC_CURSOR;
379*54216Sbostic }
380*54216Sbostic 
381*54216Sbostic /* em_universal_argument():
382*54216Sbostic  *	Universal argument (argument times 4)
383*54216Sbostic  *	[^U]
384*54216Sbostic  */
385*54216Sbostic protected el_action_t
386*54216Sbostic /*ARGSUSED*/
387*54216Sbostic em_universal_argument(el, c)
388*54216Sbostic     EditLine *el;
389*54216Sbostic     int c;
390*54216Sbostic {				/* multiply current argument by 4 */
391*54216Sbostic     if (el->el_state.argument > 1000000)
392*54216Sbostic 	return CC_ERROR;
393*54216Sbostic     el->el_state.doingarg = 1;
394*54216Sbostic     el->el_state.argument *= 4;
395*54216Sbostic     return CC_ARGHACK;
396*54216Sbostic }
397*54216Sbostic 
398*54216Sbostic /* em_meta_next():
399*54216Sbostic  *	Add 8th bit to next character typed
400*54216Sbostic  *	[<ESC>]
401*54216Sbostic  */
402*54216Sbostic protected el_action_t
403*54216Sbostic /*ARGSUSED*/
404*54216Sbostic em_meta_next(el, c)
405*54216Sbostic     EditLine *el;
406*54216Sbostic     int c;
407*54216Sbostic {
408*54216Sbostic     el->el_state.metanext = 1;
409*54216Sbostic     return CC_ARGHACK;
410*54216Sbostic }
411*54216Sbostic 
412*54216Sbostic 
413*54216Sbostic /* em_toggle_overwrite():
414*54216Sbostic  *	Switch from insert to overwrite mode or vice versa
415*54216Sbostic  */
416*54216Sbostic protected el_action_t
417*54216Sbostic /*ARGSUSED*/
418*54216Sbostic em_toggle_overwrite(el, c)
419*54216Sbostic     EditLine *el;
420*54216Sbostic     int c;
421*54216Sbostic {
422*54216Sbostic     el->el_state.inputmode =
423*54216Sbostic 	(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
424*54216Sbostic     return CC_NORM;
425*54216Sbostic }
426*54216Sbostic 
427*54216Sbostic 
428*54216Sbostic /* em_copy_prev_word():
429*54216Sbostic  *	Copy current word to cursor
430*54216Sbostic  */
431*54216Sbostic protected el_action_t
432*54216Sbostic /*ARGSUSED*/
433*54216Sbostic em_copy_prev_word(el, c)
434*54216Sbostic     EditLine *el;
435*54216Sbostic     int c;
436*54216Sbostic {
437*54216Sbostic     char *cp, *oldc, *dp;
438*54216Sbostic 
439*54216Sbostic     if (el->el_line.cursor == el->el_line.buffer)
440*54216Sbostic 	return CC_ERROR;
441*54216Sbostic 
442*54216Sbostic     oldc = el->el_line.cursor;
443*54216Sbostic     /* does a bounds check */
444*54216Sbostic     cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
445*54216Sbostic 		      el->el_state.argument, ce__isword);
446*54216Sbostic 
447*54216Sbostic     c_insert(el, oldc - cp);
448*54216Sbostic     for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
449*54216Sbostic 	*dp++ = *cp;
450*54216Sbostic 
451*54216Sbostic     el->el_line.cursor = dp;		/* put cursor at end */
452*54216Sbostic 
453*54216Sbostic     return CC_REFRESH;
454*54216Sbostic }
455*54216Sbostic 
456*54216Sbostic 
457*54216Sbostic /* em_inc_search_next():
458*54216Sbostic  *	Emacs incremental next search
459*54216Sbostic  */
460*54216Sbostic protected el_action_t
461*54216Sbostic /*ARGSUSED*/
462*54216Sbostic em_inc_search_next(el, c)
463*54216Sbostic     EditLine *el;
464*54216Sbostic     int c;
465*54216Sbostic {
466*54216Sbostic     el->el_search.patlen = 0;
467*54216Sbostic     return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
468*54216Sbostic }
469*54216Sbostic 
470*54216Sbostic 
471*54216Sbostic /* em_inc_search_prev():
472*54216Sbostic  *	Emacs incremental reverse search
473*54216Sbostic  */
474*54216Sbostic protected el_action_t
475*54216Sbostic /*ARGSUSED*/
476*54216Sbostic em_inc_search_prev(el, c)
477*54216Sbostic     EditLine *el;
478*54216Sbostic     int c;
479*54216Sbostic {
480*54216Sbostic     el->el_search.patlen = 0;
481*54216Sbostic     return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
482*54216Sbostic }
483