Commit | Line | Data |
---|---|---|
1de8a231 KB |
1 | /*- |
2 | * Copyright (c) 1992 The Regents of the University of California. | |
3 | * 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 | ||
b6dd18ed CZ |
11 | #if !defined(lint) && !defined(SCCSID) |
12 | static char sccsid[] = "@(#)emacs.c 5.2 (Berkeley) %G%"; | |
13 | #endif /* not lint && not SCCSID */ | |
1de8a231 KB |
14 | |
15 | /* | |
b6dd18ed | 16 | * emacs.c: Emacs functions |
1de8a231 KB |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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 | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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*/ | |
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 | } |