emacs.c revision 1573
1127412Sgad/*-
2127412Sgad * Copyright (c) 1992, 1993
3127412Sgad *	The Regents of the University of California.  All rights reserved.
4161458Syar *
5161458Syar * This code is derived from software contributed to Berkeley by
6127412Sgad * Christos Zoulas of Cornell University.
7127431Sgad *
8127412Sgad * Redistribution and use in source and binary forms, with or without
9127437Sru * modification, are permitted provided that the following conditions
10127437Sru * are met:
11127412Sgad * 1. Redistributions of source code must retain the above copyright
12127437Sru *    notice, this list of conditions and the following disclaimer.
13127437Sru * 2. Redistributions in binary form must reproduce the above copyright
14127412Sgad *    notice, this list of conditions and the following disclaimer in the
15161458Syar *    documentation and/or other materials provided with the distribution.
16161458Syar * 3. All advertising materials mentioning features or use of this software
17161458Syar *    must display the following acknowledgement:
18127412Sgad *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if !defined(lint) && !defined(SCCSID)
38static char sccsid[] = "@(#)emacs.c	8.1 (Berkeley) 6/4/93";
39#endif /* not lint && not SCCSID */
40
41/*
42 * emacs.c: Emacs functions
43 */
44#include "sys.h"
45#include "el.h"
46
47/* em_delete_or_list():
48 *	Delete character under cursor or list completions if at end of line
49 *	[^D]
50 */
51protected el_action_t
52/*ARGSUSED*/
53em_delete_or_list(el, c)
54    EditLine *el;
55    int c;
56{
57    if (el->el_line.cursor == el->el_line.lastchar) {	/* if I'm at the end */
58#ifdef notyet
59	if (el->el_line.cursor == el->el_line.buffer) {	/* and the beginning */
60#endif
61	    term_overwrite(el, STReof, 4);/* then do a EOF */
62	    term__flush();
63	    return CC_EOF;
64#ifdef notyet
65	}
66	else {
67	    re_goto_bottom(el);
68	    *el->el_line.lastchar = '\0';		/* just in case */
69	    return CC_LIST_CHOICES;
70	}
71#endif
72    }
73    else {
74	c_delafter(el, el->el_state.argument);	/* delete after dot */
75	if (el->el_line.cursor > el->el_line.lastchar)
76	    el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
77	return CC_REFRESH;
78    }
79}
80
81
82/* em_delete_next_word():
83 *	Cut from cursor to end of current word
84 *	[M-d]
85 */
86protected el_action_t
87/*ARGSUSED*/
88em_delete_next_word(el, c)
89    EditLine *el;
90    int c;
91{
92    char *cp, *p, *kp;
93
94    if (el->el_line.cursor == el->el_line.lastchar)
95	return CC_ERROR;
96
97    cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
98		      el->el_state.argument, ce__isword);
99
100    for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
101	/* save the text */
102	*kp++ = *p;
103    el->el_chared.c_kill.last = kp;
104
105    c_delafter(el, cp - el->el_line.cursor);		/* delete after dot */
106    if (el->el_line.cursor > el->el_line.lastchar)
107	el->el_line.cursor = el->el_line.lastchar;	/* bounds check */
108    return CC_REFRESH;
109}
110
111
112/* em_yank():
113 *	Paste cut buffer at cursor position
114 *	[^Y]
115 */
116protected el_action_t
117/*ARGSUSED*/
118em_yank(el, c)
119    EditLine *el;
120    int c;
121{
122    char *kp, *cp;
123
124    if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
125	return CC_ERROR;
126
127    if (el->el_line.lastchar +
128	(el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
129	el->el_line.limit)
130	return CC_ERROR;
131
132    el->el_chared.c_kill.mark = el->el_line.cursor;
133    cp = el->el_line.cursor;
134
135    /* open the space, */
136    c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
137    /* copy the chars */
138    for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
139	*cp++ = *kp;
140
141    /* if an arg, cursor at beginning else cursor at end */
142    if (el->el_state.argument == 1)
143	el->el_line.cursor = cp;
144
145    return CC_REFRESH;
146}
147
148
149/* em_kill_line():
150 *	Cut the entire line and save in cut buffer
151 *	[^U]
152 */
153protected el_action_t
154/*ARGSUSED*/
155em_kill_line(el, c)
156    EditLine *el;
157    int c;
158{
159    char *kp, *cp;
160
161    cp = el->el_line.buffer;
162    kp = el->el_chared.c_kill.buf;
163    while (cp < el->el_line.lastchar)
164	*kp++ = *cp++;		/* copy it */
165    el->el_chared.c_kill.last = kp;
166    el->el_line.lastchar = el->el_line.buffer;	/* zap! -- delete all of it */
167    el->el_line.cursor = el->el_line.buffer;
168    return CC_REFRESH;
169}
170
171
172/* em_kill_region():
173 *	Cut area between mark and cursor and save in cut buffer
174 *	[^W]
175 */
176protected el_action_t
177/*ARGSUSED*/
178em_kill_region(el, c)
179    EditLine *el;
180    int c;
181{
182    char *kp, *cp;
183
184    if (!el->el_chared.c_kill.mark)
185	return CC_ERROR;
186
187    if (el->el_chared.c_kill.mark > el->el_line.cursor) {
188	cp = el->el_line.cursor;
189	kp = el->el_chared.c_kill.buf;
190	while (cp < el->el_chared.c_kill.mark)
191	    *kp++ = *cp++;	/* copy it */
192	el->el_chared.c_kill.last = kp;
193	c_delafter(el, cp - el->el_line.cursor);
194    }
195    else {			/* mark is before cursor */
196	cp = el->el_chared.c_kill.mark;
197	kp = el->el_chared.c_kill.buf;
198	while (cp < el->el_line.cursor)
199	    *kp++ = *cp++;	/* copy it */
200	el->el_chared.c_kill.last = kp;
201	c_delbefore(el, cp - el->el_chared.c_kill.mark);
202	el->el_line.cursor = el->el_chared.c_kill.mark;
203    }
204    return CC_REFRESH;
205}
206
207
208/* em_copy_region():
209 *	Copy area between mark and cursor to cut buffer
210 *	[M-W]
211 */
212protected el_action_t
213/*ARGSUSED*/
214em_copy_region(el, c)
215    EditLine *el;
216    int c;
217{
218    char *kp, *cp;
219
220    if (el->el_chared.c_kill.mark)
221	return CC_ERROR;
222
223    if (el->el_chared.c_kill.mark > el->el_line.cursor) {
224	cp = el->el_line.cursor;
225	kp = el->el_chared.c_kill.buf;
226	while (cp < el->el_chared.c_kill.mark)
227	    *kp++ = *cp++;	/* copy it */
228	el->el_chared.c_kill.last = kp;
229    }
230    else {
231	cp = el->el_chared.c_kill.mark;
232	kp = el->el_chared.c_kill.buf;
233	while (cp < el->el_line.cursor)
234	    *kp++ = *cp++;	/* copy it */
235	el->el_chared.c_kill.last = kp;
236    }
237    return CC_NORM;
238}
239
240
241/* em_gosmacs_traspose():
242 *	Exchange the two characters before the cursor
243 *	Gosling emacs transpose chars [^T]
244 */
245protected el_action_t
246em_gosmacs_traspose(el, c)
247    EditLine *el;
248    int c;
249{
250
251    if (el->el_line.cursor > &el->el_line.buffer[1]) {
252   	/* must have at least two chars entered */
253	c = el->el_line.cursor[-2];
254	el->el_line.cursor[-2] = el->el_line.cursor[-1];
255	el->el_line.cursor[-1] = c;
256	return CC_REFRESH;
257    }
258    else
259	return CC_ERROR;
260}
261
262
263/* em_next_word():
264 *	Move next to end of current word
265 *	[M-f]
266 */
267protected el_action_t
268/*ARGSUSED*/
269em_next_word(el, c)
270    EditLine *el;
271    int c;
272{
273    if (el->el_line.cursor == el->el_line.lastchar)
274	return CC_ERROR;
275
276    el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
277				      el->el_state.argument,
278				      ce__isword);
279
280    if (el->el_map.type == MAP_VI)
281	if (el->el_chared.c_vcmd.action & DELETE) {
282	    cv_delfini(el);
283	    return CC_REFRESH;
284	}
285
286    return CC_CURSOR;
287}
288
289/* em_upper_case():
290 *	Uppercase the characters from cursor to end of current word
291 *	[M-u]
292 */
293protected el_action_t
294/*ARGSUSED*/
295em_upper_case(el, c)
296    EditLine *el;
297    int c;
298{
299    char   *cp, *ep;
300
301    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
302		      el->el_state.argument, ce__isword);
303
304    for (cp = el->el_line.cursor; cp < ep; cp++)
305	if (islower(*cp))
306	    *cp = toupper(*cp);
307
308    el->el_line.cursor = ep;
309    if (el->el_line.cursor > el->el_line.lastchar)
310	el->el_line.cursor = el->el_line.lastchar;
311    return CC_REFRESH;
312}
313
314
315/* em_capitol_case():
316 *	Capitalize the characters from cursor to end of current word
317 *	[M-c]
318 */
319protected el_action_t
320/*ARGSUSED*/
321em_capitol_case(el, c)
322    EditLine *el;
323    int c;
324{
325    char   *cp, *ep;
326
327    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
328		      el->el_state.argument, ce__isword);
329
330    for (cp = el->el_line.cursor; cp < ep; cp++) {
331	if (isalpha(*cp)) {
332	    if (islower(*cp))
333		*cp = toupper(*cp);
334	    cp++;
335	    break;
336	}
337    }
338    for (; cp < ep; cp++)
339	if (isupper(*cp))
340	    *cp = tolower(*cp);
341
342    el->el_line.cursor = ep;
343    if (el->el_line.cursor > el->el_line.lastchar)
344	el->el_line.cursor = el->el_line.lastchar;
345    return CC_REFRESH;
346}
347
348/* em_lower_case():
349 *	Lowercase the characters from cursor to end of current word
350 *	[M-l]
351 */
352protected el_action_t
353/*ARGSUSED*/
354em_lower_case(el, c)
355    EditLine *el;
356    int c;
357{
358    char   *cp, *ep;
359
360    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
361		      el->el_state.argument, ce__isword);
362
363    for (cp = el->el_line.cursor; cp < ep; cp++)
364	if (isupper(*cp))
365	    *cp = tolower(*cp);
366
367    el->el_line.cursor = ep;
368    if (el->el_line.cursor > el->el_line.lastchar)
369	el->el_line.cursor = el->el_line.lastchar;
370    return CC_REFRESH;
371}
372
373
374/* em_set_mark():
375 *	Set the mark at cursor
376 *	[^@]
377 */
378protected el_action_t
379/*ARGSUSED*/
380em_set_mark(el, c)
381    EditLine *el;
382    int c;
383{
384    el->el_chared.c_kill.mark = el->el_line.cursor;
385    return CC_NORM;
386}
387
388
389/* em_exchange_mark():
390 *	Exchange the cursor and mark
391 *	[^X^X]
392 */
393protected el_action_t
394/*ARGSUSED*/
395em_exchange_mark(el, c)
396    EditLine *el;
397    int c;
398{
399    register char *cp;
400
401    cp = el->el_line.cursor;
402    el->el_line.cursor = el->el_chared.c_kill.mark;
403    el->el_chared.c_kill.mark = cp;
404    return CC_CURSOR;
405}
406
407/* em_universal_argument():
408 *	Universal argument (argument times 4)
409 *	[^U]
410 */
411protected el_action_t
412/*ARGSUSED*/
413em_universal_argument(el, c)
414    EditLine *el;
415    int c;
416{				/* multiply current argument by 4 */
417    if (el->el_state.argument > 1000000)
418	return CC_ERROR;
419    el->el_state.doingarg = 1;
420    el->el_state.argument *= 4;
421    return CC_ARGHACK;
422}
423
424/* em_meta_next():
425 *	Add 8th bit to next character typed
426 *	[<ESC>]
427 */
428protected el_action_t
429/*ARGSUSED*/
430em_meta_next(el, c)
431    EditLine *el;
432    int c;
433{
434    el->el_state.metanext = 1;
435    return CC_ARGHACK;
436}
437
438
439/* em_toggle_overwrite():
440 *	Switch from insert to overwrite mode or vice versa
441 */
442protected el_action_t
443/*ARGSUSED*/
444em_toggle_overwrite(el, c)
445    EditLine *el;
446    int c;
447{
448    el->el_state.inputmode =
449	(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
450    return CC_NORM;
451}
452
453
454/* em_copy_prev_word():
455 *	Copy current word to cursor
456 */
457protected el_action_t
458/*ARGSUSED*/
459em_copy_prev_word(el, c)
460    EditLine *el;
461    int c;
462{
463    char *cp, *oldc, *dp;
464
465    if (el->el_line.cursor == el->el_line.buffer)
466	return CC_ERROR;
467
468    oldc = el->el_line.cursor;
469    /* does a bounds check */
470    cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
471		      el->el_state.argument, ce__isword);
472
473    c_insert(el, oldc - cp);
474    for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
475	*dp++ = *cp;
476
477    el->el_line.cursor = dp;		/* put cursor at end */
478
479    return CC_REFRESH;
480}
481
482
483/* em_inc_search_next():
484 *	Emacs incremental next search
485 */
486protected el_action_t
487/*ARGSUSED*/
488em_inc_search_next(el, c)
489    EditLine *el;
490    int c;
491{
492    el->el_search.patlen = 0;
493    return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
494}
495
496
497/* em_inc_search_prev():
498 *	Emacs incremental reverse search
499 */
500protected el_action_t
501/*ARGSUSED*/
502em_inc_search_prev(el, c)
503    EditLine *el;
504    int c;
505{
506    el->el_search.patlen = 0;
507    return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
508}
509