Update libedit from NetBSD.
authorSimon Schubert <corecode@dragonflybsd.org>
Sun, 13 Nov 2005 11:58:31 +0000 (11:58 +0000)
committerSimon Schubert <corecode@dragonflybsd.org>
Sun, 13 Nov 2005 11:58:31 +0000 (11:58 +0000)
libedit update by: Ben Woolley <tautolog@gmail.com>
consumers update by: corecode

55 files changed:
bin/sh/Makefile
bin/sh/histedit.c
bin/sh/input.c
include/histedit.h
kerberos5/include/config.h
lib/libedit/Makefile
lib/libedit/TEST/Makefile [new file with mode: 0644]
lib/libedit/TEST/test.c
lib/libedit/chared.c
lib/libedit/chared.h
lib/libedit/common.c
lib/libedit/config.h [new file with mode: 0644]
lib/libedit/editline.3
lib/libedit/editrc.5
lib/libedit/el.c
lib/libedit/el.h
lib/libedit/emacs.c
lib/libedit/filecomplete.c [new file with mode: 0644]
lib/libedit/filecomplete.h [new file with mode: 0644]
lib/libedit/hist.c
lib/libedit/hist.h
lib/libedit/history.c
lib/libedit/key.c
lib/libedit/key.h
lib/libedit/makelist
lib/libedit/map.c
lib/libedit/map.h
lib/libedit/parse.c
lib/libedit/parse.h
lib/libedit/prompt.c
lib/libedit/prompt.h
lib/libedit/read.c
lib/libedit/read.h [new file with mode: 0644]
lib/libedit/readline.c [new file with mode: 0644]
lib/libedit/readline/Makefile [new file with mode: 0644]
lib/libedit/readline/readline.h [new file with mode: 0644]
lib/libedit/refresh.c
lib/libedit/refresh.h
lib/libedit/search.c
lib/libedit/search.h
lib/libedit/sig.c
lib/libedit/sig.h
lib/libedit/sys.h
lib/libedit/term.c
lib/libedit/term.h
lib/libedit/tokenizer.c
lib/libedit/tty.c
lib/libedit/tty.h
lib/libedit/vi.c
sbin/fsdb/fsdb.c
secure/lib/libssh/config.h
secure/usr.bin/sftp/Makefile
usr.sbin/cdcontrol/cdcontrol.c
usr.sbin/lpr/lpc/lpc.c
usr.sbin/pppctl/pppctl.c

index 90e62fe..afc1f64 100644 (file)
@@ -1,6 +1,6 @@
 #      @(#)Makefile    8.4 (Berkeley) 5/5/95
 # $FreeBSD: src/bin/sh/Makefile,v 1.30.2.1 2001/12/15 10:05:18 knu Exp $
-# $DragonFly: src/bin/sh/Makefile,v 1.4 2005/02/06 06:16:40 okumoto Exp $
+# $DragonFly: src/bin/sh/Makefile,v 1.5 2005/11/13 11:58:30 corecode Exp $
 
 WARNS?=        0       # Not yet
 
@@ -25,6 +25,10 @@ CFLAGS+=-DSHELL -I. -I${.CURDIR}
 # for debug:
 # CFLAGS+= -g -DDEBUG=2
 
+.if defined(BOOTSTRAPPING)
+CFLAGS+= -DNO_HISTORY
+.endif
+
 .PATH: ${.CURDIR}/bltin \
        ${.CURDIR}/../../usr.bin/printf \
        ${.CURDIR}/../../bin/test
index 5c246bf..bb15124 100644 (file)
@@ -35,7 +35,7 @@
  *
  * @(#)histedit.c      8.2 (Berkeley) 5/4/95
  * $FreeBSD: src/bin/sh/histedit.c,v 1.13.2.4 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/histedit.c,v 1.5 2005/11/06 11:44:02 swildner Exp $
+ * $DragonFly: src/bin/sh/histedit.c,v 1.6 2005/11/13 11:58:30 corecode Exp $
  */
 
 #include <sys/param.h>
@@ -77,6 +77,7 @@ STATIC char *fc_replace(const char *, char *, char *);
 void
 histedit(void)
 {
+       FILE *el_err;
 
 #define editing (Eflag || Vflag)
 
@@ -98,6 +99,8 @@ histedit(void)
                        /*
                         * turn editing on
                         */
+                       char *term, *shname;
+
                        INTOFF;
                        if (el_in == NULL)
                                el_in = fdopen(0, "r");
@@ -105,7 +108,16 @@ histedit(void)
                                el_out = fdopen(2, "w");
                        if (el_in == NULL || el_out == NULL)
                                goto bad;
-                       el = el_init(arg0, el_in, el_out);
+                       el_err = el_out;
+                       term = lookupvar("TERM");
+                       if (term)
+                               setenv("TERM", term, 1);
+                       else
+                               unsetenv("TERM");
+                       shname = arg0;
+                       if (shname[0] == '-')
+                               shname++;
+                       el = el_init(arg0, el_in, el_out, el_err);
                        if (el != NULL) {
                                if (hist)
                                        el_set(el, EL_HIST, history, hist);
@@ -147,12 +159,13 @@ void
 sethistsize(const char *hs)
 {
        int histsize;
+       HistEvent he;
 
        if (hist != NULL) {
                if (hs == NULL || *hs == '\0' ||
                   (histsize = atoi(hs)) < 0)
                        histsize = 100;
-               history(hist, H_EVENT, histsize);
+               history(hist, &he, H_SETSIZE, histsize);
        }
 }
 
@@ -165,9 +178,9 @@ histcmd(int argc, char **argv)
 {
        int ch;
        const char *editor = NULL;
-       const HistEvent *he;
+       HistEvent he;
        int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
-       int i;
+       int i, retval;
        const char *firststr, *laststr;
        int first, last, direction;
        char *pat = NULL, *repl;        /* ksh "fc old=new" crap */
@@ -334,16 +347,16 @@ histcmd(int argc, char **argv)
         * The history interface needs rethinking, as the following
         * convolutions will demonstrate.
         */
-       history(hist, H_FIRST);
-       he = history(hist, H_NEXT_EVENT, first);
-       for (;he != NULL; he = history(hist, direction)) {
+       history(hist, &he, H_FIRST);
+       retval = history(hist, &he, H_NEXT_EVENT, first);
+       for (;retval != -1; retval = history(hist, &he, direction)) {
                if (lflg) {
                        if (!nflg)
-                               out1fmt("%5d ", he->num);
-                       out1str(he->str);
+                               out1fmt("%5d ", he.num);
+                       out1str(he.str);
                } else {
                        char *s = pat ?
-                          fc_replace(he->str, pat, repl) : (char *)he->str;
+                          fc_replace(he.str, pat, repl) : (char *)he.str;
 
                        if (sflg) {
                                if (displayhist) {
@@ -355,7 +368,7 @@ histcmd(int argc, char **argv)
                                         *  XXX what about recursive and
                                         *  relative histnums.
                                         */
-                                       history(hist, H_ENTER, s);
+                                       history(hist, &he, H_ENTER, s);
                                }
                        } else
                                fputs(s, efp);
@@ -364,7 +377,7 @@ histcmd(int argc, char **argv)
                 * At end?  (if we were to loose last, we'd sure be
                 * messed up).
                 */
-               if (he->num == last)
+               if (he.num == last)
                        break;
        }
        if (editor) {
@@ -421,12 +434,12 @@ not_fcnumber(char *s)
 int
 str_to_event(const char *str, int last)
 {
-       const HistEvent *he;
+       HistEvent he;
        const char *s = str;
        int relative = 0;
-       int i;
+       int i, retval;
 
-       he = history(hist, H_FIRST);
+       history(hist, &he, H_FIRST);
        switch (*s) {
        case '-':
                relative = 1;
@@ -437,33 +450,33 @@ str_to_event(const char *str, int last)
        if (is_number(s)) {
                i = atoi(s);
                if (relative) {
-                       while (he != NULL && i--) {
-                               he = history(hist, H_NEXT);
+                       while (retval != -1 && i--) {
+                               retval = history(hist, &he, H_NEXT);
                        }
-                       if (he == NULL)
-                               he = history(hist, H_LAST);
+                       if (retval == -1)
+                               retval = history(hist, &he, H_LAST);
                } else {
-                       he = history(hist, H_NEXT_EVENT, i);
-                       if (he == NULL) {
+                       retval = history(hist, &he, H_NEXT_EVENT, i);
+                       if (retval == -1) {
                                /*
                                 * the notion of first and last is
                                 * backwards to that of the history package
                                 */
-                               he = history(hist, last ? H_FIRST : H_LAST);
+                               retval = history(hist, &he, last ? H_FIRST : H_LAST);
                        }
                }
-               if (he == NULL)
+               if (retval == -1)
                        error("history number %s not found (internal error)",
                               str);
        } else {
                /*
                 * pattern
                 */
-               he = history(hist, H_PREV_STR, str);
-               if (he == NULL)
+               retval = history(hist, &he, H_PREV_STR, str);
+               if (retval == -1)
                        error("history pattern not found: %s", str);
        }
-       return (he->num);
+       return (he.num);
 }
 
 int
@@ -472,7 +485,7 @@ bindcmd(int argc, char **argv)
 
        if (el == NULL)
                error("line editing is disabled");
-       return (el_parse(el, argc, argv));
+       return (el_parse(el, argc, (const char **)argv));
 }
 
 #else
index 737cbba..afaac77 100644 (file)
@@ -35,7 +35,7 @@
  *
  * @(#)input.c 8.3 (Berkeley) 6/9/95
  * $FreeBSD: src/bin/sh/input.c,v 1.14.2.2 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/input.c,v 1.5 2004/11/07 20:54:52 eirikn Exp $
+ * $DragonFly: src/bin/sh/input.c,v 1.6 2005/11/13 11:58:30 corecode Exp $
  */
 
 #include <stdio.h>     /* defines BUFSIZ */
@@ -293,8 +293,9 @@ check:
 
 #ifndef NO_HISTORY
        if (parsefile->fd == 0 && hist && something) {
+               HistEvent he;
                INTOFF;
-               history(hist, whichprompt == 1 ? H_ENTER : H_ADD, parsenextc);
+               history(hist, &he, whichprompt == 1 ? H_ENTER : H_APPEND, parsenextc);
                INTON;
        }
 #endif
index fe8dbbb..8686055 100644 (file)
@@ -1,6 +1,5 @@
-/* $FreeBSD: src/include/histedit.h,v 1.5 1999/08/27 23:44:50 peter Exp $ */
-/* $DragonFly: src/include/histedit.h,v 1.3 2003/11/14 01:01:43 dillon Exp $ */
-/*     $NetBSD: histedit.h,v 1.5 1997/04/11 17:52:45 christos Exp $    */
+/* $DragonFly: src/include/histedit.h,v 1.4 2005/11/13 11:58:30 corecode Exp $ */
+/*     $NetBSD: histedit.h,v 1.27 2005/06/12 06:58:21 christos Exp $   */
 
 /*-
  * Copyright (c) 1992, 1993
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
 /*
  * histedit.h: Line editor and history interface.
  */
-#ifndef _h_editline
-#define _h_editline
+#ifndef _HISTEDIT_H_
+#define        _HISTEDIT_H_
 
 #include <sys/types.h>
 #include <stdio.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * ==== Editing ====
  */
+
 typedef struct editline EditLine;
 
 /*
  * For user-defined function interface
  */
 typedef struct lineinfo {
-    const char *buffer;
-    const char *cursor;
-    const char *lastchar;
+       const char      *buffer;
+       const char      *cursor;
+       const char      *lastchar;
 } LineInfo;
 
-
 /*
  * EditLine editor function return codes.
  * For user-defined function interface
@@ -71,46 +70,53 @@ typedef struct lineinfo {
 #define        CC_NORM         0
 #define        CC_NEWLINE      1
 #define        CC_EOF          2
-#define CC_ARGHACK     3
-#define CC_REFRESH     4
+#define        CC_ARGHACK      3
+#define        CC_REFRESH      4
 #define        CC_CURSOR       5
 #define        CC_ERROR        6
-#define CC_FATAL       7
-#define CC_REDISPLAY   8
+#define        CC_FATAL        7
+#define        CC_REDISPLAY    8
+#define        CC_REFRESH_BEEP 9
 
 /*
  * Initialization, cleanup, and resetting
  */
-EditLine       *el_init        (const char *, FILE *, FILE *);
-void            el_reset       (EditLine *);
-void            el_end         (EditLine *);
-
+EditLine       *el_init(const char *, FILE *, FILE *, FILE *);
+void            el_end(EditLine *);
+void            el_reset(EditLine *);
 
 /*
  * Get a line, a character or push a string back in the input queue
  */
-const char    *el_gets (EditLine *, int *);
-int             el_getc        (EditLine *, char *);
-void            el_push        (EditLine *, const char *);
+const char     *el_gets(EditLine *, int *);
+int             el_getc(EditLine *, char *);
+void            el_push(EditLine *, char *);
+
+/*
+ * Beep!
+ */
+void            el_beep(EditLine *);
 
 /*
  * High level function internals control
  * Parses argc, argv array and executes builtin editline commands
  */
-int             el_parse       (EditLine *, int, char **); 
+int             el_parse(EditLine *, int, const char **);
 
 /*
- * Low level editline access function
+ * Low level editline access functions
  */
-int             el_set         (EditLine *, int, ...);
+int             el_set(EditLine *, int, ...);
+int             el_get(EditLine *, int, void *);
+unsigned char  _el_fn_complete(EditLine *, int);
 
 /*
  * el_set/el_get parameters
  */
-#define EL_PROMPT      0       /* , el_pfunc_t);               */
-#define EL_TERMINAL    1       /* , const char *);             */
-#define EL_EDITOR      2       /* , const char *);             */
-#define EL_SIGNAL      3       /* , int);                      */
+#define        EL_PROMPT       0       /* , el_pfunc_t);               */
+#define        EL_TERMINAL     1       /* , const char *);             */
+#define        EL_EDITOR       2       /* , const char *);             */
+#define        EL_SIGNAL       3       /* , int);                      */
 #define        EL_BIND         4       /* , const char *, ..., NULL);  */
 #define        EL_TELLTC       5       /* , const char *, ..., NULL);  */
 #define        EL_SETTC        6       /* , const char *, ..., NULL);  */
@@ -118,30 +124,35 @@ int                el_set         (EditLine *, int, ...);
 #define        EL_SETTY        8       /* , const char *, ..., NULL);  */
 #define        EL_ADDFN        9       /* , const char *, const char * */
                                /* , el_func_t);                */
-#define EL_HIST                10      /* , hist_fun_t, const char *); */
+#define        EL_HIST         10      /* , hist_fun_t, const char *); */
+#define        EL_EDITMODE     11      /* , int);                      */
+#define        EL_RPROMPT      12      /* , el_pfunc_t);               */
+#define        EL_GETCFN       13      /* , el_rfunc_t);               */
+#define        EL_CLIENTDATA   14      /* , void *);                   */
+#define        EL_UNBUFFERED   15      /* , int);                      */
+#define        EL_PREP_TERM    16      /* , int);                      */
+
+#define EL_BUILTIN_GETCFN      (NULL)
 
 /*
  * Source named file or $PWD/.editrc or $HOME/.editrc
  */
-int            el_source       (EditLine *, const char *);
+int            el_source(EditLine *, const char *);
 
 /*
  * Must be called when the terminal changes size; If EL_SIGNAL
  * is set this is done automatically otherwise it is the responsibility
  * of the application
  */
-void            el_resize      (EditLine *);
-
-void            el_data_set    (EditLine *, void *);
-void *          el_data_get    (EditLine *);
-
+void            el_resize(EditLine *);
 
 /*
  * User-defined function interface.
  */
-const LineInfo *el_line        (EditLine *);
-int              el_insertstr  (EditLine *, char *);
-void             el_deletestr  (EditLine *, int);
+const LineInfo *el_line(EditLine *);
+int             el_insertstr(EditLine *, const char *);
+void            el_deletestr(EditLine *, int);
+
 
 /*
  * ==== History ====
@@ -150,34 +161,61 @@ void                el_deletestr  (EditLine *, int);
 typedef struct history History;
 
 typedef struct HistEvent {
-    int          num;
-    const char *str;
+       int              num;
+       const char      *str;
 } HistEvent;
 
 /*
  * History access functions.
  */
-History *              history_init    (void);
-void                   history_end     (History *);
-
-const HistEvent *      history         (History *, int, ...);
-
-#define H_FUNC          0      /* , UTSL               */
-#define H_EVENT                 1      /* , const int);        */
-#define H_FIRST                 2      /* , void);             */
-#define H_LAST          3      /* , void);             */
-#define H_PREV          4      /* , void);             */
-#define H_NEXT          5      /* , void);             */
-#define H_CURR          6      /* , void);             */
-#define H_ADD           7      /* , const char*);      */
-#define H_ENTER                 8      /* , const char*);      */
-#define H_END           9      /* , void);             */
-#define H_NEXT_STR     10      /* , const char*);      */
-#define H_PREV_STR     11      /* , const char*);      */
-#define H_NEXT_EVENT   12      /* , const int);        */
-#define H_PREV_EVENT   13      /* , const int);        */
-#define H_LOAD         14      /* , const char *);     */
-#define H_SAVE         15      /* , const char *);     */
-#define H_CLEAR                16      /* , void);             */
-
-#endif /* _h_editline */
+History *      history_init(void);
+void           history_end(History *);
+
+int            history(History *, HistEvent *, int, ...);
+
+#define        H_FUNC           0      /* , UTSL               */
+#define        H_SETSIZE        1      /* , const int);        */
+#define        H_GETSIZE        2      /* , void);             */
+#define        H_FIRST          3      /* , void);             */
+#define        H_LAST           4      /* , void);             */
+#define        H_PREV           5      /* , void);             */
+#define        H_NEXT           6      /* , void);             */
+#define        H_CURR           8      /* , const int);        */
+#define        H_SET            7      /* , int);              */
+#define        H_ADD            9      /* , const char *);     */
+#define        H_ENTER         10      /* , const char *);     */
+#define        H_APPEND        11      /* , const char *);     */
+#define        H_END           12      /* , void);             */
+#define        H_NEXT_STR      13      /* , const char *);     */
+#define        H_PREV_STR      14      /* , const char *);     */
+#define        H_NEXT_EVENT    15      /* , const int);        */
+#define        H_PREV_EVENT    16      /* , const int);        */
+#define        H_LOAD          17      /* , const char *);     */
+#define        H_SAVE          18      /* , const char *);     */
+#define        H_CLEAR         19      /* , void);             */
+#define        H_SETUNIQUE     20      /* , int);              */
+#define        H_GETUNIQUE     21      /* , void);             */
+
+
+/*
+ * ==== Tokenization ====
+ */
+
+typedef struct tokenizer Tokenizer;
+
+/*
+ * String tokenization functions, using simplified sh(1) quoting rules
+ */
+Tokenizer      *tok_init(const char *);
+void            tok_end(Tokenizer *);
+void            tok_reset(Tokenizer *);
+int             tok_line(Tokenizer *, const LineInfo *,
+                   int *, const char ***, int *, int *);
+int             tok_str(Tokenizer *, const char *,
+                   int *, const char ***);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HISTEDIT_H_ */
index cd05eea..5ac4176 100644 (file)
@@ -1,4 +1,4 @@
-/* $DragonFly: src/kerberos5/include/config.h,v 1.4 2005/01/16 14:25:46 eirikn Exp $ */
+/* $DragonFly: src/kerberos5/include/config.h,v 1.5 2005/11/13 11:58:30 corecode Exp $ */
 /* include/config.h.  Generated by configure.  */
 /* include/config.h.in.  Generated from configure.in by autoheader.  */
 
@@ -219,7 +219,7 @@ static /**/const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
 #define HAVE_FNMATCH_H 1
 
 /* Define if el_init takes four arguments. */
-/* #undef HAVE_FOUR_VALUED_EL_INIT */
+#define HAVE_FOUR_VALUED_EL_INIT 1
 
 /* define if krb_put_int takes four arguments. */
 /* #undef HAVE_FOUR_VALUED_KRB_PUT_INT */
index ef58b10..481a054 100644 (file)
@@ -1,12 +1,13 @@
-#      @(#)Makefile    8.1 (Berkeley) 6/4/93
+# @(#)Makefile 8.1 (Berkeley) 6/4/93
 # $FreeBSD: src/lib/libedit/Makefile,v 1.18.2.2 2002/07/23 10:20:19 ru Exp $
-# $DragonFly: src/lib/libedit/Makefile,v 1.3 2005/04/21 13:42:33 joerg Exp $
+# $DragonFly: src/lib/libedit/Makefile,v 1.4 2005/11/13 11:58:30 corecode Exp $
 
 LIB=   edit
-SHLIB_MAJOR=   4
+SHLIB_MAJOR=   5
 
-OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
-       parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
+OSRCS= chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c hist.c \
+       key.c map.c parse.c prompt.c read.c refresh.c search.c sig.c term.c \
+       tty.c vi.c
 
 DPADD= ${LIBNCURSES}
 LDADD= -lncurses
@@ -15,16 +16,18 @@ MAN=        editline.3 editrc.5
 
 MLINKS=        editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
        editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \
-       editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \
-       editline.3 el_resize.3 editline.3 el_line.3 \
+       editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_get.3 \
+       editline.3 el_source.3 editline.3 el_resize.3 editline.3 el_line.3 \
        editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
        editline.3 history_init.3 editline.3 history_end.3 \
-       editline.3 history.3 editline.3 el_data_get.3 editline.3 el_data_set.3
+       editline.3 history.3 \
+       editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \
+       editline.3 tok_line.3 editline.3 tok_str.3
 
 # For speed and debugging
 #SRCS=   ${OSRCS} tokenizer.c history.c
 # For protection
-SRCS=  editline.c tokenizer.c history.c
+SRCS=  editline.c tokenizer.c history.c readline.c
 
 SRCS+= common.h emacs.h fcns.h help.h vi.h
 
@@ -36,6 +39,8 @@ CFLAGS+=#-DDEBUG_PASTE
 AHDR=vi.h emacs.h common.h
 ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
 
+# SUBDIR=      readline
+
 vi.h: vi.c makelist
        sh ${.CURDIR}/makelist -h ${.CURDIR}/vi.c > ${.TARGET}
 
@@ -63,7 +68,10 @@ editline.c:
 beforedepend editline.o editline.po editline.So: \
        vi.h emacs.h common.h fcns.h fcns.c help.h help.c
 
-test:  test.o libedit.a ${DPADD} ${LIBTERMCAP}
-       ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD}
+# Not up to date
+#test.o:       ${.CURDIR}/TEST/test.c
+#
+#test: test.o libedit.a ${DPADD} ${LIBTERMCAP}
+#      ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD}
 
 .include <bsd.lib.mk>
diff --git a/lib/libedit/TEST/Makefile b/lib/libedit/TEST/Makefile
new file mode 100644 (file)
index 0000000..eb0864b
--- /dev/null
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile,v 1.2 2003/12/05 13:37:48 lukem Exp $
+# $DragonFly: src/lib/libedit/TEST/Makefile,v 1.1 2005/11/13 11:58:30 corecode Exp $
+
+NOMAN=1
+PROG=test
+CPPFLAGS=-I${.CURDIR}/..
+LDADD+=-ledit -ltermcap
+DPADD+=${LIBEDIT} ${LIBTERMCAP}
+
+.ifdef DEBUG
+CPPFLAGS+=-DDEBUG
+.endif
+
+.include <bsd.prog.mk>
index 08ec245..3682527 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#) Copyright (c) 1992, 1993 The Regents of the University of California.  All rights reserved.
  * @(#)test.c  8.1 (Berkeley) 6/4/93
+ * $NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $
+ * $DragonFly: src/lib/libedit/TEST/test.c,v 1.3 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n");
+#endif /* not lint */
+
 /*
  * test.c: A little test program
  */
-#include "sys.h"
 #include <stdio.h>
 #include <string.h>
 #include <signal.h>
 #include <dirent.h>
 
 #include "histedit.h"
-#include "tokenizer.h"
 
 static int continuation = 0;
-static EditLine *el = NULL;
+volatile sig_atomic_t gotsig = 0;
+
+static unsigned char   complete(EditLine *, int);
+       int     main(int, char **);
+static char   *prompt(EditLine *);
+static void    sig(int);
 
 static char *
-/*ARGSUSED*/
-prompt(el)
-    EditLine *el;
+prompt(EditLine *el)
 {
-    static char a[] = "Edit$";
-    static char b[] = "Edit>";
-    return continuation ? b : a;
+       static char a[] = "Edit$ ";
+       static char b[] = "Edit> ";
+
+       return (continuation ? b : a);
 }
 
 static void
-sig(i)
-    int i;
+sig(int i)
 {
-    (void) fprintf(stderr, "Got signal %d.\n", i);
-    el_reset(el);
+       gotsig = i;
 }
 
 static unsigned char
-/*ARGSUSED*/
-complete(el, ch)
-    EditLine *el;
-    int ch;
+complete(EditLine *el, int ch)
 {
-    DIR *dd = opendir(".");
-    struct dirent *dp;
-    const char* ptr;
-    const LineInfo *lf = el_line(el);
-    int len;
-
-    /*
-     * Find the last word
-     */
-    for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--)
-       continue;
-    len = lf->cursor - ++ptr;
-
-    for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
-       if (len > strlen(dp->d_name))
-           continue;
-       if (strncmp(dp->d_name, ptr, len) == 0) {
-           closedir(dd);
-           if (el_insertstr(el, &dp->d_name[len]) == -1)
-               return CC_ERROR;
-           else
-               return CC_REFRESH;
+       DIR *dd = opendir(".");
+       struct dirent *dp;
+       const char* ptr;
+       const LineInfo *lf = el_line(el);
+       int len;
+
+       /*
+        * Find the last word
+        */
+       for (ptr = lf->cursor - 1;
+           !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)
+               continue;
+       len = lf->cursor - ++ptr;
+
+       for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
+               if (len > strlen(dp->d_name))
+                       continue;
+               if (strncmp(dp->d_name, ptr, len) == 0) {
+                       closedir(dd);
+                       if (el_insertstr(el, &dp->d_name[len]) == -1)
+                               return (CC_ERROR);
+                       else
+                               return (CC_REFRESH);
+               }
        }
-    }
 
-    closedir(dd);
-    return CC_ERROR;
+       closedir(dd);
+       return (CC_ERROR);
 }
 
 int
-/*ARGSUSED*/
-main(argc, argv)
-    int argc;
-    char *argv[];
+main(int argc, char *argv[])
 {
-    int num;
-    const char *buf;
-    Tokenizer *tok;
-    History *hist;
+       EditLine *el = NULL;
+       int num;
+       const char *buf;
+       Tokenizer *tok;
+#if 0
+       int lastevent = 0;
+#endif
+       int ncontinuation;
+       History *hist;
+       HistEvent ev;
 
-    (void) signal(SIGINT, sig);
-    (void) signal(SIGQUIT, sig);
-    (void) signal(SIGHUP, sig);
-    (void) signal(SIGTERM, sig);
+       (void) signal(SIGINT, sig);
+       (void) signal(SIGQUIT, sig);
+       (void) signal(SIGHUP, sig);
+       (void) signal(SIGTERM, sig);
 
-    hist = history_init();             /* Init the builtin history     */
-    history(hist, H_EVENT, 100);       /* Remember 100 events          */
+       hist = history_init();          /* Init the builtin history     */
+                                       /* Remember 100 events          */
+       history(hist, &ev, H_SETSIZE, 100);
 
-    tok  = tok_init(NULL);             /* Initialize the tokenizer     */
+       tok  = tok_init(NULL);          /* Initialize the tokenizer     */
 
-    el = el_init(*argv, stdin, stdout);        /* Initialize editline          */
+                                       /* Initialize editline          */
+       el = el_init(*argv, stdin, stdout, stderr);
 
-    el_set(el, EL_EDITOR, "vi");       /* Default editor is vi         */
-    el_set(el, EL_SIGNAL, 1);          /* Handle signals gracefully    */
-    el_set(el, EL_PROMPT, prompt);     /* Set the prompt function      */
+       el_set(el, EL_EDITOR, "vi");    /* Default editor is vi         */
+       el_set(el, EL_SIGNAL, 1);       /* Handle signals gracefully    */
+       el_set(el, EL_PROMPT, prompt);  /* Set the prompt function      */
 
-    /* Tell editline to use this history interface                     */
-    el_set(el, EL_HIST, history, hist);
+                       /* Tell editline to use this history interface  */
+       el_set(el, EL_HIST, history, hist);
 
-    /* Add a user-defined function                                     */
-    el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
+                                       /* Add a user-defined function  */
+       el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete);
 
-    el_set(el, EL_BIND, "^I", "ed-complete", NULL);/* Bind tab to it   */
+                                       /* Bind tab to it               */
+       el_set(el, EL_BIND, "^I", "ed-complete", NULL);
 
-    /*
-     * Bind j, k in vi command mode to previous and next line, instead
-     * of previous and next history.
-     */
-    el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
-    el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
+       /*
+        * Bind j, k in vi command mode to previous and next line, instead
+        * of previous and next history.
+        */
+       el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL);
+       el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL);
 
-    /*
-     * Source the user's defaults file.
-     */
-    el_source(el, NULL);
+       /*
+        * Source the user's defaults file.
+        */
+       el_source(el, NULL);
 
-    while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
-       int ac;
-       char **av;
+       while ((buf = el_gets(el, &num)) != NULL && num != 0)  {
+               int ac, cc, co;
 #ifdef DEBUG
-       (void) fprintf(stderr, "got %d %s", num, buf);
+               int i;
 #endif
-       if (!continuation && num == 1)
-           continue;
-       if (tok_line(tok, buf, &ac, &av) > 0) {
-           history(hist, continuation ? H_ADD : H_ENTER, buf);
-           continuation = 1;
-           continue;
-       }
-       history(hist, continuation ? H_ADD : H_ENTER, buf);
-
-       continuation = 0;
-
-       if (strcmp(av[0], "history") == 0) {
-           const struct HistEvent *he;
-
-           switch (ac) {
-           case 1:
-               for (he = history(hist, H_LAST); he;
-                    he = history(hist, H_PREV))
-                   (void) fprintf(stdout, "%4d %s", he->num, he->str);
-               break;
-
-           case 2:
-               if (strcmp(av[1], "clear") == 0)
-                    history(hist, H_CLEAR);
-               else
-                    goto badhist;
-               break;
-
-           case 3:
-               if (strcmp(av[1], "load") == 0)
-                    history(hist, H_LOAD, av[2]);
-               else if (strcmp(av[1], "save") == 0)
-                    history(hist, H_SAVE, av[2]);
-               break;
-
-           badhist:
-           default:
-               (void) fprintf(stderr, "Bad history arguments\n");
-               break;
-           }
-       }
-       else if (el_parse(el, ac, av) == -1) {
-           switch (fork()) {
-           case 0:
-               execvp(av[0], av);
-               perror(av[0]);
-               _exit(1);
-               /*NOTREACHED*/
-               break;
-
-           case -1:
-               perror("fork");
-               break;
-
-           default:
-               if (wait(&num) == -1)
-                   perror("wait");
-               (void) fprintf(stderr, "Exit %x\n", num);
-               break;
-           }
+               const char **av;
+               const LineInfo *li;
+               li = el_line(el);
+#ifdef DEBUG
+               (void) fprintf(stderr, "==> got %d %s", num, buf);
+               (void) fprintf(stderr, "  > li `%.*s_%.*s'\n",
+                   (li->cursor - li->buffer), li->buffer,
+                   (li->lastchar - 1 - li->cursor),
+                   (li->cursor >= li->lastchar) ? "" : li->cursor);
+
+#endif
+               if (gotsig) {
+                       (void) fprintf(stderr, "Got signal %d.\n", gotsig);
+                       gotsig = 0;
+                       el_reset(el);
+               }
+
+               if (!continuation && num == 1)
+                       continue;
+
+               ac = cc = co = 0;
+               ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co);
+               if (ncontinuation < 0) {
+                       (void) fprintf(stderr, "Internal error\n");
+                       continuation = 0;
+                       continue;
+               }
+#ifdef DEBUG
+               (void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n",
+                   ncontinuation, ac, cc, co);
+#endif
+#if 0
+               if (continuation) {
+                       /*
+                        * Append to the right event in case the user
+                        * moved around in history.
+                        */
+                       if (history(hist, &ev, H_SET, lastevent) == -1)
+                               err(1, "%d: %s", lastevent, ev.str);
+                       history(hist, &ev, H_ADD , buf);
+               } else {
+                       history(hist, &ev, H_ENTER, buf);
+                       lastevent = ev.num;
+               }
+#else
+                               /* Simpler */
+               history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf);
+#endif
+
+               continuation = ncontinuation;
+               ncontinuation = 0;
+               if (continuation)
+                       continue;
+#ifdef DEBUG
+               for (i = 0; i < ac; i++) {
+                       (void) fprintf(stderr, "  > arg# %2d ", i);
+                       if (i != cc)
+                               (void) fprintf(stderr, "`%s'\n", av[i]);
+                       else
+                               (void) fprintf(stderr, "`%.*s_%s'\n",
+                                   co, av[i], av[i] + co);
+               }
+#endif
+
+               if (strcmp(av[0], "history") == 0) {
+                       int rv;
+
+                       switch (ac) {
+                       case 1:
+                               for (rv = history(hist, &ev, H_LAST); rv != -1;
+                                   rv = history(hist, &ev, H_PREV))
+                                       (void) fprintf(stdout, "%4d %s",
+                                           ev.num, ev.str);
+                               break;
+
+                       case 2:
+                               if (strcmp(av[1], "clear") == 0)
+                                        history(hist, &ev, H_CLEAR);
+                               else
+                                        goto badhist;
+                               break;
+
+                       case 3:
+                               if (strcmp(av[1], "load") == 0)
+                                        history(hist, &ev, H_LOAD, av[2]);
+                               else if (strcmp(av[1], "save") == 0)
+                                        history(hist, &ev, H_SAVE, av[2]);
+                               break;
+
+                       badhist:
+                       default:
+                               (void) fprintf(stderr,
+                                   "Bad history arguments\n");
+                               break;
+                       }
+               } else if (el_parse(el, ac, av) == -1) {
+                       switch (fork()) {
+                       case 0:
+                               execvp(av[0], (char *const *)(void *)(unsigned long)(const void *)(av));
+                               perror(av[0]);
+                               _exit(1);
+                               /*NOTREACHED*/
+                               break;
+
+                       case -1:
+                               perror("fork");
+                               break;
+
+                       default:
+                               if (wait(&num) == -1)
+                                       perror("wait");
+                               (void) fprintf(stderr, "Exit %x\n", num);
+                               break;
+                       }
+               }
+
+               tok_reset(tok);
        }
-       tok_reset(tok);
-    }
 
-    el_end(el);
-    tok_end(tok);
-    history_end(hist);
+       el_end(el);
+       tok_end(tok);
+       history_end(hist);
 
-    return 0;
+       return (0);
 }
index da1b9d1..c5b0d00 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#)chared.c        8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/chared.c,v 1.6 2005/08/04 17:27:09 drhodus Exp $
+ * @(#)chared.c 8.1 (Berkeley) 6/4/93
+ * $NetBSD: chared.c,v 1.23 2005/06/01 11:37:52 lukem Exp $
+ * $DragonFly: src/lib/libedit/chared.c,v 1.7 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * chared.c: Character editor utilities
  */
-#include "sys.h"
-
 #include <stdlib.h>
 #include "el.h"
 
+/* value to leave unused in line buffer */
+#define        EL_LEAVE        2
+
 /* cv_undo():
  *     Handle state for the vi undo command
  */
 protected void
-cv_undo(EditLine *el, int action, int size, char *ptr)
+cv_undo(EditLine *el)
 {
-    c_undo_t *vu = &el->el_chared.c_undo;
-    vu->action = action;
-    vu->ptr    = ptr;
-    vu->isize  = size;
-    (void) memcpy(vu->buf, vu->ptr, size);
-#ifdef DEBUG_UNDO
-    (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
-                  vu->ptr, vu->isize, vu->dsize);
-#endif
+       c_undo_t *vu = &el->el_chared.c_undo;
+       c_redo_t *r = &el->el_chared.c_redo;
+       unsigned int size;
+
+       /* Save entire line for undo */
+       size = el->el_line.lastchar - el->el_line.buffer;
+       vu->len = size;
+       vu->cursor = el->el_line.cursor - el->el_line.buffer;
+       memcpy(vu->buf, el->el_line.buffer, size);
+
+       /* save command info for redo */
+       r->count = el->el_state.doingarg ? el->el_state.argument : 0;
+       r->action = el->el_chared.c_vcmd.action;
+       r->pos = r->buf;
+       r->cmd = el->el_state.thiscmd;
+       r->ch = el->el_state.thisch;
+}
+
+/* cv_yank():
+ *     Save yank/delete data for paste
+ */
+protected void
+cv_yank(EditLine *el, const char *ptr, int size)
+{
+       c_kill_t *k = &el->el_chared.c_kill;
+
+       memcpy(k->buf, ptr, size +0u);
+       k->last = k->buf + size;
 }
 
 
@@ -69,18 +88,20 @@ cv_undo(EditLine *el, int action, int size, char *ptr)
 protected void
 c_insert(EditLine *el, int num)
 {
-    char *cp;
+       char *cp;
 
-    if (el->el_line.lastchar + num >= el->el_line.limit)
-       return;                 /* can't go past end of buffer */
+       if (el->el_line.lastchar + num >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, num +0u))
+                       return;         /* can't go past end of buffer */
+       }
 
-    if (el->el_line.cursor < el->el_line.lastchar) {
-       /* if I must move chars */
-       for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
-           cp[num] = *cp;
-    }
-    el->el_line.lastchar += num;
-} /* end c_insert */
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               /* if I must move chars */
+               for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
+                       cp[num] = *cp;
+       }
+       el->el_line.lastchar += num;
+}
 
 
 /* c_delafter():
@@ -90,20 +111,37 @@ protected void
 c_delafter(EditLine *el, int num)
 {
 
-    if (el->el_line.cursor + num > el->el_line.lastchar)
-       num = el->el_line.lastchar - el->el_line.cursor;
+       if (el->el_line.cursor + num > el->el_line.lastchar)
+               num = el->el_line.lastchar - el->el_line.cursor;
+
+       if (el->el_map.current != el->el_map.emacs) {
+               cv_undo(el);
+               cv_yank(el, el->el_line.cursor, num);
+       }
+
+       if (num > 0) {
+               char *cp;
+
+               for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= num;
+       }
+}
 
-    if (num > 0) {
-       char *cp;
 
-       if (el->el_map.current != el->el_map.emacs)
-           cv_undo(el, INSERT, num, el->el_line.cursor);
+/* c_delafter1():
+ *     Delete the character after the cursor, do not yank
+ */
+protected void
+c_delafter1(EditLine *el)
+{
+       char *cp;
 
        for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
-           *cp = cp[num];
+               *cp = cp[1];
 
-       el->el_line.lastchar -= num;
-    }
+       el->el_line.lastchar--;
 }
 
 
