Initial checkin of libedit. This is straight from the 4.4BSD v2.1.5 CDROM

This commit is contained in:
gdr 1997-04-16 04:58:54 +00:00
parent 0f32e3990b
commit 5b657fd55a
36 changed files with 14005 additions and 0 deletions

54
lib/libedit/Makefile Normal file
View File

@ -0,0 +1,54 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
LIB= edit
OSRCS= chared.c common.c el.c emacs.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 \
help.c fcns.c help.h
LDADD+= -ltermcap
# For speed and debugging
#SRCS= ${OSRCS} tokenizer.c history.c
# For protection
SRCS= editline.c tokenizer.c history.c
CLEANFILES+=common.h emacs.h fcns.h help.h vi.h help.c fcns.c editline.c
CFLAGS+=-I. -I${.CURDIR}
CFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
CFLAGS+=#-DDEBUG_PASTE
AHDR=vi.h emacs.h common.h
ASRC=${.CURDIR}/vi.c ${.CURDIR}/emacs.c ${.CURDIR}/common.c
vi.h: vi.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/vi.c > ${.TARGET}
emacs.h: emacs.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/emacs.c > ${.TARGET}
common.h: common.c makelist
sh ${.CURDIR}/makelist -h ${.CURDIR}/common.c > ${.TARGET}
fcns.h: ${AHDR} makelist
sh ${.CURDIR}/makelist -fh ${AHDR} > ${.TARGET}
fcns.c: ${AHDR} fcns.h makelist
sh ${.CURDIR}/makelist -fc ${AHDR} > ${.TARGET}
help.c: ${ASRC} makelist
sh ${.CURDIR}/makelist -bc ${ASRC} > ${.TARGET}
help.h: ${ASRC} makelist
sh ${.CURDIR}/makelist -bh ${ASRC} > ${.TARGET}
editline.c: ${OSRCS}
sh ${.CURDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}
.depend: vi.h emacs.h common.h fcns.h help.h help.c
test: test.o libedit.a ${DPADD} ${LIBTERMCAP}
${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
.include <bsd.lib.mk>

213
lib/libedit/TEST/test.c Normal file
View File

@ -0,0 +1,213 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* test.c: A little test program
*/
#include "sys.h"
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include "histedit.h"
#include "tokenizer.h"
static int continuation = 0;
static EditLine *el = NULL;
static char *
/*ARGSUSED*/
prompt(el)
EditLine *el;
{
static char a[] = "Edit$";
static char b[] = "Edit>";
return continuation ? b : a;
}
static void
sig(i)
int i;
{
(void) fprintf(stderr, "Got signal %d.\n", i);
el_reset(el);
}
static unsigned char
/*ARGSUSED*/
complete(el, ch)
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;
}
}
closedir(dd);
return CC_ERROR;
}
int
/*ARGSUSED*/
main(argc, argv)
int argc;
char *argv[];
{
int num;
const char *buf;
Tokenizer *tok;
History *hist;
(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 */
tok = tok_init(NULL); /* Initialize the tokenizer */
el = el_init(*argv, stdin, stdout); /* Initialize editline */
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);
/* 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 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);
while ((buf = el_gets(el, &num)) != NULL && num != 0) {
int ac;
char **av;
#ifdef DEBUG
(void) fprintf(stderr, "got %d %s", num, buf);
#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 (el_parse(el, ac, av) != -1) {
tok_reset(tok);
continue;
}
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;
}
tok_reset(tok);
}
el_end(el);
tok_end(tok);
history_end(hist);
return 0;
}

639
lib/libedit/chared.c Normal file
View File

@ -0,0 +1,639 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* chared.c: Character editor utilities
*/
#include "sys.h"
#include <stdlib.h>
#include "el.h"
/* cv_undo():
* Handle state for the vi undo command
*/
protected void
cv_undo(el, action, size, ptr)
EditLine *el;
int action, size;
char *ptr;
{
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_insert():
* Insert num characters
*/
protected void
c_insert(el, num)
EditLine *el;
int num;
{
char *cp;
if (el->el_line.lastchar + num >= el->el_line.limit)
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 */
/* c_delafter():
* Delete num characters after the cursor
*/
protected void
c_delafter(el, num)
EditLine *el;
int num;
{
if (el->el_line.cursor + num > el->el_line.lastchar)
num = el->el_line.lastchar - el->el_line.cursor;
if (num > 0) {
char *cp;
if (el->el_map.current != el->el_map.emacs)
cv_undo(el, INSERT, num, el->el_line.cursor);
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
el->el_line.lastchar -= num;
}
}
/* c_delbefore():
* Delete num characters before the cursor
*/
protected void
c_delbefore(el, num)
EditLine *el;
int num;
{
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, 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;
}
}
/* ce__isword():
* Return if p is part of a word according to emacs
*/
protected int
ce__isword(p)
int p;
{
return isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL;
}
/* cv__isword():
* Return if p is part of a word according to vi
*/
protected int
cv__isword(p)
int p;
{
return !isspace(p);
}
/* c__prev_word():
* Find the previous word
*/
protected char *
c__prev_word(p, low, n, wtest)
register char *p, *low;
register int n;
int (*wtest) __P((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;
}
/* c__next_word():
* Find the next word
*/
protected char *
c__next_word(p, high, n, wtest)
register char *p, *high;
register int n;
int (*wtest) __P((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;
}
/* cv_next_word():
* Find the next word vi style
*/
protected char *
cv_next_word(el, p, high, n, wtest)
EditLine *el;
register char *p, *high;
register int n;
int (*wtest) __P((int));
{
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 (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;
}
/* cv_prev_word():
* Find the previous word vi style
*/
protected char *
cv_prev_word(el, p, low, n, wtest)
EditLine *el;
register char *p, *low;
register int n;
int (*wtest) __P((int));
{
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--;
p++;
while (isspace((unsigned char) *p))
p++;
}
/* p now points where we want it */
if (p < low)
return low;
else
return p;
}
#ifdef notdef
/* c__number():
* Ignore character p points to, return number appearing after that.
* A '$' by itself means a big number; "$-" is for negative; '^' means 1.
* Return p pointing to last char used.
*/
protected char *
c__number(p, num, dval)
char *p; /* character position */
int *num; /* Return value */
int dval; /* dval is the number to subtract from like $-3 */
{
register int i;
register int sign = 1;
if (*++p == '^') {
*num = 1;
return p;
}
if (*p == '$') {
if (*++p != '-') {
*num = 0x7fffffff; /* Handle $ */
return --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;
}
#endif
/* cv_delfini():
* Finish vi delete action
*/
protected void
cv_delfini(el)
EditLine *el;
{
register int size;
int oaction;
if (el->el_chared.c_vcmd.action & INSERT)
el->el_map.current = el->el_map.key;
oaction = el->el_chared.c_vcmd.action;
el->el_chared.c_vcmd.action = NOP;
if (el->el_chared.c_vcmd.pos == 0)
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);
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;
}
#ifdef notdef
/* ce__endword():
* Go to the end of this word according to emacs
*/
protected char *
ce__endword(p, high, n)
char *p, *high;
int n;
{
p++;
while (n--) {
while ((p < high) && isspace((unsigned char) *p))
p++;
while ((p < high) && !isspace((unsigned char) *p))
p++;
}
p--;
return p;
}
#endif
/* cv__endword():
* Go to the end of this word according to vi
*/
protected char *
cv__endword(p, high, n)
char *p, *high;
int n;
{
p++;
while (n--) {
while ((p < high) && isspace((unsigned char) *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;
}
/* ch_init():
* Initialize the character editor
*/
protected int
ch_init(el)
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;
}
/* ch_reset():
* Reset the character editor
*/
protected void
ch_reset(el)
EditLine *el;
{
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_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.mark = el->el_line.buffer;
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_history.eventno = 0;
}
/* ch_end():
* Free the data structures used by the editor
*/
protected void
ch_end(el)
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_insertstr():
* Insert string at cursorI
*/
public int
el_insertstr(el, s)
EditLine *el;
char *s;
{
int len;
if ((len = strlen(s)) == 0)
return -1;
if (el->el_line.lastchar + len >= el->el_line.limit)
return -1;
c_insert(el, len);
while (*s)
*el->el_line.cursor++ = *s++;
return 0;
}
/* el_deletestr():
* Delete num characters before the cursor
*/
public void
el_deletestr(el, n)
EditLine *el;
int n;
{
if (n <= 0)
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_gets():
* Get a string
*/
protected int
c_gets(el, buf)
EditLine *el;
char *buf;
{
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 0010: /* Delete and backspace */
case 0177:
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 0033: /* 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;
}
}
buf[len] = ch;
return len;
}
/* c_hpos():
* Return the current horizontal position of the cursor
*/
protected int
c_hpos(el)
EditLine *el;
{
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;
}
}

158
lib/libedit/chared.h Normal file
View File

@ -0,0 +1,158 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)chared.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.chared.h: Character editor interface
*/
#ifndef _h_el_chared
#define _h_el_chared
#include <ctype.h>
#include <string.h>
#include "histedit.h"
#define EL_MAXMACRO 10
/*
* This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works
* like real vi: i.e. the transition from command<->insert modes moves
* the cursor.
*
* On the other hand we really don't want to move the cursor, because
* all the editing commands don't include the character under the cursor.
* Probably the best fix is to make all the editing commands aware of
* this fact.
*/
#define VI_MOVE
typedef struct c_macro_t {
int level;
char **macro;
char *nline;
} c_macro_t;
/*
* Undo information for both vi and emacs
*/
typedef struct c_undo_t {
int action;
int isize;
int dsize;
char *ptr;
char *buf;
} c_undo_t;
/*
* Current action information for vi
*/
typedef struct c_vcmd_t {
int action;
char *pos;
char *ins;
} c_vcmd_t;
/*
* Kill buffer for emacs
*/
typedef struct c_kill_t {
char *buf;
char *last;
char *mark;
} c_kill_t;
/*
* Note that we use both data structures because the user can bind
* 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;
} el_chared_t;
#define STReof "^D\b\b"
#define STRQQ "\"\""
#define isglob(a) (strchr("*[]?", (a)) != NULL)
#define isword(a) (isprint(a))
#define NOP 0x00
#define DELETE 0x01
#define INSERT 0x02
#define CHANGE 0x04
#define CHAR_FWD 0
#define CHAR_BACK 1
#define MODE_INSERT 0
#define MODE_REPLACE 1
#define MODE_REPLACE_1 2
#include "common.h"
#include "vi.h"
#include "emacs.h"
#include "search.h"
#include "fcns.h"
protected int cv__isword __P((int));
protected void cv_delfini __P((EditLine *));
protected char *cv__endword __P((char *, char *, int));
protected int ce__isword __P((int));
protected void cv_undo __P((EditLine *, int, int, char *));
protected char *cv_next_word __P((EditLine*, char *, char *, int,
int (*)(int)));
protected char *cv_prev_word __P((EditLine*, char *, char *, int,
int (*)(int)));
protected char *c__next_word __P((char *, char *, int, int (*)(int)));
protected char *c__prev_word __P((char *, char *, int, int (*)(int)));
protected void c_insert __P((EditLine *, int));
protected void c_delbefore __P((EditLine *, int));
protected void c_delafter __P((EditLine *, int));
protected int c_gets __P((EditLine *, char *));
protected int c_hpos __P((EditLine *));
protected int ch_init __P((EditLine *));
protected void ch_reset __P((EditLine *));
protected void ch_end __P((EditLine *));
#endif /* _h_el_chared */

994
lib/libedit/common.c Normal file
View File

@ -0,0 +1,994 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* common.c: Common Editor functions
*/
#include "sys.h"
#include "el.h"
/* ed_end_of_file():
* Indicate end of file
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
ed_end_of_file(el, c)
EditLine *el;
int c;
{
re_goto_bottom(el);
*el->el_line.lastchar = '\0';
return CC_EOF;
}
/* ed_insert():
* Add character to the line
* Insert a character [bound to all insert keys]
*/
protected el_action_t
ed_insert(el, c)
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);
}
c_insert(el, 1);
*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);
}
c_insert(el, el->el_state.argument);
while (el->el_state.argument--)
*el->el_line.cursor++ = c;
re_refresh(el);
}
if (el->el_state.inputmode == MODE_REPLACE_1)
(void) vi_command_mode(el, 0);
return CC_NORM;
}
/* ed_delete_prev_word():
* Delete from beginning of current word to cursor
* [M-^?] [^W]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_prev_word(el, c)
EditLine *el;
int c;
{
char *cp, *p, *kp;
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);
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;
}
/* ed_delete_next_char():
* Delete character under cursor
* [^D] [x]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_next_char(el, c)
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);
#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 */
#ifdef KSHVI
return CC_ERROR;
#else
term_overwrite(el, STReof, 4);/* then do a EOF */
term__flush();
return CC_EOF;
#endif
}
else {
#ifdef KSHVI
el->el_line.cursor--;
#else
return CC_ERROR;
#endif
}
}
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;
}
/* ed_kill_line():
* Cut to the end of line
* [^K] [^K]
*/
protected el_action_t
/*ARGSUSED*/
ed_kill_line(el, c)
EditLine *el;
int c;
{
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;
}
/* ed_move_to_end():
* Move cursor to the end of line
* [^E] [^E]
*/
protected el_action_t
/*ARGSUSED*/
ed_move_to_end(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.lastchar;
if (el->el_map.type == MAP_VI) {
#ifdef VI_MOVE
el->el_line.cursor--;
#endif
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
}
return CC_CURSOR;
}
/* ed_move_to_beg():
* Move cursor to the beginning of line
* [^A] [^A]
*/
protected el_action_t
/*ARGSUSED*/
ed_move_to_beg(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.buffer;
if (el->el_map.type == MAP_VI) {
/* We want FIRST non space character */
while (isspace(*el->el_line.cursor))
el->el_line.cursor++;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
}
return CC_CURSOR;
}
/* ed_transpose_chars():
* Exchange the character to the left of the cursor with the one under it
* [^T] [^T]
*/
protected el_action_t
ed_transpose_chars(el, c)
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;
}
/* ed_next_char():
* Move to the right one character
* [^F] [^F]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_char(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor >= el->el_line.lastchar)
return CC_ERROR;
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_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* ed_prev_word():
* Move to the beginning of the current word
* [M-b] [b]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_word(el, c)
EditLine *el;
int c;
{
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_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* ed_prev_char():
* Move to the left one character
* [^B] [^B]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_char(el, c)
EditLine *el;
int c;
{
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;
}
return CC_CURSOR;
}
else
return CC_ERROR;
}
/* ed_quoted_insert():
* Add the next character typed verbatim
* [^V] [^V]
*/
protected el_action_t
ed_quoted_insert(el, c)
EditLine *el;
int c;
{
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);
}
/* ed_digit():
* Adds to argument or enters a digit
*/
protected el_action_t
ed_digit(el, c)
EditLine *el;
int c;
{
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;
}
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;
}
/* ed_argument_digit():
* Digit that starts argument
* For ESC-n
*/
protected el_action_t
ed_argument_digit(el, c)
EditLine *el;
register int c;
{
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;
}
/* ed_unassigned():
* Indicates unbound character
* Bound to keys that are not assigned
*/
protected el_action_t
/*ARGSUSED*/
ed_unassigned(el, c)
EditLine *el;
int c;
{
term_beep(el);
term__flush();
return CC_NORM;
}
/**
** TTY key handling.
**/
/* ed_tty_sigint():
* Tty interrupt character
* [^C]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigint(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_dsusp():
* Tty delayed suspend character
* [^Y]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_dsusp(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_flush_output():
* Tty flush output characters
* [^O]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_flush_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_sigquit():
* Tty quit character
* [^\]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigquit(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_sigtstp():
* Tty suspend character
* [^Z]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigtstp(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_stop_output():
* Tty disallow output characters
* [^S]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_stop_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_tty_start_output():
* Tty allow output characters
* [^Q]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_start_output(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_newline():
* Execute command
* [^J]
*/
protected el_action_t
/*ARGSUSED*/
ed_newline(el, c)
EditLine *el;
int c;
{
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;
}
/* ed_delete_prev_char():
* Delete the character to the left of the cursor
* [^?]
*/
protected el_action_t
/*ARGSUSED*/
ed_delete_prev_char(el, c)
EditLine *el;
int c;
{
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;
}
/* ed_clear_screen():
* Clear screen leaving current line at the top
* [^L]
*/
protected el_action_t
/*ARGSUSED*/
ed_clear_screen(el, c)
EditLine *el;
int c;
{
term_clear_screen(el); /* clear the whole real screen */
re_clear_display(el); /* reset everything */
return CC_REFRESH;
}
/* ed_redisplay():
* Redisplay everything
* ^R
*/
protected el_action_t
/*ARGSUSED*/
ed_redisplay(el, c)
EditLine *el;
int c;
{
re_clear_lines(el);
re_clear_display(el);
return CC_REFRESH;
}
/* ed_start_over():
* Erase current line and start from scratch
* [^G]
*/
protected el_action_t
/*ARGSUSED*/
ed_start_over(el, c)
EditLine *el;
int c;
{
ch_reset(el);
return CC_REFRESH;
}
/* ed_sequence_lead_in():
* First character in a bound sequence
* Placeholder for external keys
*/
protected el_action_t
/*ARGSUSED*/
ed_sequence_lead_in(el, c)
EditLine *el;
int c;
{
return CC_NORM;
}
/* ed_prev_history():
* Move to the previous history line
* [^P] [k]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_history(el, c)
EditLine *el;
int c;
{
char beep = 0;
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
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) {
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 */
}
/* ed_next_history():
* Move to the next history line
* [^N] [j]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_history(el, c)
EditLine *el;
int c;
{
el->el_chared.c_undo.action = NOP;
*el->el_line.lastchar = '\0'; /* just in case */
el->el_history.eventno -= el->el_state.argument;
if (el->el_history.eventno < 0) {
el->el_history.eventno = 0;
return CC_ERROR; /* make it beep */
}
return hist_get(el);
}
/* ed_search_prev_history():
* Search previous in history for a line matching the current
* next search history [M-P] [K]
*/
protected el_action_t
/*ARGSUSED*/
ed_search_prev_history(el, c)
EditLine *el;
int c;
{
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) {
#ifdef DEBUG_EDIT
(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;
hp = HIST_FIRST(el);
if (hp == NULL)
return CC_ERROR;
c_setpat(el); /* Set search pattern !! */
for (h = 1; h <= el->el_history.eventno; h++)
hp = HIST_NEXT(el);
while (hp != NULL) {
#ifdef SDEBUG
(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;
}
h++;
hp = HIST_NEXT(el);
}
if (!found) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
el->el_history.eventno = h;
return hist_get(el);
}
/* ed_search_next_history():
* Search next in history for a line matching the current
* [M-N] [J]
*/
protected el_action_t
/*ARGSUSED*/
ed_search_next_history(el, c)
EditLine *el;
int c;
{
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)
return CC_ERROR;
if (el->el_history.ref == NULL)
return CC_ERROR;
hp = HIST_FIRST(el);
if (hp == NULL)
return CC_ERROR;
c_setpat(el); /* Set search pattern !! */
for (h = 1; h < el->el_history.eventno && hp; h++) {
#ifdef SDEBUG
(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)) {
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "not found\n");
#endif
return CC_ERROR;
}
}
el->el_history.eventno = found;
return hist_get(el);
}
/* ed_prev_line():
* Move up one line
* Could be [k] [^p]
*/
protected el_action_t
/*ARGSUSED*/
ed_prev_line(el, c)
EditLine *el;
int c;
{
char *ptr;
int nchars = c_hpos(el);
/*
* 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;
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 character requested
*/
for (ptr++;
nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
ptr++)
continue;
el->el_line.cursor = ptr;
return CC_CURSOR;
}
/* ed_next_line():
* Move down one line
* Could be [j] [^n]
*/
protected el_action_t
/*ARGSUSED*/
ed_next_line(el, c)
EditLine *el;
int c;
{
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;
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;
el->el_line.cursor = ptr;
return CC_CURSOR;
}
/* ed_command():
* Editline extended command
* [M-X] [:]
*/
protected el_action_t
/*ARGSUSED*/
ed_command(el, c)
EditLine *el;
int c;
{
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);
tmplen = c_gets(el, tmpbuf);
tmpbuf[tmplen] = '\0';
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (parse_line(el, tmpbuf) == -1)
return CC_ERROR;
else
return CC_REFRESH;
}

