1 /* $Header: /src/pub/tcsh/ed.chared.c,v 3.63 2000/11/11 23:03:33 christos 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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
40 e_dabbrev_expand() did not do proper completion if quoted spaces were present
41 in the string being completed. Exemple:
45 # echo h<press key bound to dabbrev-expande>
49 # echo h<press key bound to dabbrev-expande>
50 # echo hello\ world<cursor>
52 The same problem occured if spaces were present in a string withing quotation
57 # echo "h<press key bound to dabbrev-expande>
60 The former problem could be solved with minor modifications of c_preword()
61 and c_endword(). The latter, however, required a significant rewrite of
62 c_preword(), since quoted strings must be parsed from start to end to
63 determine if a given character is inside or outside the quotation marks.
65 Compare the following two strings:
67 # echo \"" 'foo \' bar\"
69 # echo '\"" 'foo \' bar\"
72 The only difference between the two echo lines is in the first character
73 after the echo command. The result is either one or three arguments.
79 RCSID("$Id: ed.chared.c,v 3.63 2000/11/11 23:03:33 christos Exp $")
87 #define TCSHOP_NOP 0x00
88 #define TCSHOP_DELETE 0x01
89 #define TCSHOP_INSERT 0x02
90 #define TCSHOP_CHANGE 0x04
97 * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
99 #define C_CLASS_WHITE 1
100 #define C_CLASS_ALNUM 2
101 #define C_CLASS_OTHER 3
103 static Char *InsertPos = InputBuf; /* Where insertion starts */
104 static Char *ActionPos = 0; /* Where action begins */
105 static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */
109 static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
110 static Char patbuf[INBUFSIZE]; /* Search target */
111 static int patlen = 0;
115 static int srch_dir = CHAR_FWD; /* Direction of last search */
116 static Char srch_char = 0; /* Search target */
118 /* all routines that start with c_ are private to this set of routines */
119 static void c_alternativ_key_map __P((int));
120 static void c_insert __P((int));
121 void c_delafter __P((int));
122 void c_delbefore __P((int));
123 static int c_to_class __P((int));
124 static Char *c_prev_word __P((Char *, Char *, int));
125 static Char *c_next_word __P((Char *, Char *, int));
126 static Char *c_number __P((Char *, int *, int));
127 static Char *c_expand __P((Char *));
128 static void c_excl __P((Char *));
129 static void c_substitute __P((void));
130 static void c_delfini __P((void));
131 static int c_hmatch __P((Char *));
132 static void c_hsetpat __P((void));
134 static void c_get_word __P((Char **, Char **));
136 static Char *c_preword __P((Char *, Char *, int));
137 static Char *c_nexword __P((Char *, Char *, int));
138 static Char *c_endword __P((Char *, Char *, int));
139 static Char *c_eword __P((Char *, Char *, int));
140 static CCRETVAL c_get_histline __P((void));
141 static CCRETVAL c_search_line __P((Char *, int));
142 static CCRETVAL v_repeat_srch __P((int));
143 static CCRETVAL e_inc_search __P((int));
144 static CCRETVAL v_search __P((int));
145 static CCRETVAL v_csearch_fwd __P((int, int, int));
146 static CCRETVAL v_action __P((int));
147 static CCRETVAL v_csearch_back __P((int, int, int));
149 #if defined(DSPMBYTE)
150 static void e_charfwd_mbyte __P((int));
151 static void e_charback_mbyte __P((int));
153 static int extins = 0;
157 c_alternativ_key_map(state)
162 CurrentKeyMap = CcKeyMap;
165 CurrentKeyMap = CcAltMap;
171 AltKeyMap = (Char) state;
180 if (LastChar + num >= InputLim)
181 return; /* can't go past end of buffer */
183 if (Cursor < LastChar) { /* if I must move chars */
184 for (cp = LastChar; cp >= Cursor; cp--)
194 register Char *cp, *kp = NULL;
196 #if defined(DSPMBYTE)
202 if (num > LastChar - Cursor)
203 num = (int) (LastChar - Cursor); /* bounds check */
205 if (num > 0) { /* if I can delete anything */
206 #if defined(DSPMBYTE)
207 /* check for code of deleted character */
208 if (_enable_mbdisp) {
209 for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) {
211 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
213 extdel = 0; /* if 2nd. byte, force set to 0 */
218 kp = UndoBuf; /* Set Up for VI undo command */
219 UndoAction = TCSHOP_INSERT;
222 for (cp = Cursor; cp <= LastChar; cp++) {
223 *kp++ = *cp; /* Save deleted chars into undobuf */
228 for (cp = Cursor; cp <= LastChar; cp++)
231 #if defined(DSPMBYTE)
232 if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) {
235 *kp++ = *Cursor; /* Save deleted chars into undobuf */
237 for (cp = Cursor; cp <= LastChar; cp++)
249 * XXX: We don't want to do that. In emacs mode overwrite should be
250 * sticky. I am not sure how that affects vi mode
252 inputmode = MODE_INSERT;
258 c_delbefore(num) /* delete before dot, with bounds checking */
261 register Char *cp, *kp = NULL;
263 #if defined(DSPMBYTE)
270 if (num > Cursor - InputBuf)
271 num = (int) (Cursor - InputBuf); /* bounds check */
273 if (num > 0) { /* if I can delete anything */
274 #if defined(DSPMBYTE)
275 nowcur = Cursor - num;
279 kp = UndoBuf; /* Set Up for VI undo command */
280 UndoAction = TCSHOP_INSERT;
282 UndoPtr = Cursor - num;
283 for (cp = Cursor - num; cp <= LastChar; cp++) {
289 for (cp = Cursor - num; cp <= LastChar; cp++)
292 #if defined(DSPMBYTE)
293 if (_enable_mbdisp) {
294 for (wkcp = InputBuf; wkcp < nowcur; wkcp++) {
296 extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
298 extdel = 0; /* if 2nd. byte, force set to 0 */
300 if (extdel && Ismbyte2(delc)) {
305 /* Save deleted chars into undobuf */
307 for (cp = nowcur - 1; cp <= LastChar; cp++)
320 register Char *p, *low;
324 register Char *prev = low;
327 while (prev < p) { /* Skip initial spaces */
328 if (!Isspace(*prev) || (Isspace(*prev) && *(prev-1) == (Char)'\\'))
337 new = c_endword(prev-1, p, 1); /* Skip to next space */
338 new++; /* Step away from end of word */
339 while (new <= p) { /* Skip trailing spaces */
340 if (!Isspace(*new) || (Isspace(*new) && *(new-1) == (Char)'\\'))
346 p = prev; /* Set to previous word start */
355 * c_to_class() returns the class of the given character.
357 * This is used to make the c_prev_word() and c_next_word() functions
358 * work like vi's, which classify characters. A word is a sequence of
359 * characters belonging to the same class, classes being defined as
363 * 2/ alphanumeric chars, + underscore
371 return C_CLASS_WHITE;
373 if (Isdigit(ch) || Isalpha(ch) || ch == '_')
374 return C_CLASS_ALNUM;
376 return C_CLASS_OTHER;
380 c_prev_word(p, low, n)
381 register Char *p, *low;
388 while ((p >= low) && !isword(*p))
390 while ((p >= low) && isword(*p))
394 /* cp now points to one character before the word */
398 /* cp now points where we want it */
403 register int c_class;
408 /* scan until beginning of current word (may be all whitespace!) */
409 c_class = c_to_class(*p);
410 while ((p >= low) && c_class == c_to_class(*p))
413 /* if this was a non_whitespace word, we're ready */
414 if (c_class != C_CLASS_WHITE)
417 /* otherwise, move back to beginning of the word just found */
418 c_class = c_to_class(*p);
419 while ((p >= low) && c_class == c_to_class(*p))
423 p++; /* correct overshoot */
429 c_next_word(p, high, n)
430 register Char *p, *high;
435 while ((p < high) && !isword(*p))
437 while ((p < high) && isword(*p))
442 /* p now points where we want it */
447 register int c_class;
452 /* scan until end of current word (may be all whitespace!) */
453 c_class = c_to_class(*p);
454 while ((p < high) && c_class == c_to_class(*p))
457 /* if this was all whitespace, we're ready */
458 if (c_class == C_CLASS_WHITE)
461 /* if we've found white-space at the end of the word, skip it */
462 while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
466 p--; /* correct overshoot */
472 c_nexword(p, high, n)
473 register Char *p, *high;
477 while ((p < high) && !Isspace(*p))
479 while ((p < high) && Isspace(*p))
485 /* p now points where we want it */
490 * Expand-History (originally "Magic-Space") code added by
491 * Ray Moody <ray@gibbs.physics.purdue.edu>
492 * this is a neat, but odd, addition.
496 * c_number: Ignore character p points to, return number appearing after that.
497 * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
498 * Return p pointing to last char used.
502 * dval is the number to subtract from for things like $-3
506 c_number(p, num, dval)
512 register int sign = 1;
520 *num = NCARGS; /* Handle $ */
523 sign = -1; /* Handle $- */
526 for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
528 *num = (sign < 0 ? dval - i : i);
533 * excl_expand: There is an excl to be expanded to p -- do the right thing
534 * with it and return a version of p advanced over the expanded stuff. Also,
535 * update tsh_cur and related things as appropriate...
543 register struct Hist *h = Histlist.Hnext;
544 register struct wordent *l;
545 int i, from, to, dval;
551 Char *modbuf, *omodbuf;
556 switch (*(q = p + 1)) {
559 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
563 if ((l = (h->Hlex).prev) != 0)
564 bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
568 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
572 if (been_once) { /* unknown argument */
573 /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
574 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
580 if (*q == ':') /* short form: !:arg */
585 * Search for a space, tab, or colon. See if we have a number (as
586 * in !1234:xyz). Remember the number.
588 for (i = 0, all_dig = 1;
589 *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
591 * PWP: !-4 is a valid history argument too, therefore the test
592 * is if not a digit, or not a - as the first character.
594 if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
597 all_dig = 2;/* we are sneeky about this */
599 i = 10 * i + *q - '0';
604 * If we have a number, search for event i. Otherwise, search for
605 * a named event (as in !foo). (In this case, I is the length of
610 i = -i; /* make it negitive */
611 if (i < 0) /* if !-4 (for example) */
612 i = eventno + 1 + i; /* remember: i is < 0 */
613 for (; h; h = h->Hnext) {
619 for (i = (int) (q - p); h; h = h->Hnext) {
620 if ((l = &h->Hlex) != 0) {
621 if (!Strncmp(p + 1, l->next->word, (size_t) i))
629 if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
630 q[1] == '$' || q[1] == '^') { /* get some args */
631 p = q[1] == ':' ? ++q : q;
635 if ((q[1] < '0' || q[1] > '9') &&
636 q[1] != '-' && q[1] != '$' && q[1] != '^')
641 if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
644 * Count up the number of words in this event. Store it in dval.
645 * Dval will be fed to number.
648 if ((l = h->Hlex.prev) != 0) {
649 for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
657 q = c_number(q, &from, dval);
660 if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
663 q = c_number(q, &to, dval);
665 else if (q[1] == '*') {
672 if (from < 0 || to < from)
674 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
676 else { /* get whole cmd */
677 bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
683 * Apply modifiers, if any.
687 modbuf = omodbuf = buf;
688 while (q[1] == ':' && modbuf != NULL) {
698 if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
700 xfree((ptr_t) omodbuf);
708 /* Not implemented; this needs to be done before expanding
709 * lex. We don't have the words available to us anymore.
729 if (omodbuf != buf) {
730 (void) Strcpy(buf, omodbuf);
731 xfree((ptr_t) omodbuf);
737 * Now replace the text from op to q inclusive with the text from buf to
743 * Now replace text non-inclusively like a real CS major!
745 if (LastChar + (bend - buf) - (q - op) >= InputLim)
747 (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
748 (size_t) ((LastChar - q) * sizeof(Char)));
749 LastChar += (bend - buf) - (q - op);
750 Cursor += (bend - buf) - (q - op);
751 (void) memmove((ptr_t) op, (ptr_t) buf,
752 (size_t) ((bend - buf) * sizeof(Char)));
754 return(op + (bend - buf));
761 * c_excl: An excl has been found at point p -- back up and find some white
762 * space (or the beginning of the buffer) and properly expand all the excl's
763 * from there up to the current cursor position. We also avoid (trying to)
775 * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
776 * back p up to just before the current word.
778 if ((p[1] == ' ' || p[1] == '\t') &&
779 (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
780 for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
786 while (*p != ' ' && *p != '\t' && p > InputBuf)
791 * Forever: Look for history char. (Stop looking when we find the cursor.)
792 * Count backslashes. Of odd, skip history char. Return if all done.
793 * Expand if even number of backslashes.
796 while (*p != HIST && p < Cursor)
798 for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
816 * Start p out one character before the cursor. Move it backwards looking
817 * for white space, the beginning of the line, or a history character.
820 p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
824 * If we found a history character, go expand it.
832 c_delfini() /* Finish up delete action */
836 if (ActionFlag & TCSHOP_INSERT)
837 c_alternativ_key_map(0);
839 ActionFlag = TCSHOP_NOP;
844 UndoAction = TCSHOP_INSERT;
846 if (Cursor > ActionPos) {
847 Size = (int) (Cursor-ActionPos);
850 #if defined(DSPMBYTE)
851 if (_enable_mbdisp && extdel) {
858 else if (Cursor < ActionPos) {
859 Size = (int)(ActionPos-Cursor);
871 c_endword(p, high, n)
872 register Char *p, *high;
875 register int inquote = 0;
879 while (p < high) { /* Skip spaces */
880 if (!Isspace(*p) || (Isspace(*p) && *(p-1) == (Char)'\\'))
884 while (p < high) { /* Skip string */
885 if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
886 if ((!inquote && *(p-1) != (Char)'\\') || inquote) { /* Should it be honored? */
887 if (inquote == 0) inquote = *p;
888 else if (inquote == *p) inquote = 0;
891 if (!inquote && (Isspace(*p) && *(p-1) != (Char)'\\')) /* Break if unquoted space */
904 register Char *p, *high;
910 while ((p < high) && Isspace(*p))
914 while ((p < high) && Isalnum(*p))
917 while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
931 if (Hist_num == 0) { /* if really the current line */
932 copyn(InputBuf, HistBuf, INBUFSIZE);
933 LastChar = InputBuf + (LastHist - HistBuf);
949 for (h = 1; h < Hist_num; h++) {
950 if ((hp->Hnext) == NULL) {
957 if (HistLit && hp->histline) {
958 copyn(InputBuf, hp->histline, INBUFSIZE);
962 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
965 LastChar = InputBuf + Strlen(InputBuf);
967 if (LastChar > InputBuf) {
968 if (LastChar[-1] == '\n')
971 if (LastChar[-1] == ' ')
974 if (LastChar < InputBuf)
989 c_search_line(pattern, dir)
996 len = (int) Strlen(pattern);
998 if (dir == F_UP_SEARCH_HIST) {
999 for (cp = Cursor; cp >= InputBuf; cp--)
1000 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1001 Gmatch(cp, pattern)) {
1007 for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
1008 if (Strncmp(cp, pattern, (size_t) len) == 0 ||
1009 Gmatch(cp, pattern)) {
1021 static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
1022 STRbck[] = { 'b', 'c', 'k', '\0' };
1023 static Char pchar = ':'; /* ':' = normal, '?' = failed */
1024 static Char endcmd[2];
1026 *oldCursor = Cursor,
1028 CCRETVAL ret = CC_NORM;
1029 int oldHist_num = Hist_num,
1034 if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
1039 if (patlen == 0) { /* first round */
1041 patbuf[patlen++] = '*';
1045 for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
1046 *cp; *LastChar++ = *cp++)
1048 *LastChar++ = pchar;
1049 for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
1054 if (GetNextChar(&ch) != 1)
1055 return(e_send_eof(0));
1057 switch (CurrentKeyMap[(unsigned char) ch]) {
1061 if (patlen > INBUFSIZE - 3)
1064 patbuf[patlen++] = ch;
1072 newdir = F_DOWN_SEARCH_HIST;
1077 newdir = F_UP_SEARCH_HIST;
1090 case 0007: /* ^G: Abort */
1095 case 0027: /* ^W: Append word */
1096 /* No can do if globbing characters in pattern */
1097 for (cp = &patbuf[1]; ; cp++)
1098 if (cp >= &patbuf[patlen]) {
1099 Cursor += patlen - 1;
1100 cp = c_next_word(Cursor, LastChar, 1);
1101 while (Cursor < cp && *Cursor != '\n') {
1102 if (patlen > INBUFSIZE - 3) {
1106 patbuf[patlen++] = *Cursor;
1107 *LastChar++ = *Cursor++;
1113 } else if (isglob(*cp)) {
1119 default: /* Terminate and execute cmd */
1124 case 0033: /* ESC: Terminate */
1132 while (LastChar > InputBuf && *LastChar != '\n')
1138 /* Can't search if unmatched '[' */
1139 for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
1140 if (*cp == '[' || *cp == ']') {
1145 if (patlen > 1 && ch != '[') {
1146 if (redo && newdir == dir) {
1147 if (pchar == '?') { /* wrap around */
1148 Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
1149 if (c_get_histline() == CC_ERROR)
1150 /* Hist_num was fixed by first call */
1151 (void) c_get_histline();
1152 Cursor = newdir == F_UP_SEARCH_HIST ?
1153 LastChar : InputBuf;
1155 Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
1157 patbuf[patlen++] = '*';
1158 patbuf[patlen] = '\0';
1159 if (Cursor < InputBuf || Cursor > LastChar ||
1160 (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
1161 LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
1162 ret = newdir == F_UP_SEARCH_HIST ?
1163 e_up_search_hist(0) : e_down_search_hist(0);
1164 if (ret != CC_ERROR) {
1165 Cursor = newdir == F_UP_SEARCH_HIST ?
1166 LastChar : InputBuf;
1167 (void) c_search_line(&patbuf[1], newdir);
1170 patbuf[--patlen] = '\0';
1171 if (ret == CC_ERROR) {
1173 if (Hist_num != oldHist_num) {
1174 Hist_num = oldHist_num;
1175 if (c_get_histline() == CC_ERROR)
1185 ret = e_inc_search(newdir);
1187 if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
1188 /* break abort of failed search at last non-failed */
1194 if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
1195 /* restore on normal return or error exit */
1198 if (Hist_num != oldHist_num) {
1199 Hist_num = oldHist_num;
1200 if (c_get_histline() == CC_ERROR)
1204 if (ret == CC_ERROR)
1207 if (done || ret != CC_NORM)
1219 Char tmpbuf[INBUFSIZE];
1220 Char oldbuf[INBUFSIZE];
1224 copyn(oldbuf, InputBuf, INBUFSIZE);
1228 tmpbuf[tmplen++] = '*';
1231 LastChar = InputBuf;
1235 c_insert(2); /* prompt + '\n' */
1237 *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
1239 for (ch = 0;ch == 0;) {
1240 if (GetNextChar(&ch) != 1)
1241 return(e_send_eof(0));
1243 case 0010: /* Delete and backspace */
1248 tmpbuf[tmplen--] = '\0';
1251 copyn(InputBuf, oldbuf, INBUFSIZE);
1260 case 0033: /* ESC */
1262 case '\r': /* Newline */
1265 case '\012': /* ASCII Line feed */
1266 case '\015': /* ASCII (or EBCDIC) Return */
1271 if (tmplen >= INBUFSIZE)
1274 tmpbuf[tmplen++] = ch;
1286 * Use the old pattern, but wild-card it.
1290 LastChar = InputBuf;
1295 if (patbuf[0] != '*') {
1296 (void) Strcpy(tmpbuf, patbuf);
1298 (void) Strcpy(&patbuf[1], tmpbuf);
1300 patbuf[patlen++] = '*';
1301 patbuf[patlen] = '\0';
1305 tmpbuf[tmplen++] = '*';
1306 tmpbuf[tmplen] = '\0';
1307 (void) Strcpy(patbuf, tmpbuf);
1310 LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
1311 Cursor = LastChar = InputBuf;
1312 if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
1313 e_down_search_hist(0)) == CC_ERROR) {
1331 * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
1332 * entry point, called from the CcKeyMap indirected into the
1343 ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
1346 if (UndoPtr > Cursor)
1347 UndoSize = (int)(UndoPtr - Cursor);
1349 UndoSize = (int)(Cursor - UndoPtr);
1351 inputmode = MODE_INSERT;
1352 c_alternativ_key_map(1);
1355 * We don't want to move the cursor, because all the editing
1356 * commands don't include the character under the cursor.
1358 if (Cursor > InputBuf)
1369 { /* bound to keys that arn't really assigned */
1381 #if defined(DSPMBYTE)
1384 static int exterr = 0;
1386 #ifndef SHORT_STRINGS
1387 c &= ASCII; /* no meta chars ever */
1389 #if defined(DSPMBYTE)
1390 ret = (CCRETVAL) CC_NORM;
1394 return(CC_ERROR); /* no NULs in the input ever!! */
1396 if (LastChar + Argument >= InputLim)
1397 return(CC_ERROR); /* end of buffer space */
1399 if (Argument == 1) { /* How was this optimized ???? */
1401 #if defined(DSPMBYTE)
1402 if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) {
1408 if (inputmode != MODE_INSERT) {
1409 UndoBuf[UndoSize++] = *Cursor;
1410 UndoBuf[UndoSize] = '\0';
1411 c_delafter(1); /* Do NOT use the saving ONE */
1416 #if defined(DSPMBYTE)
1417 /* 1st. byte is store to special buffer, and replace space */
1418 if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1421 *Cursor++ = (Char) ' ';
1423 else if (_enable_mbdisp && extins && Ismbyte2(c)) {
1424 *(Cursor-1) = savec;
1425 *Cursor++ = (Char) c;
1432 *Cursor++ = (Char) c;
1433 DoingArg = 0; /* just in case */
1434 if (ret != CC_REFRESH)
1435 RefPlusOne(); /* fast refresh for one char. */
1437 *Cursor++ = (Char) c;
1438 DoingArg = 0; /* just in case */
1439 RefPlusOne(); /* fast refresh for one char. */
1443 #if defined(DSPMBYTE)
1444 /* Cannot use ESC-(number) for multi-byte */
1445 if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
1450 else if (_enable_mbdisp && extins && exterr && Ismbyte2(c))
1457 if (inputmode != MODE_INSERT) {
1459 for(i=0;i<Argument;i++)
1460 UndoBuf[UndoSize++] = *(Cursor+i);
1462 UndoBuf[UndoSize] = '\0';
1463 c_delafter(Argument); /* Do NOT use the saving ONE */
1469 *Cursor++ = (Char) c;
1473 if (inputmode == MODE_REPLACE_1)
1474 (void) v_cmd_mode(0);
1476 #if defined(DSPMBYTE)
1484 InsertStr(s) /* insert ASCIZ s at cursor (for complete) */
1489 if ((len = (int) Strlen(s)) <= 0)
1491 if (LastChar + len >= InputLim)
1492 return -1; /* end of buffer space */
1501 DeleteBack(n) /* delete the n characters before . */
1506 if (Cursor >= &InputBuf[n]) {
1507 c_delbefore(n); /* delete before dot */
1508 if (n > Cursor - InputBuf)
1509 Cursor = InputBuf; /* bounds check */
1512 #if defined(DSPMBYTE)
1513 if(_enable_mbdisp && extdel && Cursor > InputBuf) {
1522 e_digit(c) /* gray magic here */
1526 return(CC_ERROR); /* no NULs in the input ever!! */
1528 if (DoingArg) { /* if doing an arg, add this in... */
1529 if (LastCmd == F_ARGFOUR) /* if last command was ^U */
1532 if (Argument > 1000000)
1534 Argument = (Argument * 10) + (c - '0');
1539 if (LastChar + 1 >= InputLim)
1540 return CC_ERROR; /* end of buffer space */
1542 if (inputmode != MODE_INSERT) {
1543 UndoBuf[UndoSize++] = *Cursor;
1544 UndoBuf[UndoSize] = '\0';
1545 c_delafter(1); /* Do NOT use the saving ONE */
1548 *Cursor++ = (Char) c;
1549 DoingArg = 0; /* just in case */
1550 RefPlusOne(); /* fast refresh for one char. */
1556 e_argdigit(c) /* for ESC-n */
1562 return(CC_ERROR); /* no NULs in the input ever!! */
1564 if (DoingArg) { /* if doing an arg, add this in... */
1565 if (Argument > 1000000)
1567 Argument = (Argument * 10) + (c - '0');
1569 else { /* else starting an argument */
1577 v_zero(c) /* command mode 0 for vi */
1580 if (DoingArg) { /* if doing an arg, add this in... */
1581 if (Argument > 1000000)
1583 Argument = (Argument * 10) + (c - '0');
1586 else { /* else starting an argument */
1588 if (ActionFlag & TCSHOP_DELETE) {
1592 RefCursor(); /* move the cursor */
1601 { /* always ignore argument */
1603 /* PastBottom(); NOW done in ed.inputl.c */
1604 *LastChar++ = '\n'; /* for the benefit of CSH */
1605 *LastChar = '\0'; /* just in case */
1607 InsertPos = InputBuf; /* Reset editing position */
1615 { /* for when ^D is ONLY send-eof */
1618 *LastChar = '\0'; /* just in case */
1628 *LastChar = '\0'; /* just in case */
1629 return(CC_COMPLETE);
1638 *LastChar = '\0'; /* just in case */
1639 return(CC_COMPLETE_BACK);
1648 *LastChar = '\0'; /* just in case */
1649 return(CC_COMPLETE_FWD);
1658 *LastChar = '\0'; /* just in case */
1659 return(CC_COMPLETE_ALL);
1668 if (Cursor < LastChar)
1670 *LastChar = '\0'; /* just in case */
1671 return(CC_COMPLETE);
1683 *LastChar = '\0'; /* just in case */
1685 if (Hist_num <= 0) {
1689 hp = Histlist.Hnext;
1690 if (hp == NULL) { /* this is only if no history */
1694 for (h = 1; h < Hist_num; h++)
1697 if (!CurrentHistLit) {
1699 copyn(InputBuf, hp->histline, INBUFSIZE);
1707 (void) sprlex(InputBuf, sizeof(InputBuf) / sizeof(Char), &hp->Hlex);
1711 LastChar = InputBuf + Strlen(InputBuf);
1712 if (LastChar > InputBuf) {
1713 if (LastChar[-1] == '\n')
1715 if (LastChar[-1] == ' ')
1717 if (LastChar < InputBuf)
1718 LastChar = InputBuf;
1739 UndoAction = TCSHOP_NOP;
1740 *LastChar = '\0'; /* just in case */
1742 if (Hist_num == 0) { /* save the current buffer away */
1743 copyn(HistBuf, InputBuf, INBUFSIZE);
1744 LastHist = HistBuf + (LastChar - InputBuf);
1747 Hist_num += Argument;
1749 if (c_get_histline() == CC_ERROR) {
1751 (void) c_get_histline(); /* Hist_num was fixed by first call */
1758 return(CC_NORM); /* was CC_UP_HIST */
1767 UndoAction = TCSHOP_NOP;
1768 *LastChar = '\0'; /* just in case */
1770 Hist_num -= Argument;
1774 return(CC_ERROR); /* make it beep */
1777 return(c_get_histline());
1783 * c_hmatch() return True if the pattern matches the prefix
1789 if (Strncmp(patbuf, str, (size_t) patlen) == 0)
1791 return Gmatch(str, patbuf);
1795 * c_hsetpat(): Set the history seatch pattern
1800 if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
1801 patlen = (int) (Cursor - InputBuf);
1802 if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
1804 (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
1805 patbuf[patlen] = '\0';
1808 patlen = (int) Strlen(patbuf);
1811 xprintf("\nHist_num = %d\n", Hist_num);
1812 xprintf("patlen = %d\n", patlen);
1813 xprintf("patbuf = \"%S\"\n", patbuf);
1814 xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
1828 ActionFlag = TCSHOP_NOP;
1829 UndoAction = TCSHOP_NOP;
1830 *LastChar = '\0'; /* just in case */
1833 xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
1841 copyn(HistBuf, InputBuf, INBUFSIZE);
1842 LastHist = HistBuf + (LastChar - InputBuf);
1846 hp = Histlist.Hnext;
1850 c_hsetpat(); /* Set search pattern !! */
1852 for (h = 1; h <= Hist_num; h++)
1855 while (hp != NULL) {
1856 Char sbuf[INBUFSIZE], *hl;
1857 if (hp->histline == NULL) {
1858 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1861 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1864 xprintf("Comparing with \"%S\"\n", hl);
1866 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1867 hl[LastChar-InputBuf]) && c_hmatch(hl)) {
1877 xprintf("not found\n");
1884 return(c_get_histline());
1889 e_down_search_hist(c)
1897 ActionFlag = TCSHOP_NOP;
1898 UndoAction = TCSHOP_NOP;
1899 *LastChar = '\0'; /* just in case */
1904 hp = Histlist.Hnext;
1908 c_hsetpat(); /* Set search pattern !! */
1910 for (h = 1; h < Hist_num && hp; h++) {
1911 Char sbuf[INBUFSIZE], *hl;
1912 if (hp->histline == NULL) {
1913 hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1916 hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf) / sizeof(Char),
1919 xprintf("Comparing with \"%S\"\n", hl);
1921 if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
1922 hl[LastChar-InputBuf]) && c_hmatch(hl))
1927 if (!found) { /* is it the current history number? */
1928 if (!c_hmatch(HistBuf)) {
1930 xprintf("not found\n");
1938 return(c_get_histline());
1948 *LastChar = '\0'; /* just in case */
1958 *LastChar = '\0'; /* just in case */
1968 *LastChar = '\0'; /* just in case */
1969 return(CC_CORRECT_L);
1977 register struct process *pp;
1978 extern bool tellwhat;
1981 if ((pp = find_stop_ed()) != NULL) {
1982 /* save our editor state so we can restore it */
1984 copyn(WhichBuf, InputBuf, INBUFSIZE);
1985 LastWhich = WhichBuf + (LastChar - InputBuf);
1986 CursWhich = WhichBuf + (Cursor - InputBuf);
1987 HistWhich = Hist_num;
1988 Hist_num = 0; /* for the history commands */
1990 /* put the tty in a sane mode */
1992 (void) Cookedmode(); /* make sure the tty is set up correctly */
1997 (void) Rawmode(); /* go on */
2011 *LastChar = '\0'; /* just in case */
2012 return(CC_LIST_CHOICES);
2022 *LastChar = '\0'; /* just in case */
2023 return(CC_LIST_ALL);
2033 *LastChar = '\0'; /* just in case */
2034 return(CC_LIST_GLOB);
2043 *LastChar = '\0'; /* just in case */
2044 return(CC_EXPAND_GLOB);
2053 *LastChar = '\0'; /* just in case */
2054 return(CC_NORMALIZE_PATH);
2059 e_normalize_command(c)
2063 *LastChar = '\0'; /* just in case */
2064 return(CC_NORMALIZE_COMMAND);
2073 *LastChar = '\0'; /* just in case */
2074 return(CC_EXPAND_VARS);
2081 { /* do a fast command line which(1) */
2084 *LastChar = '\0'; /* just in case */
2092 { /* insert the last element of the prev. cmd */
2094 register struct Hist *hp;
2095 register struct wordent *wp, *firstp;
2097 Char buf[INBUFSIZE];
2103 hp = Histlist.Hnext;
2104 if (hp == NULL) { /* this is only if no history */
2108 wp = (hp->Hlex).prev;
2110 if (wp->prev == (struct wordent *) NULL)
2111 return(CC_ERROR); /* an empty history entry */
2113 firstp = (hp->Hlex).next;
2115 /* back up arg words in lex */
2116 for (i = 0; i < Argument && wp != firstp; i++) {
2120 cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
2132 { /* expand to preceding word matching prefix */
2133 register Char *cp, *ncp, *bp;
2134 register struct Hist *hp;
2135 register int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
2136 register bool found = 0;
2137 Char hbuf[INBUFSIZE];
2138 static int oldevent, hist, word;
2139 static Char *start, *oldcursor;
2145 cp = c_preword(Cursor, InputBuf, 1);
2146 if (cp == Cursor || Isspace(*cp))
2149 hp = Histlist.Hnext;
2151 if (Argument == 1 && eventno == oldevent && cp == start &&
2152 Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
2153 /* continue previous search - go to last match (hist/word) */
2154 if (hist != 0) { /* need to move up history */
2155 for (i = 1; i < hist && hp != NULL; i++)
2157 if (hp == NULL) /* "can't happen" */
2159 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2164 cp = c_preword(cp, bp, word);
2165 } else { /* starting new search */
2168 patlen = (int) (Cursor - cp);
2169 (void) Strncpy(patbuf, cp, patlen);
2175 ncp = c_preword(cp, bp, 1);
2176 if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
2181 cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
2188 len = (int) (c_endword(ncp-1, cp, 1) - ncp + 1);
2191 if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
2192 /* We don't fully check distinct matches as Gnuemacs does: */
2193 if (Argument > 1) { /* just count matches */
2194 if (++arg >= Argument)
2196 } else { /* match if distinct from previous */
2197 if (len != Cursor - start || Strncmp(cp, start, len) != 0)
2203 if (LastChar + len - (Cursor - start) >= InputLim)
2204 return(CC_ERROR); /* no room */
2205 DeleteBack(Cursor - start);
2217 { /* almost like GnuEmacs */
2218 register Char *kp, *cp;
2221 if (LastKill == KillBuf) /* if zero content */
2224 if (LastChar + (LastKill - KillBuf) >= InputLim)
2225 return(CC_ERROR); /* end of buffer space */
2228 Mark = Cursor; /* set the mark */
2229 cp = Cursor; /* for speed */
2231 c_insert((int)(LastKill - KillBuf)); /* open the space, */
2232 for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */
2235 if (Argument == 1) /* if an arg, cursor at beginning */
2236 Cursor = cp; /* else cursor at end */
2243 v_delprev(c) /* Backspace key in insert mode */
2251 if (InsertPos != 0) {
2252 if (Argument <= Cursor - InsertPos) {
2253 c_delbefore(Argument); /* delete before */
2255 #if defined(DSPMBYTE)
2256 if (_enable_mbdisp && extdel) {
2273 if (Cursor > InputBuf) {
2274 c_delbefore(Argument); /* delete before dot */
2275 if (Argument > Cursor - InputBuf)
2276 Cursor = InputBuf; /* bounds check */
2279 #if defined(DSPMBYTE)
2280 if (_enable_mbdisp && extdel && Cursor > InputBuf) {
2297 register Char *cp, *p, *kp;
2300 if (Cursor == InputBuf)
2304 cp = c_prev_word(Cursor, InputBuf, Argument);
2306 for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */
2310 c_delbefore((int)(Cursor - cp)); /* delete before dot */
2312 if (Cursor < InputBuf)
2313 Cursor = InputBuf; /* bounds check */
2317 /* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
2319 * Changed the names of some of the ^D family of editor functions to
2320 * correspond to what they actually do and created new e_delnext_list
2323 * Old names: New names:
2325 * delete-char delete-char-or-eof
2326 * F_DELNEXT F_DELNEXT_EOF
2327 * e_delnext e_delnext_eof
2328 * edelnxt edelnxteof
2329 * delete-char-or-eof delete-char
2330 * F_DELNEXT_EOF F_DELNEXT
2331 * e_delnext_eof e_delnext
2332 * edelnxteof edelnxt
2333 * delete-char-or-list delete-char-or-list-or-eof
2334 * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
2335 * e_list_delnext e_delnext_list_eof
2337 * (no old equivalent) delete-char-or-list
2343 /* added by mtk@ari.ncl.omron.co.jp (920818) */
2344 /* rename e_delnext() -> e_delnext_eof() */
2351 if (Cursor == LastChar) {/* if I'm at the end */
2356 if (Cursor != InputBuf)
2362 c_delafter(Argument); /* delete after dot */
2363 if (Cursor > LastChar)
2364 Cursor = LastChar; /* bounds check */
2375 if (Cursor == LastChar) {/* if I'm at the end */
2377 if (Cursor == InputBuf) {
2378 /* if I'm also at the beginning */
2379 so_write(STReof, 4);/* then do a EOF */
2387 if (Cursor != InputBuf)
2393 c_delafter(Argument); /* delete after dot */
2394 if (Cursor > LastChar)
2395 Cursor = LastChar; /* bounds check */
2405 if (Cursor == LastChar) { /* if I'm at the end */
2407 *LastChar = '\0'; /* just in case */
2408 return(CC_LIST_CHOICES);
2411 c_delafter(Argument); /* delete after dot */
2412 if (Cursor > LastChar)
2413 Cursor = LastChar; /* bounds check */
2420 e_delnext_list_eof(c)
2424 if (Cursor == LastChar) { /* if I'm at the end */
2425 if (Cursor == InputBuf) { /* if I'm also at the beginning */
2426 so_write(STReof, 4);/* then do a EOF */
2432 *LastChar = '\0'; /* just in case */
2433 return(CC_LIST_CHOICES);
2437 c_delafter(Argument); /* delete after dot */
2438 if (Cursor > LastChar)
2439 Cursor = LastChar; /* bounds check */
2452 if (Cursor == LastChar && Cursor == InputBuf) {
2453 so_write(STReof, 4); /* then do a EOF */
2459 *LastChar = '\0'; /* just in case */
2460 rv = CC_LIST_CHOICES;
2470 register Char *cp, *p, *kp;
2473 if (Cursor == LastChar)
2477 cp = c_next_word(Cursor, LastChar, Argument);
2479 for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */
2483 c_delafter((int)(cp - Cursor)); /* delete after dot */
2484 if (Cursor > LastChar)
2485 Cursor = LastChar; /* bounds check */
2497 if (ActionFlag & TCSHOP_DELETE) {
2501 RefCursor(); /* move the cursor */
2514 while (Isspace(*Cursor)) /* We want FIRST non space character */
2516 if (ActionFlag & TCSHOP_DELETE) {
2522 RefCursor(); /* move the cursor */
2531 register Char *kp, *cp;
2536 while (cp < LastChar)
2537 *kp++ = *cp++; /* copy it */
2539 LastChar = Cursor; /* zap! -- delete to end */
2549 register Char *kp, *cp;
2555 *kp++ = *cp++; /* copy it */
2557 c_delbefore((int)(Cursor - InputBuf));
2558 Cursor = InputBuf; /* zap! */
2567 register Char *kp, *cp;
2572 while (cp < LastChar)
2573 *kp++ = *cp++; /* copy it */
2575 LastChar = InputBuf; /* zap! -- delete all of it */
2585 register Char *kp, *cp;
2591 if (Mark > Cursor) {
2595 *kp++ = *cp++; /* copy it */
2597 c_delafter((int)(cp - Cursor)); /* delete it - UNUSED BY VI mode */
2599 else { /* mark is before cursor */
2603 *kp++ = *cp++; /* copy it */
2605 c_delbefore((int)(cp - Mark));
2616 register Char *kp, *cp;
2622 if (Mark > Cursor) {
2626 *kp++ = *cp++; /* copy it */
2629 else { /* mark is before cursor */
2633 *kp++ = *cp++; /* copy it */
2636 return(CC_NORM); /* don't even need to Refresh() */
2648 /* do nothing if we are at beginning of line or have only one char */
2649 if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
2653 if (Cursor < LastChar) {
2657 Cursor[-2] = Cursor[-1];
2666 { /* gosmacs style ^T */
2670 if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
2672 Cursor[-2] = Cursor[-1];
2681 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2684 e_charback_mbyte(argument)
2687 if (!_enable_mbdisp) {
2688 if (Argument > Cursor - InputBuf)
2694 while (0 < argument && Cursor > InputBuf) {
2695 if (Cursor - 1 != InputBuf &&
2696 Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) {
2712 if (Cursor > InputBuf) {
2713 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2714 e_charback_mbyte(Argument);
2716 if (Argument > Cursor - InputBuf)
2723 if (ActionFlag & TCSHOP_DELETE) {
2742 if (Cursor == InputBuf)
2746 Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */
2748 if (ActionFlag & TCSHOP_DELETE) {
2763 if (Cursor == InputBuf)
2767 Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
2770 if (ActionFlag & TCSHOP_DELETE) {
2779 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2782 e_charfwd_mbyte(argument)
2785 if (!_enable_mbdisp)
2788 while (0 < argument && Cursor < LastChar) {
2789 if (Cursor + 1 != LastChar &&
2790 Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) {
2805 if (Cursor < LastChar) {
2806 #if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
2807 e_charfwd_mbyte(Argument);
2811 if (Cursor > LastChar)
2815 if (ActionFlag & TCSHOP_DELETE) {
2834 if (Cursor == LastChar)
2838 Cursor = c_next_word(Cursor, LastChar, Argument);
2841 if (ActionFlag & TCSHOP_DELETE) {
2856 if (Cursor == LastChar)
2860 Cursor = c_nexword(Cursor, LastChar, Argument);
2863 if (ActionFlag & TCSHOP_DELETE) {
2878 if (Cursor == LastChar)
2882 Cursor = c_next_word(Cursor, LastChar, Argument);
2883 if (Cursor < LastChar)
2887 if (ActionFlag & TCSHOP_DELETE) {
2901 CCRETVAL rv = CC_ERROR;
2903 xprintf("dir %d patlen %d patbuf %S\n",
2907 LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
2908 LastChar = InputBuf;
2910 case F_DOWN_SEARCH_HIST:
2911 rv = e_down_search_hist(0);
2913 case F_UP_SEARCH_HIST:
2914 rv = e_up_search_hist(0);
2923 v_csearch_back(ch, count, tflag)
2924 int ch, count, tflag;
2932 while (cp > InputBuf && *cp != ch)
2936 if (cp < InputBuf || (cp == InputBuf && *cp != ch))
2939 if (*cp == ch && tflag)
2944 if (ActionFlag & TCSHOP_DELETE) {
2955 v_csearch_fwd(ch, count, tflag)
2956 int ch, count, tflag;
2964 while (cp < LastChar && *cp != ch)
2971 if (*cp == ch && tflag)
2976 if (ActionFlag & TCSHOP_DELETE) {
2990 register Char *cp, *kp;
2992 if (ActionFlag == TCSHOP_DELETE) {
2993 ActionFlag = TCSHOP_NOP;
2998 for (cp = InputBuf; cp < LastChar; cp++) {
3003 UndoAction = TCSHOP_INSERT;
3005 LastChar = InputBuf;
3007 if (c & TCSHOP_INSERT)
3008 c_alternativ_key_map(0);
3013 else if (ActionFlag == TCSHOP_NOP) {
3017 return(CC_ARGHACK); /* Do NOT clear out argument */
3029 /* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
3031 c_get_word(begin, end)
3038 while (Argument--) {
3039 while ((cp <= LastChar) && (isword(*cp)))
3042 while ((cp >= InputBuf) && (isword(*cp)))
3047 #endif /* COMMENT */
3057 end = c_next_word(Cursor, LastChar, Argument);
3059 for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
3064 if (Cursor > LastChar)
3078 end = c_next_word(Cursor, LastChar, Argument);
3081 for (; cp < end; cp++) {
3089 for (; cp < end; cp++)
3094 if (Cursor > LastChar)
3107 end = c_next_word(Cursor, LastChar, Argument);
3109 for (cp = Cursor; cp < end; cp++)
3114 if (Cursor > LastChar)
3149 { /* multiply current argument by 4 */
3151 if (Argument > 1000000)
3168 num = GetNextChar(&ch);
3171 return e_insert(ch);
3173 return e_send_eof(0);
3183 return(CC_ARGHACK); /* preserve argument */
3192 CurrentKeyMap = CcAltMap;
3193 return(CC_ARGHACK); /* preserve argument */
3202 { /* move to beginning of line and start vi
3209 UndoAction = TCSHOP_DELETE;
3211 RefCursor(); /* move the cursor */
3212 c_alternativ_key_map(0);
3220 { /* vi mode overwrite one character */
3222 c_alternativ_key_map(0);
3223 inputmode = MODE_REPLACE_1;
3224 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3234 { /* vi mode start overwriting */
3236 c_alternativ_key_map(0);
3237 inputmode = MODE_REPLACE;
3238 UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
3248 { /* vi mode substitute for one char */
3250 c_delafter(Argument);
3251 c_alternativ_key_map(0);
3259 { /* vi mode replace whole line */
3261 (void) e_killall(0);
3262 c_alternativ_key_map(0);
3270 { /* vi mode change to end of line */
3272 (void) e_killend(0);
3273 c_alternativ_key_map(0);
3281 { /* vi mode start inserting */
3283 c_alternativ_key_map(0);
3287 UndoAction = TCSHOP_DELETE;
3296 { /* vi mode start adding */
3298 c_alternativ_key_map(0);
3299 if (Cursor < LastChar)
3302 if (Cursor > LastChar)
3309 UndoAction = TCSHOP_DELETE;
3318 { /* vi mode to add at end of line */
3320 c_alternativ_key_map(0);
3323 InsertPos = LastChar; /* Mark where insertion begins */
3325 UndoAction = TCSHOP_DELETE;
3339 if (Cursor < LastChar) {
3340 #ifndef WINNT_NATIVE
3344 #endif /* WINNT_NATIVE */
3346 *Cursor++ = Tolower(c);
3347 else if (Islower(c))
3348 *Cursor++ = Toupper(c);
3351 RefPlusOne(); /* fast refresh for one char */
3366 for (p = InputBuf; Isspace(*p); p++)
3373 return(e_newline(0));
3380 { /* erase all of current line, start again */
3382 ResetInLine(0); /* reset the input pointers */
3403 ClearScreen(); /* clear the whole real screen */
3404 ClearDisp(); /* reset everything */
3414 #if defined(_MINIX) || defined(WINNT_NATIVE)
3415 /* SAK PATCH: erase all of current line, start again */
3416 ResetInLine(0); /* reset the input pointers */
3419 return (CC_REFRESH);
3420 #else /* !_MINIX && !WINNT_NATIVE */
3423 #endif /* _MINIX || WINNT_NATIVE */
3427 * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
3428 * Function to send a character back to the input stream in cooked
3429 * mode. Only works if we have TIOCSTI
3437 extern int Tty_raw_mode;
3438 int was_raw = Tty_raw_mode;
3442 (void) Cookedmode();
3444 (void) write(SHIN, "\n", 1);
3445 (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
3449 return(e_redisp(c));
3450 #else /* !TIOCSTI */
3452 #endif /* !TIOCSTI */
3461 inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
3521 *LastChar = '\0'; /* just in case */
3532 *LastChar = '\0'; /* just in case */
3534 return(e_insert(' '));
3544 return e_inc_search(F_DOWN_SEARCH_HIST);
3555 return e_inc_search(F_UP_SEARCH_HIST);
3563 register Char *cp, *oldc, *dp;
3566 if (Cursor == InputBuf)
3571 /* does a bounds check */
3572 cp = c_prev_word(Cursor, InputBuf, Argument);
3574 c_insert((int)(oldc - cp));
3575 for (dp = oldc; cp < oldc && dp < LastChar; cp++)
3578 Cursor = dp; /* put cursor at end */
3602 * Here we pass &c to the ioctl because some os's (NetBSD) expect it
3603 * there even if they don't use it. (lukem@netbsd.org)
3605 if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
3607 xprintf(CGETS(5, 1, "Load average unavailable\n"));
3618 * Delete with insert == change: first we delete and then we leave in
3621 return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
3630 return(v_action(TCSHOP_DELETE));
3640 if (Cursor == LastChar)
3644 Cursor = c_endword(Cursor, LastChar, Argument);
3646 if (ActionFlag & TCSHOP_DELETE)
3663 if (Cursor == LastChar)
3667 Cursor = c_eword(Cursor, LastChar, Argument);
3669 if (ActionFlag & TCSHOP_DELETE) {
3687 if (GetNextChar(&ch) != 1)
3688 return e_send_eof(0);
3690 srch_dir = CHAR_FWD;
3693 return v_csearch_fwd(ch, Argument, 0);
3705 if (GetNextChar(&ch) != 1)
3706 return e_send_eof(0);
3708 srch_dir = CHAR_BACK;
3711 return v_csearch_back(ch, Argument, 0);
3722 if (GetNextChar(&ch) != 1)
3723 return e_send_eof(0);
3725 return v_csearch_fwd(ch, Argument, 1);
3737 if (GetNextChar(&ch) != 1)
3738 return e_send_eof(0);
3740 return v_csearch_back(ch, Argument, 1);
3752 return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
3753 v_csearch_back(srch_char, Argument, 0);
3765 return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
3766 v_csearch_back(srch_char, Argument, 0);
3775 register Char *kp, *cp;
3780 switch (UndoAction) {
3781 case TCSHOP_DELETE|TCSHOP_INSERT:
3783 if (UndoSize == 0) return(CC_NORM);
3786 for (loop=0; loop < UndoSize; loop++) /* copy the chars */
3787 *kp++ = *cp++; /* into UndoBuf */
3789 for (cp = UndoPtr; cp <= LastChar; cp++)
3792 LastChar -= UndoSize;
3795 UndoAction = TCSHOP_INSERT;
3799 if (UndoSize == 0) return(CC_NORM);
3803 c_insert(UndoSize); /* open the space, */
3804 for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
3807 UndoAction = TCSHOP_DELETE;
3811 if (UndoSize == 0) return(CC_NORM);
3815 size = (int)(Cursor-LastChar); /* NOT NSL independant */
3816 if (size < UndoSize)
3818 for(loop = 0; loop < size; loop++) {
3838 return v_search(F_UP_SEARCH_HIST);
3847 return v_search(F_DOWN_SEARCH_HIST);
3856 if (patlen == 0) return(CC_ERROR);
3857 return(v_repeat_srch(searchdir));
3866 if (patlen == 0) return(CC_ERROR);
3867 return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
3868 F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
3871 #ifndef WINNT_NATIVE
3872 /* Since ed.defns.h is generated from ed.defns.c, these empty
3873 functions will keep the F_NUM_FNS consistent
3876 e_copy_to_clipboard(c)
3884 e_paste_from_clipboard(c)
3919 #endif /* !WINNT_NATIVE */
3923 MoveCursor(n) /* move cursor + right - left char */
3926 Cursor = Cursor + n;
3927 if (Cursor < InputBuf)
3929 if (Cursor > LastChar)
3944 if (p < InputBuf || p > LastChar)
3945 return 1; /* Error */