@@ -114,20 +152,39 @@ protected void
 c_delbefore(EditLine *el, int num)
 {
 
-    if (el->el_line.cursor - num < el->el_line.buffer)
-       num = el->el_line.cursor - el->el_line.buffer;
+       if (el->el_line.cursor - num < el->el_line.buffer)
+               num = el->el_line.cursor - el->el_line.buffer;
 
-    if (num > 0) {
-       char *cp;
+       if (el->el_map.current != el->el_map.emacs) {
+               cv_undo(el);
+               cv_yank(el, el->el_line.cursor - num, num);
+       }
+
+       if (num > 0) {
+               char *cp;
 
-       if (el->el_map.current != el->el_map.emacs)
-           cv_undo(el, INSERT, num, el->el_line.cursor - num);
+               for (cp = el->el_line.cursor - num;
+                   cp <= el->el_line.lastchar;
+                   cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= num;
+       }
+}
+
+
+/* c_delbefore1():
+ *     Delete the character before the cursor, do not yank
+ */
+protected void
+c_delbefore1(EditLine *el)
+{
+       char *cp;
 
-       for (cp = el->el_line.cursor - num; cp <= el->el_line.lastchar; cp++)
-           *cp = cp[num];
+       for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
+               *cp = cp[1];
 
-       el->el_line.lastchar -= num;
-    }
+       el->el_line.lastchar--;
 }
 
 
@@ -137,31 +194,31 @@ c_delbefore(EditLine *el, int num)
 protected int
 ce__isword(int p)
 {
-    return isalpha((unsigned char) p) || isdigit((unsigned char) p) || strchr("*?_-.[]~=", p) != NULL;
+       return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
 }
 
 
 /* cv__isword():
- *     Return type of word for p according to vi
+ *     Return if p is part of a word according to vi
  */
 protected int
 cv__isword(int p)
 {
-    if (isspace((unsigned char) p))
-        return 0;
-    if ((unsigned char) p == '_' || isalnum((unsigned char) p))
-        return 1;
-    return 2;
+       if (isalnum(p) || p == '_')
+               return 1;
+       if (isgraph(p))
+               return 2;
+       return 0;
 }
 
 
-/* c___isword():
- *     Return if p is part of a space-delimited word (!isspace)
+/* cv__isWord():
+ *     Return if p is part of a big word according to vi
  */
 protected int
-c___isword(int p)
+cv__isWord(int p)
 {
-    return !isspace((unsigned char) p);
+       return (!isspace(p));
 }
 
 
@@ -171,21 +228,21 @@ c___isword(int p)
 protected char *
 c__prev_word(char *p, char *low, int n, int (*wtest)(int))
 {
-    p--;
-
-    while (n--) {
-       while ((p >= low) && !(*wtest)((unsigned char) *p))
-           p--;
-       while ((p >= low) && (*wtest)((unsigned char) *p))
-           p--;
-    }
-
-    /* cp now points to one character before the word */
-    p++;
-    if (p < low)
-       p = low;
-    /* cp now points where we want it */
-    return p;
+       p--;
+
+       while (n--) {
+               while ((p >= low) && !(*wtest)((unsigned char) *p))
+                       p--;
+               while ((p >= low) && (*wtest)((unsigned char) *p))
+                       p--;
+       }
+
+       /* cp now points to one character before the word */
+       p++;
+       if (p < low)
+               p = low;
+       /* cp now points where we want it */
+       return (p);
 }
 
 
@@ -195,16 +252,16 @@ c__prev_word(char *p, char *low, int n, int (*wtest)(int))
 protected char *
 c__next_word(char *p, char *high, int n, int (*wtest)(int))
 {
-    while (n--) {
-       while ((p < high) && !(*wtest)((unsigned char) *p))
-           p++;
-       while ((p < high) && (*wtest)((unsigned char) *p))
-           p++;
-    }
-    if (p > high)
-       p = high;
-    /* p now points where we want it */
-    return p;
+       while (n--) {
+               while ((p < high) && !(*wtest)((unsigned char) *p))
+                       p++;
+               while ((p < high) && (*wtest)((unsigned char) *p))
+                       p++;
+       }
+       if (p > high)
+               p = high;
+       /* p now points where we want it */
+       return (p);
 }
 
 /* cv_next_word():
@@ -213,26 +270,26 @@ c__next_word(char *p, char *high, int n, int (*wtest)(int))
 protected char *
 cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
 {
-    int test;
+       int test;
+
+       while (n--) {
+               test = (*wtest)((unsigned char) *p);
+               while ((p < high) && (*wtest)((unsigned char) *p) == test)
+                       p++;
+               /*
+                * vi historically deletes with cw only the word preserving the
+                * trailing whitespace! This is not what 'w' does..
+                */
+               if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
+                       while ((p < high) && isspace((unsigned char) *p))
+                               p++;
+       }
 
-    while (n--) {
-       test = (*wtest)((unsigned char) *p);
-       while ((p < high) && (*wtest)((unsigned char) *p) == test)
-           p++;
-       /*
-        * vi historically deletes with cw only the word preserving the
-        * trailing whitespace! This is not what 'w' does..
-        */
-       if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
-           while ((p < high) && isspace((unsigned char) *p))
-               p++;
-    }
-
-    /* p now points where we want it */
-    if (p > high)
-       return high;
-    else
-       return p;
+       /* p now points where we want it */
+       if (p > high)
+               return (high);
+       else
+               return (p);
 }
 
 
@@ -240,32 +297,25 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
  *     Find the previous word vi style
  */
 protected char *
-cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
+cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
 {
-    int test;
+       int test;
 
-    while (n--) {
        p--;
-       /*
-        * vi historically deletes with cb only the word preserving the
-        * leading whitespace! This is not what 'b' does..
-        */
-       if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
-           while ((p > low) && isspace((unsigned char) *p))
-               p--;
-       test = (*wtest)((unsigned char) *p);
-       while ((p >= low) && (*wtest)((unsigned char) *p) == test)
-           p--;
+       while (n--) {
+               while ((p > low) && isspace((unsigned char) *p))
+                       p--;
+               test = (*wtest)((unsigned char) *p);
+               while ((p >= low) && (*wtest)((unsigned char) *p) == test)
+                       p--;
+       }
        p++;
-       while (isspace((unsigned char) *p))
-               p++;
-    }
-
-    /* p now points where we want it */
-    if (p < low)
-       return low;
-    else
-       return p;
+
+       /* p now points where we want it */
+       if (p < low)
+               return (low);
+       else
+               return (p);
 }
 
 
@@ -279,28 +329,27 @@ protected char *
 c__number(
     char *p,   /* character position */
     int *num,  /* Return value */
-    int dval,  /* dval is the number to subtract from like $-3 */
-)
+    int dval)  /* dval is the number to subtract from like $-3 */
 {
-    int i;
-    int sign = 1;
-
-    if (*++p == '^') {
-       *num = 1;
-       return p;
-    }
-    if (*p == '$') {
-       if (*++p != '-') {
-           *num = 0x7fffffff;  /* Handle $ */
-           return --p;
+       int i;
+       int sign = 1;
+
+       if (*++p == '^') {
+               *num = 1;
+               return (p);
+       }
+       if (*p == '$') {
+               if (*++p != '-') {
+                       *num = 0x7fffffff;      /* Handle $ */
+                       return (--p);
+               }
+               sign = -1;                      /* Handle $- */
+               ++p;
        }
-       sign = -1;              /* Handle $- */
-       ++p;
-    }
-    for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
-       continue;
-    *num = (sign < 0 ? dval - i : i);
-    return --p;
+       for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
+               continue;
+       *num = (sign < 0 ? dval - i : i);
+       return (--p);
 }
 #endif
 
@@ -310,50 +359,35 @@ c__number(
 protected void
 cv_delfini(EditLine *el)
 {
-    int size;
-    int oaction;
-
-    if (el->el_chared.c_vcmd.action & INSERT)
-       el->el_map.current = el->el_map.key;
+       int size;
+       int action = el->el_chared.c_vcmd.action;
 
-    oaction = el->el_chared.c_vcmd.action;
-    el->el_chared.c_vcmd.action = NOP;
+       if (action & INSERT)
+               el->el_map.current = el->el_map.key;
 
-    if (el->el_chared.c_vcmd.pos == 0)
-       return;
+       if (el->el_chared.c_vcmd.pos == 0)
+               /* sanity */
+               return;
 
-
-    if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
-       size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
-       c_delbefore(el, size);
+       size = el->el_line.cursor - el->el_chared.c_vcmd.pos;
+       if (size == 0)
+               size = 1;
        el->el_line.cursor = el->el_chared.c_vcmd.pos;
-       re_refresh_cursor(el);
-    }
-    else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
-       size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
-       c_delafter(el, size);
-    }
-    else {
-       size = 1;
-       c_delafter(el, size);
-    }
-    switch (oaction) {
-    case DELETE|INSERT:
-       el->el_chared.c_undo.action = DELETE|INSERT;
-       break;
-    case DELETE:
-       el->el_chared.c_undo.action = INSERT;
-       break;
-    case NOP:
-    case INSERT:
-    default:
-       abort();
-       break;
-    }
-
-
-    el->el_chared.c_undo.ptr = el->el_line.cursor;
-    el->el_chared.c_undo.dsize = size;
+       if (action & YANK) {
+               if (size > 0)
+                       cv_yank(el, el->el_line.cursor, size);
+               else
+                       cv_yank(el, el->el_line.cursor + size, -size);
+       } else {
+               if (size > 0) {
+                       c_delafter(el, size);
+                       re_refresh_cursor(el);
+               } else  {
+                       c_delbefore(el, -size);
+                       el->el_line.cursor += size;
+               }
+       }
+       el->el_chared.c_vcmd.action = NOP;
 }
 
 
@@ -364,17 +398,17 @@ cv_delfini(EditLine *el)
 protected char *
 ce__endword(char *p, char *high, int n)
 {
-    p++;
+       p++;
 
-    while (n--) {
-       while ((p < high) && isspace((unsigned char) *p))
-           p++;
-       while ((p < high) && !isspace((unsigned char) *p))
-           p++;
-    }
+       while (n--) {
+               while ((p < high) && isspace((unsigned char) *p))
+                       p++;
+               while ((p < high) && !isspace((unsigned char) *p))
+                       p++;
+       }
 
-    p--;
-    return p;
+       p--;
+       return (p);
 }
 #endif
 
@@ -383,24 +417,22 @@ ce__endword(char *p, char *high, int n)
  *     Go to the end of this word according to vi
  */
 protected char *
-cv__endword(char *p, char *high, int n)
+cv__endword(char *p, char *high, int n, int (*wtest)(int))
 {
-    p++;
+       int test;
 
-    while (n--) {
-       while ((p < high) && isspace((unsigned char) *p))
-           p++;
+       p++;
 
-       if (isalnum((unsigned char) *p))
-           while ((p < high) && isalnum((unsigned char) *p))
-               p++;
-       else
-           while ((p < high) && !(isspace((unsigned char) *p) ||
-                                  isalnum((unsigned char) *p)))
-               p++;
-    }
-    p--;
-    return p;
+       while (n--) {
+               while ((p < high) && isspace((unsigned char) *p))
+                       p++;
+
+               test = (*wtest)((unsigned char) *p);
+               while ((p < high) && (*wtest)((unsigned char) *p) == test)
+                       p++;
+       }
+       p--;
+       return (p);
 }
 
 /* ch_init():
@@ -409,41 +441,53 @@ cv__endword(char *p, char *high, int n)
 protected int
 ch_init(EditLine *el)
 {
-    el->el_line.buffer              = (char *)  el_malloc(EL_BUFSIZ);
-    (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
-    el->el_line.cursor              = el->el_line.buffer;
-    el->el_line.lastchar            = el->el_line.buffer;
-    el->el_line.limit                      = &el->el_line.buffer[EL_BUFSIZ - 2];
-
-    el->el_chared.c_undo.buf        = (char *)  el_malloc(EL_BUFSIZ);
-    (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
-    el->el_chared.c_undo.action     = NOP;
-    el->el_chared.c_undo.isize      = 0;
-    el->el_chared.c_undo.dsize      = 0;
-    el->el_chared.c_undo.ptr        = el->el_line.buffer;
-
-    el->el_chared.c_vcmd.action     = NOP;
-    el->el_chared.c_vcmd.pos        = el->el_line.buffer;
-    el->el_chared.c_vcmd.ins        = el->el_line.buffer;
-
-    el->el_chared.c_kill.buf        = (char *)  el_malloc(EL_BUFSIZ);
-    (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
-    el->el_chared.c_kill.mark       = el->el_line.buffer;
-    el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
-
-    el->el_map.current              = el->el_map.key;
-
-    el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
-    el->el_state.doingarg  = 0;
-    el->el_state.metanext  = 0;
-    el->el_state.argument  = 1;
-    el->el_state.lastcmd   = ED_UNASSIGNED;
-
-    el->el_chared.c_macro.nline     = NULL;
-    el->el_chared.c_macro.level     = -1;
-    el->el_chared.c_macro.macro     = (char **) el_malloc(EL_MAXMACRO *
-                                                         sizeof(char *));
-    return 0;
+       el->el_line.buffer              = (char *) el_malloc(EL_BUFSIZ);
+       if (el->el_line.buffer == NULL)
+               return (-1);
+
+       (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
+       el->el_line.cursor              = el->el_line.buffer;
+       el->el_line.lastchar            = el->el_line.buffer;
+       el->el_line.limit               = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
+
+       el->el_chared.c_undo.buf        = (char *) el_malloc(EL_BUFSIZ);
+       if (el->el_chared.c_undo.buf == NULL)
+               return (-1);
+       (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
+       el->el_chared.c_undo.len        = -1;
+       el->el_chared.c_undo.cursor     = 0;
+       el->el_chared.c_redo.buf        = (char *) el_malloc(EL_BUFSIZ);
+       if (el->el_chared.c_redo.buf == NULL)
+               return (-1);
+       el->el_chared.c_redo.pos        = el->el_chared.c_redo.buf;
+       el->el_chared.c_redo.lim        = el->el_chared.c_redo.buf + EL_BUFSIZ;
+       el->el_chared.c_redo.cmd        = ED_UNASSIGNED;
+
+       el->el_chared.c_vcmd.action     = NOP;
+       el->el_chared.c_vcmd.pos        = el->el_line.buffer;
+
+       el->el_chared.c_kill.buf        = (char *) el_malloc(EL_BUFSIZ);
+       if (el->el_chared.c_kill.buf == NULL)
+               return (-1);
+       (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
+       el->el_chared.c_kill.mark       = el->el_line.buffer;
+       el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
+
+       el->el_map.current              = el->el_map.key;
+
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
+
+       el->el_chared.c_macro.level     = -1;
+       el->el_chared.c_macro.offset    = 0;
+       el->el_chared.c_macro.macro     = (char **) el_malloc(EL_MAXMACRO *
+           sizeof(char *));
+       if (el->el_chared.c_macro.macro == NULL)
+               return (-1);
+       return (0);
 }
 
 /* ch_reset():
@@ -452,33 +496,116 @@ ch_init(EditLine *el)
 protected void
 ch_reset(EditLine *el)
 {
-    el->el_line.cursor              = el->el_line.buffer;
-    el->el_line.lastchar            = el->el_line.buffer;
+       el->el_line.cursor              = el->el_line.buffer;
+       el->el_line.lastchar            = el->el_line.buffer;
 
-    el->el_chared.c_undo.action     = NOP;
-    el->el_chared.c_undo.isize      = 0;
-    el->el_chared.c_undo.dsize      = 0;
-    el->el_chared.c_undo.ptr        = el->el_line.buffer;
+       el->el_chared.c_undo.len        = -1;
+       el->el_chared.c_undo.cursor     = 0;
 
-    el->el_chared.c_vcmd.action     = NOP;
-    el->el_chared.c_vcmd.pos        = el->el_line.buffer;
-    el->el_chared.c_vcmd.ins        = el->el_line.buffer;
+       el->el_chared.c_vcmd.action     = NOP;
+       el->el_chared.c_vcmd.pos        = el->el_line.buffer;
 
-    el->el_chared.c_kill.mark       = el->el_line.buffer;
+       el->el_chared.c_kill.mark       = el->el_line.buffer;
 
-    el->el_map.current              = el->el_map.key;
+       el->el_map.current              = el->el_map.key;
 
-    el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
-    el->el_state.doingarg  = 0;
-    el->el_state.metanext  = 0;
-    el->el_state.argument  = 1;
-    el->el_state.lastcmd   = ED_UNASSIGNED;
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
 
-    el->el_chared.c_macro.level     = -1;
+       el->el_chared.c_macro.level     = -1;
 
-    el->el_history.eventno = 0;
+       el->el_history.eventno          = 0;
 }
 
+/* ch_enlargebufs():
+ *     Enlarge line buffer to be able to hold twice as much characters.
+ *     Returns 1 if successful, 0 if not.
+ */
+protected int
+ch_enlargebufs(el, addlen)
+       EditLine *el;
+       size_t addlen;
+{
+       size_t sz, newsz;
+       char *newbuffer, *oldbuf, *oldkbuf;
+
+       sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
+       newsz = sz * 2;
+       /*
+        * If newly required length is longer than current buffer, we need
+        * to make the buffer big enough to hold both old and new stuff.
+        */
+       if (addlen > sz) {
+               while(newsz - sz < addlen)
+                       newsz *= 2;
+       }
+
+       /*
+        * Reallocate line buffer.
+        */
+       newbuffer = el_realloc(el->el_line.buffer, newsz);
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, newsz - sz);
+           
+       oldbuf = el->el_line.buffer;
+
+       el->el_line.buffer = newbuffer;
+       el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
+       el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
+       /* don't set new size until all buffers are enlarged */
+       el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
+
+       /*
+        * Reallocate kill buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, newsz - sz);
+
+       oldkbuf = el->el_chared.c_kill.buf;
+
+       el->el_chared.c_kill.buf = newbuffer;
+       el->el_chared.c_kill.last = newbuffer +
+                                       (el->el_chared.c_kill.last - oldkbuf);
+       el->el_chared.c_kill.mark = el->el_line.buffer +
+                                       (el->el_chared.c_kill.mark - oldbuf);
+
+       /*
+        * Reallocate undo buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, newsz - sz);
+       el->el_chared.c_undo.buf = newbuffer;
+
+       newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz);
+       if (!newbuffer)
+               return 0;
+       el->el_chared.c_redo.pos = newbuffer +
+                       (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.lim = newbuffer +
+                       (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.buf = newbuffer;
+       
+       if (!hist_enlargebuf(el, sz, newsz))
+               return 0;
+
+       /* Safe to set enlarged buffer size */
+       el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
+       return 1;
+}
 
 /* ch_end():
  *     Free the data structures used by the editor
@@ -486,16 +613,21 @@ ch_reset(EditLine *el)
 protected void
 ch_end(EditLine *el)
 {
-    el_free((ptr_t) el->el_line.buffer);
-    el->el_line.buffer = NULL;
-    el->el_line.limit = NULL;
-    el_free((ptr_t) el->el_chared.c_undo.buf);
-    el->el_chared.c_undo.buf = NULL;
-    el_free((ptr_t) el->el_chared.c_kill.buf);
-    el->el_chared.c_kill.buf = NULL;
-    el_free((ptr_t) el->el_chared.c_macro.macro);
-    el->el_chared.c_macro.macro = NULL;
-    ch_reset(el);
+       el_free((ptr_t) el->el_line.buffer);
+       el->el_line.buffer = NULL;
+       el->el_line.limit = NULL;
+       el_free((ptr_t) el->el_chared.c_undo.buf);
+       el->el_chared.c_undo.buf = NULL;
+       el_free((ptr_t) el->el_chared.c_redo.buf);
+       el->el_chared.c_redo.buf = NULL;
+       el->el_chared.c_redo.pos = NULL;
+       el->el_chared.c_redo.lim = NULL;
+       el->el_chared.c_redo.cmd = ED_UNASSIGNED;
+       el_free((ptr_t) el->el_chared.c_kill.buf);
+       el->el_chared.c_kill.buf = NULL;
+       el_free((ptr_t) el->el_chared.c_macro.macro);
+       el->el_chared.c_macro.macro = NULL;
+       ch_reset(el);
 }
 
 
@@ -503,19 +635,21 @@ ch_end(EditLine *el)
  *     Insert string at cursorI
  */
 public int
