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[] = "@(#)common.c 8.1 (Berkeley) 06/04/93";
13 #endif /* not lint && not SCCSID */
14
15 /*
16 * common.c: Common Editor functions
17 */
18 #include "sys.h"
19 #include "el.h"
20
21 /* ed_end_of_file():
22 * Indicate end of file
23 * [^D]
24 */
25 protected el_action_t
26 /*ARGSUSED*/
ed_end_of_file(el,c)27 ed_end_of_file(el, c)
28 EditLine *el;
29 int c;
30 {
31 re_goto_bottom(el);
32 *el->el_line.lastchar = '\0';
33 return CC_EOF;
34 }
35
36
37 /* ed_insert():
38 * Add character to the line
39 * Insert a character [bound to all insert keys]
40 */
41 protected el_action_t
ed_insert(el,c)42 ed_insert(el, c)
43 EditLine *el;
44 int c;
45 {
46 int i;
47
48 if (c == '\0')
49 return CC_ERROR;
50
51 if (el->el_line.lastchar + el->el_state.argument >=
52 el->el_line.limit)
53 return CC_ERROR; /* end of buffer space */
54
55 if (el->el_state.argument == 1) {
56 if (el->el_state.inputmode != MODE_INSERT) {
57 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
58 *el->el_line.cursor;
59 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
60 c_delafter(el, 1);
61 }
62
63 c_insert(el, 1);
64
65 *el->el_line.cursor++ = c;
66 el->el_state.doingarg = 0; /* just in case */
67 re_fastaddc(el); /* fast refresh for one char. */
68 }
69 else {
70 if (el->el_state.inputmode != MODE_INSERT) {
71
72 for(i = 0;i < el->el_state.argument; i++)
73 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
74 el->el_line.cursor[i];
75
76 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
77 c_delafter(el, el->el_state.argument);
78 }
79
80 c_insert(el, el->el_state.argument);
81
82 while (el->el_state.argument--)
83 *el->el_line.cursor++ = c;
84 re_refresh(el);
85 }
86
87 if (el->el_state.inputmode == MODE_REPLACE_1)
88 (void) vi_command_mode(el, 0);
89
90 return CC_NORM;
91 }
92
93
94 /* ed_delete_prev_word():
95 * Delete from beginning of current word to cursor
96 * [M-^?] [^W]
97 */
98 protected el_action_t
99 /*ARGSUSED*/
ed_delete_prev_word(el,c)100 ed_delete_prev_word(el, c)
101 EditLine *el;
102 int c;
103 {
104 char *cp, *p, *kp;
105
106 if (el->el_line.cursor == el->el_line.buffer)
107 return CC_ERROR;
108
109 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
110 el->el_state.argument, ce__isword);
111
112 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
113 *kp++ = *p;
114 el->el_chared.c_kill.last = kp;
115
116 c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
117 el->el_line.cursor = cp;
118 if (el->el_line.cursor < el->el_line.buffer)
119 el->el_line.cursor = el->el_line.buffer; /* bounds check */
120 return CC_REFRESH;
121 }
122
123
124 /* ed_delete_next_char():
125 * Delete character under cursor
126 * [^D] [x]
127 */
128 protected el_action_t
129 /*ARGSUSED*/
ed_delete_next_char(el,c)130 ed_delete_next_char(el, c)
131 EditLine *el;
132 int c;
133 {
134 #ifdef notdef /* XXX */
135 #define EL el->el_line
136 fprintf(stderr, "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
137 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
138 #endif
139 if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
140 if (el->el_map.type == MAP_VI) {
141 if (el->el_line.cursor == el->el_line.buffer) {
142 /* if I'm also at the beginning */
143 #ifdef KSHVI
144 return CC_ERROR;
145 #else
146 term_overwrite(el, STReof, 4);/* then do a EOF */
147 term__flush();
148 return CC_EOF;
149 #endif
150 }
151 else {
152 #ifdef KSHVI
153 el->el_line.cursor--;
154 #else
155 return CC_ERROR;
156 #endif
157 }
158 }
159 else {
160 if (el->el_line.cursor != el->el_line.buffer)
161 el->el_line.cursor--;
162 else
163 return CC_ERROR;
164 }
165 }
166 c_delafter(el, el->el_state.argument); /* delete after dot */
167 if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
168 el->el_line.cursor = el->el_line.lastchar - 1; /* bounds check */
169 return CC_REFRESH;
170 }
171
172
173 /* ed_kill_line():
174 * Cut to the end of line
175 * [^K] [^K]
176 */
177 protected el_action_t
178 /*ARGSUSED*/
ed_kill_line(el,c)179 ed_kill_line(el, c)
180 EditLine *el;
181 int c;
182 {
183 char *kp, *cp;
184
185 cp = el->el_line.cursor;
186 kp = el->el_chared.c_kill.buf;
187 while (cp < el->el_line.lastchar)
188 *kp++ = *cp++; /* copy it */
189 el->el_chared.c_kill.last = kp;
190 el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
191 return CC_REFRESH;
192 }
193
194
195 /* ed_move_to_end():
196 * Move cursor to the end of line
197 * [^E] [^E]
198 */
199 protected el_action_t
200 /*ARGSUSED*/
ed_move_to_end(el,c)201 ed_move_to_end(el, c)
202 EditLine *el;
203 int c;
204 {
205 el->el_line.cursor = el->el_line.lastchar;
206 if (el->el_map.type == MAP_VI) {
207 #ifdef VI_MOVE
208 el->el_line.cursor--;
209 #endif
210 if (el->el_chared.c_vcmd.action & DELETE) {
211 cv_delfini(el);
212 return CC_REFRESH;
213 }
214 }
215 return CC_CURSOR;
216 }
217
218
219 /* ed_move_to_beg():
220 * Move cursor to the beginning of line
221 * [^A] [^A]
222 */
223 protected el_action_t
224 /*ARGSUSED*/
ed_move_to_beg(el,c)225 ed_move_to_beg(el, c)
226 EditLine *el;
227 int c;
228 {
229 el->el_line.cursor = el->el_line.buffer;
230
231 if (el->el_map.type == MAP_VI) {
232 /* We want FIRST non space character */
233 while (isspace(*el->el_line.cursor))
234 el->el_line.cursor++;
235 if (el->el_chared.c_vcmd.action & DELETE) {
236 cv_delfini(el);
237 return CC_REFRESH;
238 }
239 }
240
241 return CC_CURSOR;
242 }
243
244
245 /* ed_transpose_chars():
246 * Exchange the character to the left of the cursor with the one under it
247 * [^T] [^T]
248 */
249 protected el_action_t
ed_transpose_chars(el,c)250 ed_transpose_chars(el, c)
251 EditLine *el;
252 int c;
253 {
254 if (el->el_line.cursor < el->el_line.lastchar) {
255 if (el->el_line.lastchar <= &el->el_line.buffer[1])
256 return CC_ERROR;
257 else
258 el->el_line.cursor++;
259 }
260 if (el->el_line.cursor > &el->el_line.buffer[1]) {
261 /* must have at least two chars entered */
262 c = el->el_line.cursor[-2];
263 el->el_line.cursor[-2] = el->el_line.cursor[-1];
264 el->el_line.cursor[-1] = c;
265 return CC_REFRESH;
266 }
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
277 /*ARGSUSED*/
ed_next_char(el,c)278 ed_next_char(el, c)
279 EditLine *el;
280 int c;
281 {
282 if (el->el_line.cursor >= el->el_line.lastchar)
283 return CC_ERROR;
284
285 el->el_line.cursor += el->el_state.argument;
286 if (el->el_line.cursor > el->el_line.lastchar)
287 el->el_line.cursor = el->el_line.lastchar;
288
289 if (el->el_map.type == MAP_VI)
290 if (el->el_chared.c_vcmd.action & DELETE) {
291 cv_delfini(el);
292 return CC_REFRESH;
293 }
294
295 return CC_CURSOR;
296 }
297
298
299 /* ed_prev_word():
300 * Move to the beginning of the current word
301 * [M-b] [b]
302 */
303 protected el_action_t
304 /*ARGSUSED*/
ed_prev_word(el,c)305 ed_prev_word(el, c)
306 EditLine *el;
307 int c;
308 {
309 if (el->el_line.cursor == el->el_line.buffer)
310 return CC_ERROR;
311
312 el->el_line.cursor = c__prev_word(el->el_line.cursor, 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 & DELETE) {
318 cv_delfini(el);
319 return CC_REFRESH;
320 }
321
322 return CC_CURSOR;
323 }
324
325
326 /* ed_prev_char():
327 * Move to the left one character
328 * [^B] [^B]
329 */
330 protected el_action_t
331 /*ARGSUSED*/
ed_prev_char(el,c)332 ed_prev_char(el, c)
333 EditLine *el;
334 int c;
335 {
336 if (el->el_line.cursor > el->el_line.buffer) {
337 el->el_line.cursor -= el->el_state.argument;
338 if (el->el_line.cursor < el->el_line.buffer)
339 el->el_line.cursor = el->el_line.buffer;
340
341 if (el->el_map.type == MAP_VI)
342 if (el->el_chared.c_vcmd.action & DELETE) {
343 cv_delfini(el);
344 return CC_REFRESH;
345 }
346
347 return CC_CURSOR;
348 }
349 else
350 return CC_ERROR;
351 }
352
353
354 /* ed_quoted_insert():
355 * Add the next character typed verbatim
356 * [^V] [^V]
357 */
358 protected el_action_t
ed_quoted_insert(el,c)359 ed_quoted_insert(el, c)
360 EditLine *el;
361 int c;
362 {
363 int num;
364 char tc;
365
366 tty_quotemode(el);
367 num = el_getc(el, &tc);
368 c = (unsigned char) tc;
369 tty_noquotemode(el);
370 if (num == 1)
371 return ed_insert(el, c);
372 else
373 return ed_end_of_file(el, 0);
374 }
375
376
377 /* ed_digit():
378 * Adds to argument or enters a digit
379 */
380 protected el_action_t
ed_digit(el,c)381 ed_digit(el, c)
382 EditLine *el;
383 int c;
384 {
385 if (!isdigit(c))
386 return CC_ERROR;
387
388 if (el->el_state.doingarg) {
389 /* if doing an arg, add this in... */
390 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
391 el->el_state.argument = c - '0';
392 else {
393 if (el->el_state.argument > 1000000)
394 return CC_ERROR;
395 el->el_state.argument =
396 (el->el_state.argument * 10) + (c - '0');
397 }
398 return CC_ARGHACK;
399 }
400 else {
401 if (el->el_line.lastchar + 1 >= el->el_line.limit)
402 return CC_ERROR;
403
404 if (el->el_state.inputmode != MODE_INSERT) {
405 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
406 *el->el_line.cursor;
407 el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
408 c_delafter(el, 1);
409 }
410 c_insert(el, 1);
411 *el->el_line.cursor++ = c;
412 el->el_state.doingarg = 0;
413 re_fastaddc(el);
414 }
415 return CC_NORM;
416 }
417
418
419 /* ed_argument_digit():
420 * Digit that starts argument
421 * For ESC-n
422 */
423 protected el_action_t
ed_argument_digit(el,c)424 ed_argument_digit(el, c)
425 EditLine *el;
426 register int c;
427 {
428 if (!isdigit(c))
429 return CC_ERROR;
430
431 if (el->el_state.doingarg) {
432 if (el->el_state.argument > 1000000)
433 return CC_ERROR;
434 el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
435 }
436 else { /* else starting an argument */
437 el->el_state.argument = c - '0';
438 el->el_state.doingarg = 1;
439 }
440 return CC_ARGHACK;
441 }
442
443
444 /* ed_unassigned():
445 * Indicates unbound character
446 * Bound to keys that are not assigned
447 */
448 protected el_action_t
449 /*ARGSUSED*/
ed_unassigned(el,c)450 ed_unassigned(el, c)
451 EditLine *el;
452 int c;
453 {
454 term_beep(el);
455 term__flush();
456 return CC_NORM;
457 }
458
459
460 /**
461 ** TTY key handling.
462 **/
463
464 /* ed_tty_sigint():
465 * Tty interrupt character
466 * [^C]
467 */
468 protected el_action_t
469 /*ARGSUSED*/
ed_tty_sigint(el,c)470 ed_tty_sigint(el, c)
471 EditLine *el;
472 int c;
473 {
474 return CC_NORM;
475 }
476
477
478 /* ed_tty_dsusp():
479 * Tty delayed suspend character
480 * [^Y]
481 */
482 protected el_action_t
483 /*ARGSUSED*/
ed_tty_dsusp(el,c)484 ed_tty_dsusp(el, c)
485 EditLine *el;
486 int c;
487 {
488 return CC_NORM;
489 }
490
491
492 /* ed_tty_flush_output():
493 * Tty flush output characters
494 * [^O]
495 */
496 protected el_action_t
497 /*ARGSUSED*/
ed_tty_flush_output(el,c)498 ed_tty_flush_output(el, c)
499 EditLine *el;
500 int c;
501 {
502 return CC_NORM;
503 }
504
505
506 /* ed_tty_sigquit():
507 * Tty quit character
508 * [^\]
509 */
510 protected el_action_t
511 /*ARGSUSED*/
ed_tty_sigquit(el,c)512 ed_tty_sigquit(el, c)
513 EditLine *el;
514 int c;
515 {
516 return CC_NORM;
517 }
518
519
520 /* ed_tty_sigtstp():
521 * Tty suspend character
522 * [^Z]
523 */
524 protected el_action_t
525 /*ARGSUSED*/
ed_tty_sigtstp(el,c)526 ed_tty_sigtstp(el, c)
527 EditLine *el;
528 int c;
529 {
530 return CC_NORM;
531 }
532
533
534 /* ed_tty_stop_output():
535 * Tty disallow output characters
536 * [^S]
537 */
538 protected el_action_t
539 /*ARGSUSED*/
ed_tty_stop_output(el,c)540 ed_tty_stop_output(el, c)
541 EditLine *el;
542 int c;
543 {
544 return CC_NORM;
545 }
546
547
548 /* ed_tty_start_output():
549 * Tty allow output characters
550 * [^Q]
551 */
552 protected el_action_t
553 /*ARGSUSED*/
ed_tty_start_output(el,c)554 ed_tty_start_output(el, c)
555 EditLine *el;
556 int c;
557 {
558 return CC_NORM;
559 }
560
561
562 /* ed_newline():
563 * Execute command
564 * [^J]
565 */
566 protected el_action_t
567 /*ARGSUSED*/
ed_newline(el,c)568 ed_newline(el, c)
569 EditLine *el;
570 int c;
571 {
572 re_goto_bottom(el);
573 *el->el_line.lastchar++ = '\n';
574 *el->el_line.lastchar = '\0';
575 if (el->el_map.type == MAP_VI)
576 el->el_chared.c_vcmd.ins = el->el_line.buffer;
577 return CC_NEWLINE;
578 }
579
580
581 /* ed_delete_prev_char():
582 * Delete the character to the left of the cursor
583 * [^?]
584 */
585 protected el_action_t
586 /*ARGSUSED*/
ed_delete_prev_char(el,c)587 ed_delete_prev_char(el, c)
588 EditLine *el;
589 int c;
590 {
591 if (el->el_line.cursor <= el->el_line.buffer)
592 return CC_ERROR;
593
594 c_delbefore(el, el->el_state.argument);
595 el->el_line.cursor -= el->el_state.argument;
596 if (el->el_line.cursor < el->el_line.buffer)
597 el->el_line.cursor = el->el_line.buffer;
598 return CC_REFRESH;
599 }
600
601
602 /* ed_clear_screen():
603 * Clear screen leaving current line at the top
604 * [^L]
605 */
606 protected el_action_t
607 /*ARGSUSED*/
ed_clear_screen(el,c)608 ed_clear_screen(el, c)
609 EditLine *el;
610 int c;
611 {
612 term_clear_screen(el); /* clear the whole real screen */
613 re_clear_display(el); /* reset everything */
614 return CC_REFRESH;
615 }
616
617
618 /* ed_redisplay():
619 * Redisplay everything
620 * ^R
621 */
622 protected el_action_t
623 /*ARGSUSED*/
ed_redisplay(el,c)624 ed_redisplay(el, c)
625 EditLine *el;
626 int c;
627 {
628 re_clear_lines(el);
629 re_clear_display(el);
630 return CC_REFRESH;
631 }
632
633
634 /* ed_start_over():
635 * Erase current line and start from scratch
636 * [^G]
637 */
638 protected el_action_t
639 /*ARGSUSED*/
ed_start_over(el,c)640 ed_start_over(el, c)
641 EditLine *el;
642 int c;
643 {
644 ch_reset(el);
645 return CC_REFRESH;
646 }
647
648
649 /* ed_sequence_lead_in():
650 * First character in a bound sequence
651 * Placeholder for external keys
652 */
653 protected el_action_t
654 /*ARGSUSED*/
ed_sequence_lead_in(el,c)655 ed_sequence_lead_in(el, c)
656 EditLine *el;
657 int c;
658 {
659 return CC_NORM;
660 }
661
662
663 /* ed_prev_history():
664 * Move to the previous history line
665 * [^P] [k]
666 */
667 protected el_action_t
668 /*ARGSUSED*/
ed_prev_history(el,c)669 ed_prev_history(el, c)
670 EditLine *el;
671 int c;
672 {
673 char beep = 0;
674
675 el->el_chared.c_undo.action = NOP;
676 *el->el_line.lastchar = '\0'; /* just in case */
677
678 if (el->el_history.eventno == 0) { /* save the current buffer away */
679 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
680 el->el_history.last = el->el_history.buf +
681 (el->el_line.lastchar - el->el_line.buffer);
682 }
683
684 el->el_history.eventno += el->el_state.argument;
685
686 if (hist_get(el) == CC_ERROR) {
687 beep = 1;
688 /* el->el_history.eventno was fixed by first call */
689 (void) hist_get(el);
690 }
691
692 re_refresh(el);
693 if (beep)
694 return CC_ERROR;
695 else
696 return CC_NORM; /* was CC_UP_HIST */
697 }
698
699
700 /* ed_next_history():
701 * Move to the next history line
702 * [^N] [j]
703 */
704 protected el_action_t
705 /*ARGSUSED*/
ed_next_history(el,c)706 ed_next_history(el, c)
707 EditLine *el;
708 int c;
709 {
710 el->el_chared.c_undo.action = NOP;
711 *el->el_line.lastchar = '\0'; /* just in case */
712
713 el->el_history.eventno -= el->el_state.argument;
714
715 if (el->el_history.eventno < 0) {
716 el->el_history.eventno = 0;
717 return CC_ERROR; /* make it beep */
718 }
719
720 return hist_get(el);
721 }
722
723
724 /* ed_search_prev_history():
725 * Search previous in history for a line matching the current
726 * next search history [M-P] [K]
727 */
728 protected el_action_t
729 /*ARGSUSED*/
ed_search_prev_history(el,c)730 ed_search_prev_history(el, c)
731 EditLine *el;
732 int c;
733 {
734 const char *hp;
735 int h;
736 bool_t found = 0;
737
738 el->el_chared.c_vcmd.action = NOP;
739 el->el_chared.c_undo.action = NOP;
740 *el->el_line.lastchar = '\0'; /* just in case */
741 if (el->el_history.eventno < 0) {
742 #ifdef DEBUG_EDIT
743 (void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
744 #endif
745 el->el_history.eventno = 0;
746 return CC_ERROR;
747 }
748
749 if (el->el_history.eventno == 0) {
750 (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
751 el->el_history.last = el->el_history.buf +
752 (el->el_line.lastchar - el->el_line.buffer);
753 }
754
755
756 if (el->el_history.ref == NULL)
757 return CC_ERROR;
758
759 hp = HIST_FIRST(el);
760 if (hp == NULL)
761 return CC_ERROR;
762
763 c_setpat(el); /* Set search pattern !! */
764
765 for (h = 1; h <= el->el_history.eventno; h++)
766 hp = HIST_NEXT(el);
767
768 while (hp != NULL) {
769 #ifdef SDEBUG
770 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
771 #endif
772 if ((strncmp(hp, el->el_line.buffer,
773 el->el_line.lastchar - el->el_line.buffer) ||
774 hp[el->el_line.lastchar-el->el_line.buffer]) &&
775 c_hmatch(el, hp)) {
776 found++;
777 break;
778 }
779 h++;
780 hp = HIST_NEXT(el);
781 }
782
783 if (!found) {
784 #ifdef SDEBUG
785 (void) fprintf(el->el_errfile, "not found\n");
786 #endif
787 return CC_ERROR;
788 }
789
790 el->el_history.eventno = h;
791
792 return hist_get(el);
793 }
794
795
796 /* ed_search_next_history():
797 * Search next in history for a line matching the current
798 * [M-N] [J]
799 */
800 protected el_action_t
801 /*ARGSUSED*/
ed_search_next_history(el,c)802 ed_search_next_history(el, c)
803 EditLine *el;
804 int c;
805 {
806 const char *hp;
807 int h;
808 bool_t found = 0;
809
810 el->el_chared.c_vcmd.action = NOP;
811 el->el_chared.c_undo.action = NOP;
812 *el->el_line.lastchar = '\0'; /* just in case */
813
814 if (el->el_history.eventno == 0)
815 return CC_ERROR;
816
817 if (el->el_history.ref == NULL)
818 return CC_ERROR;
819
820 hp = HIST_FIRST(el);
821 if (hp == NULL)
822 return CC_ERROR;
823
824 c_setpat(el); /* Set search pattern !! */
825
826 for (h = 1; h < el->el_history.eventno && hp; h++) {
827 #ifdef SDEBUG
828 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
829 #endif
830 if ((strncmp(hp, el->el_line.buffer,
831 el->el_line.lastchar - el->el_line.buffer) ||
832 hp[el->el_line.lastchar-el->el_line.buffer]) &&
833 c_hmatch(el, hp))
834 found = h;
835 hp = HIST_NEXT(el);
836 }
837
838 if (!found) { /* is it the current history number? */
839 if (!c_hmatch(el, el->el_history.buf)) {
840 #ifdef SDEBUG
841 (void) fprintf(el->el_errfile, "not found\n");
842 #endif
843 return CC_ERROR;
844 }
845 }
846
847 el->el_history.eventno = found;
848
849 return hist_get(el);
850 }
851
852
853 /* ed_prev_line():
854 * Move up one line
855 * Could be [k] [^p]
856 */
857 protected el_action_t
858 /*ARGSUSED*/
ed_prev_line(el,c)859 ed_prev_line(el, c)
860 EditLine *el;
861 int c;
862 {
863 char *ptr;
864 int nchars = c_hpos(el);
865
866 /*
867 * Move to the line requested
868 */
869 if (*(ptr = el->el_line.cursor) == '\n')
870 ptr--;
871
872 for (; ptr >= el->el_line.buffer; ptr--)
873 if (*ptr == '\n' && --el->el_state.argument <= 0)
874 break;
875
876 if (el->el_state.argument > 0)
877 return CC_ERROR;
878
879 /*
880 * Move to the beginning of the line
881 */
882 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
883 continue;
884
885 /*
886 * Move to the character requested
887 */
888 for (ptr++;
889 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
890 ptr++)
891 continue;
892
893 el->el_line.cursor = ptr;
894 return CC_CURSOR;
895 }
896
897
898 /* ed_next_line():
899 * Move down one line
900 * Could be [j] [^n]
901 */
902 protected el_action_t
903 /*ARGSUSED*/
ed_next_line(el,c)904 ed_next_line(el, c)
905 EditLine *el;
906 int c;
907 {
908 char *ptr;
909 int nchars = c_hpos(el);
910
911 /*
912 * Move to the line requested
913 */
914 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
915 if (*ptr == '\n' && --el->el_state.argument <= 0)
916 break;
917
918 if (el->el_state.argument > 0)
919 return CC_ERROR;
920
921 /*
922 * Move to the character requested
923 */
924 for (ptr++;
925 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
926 ptr++)
927 continue;
928
929 el->el_line.cursor = ptr;
930 return CC_CURSOR;
931 }
932
933
934 /* ed_command():
935 * Editline extended command
936 * [M-X] [:]
937 */
938 protected el_action_t
939 /*ARGSUSED*/
ed_command(el,c)940 ed_command(el, c)
941 EditLine *el;
942 int c;
943 {
944 char tmpbuf[EL_BUFSIZ];
945 int tmplen;
946
947 el->el_line.buffer[0] = '\0';
948 el->el_line.lastchar = el->el_line.buffer;
949 el->el_line.cursor = el->el_line.buffer;
950
951 c_insert(el, 3); /* prompt + ": " */
952 *el->el_line.cursor++ = '\n';
953 *el->el_line.cursor++ = ':';
954 *el->el_line.cursor++ = ' ';
955 re_refresh(el);
956
957 tmplen = c_gets(el, tmpbuf);
958 tmpbuf[tmplen] = '\0';
959
960 el->el_line.buffer[0] = '\0';
961 el->el_line.lastchar = el->el_line.buffer;
962 el->el_line.cursor = el->el_line.buffer;
963
964 if (parse_line(el, tmpbuf) == -1)
965 return CC_ERROR;
966 else
967 return CC_REFRESH;
968 }
969