335
lib/libedit/el.c Normal file
View File

@ -0,0 +1,335 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
#endif /* not lint && not SCCSID */
/*
* el.c: EditLine interface functions
*/
#include "sys.h"
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <stdlib.h>
#if __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include "el.h"
/* el_init():
* Initialize editline and set default parameters.
*/
public EditLine *
el_init(prog, fin, fout)
const char *prog;
FILE *fin, *fout;
{
EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));
#ifdef DEBUG
char *tty;
#endif
if (el == NULL)
return NULL;
memset(el, 0, sizeof(EditLine));
el->el_infd = fileno(fin);
el->el_outfile = fout;
el->el_prog = strdup(prog);
#ifdef DEBUG
if ((tty = getenv("DEBUGTTY")) != NULL) {
el->el_errfile = fopen(tty, "w");
if (el->el_errfile == NULL) {
extern errno;
(void) fprintf(stderr, "Cannot open %s (%s).\n",
tty, strerror(errno));
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;
return el;
} /* end el_init */
/* el_end():
* Clean up.
*/
public void
el_end(el)
EditLine *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);
el_free((ptr_t) el->el_prog);
el_free((ptr_t) el);
} /* end el_end */
/* el_reset():
* Reset the tty and the parser
*/
public void
el_reset(el)
EditLine *el;
{
tty_cookedmode(el);
ch_reset(el); /* XXX: Do we want that? */
}
/* el_set():
* set the editline parameters
*/
public int
#if __STDC__
el_set(EditLine *el, int op, ...)
#else
el_set(va_alist)
va_dcl
#endif
{
va_list va;
int rv;
#if __STDC__
va_start(va, op);
#else
EditLine *el;
int op;
va_start(va);
el = va_arg(va, EditLine *);
op = va_arg(va, int);
#endif
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:
{
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;
abort();
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);
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 *);
rv = hist_set(el, func, ptr);
}
break;
default:
rv = -1;
}
va_end(va);
return rv;
} /* end el_set */
/* el_line():
* Return editing info
*/
public const LineInfo *
el_line(el)
EditLine *el;
{
return (const LineInfo *) &el->el_line;
}
static const char elpath[] = "/.editrc";
/* el_source():
* Source a file
*/
public int
el_source(el, fname)
EditLine *el;
const char *fname;
{
FILE *fp;
size_t len;
char *ptr, path[MAXPATHLEN];
if (fname == NULL) {
fname = &elpath[1];
if ((fp = fopen(fname, "r")) == NULL) {
if ((ptr = getenv("HOME")) == NULL)
return -1;
fname = strncpy(path, ptr, MAXPATHLEN);
(void) strncat(path, elpath, MAXPATHLEN);
path[MAXPATHLEN-1] = '\0';
}
}
if ((fp = fopen(fname, "r")) == NULL)
return -1;
while ((ptr = fgetln(fp, &len)) != NULL)
ptr[len - 1] = '\0';
if (parse_line(el, ptr) == -1) {
(void) fclose(fp);
return -1;
}
(void) fclose(fp);
return 0;
}
/* el_resize():
* Called from program when terminal is resized
*/
public void
el_resize(el)
EditLine *el;
{
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);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}

129
lib/libedit/el.h Normal file
View File

@ -0,0 +1,129 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)el.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.h: Internal structures.
*/
#ifndef _h_el
#define _h_el
/*
* Local defaults
*/
#define KSHVI
#define VIDEFAULT
#define ANCHOR
#include <stdio.h>
#include <sys/types.h>
#define EL_BUFSIZ 1024 /* Maximum line size */
#define HANDLE_SIGNALS 1
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;
} coord_t;
typedef struct el_line_t {
char *buffer, /* Input line */
*cursor, /* Cursor position */
*lastchar, /* Last character */
*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 */
} 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_free(a) free(a)
#include "tty.h"
#include "prompt.h"
#include "key.h"
#include "term.h"
#include "refresh.h"
#include "chared.h"
#include "common.h"
#include "search.h"
#include "hist.h"
#include "map.h"
#include "parse.h"
#include "sig.h"
#include "help.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 */
};
#endif /* _h_el */

504
lib/libedit/emacs.c Normal file
View File

@ -0,0 +1,504 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* emacs.c: Emacs functions
*/
#include "sys.h"
#include "el.h"
/* em_delete_or_list():
* Delete character under cursor or list completions if at end of line
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
em_delete_or_list(el, c)
EditLine *el;
int c;
{
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 {
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;
}
}
/* em_delete_next_word():
* Cut from cursor to end of current word
* [M-d]
*/
protected el_action_t
/*ARGSUSED*/
em_delete_next_word(el, c)
EditLine *el;
int c;
{
char *cp, *p, *kp;
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);
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;
}
/* em_yank():
* Paste cut buffer at cursor position
* [^Y]
*/
protected el_action_t
/*ARGSUSED*/
em_yank(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
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;
/* 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;
return CC_REFRESH;
}
/* em_kill_line():
* Cut the entire line and save in cut buffer
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
em_kill_line(el, c)
EditLine *el;
int c;
{
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;
}
/* em_kill_region():
* Cut area between mark and cursor and save in cut buffer
* [^W]
*/
protected el_action_t
/*ARGSUSED*/
em_kill_region(el, c)
EditLine *el;
int c;
{
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;
}
/* em_copy_region():
* Copy area between mark and cursor to cut buffer
* [M-W]
*/
protected el_action_t
/*ARGSUSED*/
em_copy_region(el, c)
EditLine *el;
int c;
{
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():
* Exchange the two characters before the cursor
* Gosling emacs transpose chars [^T]
*/
protected el_action_t
em_gosmacs_traspose(el, c)
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;
}
/* em_next_word():
* Move next to end of current word
* [M-f]
*/
protected el_action_t
/*ARGSUSED*/
em_next_word(el, c)
EditLine *el;
int c;
{
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;
}
/* em_upper_case():
* Uppercase the characters from cursor to end of current word
* [M-u]
*/
protected el_action_t
/*ARGSUSED*/
em_upper_case(el, c)
EditLine *el;
int c;
{
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 (islower(*cp))
*cp = toupper(*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_capitol_case():
* Capitalize the characters from cursor to end of current word
* [M-c]
*/
protected el_action_t
/*ARGSUSED*/
em_capitol_case(el, c)
EditLine *el;
int c;
{
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(*cp)) {
if (islower(*cp))
*cp = toupper(*cp);
cp++;
break;
}
}
for (; cp < ep; cp++)
if (isupper(*cp))
*cp = tolower(*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(el, c)
EditLine *el;
int c;
{
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 (isupper(*cp))
*cp = tolower(*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_set_mark():
* Set the mark at cursor
* [^@]
*/
protected el_action_t
/*ARGSUSED*/
em_set_mark(el, c)
EditLine *el;
int c;
{
el->el_chared.c_kill.mark = el->el_line.cursor;
return CC_NORM;
}
/* em_exchange_mark():
* Exchange the cursor and mark
* [^X^X]
*/
protected el_action_t
/*ARGSUSED*/
em_exchange_mark(el, c)
EditLine *el;
int c;
{
register 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;
}
/* em_universal_argument():
* Universal argument (argument times 4)
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
em_universal_argument(el, c)
EditLine *el;
int c;
{ /* 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;
}
/* em_meta_next():
* Add 8th bit to next character typed
* [<ESC>]
*/
protected el_action_t
/*ARGSUSED*/
em_meta_next(el, c)
EditLine *el;
int c;
{
el->el_state.metanext = 1;
return CC_ARGHACK;
}
/* em_toggle_overwrite():
* Switch from insert to overwrite mode or vice versa
*/
protected el_action_t
/*ARGSUSED*/
em_toggle_overwrite(el, c)
EditLine *el;
int c;
{
el->el_state.inputmode =
(el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT;
return CC_NORM;
}
/* em_copy_prev_word():
* Copy current word to cursor
*/
protected el_action_t
/*ARGSUSED*/
em_copy_prev_word(el, c)
EditLine *el;
int c;
{
char *cp, *oldc, *dp;
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);
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 */
return CC_REFRESH;
}
/* em_inc_search_next():
* Emacs incremental next search
*/
protected el_action_t
/*ARGSUSED*/
em_inc_search_next(el, c)
EditLine *el;
int c;
{
el->el_search.patlen = 0;
return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
}
/* em_inc_search_prev():
* Emacs incremental reverse search
*/
protected el_action_t
/*ARGSUSED*/
em_inc_search_prev(el, c)
EditLine *el;
int c;
{
el->el_search.patlen = 0;
return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
}

170
lib/libedit/hist.c Normal file
View File

@ -0,0 +1,170 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* hist.c: History access functions
*/
#include "sys.h"
#include <stdlib.h>
#include "el.h"
/* hist_init():
* Initialization function.
*/
protected int
hist_init(el)
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;
}
/* hist_end():
* clean up history;
*/
protected void
hist_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_history.buf);
el->el_history.buf = NULL;
}
/* hist_set():
* Set new history interface
*/
protected int
hist_set(el, fun, ptr)
EditLine *el;
hist_fun_t fun;
ptr_t ptr;
{
el->el_history.ref = ptr;
el->el_history.fun = fun;
return 0;
}
/* hist_get():
* Get a history line and update it in the buffer.
* eventno tells us the event to get.
*/
protected el_action_t
hist_get(el)
EditLine *el;
{
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);
#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;
}
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) strncpy(el->el_line.buffer, hp, EL_BUFSIZ);
el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
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;
}
#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;
}
/* hist_list()
* List history entries
*/
protected int
/*ARGSUSED*/
hist_list(el, argc, argv)
EditLine *el;
int argc;
char **argv;
{
const char *str;
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;
}

75
lib/libedit/hist.h Normal file
View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)hist.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.hist.c: History functions
*/
#ifndef _h_el_hist
#define _h_el_hist
#include "histedit.h"
typedef const HistEvent * (*hist_fun_t) __P((ptr_t, 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 */
} 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_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)
protected int hist_init __P((EditLine *));
protected void hist_end __P((EditLine *));
protected el_action_t hist_get __P((EditLine *));
protected int hist_set __P((EditLine *, hist_fun_t, ptr_t));
protected int hist_list __P((EditLine *, int, char **));
#endif /* _h_el_hist */

602
lib/libedit/history.c Normal file
View File