-el_insertstr(EditLine *el, char *s)
+el_insertstr(EditLine *el, const char *s)
 {
-    int len;
+       size_t len;
 
-    if ((len = strlen(s)) == 0)
-       return -1;
-    if (el->el_line.lastchar + len >= el->el_line.limit)
-       return -1;
+       if ((len = strlen(s)) == 0)
+               return (-1);
+       if (el->el_line.lastchar + len >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, len))
+                       return (-1);
+       }
 
-    c_insert(el, len);
-    while (*s)
-       *el->el_line.cursor++ = *s++;
-    return 0;
+       c_insert(el, (int)len);
+       while (*s)
+               *el->el_line.cursor++ = *s++;
+       return (0);
 }
 
 
@@ -525,68 +659,80 @@ el_insertstr(EditLine *el, char *s)
 public void
 el_deletestr(EditLine *el, int n)
 {
-    if (n <= 0)
-       return;
+       if (n <= 0)
+               return;
 
-    if (el->el_line.cursor < &el->el_line.buffer[n])
-       return;
+       if (el->el_line.cursor < &el->el_line.buffer[n])
+               return;
 
-    c_delbefore(el, n);                /* delete before dot */
-    el->el_line.cursor -= n;
-    if (el->el_line.cursor < el->el_line.buffer)
-       el->el_line.cursor = el->el_line.buffer;
+       c_delbefore(el, n);             /* delete before dot */
+       el->el_line.cursor -= n;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
 }
 
 /* c_gets():
  *     Get a string
  */
 protected int
-c_gets(EditLine *el, char *buf)
+c_gets(EditLine *el, char *buf, const char *prompt)
 {
-    char ch;
-    int len = 0;
-
-    for (ch = 0; ch == 0;) {
-       if (el_getc(el, &ch) != 1)
-           return ed_end_of_file(el, 0);
-       switch (ch) {
-       case '\010':      /* Delete and backspace */
-       case '\177':
-           if (len > 1) {
-               *el->el_line.cursor-- = '\0';
-               el->el_line.lastchar = el->el_line.cursor;
-               buf[len--] = '\0';
-           }
-           else {
-               el->el_line.buffer[0] = '\0';
-               el->el_line.lastchar = el->el_line.buffer;
-               el->el_line.cursor = el->el_line.buffer;
-               return CC_REFRESH;
-           }
-           re_refresh(el);
-           ch = 0;
-           break;
-
-       case '\033':      /* ESC */
-       case '\r':      /* Newline */
-       case '\n':
-           break;
-
-       default:
-           if (len >= EL_BUFSIZ)
-               term_beep(el);
-           else {
-               buf[len++] = ch;
-               *el->el_line.cursor++ = ch;
-               el->el_line.lastchar = el->el_line.cursor;
-           }
-           re_refresh(el);
-           ch = 0;
-           break;
+       char ch;
+       int len;
+       char *cp = el->el_line.buffer;
+
+       if (prompt) {
+               len = strlen(prompt);
+               memcpy(cp, prompt, len + 0u);
+               cp += len;
+       }
+       len = 0;
+
+       for (;;) {
+               el->el_line.cursor = cp;
+               *cp = ' ';
+               el->el_line.lastchar = cp + 1;
+               re_refresh(el);
+
+               if (el_getc(el, &ch) != 1) {
+                       ed_end_of_file(el, 0);
+                       len = -1;
+                       break;
+               }
+
+               switch (ch) {
+
+               case 0010:      /* Delete and backspace */
+               case 0177:
+                       if (len <= 0) {
+                               len = -1;
+                               break;
+                       }
+                       cp--;
+                       continue;
+
+               case 0033:      /* ESC */
+               case '\r':      /* Newline */
+               case '\n':
+                       buf[len] = ch;
+                       break;
+
+               default:
+                       if (len >= EL_BUFSIZ - 16)
+                               term_beep(el);
+                       else {
+                               buf[len++] = ch;
+                               *cp++ = ch;
+                       }
+                       continue;
+               }
+               break;
        }
-    }
-    buf[len] = ch;
-    return len;
+
+       el->el_line.buffer[0] = '\0';
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return len;
 }
 
 
@@ -596,18 +742,18 @@ c_gets(EditLine *el, char *buf)
 protected int
 c_hpos(EditLine *el)
 {
-    char *ptr;
+       char *ptr;
 
-    /*
-     * Find how many characters till the beginning of this line.
-     */
-    if (el->el_line.cursor == el->el_line.buffer)
-       return 0;
-    else {
-       for (ptr = el->el_line.cursor - 1;
-            ptr >= el->el_line.buffer && *ptr != '\n';
-            ptr--)
-           continue;
-       return el->el_line.cursor - ptr - 1;
-    }
+       /*
+        * Find how many characters till the beginning of this line.
+        */
+       if (el->el_line.cursor == el->el_line.buffer)
+               return (0);
+       else {
+               for (ptr = el->el_line.cursor - 1;
+                    ptr >= el->el_line.buffer && *ptr != '\n';
+                    ptr--)
+                       continue;
+               return (el->el_line.cursor - ptr - 1);
+       }
 }
index 6829582..e82f78d 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)chared.h    8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/chared.h,v 1.3 2003/11/12 20:21:29 eirikn Exp $
+ * @(#)chared.h        8.1 (Berkeley) 6/4/93
+ * $NetBSD: chared.h,v 1.14 2004/08/13 12:10:39 mycroft Exp $
+ * $DragonFly: src/lib/libedit/chared.h,v 1.4 2005/11/13 11:58:30 corecode Exp $
  */
 
 /*
  * el.chared.h: Character editor interface
  */
 #ifndef _h_el_chared
-#define _h_el_chared
+#define        _h_el_chared
 
 #include <ctype.h>
 #include <string.h>
 
 #include "histedit.h"
 
-#define EL_MAXMACRO 10
+#define        EL_MAXMACRO     10
 
 /*
  * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
  * Probably the best fix is to make all the editing commands aware of
  * this fact.
  */
-#define VI_MOVE
+#define        VI_MOVE
 
 
 typedef struct c_macro_t {
-    int    level;
-    char **macro;
-    char  *nline;
+       int       level;
+       int       offset;
+       char    **macro;
 } c_macro_t;
 
 /*
- * Undo information for both vi and emacs
+ * Undo information for vi - no undo in emacs (yet)
  */
 typedef struct c_undo_t {
-    int   action;
-    int   isize;
-    int   dsize;
-    char *ptr;
-    char *buf;
+       int      len;                   /* length of saved line */
+       int      cursor;                /* position of saved cursor */
+       char    *buf;                   /* full saved text */
 } c_undo_t;
 
+/* redo for vi */
+typedef struct c_redo_t {
+       char    *buf;                   /* redo insert key sequence */
+       char    *pos;
+       char    *lim;
+       el_action_t     cmd;            /* command to redo */
+       char    ch;                     /* char that invoked it */
+       int     count;
+       int     action;                 /* from cv_action() */
+} c_redo_t;
+
 /*
  * Current action information for vi
  */
 typedef struct c_vcmd_t {
-    int   action;
-    char *pos;
-    char *ins;
+       int      action;
+       char    *pos;
 } c_vcmd_t;
 
 /*
  * Kill buffer for emacs
  */
 typedef struct c_kill_t {
-    char *buf;
-    char *last;
-    char *mark;
+       char    *buf;
+       char    *last;
+       char    *mark;
 } c_kill_t;
 
 /*
@@ -103,30 +108,31 @@ typedef struct c_kill_t {
  * commands from both editors!
  */
 typedef struct el_chared_t {
-    c_undo_t    c_undo;
-    c_kill_t    c_kill;
-    c_vcmd_t    c_vcmd;
-    c_macro_t   c_macro;
+       c_undo_t        c_undo;
+       c_kill_t        c_kill;
+       c_redo_t        c_redo;
+       c_vcmd_t        c_vcmd;
+       c_macro_t       c_macro;
 } el_chared_t;
 
 
-#define STReof "^D\b\b"
-#define STRQQ  "\"\""
+#define        STReof          "^D\b\b"
+#define        STRQQ           "\"\""
 
-#define isglob(a) (strchr("*[]?", (a)) != NULL)
-#define isword(a) (isprint(a))
+#define        isglob(a)       (strchr("*[]?", (a)) != NULL)
+#define        isword(a)       (isprint(a))
 
-#define NOP              0x00
-#define DELETE           0x01
-#define INSERT           0x02
-#define CHANGE           0x04
+#define        NOP             0x00
+#define        DELETE          0x01
+#define        INSERT          0x02
+#define        YANK            0x04
 
-#define CHAR_FWD       0
-#define CHAR_BACK      1
+#define        CHAR_FWD        (+1)
+#define        CHAR_BACK       (-1)
 
-#define MODE_INSERT    0
-#define MODE_REPLACE   1
-#define MODE_REPLACE_1 2
+#define        MODE_INSERT     0
+#define        MODE_REPLACE    1
+#define        MODE_REPLACE_1  2
 
 #include "common.h"
 #include "vi.h"
@@ -135,26 +141,28 @@ typedef struct el_chared_t {
 #include "fcns.h"
 
 
-protected int   cv__isword     (int);
-protected void  cv_delfini     (EditLine *);
-protected char *cv__endword    (char *, char *, int);
-protected int   ce__isword     (int);
-protected int   c___isword     (int);
-protected void  cv_undo                (EditLine *, int, int, char *);
-protected char *cv_next_word   (EditLine*, char *, char *, int,
-                                    int (*)(int));
-protected char *cv_prev_word   (EditLine*, char *, char *, int,
-                                    int (*)(int));
-protected char *c__next_word   (char *, char *, int, int (*)(int));
-protected char *c__prev_word   (char *, char *, int, int (*)(int));
-protected void  c_insert       (EditLine *, int);
-protected void  c_delbefore    (EditLine *, int);
-protected void  c_delafter     (EditLine *, int);
-protected int   c_gets         (EditLine *, char *);
-protected int   c_hpos         (EditLine *);
-
-protected int   ch_init                (EditLine *);
-protected void  ch_reset       (EditLine *);
-protected void  ch_end         (EditLine *);
+protected int   cv__isword(int);
+protected int   cv__isWord(int);
+protected void  cv_delfini(EditLine *);
+protected char *cv__endword(char *, char *, int, int (*)(int));
+protected int   ce__isword(int);
+protected void  cv_undo(EditLine *);
+protected void  cv_yank(EditLine *, const char *, int);
+protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int));
+protected char *cv_prev_word(char *, char *, int, int (*)(int));
+protected char *c__next_word(char *, char *, int, int (*)(int));
+protected char *c__prev_word(char *, char *, int, int (*)(int));
+protected void  c_insert(EditLine *, int);
+protected void  c_delbefore(EditLine *, int);
+protected void  c_delbefore1(EditLine *);
+protected void  c_delafter(EditLine *, int);
+protected void  c_delafter1(EditLine *);
+protected int   c_gets(EditLine *, char *, const char *);
+protected int   c_hpos(EditLine *);
+
+protected int   ch_init(EditLine *);
+protected void  ch_reset(EditLine *);
+protected int   ch_enlargebufs(EditLine *, size_t);
+protected void  ch_end(EditLine *);
 
 #endif /* _h_el_chared */
index 415e152..4a5e01a 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#)common.c        8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/common.c,v 1.4 2005/08/04 17:27:09 drhodus Exp $
+ * @(#)common.c 8.1 (Berkeley) 6/4/93
+ * $NetBSD: common.c,v 1.16 2003/08/07 16:44:30 agc Exp $
+ * $DragonFly: src/lib/libedit/common.c,v 1.5 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * common.c: Common Editor functions
  */
-#include "sys.h"
 #include "el.h"
 
 /* ed_end_of_file():
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_end_of_file(EditLine *el, int c)
+ed_end_of_file(EditLine *el, int c __attribute__((__unused__)))
 {
-    re_goto_bottom(el);
-    *el->el_line.lastchar = '\0';
-    return CC_EOF;
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar = '\0';
+       return (CC_EOF);
 }
 
 
@@ -64,54 +63,38 @@ ed_end_of_file(EditLine *el, int c)
 protected el_action_t
 ed_insert(EditLine *el, int c)
 {
-    int i;
-
-    if (c == '\0')
-       return CC_ERROR;
-
-    if (el->el_line.lastchar + el->el_state.argument >=
-       el->el_line.limit)
-       return CC_ERROR;        /* end of buffer space */
-
-    if (el->el_state.argument == 1) {
-       if (el->el_state.inputmode != MODE_INSERT) {
-           el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-               *el->el_line.cursor;
-           el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
-           c_delafter(el, 1);
-       }
+       int count = el->el_state.argument;
 
-        c_insert(el, 1);
+       if (c == '\0')
+               return (CC_ERROR);
 
-       *el->el_line.cursor++ = c;
-       el->el_state.doingarg = 0;              /* just in case */
-       re_fastaddc(el);                        /* fast refresh for one char. */
-    }
-    else {
-       if (el->el_state.inputmode != MODE_INSERT) {
-
-           for(i = 0;i < el->el_state.argument; i++)
-               el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-                       el->el_line.cursor[i];
-
-           el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
-           c_delafter(el, el->el_state.argument);
-       }
+       if (el->el_line.lastchar + el->el_state.argument >=
+           el->el_line.limit) {
+               /* end of buffer space, try to allocate more */
+               if (!ch_enlargebufs(el, (size_t) count))
+                       return CC_ERROR;        /* error allocating more */
+       }
 
-        c_insert(el, el->el_state.argument);
+       if (count == 1) {
+               if (el->el_state.inputmode == MODE_INSERT
+                   || el->el_line.cursor >= el->el_line.lastchar)
+                       c_insert(el, 1);
 
-       while (el->el_state.argument--)
-           *el->el_line.cursor++ = c;
-       re_refresh(el);
-    }
+               *el->el_line.cursor++ = c;
+               re_fastaddc(el);                /* fast refresh for one char. */
+       } else {
+               if (el->el_state.inputmode != MODE_REPLACE_1)
+                       c_insert(el, el->el_state.argument);
 
-    if (el->el_state.inputmode == MODE_REPLACE_1 || el->el_state.inputmode == MODE_REPLACE)
-       el->el_chared.c_undo.action=CHANGE;
+               while (count-- && el->el_line.cursor < el->el_line.lastchar)
+                       *el->el_line.cursor++ = c;
+               re_refresh(el);
+       }
 
-    if (el->el_state.inputmode == MODE_REPLACE_1)
-       return vi_command_mode(el, 0);
+       if (el->el_state.inputmode == MODE_REPLACE_1)
+               return vi_command_mode(el, 0);
 
-    return CC_NORM;
+       return (CC_NORM);
 }
 
 
@@ -121,25 +104,25 @@ ed_insert(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_prev_word(EditLine *el, int c)
+ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *cp, *p, *kp;
+       char *cp, *p, *kp;
 
-    if (el->el_line.cursor == el->el_line.buffer)
-       return CC_ERROR;
+       if (el->el_line.cursor == el->el_line.buffer)
+               return (CC_ERROR);
 
-    cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
-                     el->el_state.argument, ce__isword);
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
 
-    for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
-       *kp++ = *p;
-    el->el_chared.c_kill.last = kp;
+       for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
 
-    c_delbefore(el, el->el_line.cursor - cp);  /* delete before dot */
-    el->el_line.cursor = cp;
-    if (el->el_line.cursor < el->el_line.buffer)
-       el->el_line.cursor = el->el_line.buffer;        /* bounds check */
-    return CC_REFRESH;
+       c_delbefore(el, el->el_line.cursor - cp);       /* delete before dot */
+       el->el_line.cursor = cp;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer; /* bounds check */
+       return (CC_REFRESH);
 }
 
 
@@ -149,44 +132,48 @@ ed_delete_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_next_char(EditLine *el, int c)
-{
-#ifdef notdef /* XXX */
-#define EL el->el_line
-fprintf(stderr, "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
-       EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, EL.lastchar, EL.limit, EL.limit);
+ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))
+{
+#ifdef notdef                  /* XXX */
+#define        EL      el->el_line
+       (void) fprintf(el->el_errlfile,
+           "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
+           EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
+           EL.lastchar, EL.limit, EL.limit);
 #endif
-    if (el->el_line.cursor == el->el_line.lastchar) {/* if I'm at the end */
-       if (el->el_map.type == MAP_VI) {
-           if (el->el_line.cursor == el->el_line.buffer) {
-               /* if I'm also at the beginning */
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                       /* if I'm at the end */
+               if (el->el_map.type == MAP_VI) {
+                       if (el->el_line.cursor == el->el_line.buffer) {
+                               /* if I'm also at the beginning */
 #ifdef KSHVI
-               return CC_ERROR;
+                               return (CC_ERROR);
 #else
-               term_overwrite(el, STReof, 4);/* then do a EOF */
-               term__flush();
-               return CC_EOF;
+                               term_overwrite(el, STReof, 4);
+                                       /* then do a EOF */
+                               term__flush();
+                               return (CC_EOF);
 #endif
-           }
-           else  {
+                       } else {
 #ifdef KSHVI
-               el->el_line.cursor--;
+                               el->el_line.cursor--;
 #else
-               return CC_ERROR;
+                               return (CC_ERROR);
 #endif
-           }
-       }
-       else {
-           if (el->el_line.cursor != el->el_line.buffer)
-               el->el_line.cursor--;
-           else
-               return CC_ERROR;
+                       }
+               } else {
+                       if (el->el_line.cursor != el->el_line.buffer)
+                               el->el_line.cursor--;
+                       else
+                               return (CC_ERROR);
+               }
        }
-    }
-    c_delafter(el, el->el_state.argument);     /* delete after dot */
-    if (el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer)
-       el->el_line.cursor = el->el_line.lastchar - 1;  /* bounds check */
-    return CC_REFRESH;
+       c_delafter(el, el->el_state.argument);  /* delete after dot */
+       if (el->el_line.cursor >= el->el_line.lastchar &&
+           el->el_line.cursor > el->el_line.buffer)
+                       /* bounds check */
+               el->el_line.cursor = el->el_line.lastchar - 1;
+       return (CC_REFRESH);
 }
 
 
@@ -196,17 +183,18 @@ fprintf(stderr, "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_kill_line(EditLine *el, int c)
+ed_kill_line(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *kp, *cp;
+       char *kp, *cp;
 
-    cp = el->el_line.cursor;
-    kp = el->el_chared.c_kill.buf;
-    while (cp < el->el_line.lastchar)
-       *kp++ = *cp++;          /* copy it */
-    el->el_chared.c_kill.last = kp;
-    el->el_line.lastchar = el->el_line.cursor; /* zap! -- delete to end */
-    return CC_REFRESH;
+       cp = el->el_line.cursor;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                       /* zap! -- delete to end */
+       el->el_line.lastchar = el->el_line.cursor;
+       return (CC_REFRESH);
 }
 
 
@@ -216,19 +204,20 @@ ed_kill_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_move_to_end(EditLine *el, int c)
+ed_move_to_end(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_line.cursor = el->el_line.lastchar;
-    if (el->el_map.type == MAP_VI) {
+
+       el->el_line.cursor = el->el_line.lastchar;
+       if (el->el_map.type == MAP_VI) {
 #ifdef VI_MOVE
-       el->el_line.cursor--;
+               el->el_line.cursor--;
 #endif
-       if (el->el_chared.c_vcmd.action & DELETE) {
-           cv_delfini(el);
-           return CC_REFRESH;
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return (CC_REFRESH);
+               }
        }
-    }
-    return CC_CURSOR;
+       return (CC_CURSOR);
 }
 
 
@@ -238,21 +227,21 @@ ed_move_to_end(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_move_to_beg(EditLine *el, int c)
+ed_move_to_beg(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_line.cursor = el->el_line.buffer;
 
-    if (el->el_map.type == MAP_VI) {
-        /* We want FIRST non space character */
-       while (isspace((unsigned char) *el->el_line.cursor))
-           el->el_line.cursor++;
-       if (el->el_chared.c_vcmd.action & DELETE) {
-           cv_delfini(el);
-           return CC_REFRESH;
-       }
-    }
+       el->el_line.cursor = el->el_line.buffer;
 
-    return CC_CURSOR;
+       if (el->el_map.type == MAP_VI) {
+                       /* We want FIRST non space character */
+               while (isspace((unsigned char) *el->el_line.cursor))
+                       el->el_line.cursor++;
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return (CC_REFRESH);
+               }
+       }
+       return (CC_CURSOR);
 }
 
 
@@ -263,21 +252,21 @@ ed_move_to_beg(EditLine *el, int c)
 protected el_action_t
 ed_transpose_chars(EditLine *el, int c)
 {
-    if (el->el_line.cursor < el->el_line.lastchar) {
-       if (el->el_line.lastchar <= &el->el_line.buffer[1])
-           return CC_ERROR;
-       else
-           el->el_line.cursor++;
-    }
-    if (el->el_line.cursor > &el->el_line.buffer[1]) {
-       /* must have at least two chars entered */
-       c = el->el_line.cursor[-2];
-       el->el_line.cursor[-2] = el->el_line.cursor[-1];
-       el->el_line.cursor[-1] = c;
-       return CC_REFRESH;
-    }
-    else
-       return CC_ERROR;
+
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               if (el->el_line.lastchar <= &el->el_line.buffer[1])
+                       return (CC_ERROR);
+               else
+                       el->el_line.cursor++;
+       }
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return (CC_REFRESH);
+       } else
+               return (CC_ERROR);
 }
 
 
@@ -287,22 +276,26 @@ ed_transpose_chars(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_char(EditLine *el, int c)
+ed_next_char(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor >= el->el_line.lastchar)
-       return CC_ERROR;
+       char *lim = el->el_line.lastchar;
 
-    el->el_line.cursor += el->el_state.argument;
-    if (el->el_line.cursor > el->el_line.lastchar)
-       el->el_line.cursor = el->el_line.lastchar;
+       if (el->el_line.cursor >= lim ||
+           (el->el_line.cursor == lim - 1 &&
+           el->el_map.type == MAP_VI &&
+           el->el_chared.c_vcmd.action == NOP))
+               return (CC_ERROR);
 
-    if (el->el_map.type == MAP_VI)
-       if (el->el_chared.c_vcmd.action & DELETE) {
-           cv_delfini(el);
-           return CC_REFRESH;
-       }
+       el->el_line.cursor += el->el_state.argument;
+       if (el->el_line.cursor > lim)
+               el->el_line.cursor = lim;
 
-    return CC_CURSOR;
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return (CC_REFRESH);
+               }
+       return (CC_CURSOR);
 }
 
 
@@ -312,22 +305,23 @@ ed_next_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_word(EditLine *el, int c)
+ed_prev_word(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor == el->el_line.buffer)
-       return CC_ERROR;
 
-    el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer,
-                                     el->el_state.argument,
-                                     ce__isword);
+       if (el->el_line.cursor == el->el_line.buffer)
+               return (CC_ERROR);
 
-    if (el->el_map.type == MAP_VI)
-       if (el->el_chared.c_vcmd.action & DELETE) {
-           cv_delfini(el);
-           return CC_REFRESH;
-       }
+       el->el_line.cursor = c__prev_word(el->el_line.cursor,
+           el->el_line.buffer,
+           el->el_state.argument,
+           ce__isword);
 
-    return CC_CURSOR;
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return (CC_REFRESH);
+               }
+       return (CC_CURSOR);
 }
 
 
@@ -337,23 +331,22 @@ ed_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_char(EditLine *el, int c)
+ed_prev_char(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor > el->el_line.buffer) {
-       el->el_line.cursor -= el->el_state.argument;
-       if (el->el_line.cursor < el->el_line.buffer)
-           el->el_line.cursor = el->el_line.buffer;
 
-       if (el->el_map.type == MAP_VI)
-           if (el->el_chared.c_vcmd.action & DELETE) {
-               cv_delfini(el);
-               return CC_REFRESH;
-           }
+       if (el->el_line.cursor > el->el_line.buffer) {
+               el->el_line.cursor -= el->el_state.argument;
+               if (el->el_line.cursor < el->el_line.buffer)
+                       el->el_line.cursor = el->el_line.buffer;
 
-       return CC_CURSOR;
-    }
-    else
-       return CC_ERROR;
+               if (el->el_map.type == MAP_VI)
+                       if (el->el_chared.c_vcmd.action != NOP) {
+                               cv_delfini(el);
+                               return (CC_REFRESH);
+                       }
+               return (CC_CURSOR);
+       } else
+               return (CC_ERROR);
 }
 
 
@@ -364,17 +357,17 @@ ed_prev_char(EditLine *el, int c)
 protected el_action_t
 ed_quoted_insert(EditLine *el, int c)
 {
-    int     num;
-    char    tc;
+       int num;
+       char tc;
 
-    tty_quotemode(el);
-    num = el_getc(el, &tc);
-    c = (unsigned char) tc;
-    tty_noquotemode(el);
-    if (num == 1)
-       return ed_insert(el, c);
-    else
-       return ed_end_of_file(el, 0);
+       tty_quotemode(el);
+       num = el_getc(el, &tc);
+       c = (unsigned char) tc;
+       tty_noquotemode(el);
+       if (num == 1)
+               return (ed_insert(el, c));
+       else
+               return (ed_end_of_file(el, 0));
 }
 
 
@@ -384,37 +377,24 @@ ed_quoted_insert(EditLine *el, int c)
 protected el_action_t
 ed_digit(EditLine *el, int c)
 {
-    if (!isdigit((unsigned char) c))
-       return CC_ERROR;
-
-    if (el->el_state.doingarg) {
-       /* if doing an arg, add this in... */
-       if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
-           el->el_state.argument = c - '0';
-       else {
-           if (el->el_state.argument > 1000000)
-               return CC_ERROR;
-           el->el_state.argument =
-               (el->el_state.argument * 10) + (c - '0');
+
+       if (!isdigit(c))
+               return (CC_ERROR);
+
+       if (el->el_state.doingarg) {
+                       /* if doing an arg, add this in... */
+               if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
+                       el->el_state.argument = c - '0';
+               else {
+                       if (el->el_state.argument > 1000000)
+                               return (CC_ERROR);
+                       el->el_state.argument =
+                           (el->el_state.argument * 10) + (c - '0');
+               }
+               return (CC_ARGHACK);
        }
-       return CC_ARGHACK;
-    }
-    else {
-       if (el->el_line.lastchar + 1 >= el->el_line.limit)
-           return CC_ERROR;
-
-       if (el->el_state.inputmode != MODE_INSERT) {
-           el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
-               *el->el_line.cursor;
-           el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] = '\0';
-           c_delafter(el, 1);
-       }
-       c_insert(el, 1);
-       *el->el_line.cursor++ = c;
-       el->el_state.doingarg = 0;
-       re_fastaddc(el);
-    }
-    return CC_NORM;
+
+       return ed_insert(el, c);
 }
 
 
@@ -425,19 +405,20 @@ ed_digit(EditLine *el, int c)
 protected el_action_t
 ed_argument_digit(EditLine *el, int c)
 {
-    if (!isdigit((unsigned char) c))
-       return CC_ERROR;
 
-    if (el->el_state.doingarg) {
-       if (el->el_state.argument > 1000000)
-           return CC_ERROR;
-       el->el_state.argument = (el->el_state.argument * 10) + (c - '0');
-    }
-    else {                     /* else starting an argument */
-       el->el_state.argument = c - '0';
-       el->el_state.doingarg = 1;
-    }
-    return CC_ARGHACK;
+       if (!isdigit(c))
+               return (CC_ERROR);
+
+       if (el->el_state.doingarg) {
+               if (el->el_state.argument > 1000000)
+                       return (CC_ERROR);
+               el->el_state.argument = (el->el_state.argument * 10) +
+                   (c - '0');
+       } else {                /* else starting an argument */
+               el->el_state.argument = c - '0';
+               el->el_state.doingarg = 1;
+       }
+       return (CC_ARGHACK);
 }
 
 
