summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/ed.chared.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcsh/ed.chared.c')
-rw-r--r--contrib/tcsh/ed.chared.c4005
1 files changed, 4005 insertions, 0 deletions
diff --git a/contrib/tcsh/ed.chared.c b/contrib/tcsh/ed.chared.c
new file mode 100644
index 0000000..7703bbe
--- /dev/null
+++ b/contrib/tcsh/ed.chared.c
@@ -0,0 +1,4005 @@
+/* $Header: /src/pub/tcsh/ed.chared.c,v 3.59 1999/08/13 16:34:57 christos Exp $ */
+/*
+ * ed.chared.c: Character editing functions.
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ Bjorn Knutsson @ Thu Jun 24 19:02:17 1999
+
+ e_dabbrev_expand() did not do proper completion if quoted spaces were present
+ in the string being completed. Exemple:
+
+ # echo hello\ world
+ hello world
+ # echo h<press key bound to dabbrev-expande>
+ # echo hello\<cursor>
+
+ Correct behavior is:
+ # echo h<press key bound to dabbrev-expande>
+ # echo hello\ world<cursor>
+
+ The same problem occured if spaces were present in a string withing quotation
+ marks. Example:
+
+ # echo "hello world"
+ hello world
+ # echo "h<press key bound to dabbrev-expande>
+ # echo "hello<cursor>
+
+ The former problem could be solved with minor modifications of c_preword()
+ and c_endword(). The latter, however, required a significant rewrite of
+ c_preword(), since quoted strings must be parsed from start to end to
+ determine if a given character is inside or outside the quotation marks.
+
+ Compare the following two strings:
+
+ # echo \"" 'foo \' bar\"
+ " 'foo \' bar\
+ # echo '\"" 'foo \' bar\"
+ \"" foo ' bar"
+
+ The only difference between the two echo lines is in the first character
+ after the echo command. The result is either one or three arguments.
+
+ */
+
+#include "sh.h"
+
+RCSID("$Id: ed.chared.c,v 3.59 1999/08/13 16:34:57 christos Exp $")
+
+#include "ed.h"
+#include "tw.h"
+#include "ed.defns.h"
+
+/* #define SDEBUG */
+
+#define TCSHOP_NOP 0x00
+#define TCSHOP_DELETE 0x01
+#define TCSHOP_INSERT 0x02
+#define TCSHOP_CHANGE 0x04
+
+#define CHAR_FWD 0
+#define CHAR_BACK 1
+
+/*
+ * vi word treatment
+ * from: Gert-Jan Vons <vons@cesar.crbca1.sinet.slb.com>
+ */
+#define C_CLASS_WHITE 1
+#define C_CLASS_ALNUM 2
+#define C_CLASS_OTHER 3
+
+static Char *InsertPos = InputBuf; /* Where insertion starts */
+static Char *ActionPos = 0; /* Where action begins */
+static int ActionFlag = TCSHOP_NOP; /* What delayed action to take */
+/*
+ * Word search state
+ */
+static int searchdir = F_UP_SEARCH_HIST; /* Direction of last search */
+static Char patbuf[INBUFSIZE]; /* Search target */
+static int patlen = 0;
+/*
+ * Char search state
+ */
+static int srch_dir = CHAR_FWD; /* Direction of last search */
+static Char srch_char = 0; /* Search target */
+
+/* all routines that start with c_ are private to this set of routines */
+static void c_alternativ_key_map __P((int));
+static void c_insert __P((int));
+static void c_delafter __P((int));
+static void c_delbefore __P((int));
+static int c_to_class __P((int));
+static Char *c_prev_word __P((Char *, Char *, int));
+static Char *c_next_word __P((Char *, Char *, int));
+static Char *c_number __P((Char *, int *, int));
+static Char *c_expand __P((Char *));
+static void c_excl __P((Char *));
+static void c_substitute __P((void));
+static void c_delfini __P((void));
+static int c_hmatch __P((Char *));
+static void c_hsetpat __P((void));
+#ifdef COMMENT
+static void c_get_word __P((Char **, Char **));
+#endif
+static Char *c_preword __P((Char *, Char *, int));
+static Char *c_nexword __P((Char *, Char *, int));
+static Char *c_endword __P((Char *, Char *, int));
+static Char *c_eword __P((Char *, Char *, int));
+static CCRETVAL c_get_histline __P((void));
+static CCRETVAL c_search_line __P((Char *, int));
+static CCRETVAL v_repeat_srch __P((int));
+static CCRETVAL e_inc_search __P((int));
+static CCRETVAL v_search __P((int));
+static CCRETVAL v_csearch_fwd __P((int, int, int));
+static CCRETVAL v_action __P((int));
+static CCRETVAL v_csearch_back __P((int, int, int));
+
+#if defined(DSPMBYTE)
+static void e_charfwd_mbyte __P((int));
+static void e_charback_mbyte __P((int));
+static int extdel;
+static int extins = 0;
+#endif
+
+static void
+c_alternativ_key_map(state)
+ int state;
+{
+ switch (state) {
+ case 0:
+ CurrentKeyMap = CcKeyMap;
+ break;
+ case 1:
+ CurrentKeyMap = CcAltMap;
+ break;
+ default:
+ return;
+ }
+
+ AltKeyMap = (Char) state;
+}
+
+static void
+c_insert(num)
+ register int num;
+{
+ register Char *cp;
+
+ if (LastChar + num >= InputLim)
+ return; /* can't go past end of buffer */
+
+ if (Cursor < LastChar) { /* if I must move chars */
+ for (cp = LastChar; cp >= Cursor; cp--)
+ cp[num] = *cp;
+ }
+ LastChar += num;
+}
+
+static void
+c_delafter(num)
+ register int num;
+{
+ register Char *cp, *kp = NULL;
+
+#if defined(DSPMBYTE)
+ Char *wkcp;
+
+ extdel = 0;
+#endif
+
+ if (num > LastChar - Cursor)
+ num = (int) (LastChar - Cursor); /* bounds check */
+
+ if (num > 0) { /* if I can delete anything */
+#if defined(DSPMBYTE)
+ /* check for code of deleted character */
+ if (_enable_mbdisp) {
+ for (wkcp = Cursor ; wkcp < Cursor + num; wkcp++) {
+ if (extdel == 0)
+ extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
+ else
+ extdel = 0; /* if 2nd. byte, force set to 0 */
+ }
+ }
+#endif
+ if (VImode) {
+ kp = UndoBuf; /* Set Up for VI undo command */
+ UndoAction = TCSHOP_INSERT;
+ UndoSize = num;
+ UndoPtr = Cursor;
+ for (cp = Cursor; cp <= LastChar; cp++) {
+ *kp++ = *cp; /* Save deleted chars into undobuf */
+ *cp = cp[num];
+ }
+ }
+ else
+ for (cp = Cursor; cp <= LastChar; cp++)
+ *cp = cp[num];
+ LastChar -= num;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel && Ismbyte2(*Cursor)) {
+ if( VImode ) {
+ UndoSize++;
+ *kp++ = *Cursor; /* Save deleted chars into undobuf */
+ }
+ for (cp = Cursor; cp <= LastChar; cp++)
+ *cp = cp[1];
+ LastChar--;
+ e_redisp( 1 );
+ }
+ else
+ extdel = 0;
+#endif
+ }
+#ifdef notdef
+ else {
+ /*
+ * XXX: We don't want to do that. In emacs mode overwrite should be
+ * sticky. I am not sure how that affects vi mode
+ */
+ inputmode = MODE_INSERT;
+ }
+#endif /* notdef */
+}
+
+static void
+c_delbefore(num) /* delete before dot, with bounds checking */
+ register int num;
+{
+ register Char *cp, *kp = NULL;
+
+#if defined(DSPMBYTE)
+ Char *nowcur, *wkcp;
+ Char delc;
+
+ extdel = 0;
+#endif
+
+ if (num > Cursor - InputBuf)
+ num = (int) (Cursor - InputBuf); /* bounds check */
+
+ if (num > 0) { /* if I can delete anything */
+#if defined(DSPMBYTE)
+ nowcur = Cursor - num;
+ delc = *nowcur;
+#endif
+ if (VImode) {
+ kp = UndoBuf; /* Set Up for VI undo command */
+ UndoAction = TCSHOP_INSERT;
+ UndoSize = num;
+ UndoPtr = Cursor - num;
+ for (cp = Cursor - num; cp <= LastChar; cp++) {
+ *kp++ = *cp;
+ *cp = cp[num];
+ }
+ }
+ else
+ for (cp = Cursor - num; cp <= LastChar; cp++)
+ *cp = cp[num];
+ LastChar -= num;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp) {
+ for (wkcp = InputBuf; wkcp < nowcur; wkcp++) {
+ if(extdel == 0)
+ extdel = Ismbyte1(*wkcp); /* check to 1st. byte */
+ else
+ extdel = 0; /* if 2nd. byte, force set to 0 */
+ }
+ if (extdel && Ismbyte2(delc)) {
+ if( VImode ) {
+ UndoSize++;
+ UndoPtr--;
+ *kp++ = *(nowcur-1);
+ /* Save deleted chars into undobuf */
+ }
+ for (cp = nowcur - 1; cp <= LastChar; cp++)
+ *cp = cp[1];
+ LastChar--;
+ }
+ }
+ else
+ extdel = 0;
+#endif
+ }
+}
+
+static Char *
+c_preword(p, low, n)
+ register Char *p, *low;
+ register int n;
+{
+ while (n--) {
+ register Char *prev = low;
+ register Char *new;
+
+ while (prev < p) { /* Skip initial spaces */
+ if (!Isspace(*prev) || (Isspace(*prev) && *(prev-1) == (Char)'\\'))
+ break;
+ prev++;
+ }
+
+ new = prev;
+
+ while (new < p) {
+ prev = new;
+ new = c_endword(prev-1, p, 1); /* Skip to next space */
+ new++; /* Step away from end of word */
+ while (new <= p) { /* Skip trailing spaces */
+ if (!Isspace(*new) || (Isspace(*new) && *(new-1) == (Char)'\\'))
+ break;
+ new++;
+ }
+ }
+
+ p = prev; /* Set to previous word start */
+
+ }
+ if (p < low)
+ p = low;
+ return (p);
+}
+
+/*
+ * c_to_class() returns the class of the given character.
+ *
+ * This is used to make the c_prev_word() and c_next_word() functions
+ * work like vi's, which classify characters. A word is a sequence of
+ * characters belonging to the same class, classes being defined as
+ * follows:
+ *
+ * 1/ whitespace
+ * 2/ alphanumeric chars, + underscore
+ * 3/ others
+ */
+static int
+c_to_class(ch)
+register int ch;
+{
+ if (Isspace(ch))
+ return C_CLASS_WHITE;
+
+ if (Isdigit(ch) || Isalpha(ch) || ch == '_')
+ return C_CLASS_ALNUM;
+
+ return C_CLASS_OTHER;
+}
+
+static Char *
+c_prev_word(p, low, n)
+ register Char *p, *low;
+ register int n;
+{
+ p--;
+
+ if (!VImode) {
+ while (n--) {
+ while ((p >= low) && !isword(*p))
+ p--;
+ while ((p >= low) && isword(*p))
+ p--;
+ }
+
+ /* cp now points to one character before the word */
+ p++;
+ if (p < low)
+ p = low;
+ /* cp now points where we want it */
+ return(p);
+ }
+
+ while (n--) {
+ register int c_class;
+
+ if (p < low)
+ break;
+
+ /* scan until beginning of current word (may be all whitespace!) */
+ c_class = c_to_class(*p);
+ while ((p >= low) && c_class == c_to_class(*p))
+ p--;
+
+ /* if this was a non_whitespace word, we're ready */
+ if (c_class != C_CLASS_WHITE)
+ continue;
+
+ /* otherwise, move back to beginning of the word just found */
+ c_class = c_to_class(*p);
+ while ((p >= low) && c_class == c_to_class(*p))
+ p--;
+ }
+
+ p++; /* correct overshoot */
+
+ return (p);
+}
+
+static Char *
+c_next_word(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ if (!VImode) {
+ while (n--) {
+ while ((p < high) && !isword(*p))
+ p++;
+ while ((p < high) && isword(*p))
+ p++;
+ }
+ if (p > high)
+ p = high;
+ /* p now points where we want it */
+ return(p);
+ }
+
+ while (n--) {
+ register int c_class;
+
+ if (p >= high)
+ break;
+
+ /* scan until end of current word (may be all whitespace!) */
+ c_class = c_to_class(*p);
+ while ((p < high) && c_class == c_to_class(*p))
+ p++;
+
+ /* if this was all whitespace, we're ready */
+ if (c_class == C_CLASS_WHITE)
+ continue;
+
+ /* if we've found white-space at the end of the word, skip it */
+ while ((p < high) && c_to_class(*p) == C_CLASS_WHITE)
+ p++;
+ }
+
+ p--; /* correct overshoot */
+
+ return (p);
+}
+
+static Char *
+c_nexword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ while (n--) {
+ while ((p < high) && !Isspace(*p))
+ p++;
+ while ((p < high) && Isspace(*p))
+ p++;
+ }
+
+ if (p > high)
+ p = high;
+ /* p now points where we want it */
+ return(p);
+}
+
+/*
+ * Expand-History (originally "Magic-Space") code added by
+ * Ray Moody <ray@gibbs.physics.purdue.edu>
+ * this is a neat, but odd, addition.
+ */
+
+/*
+ * c_number: Ignore character p points to, return number appearing after that.
+ * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
+ * Return p pointing to last char used.
+ */
+
+/*
+ * dval is the number to subtract from for things like $-3
+ */
+
+static Char *
+c_number(p, num, dval)
+ register Char *p;
+ register int *num;
+ register int dval;
+{
+ register int i;
+ register int sign = 1;
+
+ if (*++p == '^') {
+ *num = 1;
+ return(p);
+ }
+ if (*p == '$') {
+ if (*++p != '-') {
+ *num = NCARGS; /* Handle $ */
+ return(--p);
+ }
+ sign = -1; /* Handle $- */
+ ++p;
+ }
+ for (i = 0; *p >= '0' && *p <= '9'; i = 10 * i + *p++ - '0')
+ continue;
+ *num = (sign < 0 ? dval - i : i);
+ return(--p);
+}
+
+/*
+ * excl_expand: There is an excl to be expanded to p -- do the right thing
+ * with it and return a version of p advanced over the expanded stuff. Also,
+ * update tsh_cur and related things as appropriate...
+ */
+
+static Char *
+c_expand(p)
+ register Char *p;
+{
+ register Char *q;
+ register struct Hist *h = Histlist.Hnext;
+ register struct wordent *l;
+ int i, from, to, dval;
+ bool all_dig;
+ bool been_once = 0;
+ Char *op = p;
+ Char buf[INBUFSIZE];
+ Char *bend = buf;
+ Char *modbuf, *omodbuf;
+
+ if (!h)
+ goto excl_err;
+excl_sw:
+ switch (*(q = p + 1)) {
+
+ case '^':
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, 1);
+ break;
+
+ case '$':
+ if ((l = (h->Hlex).prev) != 0)
+ bend = expand_lex(buf, INBUFSIZE, l->prev->prev, 0, 0);
+ break;
+
+ case '*':
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
+ break;
+
+ default:
+ if (been_once) { /* unknown argument */
+ /* assume it's a modifier, e.g. !foo:h, and get whole cmd */
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ q -= 2;
+ break;
+ }
+ been_once = 1;
+
+ if (*q == ':') /* short form: !:arg */
+ --q;
+
+ if (*q != HIST) {
+ /*
+ * Search for a space, tab, or colon. See if we have a number (as
+ * in !1234:xyz). Remember the number.
+ */
+ for (i = 0, all_dig = 1;
+ *q != ' ' && *q != '\t' && *q != ':' && q < Cursor; q++) {
+ /*
+ * PWP: !-4 is a valid history argument too, therefore the test
+ * is if not a digit, or not a - as the first character.
+ */
+ if ((*q < '0' || *q > '9') && (*q != '-' || q != p + 1))
+ all_dig = 0;
+ else if (*q == '-')
+ all_dig = 2;/* we are sneeky about this */
+ else
+ i = 10 * i + *q - '0';
+ }
+ --q;
+
+ /*
+ * If we have a number, search for event i. Otherwise, search for
+ * a named event (as in !foo). (In this case, I is the length of
+ * the named event).
+ */
+ if (all_dig) {
+ if (all_dig == 2)
+ i = -i; /* make it negitive */
+ if (i < 0) /* if !-4 (for example) */
+ i = eventno + 1 + i; /* remember: i is < 0 */
+ for (; h; h = h->Hnext) {
+ if (h->Hnum == i)
+ break;
+ }
+ }
+ else {
+ for (i = (int) (q - p); h; h = h->Hnext) {
+ if ((l = &h->Hlex) != 0) {
+ if (!Strncmp(p + 1, l->next->word, (size_t) i))
+ break;
+ }
+ }
+ }
+ }
+ if (!h)
+ goto excl_err;
+ if (q[1] == ':' || q[1] == '-' || q[1] == '*' ||
+ q[1] == '$' || q[1] == '^') { /* get some args */
+ p = q[1] == ':' ? ++q : q;
+ /*
+ * Go handle !foo:*
+ */
+ if ((q[1] < '0' || q[1] > '9') &&
+ q[1] != '-' && q[1] != '$' && q[1] != '^')
+ goto excl_sw;
+ /*
+ * Go handle !foo:$
+ */
+ if (q[1] == '$' && (q[2] != '-' || q[3] < '0' || q[3] > '9'))
+ goto excl_sw;
+ /*
+ * Count up the number of words in this event. Store it in dval.
+ * Dval will be fed to number.
+ */
+ dval = 0;
+ if ((l = h->Hlex.prev) != 0) {
+ for (l = l->prev; l != h->Hlex.next; l = l->prev, dval++)
+ continue;
+ }
+ if (!dval)
+ goto excl_err;
+ if (q[1] == '-')
+ from = 0;
+ else
+ q = c_number(q, &from, dval);
+ if (q[1] == '-') {
+ ++q;
+ if ((q[1] < '0' || q[1] > '9') && q[1] != '$')
+ to = dval - 1;
+ else
+ q = c_number(q, &to, dval);
+ }
+ else if (q[1] == '*') {
+ ++q;
+ to = NCARGS;
+ }
+ else {
+ to = from;
+ }
+ if (from < 0 || to < from)
+ goto excl_err;
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
+ }
+ else { /* get whole cmd */
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ }
+ break;
+ }
+
+ /*
+ * Apply modifiers, if any.
+ */
+ if (q[1] == ':') {
+ *bend = '\0';
+ modbuf = omodbuf = buf;
+ while (q[1] == ':' && modbuf != NULL) {
+ switch (q[2]) {
+ case 'r':
+ case 'e':
+ case 'h':
+ case 't':
+ case 'q':
+ case 'x':
+ case 'u':
+ case 'l':
+ if ((modbuf = domod(omodbuf, (int) q[2])) != NULL) {
+ if (omodbuf != buf)
+ xfree((ptr_t) omodbuf);
+ omodbuf = modbuf;
+ }
+ ++q;
+ break;
+
+ case 'a':
+ case 'g':
+ /* Not implemented; this needs to be done before expanding
+ * lex. We don't have the words available to us anymore.
+ */
+ ++q;
+ break;
+
+ case 'p':
+ /* Ok */
+ ++q;
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ ++q;
+ break;
+ }
+ if (q[1])
+ ++q;
+ }
+ if (omodbuf != buf) {
+ (void) Strcpy(buf, omodbuf);
+ xfree((ptr_t) omodbuf);
+ bend = Strend(buf);
+ }
+ }
+
+ /*
+ * Now replace the text from op to q inclusive with the text from buf to
+ * bend.
+ */
+ q++;
+
+ /*
+ * Now replace text non-inclusively like a real CS major!
+ */
+ if (LastChar + (bend - buf) - (q - op) >= InputLim)
+ goto excl_err;
+ (void) memmove((ptr_t) (q + (bend - buf) - (q - op)), (ptr_t) q,
+ (size_t) ((LastChar - q) * sizeof(Char)));
+ LastChar += (bend - buf) - (q - op);
+ Cursor += (bend - buf) - (q - op);
+ (void) memmove((ptr_t) op, (ptr_t) buf,
+ (size_t) ((bend - buf) * sizeof(Char)));
+ *LastChar = '\0';
+ return(op + (bend - buf));
+excl_err:
+ SoundBeep();
+ return(op + 1);
+}
+
+/*
+ * c_excl: An excl has been found at point p -- back up and find some white
+ * space (or the beginning of the buffer) and properly expand all the excl's
+ * from there up to the current cursor position. We also avoid (trying to)
+ * expanding '>!'
+ */
+
+static void
+c_excl(p)
+ register Char *p;
+{
+ register int i;
+ register Char *q;
+
+ /*
+ * if />[SPC TAB]*![SPC TAB]/, back up p to just after the >. otherwise,
+ * back p up to just before the current word.
+ */
+ if ((p[1] == ' ' || p[1] == '\t') &&
+ (p[-1] == ' ' || p[-1] == '\t' || p[-1] == '>')) {
+ for (q = p - 1; q > InputBuf && (*q == ' ' || *q == '\t'); --q)
+ continue;
+ if (*q == '>')
+ ++p;
+ }
+ else {
+ while (*p != ' ' && *p != '\t' && p > InputBuf)
+ --p;
+ }
+
+ /*
+ * Forever: Look for history char. (Stop looking when we find the cursor.)
+ * Count backslashes. Of odd, skip history char. Return if all done.
+ * Expand if even number of backslashes.
+ */
+ for (;;) {
+ while (*p != HIST && p < Cursor)
+ ++p;
+ for (i = 1; (p - i) >= InputBuf && p[-i] == '\\'; i++)
+ continue;
+ if (i % 2 == 0)
+ ++p;
+ if (p >= Cursor)
+ return;
+ if (i % 2 == 1)
+ p = c_expand(p);
+ }
+}
+
+
+static void
+c_substitute()
+{
+ register Char *p;
+
+ /*
+ * Start p out one character before the cursor. Move it backwards looking
+ * for white space, the beginning of the line, or a history character.
+ */
+ for (p = Cursor - 1;
+ p > InputBuf && *p != ' ' && *p != '\t' && *p != HIST; --p)
+ continue;
+
+ /*
+ * If we found a history character, go expand it.
+ */
+ if (*p == HIST)
+ c_excl(p);
+ Refresh();
+}
+
+static void
+c_delfini() /* Finish up delete action */
+{
+ register int Size;
+
+ if (ActionFlag & TCSHOP_INSERT)
+ c_alternativ_key_map(0);
+
+ ActionFlag = TCSHOP_NOP;
+
+ if (ActionPos == 0)
+ return;
+
+ UndoAction = TCSHOP_INSERT;
+
+ if (Cursor > ActionPos) {
+ Size = (int) (Cursor-ActionPos);
+ c_delbefore(Size);
+ Cursor = ActionPos;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel) {
+ Cursor--;
+ e_redisp(1);
+ }
+#endif
+ RefCursor();
+ }
+ else if (Cursor < ActionPos) {
+ Size = (int)(ActionPos-Cursor);
+ c_delafter(Size);
+ }
+ else {
+ Size = 1;
+ c_delafter(Size);
+ }
+ UndoPtr = Cursor;
+ UndoSize = Size;
+}
+
+static Char *
+c_endword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ register int inquote = 0;
+ p++;
+
+ while (n--) {
+ while (p < high) { /* Skip spaces */
+ if (!Isspace(*p) || (Isspace(*p) && *(p-1) == (Char)'\\'))
+ break;
+ p++;
+ }
+ while (p < high) { /* Skip string */
+ if ((*p == (Char)'\'' || *p == (Char)'"')) { /* Quotation marks? */
+ if ((!inquote && *(p-1) != (Char)'\\') || inquote) { /* Should it be honored? */
+ if (inquote == 0) inquote = *p;
+ else if (inquote == *p) inquote = 0;
+ }
+ }
+ if (!inquote && (Isspace(*p) && *(p-1) != (Char)'\\')) /* Break if unquoted space */
+ break;
+ p++;
+ }
+ }
+
+ p--;
+ return(p);
+}
+
+
+static Char *
+c_eword(p, high, n)
+ register Char *p, *high;
+ register int n;
+{
+ p++;
+
+ while (n--) {
+ while ((p < high) && Isspace(*p))
+ p++;
+
+ if (Isalnum(*p))
+ while ((p < high) && Isalnum(*p))
+ p++;
+ else
+ while ((p < high) && !(Isspace(*p) || Isalnum(*p)))
+ p++;
+ }
+
+ p--;
+ return(p);
+}
+
+static CCRETVAL
+c_get_histline()
+{
+ struct Hist *hp;
+ int h;
+
+ if (Hist_num == 0) { /* if really the current line */
+ copyn(InputBuf, HistBuf, INBUFSIZE);
+ LastChar = InputBuf + (LastHist - HistBuf);
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+ }
+
+ hp = Histlist.Hnext;
+ if (hp == NULL)
+ return(CC_ERROR);
+
+ for (h = 1; h < Hist_num; h++) {
+ if ((hp->Hnext) == NULL) {
+ Hist_num = h;
+ return(CC_ERROR);
+ }
+ hp = hp->Hnext;
+ }
+
+ if (HistLit && hp->histline) {
+ copyn(InputBuf, hp->histline, INBUFSIZE);
+ CurrentHistLit = 1;
+ }
+ else {
+ (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex);
+ CurrentHistLit = 0;
+ }
+ LastChar = InputBuf + Strlen(InputBuf);
+
+ if (LastChar > InputBuf) {
+ if (LastChar[-1] == '\n')
+ LastChar--;
+#if 0
+ if (LastChar[-1] == ' ')
+ LastChar--;
+#endif
+ if (LastChar < InputBuf)
+ LastChar = InputBuf;
+ }
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+}
+
+static CCRETVAL
+c_search_line(pattern, dir)
+Char *pattern;
+int dir;
+{
+ Char *cp;
+ int len;
+
+ len = (int) Strlen(pattern);
+
+ if (dir == F_UP_SEARCH_HIST) {
+ for (cp = Cursor; cp >= InputBuf; cp--)
+ if (Strncmp(cp, pattern, (size_t) len) == 0 ||
+ Gmatch(cp, pattern)) {
+ Cursor = cp;
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+ } else {
+ for (cp = Cursor; *cp != '\0' && cp < InputLim; cp++)
+ if (Strncmp(cp, pattern, (size_t) len) == 0 ||
+ Gmatch(cp, pattern)) {
+ Cursor = cp;
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+ }
+}
+
+static CCRETVAL
+e_inc_search(dir)
+ int dir;
+{
+ static Char STRfwd[] = { 'f', 'w', 'd', '\0' },
+ STRbck[] = { 'b', 'c', 'k', '\0' };
+ static Char pchar = ':'; /* ':' = normal, '?' = failed */
+ static Char endcmd[2];
+ Char ch, *cp,
+ *oldCursor = Cursor,
+ oldpchar = pchar;
+ CCRETVAL ret = CC_NORM;
+ int oldHist_num = Hist_num,
+ oldpatlen = patlen,
+ newdir = dir,
+ done, redo;
+
+ if (LastChar + sizeof(STRfwd)/sizeof(Char) + 2 + patlen >= InputLim)
+ return(CC_ERROR);
+
+ for (;;) {
+
+ if (patlen == 0) { /* first round */
+ pchar = ':';
+ patbuf[patlen++] = '*';
+ }
+ done = redo = 0;
+ *LastChar++ = '\n';
+ for (cp = newdir == F_UP_SEARCH_HIST ? STRbck : STRfwd;
+ *cp; *LastChar++ = *cp++)
+ continue;
+ *LastChar++ = pchar;
+ for (cp = &patbuf[1]; cp < &patbuf[patlen]; *LastChar++ = *cp++)
+ continue;
+ *LastChar = '\0';
+ Refresh();
+
+ if (GetNextChar(&ch) != 1)
+ return(e_send_eof(0));
+
+ switch (CurrentKeyMap[(unsigned char) ch]) {
+ case F_INSERT:
+ case F_DIGIT:
+ case F_MAGIC_SPACE:
+ if (patlen > INBUFSIZE - 3)
+ SoundBeep();
+ else {
+ patbuf[patlen++] = ch;
+ *LastChar++ = ch;
+ *LastChar = '\0';
+ Refresh();
+ }
+ break;
+
+ case F_INC_FWD:
+ newdir = F_DOWN_SEARCH_HIST;
+ redo++;
+ break;
+
+ case F_INC_BACK:
+ newdir = F_UP_SEARCH_HIST;
+ redo++;
+ break;
+
+ case F_DELPREV:
+ if (patlen > 1)
+ done++;
+ else
+ SoundBeep();
+ break;
+
+ default:
+ switch (ch) {
+ case 0007: /* ^G: Abort */
+ ret = CC_ERROR;
+ done++;
+ break;
+
+ case 0027: /* ^W: Append word */
+ /* No can do if globbing characters in pattern */
+ for (cp = &patbuf[1]; ; cp++)
+ if (cp >= &patbuf[patlen]) {
+ Cursor += patlen - 1;
+ cp = c_next_word(Cursor, LastChar, 1);
+ while (Cursor < cp && *Cursor != '\n') {
+ if (patlen > INBUFSIZE - 3) {
+ SoundBeep();
+ break;
+ }
+ patbuf[patlen++] = *Cursor;
+ *LastChar++ = *Cursor++;
+ }
+ Cursor = oldCursor;
+ *LastChar = '\0';
+ Refresh();
+ break;
+ } else if (isglob(*cp)) {
+ SoundBeep();
+ break;
+ }
+ break;
+
+ default: /* Terminate and execute cmd */
+ endcmd[0] = ch;
+ PushMacro(endcmd);
+ /*FALLTHROUGH*/
+
+ case 0033: /* ESC: Terminate */
+ ret = CC_REFRESH;
+ done++;
+ break;
+ }
+ break;
+ }
+
+ while (LastChar > InputBuf && *LastChar != '\n')
+ *LastChar-- = '\0';
+ *LastChar = '\0';
+
+ if (!done) {
+
+ /* Can't search if unmatched '[' */
+ for (cp = &patbuf[patlen - 1], ch = ']'; cp > patbuf; cp--)
+ if (*cp == '[' || *cp == ']') {
+ ch = *cp;
+ break;
+ }
+
+ if (patlen > 1 && ch != '[') {
+ if (redo && newdir == dir) {
+ if (pchar == '?') { /* wrap around */
+ Hist_num = newdir == F_UP_SEARCH_HIST ? 0 : 0x7fffffff;
+ if (c_get_histline() == CC_ERROR)
+ /* Hist_num was fixed by first call */
+ (void) c_get_histline();
+ Cursor = newdir == F_UP_SEARCH_HIST ?
+ LastChar : InputBuf;
+ } else
+ Cursor += newdir == F_UP_SEARCH_HIST ? -1 : 1;
+ }
+ patbuf[patlen++] = '*';
+ patbuf[patlen] = '\0';
+ if (Cursor < InputBuf || Cursor > LastChar ||
+ (ret = c_search_line(&patbuf[1], newdir)) == CC_ERROR) {
+ LastCmd = (KEYCMD) newdir; /* avoid c_hsetpat */
+ ret = newdir == F_UP_SEARCH_HIST ?
+ e_up_search_hist(0) : e_down_search_hist(0);
+ if (ret != CC_ERROR) {
+ Cursor = newdir == F_UP_SEARCH_HIST ?
+ LastChar : InputBuf;
+ (void) c_search_line(&patbuf[1], newdir);
+ }
+ }
+ patbuf[--patlen] = '\0';
+ if (ret == CC_ERROR) {
+ SoundBeep();
+ if (Hist_num != oldHist_num) {
+ Hist_num = oldHist_num;
+ if (c_get_histline() == CC_ERROR)
+ return(CC_ERROR);
+ }
+ Cursor = oldCursor;
+ pchar = '?';
+ } else {
+ pchar = ':';
+ }
+ }
+
+ ret = e_inc_search(newdir);
+
+ if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
+ /* break abort of failed search at last non-failed */
+ ret = CC_NORM;
+ }
+
+ }
+
+ if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
+ /* restore on normal return or error exit */
+ pchar = oldpchar;
+ patlen = oldpatlen;
+ if (Hist_num != oldHist_num) {
+ Hist_num = oldHist_num;
+ if (c_get_histline() == CC_ERROR)
+ return(CC_ERROR);
+ }
+ Cursor = oldCursor;
+ if (ret == CC_ERROR)
+ Refresh();
+ }
+ if (done || ret != CC_NORM)
+ return(ret);
+
+ }
+
+}
+
+static CCRETVAL
+v_search(dir)
+ int dir;
+{
+ Char ch;
+ Char tmpbuf[INBUFSIZE];
+ Char oldbuf[INBUFSIZE];
+ Char *oldlc, *oldc;
+ int tmplen;
+
+ copyn(oldbuf, InputBuf, INBUFSIZE);
+ oldlc = LastChar;
+ oldc = Cursor;
+ tmplen = 0;
+ tmpbuf[tmplen++] = '*';
+
+ InputBuf[0] = '\0';
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ searchdir = dir;
+
+ c_insert(2); /* prompt + '\n' */
+ *Cursor++ = '\n';
+ *Cursor++ = dir == F_UP_SEARCH_HIST ? '?' : '/';
+ Refresh();
+ for (ch = 0;ch == 0;) {
+ if (GetNextChar(&ch) != 1)
+ return(e_send_eof(0));
+ switch (ASC(ch)) {
+ case 0010: /* Delete and backspace */
+ case 0177:
+ if (tmplen > 1) {
+ *Cursor-- = '\0';
+ LastChar = Cursor;
+ tmpbuf[tmplen--] = '\0';
+ }
+ else {
+ copyn(InputBuf, oldbuf, INBUFSIZE);
+ LastChar = oldlc;
+ Cursor = oldc;
+ return(CC_REFRESH);
+ }
+ Refresh();
+ ch = 0;
+ break;
+
+ case 0033: /* ESC */
+#ifndef _OSD_POSIX
+ case '\r': /* Newline */
+ case '\n':
+#else
+ case '\012': /* Newline */
+ case '\015': /* Return */
+#endif
+ break;
+
+ default:
+ if (tmplen >= INBUFSIZE)
+ SoundBeep();
+ else {
+ tmpbuf[tmplen++] = ch;
+ *Cursor++ = ch;
+ LastChar = Cursor;
+ }
+ Refresh();
+ ch = 0;
+ break;
+ }
+ }
+
+ if (tmplen == 1) {
+ /*
+ * Use the old pattern, but wild-card it.
+ */
+ if (patlen == 0) {
+ InputBuf[0] = '\0';
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ Refresh();
+ return(CC_ERROR);
+ }
+ if (patbuf[0] != '*') {
+ (void) Strcpy(tmpbuf, patbuf);
+ patbuf[0] = '*';
+ (void) Strcpy(&patbuf[1], tmpbuf);
+ patlen++;
+ patbuf[patlen++] = '*';
+ patbuf[patlen] = '\0';
+ }
+ }
+ else {
+ tmpbuf[tmplen++] = '*';
+ tmpbuf[tmplen] = '\0';
+ (void) Strcpy(patbuf, tmpbuf);
+ patlen = tmplen;
+ }
+ LastCmd = (KEYCMD) dir; /* avoid c_hsetpat */
+ Cursor = LastChar = InputBuf;
+ if ((dir == F_UP_SEARCH_HIST ? e_up_search_hist(0) :
+ e_down_search_hist(0)) == CC_ERROR) {
+ Refresh();
+ return(CC_ERROR);
+ }
+ else {
+ if (ch == 0033) {
+ Refresh();
+ *LastChar++ = '\n';
+ *LastChar = '\0';
+ PastBottom();
+ return(CC_NEWLINE);
+ }
+ else
+ return(CC_REFRESH);
+ }
+}
+
+/*
+ * semi-PUBLIC routines. Any routine that is of type CCRETVAL is an
+ * entry point, called from the CcKeyMap indirected into the
+ * CcFuncTbl array.
+ */
+
+/*ARGSUSED*/
+CCRETVAL
+v_cmd_mode(c)
+ int c;
+{
+ USE(c);
+ InsertPos = 0;
+ ActionFlag = TCSHOP_NOP; /* [Esc] cancels pending action */
+ ActionPos = 0;
+ DoingArg = 0;
+ if (UndoPtr > Cursor)
+ UndoSize = (int)(UndoPtr - Cursor);
+ else
+ UndoSize = (int)(Cursor - UndoPtr);
+
+ inputmode = MODE_INSERT;
+ c_alternativ_key_map(1);
+#ifdef notdef
+ /*
+ * We don't want to move the cursor, because all the editing
+ * commands don't include the character under the cursor.
+ */
+ if (Cursor > InputBuf)
+ Cursor--;
+#endif
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_unassigned(c)
+ int c;
+{ /* bound to keys that arn't really assigned */
+ USE(c);
+ SoundBeep();
+ flush();
+ return(CC_NORM);
+}
+
+CCRETVAL
+e_insert(c)
+ register int c;
+{
+ register int i;
+#if defined(DSPMBYTE)
+ CCRETVAL ret;
+ static Char savec;
+ static int exterr = 0;
+#endif
+#ifndef SHORT_STRINGS
+ c &= ASCII; /* no meta chars ever */
+#endif
+#if defined(DSPMBYTE)
+ ret = (CCRETVAL) CC_NORM;
+#endif
+
+ if (!c)
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (LastChar + Argument >= InputLim)
+ return(CC_ERROR); /* end of buffer space */
+
+ if (Argument == 1) { /* How was this optimized ???? */
+
+#if defined(DSPMBYTE)
+ if(_enable_mbdisp && extins && exterr && Ismbyte2(c)) {
+ extins = 0;
+ exterr = 0;
+ return(CC_ERROR);
+ }
+#endif
+ if (inputmode != MODE_INSERT) {
+ UndoBuf[UndoSize++] = *Cursor;
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(1); /* Do NOT use the saving ONE */
+ }
+
+ c_insert(1);
+
+#if defined(DSPMBYTE)
+ /* 1st. byte is store to special buffer, and replace space */
+ if(_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
+ extins++;
+ savec = (Char) c;
+ *Cursor++ = (Char) ' ';
+ }
+ else if (_enable_mbdisp && extins && Ismbyte2(c)) {
+ *(Cursor-1) = savec;
+ *Cursor++ = (Char) c;
+ extins = 0;
+ e_redisp(1);
+ Refresh();
+ ret = CC_REFRESH;
+ }
+ else
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ if (ret != CC_REFRESH)
+ RefPlusOne(); /* fast refresh for one char. */
+#else
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ RefPlusOne(); /* fast refresh for one char. */
+#endif
+ }
+ else {
+#if defined(DSPMBYTE)
+ /* Cannot use ESC-(number) for multi-byte */
+ if (_enable_mbdisp && extins == 0 && Ismbyte1(c)) {
+ extins++;
+ exterr++;
+ return(CC_ERROR);
+ }
+ else if (_enable_mbdisp && extins && exterr && Ismbyte2(c))
+ {
+ extins = 0;
+ exterr = 0;
+ return(CC_ERROR);
+ }
+#endif
+ if (inputmode != MODE_INSERT) {
+
+ for(i=0;i<Argument;i++)
+ UndoBuf[UndoSize++] = *(Cursor+i);
+
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(Argument); /* Do NOT use the saving ONE */
+ }
+
+ c_insert(Argument);
+
+ while (Argument--)
+ *Cursor++ = (Char) c;
+ Refresh();
+ }
+
+ if (inputmode == MODE_REPLACE_1)
+ (void) v_cmd_mode(0);
+
+#if defined(DSPMBYTE)
+ return(ret);
+#else
+ return(CC_NORM);
+#endif
+}
+
+int
+InsertStr(s) /* insert ASCIZ s at cursor (for complete) */
+ Char *s;
+{
+ register int len;
+
+ if ((len = (int) Strlen(s)) <= 0)
+ return -1;
+ if (LastChar + len >= InputLim)
+ return -1; /* end of buffer space */
+
+ c_insert(len);
+ while (len--)
+ *Cursor++ = *s++;
+ return 0;
+}
+
+void
+DeleteBack(n) /* delete the n characters before . */
+ int n;
+{
+ if (n <= 0)
+ return;
+ if (Cursor >= &InputBuf[n]) {
+ c_delbefore(n); /* delete before dot */
+ if (n > Cursor - InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ else
+ Cursor -= n;
+#if defined(DSPMBYTE)
+ if(_enable_mbdisp && extdel && Cursor > InputBuf) {
+ Cursor--;
+ e_redisp(1);
+ }
+#endif
+ }
+}
+
+CCRETVAL
+e_digit(c) /* gray magic here */
+ register int c;
+{
+ if (!Isdigit(c))
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (LastCmd == F_ARGFOUR) /* if last command was ^U */
+ Argument = c - '0';
+ else {
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ }
+ return(CC_ARGHACK);
+ }
+ else {
+ if (LastChar + 1 >= InputLim)
+ return CC_ERROR; /* end of buffer space */
+
+ if (inputmode != MODE_INSERT) {
+ UndoBuf[UndoSize++] = *Cursor;
+ UndoBuf[UndoSize] = '\0';
+ c_delafter(1); /* Do NOT use the saving ONE */
+ }
+ c_insert(1);
+ *Cursor++ = (Char) c;
+ DoingArg = 0; /* just in case */
+ RefPlusOne(); /* fast refresh for one char. */
+ }
+ return(CC_NORM);
+}
+
+CCRETVAL
+e_argdigit(c) /* for ESC-n */
+ register int c;
+{
+ c &= ASCII;
+
+ if (!Isdigit(c))
+ return(CC_ERROR); /* no NULs in the input ever!! */
+
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ }
+ else { /* else starting an argument */
+ Argument = c - '0';
+ DoingArg = 1;
+ }
+ return(CC_ARGHACK);
+}
+
+CCRETVAL
+v_zero(c) /* command mode 0 for vi */
+ register int c;
+{
+ if (DoingArg) { /* if doing an arg, add this in... */
+ if (Argument > 1000000)
+ return CC_ERROR;
+ Argument = (Argument * 10) + (c - '0');
+ return(CC_ARGHACK);
+ }
+ else { /* else starting an argument */
+ Cursor = InputBuf;
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_newline(c)
+ int c;
+{ /* always ignore argument */
+ USE(c);
+ /* PastBottom(); NOW done in ed.inputl.c */
+ *LastChar++ = '\n'; /* for the benefit of CSH */
+ *LastChar = '\0'; /* just in case */
+ if (VImode)
+ InsertPos = InputBuf; /* Reset editing position */
+ return(CC_NEWLINE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_send_eof(c)
+ int c;
+{ /* for when ^D is ONLY send-eof */
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_EOF);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_back(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_BACK);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_fwd(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_FWD);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_complete_all(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE_ALL);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_cm_complete(c)
+ int c;
+{
+ USE(c);
+ if (Cursor < LastChar)
+ Cursor++;
+ *LastChar = '\0'; /* just in case */
+ return(CC_COMPLETE);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_toggle_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num <= 0) {
+ return CC_ERROR;
+ }
+
+ hp = Histlist.Hnext;
+ if (hp == NULL) { /* this is only if no history */
+ return(CC_ERROR);
+ }
+
+ for (h = 1; h < Hist_num; h++)
+ hp = hp->Hnext;
+
+ if (!CurrentHistLit) {
+ if (hp->histline) {
+ copyn(InputBuf, hp->histline, INBUFSIZE);
+ CurrentHistLit = 1;
+ }
+ else {
+ return CC_ERROR;
+ }
+ }
+ else {
+ (void) sprlex(InputBuf, sizeof(InputBuf), &hp->Hlex);
+ CurrentHistLit = 0;
+ }
+
+ LastChar = InputBuf + Strlen(InputBuf);
+ if (LastChar > InputBuf) {
+ if (LastChar[-1] == '\n')
+ LastChar--;
+ if (LastChar[-1] == ' ')
+ LastChar--;
+ if (LastChar < InputBuf)
+ LastChar = InputBuf;
+ }
+
+#ifdef KSHVI
+ if (VImode)
+ Cursor = InputBuf;
+ else
+#endif /* KSHVI */
+ Cursor = LastChar;
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_up_hist(c)
+ int c;
+{
+ Char beep = 0;
+
+ USE(c);
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num == 0) { /* save the current buffer away */
+ copyn(HistBuf, InputBuf, INBUFSIZE);
+ LastHist = HistBuf + (LastChar - InputBuf);
+ }
+
+ Hist_num += Argument;
+
+ if (c_get_histline() == CC_ERROR) {
+ beep = 1;
+ (void) c_get_histline(); /* Hist_num was fixed by first call */
+ }
+
+ Refresh();
+ if (beep)
+ return(CC_ERROR);
+ else
+ return(CC_NORM); /* was CC_UP_HIST */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_down_hist(c)
+ int c;
+{
+ USE(c);
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ Hist_num -= Argument;
+
+ if (Hist_num < 0) {
+ Hist_num = 0;
+ return(CC_ERROR); /* make it beep */
+ }
+
+ return(c_get_histline());
+}
+
+
+
+/*
+ * c_hmatch() return True if the pattern matches the prefix
+ */
+static int
+c_hmatch(str)
+Char *str;
+{
+ if (Strncmp(patbuf, str, (size_t) patlen) == 0)
+ return 1;
+ return Gmatch(str, patbuf);
+}
+
+/*
+ * c_hsetpat(): Set the history seatch pattern
+ */
+static void
+c_hsetpat()
+{
+ if (LastCmd != F_UP_SEARCH_HIST && LastCmd != F_DOWN_SEARCH_HIST) {
+ patlen = (int) (Cursor - InputBuf);
+ if (patlen >= INBUFSIZE) patlen = INBUFSIZE -1;
+ if (patlen >= 0) {
+ (void) Strncpy(patbuf, InputBuf, (size_t) patlen);
+ patbuf[patlen] = '\0';
+ }
+ else
+ patlen = (int) Strlen(patbuf);
+ }
+#ifdef SDEBUG
+ xprintf("\nHist_num = %d\n", Hist_num);
+ xprintf("patlen = %d\n", patlen);
+ xprintf("patbuf = \"%S\"\n", patbuf);
+ xprintf("Cursor %d LastChar %d\n", Cursor - InputBuf, LastChar - InputBuf);
+#endif
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_up_search_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+ bool found = 0;
+
+ USE(c);
+ ActionFlag = TCSHOP_NOP;
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+ if (Hist_num < 0) {
+#ifdef DEBUG_EDIT
+ xprintf("%s: e_up_search_hist(): Hist_num < 0; resetting.\n", progname);
+#endif
+ Hist_num = 0;
+ return(CC_ERROR);
+ }
+
+ if (Hist_num == 0)
+ {
+ copyn(HistBuf, InputBuf, INBUFSIZE);
+ LastHist = HistBuf + (LastChar - InputBuf);
+ }
+
+
+ hp = Histlist.Hnext;
+ if (hp == NULL)
+ return(CC_ERROR);
+
+ c_hsetpat(); /* Set search pattern !! */
+
+ for (h = 1; h <= Hist_num; h++)
+ hp = hp->Hnext;
+
+ while (hp != NULL) {
+ Char sbuf[INBUFSIZE], *hl;
+ if (hp->histline == NULL) {
+ hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex));
+ }
+ hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex);
+#ifdef SDEBUG
+ xprintf("Comparing with \"%S\"\n", hl);
+#endif
+ if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
+ hl[LastChar-InputBuf]) && c_hmatch(hl)) {
+ found++;
+ break;
+ }
+ h++;
+ hp = hp->Hnext;
+ }
+
+ if (!found) {
+#ifdef SDEBUG
+ xprintf("not found\n");
+#endif
+ return(CC_ERROR);
+ }
+
+ Hist_num = h;
+
+ return(c_get_histline());
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_down_search_hist(c)
+ int c;
+{
+ struct Hist *hp;
+ int h;
+ bool found = 0;
+
+ USE(c);
+ ActionFlag = TCSHOP_NOP;
+ UndoAction = TCSHOP_NOP;
+ *LastChar = '\0'; /* just in case */
+
+ if (Hist_num == 0)
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ if (hp == 0)
+ return(CC_ERROR);
+
+ c_hsetpat(); /* Set search pattern !! */
+
+ for (h = 1; h < Hist_num && hp; h++) {
+ Char sbuf[INBUFSIZE], *hl;
+ if (hp->histline == NULL) {
+ hp->histline = Strsave(sprlex(sbuf, sizeof(sbuf), &hp->Hlex));
+ }
+ hl = HistLit ? hp->histline : sprlex(sbuf, sizeof(sbuf), &hp->Hlex);
+#ifdef SDEBUG
+ xprintf("Comparing with \"%S\"\n", hl);
+#endif
+ if ((Strncmp(hl, InputBuf, (size_t) (LastChar - InputBuf)) ||
+ hl[LastChar-InputBuf]) && c_hmatch(hl))
+ found = h;
+ hp = hp->Hnext;
+ }
+
+ if (!found) { /* is it the current history number? */
+ if (!c_hmatch(HistBuf)) {
+#ifdef SDEBUG
+ xprintf("not found\n");
+#endif
+ return(CC_ERROR);
+ }
+ }
+
+ Hist_num = found;
+
+ return(c_get_histline());
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_helpme(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_HELPME);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_correct(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_CORRECT);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_correctl(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_CORRECT_L);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_run_fg_editor(c)
+ int c;
+{
+ register struct process *pp;
+ extern bool tellwhat;
+
+ USE(c);
+ if ((pp = find_stop_ed()) != NULL) {
+ /* save our editor state so we can restore it */
+ tellwhat = 1;
+ copyn(WhichBuf, InputBuf, INBUFSIZE);
+ LastWhich = WhichBuf + (LastChar - InputBuf);
+ CursWhich = WhichBuf + (Cursor - InputBuf);
+ HistWhich = Hist_num;
+ Hist_num = 0; /* for the history commands */
+
+ /* put the tty in a sane mode */
+ PastBottom();
+ (void) Cookedmode(); /* make sure the tty is set up correctly */
+
+ /* do it! */
+ fg_proc_entry(pp);
+
+ (void) Rawmode(); /* go on */
+ Refresh();
+ tellwhat = 0;
+ }
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_choices(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_all(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_ALL);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_glob(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_GLOB);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_glob(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_EXPAND_GLOB);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_normalize_path(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_NORMALIZE_PATH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_normalize_command(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_NORMALIZE_COMMAND);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_vars(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ return(CC_EXPAND_VARS);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_which(c)
+ int c;
+{ /* do a fast command line which(1) */
+ USE(c);
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_WHICH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_last_item(c)
+ int c;
+{ /* insert the last element of the prev. cmd */
+ register Char *cp;
+ register struct Hist *hp;
+ register struct wordent *wp, *firstp;
+ register int i;
+ Char buf[INBUFSIZE];
+
+ USE(c);
+ if (Argument <= 0)
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ if (hp == NULL) { /* this is only if no history */
+ return(CC_ERROR);
+ }
+
+ wp = (hp->Hlex).prev;
+
+ if (wp->prev == (struct wordent *) NULL)
+ return(CC_ERROR); /* an empty history entry */
+
+ firstp = (hp->Hlex).next;
+
+ /* back up arg words in lex */
+ for (i = 0; i < Argument && wp != firstp; i++) {
+ wp = wp->prev;
+ }
+
+ cp = expand_lex(buf, INBUFSIZE, wp->prev, 0, i - 1);
+ *cp = '\0';
+ if (InsertStr(buf))
+ return(CC_ERROR);
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_dabbrev_expand(c)
+ int c;
+{ /* expand to preceding word matching prefix */
+ register Char *cp, *ncp, *bp;
+ register struct Hist *hp;
+ register int arg = 0, len = 0, i; /* len = 0 to shut up gcc -Wall */
+ register bool found = 0;
+ Char hbuf[INBUFSIZE];
+ static int oldevent, hist, word;
+ static Char *start, *oldcursor;
+
+ USE(c);
+ if (Argument <= 0)
+ return(CC_ERROR);
+
+ cp = c_preword(Cursor, InputBuf, 1);
+ if (cp == Cursor || Isspace(*cp))
+ return(CC_ERROR);
+
+ hp = Histlist.Hnext;
+ bp = InputBuf;
+ if (Argument == 1 && eventno == oldevent && cp == start &&
+ Cursor == oldcursor && patlen > 0 && Strncmp(patbuf, cp, patlen) == 0){
+ /* continue previous search - go to last match (hist/word) */
+ if (hist != 0) { /* need to move up history */
+ for (i = 1; i < hist && hp != NULL; i++)
+ hp = hp->Hnext;
+ if (hp == NULL) /* "can't happen" */
+ return(CC_ERROR);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ *cp = '\0';
+ bp = hbuf;
+ hp = hp->Hnext;
+ }
+ cp = c_preword(cp, bp, word);
+ } else { /* starting new search */
+ oldevent = eventno;
+ start = cp;
+ patlen = (int) (Cursor - cp);
+ (void) Strncpy(patbuf, cp, patlen);
+ hist = 0;
+ word = 0;
+ }
+
+ while (!found) {
+ ncp = c_preword(cp, bp, 1);
+ if (ncp == cp || Isspace(*ncp)) { /* beginning of line */
+ hist++;
+ word = 0;
+ if (hp == NULL)
+ return(CC_ERROR);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ *cp = '\0';
+ bp = hbuf;
+ hp = hp->Hnext;
+ continue;
+ } else {
+ word++;
+ len = (int) (c_endword(ncp-1, cp, 1) - ncp + 1);
+ cp = ncp;
+ }
+ if (len > patlen && Strncmp(cp, patbuf, patlen) == 0) {
+ /* We don't fully check distinct matches as Gnuemacs does: */
+ if (Argument > 1) { /* just count matches */
+ if (++arg >= Argument)
+ found++;
+ } else { /* match if distinct from previous */
+ if (len != Cursor - start || Strncmp(cp, start, len) != 0)
+ found++;
+ }
+ }
+ }
+
+ if (LastChar + len - (Cursor - start) >= InputLim)
+ return(CC_ERROR); /* no room */
+ DeleteBack(Cursor - start);
+ c_insert(len);
+ while (len--)
+ *Cursor++ = *cp++;
+ oldcursor = Cursor;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_yank_kill(c)
+ int c;
+{ /* almost like GnuEmacs */
+ register Char *kp, *cp;
+
+ USE(c);
+ if (LastKill == KillBuf) /* if zero content */
+ return(CC_ERROR);
+
+ if (LastChar + (LastKill - KillBuf) >= InputLim)
+ return(CC_ERROR); /* end of buffer space */
+
+ /* else */
+ Mark = Cursor; /* set the mark */
+ cp = Cursor; /* for speed */
+
+ c_insert((int)(LastKill - KillBuf)); /* open the space, */
+ for (kp = KillBuf; kp < LastKill; kp++) /* copy the chars */
+ *cp++ = *kp;
+
+ if (Argument == 1) /* if an arg, cursor at beginning */
+ Cursor = cp; /* else cursor at end */
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_delprev(c) /* Backspace key in insert mode */
+ int c;
+{
+ int rc;
+
+ USE(c);
+ rc = CC_ERROR;
+
+ if (InsertPos != 0) {
+ if (Argument <= Cursor - InsertPos) {
+ c_delbefore(Argument); /* delete before */
+ Cursor -= Argument;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel) {
+ Cursor--;
+ e_redisp(c);
+ }
+#endif
+ rc = CC_REFRESH;
+ }
+ }
+ return(rc);
+} /* v_delprev */
+
+/*ARGSUSED*/
+CCRETVAL
+e_delprev(c)
+ int c;
+{
+ USE(c);
+ if (Cursor > InputBuf) {
+ c_delbefore(Argument); /* delete before dot */
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ else
+ Cursor -= Argument;
+#if defined(DSPMBYTE)
+ if (_enable_mbdisp && extdel && Cursor > InputBuf) {
+ Cursor--;
+ e_redisp(c);
+ }
+#endif
+ return(CC_REFRESH);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delwordprev(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ cp = c_prev_word(Cursor, InputBuf, Argument);
+
+ for (p = cp, kp = KillBuf; p < Cursor; p++) /* save the text */
+ *kp++ = *p;
+ LastKill = kp;
+
+ c_delbefore((int)(Cursor - cp)); /* delete before dot */
+ Cursor = cp;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/* DCS <dcs@neutron.chem.yale.edu>, 9 Oct 93
+ *
+ * Changed the names of some of the ^D family of editor functions to
+ * correspond to what they actually do and created new e_delnext_list
+ * for completeness.
+ *
+ * Old names: New names:
+ *
+ * delete-char delete-char-or-eof
+ * F_DELNEXT F_DELNEXT_EOF
+ * e_delnext e_delnext_eof
+ * edelnxt edelnxteof
+ * delete-char-or-eof delete-char
+ * F_DELNEXT_EOF F_DELNEXT
+ * e_delnext_eof e_delnext
+ * edelnxteof edelnxt
+ * delete-char-or-list delete-char-or-list-or-eof
+ * F_LIST_DELNEXT F_DELNEXT_LIST_EOF
+ * e_list_delnext e_delnext_list_eof
+ * edellsteof
+ * (no old equivalent) delete-char-or-list
+ * F_DELNEXT_LIST
+ * e_delnext_list
+ * e_delnxtlst
+ */
+
+/* added by mtk@ari.ncl.omron.co.jp (920818) */
+/* rename e_delnext() -> e_delnext_eof() */
+/*ARGSUSED*/
+CCRETVAL
+e_delnext(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) {/* if I'm at the end */
+ if (!VImode) {
+ return(CC_ERROR);
+ }
+ else {
+ if (Cursor != InputBuf)
+ Cursor--;
+ else
+ return(CC_ERROR);
+ }
+ }
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_eof(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) {/* if I'm at the end */
+ if (!VImode) {
+ if (Cursor == InputBuf) {
+ /* if I'm also at the beginning */
+ so_write(STReof, 4);/* then do a EOF */
+ flush();
+ return(CC_EOF);
+ }
+ else
+ return(CC_ERROR);
+ }
+ else {
+ if (Cursor != InputBuf)
+ Cursor--;
+ else
+ return(CC_ERROR);
+ }
+ }
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_list(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) { /* if I'm at the end */
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+ }
+ else {
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delnext_list_eof(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar) { /* if I'm at the end */
+ if (Cursor == InputBuf) { /* if I'm also at the beginning */
+ so_write(STReof, 4);/* then do a EOF */
+ flush();
+ return(CC_EOF);
+ }
+ else {
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ return(CC_LIST_CHOICES);
+ }
+ }
+ else {
+ c_delafter(Argument); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_list_eof(c)
+ int c;
+{
+ CCRETVAL rv;
+
+ USE(c);
+ if (Cursor == LastChar && Cursor == InputBuf) {
+ so_write(STReof, 4); /* then do a EOF */
+ flush();
+ rv = CC_EOF;
+ }
+ else {
+ PastBottom();
+ *LastChar = '\0'; /* just in case */
+ rv = CC_LIST_CHOICES;
+ }
+ return rv;
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_delwordnext(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ cp = c_next_word(Cursor, LastChar, Argument);
+
+ for (p = Cursor, kp = KillBuf; p < cp; p++) /* save the text */
+ *kp++ = *p;
+ LastKill = kp;
+
+ c_delafter((int)(cp - Cursor)); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_toend(c)
+ int c;
+{
+ USE(c);
+ Cursor = LastChar;
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tobeg(c)
+ int c;
+{
+ USE(c);
+ Cursor = InputBuf;
+
+ if (VImode) {
+ while (Isspace(*Cursor)) /* We want FIRST non space character */
+ Cursor++;
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ }
+
+ RefCursor(); /* move the cursor */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killend(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < LastChar)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ LastChar = Cursor; /* zap! -- delete to end */
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_killbeg(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = InputBuf;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delbefore((int)(Cursor - InputBuf));
+ Cursor = InputBuf; /* zap! */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killall(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ cp = InputBuf;
+ kp = KillBuf;
+ while (cp < LastChar)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ LastChar = InputBuf; /* zap! -- delete all of it */
+ Cursor = InputBuf;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_killregion(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ if (!Mark)
+ return(CC_ERROR);
+
+ if (Mark > Cursor) {
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < Mark)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delafter((int)(cp - Cursor)); /* delete it - UNUSED BY VI mode */
+ }
+ else { /* mark is before cursor */
+ cp = Mark;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ c_delbefore((int)(cp - Mark));
+ Cursor = Mark;
+ }
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_copyregion(c)
+ int c;
+{
+ register Char *kp, *cp;
+
+ USE(c);
+ if (!Mark)
+ return(CC_ERROR);
+
+ if (Mark > Cursor) {
+ cp = Cursor;
+ kp = KillBuf;
+ while (cp < Mark)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ }
+ else { /* mark is before cursor */
+ cp = Mark;
+ kp = KillBuf;
+ while (cp < Cursor)
+ *kp++ = *cp++; /* copy it */
+ LastKill = kp;
+ }
+ return(CC_NORM); /* don't even need to Refresh() */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_charswitch(cc)
+ int cc;
+{
+ register Char c;
+
+ USE(cc);
+
+ /* do nothing if we are at beginning of line or have only one char */
+ if (Cursor == &InputBuf[0] || LastChar == &InputBuf[1]) {
+ return(CC_ERROR);
+ }
+
+ if (Cursor < LastChar) {
+ Cursor++;
+ }
+ c = Cursor[-2];
+ Cursor[-2] = Cursor[-1];
+ Cursor[-1] = c;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_gcharswitch(cc)
+ int cc;
+{ /* gosmacs style ^T */
+ register Char c;
+
+ USE(cc);
+ if (Cursor > &InputBuf[1]) {/* must have at least two chars entered */
+ c = Cursor[-2];
+ Cursor[-2] = Cursor[-1];
+ Cursor[-1] = c;
+ return(CC_REFRESH);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+/*ARGSUSED*/
+static void
+e_charback_mbyte(argument)
+ int argument;
+{
+ if (!_enable_mbdisp) {
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf;
+ else
+ Cursor -= Argument;
+ }
+ else {
+ while (0 < argument && Cursor > InputBuf) {
+ if (Cursor - 1 != InputBuf &&
+ Ismbyte1(*(Cursor - 2)) && Ismbyte2(*(Cursor - 1))) {
+ Cursor--;
+ }
+ Cursor--;
+ argument--;
+ }
+ }
+}
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+e_charback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor > InputBuf) {
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+ e_charback_mbyte(Argument);
+#else
+ if (Argument > Cursor - InputBuf)
+ Cursor = InputBuf;
+ else
+ Cursor -= Argument;
+#endif
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_preword(Cursor, InputBuf, Argument); /* bounds check */
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_wordback(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_prev_word(Cursor, InputBuf, Argument); /* bounds check */
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+/*ARGSUSED*/
+static void
+e_charfwd_mbyte(argument)
+ int argument;
+{
+ if (!_enable_mbdisp)
+ Cursor += argument;
+ else
+ while (0 < argument && Cursor < LastChar) {
+ if (Cursor + 1 != LastChar &&
+ Ismbyte1(*Cursor) && Ismbyte2(*(Cursor + 1))) {
+ Cursor++;
+ }
+ Cursor++;
+ argument--;
+ }
+}
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+e_charfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor < LastChar) {
+#if defined(DSPMBYTE) /* BY TAGA Nayuta VERY THANKS */
+ e_charfwd_mbyte(Argument);
+#else
+ Cursor += Argument;
+#endif
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+ }
+ else {
+ return(CC_ERROR);
+ }
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_wordfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_next_word(Cursor, LastChar, Argument);
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordfwd(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_nexword(Cursor, LastChar, Argument);
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_wordbegnext(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_next_word(Cursor, LastChar, Argument);
+ if (Cursor < LastChar)
+ Cursor++;
+
+ if (VImode)
+ if (ActionFlag & TCSHOP_DELETE) {
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+static CCRETVAL
+v_repeat_srch(c)
+ int c;
+{
+ CCRETVAL rv = CC_ERROR;
+#ifdef SDEBUG
+ xprintf("dir %d patlen %d patbuf %S\n",
+ c, patlen, patbuf);
+#endif
+
+ LastCmd = (KEYCMD) c; /* Hack to stop c_hsetpat */
+ LastChar = InputBuf;
+ switch (c) {
+ case F_DOWN_SEARCH_HIST:
+ rv = e_down_search_hist(0);
+ break;
+ case F_UP_SEARCH_HIST:
+ rv = e_up_search_hist(0);
+ break;
+ default:
+ break;
+ }
+ return rv;
+}
+
+static CCRETVAL
+v_csearch_back(ch, count, tflag)
+ int ch, count, tflag;
+{
+ Char *cp;
+
+ cp = Cursor;
+ while (count--) {
+ if (*cp == ch)
+ cp--;
+ while (cp > InputBuf && *cp != ch)
+ cp--;
+ }
+
+ if (cp < InputBuf || (cp == InputBuf && *cp != ch))
+ return(CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp++;
+
+ Cursor = cp;
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+static CCRETVAL
+v_csearch_fwd(ch, count, tflag)
+ int ch, count, tflag;
+{
+ Char *cp;
+
+ cp = Cursor;
+ while (count--) {
+ if(*cp == ch)
+ cp++;
+ while (cp < LastChar && *cp != ch)
+ cp++;
+ }
+
+ if (cp >= LastChar)
+ return(CC_ERROR);
+
+ if (*cp == ch && tflag)
+ cp--;
+
+ Cursor = cp;
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+static CCRETVAL
+v_action(c)
+ int c;
+{
+ register Char *cp, *kp;
+
+ if (ActionFlag == TCSHOP_DELETE) {
+ ActionFlag = TCSHOP_NOP;
+ ActionPos = 0;
+
+ UndoSize = 0;
+ kp = UndoBuf;
+ for (cp = InputBuf; cp < LastChar; cp++) {
+ *kp++ = *cp;
+ UndoSize++;
+ }
+
+ UndoAction = TCSHOP_INSERT;
+ UndoPtr = InputBuf;
+ LastChar = InputBuf;
+ Cursor = InputBuf;
+ if (c & TCSHOP_INSERT)
+ c_alternativ_key_map(0);
+
+ return(CC_REFRESH);
+ }
+#ifdef notdef
+ else if (ActionFlag == TCSHOP_NOP) {
+#endif
+ ActionPos = Cursor;
+ ActionFlag = c;
+ return(CC_ARGHACK); /* Do NOT clear out argument */
+#ifdef notdef
+ }
+ else {
+ ActionFlag = 0;
+ ActionPos = 0;
+ return(CC_ERROR);
+ }
+#endif
+}
+
+#ifdef COMMENT
+/* by: Brian Allison <uiucdcs!convex!allison@RUTGERS.EDU> */
+static void
+c_get_word(begin, end)
+ Char **begin;
+ Char **end;
+{
+ Char *cp;
+
+ cp = &Cursor[0];
+ while (Argument--) {
+ while ((cp <= LastChar) && (isword(*cp)))
+ cp++;
+ *end = --cp;
+ while ((cp >= InputBuf) && (isword(*cp)))
+ cp--;
+ *begin = ++cp;
+ }
+}
+#endif /* COMMENT */
+
+/*ARGSUSED*/
+CCRETVAL
+e_uppercase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ for (cp = Cursor; cp < end; cp++) /* PWP: was cp=begin */
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_capitolcase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ cp = Cursor;
+ for (; cp < end; cp++) {
+ if (Isalpha(*cp)) {
+ if (Islower(*cp))
+ *cp = Toupper(*cp);
+ cp++;
+ break;
+ }
+ }
+ for (; cp < end; cp++)
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_lowercase(c)
+ int c;
+{
+ Char *cp, *end;
+
+ USE(c);
+ end = c_next_word(Cursor, LastChar, Argument);
+
+ for (cp = Cursor; cp < end; cp++)
+ if (Isupper(*cp))
+ *cp = Tolower(*cp);
+
+ Cursor = end;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return(CC_REFRESH);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_set_mark(c)
+ int c;
+{
+ USE(c);
+ Mark = Cursor;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_exchange_mark(c)
+ int c;
+{
+ register Char *cp;
+
+ USE(c);
+ cp = Cursor;
+ Cursor = Mark;
+ Mark = cp;
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_argfour(c)
+ int c;
+{ /* multiply current argument by 4 */
+ USE(c);
+ if (Argument > 1000000)
+ return CC_ERROR;
+ DoingArg = 1;
+ Argument *= 4;
+ return(CC_ARGHACK);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_quote(c)
+ int c;
+{
+ Char ch;
+ int num;
+
+ USE(c);
+ QuoteModeOn();
+ num = GetNextChar(&ch);
+ QuoteModeOff();
+ if (num == 1)
+ return e_insert(ch);
+ else
+ return e_send_eof(0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_metanext(c)
+ int c;
+{
+ USE(c);
+ MetaNext = 1;
+ return(CC_ARGHACK); /* preserve argument */
+}
+
+#ifdef notdef
+/*ARGSUSED*/
+CCRETVAL
+e_extendnext(c)
+ int c;
+{
+ CurrentKeyMap = CcAltMap;
+ return(CC_ARGHACK); /* preserve argument */
+}
+
+#endif
+
+/*ARGSUSED*/
+CCRETVAL
+v_insbeg(c)
+ int c;
+{ /* move to beginning of line and start vi
+ * insert mode */
+ USE(c);
+ Cursor = InputBuf;
+ InsertPos = Cursor;
+
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ RefCursor(); /* move the cursor */
+ c_alternativ_key_map(0);
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_replone(c)
+ int c;
+{ /* vi mode overwrite one character */
+ USE(c);
+ c_alternativ_key_map(0);
+ inputmode = MODE_REPLACE_1;
+ UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
+ UndoPtr = Cursor;
+ UndoSize = 0;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_replmode(c)
+ int c;
+{ /* vi mode start overwriting */
+ USE(c);
+ c_alternativ_key_map(0);
+ inputmode = MODE_REPLACE;
+ UndoAction = TCSHOP_CHANGE; /* Set Up for VI undo command */
+ UndoPtr = Cursor;
+ UndoSize = 0;
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_substchar(c)
+ int c;
+{ /* vi mode substitute for one char */
+ USE(c);
+ c_delafter(Argument);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_substline(c)
+ int c;
+{ /* vi mode replace whole line */
+ USE(c);
+ (void) e_killall(0);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_chgtoend(c)
+ int c;
+{ /* vi mode change to end of line */
+ USE(c);
+ (void) e_killend(0);
+ c_alternativ_key_map(0);
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_insert(c)
+ int c;
+{ /* vi mode start inserting */
+ USE(c);
+ c_alternativ_key_map(0);
+
+ InsertPos = Cursor;
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_add(c)
+ int c;
+{ /* vi mode start adding */
+ USE(c);
+ c_alternativ_key_map(0);
+ if (Cursor < LastChar)
+ {
+ Cursor++;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ RefCursor();
+ }
+
+ InsertPos = Cursor;
+ UndoPtr = Cursor;
+ UndoAction = TCSHOP_DELETE;
+
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_addend(c)
+ int c;
+{ /* vi mode to add at end of line */
+ USE(c);
+ c_alternativ_key_map(0);
+ Cursor = LastChar;
+
+ InsertPos = LastChar; /* Mark where insertion begins */
+ UndoPtr = LastChar;
+ UndoAction = TCSHOP_DELETE;
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_change_case(cc)
+ int cc;
+{
+ char c;
+
+ USE(cc);
+ if (Cursor < LastChar) {
+#ifndef WINNT
+ c = *Cursor;
+#else
+ c = CHAR & *Cursor;
+#endif /* WINNT */
+ if (Isupper(c))
+ *Cursor++ = Tolower(c);
+ else if (Islower(c))
+ *Cursor++ = Toupper(c);
+ else
+ Cursor++;
+ RefPlusOne(); /* fast refresh for one char */
+ return(CC_NORM);
+ }
+ return(CC_ERROR);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand(c)
+ int c;
+{
+ register Char *p;
+ extern bool justpr;
+
+ USE(c);
+ for (p = InputBuf; Isspace(*p); p++)
+ continue;
+ if (p == LastChar)
+ return(CC_ERROR);
+
+ justpr++;
+ Expand++;
+ return(e_newline(0));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_startover(c)
+ int c;
+{ /* erase all of current line, start again */
+ USE(c);
+ ResetInLine(0); /* reset the input pointers */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_redisp(c)
+ int c;
+{
+ USE(c);
+ ClearLines();
+ ClearDisp();
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_cleardisp(c)
+ int c;
+{
+ USE(c);
+ ClearScreen(); /* clear the whole real screen */
+ ClearDisp(); /* reset everything */
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_int(c)
+ int c;
+{
+ USE(c);
+#if defined(_MINIX) || defined(WINNT)
+ /* SAK PATCH: erase all of current line, start again */
+ ResetInLine(0); /* reset the input pointers */
+ xputchar('\n');
+ ClearDisp();
+ return (CC_REFRESH);
+#else /* !_MINIX && !WINNT */
+ /* do no editing */
+ return (CC_NORM);
+#endif /* _MINIX || WINNT */
+}
+
+/*
+ * From: ghazi@cesl.rutgers.edu (Kaveh R. Ghazi)
+ * Function to send a character back to the input stream in cooked
+ * mode. Only works if we have TIOCSTI
+ */
+/*ARGSUSED*/
+CCRETVAL
+e_stuff_char(c)
+ int c;
+{
+#ifdef TIOCSTI
+ extern int Tty_raw_mode;
+ int was_raw = Tty_raw_mode;
+ char ch = (char) c;
+
+ if (was_raw)
+ (void) Cookedmode();
+
+ (void) write(SHIN, "\n", 1);
+ (void) ioctl(SHIN, TIOCSTI, (ioctl_t) &ch);
+
+ if (was_raw)
+ (void) Rawmode();
+ return(e_redisp(c));
+#else /* !TIOCSTI */
+ return(CC_ERROR);
+#endif /* !TIOCSTI */
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_insovr(c)
+ int c;
+{
+ USE(c);
+ inputmode = (inputmode == MODE_INSERT ? MODE_REPLACE : MODE_INSERT);
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_dsusp(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_flusho(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_quit(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_tsusp(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_stopo(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_expand_history(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ c_substitute();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_magic_space(c)
+ int c;
+{
+ USE(c);
+ *LastChar = '\0'; /* just in case */
+ c_substitute();
+ return(e_insert(' '));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_inc_fwd(c)
+ int c;
+{
+ USE(c);
+ patlen = 0;
+ return e_inc_search(F_DOWN_SEARCH_HIST);
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+e_inc_back(c)
+ int c;
+{
+ USE(c);
+ patlen = 0;
+ return e_inc_search(F_UP_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_copyprev(c)
+ int c;
+{
+ register Char *cp, *oldc, *dp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ oldc = Cursor;
+ /* does a bounds check */
+ cp = c_prev_word(Cursor, InputBuf, Argument);
+
+ c_insert((int)(oldc - cp));
+ for (dp = oldc; cp < oldc && dp < LastChar; cp++)
+ *dp++ = *cp;
+
+ Cursor = dp; /* put cursor at end */
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_tty_starto(c)
+ int c;
+{
+ USE(c);
+ /* do no editing */
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+e_load_average(c)
+ int c;
+{
+ USE(c);
+ PastBottom();
+#ifdef TIOCSTAT
+ /*
+ * Here we pass &c to the ioctl because some os's (NetBSD) expect it
+ * there even if they don't use it. (lukem@netbsd.org)
+ */
+ if (ioctl(SHIN, TIOCSTAT, (ioctl_t) &c) < 0)
+#endif
+ xprintf(CGETS(5, 1, "Load average unavailable\n"));
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_chgmeta(c)
+ int c;
+{
+ USE(c);
+ /*
+ * Delete with insert == change: first we delete and then we leave in
+ * insert mode.
+ */
+ return(v_action(TCSHOP_DELETE|TCSHOP_INSERT));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_delmeta(c)
+ int c;
+{
+ USE(c);
+ return(v_action(TCSHOP_DELETE));
+}
+
+
+/*ARGSUSED*/
+CCRETVAL
+v_endword(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_endword(Cursor, LastChar, Argument);
+
+ if (ActionFlag & TCSHOP_DELETE)
+ {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_eword(c)
+ int c;
+{
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ Cursor = c_eword(Cursor, LastChar, Argument);
+
+ if (ActionFlag & TCSHOP_DELETE) {
+ Cursor++;
+ c_delfini();
+ return(CC_REFRESH);
+ }
+
+ RefCursor();
+ return(CC_NORM);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_char_fwd(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ srch_dir = CHAR_FWD;
+ srch_char = ch;
+
+ return v_csearch_fwd(ch, Argument, 0);
+
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_char_back(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ srch_dir = CHAR_BACK;
+ srch_char = ch;
+
+ return v_csearch_back(ch, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_charto_fwd(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ return v_csearch_fwd(ch, Argument, 1);
+
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_charto_back(c)
+ int c;
+{
+ Char ch;
+
+ USE(c);
+ if (GetNextChar(&ch) != 1)
+ return e_send_eof(0);
+
+ return v_csearch_back(ch, Argument, 1);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rchar_fwd(c)
+ int c;
+{
+ USE(c);
+ if (srch_char == 0)
+ return CC_ERROR;
+
+ return srch_dir == CHAR_FWD ? v_csearch_fwd(srch_char, Argument, 0) :
+ v_csearch_back(srch_char, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rchar_back(c)
+ int c;
+{
+ USE(c);
+ if (srch_char == 0)
+ return CC_ERROR;
+
+ return srch_dir == CHAR_BACK ? v_csearch_fwd(srch_char, Argument, 0) :
+ v_csearch_back(srch_char, Argument, 0);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_undo(c)
+ int c;
+{
+ register int loop;
+ register Char *kp, *cp;
+ Char temp;
+ int size;
+
+ USE(c);
+ switch (UndoAction) {
+ case TCSHOP_DELETE|TCSHOP_INSERT:
+ case TCSHOP_DELETE:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ kp = UndoBuf;
+ for (loop=0; loop < UndoSize; loop++) /* copy the chars */
+ *kp++ = *cp++; /* into UndoBuf */
+
+ for (cp = UndoPtr; cp <= LastChar; cp++)
+ *cp = cp[UndoSize];
+
+ LastChar -= UndoSize;
+ Cursor = UndoPtr;
+
+ UndoAction = TCSHOP_INSERT;
+ break;
+
+ case TCSHOP_INSERT:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ Cursor = UndoPtr;
+ kp = UndoBuf;
+ c_insert(UndoSize); /* open the space, */
+ for (loop = 0; loop < UndoSize; loop++) /* copy the chars */
+ *cp++ = *kp++;
+
+ UndoAction = TCSHOP_DELETE;
+ break;
+
+ case TCSHOP_CHANGE:
+ if (UndoSize == 0) return(CC_NORM);
+ cp = UndoPtr;
+ Cursor = UndoPtr;
+ kp = UndoBuf;
+ size = (int)(Cursor-LastChar); /* NOT NSL independant */
+ if (size < UndoSize)
+ size = UndoSize;
+ for(loop = 0; loop < size; loop++) {
+ temp = *kp;
+ *kp++ = *cp;
+ *cp++ = temp;
+ }
+ break;
+
+ default:
+ return(CC_ERROR);
+ }
+
+ return(CC_REFRESH);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_ush_meta(c)
+ int c;
+{
+ USE(c);
+ return v_search(F_UP_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_dsh_meta(c)
+ int c;
+{
+ USE(c);
+ return v_search(F_DOWN_SEARCH_HIST);
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rsrch_fwd(c)
+ int c;
+{
+ USE(c);
+ if (patlen == 0) return(CC_ERROR);
+ return(v_repeat_srch(searchdir));
+}
+
+/*ARGSUSED*/
+CCRETVAL
+v_rsrch_back(c)
+ int c;
+{
+ USE(c);
+ if (patlen == 0) return(CC_ERROR);
+ return(v_repeat_srch(searchdir == F_UP_SEARCH_HIST ?
+ F_DOWN_SEARCH_HIST : F_UP_SEARCH_HIST));
+}
+
+#ifndef WINNT
+/* Since ed.defns.h is generated from ed.defns.c, these empty
+ functions will keep the F_NUM_FNS consistent
+ */
+CCRETVAL
+e_copy_to_clipboard(c)
+ int c;
+{
+ USE(c);
+ return CC_ERROR;
+}
+
+CCRETVAL
+e_paste_from_clipboard(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+
+CCRETVAL
+e_dosify_next(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+CCRETVAL
+e_dosify_prev(c)
+ int c;
+{
+ USE(c);
+ return (CC_ERROR);
+}
+#else /* WINNT */
+/*ARGSUSED*/
+CCRETVAL
+e_dosify_next(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == LastChar)
+ return(CC_ERROR);
+ /* else */
+
+ cp = Cursor;
+ while( cp < LastChar) {
+ if ( (*cp & CHAR == ' ') && (cp[-1] & CHAR != '\\') )
+ break;
+ cp++;
+ }
+
+ for (p = Cursor, kp = KillBuf; p < cp; p++) {/* save the text */
+ if ( ( *p & CHAR ) == '/') {
+ *kp++ = '\\';
+ *kp++ = '\\';
+ }
+ else
+ *kp++ = *p;
+ }
+ LastKill = kp;
+
+ c_delafter((int)(cp - Cursor)); /* delete after dot */
+ if (Cursor > LastChar)
+ Cursor = LastChar; /* bounds check */
+ return (e_yank_kill(c));
+}
+/*ARGSUSED*/
+CCRETVAL
+e_dosify_prev(c)
+ int c;
+{
+ register Char *cp, *p, *kp;
+
+ USE(c);
+ if (Cursor == InputBuf)
+ return(CC_ERROR);
+ /* else */
+
+ cp = Cursor-1;
+ /* Skip trailing spaces */
+ while ((cp > InputBuf) && ( (*cp & CHAR) == ' '))
+ cp--;
+
+ while (cp > InputBuf) {
+ if ( ((*cp & CHAR) == ' ') && ((cp[-1] & CHAR) != '\\') )
+ break;
+ cp--;
+ }
+
+ for (p = cp, kp = KillBuf; p < Cursor; p++) {/* save the text */
+ if ( ( *p & CHAR ) == '/') {
+ *kp++ = '\\';
+ *kp++ = '\\';
+ }
+ else
+ *kp++ = *p;
+ }
+ LastKill = kp;
+
+ c_delbefore((int)(Cursor - cp)); /* delete before dot */
+ Cursor = cp;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf; /* bounds check */
+ return(e_yank_kill(c));
+}
+#endif /* !WINNT */
+
+#ifdef notdef
+void
+MoveCursor(n) /* move cursor + right - left char */
+ int n;
+{
+ Cursor = Cursor + n;
+ if (Cursor < InputBuf)
+ Cursor = InputBuf;
+ if (Cursor > LastChar)
+ Cursor = LastChar;
+ return;
+}
+
+Char *
+GetCursor()
+{
+ return(Cursor);
+}
+
+int
+PutCursor(p)
+ Char *p;
+{
+ if (p < InputBuf || p > LastChar)
+ return 1; /* Error */
+ Cursor = p;
+ return 0;
+}
+#endif
OpenPOWER on IntegriCloud