1 /* $OpenBSD: common.c,v 1.23 2023/03/08 04:43:05 guenther Exp $ */
2 /* $NetBSD: common.c,v 1.24 2009/12/30 22:37:40 christos Exp $ */
3
4 /*-
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Christos Zoulas of Cornell University.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include "config.h"
37
38 /*
39 * common.c: Common Editor functions
40 */
41 #include <ctype.h>
42 #include <string.h>
43
44 #include "el.h"
45 #include "common.h"
46 #include "fcns.h"
47 #include "parse.h"
48 #include "vi.h"
49
50 /* ed_end_of_file():
51 * Indicate end of file
52 * [^D]
53 */
54 protected el_action_t
ed_end_of_file(EditLine * el,wint_t c)55 ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
56 {
57
58 re_goto_bottom(el);
59 *el->el_line.lastchar = '\0';
60 return CC_EOF;
61 }
62
63
64 /* ed_insert():
65 * Add character to the line
66 * Insert a character [bound to all insert keys]
67 */
68 protected el_action_t
ed_insert(EditLine * el,wint_t c)69 ed_insert(EditLine *el, wint_t c)
70 {
71 int count = el->el_state.argument;
72
73 if (c == '\0')
74 return CC_ERROR;
75
76 if (el->el_line.lastchar + el->el_state.argument >=
77 el->el_line.limit) {
78 /* end of buffer space, try to allocate more */
79 if (!ch_enlargebufs(el, (size_t) count))
80 return CC_ERROR; /* error allocating more */
81 }
82
83 if (count == 1) {
84 if (el->el_state.inputmode == MODE_INSERT
85 || el->el_line.cursor >= el->el_line.lastchar)
86 c_insert(el, 1);
87
88 *el->el_line.cursor++ = c;
89 re_fastaddc(el); /* fast refresh for one char. */
90 } else {
91 if (el->el_state.inputmode != MODE_REPLACE_1)
92 c_insert(el, el->el_state.argument);
93
94 while (count-- && el->el_line.cursor < el->el_line.lastchar)
95 *el->el_line.cursor++ = c;
96 re_refresh(el);
97 }
98
99 if (el->el_state.inputmode == MODE_REPLACE_1)
100 return vi_command_mode(el, 0);
101
102 return CC_NORM;
103 }
104
105
106 /* ed_delete_prev_word():
107 * Delete from beginning of current word to cursor
108 * [M-^?] [^W]
109 */
110 protected el_action_t
ed_delete_prev_word(EditLine * el,wint_t c)111 ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
112 {
113 wchar_t *cp, *p, *kp;
114
115 if (el->el_line.cursor == el->el_line.buffer)
116 return CC_ERROR;
117
118 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
119 el->el_state.argument, ce__isword);
120
121 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
122 *kp++ = *p;
123 el->el_chared.c_kill.last = kp;
124
125 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
126 el->el_line.cursor = cp;
127 if (el->el_line.cursor < el->el_line.buffer)
128 el->el_line.cursor = el->el_line.buffer; /* bounds check */
129 return CC_REFRESH;
130 }
131
132
133 /* ed_delete_next_char():
134 * Delete character under cursor
135 * [^D] [x]
136 */
137 protected el_action_t
ed_delete_next_char(EditLine * el,wint_t c)138 ed_delete_next_char(EditLine *el, wint_t c)
139 {
140 #ifdef notdef /* XXX */
141 #define EL el->el_line
142 (void) fprintf(el->el_errfile,
143 "\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
144 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
145 EL.lastchar, EL.limit, EL.limit);
146 #endif
147 if (el->el_line.cursor == el->el_line.lastchar) {
148 /* if I'm at the end */
149 if (el->el_map.type == MAP_VI) {
150 if (el->el_line.cursor == el->el_line.buffer) {
151 /* if I'm also at the beginning */
152 #ifdef KSHVI
153 return CC_ERROR;
154 #else
155 /* then do an EOF */
156 terminal_writec(el, c);
157 return CC_EOF;
158 #endif
159 } else {
160 #ifdef KSHVI
161 el->el_line.cursor--;
162 #else
163 return CC_ERROR;
164 #endif
165 }
166 } else {
167 if (el->el_line.cursor != el->el_line.buffer)
168 el->el_line.cursor--;
169 else
170 return CC_ERROR;
171 }
172 }
173 c_delafter(el, el->el_state.argument); /* delete after dot */
174 if (el->el_line.cursor >= el->el_line.lastchar &&
175 el->el_line.cursor > el->el_line.buffer)
176 /* bounds check */
177 el->el_line.cursor = el->el_line.lastchar - 1;
178 return CC_REFRESH;
179 }
180
181
182 /* ed_kill_line():
183 * Cut to the end of line
184 * [^K] [^K]
185 */
186 protected el_action_t
ed_kill_line(EditLine * el,wint_t c)187 ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
188 {
189 wchar_t *kp, *cp;
190
191 cp = el->el_line.cursor;
192 kp = el->el_chared.c_kill.buf;
193 while (cp < el->el_line.lastchar)
194 *kp++ = *cp++; /* copy it */
195 el->el_chared.c_kill.last = kp;
196 /* zap! -- delete to end */
197 el->el_line.lastchar = el->el_line.cursor;
198 return CC_REFRESH;
199 }
200
201
202 /* ed_move_to_end():
203 * Move cursor to the end of line
204 * [^E] [^E]
205 */
206 protected el_action_t
ed_move_to_end(EditLine * el,wint_t c)207 ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
208 {
209
210 el->el_line.cursor = el->el_line.lastchar;
211 if (el->el_map.type == MAP_VI) {
212 if (el->el_chared.c_vcmd.action != NOP) {
213 cv_delfini(el);
214 return CC_REFRESH;
215 }
216 #ifdef VI_MOVE
217 el->el_line.cursor--;
218 #endif
219 }
220 return CC_CURSOR;
221 }
222
223
224 /* ed_move_to_beg():
225 * Move cursor to the beginning of line
226 * [^A] [^A]
227 */
228 protected el_action_t
ed_move_to_beg(EditLine * el,wint_t c)229 ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
230 {
231
232 el->el_line.cursor = el->el_line.buffer;
233
234 if (el->el_map.type == MAP_VI) {
235 /* We want FIRST non space character */
236 while (iswspace(*el->el_line.cursor))
237 el->el_line.cursor++;
238 if (el->el_chared.c_vcmd.action != NOP) {
239 cv_delfini(el);
240 return CC_REFRESH;
241 }
242 }
243 return CC_CURSOR;
244 }
245
246
247 /* ed_transpose_chars():
248 * Exchange the character to the left of the cursor with the one under it
249 * [^T] [^T]
250 */
251 protected el_action_t
ed_transpose_chars(EditLine * el,wint_t c)252 ed_transpose_chars(EditLine *el, wint_t c)
253 {
254
255 if (el->el_line.cursor < el->el_line.lastchar) {
256 if (el->el_line.lastchar <= &el->el_line.buffer[1])
257 return CC_ERROR;
258 else
259 el->el_line.cursor++;
260 }
261 if (el->el_line.cursor > &el->el_line.buffer[1]) {
262 /* must have at least two chars entered */
263 c = el->el_line.cursor[-2];
264 el->el_line.cursor[-2] = el->el_line.cursor[-1];
265 el->el_line.cursor[-1] = c;
266 return CC_REFRESH;
267 } else
268 return CC_ERROR;
269 }
270
271
272 /* ed_next_char():
273 * Move to the right one character
274 * [^F] [^F]
275 */
276 protected el_action_t
ed_next_char(EditLine * el,wint_t c)277 ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
278 {
279 wchar_t *lim = el->el_line.lastchar;
280
281 if (el->el_line.cursor >= lim ||
282 (el->el_line.cursor == lim - 1 &&
283 el->el_map.type == MAP_VI &&
284 el->el_chared.c_vcmd.action == NOP))
285 return CC_ERROR;
286
287 el->el_line.cursor += el->el_state.argument;
288 if (el->el_line.cursor > lim)
289 el->el_line.cursor = lim;
290
291 if (el->el_map.type == MAP_VI)
292 if (el->el_chared.c_vcmd.action != NOP) {
293 cv_delfini(el);
294 return CC_REFRESH;
295 }
296 return CC_CURSOR;
297 }
298
299
300 /* ed_prev_word():
301 * Move to the beginning of the current word
302 * [M-b] [b]
303 */
304 protected el_action_t
ed_prev_word(EditLine * el,wint_t c)305 ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
306 {
307
308 if (el->el_line.cursor == el->el_line.buffer)
309 return CC_ERROR;
310
311 el->el_line.cursor = c__prev_word(el->el_line.cursor,
312 el->el_line.buffer,
313 el->el_state.argument,
314 ce__isword);
315
316 if (el->el_map.type == MAP_VI)
317 if (el->el_chared.c_vcmd.action != NOP) {
318 cv_delfini(el);
319 return CC_REFRESH;
320 }
321 return CC_CURSOR;
322 }
323
324
325 /* ed_prev_char():
326 * Move to the left one character
327 * [^B] [^B]
328 */
329 protected el_action_t
ed_prev_char(EditLine * el,wint_t c)330 ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
331 {
332
333 if (el->el_line.cursor > el->el_line.buffer) {
334 el->el_line.cursor -= el->el_state.argument;
335 if (el->el_line.cursor < el->el_line.buffer)
336 el->el_line.cursor = el->el_line.buffer;
337
338 if (el->el_map.type == MAP_VI)
339 if (el->el_chared.c_vcmd.action != NOP) {
340 cv_delfini(el);
341 return CC_REFRESH;
342 }
343 return CC_CURSOR;
344 } else
345 return CC_ERROR;
346 }
347
348
349 /* ed_quoted_insert():
350 * Add the next character typed verbatim
351 * [^V] [^V]
352 */
353 protected el_action_t
ed_quoted_insert(EditLine * el,wint_t c)354 ed_quoted_insert(EditLine *el, wint_t c)
355 {
356 int num;
357
358 tty_quotemode(el);
359 num = el_wgetc(el, &c);
360 tty_noquotemode(el);
361 if (num == 1)
362 return ed_insert(el, c);
363 else
364 return ed_end_of_file(el, 0);
365 }
366
367
368 /* ed_digit():
369 * Adds to argument or enters a digit
370 */
371 protected el_action_t
ed_digit(EditLine * el,wint_t c)372 ed_digit(EditLine *el, wint_t c)
373 {
374
375 if (!iswdigit(c))
376 return CC_ERROR;
377
378 if (el->el_state.doingarg) {
379 /* if doing an arg, add this in... */
380 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
381 el->el_state.argument = c - '0';
382 else {
383 if (el->el_state.argument > 1000000)
384 return CC_ERROR;
385 el->el_state.argument =
386 (el->el_state.argument * 10) + (c - '0');
387 }
388 return CC_ARGHACK;
389 }
390
391 return ed_insert(el, c);
392 }
393
394
395 /* ed_argument_digit():
396 * Digit that starts argument
397 * For ESC-n
398 */
399 protected el_action_t
ed_argument_digit(EditLine * el,wint_t c)400 ed_argument_digit(EditLine *el, wint_t c)
401 {
402
403 if (!iswdigit(c))
404 return CC_ERROR;
405
406 if (el->el_state.doingarg) {
407 if (el->el_state.argument > 1000000)
408 return CC_ERROR;
409 el->el_state.argument = (el->el_state.argument * 10) +
410 (c - '0');
411 } else { /* else starting an argument */
412 el->el_state.argument = c - '0';
413 el->el_state.doingarg = 1;
414 }
415 return CC_ARGHACK;
416 }
417
418
419 /* ed_unassigned():
420 * Indicates unbound character
421 * Bound to keys that are not assigned
422 */
423 protected el_action_t
ed_unassigned(EditLine * el,wint_t c)424 ed_unassigned(EditLine *el, wint_t c __attribute__((__unused__)))
425 {
426
427 return CC_ERROR;
428 }
429
430
431 /* ed_ignore():
432 * Input characters that have no effect
433 * [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
434 */
435 protected el_action_t
ed_ignore(EditLine * el,wint_t c)436 ed_ignore(EditLine *el __attribute__((__unused__)),
437 wint_t c __attribute__((__unused__)))
438 {
439
440 return CC_NORM;
441 }
442
443
444 /* ed_newline():
445 * Execute command
446 * [^J]
447 */
448 protected el_action_t
ed_newline(EditLine * el,wint_t c)449 ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
450 {
451
452 re_goto_bottom(el);
453 *el->el_line.lastchar++ = '\n';
454 *el->el_line.lastchar = '\0';
455 return CC_NEWLINE;
456 }
457
458
459 /* ed_delete_prev_char():
460 * Delete the character to the left of the cursor
461 * [^?]
462 */
463 protected el_action_t
ed_delete_prev_char(EditLine * el,wint_t c)464 ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
465 {
466
467 if (el->el_line.cursor <= el->el_line.buffer)
468 return CC_ERROR;
469
470 c_delbefore(el, el->el_state.argument);
471 el->el_line.cursor -= el->el_state.argument;
472 if (el->el_line.cursor < el->el_line.buffer)
473 el->el_line.cursor = el->el_line.buffer;
474 return CC_REFRESH;
475 }
476
477
478 /* ed_clear_screen():
479 * Clear screen leaving current line at the top
480 * [^L]
481 */
482 protected el_action_t
ed_clear_screen(EditLine * el,wint_t c)483 ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
484 {
485
486 terminal_clear_screen(el); /* clear the whole real screen */
487 re_clear_display(el); /* reset everything */
488 return CC_REFRESH;
489 }
490
491
492 /* ed_redisplay():
493 * Redisplay everything
494 * ^R
495 */
496 protected el_action_t
ed_redisplay(EditLine * el,wint_t c)497 ed_redisplay(EditLine *el __attribute__((__unused__)),
498 wint_t c __attribute__((__unused__)))
499 {
500
501 return CC_REDISPLAY;
502 }
503
504
505 /* ed_start_over():
506 * Erase current line and start from scratch
507 * [^G]
508 */
509 protected el_action_t
ed_start_over(EditLine * el,wint_t c)510 ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
511 {
512
513 ch_reset(el);
514 return CC_REFRESH;
515 }
516
517
518 /* ed_sequence_lead_in():
519 * First character in a bound sequence
520 * Placeholder for external keys
521 */
522 protected el_action_t
ed_sequence_lead_in(EditLine * el,wint_t c)523 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
524 wint_t c __attribute__((__unused__)))
525 {
526
527 return CC_NORM;
528 }
529
530
531 /* ed_prev_history():
532 * Move to the previous history line
533 * [^P] [k]
534 */
535 protected el_action_t
ed_prev_history(EditLine * el,wint_t c)536 ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
537 {
538 char beep = 0;
539 int sv_event = el->el_history.eventno;
540
541 el->el_chared.c_undo.len = -1;
542 *el->el_line.lastchar = '\0'; /* just in case */
543
544 if (el->el_history.eventno == 0) { /* save the current buffer
545 * away */
546 (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
547 EL_BUFSIZ);
548 el->el_history.last = el->el_history.buf +
549 (el->el_line.lastchar - el->el_line.buffer);
550 }
551 el->el_history.eventno += el->el_state.argument;
552
553 if (hist_get(el) == CC_ERROR) {
554 if (el->el_map.type == MAP_VI) {
555 el->el_history.eventno = sv_event;
556 }
557 beep = 1;
558 /* el->el_history.eventno was fixed by first call */
559 (void) hist_get(el);
560 }
561 if (beep)
562 return CC_REFRESH_BEEP;
563 return CC_REFRESH;
564 }
565
566
567 /* ed_next_history():
568 * Move to the next history line
569 * [^N] [j]
570 */
571 protected el_action_t
ed_next_history(EditLine * el,wint_t c)572 ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
573 {
574 el_action_t beep = CC_REFRESH, rval;
575
576 el->el_chared.c_undo.len = -1;
577 *el->el_line.lastchar = '\0'; /* just in case */
578
579 el->el_history.eventno -= el->el_state.argument;
580
581 if (el->el_history.eventno < 0) {
582 el->el_history.eventno = 0;
583 beep = CC_REFRESH_BEEP;
584 }
585 rval = hist_get(el);
586 if (rval == CC_REFRESH)
587 return beep;
588 return rval;
589
590 }
591
592
593 /* ed_search_prev_history():
594 * Search previous in history for a line matching the current
595 * next search history [M-P] [K]
596 */
597 protected el_action_t
ed_search_prev_history(EditLine * el,wint_t c)598 ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
599 {
600 const wchar_t *hp;
601 int h;
602 int found = 0;
603
604 el->el_chared.c_vcmd.action = NOP;
605 el->el_chared.c_undo.len = -1;
606 *el->el_line.lastchar = '\0'; /* just in case */
607 if (el->el_history.eventno < 0) {
608 #ifdef DEBUG_EDIT
609 (void) fprintf(el->el_errfile,
610 "e_prev_search_hist(): eventno < 0;\n");
611 #endif
612 el->el_history.eventno = 0;
613 return CC_ERROR;
614 }
615 if (el->el_history.eventno == 0) {
616 (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
617 EL_BUFSIZ);
618 el->el_history.last = el->el_history.buf +
619 (el->el_line.lastchar - el->el_line.buffer);
620 }
621 if (el->el_history.ref == NULL)
622 return CC_ERROR;
623
624 hp = HIST_FIRST(el);
625 if (hp == NULL)
626 return CC_ERROR;
627
628 c_setpat(el); /* Set search pattern !! */
629
630 for (h = 1; h <= el->el_history.eventno; h++)
631 hp = HIST_NEXT(el);
632
633 while (hp != NULL) {
634 #ifdef SDEBUG
635 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
636 #endif
637 if ((wcsncmp(hp, el->el_line.buffer, (size_t)
638 (el->el_line.lastchar - el->el_line.buffer)) ||
639 hp[el->el_line.lastchar - el->el_line.buffer]) &&
640 c_hmatch(el, hp)) {
641 found = 1;
642 break;
643 }
644 h++;
645 hp = HIST_NEXT(el);
646 }
647
648 if (!found) {
649 #ifdef SDEBUG
650 (void) fprintf(el->el_errfile, "not found\n");
651 #endif
652 return CC_ERROR;
653 }
654 el->el_history.eventno = h;
655
656 return hist_get(el);
657 }
658
659
660 /* ed_search_next_history():
661 * Search next in history for a line matching the current
662 * [M-N] [J]
663 */
664 protected el_action_t
ed_search_next_history(EditLine * el,wint_t c)665 ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
666 {
667 const wchar_t *hp;
668 int h;
669 int found = 0;
670
671 el->el_chared.c_vcmd.action = NOP;
672 el->el_chared.c_undo.len = -1;
673 *el->el_line.lastchar = '\0'; /* just in case */
674
675 if (el->el_history.eventno == 0)
676 return CC_ERROR;
677
678 if (el->el_history.ref == NULL)
679 return CC_ERROR;
680
681 hp = HIST_FIRST(el);
682 if (hp == NULL)
683 return CC_ERROR;
684
685 c_setpat(el); /* Set search pattern !! */
686
687 for (h = 1; h < el->el_history.eventno && hp; h++) {
688 #ifdef SDEBUG
689 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
690 #endif
691 if ((wcsncmp(hp, el->el_line.buffer, (size_t)
692 (el->el_line.lastchar - el->el_line.buffer)) ||
693 hp[el->el_line.lastchar - el->el_line.buffer]) &&
694 c_hmatch(el, hp))
695 found = h;
696 hp = HIST_NEXT(el);
697 }
698
699 if (!found) { /* is it the current history number? */
700 if (!c_hmatch(el, el->el_history.buf)) {
701 #ifdef SDEBUG
702 (void) fprintf(el->el_errfile, "not found\n");
703 #endif
704 return CC_ERROR;
705 }
706 }
707 el->el_history.eventno = found;
708
709 return hist_get(el);
710 }
711
712
713 /* ed_prev_line():
714 * Move up one line
715 * Could be [k] [^p]
716 */
717 protected el_action_t
ed_prev_line(EditLine * el,wint_t c)718 ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
719 {
720 wchar_t *ptr;
721 int nchars = c_hpos(el);
722
723 /*
724 * Move to the line requested
725 */
726 if (*(ptr = el->el_line.cursor) == '\n')
727 ptr--;
728
729 for (; ptr >= el->el_line.buffer; ptr--)
730 if (*ptr == '\n' && --el->el_state.argument <= 0)
731 break;
732
733 if (el->el_state.argument > 0)
734 return CC_ERROR;
735
736 /*
737 * Move to the beginning of the line
738 */
739 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
740 continue;
741
742 /*
743 * Move to the character requested
744 */
745 for (ptr++;
746 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
747 ptr++)
748 continue;
749
750 el->el_line.cursor = ptr;
751 return CC_CURSOR;
752 }
753
754
755 /* ed_next_line():
756 * Move down one line
757 * Could be [j] [^n]
758 */
759 protected el_action_t
ed_next_line(EditLine * el,wint_t c)760 ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
761 {
762 wchar_t *ptr;
763 int nchars = c_hpos(el);
764
765 /*
766 * Move to the line requested
767 */
768 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
769 if (*ptr == '\n' && --el->el_state.argument <= 0)
770 break;
771
772 if (el->el_state.argument > 0)
773 return CC_ERROR;
774
775 /*
776 * Move to the character requested
777 */
778 for (ptr++;
779 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
780 ptr++)
781 continue;
782
783 el->el_line.cursor = ptr;
784 return CC_CURSOR;
785 }
786
787
788 /* ed_command():
789 * Editline extended command
790 * [M-X] [:]
791 */
792 protected el_action_t
ed_command(EditLine * el,wint_t c)793 ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
794 {
795 wchar_t tmpbuf[EL_BUFSIZ];
796 int tmplen;
797
798 tmplen = c_gets(el, tmpbuf, L"\n: ");
799 terminal__putc(el, '\n');
800
801 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
802 terminal_beep(el);
803
804 el->el_map.current = el->el_map.key;
805 re_clear_display(el);
806 return CC_REFRESH;
807 }
808