bnx: Remove unused code
[dragonfly.git] / contrib / tcsh-6 / ed.chared.c
CommitLineData
57e3f2b5 1/* $Header: /p/tcsh/cvsroot/tcsh/ed.chared.c,v 3.95 2009/06/25 21:15:37 christos Exp $ */
7d8fb588
MS
2/*
3 * ed.chared.c: Character editing functions.
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33/*
34 Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
35
36 e_dabbrev_expand() did not do proper completion if quoted spaces were present
37 in the string being completed. Exemple:
38
39 # echo hello\ world
40 hello world
41 # echo h<press key bound to dabbrev-expande>
42 # echo hello\<cursor>
43
44 Correct behavior is:
45 # echo h<press key bound to dabbrev-expande>
46 # echo hello\ world<cursor>
47
48 The same problem occured if spaces were present in a string withing quotation
49 marks. Example:
50
51 # echo "hello world"
52 hello world
53 # echo "h<press key bound to dabbrev-expande>
54 # echo "hello<cursor>
55
56 The former problem could be solved with minor modifications of c_preword()
57 and c_endword(). The latter, however, required a significant rewrite of
58 c_preword(), since quoted strings must be parsed from start to end to
59 determine if a given character is inside or outside the quotation marks.
60
61 Compare the following two strings:
62
63 # echo \"" 'foo \' bar\"
64 " 'foo \' bar\
65 # echo '\"" 'foo \' bar\"
66 \"" foo ' bar"
67
68 The only difference between the two echo lines is in the first character
69 after the echo command. The result is either one or three arguments.
70
71 */
72
73#include "sh.h"
74
57e3f2b5 75RCSID("$tcsh: ed.chared.c,v 3.95 2009/06/25 21:15:37 christos Exp $")
7d8fb588
MS
76
77#include "ed.h"
78#include "tw.h"
79#include "ed.defns.h"
80
81/* #define SDEBUG */
82
83#define TCSHOP_NOP 0x00
84#define TCSHOP_DELETE 0x01
85#define TCSHOP_INSERT 0x02
86#define TCSHOP_CHANGE 0x04
87
88#define CHAR_FWD 0
89#define CHAR_BACK 1
90
91/*
92 * vi word treatment
93 * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
94 */
95#define C_CLASS_WHITE 1
96#define C_CLASS_ALNUM 2
97#define C_CLASS_OTHER 3
98
99static Char *InsertPos = InputBuf; /* Where insertion starts */
100static Char *ActionPos = 0; /* Where action begins */
101static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */
102/*
103 * Word search state
104 */
105static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
106static struct Strbuf patbuf; /* = Strbuf_INIT; Search target */
107/*
108 * Char search state
109 */
110static int srch_dir = CHAR_FWD; /* Direction of last search */
111static Char srch_char = 0; /* Search target */
112
113/* all routines that start with c_ are private to this set of routines */
114static void c_alternativ_key_map (int);
115void c_insert (int);
116void c_delafter (int);
117void c_delbefore (int);
118static int c_to_class (Char);
119static Char *c_prev_word (Char *, Char *, int);
120static Char *c_next_word (Char *, Char *, int);
121static Char *c_number (Char *, int *, int);
122static Char *c_expand (Char *);
57e3f2b5
SS
123static int c_excl (Char *);
124static int c_substitute (void);
7d8fb588
MS
125static void c_delfini (void);
126static int c_hmatch (Char *);
127static void c_hsetpat (void);
128#ifdef COMMENT
129static void c_get_word (Char **, Char **);
130#endif
131static Char *c_preword (Char *, Char *, int, Char *);
132static Char *c_nexword (Char *, Char *, int);
133static Char *c_endword (Char *, Char *, int, Char *);
134static Char *c_eword (Char *, Char *, int);
135static void c_push_kill (Char *, Char *);
136static void c_save_inputbuf (void);
137static CCRETVAL c_search_line (Char *, int);
138static CCRETVAL v_repeat_srch (int);
139static CCRETVAL e_inc_search (int);
140#ifdef notyet
141static CCRETVAL e_insert_str (Char *);
142#endif
143static CCRETVAL v_search (int);
144static CCRETVAL v_csearch_fwd (Char, int, int);
145static CCRETVAL v_action (int);
146static CCRETVAL v_csearch_back (Char, int, int);
147
148static void
149c_alternativ_key_map(int state)
150{
151 switch (state) {
152 case 0:
153 CurrentKeyMap = CcKeyMap;
154 break;
155 case 1:
156 CurrentKeyMap = CcAltMap;
157 break;
158 default:
159 return;
160 }
161
162 AltKeyMap = (Char) state;
163}
164
165void
166c_insert(int num)
167{
168 Char *cp;
169
170 if (LastChar + num >= InputLim)
171 return; /* can't go past end of buffer */
172
173 if (Cursor < LastChar) { /* if I must move chars */
174 for (cp = LastChar; cp >= Cursor; cp--)
175 cp[num] = *cp;
176 if (Mark && Mark > Cursor)
177 Mark += num;
178 }
179 LastChar += num;
180}
181
182void
183c_delafter(int num)
184{
185 Char *cp, *kp = NULL;
186
187 if (num > LastChar - Cursor)
188 num = (int) (LastChar - Cursor); /* bounds check */
189
190 if (num > 0) { /* if I can delete anything */
191 if (VImode) {
192 kp = UndoBuf; /* Set Up for VI undo command */
193 UndoAction = TCSHOP_INSERT;
194 UndoSize = num;
195 UndoPtr = Cursor;
196 for (cp = Cursor; cp <= LastChar; cp++) {
197 *kp++ = *cp; /* Save deleted chars into undobuf */
198 *cp = cp[num];
199 }
200 }
201 else
202 for (cp = Cursor; cp + num <= LastChar; cp++)
203 *cp = cp[num];
204 LastChar -= num;
205 /* Mark was within the range of the deleted word? */
206 if (Mark && Mark > Cursor && Mark <= Cursor+num)
207 Mark = Cursor;
208 /* Mark after the deleted word? */
209 else if (Mark && Mark > Cursor)
210 Mark -= num;
211 }
212#ifdef notdef
213 else {
214 /*
215 * XXX: We don't want to do that. In emacs mode overwrite should be
216 * sticky. I am not sure how that affects vi mode
217 */
218 inputmode = MODE_INSERT;
219 }
220#endif /* notdef */
221}
222
223void
224c_delbefore(int num) /* delete before dot, with bounds checking */
225{
226 Char *cp, *kp = NULL;
227
228 if (num > Cursor - InputBuf)
229 num = (int) (Cursor - InputBuf); /* bounds check */
230
231 if (num > 0) { /* if I can delete anything */
232 if (VImode) {
233 kp = UndoBuf; /* Set Up for VI undo command */
234 UndoAction = TCSHOP_INSERT;
235 UndoSize = num;
236 UndoPtr = Cursor - num;
237 for (cp = Cursor - num; cp <= LastChar; cp++) {
238 *kp++ = *cp;
239 *cp = cp[num];
240 }
241 }
242 else
243 for (cp = Cursor - num; cp + num <= LastChar; cp++)
244 *cp = cp[num];
245 LastChar -= num;
246 Cursor -= num;
247 /* Mark was within the range of the deleted word? */
248 if (Mark && Mark > Cursor && Mark <= Cursor+num)
249 Mark = Cursor;
250 /* Mark after the deleted word? */
251 else if (Mark && Mark > Cursor)
252 Mark -= num;
253 }
254}
255
256static Char *
257c_preword(Char *p, Char *low, int n, Char *delim)
258{
259 while (n--) {
260 Char *prev = low;
261 Char *new;
262
263 while (prev < p) { /* Skip initial non-word chars */
264 if (!Strchr(delim, *prev) || *(prev-1) == (Char)'\\')
265 break;
266 prev++;
267 }
268
269 new = prev;
270
271 while (new < p) {
272 prev = new;
273 new = c_endword(prev-1, p, 1, delim); /* Skip to next non-word char */
274 new++; /* Step away from end of word */
275 while (new <= p) { /* Skip trailing non-word chars */
276 if (!Strchr(delim, *new) || *(new-1) == (Char)'\\')
277 break;
278 new++;
279 }
280 }
281
282 p = prev; /* Set to previous word start */
283
284 }
285 if (p < low)
286 p = low;
287 return (p);
288}
289
290/*
291 * c_to_class() returns the class of the given character.
292 *
293 * This is used to make the c_prev_word() and c_next_word() functions
294 * work like vi's, which classify characters. A word is a sequence of
295 * characters belonging to the same class, classes being defined as
296 * follows:
297 *
298 * 1/ whitespace
299 * 2/ alphanumeric chars, + underscore
300 * 3/ others
301 */
302static int
303c_to_class(Char ch)
304{
305 if (Isspace(ch))
306 return C_CLASS_WHITE;
307
308 if (Isdigit(ch) || Isalpha(ch) || ch == '_')
309 return C_CLASS_ALNUM;
310
311 return C_CLASS_OTHER;
312}
313
314static Char *
315c_prev_word(Char *p, Char *low, int n)
316{
317 p--;
318
319 if (!VImode) {
320 while (n--) {
321 while ((p >= low) && !isword(*p))
322 p--;
323 while ((p >= low) && isword(*p))
324 p--;
325 }
326
327 /* cp now points to one character before the word */
328 p++;
329 if (p < low)
330 p = low;
331 /* cp now points where we want it */
332 return(p);
333 }
334
335 while (n--) {
336 int c_class;
337
338 if (p < low)
339 break;
340
341 /* scan until beginning of current word (may be all whitespace!) */
342 c_class = c_to_class(*p);
343 while ((p >= low) && c_class == c_to_class(*p))
344 p--;
345
346 /* if this was a non_whitespace word, we're ready */
347 if (c_class != C_CLASS_WHITE)
348 continue;
349
350 /* otherwise, move back to beginning of the word just found */
351 c_class = c_to_class(*p);
352 while ((p >= low) && c_class == c_to_class(*p))
353 p--;
354 }
355
356 p++; /* correct overshoot */
357
358 return (p);
359}
360
361static Char *
362c_next_word(Char *p, Char *high, int n)
363{
364 if (!VImode) {
365 while (n--) {
366 while ((p < high) && !isword(*p))
367 p++;
368 while ((p < high) && isword(*p))
369 p++;
370 }
371 if (p > high)
372 p = high;
373 /* p now points where we want it */
374 return(p);
375 }
376
377 while (n--) {
378 int c_class;
379
380 if (p >= high)
381 break;
382
383 /* scan until end of current word (may be all whitespace!) */
384 c_class = c_to_class(*p);
385 while ((p < high) && c_class == c_to_class(*p))
386 p++;
387
388 /* if this was all whitespace, we're ready */
389 if (c_class == C_CLASS_WHITE)
390 continue;
391
392 /* if we've found white-space at the end of the word, skip it */
393 while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
394 p++;
395 }
396
397 p--; /* correct overshoot */
398
399 return (p);
400}
401
402static Char *
403c_nexword(Char *p, Char *high, int n)
404{
405 while (n--) {
406 while ((p < high) && !Isspace(*p))
407 p++;
408 while ((p < high) && Isspace(*p))
409 p++;
410 }
411
412 if (p > high)
413 p = high;
414 /* p now points where we want it */
415 return(p);
416}
417
418/*
419 * Expand-History (originally "Magic-Space") code added by
420 * Ray Moody <ray@gibbs.physics.purdue.edu>
421 * this is a neat, but odd, addition.
422 */
423
424/*
425 * c_number: Ignore character p points to, return number appearing after that.
426 * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
427 * Return p pointing to last char used.
428 */
429
430/*
431 * dval is the number to subtract from for things like $-3
432 */
433
434static Char *
435c_number(Char *p, int *num, int dval)
436{
437 int i;
438 int sign = 1;
439
440 if (*++p == '^') {
441 *num = 1;
442 return(p);
443 }
444 if (*p == '$') {
445 if (*++p != '-') {
446 *num = INT_MAX; /* Handle $ */
447 return(--p);
448 }
449 sign = -1; /* Handle $- */
450 ++p;
451 }
452 for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
453 continue;
454 *num = (sign < 0 ? dval - i : i);
455 return(--p);
456}
457
458/*
459 * excl_expand: There is an excl to be expanded to p -- do the right thing
460 * with it and return a version of p advanced over the expanded stuff. Also,
461 * update tsh_cur and related things as appropriate...
462 */
463
464static Char *
465c_expand(Char *p)
466{
467 Char *q;
468 struct Hist *h = Histlist.Hnext;
469 struct wordent *l;
470 int i, from, to, dval;
471 int all_dig;
472 int been_once = 0;
473 Char *op = p;
474 Char *buf;
475 size_t buf_len;
476 Char *modbuf;
477
478 buf = NULL;
479 if (!h)
480 goto excl_err;
481excl_sw:
482 switch (*(q = p + 1)) {
483
484 case '^':
485 buf = expand_lex(&h->Hlex, 1, 1);
486 break;
487
488 case '$':
489 if ((l = (h->Hlex).prev) != 0)
490 buf = expand_lex(l->prev->prev, 0, 0);
491 break;
492
493 case '*':
494 buf = expand_lex(&h->Hlex, 1, INT_MAX);
495 break;
496
497 default:
498 if (been_once) { /* unknown argument */
499 /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
500 buf = expand_lex(&h->Hlex, 0, INT_MAX);
501 q -= 2;
502 break;
503 }
504 been_once = 1;
505
506 if (*q == ':') /* short form: !:arg */
507 --q;
508
509 if (*q != HIST) {
510 /*
511 * Search for a space, tab, or colon. See if we have a number (as
512 * in !1234:xyz). Remember the number.
513 */
514 for (i = 0, all_dig = 1;
515 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
516 /*
517 * PWP: !-4 is a valid history argument too, therefore the test
518 * is if not a digit, or not a - as the first character.
519 */
520 if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
521 all_dig = 0;
522 else if (*q == '-')
523 all_dig = 2;/* we are sneeky about this */
524 else
525 i = 10 * i + *q - '0';
526 }
527 --q;
528
529 /*
530 * If we have a number, search for event i. Otherwise, search for
531 * a named event (as in !foo). (In this case, I is the length of
532 * the named event).
533 */
534 if (all_dig) {
535 if (all_dig == 2)
536 i = -i; /* make it negitive */
537 if (i < 0) /* if !-4 (for example) */
538 i = eventno + 1 + i; /* remember: i is < 0 */
539 for (; h; h = h->Hnext) {
540 if (h->Hnum == i)
541 break;
542 }
543 }
544 else {
545 for (i = (int) (q - p); h; h = h->Hnext) {
546 if ((l = &h->Hlex) != 0) {
547 if (!Strncmp(p + 1, l->next->word, (size_t) i))
548 break;
549 }
550 }
551 }
552 }
553 if (!h)
554 goto excl_err;
555 if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
556 q[1] == '$' || q[1] == '^') { /* get some args */
557 p = q[1] == ':' ? ++q : q;
558 /*
559 * Go handle !foo:*
560 */
561 if ((q[1] < '0' || q[1] > '9') &&
562 q[1] != '-' && q[1] != '$' && q[1] != '^')
563 goto excl_sw;
564 /*
565 * Go handle !foo:$
566 */
567 if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
568 goto excl_sw;
569 /*
570 * Count up the number of words in this event. Store it in dval.
571 * Dval will be fed to number.
572 */
573 dval = 0;
574 if ((l = h->Hlex.prev) != 0) {
575 for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
576 continue;
577 }
578 if (!dval)
579 goto excl_err;
580 if (q[1] == '-')
581 from = 0;
582 else
583 q = c_number(q, &from, dval);
584 if (q[1] == '-') {
585 ++q;
586 if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
587 to = dval - 1;
588 else
589 q = c_number(q, &to, dval);
590 }
591 else if (q[1] == '*') {
592 ++q;
593 to = INT_MAX;
594 }
595 else {
596 to = from;
597 }
598 if (from < 0 || to < from)
599 goto excl_err;
600 buf = expand_lex(&h->Hlex, from, to);
601 }
602 else /* get whole cmd */
603 buf = expand_lex(&h->Hlex, 0, INT_MAX);
604 break;
605 }
606 if (buf == NULL)
607 buf = SAVE("");
608
609 /*
610 * Apply modifiers, if any.
611 */
612 if (q[1] == ':') {
613 modbuf = buf;
614 while (q[1] == ':' && modbuf != NULL) {
615 switch (q[2]) {
616 case 'r':
617 case 'e':
618 case 'h':
619 case 't':
620 case 'q':
621 case 'x':
622 case 'u':
623 case 'l':
624 if ((modbuf = domod(buf, (int) q[2])) != NULL) {
625 xfree(buf);
626 buf = modbuf;
627 }
628 ++q;
629 break;
630
631 case 'a':
632 case 'g':
633 /* Not implemented; this needs to be done before expanding
634 * lex. We don't have the words available to us anymore.
635 */
636 ++q;
637 break;
638
639 case 'p':
640 /* Ok */
641 ++q;
642 break;
643
644 case '\0':
645 break;
646
647 default:
648 ++q;
649 break;
650 }
651 if (q[1])
652 ++q;
653 }
654 }
655
656 buf_len = Strlen(buf);
657 /*
658 * Now replace the text from op to q inclusive with the text from buf.
659 */
660 q++;
661
662 /*
663 * Now replace text non-inclusively like a real CS major!
664 */
665 if (LastChar + buf_len - (q - op) >= InputLim)
666 goto excl_err;
667 (void) memmove(op + buf_len, q, (LastChar - q) * sizeof(Char));
668 LastChar += buf_len - (q - op);
669 Cursor += buf_len - (q - op);
670 (void) memcpy(op, buf, buf_len * sizeof(Char));
671 *LastChar = '\0';
672 xfree(buf);
673 return op + buf_len;
674excl_err:
675 xfree(buf);
676 SoundBeep();
677 return(op + 1);
678}
679
680/*
681 * c_excl: An excl has been found at point p -- back up and find some white
682 * space (or the beginning of the buffer) and properly expand all the excl's
683 * from there up to the current cursor position. We also avoid (trying to)
684 * expanding '>!'
57e3f2b5
SS
685 * Returns number of expansions attempted (doesn't matter whether they succeeded
686 * or not).
7d8fb588
MS
687 */
688
57e3f2b5 689static int
7d8fb588
MS
690c_excl(Char *p)
691{
692 int i;
693 Char *q;
57e3f2b5 694 int nr_exp;
7d8fb588
MS
695
696 /*
697 * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
698 * back p up to just before the current word.
699 */
700 if ((p[1] == ' ' || p[1] == '\t') &&
701 (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
702 for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
703 continue;
704 if (*q == '>')
705 ++p;
706 }
707 else {
708 while (*p != ' ' && *p != '\t' && p > InputBuf)
709 --p;
710 }
711
712 /*
713 * Forever: Look for history char. (Stop looking when we find the cursor.)
57e3f2b5
SS
714 * Count backslashes. If odd, skip history char. Expand if even number of
715 * backslashes.
7d8fb588 716 */
57e3f2b5 717 nr_exp = 0;
7d8fb588
MS
718 for (;;) {
719 while (*p != HIST && p < Cursor)
720 ++p;
721 for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
722 continue;
723 if (i % 2 == 0)
724 ++p;
57e3f2b5
SS
725 if (p >= Cursor) /* all done */
726 return nr_exp;
727 if (i % 2 == 1) {
7d8fb588 728 p = c_expand(p);
57e3f2b5
SS
729 ++nr_exp;
730 }
7d8fb588 731 }
57e3f2b5
SS
732
733 return nr_exp;
7d8fb588
MS
734}
735
736
57e3f2b5 737static int
7d8fb588
MS
738c_substitute(void)
739{
740 Char *p;
57e3f2b5 741 int nr_exp;
7d8fb588
MS
742
743 /*
744 * Start p out one character before the cursor. Move it backwards looking
745 * for white space, the beginning of the line, or a history character.
746 */
747 for (p = Cursor - 1;
748 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
749 continue;
750
751 /*
752 * If we found a history character, go expand it.
753 */
754 if (*p == HIST)
57e3f2b5
SS
755 nr_exp = c_excl(p);
756 else
757 nr_exp = 0;
7d8fb588 758 Refresh();
57e3f2b5
SS
759
760 return nr_exp;
7d8fb588
MS
761}
762
763static void
764c_delfini(void) /* Finish up delete action */
765{
766 int Size;
767
768 if (ActionFlag & TCSHOP_INSERT)
769 c_alternativ_key_map(0);
770
771 ActionFlag = TCSHOP_NOP;
772
773 if (ActionPos == 0)
774 return;
775
776 UndoAction = TCSHOP_INSERT;
777
778 if (Cursor > ActionPos) {
779 Size = (int) (Cursor-ActionPos);
780 c_delbefore(Size);
781 RefCursor();
782 }
783 else if (Cursor < ActionPos) {
784 Size = (int)(ActionPos-Cursor);
785 c_delafter(Size);
786 }
787 else {
788 Size = 1;
789 c_delafter(Size);
790 }
791 UndoPtr = Cursor;
792 UndoSize = Size;
793}
794
795static Char *
796c_endword(Char *p, Char *high, int n, Char *delim)
797{
798 Char inquote = 0;
799 p++;
800
801 while (n--) {
802 while (p < high) { /* Skip non-word chars */
803 if (!Strchr(delim, *p) || *(p-1) == (Char)'\\')
804 break;
805 p++;
806 }
807 while (p < high) { /* Skip string */
808 if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
809 if (inquote || *(p-1) != (Char)'\\') { /* Should it be honored? */
810 if (inquote == 0) inquote = *p;
811 else if (inquote == *p) inquote = 0;
812 }
813 }
814 /* Break if unquoted non-word char */
815 if (!inquote && Strchr(delim, *p) && *(p-1) != (Char)'\\')
816 break;
817 p++;
818 }
819 }
820
821 p--;
822 return(p);
823}
824
825
826static Char *
827c_eword(Char *p, Char *high, int n)
828{
829 p++;
830
831 while (n--) {
832 while ((p < high) && Isspace(*p))
833 p++;
834
835 if (Isalnum(*p))
836 while ((p < high) && Isalnum(*p))
837 p++;
838 else
839 while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
840 p++;
841 }
842
843 p--;
844 return(p);
845}
846
847/* Set the max length of the kill ring */
848void
849SetKillRing(int max)
850{
851 CStr *new;
852 int count, i, j;
853
854 if (max < 1)
855 max = 1; /* no ring, but always one buffer */
856 if (max == KillRingMax)
857 return;
858 new = xcalloc(max, sizeof(CStr));
859 if (KillRing != NULL) {
860 if (KillRingLen != 0) {
861 if (max >= KillRingLen) {
862 count = KillRingLen;
863 j = KillPos;
864 } else {
865 count = max;
866 j = (KillPos - count + KillRingLen) % KillRingLen;
867 }
868 for (i = 0; i < KillRingLen; i++) {
869 if (i < count) /* copy latest */
870 new[i] = KillRing[j];
871 else /* free the others */
872 xfree(KillRing[j].buf);
873 j = (j + 1) % KillRingLen;
874 }
875 KillRingLen = count;
876 KillPos = count % max;
877 YankPos = count - 1;
878 }
879 xfree(KillRing);
880 }
881 KillRing = new;
882 KillRingMax = max;
883}
884
885/* Push string from start upto (but not including) end onto kill ring */
886static void
887c_push_kill(Char *start, Char *end)
888{
889 CStr save, *pos;
890 Char *dp, *cp, *kp;
891 int len = end - start, i, j, k;
892
893 /* Check for duplicates? */
894 if (KillRingLen > 0 && (dp = varval(STRkilldup)) != STRNULL) {
895 YankPos = (KillPos - 1 + KillRingLen) % KillRingLen;
896 if (eq(dp, STRerase)) { /* erase earlier one (actually move up) */
897 j = YankPos;
898 for (i = 0; i < KillRingLen; i++) {
899 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
900 KillRing[j].buf[len] == '\0') {
901 save = KillRing[j];
902 for ( ; i > 0; i--) {
903 k = j;
904 j = (j + 1) % KillRingLen;
905 KillRing[k] = KillRing[j];
906 }
907 KillRing[j] = save;
908 return;
909 }
910 j = (j - 1 + KillRingLen) % KillRingLen;
911 }
912 } else if (eq(dp, STRall)) { /* skip if any earlier */
913 for (i = 0; i < KillRingLen; i++)
914 if (Strncmp(KillRing[i].buf, start, (size_t) len) == 0 &&
915 KillRing[i].buf[len] == '\0')
916 return;
917 } else if (eq(dp, STRprev)) { /* skip if immediately previous */
918 j = YankPos;
919 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
920 KillRing[j].buf[len] == '\0')
921 return;
922 }
923 }
924
925 /* No duplicate, go ahead and push */
926 len++; /* need space for '\0' */
927 YankPos = KillPos;
928 if (KillRingLen < KillRingMax)
929 KillRingLen++;
930 pos = &KillRing[KillPos];
931 KillPos = (KillPos + 1) % KillRingMax;
932 if (pos->len < len) {
933 pos->buf = xrealloc(pos->buf, len * sizeof(Char));
934 pos->len = len;
935 }
936 cp = start;
937 kp = pos->buf;
938 while (cp < end)
939 *kp++ = *cp++;
940 *kp = '\0';
941}
942
943/* Save InputBuf etc in SavedBuf etc for restore after cmd exec */
944static void
945c_save_inputbuf()
946{
947 SavedBuf.len = 0;
948 Strbuf_append(&SavedBuf, InputBuf);
949 Strbuf_terminate(&SavedBuf);
950 LastSaved = LastChar - InputBuf;
951 CursSaved = Cursor - InputBuf;
952 HistSaved = Hist_num;
953 RestoreSaved = 1;
954}
955
956CCRETVAL
957GetHistLine()
958{
959 struct Hist *hp;
960 int h;
961
962 if (Hist_num == 0) { /* if really the current line */
963 if (HistBuf.s != NULL)
964 copyn(InputBuf, HistBuf.s, INBUFSIZE);/*FIXBUF*/
965 else
966 *InputBuf = '\0';
967 LastChar = InputBuf + HistBuf.len;
968
969#ifdef KSHVI
970 if (VImode)
971 Cursor = InputBuf;
972 else
973#endif /* KSHVI */
974 Cursor = LastChar;
975
976 return(CC_REFRESH);
977 }
978
979 hp = Histlist.Hnext;
980 if (hp == NULL)
981 return(CC_ERROR);
982
983 for (h = 1; h < Hist_num; h++) {
984 if ((hp->Hnext) == NULL) {
985 Hist_num = h;
986 return(CC_ERROR);
987 }
988 hp = hp->Hnext;
989 }
990
991 if (HistLit && hp->histline) {
992 copyn(InputBuf, hp->histline, INBUFSIZE);/*FIXBUF*/
993 CurrentHistLit = 1;
994 }
995 else {
996 Char *p;
997
998 p = sprlex(&hp->Hlex);
999 copyn(InputBuf, p, sizeof(InputBuf) / sizeof(Char));/*FIXBUF*/
1000 xfree(p);
1001 CurrentHistLit = 0;
1002 }
1003 LastChar = Strend(InputBuf);
1004
1005 if (LastChar > InputBuf) {
1006 if (LastChar[-1] == '\n')
1007 LastChar--;
1008#if 0
1009 if (LastChar[-1] == ' ')
1010 LastChar--;
1011#endif
1012 if (LastChar < InputBuf)
1013 LastChar = InputBuf;
1014 }
1015
1016#ifdef KSHVI
1017 if (VImode)
1018 Cursor = InputBuf;
1019 else
1020#endif /* KSHVI */
1021 Cursor = LastChar;
1022
1023 return(CC_REFRESH);
1024}
1025
1026static CCRETVAL
1027c_search_line(Char *pattern, int dir)
1028{
1029 Char *cp;
1030 size_t len;
1031
1032 len = Strlen(pattern);
1033
1034 if (dir == F_UP_SEARCH_HIST) {
1035 for (cp = Cursor; cp >= InputBuf; cp--)
1036 if (Strncmp(cp, pattern, len) == 0 ||
1037 Gmatch(cp, pattern)) {
1038 Cursor = cp;
1039 return(CC_NORM);
1040 }
1041 return(CC_ERROR);
1042 } else {
1043 for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1044 if (Strncmp(cp, pattern, len) == 0 ||
1045 Gmatch(cp, pattern)) {
1046 Cursor = cp;
1047 return(CC_NORM);
1048 }
1049 return(CC_ERROR);
1050 }
1051}
1052
1053static CCRETVAL
1054e_inc_search(int dir)
1055{
1056 static const Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1057 STRbck[] = { 'b', 'c', 'k', '\0' };
1058 static Char pchar = ':'; /* ':' = normal, '?' = failed */
1059 static Char endcmd[2];
1060 const Char *cp;
1061 Char ch,
1062 *oldCursor = Cursor,
1063 oldpchar = pchar;
1064 CCRETVAL ret = CC_NORM;
1065 int oldHist_num = Hist_num,
1066 oldpatlen = patbuf.len,
1067 newdir = dir,
1068 done, redo;
1069
1070 if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patbuf.len >= InputLim)
1071 return(CC_ERROR);
1072
1073 for (;;) {
1074
1075 if (patbuf.len == 0) { /* first round */
1076 pchar = ':';
1077 Strbuf_append1(&patbuf, '*');
1078 }
1079 done = redo = 0;
1080 *LastChar++ = '\n';
1081 for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
1082 *cp; *LastChar++ = *cp++)
1083 continue;
1084 *LastChar++ = pchar;
1085 for (cp = &patbuf.s[1]; cp < &patbuf.s[patbuf.len];
1086 *LastChar++ = *cp++)
1087 continue;
1088 *LastChar = '\0';
1089 if (adrof(STRhighlight) && pchar == ':') {
1090 /* if the no-glob-search patch is applied, remove the - 1 below */
1091 IncMatchLen = patbuf.len - 1;
1092 ClearLines();
1093 ClearDisp();
1094 }
1095 Refresh();
1096
1097 if (GetNextChar(&ch) != 1)
1098 return(e_send_eof(0));
1099
1100 switch (ch > NT_NUM_KEYS
1101 ? F_INSERT : CurrentKeyMap[(unsigned char) ch]) {
1102 case F_INSERT:
1103 case F_DIGIT:
1104 case F_MAGIC_SPACE:
1105 if (LastChar + 1 >= InputLim) /*FIXBUF*/
1106 SoundBeep();
1107 else {
1108 Strbuf_append1(&patbuf, ch);
1109 *LastChar++ = ch;
1110 *LastChar = '\0';
1111 Refresh();
1112 }
1113 break;
1114
1115 case F_INC_FWD:
1116 newdir = F_DOWN_SEARCH_HIST;
1117 redo++;
1118 break;
1119
1120 case F_INC_BACK:
1121 newdir = F_UP_SEARCH_HIST;
1122 redo++;
1123 break;
1124
1125 case F_DELPREV:
1126 if (patbuf.len > 1)
1127 done++;
1128 else
1129 SoundBeep();
1130 break;
1131
1132 default:
1133 switch (ASC(ch)) {
1134 case 0007: /* ^G: Abort */
1135 ret = CC_ERROR;
1136 done++;
1137 break;
1138
1139 case 0027: /* ^W: Append word */
1140 /* No can do if globbing characters in pattern */
1141 for (cp = &patbuf.s[1]; ; cp++)
1142 if (cp >= &patbuf.s[patbuf.len]) {
1143 Cursor += patbuf.len - 1;
1144 cp = c_next_word(Cursor, LastChar, 1);
1145 while (Cursor < cp && *Cursor != '\n') {
1146 if (LastChar + 1 >= InputLim) {/*FIXBUF*/
1147 SoundBeep();
1148 break;
1149 }
1150 Strbuf_append1(&patbuf, *Cursor);
1151 *LastChar++ = *Cursor++;
1152 }
1153 Cursor = oldCursor;
1154 *LastChar = '\0';
1155 Refresh();
1156 break;
1157 } else if (isglob(*cp)) {
1158 SoundBeep();
1159 break;
1160 }
1161 break;
1162
1163 default: /* Terminate and execute cmd */
1164 endcmd[0] = ch;
1165 PushMacro(endcmd);
1166 /*FALLTHROUGH*/
1167
1168 case 0033: /* ESC: Terminate */
1169 ret = CC_REFRESH;
1170 done++;
1171 break;
1172 }
1173 break;
1174 }
1175
1176 while (LastChar > InputBuf && *LastChar != '\n')
1177 *LastChar-- = '\0';
1178 *LastChar = '\0';
1179
1180 if (!done) {
1181
1182 /* Can't search if unmatched '[' */
1183 for (cp = &patbuf.s[patbuf.len - 1], ch = ']'; cp > patbuf.s; cp--)
1184 if (*cp == '[' || *cp == ']') {
1185 ch = *cp;
1186 break;
1187 }
1188
1189 if (patbuf.len > 1 && ch != '[') {
1190 if (redo && newdir == dir) {
1191 if (pchar == '?') { /* wrap around */
1192 Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : INT_MAX;
1193 if (GetHistLine() == CC_ERROR)
1194 /* Hist_num was fixed by first call */
1195 (void) GetHistLine();
1196 Cursor = newdir == F_UP_SEARCH_HIST ?
1197 LastChar : InputBuf;
1198 } else
1199 Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
1200 }
1201 Strbuf_append1(&patbuf, '*');
1202 Strbuf_terminate(&patbuf);
1203 if (Cursor < InputBuf || Cursor > LastChar ||
1204 (ret = c_search_line(&patbuf.s[1], newdir)) == CC_ERROR) {
1205 LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
1206 ret = newdir == F_UP_SEARCH_HIST ?
1207 e_up_search_hist(0) : e_down_search_hist(0);
1208 if (ret != CC_ERROR) {
1209 Cursor = newdir == F_UP_SEARCH_HIST ?
1210 LastChar : InputBuf;
1211 (void) c_search_line(&patbuf.s[1], newdir);
1212 }
1213 }
1214 patbuf.s[--patbuf.len] = '\0';
1215 if (ret == CC_ERROR) {
1216 SoundBeep();
1217 if (Hist_num != oldHist_num) {
1218 Hist_num = oldHist_num;
1219 if (GetHistLine() == CC_ERROR)
1220 return(CC_ERROR);
1221 }
1222 Cursor = oldCursor;
1223 pchar = '?';
1224 } else {
1225 pchar = ':';
1226 }
1227 }
1228
1229 ret = e_inc_search(newdir);
1230
1231 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
1232 /* break abort of failed search at last non-failed */
1233 ret = CC_NORM;
1234 }
1235
1236 }
1237
1238 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
1239 /* restore on normal return or error exit */
1240 pchar = oldpchar;
1241 patbuf.len = oldpatlen;
1242 if (Hist_num != oldHist_num) {
1243 Hist_num = oldHist_num;
1244 if (GetHistLine() == CC_ERROR)
1245 return(CC_ERROR);
1246 }
1247 Cursor = oldCursor;
1248 if (ret == CC_ERROR)
1249 Refresh();
1250 }
1251 if (done || ret != CC_NORM)
1252 return(ret);
1253
1254 }
1255
1256}
1257
1258static CCRETVAL
1259v_search(int dir)
1260{
1261 struct Strbuf tmpbuf = Strbuf_INIT;
1262 Char ch;
1263 Char *oldbuf;
1264 Char *oldlc, *oldc;
1265
1266 cleanup_push(&tmpbuf, Strbuf_cleanup);
1267 oldbuf = Strsave(InputBuf);
1268 cleanup_push(oldbuf, xfree);
1269 oldlc = LastChar;
1270 oldc = Cursor;
1271 Strbuf_append1(&tmpbuf, '*');
1272
1273 InputBuf[0] = '\0';
1274 LastChar = InputBuf;
1275 Cursor = InputBuf;
1276 searchdir = dir;
1277
1278 c_insert(2); /* prompt + '\n' */
1279 *Cursor++ = '\n';
1280 *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
1281 Refresh();
1282 for (ch = 0;ch == 0;) {
1283 if (GetNextChar(&ch) != 1) {
1284 cleanup_until(&tmpbuf);
1285 return(e_send_eof(0));
1286 }
1287 switch (ASC(ch)) {
1288 case 0010: /* Delete and backspace */
1289 case 0177:
1290 if (tmpbuf.len > 1) {
1291 *Cursor-- = '\0';
1292 LastChar = Cursor;
1293 tmpbuf.len--;
1294 }
1295 else {
1296 copyn(InputBuf, oldbuf, INBUFSIZE);/*FIXBUF*/
1297 LastChar = oldlc;
1298 Cursor = oldc;
1299 cleanup_until(&tmpbuf);
1300 return(CC_REFRESH);
1301 }
1302 Refresh();
1303 ch = 0;
1304 break;
1305
1306 case 0033: /* ESC */
1307#ifdef IS_ASCII
1308 case '\r': /* Newline */
1309 case '\n':
1310#else
1311 case '\012': /* ASCII Line feed */
1312 case '\015': /* ASCII (or EBCDIC) Return */
1313#endif
1314 break;
1315
1316 default:
1317 Strbuf_append1(&tmpbuf, ch);
1318 *Cursor++ = ch;
1319 LastChar = Cursor;
1320 Refresh();
1321 ch = 0;
1322 break;
1323 }
1324 }
1325 cleanup_until(oldbuf);
1326
1327 if (tmpbuf.len == 1) {
1328 /*
1329 * Use the old pattern, but wild-card it.
1330 */
1331 if (patbuf.len == 0) {
1332 InputBuf[0] = '\0';
1333 LastChar = InputBuf;
1334 Cursor = InputBuf;
1335 Refresh();
1336 cleanup_until(&tmpbuf);
1337 return(CC_ERROR);
1338 }
1339 if (patbuf.s[0] != '*') {
1340 oldbuf = Strsave(patbuf.s);
1341 patbuf.len = 0;
1342 Strbuf_append1(&patbuf, '*');
1343 Strbuf_append(&patbuf, oldbuf);
1344 xfree(oldbuf);
1345 Strbuf_append1(&patbuf, '*');
1346 Strbuf_terminate(&patbuf);
1347 }
1348 }
1349 else {
1350 Strbuf_append1(&tmpbuf, '*');
1351 Strbuf_terminate(&tmpbuf);
1352 patbuf.len = 0;
1353 Strbuf_append(&patbuf, tmpbuf.s);
1354 Strbuf_terminate(&patbuf);
1355 }
1356 cleanup_until(&tmpbuf);
1357 LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
1358 Cursor = LastChar = InputBuf;
1359 if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
1360 e_down_search_hist(0)) == CC_ERROR) {
1361 Refresh();
1362 return(CC_ERROR);
1363 }
1364 else {
1365 if (ASC(ch) == 0033) {
1366 Refresh();
1367 *LastChar++ = '\n';
1368 *LastChar = '\0';
1369 PastBottom();
1370 return(CC_NEWLINE);
1371 }
1372 else
1373 return(CC_REFRESH);
1374 }
1375}
1376
1377/*
1378 * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
1379 * entry point, called from the CcKeyMap indirected into the
1380 * CcFuncTbl array.
1381 */
1382
1383/*ARGSUSED*/
1384CCRETVAL
1385v_cmd_mode(Char c)
1386{
1387 USE(c);
1388 InsertPos = 0;
1389 ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
1390 ActionPos = 0;
1391 DoingArg = 0;
1392 if (UndoPtr > Cursor)
1393 UndoSize = (int)(UndoPtr - Cursor);
1394 else
1395 UndoSize = (int)(Cursor - UndoPtr);
1396
1397 inputmode = MODE_INSERT;
1398 c_alternativ_key_map(1);
1399#ifdef notdef
1400 /*
1401 * We don't want to move the cursor, because all the editing
1402 * commands don't include the character under the cursor.
1403 */
1404 if (Cursor > InputBuf)
1405 Cursor--;
1406#endif
1407 RefCursor();
1408 return(CC_NORM);
1409}
1410
1411/*ARGSUSED*/
1412CCRETVAL
1413e_unassigned(Char c)
1414{ /* bound to keys that arn't really assigned */
1415 USE(c);
1416 SoundBeep();
1417 flush();
1418 return(CC_NORM);
1419}
1420
1421#ifdef notyet
1422static CCRETVAL
1423e_insert_str(Char *c)
1424{
1425 int i, n;
1426
1427 n = Strlen(c);
1428 if (LastChar + Argument * n >= InputLim)
1429 return(CC_ERROR); /* end of buffer space */
1430 if (inputmode != MODE_INSERT) {
1431 c_delafter(Argument * Strlen(c));
1432 }
1433 c_insert(Argument * n);
1434 while (Argument--) {
1435 for (i = 0; i < n; i++)
1436 *Cursor++ = c[i];
1437 }
1438 Refresh();
1439 return(CC_NORM);
1440}
1441#endif
1442
1443CCRETVAL
1444e_insert(Char c)
1445{
1446#ifndef SHORT_STRINGS
1447 c &= ASCII; /* no meta chars ever */
1448#endif
1449
1450 if (!c)
1451 return(CC_ERROR); /* no NULs in the input ever!! */
1452
1453 if (LastChar + Argument >= InputLim)
1454 return(CC_ERROR); /* end of buffer space */
1455
1456 if (Argument == 1) { /* How was this optimized ???? */
1457
1458 if (inputmode != MODE_INSERT) {
1459 UndoBuf[UndoSize++] = *Cursor;
1460 UndoBuf[UndoSize] = '\0';
1461 c_delafter(1); /* Do NOT use the saving ONE */
1462 }
1463
1464 c_insert(1);
1465 *Cursor++ = (Char) c;
1466 DoingArg = 0; /* just in case */
1467 RefPlusOne(1); /* fast refresh for one char. */
1468 }
1469 else {
1470 if (inputmode != MODE_INSERT) {
1471 int i;
1472 for(i = 0; i < Argument; i++)
1473 UndoBuf[UndoSize++] = *(Cursor + i);
1474
1475 UndoBuf[UndoSize] = '\0';
1476 c_delafter(Argument); /* Do NOT use the saving ONE */
1477 }
1478
1479 c_insert(Argument);
1480
1481 while (Argument--)
1482 *Cursor++ = (Char) c;
1483 Refresh();
1484 }
1485
1486 if (inputmode == MODE_REPLACE_1)
1487 (void) v_cmd_mode(0);
1488
1489 return(CC_NORM);
1490}
1491
1492int
1493InsertStr(Char *s) /* insert ASCIZ s at cursor (for complete) */
1494{
1495 int len;
1496
1497 if ((len = (int) Strlen(s)) <= 0)
1498 return -1;
1499 if (LastChar + len >= InputLim)
1500 return -1; /* end of buffer space */
1501
1502 c_insert(len);
1503 while (len--)
1504 *Cursor++ = *s++;
1505 return 0;
1506}
1507
1508void
1509DeleteBack(int n) /* delete the n characters before . */
1510{
1511 if (n <= 0)
1512 return;
1513 if (Cursor >= &InputBuf[n]) {
1514 c_delbefore(n); /* delete before dot */
1515 }
1516}
1517
1518CCRETVAL
1519e_digit(Char c) /* gray magic here */
1520{
1521 if (!Isdigit(c))
1522 return(CC_ERROR); /* no NULs in the input ever!! */
1523
1524 if (DoingArg) { /* if doing an arg, add this in... */
1525 if (LastCmd == F_ARGFOUR) /* if last command was ^U */
1526 Argument = c - '0';
1527 else {
1528 if (Argument > 1000000)
1529 return CC_ERROR;
1530 Argument = (Argument * 10) + (c - '0');
1531 }
1532 return(CC_ARGHACK);
1533 }
1534 else {
1535 if (LastChar + 1 >= InputLim)
1536 return CC_ERROR; /* end of buffer space */
1537
1538 if (inputmode != MODE_INSERT) {
1539 UndoBuf[UndoSize++] = *Cursor;
1540 UndoBuf[UndoSize] = '\0';
1541 c_delafter(1); /* Do NOT use the saving ONE */
1542 }
1543 c_insert(1);
1544 *Cursor++ = (Char) c;
1545 DoingArg = 0; /* just in case */
1546 RefPlusOne(1); /* fast refresh for one char. */
1547 }
1548 return(CC_NORM);
1549}
1550
1551CCRETVAL
1552e_argdigit(Char c) /* for ESC-n */
1553{
1554#ifdef IS_ASCII
1555 c &= ASCII;
1556#else
1557 c = CTL_ESC(ASC(c) & ASCII); /* stripping for EBCDIC done the ASCII way */
1558#endif
1559
1560 if (!Isdigit(c))
1561 return(CC_ERROR); /* no NULs in the input ever!! */
1562
1563 if (DoingArg) { /* if doing an arg, add this in... */
1564 if (Argument > 1000000)
1565 return CC_ERROR;
1566 Argument = (Argument * 10) + (c - '0');
1567 }
1568 else { /* else starting an argument */
1569 Argument = c - '0';
1570 DoingArg = 1;
1571 }
1572 return(CC_ARGHACK);
1573}
1574
1575CCRETVAL
1576v_zero(Char c) /* command mode 0 for vi */
1577{
1578 if (DoingArg) { /* if doing an arg, add this in... */
1579 if (Argument > 1000000)
1580 return CC_ERROR;
1581 Argument = (Argument * 10) + (c - '0');
1582 return(CC_ARGHACK);
1583 }
1584 else { /* else starting an argument */
1585 Cursor = InputBuf;
1586 if (ActionFlag & TCSHOP_DELETE) {
1587 c_delfini();
1588 return(CC_REFRESH);
1589 }
1590 RefCursor(); /* move the cursor */
1591 return(CC_NORM);
1592 }
1593}
1594
1595/*ARGSUSED*/
1596CCRETVAL
1597e_newline(Char c)
1598{ /* always ignore argument */
1599 USE(c);
1600 if (adrof(STRhighlight) && MarkIsSet) {
1601 MarkIsSet = 0;
1602 ClearLines();
1603 ClearDisp();
1604 Refresh();
1605 }
1606 MarkIsSet = 0;
1607
1608 /* PastBottom(); NOW done in ed.inputl.c */
1609 *LastChar++ = '\n'; /* for the benefit of CSH */
1610 *LastChar = '\0'; /* just in case */
1611 if (VImode)
1612 InsertPos = InputBuf; /* Reset editing position */
1613 return(CC_NEWLINE);
1614}
1615
1616/*ARGSUSED*/
1617CCRETVAL
1618e_newline_hold(Char c)
1619{
1620 USE(c);
1621 c_save_inputbuf();
1622 HistSaved = 0;
1623 *LastChar++ = '\n'; /* for the benefit of CSH */
1624 *LastChar = '\0'; /* just in case */
1625 return(CC_NEWLINE);
1626}
1627
1628/*ARGSUSED*/
1629CCRETVAL
1630e_newline_down_hist(Char c)
1631{
1632 USE(c);
1633 if (Hist_num > 1) {
1634 HistSaved = Hist_num;
1635 }
1636 *LastChar++ = '\n'; /* for the benefit of CSH */
1637 *LastChar = '\0'; /* just in case */
1638 return(CC_NEWLINE);
1639}
1640
1641/*ARGSUSED*/
1642CCRETVAL
1643e_send_eof(Char c)
1644{ /* for when ^D is ONLY send-eof */
1645 USE(c);
1646 PastBottom();
1647 *LastChar = '\0'; /* just in case */
1648 return(CC_EOF);
1649}
1650
1651/*ARGSUSED*/
1652CCRETVAL
1653e_complete(Char c)
1654{
1655 USE(c);
1656 *LastChar = '\0'; /* just in case */
1657 return(CC_COMPLETE);
1658}
1659
1660/*ARGSUSED*/
1661CCRETVAL
1662e_complete_back(Char c)
1663{
1664 USE(c);
1665 *LastChar = '\0'; /* just in case */
1666 return(CC_COMPLETE_BACK);
1667}
1668
1669/*ARGSUSED*/
1670CCRETVAL
1671e_complete_fwd(Char c)
1672{
1673 USE(c);
1674 *LastChar = '\0'; /* just in case */
1675 return(CC_COMPLETE_FWD);
1676}
1677
1678/*ARGSUSED*/
1679CCRETVAL
1680e_complete_all(Char c)
1681{
1682 USE(c);
1683 *LastChar = '\0'; /* just in case */
1684 return(CC_COMPLETE_ALL);
1685}
1686
1687/*ARGSUSED*/
1688CCRETVAL
1689v_cm_complete(Char c)
1690{
1691 USE(c);
1692 if (Cursor < LastChar)
1693 Cursor++;
1694 *LastChar = '\0'; /* just in case */
1695 return(CC_COMPLETE);
1696}
1697
1698/*ARGSUSED*/
1699CCRETVAL
1700e_toggle_hist(Char c)
1701{
1702 struct Hist *hp;
1703 int h;
1704
1705 USE(c);
1706 *LastChar = '\0'; /* just in case */
1707
1708 if (Hist_num <= 0) {
1709 return CC_ERROR;
1710 }
1711
1712 hp = Histlist.Hnext;
1713 if (hp == NULL) { /* this is only if no history */
1714 return(CC_ERROR);
1715 }
1716
1717 for (h = 1; h < Hist_num; h++)
1718 hp = hp->Hnext;
1719
1720 if (!CurrentHistLit) {
1721 if (hp->histline) {
1722 copyn(InputBuf, hp->histline, INBUFSIZE);/*FIXBUF*/
1723 CurrentHistLit = 1;
1724 }
1725 else {
1726 return CC_ERROR;
1727 }
1728 }
1729 else {
1730 Char *p;
1731
1732 p = sprlex(&hp->Hlex);
1733 copyn(InputBuf, p, sizeof(InputBuf) / sizeof(Char));/*FIXBUF*/
1734 xfree(p);
1735 CurrentHistLit = 0;
1736 }
1737
1738 LastChar = Strend(InputBuf);
1739 if (LastChar > InputBuf) {
1740 if (LastChar[-1] == '\n')
1741 LastChar--;
1742 if (LastChar[-1] == ' ')
1743 LastChar--;
1744 if (LastChar < InputBuf)
1745 LastChar = InputBuf;
1746 }
1747
1748#ifdef KSHVI
1749 if (VImode)
1750 Cursor = InputBuf;
1751 else
1752#endif /* KSHVI */
1753 Cursor = LastChar;
1754
1755 return(CC_REFRESH);
1756}
1757
1758/*ARGSUSED*/
1759CCRETVAL
1760e_up_hist(Char c)
1761{
1762 Char beep = 0;
1763
1764 USE(c);
1765 UndoAction = TCSHOP_NOP;
1766 *LastChar = '\0'; /* just in case */
1767
1768 if (Hist_num == 0) { /* save the current buffer away */
1769 HistBuf.len = 0;
1770 Strbuf_append(&HistBuf, InputBuf);
1771 Strbuf_terminate(&HistBuf);
1772 }
1773
1774 Hist_num += Argument;
1775
1776 if (GetHistLine() == CC_ERROR) {
1777 beep = 1;
1778 (void) GetHistLine(); /* Hist_num was fixed by first call */
1779 }
1780
1781 Refresh();
1782 if (beep)
1783 return(CC_ERROR);
1784 else
1785 return(CC_NORM); /* was CC_UP_HIST */
1786}
1787
1788/*ARGSUSED*/
1789CCRETVAL
1790e_down_hist(Char c)
1791{
1792 USE(c);
1793 UndoAction = TCSHOP_NOP;
1794 *LastChar = '\0'; /* just in case */
1795
1796 Hist_num -= Argument;
1797
1798 if (Hist_num < 0) {
1799 Hist_num = 0;
1800 return(CC_ERROR); /* make it beep */
1801 }
1802
1803 return(GetHistLine());
1804}
1805
1806
1807
1808/*
1809 * c_hmatch() return True if the pattern matches the prefix
1810 */
1811static int
1812c_hmatch(Char *str)
1813{
1814 if (Strncmp(patbuf.s, str, patbuf.len) == 0)
1815 return 1;
1816 return Gmatch(str, patbuf.s);
1817}
1818
1819/*
1820 * c_hsetpat(): Set the history seatch pattern
1821 */
1822static void
1823c_hsetpat(void)
1824{
1825 if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1826 patbuf.len = 0;
1827 Strbuf_appendn(&patbuf, InputBuf, Cursor - InputBuf);
1828 Strbuf_terminate(&patbuf);
1829 }
1830#ifdef SDEBUG
1831 xprintf("\nHist_num = %d\n", Hist_num);
1832 xprintf("patlen = %d\n", (int)patbuf.len);
1833 xprintf("patbuf = \"%S\"\n", patbuf.s);
1834 xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
1835#endif
1836}
1837
1838/*ARGSUSED*/
1839CCRETVAL
1840e_up_search_hist(Char c)
1841{
1842 struct Hist *hp;
1843 int h;
1844 int found = 0;
1845
1846 USE(c);
1847 ActionFlag = TCSHOP_NOP;
1848 UndoAction = TCSHOP_NOP;
1849 *LastChar = '\0'; /* just in case */
1850 if (Hist_num < 0) {
1851#ifdef DEBUG_EDIT
1852 xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
1853#endif
1854 Hist_num = 0;
1855 return(CC_ERROR);
1856 }
1857
1858 if (Hist_num == 0) {
1859 HistBuf.len = 0;
1860 Strbuf_append(&HistBuf, InputBuf);
1861 Strbuf_terminate(&HistBuf);
1862 }
1863
1864
1865 hp = Histlist.Hnext;
1866 if (hp == NULL)
1867 return(CC_ERROR);
1868
1869 c_hsetpat(); /* Set search pattern !! */
1870
1871 for (h = 1; h <= Hist_num; h++)
1872 hp = hp->Hnext;
1873
1874 while (hp != NULL) {
1875 Char *hl;
1876 int matched;
1877
1878 if (hp->histline == NULL)
1879 hp->histline = sprlex(&hp->Hlex);
1880 if (HistLit)
1881 hl = hp->histline;
1882 else {
1883 hl = sprlex(&hp->Hlex);
1884 cleanup_push(hl, xfree);
1885 }
1886#ifdef SDEBUG
1887 xprintf("Comparing with \"%S\"\n", hl);
1888#endif
1889 matched = (Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1890 hl[LastChar-InputBuf]) && c_hmatch(hl);
1891 if (!HistLit)
1892 cleanup_until(hl);
1893 if (matched) {
1894 found++;
1895 break;
1896 }
1897 h++;
1898 hp = hp->Hnext;
1899 }
1900
1901 if (!found) {
1902#ifdef SDEBUG
1903 xprintf("not found\n");
1904#endif
1905 return(CC_ERROR);
1906 }
1907
1908 Hist_num = h;
1909
1910 return(GetHistLine());
1911}
1912
1913/*ARGSUSED*/
1914CCRETVAL
1915e_down_search_hist(Char c)
1916{
1917 struct Hist *hp;
1918 int h;
1919 int found = 0;
1920
1921 USE(c);
1922 ActionFlag = TCSHOP_NOP;
1923 UndoAction = TCSHOP_NOP;
1924 *LastChar = '\0'; /* just in case */
1925
1926 if (Hist_num == 0)
1927 return(CC_ERROR);
1928
1929 hp = Histlist.Hnext;
1930 if (hp == 0)
1931 return(CC_ERROR);
1932
1933 c_hsetpat(); /* Set search pattern !! */
1934
1935 for (h = 1; h < Hist_num && hp; h++) {
1936 Char *hl;
1937 if (hp->histline == NULL)
1938 hp->histline = sprlex(&hp->Hlex);
1939 if (HistLit)
1940 hl = hp->histline;
1941 else {
1942 hl = sprlex(&hp->Hlex);
1943 cleanup_push(hl, xfree);
1944 }
1945#ifdef SDEBUG
1946 xprintf("Comparing with \"%S\"\n", hl);
1947#endif
1948 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1949 hl[LastChar-InputBuf]) && c_hmatch(hl))
1950 found = h;
1951 if (!HistLit)
1952 cleanup_until(hl);
1953 hp = hp->Hnext;
1954 }
1955
1956 if (!found) { /* is it the current history number? */
1957 if (!c_hmatch(HistBuf.s)) {
1958#ifdef SDEBUG
1959 xprintf("not found\n");
1960#endif
1961 return(CC_ERROR);
1962 }
1963 }
1964
1965 Hist_num = found;
1966
1967 return(GetHistLine());
1968}
1969
1970/*ARGSUSED*/
1971CCRETVAL
1972e_helpme(Char c)
1973{
1974 USE(c);
1975 PastBottom();
1976 *LastChar = '\0'; /* just in case */
1977 return(CC_HELPME);
1978}
1979
1980/*ARGSUSED*/
1981CCRETVAL
1982e_correct(Char c)
1983{
1984 USE(c);
1985 *LastChar = '\0'; /* just in case */
1986 return(CC_CORRECT);
1987}
1988
1989/*ARGSUSED*/
1990CCRETVAL
1991e_correctl(Char c)
1992{
1993 USE(c);
1994 *LastChar = '\0'; /* just in case */
1995 return(CC_CORRECT_L);
1996}
1997
1998/*ARGSUSED*/
1999CCRETVAL
2000e_run_fg_editor(Char c)
2001{
2002 struct process *pp;
2003
2004 USE(c);
2005 if ((pp = find_stop_ed()) != NULL) {
2006 /* save our editor state so we can restore it */
2007 c_save_inputbuf();
2008 Hist_num = 0; /* for the history commands */
2009
2010 /* put the tty in a sane mode */
2011 PastBottom();
2012 (void) Cookedmode(); /* make sure the tty is set up correctly */
2013
2014 /* do it! */
2015 fg_proc_entry(pp);
2016
2017 (void) Rawmode(); /* go on */
2018 Refresh();
2019 RestoreSaved = 0;
2020 HistSaved = 0;
2021 }
2022 return(CC_NORM);
2023}
2024
2025/*ARGSUSED*/
2026CCRETVAL
2027e_list_choices(Char c)
2028{
2029 USE(c);
2030 PastBottom();
2031 *LastChar = '\0'; /* just in case */
2032 return(CC_LIST_CHOICES);
2033}
2034
2035/*ARGSUSED*/
2036CCRETVAL
2037e_list_all(Char c)
2038{
2039 USE(c);
2040 PastBottom();
2041 *LastChar = '\0'; /* just in case */
2042 return(CC_LIST_ALL);
2043}
2044
2045/*ARGSUSED*/
2046CCRETVAL
2047e_list_glob(Char c)
2048{
2049 USE(c);
2050 PastBottom();
2051 *LastChar = '\0'; /* just in case */
2052 return(CC_LIST_GLOB);
2053}
2054
2055/*ARGSUSED*/
2056CCRETVAL
2057e_expand_glob(Char c)
2058{
2059 USE(c);
2060 *LastChar = '\0'; /* just in case */
2061 return(CC_EXPAND_GLOB);
2062}
2063
2064/*ARGSUSED*/
2065CCRETVAL
2066e_normalize_path(Char c)
2067{
2068 USE(c);
2069 *LastChar = '\0'; /* just in case */
2070 return(CC_NORMALIZE_PATH);
2071}
2072
2073/*ARGSUSED*/
2074CCRETVAL
2075e_normalize_command(Char c)
2076{
2077 USE(c);
2078 *LastChar = '\0'; /* just in case */
2079 return(CC_NORMALIZE_COMMAND);
2080}
2081
2082/*ARGSUSED*/
2083CCRETVAL
2084e_expand_vars(Char c)
2085{
2086 USE(c);
2087 *LastChar = '\0'; /* just in case */
2088 return(CC_EXPAND_VARS);
2089}
2090
2091/*ARGSUSED*/
2092CCRETVAL
2093e_which(Char c)
2094{ /* do a fast command line which(1) */
2095 USE(c);
2096 c_save_inputbuf();
2097 Hist_num = 0; /* for the history commands */
2098 PastBottom();
2099 *LastChar = '\0'; /* just in case */
2100 return(CC_WHICH);
2101}
2102
2103/*ARGSUSED*/
2104CCRETVAL
2105e_last_item(Char c)
2106{ /* insert the last element of the prev. cmd */
2107 struct Hist *hp;
2108 struct wordent *wp, *firstp;
2109 int i;
2110 Char *expanded;
2111
2112 USE(c);
2113 if (Argument <= 0)
2114 return(CC_ERROR);
2115
2116 hp = Histlist.Hnext;
2117 if (hp == NULL) { /* this is only if no history */
2118 return(CC_ERROR);
2119 }
2120
2121 wp = (hp->Hlex).prev;
2122
2123 if (wp->prev == (struct wordent *) NULL)
2124 return(CC_ERROR); /* an empty history entry */
2125
2126 firstp = (hp->Hlex).next;
2127
2128 /* back up arg words in lex */
2129 for (i = 0; i < Argument && wp != firstp; i++) {
2130 wp = wp->prev;
2131 }
2132
2133 expanded = expand_lex(wp->prev, 0, i - 1);
2134 if (InsertStr(expanded)) {
2135 xfree(expanded);
2136 return(CC_ERROR);
2137 }
2138
2139 xfree(expanded);
2140 return(CC_REFRESH);
2141}
2142
2143/*ARGSUSED*/
2144CCRETVAL
2145e_dabbrev_expand(Char c)
2146{ /* expand to preceding word matching prefix */
2147 Char *cp, *ncp, *bp;
2148 struct Hist *hp;
2149 int arg = 0, i;
2150 size_t len = 0;
2151 int found = 0;
2152 Char *hbuf;
2153 static int oldevent, hist, word;
2154 static Char *start, *oldcursor;
2155
2156 USE(c);
2157 if (Argument <= 0)
2158 return(CC_ERROR);
2159
2160 cp = c_preword(Cursor, InputBuf, 1, STRshwordsep);
2161 if (cp == Cursor || Isspace(*cp))
2162 return(CC_ERROR);
2163
2164 hbuf = NULL;
2165 hp = Histlist.Hnext;
2166 bp = InputBuf;
2167 if (Argument == 1 && eventno == oldevent && cp == start &&
2168 Cursor == oldcursor && patbuf.len > 0
2169 && Strncmp(patbuf.s, cp, patbuf.len) == 0){
2170 /* continue previous search - go to last match (hist/word) */
2171 if (hist != 0) { /* need to move up history */
2172 for (i = 1; i < hist && hp != NULL; i++)
2173 hp = hp->Hnext;
2174 if (hp == NULL) /* "can't happen" */
2175 goto err_hbuf;
2176 hbuf = expand_lex(&hp->Hlex, 0, INT_MAX);
2177 cp = Strend(hbuf);
2178 bp = hbuf;
2179 hp = hp->Hnext;
2180 }
2181 cp = c_preword(cp, bp, word, STRshwordsep);
2182 } else { /* starting new search */
2183 oldevent = eventno;
2184 start = cp;
2185 patbuf.len = 0;
2186 Strbuf_appendn(&patbuf, cp, Cursor - cp);
2187 hist = 0;
2188 word = 0;
2189 }
2190
2191 while (!found) {
2192 ncp = c_preword(cp, bp, 1, STRshwordsep);
2193 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
2194 hist++;
2195 word = 0;
2196 if (hp == NULL)
2197 goto err_hbuf;
2198 hbuf = expand_lex(&hp->Hlex, 0, INT_MAX);
2199 cp = Strend(hbuf);
2200 bp = hbuf;
2201 hp = hp->Hnext;
2202 continue;
2203 } else {
2204 word++;
2205 len = c_endword(ncp-1, cp, 1, STRshwordsep) - ncp + 1;
2206 cp = ncp;
2207 }
2208 if (len > patbuf.len && Strncmp(cp, patbuf.s, patbuf.len) == 0) {
2209 /* We don't fully check distinct matches as Gnuemacs does: */
2210 if (Argument > 1) { /* just count matches */
2211 if (++arg >= Argument)
2212 found++;
2213 } else { /* match if distinct from previous */
2214 if (len != (size_t)(Cursor - start)
2215 || Strncmp(cp, start, len) != 0)
2216 found++;
2217 }
2218 }
2219 }
2220
2221 if (LastChar + len - (Cursor - start) >= InputLim)
2222 goto err_hbuf; /* no room */
2223 DeleteBack(Cursor - start);
2224 c_insert(len);
2225 while (len--)
2226 *Cursor++ = *cp++;
2227 oldcursor = Cursor;
2228 xfree(hbuf);
2229 return(CC_REFRESH);
2230
2231 err_hbuf:
2232 xfree(hbuf);
2233 return CC_ERROR;
2234}
2235
2236/*ARGSUSED*/
2237CCRETVAL
2238e_yank_kill(Char c)
2239{ /* almost like GnuEmacs */
2240 int len;
2241 Char *kp, *cp;
2242
2243 USE(c);
2244 if (KillRingLen == 0) /* nothing killed */
2245 return(CC_ERROR);
2246 len = Strlen(KillRing[YankPos].buf);
2247 if (LastChar + len >= InputLim)
2248 return(CC_ERROR); /* end of buffer space */
2249
2250 /* else */
2251 cp = Cursor; /* for speed */
2252
2253 c_insert(len); /* open the space, */
2254 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2255 *cp++ = *kp;
2256
2257 if (Argument == 1) { /* if no arg */
2258 Mark = Cursor; /* mark at beginning, cursor at end */
2259 Cursor = cp;
2260 } else {
2261 Mark = cp; /* else cursor at beginning, mark at end */
2262 }
2263
2264 if (adrof(STRhighlight) && MarkIsSet) {
2265 ClearLines();
2266 ClearDisp();
2267 }
2268 MarkIsSet = 0;
2269 return(CC_REFRESH);
2270}
2271
2272/*ARGSUSED*/
2273CCRETVAL
2274e_yank_pop(Char c)
2275{ /* almost like GnuEmacs */
2276 int m_bef_c, del_len, ins_len;
2277 Char *kp, *cp;
2278
2279 USE(c);
2280
2281#if 0
2282 /* XXX This "should" be here, but doesn't work, since LastCmd
2283 gets set on CC_ERROR and CC_ARGHACK, which it shouldn't(?).
2284 (But what about F_ARGFOUR?) I.e. if you hit M-y twice the
2285 second one will "succeed" even if the first one wasn't preceded
2286 by a yank, and giving an argument is impossible. Now we "succeed"
2287 regardless of previous command, which is wrong too of course. */
2288 if (LastCmd != F_YANK_KILL && LastCmd != F_YANK_POP)
2289 return(CC_ERROR);
2290#endif
2291
2292 if (KillRingLen == 0) /* nothing killed */
2293 return(CC_ERROR);
2294 YankPos -= Argument;
2295 while (YankPos < 0)
2296 YankPos += KillRingLen;
2297 YankPos %= KillRingLen;
2298
2299 if (Cursor > Mark) {
2300 del_len = Cursor - Mark;
2301 m_bef_c = 1;
2302 } else {
2303 del_len = Mark - Cursor;
2304 m_bef_c = 0;
2305 }
2306 ins_len = Strlen(KillRing[YankPos].buf);
2307 if (LastChar + ins_len - del_len >= InputLim)
2308 return(CC_ERROR); /* end of buffer space */
2309
2310 if (m_bef_c) {
2311 c_delbefore(del_len);
2312 } else {
2313 c_delafter(del_len);
2314 }
2315 cp = Cursor; /* for speed */
2316
2317 c_insert(ins_len); /* open the space, */
2318 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2319 *cp++ = *kp;
2320
2321 if (m_bef_c) {
2322 Mark = Cursor; /* mark at beginning, cursor at end */
2323 Cursor = cp;
2324 } else {
2325 Mark = cp; /* else cursor at beginning, mark at end */
2326 }
2327
2328 if (adrof(STRhighlight) && MarkIsSet) {
2329 ClearLines();
2330 ClearDisp();
2331 }
2332 MarkIsSet = 0;
2333 return(CC_REFRESH);
2334}
2335
2336/*ARGSUSED*/
2337CCRETVAL
2338v_delprev(Char c) /* Backspace key in insert mode */
2339{
2340 int rc;
2341
2342 USE(c);
2343 rc = CC_ERROR;
2344
2345 if (InsertPos != 0) {
2346 if (Argument <= Cursor - InsertPos) {
2347 c_delbefore(Argument); /* delete before */
2348 rc = CC_REFRESH;
2349 }
2350 }
2351 return(rc);
2352} /* v_delprev */
2353
2354/*ARGSUSED*/
2355CCRETVAL
2356e_delprev(Char c)
2357{
2358 USE(c);
2359 if (Cursor > InputBuf) {
2360 c_delbefore(Argument); /* delete before dot */
2361 return(CC_REFRESH);
2362 }
2363 else {
2364 return(CC_ERROR);
2365 }
2366}
2367
2368/*ARGSUSED*/
2369CCRETVAL
2370e_delwordprev(Char c)
2371{
2372 Char *cp;
2373
2374 USE(c);
2375 if (Cursor == InputBuf)
2376 return(CC_ERROR);
2377 /* else */
2378
2379 cp = c_prev_word(Cursor, InputBuf, Argument);
2380
2381 c_push_kill(cp, Cursor); /* save the text */
2382
2383 c_delbefore((int)(Cursor - cp)); /* delete before dot */
2384 return(CC_REFRESH);
2385}
2386
2387/* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
2388 *
2389 * Changed the names of some of the ^D family of editor functions to
2390 * correspond to what they actually do and created new e_delnext_list
2391 * for completeness.
2392 *
2393 * Old names: New names:
2394 *
2395 * delete-char delete-char-or-eof
2396 * F_DELNEXT F_DELNEXT_EOF
2397 * e_delnext e_delnext_eof
2398 * edelnxt edelnxteof
2399 * delete-char-or-eof delete-char
2400 * F_DELNEXT_EOF F_DELNEXT
2401 * e_delnext_eof e_delnext
2402 * edelnxteof edelnxt
2403 * delete-char-or-list delete-char-or-list-or-eof
2404 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
2405 * e_list_delnext e_delnext_list_eof
2406 * edellsteof
2407 * (no old equivalent) delete-char-or-list
2408 * F_DELNEXT_LIST
2409 * e_delnext_list
2410 * e_delnxtlst
2411 */
2412
2413/* added by mtk@ari.ncl.omron.co.jp (920818) */
2414/* rename e_delnext() -> e_delnext_eof() */
2415/*ARGSUSED*/
2416CCRETVAL
2417e_delnext(Char c)
2418{
2419 USE(c);
2420 if (Cursor == LastChar) {/* if I'm at the end */
2421 if (!VImode) {
2422 return(CC_ERROR);
2423 }
2424 else {
2425 if (Cursor != InputBuf)
2426 Cursor--;
2427 else
2428 return(CC_ERROR);
2429 }
2430 }
2431 c_delafter(Argument); /* delete after dot */
2432 if (Cursor > LastChar)
2433 Cursor = LastChar; /* bounds check */
2434 return(CC_REFRESH);
2435}
2436
2437
2438/*ARGSUSED*/
2439CCRETVAL
2440e_delnext_eof(Char c)
2441{
2442 USE(c);
2443 if (Cursor == LastChar) {/* if I'm at the end */
2444 if (!VImode) {
2445 if (Cursor == InputBuf) {
2446 /* if I'm also at the beginning */
2447 so_write(STReof, 4);/* then do a EOF */
2448 flush();
2449 return(CC_EOF);
2450 }
2451 else
2452 return(CC_ERROR);
2453 }
2454 else {
2455 if (Cursor != InputBuf)
2456 Cursor--;
2457 else
2458 return(CC_ERROR);
2459 }
2460 }
2461 c_delafter(Argument); /* delete after dot */
2462 if (Cursor > LastChar)
2463 Cursor = LastChar; /* bounds check */
2464 return(CC_REFRESH);
2465}
2466
2467/*ARGSUSED*/
2468CCRETVAL
2469e_delnext_list(Char c)
2470{
2471 USE(c);
2472 if (Cursor == LastChar) { /* if I'm at the end */
2473 PastBottom();
2474 *LastChar = '\0'; /* just in case */
2475 return(CC_LIST_CHOICES);
2476 }
2477 else {
2478 c_delafter(Argument); /* delete after dot */
2479 if (Cursor > LastChar)
2480 Cursor = LastChar; /* bounds check */
2481 return(CC_REFRESH);
2482 }
2483}
2484
2485/*ARGSUSED*/
2486CCRETVAL
2487e_delnext_list_eof(Char c)
2488{
2489 USE(c);
2490 if (Cursor == LastChar) { /* if I'm at the end */
2491 if (Cursor == InputBuf) { /* if I'm also at the beginning */
2492 so_write(STReof, 4);/* then do a EOF */
2493 flush();
2494 return(CC_EOF);
2495 }
2496 else {
2497 PastBottom();
2498 *LastChar = '\0'; /* just in case */
2499 return(CC_LIST_CHOICES);
2500 }
2501 }
2502 else {
2503 c_delafter(Argument); /* delete after dot */
2504 if (Cursor > LastChar)
2505 Cursor = LastChar; /* bounds check */
2506 return(CC_REFRESH);
2507 }
2508}
2509
2510/*ARGSUSED*/
2511CCRETVAL
2512e_list_eof(Char c)
2513{
2514 CCRETVAL rv;
2515
2516 USE(c);
2517 if (Cursor == LastChar && Cursor == InputBuf) {
2518 so_write(STReof, 4); /* then do a EOF */
2519 flush();
2520 rv = CC_EOF;
2521 }
2522 else {
2523 PastBottom();
2524 *LastChar = '\0'; /* just in case */
2525 rv = CC_LIST_CHOICES;
2526 }
2527 return rv;
2528}
2529
2530/*ARGSUSED*/
2531CCRETVAL
2532e_delwordnext(Char c)
2533{
2534 Char *cp;
2535
2536 USE(c);
2537 if (Cursor == LastChar)
2538 return(CC_ERROR);
2539 /* else */
2540
2541 cp = c_next_word(Cursor, LastChar, Argument);
2542
2543 c_push_kill(Cursor, cp); /* save the text */
2544
2545 c_delafter((int)(cp - Cursor)); /* delete after dot */
2546 if (Cursor > LastChar)
2547 Cursor = LastChar; /* bounds check */
2548 return(CC_REFRESH);
2549}
2550
2551/*ARGSUSED*/
2552CCRETVAL
2553e_toend(Char c)
2554{
2555 USE(c);
2556 Cursor = LastChar;
2557 if (VImode)
2558 if (ActionFlag & TCSHOP_DELETE) {
2559 c_delfini();
2560 return(CC_REFRESH);
2561 }
2562 RefCursor(); /* move the cursor */
2563 return(CC_NORM);
2564}
2565
2566/*ARGSUSED*/
2567CCRETVAL
2568e_tobeg(Char c)
2569{
2570 USE(c);
2571 Cursor = InputBuf;
2572
2573 if (VImode) {
2574 while (Isspace(*Cursor)) /* We want FIRST non space character */
2575 Cursor++;
2576 if (ActionFlag & TCSHOP_DELETE) {
2577 c_delfini();
2578 return(CC_REFRESH);
2579 }
2580 }
2581
2582 RefCursor(); /* move the cursor */
2583 return(CC_NORM);
2584}
2585
2586/*ARGSUSED*/
2587CCRETVAL
2588e_killend(Char c)
2589{
2590 USE(c);
2591 c_push_kill(Cursor, LastChar); /* copy it */
2592 LastChar = Cursor; /* zap! -- delete to end */
2593 if (Mark > Cursor)
2594 Mark = Cursor;
2595 MarkIsSet = 0;
2596 return(CC_REFRESH);
2597}
2598
2599
2600/*ARGSUSED*/
2601CCRETVAL
2602e_killbeg(Char c)
2603{
2604 USE(c);
2605 c_push_kill(InputBuf, Cursor); /* copy it */
2606 c_delbefore((int)(Cursor - InputBuf));
2607 if (Mark && Mark > Cursor)
2608 Mark -= Cursor-InputBuf;
2609 return(CC_REFRESH);
2610}
2611
2612/*ARGSUSED*/
2613CCRETVAL
2614e_killall(Char c)
2615{
2616 USE(c);
2617 c_push_kill(InputBuf, LastChar); /* copy it */
2618 Cursor = Mark = LastChar = InputBuf; /* zap! -- delete all of it */
2619 MarkIsSet = 0;
2620 return(CC_REFRESH);
2621}
2622
2623/*ARGSUSED*/
2624CCRETVAL
2625e_killregion(Char c)
2626{
2627 USE(c);
2628 if (!Mark)
2629 return(CC_ERROR);
2630
2631 if (Mark > Cursor) {
2632 c_push_kill(Cursor, Mark); /* copy it */
2633 c_delafter((int)(Mark - Cursor)); /* delete it - UNUSED BY VI mode */
2634 Mark = Cursor;
2635 }
2636 else { /* mark is before cursor */
2637 c_push_kill(Mark, Cursor); /* copy it */
2638 c_delbefore((int)(Cursor - Mark));
2639 }
2640 if (adrof(STRhighlight) && MarkIsSet) {
2641 ClearLines();
2642 ClearDisp();
2643 }
2644 MarkIsSet = 0;
2645 return(CC_REFRESH);
2646}
2647
2648/*ARGSUSED*/
2649CCRETVAL
2650e_copyregion(Char c)
2651{
2652 USE(c);
2653 if (!Mark)
2654 return(CC_ERROR);
2655
2656 if (Mark > Cursor) {
2657 c_push_kill(Cursor, Mark); /* copy it */
2658 }
2659 else { /* mark is before cursor */
2660 c_push_kill(Mark, Cursor); /* copy it */
2661 }
2662 return(CC_NORM); /* don't even need to Refresh() */
2663}
2664
2665/*ARGSUSED*/
2666CCRETVAL
2667e_charswitch(Char cc)
2668{
2669 Char c;
2670
2671 USE(cc);
2672
2673 /* do nothing if we are at beginning of line or have only one char */
2674 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
2675 return(CC_ERROR);
2676 }
2677
2678 if (Cursor < LastChar) {
2679 Cursor++;
2680 }
2681 c = Cursor[-2];
2682 Cursor[-2] = Cursor[-1];
2683 Cursor[-1] = c;
2684 return(CC_REFRESH);
2685}
2686
2687/*ARGSUSED*/
2688CCRETVAL
2689e_gcharswitch(Char cc)
2690{ /* gosmacs style ^T */
2691 Char c;
2692
2693 USE(cc);
2694 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
2695 c = Cursor[-2];
2696 Cursor[-2] = Cursor[-1];
2697 Cursor[-1] = c;
2698 return(CC_REFRESH);
2699 }
2700 else {
2701 return(CC_ERROR);
2702 }
2703}
2704
2705/*ARGSUSED*/
2706CCRETVAL
2707e_charback(Char c)
2708{
2709 USE(c);
2710 if (Cursor > InputBuf) {
2711 if (Argument > Cursor - InputBuf)
2712 Cursor = InputBuf;
2713 else
2714 Cursor -= Argument;
2715
2716 if (VImode)
2717 if (ActionFlag & TCSHOP_DELETE) {
2718 c_delfini();
2719 return(CC_REFRESH);
2720 }
2721
2722 RefCursor();
2723 return(CC_NORM);
2724 }
2725 else {
2726 return(CC_ERROR);
2727 }
2728}
2729
2730/*ARGSUSED*/
2731CCRETVAL
2732v_wordback(Char c)
2733{
2734 USE(c);
2735 if (Cursor == InputBuf)
2736 return(CC_ERROR);
2737 /* else */
2738
2739 Cursor = c_preword(Cursor, InputBuf, Argument, STRshwspace); /* bounds check */
2740
2741 if (ActionFlag & TCSHOP_DELETE) {
2742 c_delfini();
2743 return(CC_REFRESH);
2744 }
2745
2746 RefCursor();
2747 return(CC_NORM);
2748}
2749
2750/*ARGSUSED*/
2751CCRETVAL
2752e_wordback(Char c)
2753{
2754 USE(c);
2755 if (Cursor == InputBuf)
2756 return(CC_ERROR);
2757 /* else */
2758
2759 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
2760
2761 if (VImode)
2762 if (ActionFlag & TCSHOP_DELETE) {
2763 c_delfini();
2764 return(CC_REFRESH);
2765 }
2766
2767 RefCursor();
2768 return(CC_NORM);
2769}
2770
2771/*ARGSUSED*/
2772CCRETVAL
2773e_charfwd(Char c)
2774{
2775 USE(c);
2776 if (Cursor < LastChar) {
2777 Cursor += Argument;
2778 if (Cursor > LastChar)
2779 Cursor = LastChar;
2780
2781 if (VImode)
2782 if (ActionFlag & TCSHOP_DELETE) {
2783 c_delfini();
2784 return(CC_REFRESH);
2785 }
2786
2787 RefCursor();
2788 return(CC_NORM);
2789 }
2790 else {
2791 return(CC_ERROR);
2792 }
2793}
2794
2795/*ARGSUSED*/
2796CCRETVAL
2797e_wordfwd(Char c)
2798{
2799 USE(c);
2800 if (Cursor == LastChar)
2801 return(CC_ERROR);
2802 /* else */
2803
2804 Cursor = c_next_word(Cursor, LastChar, Argument);
2805
2806 if (VImode)
2807 if (ActionFlag & TCSHOP_DELETE) {
2808 c_delfini();
2809 return(CC_REFRESH);
2810 }
2811
2812 RefCursor();
2813 return(CC_NORM);
2814}
2815
2816/*ARGSUSED*/
2817CCRETVAL
2818v_wordfwd(Char c)
2819{
2820 USE(c);
2821 if (Cursor == LastChar)
2822 return(CC_ERROR);
2823 /* else */
2824
2825 Cursor = c_nexword(Cursor, LastChar, Argument);
2826
2827 if (VImode)
2828 if (ActionFlag & TCSHOP_DELETE) {
2829 c_delfini();
2830 return(CC_REFRESH);
2831 }
2832
2833 RefCursor();
2834 return(CC_NORM);
2835}
2836
2837/*ARGSUSED*/
2838CCRETVAL
2839v_wordbegnext(Char c)
2840{
2841 USE(c);
2842 if (Cursor == LastChar)
2843 return(CC_ERROR);
2844 /* else */
2845
2846 Cursor = c_next_word(Cursor, LastChar, Argument);
2847 if (Cursor < LastChar)
2848 Cursor++;
2849
2850 if (VImode)
2851 if (ActionFlag & TCSHOP_DELETE) {
2852 c_delfini();
2853 return(CC_REFRESH);
2854 }
2855
2856 RefCursor();
2857 return(CC_NORM);
2858}
2859
2860/*ARGSUSED*/
2861static CCRETVAL
2862v_repeat_srch(int c)
2863{
2864 CCRETVAL rv = CC_ERROR;
2865#ifdef SDEBUG
2866 xprintf("dir %d patlen %d patbuf %S\n",
2867 c, (int)patbuf.len, patbuf.s);
2868#endif
2869
2870 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
2871 LastChar = InputBuf;
2872 switch (c) {
2873 case F_DOWN_SEARCH_HIST:
2874 rv = e_down_search_hist(0);
2875 break;
2876 case F_UP_SEARCH_HIST:
2877 rv = e_up_search_hist(0);
2878 break;
2879 default:
2880 break;
2881 }
2882 return rv;
2883}
2884
2885static CCRETVAL
2886v_csearch_back(Char ch, int count, int tflag)
2887{
2888 Char *cp;
2889
2890 cp = Cursor;
2891 while (count--) {
2892 if (*cp == ch)
2893 cp--;
2894 while (cp > InputBuf && *cp != ch)
2895 cp--;
2896 }
2897
2898 if (cp < InputBuf || (cp == InputBuf && *cp != ch))
2899 return(CC_ERROR);
2900
2901 if (*cp == ch && tflag)
2902 cp++;
2903
2904 Cursor = cp;
2905
2906 if (ActionFlag & TCSHOP_DELETE) {
2907 Cursor++;
2908 c_delfini();
2909 return(CC_REFRESH);
2910 }
2911
2912 RefCursor();
2913 return(CC_NORM);
2914}
2915
2916static CCRETVAL
2917v_csearch_fwd(Char ch, int count, int tflag)
2918{
2919 Char *cp;
2920
2921 cp = Cursor;
2922 while (count--) {
2923 if(*cp == ch)
2924 cp++;
2925 while (cp < LastChar && *cp != ch)
2926 cp++;
2927 }
2928
2929 if (cp >= LastChar)
2930 return(CC_ERROR);
2931
2932 if (*cp == ch && tflag)
2933 cp--;
2934
2935 Cursor = cp;
2936
2937 if (ActionFlag & TCSHOP_DELETE) {
2938 Cursor++;
2939 c_delfini();
2940 return(CC_REFRESH);
2941 }
2942 RefCursor();
2943 return(CC_NORM);
2944}
2945
2946/*ARGSUSED*/
2947static CCRETVAL
2948v_action(int c)
2949{
2950 Char *cp, *kp;
2951
2952 if (ActionFlag == TCSHOP_DELETE) {
2953 ActionFlag = TCSHOP_NOP;
2954 ActionPos = 0;
2955
2956 UndoSize = 0;
2957 kp = UndoBuf;
2958 for (cp = InputBuf; cp < LastChar; cp++) {
2959 *kp++ = *cp;
2960 UndoSize++;
2961 }
2962
2963 UndoAction = TCSHOP_INSERT;
2964 UndoPtr = InputBuf;
2965 LastChar = InputBuf;
2966 Cursor = InputBuf;
2967 if (c & TCSHOP_INSERT)
2968 c_alternativ_key_map(0);
2969
2970 return(CC_REFRESH);
2971 }
2972#ifdef notdef
2973 else if (ActionFlag == TCSHOP_NOP) {
2974#endif
2975 ActionPos = Cursor;
2976 ActionFlag = c;
2977 return(CC_ARGHACK); /* Do NOT clear out argument */
2978#ifdef notdef
2979 }
2980 else {
2981 ActionFlag = 0;
2982 ActionPos = 0;
2983 return(CC_ERROR);
2984 }
2985#endif
2986}
2987
2988#ifdef COMMENT
2989/* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
2990static void
2991c_get_word(Char **begin, Char **end)
2992{
2993 Char *cp;
2994
2995 cp = &Cursor[0];
2996 while (Argument--) {
2997 while ((cp <= LastChar) && (isword(*cp)))
2998 cp++;
2999 *end = --cp;
3000 while ((cp >= InputBuf) && (isword(*cp)))
3001 cp--;
3002 *begin = ++cp;
3003 }
3004}
3005#endif /* COMMENT */
3006
3007/*ARGSUSED*/
3008CCRETVAL
3009e_uppercase(Char c)
3010{
3011 Char *cp, *end;
3012
3013 USE(c);
3014 end = c_next_word(Cursor, LastChar, Argument);
3015
3016 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
3017 if (Islower(*cp))
3018 *cp = Toupper(*cp);
3019
3020 Cursor = end;
3021 if (Cursor > LastChar)
3022 Cursor = LastChar;
3023 return(CC_REFRESH);
3024}
3025
3026
3027/*ARGSUSED*/
3028CCRETVAL
3029e_capitolcase(Char c)
3030{
3031 Char *cp, *end;
3032
3033 USE(c);
3034 end = c_next_word(Cursor, LastChar, Argument);
3035
3036 cp = Cursor;
3037 for (; cp < end; cp++) {
3038 if (Isalpha(*cp)) {
3039 if (Islower(*cp))
3040 *cp = Toupper(*cp);
3041 cp++;
3042 break;
3043 }
3044 }
3045 for (; cp < end; cp++)
3046 if (Isupper(*cp))
3047 *cp = Tolower(*cp);
3048
3049 Cursor = end;
3050 if (Cursor > LastChar)
3051 Cursor = LastChar;
3052 return(CC_REFRESH);
3053}
3054
3055/*ARGSUSED*/
3056CCRETVAL
3057e_lowercase(Char c)
3058{
3059 Char *cp, *end;
3060
3061 USE(c);
3062 end = c_next_word(Cursor, LastChar, Argument);
3063
3064 for (cp = Cursor; cp < end; cp++)
3065 if (Isupper(*cp))
3066 *cp = Tolower(*cp);
3067
3068 Cursor = end;
3069 if (Cursor > LastChar)
3070 Cursor = LastChar;
3071 return(CC_REFRESH);
3072}
3073
3074
3075/*ARGSUSED*/
3076CCRETVAL
3077e_set_mark(Char c)
3078{
3079 USE(c);
3080 if (adrof(STRhighlight) && MarkIsSet && Mark != Cursor) {
3081 ClearLines();
3082 ClearDisp();
3083 Refresh();
3084 }
3085 Mark = Cursor;
3086 MarkIsSet = 1;
3087 return(CC_NORM);
3088}
3089
3090/*ARGSUSED*/
3091CCRETVAL
3092e_exchange_mark(Char c)
3093{
3094 Char *cp;
3095
3096 USE(c);
3097 cp = Cursor;
3098 Cursor = Mark;
3099 Mark = cp;
3100 RefCursor();
3101 return(CC_NORM);
3102}
3103
3104/*ARGSUSED*/
3105CCRETVAL
3106e_argfour(Char c)
3107{ /* multiply current argument by 4 */
3108 USE(c);
3109 if (Argument > 1000000)
3110 return CC_ERROR;
3111 DoingArg = 1;
3112 Argument *= 4;
3113 return(CC_ARGHACK);
3114}
3115
3116static void
3117quote_mode_cleanup(void *unused)
3118{
3119 USE(unused);
3120 QuoteModeOff();
3121}
3122
3123/*ARGSUSED*/
3124CCRETVAL
3125e_quote(Char c)
3126{
3127 Char ch;
3128 int num;
3129
3130 USE(c);
3131 QuoteModeOn();
3132 cleanup_push(&c, quote_mode_cleanup); /* Using &c just as a mark */
3133 num = GetNextChar(&ch);
3134 cleanup_until(&c);
3135 if (num == 1)
3136 return e_insert(ch);
3137 else
3138 return e_send_eof(0);
3139}
3140
3141/*ARGSUSED*/
3142CCRETVAL
3143e_metanext(Char c)
3144{
3145 USE(c);
3146 MetaNext = 1;
3147 return(CC_ARGHACK); /* preserve argument */
3148}
3149
3150#ifdef notdef
3151/*ARGSUSED*/
3152CCRETVAL
3153e_extendnext(Char c)
3154{
3155 CurrentKeyMap = CcAltMap;
3156 return(CC_ARGHACK); /* preserve argument */
3157}
3158
3159#endif
3160
3161/*ARGSUSED*/
3162CCRETVAL
3163v_insbeg(Char c)
3164{ /* move to beginning of line and start vi
3165 * insert mode */
3166 USE(c);
3167 Cursor = InputBuf;
3168 InsertPos = Cursor;
3169
3170 UndoPtr = Cursor;
3171 UndoAction = TCSHOP_DELETE;
3172
3173 RefCursor(); /* move the cursor */
3174 c_alternativ_key_map(0);
3175 return(CC_NORM);
3176}
3177
3178/*ARGSUSED*/
3179CCRETVAL
3180v_replone(Char c)
3181{ /* vi mode overwrite one character */
3182 USE(c);
3183 c_alternativ_key_map(0);
3184 inputmode = MODE_REPLACE_1;
3185 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3186 UndoPtr = Cursor;
3187 UndoSize = 0;
3188 return(CC_NORM);
3189}
3190
3191/*ARGSUSED*/
3192CCRETVAL
3193v_replmode(Char c)
3194{ /* vi mode start overwriting */
3195 USE(c);
3196 c_alternativ_key_map(0);
3197 inputmode = MODE_REPLACE;
3198 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3199 UndoPtr = Cursor;
3200 UndoSize = 0;
3201 return(CC_NORM);
3202}
3203
3204/*ARGSUSED*/
3205CCRETVAL
3206v_substchar(Char c)
3207{ /* vi mode substitute for one char */
3208 USE(c);
3209 c_delafter(Argument);
3210 c_alternativ_key_map(0);
3211 return(CC_REFRESH);
3212}
3213
3214/*ARGSUSED*/
3215CCRETVAL
3216v_substline(Char c)
3217{ /* vi mode replace whole line */
3218 USE(c);
3219 (void) e_killall(0);
3220 c_alternativ_key_map(0);
3221 return(CC_REFRESH);
3222}
3223
3224/*ARGSUSED*/
3225CCRETVAL
3226v_chgtoend(Char c)
3227{ /* vi mode change to end of line */
3228 USE(c);
3229 (void) e_killend(0);
3230 c_alternativ_key_map(0);
3231 return(CC_REFRESH);
3232}
3233
3234/*ARGSUSED*/
3235CCRETVAL
3236v_insert(Char c)
3237{ /* vi mode start inserting */
3238 USE(c);
3239 c_alternativ_key_map(0);
3240
3241 InsertPos = Cursor;
3242 UndoPtr = Cursor;
3243 UndoAction = TCSHOP_DELETE;
3244
3245 return(CC_NORM);
3246}
3247
3248/*ARGSUSED*/
3249CCRETVAL
3250v_add(Char c)
3251{ /* vi mode start adding */
3252 USE(c);
3253 c_alternativ_key_map(0);
3254 if (Cursor < LastChar)
3255 {
3256 Cursor++;
3257 if (Cursor > LastChar)
3258 Cursor = LastChar;
3259 RefCursor();
3260 }
3261
3262 InsertPos = Cursor;
3263 UndoPtr = Cursor;
3264 UndoAction = TCSHOP_DELETE;
3265
3266 return(CC_NORM);
3267}
3268
3269/*ARGSUSED*/
3270CCRETVAL
3271v_addend(Char c)
3272{ /* vi mode to add at end of line */
3273 USE(c);
3274 c_alternativ_key_map(0);
3275 Cursor = LastChar;
3276
3277 InsertPos = LastChar; /* Mark where insertion begins */
3278 UndoPtr = LastChar;
3279 UndoAction = TCSHOP_DELETE;
3280
3281 RefCursor();
3282 return(CC_NORM);
3283}
3284
3285/*ARGSUSED*/
3286CCRETVAL
3287v_change_case(Char cc)
3288{
3289 Char c;
3290
3291 USE(cc);
3292 if (Cursor < LastChar) {
3293#ifndef WINNT_NATIVE
3294 c = *Cursor;
3295#else
3296 c = CHAR & *Cursor;
3297#endif /* WINNT_NATIVE */
3298 if (Isupper(c))
3299 *Cursor++ = Tolower(c);
3300 else if (Islower(c))
3301 *Cursor++ = Toupper(c);
3302 else
3303 Cursor++;
3304 RefPlusOne(1); /* fast refresh for one char */
3305 return(CC_NORM);
3306 }
3307 return(CC_ERROR);
3308}
3309
3310/*ARGSUSED*/
3311CCRETVAL
3312e_expand(Char c)
3313{
3314 Char *p;
3315
3316 USE(c);
3317 for (p = InputBuf; Isspace(*p); p++)
3318 continue;
3319 if (p == LastChar)
3320 return(CC_ERROR);
3321
3322 justpr++;
3323 Expand++;
3324 return(e_newline(0));
3325}
3326
3327/*ARGSUSED*/
3328CCRETVAL
3329e_startover(Char c)
3330{ /* erase all of current line, start again */
3331 USE(c);
3332 ResetInLine(0); /* reset the input pointers */
3333 return(CC_REFRESH);
3334}
3335
3336/*ARGSUSED*/
3337CCRETVAL
3338e_redisp(Char c)
3339{
3340 USE(c);
3341 ClearLines();
3342 ClearDisp();
3343 return(CC_REFRESH);
3344}
3345
3346/*ARGSUSED*/
3347CCRETVAL
3348e_cleardisp(Char c)
3349{
3350 USE(c);
3351 ClearScreen(); /* clear the whole real screen */
3352 ClearDisp(); /* reset everything */
3353 return(CC_REFRESH);
3354}
3355
3356/*ARGSUSED*/
3357CCRETVAL
3358e_tty_int(Char c)
3359{
3360 USE(c);
3361#if defined(_MINIX) || defined(WINNT_NATIVE)
3362 /* SAK PATCH: erase all of current line, start again */
3363 ResetInLine(0); /* reset the input pointers */
3364 xputchar('\n');
3365 ClearDisp();
3366 return (CC_REFRESH);
3367#else /* !_MINIX && !WINNT_NATIVE */
3368 /* do no editing */
3369 return (CC_NORM);
3370#endif /* _MINIX || WINNT_NATIVE */
3371}
3372
3373/*
3374 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
3375 * Function to send a character back to the input stream in cooked
3376 * mode. Only works if we have TIOCSTI
3377 */
3378/*ARGSUSED*/
3379CCRETVAL
3380e_stuff_char(Char c)
3381{
3382#ifdef TIOCSTI
3383 int was_raw = Tty_raw_mode;
3384 char buf[MB_LEN_MAX];
3385 size_t i, len;
3386
3387 if (was_raw)
3388 (void) Cookedmode();
3389
3390 (void) xwrite(SHIN, "\n", 1);
3391 len = one_wctomb(buf, c & CHAR);
3392 for (i = 0; i < len; i++)
3393 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &buf[i]);
3394
3395 if (was_raw)
3396 (void) Rawmode();
3397 return(e_redisp(c));
3398#else /* !TIOCSTI */
3399 return(CC_ERROR);
3400#endif /* !TIOCSTI */
3401}
3402
3403/*ARGSUSED*/
3404CCRETVAL
3405e_insovr(Char c)
3406{
3407 USE(c);
3408 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
3409 return(CC_NORM);
3410}
3411
3412/*ARGSUSED*/
3413CCRETVAL
3414e_tty_dsusp(Char c)
3415{
3416 USE(c);
3417 /* do no editing */
3418 return(CC_NORM);
3419}
3420
3421/*ARGSUSED*/
3422CCRETVAL
3423e_tty_flusho(Char c)
3424{
3425 USE(c);
3426 /* do no editing */
3427 return(CC_NORM);
3428}
3429
3430/*ARGSUSED*/
3431CCRETVAL
3432e_tty_quit(Char c)
3433{
3434 USE(c);
3435 /* do no editing */
3436 return(CC_NORM);
3437}
3438
3439/*ARGSUSED*/
3440CCRETVAL
3441e_tty_tsusp(Char c)
3442{
3443 USE(c);
3444 /* do no editing */
3445 return(CC_NORM);
3446}
3447
3448/*ARGSUSED*/
3449CCRETVAL
3450e_tty_stopo(Char c)
3451{
3452 USE(c);
3453 /* do no editing */
3454 return(CC_NORM);
3455}
3456
57e3f2b5
SS
3457/* returns the number of (attempted) expansions */
3458int
3459ExpandHistory(void)
3460{
3461 *LastChar = '\0'; /* just in case */
3462 return c_substitute();
3463}
3464
7d8fb588
MS
3465/*ARGSUSED*/
3466CCRETVAL
3467e_expand_history(Char c)
3468{
3469 USE(c);
57e3f2b5 3470 (void)ExpandHistory();
7d8fb588
MS
3471 return(CC_NORM);
3472}
3473
3474/*ARGSUSED*/
3475CCRETVAL
3476e_magic_space(Char c)
3477{
3478 USE(c);
3479 *LastChar = '\0'; /* just in case */
57e3f2b5 3480 (void)c_substitute();
7d8fb588
MS
3481 return(e_insert(' '));
3482}
3483
3484/*ARGSUSED*/
3485CCRETVAL
3486e_inc_fwd(Char c)
3487{
3488 CCRETVAL ret;
3489
3490 USE(c);
3491 patbuf.len = 0;
3492 MarkIsSet = 0;
3493 ret = e_inc_search(F_DOWN_SEARCH_HIST);
3494 if (adrof(STRhighlight) && IncMatchLen) {
3495 IncMatchLen = 0;
3496 ClearLines();
3497 ClearDisp();
3498 Refresh();
3499 }
3500 IncMatchLen = 0;
3501 return ret;
3502}
3503
3504
3505/*ARGSUSED*/
3506CCRETVAL
3507e_inc_back(Char c)
3508{
3509 CCRETVAL ret;
3510
3511 USE(c);
3512 patbuf.len = 0;
3513 MarkIsSet = 0;
3514 ret = e_inc_search(F_UP_SEARCH_HIST);
3515 if (adrof(STRhighlight) && IncMatchLen) {
3516 IncMatchLen = 0;
3517 ClearLines();
3518 ClearDisp();
3519 Refresh();
3520 }
3521 IncMatchLen = 0;
3522 return ret;
3523}
3524
3525/*ARGSUSED*/
3526CCRETVAL
3527e_copyprev(Char c)
3528{
3529 Char *cp, *oldc, *dp;
3530
3531 USE(c);
3532 if (Cursor == InputBuf)
3533 return(CC_ERROR);
3534 /* else */
3535
3536 oldc = Cursor;
3537 /* does a bounds check */
3538 cp = c_prev_word(Cursor, InputBuf, Argument);
3539
3540 c_insert((int)(oldc - cp));
3541 for (dp = oldc; cp < oldc && dp < LastChar; cp++)
3542 *dp++ = *cp;
3543
3544 Cursor = dp; /* put cursor at end */
3545
3546 return(CC_REFRESH);
3547}
3548
3549/*ARGSUSED*/
3550CCRETVAL
3551e_tty_starto(Char c)
3552{
3553 USE(c);
3554 /* do no editing */
3555 return(CC_NORM);
3556}
3557
3558/*ARGSUSED*/
3559CCRETVAL
3560e_load_average(Char c)
3561{
3562 USE(c);
3563 PastBottom();
3564#ifdef TIOCSTAT
3565 /*
3566 * Here we pass &c to the ioctl because some os's (NetBSD) expect it
3567 * there even if they don't use it. (lukem@netbsd.org)
3568 */
3569 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
3570#endif
57e3f2b5 3571 xprintf("%s", CGETS(5, 1, "Load average unavailable\n"));
7d8fb588
MS
3572 return(CC_REFRESH);
3573}
3574
3575/*ARGSUSED*/
3576CCRETVAL
3577v_chgmeta(Char c)
3578{
3579 USE(c);
3580 /*
3581 * Delete with insert == change: first we delete and then we leave in
3582 * insert mode.
3583 */
3584 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
3585}
3586
3587/*ARGSUSED*/
3588CCRETVAL
3589v_delmeta(Char c)
3590{
3591 USE(c);
3592 return(v_action(TCSHOP_DELETE));
3593}
3594
3595
3596/*ARGSUSED*/
3597CCRETVAL
3598v_endword(Char c)
3599{
3600 USE(c);
3601 if (Cursor == LastChar)
3602 return(CC_ERROR);
3603 /* else */
3604
3605 Cursor = c_endword(Cursor, LastChar, Argument, STRshwspace);
3606
3607 if (ActionFlag & TCSHOP_DELETE)
3608 {
3609 Cursor++;
3610 c_delfini();
3611 return(CC_REFRESH);
3612 }
3613
3614 RefCursor();
3615 return(CC_NORM);
3616}
3617
3618/*ARGSUSED*/
3619CCRETVAL
3620v_eword(Char c)
3621{
3622 USE(c);
3623 if (Cursor == LastChar)
3624 return(CC_ERROR);
3625 /* else */
3626
3627 Cursor = c_eword(Cursor, LastChar, Argument);
3628
3629 if (ActionFlag & TCSHOP_DELETE) {
3630 Cursor++;
3631 c_delfini();
3632 return(CC_REFRESH);
3633 }
3634
3635 RefCursor();
3636 return(CC_NORM);
3637}
3638
3639/*ARGSUSED*/
3640CCRETVAL
3641v_char_fwd(Char c)
3642{
3643 Char ch;
3644
3645 USE(c);
3646 if (GetNextChar(&ch) != 1)
3647 return e_send_eof(0);
3648
3649 srch_dir = CHAR_FWD;
3650 srch_char = ch;
3651
3652 return v_csearch_fwd(ch, Argument, 0);
3653
3654}
3655
3656/*ARGSUSED*/
3657CCRETVAL
3658v_char_back(Char c)
3659{
3660 Char ch;
3661
3662 USE(c);
3663 if (GetNextChar(&ch) != 1)
3664 return e_send_eof(0);
3665
3666 srch_dir = CHAR_BACK;
3667 srch_char = ch;
3668
3669 return v_csearch_back(ch, Argument, 0);
3670}
3671
3672/*ARGSUSED*/
3673CCRETVAL
3674v_charto_fwd(Char c)
3675{
3676 Char ch;
3677
3678 USE(c);
3679 if (GetNextChar(&ch) != 1)
3680 return e_send_eof(0);
3681
3682 return v_csearch_fwd(ch, Argument, 1);
3683
3684}
3685
3686/*ARGSUSED*/
3687CCRETVAL
3688v_charto_back(Char c)
3689{
3690 Char ch;
3691
3692 USE(c);
3693 if (GetNextChar(&ch) != 1)
3694 return e_send_eof(0);
3695
3696 return v_csearch_back(ch, Argument, 1);
3697}
3698
3699/*ARGSUSED*/
3700CCRETVAL
3701v_rchar_fwd(Char c)
3702{
3703 USE(c);
3704 if (srch_char == 0)
3705 return CC_ERROR;
3706
3707 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
3708 v_csearch_back(srch_char, Argument, 0);
3709}
3710
3711/*ARGSUSED*/
3712CCRETVAL
3713v_rchar_back(Char c)
3714{
3715 USE(c);
3716 if (srch_char == 0)
3717 return CC_ERROR;
3718
3719 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
3720 v_csearch_back(srch_char, Argument, 0);
3721}
3722
3723/*ARGSUSED*/
3724CCRETVAL
3725v_undo(Char c)
3726{
3727 int loop;
3728 Char *kp, *cp;
3729 Char temp;
3730 int size;
3731
3732 USE(c);
3733 switch (UndoAction) {
3734 case TCSHOP_DELETE|TCSHOP_INSERT:
3735 case TCSHOP_DELETE:
3736 if (UndoSize == 0) return(CC_NORM);
3737 cp = UndoPtr;
3738 kp = UndoBuf;
3739 for (loop=0; loop < UndoSize; loop++) /* copy the chars */
3740 *kp++ = *cp++; /* into UndoBuf */
3741
3742 for (cp = UndoPtr; cp <= LastChar; cp++)
3743 *cp = cp[UndoSize];
3744
3745 LastChar -= UndoSize;
3746 Cursor = UndoPtr;
3747
3748 UndoAction = TCSHOP_INSERT;
3749 break;
3750
3751 case TCSHOP_INSERT:
3752 if (UndoSize == 0) return(CC_NORM);
3753 cp = UndoPtr;
3754 Cursor = UndoPtr;
3755 kp = UndoBuf;
3756 c_insert(UndoSize); /* open the space, */
3757 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
3758 *cp++ = *kp++;
3759
3760 UndoAction = TCSHOP_DELETE;
3761 break;
3762
3763 case TCSHOP_CHANGE:
3764 if (UndoSize == 0) return(CC_NORM);
3765 cp = UndoPtr;
3766 Cursor = UndoPtr;
3767 kp = UndoBuf;
3768 size = (int)(Cursor-LastChar); /* NOT NSL independant */
3769 if (size < UndoSize)
3770 size = UndoSize;
3771 for(loop = 0; loop < size; loop++) {
3772 temp = *kp;
3773 *kp++ = *cp;
3774 *cp++ = temp;
3775 }
3776 break;
3777
3778 default:
3779 return(CC_ERROR);
3780 }
3781
3782 return(CC_REFRESH);
3783}
3784
3785/*ARGSUSED*/
3786CCRETVAL
3787v_ush_meta(Char c)
3788{
3789 USE(c);
3790 return v_search(F_UP_SEARCH_HIST);
3791}
3792
3793/*ARGSUSED*/
3794CCRETVAL
3795v_dsh_meta(Char c)
3796{
3797 USE(c);
3798 return v_search(F_DOWN_SEARCH_HIST);
3799}
3800
3801/*ARGSUSED*/
3802CCRETVAL
3803v_rsrch_fwd(Char c)
3804{
3805 USE(c);
3806 if (patbuf.len == 0) return(CC_ERROR);
3807 return(v_repeat_srch(searchdir));
3808}
3809
3810/*ARGSUSED*/
3811CCRETVAL
3812v_rsrch_back(Char c)
3813{
3814 USE(c);
3815 if (patbuf.len == 0) return(CC_ERROR);
3816 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
3817 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
3818}
3819
3820#ifndef WINNT_NATIVE
3821/* Since ed.defns.h is generated from ed.defns.c, these empty
3822 functions will keep the F_NUM_FNS consistent
3823 */
3824CCRETVAL
3825e_copy_to_clipboard(Char c)
3826{
3827 USE(c);
3828 return CC_ERROR;
3829}
3830
3831CCRETVAL
3832e_paste_from_clipboard(Char c)
3833{
3834 USE(c);
3835 return (CC_ERROR);
3836}
3837
3838CCRETVAL
3839e_dosify_next(Char c)
3840{
3841 USE(c);
3842 return (CC_ERROR);
3843}
3844CCRETVAL
3845e_dosify_prev(Char c)
3846{
3847 USE(c);
3848 return (CC_ERROR);
3849}
3850CCRETVAL
3851e_page_up(Char c)
3852{
3853 USE(c);
3854 return (CC_ERROR);
3855}
3856CCRETVAL
3857e_page_down(Char c)
3858{
3859 USE(c);
3860 return (CC_ERROR);
3861}
3862#endif /* !WINNT_NATIVE */
3863
3864#ifdef notdef
3865void
3866MoveCursor(int n) /* move cursor + right - left char */
3867{
3868 Cursor = Cursor + n;
3869 if (Cursor < InputBuf)
3870 Cursor = InputBuf;
3871 if (Cursor > LastChar)
3872 Cursor = LastChar;
3873 return;
3874}
3875
3876Char *
3877GetCursor(void)
3878{
3879 return(Cursor);
3880}
3881
3882int
3883PutCursor(Char *p)
3884{
3885 if (p < InputBuf || p > LastChar)
3886 return 1; /* Error */
3887 Cursor = p;
3888 return 0;
3889}
3890#endif