@@ -447,11 +428,10 @@ ed_argument_digit(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_unassigned(EditLine *el, int c)
+ed_unassigned(EditLine *el, int c __attribute__((__unused__)))
 {
-    term_beep(el);
-    term__flush();
-    return CC_NORM;
+
+       return (CC_ERROR);
 }
 
 
@@ -465,9 +445,11 @@ ed_unassigned(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigint(EditLine *el, int c)
+ed_tty_sigint(EditLine *el __attribute__((__unused__)), 
+             int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -477,9 +459,11 @@ ed_tty_sigint(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_dsusp(EditLine *el, int c)
+ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 
+            int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -489,9 +473,11 @@ ed_tty_dsusp(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_flush_output(EditLine *el, int c)
+ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 
+                   int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -501,9 +487,11 @@ ed_tty_flush_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigquit(EditLine *el, int c)
+ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 
+              int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -513,9 +501,11 @@ ed_tty_sigquit(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_sigtstp(EditLine *el, int c)
+ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 
+              int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -525,9 +515,11 @@ ed_tty_sigtstp(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_stop_output(EditLine *el, int c)
+ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 
+                  int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -537,9 +529,11 @@ ed_tty_stop_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_tty_start_output(EditLine *el, int c)
+ed_tty_start_output(EditLine *el __attribute__((__unused__)), 
+                   int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -549,14 +543,13 @@ ed_tty_start_output(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_newline(EditLine *el, int c)
+ed_newline(EditLine *el, int c __attribute__((__unused__)))
 {
-    re_goto_bottom(el);
-    *el->el_line.lastchar++ = '\n';
-    *el->el_line.lastchar = '\0';
-    if (el->el_map.type == MAP_VI)
-       el->el_chared.c_vcmd.ins = el->el_line.buffer;
-    return CC_NEWLINE;
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar++ = '\n';
+       *el->el_line.lastchar = '\0';
+       return (CC_NEWLINE);
 }
 
 
@@ -566,16 +559,17 @@ ed_newline(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_delete_prev_char(EditLine *el, int c)
+ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor <= el->el_line.buffer)
-       return CC_ERROR;
 
-    c_delbefore(el, el->el_state.argument);
-    el->el_line.cursor -= el->el_state.argument;
-    if (el->el_line.cursor < el->el_line.buffer)
-       el->el_line.cursor = el->el_line.buffer;
-    return CC_REFRESH;
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return (CC_ERROR);
+
+       c_delbefore(el, el->el_state.argument);
+       el->el_line.cursor -= el->el_state.argument;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+       return (CC_REFRESH);
 }
 
 
@@ -585,11 +579,12 @@ ed_delete_prev_char(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_clear_screen(EditLine *el, int c)
+ed_clear_screen(EditLine *el, int c __attribute__((__unused__)))
 {
-    term_clear_screen(el);     /* clear the whole real screen */
-    re_clear_display(el);              /* reset everything */
-    return CC_REFRESH;
+
+       term_clear_screen(el);  /* clear the whole real screen */
+       re_clear_display(el);   /* reset everything */
+       return (CC_REFRESH);
 }
 
 
@@ -599,9 +594,11 @@ ed_clear_screen(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_redisplay(EditLine *el, int c)
+ed_redisplay(EditLine *el __attribute__((__unused__)), 
+            int c __attribute__((__unused__)))
 {
-    return CC_REDISPLAY;
+
+       return (CC_REDISPLAY);
 }
 
 
@@ -611,10 +608,11 @@ ed_redisplay(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_start_over(EditLine *el, int c)
+ed_start_over(EditLine *el, int c __attribute__((__unused__)))
 {
-    ch_reset(el);
-    return CC_REFRESH;
+
+       ch_reset(el);
+       return (CC_REFRESH);
 }
 
 
@@ -624,9 +622,11 @@ ed_start_over(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_sequence_lead_in(EditLine *el, int c)
+ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 
+                   int c __attribute__((__unused__)))
 {
-    return CC_NORM;
+
+       return (CC_NORM);
 }
 
 
@@ -636,32 +636,35 @@ ed_sequence_lead_in(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_history(EditLine *el, int c)
+ed_prev_history(EditLine *el, int c __attribute__((__unused__)))
 {
-    char    beep = 0;
-
-    el->el_chared.c_undo.action = NOP;
-    *el->el_line.lastchar = '\0';              /* just in case */
+       char beep = 0;
+       int sv_event = el->el_history.eventno;
 
-    if (el->el_history.eventno == 0) { /* save the current buffer away */
-       (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
-       el->el_history.last = el->el_history.buf +
-               (el->el_line.lastchar - el->el_line.buffer);
-    }
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';           /* just in case */
 
-    el->el_history.eventno += el->el_state.argument;
-
-    if (hist_get(el) == CC_ERROR) {
-       beep = 1;
-       /* el->el_history.eventno was fixed by first call */
-       (void) hist_get(el);
-    }
-
-    re_refresh(el);
-    if (beep)
-       return CC_ERROR;
-    else
-       return CC_NORM; /* was CC_UP_HIST */
+       if (el->el_history.eventno == 0) {      /* save the current buffer
+                                                * away */
+               (void) strncpy(el->el_history.buf, el->el_line.buffer,
+                   EL_BUFSIZ);
+               el->el_history.last = el->el_history.buf +
+                   (el->el_line.lastchar - el->el_line.buffer);
+       }
+       el->el_history.eventno += el->el_state.argument;
+
+       if (hist_get(el) == CC_ERROR) {
+               if (el->el_map.type == MAP_VI) {
+                       el->el_history.eventno = sv_event;
+                       return CC_ERROR;
+               }
+               beep = 1;
+               /* el->el_history.eventno was fixed by first call */
+               (void) hist_get(el);
+       }
+       if (beep)
+               return CC_REFRESH_BEEP;
+       return CC_REFRESH;
 }
 
 
@@ -671,19 +674,24 @@ ed_prev_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_history(EditLine *el, int c)
+ed_next_history(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_chared.c_undo.action = NOP;
-    *el->el_line.lastchar = '\0';              /* just in case */
+       el_action_t beep = CC_REFRESH, rval;
 
-    el->el_history.eventno -= el->el_state.argument;
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
 
-    if (el->el_history.eventno < 0) {
-       el->el_history.eventno = 0;
-       return CC_ERROR;        /* make it beep */
-    }
+       el->el_history.eventno -= el->el_state.argument;
+
+       if (el->el_history.eventno < 0) {
+               el->el_history.eventno = 0;
+               beep = CC_REFRESH_BEEP;
+       }
+       rval = hist_get(el);
+       if (rval == CC_REFRESH)
+               return beep;
+       return rval;
 
-    return hist_get(el);
 }
 
 
@@ -693,67 +701,65 @@ ed_next_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_search_prev_history(EditLine *el, int c)
+ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))
 {
-    const char *hp;
-    int h;
-    bool_t    found = 0;
+       const char *hp;
+       int h;
+       bool_t found = 0;
 
-    el->el_chared.c_vcmd.action = NOP;
-    el->el_chared.c_undo.action = NOP;
-    *el->el_line.lastchar = '\0';              /* just in case */
-    if (el->el_history.eventno < 0) {
+       el->el_chared.c_vcmd.action = NOP;
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+       if (el->el_history.eventno < 0) {
 #ifdef DEBUG_EDIT
-       (void) fprintf(el->el_errfile, "e_prev_search_hist(): eventno < 0;\n");
+               (void) fprintf(el->el_errfile,
+                   "e_prev_search_hist(): eventno < 0;\n");
 #endif
-       el->el_history.eventno = 0;
-       return CC_ERROR;
-    }
-
-    if (el->el_history.eventno == 0) {
-       (void) strncpy(el->el_history.buf, el->el_line.buffer, EL_BUFSIZ);
-       el->el_history.last = el->el_history.buf +
-               (el->el_line.lastchar - el->el_line.buffer);
-    }
-
-
-    if (el->el_history.ref == NULL)
-       return CC_ERROR;
+               el->el_history.eventno = 0;
+               return (CC_ERROR);
+       }
+       if (el->el_history.eventno == 0) {
+               (void) strncpy(el->el_history.buf, el->el_line.buffer,
+                   EL_BUFSIZ);
+               el->el_history.last = el->el_history.buf +
+                   (el->el_line.lastchar - el->el_line.buffer);
+       }
+       if (el->el_history.ref == NULL)
+               return (CC_ERROR);
 
-    hp = HIST_FIRST(el);
-    if (hp == NULL)
-       return CC_ERROR;
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return (CC_ERROR);
 
-    c_setpat(el);              /* Set search pattern !! */
+       c_setpat(el);           /* Set search pattern !! */
 
-    for (h = 1; h <= el->el_history.eventno; h++)
-       hp = HIST_NEXT(el);
+       for (h = 1; h <= el->el_history.eventno; h++)
+               hp = HIST_NEXT(el);
 
-    while (hp != NULL) {
+       while (hp != NULL) {
 #ifdef SDEBUG
-       (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
 #endif
-       if ((strncmp(hp, el->el_line.buffer,
-                    el->el_line.lastchar - el->el_line.buffer) ||
-           hp[el->el_line.lastchar-el->el_line.buffer]) &&
-           c_hmatch(el, hp)) {
-           found++;
-           break;
+               if ((strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp)) {
+                       found++;
+                       break;
+               }
+               h++;
+               hp = HIST_NEXT(el);
        }
-       h++;
-       hp = HIST_NEXT(el);
-    }
 
-    if (!found) {
+       if (!found) {
 #ifdef SDEBUG
-       (void) fprintf(el->el_errfile, "not found\n");
+               (void) fprintf(el->el_errfile, "not found\n");
 #endif
-       return CC_ERROR;
-    }
-
-    el->el_history.eventno = h;
+               return (CC_ERROR);
+       }
+       el->el_history.eventno = h;
 
-    return hist_get(el);
+       return (hist_get(el));
 }
 
 
@@ -763,52 +769,51 @@ ed_search_prev_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_search_next_history(EditLine *el, int c)
+ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))
 {
-    const char *hp;
-    int h;
-    bool_t    found = 0;
+       const char *hp;
+       int h;
+       bool_t found = 0;
 
-    el->el_chared.c_vcmd.action = NOP;
-    el->el_chared.c_undo.action = NOP;
-    *el->el_line.lastchar = '\0';              /* just in case */
+       el->el_chared.c_vcmd.action = NOP;
+       el->el_chared.c_undo.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
 
-    if (el->el_history.eventno == 0)
-       return CC_ERROR;
+       if (el->el_history.eventno == 0)
+               return (CC_ERROR);
 
-    if (el->el_history.ref == NULL)
-       return CC_ERROR;
+       if (el->el_history.ref == NULL)
+               return (CC_ERROR);
 
-    hp = HIST_FIRST(el);
-    if (hp == NULL)
-       return CC_ERROR;
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return (CC_ERROR);
 
-    c_setpat(el);              /* Set search pattern !! */
+       c_setpat(el);           /* Set search pattern !! */
 
-    for (h = 1; h < el->el_history.eventno && hp; h++) {
+       for (h = 1; h < el->el_history.eventno && hp; h++) {
 #ifdef SDEBUG
-       (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
 #endif
-       if ((strncmp(hp, el->el_line.buffer,
-                    el->el_line.lastchar - el->el_line.buffer) ||
-            hp[el->el_line.lastchar-el->el_line.buffer]) &&
-           c_hmatch(el, hp))
-           found = h;
-       hp = HIST_NEXT(el);
-    }
-
-    if (!found) {              /* is it the current history number? */
-       if (!c_hmatch(el, el->el_history.buf)) {
+               if ((strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp))
+                       found = h;
+               hp = HIST_NEXT(el);
+       }
+
+       if (!found) {           /* is it the current history number? */
+               if (!c_hmatch(el, el->el_history.buf)) {
 #ifdef SDEBUG
-           (void) fprintf(el->el_errfile, "not found\n");
+                       (void) fprintf(el->el_errfile, "not found\n");
 #endif
-           return CC_ERROR;
+                       return (CC_ERROR);
+               }
        }
-    }
-
-    el->el_history.eventno = found;
+       el->el_history.eventno = found;
 
-    return hist_get(el);
+       return (hist_get(el));
 }
 
 
@@ -818,40 +823,40 @@ ed_search_next_history(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_prev_line(EditLine *el, int c)
+ed_prev_line(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *ptr;
-    int nchars = c_hpos(el);
+       char *ptr;
+       int nchars = c_hpos(el);
 
-    /*
-     * Move to the line requested
-     */
-    if (*(ptr = el->el_line.cursor) == '\n')
-       ptr--;
+       /*
+         * Move to the line requested
+         */
+       if (*(ptr = el->el_line.cursor) == '\n')
+               ptr--;
 
-    for (; ptr >= el->el_line.buffer; ptr--)
-       if (*ptr == '\n' && --el->el_state.argument <= 0)
-           break;
+       for (; ptr >= el->el_line.buffer; ptr--)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
 
-    if (el->el_state.argument > 0)
-       return CC_ERROR;
+       if (el->el_state.argument > 0)
+               return (CC_ERROR);
 
-    /*
-     * Move to the beginning of the line
-     */
-    for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
-       continue;
+       /*
+         * Move to the beginning of the line
+         */
+       for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
+               continue;
 
-    /*
-     * Move to the character requested
-     */
-    for (ptr++;
-        nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
-        ptr++)
-       continue;
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
 
-    el->el_line.cursor = ptr;
-    return CC_CURSOR;
+       el->el_line.cursor = ptr;
+       return (CC_CURSOR);
 }
 
 
@@ -861,31 +866,31 @@ ed_prev_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_next_line(EditLine *el, int c)
+ed_next_line(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *ptr;
-    int nchars = c_hpos(el);
+       char *ptr;
+       int nchars = c_hpos(el);
 
-    /*
-     * Move to the line requested
-     */
-    for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
-       if (*ptr == '\n' && --el->el_state.argument <= 0)
-           break;
+       /*
+         * Move to the line requested
+         */
+       for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
 
-    if (el->el_state.argument > 0)
-       return CC_ERROR;
+       if (el->el_state.argument > 0)
+               return (CC_ERROR);
 
-    /*
-     * Move to the character requested
-     */
-    for (ptr++;
-        nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
-        ptr++)
-       continue;
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
 
-    el->el_line.cursor = ptr;
-    return CC_CURSOR;
+       el->el_line.cursor = ptr;
+       return (CC_CURSOR);
 }
 
 
@@ -895,30 +900,18 @@ ed_next_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-ed_command(EditLine *el, int c)
+ed_command(EditLine *el, int c __attribute__((__unused__)))
 {
-    char tmpbuf[EL_BUFSIZ];
-    int tmplen;
-
-    el->el_line.buffer[0] = '\0';
-    el->el_line.lastchar = el->el_line.buffer;
-    el->el_line.cursor = el->el_line.buffer;
-
-    c_insert(el, 3);   /* prompt + ": " */
-    *el->el_line.cursor++ = '\n';
-    *el->el_line.cursor++ = ':';
-    *el->el_line.cursor++ = ' ';
-    re_refresh(el);
+       char tmpbuf[EL_BUFSIZ];
+       int tmplen;
 
-    tmplen = c_gets(el, tmpbuf);
-    tmpbuf[tmplen] = '\0';
+       tmplen = c_gets(el, tmpbuf, "\n: ");
+       term__putc('\n');
 
-    el->el_line.buffer[0] = '\0';
-    el->el_line.lastchar = el->el_line.buffer;
-    el->el_line.cursor = el->el_line.buffer;
+       if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
+               term_beep(el);
 
-    if (parse_line(el, tmpbuf) == -1)
-       return CC_ERROR;
-    else
+       el->el_map.current = el->el_map.key;
+       re_clear_display(el);
        return CC_REFRESH;
 }
diff --git a/lib/libedit/config.h b/lib/libedit/config.h
new file mode 100644 (file)
index 0000000..5671b01
--- /dev/null
@@ -0,0 +1,19 @@
+/* $DragonFly: src/lib/libedit/config.h,v 1.1 2005/11/13 11:58:30 corecode Exp $ */
+/* config.h.  Generated automatically by configure.  */
+/* #undef SUNOS */
+
+#define HAVE_SYS_CDEFS_H 1
+#define HAVE_TERMCAP_H 1
+#define HAVE_CURSES_H 1
+#define HAVE_NCURSES_H 1
+#define HAVE_TERM_H 1
+#define HAVE_VIS_H 1
+#define HAVE_ISSETUGID 1
+
+#define HAVE_STRLCAT 1
+#define HAVE_STRLCPY 1
+#define HAVE_FGETLN 1
+#define HAVE_STRVIS 1
+#define HAVE_STRUNVIS 1
+
+#include "sys.h"
index 1689b27..11836ef 100644 (file)
@@ -1,6 +1,4 @@
-.\"    $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $
-.\"
-.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
 .\" All rights reserved.
 .\"
 .\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
@@ -24,8 +22,8 @@
 .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
-.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libedit/editline.3,v 1.8.2.7 2001/12/17 10:08:30 ru Exp $
-.\" $DragonFly: src/lib/libedit/editline.3,v 1.2 2003/06/17 04:26:49 dillon Exp $
+.\" $NetBSD: editline.3,v 1.46 2005/03/19 17:36:02 christos Exp $
+.\" $DragonFly: src/lib/libedit/editline.3,v 1.3 2005/11/13 11:58:30 corecode Exp $
 .\"
-.Dd January 11, 1997
+.Dd March 19, 2005
 .Os
 .Dt EDITLINE 3
 .Sh NAME
 .Nm el_line ,
 .Nm el_insertstr ,
 .Nm el_deletestr ,
-.Nm el_data_set ,
-.Nm el_data_get ,
 .Nm history_init ,
 .Nm history_end ,
-.Nm history
-.Nd line editor and history functions
+.Nm history ,
+.Nm tok_init ,
+.Nm tok_end ,
+.Nm tok_reset ,
+.Nm tok_line ,
+.Nm tok_str
+.Nd line editor, history and tokenization functions
 .Sh LIBRARY
 .Lb libedit
 .Sh SYNOPSIS
 .In histedit.h
 .Ft EditLine *
-.Fn el_init "const char *prog" "FILE *fin" "FILE *fout"
+.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr"
 .Ft void
 .Fn el_end "EditLine *e"
 .Ft void
 .Ft void
 .Fn el_push "EditLine *e" "const char *str"
 .Ft int
-.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
+.Fn el_parse "EditLine *e" "int argc" "const char *argv[]"
 .Ft int
 .Fn el_set "EditLine *e" "int op" "..."
 .Ft int
+.Fn el_get "EditLine *e" "int op" "void *result"
+.Ft int
 .Fn el_source "EditLine *e" "const char *file"
 .Ft void
 .Fn el_resize "EditLine *e"
 .Ft const LineInfo *
 .Fn el_line "EditLine *e"
 .Ft int
-.Fn el_insertstr "EditLine *e" "char *str"
+.Fn el_insertstr "EditLine *e" "const char *str"
 .Ft void
 .Fn el_deletestr "EditLine *e" "int count"
-.Ft void
-.Fn el_data_set "EditLine *e" "void *data"
-.Ft void *
-.Fn el_data_get "EditLine *e"
 .Ft History *
 .Fn history_init
 .Ft void
 .Fn history_end "History *h"
-.Ft const HistEvent *
-.Fn history "History *h" "int op" "..."
+.Ft int
+.Fn history "History *h" "HistEvent *ev" "int op" "..."
+.Ft Tokenizer *
+.Fn tok_init "const char *IFS"
+.Ft void
+.Fn tok_end "Tokenizer *t"
+.Ft void
+.Fn tok_reset "Tokenizer *t"
+.Ft int
+.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro"
+.Ft int
+.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]"
 .Sh DESCRIPTION
 The
 .Nm
-library provides generic line editing and history functions,
+library provides generic line editing, history and tokenization functions,
 similar to those found in
 .Xr sh 1 .
 .Pp
@@ -131,10 +140,11 @@ to be used by all other line editing functions.
 is the name of the invoking program, used when reading the
 .Xr editrc 5
 file to determine which settings to use.
-.Fa fin
-and
+.Fa fin ,
 .Fa fout
-are the input and output streams (respectively) to use.
+and
+.Fa ferr
+are the input, output, and error streams (respectively) to use.
 In this documentation, references to
 .Dq the tty
 are actually to this input/output stream combination.
@@ -158,7 +168,7 @@ if no characters were read or if an error occurred.
 Read a character from the tty.
 .Fa ch
 is modified to contain the character read.
-Returns the number of characters read if successful, -1 otherwise.
+Returns the number of characters read if successful, \-1 otherwise.
 .It Fn el_push
 Pushes
 .Fa str
@@ -180,7 +190,7 @@ to execute builtin
 .Nm
 commands.
 If the command is prefixed with
-.Dq prog:
+.Dq prog :
 then
 .Fn el_parse
 will only execute the command if
@@ -190,7 +200,7 @@ matches the
 argument supplied to
 .Fn el_init .
 The return value is
--1 if the command is unknown,
+\-1 if the command is unknown,
 0 if there was no error or
 .Dq prog
 didn't match, or
@@ -198,17 +208,6 @@ didn't match, or
 Refer to
 .Xr editrc 5
 for more information.
-.Pp
-.Em NOTE :
-.Va argv[0]
-may be modified by
-.Fn el_parse .
-The colon between
-.Dq prog
-and the command,
-.Ar command ,
-will be replaced with a NUL
-.Pq Dq \e0 .
 .It Fn el_set
 Set
 .Nm
@@ -225,6 +224,10 @@ are supported, along with the required argument list:
 Define prompt printing function as
 .Fa f ,
 which is to return a string that contains the prompt.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
+Define right side prompt printing function as
+.Fa f ,
+which is to return a string that contains the prompt.
 .It Dv EL_TERMINAL , Fa "const char *type"
 Define terminal type of the tty to be
 .Fa type ,
@@ -316,7 +319,7 @@ for more information.
 .It Dv EL_ADDFN , Xo
 .Fa "const char *name" ,
 .Fa "const char *help" ,
-.Fa "unsigned char (*func)(EditLine *e, int ch)
+.Fa "unsigned char (*func)(EditLine *e, int ch)"
 .Xc
 Add a user defined function,
 .Fn func ,
@@ -345,6 +348,8 @@ EOF was entered.
 Expecting further command input as arguments, do nothing visually.
 .It Dv CC_REFRESH
 Refresh display.
+.It Dv CC_REFRESH_BEEP
+Refresh display, and beep.
 .It Dv CC_CURSOR
 Cursor moved, so update and perform
 .Dv CC_REFRESH .
@@ -366,6 +371,85 @@ Defines which history function to use, which is usually
 .Fa ptr
 should be the value returned by
 .Fn history_init .
+.It Dv EL_EDITMODE , Fa "int flag"
+If
+.Fa flag
+is non-zero,
+editing is enabled (the default).
+Note that this is only an indication, and does not
+affect the operation of
+.Nm .
+At this time, it is the caller's responsibility to
+check this
+(using
+.Fn el_get )
+to determine if editing should be enabled or not.
+.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
+Define the character reading function as
+.Fa f ,
+which is to return the number of characters read and store them in
+.Fa c .
+This function is called internally by
+.Fn el_gets
+and
+.Fn el_getc .
+The builtin function can be set or restored with the special function
+name ``EL_BUILTIN_GETCFN''.
+.It Dv EL_CLIENTDATA , Fa "void *data"
+Register
+.Fa data
+to be associated with this EditLine structure.
+It can be retrieved with the corresponding
+.Fn el_get
+call.
+.El
+.It Fn el_get
+Get
+.Nm
+parameters.
+.Fa op
+determines which parameter to retrieve into
+.Fa result .
+Returns 0 if successful, \-1 otherwise.
+.Pp
+The following values for
+.Fa op
+are supported, along with actual type of
+.Fa result :
+.Bl -tag -width 4n
+.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
+Return a pointer to the function that displays the prompt.
+.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)"
+Return a pointer to the function that displays the rightside prompt.
+.It Dv EL_EDITOR , Fa "const char *"
+Return the name of the editor, which will be one of
+.Dq emacs
+or
+.Dq vi .
+.It Dv EL_SIGNAL , Fa "int *"
+Return non-zero if
+.Nm
+has installed private signal handlers (see
+.Fn el_get
+above).
+.It Dv EL_EDITMODE, Fa "int *"
+Return non-zero if editing is enabled.
+.It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"
+Return a pointer to the function that read characters, which is equal to
+``EL_BUILTIN_GETCFN'' in the case of the default builtin function.
+.It Dv EL_CLIENTDATA , Fa "void **data"
+Retrieve
+.Fa data
+previously registered with the corresponding
+.Fn el_set
+call.
+.It Dv EL_UNBUFFERED, Fa "int"
+Sets or clears unbuffered mode.
+In this mode,
+.Fn el_gets
+will return immediately after processing a single character.
+.It Dv EL_PREP_TERM, Fa "int"
+Sets or clears terminal editing mode.
 .El
 .It Fn el_source
 Initialise
@@ -380,6 +464,8 @@ If
 is
 .Dv NULL ,
 try
+.Pa $PWD/.editrc
+then
 .Pa $HOME/.editrc .
 Refer to
 .Xr editrc 5
@@ -406,22 +492,27 @@ typedef struct lineinfo {
     const char *lastchar;  /* address of last character */
 } LineInfo;
 .Ed
+.Pp
+.Fa buffer
+is not NUL terminated.
+This function may be called after
+.Fn el_gets
+to obtain the
+.Fa LineInfo
+structure pertaining to line returned by that function,
+and from within user defined functions added with
+.Dv EL_ADDFN .
 .It Fn el_insertstr
 Insert
 .Fa str
 into the line at the cursor.
-Returns -1 if
+Returns \-1 if
 .Fa str
 is empty or won't fit, and 0 otherwise.
 .It Fn el_deletestr
 Delete
 .Fa num
 characters before the cursor.
-.It Fn el_data_set
-Set the user data to
-.Fa data .
-.It Fn el_data_get
-Get the user data.
 .El
 .Sh HISTORY LIST FUNCTIONS
 The history functions use a common data structure,
@@ -446,14 +537,18 @@ Perform operation
 .Fa op
 on the history list, with optional arguments as needed by the
 operation.
+.Fa ev
+is changed accordingly to operation.
 The following values for
 .Fa op
 are supported, along with the required argument list:
 .Bl -tag -width 4n
-.It Dv H_EVENT , Fa "int size"
+.It Dv H_SETSIZE , Fa "int size"
 Set size of history to
 .Fa size
 elements.
+.It Dv H_GETSIZE
+Get number of events currently in history.
 .It Dv H_END
 Cleans up and finishes with
 .Fa h ,
@@ -468,6 +563,7 @@ Clear the history.
 .Fa "history_gfun_t last" ,
 .Fa "history_gfun_t prev" ,
 .Fa "history_gfun_t curr" ,
+.Fa "history_sfun_t set" ,
 .Fa "history_vfun_t clear" ,
 .Fa "history_efun_t enter" ,
 .Fa "history_efun_t add"
@@ -485,17 +581,36 @@ Return the previous element in the history.
 Return the next element in the history.
 .It Dv H_CURR
 Return the current element in the history.
+.It Dv H_SET
+Set the cursor to point to the requested element.
 .It Dv H_ADD , Fa "const char *str"
 Append
 .Fa str
-to the current element of the history, or create an element with
+to the current element of the history, or perform the
 .Dv H_ENTER
-if there isn't one.
+operation with argument
+.Fa str
+if there is no current element.
+.It Dv H_APPEND , Fa "const char *str"
+Append
+.Fa str
+to the last new element of the history.
 .It Dv H_ENTER , Fa "const char *str"
 Add
 .Fa str
 as a new element to the history, and, if necessary,
 removing the oldest entry to keep the list to the created size.
+If
+.Dv H_SETUNIQUE
+was has been called with a non-zero arguments, the element
+will not be entered into the history if its contents match
+the ones of the current history element.
+If the element is entered
+.Fn history
+returns 1, if it is ignored as a duplicate returns 0.
+Finally
+.Fn history
+returns \-1 if an error occurred.
 .It Dv H_PREV_STR , Fa "const char *str"
 Return the closest previous event that starts with
 .Fa str .
@@ -514,8 +629,94 @@ Load the history list stored in
 .It Dv H_SAVE , Fa "const char *file"
 Save the history list to
 .Fa file .
+.It Dv H_SETUNIQUE , Fa "int unique"
+Set if the adjacent identical event strings should not be entered into
+the history.
+.It Dv H_GETUNIQUE
+Retrieve the current setting if if adjacent elements should be entered into
+the history.
 .El
+.Pp
+.Fn history
+returns \*[Gt]= 0 if the operation
+.Fa op
+succeeds.
+Otherwise, \-1 is returned and
+.Fa ev
+is updated to contain more details about the error.
 .El
+.Sh TOKENIZATION FUNCTIONS
+The tokenization functions use a common data structure,
+.Fa Tokenizer ,
+which is created by
+.Fn tok_init
+and freed by
+.Fn tok_end .
+.Pp
+The following functions are available:
+.Bl -tag -width 4n
+.It Fn tok_init
+Initialise the tokenizer, and return a data structure
+to be used by all other tokenizer functions.
+.Fa IFS
+contains the Input Field Separators, which defaults to
+.Aq space ,
+.Aq tab ,
+and
+.Aq newline
+if
+.Dv NULL .
+.It Fn tok_end
+Clean up and finish with
+.Fa t ,
+assumed to have been created with
+.Fn tok_init .
+.It Fn tok_reset
+Reset the tokenizer state.
+Use after a line has been successfully tokenized
+by
+.Fn tok_line
+or
+.Fn tok_str
+and before a new line is to be tokenized.
+.It Fn tok_line
+Tokenize
+.Fa li ,
+If successful, modify:
+.Fa argv
+to contain the words,
+.Fa argc
+to contain the number of words,
+.Fa cursorc
+(if not
+.Dv NULL )
+to contain the index of the word containing the cursor,
+and
+.Fa cursoro
+(if not
+.Dv NULL )
+to contain the offset within
+.Fa argv[cursorc]
+of the cursor.
+.Pp
+Returns
+0 if successful,
+\-1 for an internal error,
+1 for an unmatched single quote,
+2 for an unmatched double quote,
+and
+3 for a backslash quoted
+.Aq newline .
+A positive exit code indicates that another line should be read
+and tokenization attempted again.
+.
+.It Fn tok_str
+A simpler form of
+.Fn tok_line ;
+.Fa str
+is a NUL terminated string to tokenize.
+.El
+.
 .\"XXX.Sh EXAMPLES
 .\"XXX: provide some examples
 .Sh SEE ALSO
@@ -528,20 +729,43 @@ The
 .Nm
 library first appeared in
 .Bx 4.4 .
+.Dv CC_REDISPLAY
+appeared in
+.Nx 1.3 .
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE
+and the readline emulation appeared in
+.Nx 1.4 .
+.Dv EL_RPROMPT
+appeared in
+.Nx 1.5 .
 .Sh AUTHORS
-.An -nosplit
 The
 .Nm
-library was written by
-.An Christos Zoulas ,
-and this manual was written by
-.An Luke Mewburn .
+library was written by Christos Zoulas.
+Luke Mewburn wrote this manual and implemented
+.Dv CC_REDISPLAY ,
+.Dv CC_REFRESH_BEEP ,
+.Dv EL_EDITMODE ,
+and
+.Dv EL_RPROMPT .
+Jaromir Dolecek implemented the readline emulation.
 .Sh BUGS
-This documentation is probably incomplete.
-.Pp
-.Fn el_parse
-should not modify the supplied
-.Va argv[0] .
-.Pp
-The tokenization functions are not publicly defined in
-.Li <histedit.h> .
+At this time, it is the responsibility of the caller to
+check the result of the
+.Dv EL_EDITMODE
+operation of
+.Fn el_get
+(after an
+.Fn el_source
+or
+.Fn el_parse )
+to determine if
+.Nm
+should be used for further input.
+I.e.,
+.Dv EL_EDITMODE
+is purely an indication of the result of the most recent
+.Xr editrc 5
+.Ic edit
+command.
index 686944c..563a231 100644 (file)
@@ -1,6 +1,4 @@
-.\"    $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $
-.\"
-.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
 .\" All rights reserved.
 .\"
 .\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
@@ -24,8 +22,8 @@
 .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
-.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libedit/editrc.5,v 1.5.2.4 2001/08/17 15:42:57 ru Exp $
-.\" $DragonFly: src/lib/libedit/editrc.5,v 1.2 2003/06/17 04:26:49 dillon Exp $
+.\" $NetBSD: editrc.5,v 1.19 2003/11/01 23:35:33 christos Exp $
+.\" $DragonFly: src/lib/libedit/editrc.5,v 1.3 2005/11/13 11:58:30 corecode Exp $
 .\"
-.Dd January 11, 1997
+.Dd October 18, 2003
 .Os
 .Dt EDITRC 5
 .Sh NAME
@@ -51,10 +49,8 @@ file defines various settings to be used by the
 .Xr editline 3
 library.
 .Pp
-The format of each line is either:
-.Dl prog:command [arg [...]]
-or
-.Dl command [arg [...]]
+The format of each line is:
+.Dl [prog:]command [arg [...]]
 .Pp
 .Ar command
 is one of the
@@ -67,7 +63,7 @@ for more information.
 .Ar prog
 is the program name string that a program defines when it calls
 .Xr el_init 3
-to setup
+to set up
 .Xr editline 3 ,
 which is usually
 .Va argv[0] .
@@ -82,6 +78,12 @@ style
 regular expression, in which case
 .Ar command
 will be executed for any program that matches the regular expression.
+.Pp
+If
+.Ar prog
+is absent,
+.Ar command
+is executed for all programs.
 .Sh BUILTIN COMMANDS
 The
 .Nm editline
@@ -150,6 +152,11 @@ are themselves reinterpreted, and this continues for ten levels of
 interpretation.
 .El
 .Pp
+.Ar command
+may be one of the commands documented in
+.Sx "EDITOR COMMANDS"
+below, or another key.
+.Pp
 .Ar key
 and
 .Ar command
@@ -157,8 +164,10 @@ can contain control characters of the form
 .Sm off
 .Sq No ^ Ar character
 .Sm on
-(e.g.\&
-.Sq ^A ) ,
+.Po
+e.g.
+.Sq ^A
+.Pc ,
 and the following backslashed escape sequences:
 .Pp
 .Bl -tag -compact -offset indent -width 4n
@@ -218,8 +227,28 @@ returns an empty string for non-existent capabilities, rather than
 causing an error.
 .Fl v
 causes messages to be verbose.
-.It Ic history
-List the history.
+.It Ic edit Op Li on | Li off
+Enable or disable the
+.Nm editline
+functionality in a program.
+.It Ic history Ar list | Ar size Dv n | Ar unique Dv n
+The 
+.Ar list
+command lists all entries in the history.
+The
+.Ar size
+command sets the history size to
+.Dv n
+entries.
+The
+.Ar unique
+command controls if history should keep duplicate entries.
+If
+.Dv n
+is non zero, only keep unique history entries.
+If
+.Dv n
+is zero, then keep all entries (the default).
 .It Ic telltc
 List the values of all the terminal capabilities (see
 .Xr termcap 5 ) .
@@ -239,6 +268,7 @@ No sanity checking is done.
 .Op Ar +mode
 .Op Ar -mode
 .Op Ar mode
+.Op Ar char=c
 .Xc
 Control which tty modes that
 .Nm
@@ -260,9 +290,13 @@ set of tty modes respectively; defaulting to
 Without other arguments,
 .Ic setty
 lists the modes in the chosen set which are fixed on
-.Pq Sq +mode
+.Po
+.Sq +mode
+.Pc
 or off
-.Pq Sq -mode .
+.Po
+.Sq -mode
+.Pc .
 .Fl a
 lists all tty modes in the chosen set regardless of the setting.
 With
@@ -275,18 +309,210 @@ fixes
 on or off or removes control of
 .Ar mode
 in the chosen set.
+.Pp
+.Ic Setty
+can also be used to set tty characters to particular values using
+.Ar char=value .
+If
+.Ar value
+is empty
+then the character is set to
+.Dv _POSIX_VDISABLE .
+.El
+.Sh EDITOR COMMANDS
+The following editor commands are available for use in key bindings:
+.\" Section automatically generated with makelist
+.Bl -tag -width 4n
+.It Ic vi-paste-next
+Vi paste previous deletion to the right of the cursor.
+.It Ic vi-paste-prev
+Vi paste previous deletion to the left of the cursor.
+.It Ic vi-prev-space-word
+Vi move to the previous space delimited word.
+.It Ic vi-prev-word
+Vi move to the previous word.
+.It Ic vi-next-space-word
+Vi move to the next space delimited word.
+.It Ic vi-next-word
+Vi move to the next word.
+.It Ic vi-change-case
+Vi change case of character under the cursor and advance one character.
+.It Ic vi-change-meta
+Vi change prefix command.
+.It Ic vi-insert-at-bol
+Vi enter insert mode at the beginning of line.
+.It Ic vi-replace-char
+Vi replace character under the cursor with the next character typed.
+.It Ic vi-replace-mode
+Vi enter replace mode.
+.It Ic vi-substitute-char
+Vi replace character under the cursor and enter insert mode.
+.It Ic vi-substitute-line
+Vi substitute entire line.
+.It Ic vi-change-to-eol
+Vi change to end of line.
+.It Ic vi-insert
+Vi enter insert mode.
+.It Ic vi-add
+Vi enter insert mode after the cursor.
+.It Ic vi-add-at-eol
+Vi enter insert mode at end of line.
+.It Ic vi-delete-meta
+Vi delete prefix command.
+.It Ic vi-end-word
+Vi move to the end of the current space delimited word.
+.It Ic vi-to-end-word
+Vi move to the end of the current word.
+.It Ic vi-undo
+Vi undo last change.
+.It Ic vi-command-mode
+Vi enter command mode (use alternative key bindings).
+.It Ic vi-zero
+Vi move to the beginning of line.
+.It Ic vi-delete-prev-char
+Vi move to previous character (backspace).
+.It Ic vi-list-or-eof
+Vi list choices for completion or indicate end of file if empty line.
+.It Ic vi-kill-line-prev
+Vi cut from beginning of line to cursor.
+.It Ic vi-search-prev
+Vi search history previous.
+.It Ic vi-search-next
+Vi search history next.
+.It Ic vi-repeat-search-next
+Vi repeat current search in the same search direction.
+.It Ic vi-repeat-search-prev
+Vi repeat current search in the opposite search direction.
+.It Ic vi-next-char
+Vi move to the character specified next.
+.It Ic vi-prev-char
+Vi move to the character specified previous.
+.It Ic vi-to-next-char
+Vi move up to the character specified next.
+.It Ic vi-to-prev-char
+Vi move up to the character specified previous.
+.It Ic vi-repeat-next-char
+Vi repeat current character search in the same search direction.
+.It Ic vi-repeat-prev-char
+Vi repeat current character search in the opposite search direction.
+.It Ic em-delete-or-list
+Delete character under cursor or list completions if at end of line.
+.It Ic em-delete-next-word
+Cut from cursor to end of current word.
+.It Ic em-yank
+Paste cut buffer at cursor position.
+.It Ic em-kill-line
+Cut the entire line and save in cut buffer.
+.It Ic em-kill-region
+Cut area between mark and cursor and save in cut buffer.
+.It Ic em-copy-region
+Copy area between mark and cursor to cut buffer.
+.It Ic em-gosmacs-transpose
+Exchange the two characters before the cursor.
+.It Ic em-next-word
+Move next to end of current word.
+.It Ic em-upper-case
+Uppercase the characters from cursor to end of current word.
+.It Ic em-capitol-case
+Capitalize the characters from cursor to end of current word.
+.It Ic em-lower-case
+Lowercase the characters from cursor to end of current word.
+.It Ic em-set-mark
+Set the mark at cursor.
+.It Ic em-exchange-mark
+Exchange the cursor and mark.
+.It Ic em-universal-argument
+Universal argument (argument times 4).
+.It Ic em-meta-next
+Add 8th bit to next character typed.
+.It Ic em-toggle-overwrite
+Switch from insert to overwrite mode or vice versa.
+.It Ic em-copy-prev-word
+Copy current word to cursor.
+.It Ic em-inc-search-next
+Emacs incremental next search.
+.It Ic em-inc-search-prev
+Emacs incremental reverse search.
+.It Ic ed-end-of-file
+Indicate end of file.
+.It Ic ed-insert
+Add character to the line.
+.It Ic ed-delete-prev-word
+Delete from beginning of current word to cursor.
+.It Ic ed-delete-next-char
+Delete character under cursor.
+.It Ic ed-kill-line
+Cut to the end of line.
+.It Ic ed-move-to-end
+Move cursor to the end of line.
+.It Ic ed-move-to-beg
+Move cursor to the beginning of line.
+.It Ic ed-transpose-chars
+Exchange the character to the left of the cursor with the one under it.
+.It Ic ed-next-char
+Move to the right one character.
+.It Ic ed-prev-word
+Move to the beginning of the current word.
+.It Ic ed-prev-char
+Move to the left one character.
+.It Ic ed-quoted-insert
+Add the next character typed verbatim.
+.It Ic ed-digit
+Adds to argument or enters a digit.
+.It Ic ed-argument-digit
+Digit that starts argument.
+.It Ic ed-unassigned
+Indicates unbound character.
+.It Ic ed-tty-sigint
+Tty interrupt character.
+.It Ic ed-tty-dsusp
+Tty delayed suspend character.
+.It Ic ed-tty-flush-output
+Tty flush output characters.
+.It Ic ed-tty-sigquit
+Tty quit character.
+.It Ic ed-tty-sigtstp
+Tty suspend character.
+.It Ic ed-tty-stop-output
+Tty disallow output characters.
+.It Ic ed-tty-start-output
+Tty allow output characters.
+.It Ic ed-newline
+Execute command.
+.It Ic ed-delete-prev-char
+Delete the character to the left of the cursor.
+.It Ic ed-clear-screen
+Clear screen leaving current line at the top.
+.It Ic ed-redisplay
+Redisplay everything.
+.It Ic ed-start-over
+Erase current line and start from scratch.
+.It Ic ed-sequence-lead-in
+First character in a bound sequence.
+.It Ic ed-prev-history
+Move to the previous history line.
+.It Ic ed-next-history
+Move to the next history line.
+.It Ic ed-search-prev-history
+Search previous in history for a line matching the current.
+.It Ic ed-search-next-history
+Search next in history for a line matching the current.
+.It Ic ed-prev-line
+Move up one line.
+.It Ic ed-next-line
+Move down one line.
+.It Ic ed-command
+Editline extended command.
 .El
+.\" End of section automatically generated with makelist
 .Sh SEE ALSO
 .Xr editline 3 ,
 .Xr regex 3 ,
 .Xr termcap 5
 .Sh AUTHORS
-.An -nosplit
 The
 .Nm editline
-library was written by
-.An Christos Zoulas ,
-and this manual was written by
-.An Luke Mewburn ,
+library was written by Christos Zoulas,
+and this manual was written by Luke Mewburn,
 with some sections inspired by
 .Xr tcsh 1 .
index b46920f..eaac5c3 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#)el.c    8.2 (Berkeley) 1/3/94
- * $FreeBSD: src/lib/libedit/el.c,v 1.6.2.1 2000/05/22 06:07:00 imp Exp $
- * $DragonFly: src/lib/libedit/el.c,v 1.4 2005/08/04 17:27:09 drhodus Exp $
+ * @(#)el.c     8.2 (Berkeley) 1/3/94
+ * $NetBSD: el.c,v 1.39 2004/07/08 00:51:36 christos Exp $
+ * $DragonFly: src/lib/libedit/el.c,v 1.5 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * el.c: EditLine interface functions
  */
-#include "sys.h"
-
 #include <sys/types.h>
 #include <sys/param.h>
-#include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
  *     Initialize editline and set default parameters.
  */
 public EditLine *
-el_init(const char *prog, FILE *fin, FILE *fout)
+el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
 {
-    EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
-#ifdef DEBUG
-    char *tty;
-#endif
 
-    if (el == NULL)
-       return NULL;
+       EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
 
-    memset(el, 0, sizeof(EditLine));
+       if (el == NULL)
+               return (NULL);
 
-    el->el_infd  = fileno(fin);
-    el->el_outfile = fout;
-    el->el_prog = strdup(prog);
+       memset(el, 0, sizeof(EditLine));
 
-#ifdef DEBUG
-    if (issetugid() == 0 && (tty = getenv("DEBUGTTY")) != NULL) {
-       el->el_errfile = fopen(tty, "w");
-       if (el->el_errfile == NULL) {
-               (void) fprintf(stderr, "Cannot open %s (%s).\n",
-                              tty, strerror(errno));
+       el->el_infd = fileno(fin);
+       el->el_outfile = fout;
+       el->el_errfile = ferr;
+       if ((el->el_prog = el_strdup(prog)) == NULL) {
+               el_free(el);
                return NULL;
        }
-    }
-    else
-#endif
-       el->el_errfile = stderr;
-
-    /*
-     * Initialize all the modules. Order is important!!!
-     */
-    (void) term_init(el);
-    (void) tty_init(el);
-    (void) key_init(el);
-    (void) map_init(el);
-    (void) ch_init(el);
-    (void) search_init(el);
-    (void) hist_init(el);
-    (void) prompt_init(el);
-    (void) sig_init(el);
-    el->el_flags = 0;
-    el->data = NULL;
-
-    return el;
-} /* end el_init */
+
+       /*
+         * Initialize all the modules. Order is important!!!
+         */
+       el->el_flags = 0;
+
+       if (term_init(el) == -1) {
+               el_free(el->el_prog);
+               el_free(el);
+               return NULL;
+       }
+       (void) key_init(el);
+       (void) map_init(el);
+       if (tty_init(el) == -1)
+               el->el_flags |= NO_TTY;
+       (void) ch_init(el);
+       (void) search_init(el);
+       (void) hist_init(el);
+       (void) prompt_init(el);
+       (void) sig_init(el);
+       (void) read_init(el);
+
+       return (el);
+}
 
 
 /* el_end():
@@ -109,24 +99,25 @@ el_init(const char *prog, FILE *fin, FILE *fout)
 public void
 el_end(EditLine *el)
 {
-    if (el == NULL)
-       return;
 
-    el_reset(el);
+       if (el == NULL)
+               return;
+
+       el_reset(el);
 
-    term_end(el);
-    tty_end(el);
-    key_end(el);
-    map_end(el);
-    ch_end(el);
-    search_end(el);
-    hist_end(el);
-    prompt_end(el);
-    sig_end(el);
+       term_end(el);
+       key_end(el);
+       map_end(el);
+       tty_end(el);
+       ch_end(el);
+       search_end(el);
+       hist_end(el);
+       prompt_end(el);
+       sig_end(el);
 
-    el_free((ptr_t) el->el_prog);
-    el_free((ptr_t) el);
-} /* end el_end */
+       el_free((ptr_t) el->el_prog);
+       el_free((ptr_t) el);
+}
 
 
 /* el_reset():
@@ -135,8 +126,9 @@ el_end(EditLine *el)
 public void
 el_reset(EditLine *el)
 {
-    tty_cookedmode(el);
-    ch_reset(el);      /* XXX: Do we want that? */
+
+       tty_cookedmode(el);
+       ch_reset(el);           /* XXX: Do we want that? */
 }
 
 
@@ -146,101 +138,273 @@ el_reset(EditLine *el)
 public int
 el_set(EditLine *el, int op, ...)
 {
-    va_list va;
-    int rv;
-    va_start(va, op);
-
-    switch (op) {
-    case EL_PROMPT:
-       rv = prompt_set(el, va_arg(va, el_pfunc_t));
-       break;
-
-    case EL_TERMINAL:
-       rv = term_set(el, va_arg(va, char *));
-       break;
-
-    case EL_EDITOR:
-       rv = map_set_editor(el, va_arg(va, char *));
-       break;
-
-    case EL_SIGNAL:
-       if (va_arg(va, int))
-           el->el_flags |= HANDLE_SIGNALS;
-       else
-           el->el_flags &= ~HANDLE_SIGNALS;
-       rv = 0;
-       break;
-
-    case EL_BIND:
-    case EL_TELLTC:
-    case EL_SETTC:
-    case EL_ECHOTC:
-    case EL_SETTY:
+       va_list va;
+       int rv = 0;
+
+       if (el == NULL)
+               return (-1);
+       va_start(va, op);
+
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT:
+               rv = prompt_set(el, va_arg(va, el_pfunc_t), op);
+               break;
+
+       case EL_TERMINAL:
+               rv = term_set(el, va_arg(va, char *));
+               break;
+
+       case EL_EDITOR:
+               rv = map_set_editor(el, va_arg(va, char *));
+               break;
+
+       case EL_SIGNAL:
+               if (va_arg(va, int))
+                       el->el_flags |= HANDLE_SIGNALS;
+               else
+                       el->el_flags &= ~HANDLE_SIGNALS;
+               break;
+
+       case EL_BIND:
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY:
        {
-           char *argv[20];
-           int i;
-           for (i = 1; i < 20; i++)
-               if ((argv[i] = va_arg(va, char *)) == NULL)
-                    break;
-
-           switch (op) {
-           case EL_BIND:
-               argv[0] = "bind";
-               rv = map_bind(el, i, argv);
+               const char *argv[20];
+               int i;
+
+               for (i = 1; i < 20; i++)
+                       if ((argv[i] = va_arg(va, char *)) == NULL)
+                               break;
+
+               switch (op) {
+               case EL_BIND:
+                       argv[0] = "bind";
+                       rv = map_bind(el, i, argv);
+                       break;
+
+               case EL_TELLTC:
+                       argv[0] = "telltc";
+                       rv = term_telltc(el, i, argv);
+                       break;
+
+               case EL_SETTC:
+                       argv[0] = "settc";
+                       rv = term_settc(el, i, argv);
+                       break;
+
+               case EL_ECHOTC:
+                       argv[0] = "echotc";
+                       rv = term_echotc(el, i, argv);
+                       break;
+
+               case EL_SETTY:
+                       argv[0] = "setty";
+                       rv = tty_stty(el, i, argv);
+                       break;
+
+               default:
+                       rv = -1;
+                       EL_ABORT((el->el_errfile, "Bad op %d\n", op));
+                       break;
+               }
                break;
+       }
+
+       case EL_ADDFN:
+       {
+               char *name = va_arg(va, char *);
+               char *help = va_arg(va, char *);
+               el_func_t func = va_arg(va, el_func_t);
 
-           case EL_TELLTC:
-               argv[0] = "telltc";
-               rv = term_telltc(el, i, argv);
+               rv = map_addfunc(el, name, help, func);
                break;
+       }
+
+       case EL_HIST:
+       {
+               hist_fun_t func = va_arg(va, hist_fun_t);
+               ptr_t ptr = va_arg(va, char *);
 
-           case EL_SETTC:
-               argv[0] = "settc";
-               rv = term_settc(el, i, argv);
+               rv = hist_set(el, func, ptr);
                break;
+       }
 
-           case EL_ECHOTC:
-               argv[0] = "echotc";
-               rv = term_echotc(el, i, argv);
+       case EL_EDITMODE:
+               if (va_arg(va, int))
+                       el->el_flags &= ~EDIT_DISABLED;
+               else
+                       el->el_flags |= EDIT_DISABLED;
+               rv = 0;
                break;
 
-           case EL_SETTY:
-               argv[0] = "setty";
-               rv = tty_stty(el, i, argv);
+       case EL_GETCFN:
+       {
+               el_rfunc_t rc = va_arg(va, el_rfunc_t);
+               rv = el_read_setfn(el, rc);
+               break;
+       }
+
+       case EL_CLIENTDATA:
+               el->el_data = va_arg(va, void *);
+               break;
+
+       case EL_UNBUFFERED:
+               rv = va_arg(va, int);
+               if (rv && !(el->el_flags & UNBUFFERED)) {
+                       el->el_flags |= UNBUFFERED;
+                       read_prepare(el);
+               } else if (!rv && (el->el_flags & UNBUFFERED)) {
+                       el->el_flags &= ~UNBUFFERED;
+                       read_finish(el);
+               }
+               rv = 0;
                break;
 
-           default:
+       case EL_PREP_TERM:
+               rv = va_arg(va, int);
+               if (rv)
+                       (void) tty_rawmode(el);
+               else
+                       (void) tty_cookedmode(el);
+               rv = 0;
+               break;
+
+       default:
                rv = -1;
-               abort();
                break;
-           }
        }
-       break;
 
-    case EL_ADDFN:
+       va_end(va);
+       return (rv);
+}
+
+
+/* el_get():
+ *     retrieve the editline parameters
+ */
+public int
+el_get(EditLine *el, int op, void *ret)
+{
+       int rv;
+
+       if (el == NULL || ret == NULL)
+               return (-1);
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT:
+               rv = prompt_get(el, (void *) &ret, op);
+               break;
+
+       case EL_EDITOR:
+               rv = map_get_editor(el, (void *) &ret);
+               break;
+
+       case EL_SIGNAL:
+               *((int *) ret) = (el->el_flags & HANDLE_SIGNALS);
+               rv = 0;
+               break;
+
+       case EL_EDITMODE:
+               *((int *) ret) = (!(el->el_flags & EDIT_DISABLED));
+               rv = 0;
+               break;
+
+       case EL_TERMINAL:
+               term_get(el, (const char **)ret);
+               rv = 0;
+               break;
+
+#if 0                          /* XXX */
+       case EL_BIND:
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY:
        {
-           char        *name = va_arg(va, char *);
-           char        *help = va_arg(va, char *);
-           el_func_t    func = va_arg(va, el_func_t);
-           rv = map_addfunc(el, name, help, func);
+               const char *argv[20];
+               int i;
+
+               for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++)
+                       if ((argv[i] = va_arg(va, char *)) == NULL)
+                               break;
+
+               switch (op) {
+               case EL_BIND:
+                       argv[0] = "bind";
+                       rv = map_bind(el, i, argv);
+                       break;
+
+               case EL_TELLTC:
+                       argv[0] = "telltc";
+                       rv = term_telltc(el, i, argv);
+                       break;
+
+               case EL_SETTC:
+                       argv[0] = "settc";
+                       rv = term_settc(el, i, argv);
+                       break;
+
+               case EL_ECHOTC:
+                       argv[0] = "echotc";
+                       rv = term_echotc(el, i, argv);
+                       break;
+
+               case EL_SETTY:
+                       argv[0] = "setty";
+                       rv = tty_stty(el, i, argv);
+                       break;
+
+               default:
+                       rv = -1;
+                       EL_ABORT((el->errfile, "Bad op %d\n", op));
+                       break;
+               }
+               break;
        }
-       break;
 
-    case EL_HIST:
+       case EL_ADDFN:
        {
-           hist_fun_t func = va_arg(va, hist_fun_t);
-           ptr_t      ptr = va_arg(va, char *);
-           rv = hist_set(el, func, ptr);
+               char *name = va_arg(va, char *);
+               char *help = va_arg(va, char *);
+               el_func_t func = va_arg(va, el_func_t);
+
+               rv = map_addfunc(el, name, help, func);
+               break;
        }
-       break;
 
-    default:
-       rv = -1;
-    }
+       case EL_HIST:
+               {
+                       hist_fun_t func = va_arg(va, hist_fun_t);
+                       ptr_t ptr = va_arg(va, char *);
+                       rv = hist_set(el, func, ptr);
+               }
+               break;
+#endif /* XXX */
+
+       case EL_GETCFN:
+               *((el_rfunc_t *)ret) = el_read_getfn(el);
+               rv = 0;
+               break;
+
+       case EL_CLIENTDATA:
+               *((void **)ret) = el->el_data;
+               rv = 0;
+               break;
+
+       case EL_UNBUFFERED:
+               *((int *) ret) = (!(el->el_flags & UNBUFFERED));
+               rv = 0;
+               break;
 
-    va_end(va);
-    return rv;
-} /* end el_set */
+       default:
+               rv = -1;
+       }
+
+       return (rv);
+}
 
 
 /* el_line():
@@ -249,10 +413,10 @@ el_set(EditLine *el, int op, ...)
 public const LineInfo *
 el_line(EditLine *el)
 {
-    return (const LineInfo *) &el->el_line;
+
+       return (const LineInfo *) (void *) &el->el_line;
 }
 
-static const char elpath[] = "/.editrc";
 
 /* el_source():
  *     Source a file
@@ -260,33 +424,51 @@ static const char elpath[] = "/.editrc";
 public int
 el_source(EditLine *el, const char *fname)
 {
-    FILE *fp;
-    size_t len;
-    char *ptr, path[MAXPATHLEN];
-
-    if (fname == NULL) {
-       if (issetugid() != 0 || (ptr = getenv("HOME")) == NULL)
-           return -1;
-       (void) snprintf(path, sizeof(path), "%s%s", ptr, elpath);
-       fname = path;
-    }
-
-    if ((fp = fopen(fname, "r")) == NULL)
-       return -1;
-
-    while ((ptr = fgetln(fp, &len)) != NULL) {
-       if (ptr[len - 1] == '\n')
-           --len;
-       ptr[len] = '\0';
-
-       if (parse_line(el, ptr) == -1) {
-           (void) fclose(fp);
-           return -1;
+       FILE *fp;
+       size_t len;
+       char *ptr;
+
+       fp = NULL;
+       if (fname == NULL) {
+#ifdef HAVE_ISSETUGID
+               static const char elpath[] = "/.editrc";
+               char path[MAXPATHLEN];
+
+               if (issetugid())
+                       return (-1);
+               if ((ptr = getenv("HOME")) == NULL)
+                       return (-1);
+               if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path))
+                       return (-1);
+               if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))
+                       return (-1);
+               fname = path;
+#else
+               /*
+                * If issetugid() is missing, always return an error, in order
+                * to keep from inadvertently opening up the user to a security
+                * hole.
+                */
+               return (-1);
+#endif
+       }
+       if (fp == NULL)
+               fp = fopen(fname, "r");
+       if (fp == NULL)
+               return (-1);
+
+       while ((ptr = fgetln(fp, &len)) != NULL) {
+               if (len > 0 && ptr[len - 1] == '\n')
+                       --len;
+               ptr[len] = '\0';
+               if (parse_line(el, ptr) == -1) {
+                       (void) fclose(fp);
+                       return (-1);
+               }
        }
-    }
 
-    (void) fclose(fp);
-    return 0;
+       (void) fclose(fp);
+       return (0);
 }
 
 
@@ -296,31 +478,55 @@ el_source(EditLine *el, const char *fname)
 public void
 el_resize(EditLine *el)
 {
-    int lins, cols;
-    sigset_t oset, nset;
-    (void) sigemptyset(&nset);
-    (void) sigaddset(&nset, SIGWINCH);
-    (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+       int lins, cols;
+       sigset_t oset, nset;
+
+       (void) sigemptyset(&nset);
+       (void) sigaddset(&nset, SIGWINCH);
+       (void) sigprocmask(SIG_BLOCK, &nset, &oset);
 
-    /* get the correct window size */
-    if (term_get_size(el, &lins, &cols))
-       term_change_size(el, lins, cols);
+       /* get the correct window size */
+       if (term_get_size(el, &lins, &cols))
+               term_change_size(el, lins, cols);
 
-    (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
 }
 
+
+/* el_beep():
+ *     Called from the program to beep
+ */
 public void
-el_data_set(EditLine *el, void *data)
+el_beep(EditLine *el)
 {
-    el->data = data;
 
-    return;
+       term_beep(el);
 }
 
-public void *
-el_data_get(EditLine *el)
+
+/* el_editmode()
+ *     Set the state of EDIT_DISABLED from the `edit' command.
+ */
+protected int
+/*ARGSUSED*/
+el_editmode(EditLine *el, int argc, const char **argv)
 {
-    if (el->data)
-       return (el->data);
-    return (NULL);
+       const char *how;
+
+       if (argv == NULL || argc != 2 || argv[1] == NULL)
+               return (-1);
+
+       how = argv[1];
+       if (strcmp(how, "on") == 0) {
+               el->el_flags &= ~EDIT_DISABLED;
+               tty_rawmode(el);
+       } else if (strcmp(how, "off") == 0) {
+               tty_cookedmode(el);
+               el->el_flags |= EDIT_DISABLED;
+       }
+       else {
+               (void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);
+               return (-1);
+       }
+       return (0);
 }
index 9514a70..c8f94b5 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)el.h        8.1 (Berkeley) 6/4/93
+ * @(#)el.h    8.1 (Berkeley) 6/4/93
+ * $NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $
+ * $DragonFly: src/lib/libedit/el.h,v 1.2 2005/11/13 11:58:30 corecode Exp $
  */
 
 /*
  * el.h: Internal structures.
  */
 #ifndef _h_el
-#define _h_el
+#define        _h_el
 /*
  * Local defaults
  */
-#define KSHVI
-#define VIDEFAULT
-#define ANCHOR
+#define        KSHVI
+#define        VIDEFAULT
+#define        ANCHOR
 
 #include <stdio.h>
 #include <sys/types.h>
 
-#define EL_BUFSIZ      1024            /* Maximum line size            */
+#define        EL_BUFSIZ       1024            /* Maximum line size            */
 
-#define HANDLE_SIGNALS 1
+#define        HANDLE_SIGNALS  0x01
+#define        NO_TTY          0x02
+#define        EDIT_DISABLED   0x04
+#define        UNBUFFERED      0x08
 
 typedef int bool_t;                    /* True or not                  */
 
 typedef unsigned char el_action_t;     /* Index to command array       */
 
 typedef struct coord_t {               /* Position on the screen       */
-    int h, v;
+       int     h;
+       int     v;
 } coord_t;
 
 typedef struct el_line_t {
-    char *buffer,                      /* Input line                   */
-        *cursor,                       /* Cursor position              */
-        *lastchar,                     /* Last character               */
-        *limit;                        /* Max position                 */
+       char    *buffer;                /* Input line                   */
+       char    *cursor;                /* Cursor position              */
+       char    *lastchar;              /* Last character               */
+       const char      *limit;         /* Max position                 */
 } el_line_t;
 
 /*
  * Editor state
  */
 typedef struct el_state_t {
-    int        inputmode;              /* What mode are we in?         */
-    int        doingarg;               /* Are we getting an argument?  */
-    int                argument;               /* Numeric argument             */
-    int                metanext;               /* Is the next char a meta char */
-    el_action_t lastcmd;               /* Previous command             */
+       int             inputmode;      /* What mode are we in?         */
+       int             doingarg;       /* Are we getting an argument?  */
+       int             argument;       /* Numeric argument             */
+       int             metanext;       /* Is the next char a meta char */
+       el_action_t     lastcmd;        /* Previous command             */
+       el_action_t     thiscmd;        /* this command                 */
+       char            thisch;         /* char that generated it       */
 } el_state_t;
 
 /*
  * Until we come up with something better...
  */
-#define el_malloc(a)   malloc(a)
-#define el_realloc(a,b)        realloc(a, b)
-#define el_reallocf(a,b) reallocf(a, b)
-#define el_free(a)     free(a)
+#define        el_strdup(a)    strdup(a)
+#define        el_malloc(a)    malloc(a)
+#define        el_realloc(a,b) realloc(a, b)
+#define        el_free(a)      free(a)
 
 #include "tty.h"
 #include "prompt.h"
@@ -102,31 +106,44 @@ typedef struct el_state_t {
 #include "parse.h"
 #include "sig.h"
 #include "help.h"
+#include "read.h"
 
 struct editline {
-    char        *el_prog;      /* the program name                     */
-    FILE         *el_outfile;  /* Stdio stuff                          */
-    FILE         *el_errfile;  /* Stdio stuff                          */
-    int           el_infd;     /* Input file descriptor                */
-    int                  el_flags;     /* Various flags.                       */
-    coord_t       el_cursor;   /* Cursor location                      */
-    char        **el_display,  /* Real screen image = what is there    */
-               **el_vdisplay;  /* Virtual screen image = what we see   */
-
-    el_line_t     el_line;     /* The current line information         */
-    el_state_t   el_state;     /* Current editor state                 */
-    el_term_t     el_term;     /* Terminal dependent stuff             */
-    el_tty_t     el_tty;       /* Tty dependent stuff                  */
-    el_refresh_t  el_refresh;  /* Refresh stuff                        */
-    el_prompt_t   el_prompt;   /* Prompt stuff                         */
-    el_chared_t          el_chared;    /* Characted editor stuff               */
-    el_map_t     el_map;       /* Key mapping stuff                    */
-    el_key_t     el_key;       /* Key binding stuff                    */
-    el_history_t  el_history;  /* History stuff                        */
-    el_search_t          el_search;    /* Search stuff                         */
-    el_signal_t          el_signal;    /* Signal handling stuff                */
-
-    void         *data;                /* user data */
+       char             *el_prog;      /* the program name             */
+       FILE             *el_outfile;   /* Stdio stuff                  */
+       FILE             *el_errfile;   /* Stdio stuff                  */
+       int               el_infd;      /* Input file descriptor        */
+       int               el_flags;     /* Various flags.               */
+       coord_t           el_cursor;    /* Cursor location              */
+       char            **el_display;   /* Real screen image = what is there */
+       char            **el_vdisplay;  /* Virtual screen image = what we see */
+       void             *el_data;      /* Client data                  */
+       el_line_t         el_line;      /* The current line information */
+       el_state_t        el_state;     /* Current editor state         */
+       el_term_t         el_term;      /* Terminal dependent stuff     */
+       el_tty_t          el_tty;       /* Tty dependent stuff          */
+       el_refresh_t      el_refresh;   /* Refresh stuff                */
+       el_prompt_t       el_prompt;    /* Prompt stuff                 */
+       el_prompt_t       el_rprompt;   /* Prompt stuff                 */
+       el_chared_t       el_chared;    /* Characted editor stuff       */
+       el_map_t          el_map;       /* Key mapping stuff            */
+       el_key_t          el_key;       /* Key binding stuff            */
+       el_history_t      el_history;   /* History stuff                */
+       el_search_t       el_search;    /* Search stuff                 */
+       el_signal_t       el_signal;    /* Signal handling stuff        */
+       el_read_t         el_read;      /* Character reading stuff      */
 };
 
+protected int  el_editmode(EditLine *, int, const char **);
+
+#ifdef DEBUG
+#define        EL_ABORT(a)     do { \
+                               fprintf(el->el_errfile, "%s, %d: ", \
+                                        __FILE__, __LINE__); \
+                               fprintf a; \
+                               abort(); \
+                       } while( /*CONSTCOND*/0);
+#else
+#define EL_ABORT(a)    abort()
+#endif
 #endif /* _h_el */
index 1e2c868..f35970b 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#)emacs.c 8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/emacs.c,v 1.4 2005/08/04 17:27:09 drhodus Exp $
+ * @(#)emacs.c  8.1 (Berkeley) 6/4/93
+ * $NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $
+ * $DragonFly: src/lib/libedit/emacs.c,v 1.5 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * emacs.c: Emacs functions
  */
-#include "sys.h"
 #include "el.h"
 
 /* em_delete_or_list():
  */
 protected el_action_t
 /*ARGSUSED*/
-em_delete_or_list(EditLine *el, int c)
+em_delete_or_list(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor == el->el_line.lastchar) {  /* if I'm at the end */
-       if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */
-           term_overwrite(el, STReof, 4);/* then do a EOF */
-           term__flush();
-           return CC_EOF;
-       }
-       else {
-           /* Here we could list completions, but it is an error right now */
-           term_beep(el);
-           return CC_ERROR;
+
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                                       /* if I'm at the end */
+               if (el->el_line.cursor == el->el_line.buffer) {
+                                       /* and the beginning */
+                       term_overwrite(el, STReof, 4);  /* then do a EOF */
+                       term__flush();
+                       return (CC_EOF);
+               } else {
+                       /*
+                        * Here we could list completions, but it is an
+                        * error right now
+                        */
+                       term_beep(el);
+                       return (CC_ERROR);
+               }
+       } else {
+               if (el->el_state.doingarg)
+                       c_delafter(el, el->el_state.argument);
+               else
+                       c_delafter1(el);
+               if (el->el_line.cursor > el->el_line.lastchar)
+                       el->el_line.cursor = el->el_line.lastchar;
+                               /* bounds check */
+               return (CC_REFRESH);
        }
-    }
-    else {
-       c_delafter(el, el->el_state.argument);  /* delete after dot */
-       if (el->el_line.cursor > el->el_line.lastchar)
-           el->el_line.cursor = el->el_line.lastchar;  /* bounds check */
-       return CC_REFRESH;
-    }
 }
 
 
@@ -78,25 +84,26 @@ em_delete_or_list(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_delete_next_word(EditLine *el, int c)
+em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *cp, *p, *kp;
+       char *cp, *p, *kp;
 
-    if (el->el_line.cursor == el->el_line.lastchar)
-       return CC_ERROR;
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return (CC_ERROR);
 
-    cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
-                     el->el_state.argument, ce__isword);
+       cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
 
-    for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
-       /* save the text */
-       *kp++ = *p;
-    el->el_chared.c_kill.last = kp;
+       for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
+                               /* save the text */
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
 
-    c_delafter(el, cp - el->el_line.cursor);           /* delete after dot */
-    if (el->el_line.cursor > el->el_line.lastchar)
-       el->el_line.cursor = el->el_line.lastchar;      /* bounds check */
-    return CC_REFRESH;
+       c_delafter(el, cp - el->el_line.cursor);        /* delete after dot */
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+                               /* bounds check */
+       return (CC_REFRESH);
 }
 
 
@@ -106,32 +113,32 @@ em_delete_next_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_yank(EditLine *el, int c)
+em_yank(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *kp, *cp;
+       char *kp, *cp;
 
-    if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
-       return CC_ERROR;
+       if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
+               return (CC_NORM);
 
-    if (el->el_line.lastchar +
-       (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
-       el->el_line.limit)
-       return CC_ERROR;
+       if (el->el_line.lastchar +
+           (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
+           el->el_line.limit)
+               return (CC_ERROR);
 
-    el->el_chared.c_kill.mark = el->el_line.cursor;
-    cp = el->el_line.cursor;
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       cp = el->el_line.cursor;
 
-    /* open the space, */
-    c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
-    /* copy the chars */
-    for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
-       *cp++ = *kp;
+       /* open the space, */
+       c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
+       /* copy the chars */
+       for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
+               *cp++ = *kp;
 
-    /* if an arg, cursor at beginning else cursor at end */
-    if (el->el_state.argument == 1)
-       el->el_line.cursor = cp;
+       /* if an arg, cursor at beginning else cursor at end */
+       if (el->el_state.argument == 1)
+               el->el_line.cursor = cp;
 
-    return CC_REFRESH;
+       return (CC_REFRESH);
 }
 
 
@@ -141,18 +148,19 @@ em_yank(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_kill_line(EditLine *el, int c)
+em_kill_line(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *kp, *cp;
-
-    cp = el->el_line.buffer;
-    kp = el->el_chared.c_kill.buf;
-    while (cp < el->el_line.lastchar)
-       *kp++ = *cp++;          /* copy it */
-    el->el_chared.c_kill.last = kp;
-    el->el_line.lastchar = el->el_line.buffer; /* zap! -- delete all of it */
-    el->el_line.cursor = el->el_line.buffer;
-    return CC_REFRESH;
+       char *kp, *cp;
+
+       cp = el->el_line.buffer;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                               /* zap! -- delete all of it */
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return (CC_REFRESH);
 }
 
 
@@ -162,31 +170,30 @@ em_kill_line(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_kill_region(EditLine *el, int c)
+em_kill_region(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *kp, *cp;
-
-    if (!el->el_chared.c_kill.mark)
-       return CC_ERROR;
-
-    if (el->el_chared.c_kill.mark > el->el_line.cursor) {
-       cp = el->el_line.cursor;
-       kp = el->el_chared.c_kill.buf;
-       while (cp < el->el_chared.c_kill.mark)
-           *kp++ = *cp++;      /* copy it */
-       el->el_chared.c_kill.last = kp;
-       c_delafter(el, cp - el->el_line.cursor);
-    }
-    else {                     /* mark is before cursor */
-       cp = el->el_chared.c_kill.mark;
-       kp = el->el_chared.c_kill.buf;
-       while (cp < el->el_line.cursor)
-           *kp++ = *cp++;      /* copy it */
-       el->el_chared.c_kill.last = kp;
-       c_delbefore(el, cp - el->el_chared.c_kill.mark);
-       el->el_line.cursor = el->el_chared.c_kill.mark;
-    }
-    return CC_REFRESH;
+       char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return (CC_ERROR);
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delafter(el, cp - el->el_line.cursor);
+       } else {                /* mark is before cursor */
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delbefore(el, cp - el->el_chared.c_kill.mark);
+               el->el_line.cursor = el->el_chared.c_kill.mark;
+       }
+       return (CC_REFRESH);
 }
 
 
@@ -196,48 +203,46 @@ em_kill_region(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_copy_region(EditLine *el, int c)
+em_copy_region(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *kp, *cp;
-
-    if (el->el_chared.c_kill.mark)
-       return CC_ERROR;
-
-    if (el->el_chared.c_kill.mark > el->el_line.cursor) {
-       cp = el->el_line.cursor;
-       kp = el->el_chared.c_kill.buf;
-       while (cp < el->el_chared.c_kill.mark)
-           *kp++ = *cp++;      /* copy it */
-       el->el_chared.c_kill.last = kp;
-    }
-    else {
-       cp = el->el_chared.c_kill.mark;
-       kp = el->el_chared.c_kill.buf;
-       while (cp < el->el_line.cursor)
-           *kp++ = *cp++;      /* copy it */
-       el->el_chared.c_kill.last = kp;
-    }
-    return CC_NORM;
+       char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return (CC_ERROR);
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       } else {
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       }
+       return (CC_NORM);
 }
 
 
-/* em_gosmacs_traspose():
+/* em_gosmacs_transpose():
  *     Exchange the two characters before the cursor
  *     Gosling emacs transpose chars [^T]
  */
 protected el_action_t
-em_gosmacs_traspose(EditLine *el, int c)
+em_gosmacs_transpose(EditLine *el, int c)
 {
 
-    if (el->el_line.cursor > &el->el_line.buffer[1]) {
-       /* must have at least two chars entered */
-       c = el->el_line.cursor[-2];
-       el->el_line.cursor[-2] = el->el_line.cursor[-1];
-       el->el_line.cursor[-1] = c;
-       return CC_REFRESH;
-    }
-    else
-       return CC_ERROR;
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return (CC_REFRESH);
+       } else
+               return (CC_ERROR);
 }
 
 
@@ -247,45 +252,46 @@ em_gosmacs_traspose(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_next_word(EditLine *el, int c)
+em_next_word(EditLine *el, int c __attribute__((__unused__)))
 {
-    if (el->el_line.cursor == el->el_line.lastchar)
-       return CC_ERROR;
-
-    el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar,
-                                     el->el_state.argument,
-                                     ce__isword);
-
-    if (el->el_map.type == MAP_VI)
-       if (el->el_chared.c_vcmd.action & DELETE) {
-           cv_delfini(el);
-           return CC_REFRESH;
-       }
-
-    return CC_CURSOR;
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return (CC_ERROR);
+
+       el->el_line.cursor = c__next_word(el->el_line.cursor,
+           el->el_line.lastchar,
+           el->el_state.argument,
+           ce__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return (CC_REFRESH);
+               }
+       return (CC_CURSOR);
 }
 
+
 /* em_upper_case():
  *     Uppercase the characters from cursor to end of current word
  *     [M-u]
  */
 protected el_action_t
 /*ARGSUSED*/
-em_upper_case(EditLine *el, int c)
+em_upper_case(EditLine *el, int c __attribute__((__unused__)))
 {
-    char   *cp, *ep;
+       char *cp, *ep;
 
-    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
-                     el->el_state.argument, ce__isword);
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
 
-    for (cp = el->el_line.cursor; cp < ep; cp++)
-       if (islower((unsigned char)*cp))
-           *cp = toupper((unsigned char)*cp);
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (islower((unsigned char)*cp))
+                       *cp = toupper((unsigned char)*cp);
 
-    el->el_line.cursor = ep;
-    if (el->el_line.cursor > el->el_line.lastchar)
-       el->el_line.cursor = el->el_line.lastchar;
-    return CC_REFRESH;
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return (CC_REFRESH);
 }
 
 
@@ -295,52 +301,53 @@ em_upper_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_capitol_case(EditLine *el, int c)
+em_capitol_case(EditLine *el, int c __attribute__((__unused__)))
 {
-    char   *cp, *ep;
-
-    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
-                     el->el_state.argument, ce__isword);
-
-    for (cp = el->el_line.cursor; cp < ep; cp++) {
-       if (isalpha((unsigned char)*cp)) {
-           if (islower((unsigned char)*cp))
-               *cp = toupper((unsigned char)*cp);
-           cp++;
-           break;
+       char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++) {
+               if (isalpha((unsigned char)*cp)) {
+                       if (islower((unsigned char)*cp))
+                               *cp = toupper((unsigned char)*cp);
+                       cp++;
+                       break;
+               }
        }
-    }
-    for (; cp < ep; cp++)
-       if (isupper((unsigned char)*cp))
-           *cp = tolower((unsigned char)*cp);
-
-    el->el_line.cursor = ep;
-    if (el->el_line.cursor > el->el_line.lastchar)
-       el->el_line.cursor = el->el_line.lastchar;
-    return CC_REFRESH;
+       for (; cp < ep; cp++)
+               if (isupper((unsigned char)*cp))
+                       *cp = tolower((unsigned char)*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return (CC_REFRESH);
 }
 
+
 /* em_lower_case():
  *     Lowercase the characters from cursor to end of current word
  *     [M-l]
  */
 protected el_action_t
 /*ARGSUSED*/
-em_lower_case(EditLine *el, int c)
+em_lower_case(EditLine *el, int c __attribute__((__unused__)))
 {
-    char   *cp, *ep;
+       char *cp, *ep;
 
-    ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
-                     el->el_state.argument, ce__isword);
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
 
-    for (cp = el->el_line.cursor; cp < ep; cp++)
-       if (isupper((unsigned char)*cp))
-           *cp = tolower((unsigned char)*cp);
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (isupper((unsigned char)*cp))
+                       *cp = tolower((unsigned char)*cp);
 
-    el->el_line.cursor = ep;
-    if (el->el_line.cursor > el->el_line.lastchar)
-       el->el_line.cursor = el->el_line.lastchar;
-    return CC_REFRESH;
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return (CC_REFRESH);
 }
 
 
@@ -350,10 +357,11 @@ em_lower_case(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_set_mark(EditLine *el, int c)
+em_set_mark(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_chared.c_kill.mark = el->el_line.cursor;
-    return CC_NORM;
+
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       return (CC_NORM);
 }
 
 
@@ -363,41 +371,45 @@ em_set_mark(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_exchange_mark(EditLine *el, int c)
+em_exchange_mark(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *cp;
+       char *cp;
 
-    cp = el->el_line.cursor;
-    el->el_line.cursor = el->el_chared.c_kill.mark;
-    el->el_chared.c_kill.mark = cp;
-    return CC_CURSOR;
+       cp = el->el_line.cursor;
+       el->el_line.cursor = el->el_chared.c_kill.mark;
+       el->el_chared.c_kill.mark = cp;
+       return (CC_CURSOR);
 }
 
+
 /* em_universal_argument():
  *     Universal argument (argument times 4)
  *     [^U]
  */
 protected el_action_t
 /*ARGSUSED*/
-em_universal_argument(EditLine *el, int c)
+em_universal_argument(EditLine *el, int c __attribute__((__unused__)))
 {                              /* multiply current argument by 4 */
-    if (el->el_state.argument > 1000000)
-       return CC_ERROR;
-    el->el_state.doingarg = 1;
-    el->el_state.argument *= 4;
-    return CC_ARGHACK;
+
+       if (el->el_state.argument > 1000000)
+               return (CC_ERROR);
+       el->el_state.doingarg = 1;
+       el->el_state.argument *= 4;
+       return (CC_ARGHACK);
 }
 
+
 /* em_meta_next():
  *     Add 8th bit to next character typed
  *     [<ESC>]
  */
 protected el_action_t
 /*ARGSUSED*/
-em_meta_next(EditLine *el, int c)
+em_meta_next(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_state.metanext = 1;
-    return CC_ARGHACK;
+
+       el->el_state.metanext = 1;
+       return (CC_ARGHACK);
 }
 
 
@@ -406,11 +418,12 @@ em_meta_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_toggle_overwrite(EditLine *el, int c)
+em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_state.inputmode =
-       (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
-    return CC_NORM;
+
+       el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
+           MODE_REPLACE : MODE_INSERT;
+       return (CC_NORM);
 }
 
 
@@ -419,25 +432,25 @@ em_toggle_overwrite(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_copy_prev_word(EditLine *el, int c)
+em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))
 {
-    char *cp, *oldc, *dp;
+       char *cp, *oldc, *dp;
 
-    if (el->el_line.cursor == el->el_line.buffer)
-       return CC_ERROR;
+       if (el->el_line.cursor == el->el_line.buffer)
+               return (CC_ERROR);
 
-    oldc = el->el_line.cursor;
-    /* does a bounds check */
-    cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
-                     el->el_state.argument, ce__isword);
+       oldc = el->el_line.cursor;
+       /* does a bounds check */
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
 
-    c_insert(el, oldc - cp);
-    for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
-       *dp++ = *cp;
+       c_insert(el, oldc - cp);
+       for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
+               *dp++ = *cp;
 
-    el->el_line.cursor = dp;           /* put cursor at end */
+       el->el_line.cursor = dp;/* put cursor at end */
 
-    return CC_REFRESH;
+       return (CC_REFRESH);
 }
 
 
@@ -446,10 +459,11 @@ em_copy_prev_word(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_inc_search_next(EditLine *el, int c)
+em_inc_search_next(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_search.patlen = 0;
-    return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
+
+       el->el_search.patlen = 0;
+       return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
 }
 
 
@@ -458,8 +472,32 @@ em_inc_search_next(EditLine *el, int c)
  */
 protected el_action_t
 /*ARGSUSED*/
-em_inc_search_prev(EditLine *el, int c)
+em_inc_search_prev(EditLine *el, int c __attribute__((__unused__)))
+{
+
+       el->el_search.patlen = 0;
+       return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
+}
+
+
+/* em_delete_prev_char():
+ *     Delete the character to the left of the cursor
+ *     [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))
 {
-    el->el_search.patlen = 0;
-    return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
+
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return (CC_ERROR);
+
+       if (el->el_state.doingarg)
+               c_delbefore(el, el->el_state.argument);
+       else
+               c_delbefore1(el);
+       el->el_line.cursor -= el->el_state.argument;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+       return (CC_REFRESH);
 }
diff --git a/lib/libedit/filecomplete.c b/lib/libedit/filecomplete.c
new file mode 100644 (file)
index 0000000..9c3c1cd
--- /dev/null
@@ -0,0 +1,553 @@
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: filecomplete.c,v 1.7 2005/06/11 18:18:59 christos Exp $
+ * $DragonFly: src/lib/libedit/filecomplete.c,v 1.1 2005/11/13 11:58:30 corecode Exp $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_VIS_H
+#include <vis.h>
+#else
+#include "np/vis.h"
+#endif
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#include "el.h"
+#include "fcns.h"              /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
+    '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
+
+
+/********************************/
+/* completion functions */
+
+/*
+ * does tilde expansion of strings of type ``~user/foo''
+ * if ``user'' isn't valid user name or ``txt'' doesn't start
+ * w/ '~', returns pointer to strdup()ed copy of ``txt''
+ *
+ * it's callers's responsibility to free() returned string
+ */
+char *
+fn_tilde_expand(const char *txt)
+{
+       /*
+               XXX: replace the next line with this line when getpwuid_r or
+               getpwnam_r become available:
+       struct passwd pwres, *pass;
+       */
+       struct passwd *pass;
+       char *temp;
+       size_t len = 0;
+       char pwbuf[1024];
+
+       if (txt[0] != '~')
+               return (strdup(txt));
+
+       temp = strchr(txt + 1, '/');
+       if (temp == NULL) {
+               temp = strdup(txt + 1);
+               if (temp == NULL)
+                       return NULL;
+       } else {
+               len = temp - txt + 1;   /* text until string after slash */
+               temp = malloc(len);
+               if (temp == NULL)
+                       return NULL;
+               (void)strncpy(temp, txt + 1, len - 2);
+               temp[len - 2] = '\0';
+       }
+       if (temp[0] == 0) {
+               /*
+                       XXX: use the following instead of the next line when
+                       getpwuid_r is available:
+               if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+                       pass = NULL;
+               */
+               pass = getpwuid(getuid());
+       } else {
+               
+               /*
+                       XXX: use the following instead of the next line when
+                       getpwname_r is available:
+               if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+                       pass = NULL;
+               */
+               pass = getpwnam(temp);
+       }
+       free(temp);             /* value no more needed */
+       if (pass == NULL)
+               return (strdup(txt));
+
+       /* update pointer txt to point at string immedially following */
+       /* first slash */
+       txt += len;
+
+       temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1);
+       if (temp == NULL)
+               return NULL;
+       (void)sprintf(temp, "%s/%s", pass->pw_dir, txt);
+
+       return (temp);
+}
+
+
+/*
+ * return first found file name starting by the ``text'' or NULL if no
+ * such file can be found
+ * value of ``state'' is ignored
+ *
+ * it's caller's responsibility to free returned string
+ */
+char *
+fn_filename_completion_function(const char *text, int state)
+{
+       static DIR *dir = NULL;
+       static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
+       static size_t filename_len = 0;
+       struct dirent *entry;
+       char *temp;
+       size_t len;
+
+       if (state == 0 || dir == NULL) {
+               temp = strrchr(text, '/');
+               if (temp) {
+                       char *nptr;
+                       temp++;
+                       nptr = realloc(filename, strlen(temp) + 1);
+                       if (nptr == NULL) {
+                               free(filename);
+                               return NULL;
+                       }
+                       filename = nptr;
+                       (void)strcpy(filename, temp);
+                       len = temp - text;      /* including last slash */
+                       nptr = realloc(dirname, len + 1);
+                       if (nptr == NULL) {
+                               free(filename);
+                               return NULL;
+                       }
+                       dirname = nptr;
+                       (void)strncpy(dirname, text, len);
+                       dirname[len] = '\0';
+               } else {
+                       if (*text == 0)
+                               filename = NULL;
+                       else {
+                               filename = strdup(text);
+                               if (filename == NULL)
+                                       return NULL;
+                       }
+                       dirname = NULL;
+               }
+
+               if (dir != NULL) {
+                       (void)closedir(dir);
+                       dir = NULL;
+               }
+
+               /* support for ``~user'' syntax */
+               free(dirpath);
+
+               if (dirname == NULL && (dirname = strdup("./")) == NULL)
+                       return NULL;
+
+               if (*dirname == '~')
+                       dirpath = fn_tilde_expand(dirname);
+               else
+                       dirpath = strdup(dirname);
+
+               if (dirpath == NULL)
+                       return NULL;
+
+               dir = opendir(dirpath);
+               if (!dir)
+                       return (NULL);  /* cannot open the directory */
+
+               /* will be used in cycle */
+               filename_len = filename ? strlen(filename) : 0;
+       }
+
+       /* find the match */
+       while ((entry = readdir(dir)) != NULL) {
+               /* skip . and .. */
+               if (entry->d_name[0] == '.' && (!entry->d_name[1]
+                   || (entry->d_name[1] == '.' && !entry->d_name[2])))
+                       continue;
+               if (filename_len == 0)
+                       break;
+               /* otherwise, get first entry where first */
+               /* filename_len characters are equal      */
+               if (entry->d_name[0] == filename[0]
+#if defined(__SVR4) || defined(__linux__)
+                   && strlen(entry->d_name) >= filename_len
+#else
+                   && entry->d_namlen >= filename_len
+#endif
+                   && strncmp(entry->d_name, filename,
+                       filename_len) == 0)
+                       break;
+       }
+
+       if (entry) {            /* match found */
+
+#if defined(__SVR4) || defined(__linux__)
+               len = strlen(entry->d_name);
+#else
+               len = entry->d_namlen;
+#endif
+
+               temp = malloc(strlen(dirname) + len + 1);
+               if (temp == NULL)
+                       return NULL;
+               (void)sprintf(temp, "%s%s", dirname, entry->d_name);
+       } else {
+               (void)closedir(dir);
+               dir = NULL;
+               temp = NULL;
+       }
+
+       return (temp);
+}
+
+
+static const char *
+append_char_function(const char *name)
+{
+       struct stat stbuf;
+       char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
+       const char *rs = "";
+
+       if (stat(expname ? expname : name, &stbuf) == -1)
+               goto out;
+       if (S_ISDIR(stbuf.st_mode))
+               rs = "/";
+out:
+       if (expname)
+               free(expname);
+       return rs;
+}
+/*
+ * returns list of completions for text given
+ * non-static for readline.
+ */
+char ** completion_matches(const char *, char *(*)(const char *, int));
+char **
+completion_matches(const char *text, char *(*genfunc)(const char *, int))
+{
+       char **match_list = NULL, *retstr, *prevstr;
+       size_t match_list_len, max_equal, which, i;
+       size_t matches;
+
+       matches = 0;
+       match_list_len = 1;
+       while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
+               /* allow for list terminator here */
+               if (matches + 3 >= match_list_len) {
+                       char **nmatch_list;
+                       while (matches + 3 >= match_list_len)
+                               match_list_len <<= 1;
+                       nmatch_list = realloc(match_list,
+                           match_list_len * sizeof(char *));
+                       if (nmatch_list == NULL) {
+                               free(match_list);
+                               return NULL;
+                       }
+                       match_list = nmatch_list;
+
+               }
+               match_list[++matches] = retstr;
+       }
+
+       if (!match_list)
+               return NULL;    /* nothing found */
+
+       /* find least denominator and insert it to match_list[0] */
+       which = 2;
+       prevstr = match_list[1];
+       max_equal = strlen(prevstr);
+       for (; which <= matches; which++) {
+               for (i = 0; i < max_equal &&
+                   prevstr[i] == match_list[which][i]; i++)
+                       continue;
+               max_equal = i;
+       }
+
+       retstr = malloc(max_equal + 1);
+       if (retstr == NULL) {
+               free(match_list);
+               return NULL;
+       }
+       (void)strncpy(retstr, match_list[1], max_equal);
+       retstr[max_equal] = '\0';
+       match_list[0] = retstr;
+
+       /* add NULL as last pointer to the array */
+       match_list[matches + 1] = (char *) NULL;
+
+       return (match_list);
+}
+
+/*
+ * Sort function for qsort(). Just wrapper around strcasecmp().
+ */
+static int
+_fn_qsort_string_compare(const void *i1, const void *i2)
+{
+       const char *s1 = ((const char * const *)i1)[0];
+       const char *s2 = ((const char * const *)i2)[0];
+
+       return strcasecmp(s1, s2);
+}
+
+/*
+ * Display list of strings in columnar format on readline's output stream.
+ * 'matches' is list of strings, 'len' is number of strings in 'matches',
+ * 'max' is maximum length of string in 'matches'.
+ */
+void
+fn_display_match_list (EditLine *el, char **matches, int len, int max)
+{
+       int i, idx, limit, count;
+       int screenwidth = el->el_term.t_size.h;
+
+       /*
+        * Find out how many entries can be put on one line, count
+        * with two spaces between strings.
+        */
+       limit = screenwidth / (max + 2);
+       if (limit == 0)
+               limit = 1;
+
+       /* how many lines of output */
+       count = len / limit;
+       if (count * limit < len)
+               count++;
+
+       /* Sort the items if they are not already sorted. */
+       qsort(&matches[1], (size_t)(len - 1), sizeof(char *),
+           _fn_qsort_string_compare);
+
+       idx = 1;
+       for(; count > 0; count--) {
+               for(i = 0; i < limit && matches[idx]; i++, idx++)
+                       (void)fprintf(el->el_outfile, "%-*s  ", max,
+                           matches[idx]);
+               (void)fprintf(el->el_outfile, "\n");
+       }
+}
+
+/*
+ * Complete the word at or before point,
+ * 'what_to_do' says what to do with the completion.
+ * \t   means do standard completion.
+ * `?' means list the possible completions.
+ * `*' means insert all of the possible completions.
+ * `!' means to do standard completion, and list all possible completions if
+ * there is more than one.
+ *
+ * Note: '*' support is not implemented
+ *       '!' could never be invoked
+ */
+int
+fn_complete(EditLine *el,
+       char *(*complet_func)(const char *, int),
+       char **(*attempted_completion_function)(const char *, int, int),
+       const char *word_break, const char *special_prefixes,
+       const char *(*app_func)(const char *), int query_items,
+       int *completion_type, int *over, int *point, int *end)
+{
+       const LineInfo *li;
+       char *temp, **matches;
+       const char *ctemp;
+       size_t len;
+       int what_to_do = '\t';
+
+       if (el->el_state.lastcmd == el->el_state.thiscmd)
+               what_to_do = '?';
+
+       /* readline's rl_complete() has to be told what we did... */
+       if (completion_type != NULL)
+               *completion_type = what_to_do;
+
+       if (!complet_func)
+               complet_func = fn_filename_completion_function;
+       if (!app_func)
+               app_func = append_char_function;
+
+       /* We now look backwards for the start of a filename/variable word */
+       li = el_line(el);
+       ctemp = (const char *) li->cursor;
+       while (ctemp > li->buffer
+           && !strchr(word_break, ctemp[-1])
+           && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) )
+               ctemp--;
+
+       len = li->cursor - ctemp;
+       temp = alloca(len + 1);
+       (void)strncpy(temp, ctemp, len);
+       temp[len] = '\0';
+
+       /* these can be used by function called in completion_matches() */
+       /* or (*attempted_completion_function)() */
+       if (point != 0)
+               *point = li->cursor - li->buffer;
+       if (end != NULL)
+               *end = li->lastchar - li->buffer;
+
+       if (attempted_completion_function) {
+               int cur_off = li->cursor - li->buffer;
+               matches = (*attempted_completion_function) (temp,
+                   (int)(cur_off - len), cur_off);
+       } else
+               matches = 0;
+       if (!attempted_completion_function || 
+           (over != NULL && *over && !matches))
+               matches = completion_matches(temp, complet_func);
+
+       if (over != NULL)
+               *over = 0;
+
+       if (matches) {
+               int i, retval = CC_REFRESH;
+               int matches_num, maxlen, match_len, match_display=1;
+
+               /*
+                * Only replace the completed string with common part of
+                * possible matches if there is possible completion.
+                */
+               if (matches[0][0] != '\0') {
+                       el_deletestr(el, (int) len);
+                       el_insertstr(el, matches[0]);
+               }
+
+               if (what_to_do == '?')
+                       goto display_matches;
+
+               if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+                       /*
+                        * We found exact match. Add a space after
+                        * it, unless we do filename completion and the
+                        * object is a directory.
+                        */
+                       el_insertstr(el, (*append_char_function)(matches[0])); 
+               } else if (what_to_do == '!') {
+    display_matches:
+                       /*
+                        * More than one match and requested to list possible
+                        * matches.
+                        */
+
+                       for(i=1, maxlen=0; matches[i]; i++) {
+                               match_len = strlen(matches[i]);
+                               if (match_len > maxlen)
+                                       maxlen = match_len;
+                       }
+                       matches_num = i - 1;
+                               
+                       /* newline to get on next line from command line */
+                       (void)fprintf(el->el_outfile, "\n");
+
+                       /*
+                        * If there are too many items, ask user for display
+                        * confirmation.
+                        */
+                       if (matches_num > query_items) {
+                               (void)fprintf(el->el_outfile,
+                                   "Display all %d possibilities? (y or n) ",
+                                   matches_num);
+                               (void)fflush(el->el_outfile);
+                               if (getc(stdin) != 'y')
+                                       match_display = 0;
+                               (void)fprintf(el->el_outfile, "\n");
+                       }
+
+                       if (match_display)
+                               fn_display_match_list(el, matches, matches_num,
+                                       maxlen);
+                       retval = CC_REDISPLAY;
+               } else if (matches[0][0]) {
+                       /*
+                        * There was some common match, but the name was
+                        * not complete enough. Next tab will print possible
+                        * completions.
+                        */
+                       el_beep(el);
+               } else {
+                       /* lcd is not a valid object - further specification */
+                       /* is needed */
+                       el_beep(el);
+                       retval = CC_NORM;
+               }
+
+               /* free elements of array and the array itself */
+               for (i = 0; matches[i]; i++)
+                       free(matches[i]);
+               free(matches), matches = NULL;
+
+               return (retval);
+       }
+       return (CC_NORM);
+}
+
+/*
+ * el-compatible wrapper around rl_complete; needed for key binding
+ */
+/* ARGSUSED */
+unsigned char
+_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
+{
+       return (unsigned char)fn_complete(el, NULL, NULL,
+           break_chars, NULL, NULL, 100,
+           NULL, NULL, NULL, NULL);
+}
diff --git a/lib/libedit/filecomplete.h b/lib/libedit/filecomplete.h
new file mode 100644 (file)
index 0000000..0748ced
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: filecomplete.h,v 1.4 2005/06/11 18:18:59 christos Exp $
+ * $DragonFly: src/lib/libedit/filecomplete.h,v 1.1 2005/11/13 11:58:30 corecode Exp $
+ */
+#ifndef _FILECOMPLETE_H_
+#define _FILECOMPLETE_H_
+
+int fn_complete(EditLine *,
+    char *(*)(const char *, int),
+    char **(*)(const char *, int, int),
+    const char *, const char *, const char *(*)(const char *), int,
+    int *, int *, int *, int *);
+
+void fn_display_match_list(EditLine *, char **, int, int);
+char *fn_tilde_expand(const char *);
+char *fn_filename_completion_function(const char *, int);
+
+#endif
index 1cae599..daaa58c 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  *
  * @(#)hist.c  8.1 (Berkeley) 6/4/93
+ * $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $"
+ * $DragonFly: src/lib/libedit/hist.c,v 1.3 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * hist.c: History access functions
  */
-#include "sys.h"
 #include <stdlib.h>
 #include "el.h"
 
  *     Initialization function.
  */
 protected int
-hist_init(el)
-    EditLine *el;
+hist_init(EditLine *el)
 {
-    el->el_history.fun  = NULL;
-    el->el_history.ref  = NULL;
-    el->el_history.buf   = (char *) el_malloc(EL_BUFSIZ);
-    el->el_history.last  = el->el_history.buf;
-    return 0;
+
+       el->el_history.fun = NULL;
+       el->el_history.ref = NULL;
+       el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
+       el->el_history.sz  = EL_BUFSIZ;
+       if (el->el_history.buf == NULL)
+               return (-1);
+       el->el_history.last = el->el_history.buf;
+       return (0);
 }
 
 
@@ -62,11 +64,11 @@ hist_init(el)
  *     clean up history;
  */
 protected void
-hist_end(el)
-    EditLine *el;
+hist_end(EditLine *el)
 {
-    el_free((ptr_t) el->el_history.buf);
-    el->el_history.buf   = NULL;
+
+       el_free((ptr_t) el->el_history.buf);
+       el->el_history.buf = NULL;
 }
 
 
@@ -74,15 +76,12 @@ hist_end(el)
  *     Set new history interface
  */
 protected int
-hist_set(el, fun, ptr)
-    EditLine *el;
-    hist_fun_t fun;
-    ptr_t ptr;
-
+hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr)
 {
-    el->el_history.ref = ptr;
-    el->el_history.fun = fun;
-    return 0;
+
+       el->el_history.ref = ptr;
+       el->el_history.fun = fun;
+       return (0);
 }
 
 
@@ -91,78 +90,116 @@ hist_set(el, fun, ptr)
  *     eventno tells us the event to get.
  */
 protected el_action_t
-hist_get(el)
-    EditLine *el;
+hist_get(EditLine *el)
 {
-    const char    *hp;
-    int     h;
+       const char *hp;
+       int h;
 
-    if (el->el_history.eventno == 0) { /* if really the current line */
-       (void) strncpy(el->el_line.buffer, el->el_history.buf, EL_BUFSIZ);
-       el->el_line.lastchar = el->el_line.buffer +
-               (el->el_history.last - el->el_history.buf);
+       if (el->el_history.eventno == 0) {      /* if really the current line */
+               (void) strncpy(el->el_line.buffer, el->el_history.buf,
+                   el->el_history.sz);
+               el->el_line.lastchar = el->el_line.buffer +
+                   (el->el_history.last - el->el_history.buf);
 
 #ifdef KSHVI
-    if (el->el_map.type == MAP_VI)
-       el->el_line.cursor = el->el_line.buffer;
-    else
+               if (el->el_map.type == MAP_VI)
+                       el->el_line.cursor = el->el_line.buffer;
+               else
 #endif /* KSHVI */
-       el->el_line.cursor = el->el_line.lastchar;
+                       el->el_line.cursor = el->el_line.lastchar;
+
+               return (CC_REFRESH);
+       }
+       if (el->el_history.ref == NULL)
+               return (CC_ERROR);
+
+       hp = HIST_FIRST(el);
+
+       if (hp == NULL)
+               return (CC_ERROR);
+
+       for (h = 1; h < el->el_history.eventno; h++)
+               if ((hp = HIST_NEXT(el)) == NULL) {
+                       el->el_history.eventno = h;
+                       return (CC_ERROR);
+               }
+       (void) strlcpy(el->el_line.buffer, hp,
+                       (size_t)(el->el_line.limit - el->el_line.buffer));
+       el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
+
+       if (el->el_line.lastchar > el->el_line.buffer
+           && el->el_line.lastchar[-1] == '\n')
+               el->el_line.lastchar--;
+       if (el->el_line.lastchar > el->el_line.buffer
+           && el->el_line.lastchar[-1] == ' ')
+               el->el_line.lastchar--;
+#ifdef KSHVI
+       if (el->el_map.type == MAP_VI)
+               el->el_line.cursor = el->el_line.buffer;
+       else
+#endif /* KSHVI */
+               el->el_line.cursor = el->el_line.lastchar;
+
+       return (CC_REFRESH);
+}
 
-       return CC_REFRESH;
-    }
 
-    if (el->el_history.ref == NULL)
-       return CC_ERROR;
+/* hist_command()
+ *     process a history command
+ */
+protected int
+hist_command(EditLine *el, int argc, const char **argv)
+{
+       const char *str;
+       int num;
+       HistEvent ev;
 
-    hp = HIST_FIRST(el);
+       if (el->el_history.ref == NULL)
+               return (-1);
 
-    if (hp == NULL)
-       return CC_ERROR;
+       if (argc == 1 || strcmp(argv[1], "list") == 0) {
+                /* List history entries */
 
-    for (h = 1; h < el->el_history.eventno; h++)
-       if ((hp = HIST_NEXT(el)) == NULL) {
-           el->el_history.eventno = h;
-           return CC_ERROR;
+               for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
+                       (void) fprintf(el->el_outfile, "%d %s",
+                           el->el_history.ev.num, str);
+               return (0);
        }
 
-    (void) strncpy(el->el_line.buffer, hp, EL_BUFSIZ);
-    el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
+       if (argc != 3)
+               return (-1);
 
-    if (el->el_line.lastchar > el->el_line.buffer) {
-       if (el->el_line.lastchar[-1] == '\n')
-           el->el_line.lastchar--;
-       if (el->el_line.lastchar[-1] == ' ')
-           el->el_line.lastchar--;
-       if (el->el_line.lastchar < el->el_line.buffer)
-           el->el_line.lastchar = el->el_line.buffer;
-    }
+       num = (int)strtol(argv[2], NULL, 0);
 
-#ifdef KSHVI
-    if (el->el_map.type == MAP_VI)
-       el->el_line.cursor = el->el_line.buffer;
-    else
-#endif /* KSHVI */
-       el->el_line.cursor = el->el_line.lastchar;
+       if (strcmp(argv[1], "size") == 0)
+               return history(el->el_history.ref, &ev, H_SETSIZE, num);
+
+       if (strcmp(argv[1], "unique") == 0)
+               return history(el->el_history.ref, &ev, H_SETUNIQUE, num);
 
-    return CC_REFRESH;
+       return -1;
 }
 
-/* hist_list()
- *     List history entries
+/* hist_enlargebuf()
+ *     Enlarge history buffer to specified value. Called from el_enlargebufs().
+ *     Return 0 for failure, 1 for success.
  */
 protected int
 /*ARGSUSED*/
-hist_list(el, argc, argv)
-    EditLine *el;
-    int argc;
-    char **argv;
+hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
 {
-    const char *str;
+       char *newbuf;
 
-    if (el->el_history.ref == NULL)
-       return -1;
-    for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
-       (void) fprintf(el->el_outfile, "%d %s", el->el_history.ev->num, str);
-    return 0;
+       newbuf = realloc(el->el_history.buf, newsz);
+       if (!newbuf)
+               return 0;
+
+       (void) memset(&newbuf[oldsz], '\0', newsz - oldsz);
+
+       el->el_history.last = newbuf +
+                               (el->el_history.last - el->el_history.buf);
+       el->el_history.buf = newbuf;
+       el->el_history.sz  = newsz;
+
+       return 1;
 }
index d6d8fda..e64294a 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)hist.h      8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/hist.h,v 1.3 2003/11/12 20:21:29 eirikn Exp $
+ * @(#)hist.h  8.1 (Berkeley) 6/4/93
+ * $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $
+ * $DragonFly: src/lib/libedit/hist.h,v 1.4 2005/11/13 11:58:30 corecode Exp $
  */
 
 /*
  * el.hist.c: History functions
  */
 #ifndef _h_el_hist
-#define _h_el_hist
+#define        _h_el_hist
 
 #include "histedit.h"
 
-typedef const HistEvent *      (*hist_fun_t) (ptr_t, int, ...);
+typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...);
 
 typedef struct el_history_t {
-    char *buf;                         /* The history buffer           */
-    char *last;                                /* The last character           */
-    int eventno;                       /* Event we are looking for     */
-    ptr_t ref;                         /* Argument for history fcns    */
-    hist_fun_t fun;                    /* Event access                 */
-    const HistEvent *ev;               /* Event cookie                 */
+       char            *buf;           /* The history buffer           */
+       size_t          sz;             /* Size of history buffer       */
+       char            *last;          /* The last character           */
+       int              eventno;       /* Event we are looking for     */
+       ptr_t            ref;           /* Argument for history fcns    */
+       hist_fun_t       fun;           /* Event access                 */
+       HistEvent        ev;            /* Event cookie                 */
 } el_history_t;
 
-#define HIST_FUN(el, fn, arg)  \
-    ((((el)->el_history.ev = \
-       (*(el)->el_history.fun)((el)->el_history.ref, fn, arg)) == NULL) ? \
-     NULL : (el)->el_history.ev->str)
+#define        HIST_FUN(el, fn, arg)   \
+    ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
+       fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
 
 #define        HIST_NEXT(el)           HIST_FUN(el, H_NEXT, NULL)
 #define        HIST_FIRST(el)          HIST_FUN(el, H_FIRST, NULL)
 #define        HIST_LAST(el)           HIST_FUN(el, H_LAST, NULL)
 #define        HIST_PREV(el)           HIST_FUN(el, H_PREV, NULL)
-#define        HIST_EVENT(el, num)     HIST_FUN(el, H_EVENT, num)
-#define HIST_LOAD(el, fname)   HIST_FUN(el, H_LOAD fname)
-#define HIST_SAVE(el, fname)   HIST_FUN(el, H_SAVE fname)
+#define        HIST_SET(el, num)       HIST_FUN(el, H_SET, num)
+#define        HIST_LOAD(el, fname)    HIST_FUN(el, H_LOAD fname)
+#define        HIST_SAVE(el, fname)    HIST_FUN(el, H_SAVE fname)
 
-protected int          hist_init       (EditLine *);
-protected void                 hist_end        (EditLine *);
-protected el_action_t  hist_get        (EditLine *);
-protected int          hist_set        (EditLine *, hist_fun_t, ptr_t);
-protected int          hist_list       (EditLine *, int, char **);
+protected int          hist_init(EditLine *);
+protected void         hist_end(EditLine *);
+protected el_action_t  hist_get(EditLine *);
+protected int          hist_set(EditLine *, hist_fun_t, ptr_t);
+protected int          hist_command(EditLine *, int, const char **);
+protected int          hist_enlargebuf(EditLine *, size_t, size_t);
 
 #endif /* _h_el_hist */
index ccf09fb..95f53de 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  *
  * @(#)history.c       8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/history.c,v 1.5 2004/07/27 11:22:34 asmodai Exp $
+ * $NetBSD: history.c,v 1.29 2005/07/06 21:13:02 christos Exp $
+ * $DragonFly: src/lib/libedit/history.c,v 1.6 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * hist.c: History access functions
  */
-#include "sys.h"
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#ifdef HAVE_VIS_H
+#include <vis.h>
+#else
+#include "np/vis.h"
+#endif
+#include <sys/stat.h>
 
-static const char hist_cookie[] = "_HiStOrY_V1_\n";
+static const char hist_cookie[] = "_HiStOrY_V2_\n";
 
 #include "histedit.h"
 
-typedef const HistEvent *      (*history_gfun_t) (ptr_t);
-typedef const HistEvent *      (*history_efun_t) (ptr_t, const char *);
-typedef void                   (*history_vfun_t) (ptr_t);
+typedef int (*history_gfun_t)(ptr_t, HistEvent *);
+typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *);
+typedef void (*history_vfun_t)(ptr_t, HistEvent *);
+typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int);
 
 struct history {
-    ptr_t         h_ref;               /* Argument for history fcns    */
-    history_gfun_t h_first;            /* Get the first element        */
-    history_gfun_t h_next;             /* Get the next element         */
-    history_gfun_t h_last;             /* Get the last element         */
-    history_gfun_t h_prev;             /* Get the previous element     */
-    history_gfun_t h_curr;             /* Get the current element      */
-    history_vfun_t h_clear;            /* Clear the history list       */
-    history_efun_t h_enter;            /* Add an element               */
-    history_efun_t h_add;              /* Append to an element         */
+       ptr_t h_ref;            /* Argument for history fcns     */
+       int h_ent;              /* Last entry point for history  */
+       history_gfun_t h_first; /* Get the first element         */
+       history_gfun_t h_next;  /* Get the next element          */
+       history_gfun_t h_last;  /* Get the last element          */
+       history_gfun_t h_prev;  /* Get the previous element      */
+       history_gfun_t h_curr;  /* Get the current element       */
+       history_sfun_t h_set;   /* Set the current element       */
+       history_vfun_t h_clear; /* Clear the history list        */
+       history_efun_t h_enter; /* Add an element                */
+       history_efun_t h_add;   /* Append to an element          */
 };
 
