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