@ -0,0 +1,602 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* hist.c: History access functions
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "histedit.h"
typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
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_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 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 __P((History *, int));
private int history_set_fun __P((History *, history_gfun_t,
history_gfun_t,
history_gfun_t,
history_gfun_t,
history_gfun_t,
history_efun_t,
history_efun_t, ptr_t));
private const HistEvent *history_prev_event __P((History *, int));
private const HistEvent *history_next_event __P((History *, int));
private const HistEvent *history_next_string __P((History *, const char *));
private const HistEvent *history_prev_string __P((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 */
} 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 */
} history_t;
private const HistEvent *history_def_first __P((ptr_t));
private const HistEvent *history_def_last __P((ptr_t));
private const HistEvent *history_def_next __P((ptr_t));
private const HistEvent *history_def_prev __P((ptr_t));
private const HistEvent *history_def_curr __P((ptr_t));
private const HistEvent *history_def_enter __P((ptr_t, const char *));
private const HistEvent *history_def_add __P((ptr_t, const char *));
private void history_def_init __P((ptr_t *, int));
private void history_def_end __P((ptr_t));
private const HistEvent *history_def_insert __P((history_t *, const char *));
private void history_def_delete __P((history_t *, hentry_t *));
#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
/* history_def_first():
* Default function to return the first event in the history.
*/
private const HistEvent *
history_def_first(p)
ptr_t p;
{
history_t *h = (history_t *) p;
h->cursor = h->list.next;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_last():
* Default function to return the last event in the history.
*/
private const HistEvent *
history_def_last(p)
ptr_t p;
{
history_t *h = (history_t *) p;
h->cursor = h->list.prev;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_next():
* Default function to return the next event in the history.
*/
private const HistEvent *
history_def_next(p)
ptr_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)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_prev():
* Default function to return the previous event in the history.
*/
private const HistEvent *
history_def_prev(p)
ptr_t p;
{
history_t *h = (history_t *) p;
if (h->cursor != &h->list)
h->cursor = h->cursor->prev;
else
return NULL;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_curr():
* Default function to return the current event in the history.
*/
private const HistEvent *
history_def_curr(p)
ptr_t p;
{
history_t *h = (history_t *) p;
if (h->cursor != &h->list)
return &h->cursor->ev;
else
return NULL;
}
/* history_def_add():
* Append string to element
*/
private const HistEvent *
history_def_add(p, str)
ptr_t p;
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);
(void) strcat(s, str);
h_free((ptr_t) h->cursor->ev.str);
h->cursor->ev.str = s;
return &h->cursor->ev;
}
/* history_def_delete():
* Delete element hp of the h list
*/
private void
history_def_delete(h, hp)
history_t *h;
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--;
}
/* 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;
{
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;
}
/* 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;
{
history_t *h = (history_t *) p;
const HistEvent *ev;
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 + 1)
history_def_delete(h, h->list.prev);
return ev;
}
/* history_def_init():
* Default history initialization function
*/
private void
history_def_init(p, n)
ptr_t *p;
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_def_end():
* Default history cleanup function
*/
private void
history_def_end(p)
ptr_t p;
{
history_t *h = (history_t *) p;
while (h->list.prev != &h->list)
history_def_delete(h, h->list.prev);
}
/************************************************************************/
/* history_init():
* Initialization function.
*/
public History *
history_init()
{
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_enter = history_def_enter;
h->h_add = history_def_add;
return h;
}
/* history_end():
* clean up history;
*/
public void
history_end(h)
History *h;
{
if (h->h_next == history_def_next)
history_def_end(h->h_ref);
}
/* history_set_num():
* Set history number of events
*/
private int
history_set_num(h, num)
History *h;
int num;
{
if (h->h_next != history_def_next || num < 0)
return -1;
history_def_set(h->h_ref, num);
return 0;
}
/* history_set_fun():
* Set history functions
*/
private int
history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
History *h;
history_gfun_t first, next, last, prev, curr;
history_efun_t enter, add;
ptr_t ptr;
{
if (first == NULL || next == NULL ||
last == NULL || prev == NULL || curr == NULL ||
enter == NULL || add == NULL ||
ptr == 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_enter = history_def_enter;
h->h_add = history_def_add;
}
return -1;
}
if (h->h_next == history_def_next)
history_def_end(h->h_ref);
h->h_next = next;
h->h_first = first;
h->h_enter = enter;
h->h_add = add;
return 0;
}
/* history_prev_event():
* Find the previous event, with number given
*/
private const HistEvent *
history_prev_event(h, num)
History *h;
int num;
{
const HistEvent *ev;
for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
if (ev->num == num)
return ev;
return NULL;
}
/* history_next_event():
* Find the next event, with number given
*/
private const HistEvent *
history_next_event(h, num)
History *h;
int num;
{
const HistEvent *ev;
for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
if (ev->num == num)
return ev;
return NULL;
}
/* history_prev_string():
* Find the previous event beginning with string
*/
private const HistEvent *
history_prev_string(h, str)
History *h;
const char* str;
{
const HistEvent *ev;
size_t len = strlen(str);
for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
if (strncmp(str, ev->str, len) == 0)
return ev;
return NULL;
}
/* history_next_string():
* Find the next event beginning with string
*/
private const HistEvent *
history_next_string(h, str)
History *h;
const char* str;
{
const HistEvent *ev;
size_t len = strlen(str);
for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
if (strncmp(str, ev->str, len) == 0)
return ev;
return NULL;
}
/* history():
* User interface to history functions.
*/
const HistEvent *
#if __STDC__
history(History *h, int fun, ...)
#else
history(va_alist)
va_dcl
#endif
{
va_list va;
const HistEvent *ev = NULL;
const char *str;
static const HistEvent sev = { 0, "" };
#if __STDC__
va_start(va, fun);
#else
History *h;
int fun;
va_start(va);
h = va_arg(va, History *);
fun = va_arg(va, int);
#endif
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_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)
ev = &sev;
break;
case H_FUNC:
{
history_gfun_t first = va_arg(va, history_gfun_t);
history_gfun_t next = va_arg(va, history_gfun_t);
history_gfun_t last = va_arg(va, history_gfun_t);
history_gfun_t prev = va_arg(va, history_gfun_t);
history_gfun_t curr = va_arg(va, history_gfun_t);
history_efun_t enter = va_arg(va, history_efun_t);
history_efun_t add = va_arg(va, history_efun_t);
ptr_t ptr = va_arg(va, ptr_t);
if (history_set_fun(h, first, next, last, prev,
curr, enter, add, ptr) == 0)
ev = &sev;
}
break;
case H_END:
history_end(h);
break;
default:
break;
}
va_end(va);
return ev;
}

726
lib/libedit/key.c Normal file
View File

@ -0,0 +1,726 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* key.c: This module contains the procedures for maintaining
* the extended-key map.
*
* An extended-key (key) is a sequence of keystrokes introduced
* with an sequence introducer and consisting of an arbitrary
* number of characters. This module maintains a map (the el->el_key.map)
* to convert these extended-key sequences into input strs
* (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
*
* Warning:
* If key is a substr of some other keys, then the longer
* keys are lost!! That is, if the keys "abcd" and "abcef"
* are in el->el_key.map, adding the key "abc" will cause the first two
* definitions to be lost.
*
* Restrictions:
* -------------
* 1) It is not possible to have one key that is a
* substr of another.
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#include "el.h"
/*
* The Nodes of the el->el_key.map. The el->el_key.map is a linked list
* 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 */
};
private int node_trav __P((EditLine *, key_node_t *, char *,
key_value_t *));
private int node__try __P((key_node_t *, char *,
key_value_t *, int));
private key_node_t *node__get __P((int));
private void node__put __P((key_node_t *));
private int node__delete __P((key_node_t **, char *));
private int node_lookup __P((EditLine *, char *, key_node_t *,
int));
private int node_enum __P((EditLine *, key_node_t *, int));
private int key__decode_char __P((char *, int, int));
#define KEY_BUFSIZ EL_BUFSIZ
/* key_init():
* Initialize the key maps
*/
protected int
key_init(el)
EditLine *el;
{
el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ);
el->el_key.map = NULL;
key_reset(el);
return 0;
}
/* key_end():
* Free the key maps
*/
protected void
key_end(el)
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;
}
/* key_map_cmd():
* Associate cmd with a key value
*/
protected key_value_t *
key_map_cmd(el, cmd)
EditLine *el;
int cmd;
{
el->el_key.val.cmd = (el_action_t) cmd;
return &el->el_key.val;
}
/* key_map_str():
* Associate str with a key value
*/
protected key_value_t *
key_map_str(el, str)
EditLine *el;
char *str;
{
el->el_key.val.str = str;
return &el->el_key.val;
}
/* key_reset():
* Takes all nodes on el->el_key.map and puts them on free list. Then
* initializes el->el_key.map with arrow keys
* [Always bind the ansi arrow keys?]
*/
protected void
key_reset(el)
EditLine *el;
{
node__put(el->el_key.map);
el->el_key.map = NULL;
return;
}
/* key_get():
* Calls the recursive function with entry point el->el_key.map
* Looks up *ch in map and then reads characters until a
* complete match is found or a mismatch occurs. Returns the
* type of the match found (XK_STR, XK_CMD, or XK_EXE).
* Returns NULL in val.str and XK_STR for no match.
* The last character read is returned in *ch.
*/
protected int
key_get(el, ch, val)
EditLine *el;
char *ch;
key_value_t *val;
{
return node_trav(el, el->el_key.map, ch, val);
}
/* key_add():
* Adds key to the el->el_key.map and associates the value in val with it.
* If key is already is in el->el_key.map, the new code is applied to the
* existing key. Ntype specifies if code is a command, an
* out str or a unix command.
*/
protected void
key_add(el, key, val, ntype)
EditLine *el;
char *key;
key_value_t *val;
int ntype;
{
if (key[0] == '\0') {
(void) fprintf(el->el_errfile,
"key_add: Null extended-key not allowed.\n");
return;
}
if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
(void) fprintf(el->el_errfile,
"key_add: sequence-lead-in command not allowed\n");
return;
}
if (el->el_key.map == NULL)
/* tree is initially empty. Set up new node to match key[0] */
el->el_key.map = node__get(key[0]); /* it is properly initialized */
/* Now recurse through el->el_key.map */
(void) node__try(el->el_key.map, key, val, ntype);
return;
}
/* key_clear():
*
*/
protected void
key_clear(el, map, in)
EditLine *el;
el_action_t *map;
char *in;
{
if ((map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) &&
((map == el->el_map.key &&
el->el_map.alt[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN) ||
(map == el->el_map.alt &&
el->el_map.key[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN)))
(void) key_delete(el, in);
}
/* key_delete():
* Delete the key and all longer keys staring with key, if
* they exists.
*/
protected int
key_delete(el, key)
EditLine *el;
char *key;
{
if (key[0] == '\0') {
(void) fprintf(el->el_errfile,
"key_delete: Null extended-key not allowed.\n");
return -1;
}
if (el->el_key.map == NULL)
return 0;
(void) node__delete(&el->el_key.map, key);
return 0;
}
/* key_print():
* Print the binding associated with key key.
* Print entire el->el_key.map if null
*/
protected void
key_print(el, key)
EditLine *el;
char *key;
{
/* do nothing if el->el_key.map is empty and null key specified */
if (el->el_key.map == NULL && *key == 0)
return;
el->el_key.buf[0] = '"';
if (node_lookup(el, key, el->el_key.map, 1) <= -1)
/* key is not bound */
(void) fprintf(el->el_errfile, "Unbound extended key \"%s\"\n", key);
return;
}
/* node_trav():
* recursively traverses node in tree until match or mismatch is
* found. May read in more characters.
*/
private int
node_trav(el, ptr, ch, val)
EditLine *el;
key_node_t *ptr;
char *ch;
key_value_t *val;
{
if (ptr->ch == *ch) {
/* match found */
if (ptr->next) {
/* key not complete so get next char */
if (el_getc(el, ch) != 1) { /* if EOF or error */
val->cmd = ED_END_OF_FILE;
return XK_CMD;/* PWP: Pretend we just read an end-of-file */
}
return node_trav(el, ptr->next, ch, val);
}
else {
*val = ptr->val;
if (ptr->type != XK_CMD)
*ch = '\0';
return ptr->type;
}
}
else {
/* no match found here */
if (ptr->sibling) {
/* try next sibling */
return node_trav(el, ptr->sibling, ch, val);
}
else {
/* no next sibling -- mismatch */
val->str = NULL;
return XK_STR;
}
}
}
/* node__try():
* Find a node that matches *str or allocate a new one
*/
private int
node__try(ptr, str, val, ntype)
key_node_t *ptr;
char *str;
key_value_t *val;
int ntype;
{
if (ptr->ch != *str) {
key_node_t *xm;
for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
if (xm->sibling->ch == *str)
break;
if (xm->sibling == NULL)
xm->sibling = node__get(*str); /* setup new node */
ptr = xm->sibling;
}
if (*++str == '\0') {
/* we're there */
if (ptr->next != NULL) {
node__put(ptr->next); /* lose longer keys with this prefix */
ptr->next = NULL;
}
switch (ptr->type) {
case XK_CMD:
case XK_NOD:
break;
case XK_STR:
case XK_EXE:
if (ptr->val.str)
el_free((ptr_t) ptr->val.str);
break;
default:
abort();
break;
}
switch (ptr->type = ntype) {
case XK_CMD:
ptr->val = *val;
break;
case XK_STR:
case XK_EXE:
ptr->val.str = strdup(val->str);
break;
default:
abort();
break;
}
}
else {
/* still more chars to go */
if (ptr->next == NULL)
ptr->next = node__get(*str); /* setup new node */
(void) node__try(ptr->next, str, val, ntype);
}
return 0;
}
/* node__delete():
* Delete node that matches str
*/
private int
node__delete(inptr, str)
key_node_t **inptr;
char *str;
{
key_node_t *ptr;
key_node_t *prev_ptr = NULL;
ptr = *inptr;
if (ptr->ch != *str) {
key_node_t *xm;
for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
if (xm->sibling->ch == *str)
break;
if (xm->sibling == NULL)
return 0;
prev_ptr = xm;
ptr = xm->sibling;
}
if (*++str == '\0') {
/* we're there */
if (prev_ptr == NULL)
*inptr = ptr->sibling;
else
prev_ptr->sibling = ptr->sibling;
ptr->sibling = NULL;
node__put(ptr);
return 1;
}
else if (ptr->next != NULL && node__delete(&ptr->next, str) == 1) {
if (ptr->next != NULL)
return 0;
if (prev_ptr == NULL)
*inptr = ptr->sibling;
else
prev_ptr->sibling = ptr->sibling;
ptr->sibling = NULL;
node__put(ptr);
return 1;
}
else {
return 0;
}
}
/* node__put():
* Puts a tree of nodes onto free list using free(3).
*/
private void
node__put(ptr)
key_node_t *ptr;
{
if (ptr == NULL)
return;
if (ptr->next != NULL) {
node__put(ptr->next);
ptr->next = NULL;
}
node__put(ptr->sibling);
switch (ptr->type) {
case XK_CMD:
case XK_NOD:
break;
case XK_EXE:
case XK_STR:
if (ptr->val.str != NULL)
el_free((ptr_t) ptr->val.str);
break;
default:
abort();
break;
}
el_free((ptr_t) ptr);
}
/* node__get():
* Returns pointer to an key_node_t for ch.
*/
private key_node_t *
node__get(ch)
int ch;
{
key_node_t *ptr;
ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t));
ptr->ch = ch;
ptr->type = XK_NOD;
ptr->val.str = NULL;
ptr->next = NULL;
ptr->sibling = NULL;
return ptr;
}
/* node_lookup():
* look for the str starting at node ptr.
* Print if last node
*/
private int
node_lookup(el, str, ptr, cnt)
EditLine *el;
char *str;
key_node_t *ptr;
int cnt;
{
int ncnt;
if (ptr == NULL)
return -1; /* cannot have null ptr */
if (*str == 0) {
/* no more chars in str. node_enum from here. */
(void) node_enum(el, ptr, cnt);
return 0;
}
else {
/* If match put this char into el->el_key.buf. Recurse */
if (ptr->ch == *str) {
/* match found */
ncnt = key__decode_char(el->el_key.buf, cnt,
(unsigned char) ptr->ch);
if (ptr->next != NULL)
/* not yet at leaf */
return node_lookup(el, str + 1, ptr->next, ncnt + 1);
else {
/* next node is null so key should be complete */
if (str[1] == 0) {
el->el_key.buf[ncnt + 1] = '"';
el->el_key.buf[ncnt + 2] = '\0';
key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
return 0;
}
else
return -1;/* mismatch -- str still has chars */
}
}
else {
/* no match found try sibling */
if (ptr->sibling)
return node_lookup(el, str, ptr->sibling, cnt);
else
return -1;
}
}
}
/* node_enum():
* Traverse the node printing the characters it is bound in buffer
*/
private int
node_enum(el, ptr, cnt)
EditLine *el;
key_node_t *ptr;
int cnt;
{
int ncnt;
if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */
el->el_key.buf[++cnt] = '"';
el->el_key.buf[++cnt] = '\0';
(void) fprintf(el->el_errfile,
"Some extended keys too long for internal print buffer");
(void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf);
return 0;
}
if (ptr == NULL) {
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile, "node_enum: BUG!! Null ptr passed\n!");
#endif
return -1;
}
/* put this char at end of str */
ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch);
if (ptr->next == NULL) {
/* print this key and function */
el->el_key.buf[ncnt + 1] = '"';
el->el_key.buf[ncnt + 2] = '\0';
key_kprint(el, el->el_key.buf, &ptr->val, ptr->type);
}
else
(void) node_enum(el, ptr->next, ncnt + 1);
/* go to sibling if there is one */
if (ptr->sibling)
(void) node_enum(el, ptr->sibling, cnt);
return 0;
}
/* key_kprint():
* Print the specified key and its associated
* function specified by val
*/
protected void
key_kprint(el, key, val, ntype)
EditLine *el;
char *key;
key_value_t *val;
int ntype;
{
el_bindings_t *fp;
char unparsbuf[EL_BUFSIZ];
static char *fmt = "%-15s-> %s\n";
if (val != NULL)
switch (ntype) {
case XK_STR:
case XK_EXE:
(void) fprintf(el->el_errfile, fmt, key,
key__decode_str(val->str, unparsbuf,
ntype == XK_STR ? "\"\"" : "[]"));
break;
case XK_CMD:
for (fp = el->el_map.help; fp->name; fp++)
if (val->cmd == fp->func) {
(void) fprintf(el->el_errfile, fmt, key, fp->name);
break;
}
#ifdef DEBUG_KEY
if (fp->name == NULL)
(void) fprintf(el->el_errfile, "BUG! Command not found.\n");
#endif
break;
default:
abort();
break;
}
else
(void) fprintf(el->el_errfile, fmt, key, "no input");
}
/* key__decode_char():
* Put a printable form of char in buf.
*/
private int
key__decode_char(buf, cnt, ch)
char *buf;
int cnt, ch;
{
if (ch == 0) {
buf[cnt++] = '^';
buf[cnt] = '@';
return cnt;
}
if (iscntrl(ch)) {
buf[cnt++] = '^';
if (ch == '\177')
buf[cnt] = '?';
else
buf[cnt] = ch | 0100;
}
else if (ch == '^') {
buf[cnt++] = '\\';
buf[cnt] = '^';
}
else if (ch == '\\') {
buf[cnt++] = '\\';
buf[cnt] = '\\';
}
else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
buf[cnt] = ch;
}
else {
buf[cnt++] = '\\';
buf[cnt++] = ((ch >> 6) & 7) + '0';
buf[cnt++] = ((ch >> 3) & 7) + '0';
buf[cnt] = (ch & 7) + '0';
}
return cnt;
}
/* key__decode_str():
* Make a printable version of the ey
*/
protected char *
key__decode_str(str, buf, sep)
char *str;
char *buf;
char *sep;
{
char *b, *p;
b = buf;
if (sep[0] != '\0')
*b++ = sep[0];
if (*str == 0) {
*b++ = '^';
*b++ = '@';
if (sep[0] != '\0' && sep[1] != '\0')
*b++ = sep[1];
*b++ = 0;
return buf;
}
for (p = str; *p != 0; p++) {
if (iscntrl((unsigned char) *p)) {
*b++ = '^';
if (*p == '\177')
*b++ = '?';
else
*b++ = *p | 0100;
}
else if (*p == '^' || *p == '\\') {
*b++ = '\\';
*b++ = *p;
}
else if (*p == ' ' || (isprint((unsigned char) *p) &&
!isspace((unsigned char) *p))) {
*b++ = *p;
}
else {
*b++ = '\\';
*b++ = ((*p >> 6) & 7) + '0';
*b++ = ((*p >> 3) & 7) + '0';
*b++ = (*p & 7) + '0';
}
}
if (sep[0] != '\0' && sep[1] != '\0')
*b++ = sep[1];
*b++ = 0;
return buf; /* should check for overflow */
}

