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