source: trunk/third/tcsh/ed.chared.c @ 12039

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