80
lib/libedit/key.h Normal file
View File

@ -0,0 +1,80 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)key.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.key.h: Key macro header
*/
#ifndef _h_el_key
#define _h_el_key
typedef union key_value_t {
el_action_t cmd; /* If it is a command the # */
char *str; /* If it is a string... */
} key_value_t;
typedef struct key_node_t key_node_t;
typedef struct el_key_t {
char *buf; /* Key print buffer */
key_node_t *map; /* Key map */
key_value_t val; /* Local conversion buffer */
} el_key_t;
#define XK_CMD 0
#define XK_STR 1
#define XK_NOD 2
#define XK_EXE 3
protected int key_init __P((EditLine *));
protected void key_end __P((EditLine *));
protected key_value_t * key_map_cmd __P((EditLine *, int));
protected key_value_t * key_map_str __P((EditLine *, char *));
protected void key_reset __P((EditLine *));
protected int key_get __P((EditLine *, char *,
key_value_t *));
protected void key_add __P((EditLine *, char *, key_value_t *,
int));
protected void key_clear __P((EditLine *, el_action_t *,
char *));
protected int key_delete __P((EditLine *, char *));
protected void key_print __P((EditLine *, char *));
protected void key_kprint __P((EditLine *, char *,
key_value_t *, int));
protected char *key__decode_str __P((char *, char *, char *));
#endif /* _h_el_key */

187
lib/libedit/makelist Normal file
View File

@ -0,0 +1,187 @@
#!/bin/sh -
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
#
# This code is derived from software contributed to Berkeley by
# Christos Zoulas of Cornell University.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)makelist 5.3 (Berkeley) 6/4/93
# makelist.sh: Automatically generate header files...
AWK=/usr/bin/awk
USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh <filenames>"
if [ "x$1" = "x" ]
then
echo $USAGE 1>&2
exit 1
fi
FLAG="$1"
shift
FILES="$@"
case $FLAG in
-h)
OIFS="$IFS"
IFS=".$IFS"
set - $FILES
IFS="$OIFS"
hdr="_h_`basename $1`_$2"
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
name = substr($2, 1, length($2) - 3);
printf("protected el_action_t\t%-25.25s __P((EditLine *, int));\n", name);
}
}
END {
printf("#endif /* %s */\n", "'$hdr'");
}';;
-bc)
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"sys.h\"\n#include \"el.h\"\n");
printf("private struct el_bindings_t el_func_help[] = {\n");
low = "abcdefghijklmnopqrstuvwxyz_";
high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
for (i = 1; i <= length(low); i++)
tr[substr(low, i, 1)] = substr(high, i, 1);
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
name = substr($2, 1, length($2) - 3);
uname = "";
fname = "";
for (i = 1; i <= length(name); i++) {
s = substr(name, i, 1);
uname = uname tr[s];
if (s == "_")
s = "-";
fname = fname s;
}
printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ",");
ok = 1;
}
}
/^ \*/ {
if (ok) {
printf(" \"");
for (i = 2; i < NF; i++)
printf("%s ", $i);
printf("%s\" },\n", $i);
ok = 0;
}
}
END {
printf(" { NULL, 0, NULL }\n");
printf("};\n");
printf("\nprotected el_bindings_t* help__get()");
printf("{ return el_func_help; }\n");
}';;
-bh)
$AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_help_c\n#define _h_help_c\n");
printf("protected el_bindings_t *help__get\t__P((void));\n");
printf("#endif /* _h_help_c */\n");
}' /dev/null;;
-fh)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
sort | tr '[a-z]' '[A-Z]' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
count = 0;
}
{
printf("#define\t%-30.30s\t%3d\n", $1, count++);
}
END {
printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
printf("typedef el_action_t (*el_func_t) __P((EditLine *, int));");
printf("\nprotected el_func_t* func__get __P((void));\n");
printf("#endif /* _h_fcns_c */\n");
}';;
-fc)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"sys.h\"\n#include \"el.h\"\n");
printf("private el_func_t el_func[] = {");
maxlen = 80;
needn = 1;
len = 0;
}
{
clen = 25 + 2;
len += clen;
if (len >= maxlen)
needn = 1;
if (needn) {
printf("\n ");
needn = 0;
len = 4 + clen;
}
s = $1 ",";
printf("%-26.26s ", s);
}
END {
printf("\n};\n");
printf("\nprotected el_func_t* func__get() { return el_func; }\n");
}';;
-e)
echo "$FILES" | tr ' ' '\012' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#define protected static\n");
printf("#define SCCSID\n");
}
{
printf("#include \"%s\"\n", $1);
}';;
*)
echo $USAGE 1>&2
exit 1;;
esac

1397
lib/libedit/map.c Normal file

File diff suppressed because it is too large Load Diff

77
lib/libedit/map.h Normal file
View File

@ -0,0 +1,77 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)map.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.map.h: Editor maps
*/
#ifndef _h_el_map
#define _h_el_map
typedef struct el_bindings_t { /* for the "bind" shell command */
const char *name; /* function name for bind command */
int func; /* function numeric value */
const char *description; /* description of function */
} el_bindings_t;
typedef struct el_map_t {
el_action_t *alt; /* The current alternate key map */
el_action_t *key; /* The current normal key map */
el_action_t *current; /* The keymap we are using */
el_action_t *emacs; /* The default emacs key map */
el_action_t *vic; /* The vi command mode key map */
el_action_t *vii; /* The vi insert mode key map */
int type; /* Emacs or vi */
el_bindings_t *help; /* The help for the editor functions */
el_func_t *func; /* List of available functions */
int nfunc; /* The number of functions/help items */
} el_map_t;
#define MAP_EMACS 0
#define MAP_VI 1
protected int map_bind __P((EditLine *, int, char **));
protected int map_init __P((EditLine *));
protected void map_end __P((EditLine *));
protected void map_init_vi __P((EditLine *));
protected void map_init_emacs __P((EditLine *));
protected int map_set_editor __P((EditLine *, char *));
protected int map_addfunc __P((EditLine *, const char *,
const char *, el_func_t));
#endif /* _h_el_map */

250
lib/libedit/parse.c Normal file
View File

@ -0,0 +1,250 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* parse.c: parse an editline extended command
*
* commands are:
*
* bind
* echotc
* settc
* gettc
*/
#include "sys.h"
#include "el.h"
#include "tokenizer.h"
private struct {
char *name;
int (*func) __P((EditLine *, int, char **));
} cmds[] = {
{ "bind", map_bind },
{ "echotc", term_echotc },
{ "history", hist_list },
{ "telltc", term_telltc },
{ "settc", term_settc },
{ "setty", tty_stty },
{ NULL, NULL }
};
/* parse_line():
* Parse a line and dispatch it
*/
protected int
parse_line(el, line)
EditLine *el;
const char *line;
{
char **argv;
int argc;
Tokenizer *tok;
tok = tok_init(NULL);
tok_line(tok, line, &argc, &argv);
argc = el_parse(el, argc, argv);
tok_end(tok);
return argc;
}
/* el_parse():
* Command dispatcher
*/
public int
el_parse(el, argc, argv)
EditLine *el;
int argc;
char *argv[];
{
char *ptr;
int i;
if (argc < 1)
return 0;
for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++)
continue;
if (*ptr == ':') {
*ptr = '\0';
if (el_match(el->el_prog, ptr))
return 0;
}
else
ptr = argv[0];
for (i = 0; cmds[i].name != NULL; i++)
if (strcmp(cmds[i].name, ptr) == 0) {
i = (*cmds[i].func)(el, argc, argv);
return -i;
}
return -1;
}
/* parse__escape():
* Parse a string of the form ^<char> \<odigit> \<char> and return
* the appropriate character or -1 if the escape is not valid
*/
protected int
parse__escape(ptr)
const char ** const ptr;
{
const char *p;
int c;
p = *ptr;
if (p[1] == 0)
return -1;
if (*p == '\\') {
p++;
switch (*p) {
case 'a':
c = '\007'; /* Bell */
break;
case 'b':
c = '\010'; /* Backspace */
break;
case 't':
c = '\011'; /* Horizontal Tab */
break;
case 'n':
c = '\012'; /* New Line */
break;
case 'v':
c = '\013'; /* Vertical Tab */
break;
case 'f':
c = '\014'; /* Form Feed */
break;
case 'r':
c = '\015'; /* Carriage Return */
break;
case 'e':
c = '\033'; /* Escape */
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
int cnt, ch;
for (cnt = 0, c = 0; cnt < 3; cnt++) {
ch = *p++;
if (ch < '0' || ch > '7') {
p--;
break;
}
c = (c << 3) | (ch - '0');
}
if ((c & 0xffffff00) != 0)
return -1;
--p;
}
break;
default:
c = *p;
break;
}
}
else if (*p == '^' && isalpha((unsigned char) *p)) {
p++;
c = (*p == '?') ? '\177' : (*p & 0237);
}
else
c = *p;
*ptr = ++p;
return c;
}
/* parse__string():
* Parse the escapes from in and put the raw string out
*/
protected char *
parse__string(out, in)
char *out;
const char *in;
{
char *rv = out;
int n;
for (;;)
switch (*in) {
case '\0':
*out = '\0';
return rv;
case '\\':
case '^':
if ((n = parse__escape(&in)) == -1)
return NULL;
*out++ = n;
break;
default:
*out++ = *in++;
break;
}
}
/* parse_cmd():
* Return the command number for the command string given
* or -1 if one is not found
*/
protected int
parse_cmd(el, cmd)
EditLine *el;
const char *cmd;
{
el_bindings_t *b;
for (b = el->el_map.help; b->name != NULL; b++)
if (strcmp(b->name, cmd) == 0)
return b->func;
return -1;
}

50
lib/libedit/parse.h Normal file
View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)parse.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.parse.h: Parser functions
*/
#ifndef _h_el_parse
#define _h_el_parse
protected int parse_line __P((EditLine *, const char *));
protected int parse__escape __P((const char ** const));
protected char * parse__string __P((char *, const char *));
protected int parse_cmd __P((EditLine *, const char *));
#endif /* _h_el_parse */

123
lib/libedit/prompt.c Normal file
View File

@ -0,0 +1,123 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* prompt.c: Prompt printing functions
*/
#include "sys.h"
#include <stdio.h>
#include "el.h"
private char *prompt_default __P((EditLine *));
/* prompt_default():
* Just a default prompt, in case the user did not provide one
*/
private char *
/*ARGSUSED*/
prompt_default(el)
EditLine *el;
{
static char a[3] = { '?', ' ', '\0' };
return a;
}
/* prompt_print():
* Print the prompt and update the prompt position.
* We use an array of integers in case we want to pass
* literal escape sequences in the prompt and we want a
* bit to flag them
*/
protected void
prompt_print(el)
EditLine *el;
{
char *p = (*el->el_prompt.p_func)(el);
while (*p)
re_putc(el, *p++);
el->el_prompt.p_pos.v = el->el_refresh.r_cursor.v;
el->el_prompt.p_pos.h = el->el_refresh.r_cursor.h;
} /* end prompt_print */
/* prompt_init():
* Initialize the prompt stuff
*/
protected int
prompt_init(el)
EditLine *el;
{
el->el_prompt.p_func = prompt_default;
el->el_prompt.p_pos.v = 0;
el->el_prompt.p_pos.h = 0;
return 0;
} /* end prompt_init */
/* prompt_end():
* Clean up the prompt stuff
*/
protected void
/*ARGSUSED*/
prompt_end(el)
EditLine *el;
{
} /* end prompt_end */
/* prompt_set():
* Install a prompt printing function
*/
protected int
prompt_set(el, prf)
EditLine *el;
el_pfunc_t prf;
{
if (prf == NULL)
el->el_prompt.p_func = prompt_default;
else
el->el_prompt.p_func = prf;
el->el_prompt.p_pos.v = 0;
el->el_prompt.p_pos.h = 0;
return 0;
} /* end prompt_set */

59
lib/libedit/prompt.h Normal file
View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)prompt.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.prompt.h: Prompt printing stuff
*/
#ifndef _h_el_prompt
#define _h_el_prompt
#include "histedit.h"
typedef char * (*el_pfunc_t) __P((EditLine*));
typedef struct el_prompt_t {
el_pfunc_t p_func; /* Function to return the prompt */
coord_t p_pos; /* position in the line after prompt */
} el_prompt_t;
protected void prompt_print __P((EditLine *));
protected int prompt_set __P((EditLine *, el_pfunc_t));
protected int prompt_init __P((EditLine *));
protected void prompt_end __P((EditLine *));
#endif /* _h_el_prompt */

437
lib/libedit/read.c Normal file
View File

