1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.83 2005/03/03 16:21:08 kim Exp $ */
3 * ed.chared.c: Character editing functions.
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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:
41 # echo h<press key bound to dabbrev-expande>
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
53 # echo "h<press key bound to dabbrev-expande>
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\"
65 # echo '\"" '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.
75 RCSID("$Id: ed.chared.c,v 3.83 2005/03/03 16:21:08 kim Exp $")
83 #define TCSHOP_NOP 0x00
84 #define TCSHOP_DELETE 0x01
85 #define TCSHOP_INSERT 0x02
86 #define TCSHOP_CHANGE 0x04
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 */
105 static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
106 static Char patbuf[INBUFSIZE]; /* Search target */
107 static int patlen = 0;
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((Char));
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));
130 static void c_get_word __P((Char **, Char **));
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 e_insert_str __P((Char *));
142 static CCRETVAL v_search __P((int));
143 static CCRETVAL v_csearch_fwd __P((Char, int, int));
144 static CCRETVAL v_action __P((int));
145 static CCRETVAL v_csearch_back __P((Char, int, int));
148 c_alternativ_key_map(state)
153 CurrentKeyMap = CcKeyMap;
156 CurrentKeyMap = CcAltMap;
162 AltKeyMap = (Char) state;
171 if (LastChar + num >= InputLim)
172 return; /* can't go past end of buffer */
174 if (Cursor < LastChar) { /* if I must move chars */
175 for (cp = LastChar; cp >= Cursor; cp--)
177 if (Mark && Mark > Cursor)
187 Char *cp, *kp = NULL;
189 if (num > LastChar - Cursor)
190 num = (int) (LastChar - Cursor); /* bounds check */
192 if (num > 0) { /* if I can delete anything */
193 num = NLSExtend(Cursor, LastChar - Cursor, num);
195 kp = UndoBuf; /* Set Up for VI undo command */
196 UndoAction = TCSHOP_INSERT;
199 for (cp = Cursor; cp <= LastChar; cp++) {
200 *kp++ = *cp; /* Save deleted chars into undobuf */
205 for (cp = Cursor; cp + num <= LastChar; cp++)
208 if (Mark && Mark > Cursor)
214 * XXX: We don't want to do that. In emacs mode overwrite should be
215 * sticky. I am not sure how that affects vi mode
217 inputmode = MODE_INSERT;
223 c_delbefore(num) /* delete before dot, with bounds checking */
226 Char *cp, *kp = NULL;
228 if (num > Cursor - InputBuf)
229 num = (int) (Cursor - InputBuf); /* bounds check */
231 if (num > 0) { /* if I can delete anything */
232 num = NLSExtend(Cursor, Cursor - InputBuf, -num);
234 kp = UndoBuf; /* Set Up for VI undo command */
235 UndoAction = TCSHOP_INSERT;
237 UndoPtr = Cursor - num;
238 for (cp = Cursor - num; cp <= LastChar; cp++) {
244 for (cp = Cursor - num; cp + num <= LastChar; cp++)
248 if (Mark && Mark > Cursor)
254 c_preword(p, low, n, delim)
255 Char *p, *low, *delim;
262 while (prev < p) { /* Skip initial non-word chars */
263 if (!Strchr(delim, *prev) || *(prev-1) == (Char)'\\')
272 new = c_endword(prev-1, p, 1, delim); /* Skip to next non-word char */
273 new++; /* Step away from end of word */
274 while (new <= p) { /* Skip trailing non-word chars */
275 if (!Strchr(delim, *new) || *(new-1) == (Char)'\\')
281 p = prev; /* Set to previous word start */
290 * c_to_class() returns the class of the given character.
292 * This is used to make the c_prev_word() and c_next_word() functions
293 * work like vi's, which classify characters. A word is a sequence of
294 * characters belonging to the same class, classes being defined as
298 * 2/ alphanumeric chars, + underscore
306 return C_CLASS_WHITE;
308 if (Isdigit(ch) || Isalpha(ch) || ch == '_')
309 return C_CLASS_ALNUM;
311 return C_CLASS_OTHER;
315 c_prev_word(p, low, n)
323 while ((p >= low) && !isword(*p))
325 while ((p >= low) && isword(*p))
329 /* cp now points to one character before the word */
333 /* cp now points where we want it */
343 /* scan until beginning of current word (may be all whitespace!) */
344 c_class = c_to_class(*p);
345 while ((p >= low) && c_class == c_to_class(*p))
348 /* if this was a non_whitespace word, we're ready */
349 if (c_class != C_CLASS_WHITE)
352 /* otherwise, move back to beginning of the word just found */
353 c_class = c_to_class(*p);
354 while ((p >= low) && c_class == c_to_class(*p))
358 p++; /* correct overshoot */
364 c_next_word(p, high, n)
370 while ((p < high) && !isword(*p))
372 while ((p < high) && isword(*p))
377 /* p now points where we want it */
387 /* scan until end of current word (may be all whitespace!) */
388 c_class = c_to_class(*p);
389 while ((p < high) && c_class == c_to_class(*p))
392 /* if this was all whitespace, we're ready */
393 if (c_class == C_CLASS_WHITE)
396 /* if we've found white-space at the end of the word, skip it */
397 while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
401 p--; /* correct overshoot */
407 c_nexword(p, high, n)
412 while ((p < high) && !Isspace(*p))
414 while ((p < high) && Isspace(*p))
420 /* p now points where we want it */
425 * Expand-History (originally "Magic-Space") code added by
426 * Ray Moody <ray@gibbs.physics.purdue.edu>
427 * this is a neat, but odd, addition.
431 * c_number: Ignore character p points to, return number appearing after that.
432 * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
433 * Return p pointing to last char used.
437 * dval is the number to subtract from for things like $-3
441 c_number(p, num, dval)
455 *num = NCARGS; /* Handle $ */
458 sign = -1; /* Handle $- */
461 for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
463 *num = (sign < 0 ? dval - i : i);
468 * excl_expand: There is an excl to be expanded to p -- do the right thing
469 * with it and return a version of p advanced over the expanded stuff. Also,
470 * update tsh_cur and related things as appropriate...
478 struct Hist *h = Histlist.Hnext;
480 int i, from, to, dval;
486 Char *modbuf, *omodbuf;
491 switch (*(q = p + 1)) {
494 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
498 if ((l = (h->Hlex).prev) != 0)
499 bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
503 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
507 if (been_once) { /* unknown argument */
508 /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
509 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
515 if (*q == ':') /* short form: !:arg */
520 * Search for a space, tab, or colon. See if we have a number (as
521 * in !1234:xyz). Remember the number.
523 for (i = 0, all_dig = 1;
524 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
526 * PWP: !-4 is a valid history argument too, therefore the test
527 * is if not a digit, or not a - as the first character.
529 if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
532 all_dig = 2;/* we are sneeky about this */
534 i = 10 * i + *q - '0';
539 * If we have a number, search for event i. Otherwise, search for
540 * a named event (as in !foo). (In this case, I is the length of
545 i = -i; /* make it negitive */
546 if (i < 0) /* if !-4 (for example) */
547 i = eventno + 1 + i; /* remember: i is < 0 */
548 for (; h; h = h->Hnext) {
554 for (i = (int) (q - p); h; h = h->Hnext) {
555 if ((l = &h->Hlex) != 0) {
556 if (!Strncmp(p + 1, l->next->word, (size_t) i))
564 if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
565 q[1] == '$' || q[1] == '^') { /* get some args */
566 p = q[1] == ':' ? ++q : q;
570 if ((q[1] < '0' || q[1] > '9') &&
571 q[1] != '-' && q[1] != '$' && q[1] != '^')
576 if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
579 * Count up the number of words in this event. Store it in dval.
580 * Dval will be fed to number.
583 if ((l = h->Hlex.prev) != 0) {
584 for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
592 q = c_number(q, &from, dval);
595 if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
598 q = c_number(q, &to, dval);
600 else if (q[1] == '*') {
607 if (from < 0 || to < from)
609 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
611 else { /* get whole cmd */
612 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
618 * Apply modifiers, if any.
622 modbuf = omodbuf = buf;
623 while (q[1] == ':' && modbuf != NULL) {
633 if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
635 xfree((ptr_t) omodbuf);
643 /* Not implemented; this needs to be done before expanding
644 * lex. We don't have the words available to us anymore.
664 if (omodbuf != buf) {
665 (void) Strcpy(buf, omodbuf);
666 xfree((ptr_t) omodbuf);
672 * Now replace the text from op to q inclusive with the text from buf to
678 * Now replace text non-inclusively like a real CS major!
680 if (LastChar + (bend - buf) - (q - op) >= InputLim)
682 (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
683 (size_t) ((LastChar - q) * sizeof(Char)));
684 LastChar += (bend - buf) - (q - op);
685 Cursor += (bend - buf) - (q - op);
686 (void) memmove((ptr_t) op, (ptr_t) buf,
687 (size_t) ((bend - buf) * sizeof(Char)));
689 return(op + (bend - buf));
696 * c_excl: An excl has been found at point p -- back up and find some white
697 * space (or the beginning of the buffer) and properly expand all the excl's
698 * from there up to the current cursor position. We also avoid (trying to)
710 * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
711 * back p up to just before the current word.
713 if ((p[1] == ' ' || p[1] == '\t') &&
714 (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
715 for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
721 while (*p != ' ' && *p != '\t' && p > InputBuf)
726 * Forever: Look for history char. (Stop looking when we find the cursor.)
727 * Count backslashes. Of odd, skip history char. Return if all done.
728 * Expand if even number of backslashes.
731 while (*p != HIST && p < Cursor)
733 for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
751 * Start p out one character before the cursor. Move it backwards looking
752 * for white space, the beginning of the line, or a history character.
755 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
759 * If we found a history character, go expand it.
767 c_delfini() /* Finish up delete action */
771 if (ActionFlag & TCSHOP_INSERT)
772 c_alternativ_key_map(0);
774 ActionFlag = TCSHOP_NOP;
779 UndoAction = TCSHOP_INSERT;
781 if (Cursor > ActionPos) {
782 Size = (int) (Cursor-ActionPos);
786 else if (Cursor < ActionPos) {
787 Size = (int)(ActionPos-Cursor);
799 c_endword(p, high, n, delim)
800 Char *p, *high, *delim;
807 while (p < high) { /* Skip non-word chars */
808 if (!Strchr(delim, *p) || *(p-1) == (Char)'\\')
812 while (p < high) { /* Skip string */
813 if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
814 if (inquote || *(p-1) != (Char)'\\') { /* Should it be honored? */
815 if (inquote == 0) inquote = *p;
816 else if (inquote == *p) inquote = 0;
819 /* Break if unquoted non-word char */
820 if (!inquote && Strchr(delim, *p) && *(p-1) != (Char)'\\')
839 while ((p < high) && Isspace(*p))
843 while ((p < high) && Isalnum(*p))
846 while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
854 /* Set the max length of the kill ring */
863 max = 1; /* no ring, but always one buffer */
864 if (max == KillRingMax)
866 new = (CStr *)xcalloc((size_t) max, sizeof(CStr));
867 if (KillRing != NULL) {
868 if (KillRingLen != 0) {
869 if (max >= KillRingLen) {
874 j = (KillPos - count + KillRingLen) % KillRingLen;
876 for (i = 0; i < KillRingLen; i++) {
877 if (i < count) /* copy latest */
878 new[i] = KillRing[j];
879 else /* free the others */
880 xfree(KillRing[j].buf);
881 j = (j + 1) % KillRingLen;
884 KillPos = count % max;
893 /* Push string from start upto (but not including) end onto kill ring */
895 c_push_kill(start, end)
900 int len = end - start, i, j, k;
902 /* Check for duplicates? */
903 if (KillRingLen > 0 && (dp = varval(STRkilldup)) != STRNULL) {
904 YankPos = (KillPos - 1 + KillRingLen) % KillRingLen;
905 if (eq(dp, STRerase)) { /* erase earlier one (actually move up) */
907 for (i = 0; i < KillRingLen; i++) {
908 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
909 KillRing[j].buf[len] == '\0') {
911 for ( ; i > 0; i--) {
913 j = (j + 1) % KillRingLen;
914 KillRing[k] = KillRing[j];
919 j = (j - 1 + KillRingLen) % KillRingLen;
921 } else if (eq(dp, STRall)) { /* skip if any earlier */
922 for (i = 0; i < KillRingLen; i++)
923 if (Strncmp(KillRing[i].buf, start, (size_t) len) == 0 &&
924 KillRing[i].buf[len] == '\0')
926 } else if (eq(dp, STRprev)) { /* skip if immediately previous */
928 if (Strncmp(KillRing[j].buf, start, (size_t) len) == 0 &&
929 KillRing[j].buf[len] == '\0')
934 /* No duplicate, go ahead and push */
935 len++; /* need space for '\0' */
937 if (KillRingLen < KillRingMax)
939 pos = &KillRing[KillPos];
940 KillPos = (KillPos + 1) % KillRingMax;
941 if (pos->len < len) {
942 if (pos->buf == NULL)
943 pos->buf = (Char *) xmalloc(len * sizeof(Char));
945 pos->buf = (Char *) xrealloc((ptr_t) pos->buf, len * sizeof(Char));
961 if (Hist_num == 0) { /* if really the current line */
962 copyn(InputBuf, HistBuf, INBUFSIZE);
963 LastChar = InputBuf + (LastHist - HistBuf);
979 for (h = 1; h < Hist_num; h++) {
980 if ((hp->Hnext) == NULL) {
987 if (HistLit && hp->histline) {
988 copyn(InputBuf, hp->histline, INBUFSIZE);
992 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
995 LastChar = InputBuf + Strlen(InputBuf);
997 if (LastChar > InputBuf) {
998 if (LastChar[-1] == '\n')
1001 if (LastChar[-1] == ' ')
1004 if (LastChar < InputBuf)
1005 LastChar = InputBuf;
1019 c_search_line(pattern, dir)
1026 len = (int) Strlen(pattern);
1028 if (dir == F_UP_SEARCH_HIST) {
1029 for (cp = Cursor; cp >= InputBuf; cp--)
1030 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1031 Gmatch(cp, pattern)) {
1037 for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1038 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1039 Gmatch(cp, pattern)) {
1051 static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1052 STRbck[] = { 'b', 'c', 'k', '\0' };
1053 static Char pchar = ':'; /* ':' = normal, '?' = failed */
1054 static Char endcmd[2];
1056 *oldCursor = Cursor,
1058 CCRETVAL ret = CC_NORM;
1059 int oldHist_num = Hist_num,
1064 if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
1069 if (patlen == 0) { /* first round */
1071 patbuf[patlen++] = '*';
1075 for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
1076 *cp; *LastChar++ = *cp++)
1078 *LastChar++ = pchar;
1079 for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
1084 if (GetNextChar(&ch) != 1)
1085 return(e_send_eof(0));
1087 switch (ch > NT_NUM_KEYS
1088 ? F_INSERT : CurrentKeyMap[(unsigned char) ch]) {
1092 if (patlen > INBUFSIZE - 3)
1095 patbuf[patlen++] = ch;
1103 newdir = F_DOWN_SEARCH_HIST;
1108 newdir = F_UP_SEARCH_HIST;
1121 case 0007: /* ^G: Abort */
1126 case 0027: /* ^W: Append word */
1127 /* No can do if globbing characters in pattern */
1128 for (cp = &patbuf[1]; ; cp++)
1129 if (cp >= &patbuf[patlen]) {
1130 Cursor += patlen - 1;
1131 cp = c_next_word(Cursor, LastChar, 1);
1132 while (Cursor < cp && *Cursor != '\n') {
1133 if (patlen > INBUFSIZE - 3) {
1137 patbuf[patlen++] = *Cursor;
1138 *LastChar++ = *Cursor++;
1144 } else if (isglob(*cp)) {
1150 default: /* Terminate and execute cmd */
1155 case 0033: /* ESC: Terminate */
1163 while (LastChar > InputBuf && *LastChar != '\n')
1169 /* Can't search if unmatched '[' */
1170 for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
1171 if (*cp == '[' || *cp == ']') {
1176 if (patlen > 1 && ch != '[') {
1177 if (redo && newdir == dir) {
1178 if (pchar == '?') { /* wrap around */
1179 Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
1180 if (c_get_histline() == CC_ERROR)
1181 /* Hist_num was fixed by first call */
1182 (void) c_get_histline();
1183 Cursor = newdir == F_UP_SEARCH_HIST ?
1184 LastChar : InputBuf;
1186 Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
1188 patbuf[patlen++] = '*';
1189 patbuf[patlen] = '\0';
1190 if (Cursor < InputBuf || Cursor > LastChar ||
1191 (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
1192 LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
1193 ret = newdir == F_UP_SEARCH_HIST ?
1194 e_up_search_hist(0) : e_down_search_hist(0);
1195 if (ret != CC_ERROR) {
1196 Cursor = newdir == F_UP_SEARCH_HIST ?
1197 LastChar : InputBuf;
1198 (void) c_search_line(&patbuf[1], newdir);
1201 patbuf[--patlen] = '\0';
1202 if (ret == CC_ERROR) {
1204 if (Hist_num != oldHist_num) {
1205 Hist_num = oldHist_num;
1206 if (c_get_histline() == CC_ERROR)
1216 ret = e_inc_search(newdir);
1218 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
1219 /* break abort of failed search at last non-failed */
1225 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
1226 /* restore on normal return or error exit */
1229 if (Hist_num != oldHist_num) {
1230 Hist_num = oldHist_num;
1231 if (c_get_histline() == CC_ERROR)
1235 if (ret == CC_ERROR)
1238 if (done || ret != CC_NORM)
1250 Char tmpbuf[INBUFSIZE];
1251 Char oldbuf[INBUFSIZE];
1255 copyn(oldbuf, InputBuf, INBUFSIZE);
1259 tmpbuf[tmplen++] = '*';
1262 LastChar = InputBuf;
1266 c_insert(2); /* prompt + '\n' */
1268 *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
1270 for (ch = 0;ch == 0;) {
1271 if (GetNextChar(&ch) != 1)
1272 return(e_send_eof(0));
1274 case 0010: /* Delete and backspace */
1279 tmpbuf[tmplen--] = '\0';
1282 copyn(InputBuf, oldbuf, INBUFSIZE);
1291 case 0033: /* ESC */
1293 case '\r': /* Newline */
1296 case '\012': /* ASCII Line feed */
1297 case '\015': /* ASCII (or EBCDIC) Return */
1302 if (tmplen >= INBUFSIZE)
1305 tmpbuf[tmplen++] = ch;
1317 * Use the old pattern, but wild-card it.
1321 LastChar = InputBuf;
1326 if (patbuf[0] != '*') {
1327 (void) Strcpy(tmpbuf, patbuf);
1329 (void) Strcpy(&patbuf[1], tmpbuf);
1331 patbuf[patlen++] = '*';
1332 patbuf[patlen] = '\0';
1336 tmpbuf[tmplen++] = '*';
1337 tmpbuf[tmplen] = '\0';
1338 (void) Strcpy(patbuf, tmpbuf);
1341 LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
1342 Cursor = LastChar = InputBuf;
1343 if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
1344 e_down_search_hist(0)) == CC_ERROR) {
1362 * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
1363 * entry point, called from the CcKeyMap indirected into the
1374 ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
1377 if (UndoPtr > Cursor)
1378 UndoSize = (int)(UndoPtr - Cursor);
1380 UndoSize = (int)(Cursor - UndoPtr);
1382 inputmode = MODE_INSERT;
1383 c_alternativ_key_map(1);
1386 * We don't want to move the cursor, because all the editing
1387 * commands don't include the character under the cursor.
1389 if (Cursor > InputBuf)
1400 { /* bound to keys that arn't really assigned */
1414 if (LastChar + Argument * n >= InputLim)
1415 return(CC_ERROR); /* end of buffer space */
1416 if (inputmode != MODE_INSERT) {
1417 c_delafter(Argument * NLSChars(c));
1419 c_insert(Argument * n);
1420 while (Argument--) {
1421 for (i = 0; i < n; i++)
1432 #ifndef SHORT_STRINGS
1433 c &= ASCII; /* no meta chars ever */
1437 return(CC_ERROR); /* no NULs in the input ever!! */
1439 if (LastChar + Argument >= InputLim)
1440 return(CC_ERROR); /* end of buffer space */
1442 if (!NLSFinished(Cursor, 0, c)) {
1443 Char buf[MB_LEN_MAX + 1];
1448 if (GetNextChar(&c) != 1)
1450 f = NLSFinished(buf, i, (eChar)c);
1456 } while (!f && i < MB_CUR_MAX);
1459 return e_insert_str(buf);
1464 if (Argument == 1) { /* How was this optimized ???? */
1466 if (inputmode != MODE_INSERT) {
1467 UndoBuf[UndoSize++] = *Cursor;
1468 UndoBuf[UndoSize] = '\0';
1469 c_delafter(1); /* Do NOT use the saving ONE */
1473 *Cursor++ = (Char) c;
1474 DoingArg = 0; /* just in case */
1475 RefPlusOne(1); /* fast refresh for one char. */
1478 if (inputmode != MODE_INSERT) {
1480 for(i = 0; i < Argument; i++)
1481 UndoBuf[UndoSize++] = *(Cursor + i);
1483 UndoBuf[UndoSize] = '\0';
1484 c_delafter(Argument); /* Do NOT use the saving ONE */
1490 *Cursor++ = (Char) c;
1494 if (inputmode == MODE_REPLACE_1)
1495 (void) v_cmd_mode(0);
1501 InsertStr(s) /* insert ASCIZ s at cursor (for complete) */
1506 if ((len = (int) Strlen(s)) <= 0)
1508 if (LastChar + len >= InputLim)
1509 return -1; /* end of buffer space */
1518 DeleteBack(n) /* delete the n characters before . */
1523 if (Cursor >= &InputBuf[n]) {
1524 c_delbefore(n); /* delete before dot */
1529 e_digit(c) /* gray magic here */
1533 return(CC_ERROR); /* no NULs in the input ever!! */
1535 if (DoingArg) { /* if doing an arg, add this in... */
1536 if (LastCmd == F_ARGFOUR) /* if last command was ^U */
1539 if (Argument > 1000000)
1541 Argument = (Argument * 10) + (c - '0');
1546 if (LastChar + 1 >= InputLim)
1547 return CC_ERROR; /* end of buffer space */
1549 if (inputmode != MODE_INSERT) {
1550 UndoBuf[UndoSize++] = *Cursor;
1551 UndoBuf[UndoSize] = '\0';
1552 c_delafter(1); /* Do NOT use the saving ONE */
1555 *Cursor++ = (Char) c;
1556 DoingArg = 0; /* just in case */
1557 RefPlusOne(1); /* fast refresh for one char. */
1563 e_argdigit(c) /* for ESC-n */
1569 return(CC_ERROR); /* no NULs in the input ever!! */
1571 if (DoingArg) { /* if doing an arg, add this in... */
1572 if (Argument > 1000000)
1574 Argument = (Argument * 10) + (c - '0');
1576 else { /* else starting an argument */
1584 v_zero(c) /* command mode 0 for vi */
1587 if (DoingArg) { /* if doing an arg, add this in... */
1588 if (Argument > 1000000)
1590 Argument = (Argument * 10) + (c - '0');
1593 else { /* else starting an argument */
1595 if (ActionFlag & TCSHOP_DELETE) {
1599 RefCursor(); /* move the cursor */
1608 { /* always ignore argument */
1610 /* PastBottom(); NOW done in ed.inputl.c */
1611 *LastChar++ = '\n'; /* for the benefit of CSH */
1612 *LastChar = '\0'; /* just in case */
1614 InsertPos = InputBuf; /* Reset editing position */
1622 { /* for when ^D is ONLY send-eof */
1625 *LastChar = '\0'; /* just in case */
1635 *LastChar = '\0'; /* just in case */
1636 return(CC_COMPLETE);
1645 *LastChar = '\0'; /* just in case */
1646 return(CC_COMPLETE_BACK);
1655 *LastChar = '\0'; /* just in case */
1656 return(CC_COMPLETE_FWD);
1665 *LastChar = '\0'; /* just in case */
1666 return(CC_COMPLETE_ALL);
1675 if (Cursor < LastChar)
1677 *LastChar = '\0'; /* just in case */
1678 return(CC_COMPLETE);
1690 *LastChar = '\0'; /* just in case */
1692 if (Hist_num <= 0) {
1696 hp = Histlist.Hnext;
1697 if (hp == NULL) { /* this is only if no history */
1701 for (h = 1; h < Hist_num; h++)
1704 if (!CurrentHistLit) {
1706 copyn(InputBuf, hp->histline, INBUFSIZE);
1714 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1718 LastChar = InputBuf + Strlen(InputBuf);
1719 if (LastChar > InputBuf) {
1720 if (LastChar[-1] == '\n')
1722 if (LastChar[-1] == ' ')
1724 if (LastChar < InputBuf)
1725 LastChar = InputBuf;
1746 UndoAction = TCSHOP_NOP;
1747 *LastChar = '\0'; /* just in case */
1749 if (Hist_num == 0) { /* save the current buffer away */
1750 copyn(HistBuf, InputBuf, INBUFSIZE);
1751 LastHist = HistBuf + (LastChar - InputBuf);
1754 Hist_num += Argument;
1756 if (c_get_histline() == CC_ERROR) {
1758 (void) c_get_histline(); /* Hist_num was fixed by first call */
1765 return(CC_NORM); /* was CC_UP_HIST */
1774 UndoAction = TCSHOP_NOP;
1775 *LastChar = '\0'; /* just in case */
1777 Hist_num -= Argument;
1781 return(CC_ERROR); /* make it beep */
1784 return(c_get_histline());
1790 * c_hmatch() return True if the pattern matches the prefix
1796 if (Strncmp(patbuf, str, (size_t) patlen) == 0)
1798 return Gmatch(str, patbuf);
1802 * c_hsetpat(): Set the history seatch pattern
1807 if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1808 patlen = (int) (Cursor - InputBuf);
1809 if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
1811 (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
1812 patbuf[patlen] = '\0';
1815 patlen = (int) Strlen(patbuf);
1818 xprintf("\nHist_num = %d\n", Hist_num);
1819 xprintf("patlen = %d\n", patlen);
1820 xprintf("patbuf = \"%S\"\n", patbuf);
1821 xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
1835 ActionFlag = TCSHOP_NOP;
1836 UndoAction = TCSHOP_NOP;
1837 *LastChar = '\0'; /* just in case */
1840 xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
1848 copyn(HistBuf, InputBuf, INBUFSIZE);
1849 LastHist = HistBuf + (LastChar - InputBuf);
1853 hp = Histlist.Hnext;
1857 c_hsetpat(); /* Set search pattern !! */
1859 for (h = 1; h <= Hist_num; h++)
1862 while (hp != NULL) {
1863 Char sbuf[INBUFSIZE], *hl;
1864 if (hp->histline == NULL) {
1865 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1868 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1871 xprintf("Comparing with \"%S\"\n", hl);
1873 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1874 hl[LastChar-InputBuf]) && c_hmatch(hl)) {
1884 xprintf("not found\n");
1891 return(c_get_histline());
1896 e_down_search_hist(c)
1904 ActionFlag = TCSHOP_NOP;
1905 UndoAction = TCSHOP_NOP;
1906 *LastChar = '\0'; /* just in case */
1911 hp = Histlist.Hnext;
1915 c_hsetpat(); /* Set search pattern !! */
1917 for (h = 1; h < Hist_num && hp; h++) {
1918 Char sbuf[INBUFSIZE], *hl;
1919 if (hp->histline == NULL) {
1920 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1923 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1926 xprintf("Comparing with \"%S\"\n", hl);
1928 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1929 hl[LastChar-InputBuf]) && c_hmatch(hl))
1934 if (!found) { /* is it the current history number? */
1935 if (!c_hmatch(HistBuf)) {
1937 xprintf("not found\n");
1945 return(c_get_histline());
1955 *LastChar = '\0'; /* just in case */
1965 *LastChar = '\0'; /* just in case */
1975 *LastChar = '\0'; /* just in case */
1976 return(CC_CORRECT_L);
1987 if ((pp = find_stop_ed()) != NULL) {
1988 /* save our editor state so we can restore it */
1990 copyn(WhichBuf, InputBuf, INBUFSIZE);
1991 LastWhich = WhichBuf + (LastChar - InputBuf);
1992 CursWhich = WhichBuf + (Cursor - InputBuf);
1993 HistWhich = Hist_num;
1994 Hist_num = 0; /* for the history commands */
1996 /* put the tty in a sane mode */
1998 (void) Cookedmode(); /* make sure the tty is set up correctly */
2003 (void) Rawmode(); /* go on */
2017 *LastChar = '\0'; /* just in case */
2018 return(CC_LIST_CHOICES);
2028 *LastChar = '\0'; /* just in case */
2029 return(CC_LIST_ALL);
2039 *LastChar = '\0'; /* just in case */
2040 return(CC_LIST_GLOB);
2049 *LastChar = '\0'; /* just in case */
2050 return(CC_EXPAND_GLOB);
2059 *LastChar = '\0'; /* just in case */
2060 return(CC_NORMALIZE_PATH);
2065 e_normalize_command(c)
2069 *LastChar = '\0'; /* just in case */
2070 return(CC_NORMALIZE_COMMAND);
2079 *LastChar = '\0'; /* just in case */
2080 return(CC_EXPAND_VARS);
2087 { /* do a fast command line which(1) */
2090 *LastChar = '\0'; /* just in case */
2098 { /* insert the last element of the prev. cmd */
2101 struct wordent *wp, *firstp;
2103 Char buf[INBUFSIZE];
2109 hp = Histlist.Hnext;
2110 if (hp == NULL) { /* this is only if no history */
2114 wp = (hp->Hlex).prev;
2116 if (wp->prev == (struct wordent *) NULL)
2117 return(CC_ERROR); /* an empty history entry */
2119 firstp = (hp->Hlex).next;
2121 /* back up arg words in lex */
2122 for (i = 0; i < Argument && wp != firstp; i++) {
2126 cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
2138 { /* expand to preceding word matching prefix */
2139 Char *cp, *ncp, *bp;
2141 int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
2143 Char hbuf[INBUFSIZE];
2144 static int oldevent, hist, word;
2145 static Char *start, *oldcursor;
2151 cp = c_preword(Cursor, InputBuf, 1, STRshwordsep);
2152 if (cp == Cursor || Isspace(*cp))
2155 hp = Histlist.Hnext;
2157 if (Argument == 1 && eventno == oldevent && cp == start &&
2158 Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
2159 /* continue previous search - go to last match (hist/word) */
2160 if (hist != 0) { /* need to move up history */
2161 for (i = 1; i < hist && hp != NULL; i++)
2163 if (hp == NULL) /* "can't happen" */
2165 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2170 cp = c_preword(cp, bp, word, STRshwordsep);
2171 } else { /* starting new search */
2174 patlen = (int) (Cursor - cp);
2175 (void) Strncpy(patbuf, cp, patlen);
2181 ncp = c_preword(cp, bp, 1, STRshwordsep);
2182 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
2187 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2194 len = (int) (c_endword(ncp-1, cp, 1, STRshwordsep) - ncp + 1);
2197 if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
2198 /* We don't fully check distinct matches as Gnuemacs does: */
2199 if (Argument > 1) { /* just count matches */
2200 if (++arg >= Argument)
2202 } else { /* match if distinct from previous */
2203 if (len != Cursor - start || Strncmp(cp, start, len) != 0)
2209 if (LastChar + len - (Cursor - start) >= InputLim)
2210 return(CC_ERROR); /* no room */
2211 DeleteBack(Cursor - start);
2223 { /* almost like GnuEmacs */
2228 if (KillRingLen == 0) /* nothing killed */
2230 len = Strlen(KillRing[YankPos].buf);
2231 if (LastChar + len >= InputLim)
2232 return(CC_ERROR); /* end of buffer space */
2235 cp = Cursor; /* for speed */
2237 c_insert(len); /* open the space, */
2238 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2241 if (Argument == 1) { /* if no arg */
2242 Mark = Cursor; /* mark at beginning, cursor at end */
2245 Mark = cp; /* else cursor at beginning, mark at end */
2255 { /* almost like GnuEmacs */
2256 int m_bef_c, del_len, ins_len;
2262 /* XXX This "should" be here, but doesn't work, since LastCmd
2263 gets set on CC_ERROR and CC_ARGHACK, which it shouldn't(?).
2264 (But what about F_ARGFOUR?) I.e. if you hit M-y twice the
2265 second one will "succeed" even if the first one wasn't preceded
2266 by a yank, and giving an argument is impossible. Now we "succeed"
2267 regardless of previous command, which is wrong too of course. */
2268 if (LastCmd != F_YANK_KILL && LastCmd != F_YANK_POP)
2272 if (KillRingLen == 0) /* nothing killed */
2274 YankPos -= Argument;
2276 YankPos += KillRingLen;
2277 YankPos %= KillRingLen;
2279 if (Cursor > Mark) {
2280 del_len = Cursor - Mark;
2283 del_len = Mark - Cursor;
2286 ins_len = Strlen(KillRing[YankPos].buf);
2287 if (LastChar + ins_len - del_len >= InputLim)
2288 return(CC_ERROR); /* end of buffer space */
2291 c_delbefore(del_len);
2293 c_delafter(del_len);
2295 cp = Cursor; /* for speed */
2297 c_insert(ins_len); /* open the space, */
2298 for (kp = KillRing[YankPos].buf; *kp; kp++) /* copy the chars */
2302 Mark = Cursor; /* mark at beginning, cursor at end */
2305 Mark = cp; /* else cursor at beginning, mark at end */
2313 v_delprev(c) /* Backspace key in insert mode */
2321 if (InsertPos != 0) {
2322 if (Argument <= Cursor - InsertPos) {
2323 c_delbefore(Argument); /* delete before */
2336 if (Cursor > InputBuf) {
2337 c_delbefore(Argument); /* delete before dot */
2353 if (Cursor == InputBuf)
2357 cp = c_prev_word(Cursor, InputBuf, Argument);
2359 c_push_kill(cp, Cursor); /* save the text */
2361 c_delbefore((int)(Cursor - cp)); /* delete before dot */
2365 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
2367 * Changed the names of some of the ^D family of editor functions to
2368 * correspond to what they actually do and created new e_delnext_list
2371 * Old names: New names:
2373 * delete-char delete-char-or-eof
2374 * F_DELNEXT F_DELNEXT_EOF
2375 * e_delnext e_delnext_eof
2376 * edelnxt edelnxteof
2377 * delete-char-or-eof delete-char
2378 * F_DELNEXT_EOF F_DELNEXT
2379 * e_delnext_eof e_delnext
2380 * edelnxteof edelnxt
2381 * delete-char-or-list delete-char-or-list-or-eof
2382 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
2383 * e_list_delnext e_delnext_list_eof
2385 * (no old equivalent) delete-char-or-list
2391 /* added by mtk@ari.ncl.omron.co.jp (920818) */
2392 /* rename e_delnext() -> e_delnext_eof() */
2399 if (Cursor == LastChar) {/* if I'm at the end */
2404 if (Cursor != InputBuf)
2410 c_delafter(Argument); /* delete after dot */
2411 if (Cursor > LastChar)
2412 Cursor = LastChar; /* bounds check */
2423 if (Cursor == LastChar) {/* if I'm at the end */
2425 if (Cursor == InputBuf) {
2426 /* if I'm also at the beginning */
2427 so_write(STReof, 4);/* then do a EOF */
2435 if (Cursor != InputBuf)
2441 c_delafter(Argument); /* delete after dot */
2442 if (Cursor > LastChar)
2443 Cursor = LastChar; /* bounds check */
2453 if (Cursor == LastChar) { /* if I'm at the end */
2455 *LastChar = '\0'; /* just in case */
2456 return(CC_LIST_CHOICES);
2459 c_delafter(Argument); /* delete after dot */
2460 if (Cursor > LastChar)
2461 Cursor = LastChar; /* bounds check */
2468 e_delnext_list_eof(c)
2472 if (Cursor == LastChar) { /* if I'm at the end */
2473 if (Cursor == InputBuf) { /* if I'm also at the beginning */
2474 so_write(STReof, 4);/* then do a EOF */
2480 *LastChar = '\0'; /* just in case */
2481 return(CC_LIST_CHOICES);
2485 c_delafter(Argument); /* delete after dot */
2486 if (Cursor > LastChar)
2487 Cursor = LastChar; /* bounds check */
2500 if (Cursor == LastChar && Cursor == InputBuf) {
2501 so_write(STReof, 4); /* then do a EOF */
2507 *LastChar = '\0'; /* just in case */
2508 rv = CC_LIST_CHOICES;
2521 if (Cursor == LastChar)
2525 cp = c_next_word(Cursor, LastChar, Argument);
2527 c_push_kill(Cursor, cp); /* save the text */
2529 c_delafter((int)(cp - Cursor)); /* delete after dot */
2530 if (Cursor > LastChar)
2531 Cursor = LastChar; /* bounds check */
2543 if (ActionFlag & TCSHOP_DELETE) {
2547 RefCursor(); /* move the cursor */
2560 while (Isspace(*Cursor)) /* We want FIRST non space character */
2562 if (ActionFlag & TCSHOP_DELETE) {
2568 RefCursor(); /* move the cursor */
2578 c_push_kill(Cursor, LastChar); /* copy it */
2579 Mark = LastChar = Cursor; /* zap! -- delete to end */
2590 c_push_kill(InputBuf, Cursor); /* copy it */
2591 c_delbefore((int)(Cursor - InputBuf));
2592 if (Mark && Mark > Cursor)
2593 Mark -= Cursor-InputBuf;
2603 c_push_kill(InputBuf, LastChar); /* copy it */
2604 Cursor = Mark = LastChar = InputBuf; /* zap! -- delete all of it */
2617 if (Mark > Cursor) {
2618 c_push_kill(Cursor, Mark); /* copy it */
2619 c_delafter((int)(Mark - Cursor)); /* delete it - UNUSED BY VI mode */
2622 else { /* mark is before cursor */
2623 c_push_kill(Mark, Cursor); /* copy it */
2624 c_delbefore((int)(Cursor - Mark));
2638 if (Mark > Cursor) {
2639 c_push_kill(Cursor, Mark); /* copy it */
2641 else { /* mark is before cursor */
2642 c_push_kill(Mark, Cursor); /* copy it */
2644 return(CC_NORM); /* don't even need to Refresh() */
2656 /* do nothing if we are at beginning of line or have only one char */
2657 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
2661 if (Cursor < LastChar) {
2665 Cursor[-2] = Cursor[-1];
2674 { /* gosmacs style ^T */
2678 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
2680 Cursor[-2] = Cursor[-1];
2696 if (Cursor > InputBuf) {
2697 num = NLSExtend(Cursor, Cursor - InputBuf, -Argument);
2698 if (num > Cursor - InputBuf)
2704 if (ActionFlag & TCSHOP_DELETE) {
2723 if (Cursor == InputBuf)
2727 Cursor = c_preword(Cursor, InputBuf, Argument, STRshwspace); /* bounds check */
2729 if (ActionFlag & TCSHOP_DELETE) {
2744 if (Cursor == InputBuf)
2748 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
2751 if (ActionFlag & TCSHOP_DELETE) {
2767 if (Cursor < LastChar) {
2768 num = NLSExtend(Cursor, LastChar - Cursor, Argument);
2770 if (Cursor > LastChar)
2774 if (ActionFlag & TCSHOP_DELETE) {
2793 if (Cursor == LastChar)
2797 Cursor = c_next_word(Cursor, LastChar, Argument);
2800 if (ActionFlag & TCSHOP_DELETE) {
2815 if (Cursor == LastChar)
2819 Cursor = c_nexword(Cursor, LastChar, Argument);
2822 if (ActionFlag & TCSHOP_DELETE) {
2837 if (Cursor == LastChar)
2841 Cursor = c_next_word(Cursor, LastChar, Argument);
2842 if (Cursor < LastChar)
2846 if (ActionFlag & TCSHOP_DELETE) {
2860 CCRETVAL rv = CC_ERROR;
2862 xprintf("dir %d patlen %d patbuf %S\n",
2866 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
2867 LastChar = InputBuf;
2869 case F_DOWN_SEARCH_HIST:
2870 rv = e_down_search_hist(0);
2872 case F_UP_SEARCH_HIST:
2873 rv = e_up_search_hist(0);
2882 v_csearch_back(ch, count, tflag)
2892 while (cp > InputBuf && *cp != ch)
2896 if (cp < InputBuf || (cp == InputBuf && *cp != ch))
2899 if (*cp == ch && tflag)
2904 if (ActionFlag & TCSHOP_DELETE) {
2915 v_csearch_fwd(ch, count, tflag)
2925 while (cp < LastChar && *cp != ch)
2932 if (*cp == ch && tflag)
2937 if (ActionFlag & TCSHOP_DELETE) {
2953 if (ActionFlag == TCSHOP_DELETE) {
2954 ActionFlag = TCSHOP_NOP;
2959 for (cp = InputBuf; cp < LastChar; cp++) {
2964 UndoAction = TCSHOP_INSERT;
2966 LastChar = InputBuf;
2968 if (c & TCSHOP_INSERT)
2969 c_alternativ_key_map(0);
2974 else if (ActionFlag == TCSHOP_NOP) {
2978 return(CC_ARGHACK); /* Do NOT clear out argument */
2990 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
2992 c_get_word(begin, end)
2999 while (Argument--) {
3000 while ((cp <= LastChar) && (isword(*cp)))
3003 while ((cp >= InputBuf) && (isword(*cp)))
3008 #endif /* COMMENT */
3018 end = c_next_word(Cursor, LastChar, Argument);
3020 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
3025 if (Cursor > LastChar)
3039 end = c_next_word(Cursor, LastChar, Argument);
3042 for (; cp < end; cp++) {
3050 for (; cp < end; cp++)
3055 if (Cursor > LastChar)
3068 end = c_next_word(Cursor, LastChar, Argument);
3070 for (cp = Cursor; cp < end; cp++)
3075 if (Cursor > LastChar)
3110 { /* multiply current argument by 4 */
3112 if (Argument > 1000000)
3129 num = GetNextChar(&ch);
3132 return e_insert(ch);
3134 return e_send_eof(0);
3144 return(CC_ARGHACK); /* preserve argument */
3153 CurrentKeyMap = CcAltMap;
3154 return(CC_ARGHACK); /* preserve argument */
3163 { /* move to beginning of line and start vi
3170 UndoAction = TCSHOP_DELETE;
3172 RefCursor(); /* move the cursor */
3173 c_alternativ_key_map(0);
3181 { /* vi mode overwrite one character */
3183 c_alternativ_key_map(0);
3184 inputmode = MODE_REPLACE_1;
3185 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3195 { /* vi mode start overwriting */
3197 c_alternativ_key_map(0);
3198 inputmode = MODE_REPLACE;
3199 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3209 { /* vi mode substitute for one char */
3211 c_delafter(Argument);
3212 c_alternativ_key_map(0);
3220 { /* vi mode replace whole line */
3222 (void) e_killall(0);
3223 c_alternativ_key_map(0);
3231 { /* vi mode change to end of line */
3233 (void) e_killend(0);
3234 c_alternativ_key_map(0);
3242 { /* vi mode start inserting */
3244 c_alternativ_key_map(0);
3248 UndoAction = TCSHOP_DELETE;
3257 { /* vi mode start adding */
3259 c_alternativ_key_map(0);
3260 if (Cursor < LastChar)
3263 if (Cursor > LastChar)
3270 UndoAction = TCSHOP_DELETE;
3279 { /* vi mode to add at end of line */
3281 c_alternativ_key_map(0);
3284 InsertPos = LastChar; /* Mark where insertion begins */
3286 UndoAction = TCSHOP_DELETE;
3300 if (Cursor < LastChar) {
3301 #ifndef WINNT_NATIVE
3305 #endif /* WINNT_NATIVE */
3307 *Cursor++ = Tolower(c);
3308 else if (Islower(c))
3309 *Cursor++ = Toupper(c);
3312 RefPlusOne(1); /* fast refresh for one char */
3326 for (p = InputBuf; Isspace(*p); p++)
3333 return(e_newline(0));
3340 { /* erase all of current line, start again */
3342 ResetInLine(0); /* reset the input pointers */
3363 ClearScreen(); /* clear the whole real screen */
3364 ClearDisp(); /* reset everything */
3374 #if defined(_MINIX) || defined(WINNT_NATIVE)
3375 /* SAK PATCH: erase all of current line, start again */
3376 ResetInLine(0); /* reset the input pointers */
3379 return (CC_REFRESH);
3380 #else /* !_MINIX && !WINNT_NATIVE */
3383 #endif /* _MINIX || WINNT_NATIVE */
3387 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
3388 * Function to send a character back to the input stream in cooked
3389 * mode. Only works if we have TIOCSTI
3397 int was_raw = Tty_raw_mode;
3398 char buf[MB_LEN_MAX];
3402 (void) Cookedmode();
3404 (void) write(SHIN, "\n", 1);
3405 len = one_wctomb(buf, c & CHAR);
3406 for (i = 0; i < len; i++)
3407 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &buf[i]);
3411 return(e_redisp(c));
3412 #else /* !TIOCSTI */
3414 #endif /* !TIOCSTI */
3423 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
3483 *LastChar = '\0'; /* just in case */
3494 *LastChar = '\0'; /* just in case */
3496 return(e_insert(' '));
3506 return e_inc_search(F_DOWN_SEARCH_HIST);
3517 return e_inc_search(F_UP_SEARCH_HIST);
3525 Char *cp, *oldc, *dp;
3528 if (Cursor == InputBuf)
3533 /* does a bounds check */
3534 cp = c_prev_word(Cursor, InputBuf, Argument);
3536 c_insert((int)(oldc - cp));
3537 for (dp = oldc; cp < oldc && dp < LastChar; cp++)
3540 Cursor = dp; /* put cursor at end */
3564 * Here we pass &c to the ioctl because some os's (NetBSD) expect it
3565 * there even if they don't use it. (lukem@netbsd.org)
3567 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
3569 xprintf(CGETS(5, 1, "Load average unavailable\n"));
3580 * Delete with insert == change: first we delete and then we leave in
3583 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
3592 return(v_action(TCSHOP_DELETE));
3602 if (Cursor == LastChar)
3606 Cursor = c_endword(Cursor, LastChar, Argument, STRshwspace);
3608 if (ActionFlag & TCSHOP_DELETE)
3625 if (Cursor == LastChar)
3629 Cursor = c_eword(Cursor, LastChar, Argument);
3631 if (ActionFlag & TCSHOP_DELETE) {
3649 if (GetNextChar(&ch) != 1)
3650 return e_send_eof(0);
3652 srch_dir = CHAR_FWD;
3655 return v_csearch_fwd(ch, Argument, 0);
3667 if (GetNextChar(&ch) != 1)
3668 return e_send_eof(0);
3670 srch_dir = CHAR_BACK;
3673 return v_csearch_back(ch, Argument, 0);
3684 if (GetNextChar(&ch) != 1)
3685 return e_send_eof(0);
3687 return v_csearch_fwd(ch, Argument, 1);
3699 if (GetNextChar(&ch) != 1)
3700 return e_send_eof(0);
3702 return v_csearch_back(ch, Argument, 1);
3714 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
3715 v_csearch_back(srch_char, Argument, 0);
3727 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
3728 v_csearch_back(srch_char, Argument, 0);
3742 switch (UndoAction) {
3743 case TCSHOP_DELETE|TCSHOP_INSERT:
3745 if (UndoSize == 0) return(CC_NORM);
3748 for (loop=0; loop < UndoSize; loop++) /* copy the chars */
3749 *kp++ = *cp++; /* into UndoBuf */
3751 for (cp = UndoPtr; cp <= LastChar; cp++)
3754 LastChar -= UndoSize;
3757 UndoAction = TCSHOP_INSERT;
3761 if (UndoSize == 0) return(CC_NORM);
3765 c_insert(UndoSize); /* open the space, */
3766 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
3769 UndoAction = TCSHOP_DELETE;
3773 if (UndoSize == 0) return(CC_NORM);
3777 size = (int)(Cursor-LastChar); /* NOT NSL independant */
3778 if (size < UndoSize)
3780 for(loop = 0; loop < size; loop++) {
3800 return v_search(F_UP_SEARCH_HIST);
3809 return v_search(F_DOWN_SEARCH_HIST);
3818 if (patlen == 0) return(CC_ERROR);
3819 return(v_repeat_srch(searchdir));
3828 if (patlen == 0) return(CC_ERROR);
3829 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
3830 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
3833 #ifndef WINNT_NATIVE
3834 /* Since ed.defns.h is generated from ed.defns.c, these empty
3835 functions will keep the F_NUM_FNS consistent
3838 e_copy_to_clipboard(c)
3846 e_paste_from_clipboard(c)
3881 #endif /* !WINNT_NATIVE */
3885 MoveCursor(n) /* move cursor + right - left char */
3888 Cursor = Cursor + n;
3889 if (Cursor < InputBuf)
3891 if (Cursor > LastChar)
3906 if (p < InputBuf || p > LastChar)
3907 return 1; /* Error */