Vendor import NetBSD's libedit of "1997-06-25 01:14:45 -0700".
Obtained from: NetBSD
This commit is contained in:
commit
4d860275f5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/NetBSD/libedit/dist/; revision=220174 svn path=/vendor/NetBSD/libedit/1997-06-25/; revision=220175; tag=vendor/NetBSD/libedit/1997-06-25
63
Makefile
Normal file
63
Makefile
Normal file
@ -0,0 +1,63 @@
|
||||
# $NetBSD: Makefile,v 1.8 1997/05/09 07:50:14 mycroft Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||
|
||||
LIB= edit
|
||||
|
||||
OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \
|
||||
parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c
|
||||
|
||||
MAN= editline.3 editrc.5
|
||||
|
||||
MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \
|
||||
editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \
|
||||
editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \
|
||||
editline.3 el_resize.3 editline.3 el_line.3 \
|
||||
editline.3 el_insertstr.3 editline.3 el_deletestr.3 \
|
||||
editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3
|
||||
|
||||
# For speed and debugging
|
||||
#SRCS= ${OSRCS} tokenizer.c history.c
|
||||
# For protection
|
||||
SRCS= editline.c tokenizer.c history.c
|
||||
|
||||
SRCS+= common.h emacs.h fcns.h help.h vi.h
|
||||
|
||||
INCS= histedit.h
|
||||
INCSDIR=/usr/include
|
||||
|
||||
CLEANFILES+=common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h
|
||||
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}
|
||||
|
||||
test: libedit.a test.o
|
||||
${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap
|
||||
|
||||
.include <bsd.lib.mk>
|
250
TEST/test.c
Normal file
250
TEST/test.c
Normal file
@ -0,0 +1,250 @@
|
||||
/* $NetBSD */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD";
|
||||
#endif
|
||||
#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 (strcmp(av[0], "history") == 0) {
|
||||
const struct HistEvent *he;
|
||||
|
||||
switch (ac) {
|
||||
case 1:
|
||||
for (he = history(hist, H_LAST); he;
|
||||
he = history(hist, H_PREV))
|
||||
(void) fprintf(stdout, "%4d %s", he->num, he->str);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (strcmp(av[1], "clear") == 0)
|
||||
history(hist, H_CLEAR);
|
||||
else
|
||||
goto badhist;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (strcmp(av[1], "load") == 0)
|
||||
history(hist, H_LOAD, av[2]);
|
||||
else if (strcmp(av[1], "save") == 0)
|
||||
history(hist, H_SAVE, av[2]);
|
||||
break;
|
||||
|
||||
badhist:
|
||||
default:
|
||||
(void) fprintf(stderr, "Bad history arguments\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (el_parse(el, ac, av) == -1) {
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
execvp(av[0], av);
|
||||
perror(av[0]);
|
||||
_exit(1);
|
||||
/*NOTREACHED*/
|
||||
break;
|
||||
|
||||
case -1:
|
||||
perror("fork");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (wait(&num) == -1)
|
||||
perror("wait");
|
||||
(void) fprintf(stderr, "Exit %x\n", num);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tok_reset(tok);
|
||||
}
|
||||
|
||||
el_end(el);
|
||||
tok_end(tok);
|
||||
history_end(hist);
|
||||
|
||||
return 0;
|
||||
}
|
645
chared.c
Normal file
645
chared.c
Normal file
@ -0,0 +1,645 @@
|
||||
/* $NetBSD: chared.c,v 1.2 1997/01/11 06:47:48 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: chared.c,v 1.2 1997/01/11 06:47:48 lukem Exp $";
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
}
|
160
chared.h
Normal file
160
chared.h
Normal file
@ -0,0 +1,160 @@
|
||||
/* $NetBSD: chared.h,v 1.2 1997/01/11 06:47:49 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
998
common.c
Normal file
998
common.c
Normal file
@ -0,0 +1,998 @@
|
||||
/* $NetBSD: common.c,v 1.3 1997/01/14 04:17:22 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: common.c,v 1.3 1997/01/14 04:17:22 lukem Exp $";
|
||||
#endif
|
||||
#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;
|
||||
{
|
||||
return CC_REDISPLAY;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
532
editline.3
Normal file
532
editline.3
Normal file
@ -0,0 +1,532 @@
|
||||
.\" $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
.\"
|
||||
.Dd January 11, 1997
|
||||
.Os BSD 4.4
|
||||
.Dt EDITLINE 3
|
||||
.Sh NAME
|
||||
.Nm editline ,
|
||||
.Nm el_init ,
|
||||
.Nm el_end ,
|
||||
.Nm el_reset ,
|
||||
.Nm el_gets ,
|
||||
.Nm el_getc ,
|
||||
.Nm el_push ,
|
||||
.Nm el_parse ,
|
||||
.Nm el_set ,
|
||||
.Nm el_source ,
|
||||
.Nm el_resize ,
|
||||
.Nm el_line ,
|
||||
.Nm el_insertstr ,
|
||||
.Nm el_deletestr ,
|
||||
.Nm history_init ,
|
||||
.Nm history_end ,
|
||||
.Nm history
|
||||
.Nd line editor and history functions
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <histedit.h>
|
||||
.Ft EditLine *
|
||||
.Fn el_init "const char *prog" "FILE *fin" "FILE *fout"
|
||||
.Ft void
|
||||
.Fn el_end "EditLine *e"
|
||||
.Ft void
|
||||
.Fn el_reset "EditLine *e"
|
||||
.Ft const char *
|
||||
.Fn el_gets "EditLine *e" "int *count"
|
||||
.Ft int
|
||||
.Fn el_getc "EditLine *e" "char *ch"
|
||||
.Ft void
|
||||
.Fn el_push "EditLine *e" "const char *str"
|
||||
.Ft int
|
||||
.Fn el_parse "EditLine *e" "int argc" "char *argv[]"
|
||||
.Ft int
|
||||
.Fn el_set "EditLine *e" "int op" "..."
|
||||
.Ft int
|
||||
.Fn el_source "EditLine *e" "const char *file"
|
||||
.Ft void
|
||||
.Fn el_resize "EditLine *e"
|
||||
.Ft const LineInfo *
|
||||
.Fn el_line "EditLine *e"
|
||||
.Ft int
|
||||
.Fn el_insertstr "EditLine *e" "char *str"
|
||||
.Ft void
|
||||
.Fn el_deletestr "EditLine *e" "int count"
|
||||
.Ft History *
|
||||
.Fn history_init
|
||||
.Ft void
|
||||
.Fn history_end "History *h"
|
||||
.Ft HistEvent *
|
||||
.Fn history "History h" "int op" "..."
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
library provides generic line editing and history functions,
|
||||
similar to those found in
|
||||
.Xr sh 1 .
|
||||
.Pp
|
||||
These functions are available in the
|
||||
.Nm libedit
|
||||
library (which needs the
|
||||
.Nm libtermcap
|
||||
library).
|
||||
Programs should be linked with
|
||||
.Fl ledit ltermcap .
|
||||
.Sh LINE EDITING FUNCTIONS
|
||||
The line editing functions use a common data structure,
|
||||
.Fa EditLine ,
|
||||
which is created by
|
||||
.Fn el_init
|
||||
and freed by
|
||||
.Fn el_end .
|
||||
.Pp
|
||||
The following functions are available:
|
||||
.Bl -tag -width 4n
|
||||
.It Fn el_init
|
||||
Initialise the line editor, and return a data structure
|
||||
to be used by all other line editing functions.
|
||||
.Fa prog
|
||||
is the name of the invoking program, used when reading the
|
||||
.Xr editrc 5
|
||||
file to determine which settings to use.
|
||||
.Fa fin
|
||||
and
|
||||
.Fa fout
|
||||
are the input and output streams (respectively) to use.
|
||||
In this documentation, references to
|
||||
.Dq the tty
|
||||
are actually to this input/output stream combination.
|
||||
.It Fn el_end
|
||||
Clean up and finish with
|
||||
.Fa e ,
|
||||
assumed to have been created with
|
||||
.Fn el_init .
|
||||
.It Fn el_reset
|
||||
Reset the tty and the parser.
|
||||
This should be called after an error which may have upset the tty's
|
||||
state.
|
||||
.It Fn el_gets
|
||||
Read a line from the tty.
|
||||
.Fa count
|
||||
is modified to contain the number of characters read.
|
||||
Returns the line read if successful, or
|
||||
.Dv NULL
|
||||
if no characters were read or if an error occurred.
|
||||
.It Fn el_getc
|
||||
Read a character from the tty.
|
||||
.Fa ch
|
||||
is modified to contain the character read.
|
||||
Returns the number of characters read if successful, -1 otherwise.
|
||||
.It Fn el_push
|
||||
Pushes
|
||||
.Fa str
|
||||
back onto the input stream.
|
||||
This is used by the macro expansion mechanism.
|
||||
Refer to the description of
|
||||
.Ic bind
|
||||
.Fl s
|
||||
in
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Fn el_parse
|
||||
Parses the
|
||||
.Fa argv
|
||||
array (which is
|
||||
.Fa argc
|
||||
elements in size)
|
||||
to execute builtin
|
||||
.Nm
|
||||
commands.
|
||||
If the command is prefixed with
|
||||
.Dq prog:
|
||||
then
|
||||
.Fn el_parse
|
||||
will only execute the command if
|
||||
.Dq prog
|
||||
matches the
|
||||
.Fa prog
|
||||
argument supplied to
|
||||
.Fn el_init .
|
||||
The return value is
|
||||
-1 if the command is unknown,
|
||||
0 if there was no error or
|
||||
.Dq prog
|
||||
didn't match, or
|
||||
1 if the command returned an error.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.Pp
|
||||
.Em NOTE:
|
||||
.Va argv[0]
|
||||
may be modified by
|
||||
.Fn el_parse .
|
||||
The colon between
|
||||
.Dq prog
|
||||
and the command,
|
||||
.Ar command ,
|
||||
will be replaced with a NUL
|
||||
.Po
|
||||
.Dq \e0
|
||||
.Pc .
|
||||
.It Fn el_set
|
||||
Set
|
||||
.Nm
|
||||
parameters.
|
||||
.Fa op
|
||||
determines which parameter to set, and each operation has its
|
||||
own parameter list.
|
||||
.Pp
|
||||
The following values for
|
||||
.Fa op
|
||||
are supported, along with the required argument list:
|
||||
.Bl -tag -width 4n
|
||||
.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)"
|
||||
Define prompt printing function as
|
||||
.Fa f ,
|
||||
which is to return a string that contains the prompt.
|
||||
.It Dv EL_TERMINAL , Fa "const char *type"
|
||||
Define terminal type of the tty to be
|
||||
.Fa type ,
|
||||
or to
|
||||
.Ev TERM
|
||||
if
|
||||
.Fa type
|
||||
is
|
||||
.Dv NULL .
|
||||
.It Dv EL_EDITOR , Fa "const char *mode"
|
||||
Set editing mode to
|
||||
.Fa mode ,
|
||||
which must be one of
|
||||
.Dq emacs
|
||||
or
|
||||
.Dq vi .
|
||||
.It Dv EL_SIGNAL , Fa "int flag"
|
||||
If
|
||||
.Fa flag
|
||||
is non-zero,
|
||||
.Nm
|
||||
will install its own signal handler for the following signals when
|
||||
reading command input:
|
||||
.Dv SIGCONT ,
|
||||
.Dv SIGHUP ,
|
||||
.Dv SIGINT ,
|
||||
.Dv SIGQUIT ,
|
||||
.Dv SIGSTOP ,
|
||||
.Dv SIGTERM ,
|
||||
.Dv SIGTSTP ,
|
||||
and
|
||||
.Dv SIGWINCH .
|
||||
Otherwise, the current signal handlers will be used.
|
||||
.It Dv EL_BIND , Xo
|
||||
.Fa "const char *" ,
|
||||
.Fa "..." ,
|
||||
.Dv NULL
|
||||
.Xc
|
||||
Perform the
|
||||
.Ic bind
|
||||
builtin command.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Dv EL_ECHOTC , Xo
|
||||
.Fa "const char *" ,
|
||||
.Fa "..." ,
|
||||
.Dv NULL
|
||||
.Xc
|
||||
Perform the
|
||||
.Ic echotc
|
||||
builtin command.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Dv EL_SETTC , Xo
|
||||
.Fa "const char *" ,
|
||||
.Fa "..." ,
|
||||
.Dv NULL
|
||||
.Xc
|
||||
Perform the
|
||||
.Ic settc
|
||||
builtin command.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Dv EL_SETTY , Xo
|
||||
.Fa "const char *" ,
|
||||
.Fa "..." ,
|
||||
.Dv NULL
|
||||
.Xc
|
||||
Perform the
|
||||
.Ic setty
|
||||
builtin command.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Dv EL_TELLTC , Xo
|
||||
.Fa "const char *" ,
|
||||
.Fa "..." ,
|
||||
.Dv NULL
|
||||
.Xc
|
||||
Perform the
|
||||
.Ic telltc
|
||||
builtin command.
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.It Dv EL_ADDFN , Xo
|
||||
.Fa "const char *name" ,
|
||||
.Fa "const char *help" ,
|
||||
.Fa "unsigned char (*func)(EditLine *e, int ch)
|
||||
.Xc
|
||||
Add a user defined function,
|
||||
.Fn func ,
|
||||
referred to as
|
||||
.Fa name
|
||||
which is invoked when a key which is bound to
|
||||
.Fa name
|
||||
is entered.
|
||||
.Fa help
|
||||
is a description of
|
||||
.Fa name .
|
||||
At invocation time,
|
||||
.Fa ch
|
||||
is the key which caused the invocation.
|
||||
The return value of
|
||||
.Fn func
|
||||
should be one of:
|
||||
.Bl -tag -width "CC_REDISPLAY"
|
||||
.It Dv CC_NORM
|
||||
Add a normal character.
|
||||
.It Dv CC_NEWLINE
|
||||
End of line was entered.
|
||||
.It Dv CC_EOF
|
||||
EOF was entered.
|
||||
.It Dv CC_ARGHACK
|
||||
Expecting further command input as arguments, do nothing visually.
|
||||
.It Dv CC_REFRESH
|
||||
Refresh display.
|
||||
.It Dv CC_CURSOR
|
||||
Cursor moved, so update and perform
|
||||
.Dv CC_REFRESH.
|
||||
.It Dv CC_REDISPLAY
|
||||
Redisplay entire input line.
|
||||
This is useful if a key binding outputs extra information.
|
||||
.It Dv CC_ERROR
|
||||
An error occurred.
|
||||
Beep, and flush tty.
|
||||
.It Dv CC_FATAL
|
||||
Fatal error, reset tty to known state.
|
||||
.El
|
||||
.It Dv EL_HIST , Xo
|
||||
.Fa "History *(*func)(History *, int op, ...)" ,
|
||||
.Fa "const char *ptr"
|
||||
.Xc
|
||||
Defines which history function to use, which is usually
|
||||
.Fn history .
|
||||
.Fa ptr
|
||||
should be the value returned by
|
||||
.Fn history_init .
|
||||
.El
|
||||
.It Fn el_source
|
||||
Initialise
|
||||
.Nm
|
||||
by reading the contents of
|
||||
.Fa file .
|
||||
.Fn el_parse
|
||||
is called for each line in
|
||||
.Fa file .
|
||||
If
|
||||
.Fa file
|
||||
is
|
||||
.Dv NULL ,
|
||||
try
|
||||
.Pa $PWD/.editrc
|
||||
then
|
||||
.Pa $HOME/.editrc .
|
||||
Refer to
|
||||
.Xr editrc 5
|
||||
for details on the format of
|
||||
.Fa file .
|
||||
.It Fn el_resize
|
||||
Must be called if the terminal size changes.
|
||||
If
|
||||
.Dv EL_SIGNAL
|
||||
has been set with
|
||||
.Fn el_set ,
|
||||
then this is done automatically.
|
||||
Otherwise, it's the responsibility of the application to call
|
||||
.Fn el_resize
|
||||
on the appropriate occasions.
|
||||
.It Fn el_line
|
||||
Return the editing information for the current line in a
|
||||
.Fa LineInfo
|
||||
structure, which is defined as follows:
|
||||
.Bd -literal
|
||||
typedef struct lineinfo {
|
||||
const char *buffer; /* address of buffer */
|
||||
const char *cursor; /* address of cursor */
|
||||
const char *lastchar; /* address of last character */
|
||||
} LineInfo;
|
||||
.Ed
|
||||
.It Fn el_insertstr
|
||||
Insert
|
||||
.Fa str
|
||||
into the line at the cursor.
|
||||
Returns -1 if
|
||||
.Fa str
|
||||
is empty or won't fit, and 0 otherwise.
|
||||
.It Fn el_deletestr
|
||||
Delete
|
||||
.Fa num
|
||||
characters before the cursor.
|
||||
.El
|
||||
.Sh HISTORY LIST FUNCTIONS
|
||||
The history functions use a common data structure,
|
||||
.Fa History ,
|
||||
which is created by
|
||||
.Fn history_init
|
||||
and freed by
|
||||
.Fn history_end .
|
||||
.Pp
|
||||
The following functions are available:
|
||||
.Bl -tag -width 4n
|
||||
.It Fn history_init
|
||||
Initialise the history list, and return a data structure
|
||||
to be used by all other history list functions.
|
||||
.It Fn history_end
|
||||
Clean up and finish with
|
||||
.Fa h ,
|
||||
assumed to have been created with
|
||||
.Fn history_init .
|
||||
.It Fn history
|
||||
Perform operation
|
||||
.Fa op
|
||||
on the history list, with optional arguments as needed by the
|
||||
operation.
|
||||
The following values for
|
||||
.Fa op
|
||||
are supported, along with the required argument list:
|
||||
.Bl -tag -width 4n
|
||||
.It Dv H_EVENT , Fa "int size"
|
||||
Set size of history to
|
||||
.Fa size
|
||||
elements.
|
||||
.It Dv H_END
|
||||
Cleans up and finishes with
|
||||
.Fa h ,
|
||||
assumed to be created with
|
||||
.Fn history_init .
|
||||
.It Dv H_CLEAR
|
||||
Clear the history.
|
||||
.It Dv H_FUNC , Xo
|
||||
.Fa "void *ptr" ,
|
||||
.Fa "history_gfun_t first" ,
|
||||
.Fa "history_gfun_t next" ,
|
||||
.Fa "history_gfun_t last" ,
|
||||
.Fa "history_gfun_t prev" ,
|
||||
.Fa "history_gfun_t curr" ,
|
||||
.Fa "history_vfun_t clear" ,
|
||||
.Fa "history_efun_t enter" ,
|
||||
.Fa "history_efun_t add"
|
||||
.Xc
|
||||
Define functions to perform various history operations.
|
||||
.Fa ptr
|
||||
is the argument given to a function when it's invoked.
|
||||
.It Dv H_FIRST
|
||||
Return the first element in the history.
|
||||
.It Dv H_LAST
|
||||
Return the last element in the history.
|
||||
.It Dv H_PREV
|
||||
Return the previous element in the history.
|
||||
.It Dv H_NEXT
|
||||
Return the next element in the history.
|
||||
.It Dv H_CURR
|
||||
Return the current element in the history.
|
||||
.It Dv H_ADD , Fa "const char *str"
|
||||
Append
|
||||
.Fa str
|
||||
to the current element of the history, or create an element with
|
||||
.Dv H_ENTER
|
||||
if there isn't one.
|
||||
.It Dv H_ENTER , Fa "const char *str"
|
||||
Add
|
||||
.Fa str
|
||||
as a new element to the history, and, if necessary,
|
||||
removing the oldest entry to keep the list to the created size.
|
||||
.It Dv H_PREV_STR , Fa "const char *str"
|
||||
Return the closest previous event that starts with
|
||||
.Fa str .
|
||||
.It Dv H_NEXT_STR , Fa "const char *str"
|
||||
Return the closest next event that starts with
|
||||
.Fa str .
|
||||
.It Dv H_PREV_EVENT , Fa "int e"
|
||||
Return the previous event numbered
|
||||
.Fa e .
|
||||
.It Dv H_NEXT_EVENT , Fa "int e"
|
||||
Return the next event numbered
|
||||
.Fa e .
|
||||
.It Dv H_LOAD , Fa "const char *file"
|
||||
Load the history list stored in
|
||||
.Fa file .
|
||||
.It Dv H_SAVE , Fa "const char *file"
|
||||
Save the history list to
|
||||
.Fa file .
|
||||
.El
|
||||
.El
|
||||
.\"XXX.Sh EXAMPLES
|
||||
.\"XXX: provide some examples
|
||||
.Sh SEE ALSO
|
||||
.Xr editrc 5 ,
|
||||
.Xr sh 1 ,
|
||||
.Xr signal 3 ,
|
||||
.Xr termcap 3
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
library first appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
library was written by Christos Zoulas,
|
||||
and this manual was written by Luke Mewburn.
|
||||
.Sh BUGS
|
||||
This documentation is probably incomplete.
|
||||
.Pp
|
||||
.Fn el_parse
|
||||
should not modify the supplied
|
||||
.Va argv[0] .
|
||||
.Pp
|
||||
The tokenization functions are not publically defined in
|
||||
.Fd <histedit.h>
|
292
editrc.5
Normal file
292
editrc.5
Normal file
@ -0,0 +1,292 @@
|
||||
.\" $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 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.
|
||||
.\"
|
||||
.Dd January 11, 1997
|
||||
.Os BSD 4.4
|
||||
.Dt EDITRC 5
|
||||
.Sh NAME
|
||||
.Nm editrc
|
||||
.Nd configuration file for editline library
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
file defines various settings to be used by the
|
||||
.Xr editline 3
|
||||
library.
|
||||
.Pp
|
||||
The format of each line is either:
|
||||
.Dl prog:command [arg [...]]
|
||||
or
|
||||
.Dl command [arg [...]]
|
||||
.Pp
|
||||
.Ar command
|
||||
is one of the
|
||||
.Xr editline 3
|
||||
builtin commands.
|
||||
Refer to
|
||||
.Sx BUILTIN COMMANDS
|
||||
for more information.
|
||||
.Pp
|
||||
.Ar prog
|
||||
is the program name string that a program defines when it calls
|
||||
.Xr el_init 3
|
||||
to setup
|
||||
.Xr editline 3 ,
|
||||
which is usually
|
||||
.Va argv[0] .
|
||||
.Ar command
|
||||
will be executed for any program which matches
|
||||
.Ar prog .
|
||||
.Pp
|
||||
.Ar prog
|
||||
may also be a
|
||||
.Xr regex 3
|
||||
style
|
||||
regular expression, in which case
|
||||
.Ar command
|
||||
will be executed for any program that matches the regular expression.
|
||||
.Sh BUILTIN COMMANDS
|
||||
The
|
||||
.Nm editline
|
||||
library has some builtin commands, which affect the way
|
||||
that the line editing and history functions operate.
|
||||
These are based on similar named builtins present in the
|
||||
.Xr tcsh 1
|
||||
shell.
|
||||
.Pp
|
||||
The following builtin commands are available:
|
||||
.Bl -tag -width 4n
|
||||
.It Ic bind Xo
|
||||
.Op Fl a
|
||||
.Op Fl e
|
||||
.Op Fl k
|
||||
.Op Fl l
|
||||
.Op Fl r
|
||||
.Op Fl s
|
||||
.Op Fl v
|
||||
.Op Ar key Op Ar command
|
||||
.Xc
|
||||
Without options, list all bound keys, and the editor command to which
|
||||
each is bound.
|
||||
If
|
||||
.Ar key
|
||||
is supplied, show the bindings for
|
||||
.Ar key .
|
||||
If
|
||||
.Ar key command
|
||||
is supplied, bind
|
||||
.Ar command
|
||||
to
|
||||
.Ar key .
|
||||
Options include:
|
||||
.Bl -tag -width 4n
|
||||
.It Fl e
|
||||
Bind all keys to the standard GNU Emacs-like bindings.
|
||||
.It Fl v
|
||||
Bind all keys to the standard
|
||||
.Xr vi 1 -like
|
||||
bindings.
|
||||
.It Fl a
|
||||
List or change key bindings in the
|
||||
.Xr vi 1
|
||||
mode alternate (command mode) key map.
|
||||
.It Fl k
|
||||
.Ar key
|
||||
is interpreted as a symbolic arrow key name, which may be one of
|
||||
.Sq up ,
|
||||
.Sq down ,
|
||||
.Sq left
|
||||
or
|
||||
.Sq right .
|
||||
.It Fl l
|
||||
List all editor commands and a short description of each.
|
||||
.It Fl r
|
||||
Remove a key's binding.
|
||||
.It Fl s
|
||||
.Ar command
|
||||
is taken as a literal string and treated as terminal input when
|
||||
.Ar key
|
||||
is typed.
|
||||
Bound keys in
|
||||
.Ar command
|
||||
are themselves reinterpreted, and this continues for ten levels of
|
||||
interpretation.
|
||||
.El
|
||||
.Pp
|
||||
.Ar key
|
||||
and
|
||||
.Ar command
|
||||
can contain control characters of the form
|
||||
.Sm off
|
||||
.Sq No ^ Ar character
|
||||
.Sm on
|
||||
.Po
|
||||
e.g.
|
||||
.Sq ^A
|
||||
.Pc ,
|
||||
and the following backslashed escape sequences:
|
||||
.Pp
|
||||
.Bl -tag -compact -offset indent -width 4n
|
||||
.It Ic \ea
|
||||
Bell
|
||||
.It Ic \eb
|
||||
Backspace
|
||||
.It Ic \ee
|
||||
Escape
|
||||
.It Ic \ef
|
||||
Formfeed
|
||||
.It Ic \en
|
||||
Newline
|
||||
.It Ic \er
|
||||
Carriage return
|
||||
.It Ic \et
|
||||
Horizontal tab
|
||||
.It Ic \ev
|
||||
Vertical tab
|
||||
.Sm off
|
||||
.It Sy \e Ar nnn
|
||||
.Sm on
|
||||
The ASCII character corresponding to the octal number
|
||||
.Ar nnn .
|
||||
.El
|
||||
.Pp
|
||||
.Sq \e
|
||||
nullifies the special meaning of the following character,
|
||||
if it has any, notably
|
||||
.Sq \e
|
||||
and
|
||||
.Sq ^ .
|
||||
.It Ic echotc Xo
|
||||
.Op Fl sv
|
||||
.Ar arg
|
||||
.Ar ...
|
||||
.Xc
|
||||
Exercise terminal capabilities given in
|
||||
.Ar arg Ar ... .
|
||||
If
|
||||
.Ar arg
|
||||
is
|
||||
.Sq baud ,
|
||||
.Sq cols ,
|
||||
.Sq lines ,
|
||||
.Sq rows ,
|
||||
.Sq meta or
|
||||
.Sq tabs ,
|
||||
the value of that capability is printed, with
|
||||
.Dq yes
|
||||
or
|
||||
.Dq no
|
||||
indicating that the terminal does or does not have that capability.
|
||||
.Pp
|
||||
.Fl s
|
||||
returns an emptry string for non-existant capabilities, rather than
|
||||
causing an error.
|
||||
.Fl v
|
||||
causes messages to be verbose.
|
||||
.It Ic history
|
||||
List the history.
|
||||
.It Ic telltc
|
||||
List the values of all the terminal capabilities (see
|
||||
.Xr termcap 5 ).
|
||||
.It Ic settc Ar cap Ar val
|
||||
Set the terminal capability
|
||||
.Ar cap
|
||||
to
|
||||
.Ar val ,
|
||||
as defined in
|
||||
.Xr termcap 5 .
|
||||
No sanity checking is done.
|
||||
.It Ic setty Xo
|
||||
.Op Fl a
|
||||
.Op Fl d
|
||||
.Op Fl q
|
||||
.Op Fl x
|
||||
.Op Ar +mode
|
||||
.Op Ar -mode
|
||||
.Op Ar mode
|
||||
.Xc
|
||||
Control which tty modes that
|
||||
.Nm
|
||||
won't allow the user to change.
|
||||
.Fl d ,
|
||||
.Fl q
|
||||
or
|
||||
.Fl x
|
||||
tells
|
||||
.Ic setty
|
||||
to act on the
|
||||
.Sq edit ,
|
||||
.Sq quote
|
||||
or
|
||||
.Sq execute
|
||||
set of tty modes respectively; defaulting to
|
||||
.Fl x .
|
||||
.Pp
|
||||
Without other arguments,
|
||||
.Ic setty
|
||||
lists the modes in the chosen set which are fixed on
|
||||
.Po
|
||||
.Sq +mode
|
||||
.Pc
|
||||
or off
|
||||
.Po
|
||||
.Sq -mode
|
||||
.Pc .
|
||||
.Fl a
|
||||
lists all tty modes in the chosen set regardless of the setting.
|
||||
With
|
||||
.Ar +mode ,
|
||||
.Ar -mode
|
||||
or
|
||||
.Ar mode ,
|
||||
fixes
|
||||
.Ar mode
|
||||
on or off or removes control of
|
||||
.Ar mode
|
||||
in the chosen set.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr editline 3 ,
|
||||
.Xr regex 3 ,
|
||||
.Xr termcap 5
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm editline
|
||||
library was written by Christos Zoulas,
|
||||
and this manual was written by Luke Mewburn,
|
||||
with some sections inspired by
|
||||
.Xr tcsh 1 .
|
343
el.c
Normal file
343
el.c
Normal file
@ -0,0 +1,343 @@
|
||||
/* $NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: el.c,v 1.6 1997/04/24 18:54:16 christos Exp $";
|
||||
#endif
|
||||
#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>
|
||||
#ifdef __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
|
||||
#ifdef __STDC__
|
||||
el_set(EditLine *el, int op, ...)
|
||||
#else
|
||||
el_set(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list va;
|
||||
int rv;
|
||||
#ifdef __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;
|
||||
(void)snprintf(path, sizeof(path), "%s%s", ptr, elpath);
|
||||
fname = path;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fp = fopen(fname, "r")) == NULL)
|
||||
return -1;
|
||||
|
||||
while ((ptr = fgetln(fp, &len)) != NULL) {
|
||||
if (ptr[len - 1] == '\n')
|
||||
--len;
|
||||
ptr[len] = '\0';
|
||||
if (parse_line(el, ptr) == -1) {
|
||||
(void) fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
(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);
|
||||
}
|
131
el.h
Normal file
131
el.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* $NetBSD: el.h,v 1.2 1997/01/11 06:47:53 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
510
emacs.c
Normal file
510
emacs.c
Normal file
@ -0,0 +1,510 @@
|
||||
/* $NetBSD: emacs.c,v 1.3 1997/01/11 06:47:54 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: emacs.c,v 1.3 1997/01/11 06:47:54 lukem Exp $";
|
||||
#endif
|
||||
#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);
|
||||
}
|
176
hist.c
Normal file
176
hist.c
Normal file
@ -0,0 +1,176 @@
|
||||
/* $NetBSD: hist.c,v 1.2 1997/01/11 06:47:55 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: hist.c,v 1.2 1997/01/11 06:47:55 lukem Exp $";
|
||||
#endif
|
||||
#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;
|
||||
}
|
79
hist.h
Normal file
79
hist.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* $NetBSD: hist.h,v 1.3 1997/01/11 06:47:56 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
|
||||
#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
|
||||
|
||||
protected int hist_init __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 */
|
178
histedit.h
Normal file
178
histedit.h
Normal file
@ -0,0 +1,178 @@
|
||||
/* $NetBSD: histedit.h,v 1.5 1997/04/11 17:52:45 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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.
|
||||
*
|
||||
* @(#)histedit.h 8.2 (Berkeley) 1/3/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* histedit.h: Line editor and history interface.
|
||||
*/
|
||||
#ifndef _h_editline
|
||||
#define _h_editline
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* ==== Editing ====
|
||||
*/
|
||||
typedef struct editline EditLine;
|
||||
|
||||
/*
|
||||
* For user-defined function interface
|
||||
*/
|
||||
typedef struct lineinfo {
|
||||
const char *buffer;
|
||||
const char *cursor;
|
||||
const char *lastchar;
|
||||
} LineInfo;
|
||||
|
||||
|
||||
/*
|
||||
* EditLine editor function return codes.
|
||||
* For user-defined function interface
|
||||
*/
|
||||
#define CC_NORM 0
|
||||
#define CC_NEWLINE 1
|
||||
#define CC_EOF 2
|
||||
#define CC_ARGHACK 3
|
||||
#define CC_REFRESH 4
|
||||
#define CC_CURSOR 5
|
||||
#define CC_ERROR 6
|
||||
#define CC_FATAL 7
|
||||
#define CC_REDISPLAY 8
|
||||
|
||||
/*
|
||||
* Initialization, cleanup, and resetting
|
||||
*/
|
||||
EditLine *el_init __P((const char *, FILE *, FILE *));
|
||||
void el_reset __P((EditLine *));
|
||||
void el_end __P((EditLine *));
|
||||
|
||||
|
||||
/*
|
||||
* Get a line, a character or push a string back in the input queue
|
||||
*/
|
||||
const char *el_gets __P((EditLine *, int *));
|
||||
int el_getc __P((EditLine *, char *));
|
||||
void el_push __P((EditLine *, const char *));
|
||||
|
||||
/*
|
||||
* High level function internals control
|
||||
* Parses argc, argv array and executes builtin editline commands
|
||||
*/
|
||||
int el_parse __P((EditLine *, int, char **));
|
||||
|
||||
/*
|
||||
* Low level editline access function
|
||||
*/
|
||||
int el_set __P((EditLine *, int, ...));
|
||||
|
||||
/*
|
||||
* el_set/el_get parameters
|
||||
*/
|
||||
#define EL_PROMPT 0 /* , el_pfunc_t); */
|
||||
#define EL_TERMINAL 1 /* , const char *); */
|
||||
#define EL_EDITOR 2 /* , const char *); */
|
||||
#define EL_SIGNAL 3 /* , int); */
|
||||
#define EL_BIND 4 /* , const char *, ..., NULL); */
|
||||
#define EL_TELLTC 5 /* , const char *, ..., NULL); */
|
||||
#define EL_SETTC 6 /* , const char *, ..., NULL); */
|
||||
#define EL_ECHOTC 7 /* , const char *, ..., NULL); */
|
||||
#define EL_SETTY 8 /* , const char *, ..., NULL); */
|
||||
#define EL_ADDFN 9 /* , const char *, const char * */
|
||||
/* , el_func_t); */
|
||||
#define EL_HIST 10 /* , hist_fun_t, const char *); */
|
||||
|
||||
/*
|
||||
* Source named file or $PWD/.editrc or $HOME/.editrc
|
||||
*/
|
||||
int el_source __P((EditLine *, const char *));
|
||||
|
||||
/*
|
||||
* Must be called when the terminal changes size; If EL_SIGNAL
|
||||
* is set this is done automatically otherwise it is the responsibility
|
||||
* of the application
|
||||
*/
|
||||
void el_resize __P((EditLine *));
|
||||
|
||||
|
||||
/*
|
||||
* User-defined function interface.
|
||||
*/
|
||||
const LineInfo *el_line __P((EditLine *));
|
||||
int el_insertstr __P((EditLine *, char *));
|
||||
void el_deletestr __P((EditLine *, int));
|
||||
|
||||
/*
|
||||
* ==== History ====
|
||||
*/
|
||||
|
||||
typedef struct history History;
|
||||
|
||||
typedef struct HistEvent {
|
||||
int num;
|
||||
const char *str;
|
||||
} HistEvent;
|
||||
|
||||
/*
|
||||
* History access functions.
|
||||
*/
|
||||
History * history_init __P((void));
|
||||
void history_end __P((History *));
|
||||
|
||||
const HistEvent * history __P((History *, int, ...));
|
||||
|
||||
#define H_FUNC 0 /* , UTSL */
|
||||
#define H_EVENT 1 /* , const int); */
|
||||
#define H_FIRST 2 /* , void); */
|
||||
#define H_LAST 3 /* , void); */
|
||||
#define H_PREV 4 /* , void); */
|
||||
#define H_NEXT 5 /* , void); */
|
||||
#define H_CURR 6 /* , void); */
|
||||
#define H_ADD 7 /* , const char*); */
|
||||
#define H_ENTER 8 /* , const char*); */
|
||||
#define H_END 9 /* , void); */
|
||||
#define H_NEXT_STR 10 /* , const char*); */
|
||||
#define H_PREV_STR 11 /* , const char*); */
|
||||
#define H_NEXT_EVENT 12 /* , const int); */
|
||||
#define H_PREV_EVENT 13 /* , const int); */
|
||||
#define H_LOAD 14 /* , const char *); */
|
||||
#define H_SAVE 15 /* , const char *); */
|
||||
#define H_CLEAR 16 /* , void); */
|
||||
|
||||
#endif /* _h_editline */
|
692
history.c
Normal file
692
history.c
Normal file
@ -0,0 +1,692 @@
|
||||
/* $NetBSD: history.c,v 1.5 1997/04/11 17:52:46 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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>
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
static const char hist_cookie[] = "_HiStOrY_V1_\n";
|
||||
|
||||
#include "histedit.h"
|
||||
|
||||
typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
|
||||
typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
|
||||
typedef void (*history_vfun_t) __P((ptr_t));
|
||||
|
||||
struct history {
|
||||
ptr_t h_ref; /* Argument for history fcns */
|
||||
history_gfun_t h_first; /* Get the first element */
|
||||
history_gfun_t h_next; /* Get the next element */
|
||||
history_gfun_t h_last; /* Get the last element */
|
||||
history_gfun_t h_prev; /* Get the previous element */
|
||||
history_gfun_t h_curr; /* Get the current element */
|
||||
history_vfun_t h_clear; /* Clear the history list */
|
||||
history_efun_t h_enter; /* Add an element */
|
||||
history_efun_t h_add; /* Append to an element */
|
||||
};
|
||||
|
||||
#define HNEXT(h) (*(h)->h_next)((h)->h_ref)
|
||||
#define HFIRST(h) (*(h)->h_first)((h)->h_ref)
|
||||
#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
|
||||
#define HLAST(h) (*(h)->h_last)((h)->h_ref)
|
||||
#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
|
||||
#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
|
||||
#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
|
||||
#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
|
||||
|
||||
#define h_malloc(a) malloc(a)
|
||||
#define h_free(a) free(a)
|
||||
|
||||
|
||||
private int history_set_num __P((History *, int));
|
||||
private int history_set_fun __P((History *, History *));
|
||||
private int history_load __P((History *, const char *));
|
||||
private int history_save __P((History *, const char *));
|
||||
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_clear __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); /* XXX strcpy is safe */
|
||||
(void)strcat(s, str); /* XXX strcat is safe */
|
||||
h_free((ptr_t) h->cursor->ev.str);
|
||||
h->cursor->ev.str = s;
|
||||
return &h->cursor->ev;
|
||||
}
|
||||
|
||||
|
||||
/* history_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_clear():
|
||||
* Default history cleanup function
|
||||
*/
|
||||
private void
|
||||
history_def_clear(p)
|
||||
ptr_t p;
|
||||
{
|
||||
history_t *h = (history_t *) p;
|
||||
|
||||
while (h->list.prev != &h->list)
|
||||
history_def_delete(h, h->list.prev);
|
||||
h->eventno = 0;
|
||||
h->cur = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/* 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_clear = history_def_clear;
|
||||
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_clear(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, nh)
|
||||
History *h, *nh;
|
||||
{
|
||||
if (nh->h_first == NULL || nh->h_next == NULL ||
|
||||
nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL ||
|
||||
nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
|
||||
nh->h_ref == NULL) {
|
||||
if (h->h_next != history_def_next) {
|
||||
history_def_init(&h->h_ref, 0);
|
||||
h->h_first = history_def_first;
|
||||
h->h_next = history_def_next;
|
||||
h->h_last = history_def_last;
|
||||
h->h_prev = history_def_prev;
|
||||
h->h_curr = history_def_curr;
|
||||
h->h_clear = history_def_clear;
|
||||
h->h_enter = history_def_enter;
|
||||
h->h_add = history_def_add;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->h_next == history_def_next)
|
||||
history_def_clear(h->h_ref);
|
||||
|
||||
h->h_first = nh->h_first;
|
||||
h->h_next = nh->h_next;
|
||||
h->h_last = nh->h_last;
|
||||
h->h_prev = nh->h_prev;
|
||||
h->h_curr = nh->h_curr;
|
||||
h->h_clear = nh->h_clear;
|
||||
h->h_enter = nh->h_enter;
|
||||
h->h_add = nh->h_add;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* history_load():
|
||||
* History load function
|
||||
*/
|
||||
private int
|
||||
history_load(h, fname)
|
||||
History *h;
|
||||
const char *fname;
|
||||
{
|
||||
FILE *fp;
|
||||
char *line;
|
||||
size_t sz;
|
||||
int i = -1;
|
||||
|
||||
if ((fp = fopen(fname, "r")) == NULL)
|
||||
return i;
|
||||
|
||||
if ((line = fgetln(fp, &sz)) == NULL)
|
||||
goto done;
|
||||
|
||||
if (strncmp(line, hist_cookie, sz) != 0)
|
||||
goto done;
|
||||
|
||||
for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
|
||||
char c = line[sz];
|
||||
line[sz] = '\0';
|
||||
HENTER(h, line);
|
||||
line[sz] = c;
|
||||
}
|
||||
|
||||
done:
|
||||
(void) fclose(fp);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* history_save():
|
||||
* History save function
|
||||
*/
|
||||
private int
|
||||
history_save(h, fname)
|
||||
History *h;
|
||||
const char *fname;
|
||||
{
|
||||
FILE *fp;
|
||||
const HistEvent *ev;
|
||||
int i = 0;
|
||||
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
return -1;
|
||||
|
||||
(void) fputs(hist_cookie, fp);
|
||||
for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
|
||||
(void) fprintf(fp, "%s", ev->str);
|
||||
(void) fclose(fp);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* 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 *
|
||||
#ifdef __STDC__
|
||||
history(History *h, int fun, ...)
|
||||
#else
|
||||
history(va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list va;
|
||||
const HistEvent *ev = NULL;
|
||||
const char *str;
|
||||
static HistEvent sev = { 0, "" };
|
||||
|
||||
#ifdef __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_CLEAR:
|
||||
HCLEAR(h);
|
||||
break;
|
||||
|
||||
case H_LOAD:
|
||||
sev.num = history_load(h, va_arg(va, const char *));
|
||||
ev = &sev;
|
||||
break;
|
||||
|
||||
case H_SAVE:
|
||||
sev.num = history_save(h, va_arg(va, const char *));
|
||||
ev = &sev;
|
||||
break;
|
||||
|
||||
case H_PREV_EVENT:
|
||||
ev = history_prev_event(h, va_arg(va, int));
|
||||
break;
|
||||
|
||||
case H_NEXT_EVENT:
|
||||
ev = history_next_event(h, va_arg(va, int));
|
||||
break;
|
||||
|
||||
case H_PREV_STR:
|
||||
ev = history_prev_string(h, va_arg(va, const char*));
|
||||
break;
|
||||
|
||||
case H_NEXT_STR:
|
||||
ev = history_next_string(h, va_arg(va, const char*));
|
||||
break;
|
||||
|
||||
case H_EVENT:
|
||||
if (history_set_num(h, va_arg(va, int)) == 0) {
|
||||
sev.num = -1;
|
||||
ev = &sev;
|
||||
}
|
||||
break;
|
||||
|
||||
case H_FUNC:
|
||||
{
|
||||
History hf;
|
||||
hf.h_ref = va_arg(va, ptr_t);
|
||||
hf.h_first = va_arg(va, history_gfun_t);
|
||||
hf.h_next = va_arg(va, history_gfun_t);
|
||||
hf.h_last = va_arg(va, history_gfun_t);
|
||||
hf.h_prev = va_arg(va, history_gfun_t);
|
||||
hf.h_curr = va_arg(va, history_gfun_t);
|
||||
hf.h_clear = va_arg(va, history_vfun_t);
|
||||
hf.h_enter = va_arg(va, history_efun_t);
|
||||
hf.h_add = va_arg(va, history_efun_t);
|
||||
|
||||
if (history_set_fun(h, &hf) == 0) {
|
||||
sev.num = -1;
|
||||
ev = &sev;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case H_END:
|
||||
history_end(h);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
va_end(va);
|
||||
return ev;
|
||||
}
|
732
key.c
Normal file
732
key.c
Normal file
@ -0,0 +1,732 @@
|
||||
/* $NetBSD: key.c,v 1.2 1997/01/11 06:47:58 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: key.c,v 1.2 1997/01/11 06:47:58 lukem Exp $";
|
||||
#endif
|
||||
#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 */
|
||||
}
|
82
key.h
Normal file
82
key.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* $NetBSD: key.h,v 1.2 1997/01/11 06:47:59 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
185
makelist
Normal file
185
makelist
Normal file
@ -0,0 +1,185 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: makelist,v 1.3 1997/01/11 06:48:00 lukem Exp $
|
||||
#
|
||||
# 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)
|
||||
set - `echo $FILES | sed -e 's/\\./_/g'`
|
||||
hdr="_h_`basename $1`"
|
||||
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
|
79
map.h
Normal file
79
map.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* $NetBSD: map.h,v 1.2 1997/01/11 06:48:01 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
255
parse.c
Normal file
255
parse.c
Normal file
@ -0,0 +1,255 @@
|
||||
/* $NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: parse.c,v 1.5 1997/01/11 09:57:08 lukem Exp $";
|
||||
#endif
|
||||
#endif /* not lint && not SCCSID */
|
||||
|
||||
/*
|
||||
* parse.c: parse an editline extended command
|
||||
*
|
||||
* commands are:
|
||||
*
|
||||
* bind
|
||||
* echotc
|
||||
* gettc
|
||||
* history
|
||||
* settc
|
||||
* setty
|
||||
*/
|
||||
#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 -1;
|
||||
ptr = strchr(argv[0], ':');
|
||||
if (ptr != NULL) {
|
||||
*ptr++ = '\0';
|
||||
if (! el_match(el->el_prog, argv[0]))
|
||||
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[1])) {
|
||||
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;
|
||||
}
|
52
parse.h
Normal file
52
parse.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* $NetBSD: parse.h,v 1.2 1997/01/11 06:48:03 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
129
prompt.c
Normal file
129
prompt.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* $NetBSD: prompt.c,v 1.2 1997/01/11 06:48:04 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: prompt.c,v 1.2 1997/01/11 06:48:04 lukem Exp $";
|
||||
#endif
|
||||
#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 */
|
61
prompt.h
Normal file
61
prompt.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* $NetBSD: prompt.h,v 1.2 1997/01/11 06:48:05 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
452
read.c
Normal file
452
read.c
Normal file
@ -0,0 +1,452 @@
|
||||
/* $NetBSD: read.c,v 1.4 1997/04/11 17:52:47 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: read.c,v 1.4 1997/04/11 17:52:47 christos Exp $";
|
||||
#endif
|
||||
#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:
|
||||
# ifndef TRY_AGAIN
|
||||
# define TRY_AGAIN
|
||||
# endif
|
||||
#endif /* EWOULDBLOCK */
|
||||
|
||||
#if defined(POSIX) && defined(EAGAIN)
|
||||
# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
||||
case EAGAIN:
|
||||
# ifndef TRY_AGAIN
|
||||
# define TRY_AGAIN
|
||||
# endif
|
||||
# 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_REDISPLAY:
|
||||
re_clear_lines(el);
|
||||
re_clear_display(el);
|
||||
/* FALLTHROUGH */
|
||||
|
||||
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;
|
||||
}
|
62
refresh.h
Normal file
62
refresh.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* $NetBSD: refresh.h,v 1.2 1997/01/11 06:48:08 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
640
search.c
Normal file
640
search.c
Normal file
@ -0,0 +1,640 @@
|
||||
/* $NetBSD: search.c,v 1.4 1997/01/23 14:02:47 mrg Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: search.c,v 1.4 1997/01/23 14:02:47 mrg Exp $";
|
||||
#endif
|
||||
#endif /* not lint && not SCCSID */
|
||||
|
||||
/*
|
||||
* search.c: History and character search functions
|
||||
*/
|
||||
#include "sys.h"
|
||||
#include <stdlib.h>
|
||||
#if defined(REGEX)
|
||||
#include <regex.h>
|
||||
#elif defined(REGEXP)
|
||||
#include <regexp.h>
|
||||
#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;
|
||||
{
|
||||
#if defined (REGEX)
|
||||
regex_t re;
|
||||
int rv;
|
||||
#elif defined (REGEXP)
|
||||
regexp *rp;
|
||||
int rv;
|
||||
#else
|
||||
extern char *re_comp __P((const char *));
|
||||
extern int re_exec __P((const char *));
|
||||
#endif
|
||||
|
||||
if (strstr(str, pat) != NULL)
|
||||
return 1;
|
||||
|
||||
#if defined(REGEX)
|
||||
if (regcomp(&re, pat, 0) == 0) {
|
||||
rv = regexec(&re, str, 0, NULL, 0) == 0;
|
||||
regfree(&re);
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
return rv;
|
||||
#elif defined(REGEXP)
|
||||
if ((re = regcomp(pat)) != NULL) {
|
||||
rv = regexec(re, str);
|
||||
free((ptr_t) re);
|
||||
} else {
|
||||
rv = 0;
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
if (re_comp(pat) != NULL)
|
||||
return 0;
|
||||
else
|
||||
return re_exec(str) == 1;
|
||||
#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)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1);
|
||||
el->el_search.patbuf[0] = '.';
|
||||
el->el_search.patbuf[1] = '*';
|
||||
(void)strncpy(&el->el_search.patbuf[2], tmpbuf,
|
||||
sizeof(el->el_search.patbuf) - 3);
|
||||
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)strncpy(el->el_search.patbuf, tmpbuf,
|
||||
sizeof(el->el_search.patbuf) - 1);
|
||||
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;
|
||||
}
|
70
search.h
Normal file
70
search.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* $NetBSD: search.h,v 1.2 1997/01/11 06:48:09 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
2
shlib_version
Normal file
2
shlib_version
Normal file
@ -0,0 +1,2 @@
|
||||
major=0
|
||||
minor=0
|
199
sig.c
Normal file
199
sig.c
Normal file
@ -0,0 +1,199 @@
|
||||
/* $NetBSD: sig.c,v 1.3 1997/04/11 17:52:48 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: sig.c,v 1.3 1997/04/11 17:52:48 christos Exp $";
|
||||
#endif
|
||||
#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] = SIG_ERR;
|
||||
|
||||
(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] != SIG_ERR)
|
||||
(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);
|
||||
}
|
72
sig.h
Normal file
72
sig.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* $NetBSD: sig.h,v 1.2 1997/01/11 06:48:11 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
118
sys.h
Normal file
118
sys.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* $NetBSD: sys.h,v 1.3 1997/01/11 06:48:12 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 REGEX /* Use POSIX.2 regular expression functions */
|
||||
#undef REGEXP /* Use UNIX V8 regular expression functions */
|
||||
|
||||
#ifdef SUNOS
|
||||
# undef REGEX
|
||||
# undef REGEXP
|
||||
# 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 */
|
120
term.h
Normal file
120
term.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* $NetBSD: term.h,v 1.4 1997/01/11 06:48:14 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 void 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 */
|
54
termcap.h
Normal file
54
termcap.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* $NetBSD: termcap.h,v 1.2 1997/01/11 06:48:14 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
391
tokenizer.c
Normal file
391
tokenizer.c
Normal file
@ -0,0 +1,391 @@
|
||||
/* $NetBSD: tokenizer.c,v 1.2 1997/01/11 06:48:15 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: tokenizer.c,v 1.2 1997/01/11 06:48:15 lukem Exp $";
|
||||
#endif
|
||||
#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*));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
55
tokenizer.h
Normal file
55
tokenizer.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* $NetBSD: tokenizer.h,v 1.2 1997/01/11 06:48:16 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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 */
|
483
tty.h
Normal file
483
tty.h
Normal file
@ -0,0 +1,483 @@
|
||||
/* $NetBSD: tty.h,v 1.4 1997/04/11 21:38:02 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* 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__ */
|
||||
|
||||
/*
|
||||
* So that we don't lose job control.
|
||||
*/
|
||||
#ifdef __SVR4
|
||||
# undef CSWTCH
|
||||
#endif
|
||||
|
||||
#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;
|
||||
u_int t_setmask;
|
||||
u_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 */
|
992
vi.c
Normal file
992
vi.c
Normal file
@ -0,0 +1,992 @@
|
||||
/* $NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* 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)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
|
||||
#else
|
||||
static char rcsid[] = "$NetBSD: vi.c,v 1.2 1997/01/11 06:48:19 lukem Exp $";
|
||||
#endif
|
||||
#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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user