@ -0,0 +1,437 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* read.c: Clean this junk up! This is horrible code.
* Terminal read functions
*/
#include "sys.h"
#include <sys/errno.h>
#include <unistd.h>
#include <stdlib.h>
extern int errno;
#include "el.h"
#define OKCMD -1
private int read__fixio __P((int, int));
private int read_preread __P((EditLine *));
private int read_getcmd __P((EditLine *, el_action_t *, char *));
#ifdef DEBUG_EDIT
private void
read_debug(el)
EditLine *el;
{
if (el->el_line.cursor > el->el_line.lastchar)
(void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
if (el->el_line.cursor < el->el_line.buffer)
(void) fprintf(el->el_errfile, "cursor < buffer\r\n");
if (el->el_line.cursor > el->el_line.limit)
(void) fprintf(el->el_errfile, "cursor > limit\r\n");
if (el->el_line.lastchar > el->el_line.limit)
(void) fprintf(el->el_errfile, "lastchar > limit\r\n");
if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
(void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
}
#endif /* DEBUG_EDIT */
/* read__fixio():
* Try to recover from a read error
*/
private int
read__fixio(fd, e)
int fd, e;
{
switch (e) {
case -1: /* Make sure that the code is reachable */
#ifdef EWOULDBLOCK
case EWOULDBLOCK:
# define TRY_AGAIN
#endif /* EWOULDBLOCK */
#if defined(POSIX) && defined(EAGAIN)
# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EAGAIN:
# define TRY_AGAIN
# endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
#endif /* POSIX && EAGAIN */
e = 0;
#ifdef TRY_AGAIN
# if defined(F_SETFL) && defined(O_NDELAY)
if ((e = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
return -1;
else
e = 1;
# endif /* F_SETFL && O_NDELAY */
# ifdef FIONBIO
if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1)
return -1;
else
e = 1;
# endif /* FIONBIO */
#endif /* TRY_AGAIN */
return e ? 0 : -1;
case EINTR:
return 0;
default:
return -1;
}
}
/* read_preread():
* Try to read the stuff in the input queue;
*/
private int
read_preread(el)
EditLine *el;
{
int chrs = 0;
if (el->el_chared.c_macro.nline) {
el_free((ptr_t) el->el_chared.c_macro.nline);
el->el_chared.c_macro.nline = NULL;
}
if (el->el_tty.t_mode == ED_IO)
return 0;
#ifdef FIONREAD
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs);
if (chrs > 0) {
char buf[EL_BUFSIZ];
chrs = read(el->el_infd, buf, (size_t) MIN(chrs, EL_BUFSIZ - 1));
if (chrs > 0) {
buf[chrs] = '\0';
el->el_chared.c_macro.nline = strdup(buf);
el_push(el->el_chared.c_macro.nline);
}
}
#endif /* FIONREAD */
return chrs > 0;
}
/* el_push():
* Push a macro
*/
public void
el_push(el, str)
EditLine *el;
const char *str;
{
c_macro_t *ma = &el->el_chared.c_macro;
if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
ma->level++;
ma->macro[ma->level] = (char *) str;
}
else {
term_beep(el);
term__flush();
}
}
/* read_getcmd():
* Return next command from the input stream.
*/
private int
read_getcmd(el, cmdnum, ch)
EditLine *el;
el_action_t *cmdnum;
char *ch;
{
el_action_t cmd = 0;
int num;
while (cmd == 0 || cmd == ED_SEQUENCE_LEAD_IN) {
if ((num = el_getc(el, ch)) != 1) /* if EOF or error */
return num;
#ifdef KANJI
if ((*ch & 0200)) {
el->el_state.metanext = 0;
cmd = CcViMap[' '];
break;
}
else
#endif /* KANJI */
if (el->el_state.metanext) {
el->el_state.metanext = 0;
*ch |= 0200;
}
cmd = el->el_map.current[(unsigned char) *ch];
if (cmd == ED_SEQUENCE_LEAD_IN) {
key_value_t val;
switch (key_get(el, ch, &val)) {
case XK_CMD:
cmd = val.cmd;
break;
case XK_STR:
el_push(el, val.str);
break;
#ifdef notyet
case XK_EXE:
/* XXX: In the future to run a user function */
RunCommand(val.str);
break;
#endif
default:
abort();
break;
}
}
if (el->el_map.alt == NULL)
el->el_map.current = el->el_map.key;
}
*cmdnum = cmd;
return OKCMD;
}
/* el_getc():
* Read a character
*/
public int
el_getc(el, cp)
EditLine *el;
char *cp;
{
int num_read;
unsigned char tcp;
int tried = 0;
c_macro_t *ma = &el->el_chared.c_macro;
term__flush();
for (;;) {
if (ma->level < 0) {
if (!read_preread(el))
break;
}
if (ma->level < 0)
break;
if (*ma->macro[ma->level] == 0) {
ma->level--;
continue;
}
*cp = *ma->macro[ma->level]++ & 0377;
if (*ma->macro[ma->level] == 0) { /* Needed for QuoteMode On */
ma->level--;
}
return 1;
}
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Turning raw mode on\n");
#endif /* DEBUG_READ */
if (tty_rawmode(el) < 0) /* make sure the tty is set up correctly */
return 0;
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Reading a character\n");
#endif /* DEBUG_READ */
while ((num_read = read(el->el_infd, (char *) &tcp, 1)) == -1)
if (!tried && read__fixio(el->el_infd, errno) == 0)
tried = 1;
else {
*cp = '\0';
return -1;
}
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Got it %c\n", tcp);
#endif /* DEBUG_READ */
*cp = tcp;
return num_read;
}
public const char *
el_gets(el, nread)
EditLine *el;
int *nread;
{
int retval;
el_action_t cmdnum = 0;
int num; /* how many chars we have read at NL */
char ch;
if (el->el_flags & HANDLE_SIGNALS)
sig_set(el);
re_clear_display(el); /* reset the display stuff */
ch_reset(el);
#ifdef FIONREAD
if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
long chrs = 0;
(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) &chrs);
if (chrs == 0) {
if (tty_rawmode(el) < 0) {
if (nread)
*nread = 0;
return NULL;
}
}
}
#endif /* FIONREAD */
re_refresh(el); /* print the prompt */
for (num = OKCMD; num == OKCMD;) { /* while still editing this line */
#ifdef DEBUG_EDIT
read_debug(el);
#endif /* DEBUG_EDIT */
/* if EOF or error */
if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Returning from el_gets %d\n", num);
#endif /* DEBUG_READ */
break;
}
if (cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile,
"ERROR: illegal command from key 0%o\r\n", ch);
#endif /* DEBUG_EDIT */
continue; /* try again */
}
/* now do the real command */
#ifdef DEBUG_READ
{
el_bindings_t *b;
for (b = el->el_map.help; b->name; b++)
if (b->func == cmdnum)
break;
if (b->name)
(void) fprintf(el->el_errfile, "Executing %s\n", b->name);
else
(void) fprintf(el->el_errfile, "Error command = %d\n", cmdnum);
}
#endif /* DEBUG_READ */
retval = (*el->el_map.func[cmdnum])(el, ch);
/* save the last command here */
el->el_state.lastcmd = cmdnum;
/* use any return value */
switch (retval) {
case CC_CURSOR:
el->el_state.argument = 1;
el->el_state.doingarg = 0;
re_refresh_cursor(el);
break;
case CC_REFRESH:
el->el_state.argument = 1;
el->el_state.doingarg = 0;
re_refresh(el);
break;
case CC_NORM: /* normal char */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
break;
case CC_ARGHACK: /* Suggested by Rich Salz */
/* <rsalz@pineapple.bbn.com> */
break; /* keep going... */
case CC_EOF: /* end of file typed */
num = 0;
break;
case CC_NEWLINE: /* normal end of line */
num = el->el_line.lastchar - el->el_line.buffer;
break;
case CC_FATAL: /* fatal error, reset to known state */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "*** editor fatal ERROR ***\r\n\n");
#endif /* DEBUG_READ */
/* put (real) cursor in a known place */
re_clear_display(el); /* reset the display stuff */
ch_reset(el); /* reset the input pointers */
re_refresh(el); /* print the prompt again */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
break;
case CC_ERROR:
default: /* functions we don't know about */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n");
#endif /* DEBUG_READ */
el->el_state.argument = 1;
el->el_state.doingarg = 0;
term_beep(el);
term__flush();
break;
}
}
(void) tty_cookedmode(el); /* make sure the tty is set up correctly */
term__flush(); /* flush any buffered output */
if (el->el_flags & HANDLE_SIGNALS)
sig_clr(el);
if (nread)
*nread = num;
return num ? el->el_line.buffer : NULL;
}

1015
lib/libedit/refresh.c Normal file

File diff suppressed because it is too large Load Diff

60
lib/libedit/refresh.h Normal file
View File

@ -0,0 +1,60 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)refresh.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.refresh.h: Screen refresh functions
*/
#ifndef _h_el_refresh
#define _h_el_refresh
#include "histedit.h"
typedef struct {
coord_t r_cursor; /* Refresh cursor position */
int r_oldcv, r_newcv; /* Vertical locations */
} el_refresh_t;
protected void re_putc __P((EditLine *, int));
protected void re_clear_lines __P((EditLine *));
protected void re_clear_display __P((EditLine *));
protected void re_refresh __P((EditLine *));
protected void re_refresh_cursor __P((EditLine *));
protected void re_fastaddc __P((EditLine *));
protected void re_goto_bottom __P((EditLine *));
#endif /* _h_el_refresh */

633
lib/libedit/search.c Normal file
View File

@ -0,0 +1,633 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* search.c: History and character search functions
*/
#include "sys.h"
#include <stdlib.h>
#ifdef REGEXEC
#include <sys/types.h>
#include <regex.h>
#else
#ifdef REGEXP
#include <regexp.h>
#endif
#endif
#include "el.h"
/*
* Adjust cursor in vi mode to include the character under it
*/
#define EL_CURSOR(el) \
((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \
((el)->el_map.current == (el)->el_map.alt)))
/* search_init():
* Initialize the search stuff
*/
protected int
search_init(el)
EditLine *el;
{
el->el_search.patbuf = (char *) el_malloc(EL_BUFSIZ);
el->el_search.patlen = 0;
el->el_search.patdir = -1;
el->el_search.chacha = '\0';
el->el_search.chadir = -1;
return 0;
}
/* search_end():
* Initialize the search stuff
*/
protected void
search_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_search.patbuf);
el->el_search.patbuf = NULL;
}
#ifdef REGEXP
/* regerror():
* Handle regular expression errors
*/
public void
/*ARGSUSED*/
regerror(msg)
const char *msg;
{
}
#endif
/* el_match():
* Return if string matches pattern
*/
protected int
el_match(str, pat)
const char *str;
const char *pat;
{
#ifdef REGEXEC
regex_t re;
#else
#ifndef REGEXP
extern char *re_comp __P((const char *));
extern int re_exec __P((const char *));
#else
regexp *re;
int rv;
#endif
#endif
if (strstr(str, pat) != NULL)
return 1;
#ifdef REGEXEC
if (regcomp(&re, pat, REG_EXTENDED | REG_NOSUB) != 0)
return 0;
return (regexec(&re, str, 0, NULL, 0) == 0);
#else
#ifndef REGEXP
if (re_comp(pat) != NULL)
return 0;
else
return re_exec(str) == 1;
#else
if ((re = regcomp(pat)) != NULL) {
rv = regexec(re, str);
free((ptr_t) re);
}
else
rv = 0;
return rv;
#endif
#endif
}
/* c_hmatch():
* return True if the pattern matches the prefix
*/
protected int
c_hmatch(el, str)
EditLine *el;
const char *str;
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
el->el_search.patbuf, str);
#endif /* SDEBUG */
return el_match(str, el->el_search.patbuf);
}
/* c_setpat():
* Set the history seatch pattern
*/
protected void
c_setpat(el)
EditLine *el;
{
if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) {
el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer;
if (el->el_search.patlen >= EL_BUFSIZ)
el->el_search.patlen = EL_BUFSIZ -1;
if (el->el_search.patlen >= 0) {
(void) strncpy(el->el_search.patbuf, el->el_line.buffer,
el->el_search.patlen);
el->el_search.patbuf[el->el_search.patlen] = '\0';
}
else
el->el_search.patlen = strlen(el->el_search.patbuf);
}
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno);
(void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen);
(void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf);
(void) fprintf(el->el_errfile, "cursor %d lastchar %d\n",
EL_CURSOR(el) - el->el_line.buffer,
el->el_line.lastchar - el->el_line.buffer);
#endif
}
/* ce_inc_search():
* Emacs incremental search
*/
protected el_action_t
ce_inc_search(el, dir)
EditLine *el;
int dir;
{
static char STRfwd[] = { 'f', 'w', 'd', '\0' },
STRbck[] = { 'b', 'c', 'k', '\0' };
static char pchar = ':'; /* ':' = normal, '?' = failed */
static char endcmd[2] = { '\0', '\0' };
char ch, *cp, *ocursor = el->el_line.cursor, oldpchar = pchar;
el_action_t ret = CC_NORM;
int ohisteventno = el->el_history.eventno,
oldpatlen = el->el_search.patlen,
newdir = dir,
done, redo;
if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 +
el->el_search.patlen >= el->el_line.limit)
return CC_ERROR;
for (;;) {
if (el->el_search.patlen == 0) { /* first round */
pchar = ':';
#ifdef ANCHOR
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
#endif
}
done = redo = 0;
*el->el_line.lastchar++ = '\n';
for (cp = newdir == ED_SEARCH_PREV_HISTORY ? STRbck : STRfwd;
*cp; *el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar++ = pchar;
for (cp = &el->el_search.patbuf[1];
cp < &el->el_search.patbuf[el->el_search.patlen];
*el->el_line.lastchar++ = *cp++)
continue;
*el->el_line.lastchar = '\0';
re_refresh(el);
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
switch (el->el_map.current[(unsigned char) ch]) {
case ED_INSERT:
case ED_DIGIT:
if (el->el_search.patlen > EL_BUFSIZ - 3)
term_beep(el);
else {
el->el_search.patbuf[el->el_search.patlen++] = ch;
*el->el_line.lastchar++ = ch;
*el->el_line.lastchar = '\0';
re_refresh(el);
}
break;
case EM_INC_SEARCH_NEXT:
newdir = ED_SEARCH_NEXT_HISTORY;
redo++;
break;
case EM_INC_SEARCH_PREV:
newdir = ED_SEARCH_PREV_HISTORY;
redo++;
break;
case ED_DELETE_PREV_CHAR:
if (el->el_search.patlen > 1)
done++;
else
term_beep(el);
break;
default:
switch (ch) {
case 0007: /* ^G: Abort */
ret = CC_ERROR;
done++;
break;
case 0027: /* ^W: Append word */
/* No can do if globbing characters in pattern */
for (cp = &el->el_search.patbuf[1]; ; cp++)
if (cp >= &el->el_search.patbuf[el->el_search.patlen]) {
el->el_line.cursor += el->el_search.patlen - 1;
cp = c__next_word(el->el_line.cursor,
el->el_line.lastchar, 1, ce__isword);
while (el->el_line.cursor < cp &&
*el->el_line.cursor != '\n') {
if (el->el_search.patlen > EL_BUFSIZ - 3) {
term_beep(el);
break;
}
el->el_search.patbuf[el->el_search.patlen++] =
*el->el_line.cursor;
*el->el_line.lastchar++ = *el->el_line.cursor++;
}
el->el_line.cursor = ocursor;
*el->el_line.lastchar = '\0';
re_refresh(el);
break;
} else if (isglob(*cp)) {
term_beep(el);
break;
}
break;
default: /* Terminate and execute cmd */
endcmd[0] = ch;
el_push(el, endcmd);
/*FALLTHROUGH*/
case 0033: /* ESC: Terminate */
ret = CC_REFRESH;
done++;
break;
}
break;
}
while (el->el_line.lastchar > el->el_line.buffer &&
*el->el_line.lastchar != '\n')
*el->el_line.lastchar-- = '\0';
*el->el_line.lastchar = '\0';
if (!done) {
/* Can't search if unmatched '[' */
for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']';
cp > el->el_search.patbuf; cp--)
if (*cp == '[' || *cp == ']') {
ch = *cp;
break;
}
if (el->el_search.patlen > 1 && ch != '[') {
if (redo && newdir == dir) {
if (pchar == '?') { /* wrap around */
el->el_history.eventno =
newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
if (hist_get(el) == CC_ERROR)
/* el->el_history.eventno was fixed by first call */
(void) hist_get(el);
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
} else
el->el_line.cursor +=
newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1;
}
#ifdef ANCHOR
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
#endif
el->el_search.patbuf[el->el_search.patlen] = '\0';
if (el->el_line.cursor < el->el_line.buffer ||
el->el_line.cursor > el->el_line.lastchar ||
(ret = ce_search_line(el, &el->el_search.patbuf[1],
newdir)) == CC_ERROR) {
/* avoid c_setpat */
el->el_state.lastcmd = (el_action_t) newdir;
ret = newdir == ED_SEARCH_PREV_HISTORY ?
ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0);
if (ret != CC_ERROR) {
el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ?
el->el_line.lastchar : el->el_line.buffer;
(void) ce_search_line(el, &el->el_search.patbuf[1],
newdir);
}
}
el->el_search.patbuf[--el->el_search.patlen] = '\0';
if (ret == CC_ERROR) {
term_beep(el);
if (el->el_history.eventno != ohisteventno) {
el->el_history.eventno = ohisteventno;
if (hist_get(el) == CC_ERROR)
return CC_ERROR;
}
el->el_line.cursor = ocursor;
pchar = '?';
} else {
pchar = ':';
}
}
ret = ce_inc_search(el, newdir);
if (ret == CC_ERROR && pchar == '?' && oldpchar == ':')
/* break abort of failed search at last non-failed */
ret = CC_NORM;
}
if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
/* restore on normal return or error exit */
pchar = oldpchar;
el->el_search.patlen = oldpatlen;
if (el->el_history.eventno != ohisteventno) {
el->el_history.eventno = ohisteventno;
if (hist_get(el) == CC_ERROR)
return CC_ERROR;
}
el->el_line.cursor = ocursor;
if (ret == CC_ERROR)
re_refresh(el);
}
if (done || ret != CC_NORM)
return ret;
}
}
/* cv_search():
* Vi search.
*/
protected el_action_t
cv_search(el, dir)
EditLine *el;
int dir;
{
char ch;
char tmpbuf[EL_BUFSIZ];
int tmplen;
tmplen = 0;
#ifdef ANCHOR
tmpbuf[tmplen++] = '.';
tmpbuf[tmplen++] = '*';
#endif
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
el->el_search.patdir = dir;
c_insert(el, 2); /* prompt + '\n' */
*el->el_line.cursor++ = '\n';
*el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
re_refresh(el);
#ifdef ANCHOR
# define LEN 2
#else
# define LEN 0
#endif
tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
ch = tmpbuf[tmplen];
tmpbuf[tmplen] = '\0';
if (tmplen == LEN) {
/*
* Use the old pattern, but wild-card it.
*/
if (el->el_search.patlen == 0) {
el->el_line.buffer[0] = '\0';
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
re_refresh(el);
return CC_ERROR;
}
#ifdef ANCHOR
if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') {
(void) strcpy(tmpbuf, el->el_search.patbuf);
el->el_search.patbuf[0] = '.';
el->el_search.patbuf[1] = '*';
(void) strcpy(&el->el_search.patbuf[2], tmpbuf);
el->el_search.patlen++;
el->el_search.patbuf[el->el_search.patlen++] = '.';
el->el_search.patbuf[el->el_search.patlen++] = '*';
el->el_search.patbuf[el->el_search.patlen] = '\0';
}
#endif
}
else {
#ifdef ANCHOR
tmpbuf[tmplen++] = '.';
tmpbuf[tmplen++] = '*';
#endif
tmpbuf[tmplen] = '\0';
(void) strcpy(el->el_search.patbuf, tmpbuf);
el->el_search.patlen = tmplen;
}
el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;
if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
ed_search_next_history(el, 0)) == CC_ERROR) {
re_refresh(el);
return CC_ERROR;
}
else {
if (ch == 0033) {
re_refresh(el);
*el->el_line.lastchar++ = '\n';
*el->el_line.lastchar = '\0';
re_goto_bottom(el);
return CC_NEWLINE;
}
else
return CC_REFRESH;
}
}
/* ce_search_line():
* Look for a pattern inside a line
*/
protected el_action_t
ce_search_line(el, pattern, dir)
EditLine *el;
char *pattern;
int dir;
{
char *cp;
if (dir == ED_SEARCH_PREV_HISTORY) {
for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--)
if (el_match(cp, pattern)) {
el->el_line.cursor = cp;
return CC_NORM;
}
return CC_ERROR;
} else {
for (cp = el->el_line.cursor; *cp != '\0' &&
cp < el->el_line.limit; cp++)
if (el_match(cp, pattern)) {
el->el_line.cursor = cp;
return CC_NORM;
}
return CC_ERROR;
}
}
/* cv_repeat_srch():
* Vi repeat search
*/
protected el_action_t
cv_repeat_srch(el, c)
EditLine *el;
int c;
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n",
c, el->el_search.patlen, el->el_search.patbuf);
#endif
el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */
el->el_line.lastchar = el->el_line.buffer;
switch (c) {
case ED_SEARCH_NEXT_HISTORY:
return ed_search_next_history(el, 0);
case ED_SEARCH_PREV_HISTORY:
return ed_search_prev_history(el, 0);
default:
return CC_ERROR;
}
}
/* cv_csearch_back():
* Vi character search reverse
*/
protected el_action_t
cv_csearch_back(el, ch, count, tflag)
EditLine *el;
int ch, count, tflag;
{
char *cp;
cp = el->el_line.cursor;
while (count--) {
if (*cp == ch)
cp--;
while (cp > el->el_line.buffer && *cp != ch)
cp--;
}
if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch))
return CC_ERROR;
if (*cp == ch && tflag)
cp++;
el->el_line.cursor = cp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
re_refresh_cursor(el);
return CC_NORM;
}
/* cv_csearch_fwd():
* Vi character search forward
*/
protected el_action_t
cv_csearch_fwd(el, ch, count, tflag)
EditLine *el;
int ch, count, tflag;
{
char *cp;
cp = el->el_line.cursor;
while (count--) {
if(*cp == ch)
cp++;
while (cp < el->el_line.lastchar && *cp != ch)
cp++;
}
if (cp >= el->el_line.lastchar)
return CC_ERROR;
if (*cp == ch && tflag)
cp--;
el->el_line.cursor = cp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
re_refresh_cursor(el);
return CC_NORM;
}