-#define        HNEXT(h)        (*(h)->h_next)((h)->h_ref)
-#define        HFIRST(h)       (*(h)->h_first)((h)->h_ref)
-#define        HPREV(h)        (*(h)->h_prev)((h)->h_ref)
-#define        HLAST(h)        (*(h)->h_last)((h)->h_ref)
-#define        HCURR(h)        (*(h)->h_curr)((h)->h_ref)
-#define HCLEAR(h)      (*(h)->h_clear)((h)->h_ref)
-#define        HENTER(h, str)  (*(h)->h_enter)((h)->h_ref, str)
-#define        HADD(h, str)    (*(h)->h_add)((h)->h_ref, str)
-
-#define h_malloc(a)    malloc(a)
-#define h_free(a)      free(a)
-
-
-private int             history_set_num        (History *, int);
-private int             history_set_fun        (History *, History *);
-private int             history_load           (History *, const char *);
-private int             history_save           (History *, const char *);
-private const HistEvent *history_prev_event    (History *, int);
-private const HistEvent *history_next_event    (History *, int);
-private const HistEvent *history_next_string   (History *, const char *);
-private const HistEvent *history_prev_string   (History *, const char *);
+#define        HNEXT(h, ev)            (*(h)->h_next)((h)->h_ref, ev)
+#define        HFIRST(h, ev)           (*(h)->h_first)((h)->h_ref, ev)
+#define        HPREV(h, ev)            (*(h)->h_prev)((h)->h_ref, ev)
+#define        HLAST(h, ev)            (*(h)->h_last)((h)->h_ref, ev)
+#define        HCURR(h, ev)            (*(h)->h_curr)((h)->h_ref, ev)
+#define        HSET(h, ev, n)          (*(h)->h_set)((h)->h_ref, ev, n)
+#define        HCLEAR(h, ev)           (*(h)->h_clear)((h)->h_ref, ev)
+#define        HENTER(h, ev, str)      (*(h)->h_enter)((h)->h_ref, ev, str)
+#define        HADD(h, ev, str)        (*(h)->h_add)((h)->h_ref, ev, str)
+
+#define        h_strdup(a)     strdup(a)
+#define        h_malloc(a)     malloc(a)
+#define        h_realloc(a, b) realloc((a), (b))
+#define        h_free(a)       free(a)
+
+typedef struct {
+    int                num;
+    char       *str;
+} HistEventPrivate;
+
+
+
+private int history_setsize(History *, HistEvent *, int);
+private int history_getsize(History *, HistEvent *);
+private int history_setunique(History *, HistEvent *, int);
+private int history_getunique(History *, HistEvent *);
+private int history_set_fun(History *, History *);
+private int history_load(History *, const char *);
+private int history_save(History *, const char *);
+private int history_prev_event(History *, HistEvent *, int);
+private int history_next_event(History *, HistEvent *, int);
+private int history_next_string(History *, HistEvent *, const char *);
+private int history_prev_string(History *, HistEvent *, const char *);
 
 
 /***********************************************************************/
