Kernel part of bluetooth stack ported by Dmitry Komissaroff. Very much work
[dragonfly.git] / contrib / tcsh / ed.chared.c
blobced9c8beff26ca2f9860489a10c57c769ffe0b37
1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.71 2002/03/08 17:36:45 christos Exp $ */
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.
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.
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.
34 Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
36 e_dabbrev_expand() did not do proper completion if quoted spaces were present
37 in the string being completed. Exemple:
39 # echo hello\ world
40 hello world
41 # echo h<press key bound to dabbrev-expande>
42 # echo hello\<cursor>
44 Correct behavior is:
45 # echo h<press key bound to dabbrev-expande>
46 # echo hello\ world<cursor>
48 The same problem occured if spaces were present in a string withing quotation
49 marks. Example:
51 # echo "hello world"
52 hello world
53 # echo "h<press key bound to dabbrev-expande>
54 # echo "hello<cursor>
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.
61 Compare the following two strings:
63 # echo \"" 'foo \' bar\"
64 " 'foo \' bar\
65 # echo '\"" 'foo \' bar\"
66 \"" foo ' bar"
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.
73 #include "sh.h"
75 RCSID("$Id: ed.chared.c,v 3.71 2002/03/08 17:36:45 christos Exp $")
77 #include "ed.h"
78 #include "tw.h"
79 #include "ed.defns.h"
81 /* #define SDEBUG */
83 #define TCSHOP_NOP 0x00
84 #define TCSHOP_DELETE 0x01
85 #define TCSHOP_INSERT 0x02
86 #define TCSHOP_CHANGE 0x04
88 #define CHAR_FWD 0
89 #define CHAR_BACK 1
92 * vi word treatment
93 * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
95 #define C_CLASS_WHITE 1
96 #define C_CLASS_ALNUM 2
97 #define C_CLASS_OTHER 3
99 static Char *InsertPos = InputBuf; /* Where insertion starts */
100 static Char *ActionPos = 0; /* Where action begins */
101 static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */
103 * Word search state
105 static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
106 static Char patbuf[INBUFSIZE]; /* Search target */
107 static int patlen = 0;
109 * Char search state
111 static int srch_dir = CHAR_FWD; /* Direction of last search */
112 static Char srch_char = 0; /* Search target */
114 /* all routines that start with c_ are private to this set of routines */
115 static void c_alternativ_key_map __P((int));
116 void c_insert __P((int));
117 void c_delafter __P((int));
118 void c_delbefore __P((int));
119 static int c_to_class __P((int));
120 static Char *c_prev_word __P((Char *, Char *, int));
121 static Char *c_next_word __P((Char *, Char *, int));
122 static Char *c_number __P((Char *, int *, int));
123 static Char *c_expand __P((Char *));
124 static void c_excl __P((Char *));
125 static void c_substitute __P((void));
126 static void c_delfini __P((void));
127 static int c_hmatch __P((Char *));
128 static void c_hsetpat __P((void));
129 #ifdef COMMENT
130 static void c_get_word __P((Char **, Char **));
131 #endif
132 static Char *c_preword __P((Char *, Char *, int, Char *));
133 static Char *c_nexword __P((Char *, Char *, int));
134 static Char *c_endword __P((Char *, Char *, int, Char *));
135 static Char *c_eword __P((Char *, Char *, int));
136 static void c_push_kill __P((Char *, Char *));
137 static CCRETVAL c_get_histline __P((void));
138 static CCRETVAL c_search_line __P((Char *, int));
139 static CCRETVAL v_repeat_srch __P((int));
140 static CCRETVAL e_inc_search __P((int));
141 static CCRETVAL v_search __P((int));
142 static CCRETVAL v_csearch_fwd __P((int, int, int));
143 static CCRETVAL v_action __P((int));
144 static CCRETVAL v_csearch_back __P((int, int, int));
146 #if defined(DSPMBYTE)
147 static void e_charfwd_mbyte __P((int));
148 static void e_charback_mbyte __P((int));
149 static int extdel;
150 static int extins = 0;
151 #endif
153 static void
154 c_alternativ_key_map(state)
155 int state;
157 switch (state) {
158 case 0:
159 CurrentKeyMap = CcKeyMap;
160 break;
161 case 1:
162 CurrentKeyMap = CcAltMap;
163 break;
164 default:
165 return;
168 AltKeyMap = (Char) state;
171 void
172 c_insert(num)
173 int num;
175 Char *cp;
177 if (LastChar + num >= InputLim)
178 return; /* can't go past end of buffer */
180 if (Cursor < LastChar) { /* if I must move chars */
181 for (cp = LastChar; cp >= Cursor; cp--)
182 cp[num] = *cp;
184 LastChar += num;
187 void
188 c_delafter(num)
189 int num;
191 Char *cp, *kp = NULL;
193 #if defined(DSPMBYTE)
194 Char *wkcp;
196 extdel = 0;
197 #endif
199 if (num > LastChar - Cursor)
200 num = (int) (LastChar - Cursor); /* bounds check */
202 if (num > 0) { /* if I can delete anything */
203 #if defined(DSPMBYTE)
204 /* check for code of deleted character */
205 if (_enable_mbdisp) {
206 for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) {
207 if (extdel == 0)
208 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
209 else
210 extdel = 0; /* if 2nd. byte, force set to 0 */
213 #endif
214 if (VImode) {
215 kp = UndoBuf; /* Set Up for VI undo command */
216 UndoAction = TCSHOP_INSERT;
217 UndoSize = num;
218 UndoPtr = Cursor;
219 for (cp = Cursor; cp <= LastChar; cp++) {
220 *kp++ = *cp; /* Save deleted chars into undobuf */
221 *cp = cp[num];
224 else
225 for (cp = Cursor; cp <= LastChar; cp++)
226 *cp = cp[num];
227 LastChar -= num;
228 #if defined(DSPMBYTE)
229 if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) {
230 if( VImode ) {
231 UndoSize++;
232 *kp++ = *Cursor; /* Save deleted chars into undobuf */
234 for (cp = Cursor; cp <= LastChar; cp++)
235 *cp = cp[1];
236 LastChar--;
237 e_redisp( 1 );
239 else
240 extdel = 0;
241 #endif
243 #ifdef notdef
244 else {
246 * XXX: We don't want to do that. In emacs mode overwrite should be
247 * sticky. I am not sure how that affects vi mode
249 inputmode = MODE_INSERT;
251 #endif /* notdef */
254 void
255 c_delbefore(num) /* delete before dot, with bounds checking */
256 int num;
258 Char *cp, *kp = NULL;
260 #if defined(DSPMBYTE)
261 Char *nowcur, *wkcp;
262 Char delc;
264 extdel = 0;
265 #endif
267 if (num > Cursor - InputBuf)
268 num = (int) (Cursor - InputBuf); /* bounds check */
270 if (num > 0) { /* if I can delete anything */
271 #if defined(DSPMBYTE)
272 nowcur = Cursor - num;
273 delc = *nowcur;
274 #endif
275 if (VImode) {
276 kp = UndoBuf; /* Set Up for VI undo command */
277 UndoAction = TCSHOP_INSERT;
278 UndoSize = num;
279 UndoPtr = Cursor - num;
280 for (cp = Cursor - num; cp <= LastChar; cp++) {
281 *kp++ = *cp;
282 *cp = cp[num];
285 else
286 for (cp = Cursor - num; cp <= LastChar; cp++)
287 *cp = cp[num];
288 LastChar -= num;
289 #if defined(DSPMBYTE)
290 if (_enable_mbdisp) {
291 for (wkcp = InputBuf; wkcp < nowcur; wkcp++) {
292 if(extdel == 0)
293 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
294 else
295 extdel = 0; /* if 2nd. byte, force set to 0 */
297 if (extdel && Ismbyte2(delc)) {
298 if( VImode ) {
299 UndoSize++;
300 UndoPtr--;
301 *kp++ = *(nowcur-1);
302 /* Save deleted chars into undobuf */
304 for (cp = nowcur - 1; cp <= LastChar; cp++)
305 *cp = cp[1];
306 LastChar--;
309 else
310 extdel = 0;
311 #endif
315 static Char *
316 c_preword(p, low, n, delim)
317 Char *p, *low, *delim;
318 int n;
320 while (n--) {
321 Char *prev = low;
322 Char *new;
324 while (prev < p) { /* Skip initial non-word chars */
325 if (!Strchr(delim, *prev) || *(prev-1) == (Char)'\\')
326 break;
327 prev++;
330 new = prev;
332 while (new < p) {
333 prev = new;
334 new = c_endword(prev-1, p, 1, delim); /* Skip to next non-word char */
335 new++; /* Step away from end of word */
336 while (new <= p) { /* Skip trailing non-word chars */
337 if (!Strchr(delim, *new) || *(new-1) == (Char)'\\')
338 break;
339 new++;
343 p = prev; /* Set to previous word start */
346 if (p < low)
347 p = low;
348 return (p);
352 * c_to_class() returns the class of the given character.
354 * This is used to make the c_prev_word() and c_next_word() functions
355 * work like vi's, which classify characters. A word is a sequence of
356 * characters belonging to the same class, classes being defined as
357 * follows:
359 * 1/ whitespace
360 * 2/ alphanumeric chars, + underscore
361 * 3/ others
363 static int
364 c_to_class(ch)
365 int ch;
367 if (Isspace(ch))
368 return C_CLASS_WHITE;
370 if (Isdigit(ch) || Isalpha(ch) || ch == '_')
371 return C_CLASS_ALNUM;
373 return C_CLASS_OTHER;
376 static Char *
377 c_prev_word(p, low, n)
378 Char *p, *low;
379 int n;
381 p--;
383 if (!VImode) {
384 while (n--) {
385 while ((p >= low) && !isword(*p))
386 p--;
387 while ((p >= low) && isword(*p))
388 p--;
391 /* cp now points to one character before the word */
392 p++;
393 if (p < low)
394 p = low;
395 /* cp now points where we want it */
396 return(p);
399 while (n--) {
400 int c_class;
402 if (p < low)
403 break;
405 /* scan until beginning of current word (may be all whitespace!) */
406 c_class = c_to_class(*p);
407 while ((p >= low) && c_class == c_to_class(*p))
408 p--;
410 /* if this was a non_whitespace word, we're ready */
411 if (c_class != C_CLASS_WHITE)
412 continue;
414 /* otherwise, move back to beginning of the word just found */
415 c_class = c_to_class(*p);
416 while ((p >= low) && c_class == c_to_class(*p))
417 p--;
420 p++; /* correct overshoot */
422 return (p);
425 static Char *
426 c_next_word(p, high, n)
427 Char *p, *high;
428 int n;
430 if (!VImode) {
431 while (n--) {
432 while ((p < high) && !isword(*p))
433 p++;
434 while ((p < high) && isword(*p))
435 p++;
437 if (p > high)
438 p = high;
439 /* p now points where we want it */
440 return(p);
443 while (n--) {
444 int c_class;
446 if (p >= high)
447 break;
449 /* scan until end of current word (may be all whitespace!) */
450 c_class = c_to_class(*p);
451 while ((p < high) && c_class == c_to_class(*p))
452 p++;
454 /* if this was all whitespace, we're ready */
455 if (c_class == C_CLASS_WHITE)
456 continue;
458 /* if we've found white-space at the end of the word, skip it */
459 while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
460 p++;
463 p--; /* correct overshoot */
465 return (p);
468 static Char *
469 c_nexword(p, high, n)
470 Char *p, *high;
471 int n;
473 while (n--) {
474 while ((p < high) && !Isspace(*p))
475 p++;
476 while ((p < high) && Isspace(*p))
477 p++;
480 if (p > high)
481 p = high;
482 /* p now points where we want it */
483 return(p);
487 * Expand-History (originally "Magic-Space") code added by
488 * Ray Moody <ray@gibbs.physics.purdue.edu>
489 * this is a neat, but odd, addition.
493 * c_number: Ignore character p points to, return number appearing after that.
494 * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
495 * Return p pointing to last char used.
499 * dval is the number to subtract from for things like $-3
502 static Char *
503 c_number(p, num, dval)
504 Char *p;
505 int *num;
506 int dval;
508 int i;
509 int sign = 1;
511 if (*++p == '^') {
512 *num = 1;
513 return(p);
515 if (*p == '$') {
516 if (*++p != '-') {
517 *num = NCARGS; /* Handle $ */
518 return(--p);
520 sign = -1; /* Handle $- */
521 ++p;
523 for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
524 continue;
525 *num = (sign < 0 ? dval - i : i);
526 return(--p);
530 * excl_expand: There is an excl to be expanded to p -- do the right thing
531 * with it and return a version of p advanced over the expanded stuff. Also,
532 * update tsh_cur and related things as appropriate...
535 static Char *
536 c_expand(p)
537 Char *p;
539 Char *q;
540 struct Hist *h = Histlist.Hnext;
541 struct wordent *l;
542 int i, from, to, dval;
543 bool all_dig;
544 bool been_once = 0;
545 Char *op = p;
546 Char buf[INBUFSIZE];
547 Char *bend = buf;
548 Char *modbuf, *omodbuf;
550 if (!h)
551 goto excl_err;
552 excl_sw:
553 switch (*(q = p + 1)) {
555 case '^':
556 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
557 break;
559 case '$':
560 if ((l = (h->Hlex).prev) != 0)
561 bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
562 break;
564 case '*':
565 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
566 break;
568 default:
569 if (been_once) { /* unknown argument */
570 /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
571 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
572 q -= 2;
573 break;
575 been_once = 1;
577 if (*q == ':') /* short form: !:arg */
578 --q;
580 if (*q != HIST) {
582 * Search for a space, tab, or colon. See if we have a number (as
583 * in !1234:xyz). Remember the number.
585 for (i = 0, all_dig = 1;
586 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
588 * PWP: !-4 is a valid history argument too, therefore the test
589 * is if not a digit, or not a - as the first character.
591 if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
592 all_dig = 0;
593 else if (*q == '-')
594 all_dig = 2;/* we are sneeky about this */
595 else
596 i = 10 * i + *q - '0';
598 --q;
601 * If we have a number, search for event i. Otherwise, search for
602 * a named event (as in !foo). (In this case, I is the length of
603 * the named event).
605 if (all_dig) {
606 if (all_dig == 2)
607 i = -i; /* make it negitive */
608 if (i < 0) /* if !-4 (for example) */
609 i = eventno + 1 + i; /* remember: i is < 0 */
610 for (; h; h = h->Hnext) {
611 if (h->Hnum == i)
612 break;
615 else {
616 for (i = (int) (q - p); h; h = h->Hnext) {
617 if ((l = &h->Hlex) != 0) {
618 if (!Strncmp(p + 1, l->next->word, (size_t) i))
619 break;
624 if (!h)
625 goto excl_err;
626 if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
627 q[1] == '$' || q[1] == '^') { /* get some args */
628 p = q[1] == ':' ? ++q : q;
630 * Go handle !foo:*
632 if ((q[1] < '0' || q[1] > '9') &&
633 q[1] != '-' && q[1] != '$' && q[1] != '^')
634 goto excl_sw;
636 * Go handle !foo:$
638 if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
639 goto excl_sw;
641 * Count up the number of words in this event. Store it in dval.
642 * Dval will be fed to number.
644 dval = 0;
645 if ((l = h->Hlex.prev) != 0) {
646 for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
647 continue;
649 if (!dval)
650 goto excl_err;
651 if (q[1] == '-')
652 from = 0;
653 else
654 q = c_number(q, &from, dval);
655 if (q[1] == '-') {
656 ++q;
657 if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
658 to = dval - 1;
659 else
660 q = c_number(q, &to, dval);
662 else if (q[1] == '*') {
663 ++q;
664 to = NCARGS;
666 else {
667 to = from;
669 if (from < 0 || to < from)
670 goto excl_err;
671 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
673 else { /* get whole cmd */
674 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
676 break;
680 * Apply modifiers, if any.
682 if (q[1] == ':') {
683 *bend = '\0';
684 modbuf = omodbuf = buf;
685 while (q[1] == ':' && modbuf != NULL) {
686 switch (q[2]) {
687 case 'r':
688 case 'e':
689 case 'h':
690 case 't':
691 case 'q':
692 case 'x':
693 case 'u':
694 case 'l':
695 if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
696 if (omodbuf != buf)
697 xfree((ptr_t) omodbuf);
698 omodbuf = modbuf;
700 ++q;
701 break;
703 case 'a':
704 case 'g':
705 /* Not implemented; this needs to be done before expanding
706 * lex. We don't have the words available to us anymore.
708 ++q;
709 break;
711 case 'p':
712 /* Ok */
713 ++q;
714 break;
716 case '\0':
717 break;
719 default:
720 ++q;
721 break;
723 if (q[1])
724 ++q;
726 if (omodbuf != buf) {
727 (void) Strcpy(buf, omodbuf);
728 xfree((ptr_t) omodbuf);
729 bend = Strend(buf);
734 * Now replace the text from op to q inclusive with the text from buf to
735 * bend.
737 q++;
740 * Now replace text non-inclusively like a real CS major!
742 if (LastChar + (bend - buf) - (q - op) >= InputLim)
743 goto excl_err;
744 (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
745 (size_t) ((LastChar - q) * sizeof(Char)));
746 LastChar += (bend - buf) - (q - op);
747 Cursor += (bend - buf) - (q - op);
748 (void) memmove((ptr_t) op, (ptr_t) buf,
749 (size_t) ((bend - buf) * sizeof(Char)));
750 *LastChar = '\0';
751 return(op + (bend - buf));
752 excl_err:
753 SoundBeep();
754 return(op + 1);
758 * c_excl: An excl has been found at point p -- back up and find some white
759 * space (or the beginning of the buffer) and properly expand all the excl's
760 * from there up to the current cursor position. We also avoid (trying to)
761 * expanding '>!'
764 static void
765 c_excl(p)
766 Char *p;
768 int i;
769 Char *q;
772 * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
773 * back p up to just before the current word.
775 if ((p[1] == ' ' || p[1] == '\t') &&
776 (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
777 for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
778 continue;
779 if (*q == '>')
780 ++p;
782 else {
783 while (*p != ' ' && *p != '\t' && p > InputBuf)
784 --p;
788 * Forever: Look for history char. (Stop looking when we find the cursor.)
789 * Count backslashes. Of odd, skip history char. Return if all done.
790 * Expand if even number of backslashes.
792 for (;;) {
793 while (*p != HIST && p < Cursor)
794 ++p;
795 for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
796 continue;
797 if (i % 2 == 0)
798 ++p;
799 if (p >= Cursor)
800 return;
801 if (i % 2 == 1)
802 p = c_expand(p);
807 static void
808 c_substitute()
810 Char *p;
813 * Start p out one character before the cursor. Move it backwards looking
814 * for white space, the beginning of the line, or a history character.
816 for (p = Cursor - 1;
817 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
818 continue;
821 * If we found a history character, go expand it.
823 if (*p == HIST)
824 c_excl(p);
825 Refresh();
828 static void
829 c_delfini() /* Finish up delete action */
831 int Size;
833 if (ActionFlag & TCSHOP_INSERT)
834 c_alternativ_key_map(0);
836 ActionFlag = TCSHOP_NOP;
838 if (ActionPos == 0)
839 return;
841 UndoAction = TCSHOP_INSERT;
843 if (Cursor > ActionPos) {
844 Size = (int) (Cursor-ActionPos);
845 c_delbefore(Size);
846 Cursor = ActionPos;
847 #if defined(DSPMBYTE)
848 if (_enable_mbdisp && extdel) {
849 Cursor--;
850 e_redisp(1);
852 #endif
853 RefCursor();
855 else if (Cursor < ActionPos) {
856 Size = (int)(ActionPos-Cursor);
857 c_delafter(Size);
859 else {
860 Size = 1;
861 c_delafter(Size);
863 UndoPtr = Cursor;
864 UndoSize = Size;
867 static Char *
868 c_endword(p, high, n, delim)
869 Char *p, *high, *delim;
870 int n;
872 int inquote = 0;
873 p++;
875 while (n--) {
876 while (p < high) { /* Skip non-word chars */
877 if (!Strchr(delim, *p) || *(p-1) == (Char)'\\')
878 break;
879 p++;
881 while (p < high) { /* Skip string */
882 if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
883 if (inquote || *(p-1) != (Char)'\\') { /* Should it be honored? */
884 if (inquote == 0) inquote = *p;
885 else if (inquote == *p) inquote = 0;
888 /* Break if unquoted non-word char */
889 if (!inquote && Strchr(delim, *p) && *(p-1) != (Char)'\\')
890 break;
891 p++;
895 p--;
896 return(p);
900 static Char *
901 c_eword(p, high, n)
902 Char *p, *high;
903 int n;
905 p++;
907 while (n--) {
908 while ((p < high) && Isspace(*p))
909 p++;
911 if (Isalnum(*p))
912 while ((p < high) && Isalnum(*p))
913 p++;
914 else
915 while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
916 p++;
919 p--;
920 return(p);
923 /* Set the max length of the kill ring */
924 void
925 SetKillRing(max)
926 int max;
928 CStr *new;
929 int count, i, j;
931 if (max < 1)
932 max = 1; /* no ring, but always one buffer */
933 if (max == KillRingMax)
934 return;
935 new = (CStr *)xcalloc((size_t) max, sizeof(CStr));
936 if (KillRing != NULL) {
937 if (KillRingLen != 0) {
938 if (max >= KillRingLen) {
939 count = KillRingLen;
940 j = KillPos;
941 } else {
942 count = max;
943 j = (KillPos - count + KillRingLen) % KillRingLen;
945 for (i = 0; i < KillRingLen; i++) {
946 if (i < count) /* copy latest */
947 new[i] = KillRing[j];
948 else /* free the others */
949 xfree(KillRing[j].buf);
950 j = (j + 1) % KillRingLen;
952 KillRingLen = count;
953 KillPos = count % max;
954 YankPos = count - 1;
956 xfree(KillRing);
958 KillRing = new;
959 KillRingMax = max;
962 /* Push string from start upto (but not including) end onto kill ring */
963 static void
964 c_push_kill(start, end)
965 Char *start, *end;
967 CStr save, *pos;
968 Char *dp, *cp, *kp;
969 int len = end - start, i, j, k;
971 /* Check for duplicates? */
972 if (KillRingLen > 0 && (dp = varval(STRkilldup)) != STRNULL) {
973 YankPos = (KillPos - 1 + KillRingLen) % KillRingLen;
974 if (eq(dp, STRerase)) { /* erase earlier one (actually move up) */
975 j = YankPos;
976 for (i = 0; i < KillRingLen; i++) {
977 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
978 KillRing[j].buf[len] == '\0') {
979 save = KillRing[j];
980 for ( ; i > 0; i--) {
981 k = j;
982 j = (j + 1) % KillRingLen;
983 KillRing[k] = KillRing[j];
985 KillRing[j] = save;
986 return;
988 j = (j - 1 + KillRingLen) % KillRingLen;
990 } else if (eq(dp, STRall)) { /* skip if any earlier */
991 for (i = 0; i < KillRingLen; i++)
992 if (Strncmp(KillRing[i].buf, start, (size_t) len) == 0 &&
993 KillRing[i].buf[len] == '\0')
994 return;
995 } else if (eq(dp, STRprev)) { /* skip if immediately previous */
996 j = YankPos;
997 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
998 KillRing[j].buf[len] == '\0')
999 return;
1003 /* No duplicate, go ahead and push */
1004 len++; /* need space for '\0' */
1005 YankPos = KillPos;
1006 if (KillRingLen < KillRingMax)
1007 KillRingLen++;
1008 pos = &KillRing[KillPos];
1009 KillPos = (KillPos + 1) % KillRingMax;
1010 if (pos->len < len) {
1011 if (pos->buf == NULL)
1012 pos->buf = (Char *) xmalloc(len * sizeof(Char));
1013 else
1014 pos->buf = (Char *) xrealloc((ptr_t) pos->buf, len * sizeof(Char));
1015 pos->len = len;
1017 cp = start;
1018 kp = pos->buf;
1019 while (cp < end)
1020 *kp++ = *cp++;
1021 *kp = '\0';
1024 static CCRETVAL
1025 c_get_histline()
1027 struct Hist *hp;
1028 int h;
1030 if (Hist_num == 0) { /* if really the current line */
1031 copyn(InputBuf, HistBuf, INBUFSIZE);
1032 LastChar = InputBuf + (LastHist - HistBuf);
1034 #ifdef KSHVI
1035 if (VImode)
1036 Cursor = InputBuf;
1037 else
1038 #endif /* KSHVI */
1039 Cursor = LastChar;
1041 return(CC_REFRESH);
1044 hp = Histlist.Hnext;
1045 if (hp == NULL)
1046 return(CC_ERROR);
1048 for (h = 1; h < Hist_num; h++) {
1049 if ((hp->Hnext) == NULL) {
1050 Hist_num = h;
1051 return(CC_ERROR);
1053 hp = hp->Hnext;
1056 if (HistLit && hp->histline) {
1057 copyn(InputBuf, hp->histline, INBUFSIZE);
1058 CurrentHistLit = 1;
1060 else {
1061 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1062 CurrentHistLit = 0;
1064 LastChar = InputBuf + Strlen(InputBuf);
1066 if (LastChar > InputBuf) {
1067 if (LastChar[-1] == '\n')
1068 LastChar--;
1069 #if 0
1070 if (LastChar[-1] == ' ')
1071 LastChar--;
1072 #endif
1073 if (LastChar < InputBuf)
1074 LastChar = InputBuf;
1077 #ifdef KSHVI
1078 if (VImode)
1079 Cursor = InputBuf;
1080 else
1081 #endif /* KSHVI */
1082 Cursor = LastChar;
1084 return(CC_REFRESH);
1087 static CCRETVAL
1088 c_search_line(pattern, dir)
1089 Char *pattern;
1090 int dir;
1092 Char *cp;
1093 int len;
1095 len = (int) Strlen(pattern);
1097 if (dir == F_UP_SEARCH_HIST) {
1098 for (cp = Cursor; cp >= InputBuf; cp--)
1099 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1100 Gmatch(cp, pattern)) {
1101 Cursor = cp;
1102 return(CC_NORM);
1104 return(CC_ERROR);
1105 } else {
1106 for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1107 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1108 Gmatch(cp, pattern)) {
1109 Cursor = cp;
1110 return(CC_NORM);
1112 return(CC_ERROR);
1116 static CCRETVAL
1117 e_inc_search(dir)
1118 int dir;
1120 static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1121 STRbck[] = { 'b', 'c', 'k', '\0' };
1122 static Char pchar = ':'; /* ':' = normal, '?' = failed */
1123 static Char endcmd[2];
1124 Char ch, *cp,
1125 *oldCursor = Cursor,
1126 oldpchar = pchar;
1127 CCRETVAL ret = CC_NORM;
1128 int oldHist_num = Hist_num,
1129 oldpatlen = patlen,
1130 newdir = dir,
1131 done, redo;
1133 if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
1134 return(CC_ERROR);
1136 for (;;) {
1138 if (patlen == 0) { /* first round */
1139 pchar = ':';
1140 patbuf[patlen++] = '*';
1142 done = redo = 0;
1143 *LastChar++ = '\n';
1144 for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
1145 *cp; *LastChar++ = *cp++)
1146 continue;
1147 *LastChar++ = pchar;
1148 for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
1149 continue;
1150 *LastChar = '\0';
1151 Refresh();
1153 if (GetNextChar(&ch) != 1)
1154 return(e_send_eof(0));
1156 switch (CurrentKeyMap[(unsigned char) ch]) {
1157 case F_INSERT:
1158 case F_DIGIT:
1159 case F_MAGIC_SPACE:
1160 if (patlen > INBUFSIZE - 3)
1161 SoundBeep();
1162 else {
1163 patbuf[patlen++] = ch;
1164 *LastChar++ = ch;
1165 *LastChar = '\0';
1166 Refresh();
1168 break;
1170 case F_INC_FWD:
1171 newdir = F_DOWN_SEARCH_HIST;
1172 redo++;
1173 break;
1175 case F_INC_BACK:
1176 newdir = F_UP_SEARCH_HIST;
1177 redo++;
1178 break;
1180 case F_DELPREV:
1181 if (patlen > 1)
1182 done++;
1183 else
1184 SoundBeep();
1185 break;
1187 default:
1188 switch (ch) {
1189 case 0007: /* ^G: Abort */
1190 ret = CC_ERROR;
1191 done++;
1192 break;
1194 case 0027: /* ^W: Append word */
1195 /* No can do if globbing characters in pattern */
1196 for (cp = &patbuf[1]; ; cp++)
1197 if (cp >= &patbuf[patlen]) {
1198 Cursor += patlen - 1;
1199 cp = c_next_word(Cursor, LastChar, 1);
1200 while (Cursor < cp && *Cursor != '\n') {
1201 if (patlen > INBUFSIZE - 3) {
1202 SoundBeep();
1203 break;
1205 patbuf[patlen++] = *Cursor;
1206 *LastChar++ = *Cursor++;
1208 Cursor = oldCursor;
1209 *LastChar = '\0';
1210 Refresh();
1211 break;
1212 } else if (isglob(*cp)) {
1213 SoundBeep();
1214 break;
1216 break;
1218 default: /* Terminate and execute cmd */
1219 endcmd[0] = ch;
1220 PushMacro(endcmd);
1221 /*FALLTHROUGH*/
1223 case 0033: /* ESC: Terminate */
1224 ret = CC_REFRESH;
1225 done++;
1226 break;
1228 break;
1231 while (LastChar > InputBuf && *LastChar != '\n')
1232 *LastChar-- = '\0';
1233 *LastChar = '\0';
1235 if (!done) {
1237 /* Can't search if unmatched '[' */
1238 for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
1239 if (*cp == '[' || *cp == ']') {
1240 ch = *cp;
1241 break;
1244 if (patlen > 1 && ch != '[') {
1245 if (redo && newdir == dir) {
1246 if (pchar == '?') { /* wrap around */
1247 Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
1248 if (c_get_histline() == CC_ERROR)
1249 /* Hist_num was fixed by first call */
1250 (void) c_get_histline();
1251 Cursor = newdir == F_UP_SEARCH_HIST ?
1252 LastChar : InputBuf;
1253 } else
1254 Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
1256 patbuf[patlen++] = '*';
1257 patbuf[patlen] = '\0';
1258 if (Cursor < InputBuf || Cursor > LastChar ||
1259 (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
1260 LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
1261 ret = newdir == F_UP_SEARCH_HIST ?
1262 e_up_search_hist(0) : e_down_search_hist(0);
1263 if (ret != CC_ERROR) {
1264 Cursor = newdir == F_UP_SEARCH_HIST ?
1265 LastChar : InputBuf;
1266 (void) c_search_line(&patbuf[1], newdir);
1269 patbuf[--patlen] = '\0';
1270 if (ret == CC_ERROR) {
1271 SoundBeep();
1272 if (Hist_num != oldHist_num) {
1273 Hist_num = oldHist_num;
1274 if (c_get_histline() == CC_ERROR)
1275 return(CC_ERROR);
1277 Cursor = oldCursor;
1278 pchar = '?';
1279 } else {
1280 pchar = ':';
1284 ret = e_inc_search(newdir);
1286 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
1287 /* break abort of failed search at last non-failed */
1288 ret = CC_NORM;
1293 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
1294 /* restore on normal return or error exit */
1295 pchar = oldpchar;
1296 patlen = oldpatlen;
1297 if (Hist_num != oldHist_num) {
1298 Hist_num = oldHist_num;
1299 if (c_get_histline() == CC_ERROR)
1300 return(CC_ERROR);
1302 Cursor = oldCursor;
1303 if (ret == CC_ERROR)
1304 Refresh();
1306 if (done || ret != CC_NORM)
1307 return(ret);
1313 static CCRETVAL
1314 v_search(dir)
1315 int dir;
1317 Char ch;
1318 Char tmpbuf[INBUFSIZE];
1319 Char oldbuf[INBUFSIZE];
1320 Char *oldlc, *oldc;
1321 int tmplen;
1323 copyn(oldbuf, InputBuf, INBUFSIZE);
1324 oldlc = LastChar;
1325 oldc = Cursor;
1326 tmplen = 0;
1327 tmpbuf[tmplen++] = '*';
1329 InputBuf[0] = '\0';
1330 LastChar = InputBuf;
1331 Cursor = InputBuf;
1332 searchdir = dir;
1334 c_insert(2); /* prompt + '\n' */
1335 *Cursor++ = '\n';
1336 *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
1337 Refresh();
1338 for (ch = 0;ch == 0;) {
1339 if (GetNextChar(&ch) != 1)
1340 return(e_send_eof(0));
1341 switch (ASC(ch)) {
1342 case 0010: /* Delete and backspace */
1343 case 0177:
1344 if (tmplen > 1) {
1345 *Cursor-- = '\0';
1346 LastChar = Cursor;
1347 tmpbuf[tmplen--] = '\0';
1349 else {
1350 copyn(InputBuf, oldbuf, INBUFSIZE);
1351 LastChar = oldlc;
1352 Cursor = oldc;
1353 return(CC_REFRESH);
1355 Refresh();
1356 ch = 0;
1357 break;
1359 case 0033: /* ESC */
1360 #ifdef IS_ASCII
1361 case '\r': /* Newline */
1362 case '\n':
1363 #else
1364 case '\012': /* ASCII Line feed */
1365 case '\015': /* ASCII (or EBCDIC) Return */
1366 #endif
1367 break;
1369 default:
1370 if (tmplen >= INBUFSIZE)
1371 SoundBeep();
1372 else {
1373 tmpbuf[tmplen++] = ch;
1374 *Cursor++ = ch;
1375 LastChar = Cursor;
1377 Refresh();
1378 ch = 0;
1379 break;
1383 if (tmplen == 1) {
1385 * Use the old pattern, but wild-card it.
1387 if (patlen == 0) {
1388 InputBuf[0] = '\0';
1389 LastChar = InputBuf;
1390 Cursor = InputBuf;
1391 Refresh();
1392 return(CC_ERROR);
1394 if (patbuf[0] != '*') {
1395 (void) Strcpy(tmpbuf, patbuf);
1396 patbuf[0] = '*';
1397 (void) Strcpy(&patbuf[1], tmpbuf);
1398 patlen++;
1399 patbuf[patlen++] = '*';
1400 patbuf[patlen] = '\0';
1403 else {
1404 tmpbuf[tmplen++] = '*';
1405 tmpbuf[tmplen] = '\0';
1406 (void) Strcpy(patbuf, tmpbuf);
1407 patlen = tmplen;
1409 LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
1410 Cursor = LastChar = InputBuf;
1411 if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
1412 e_down_search_hist(0)) == CC_ERROR) {
1413 Refresh();
1414 return(CC_ERROR);
1416 else {
1417 if (ch == 0033) {
1418 Refresh();
1419 *LastChar++ = '\n';
1420 *LastChar = '\0';
1421 PastBottom();
1422 return(CC_NEWLINE);
1424 else
1425 return(CC_REFRESH);
1430 * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
1431 * entry point, called from the CcKeyMap indirected into the
1432 * CcFuncTbl array.
1435 /*ARGSUSED*/
1436 CCRETVAL
1437 v_cmd_mode(c)
1438 int c;
1440 USE(c);
1441 InsertPos = 0;
1442 ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
1443 ActionPos = 0;
1444 DoingArg = 0;
1445 if (UndoPtr > Cursor)
1446 UndoSize = (int)(UndoPtr - Cursor);
1447 else
1448 UndoSize = (int)(Cursor - UndoPtr);
1450 inputmode = MODE_INSERT;
1451 c_alternativ_key_map(1);
1452 #ifdef notdef
1454 * We don't want to move the cursor, because all the editing
1455 * commands don't include the character under the cursor.
1457 if (Cursor > InputBuf)
1458 Cursor--;
1459 #endif
1460 RefCursor();
1461 return(CC_NORM);
1464 /*ARGSUSED*/
1465 CCRETVAL
1466 e_unassigned(c)
1467 int c;
1468 { /* bound to keys that arn't really assigned */
1469 USE(c);
1470 SoundBeep();
1471 flush();
1472 return(CC_NORM);
1475 CCRETVAL
1476 e_insert(c)
1477 int c;
1479 int i;
1480 #if defined(DSPMBYTE)
1481 CCRETVAL ret;
1482 static Char savec;
1483 static int exterr = 0;
1484 #endif
1485 #ifndef SHORT_STRINGS
1486 c &= ASCII; /* no meta chars ever */
1487 #endif
1488 #if defined(DSPMBYTE)
1489 ret = (CCRETVAL) CC_NORM;
1490 #endif
1492 if (!c)
1493 return(CC_ERROR); /* no NULs in the input ever!! */
1495 if (LastChar + Argument >= InputLim)
1496 return(CC_ERROR); /* end of buffer space */
1498 if (Argument == 1) { /* How was this optimized ???? */
1500 #if defined(DSPMBYTE)
1501 if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) {
1502 extins = 0;
1503 exterr = 0;
1504 return(CC_ERROR);
1506 #endif
1507 if (inputmode != MODE_INSERT) {
1508 UndoBuf[UndoSize++] = *Cursor;
1509 UndoBuf[UndoSize] = '\0';
1510 c_delafter(1); /* Do NOT use the saving ONE */
1513 c_insert(1);
1515 #if defined(DSPMBYTE)
1516 /* 1st. byte is store to special buffer, and replace space */
1517 if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1518 extins++;
1519 savec = (Char) c;
1520 *Cursor++ = (Char) ' ';
1522 else if (_enable_mbdisp && extins && Ismbyte2(c)) {
1523 *(Cursor-1) = savec;
1524 *Cursor++ = (Char) c;
1525 extins = 0;
1526 e_redisp(1);
1527 Refresh();
1528 ret = CC_REFRESH;
1530 else
1531 *Cursor++ = (Char) c;
1532 DoingArg = 0; /* just in case */
1533 if (ret != CC_REFRESH)
1534 RefPlusOne(); /* fast refresh for one char. */
1535 #else
1536 *Cursor++ = (Char) c;
1537 DoingArg = 0; /* just in case */
1538 RefPlusOne(); /* fast refresh for one char. */
1539 #endif
1541 else {
1542 #if defined(DSPMBYTE)
1543 /* Cannot use ESC-(number) for multi-byte */
1544 if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1545 extins++;
1546 exterr++;
1547 return(CC_ERROR);
1549 else if (_enable_mbdisp && extins && exterr && Ismbyte2(c))
1551 extins = 0;
1552 exterr = 0;
1553 return(CC_ERROR);
1555 #endif
1556 if (inputmode != MODE_INSERT) {
1558 for(i=0;i<Argument;i++)
1559 UndoBuf[UndoSize++] = *(Cursor+i);
1561 UndoBuf[UndoSize] = '\0';
1562 c_delafter(Argument); /* Do NOT use the saving ONE */
1565 c_insert(Argument);
1567 while (Argument--)
1568 *Cursor++ = (Char) c;
1569 Refresh();
1572 if (inputmode == MODE_REPLACE_1)
1573 (void) v_cmd_mode(0);
1575 #if defined(DSPMBYTE)
1576 return(ret);
1577 #else
1578 return(CC_NORM);
1579 #endif
1583 InsertStr(s) /* insert ASCIZ s at cursor (for complete) */
1584 Char *s;
1586 int len;
1588 if ((len = (int) Strlen(s)) <= 0)
1589 return -1;
1590 if (LastChar + len >= InputLim)
1591 return -1; /* end of buffer space */
1593 c_insert(len);
1594 while (len--)
1595 *Cursor++ = *s++;
1596 return 0;
1599 void
1600 DeleteBack(n) /* delete the n characters before . */
1601 int n;
1603 if (n <= 0)
1604 return;
1605 if (Cursor >= &InputBuf[n]) {
1606 c_delbefore(n); /* delete before dot */
1607 if (n > Cursor - InputBuf)
1608 Cursor = InputBuf; /* bounds check */
1609 else
1610 Cursor -= n;
1611 #if defined(DSPMBYTE)
1612 if(_enable_mbdisp && extdel && Cursor > InputBuf) {
1613 Cursor--;
1614 e_redisp(1);
1616 #endif
1620 CCRETVAL
1621 e_digit(c) /* gray magic here */
1622 int c;
1624 if (!Isdigit(c))
1625 return(CC_ERROR); /* no NULs in the input ever!! */
1627 if (DoingArg) { /* if doing an arg, add this in... */
1628 if (LastCmd == F_ARGFOUR) /* if last command was ^U */
1629 Argument = c - '0';
1630 else {
1631 if (Argument > 1000000)
1632 return CC_ERROR;
1633 Argument = (Argument * 10) + (c - '0');
1635 return(CC_ARGHACK);
1637 else {
1638 if (LastChar + 1 >= InputLim)
1639 return CC_ERROR; /* end of buffer space */
1641 if (inputmode != MODE_INSERT) {
1642 UndoBuf[UndoSize++] = *Cursor;
1643 UndoBuf[UndoSize] = '\0';
1644 c_delafter(1); /* Do NOT use the saving ONE */
1646 c_insert(1);
1647 *Cursor++ = (Char) c;
1648 DoingArg = 0; /* just in case */
1649 RefPlusOne(); /* fast refresh for one char. */
1651 return(CC_NORM);
1654 CCRETVAL
1655 e_argdigit(c) /* for ESC-n */
1656 int c;
1658 c &= ASCII;
1660 if (!Isdigit(c))
1661 return(CC_ERROR); /* no NULs in the input ever!! */
1663 if (DoingArg) { /* if doing an arg, add this in... */
1664 if (Argument > 1000000)
1665 return CC_ERROR;
1666 Argument = (Argument * 10) + (c - '0');
1668 else { /* else starting an argument */
1669 Argument = c - '0';
1670 DoingArg = 1;
1672 return(CC_ARGHACK);
1675 CCRETVAL
1676 v_zero(c) /* command mode 0 for vi */
1677 int c;
1679 if (DoingArg) { /* if doing an arg, add this in... */
1680 if (Argument > 1000000)
1681 return CC_ERROR;
1682 Argument = (Argument * 10) + (c - '0');
1683 return(CC_ARGHACK);
1685 else { /* else starting an argument */
1686 Cursor = InputBuf;
1687 if (ActionFlag & TCSHOP_DELETE) {
1688 c_delfini();
1689 return(CC_REFRESH);
1691 RefCursor(); /* move the cursor */
1692 return(CC_NORM);
1696 /*ARGSUSED*/
1697 CCRETVAL
1698 e_newline(c)
1699 int c;
1700 { /* always ignore argument */
1701 USE(c);
1702 /* PastBottom(); NOW done in ed.inputl.c */
1703 *LastChar++ = '\n'; /* for the benefit of CSH */
1704 *LastChar = '\0'; /* just in case */
1705 if (VImode)
1706 InsertPos = InputBuf; /* Reset editing position */
1707 return(CC_NEWLINE);
1710 /*ARGSUSED*/
1711 CCRETVAL
1712 e_send_eof(c)
1713 int c;
1714 { /* for when ^D is ONLY send-eof */
1715 USE(c);
1716 PastBottom();
1717 *LastChar = '\0'; /* just in case */
1718 return(CC_EOF);
1721 /*ARGSUSED*/
1722 CCRETVAL
1723 e_complete(c)
1724 int c;
1726 USE(c);
1727 *LastChar = '\0'; /* just in case */
1728 return(CC_COMPLETE);
1731 /*ARGSUSED*/
1732 CCRETVAL
1733 e_complete_back(c)
1734 int c;
1736 USE(c);
1737 *LastChar = '\0'; /* just in case */
1738 return(CC_COMPLETE_BACK);
1741 /*ARGSUSED*/
1742 CCRETVAL
1743 e_complete_fwd(c)
1744 int c;
1746 USE(c);
1747 *LastChar = '\0'; /* just in case */
1748 return(CC_COMPLETE_FWD);
1751 /*ARGSUSED*/
1752 CCRETVAL
1753 e_complete_all(c)
1754 int c;
1756 USE(c);
1757 *LastChar = '\0'; /* just in case */
1758 return(CC_COMPLETE_ALL);
1761 /*ARGSUSED*/
1762 CCRETVAL
1763 v_cm_complete(c)
1764 int c;
1766 USE(c);
1767 if (Cursor < LastChar)
1768 Cursor++;
1769 *LastChar = '\0'; /* just in case */
1770 return(CC_COMPLETE);
1773 /*ARGSUSED*/
1774 CCRETVAL
1775 e_toggle_hist(c)
1776 int c;
1778 struct Hist *hp;
1779 int h;
1781 USE(c);
1782 *LastChar = '\0'; /* just in case */
1784 if (Hist_num <= 0) {
1785 return CC_ERROR;
1788 hp = Histlist.Hnext;
1789 if (hp == NULL) { /* this is only if no history */
1790 return(CC_ERROR);
1793 for (h = 1; h < Hist_num; h++)
1794 hp = hp->Hnext;
1796 if (!CurrentHistLit) {
1797 if (hp->histline) {
1798 copyn(InputBuf, hp->histline, INBUFSIZE);
1799 CurrentHistLit = 1;
1801 else {
1802 return CC_ERROR;
1805 else {
1806 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1807 CurrentHistLit = 0;
1810 LastChar = InputBuf + Strlen(InputBuf);
1811 if (LastChar > InputBuf) {
1812 if (LastChar[-1] == '\n')
1813 LastChar--;
1814 if (LastChar[-1] == ' ')
1815 LastChar--;
1816 if (LastChar < InputBuf)
1817 LastChar = InputBuf;
1820 #ifdef KSHVI
1821 if (VImode)
1822 Cursor = InputBuf;
1823 else
1824 #endif /* KSHVI */
1825 Cursor = LastChar;
1827 return(CC_REFRESH);
1830 /*ARGSUSED*/
1831 CCRETVAL
1832 e_up_hist(c)
1833 int c;
1835 Char beep = 0;
1837 USE(c);
1838 UndoAction = TCSHOP_NOP;
1839 *LastChar = '\0'; /* just in case */
1841 if (Hist_num == 0) { /* save the current buffer away */
1842 copyn(HistBuf, InputBuf, INBUFSIZE);
1843 LastHist = HistBuf + (LastChar - InputBuf);
1846 Hist_num += Argument;
1848 if (c_get_histline() == CC_ERROR) {
1849 beep = 1;
1850 (void) c_get_histline(); /* Hist_num was fixed by first call */
1853 Refresh();
1854 if (beep)
1855 return(CC_ERROR);
1856 else
1857 return(CC_NORM); /* was CC_UP_HIST */
1860 /*ARGSUSED*/
1861 CCRETVAL
1862 e_down_hist(c)
1863 int c;
1865 USE(c);
1866 UndoAction = TCSHOP_NOP;
1867 *LastChar = '\0'; /* just in case */
1869 Hist_num -= Argument;
1871 if (Hist_num < 0) {
1872 Hist_num = 0;
1873 return(CC_ERROR); /* make it beep */
1876 return(c_get_histline());
1882 * c_hmatch() return True if the pattern matches the prefix
1884 static int
1885 c_hmatch(str)
1886 Char *str;
1888 if (Strncmp(patbuf, str, (size_t) patlen) == 0)
1889 return 1;
1890 return Gmatch(str, patbuf);
1894 * c_hsetpat(): Set the history seatch pattern
1896 static void
1897 c_hsetpat()
1899 if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1900 patlen = (int) (Cursor - InputBuf);
1901 if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
1902 if (patlen >= 0) {
1903 (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
1904 patbuf[patlen] = '\0';
1906 else
1907 patlen = (int) Strlen(patbuf);
1909 #ifdef SDEBUG
1910 xprintf("\nHist_num = %d\n", Hist_num);
1911 xprintf("patlen = %d\n", patlen);
1912 xprintf("patbuf = \"%S\"\n", patbuf);
1913 xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
1914 #endif
1917 /*ARGSUSED*/
1918 CCRETVAL
1919 e_up_search_hist(c)
1920 int c;
1922 struct Hist *hp;
1923 int h;
1924 bool found = 0;
1926 USE(c);
1927 ActionFlag = TCSHOP_NOP;
1928 UndoAction = TCSHOP_NOP;
1929 *LastChar = '\0'; /* just in case */
1930 if (Hist_num < 0) {
1931 #ifdef DEBUG_EDIT
1932 xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
1933 #endif
1934 Hist_num = 0;
1935 return(CC_ERROR);
1938 if (Hist_num == 0)
1940 copyn(HistBuf, InputBuf, INBUFSIZE);
1941 LastHist = HistBuf + (LastChar - InputBuf);
1945 hp = Histlist.Hnext;
1946 if (hp == NULL)
1947 return(CC_ERROR);
1949 c_hsetpat(); /* Set search pattern !! */
1951 for (h = 1; h <= Hist_num; h++)
1952 hp = hp->Hnext;
1954 while (hp != NULL) {
1955 Char sbuf[INBUFSIZE], *hl;
1956 if (hp->histline == NULL) {
1957 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1958 &hp->Hlex));
1960 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1961 &hp->Hlex);
1962 #ifdef SDEBUG
1963 xprintf("Comparing with \"%S\"\n", hl);
1964 #endif
1965 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1966 hl[LastChar-InputBuf]) && c_hmatch(hl)) {
1967 found++;
1968 break;
1970 h++;
1971 hp = hp->Hnext;
1974 if (!found) {
1975 #ifdef SDEBUG
1976 xprintf("not found\n");
1977 #endif
1978 return(CC_ERROR);
1981 Hist_num = h;
1983 return(c_get_histline());
1986 /*ARGSUSED*/
1987 CCRETVAL
1988 e_down_search_hist(c)
1989 int c;
1991 struct Hist *hp;
1992 int h;
1993 bool found = 0;
1995 USE(c);
1996 ActionFlag = TCSHOP_NOP;
1997 UndoAction = TCSHOP_NOP;
1998 *LastChar = '\0'; /* just in case */
2000 if (Hist_num == 0)
2001 return(CC_ERROR);
2003 hp = Histlist.Hnext;
2004 if (hp == 0)
2005 return(CC_ERROR);
2007 c_hsetpat(); /* Set search pattern !! */
2009 for (h = 1; h < Hist_num && hp; h++) {
2010 Char sbuf[INBUFSIZE], *hl;
2011 if (hp->histline == NULL) {
2012 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
2013 &hp->Hlex));
2015 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
2016 &hp->Hlex);
2017 #ifdef SDEBUG
2018 xprintf("Comparing with \"%S\"\n", hl);
2019 #endif
2020 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
2021 hl[LastChar-InputBuf]) && c_hmatch(hl))
2022 found = h;
2023 hp = hp->Hnext;
2026 if (!found) { /* is it the current history number? */
2027 if (!c_hmatch(HistBuf)) {
2028 #ifdef SDEBUG
2029 xprintf("not found\n");
2030 #endif
2031 return(CC_ERROR);
2035 Hist_num = found;
2037 return(c_get_histline());
2040 /*ARGSUSED*/
2041 CCRETVAL
2042 e_helpme(c)
2043 int c;
2045 USE(c);
2046 PastBottom();
2047 *LastChar = '\0'; /* just in case */
2048 return(CC_HELPME);
2051 /*ARGSUSED*/
2052 CCRETVAL
2053 e_correct(c)
2054 int c;
2056 USE(c);
2057 *LastChar = '\0'; /* just in case */
2058 return(CC_CORRECT);
2061 /*ARGSUSED*/
2062 CCRETVAL
2063 e_correctl(c)
2064 int c;
2066 USE(c);
2067 *LastChar = '\0'; /* just in case */
2068 return(CC_CORRECT_L);
2071 /*ARGSUSED*/
2072 CCRETVAL
2073 e_run_fg_editor(c)
2074 int c;
2076 struct process *pp;
2077 extern bool tellwhat;
2079 USE(c);
2080 if ((pp = find_stop_ed()) != NULL) {
2081 /* save our editor state so we can restore it */
2082 tellwhat = 1;
2083 copyn(WhichBuf, InputBuf, INBUFSIZE);
2084 LastWhich = WhichBuf + (LastChar - InputBuf);
2085 CursWhich = WhichBuf + (Cursor - InputBuf);
2086 HistWhich = Hist_num;
2087 Hist_num = 0; /* for the history commands */
2089 /* put the tty in a sane mode */
2090 PastBottom();
2091 (void) Cookedmode(); /* make sure the tty is set up correctly */
2093 /* do it! */
2094 fg_proc_entry(pp);
2096 (void) Rawmode(); /* go on */
2097 Refresh();
2098 tellwhat = 0;
2100 return(CC_NORM);
2103 /*ARGSUSED*/
2104 CCRETVAL
2105 e_list_choices(c)
2106 int c;
2108 USE(c);
2109 PastBottom();
2110 *LastChar = '\0'; /* just in case */
2111 return(CC_LIST_CHOICES);
2114 /*ARGSUSED*/
2115 CCRETVAL
2116 e_list_all(c)
2117 int c;
2119 USE(c);
2120 PastBottom();
2121 *LastChar = '\0'; /* just in case */
2122 return(CC_LIST_ALL);
2125 /*ARGSUSED*/
2126 CCRETVAL
2127 e_list_glob(c)
2128 int c;
2130 USE(c);
2131 PastBottom();
2132 *LastChar = '\0'; /* just in case */
2133 return(CC_LIST_GLOB);
2136 /*ARGSUSED*/
2137 CCRETVAL
2138 e_expand_glob(c)
2139 int c;
2141 USE(c);
2142 *LastChar = '\0'; /* just in case */
2143 return(CC_EXPAND_GLOB);
2146 /*ARGSUSED*/
2147 CCRETVAL
2148 e_normalize_path(c)
2149 int c;
2151 USE(c);
2152 *LastChar = '\0'; /* just in case */
2153 return(CC_NORMALIZE_PATH);
2156 /*ARGSUSED*/
2157 CCRETVAL
2158 e_normalize_command(c)
2159 int c;
2161 USE(c);
2162 *LastChar = '\0'; /* just in case */
2163 return(CC_NORMALIZE_COMMAND);
2166 /*ARGSUSED*/
2167 CCRETVAL
2168 e_expand_vars(c)
2169 int c;
2171 USE(c);
2172 *LastChar = '\0'; /* just in case */
2173 return(CC_EXPAND_VARS);
2176 /*ARGSUSED*/
2177 CCRETVAL
2178 e_which(c)
2179 int c;
2180 { /* do a fast command line which(1) */
2181 USE(c);
2182 PastBottom();
2183 *LastChar = '\0'; /* just in case */
2184 return(CC_WHICH);
2187 /*ARGSUSED*/
2188 CCRETVAL
2189 e_last_item(c)
2190 int c;
2191 { /* insert the last element of the prev. cmd */
2192 Char *cp;
2193 struct Hist *hp;
2194 struct wordent *wp, *firstp;
2195 int i;
2196 Char buf[INBUFSIZE];
2198 USE(c);
2199 if (Argument <= 0)
2200 return(CC_ERROR);
2202 hp = Histlist.Hnext;
2203 if (hp == NULL) { /* this is only if no history */
2204 return(CC_ERROR);
2207 wp = (hp->Hlex).prev;
2209 if (wp->prev == (struct wordent *) NULL)
2210 return(CC_ERROR); /* an empty history entry */
2212 firstp = (hp->Hlex).next;
2214 /* back up arg words in lex */
2215 for (i = 0; i < Argument && wp != firstp; i++) {
2216 wp = wp->prev;
2219 cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
2220 *cp = '\0';
2221 if (InsertStr(buf))
2222 return(CC_ERROR);
2224 return(CC_REFRESH);
2227 /*ARGSUSED*/
2228 CCRETVAL
2229 e_dabbrev_expand(c)
2230 int c;
2231 { /* expand to preceding word matching prefix */
2232 Char *cp, *ncp, *bp;
2233 struct Hist *hp;
2234 int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
2235 bool found = 0;
2236 Char hbuf[INBUFSIZE];
2237 static int oldevent, hist, word;
2238 static Char *start, *oldcursor;
2240 USE(c);
2241 if (Argument <= 0)
2242 return(CC_ERROR);
2244 cp = c_preword(Cursor, InputBuf, 1, STRshwordsep);
2245 if (cp == Cursor || Isspace(*cp))
2246 return(CC_ERROR);
2248 hp = Histlist.Hnext;
2249 bp = InputBuf;
2250 if (Argument == 1 && eventno == oldevent && cp == start &&
2251 Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
2252 /* continue previous search - go to last match (hist/word) */
2253 if (hist != 0) { /* need to move up history */
2254 for (i = 1; i < hist && hp != NULL; i++)
2255 hp = hp->Hnext;
2256 if (hp == NULL) /* "can't happen" */
2257 return(CC_ERROR);
2258 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2259 *cp = '\0';
2260 bp = hbuf;
2261 hp = hp->Hnext;
2263 cp = c_preword(cp, bp, word, STRshwordsep);
2264 } else { /* starting new search */
2265 oldevent = eventno;
2266 start = cp;
2267 patlen = (int) (Cursor - cp);
2268 (void) Strncpy(patbuf, cp, patlen);
2269 hist = 0;
2270 word = 0;
2273 while (!found) {
2274 ncp = c_preword(cp, bp, 1, STRshwordsep);
2275 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
2276 hist++;
2277 word = 0;
2278 if (hp == NULL)
2279 return(CC_ERROR);
2280 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2281 *cp = '\0';
2282 bp = hbuf;
2283 hp = hp->Hnext;
2284 continue;
2285 } else {
2286 word++;
2287 len = (int) (c_endword(ncp-1, cp, 1, STRshwordsep) - ncp + 1);
2288 cp = ncp;
2290 if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
2291 /* We don't fully check distinct matches as Gnuemacs does: */
2292 if (Argument > 1) { /* just count matches */
2293 if (++arg >= Argument)
2294 found++;
2295 } else { /* match if distinct from previous */
2296 if (len != Cursor - start || Strncmp(cp, start, len) != 0)
2297 found++;
2302 if (LastChar + len - (Cursor - start) >= InputLim)
2303 return(CC_ERROR); /* no room */
2304 DeleteBack(Cursor - start);
2305 c_insert(len);
2306 while (len--)
2307 *Cursor++ = *cp++;
2308 oldcursor = Cursor;
2309 return(CC_REFRESH);
2312 /*ARGSUSED*/
2313 CCRETVAL
2314 e_yank_kill(c)
2315 int c;
2316 { /* almost like GnuEmacs */
2317 int len;
2318 Char *kp, *cp;
2320 USE(c);
2321 if (KillRingLen == 0) /* nothing killed */
2322 return(CC_ERROR);
2323 len = Strlen(KillRing[YankPos].buf);
2324 if (LastChar + len >= InputLim)
2325 return(CC_ERROR); /* end of buffer space */
2327 /* else */
2328 cp = Cursor; /* for speed */
2330 c_insert(len); /* open the space, */
2331 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2332 *cp++ = *kp;
2334 if (Argument == 1) { /* if no arg */
2335 Mark = Cursor; /* mark at beginning, cursor at end */
2336 Cursor = cp;
2337 } else {
2338 Mark = cp; /* else cursor at beginning, mark at end */
2341 return(CC_REFRESH);
2344 /*ARGSUSED*/
2345 CCRETVAL
2346 e_yank_pop(c)
2347 int c;
2348 { /* almost like GnuEmacs */
2349 int m_bef_c, del_len, ins_len;
2350 Char *kp, *cp;
2352 USE(c);
2354 #if 0
2355 /* XXX This "should" be here, but doesn't work, since LastCmd
2356 gets set on CC_ERROR and CC_ARGHACK, which it shouldn't(?).
2357 (But what about F_ARGFOUR?) I.e. if you hit M-y twice the
2358 second one will "succeed" even if the first one wasn't preceded
2359 by a yank, and giving an argument is impossible. Now we "succeed"
2360 regardless of previous command, which is wrong too of course. */
2361 if (LastCmd != F_YANK_KILL && LastCmd != F_YANK_POP)
2362 return(CC_ERROR);
2363 #endif
2365 if (KillRingLen == 0) /* nothing killed */
2366 return(CC_ERROR);
2367 YankPos -= Argument;
2368 while (YankPos < 0)
2369 YankPos += KillRingLen;
2370 YankPos %= KillRingLen;
2372 if (Cursor > Mark) {
2373 del_len = Cursor - Mark;
2374 m_bef_c = 1;
2375 } else {
2376 del_len = Mark - Cursor;
2377 m_bef_c = 0;
2379 ins_len = Strlen(KillRing[YankPos].buf);
2380 if (LastChar + ins_len - del_len >= InputLim)
2381 return(CC_ERROR); /* end of buffer space */
2383 if (m_bef_c) {
2384 c_delbefore(del_len);
2385 Cursor = Mark;
2386 } else {
2387 c_delafter(del_len);
2389 cp = Cursor; /* for speed */
2391 c_insert(ins_len); /* open the space, */
2392 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2393 *cp++ = *kp;
2395 if (m_bef_c) {
2396 Mark = Cursor; /* mark at beginning, cursor at end */
2397 Cursor = cp;
2398 } else {
2399 Mark = cp; /* else cursor at beginning, mark at end */
2402 return(CC_REFRESH);
2405 /*ARGSUSED*/
2406 CCRETVAL
2407 v_delprev(c) /* Backspace key in insert mode */
2408 int c;
2410 int rc;
2412 USE(c);
2413 rc = CC_ERROR;
2415 if (InsertPos != 0) {
2416 if (Argument <= Cursor - InsertPos) {
2417 c_delbefore(Argument); /* delete before */
2418 Cursor -= Argument;
2419 #if defined(DSPMBYTE)
2420 if (_enable_mbdisp && extdel) {
2421 Cursor--;
2422 e_redisp(c);
2424 #endif
2425 rc = CC_REFRESH;
2428 return(rc);
2429 } /* v_delprev */
2431 /*ARGSUSED*/
2432 CCRETVAL
2433 e_delprev(c)
2434 int c;
2436 USE(c);
2437 if (Cursor > InputBuf) {
2438 c_delbefore(Argument); /* delete before dot */
2439 if (Argument > Cursor - InputBuf)
2440 Cursor = InputBuf; /* bounds check */
2441 else
2442 Cursor -= Argument;
2443 #if defined(DSPMBYTE)
2444 if (_enable_mbdisp && extdel && Cursor > InputBuf) {
2445 Cursor--;
2446 e_redisp(c);
2448 #endif
2449 return(CC_REFRESH);
2451 else {
2452 return(CC_ERROR);
2456 /*ARGSUSED*/
2457 CCRETVAL
2458 e_delwordprev(c)
2459 int c;
2461 Char *cp;
2463 USE(c);
2464 if (Cursor == InputBuf)
2465 return(CC_ERROR);
2466 /* else */
2468 cp = c_prev_word(Cursor, InputBuf, Argument);
2470 c_push_kill(cp, Cursor); /* save the text */
2472 c_delbefore((int)(Cursor - cp)); /* delete before dot */
2473 Cursor = cp;
2474 if (Cursor < InputBuf)
2475 Cursor = InputBuf; /* bounds check */
2476 return(CC_REFRESH);
2479 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
2481 * Changed the names of some of the ^D family of editor functions to
2482 * correspond to what they actually do and created new e_delnext_list
2483 * for completeness.
2485 * Old names: New names:
2487 * delete-char delete-char-or-eof
2488 * F_DELNEXT F_DELNEXT_EOF
2489 * e_delnext e_delnext_eof
2490 * edelnxt edelnxteof
2491 * delete-char-or-eof delete-char
2492 * F_DELNEXT_EOF F_DELNEXT
2493 * e_delnext_eof e_delnext
2494 * edelnxteof edelnxt
2495 * delete-char-or-list delete-char-or-list-or-eof
2496 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
2497 * e_list_delnext e_delnext_list_eof
2498 * edellsteof
2499 * (no old equivalent) delete-char-or-list
2500 * F_DELNEXT_LIST
2501 * e_delnext_list
2502 * e_delnxtlst
2505 /* added by mtk@ari.ncl.omron.co.jp (920818) */
2506 /* rename e_delnext() -> e_delnext_eof() */
2507 /*ARGSUSED*/
2508 CCRETVAL
2509 e_delnext(c)
2510 int c;
2512 USE(c);
2513 if (Cursor == LastChar) {/* if I'm at the end */
2514 if (!VImode) {
2515 return(CC_ERROR);
2517 else {
2518 if (Cursor != InputBuf)
2519 Cursor--;
2520 else
2521 return(CC_ERROR);
2524 c_delafter(Argument); /* delete after dot */
2525 if (Cursor > LastChar)
2526 Cursor = LastChar; /* bounds check */
2527 return(CC_REFRESH);
2531 /*ARGSUSED*/
2532 CCRETVAL
2533 e_delnext_eof(c)
2534 int c;
2536 USE(c);
2537 if (Cursor == LastChar) {/* if I'm at the end */
2538 if (!VImode) {
2539 if (Cursor == InputBuf) {
2540 /* if I'm also at the beginning */
2541 so_write(STReof, 4);/* then do a EOF */
2542 flush();
2543 return(CC_EOF);
2545 else
2546 return(CC_ERROR);
2548 else {
2549 if (Cursor != InputBuf)
2550 Cursor--;
2551 else
2552 return(CC_ERROR);
2555 c_delafter(Argument); /* delete after dot */
2556 if (Cursor > LastChar)
2557 Cursor = LastChar; /* bounds check */
2558 return(CC_REFRESH);
2561 /*ARGSUSED*/
2562 CCRETVAL
2563 e_delnext_list(c)
2564 int c;
2566 USE(c);
2567 if (Cursor == LastChar) { /* if I'm at the end */
2568 PastBottom();
2569 *LastChar = '\0'; /* just in case */
2570 return(CC_LIST_CHOICES);
2572 else {
2573 c_delafter(Argument); /* delete after dot */
2574 if (Cursor > LastChar)
2575 Cursor = LastChar; /* bounds check */
2576 return(CC_REFRESH);
2580 /*ARGSUSED*/
2581 CCRETVAL
2582 e_delnext_list_eof(c)
2583 int c;
2585 USE(c);
2586 if (Cursor == LastChar) { /* if I'm at the end */
2587 if (Cursor == InputBuf) { /* if I'm also at the beginning */
2588 so_write(STReof, 4);/* then do a EOF */
2589 flush();
2590 return(CC_EOF);
2592 else {
2593 PastBottom();
2594 *LastChar = '\0'; /* just in case */
2595 return(CC_LIST_CHOICES);
2598 else {
2599 c_delafter(Argument); /* delete after dot */
2600 if (Cursor > LastChar)
2601 Cursor = LastChar; /* bounds check */
2602 return(CC_REFRESH);
2606 /*ARGSUSED*/
2607 CCRETVAL
2608 e_list_eof(c)
2609 int c;
2611 CCRETVAL rv;
2613 USE(c);
2614 if (Cursor == LastChar && Cursor == InputBuf) {
2615 so_write(STReof, 4); /* then do a EOF */
2616 flush();
2617 rv = CC_EOF;
2619 else {
2620 PastBottom();
2621 *LastChar = '\0'; /* just in case */
2622 rv = CC_LIST_CHOICES;
2624 return rv;
2627 /*ARGSUSED*/
2628 CCRETVAL
2629 e_delwordnext(c)
2630 int c;
2632 Char *cp;
2634 USE(c);
2635 if (Cursor == LastChar)
2636 return(CC_ERROR);
2637 /* else */
2639 cp = c_next_word(Cursor, LastChar, Argument);
2641 c_push_kill(Cursor, cp); /* save the text */
2643 c_delafter((int)(cp - Cursor)); /* delete after dot */
2644 if (Cursor > LastChar)
2645 Cursor = LastChar; /* bounds check */
2646 return(CC_REFRESH);
2649 /*ARGSUSED*/
2650 CCRETVAL
2651 e_toend(c)
2652 int c;
2654 USE(c);
2655 Cursor = LastChar;
2656 if (VImode)
2657 if (ActionFlag & TCSHOP_DELETE) {
2658 c_delfini();
2659 return(CC_REFRESH);
2661 RefCursor(); /* move the cursor */
2662 return(CC_NORM);
2665 /*ARGSUSED*/
2666 CCRETVAL
2667 e_tobeg(c)
2668 int c;
2670 USE(c);
2671 Cursor = InputBuf;
2673 if (VImode) {
2674 while (Isspace(*Cursor)) /* We want FIRST non space character */
2675 Cursor++;
2676 if (ActionFlag & TCSHOP_DELETE) {
2677 c_delfini();
2678 return(CC_REFRESH);
2682 RefCursor(); /* move the cursor */
2683 return(CC_NORM);
2686 /*ARGSUSED*/
2687 CCRETVAL
2688 e_killend(c)
2689 int c;
2691 USE(c);
2692 c_push_kill(Cursor, LastChar); /* copy it */
2693 LastChar = Cursor; /* zap! -- delete to end */
2694 return(CC_REFRESH);
2698 /*ARGSUSED*/
2699 CCRETVAL
2700 e_killbeg(c)
2701 int c;
2703 USE(c);
2704 c_push_kill(InputBuf, Cursor); /* copy it */
2705 c_delbefore((int)(Cursor - InputBuf));
2706 Cursor = InputBuf; /* zap! */
2707 return(CC_REFRESH);
2710 /*ARGSUSED*/
2711 CCRETVAL
2712 e_killall(c)
2713 int c;
2715 USE(c);
2716 c_push_kill(InputBuf, LastChar); /* copy it */
2717 LastChar = InputBuf; /* zap! -- delete all of it */
2718 Cursor = InputBuf;
2719 return(CC_REFRESH);
2722 /*ARGSUSED*/
2723 CCRETVAL
2724 e_killregion(c)
2725 int c;
2727 USE(c);
2728 if (!Mark)
2729 return(CC_ERROR);
2731 if (Mark > Cursor) {
2732 c_push_kill(Cursor, Mark); /* copy it */
2733 c_delafter((int)(Mark - Cursor)); /* delete it - UNUSED BY VI mode */
2734 Mark = Cursor;
2736 else { /* mark is before cursor */
2737 c_push_kill(Mark, Cursor); /* copy it */
2738 c_delbefore((int)(Cursor - Mark));
2739 Cursor = Mark;
2741 return(CC_REFRESH);
2744 /*ARGSUSED*/
2745 CCRETVAL
2746 e_copyregion(c)
2747 int c;
2749 USE(c);
2750 if (!Mark)
2751 return(CC_ERROR);
2753 if (Mark > Cursor) {
2754 c_push_kill(Cursor, Mark); /* copy it */
2756 else { /* mark is before cursor */
2757 c_push_kill(Mark, Cursor); /* copy it */
2759 return(CC_NORM); /* don't even need to Refresh() */
2762 /*ARGSUSED*/
2763 CCRETVAL
2764 e_charswitch(cc)
2765 int cc;
2767 Char c;
2769 USE(cc);
2771 /* do nothing if we are at beginning of line or have only one char */
2772 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
2773 return(CC_ERROR);
2776 if (Cursor < LastChar) {
2777 Cursor++;
2779 c = Cursor[-2];
2780 Cursor[-2] = Cursor[-1];
2781 Cursor[-1] = c;
2782 return(CC_REFRESH);
2785 /*ARGSUSED*/
2786 CCRETVAL
2787 e_gcharswitch(cc)
2788 int cc;
2789 { /* gosmacs style ^T */
2790 Char c;
2792 USE(cc);
2793 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
2794 c = Cursor[-2];
2795 Cursor[-2] = Cursor[-1];
2796 Cursor[-1] = c;
2797 return(CC_REFRESH);
2799 else {
2800 return(CC_ERROR);
2804 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2805 /*ARGSUSED*/
2806 static void
2807 e_charback_mbyte(argument)
2808 int argument;
2810 if (!_enable_mbdisp) {
2811 if (Argument > Cursor - InputBuf)
2812 Cursor = InputBuf;
2813 else
2814 Cursor -= Argument;
2816 else {
2817 while (0 < argument && Cursor > InputBuf) {
2818 if (Cursor - 1 != InputBuf &&
2819 Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) {
2820 Cursor--;
2822 Cursor--;
2823 argument--;
2827 #endif
2829 /*ARGSUSED*/
2830 CCRETVAL
2831 e_charback(c)
2832 int c;
2834 USE(c);
2835 if (Cursor > InputBuf) {
2836 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2837 e_charback_mbyte(Argument);
2838 #else
2839 if (Argument > Cursor - InputBuf)
2840 Cursor = InputBuf;
2841 else
2842 Cursor -= Argument;
2843 #endif
2845 if (VImode)
2846 if (ActionFlag & TCSHOP_DELETE) {
2847 c_delfini();
2848 return(CC_REFRESH);
2851 RefCursor();
2852 return(CC_NORM);
2854 else {
2855 return(CC_ERROR);
2859 /*ARGSUSED*/
2860 CCRETVAL
2861 v_wordback(c)
2862 int c;
2864 USE(c);
2865 if (Cursor == InputBuf)
2866 return(CC_ERROR);
2867 /* else */
2869 Cursor = c_preword(Cursor, InputBuf, Argument, STRshwspace); /* bounds check */
2871 if (ActionFlag & TCSHOP_DELETE) {
2872 c_delfini();
2873 return(CC_REFRESH);
2876 RefCursor();
2877 return(CC_NORM);
2880 /*ARGSUSED*/
2881 CCRETVAL
2882 e_wordback(c)
2883 int c;
2885 USE(c);
2886 if (Cursor == InputBuf)
2887 return(CC_ERROR);
2888 /* else */
2890 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
2892 if (VImode)
2893 if (ActionFlag & TCSHOP_DELETE) {
2894 c_delfini();
2895 return(CC_REFRESH);
2898 RefCursor();
2899 return(CC_NORM);
2902 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2903 /*ARGSUSED*/
2904 static void
2905 e_charfwd_mbyte(argument)
2906 int argument;
2908 if (!_enable_mbdisp)
2909 Cursor += argument;
2910 else
2911 while (0 < argument && Cursor < LastChar) {
2912 if (Cursor + 1 != LastChar &&
2913 Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) {
2914 Cursor++;
2916 Cursor++;
2917 argument--;
2920 #endif
2922 /*ARGSUSED*/
2923 CCRETVAL
2924 e_charfwd(c)
2925 int c;
2927 USE(c);
2928 if (Cursor < LastChar) {
2929 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2930 e_charfwd_mbyte(Argument);
2931 #else
2932 Cursor += Argument;
2933 #endif
2934 if (Cursor > LastChar)
2935 Cursor = LastChar;
2937 if (VImode)
2938 if (ActionFlag & TCSHOP_DELETE) {
2939 c_delfini();
2940 return(CC_REFRESH);
2943 RefCursor();
2944 return(CC_NORM);
2946 else {
2947 return(CC_ERROR);
2951 /*ARGSUSED*/
2952 CCRETVAL
2953 e_wordfwd(c)
2954 int c;
2956 USE(c);
2957 if (Cursor == LastChar)
2958 return(CC_ERROR);
2959 /* else */
2961 Cursor = c_next_word(Cursor, LastChar, Argument);
2963 if (VImode)
2964 if (ActionFlag & TCSHOP_DELETE) {
2965 c_delfini();
2966 return(CC_REFRESH);
2969 RefCursor();
2970 return(CC_NORM);
2973 /*ARGSUSED*/
2974 CCRETVAL
2975 v_wordfwd(c)
2976 int c;
2978 USE(c);
2979 if (Cursor == LastChar)
2980 return(CC_ERROR);
2981 /* else */
2983 Cursor = c_nexword(Cursor, LastChar, Argument);
2985 if (VImode)
2986 if (ActionFlag & TCSHOP_DELETE) {
2987 c_delfini();
2988 return(CC_REFRESH);
2991 RefCursor();
2992 return(CC_NORM);
2995 /*ARGSUSED*/
2996 CCRETVAL
2997 v_wordbegnext(c)
2998 int c;
3000 USE(c);
3001 if (Cursor == LastChar)
3002 return(CC_ERROR);
3003 /* else */
3005 Cursor = c_next_word(Cursor, LastChar, Argument);
3006 if (Cursor < LastChar)
3007 Cursor++;
3009 if (VImode)
3010 if (ActionFlag & TCSHOP_DELETE) {
3011 c_delfini();
3012 return(CC_REFRESH);
3015 RefCursor();
3016 return(CC_NORM);
3019 /*ARGSUSED*/
3020 static CCRETVAL
3021 v_repeat_srch(c)
3022 int c;
3024 CCRETVAL rv = CC_ERROR;
3025 #ifdef SDEBUG
3026 xprintf("dir %d patlen %d patbuf %S\n",
3027 c, patlen, patbuf);
3028 #endif
3030 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
3031 LastChar = InputBuf;
3032 switch (c) {
3033 case F_DOWN_SEARCH_HIST:
3034 rv = e_down_search_hist(0);
3035 break;
3036 case F_UP_SEARCH_HIST:
3037 rv = e_up_search_hist(0);
3038 break;
3039 default:
3040 break;
3042 return rv;
3045 static CCRETVAL
3046 v_csearch_back(ch, count, tflag)
3047 int ch, count, tflag;
3049 Char *cp;
3051 cp = Cursor;
3052 while (count--) {
3053 if (*cp == ch)
3054 cp--;
3055 while (cp > InputBuf && *cp != ch)
3056 cp--;
3059 if (cp < InputBuf || (cp == InputBuf && *cp != ch))
3060 return(CC_ERROR);
3062 if (*cp == ch && tflag)
3063 cp++;
3065 Cursor = cp;
3067 if (ActionFlag & TCSHOP_DELETE) {
3068 Cursor++;
3069 c_delfini();
3070 return(CC_REFRESH);
3073 RefCursor();
3074 return(CC_NORM);
3077 static CCRETVAL
3078 v_csearch_fwd(ch, count, tflag)
3079 int ch, count, tflag;
3081 Char *cp;
3083 cp = Cursor;
3084 while (count--) {
3085 if(*cp == ch)
3086 cp++;
3087 while (cp < LastChar && *cp != ch)
3088 cp++;
3091 if (cp >= LastChar)
3092 return(CC_ERROR);
3094 if (*cp == ch && tflag)
3095 cp--;
3097 Cursor = cp;
3099 if (ActionFlag & TCSHOP_DELETE) {
3100 Cursor++;
3101 c_delfini();
3102 return(CC_REFRESH);
3104 RefCursor();
3105 return(CC_NORM);
3108 /*ARGSUSED*/
3109 static CCRETVAL
3110 v_action(c)
3111 int c;
3113 Char *cp, *kp;
3115 if (ActionFlag == TCSHOP_DELETE) {
3116 ActionFlag = TCSHOP_NOP;
3117 ActionPos = 0;
3119 UndoSize = 0;
3120 kp = UndoBuf;
3121 for (cp = InputBuf; cp < LastChar; cp++) {
3122 *kp++ = *cp;
3123 UndoSize++;
3126 UndoAction = TCSHOP_INSERT;
3127 UndoPtr = InputBuf;
3128 LastChar = InputBuf;
3129 Cursor = InputBuf;
3130 if (c & TCSHOP_INSERT)
3131 c_alternativ_key_map(0);
3133 return(CC_REFRESH);
3135 #ifdef notdef
3136 else if (ActionFlag == TCSHOP_NOP) {
3137 #endif
3138 ActionPos = Cursor;
3139 ActionFlag = c;
3140 return(CC_ARGHACK); /* Do NOT clear out argument */
3141 #ifdef notdef
3143 else {
3144 ActionFlag = 0;
3145 ActionPos = 0;
3146 return(CC_ERROR);
3148 #endif
3151 #ifdef COMMENT
3152 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
3153 static void
3154 c_get_word(begin, end)
3155 Char **begin;
3156 Char **end;
3158 Char *cp;
3160 cp = &Cursor[0];
3161 while (Argument--) {
3162 while ((cp <= LastChar) && (isword(*cp)))
3163 cp++;
3164 *end = --cp;
3165 while ((cp >= InputBuf) && (isword(*cp)))
3166 cp--;
3167 *begin = ++cp;
3170 #endif /* COMMENT */
3172 /*ARGSUSED*/
3173 CCRETVAL
3174 e_uppercase(c)
3175 int c;
3177 Char *cp, *end;
3179 USE(c);
3180 end = c_next_word(Cursor, LastChar, Argument);
3182 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
3183 if (Islower(*cp))
3184 *cp = Toupper(*cp);
3186 Cursor = end;
3187 if (Cursor > LastChar)
3188 Cursor = LastChar;
3189 return(CC_REFRESH);
3193 /*ARGSUSED*/
3194 CCRETVAL
3195 e_capitolcase(c)
3196 int c;
3198 Char *cp, *end;
3200 USE(c);
3201 end = c_next_word(Cursor, LastChar, Argument);
3203 cp = Cursor;
3204 for (; cp < end; cp++) {
3205 if (Isalpha(*cp)) {
3206 if (Islower(*cp))
3207 *cp = Toupper(*cp);
3208 cp++;
3209 break;
3212 for (; cp < end; cp++)
3213 if (Isupper(*cp))
3214 *cp = Tolower(*cp);
3216 Cursor = end;
3217 if (Cursor > LastChar)
3218 Cursor = LastChar;
3219 return(CC_REFRESH);
3222 /*ARGSUSED*/
3223 CCRETVAL
3224 e_lowercase(c)
3225 int c;
3227 Char *cp, *end;
3229 USE(c);
3230 end = c_next_word(Cursor, LastChar, Argument);
3232 for (cp = Cursor; cp < end; cp++)
3233 if (Isupper(*cp))
3234 *cp = Tolower(*cp);
3236 Cursor = end;
3237 if (Cursor > LastChar)
3238 Cursor = LastChar;
3239 return(CC_REFRESH);
3243 /*ARGSUSED*/
3244 CCRETVAL
3245 e_set_mark(c)
3246 int c;
3248 USE(c);
3249 Mark = Cursor;
3250 return(CC_NORM);
3253 /*ARGSUSED*/
3254 CCRETVAL
3255 e_exchange_mark(c)
3256 int c;
3258 Char *cp;
3260 USE(c);
3261 cp = Cursor;
3262 Cursor = Mark;
3263 Mark = cp;
3264 RefCursor();
3265 return(CC_NORM);
3268 /*ARGSUSED*/
3269 CCRETVAL
3270 e_argfour(c)
3271 int c;
3272 { /* multiply current argument by 4 */
3273 USE(c);
3274 if (Argument > 1000000)
3275 return CC_ERROR;
3276 DoingArg = 1;
3277 Argument *= 4;
3278 return(CC_ARGHACK);
3281 /*ARGSUSED*/
3282 CCRETVAL
3283 e_quote(c)
3284 int c;
3286 Char ch;
3287 int num;
3289 USE(c);
3290 QuoteModeOn();
3291 num = GetNextChar(&ch);
3292 QuoteModeOff();
3293 if (num == 1)
3294 return e_insert(ch);
3295 else
3296 return e_send_eof(0);
3299 /*ARGSUSED*/
3300 CCRETVAL
3301 e_metanext(c)
3302 int c;
3304 USE(c);
3305 MetaNext = 1;
3306 return(CC_ARGHACK); /* preserve argument */
3309 #ifdef notdef
3310 /*ARGSUSED*/
3311 CCRETVAL
3312 e_extendnext(c)
3313 int c;
3315 CurrentKeyMap = CcAltMap;
3316 return(CC_ARGHACK); /* preserve argument */
3319 #endif
3321 /*ARGSUSED*/
3322 CCRETVAL
3323 v_insbeg(c)
3324 int c;
3325 { /* move to beginning of line and start vi
3326 * insert mode */
3327 USE(c);
3328 Cursor = InputBuf;
3329 InsertPos = Cursor;
3331 UndoPtr = Cursor;
3332 UndoAction = TCSHOP_DELETE;
3334 RefCursor(); /* move the cursor */
3335 c_alternativ_key_map(0);
3336 return(CC_NORM);
3339 /*ARGSUSED*/
3340 CCRETVAL
3341 v_replone(c)
3342 int c;
3343 { /* vi mode overwrite one character */
3344 USE(c);
3345 c_alternativ_key_map(0);
3346 inputmode = MODE_REPLACE_1;
3347 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3348 UndoPtr = Cursor;
3349 UndoSize = 0;
3350 return(CC_NORM);
3353 /*ARGSUSED*/
3354 CCRETVAL
3355 v_replmode(c)
3356 int c;
3357 { /* vi mode start overwriting */
3358 USE(c);
3359 c_alternativ_key_map(0);
3360 inputmode = MODE_REPLACE;
3361 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3362 UndoPtr = Cursor;
3363 UndoSize = 0;
3364 return(CC_NORM);
3367 /*ARGSUSED*/
3368 CCRETVAL
3369 v_substchar(c)
3370 int c;
3371 { /* vi mode substitute for one char */
3372 USE(c);
3373 c_delafter(Argument);
3374 c_alternativ_key_map(0);
3375 return(CC_REFRESH);
3378 /*ARGSUSED*/
3379 CCRETVAL
3380 v_substline(c)
3381 int c;
3382 { /* vi mode replace whole line */
3383 USE(c);
3384 (void) e_killall(0);
3385 c_alternativ_key_map(0);
3386 return(CC_REFRESH);
3389 /*ARGSUSED*/
3390 CCRETVAL
3391 v_chgtoend(c)
3392 int c;
3393 { /* vi mode change to end of line */
3394 USE(c);
3395 (void) e_killend(0);
3396 c_alternativ_key_map(0);
3397 return(CC_REFRESH);
3400 /*ARGSUSED*/
3401 CCRETVAL
3402 v_insert(c)
3403 int c;
3404 { /* vi mode start inserting */
3405 USE(c);
3406 c_alternativ_key_map(0);
3408 InsertPos = Cursor;
3409 UndoPtr = Cursor;
3410 UndoAction = TCSHOP_DELETE;
3412 return(CC_NORM);
3415 /*ARGSUSED*/
3416 CCRETVAL
3417 v_add(c)
3418 int c;
3419 { /* vi mode start adding */
3420 USE(c);
3421 c_alternativ_key_map(0);
3422 if (Cursor < LastChar)
3424 Cursor++;
3425 if (Cursor > LastChar)
3426 Cursor = LastChar;
3427 RefCursor();
3430 InsertPos = Cursor;
3431 UndoPtr = Cursor;
3432 UndoAction = TCSHOP_DELETE;
3434 return(CC_NORM);
3437 /*ARGSUSED*/
3438 CCRETVAL
3439 v_addend(c)
3440 int c;
3441 { /* vi mode to add at end of line */
3442 USE(c);
3443 c_alternativ_key_map(0);
3444 Cursor = LastChar;
3446 InsertPos = LastChar; /* Mark where insertion begins */
3447 UndoPtr = LastChar;
3448 UndoAction = TCSHOP_DELETE;
3450 RefCursor();
3451 return(CC_NORM);
3454 /*ARGSUSED*/
3455 CCRETVAL
3456 v_change_case(cc)
3457 int cc;
3459 char c;
3461 USE(cc);
3462 if (Cursor < LastChar) {
3463 #ifndef WINNT_NATIVE
3464 c = *Cursor;
3465 #else
3466 c = CHAR & *Cursor;
3467 #endif /* WINNT_NATIVE */
3468 if (Isupper(c))
3469 *Cursor++ = Tolower(c);
3470 else if (Islower(c))
3471 *Cursor++ = Toupper(c);
3472 else
3473 Cursor++;
3474 RefPlusOne(); /* fast refresh for one char */
3475 return(CC_NORM);
3477 return(CC_ERROR);
3480 /*ARGSUSED*/
3481 CCRETVAL
3482 e_expand(c)
3483 int c;
3485 Char *p;
3486 extern bool justpr;
3488 USE(c);
3489 for (p = InputBuf; Isspace(*p); p++)
3490 continue;
3491 if (p == LastChar)
3492 return(CC_ERROR);
3494 justpr++;
3495 Expand++;
3496 return(e_newline(0));
3499 /*ARGSUSED*/
3500 CCRETVAL
3501 e_startover(c)
3502 int c;
3503 { /* erase all of current line, start again */
3504 USE(c);
3505 ResetInLine(0); /* reset the input pointers */
3506 return(CC_REFRESH);
3509 /*ARGSUSED*/
3510 CCRETVAL
3511 e_redisp(c)
3512 int c;
3514 USE(c);
3515 ClearLines();
3516 ClearDisp();
3517 return(CC_REFRESH);
3520 /*ARGSUSED*/
3521 CCRETVAL
3522 e_cleardisp(c)
3523 int c;
3525 USE(c);
3526 ClearScreen(); /* clear the whole real screen */
3527 ClearDisp(); /* reset everything */
3528 return(CC_REFRESH);
3531 /*ARGSUSED*/
3532 CCRETVAL
3533 e_tty_int(c)
3534 int c;
3536 USE(c);
3537 #if defined(_MINIX) || defined(WINNT_NATIVE)
3538 /* SAK PATCH: erase all of current line, start again */
3539 ResetInLine(0); /* reset the input pointers */
3540 xputchar('\n');
3541 ClearDisp();
3542 return (CC_REFRESH);
3543 #else /* !_MINIX && !WINNT_NATIVE */
3544 /* do no editing */
3545 return (CC_NORM);
3546 #endif /* _MINIX || WINNT_NATIVE */
3550 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
3551 * Function to send a character back to the input stream in cooked
3552 * mode. Only works if we have TIOCSTI
3554 /*ARGSUSED*/
3555 CCRETVAL
3556 e_stuff_char(c)
3557 int c;
3559 #ifdef TIOCSTI
3560 extern int Tty_raw_mode;
3561 int was_raw = Tty_raw_mode;
3562 char ch = (char) c;
3564 if (was_raw)
3565 (void) Cookedmode();
3567 (void) write(SHIN, "\n", 1);
3568 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
3570 if (was_raw)
3571 (void) Rawmode();
3572 return(e_redisp(c));
3573 #else /* !TIOCSTI */
3574 return(CC_ERROR);
3575 #endif /* !TIOCSTI */
3578 /*ARGSUSED*/
3579 CCRETVAL
3580 e_insovr(c)
3581 int c;
3583 USE(c);
3584 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
3585 return(CC_NORM);
3588 /*ARGSUSED*/
3589 CCRETVAL
3590 e_tty_dsusp(c)
3591 int c;
3593 USE(c);
3594 /* do no editing */
3595 return(CC_NORM);
3598 /*ARGSUSED*/
3599 CCRETVAL
3600 e_tty_flusho(c)
3601 int c;
3603 USE(c);
3604 /* do no editing */
3605 return(CC_NORM);
3608 /*ARGSUSED*/
3609 CCRETVAL
3610 e_tty_quit(c)
3611 int c;
3613 USE(c);
3614 /* do no editing */
3615 return(CC_NORM);
3618 /*ARGSUSED*/
3619 CCRETVAL
3620 e_tty_tsusp(c)
3621 int c;
3623 USE(c);
3624 /* do no editing */
3625 return(CC_NORM);
3628 /*ARGSUSED*/
3629 CCRETVAL
3630 e_tty_stopo(c)
3631 int c;
3633 USE(c);
3634 /* do no editing */
3635 return(CC_NORM);
3638 /*ARGSUSED*/
3639 CCRETVAL
3640 e_expand_history(c)
3641 int c;
3643 USE(c);
3644 *LastChar = '\0'; /* just in case */
3645 c_substitute();
3646 return(CC_NORM);
3649 /*ARGSUSED*/
3650 CCRETVAL
3651 e_magic_space(c)
3652 int c;
3654 USE(c);
3655 *LastChar = '\0'; /* just in case */
3656 c_substitute();
3657 return(e_insert(' '));
3660 /*ARGSUSED*/
3661 CCRETVAL
3662 e_inc_fwd(c)
3663 int c;
3665 USE(c);
3666 patlen = 0;
3667 return e_inc_search(F_DOWN_SEARCH_HIST);
3671 /*ARGSUSED*/
3672 CCRETVAL
3673 e_inc_back(c)
3674 int c;
3676 USE(c);
3677 patlen = 0;
3678 return e_inc_search(F_UP_SEARCH_HIST);
3681 /*ARGSUSED*/
3682 CCRETVAL
3683 e_copyprev(c)
3684 int c;
3686 Char *cp, *oldc, *dp;
3688 USE(c);
3689 if (Cursor == InputBuf)
3690 return(CC_ERROR);
3691 /* else */
3693 oldc = Cursor;
3694 /* does a bounds check */
3695 cp = c_prev_word(Cursor, InputBuf, Argument);
3697 c_insert((int)(oldc - cp));
3698 for (dp = oldc; cp < oldc && dp < LastChar; cp++)
3699 *dp++ = *cp;
3701 Cursor = dp; /* put cursor at end */
3703 return(CC_REFRESH);
3706 /*ARGSUSED*/
3707 CCRETVAL
3708 e_tty_starto(c)
3709 int c;
3711 USE(c);
3712 /* do no editing */
3713 return(CC_NORM);
3716 /*ARGSUSED*/
3717 CCRETVAL
3718 e_load_average(c)
3719 int c;
3721 USE(c);
3722 PastBottom();
3723 #ifdef TIOCSTAT
3725 * Here we pass &c to the ioctl because some os's (NetBSD) expect it
3726 * there even if they don't use it. (lukem@netbsd.org)
3728 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
3729 #endif
3730 xprintf(CGETS(5, 1, "Load average unavailable\n"));
3731 return(CC_REFRESH);
3734 /*ARGSUSED*/
3735 CCRETVAL
3736 v_chgmeta(c)
3737 int c;
3739 USE(c);
3741 * Delete with insert == change: first we delete and then we leave in
3742 * insert mode.
3744 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
3747 /*ARGSUSED*/
3748 CCRETVAL
3749 v_delmeta(c)
3750 int c;
3752 USE(c);
3753 return(v_action(TCSHOP_DELETE));
3757 /*ARGSUSED*/
3758 CCRETVAL
3759 v_endword(c)
3760 int c;
3762 USE(c);
3763 if (Cursor == LastChar)
3764 return(CC_ERROR);
3765 /* else */
3767 Cursor = c_endword(Cursor, LastChar, Argument, STRshwspace);
3769 if (ActionFlag & TCSHOP_DELETE)
3771 Cursor++;
3772 c_delfini();
3773 return(CC_REFRESH);
3776 RefCursor();
3777 return(CC_NORM);
3780 /*ARGSUSED*/
3781 CCRETVAL
3782 v_eword(c)
3783 int c;
3785 USE(c);
3786 if (Cursor == LastChar)
3787 return(CC_ERROR);
3788 /* else */
3790 Cursor = c_eword(Cursor, LastChar, Argument);
3792 if (ActionFlag & TCSHOP_DELETE) {
3793 Cursor++;
3794 c_delfini();
3795 return(CC_REFRESH);
3798 RefCursor();
3799 return(CC_NORM);
3802 /*ARGSUSED*/
3803 CCRETVAL
3804 v_char_fwd(c)
3805 int c;
3807 Char ch;
3809 USE(c);
3810 if (GetNextChar(&ch) != 1)
3811 return e_send_eof(0);
3813 srch_dir = CHAR_FWD;
3814 srch_char = ch;
3816 return v_csearch_fwd(ch, Argument, 0);
3820 /*ARGSUSED*/
3821 CCRETVAL
3822 v_char_back(c)
3823 int c;
3825 Char ch;
3827 USE(c);
3828 if (GetNextChar(&ch) != 1)
3829 return e_send_eof(0);
3831 srch_dir = CHAR_BACK;
3832 srch_char = ch;
3834 return v_csearch_back(ch, Argument, 0);
3837 /*ARGSUSED*/
3838 CCRETVAL
3839 v_charto_fwd(c)
3840 int c;
3842 Char ch;
3844 USE(c);
3845 if (GetNextChar(&ch) != 1)
3846 return e_send_eof(0);
3848 return v_csearch_fwd(ch, Argument, 1);
3852 /*ARGSUSED*/
3853 CCRETVAL
3854 v_charto_back(c)
3855 int c;
3857 Char ch;
3859 USE(c);
3860 if (GetNextChar(&ch) != 1)
3861 return e_send_eof(0);
3863 return v_csearch_back(ch, Argument, 1);
3866 /*ARGSUSED*/
3867 CCRETVAL
3868 v_rchar_fwd(c)
3869 int c;
3871 USE(c);
3872 if (srch_char == 0)
3873 return CC_ERROR;
3875 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
3876 v_csearch_back(srch_char, Argument, 0);
3879 /*ARGSUSED*/
3880 CCRETVAL
3881 v_rchar_back(c)
3882 int c;
3884 USE(c);
3885 if (srch_char == 0)
3886 return CC_ERROR;
3888 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
3889 v_csearch_back(srch_char, Argument, 0);
3892 /*ARGSUSED*/
3893 CCRETVAL
3894 v_undo(c)
3895 int c;
3897 int loop;
3898 Char *kp, *cp;
3899 Char temp;
3900 int size;
3902 USE(c);
3903 switch (UndoAction) {
3904 case TCSHOP_DELETE|TCSHOP_INSERT:
3905 case TCSHOP_DELETE:
3906 if (UndoSize == 0) return(CC_NORM);
3907 cp = UndoPtr;
3908 kp = UndoBuf;
3909 for (loop=0; loop < UndoSize; loop++) /* copy the chars */
3910 *kp++ = *cp++; /* into UndoBuf */
3912 for (cp = UndoPtr; cp <= LastChar; cp++)
3913 *cp = cp[UndoSize];
3915 LastChar -= UndoSize;
3916 Cursor = UndoPtr;
3918 UndoAction = TCSHOP_INSERT;
3919 break;
3921 case TCSHOP_INSERT:
3922 if (UndoSize == 0) return(CC_NORM);
3923 cp = UndoPtr;
3924 Cursor = UndoPtr;
3925 kp = UndoBuf;
3926 c_insert(UndoSize); /* open the space, */
3927 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
3928 *cp++ = *kp++;
3930 UndoAction = TCSHOP_DELETE;
3931 break;
3933 case TCSHOP_CHANGE:
3934 if (UndoSize == 0) return(CC_NORM);
3935 cp = UndoPtr;
3936 Cursor = UndoPtr;
3937 kp = UndoBuf;
3938 size = (int)(Cursor-LastChar); /* NOT NSL independant */
3939 if (size < UndoSize)
3940 size = UndoSize;
3941 for(loop = 0; loop < size; loop++) {
3942 temp = *kp;
3943 *kp++ = *cp;
3944 *cp++ = temp;
3946 break;
3948 default:
3949 return(CC_ERROR);
3952 return(CC_REFRESH);
3955 /*ARGSUSED*/
3956 CCRETVAL
3957 v_ush_meta(c)
3958 int c;
3960 USE(c);
3961 return v_search(F_UP_SEARCH_HIST);
3964 /*ARGSUSED*/
3965 CCRETVAL
3966 v_dsh_meta(c)
3967 int c;
3969 USE(c);
3970 return v_search(F_DOWN_SEARCH_HIST);
3973 /*ARGSUSED*/
3974 CCRETVAL
3975 v_rsrch_fwd(c)
3976 int c;
3978 USE(c);
3979 if (patlen == 0) return(CC_ERROR);
3980 return(v_repeat_srch(searchdir));
3983 /*ARGSUSED*/
3984 CCRETVAL
3985 v_rsrch_back(c)
3986 int c;
3988 USE(c);
3989 if (patlen == 0) return(CC_ERROR);
3990 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
3991 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
3994 #ifndef WINNT_NATIVE
3995 /* Since ed.defns.h is generated from ed.defns.c, these empty
3996 functions will keep the F_NUM_FNS consistent
3998 CCRETVAL
3999 e_copy_to_clipboard(c)
4000 int c;
4002 USE(c);
4003 return CC_ERROR;
4006 CCRETVAL
4007 e_paste_from_clipboard(c)
4008 int c;
4010 USE(c);
4011 return (CC_ERROR);
4014 CCRETVAL
4015 e_dosify_next(c)
4016 int c;
4018 USE(c);
4019 return (CC_ERROR);
4021 CCRETVAL
4022 e_dosify_prev(c)
4023 int c;
4025 USE(c);
4026 return (CC_ERROR);
4028 CCRETVAL
4029 e_page_up(c)
4030 int c;
4032 USE(c);
4033 return (CC_ERROR);
4035 CCRETVAL
4036 e_page_down(c)
4037 int c;
4039 USE(c);
4040 return (CC_ERROR);
4042 #endif /* !WINNT_NATIVE */
4044 #ifdef notdef
4045 void
4046 MoveCursor(n) /* move cursor + right - left char */
4047 int n;
4049 Cursor = Cursor + n;
4050 if (Cursor < InputBuf)
4051 Cursor = InputBuf;
4052 if (Cursor > LastChar)
4053 Cursor = LastChar;
4054 return;
4057 Char *
4058 GetCursor()
4060 return(Cursor);
4064 PutCursor(p)
4065 Char *p;
4067 if (p < InputBuf || p > LastChar)
4068 return 1; /* Error */
4069 Cursor = p;
4070 return 0;
4072 #endif