68
lib/libedit/search.h Normal file
View File

@ -0,0 +1,68 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)search.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.search.h: Line and history searching utilities
*/
#ifndef _h_el_search
#define _h_el_search
#include "histedit.h"
typedef struct el_search_t {
char *patbuf; /* The pattern buffer */
int patlen; /* Length of the pattern buffer */
int patdir; /* Direction of the last search */
int chadir; /* Character search direction */
char chacha; /* Character we are looking for */
} el_search_t;
protected int el_match __P((const char *, const char *));
protected int search_init __P((EditLine *));
protected void search_end __P((EditLine *));
protected int c_hmatch __P((EditLine *, const char *));
protected void c_setpat __P((EditLine *));
protected el_action_t ce_inc_search __P((EditLine *, int));
protected el_action_t cv_search __P((EditLine *, int));
protected el_action_t ce_search_line __P((EditLine *, char *, int));
protected el_action_t cv_repeat_srch __P((EditLine *, int));
protected el_action_t cv_csearch_back __P((EditLine *, int, int, int));
protected el_action_t cv_csearch_fwd __P((EditLine *, int, int, int));
#endif /* _h_el_search */

193
lib/libedit/sig.c Normal file
View File

@ -0,0 +1,193 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* sig.c: Signal handling stuff.
* our policy is to trap all signals, set a good state
* and pass the ball to our caller.
*/
#include "sys.h"
#include "el.h"
#include <stdlib.h>
private EditLine *sel = NULL;
private int sighdl[] = {
#define _DO(a) (a),
ALLSIGS
#undef _DO
-1
};
private void sig_handler __P((int));
/* sig_handler():
* This is the handler called for all signals
* XXX: we cannot pass any data so we just store the old editline
* state in a private variable
*/
private void
sig_handler(signo)
int signo;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
(void) sigaddset(&nset, signo);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
switch (signo) {
case SIGCONT:
tty_rawmode(sel);
if (ed_redisplay(sel, 0) == CC_REFRESH)
re_refresh(sel);
term__flush();
break;
case SIGWINCH:
el_resize(sel);
break;
default:
tty_cookedmode(sel);
break;
}
for (i = 0; sighdl[i] != -1; i++)
if (signo == sighdl[i])
break;
(void) signal(signo, sel->el_signal[i]);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
(void) kill(0, signo);
}
/* sig_init():
* Initialize all signal stuff
*/
protected int
sig_init(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
#define SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t))
el->el_signal = (sig_t *) el_malloc(SIGSIZE);
for (i = 0; sighdl[i] != -1; i++)
el->el_signal[i] = BADSIG;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
return 0;
}
/* sig_end():
* Clear all signal stuff
*/
protected void
sig_end(el)
EditLine *el;
{
el_free((ptr_t) el->el_signal);
el->el_signal = NULL;
}
/* sig_set():
* set all the signal handlers
*/
protected void
sig_set(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
for (i = 0; sighdl[i] != -1; i++) {
sig_t s;
/* This could happen if we get interrupted */
if ((s = signal(sighdl[i], sig_handler)) != sig_handler)
el->el_signal[i] = s;
}
sel = el;
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}
/* sig_clr():
* clear all the signal handlers
*/
protected void
sig_clr(el)
EditLine *el;
{
int i;
sigset_t nset, oset;
(void) sigemptyset(&nset);
#define _DO(a) (void) sigaddset(&nset, SIGWINCH);
ALLSIGS
#undef _DO
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
for (i = 0; sighdl[i] != -1; i++)
if (el->el_signal[i] != BADSIG)
(void) signal(sighdl[i], el->el_signal[i]);
sel = NULL; /* we are going to die if the handler is called */
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
}

70
lib/libedit/sig.h Normal file
View File

@ -0,0 +1,70 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sig.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.sig.h: Signal handling functions
*/
#ifndef _h_el_sig
#define _h_el_sig
#include <signal.h>
#include "histedit.h"
/*
* Define here all the signals we are going to handle
* The _DO macro is used to iterate in the source code
*/
#define ALLSIGS \
_DO(SIGINT) \
_DO(SIGTSTP) \
_DO(SIGSTOP) \
_DO(SIGQUIT) \
_DO(SIGHUP) \
_DO(SIGTERM) \
_DO(SIGCONT) \
_DO(SIGWINCH)
typedef sig_t *el_signal_t;
protected void sig_end __P((EditLine*));
protected int sig_init __P((EditLine*));
protected void sig_set __P((EditLine*));
protected void sig_clr __P((EditLine*));
#endif /* _h_el_sig */

114
lib/libedit/sys.h Normal file
View File

@ -0,0 +1,114 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sys.h 8.1 (Berkeley) 6/4/93
*/
/*
* sys.h: Put all the stupid compiler and system dependencies here...
*/
#ifndef _h_sys
#define _h_sys
#ifndef public
# define public /* Externally visible functions/variables */
#endif
#ifndef private
# define private static /* Always hidden internals */
#endif
#ifndef protected
# define protected /* Redefined from elsewhere to "static" */
/* When we want to hide everything */
#endif
#include <sys/cdefs.h>
#ifndef _PTR_T
# define _PTR_T
# if __STDC__
typedef void* ptr_t;
# else
typedef char* ptr_t;
# endif
#endif
#ifndef _IOCTL_T
# define _IOCTL_T
# if __STDC__
typedef void* ioctl_t;
# else
typedef char* ioctl_t;
# endif
#endif
#include <stdio.h>
#define REGEXEC
#undef REGEXP
#ifdef SUNOS
# undef REGEXEC
# include <malloc.h>
typedef void (*sig_t)__P((int));
# ifdef __GNUC__
/*
* Broken hdrs.
*/
extern char *getenv __P((const char *));
extern int fprintf __P((FILE *, const char *, ...));
extern int sigsetmask __P((int));
extern int sigblock __P((int));
extern int ioctl __P((int, int, void *));
extern int fputc __P((int, FILE *));
extern int fgetc __P((FILE *));
extern int fflush __P((FILE *));
extern int tolower __P((int));
extern int toupper __P((int));
extern int errno, sys_nerr;
extern char *sys_errlist[];
extern void perror __P((const char *));
extern int read __P((int, const char*, int));
# include <string.h>
# define strerror(e) sys_errlist[e]
# endif
# ifdef SABER
extern ptr_t memcpy __P((ptr_t, const ptr_t, size_t));
extern ptr_t memset __P((ptr_t, int, size_t));
# endif
extern char *fgetline __P((FILE *, int *));
#endif
#endif /* _h_sys */

1379
lib/libedit/term.c Normal file

File diff suppressed because it is too large Load Diff

118
lib/libedit/term.h Normal file
View File

@ -0,0 +1,118 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)term.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.term.h: Termcap header
*/
#ifndef _h_el_term
#define _h_el_term
#include "histedit.h"
typedef struct { /* Symbolic function key bindings */
char *name; /* name of the key */
int key; /* Index in termcap table */
key_value_t fun; /* Function bound to it */
int type; /* Type of function */
} fkey_t;
typedef struct {
coord_t t_size; /* # lines and cols */
bool_t t_flags;
#define TERM_CAN_INSERT 0x01 /* Has insert cap */
#define TERM_CAN_DELETE 0x02 /* Has delete cap */
#define TERM_CAN_CEOL 0x04 /* Has CEOL cap */
#define TERM_CAN_TAB 0x08 /* Can use tabs */
#define TERM_CAN_ME 0x10 /* Can turn all attrs. */
#define TERM_CAN_UP 0x20 /* Can move up */
#define TERM_HAS_META 0x40 /* Has a meta key */
char *t_buf; /* Termcap buffer */
int t_loc; /* location used */
char **t_str; /* termcap strings */
int *t_val; /* termcap values */
char *t_cap; /* Termcap buffer */
fkey_t *t_fkey; /* Array of keys */
} el_term_t;
/*
* fKey indexes
*/
#define A_K_DN 0
#define A_K_UP 1
#define A_K_LT 2
#define A_K_RT 3
#define A_K_NKEYS 4
protected void term_move_to_line __P((EditLine *, int));
protected void term_move_to_char __P((EditLine *, int));
protected void term_clear_EOL __P((EditLine *, int));
protected void term_overwrite __P((EditLine *, char *, int));
protected void term_insertwrite __P((EditLine *, char *, int));
protected void term_deletechars __P((EditLine *, int));
protected void term_clear_screen __P((EditLine *));
protected void term_beep __P((EditLine *));
protected void term_change_size __P((EditLine *, int, int));
protected int term_get_size __P((EditLine *, int *, int *));
protected int term_init __P((EditLine *));
protected void term_bind_arrow __P((EditLine *));
protected void term_print_arrow __P((EditLine *, char *));
protected int term_clear_arrow __P((EditLine *, char *));
protected int term_set_arrow __P((EditLine *, char *,
key_value_t *, int));
protected void term_end __P((EditLine *));
protected int term_set __P((EditLine *, char *));
protected int term_settc __P((EditLine *, int, char **));
protected int term_telltc __P((EditLine *, int, char **));
protected int term_echotc __P((EditLine *, int, char **));
protected int term__putc __P((int));
protected void term__flush __P((void));
/*
* Easy access macros
*/
#define EL_FLAGS (el)->el_term.t_flags
#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT)
#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE)
#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL)
#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB)
#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME)
#define EL_HAS_META (EL_FLAGS & TERM_HAS_META)
#endif /* _h_el_term */

52
lib/libedit/termcap.h Normal file
View File

@ -0,0 +1,52 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)termcap.h 8.1 (Berkeley) 6/4/93
*/
/*
* termcap.h: I cannot find those in any include files...
*/
#ifndef _h_termcap
#define _h_termcap
int tgetent __P((char *, char *));
char *tgetstr __P((char *, char **));
int tgetflag __P((char *));
int tgetnum __P((char *));
char *tgoto __P((char *, int, int));
char *tputs __P((char *, int, void (*)(int)));
#endif /* _h_termcap */

