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;