@@ -95,228 +113,349 @@ private const HistEvent *history_prev_string     (History *, const char *);
  * Builtin- history implementation
  */
 typedef struct hentry_t {
-    HistEvent ev;              /* What we return               */
-    struct hentry_t *next;     /* Next entry                   */
-    struct hentry_t *prev;     /* Previous entry               */
+       HistEvent ev;           /* What we return                */
+       struct hentry_t *next;  /* Next entry                    */
+       struct hentry_t *prev;  /* Previous entry                */
 } hentry_t;
 
 typedef struct history_t {
-    hentry_t  list;            /* Fake list header element     */
-    hentry_t *cursor;          /* Current element in the list  */
-    int        max;                    /* Maximum number of events     */
-    int cur;                   /* Current number of events     */
-    int        eventno;                /* Current event number         */
+       hentry_t list;          /* Fake list header element     */
+       hentry_t *cursor;       /* Current element in the list  */
+       int max;                /* Maximum number of events     */
+       int cur;                /* Current number of events     */
+       int eventid;            /* For generation of unique event id     */
+       int flags;              /* History flags                */
+#define H_UNIQUE       1       /* Store only unique elements   */
 } history_t;
 
-private const HistEvent *history_def_first  (ptr_t);
-private const HistEvent *history_def_last   (ptr_t);
-private const HistEvent *history_def_next   (ptr_t);
-private const HistEvent *history_def_prev   (ptr_t);
-private const HistEvent *history_def_curr   (ptr_t);
-private const HistEvent *history_def_enter  (ptr_t, const char *);
-private const HistEvent *history_def_add    (ptr_t, const char *);
-private void             history_def_init   (ptr_t *, int);
-private void             history_def_clear  (ptr_t);
-private const HistEvent *history_def_insert (history_t *, const char *);
-private void             history_def_delete (history_t *, hentry_t *);
-
-#define history_def_set(p, num)        (void) (((history_t *) p)->max = (num))
-
+private int history_def_first(ptr_t, HistEvent *);
+private int history_def_last(ptr_t, HistEvent *);
+private int history_def_next(ptr_t, HistEvent *);
+private int history_def_prev(ptr_t, HistEvent *);
+private int history_def_curr(ptr_t, HistEvent *);
+private int history_def_set(ptr_t, HistEvent *, const int n);
+private int history_def_enter(ptr_t, HistEvent *, const char *);
+private int history_def_add(ptr_t, HistEvent *, const char *);
+private int history_def_init(ptr_t *, HistEvent *, int);
+private void history_def_clear(ptr_t, HistEvent *);
+private int history_def_insert(history_t *, HistEvent *, const char *);
+private void history_def_delete(history_t *, HistEvent *, hentry_t *);
+
+#define        history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
+#define        history_def_getsize(p)  (((history_t *)p)->cur)
+#define        history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
+#define        history_def_setunique(p, uni) \
+    if (uni) \
+       (((history_t *)p)->flags) |= H_UNIQUE; \
+    else \
+       (((history_t *)p)->flags) &= ~H_UNIQUE
+
+#define        he_strerror(code)       he_errlist[code]
+#define        he_seterrev(evp, code)  {\
+                                   evp->num = code;\
+                                   evp->str = he_strerror(code);\
+                               }
+
+/* error messages */
+static const char *const he_errlist[] = {
+       "OK",
+       "unknown error",
+       "malloc() failed",
+       "first event not found",
+       "last event not found",
+       "empty list",
+       "no next event",
+       "no previous event",
+       "current event is invalid",
+       "event not found",
+       "can't read history from file",
+       "can't write history",
+       "required parameter(s) not supplied",
+       "history size negative",
+       "function not allowed with other history-functions-set the default",
+       "bad parameters"
+};
+/* error codes */
+#define        _HE_OK                   0
+#define        _HE_UNKNOWN              1
+#define        _HE_MALLOC_FAILED        2
+#define        _HE_FIRST_NOTFOUND       3
+#define        _HE_LAST_NOTFOUND        4
+#define        _HE_EMPTY_LIST           5
+#define        _HE_END_REACHED          6
+#define        _HE_START_REACHED        7
+#define        _HE_CURR_INVALID         8
+#define        _HE_NOT_FOUND            9
+#define        _HE_HIST_READ           10
+#define        _HE_HIST_WRITE          11
+#define        _HE_PARAM_MISSING       12
+#define        _HE_SIZE_NEGATIVE       13
+#define        _HE_NOT_ALLOWED         14
+#define        _HE_BAD_PARAM           15
 
 /* history_def_first():
  *     Default function to return the first event in the history.
  */