385
lib/libedit/tokenizer.c Normal file
View File

@ -0,0 +1,385 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* tokenize.c: Bourne shell like tokenizer
*/
#include "sys.h"
#include <string.h>
#include <stdlib.h>
#include "tokenizer.h"
typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone } quote_t;
#define IFS "\t \n"
#define TOK_KEEP 1
#define TOK_EAT 2
#define WINCR 20
#define AINCR 10
#define tok_malloc(a) malloc(a)
#define tok_free(a) free(a)
#define tok_realloc(a, b) realloc(a, b)
struct tokenizer {
char *ifs; /* In field separator */
int argc, amax; /* Current and maximum number of args */
char **argv; /* Argument list */
char *wptr, *wmax; /* Space and limit on the word buffer */
char *wstart; /* Beginning of next word */
char *wspace; /* Space of word buffer */
quote_t quote; /* Quoting state */
int flags; /* flags; */
};
private void tok_finish __P((Tokenizer *));
/* tok_finish():
* Finish a word in the tokenizer.
*/
private void
tok_finish(tok)
Tokenizer *tok;
{
*tok->wptr = '\0';
if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) {
tok->argv[tok->argc++] = tok->wstart;
tok->argv[tok->argc] = NULL;
tok->wstart = ++tok->wptr;
}
tok->flags &= ~TOK_KEEP;
}
/* tok_init():
* Initialize the tokenizer
*/
public Tokenizer *
tok_init(ifs)
const char *ifs;
{
Tokenizer* tok = (Tokenizer*) tok_malloc(sizeof(Tokenizer));
tok->ifs = strdup(ifs ? ifs : IFS);
tok->argc = 0;
tok->amax = AINCR;
tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
tok->argv[0] = NULL;
tok->wspace = (char *) tok_malloc(WINCR);
tok->wmax = tok->wspace + WINCR;
tok->wstart = tok->wspace;
tok->wptr = tok->wspace;
tok->flags = 0;
tok->quote = Q_none;
return tok;
}
/* tok_reset():
* Reset the tokenizer
*/
public void
tok_reset(tok)
Tokenizer *tok;
{
tok->argc = 0;
tok->wstart = tok->wspace;
tok->wptr = tok->wspace;
tok->flags = 0;
tok->quote = Q_none;
}
/* tok_end():
* Clean up
*/
public void
tok_end(tok)
Tokenizer *tok;
{
tok_free((ptr_t) tok->ifs);
tok_free((ptr_t) tok->wspace);
tok_free((ptr_t) tok->argv);
tok_free((ptr_t) tok);
}
/* tok_line():
* Bourne shell like tokenizing
* Return:
* -1: Internal error
* 3: Quoted return
* 2: Unmatched double quote
* 1: Unmatched single quote
* 0: Ok
*/
public int
tok_line(tok, line, argc, argv)
Tokenizer *tok;
const char* line;
int *argc;
char ***argv;
{
const char *ptr;
while (1) {
switch (*(ptr = line++)) {
case '\'':
tok->flags |= TOK_KEEP;
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
tok->quote = Q_single; /* Enter single quote mode */
break;
case Q_single: /* Exit single quote mode */
tok->quote = Q_none;
break;
case Q_one: /* Quote this ' */
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
case Q_double: /* Stay in double quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this ' */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '"':
tok->flags &= ~TOK_EAT;
tok->flags |= TOK_KEEP;
switch (tok->quote) {
case Q_none: /* Enter double quote mode */
tok->quote = Q_double;
break;
case Q_double:
tok->quote = Q_none; /* Exit double quote mode */
break;
case Q_one: /* Quote this " */
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
case Q_single: /* Stay in single quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this " */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '\\':
tok->flags |= TOK_KEEP;
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none: /* Quote next character */
tok->quote = Q_one;
break;
case Q_double:
tok->quote = Q_doubleone;/* Quote next character */
break;
case Q_one:
*tok->wptr++ = *ptr;
tok->quote = Q_none; /* Quote this, restore state */
break;
case Q_single: /* Stay in single quote mode */
*tok->wptr++ = *ptr;
break;
case Q_doubleone: /* Quote this \ */
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
case '\n':
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
tok_finish(tok);
*argv = tok->argv;
*argc = tok->argc;
return(0);
case Q_single:
case Q_double:
*tok->wptr++ = *ptr; /* Add the return */
break;
case Q_doubleone:
tok->flags |= TOK_EAT;
tok->quote = Q_double; /* Back to double, eat the '\n' */
break;
case Q_one:
tok->flags |= TOK_EAT;
tok->quote = Q_none; /* No quote, more eat the '\n' */
break;
default:
return(0);
}
break;
case '\0':
switch (tok->quote) {
case Q_none:
/* Finish word and return */
if (tok->flags & TOK_EAT) {
tok->flags &= ~TOK_EAT;
return 3;
}
tok_finish(tok);
*argv = tok->argv;
*argc = tok->argc;
return(0);
case Q_single:
return(1);
case Q_double:
return(2);
case Q_doubleone:
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
case Q_one:
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
default:
tok->flags &= ~TOK_EAT;
switch (tok->quote) {
case Q_none:
if (strchr(tok->ifs, *ptr) != NULL)
tok_finish(tok);
else
*tok->wptr++ = *ptr;
break;
case Q_single:
case Q_double:
*tok->wptr++ = *ptr;
break;
case Q_doubleone:
*tok->wptr++ = '\\';
tok->quote = Q_double;
*tok->wptr++ = *ptr;
break;
case Q_one:
tok->quote = Q_none;
*tok->wptr++ = *ptr;
break;
default:
return(-1);
}
break;
}
if (tok->wptr >= tok->wmax - 4) {
size_t size = tok->wmax - tok->wspace + WINCR;
char *s = (char *) tok_realloc(tok->wspace, size);
/*SUPPRESS 22*/
int offs = s - tok->wspace;
if (offs != 0) {
int i;
for (i = 0; i < tok->argc; i++)
tok->argv[i] = tok->argv[i] + offs;
tok->wptr = tok->wptr + offs;
tok->wstart = tok->wstart + offs;
tok->wmax = s + size;
tok->wspace = s;
}
}
if (tok->argc >= tok->amax - 4) {
tok->amax += AINCR;
tok->argv = (char **) tok_realloc(tok->argv,
tok->amax * sizeof(char*));
}
}
}

53
lib/libedit/tokenizer.h Normal file
View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tokenizer.h 8.1 (Berkeley) 6/4/93
*/
/*
* tokenizer.h: Header file for tokenizer routines
*/
#ifndef _h_tokenizer
#define _h_tokenizer
typedef struct tokenizer Tokenizer;
Tokenizer *tok_init __P((const char *));
void tok_reset __P((Tokenizer *));
void tok_end __P((Tokenizer *));
int tok_line __P((Tokenizer *, const char *,
int *, char ***));
#endif /* _h_tokenizer */

1144
lib/libedit/tty.c Normal file

File diff suppressed because it is too large Load Diff

476
lib/libedit/tty.h Normal file
View File

@ -0,0 +1,476 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tty.h 8.1 (Berkeley) 6/4/93
*/
/*
* el.tty.h: Local terminal header
*/
#ifndef _h_el_tty
#define _h_el_tty
#include "histedit.h"
#include <termios.h>
/* Define our own since everyone gets it wrong! */
#define CONTROL(A) ((A) & 037)
/*
* Aix compatible names
*/
# if defined(VWERSE) && !defined(VWERASE)
# define VWERASE VWERSE
# endif /* VWERSE && !VWERASE */
# if defined(VDISCRD) && !defined(VDISCARD)
# define VDISCARD VDISCRD
# endif /* VDISCRD && !VDISCARD */
# if defined(VFLUSHO) && !defined(VDISCARD)
# define VDISCARD VFLUSHO
# endif /* VFLUSHO && VDISCARD */
# if defined(VSTRT) && !defined(VSTART)
# define VSTART VSTRT
# endif /* VSTRT && ! VSTART */
# if defined(VSTAT) && !defined(VSTATUS)
# define VSTATUS VSTAT
# endif /* VSTAT && ! VSTATUS */
# ifndef ONLRET
# define ONLRET 0
# endif /* ONLRET */
# ifndef TAB3
# ifdef OXTABS
# define TAB3 OXTABS
# else
# define TAB3 0
# endif /* OXTABS */
# endif /* !TAB3 */
# if defined(OXTABS) && !defined(XTABS)
# define XTABS OXTABS
# endif /* OXTABS && !XTABS */
# ifndef ONLCR
# define ONLCR 0
# endif /* ONLCR */
# ifndef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN */
# ifndef ECHOCTL
# define ECHOCTL 0
# endif /* ECHOCTL */
# ifndef PARENB
# define PARENB 0
# endif /* PARENB */
# ifndef EXTPROC
# define EXTPROC 0
# endif /* EXTPROC */
# ifndef FLUSHO
# define FLUSHO 0
# endif /* FLUSHO */
# if defined(VDISABLE) && !defined(_POSIX_VDISABLE)
# define _POSIX_VDISABLE VDISABLE
# endif /* VDISABLE && ! _POSIX_VDISABLE */
/*
* Work around ISC's definition of IEXTEN which is
* XCASE!
*/
# ifdef ISC
# if defined(IEXTEN) && defined(XCASE)
# if IEXTEN == XCASE
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN == XCASE */
# endif /* IEXTEN && XCASE */
# if defined(IEXTEN) && !defined(XCASE)
# define XCASE IEXTEN
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN && !XCASE */
# endif /* ISC */
/*
* Work around convex weirdness where turning off IEXTEN makes us
* lose all postprocessing!
*/
#if defined(convex) || defined(__convex__)
# if defined(IEXTEN) && IEXTEN != 0
# undef IEXTEN
# define IEXTEN 0
# endif /* IEXTEN != 0 */
#endif /* convex || __convex__ */
#ifndef _POSIX_VDISABLE
# define _POSIX_VDISABLE ((unsigned char) -1)
#endif /* _POSIX_VDISABLE */
#if !defined(CREPRINT) && defined(CRPRNT)
# define CREPRINT CRPRNT
#endif /* !CREPRINT && CRPRNT */
#if !defined(CDISCARD) && defined(CFLUSH)
# define CDISCARD CFLUSH
#endif /* !CDISCARD && CFLUSH */
#ifndef CINTR
# define CINTR CONTROL('c')
#endif /* CINTR */
#ifndef CQUIT
# define CQUIT 034 /* ^\ */
#endif /* CQUIT */
#ifndef CERASE
# define CERASE 0177 /* ^? */
#endif /* CERASE */
#ifndef CKILL
# define CKILL CONTROL('u')
#endif /* CKILL */
#ifndef CEOF
# define CEOF CONTROL('d')
#endif /* CEOF */
#ifndef CEOL
# define CEOL _POSIX_VDISABLE
#endif /* CEOL */
#ifndef CEOL2
# define CEOL2 _POSIX_VDISABLE
#endif /* CEOL2 */
#ifndef CSWTCH
# define CSWTCH _POSIX_VDISABLE
#endif /* CSWTCH */
#ifndef CDSWTCH
# define CDSWTCH _POSIX_VDISABLE
#endif /* CDSWTCH */
#ifndef CERASE2
# define CERASE2 _POSIX_VDISABLE
#endif /* CERASE2 */
#ifndef CSTART
# define CSTART CONTROL('q')
#endif /* CSTART */
#ifndef CSTOP
# define CSTOP CONTROL('s')
#endif /* CSTOP */
#ifndef CSUSP
# define CSUSP CONTROL('z')
#endif /* CSUSP */
#ifndef CDSUSP
# define CDSUSP CONTROL('y')
#endif /* CDSUSP */
#ifdef hpux
# ifndef CREPRINT
# define CREPRINT _POSIX_VDISABLE
# endif /* CREPRINT */
# ifndef CDISCARD
# define CDISCARD _POSIX_VDISABLE
# endif /* CDISCARD */
# ifndef CLNEXT
# define CLNEXT _POSIX_VDISABLE
# endif /* CLNEXT */
# ifndef CWERASE
# define CWERASE _POSIX_VDISABLE
# endif /* CWERASE */
#else /* !hpux */
# ifndef CREPRINT
# define CREPRINT CONTROL('r')
# endif /* CREPRINT */
# ifndef CDISCARD
# define CDISCARD CONTROL('o')
# endif /* CDISCARD */
# ifndef CLNEXT
# define CLNEXT CONTROL('v')
# endif /* CLNEXT */
# ifndef CWERASE
# define CWERASE CONTROL('w')
# endif /* CWERASE */
#endif /* hpux */
#ifndef CSTATUS
# define CSTATUS CONTROL('t')
#endif /* CSTATUS */
#ifndef CPAGE
# define CPAGE ' '
#endif /* CPAGE */
#ifndef CPGOFF
# define CPGOFF CONTROL('m')
#endif /* CPGOFF */
#ifndef CKILL2
# define CKILL2 _POSIX_VDISABLE
#endif /* CKILL2 */
#ifndef CBRK
# ifndef masscomp
# define CBRK 0377
# else
# define CBRK '\0'
# endif /* masscomp */
#endif /* CBRK */
#ifndef CMIN
# define CMIN CEOF
#endif /* CMIN */
#ifndef CTIME
# define CTIME CEOL
#endif /* CTIME */
/*
* Fix for sun inconsistency. On termio VSUSP and the rest of the
* ttychars > NCC are defined. So we undefine them.
*/
#if defined(TERMIO) || defined(POSIX)
# if defined(POSIX) && defined(NCCS)
# define NUMCC NCCS
# else
# ifdef NCC
# define NUMCC NCC
# endif /* NCC */
# endif /* POSIX && NCCS */
# ifdef NUMCC
# ifdef VINTR
# if NUMCC <= VINTR
# undef VINTR
# endif /* NUMCC <= VINTR */
# endif /* VINTR */
# ifdef VQUIT
# if NUMCC <= VQUIT
# undef VQUIT
# endif /* NUMCC <= VQUIT */
# endif /* VQUIT */
# ifdef VERASE
# if NUMCC <= VERASE
# undef VERASE
# endif /* NUMCC <= VERASE */
# endif /* VERASE */
# ifdef VKILL
# if NUMCC <= VKILL
# undef VKILL
# endif /* NUMCC <= VKILL */
# endif /* VKILL */
# ifdef VEOF
# if NUMCC <= VEOF
# undef VEOF
# endif /* NUMCC <= VEOF */
# endif /* VEOF */
# ifdef VEOL
# if NUMCC <= VEOL
# undef VEOL
# endif /* NUMCC <= VEOL */
# endif /* VEOL */
# ifdef VEOL2
# if NUMCC <= VEOL2
# undef VEOL2
# endif /* NUMCC <= VEOL2 */
# endif /* VEOL2 */
# ifdef VSWTCH
# if NUMCC <= VSWTCH
# undef VSWTCH
# endif /* NUMCC <= VSWTCH */
# endif /* VSWTCH */
# ifdef VDSWTCH
# if NUMCC <= VDSWTCH
# undef VDSWTCH
# endif /* NUMCC <= VDSWTCH */
# endif /* VDSWTCH */
# ifdef VERASE2
# if NUMCC <= VERASE2
# undef VERASE2
# endif /* NUMCC <= VERASE2 */
# endif /* VERASE2 */
# ifdef VSTART
# if NUMCC <= VSTART
# undef VSTART
# endif /* NUMCC <= VSTART */
# endif /* VSTART */
# ifdef VSTOP
# if NUMCC <= VSTOP
# undef VSTOP
# endif /* NUMCC <= VSTOP */
# endif /* VSTOP */
# ifdef VWERASE
# if NUMCC <= VWERASE
# undef VWERASE
# endif /* NUMCC <= VWERASE */
# endif /* VWERASE */
# ifdef VSUSP
# if NUMCC <= VSUSP
# undef VSUSP
# endif /* NUMCC <= VSUSP */
# endif /* VSUSP */
# ifdef VDSUSP
# if NUMCC <= VDSUSP
# undef VDSUSP
# endif /* NUMCC <= VDSUSP */
# endif /* VDSUSP */
# ifdef VREPRINT
# if NUMCC <= VREPRINT
# undef VREPRINT
# endif /* NUMCC <= VREPRINT */
# endif /* VREPRINT */
# ifdef VDISCARD
# if NUMCC <= VDISCARD
# undef VDISCARD
# endif /* NUMCC <= VDISCARD */
# endif /* VDISCARD */
# ifdef VLNEXT
# if NUMCC <= VLNEXT
# undef VLNEXT
# endif /* NUMCC <= VLNEXT */
# endif /* VLNEXT */
# ifdef VSTATUS
# if NUMCC <= VSTATUS
# undef VSTATUS
# endif /* NUMCC <= VSTATUS */
# endif /* VSTATUS */
# ifdef VPAGE
# if NUMCC <= VPAGE
# undef VPAGE
# endif /* NUMCC <= VPAGE */
# endif /* VPAGE */
# ifdef VPGOFF
# if NUMCC <= VPGOFF
# undef VPGOFF
# endif /* NUMCC <= VPGOFF */
# endif /* VPGOFF */
# ifdef VKILL2
# if NUMCC <= VKILL2
# undef VKILL2
# endif /* NUMCC <= VKILL2 */
# endif /* VKILL2 */
# ifdef VBRK
# if NUMCC <= VBRK
# undef VBRK
# endif /* NUMCC <= VBRK */
# endif /* VBRK */
# ifdef VMIN
# if NUMCC <= VMIN
# undef VMIN
# endif /* NUMCC <= VMIN */
# endif /* VMIN */
# ifdef VTIME
# if NUMCC <= VTIME
# undef VTIME
# endif /* NUMCC <= VTIME */
# endif /* VTIME */
# endif /* NUMCC */
#endif /* !POSIX */
#define C_INTR 0
#define C_QUIT 1
#define C_ERASE 2
#define C_KILL 3
#define C_EOF 4
#define C_EOL 5
#define C_EOL2 6
#define C_SWTCH 7
#define C_DSWTCH 8
#define C_ERASE2 9
#define C_START 10
#define C_STOP 11
#define C_WERASE 12
#define C_SUSP 13
#define C_DSUSP 14
#define C_REPRINT 15
#define C_DISCARD 16
#define C_LNEXT 17
#define C_STATUS 18
#define C_PAGE 19
#define C_PGOFF 20
#define C_KILL2 21
#define C_BRK 22
#define C_MIN 23
#define C_TIME 24
#define C_NCC 25
#define C_SH(A) (1 << (A))
/*
* Terminal dependend data structures
*/
#define EX_IO 0 /* while we are executing */
#define ED_IO 1 /* while we are editing */
#define TS_IO 2 /* new mode from terminal */
#define QU_IO 2 /* used only for quoted chars */
#define NN_IO 3 /* The number of entries */
#define M_INP 0
#define M_OUT 1
#define M_CTL 2
#define M_LIN 3
#define M_CHAR 4
#define M_NN 5
typedef struct {
char *t_name;
int t_setmask;
int t_clrmask;
} ttyperm_t[NN_IO][M_NN];
typedef unsigned char ttychar_t[NN_IO][C_NCC];
protected int tty_init __P((EditLine *));
protected void tty_end __P((EditLine *));
protected int tty_stty __P((EditLine *, int, char**));
protected int tty_rawmode __P((EditLine *));
protected int tty_cookedmode __P((EditLine *));
protected int tty_quotemode __P((EditLine *));
protected int tty_noquotemode __P((EditLine *));
protected void tty_bind_char __P((EditLine *, int));
typedef struct {
ttyperm_t t_t;
ttychar_t t_c;
struct termios t_ex, t_ed, t_ts;
int t_tabs;
int t_eight;
speed_t t_speed;
int t_mode;
unsigned char t_vdisable;
} el_tty_t;
#endif /* _h_el_tty */

986
lib/libedit/vi.c Normal file
View File

@ -0,0 +1,986 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Christos Zoulas of Cornell University.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if !defined(lint) && !defined(SCCSID)
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#endif /* not lint && not SCCSID */
/*
* vi.c: Vi mode commands.
*/
#include "sys.h"
#include "el.h"
private el_action_t cv_action __P((EditLine *, int));
/* cv_action():
* Handle vi actions.
*/
private el_action_t
cv_action(el, c)
EditLine *el;
int c;
{
register char *cp, *kp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
kp = el->el_chared.c_undo.buf;
for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
*kp++ = *cp;
el->el_chared.c_undo.dsize++;
}
el->el_chared.c_undo.action = INSERT;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (c & INSERT)
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return CC_ARGHACK;
#ifdef notdef
/*
* I don't think that this is needed. But we keep it for now
*/
else if (el_chared.c_vcmd.action == NOP) {
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return CC_ARGHACK;
}
else {
el->el_chared.c_vcmd.action = 0;
el->el_chared.c_vcmd.pos = 0;
return CC_ERROR;
}
#endif
}
/* cv_paste():
* Paste previous deletion before or after the cursor
*/
protected el_action_t
cv_paste(el, c)
EditLine *el;
int c;
{
char *ptr;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_PASTE
(void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
if (un->isize == 0)
return CC_ERROR;
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
ptr = el->el_line.cursor;
c_insert(el, un->isize);
if (el->el_line.cursor + un->isize > el->el_line.lastchar)
return CC_ERROR;
(void) memcpy(ptr, un->buf, un->isize);
return CC_REFRESH;
}
/* vi_paste_next():
* Vi paste previous deletion to the right of the cursor
* [p]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_next(el, c)
EditLine *el;
int c;
{
return cv_paste(el, 0);
}
/* vi_paste_prev():
* Vi paste previous deletion to the left of the cursor
* [P]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_prev(el, c)
EditLine *el;
int c;
{
return cv_paste(el, 1);
}
/* vi_prev_space_word():
* Vi move to the previous space delimited word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_space_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_prev_word():
* Vi move to the previous word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
ce__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_next_space_word():
* Vi move to the next space delimited word
* [W]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_space_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
cv__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;
}
/* vi_next_word():
* Vi move to the next word
* [w]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv_next_word(el, 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;
}
/* vi_change_case():
* Vi change case of character under the cursor and advance one character
* [~]
*/
protected el_action_t
vi_change_case(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor < el->el_line.lastchar) {
c = *el->el_line.cursor;
if (isupper(c))
*el->el_line.cursor++ = tolower(c);
else if (islower(c))
*el->el_line.cursor++ = toupper(c);
else
el->el_line.cursor++;
re_fastaddc(el);
return CC_NORM;
}
return CC_ERROR;
}
/* vi_change_meta():
* Vi change prefix command
* [c]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_meta(el, c)
EditLine *el;
int c;
{
/*
* Delete with insert == change: first we delete and then we leave in
* insert mode.
*/
return cv_action(el, DELETE|INSERT);
}
/* vi_insert_at_bol():
* Vi enter insert mode at the beginning of line
* [I]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert_at_bol(el, c)
EditLine *el;
int c;
{
el->el_line.cursor = el->el_line.buffer;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
el->el_map.current = el->el_map.key;
return CC_CURSOR;
}
/* vi_replace_char():
* Vi replace character under the cursor with the next character typed
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_char(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE_1;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return CC_NORM;
}
/* vi_replace_mode():
* Vi enter replace mode
* [R]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_mode(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return CC_NORM;
}
/* vi_substitute_char():
* Vi replace character under the cursor and enter insert mode
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_char(el, c)
EditLine *el;
int c;
{
c_delafter(el, el->el_state.argument);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_substitute_line():
* Vi substitute entire line
* [S]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_line(el, c)
EditLine *el;
int c;
{
(void) em_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_change_to_eol():
* Vi change to end of line
* [C]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_to_eol(el, c)
EditLine *el;
int c;
{
(void) ed_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return CC_REFRESH;
}
/* vi_insert():
* Vi enter insert mode
* [i]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return CC_NORM;
}
/* vi_add():
* Vi enter insert mode after the cursor
* [a]
*/
protected el_action_t
/*ARGSUSED*/
vi_add(el, c)
EditLine *el;
int c;
{
int ret;
el->el_map.current = el->el_map.key;
if (el->el_line.cursor < el->el_line.lastchar) {
el->el_line.cursor++;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
ret = CC_CURSOR;
}
else
ret = CC_NORM;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return ret;
}
/* vi_add_at_eol():
* Vi enter insert mode at end of line
* [A]
*/
protected el_action_t
/*ARGSUSED*/
vi_add_at_eol(el, c)
EditLine *el;
int c;
{
el->el_map.current = el->el_map.key;
el->el_line.cursor = el->el_line.lastchar;
/* Mark where insertion begins */
el->el_chared.c_vcmd.ins = el->el_line.lastchar;
el->el_chared.c_undo.ptr = el->el_line.lastchar;
el->el_chared.c_undo.action = DELETE;
return CC_CURSOR;
}
/* vi_delete_meta():
* Vi delete prefix command
* [d]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_meta(el, c)
EditLine *el;
int c;
{
return cv_action(el, DELETE);
}
/* vi_end_word():
* Vi move to the end of the current space delimited word
* [E]
*/
protected el_action_t
/*ARGSUSED*/
vi_end_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_to_end_word():
* Vi move to the end of the current word
* [e]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_end_word(el, c)
EditLine *el;
int c;
{
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
/* vi_undo():
* Vi undo last change
* [u]
*/
protected el_action_t
/*ARGSUSED*/
vi_undo(el, c)
EditLine *el;
int c;
{
char *cp, *kp;
char temp;
int i, size;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_UNDO
(void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
switch (un->action) {
case DELETE:
if (un->dsize == 0)
return CC_NORM;
(void) memcpy(un->buf, un->ptr, un->dsize);
for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
*cp = cp[un->dsize];
el->el_line.lastchar -= un->dsize;
el->el_line.cursor = un->ptr;
un->action = INSERT;
un->isize = un->dsize;
un->dsize = 0;
break;
case DELETE|INSERT:
size = un->isize - un->dsize;
if (size > 0)
i = un->dsize;
else
i = un->isize;
cp = un->ptr;
kp = un->buf;
while (i-- > 0) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
if (size > 0) {
el->el_line.cursor = cp;
c_insert(el, size);
while (size-- > 0 && cp < el->el_line.lastchar) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
}
else if (size < 0) {
size = -size;
for (; cp <= el->el_line.lastchar; cp++) {
*kp++ = *cp;
*cp = cp[size];
}
el->el_line.lastchar -= size;
}
el->el_line.cursor = un->ptr;
i = un->dsize;
un->dsize = un->isize;
un->isize = i;
break;
case INSERT:
if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
c_insert(el, un->isize);
memcpy(un->ptr, un->buf, un->isize);
un->action = DELETE;
un->dsize = un->isize;
un->isize = 0;
break;
case CHANGE:
if (un->isize == 0)
return CC_NORM;
el->el_line.cursor = un->ptr;
size = (int) (el->el_line.cursor - el->el_line.lastchar);
if (size < un->isize)
size = un->isize;
cp = un->ptr;
kp = un->buf;
for(i = 0; i < size; i++) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
un->dsize = 0;
break;
default:
return CC_ERROR;
}
return CC_REFRESH;
}
/* vi_command_mode():
* Vi enter command mode (use alternative key bindings)
* [<ESC>]
*/
protected el_action_t
/*ARGSUSED*/
vi_command_mode(el, c)
EditLine *el;
int c;
{
int size;
/* [Esc] cancels pending action */
el->el_chared.c_vcmd.ins = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_state.doingarg = 0;
size = el->el_chared.c_undo.ptr - el->el_line.cursor;
if (size < 0)
size = -size;
if (el->el_chared.c_undo.action == (INSERT|DELETE) ||
el->el_chared.c_undo.action == DELETE)
el->el_chared.c_undo.dsize = size;
else
el->el_chared.c_undo.isize = size;
el->el_state.inputmode = MODE_INSERT;
el->el_map.current = el->el_map.alt;
#ifdef VI_MOVE
if (el->el_line.cursor > el->el_line.buffer)
el->el_line.cursor--;
#endif
return CC_CURSOR;
}
/* vi_zero():
* Vi move to the beginning of line
* [0]
*/
protected el_action_t
vi_zero(el, c)
EditLine *el;
int c;
{
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');
return CC_ARGHACK;
}
else {
el->el_line.cursor = el->el_line.buffer;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return CC_REFRESH;
}
return CC_CURSOR;
}
}
/* vi_delete_prev_char():
* Vi move to previous character (backspace)
* [^H]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_chared.c_vcmd.ins == 0)
return CC_ERROR;
if (el->el_chared.c_vcmd.ins >
el->el_line.cursor - el->el_state.argument)
return CC_ERROR;
c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
return CC_REFRESH;
} /* end v_del_char_prev */
/* vi_list_or_eof():
* Vi list choices for completion or indicate end of file if empty line
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
vi_list_or_eof(el, c)
EditLine *el;
int c;
{
#ifdef notyet
if (el->el_line.cursor == el->el_line.lastchar &&
el->el_line.cursor == el->el_line.buffer) {
#endif
term_overwrite(el, STReof, 4); /* then do a EOF */
term__flush();
return CC_EOF;
#ifdef notyet
}
else {
re_goto_bottom(el);
*el->el_line.lastchar = '\0'; /* just in case */
return CC_LIST_CHOICES;
}
#endif
}
/* vi_kill_line_prev():
* Vi cut from beginning of line to cursor
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
vi_kill_line_prev(el, c)
EditLine *el;
int c;
{
char *kp, *cp;
cp = el->el_line.buffer;
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, el->el_line.cursor - el->el_line.buffer);
el->el_line.cursor = el->el_line.buffer; /* zap! */
return CC_REFRESH;
}
/* vi_search_prev():
* Vi search history previous
* [?]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_prev(el, c)
EditLine *el;
int c;
{
return cv_search(el, ED_SEARCH_PREV_HISTORY);
}
/* vi_search_next():
* Vi search history next
* [/]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_next(el, c)
EditLine *el;
int c;
{
return cv_search(el, ED_SEARCH_NEXT_HISTORY);
}
/* vi_repeat_search_next():
* Vi repeat current search in the same search direction
* [n]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_search_next(el, c)
EditLine *el;
int c;
{
if (el->el_search.patlen == 0)
return CC_ERROR;
else
return cv_repeat_srch(el, el->el_search.patdir);
}
/* vi_repeat_search_prev():
* Vi repeat current search in the opposite search direction
* [N]
*/
/*ARGSUSED*/
protected el_action_t
vi_repeat_search_prev(el, c)
EditLine *el;
int c;
{
if (el->el_search.patlen == 0)
return CC_ERROR;
else
return cv_repeat_srch(el,
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY);
}
/* vi_next_char():
* Vi move to the character specified next
* [f]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
el->el_search.chadir = CHAR_FWD;
el->el_search.chacha = ch;
return cv_csearch_fwd(el, ch, el->el_state.argument, 0);
}
/* vi_prev_char():
* Vi move to the character specified previous
* [F]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
el->el_search.chadir = CHAR_BACK;
el->el_search.chacha = ch;
return cv_csearch_back(el, ch, el->el_state.argument, 0);
}
/* vi_to_next_char():
* Vi move up to the character specified next
* [t]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_next_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
return cv_csearch_fwd(el, ch, el->el_state.argument, 1);
}
/* vi_to_prev_char():
* Vi move up to the character specified previous
* [T]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_prev_char(el, c)
EditLine *el;
int c;
{
char ch;
if (el_getc(el, &ch) != 1)
return ed_end_of_file(el, 0);
return cv_csearch_back(el, ch, el->el_state.argument, 1);
}
/* vi_repeat_next_char():
* Vi repeat current character search in the same search direction
* [;]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_next_char(el, c)
EditLine *el;
int c;
{
if (el->el_search.chacha == 0)
return CC_ERROR;
return el->el_search.chadir == CHAR_FWD ?
cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}
/* vi_repeat_prev_char():
* Vi repeat current character search in the opposite search direction
* [,]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_prev_char(el, c)
EditLine *el;
int c;
{
if (el->el_search.chacha == 0)
return CC_ERROR;
return el->el_search.chadir == CHAR_BACK ?
cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}