-private const HistEvent *
-history_def_first(p)
-    ptr_t p;
+private int
+history_def_first(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
-    h->cursor = h->list.next;
-    if (h->cursor != &h->list)
-       return &h->cursor->ev;
-    else
-       return NULL;
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.next;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_FIRST_NOTFOUND);
+               return (-1);
+       }
+
+       return (0);
 }
 
+
 /* history_def_last():
  *     Default function to return the last event in the history.
  */
-private const HistEvent *
-history_def_last(p)
-    ptr_t p;
+private int
+history_def_last(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
-    h->cursor = h->list.prev;
-    if (h->cursor != &h->list)
-       return &h->cursor->ev;
-    else
-       return NULL;
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.prev;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_LAST_NOTFOUND);
+               return (-1);
+       }
+
+       return (0);
 }
 
+
 /* history_def_next():
  *     Default function to return the next event in the history.
  */
-private const HistEvent *
-history_def_next(p)
-    ptr_t p;
+private int
+history_def_next(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
+       history_t *h = (history_t *) p;
 
-    if (h->cursor != &h->list)
-       h->cursor = h->cursor->next;
-    else
-       return NULL;
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return (-1);
+       }
+
+       if (h->cursor->next == &h->list) {
+               he_seterrev(ev, _HE_END_REACHED);
+               return (-1);
+       }
 
-    if (h->cursor != &h->list)
-       return &h->cursor->ev;
-    else
-       return NULL;
+        h->cursor = h->cursor->next;
+        *ev = h->cursor->ev;
+
+       return (0);
 }
 
 
 /* history_def_prev():
  *     Default function to return the previous event in the history.
  */
-private const HistEvent *
-history_def_prev(p)
-    ptr_t p;
+private int
+history_def_prev(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
+       history_t *h = (history_t *) p;
+
+       if (h->cursor == &h->list) {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
+               return (-1);
+       }
+
+       if (h->cursor->prev == &h->list) {
+               he_seterrev(ev, _HE_START_REACHED);
+               return (-1);
+       }
 
-    if (h->cursor != &h->list)
-       h->cursor = h->cursor->prev;
-    else
-       return NULL;
+        h->cursor = h->cursor->prev;
+        *ev = h->cursor->ev;
 
-    if (h->cursor != &h->list)
-       return &h->cursor->ev;
-    else
-       return NULL;
+       return (0);
 }
 
 
 /* history_def_curr():
  *     Default function to return the current event in the history.
  */
-private const HistEvent *
-history_def_curr(p)
-    ptr_t p;
+private int
+history_def_curr(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
+       history_t *h = (history_t *) p;
+
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
+               return (-1);
+       }
 
-    if (h->cursor != &h->list)
-       return &h->cursor->ev;
-    else
-       return NULL;
+       return (0);
+}
+
+
+/* history_def_set():
+ *     Default function to set the current event in the history to the
+ *     given one.
+ */
+private int
+history_def_set(ptr_t p, HistEvent *ev, const int n)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cur == 0) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return (-1);
+       }
+       if (h->cursor == &h->list || h->cursor->ev.num != n) {
+               for (h->cursor = h->list.next; h->cursor != &h->list;
+                   h->cursor = h->cursor->next)
+                       if (h->cursor->ev.num == n)
+                               break;
+       }
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_NOT_FOUND);
+               return (-1);
+       }
+       return (0);
 }
 
 
 /* history_def_add():
  *     Append string to element
  */
-private const HistEvent *
-history_def_add(p, str)
-    ptr_t p;
-    const char *str;
+private int
+history_def_add(ptr_t p, HistEvent *ev, const char *str)
 {
-    history_t *h = (history_t *) p;
-    size_t len;
-    char *s;
-
-    if (h->cursor == &h->list)
-       return (history_def_enter(p, str));
-    len = strlen(h->cursor->ev.str) + strlen(str) + 1;
-    s = (char *) h_malloc(len);
-    (void)strcpy(s, h->cursor->ev.str);        /* XXX strcpy is safe */
-    (void)strcat(s, str);                      /* XXX strcat is safe */
-    h_free((ptr_t) h->cursor->ev.str);
-    h->cursor->ev.str = s;
-    return &h->cursor->ev;
+       history_t *h = (history_t *) p;
+       size_t len;
+       char *s;
+       HistEventPrivate *evp = (void *)&h->cursor->ev;
+
+       if (h->cursor == &h->list)
+               return (history_def_enter(p, ev, str));
+       len = strlen(evp->str) + strlen(str) + 1;
+       s = (char *) h_malloc(len);
+       if (s == NULL) {
+               he_seterrev(ev, _HE_MALLOC_FAILED);
+               return (-1);
+       }
+       (void) strlcpy(s, h->cursor->ev.str, len);
+       (void) strlcat(s, str, len);
+       h_free((ptr_t)evp->str);
+       evp->str = s;
+       *ev = h->cursor->ev;
+       return (0);
 }
 
 
 /* history_def_delete():
  *     Delete element hp of the h list
  */
+/* ARGSUSED */
 private void
-history_def_delete(h, hp)
-    history_t *h;
-    hentry_t *hp;
+history_def_delete(history_t *h, 
+                  HistEvent *ev __attribute__((__unused__)), hentry_t *hp)
 {
-    if (hp == &h->list)
-       abort();
-    hp->prev->next = hp->next;
-    hp->next->prev = hp->prev;
-    h_free((ptr_t) hp->ev.str);
-    h_free(hp);
-    h->cur--;
+       HistEventPrivate *evp = (void *)&hp->ev;
+       if (hp == &h->list)
+               abort();
+       hp->prev->next = hp->next;
+       hp->next->prev = hp->prev;
+       h_free((ptr_t) evp->str);
+       h_free(hp);
+       h->cur--;
 }
 
 
 /* history_def_insert():
  *     Insert element with string str in the h list
  */
-private const HistEvent *
-history_def_insert(h, str)
-    history_t *h;
-    const char *str;
+private int
+history_def_insert(history_t *h, HistEvent *ev, const char *str)
 {
-    h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
-    h->cursor->ev.str = strdup(str);
-    h->cursor->next = h->list.next;
-    h->cursor->prev = &h->list;
-    h->list.next->prev = h->cursor;
-    h->list.next = h->cursor;
-    h->cur++;
-
-    return &h->cursor->ev;
+
+       h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
+       if (h->cursor == NULL)
+               goto oomem;
+       if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
+               h_free((ptr_t)h->cursor);
+               goto oomem;
+       }
+       h->cursor->ev.num = ++h->eventid;
+       h->cursor->next = h->list.next;
+       h->cursor->prev = &h->list;
+       h->list.next->prev = h->cursor;
+       h->list.next = h->cursor;
+       h->cur++;
+
+       *ev = h->cursor->ev;
+       return (0);
+oomem:
+       he_seterrev(ev, _HE_MALLOC_FAILED);
+       return (-1);
 }
 
 
 /* history_def_enter():
  *     Default function to enter an item in the history
  */
-private const HistEvent *
-history_def_enter(p, str)
-    ptr_t p;
-    const char *str;
+private int
+history_def_enter(ptr_t p, HistEvent *ev, const char *str)
 {
-    history_t *h = (history_t *) p;
-    const HistEvent *ev;
+       history_t *h = (history_t *) p;
+
+       if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
+           strcmp(h->list.next->ev.str, str) == 0)
+           return (0); 
 
+       if (history_def_insert(h, ev, str) == -1)
+               return (-1);    /* error, keep error message */
 
-    ev = history_def_insert(h, str);
-    ((HistEvent*) ev)->num = ++h->eventno;
+       /*
+         * Always keep at least one entry.
+         * This way we don't have to check for the empty list.
+         */
+       while (h->cur > h->max && h->cur > 0)
+               history_def_delete(h, ev, h->list.prev);
 
-    /*
-     * Always keep at least one entry.
-     * This way we don't have to check for the empty list.
-     */
-    while (h->cur > h->max + 1)
-       history_def_delete(h, h->list.prev);
-    return ev;
+       return (1);
 }
 
 
 /* history_def_init():
  *     Default history initialization function
  */
-private void
-history_def_init(p, n)
-    ptr_t *p;
-    int n;
+/* ARGSUSED */
+private int
+history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)
 {
-    history_t *h = (history_t *) h_malloc(sizeof(history_t));
-    if (n <= 0)
-       n = 0;
-    h->eventno = 0;
-    h->cur = 0;
-    h->max = n;
-    h->list.next = h->list.prev = &h->list;
-    h->list.ev.str = NULL;
-    h->list.ev.num = 0;
-    h->cursor = &h->list;
-    *p = (ptr_t) h;
+       history_t *h = (history_t *) h_malloc(sizeof(history_t));
+       if (h == NULL)
+               return -1;
+
+       if (n <= 0)
+               n = 0;
+       h->eventid = 0;
+       h->cur = 0;
+       h->max = n;
+       h->list.next = h->list.prev = &h->list;
+       h->list.ev.str = NULL;
+       h->list.ev.num = 0;
+       h->cursor = &h->list;
+       h->flags = 0;
+       *p = (ptr_t) h;
+       return 0;
 }
 
 
@@ -324,39 +463,48 @@ history_def_init(p, n)
  *     Default history cleanup function
  */
 private void
-history_def_clear(p)
-    ptr_t p;
+history_def_clear(ptr_t p, HistEvent *ev)
 {
-    history_t *h = (history_t *) p;
+       history_t *h = (history_t *) p;
 
-    while (h->list.prev != &h->list)
-       history_def_delete(h, h->list.prev);
-    h->eventno = 0;
-    h->cur = 0;
+       while (h->list.prev != &h->list)
+               history_def_delete(h, ev, h->list.prev);
+       h->eventid = 0;
+       h->cur = 0;
 }
 
+
+
+
 /************************************************************************/
 
 /* history_init():
  *     Initialization function.
  */
 public History *
-history_init()
+history_init(void)
 {
-    History *h = (History *) h_malloc(sizeof(History));
-
-    history_def_init(&h->h_ref, 0);
-
-    h->h_next  = history_def_next;
-    h->h_first = history_def_first;
-    h->h_last  = history_def_last;
-    h->h_prev  = history_def_prev;
-    h->h_curr  = history_def_curr;
-    h->h_clear = history_def_clear;
-    h->h_enter = history_def_enter;
-    h->h_add   = history_def_add;
-
-    return h;
+       HistEvent ev;
+       History *h = (History *) h_malloc(sizeof(History));
+       if (h == NULL)
+               return NULL;
+
+       if (history_def_init(&h->h_ref, &ev, 0) == -1) {
+               h_free((ptr_t)h);
+               return NULL;
+       }
+       h->h_ent = -1;
+       h->h_next = history_def_next;
+       h->h_first = history_def_first;
+       h->h_last = history_def_last;
+       h->h_prev = history_def_prev;
+       h->h_curr = history_def_curr;
+       h->h_set = history_def_set;
+       h->h_clear = history_def_clear;
+       h->h_enter = history_def_enter;
+       h->h_add = history_def_add;
+
+       return (h);
 }
 
 
@@ -364,27 +512,84 @@ history_init()
  *     clean up history;
  */
 public void
-history_end(h)
-    History *h;
+history_end(History *h)
 {
-    if (h->h_next == history_def_next)
-       history_def_clear(h->h_ref);
+       HistEvent ev;
+
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+       h_free(h);
 }
 
 
 
-/* history_set_num():
+/* history_setsize():
  *     Set history number of events
  */
 private int
-history_set_num(h, num)
-    History *h;
-    int num;
+history_setsize(History *h, HistEvent *ev, int num)
+{
+
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return (-1);
+       }
+       if (num < 0) {
+               he_seterrev(ev, _HE_BAD_PARAM);
+               return (-1);
+       }
+       history_def_setsize(h->h_ref, num);
+       return (0);
+}
+
+
+/* history_getsize():
+ *      Get number of events currently in history
+ */
+private int
+history_getsize(History *h, HistEvent *ev)
 {
-    if (h->h_next != history_def_next || num < 0)
-       return -1;
-    history_def_set(h->h_ref, num);
-    return 0;
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return (-1);
+       }
+       ev->num = history_def_getsize(h->h_ref);
+       if (ev->num < -1) {
+               he_seterrev(ev, _HE_SIZE_NEGATIVE);
+               return (-1);
+       }
+       return (0);
+}
+
+
+/* history_setunique():
+ *     Set if adjacent equal events should not be entered in history.
+ */
+private int
+history_setunique(History *h, HistEvent *ev, int uni)
+{
+
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return (-1);
+       }
+       history_def_setunique(h->h_ref, uni);
+       return (0);
+}
+
+
+/* history_getunique():
+ *     Get if adjacent equal events should not be entered in history.
+ */
+private int
+history_getunique(History *h, HistEvent *ev)
+{
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return (-1);
+       }
+       ev->num = history_def_getunique(h->h_ref);
+       return (0);
 }
 
 
@@ -392,39 +597,43 @@ history_set_num(h, num)
  *     Set history functions
  */
 private int
-history_set_fun(h, nh)
-    History *h, *nh;
+history_set_fun(History *h, History *nh)
 {
-    if (nh->h_first == NULL || nh->h_next == NULL ||
-       nh->h_last == NULL  || nh->h_prev == NULL || nh->h_curr == NULL ||
-       nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
-       nh->h_ref == NULL) {
-       if (h->h_next != history_def_next) {
-           history_def_init(&h->h_ref, 0);
-           h->h_first = history_def_first;
-           h->h_next  = history_def_next;
-           h->h_last  = history_def_last;
-           h->h_prev  = history_def_prev;
-           h->h_curr  = history_def_curr;
-           h->h_clear = history_def_clear;
-           h->h_enter = history_def_enter;
-           h->h_add   = history_def_add;
+       HistEvent ev;
+
+       if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
+           nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
+           nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
+           nh->h_ref == NULL) {
+               if (h->h_next != history_def_next) {
+                       history_def_init(&h->h_ref, &ev, 0);
+                       h->h_first = history_def_first;
+                       h->h_next = history_def_next;
+                       h->h_last = history_def_last;
+                       h->h_prev = history_def_prev;
+                       h->h_curr = history_def_curr;
+                       h->h_set = history_def_set;
+                       h->h_clear = history_def_clear;
+                       h->h_enter = history_def_enter;
+                       h->h_add = history_def_add;
+               }
+               return (-1);
        }
-       return -1;
-    }
-
-    if (h->h_next == history_def_next)
-       history_def_clear(h->h_ref);
-
-    h->h_first = nh->h_first;
-    h->h_next  = nh->h_next;
-    h->h_last  = nh->h_last;
-    h->h_prev  = nh->h_prev;
-    h->h_curr  = nh->h_curr;
-    h->h_clear = nh->h_clear;
-    h->h_enter = nh->h_enter;
-    h->h_add   = nh->h_add;
-    return 0;
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+
+       h->h_ent = -1;
+       h->h_first = nh->h_first;
+       h->h_next = nh->h_next;
+       h->h_last = nh->h_last;
+       h->h_prev = nh->h_prev;
+       h->h_curr = nh->h_curr;
+       h->h_set = nh->h_set;
+       h->h_clear = nh->h_clear;
+       h->h_enter = nh->h_enter;
+       h->h_add = nh->h_add;
+
+       return (0);
 }
 
 
@@ -432,34 +641,57 @@ history_set_fun(h, nh)
  *     History load function
  */
 private int
-history_load(h, fname)
-    History *h;
-    const char *fname;
+history_load(History *h, const char *fname)
 {
-    FILE *fp;
-    char *line;
-    size_t sz;
-    int i = -1;
-
-    if ((fp = fopen(fname, "r")) == NULL)
-       return i;
-
-    if ((line = fgetln(fp, &sz)) == NULL)
-       goto done;
-
-    if (strncmp(line, hist_cookie, sz) != 0)
-       goto done;
-       
-    for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
-       char c = line[sz];
-       line[sz] = '\0';
-       HENTER(h, line);
-       line[sz] = c;
-    }
-
+       FILE *fp;
+       char *line;
+       size_t sz, max_size;
+       char *ptr;
+       int i = -1;
+       HistEvent ev;
+
+       if ((fp = fopen(fname, "r")) == NULL)
+               return (i);
+
+       if ((line = fgetln(fp, &sz)) == NULL)
+               goto done;
+
+       if (strncmp(line, hist_cookie, sz) != 0)
+               goto done;
+
+       ptr = h_malloc(max_size = 1024);
+       if (ptr == NULL)
+               goto done;
+       for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+               char c = line[sz];
+
+               if (sz != 0 && line[sz - 1] == '\n')
+                       line[--sz] = '\0';
+               else
+                       line[sz] = '\0';
+
+               if (max_size < sz) {
+                       char *nptr;
+                       max_size = (sz + 1024) & ~1023;
+                       nptr = h_realloc(ptr, max_size);
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strunvis(ptr, line);
+               line[sz] = c;
+               if (HENTER(h, &ev, ptr) == -1) {
+                       h_free((ptr_t)ptr);
+                       return -1;
+               }
+       }
+oomem:
+       h_free((ptr_t)ptr);
 done:
-    (void) fclose(fp);
-    return i;
+       (void) fclose(fp);
+       return (i);
 }
 
 
@@ -467,201 +699,255 @@ done:
  *     History save function
  */
 private int
-history_save(h, fname)
-    History *h;
-    const char *fname;
+history_save(History *h, const char *fname)
 {
-    FILE *fp;
-    const HistEvent *ev;
-    int i = 0;
-
-    if ((fp = fopen(fname, "w")) == NULL)
-       return -1;
-
-    (void) fputs(hist_cookie, fp);
-    for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
-       (void) fprintf(fp, "%s", ev->str);
-    (void) fclose(fp);
-    return i;
+       FILE *fp;
+       HistEvent ev;
+       int i = -1, retval;
+       size_t len, max_size;
+       char *ptr;
+
+       if ((fp = fopen(fname, "w")) == NULL)
+               return (-1);
+
+       if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
+               goto done;
+       if (fputs(hist_cookie, fp) == EOF)
+               goto done;
+       ptr = h_malloc(max_size = 1024);
+       if (ptr == NULL)
+               goto done;
+       for (i = 0, retval = HLAST(h, &ev);
+           retval != -1;
+           retval = HPREV(h, &ev), i++) {
+               len = strlen(ev.str) * 4;
+               if (len >= max_size) {
+                       char *nptr;
+                       max_size = (len + 1024) & ~1023;
+                       nptr = h_realloc(ptr, max_size);
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strvis(ptr, ev.str, VIS_WHITE);
+               (void) fprintf(fp, "%s\n", ptr);
+       }
+oomem:
+       h_free((ptr_t)ptr);
+done:
+       (void) fclose(fp);
+       return (i);
 }
 
 
 /* history_prev_event():
  *     Find the previous event, with number given
  */
-private const HistEvent *
-history_prev_event(h, num)
-    History *h;
-    int num;
+private int
+history_prev_event(History *h, HistEvent *ev, int num)
 {
-    const HistEvent *ev;
-    for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
-       if (ev->num == num)
-           return ev;
-    return NULL;
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (ev->num == num)
+                       return (0);
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return (-1);
 }
 
 
 /* history_next_event():
  *     Find the next event, with number given
  */
-private const HistEvent *
-history_next_event(h, num)
-    History *h;
-    int num;
+private int
+history_next_event(History *h, HistEvent *ev, int num)
 {
-    const HistEvent *ev;
-    for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
-       if (ev->num == num)
-           return ev;
-    return NULL;
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (ev->num == num)
+                       return (0);
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return (-1);
 }
 
 
 /* history_prev_string():
  *     Find the previous event beginning with string
  */
-private const HistEvent *
-history_prev_string(h, str)
-    History *h;
-    const char* str;
+private int
+history_prev_string(History *h, HistEvent *ev, const char *str)
 {
-    const HistEvent *ev;
-    size_t len = strlen(str);
+       size_t len = strlen(str);
+       int retval;
 
-    for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
-       if (strncmp(str, ev->str, len) == 0)
-           return ev;
-    return NULL;
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (strncmp(str, ev->str, len) == 0)
+                       return (0);
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return (-1);
 }
 
 
 /* history_next_string():
  *     Find the next event beginning with string
  */
-private const HistEvent *
-history_next_string(h, str)
-    History *h;
-    const char* str;
+private int
+history_next_string(History *h, HistEvent *ev, const char *str)
 {
-    const HistEvent *ev;
-    size_t len = strlen(str);
+       size_t len = strlen(str);
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (strncmp(str, ev->str, len) == 0)
+                       return (0);
 
-    for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
-       if (strncmp(str, ev->str, len) == 0)
-           return ev;
-    return NULL;
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return (-1);
 }
 
 
 /* history():
  *     User interface to history functions.
  */
-const HistEvent *
-history(History *h, int fun, ...)
+int
+history(History *h, HistEvent *ev, int fun, ...)
 {
-    va_list va;
-    const HistEvent *ev = NULL;
-    const char *str;
-    static HistEvent sev = { 0, "" };
-
-    va_start(va, fun);
-
-    switch (fun) {
-    case H_ADD:
-       str = va_arg(va, const char *);
-       ev = HADD(h, str);
-       break;
-
-    case H_ENTER:
-       str = va_arg(va, const char *);
-       ev = HENTER(h, str);
-       break;
-
-    case H_FIRST:
-       ev = HFIRST(h);
-       break;
-
-    case H_NEXT:
-       ev = HNEXT(h);
-       break;
-
-    case H_LAST:
-       ev = HLAST(h);
-       break;
-
-    case H_PREV:
-       ev = HPREV(h);
-       break;
-
-    case H_CURR:
-       ev = HCURR(h);
-       break;
-
-    case H_CLEAR:
-       HCLEAR(h);
-       break;
-       
-    case H_LOAD:
-       sev.num = history_load(h, va_arg(va, const char *));
-       ev = &sev;
-       break;
-       
-    case H_SAVE:
-       sev.num = history_save(h, va_arg(va, const char *));
-       ev = &sev;
-       break;
-
-    case H_PREV_EVENT:
-       ev = history_prev_event(h, va_arg(va, int));
-       break;
-
-    case H_NEXT_EVENT:
-       ev = history_next_event(h, va_arg(va, int));
-       break;
-
-    case H_PREV_STR:
-       ev = history_prev_string(h, va_arg(va, const char*));
-       break;
-
-    case H_NEXT_STR:
-       ev = history_next_string(h, va_arg(va, const char*));
-       break;
-
-    case H_EVENT:
-       if (history_set_num(h, va_arg(va, int)) == 0) {
-           sev.num = -1;
-           ev = &sev;
-       }
-       break;
-
-    case H_FUNC:
+       va_list va;
+       const char *str;
+       int retval;
+
+       va_start(va, fun);
+
+       he_seterrev(ev, _HE_OK);
+
+       switch (fun) {
+       case H_GETSIZE:
+               retval = history_getsize(h, ev);
+               break;
+
+       case H_SETSIZE:
+               retval = history_setsize(h, ev, va_arg(va, int));
+               break;
+
+       case H_GETUNIQUE:
+               retval = history_getunique(h, ev);
+               break;
+
+       case H_SETUNIQUE:
+               retval = history_setunique(h, ev, va_arg(va, int));
+               break;
+
+       case H_ADD:
+               str = va_arg(va, const char *);
+               retval = HADD(h, ev, str);
+               break;
+
+       case H_ENTER:
+               str = va_arg(va, const char *);
+               if ((retval = HENTER(h, ev, str)) != -1)
+                       h->h_ent = ev->num;
+               break;
+
+       case H_APPEND:
+               str = va_arg(va, const char *);
+               if ((retval = HSET(h, ev, h->h_ent)) != -1)
+                       retval = HADD(h, ev, str);
+               break;
+
+       case H_FIRST:
+               retval = HFIRST(h, ev);
+               break;
+
+       case H_NEXT:
+               retval = HNEXT(h, ev);
+               break;
+
+       case H_LAST:
+               retval = HLAST(h, ev);
+               break;
+
+       case H_PREV:
+               retval = HPREV(h, ev);
+               break;
+
+       case H_CURR:
+               retval = HCURR(h, ev);
+               break;
+
+       case H_SET:
+               retval = HSET(h, ev, va_arg(va, const int));
+               break;
+
+       case H_CLEAR:
+               HCLEAR(h, ev);
+               retval = 0;
+               break;
+
+       case H_LOAD:
+               retval = history_load(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_READ);
+               break;
+
+       case H_SAVE:
+               retval = history_save(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_WRITE);
+               break;
+
+       case H_PREV_EVENT:
+               retval = history_prev_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_NEXT_EVENT:
+               retval = history_next_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_PREV_STR:
+               retval = history_prev_string(h, ev, va_arg(va, const char *));
+               break;
+
+       case H_NEXT_STR:
+               retval = history_next_string(h, ev, va_arg(va, const char *));
+               break;
+
+       case H_FUNC:
        {
-           History hf;
-           hf.h_ref   = va_arg(va, ptr_t);
-           hf.h_first = va_arg(va, history_gfun_t);
-           hf.h_next  = va_arg(va, history_gfun_t);
-           hf.h_last  = va_arg(va, history_gfun_t);
-           hf.h_prev  = va_arg(va, history_gfun_t);
-           hf.h_curr  = va_arg(va, history_gfun_t);
-           hf.h_clear = va_arg(va, history_vfun_t);
-           hf.h_enter = va_arg(va, history_efun_t);
-           hf.h_add   = va_arg(va, history_efun_t);
-
-           if (history_set_fun(h, &hf) == 0) {
-               sev.num = -1;
-               ev = &sev;
-           }
+               History hf;
+
+               hf.h_ref = va_arg(va, ptr_t);
+               h->h_ent = -1;
+               hf.h_first = va_arg(va, history_gfun_t);
+               hf.h_next = va_arg(va, history_gfun_t);
+               hf.h_last = va_arg(va, history_gfun_t);
+               hf.h_prev = va_arg(va, history_gfun_t);
+               hf.h_curr = va_arg(va, history_gfun_t);
+               hf.h_set = va_arg(va, history_sfun_t);
+               hf.h_clear = va_arg(va, history_vfun_t);
+               hf.h_enter = va_arg(va, history_efun_t);
+               hf.h_add = va_arg(va, history_efun_t);
+
+               if ((retval = history_set_fun(h, &hf)) == -1)
+                       he_seterrev(ev, _HE_PARAM_MISSING);
+               break;
        }
-       break;
 
-    case H_END:
-       history_end(h);
-       break;
+       case H_END:
+               history_end(h);
+               retval = 0;
+               break;
 
-    default:
-       break;
-    }
-    va_end(va);
-    return ev;
+       default:
+               retval = -1;
+               he_seterrev(ev, _HE_UNKNOWN);
+               break;
+       }
+       va_end(va);
+       return (retval);
 }
index 39affef..3a08f64 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * SUCH DAMAGE.
  *
  * @(#)key.c   8.1 (Berkeley) 6/4/93
- * $DragonFly: src/lib/libedit/key.c,v 1.4 2003/11/12 20:21:29 eirikn Exp $
+ * $NetBSD: key.c,v 1.16 2005/07/06 21:13:02 christos Exp $
+ * $DragonFly: src/lib/libedit/key.c,v 1.5 2005/11/13 11:58:30 corecode Exp $
  */
 
+#include "config.h"
+
 /*
  * key.c: This module contains the procedures for maintaining
  *       the extended-key map.
@@ -58,7 +57,6 @@
  *      1) It is not possible to have one key that is a
  *        substr of another.
  */
-#include "sys.h"
 #include <string.h>
 #include <stdlib.h>
 
  * of these node elements
  */
 struct key_node_t {
-    char        ch;            /* single character of key              */
-    int         type;          /* node type                            */
-    key_value_t val;           /* command code or pointer to str,      */
-                               /* if this is a leaf                    */
-    struct key_node_t *next;   /* ptr to next char of this key         */
-    struct key_node_t *sibling;        /* ptr to another key with same prefix  */
+       char            ch;             /* single character of key       */
+       int             type;           /* node type                     */
+       key_value_t     val;            /* command code or pointer to str,  */
+                                       /* if this is a leaf             */
+       struct key_node_t *next;        /* ptr to next char of this key  */
+       struct key_node_t *sibling;     /* ptr to another key with same prefix*/
 };
 
-private        int            node_trav        (EditLine *, key_node_t *, char *,
-                                            key_value_t *);
-private        int            node__try        (key_node_t *, char *,
-                                            key_value_t *, int);
-private        key_node_t    *node__get        (int);
-private        void           node__put        (key_node_t *);
-private        int            node__delete     (key_node_t **, char *);
-private        int            node_lookup      (EditLine *, char *, key_node_t *,
-                                            int);
-private        int            node_enum        (EditLine *, key_node_t *, int);
-private        int            key__decode_char (char *, int, int);
+private int             node_trav(EditLine *, key_node_t *, char *,
+    key_value_t *);
+private int             node__try(EditLine *, key_node_t *, const char *,
+    key_value_t *, int);
+private key_node_t     *node__get(int);
+private void            node__free(key_node_t *);
+private void            node__put(EditLine *, key_node_t *);
+private int             node__delete(EditLine *, key_node_t **, const char *);
+private int             node_lookup(EditLine *, const char *, key_node_t *,
+    int);
+private int             node_enum(EditLine *, key_node_t *, int);
+private int             key__decode_char(char *, int, int);
 
-#define KEY_BUFSIZ     EL_BUFSIZ
+#define        KEY_BUFSIZ      EL_BUFSIZ
 
 
 /* key_init():
  *     Initialize the key maps
  */
 protected int
-key_init(el)
-    EditLine *el;
+key_init(EditLine *el)
 {
-    el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
-    el->el_key.map = NULL;
-    key_reset(el);
-    return 0;
-}
 
+       el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
+       if (el->el_key.buf == NULL)
+               return (-1);
+       el->el_key.map = NULL;
+       key_reset(el);
+       return (0);
+}
 
 /* key_end():
  *     Free the key maps
  */
 protected void
-key_end(el)
-    EditLine *el;
+key_end(EditLine *el)
 {
-    el_free((ptr_t) el->el_key.buf);
-    el->el_key.buf = NULL;
-    /* XXX: provide a function to clear the keys */
-    el->el_key.map = NULL;
+
+       el_free((ptr_t) el->el_key.buf);
+       el->el_key.buf = NULL;
+       node__free(el->el_key.map);
 }
 
 
@@ -124,12 +123,11 @@ key_end(el)
  *     Associate cmd with a key value
  */
 protected key_value_t *
-key_map_cmd(el, cmd)
-    EditLine *el;
-    int cmd;
+key_map_cmd(EditLine *el, int cmd)
 {
-    el->el_key.val.cmd = (el_action_t) cmd;
-    return &el->el_key.val;
+
+       el->el_key.val.cmd = (el_action_t) cmd;
+       return (&el->el_key.val);
 }
 
 
@@ -137,12 +135,11 @@ key_map_cmd(el, cmd)
  *     Associate str with a key value
  */
 protected key_value_t *
-key_map_str(el, str)
-    EditLine *el;
-    char  *str;
+key_map_str(EditLine *el, char *str)
 {
-    el->el_key.val.str = str;
-    return &el->el_key.val;
+
+       el->el_key.val.str = str;
+       return (&el->el_key.val);