3 Commits

Author SHA1 Message Date
Serge Vakulenko
f33305f894 Levee editor compiled for RetroBSD. 2015-01-06 13:42:43 -08:00
Serge Vakulenko
e834303650 Levee editor compiled on Linux. 2015-01-06 12:58:23 -08:00
Serge Vakulenko
476573dae6 Imported levee editor sources from http://www.pell.portland.or.us/~orc/Code/levee/levee-3.5a.tar.gz 2015-01-06 12:54:38 -08:00
42 changed files with 10782 additions and 1 deletions

View File

@@ -241,6 +241,7 @@ file /bin/login
mode 04755 mode 04755
file /bin/lol file /bin/lol
file /bin/ls file /bin/ls
file /bin/lv
file /bin/mail file /bin/mail
mode 04755 mode 04755
file /bin/make file /bin/make
@@ -781,6 +782,7 @@ file /share/man/cat1/id.0
file /share/man/cat1/la.0 file /share/man/cat1/la.0
file /share/man/cat1/lcc.0 file /share/man/cat1/lcc.0
file /share/man/cat1/ld.0 file /share/man/cat1/ld.0
file /share/man/cat1/lv.0
file /share/man/cat1/passwd.0 file /share/man/cat1/passwd.0
file /share/man/cat1/printf.0 file /share/man/cat1/printf.0
file /share/man/cat1/ranlib.0 file /share/man/cat1/ranlib.0

View File

@@ -12,7 +12,7 @@ CFLAGS += -Werror
# /bin # /bin
SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \ SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \
cpp dc diff emg env fdisk find forth fstat glcdtest \ cpp dc diff emg env fdisk find forth fstat glcdtest \
hostname id la lcc lcpp ld ls login make man med \ hostname id la lcc lcpp ld levee ls login make man med \
more nm passwd picoc portio printf pwm \ more nm passwd picoc portio printf pwm \
rdprof ranlib re renice retroforth scm setty sl \ rdprof ranlib re renice retroforth scm setty sl \
sed sh smallc smlrc stty sysctl test uname wiznet xargs \ sed sh smallc smlrc stty sysctl test uname wiznet xargs \

1
src/cmd/levee/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
lv

56
src/cmd/levee/Makefile Normal file
View File

@@ -0,0 +1,56 @@
#
# Public Domain. 1995/03/13 - Steven Schultz
#
TOPSRC = $(shell cd ../../..; pwd)
include $(TOPSRC)/target.mk
#CFLAGS += -Werror
LIBS += -ltermcap
OBJS = blockio.o display.o editcor.o exec.o find.o \
unixcall.o globals.o insert.o main.o misc.o \
modify.o move.o ucsd.o undo.o wildargs.o \
version.o
MAN = lv.0
all: lv ${MAN}
lv: ${OBJS}
${CC} ${LDFLAGS} -o lv.elf ${OBJS} ${LIBS}
${OBJDUMP} -S lv.elf > lv.dis
${SIZE} lv.elf
${ELF2AOUT} lv.elf $@ && rm lv.elf
version.o: version.c VERSION
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
.SUFFIXES: .0 .1
.1.0:
${MANROFF} $*.1 > $@
clean:
rm -f *.o *.elf ${MAN} lv *.elf *.dis tags *~
install: all
install lv ${DESTDIR}/bin/
cp lv.0 ${DESTDIR}/share/man/cat1/
# Dependencies
blockio.o : levee.h extern.h blockio.c config.h
display.o : levee.h extern.h termcap.i display.c config.h
editcor.o : levee.h extern.h editcor.c config.h
exec.o : levee.h extern.h exec.c config.h
find.o : levee.h extern.h grep.h find.c config.h
globals.o : levee.h globals.c config.h
insert.o : levee.h extern.h insert.c config.h
main.o : levee.h extern.h main.c config.h
misc.o : levee.h extern.h misc.c config.h
modify.o : levee.h extern.h grep.h modify.c config.h
move.o : levee.h extern.h move.c config.h
rmxcall.o : levee.h rmxcall.c config.h
ucsd.o : levee.h extern.h ucsd.c config.h
undo.o : levee.h extern.h undo.c config.h
unixcall.o : levee.h extern.h unixcall.c config.h
wildargs.o : levee.h extern.h wildargs.c config.h

View File

@@ -0,0 +1,56 @@
# makefile for Levee
exedir=/usr/local/bin
mandir=/usr/local/man
CC=cc
CFLAGS=-g
LDFLAGS=-g
OBJS = blockio.o display.o editcor.o exec.o find.o \
unixcall.o globals.o insert.o main.o misc.o \
modify.o move.o ucsd.o undo.o wildargs.o \
version.o
lev: $(OBJS)
$(CC) $(LDFLAGS) -o lev $(OBJS) -lcurses
version.o: version.c VERSION
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
clean:
rm -f *.o lev
distclean spotless: clean
rm -f Makefile config.cmd config.sub config.h config.mak config.log config.md
install: install.bin install.man
install.bin: lev
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(exedir)
/usr/bin/install -s -m 755 lev $(PREFIX)$(exedir)/levee
/bin/ln -s -f levee $(PREFIX)$(exedir)/lv
install.man:
/home/sergev/Daily/workdir-2015-01-06/levee-3.5a/config.md $(PREFIX)$(mandir)/man1
/usr/bin/install -m 444 lv.1 $(PREFIX)$(mandir)/man1/levee.1
echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
# Dependencies
blockio.o : levee.h extern.h blockio.c config.h
display.o : levee.h extern.h termcap.i display.c config.h
editcor.o : levee.h extern.h editcor.c config.h
exec.o : levee.h extern.h exec.c config.h
find.o : levee.h extern.h grep.h find.c config.h
globals.o : levee.h globals.c config.h
insert.o : levee.h extern.h insert.c config.h
main.o : levee.h extern.h main.c config.h
misc.o : levee.h extern.h misc.c config.h
modify.o : levee.h extern.h grep.h modify.c config.h
move.o : levee.h extern.h move.c config.h
rmxcall.o : levee.h rmxcall.c config.h
ucsd.o : levee.h extern.h ucsd.c config.h
undo.o : levee.h extern.h undo.c config.h
unixcall.o : levee.h extern.h unixcall.c config.h
wildargs.o : levee.h extern.h wildargs.c config.h

56
src/cmd/levee/Makefile.in Normal file
View File

@@ -0,0 +1,56 @@
# makefile for Levee
exedir=@exedir@
mandir=@mandir@
CC=@CC@
CFLAGS=@CFLAGS@
LDFLAGS=@LDFLAGS@
OBJS = blockio.o display.o editcor.o exec.o find.o \
unixcall.o globals.o insert.o main.o misc.o \
modify.o move.o ucsd.o undo.o wildargs.o \
version.o
lev: $(OBJS)
$(CC) $(LDFLAGS) -o lev $(OBJS) @LIBS@
version.o: version.c VERSION
$(CC) $(CFLAGS) -c -DVERSION=\"`cat VERSION`\" version.c
clean:
rm -f *.o lev
distclean spotless: clean
rm -f @GENERATED_FILES@ @CONFIGURE_FILES@
install: install.bin install.man
install.bin: lev
@INSTALL_DIR@ $(PREFIX)$(exedir)
@INSTALL_PROGRAM@ lev $(PREFIX)$(exedir)/levee
@NOMK@@LN_S@ -f levee $(PREFIX)$(exedir)/lv
install.man:
@INSTALL_DIR@ $(PREFIX)$(mandir)/man1
@INSTALL_DATA@ lv.1 $(PREFIX)$(mandir)/man1/levee.1
@NOMK@echo ".so man1/levee.1" > $(PREFIX)$(mandir)/man1/lv.1
# Dependencies
blockio.o : levee.h extern.h blockio.c config.h
display.o : levee.h extern.h termcap.i display.c config.h
editcor.o : levee.h extern.h editcor.c config.h
exec.o : levee.h extern.h exec.c config.h
find.o : levee.h extern.h grep.h find.c config.h
globals.o : levee.h globals.c config.h
insert.o : levee.h extern.h insert.c config.h
main.o : levee.h extern.h main.c config.h
misc.o : levee.h extern.h misc.c config.h
modify.o : levee.h extern.h grep.h modify.c config.h
move.o : levee.h extern.h move.c config.h
rmxcall.o : levee.h rmxcall.c config.h
ucsd.o : levee.h extern.h ucsd.c config.h
undo.o : levee.h extern.h undo.c config.h
unixcall.o : levee.h extern.h unixcall.c config.h
wildargs.o : levee.h extern.h wildargs.c config.h

1
src/cmd/levee/VERSION Normal file
View File

@@ -0,0 +1 @@
3.5a

48
src/cmd/levee/beep.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#if OS_ATARI
#include <atari\osbind.h>
char sound[] = {
0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
0xF8,0x10,0x10,0x10,0x00,0x20,0x03
};
#define SADDR 0xFF8800L
typedef char srdef[4];
srdef *SOUND = (srdef *)SADDR;
main()
{
register i;
long ssp;
ssp = Super(0L);
for (i=0; i<sizeof(sound); i++) {
(*SOUND)[0] = i;
(*SOUND)[2] = sound[i];
}
Super(ssp);
}
#endif /*OS_ATARI*/

50
src/cmd/levee/blockio.c Normal file
View File

@@ -0,0 +1,50 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
/* read in a file -- return TRUE -- read file
FALSE-- file too big
*/
int PROC
addfile(f, start, endd, size)
FILE *f;
int start;
int endd, *size;
{
register int chunk;
chunk = read(fileno(f), core+start, (endd-start)-1);
*size = chunk;
return chunk < (endd-start)-1;
}
/* write out a file -- return TRUE if ok. */
bool PROC
putfile(f, start, endd)
register FILE *f;
register int start, endd;
{
return write(fileno(f), core+start, endd-start) == (endd-start);
}

26
src/cmd/levee/config.h Normal file
View File

@@ -0,0 +1,26 @@
/*
* configuration for levee, generated Tue Jan 6 12:41:26 PST 2015
* by sergev@ubuntu-sergev
*/
#ifndef __AC_LEVEE_D
#define __AC_LEVEE_D 1
// Size of editor data buffer.
#define SIZE 16000
#define OS_UNIX 1
#define HAVE_STRING_H 1
#define HAVE_MEMSET 1
#define HAVE_STRCHR 1
#define HAVE_BASENAME 1
#define HAVE_SIGNAL_H 1
#define HAVE_SIGNAL 1
#define HAVE_TGETENT 1
#define USE_TERMCAP 1
#define HAVE_MVCUR 1
#define mvcur __mvcur
#define HAVE_TCGETATTR 1
#define PATH_FIND "/bin/find"
#define PATH_SED "/bin/sed"
#endif/* __AC_LEVEE_D */

1219
src/cmd/levee/configure.inc Executable file

File diff suppressed because it is too large Load Diff

112
src/cmd/levee/configure.sh Executable file
View File

@@ -0,0 +1,112 @@
#! /bin/sh
# local options: ac_help is the help message that describes them
# and LOCAL_AC_OPTIONS is the script that interprets them. LOCAL_AC_OPTIONS
# is a script that's processed with eval, so you need to be very careful to
# make certain that what you quote is what you want to quote.
ac_help="
--use-termcap Link with termcap instead of curses, if possible
--partial-install Don\'t install the lv, lv(1) name links
--size=NNN Use a NNN-byte edit buffer
--dos compile for ms-dos or microsoft windows
--tos compile for the Atari ST
--rmx compile for RMX
--flexos compile for FlexOS"
LOCAL_AC_OPTIONS='
case Z$1 in
Z--partial-install)
missing_lv=1;;
Z--dos) ac_os=DOS;;
Z--tos) ac_os=ATARI=1;;
Z--flexos) ac_os=FLEXOS=1;;
Z--rmx) ac_os=RMX;;
Z--size=*) SIZE=$(echo Z$1 | sed -e 's/^Z--size=//') ;;
*) ac_error=1;;
esac;shift'
# load in the configuration file
#
TARGET=levee
. ./configure.inc
AC_INIT $TARGET
# validate --size=
#
case X"${SIZE}" in
X[0-9][0-9]*) ;;
X[0-9][0-9]*[Ll]);;
X) ;;
X*) AC_FAIL "--size=$SIZE is not a valid number" ;;
esac
AC_PROG_CC
if [ "$OS_DOS" ]; then
AC_DEFINE SIZE ${SIZE:-32000}
AC_DEFINE PROC _fastcall
AC_DEFINE TTY_ANSI 1
AC_CHECK_FUNCS basename
elif [ "$OS_ATARI" ]; then
AC_DEFINE SIZE ${SIZE:-32000}
AC_DEFINE TTY_VT52 1
AC_DEFINE HAVE_BLKFILL 1
AC_CHECK_FUNCS basename
elif [ "$OS_FLEXOS" ]; then
AC_DEFINE SIZE ${SIZE:-256000}
AC_CHECK_FUNCS basename
else
AC_DEFINE SIZE ${SIZE:-256000}
AC_DEFINE OS_UNIX 1
if AC_CHECK_HEADERS string.h; then
# Assume a mainly ANSI-compliant world, where the
# existance of string.h implies a memset() and strchr()
AC_DEFINE HAVE_MEMSET 1
AC_DEFINE HAVE_STRCHR 1
else
AC_CHECK_FUNCS memset
AC_CHECK_FUNCS strchr
fi
# for basename
if AC_CHECK_FUNCS basename; then
AC_CHECK_HEADERS libgen.h
fi
if AC_CHECK_HEADERS signal.h; then
# Assume a mainly sane world where the existance
# of signal.h means that signal() exists
AC_DEFINE HAVE_SIGNAL 1
fi
if [ "$USE_TERMCAP" ]; then
LIBORDER="-ltermcap -lcurses -lncurses"
else
LIBORDER="-lcurses -lncurses -ltermcap"
fi
if AC_LIBRARY tgetent $LIBORDER; then
AC_CHECK_HEADERS termcap.h || AC_FAIL "levee needs <termcap.h>"
AC_DEFINE USE_TERMCAP 1
# our -libtermcap might be (n)curses in disguise. If so,
# it might have a colliding mvcur() that we need to define
# ourselves out from.
AC_QUIET AC_CHECK_FUNCS mvcur && AC_DEFINE mvcur __mvcur
else
# have to use a local termcap
AC_DEFINE TERMCAP_EMULATION 1
AC_DEFINE USE_TERMCAP 1
fi
AC_CHECK_HEADERS termios.h && AC_CHECK_FUNCS tcgetattr
fi
if AC_PROG_LN_S && test -z "$missing_lv"; then
AC_SUB NOMK ''
else
AC_SUB NOMK '@#'
fi
AC_OUTPUT Makefile

349
src/cmd/levee/display.c Normal file
View File

@@ -0,0 +1,349 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
/* do a gotoXY -- allowing -1 for same row/column */
#if USE_TERMCAP | OS_ATARI
#define MAXCOLS 160
#if USE_TERMCAP
#include "termcap.i"
#endif
#else /*!(USE_TERMCAP | OS_ATARI)*/
#define MAXCOLS COLS
#endif
VOID PROC
mvcur(y,x)
int y,x;
{
#if TERMCAP_EMULATION || TTY_ANSI
static char gt[30];
#endif
if (y == -1)
y = curpos.y;
else
curpos.y = y;
if (y >= LINES)
y = LINES-1;
if (x == -1)
x = curpos.x;
else
curpos.x = x;
if (x >= COLS)
x = COLS-1;
#if TERMCAP_EMULATION
tgoto(gt,y,x);
strput(gt);
#elif USE_TERMCAP
strput( tgoto(CM, x, y) );
#elif TTY_ZTERM
zgoto(x,y);
#elif TTY_ANSI
{ register char *p = gt; /* make a ansi gotoXY string */
*p++ = 033;
*p++ = '[';
numtoa(p,1+y); p += strlen(p);
*p++ = ';';
numtoa(p,1+x); p += strlen(p);
*p++ = 'H';
WRITE_TEXT(1, gt, (p-gt));
}
#elif TTY_VT52
CM[2] = y+32;
CM[3] = x+32;
strput(CM);
#endif
}
VOID PROC
numtoa(str,num)
char *str;
int num;
{
int i = 10; /* I sure hope that str is 10 bytes long... */
bool neg = (num < 0);
if (neg)
num = -num;
str[--i] = 0;
do{
str[--i] = (num%10)+'0';
num /= 10;
}while (num > 0);
if (neg)
str[--i] = '-';
moveleft(&str[i], str, 10-i);
}
VOID PROC
printi(num)
int num;
{
char nb[10];
register int size;
numtoa(nb,num);
size = min(strlen(nb),COLS-curpos.x);
if (size > 0) {
nb[size] = 0;
zwrite(nb, size);
curpos.x += size;
}
}
VOID PROC
println()
{
zwrite("\r\n", 2);
curpos.x = 0;
curpos.y = min(curpos.y+1, LINES-1);
}
/* print a character out in a readable form --
* ^<x> for control-<x>
* spaces for <tab>
* normal for everything else
*/
static char hexdig[] = "0123456789ABCDEF";
int PROC
format(out,c)
/* format: put a displayable version of c into out */
register char *out;
register unsigned c;
{
if (c >= ' ' && c < '') {
out[0] = c;
return 1;
}
else if (c == '\t' && !list) {
register int i;
int size;
for (i = size = tabsize - (curpos.x % tabsize);i > 0;)
out[--i] = ' ';
return size;
}
else if (c < 128) {
out[0] = '^';
out[1] = c^64;
return 2;
}
else {
#if OS_DOS
out[0] = c;
return 1;
#else
out[0] = '\\';
out[1] = hexdig[(c>>4)&017];
out[2] = hexdig[c&017];
return 3;
#endif
}
}
VOID PROC
printch(c)
char c;
{
register int size;
char buf[MAXCOLS];
size = min(format(buf,c),COLS-curpos.x);
if (size > 0) {
buf[size] = 0;
zwrite(buf, size);
curpos.x += size;
}
}
VOID PROC
prints(s)
char *s;
{
int size,oxp = curpos.x;
char buf[MAXCOLS+1];
register int bi = 0;
while (*s && curpos.x < COLS) {
size = format(&buf[bi],*s++);
bi += size;
curpos.x += size;
}
size = min(bi,COLS-oxp);
if (size > 0) {
buf[size] = 0;
zwrite(buf, size);
}
}
VOID PROC
writeline(y,x,start)
int y,x,start;
{
int endd,oxp;
register int size;
char buf[MAXCOLS+1];
register int bi = 0;
endd = fseekeol(start);
if (start==0 || core[start-1] == EOL)
mvcur(y, 0);
else
mvcur(y, x);
oxp = curpos.x;
while (start < endd && curpos.x < COLS) {
size = format(&buf[bi],core[start++]);
bi += size;
curpos.x += size;
}
if (list) {
buf[bi++] = '$';
curpos.x++;
}
size = min(bi,COLS-oxp);
if (size > 0) {
buf[size] = 0;
zwrite(buf, size);
}
if (curpos.x < COLS)
strput(CE);
}
/* redraw && refresh the screen */
VOID PROC
refresh(y,x,start,endd,rest)
int y,x,start,endd;
bool rest;
{
int sp;
#if OS_ATARI
/* turn the cursor off */
asm(" clr.l -(sp) ");
asm(" move.w #21,-(sp) ");
asm(" trap #14 ");
asm(" addq.l #6,sp ");
#endif
sp = start;
while (sp <= endd) {
writeline(y, x, sp);
sp = 1+fseekeol(sp);
y++;
x = 0;
}
if (rest && sp >= bufmax)
while (y<LINES-1) { /* fill screen with ~ */
mvcur(y, 0);
printch('~'); strput(CE);
y++;
}
#if OS_ATARI
/* turn the cursor back on */
asm(" clr.w -(sp) ");
asm(" move.w #1,-(sp) ");
asm(" move.w #21,-(sp) ");
asm(" trap #14 ");
asm(" addq.l #6,sp ");
#endif
}
/* redraw everything */
VOID PROC
redisplay(flag)
bool flag;
{
if (flag)
clrprompt();
refresh(0, 0, ptop, pend, TRUE);
}
VOID PROC
scrollback(curr)
int curr;
{
mvcur(0,0); /* move to the top line */
do {
ptop = bseekeol(ptop-1);
strput(UpS);
writeline(0, 0, ptop);
} while (ptop > curr);
setend();
}
VOID PROC
scrollforward(curr)
int curr;
{
do {
writeline(LINES-1, 0, pend+1);
zwrite("\n", 1);
pend = fseekeol(pend+1);
ptop = fseekeol(ptop)+1;
} while (pend < curr);
}
/* find if the number of lines between top && bottom is less than dofscroll */
bool PROC
ok_to_scroll(top,bottom)
int top,bottom;
{
int nl, i;
nl = dofscroll;
i = top;
do
i += 1+scan(bufmax-i,'=',EOL, &core[i]);
while (--nl > 0 && i < bottom);
return(nl>0);
}
VOID PROC
clrprompt()
{
mvcur(LINES-1,0);
strput(CE);
}
VOID PROC
prompt(toot,s)
bool toot;
char *s;
{
if (toot)
error();
clrprompt();
prints(s);
}

50
src/cmd/levee/dos.asm Normal file
View File

@@ -0,0 +1,50 @@
name dos
page 55,80
title 'DOS.ASM -- assembly routines for the teeny-shell under DOS'
_TEXT segment byte public 'CODE'
assume cs:_TEXT
public _fail_criterr
;
; If we get a critical error, just fail it - dos 3.0 and up only, please!
;
_fail_criterr proc far
mov al, 3
iret
_fail_criterr endp
public _ignore_ctrlc
;
; If the user presses ^C, don't do any special handling of it.
;
_ignore_ctrlc proc far
iret
_ignore_ctrlc endp
_pexec endp
public _intr_on_ctrlc
;
; If the user presses ^C, terminate the current process.
;
_intr_on_ctrlc proc far
mov ah, 4ch
mov al, 0ffh
int 21h
_intr_on_ctrlc endp
public _crawcin
;
; get a character from standard input without any sort of magical
; processing.
;
_crawcin proc far
mov ah, 07h
int 21h
ret
_crawcin endp
_TEXT ends
end

200
src/cmd/levee/doscall.c Normal file
View File

@@ -0,0 +1,200 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* dos interface for levee (Microsoft C)
*/
#include "levee.h"
#if OS_DOS
#include <glob.h>
#include <dos.h>
int PROC
min(a,b)
int a,b;
{
return (a>b) ? b : a;
}
int PROC
max(a,b)
int a,b;
{
return (a<b) ? b : a;
}
PROC
strput(s)
char *s;
{
write(1, s, strlen(s));
}
/* get a key, mapping certain control sequences
*/
PROC
getKey()
{
register c;
extern char _far crawcin();
c = crawcin();
if (c == 0 || c == 0xe0)
switch (c=crawcin()) {
case 'K': return LTARROW;
case 'M': return RTARROW;
case 'H': return UPARROW;
case 'P': return DNARROW;
case 'I': return 'U'-'@'; /* page-up */
case 'Q': return 'D'-'@'; /* page-down */
default : return 0;
}
return c;
}
/* don't allow interruptions to happen
*/
PROC
nointr()
{
extern void _cdecl _interrupt _far ignore_ctrlc();
_dos_setvect(0x23, ignore_ctrlc);
} /* nointr */
/* have ^C do what it usually does
*/
PROC
allowintr()
{
extern void _cdecl _interrupt _far intr_on_ctrlc();
_dos_setvect(0x23, intr_on_ctrlc);
} /* allowintr */
/*
* basename() returns the filename part of a pathname
*/
char *
basename(s)
register char *s;
{
register char *p = s;
for (p = s+strlen(s); p > s; --p)
if (p[-1] == '/' || p[-1] == '\\' || p[-1] == ':')
return p;
return s;
} /* basename */
/*
* glob() expands a wildcard, via calls to _dos_findfirst/_next()
* and pathname retention.
*/
char *
glob(path, dta)
char *path;
struct glob_t *dta;
{
static char path_bfr[256]; /* full pathname to return */
static char *file_part; /* points at file - for filling */
static char isdotpattern; /* looking for files starting with . */
static char isdotordotdot; /* special case . or .. */
static struct glob_t *dta_bfr; /* pointer to desired dta */
static struct find_t dird; /* DOS dta */
register st; /* status from _dos_findxxx */
if (path) {
/* when we start searching, save the path part of the filename in
* a safe place.
*/
strcpy(path_bfr, path);
file_part = basename(path_bfr);
/* set up initial parameters for DosFindFirst()
*/
dta_bfr = dta;
if (isdotpattern = (*file_part == '.'))
/* _dos_findfirst() magically expands . and .. into their
* directory names. Admittedly, there are cases where
* this can be useful, but this is not one of them. So,
* if we find that we're matching . and .., we just
* special-case ourselves into oblivion to get around
* this particular bit of DOS silliness.
*/
isdotordotdot = (file_part[1] == 0 || file_part[1] == '.');
else
isdotordotdot = 0;
st = _dos_findfirst(path, 0x16, &dird);
}
else
st = _dos_findnext(&dird);
while (st == 0) {
/* Unless the pattern has a leading ., don't include any file
* that starts with .
*/
if (dird.name[0] == '.' && !isdotpattern)
st = _dos_findnext(&dird);
else {
/* found a file - affix the path leading to it, then return
* a pointer to the (static) buffer holding the path+the name.
*/
strlwr(dird.name); /* DOS & OS/2 are case-insensitive */
if (dta_bfr) {
dta_bfr->wr_time = dird.wr_time;
dta_bfr->wr_date = dird.wr_date;
if (isdotordotdot)
strcpy(dta_bfr->name, file_part);
else {
strncpy(dta_bfr->name, dird.name, sizeof(dta_bfr->name)-1);
dta_bfr->name[sizeof(dta_bfr->name)-1] = 0;
}
dta_bfr->size = dird.size;
dta_bfr->attrib = dird.attrib;
}
if (!isdotordotdot)
strcpy(file_part, dird.name);
return path_bfr;
}
}
/* nothing matched
*/
if (path && isdotordotdot) {
/* must be at root, so statting dot will most likely fail. Fake a
* dta.
*/
if (dta_bfr) {
memset(dta_bfr, 0, sizeof *dta_bfr);
dta_bfr->attrib = 0x10;
dta_bfr->name[0] = '.';
}
return path_bfr;
}
return (char*)0;
} /* glob */
#endif /*OS_DOS*/

644
src/cmd/levee/editcor.c Normal file
View File

@@ -0,0 +1,644 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2008 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#include <stdlib.h>
/* do some undoable modification */
/* These variables make docommand nonrecursive */
bool ok;
int newend, /* end position after change */
disp, /* start redisplay here */
newc, /* new cursor position for wierd cmds */
endY; /* final yp for endp */
/* move a line of text right || left */
VOID PROC
adjuster(sleft, endd, sw)
bool sleft;
int endd, sw;
{
bool noerror;
int np, ts,
ip,
ss, adjp,
DLEnum;
if (sw == -1)
sw = shiftwidth;
if (sleft)
sw = -sw;
curr = bseekeol(curr);
ip = curr;
noerror = TRUE;
do {
DLEnum = sw + findDLE(ip, &np, bufmax,0);
if (DLEnum >= 0 && DLEnum <= COLS && core[np] != EOL && np < bufmax) {
ts = DLEnum / tabsize;
ss = DLEnum % tabsize;
adjp = ts+ss+ip;
if (np-adjp < 0) { /* expand the buf */
moveright(&core[np], &core[adjp], bufmax-np);
insert_to_undo(&undo, adjp, adjp - np);
}
else
delete_to_undo(&undo, adjp, np - adjp);
endd += (adjp-np);
noerror = move_to_undo(&undo, ip, ts+ss);
fillchar(&core[ip], ts, TAB);
fillchar(&core[ip+ts], ss, 32);
}
else if (np > ip) { /* remove the indent code */
noerror = delete_to_undo(&undo, ip, np-ip);
endd += (ip - np);
}
ip = 1 + fseekeol(ip);
} while (noerror && ip < endd);
if (!noerror)
error();
newc = skipws(curr);
disp = curr;
newend = endd;
endY = setY(min(newend, pend));
}
/* join <count> lines together */
VOID PROC
join(count)
int count;
{
bool ok;
int lp, first;
if (lend < bufmax) { /* are we in the buffer? */
disp = lend; /* start redraw here */
newc = lend;
do { /* join until.. */
first = lend;
lp = skipws(1+first);
ok = delete_to_undo(&undo, 1+first, lp-(1+first));
if (ok) {
ok = move_to_undo(&undo, first, 1);
core[first] = ' '; /* spaces between lines */
}
count--;
lend = fseekeol(first);
} while (ok && count > 0);
endY = MAGICNUMBER;
newend = lend;
if (!ok)
error();
}
else
error();
}
VOID PROC
squiggle(endp, c, dorepl)
int endp;
char c;
bool dorepl;
{
int i;
if (endp >= curr) {
ok = move_to_undo(&undo,curr,endp-curr+1);
if (ok) {
for (i = curr;i<=endp;i++) {
if (!dorepl) { /* squiggle it to uc - lc */
if (core[i] >='A' && core[i] <='Z')
core[i] += 32;
else if (core[i]>='a' && core[i]<='z')
core[i] -= 32;
}
else
core[i] = c;
}
newend = min(endp+1,lend);
}
}
}
VOID PROC
bigreplace()
{
int len, tsiz;
tsiz = lend-curr;
if (move_to_undo(&undo, curr, tsiz))
if (SIZE - bufmax > tsiz) { /* enough room for temp copy? */
moveleft(&core[curr], &core[bufmax],lend-curr);
if (line(core, curr, lend, &len) != ESC)
error();
newend = curr+len;
moveright(&core[bufmax+len], &core[newend], lend-newend);
}
}
bool PROC
put(before)
bool before;
{
endY = setY(curr);
if (!before)
if (yank.lines)
curr = min(lend+1,bufmax);
else
curr = min(curr+1, lend);
else if (yank.lines)
curr = lstart;
newc = disp = curr;
return(putback(curr, &newend));
}
bool PROC
execute(start, end)
{
int tf;
FILE *f;
char scratch[20];
bool ret = FALSE;
int size;
strcpy(scratch, "/tmp/lv.XXXXXX");
clrprompt();
printch('!');
if ( !getlin(instring) )
return FALSE;
if ( (tf = mkstemp(scratch)) < 0 ) {
prints("[tempfile error]");
return FALSE;
}
strcat(instring, " 2>&1 <");
strcat(instring, scratch);
if ( (size = write(tf, core+start, end-start)) == (end-start) ) {
if ( (f=popen(instring, "r")) ) {
if ( deletion(start, end) && (insertfile(f, 1, start, &size) > 0) )
ret = TRUE;
pclose(f);
}
else
error();
}
close(tf);
unlink(scratch);
return ret;
}
VOID PROC
gcount()
{
do {
count = (count*10) + (ch-'0');
readchar(); /* get a char to replace the one we dumped */
} while ( count >= 0 && isdigit(ch) );
}
VOID PROC
docommand(cmd)
cmdtype cmd;
{
cmdtype movecmd; /* movement command for y, d, c */
char cmdch;
int oldc; /* old count */
int endp; /* end position before change */
extern bool s_wrapped;
resetX(); /* un-derange the cursor */
oldc = newc = -1;
endY = yp;
newend = disp = curr;
ok = TRUE; /* so far everything is working */
cmdch = ch;
if (cmd != UNDO_C && cmd != YANK_C) {
if (macro<0)
zerostack(&undo);
if (redoing != TRUE) {
rcp = rcb; /* point at start of redo buffer */
if (count > 1) { /* put in a count? */
numtoa(rcb,count);
rcp += strlen(rcb);
}
*rcp++ = cmdch; /* the command char goes in... */
xerox = TRUE; /* hoist the magical flags */
}
}
if (cmd <= YANK_C) {
readchar();
if ( isdigit(ch) && ch != '0' ) {
oldc = count;
count = 0;
gcount(); /* get a new count */
if (cmd == ADJUST_C) /* special for >>,<< wierdness */
swap(&count, &oldc); /* reverse sw & count */
else
count = count*max(oldc,1); /* combine them */
}
if (ch == cmdch) { /* diddle lines */
yank.lines = TRUE;
endp = nextline(TRUE, curr, count);
curr = bseekeol(curr);
disp = curr;
}
else { /* diddle 'things' */
yank.lines = FALSE;
movecmd = movemap[(unsigned int)ch];
if ( (ok = (findCP(curr,&endp,movecmd) == LEGALMOVE)) ) {
if (curr > endp) {
swap(&curr,&endp);
ok = (cmd != CHANGE_C);
}
if (adjcurr[(unsigned int)movecmd])
curr++;
if (adjendp[(unsigned int)movecmd])
endp++;
}
if (!ok) {
if (ch != ESC)
error();
goto killredo;
}
}
endY = setY(endp);
newend = curr;
disp = curr;
switch (cmd) {
case EXEC_C:
ok = execute(curr, endp);
break;
case DELETE_C:
ok = deletion(curr, endp);
break;
case ADJUST_C:
adjuster((cmdch == '<'), endp-1, oldc);
break;
case CHANGE_C:
if (endp <= pend+1) {
mvcur(setY(endp-1), setX(endp-1));
printch('$');
mvcur(yp, xp);
}
if (deletion(curr, endp))
ok = ((newend = insertion(1, 0, &disp, &endY, TRUE)) >= 0);
else
ok = FALSE;
break;
case YANK_C:
if (!doyank(curr, endp))
error();
return; /* xerox will not be true, nor will redoing */
}
}
else {
endp = curr;
endY = yp;
switch (cmd) {
case I_AT_NONWHITE:
case A_AT_END:
case APPEND_C:
case INSERT_C: /* variations on insert */
if (cmd != INSERT_C) {
if (cmd == APPEND_C)
curr = min(curr+1, lend);
else if (cmd == A_AT_END)
curr = lend;
else /* if (cmd == I_AT_NONWHITE) */
curr = skipws(lstart);
xp = setX(curr);
mvcur(yp,xp);
}
newend = insertion(count, 0, &disp, &endY, TRUE);
ok = (newend >= 0);
break;
case OPEN_C:
case OPENUP_C:
newend = insertion(1,setstep[ (cmd==OPENUP_C)&1 ],
&disp,&endY,TRUE)-1;
ok = (newend >= 0);
break;
case REPLACE_C:
case TWIDDLE_C:
if (cmd == REPLACE_C) {
if ((cmdch = readchar()) == ESC)
goto killredo;
}
if (findCP(curr, &endp, GO_RIGHT) == LEGALMOVE)
squiggle(endp-1, cmdch, (cmd==REPLACE_C));
break;
case PUT_BEFORE:
case PUT_AFTER:
ok = put(cmd==PUT_AFTER);
break;
case BIG_REPL_C:
bigreplace();
break;
case RESUBST_C:
ok = FALSE;
if (dst[0] != 0) {
newend = chop(curr, &lend, TRUE, &ok);
if (newend >= 0) {
endY = setY(newend+strlen(dst));
ok = TRUE;
}
}
break;
case JOIN_C:
join(count); /* join lines */
break;
case UNDO_C: /* undo last modification */
ok = fixcore(&newend) >= 0;
disp = newend;
endY = MAGICNUMBER;
break;
}
}
if (ok) {
setpos((newc<0)?newend:newc);
setend();
if (curr < ptop || curr > pend) {
yp = settop(12);
redisplay(TRUE);
}
else {
yp = setY(curr);
if (endY != setY(newend)) /* shuffled lines */
refresh(setY(disp), setX(disp), disp, pend, TRUE);
else /* refresh to end position */
refresh(setY(disp), setX(disp), disp, newend, FALSE);
}
if (curr >= bufmax && bufmax > 0) { /* adjust off end of buffer */
setpos(bufmax-1);
yp = setY(curr);
}
if (s_wrapped) {
prompt(FALSE, "search wrapped around end of buffer");
s_wrapped = 0;
}
else
clrprompt();
modified = TRUE;
}
else {
error();
killredo:
rcb[0] = 0;
}
mvcur(yp, xp);
if (xerox)
*rcp = 0; /* terminate the redo */
redoing = FALSE;
xerox = FALSE;
core[bufmax] = EOL;
}
/* Initialize && execute a macro */
VOID PROC
exmacro()
{
int mp;
mp = lookup(ch);
if (mp > 0) {
if (macro<0)
zerostack(&undo);
insertmacro(mbuffer[mp].m_text, count);
}
else
error();
}
/* redraw the screen w.r.t. the cursor */
VOID PROC
zdraw(code)
unsigned char code;
{
int nl = ERR,
np = (count>0)?to_index(count):curr;
if (movemap[code] == CR_FWD)
nl = 0;
else if (movemap[code] == CR_BACK)
nl = LINES-1;
else if (code == '.')
nl = LINES / 2;
if (nl >= 0) {
curr = np;
yp = settop(nl);
redisplay(TRUE);
mvcur(yp,xp);
}
else
error();
}
/* start up a built-in macro */
VOID PROC
macrocommand()
{
if (count > 1)
numtoa(gcb,count);
else
gcb[0] = 0;
switch (ch) { /* which macro? */
case 'x': /* x out characters */
strcat(gcb,"dl"); break;
case 'X': /* ... backwards */
strcat(gcb,"dh"); break;
case 's': /* substitute over chars */
strcat(gcb,"cl"); break;
case 'D': /* delete to end of line */
strcat(gcb,"d$"); break;
case 'C': /* change ... */
strcat(gcb,"c$"); break;
case 'Y': /* yank ... */
strcat(gcb,"y$"); break;
case '': /* scroll up one page */
strcpy(gcb,"22"); break;
case '': /* ... down one page */
strcpy(gcb,"22"); break;
case '': /* scroll up one line */
strcpy(gcb,"1"); break;
case '': /* ... down one line */
strcpy(gcb,"1"); break;
default:
error();
return;
break;
}
if (macro<0)
zerostack(&undo);
insertmacro(gcb, 1);
}
/* scroll the window up || down */
VOID PROC
scroll(down)
bool down;
{
int i;
if (count <= 0)
count = dofscroll;
strput(CURoff);
if (down) {
curr = min(bufmax-1, nextline(TRUE, curr, count));
i = min(bufmax-1, nextline(TRUE, pend, count));
if (i > pend)
scrollforward(i);
}
else {
curr = bseekeol(max(0,nextline(FALSE, curr, count)));
i = bseekeol(max(0,nextline(FALSE, ptop, count)));
if (i < ptop) {
if (canUPSCROLL)
scrollback(i);
else {
ptop = i;
setend();
redisplay(TRUE);
}
}
}
strput(CURon);
setpos(skipws(curr)); /* initialize new position - first nonwhite */
yp = setY(curr);
mvcur(yp, xp); /* go there */
}
exec_type PROC
editcore()
{
cmdtype cmd;
extern bool s_wrapped;
/* rcb[0] = 0; rcp = rcb; */
if (diddled) {
setpos(skipws(curr)); /* set cursor x position.. */
yp = settop(LINES / 2); /* Y position */
}
if (diddled || zotscreen) /* redisplay? */
redisplay(FALSE);
mvcur(yp, xp); /* and move the cursor */
for (;;) {
s_wrapped = 0;
ch = readchar(); /* get a char */
count = 0;
if (isdigit(ch) && ch != '0')
gcount(); /* ... a possible count */
switch (cmd = movemap[(unsigned int)ch]) {
case FILE_C:
wr_stat(); /* write file stats */
mvcur(yp, xp);
break;
case WINDOW_UP:
case WINDOW_DOWN:
scroll(cmd==WINDOW_UP); /* scroll the window */
break;
case REDRAW_C: /* redraw the window */
redisplay(TRUE);
mvcur(yp, xp);
break;
case MARKER_C: /* set a marker */
ch = tolower(readchar());
if (ch >= 'a' && ch <= 'z')
contexts[ch-'`'] = curr;
else if (ch != ESC)
error();
break;
case REDO_C:
if (rcb[0] != 0) {
zerostack(&undo);
insertmacro(rcb, 1);
redoing = TRUE;
}
break;
case REWINDOW:
zdraw(readchar()); /* shift the window */
break;
case DEBUG_C: /* debugging stuff -- unused */
break;
case ZZ_C: /* shortcut for :xit */
ch = readchar();
if (ch == 'Z')
insertmacro(":x\r", 1);
else if (ch != ESC)
error();
break;
case EDIT_C: /* drop into line mode */
return E_EDIT;
case COLIN_C: /* do one exec mode command */
return E_VISUAL;
case HARDMACRO:
macrocommand(); /* 'hard-wired' macros */
break;
case SOFTMACRO:
exmacro(); /* run a macro */
break;
case INSMACRO: /* macro for insert mode */
case BAD_COMMAND:
error();
break;
default:
if (cmd < DELETE_C)
movearound(cmd);
else /*if (cmd < HARDMACRO)*/
docommand(cmd);
break;
}
lastexec = 0;
}
/* never exits here */
}

1114
src/cmd/levee/exec.c Normal file

File diff suppressed because it is too large Load Diff

237
src/cmd/levee/extern.h Normal file
View File

@@ -0,0 +1,237 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#ifndef GLOBALS_D
#define GLOBALS_D
extern
char lastchar, /* Last character read via peekc */
ch; /* Global command char */
extern
exec_type mode; /* editor init state */
extern
int lastexec; /* last exec mode command */
extern
int contexts['z'-'`'+1]; /* Labels */
/* C O N S T A N T S */
extern
bool adjcurr[PARA_BACK+1],
adjendp[PARA_BACK+1];
/* A R G U M E N T S */
extern
char startcmd[]; /* initial command after read */
extern
char **argv; /* Arguments */
extern
int argc, /* # arguments */
pc; /* Index into arguments */
/* M A C R O S T U F F */
extern
struct macrecord mbuffer[];
extern
struct tmacro mcr[]; /* A place for executing macros */
/* S E A R C H S T U F F */
extern
char dst[], /* last replacement pattern */
lastpatt[], /* last search pattern */
pattern[];
extern
int RE_start[9], /* start of substitute argument */
RE_size [9], /* size of substitute argument */
lastp; /* last character matched in search */
extern
struct undostack undo; /* To undo a command */
/* R A N D O M S T R I N G S */
extern
char instring[], /* Latest input */
filenm[], /* Filename */
altnm[], /* Alternate filename */
gcb[]; /* Command buffer for mutations of insert */
extern
char undobuf[],
undotmp[],
yankbuf[];
extern
int uread, /* reading from the undo stack */
uwrite; /* writing to the undo stack */
/* B U F F E R S */
extern
char rcb[], *rcp, /* last modification command */
core[]; /* data space */
extern
struct ybuf yank; /* last deleted/yanked text */
/* STATIC INITIALIZATIONS: */
/* ttydef stuff */
#if OS_ATARI | USE_TERMCAP
extern int LINES, COLS;
#endif
#if USE_TERMCAP
extern bool CA, canUPSCROLL;
extern char FkL,
CurRT,
CurLT,
CurDN,
CurUP;
#endif /*USE_TERMCAP*/
extern char *TERMNAME,
*HO,
*UP,
*CE,
*CL,
*OL,
*BELL,
*CM,
*UpS,
*CURoff,
*CURon;
extern
char Erasechar,
eraseline;
extern
char codeversion[], /* Editor version */
fismod[], /* File is modified message */
fisro[]; /* permission denied message */
extern
char *excmds[],
wordset[],
spaces[];
extern
struct variable vars[];
extern
int autowrite,
autocopy,
overwrite,
beautify,
autoindent,
dofscroll,
shiftwidth,
tabsize,
list,
wrapscan,
bell,
magic;
/*extern
char *suffix; */
/* For movement routines */
extern
int setstep[];
/* Where the last diddling left us */
extern
struct coord curpos;
/* initialize the buffer */
extern
int curr, /* Global cursor pos */
lstart, lend, /* Start & end of current line */
count, /* Latest count */
xp, yp, /* Cursor window position */
bufmax, /* End of file here */
ptop, pend; /* Top & bottom of CRT window */
extern
bool modified, /* File has been modified */
readonly, /* is this file readonly? */
needchar, /* Peekc flag */
deranged, /* Up-arrow || down-arrow left xpos in Oz. */
indirect, /* Reading from an indirect file?? */
redoing, /* doing a redo? */
xerox, /* making a redo buffer? */
newfile, /* Editing a new file? */
newline, /* Last insert/delete included a EOL */
lineonly, /* Dumb terminal? */
zotscreen, /* do more after command in execmode */
diddled; /* force redraw when I enter editcore */
extern
int macro; /* Index into MCR macro execution stack */
extern
char lsearch;
/* movement, command codes */
extern
cmdtype movemap[];
#endif /*GLOBALS_D*/
#ifndef EXTERN_D
#define EXTERN_D
#define wc(ch) (scan(65,'=',(ch),wordset)<65)
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_MEMSET
#define fillchar(p,l,c) memset((p),(c),(l))
#elif HAVE_BLKFILL
#define fillchar(p,l,c) blkfill((p),(c),(l))
#endif
#if HAVE_STRCHR
#define index(s,c) strchr((s),(c))
#endif
extern findstates PROC findCP();
extern exec_type PROC editcore();
extern char PROC line(), peekc(), readchar();
extern char PROC *findparse(),*makepat();
extern bool PROC getlin();
extern bool PROC putfile();
extern bool PROC doyank(), deletion(), putback();
extern bool PROC pushb(),pushi(),pushmem(),uputcmd(), delete_to_undo();
extern bool PROC ok_to_scroll(), move_to_undo();
extern int PROC min(), max(), fseekeol(), bseekeol(), settop();
extern int PROC scan(), findDLE(), setY(), skipws(), nextline(), setX();
extern int PROC insertion(), chop(), fixcore(), lookup(), to_index();
extern int PROC doaddwork(), addfile(), expandargs(), to_line();
extern int PROC findfwd(), findback(), getcontext(), getKey();
extern int PROC cclass();
extern int PROC insertfile();
extern VOID PROC strput(), numtoa(), clrprompt(), setend(), error();
extern VOID PROC insert_to_undo(), resetX(), zerostack(), swap();
extern VOID PROC mvcur(), printch(), prints(), writeline(), refresh();
extern VOID PROC redisplay(), scrollback(), scrollforward(), prompt();
extern VOID PROC setpos(), resetX(), insertmacro(), wr_stat();
extern VOID PROC movearound(), printi(), println(), killargs();
extern VOID PROC exec(), initcon(), fixcon(), version(), setcmd();
extern VOID PROC toedit(), inputf(), fixmarkers(), errmsg();
#ifndef moveleft
extern VOID PROC moveleft();
#endif
#ifndef moveright
extern VOID PROC moveright();
#endif
#ifndef fillchar
extern VOID PROC fillchar();
#endif
#if USE_TERMCAP
extern void tc_init();
#endif
#endif /*EXTERN_D*/

514
src/cmd/levee/find.c Normal file
View File

@@ -0,0 +1,514 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#include "grep.h"
#include <ctype.h>
int PROC amatch();
int PROC locate();
VOID PROC patsize();
static int arg; /* arguments inside of a RE */
int PROC
REmatch(pattern, start, end)
char *pattern;
int start,end;
{
char *endp = &core[end];
if (!*pattern)
return -1;
arg = 0;
while (start <= end && !amatch(pattern, &core[start], endp))
start++;
return start;
}
int PROC
omatch(pattern, cp, endp)
char *pattern, **cp, *endp;
{
register int flag;
extern int ignorecase;
switch (*pattern) {
case LEND:
return (**cp == EOL);
case LSTART:
return (*cp == core) || (*(*cp-1) == EOL);
case TOKENB:
return (*cp == core) || !isalnum(*(*cp-1));
case TOKENE:
return !isalnum(**cp);
case LITCHAR:
if (ignorecase)
flag = (toupper(**cp) == toupper(*(pattern+1)));
else
flag = (**cp == *(pattern+1));
break;
case ANY:
flag = (**cp != EOL);
break;
case CCL:
flag = locate(pattern,*cp);
break;
case NCCL:
flag = !locate(pattern,*cp);
break;
case ARGSTART:
RE_start[arg] = (*cp)-core;
return TRUE;
case ARGEND:
RE_size[arg] = ((*cp)-core) - RE_start[arg];
++arg;
return TRUE;
default:
return TRUE;
}
if (*cp <= endp && flag) {
(*cp)++;
return TRUE;
}
return FALSE;
}
int PROC
amatch(pattern,start,endp)
char *pattern, *endp, *start;
{
int sarg = arg; /* save old arg match count for errors */
while (*pattern) {
if (*pattern == CLOSURE) {
/* Find the longest closure possible and work backwards trying
* to match the rest of the pattern.
*/
char *oldstart = start;
++pattern; /* skip over the closure token */
while (start <= endp && omatch(pattern,&start,endp))
;
/* start points at the character that failed the search.
* Try to match the rest of the pattern against it, working
* back down the line if failure
*/
patsize(&pattern);
while (start >= oldstart)
if (amatch(pattern,start--,endp))
return TRUE;
arg = sarg;
return FALSE;
}
else {
if (!omatch(pattern,&start,endp)) {
arg = sarg;
return FALSE;
}
patsize(&pattern);
}
}
lastp = start-core;
return TRUE;
}
/* increment pattern by the size of the token being scanned
*/
VOID PROC
patsize(pattern)
register char **pattern;
{
register int count;
switch (**pattern) {
case LITCHAR:
*pattern += 2;
break;
case CCL:
case NCCL:
count = *(++*pattern) & 0xff;
*pattern += 1+count;
break;
default:
(*pattern)++;
break;
}
}
int PROC
locate(pattern,linep)
/* locate: find a character in a closure */
char *pattern;
register char *linep;
{
register char *p = 1+pattern;
register int count;
if ((count = (*p++)&0xff) == 0)
return FALSE;
while (count--)
if (*p++ == *linep)
return TRUE;
return FALSE;
}
char *p;
VOID PROC
concatch(c)
/* add a character to the pattern */
char c;
{
if (p < &pattern[MAXPAT-1])
*p++ = c;
}
char PROC
esc(s)
char **s;
{
if (**s != ESCAPE || *(1+*s) == 0)
return **s;
++(*s);
switch (**s) {
case 't': return TAB;
case 'n': return EOL;
}
return **s;
}
char * PROC
dodash(src)
/* parse the innards of a [] */
char *src;
{
int k;
char *start = src;
char cs[128];
fillchar(cs,sizeof(cs),FALSE);
while (*src && *src != CCLEND) {
if (*src == DASH && src>start && src[1] != CCLEND && src[-1]<src[1]) {
for ( k = src[-1]; k <= src[1]; k++)
cs[k] = TRUE;
src++;
}
else
cs[(unsigned int)esc(&src)] = TRUE;
src++;
}
for (k=0; k < sizeof(cs); k++)
if (cs[k])
concatch((char)k);
return src;
}
char * PROC
badccl(src)
/* a [] was encountered. is it a CCL (match one of the included
* characters); or is it a NCCL (match all but the included characters)?
*/
char *src;
{
char *jstart;
if (*src == NEGATE) {
concatch(NCCL);
++src;
}
else
concatch(CCL);
jstart = p;
concatch(0); /* this will be the length of the pattern */
src = dodash(src);
*jstart = (p-jstart)-1;
return src;
}
/* patterns that cannot be closed */
char badclose[] = { LSTART, LEND, CLOSURE, 0 };
char * PROC
makepat(string,delim)
char *string, delim;
/* make up the pattern string for find -- ripped from 'Software Tools' */
{
char *cp = 0, *oldcp;
char *start = string;
int inarg = FALSE;
for(arg=0;arg<9;++arg)
RE_start[arg] = RE_size[arg] = (-1);
arg = 0;
p = pattern;
while ((*string != delim) && (*string != 0)) {
oldcp = cp;
cp = p;
if (!magic) /* kludge for nonmagical patterns */
goto normal;
if (*string == ANY)
concatch(ANY);
else if ((*string == LSTART) && (string == start))
concatch(LSTART);
else if ((*string == LEND) && (string[1] == delim || string[1] == 0))
concatch(LEND);
else if (*string == CCL)
string = badccl(1+string);
else if ((*string == CLOSURE) && (p > pattern)) {
cp = oldcp;
if (strchr(badclose, *cp) || p >= &pattern[MAXPAT-1])
return NULL;
moveright(cp,1+cp,(int)(p-cp));
*cp = CLOSURE;
p++;
}
else if (*string == ESCAPE) {
if (string[1] == ARGSTART || string[1] == ARGEND) {
if (string[1] == ARGEND)
if (!inarg)
goto normal;
if (string[1] == ARGSTART) {
if (inarg)
goto normal;
if (++arg > 9)
return NULL;
}
inarg = !inarg;
}
else if (string[1] != TOKENB && string[1] != TOKENE)
goto normal;
++string;
concatch(*string);
}
else {
normal:concatch(LITCHAR);
concatch(esc(&string));
}
if (*string)
string++;
}
if (inarg)
concatch(ARGEND);
if (p > pattern) { /* new pattern was created */
strncpy(lastpatt,start,(int)(string-start));
lastpatt[string-start] = 0;
concatch(0);
if (p-pattern >= MAXPAT)
return NULL;
}
return (*string == delim)?(string+1):(string);
}
int PROC
findfwd(pattern,start,endp)
/* look for a regular expression forward */
char *pattern;
int start, endp;
{
int ep;
while (start < endp) {
ep = fseekeol(start);
if ((start = REmatch(pattern, start, ep)) <= ep)
return start;
}
return ERR;
}
int PROC
findback(pattern,start,endp)
/* look for a regular expression backwards */
char *pattern;
int start, endp;
{
int ep,i;
while (start > endp) {
ep = bseekeol(start);
if ((i = REmatch(pattern, ep, start)) <= start)
return i;
start = ep-1;
}
return ERR;
}
bool s_wrapped = 0;
char * PROC
search(pat, start)
/* get a token for find & find it in the buffer
*/
char *pat;
int *start;
{
bool forwd;
int pos;
char *p;
forwd = ((lsearch = *pat) == '/');
if ((p=makepat(pat+1,*pat)) == NULL) {
*start = ERR;
return pat;
}
do {
if (forwd) {
pos = findfwd(pattern, (*start)+1, bufmax-1);
if ((pos == ERR) && wrapscan) {
s_wrapped = 1;
pos = findfwd(pattern, 0, (*start)-1);
}
}
else {
pos = findback(pattern, (*start)-1, 0);
if ((pos == ERR) && wrapscan) {
s_wrapped = 1;
pos = findback(pattern, bufmax-1, (*start)+1);
}
}
*start = pos;
} while (--count > 0 && *start != ERR);
return p;
}
char * PROC
findparse(src,idx,start) /* driver for ?, /, && : lineranges */
char *src;
int *idx,start;
{
int addr = start;
char c;
s_wrapped = 0;
switch (*src) {
case '/':
case '?':
/* get a token for find & find it in the buffer */
src = search(src,&addr);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* fabricate a count */
count = 0;
while (*src >= '0' && *src <= '9')
count = (count*10) + *(src++) - '0';
addr = to_index(count);
break;
case '$':
addr = bufmax-1;
src++;
break;
case '.' :
src++;
break;
case '`':
case '\'':
addr = getcontext(*(src+1), (*src == '\''));
src += 2;
break;
}
while (addr>=0 && (*src =='+' || *src == '-')) {
c = *(src++);
/* skip delimiter */
if (*src == '/' || *src == '?') {
count = 1;
if ((src = search(src,&addr)) == NULL)
break;
}
else {
if (*src >= '0' && *src <= '9') {
/* fabricate a count */
count = 0;
while (*src >= '0' && *src <= '9')
count = (count*10) + *(src++) - '0';
}
else
count = -1; /* for naked + & - */
if (count == 0) /* +0 goes to beginning of line */
addr = bseekeol(addr);
else {
addr = nextline((c=='+'), addr, count);
if (c=='-' && addr > 0)
addr = bseekeol(addr);
}
if (addr >= bufmax)
addr = -1;
}
}
*idx = addr;
return(src);
}
int PROC
nextline(advance,dest,count)
bool advance;
int dest,count;
{
if (advance)
do {
dest = fseekeol(dest) + 1;
count--;
} while (count>0 && dest<bufmax);
else
do {
dest = bseekeol(dest) - 1;
count--;
} while (count>0 && dest>=0);
return(dest);
}
int PROC
fseekeol(origin)
int origin;
{
return(origin + scan(bufmax-origin-1,'=',EOL,&core[origin]));
}
int PROC
bseekeol(origin)
int origin;
{
return(origin + scan(-origin,'=',EOL,&core[origin-1]));
}
/* get something from the context table */
int PROC
getcontext(c,begline)
char c;
bool begline;
{
int i;
if (c == '\'')
c = '`';
if (c >= '`' && c <= 'z')
i = contexts[c-'`'];
else
i = -1;
if (begline && i>=0)
return(bseekeol(i));
return(i);
}

122
src/cmd/levee/flexcall.c Normal file
View File

@@ -0,0 +1,122 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* flexos interface for levee (Metaware C)
*/
#include "levee.h"
#if OS_FLEXOS
#include <flexos.h>
#include <ctype.h>
static int oldkmode;
static int oldsmode;
int
min(a,b)
{
return (a>b) ? b : a;
}
int
max(a,b)
{
return (a<b) ? b : a;
}
strput(s)
char *s;
{
s_write(0x01, 1L, s, (long)strlen(s), 0L);
}
char *
basename(s)
char *s;
{
char *strrchr();
char *p;
if ((p=strrchr(s,'/')) || (p=strrchr(s,'\\')) || (p = strrchr(s,':')))
return 1+p;
return s;
}
getKey()
{
char c;
s_read(0x0101, 0L, &c, 1L, 0L);
return c;
}
initcon()
{
CONSOLE tty;
s_get(T_CON, 1L, &tty, SSIZE(tty));
oldkmode = tty.con_kmode;
oldsmode = tty.con_smode;
tty.con_kmode = 0x0667;
tty.con_smode = 0;
s_set(T_CON, 1L, &tty, SSIZE(tty));
}
fixcon()
{
CONSOLE tty;
s_get(T_CON, 1L, &tty, SSIZE(tty));
tty.con_kmode = oldkmode;
tty.con_smode = oldsmode;
s_set(T_CON, 1L, &tty, SSIZE(tty));
}
char *
strdup(s)
char *s;
{
char *malloc();
char *p;
if (p=malloc(strlen(s)+1))
strcpy(p, s);
return p;
}
getpid()
{
PROCESS myself;
s_get(T_PDEF, 0L, &myself, SSIZE(myself));
return myself.ps_pid;
}
strlwr(s)
char *s;
{
while (*s) {
if (isupper(*s))
*s += 32;
s++;
}
}
#endif

70
src/cmd/levee/gemcall.c Normal file
View File

@@ -0,0 +1,70 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* Gemdos (Atari ST) bindings for levee (Alcyon/Sozobon C)
*/
#include "levee.h"
#if OS_ATARI
#include <atari\osbind.h>
strput(s)
register char *s;
{
write(1, s, strlen(s));
}
zwrite(s,len)
char *s;
{
write(1, s, len);
}
min(a,b)
register int a, b;
{
return (a<b)?a:b;
}
max(a,b)
register int a, b;
{
return (a>b)?a:b;
}
unsigned
getKey()
/* get input from the keyboard. All odd keys (function keys, et al) that
* do not produce a character have their scancode orred with $80 and returned.
*/
{
unsigned c;
long key;
c = (key = Crawcin()) & 0xff;
if (!c)
c = (((unsigned)(key>>16))|0x80) & 0xff;
return c;
} /* getKey */
#endif /*OS_ATARI*/

547
src/cmd/levee/globals.c Normal file
View File

@@ -0,0 +1,547 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2008 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/* global declarations */
#include "levee.h"
#define GLOBALS
char lastchar, /* Last character read via peekc */
ch; /* Global command char */
exec_type mode; /* editor init state */
int lastexec = 0; /* last exec command */
int contexts['z'-'`'+1]; /* Labels */
/* C O N S T A N T S */
bool adjcurr[PARA_BACK+1],
adjendp[PARA_BACK+1];
/* A R G U M E N T S */
char startcmd[80] = ""; /* initial command after read */
char **argv; /* Arguments */
int argc=0, /* # arguments */
pc=0; /* Index into arguments */
#if 0
struct stat thisfile; /* status on current file, for writeout... */
#endif
/* M A C R O S T U F F */
struct macrecord mbuffer[MAXMACROS];
struct tmacro mcr[NMACROS]; /* A place for executing macros */
/* S E A R C H S T U F F */
char dst[80] = "", /* last replacement pattern */
lastpatt[80] = "", /* last search pattern */
pattern[MAXPAT] = ""; /* encoded last pattern */
int RE_start[9], /* start of substitution arguments */
RE_size [9], /* size of substitution arguments */
lastp; /* end of last pattern */
struct undostack undo; /* To undo a command */
/* R A N D O M S T R I N G S */
char instring[200], /* Latest input */
filenm[80] = "", /* Filename */
altnm[80] = ""; /* Alternate filename */
char gcb[16]; /* Command buffer for mutations of insert */
char undobuf[40];
char undotmp[40];
char yankbuf[40];
HANDLE uread, /* reading from the undo stack */
uwrite; /* writing to the undo stack */
/* B U F F E R S */
char rcb[256]; /* last modification command */
char *rcp; /* this points at the end of the redo */
char core[SIZE+1]; /* data space */
struct ybuf yank; /* last deleted/yanked text */
/* STATIC INITIALIZATIONS: */
/* ttydef stuff */
#if OS_ATARI | USE_TERMCAP
int LINES, COLS;
#endif
#if TTY_ZTERM
char *TERMNAME = "zterm",
*HO = "\001", /* goto top of screen */
*UP = "\002", /* move up 1 line? */
*CE = "\003", /* clear to end of line */
*CL = "\004", /* clearscreen */
*OL = "\005", /* open current line down */
*UpS = "\006", /* scroll up 1 line */
*BELL= "\007", /* ring the bell */
*CM = "yes", /* cursor movement exists */
*CURoff,
*CURon;
#endif /*ZTERM*/
#if TTY_ANSI
#if OS_DOS
char *TERMNAME = "braindamaged ansi",
#else
char *TERMNAME = "hardwired ansi",
#endif
*HO = "\033[H",
*UP = "\033[A",
*CE = "\033[K",
*CL = "\033[H\033[J",
#if OS_DOS
*OL = NULL,
*UpS = NULL,
#else
*OL = "\033[L",
*UpS = "\033[L",
#endif
*BELL= "\007",
*CM = "\033[%d;%dH",
*CURoff,
*CURon;
#endif /*TTY_ANSI*/
#if TTY_VT52
#if OS_ATARI
char *TERMNAME = "Atari ST",
#else
#if OS_FLEXOS
char *TERMNAME = "Flexos console",
#else
char *TERMNAME = "hardwired vt52",
#endif /*OS_FLEXOS*/
#endif /*OS_ATARI*/
*HO = "\033H",
*UP = "\033A",
*CE = "\033K",
*CL = "\033E",
*OL = "\033L",
*BELL= "\007",
*CM = "\033Y??",
#if OS_FLEXOS
*UpS = NULL, /* Reverse scrolling is painfully slow */
#else
*UpS = "\033I",
#endif
*CURoff= "\033f",
*CURon = "\033e";
#endif /*TTY_VT52*/
#if USE_TERMCAP
bool CA, canUPSCROLL;
char FkL, CurRT, CurLT, CurUP, CurDN;
char *TERMNAME, /* will be set in termcap handling */
*HO,
*UP,
*CE,
*CL,
*OL,
*BELL,
*CM,
*UpS,
*CURoff,
*CURon;
#endif /*USE_TERMCAP*/
char Erasechar = ERASE, /* our erase character */
eraseline = 'X'-'@'; /* and line-kill character */
char fismod[] = "File is modified", /* File is modified message */
fisro[] = "File is readonly"; /* when you can't write the file */
char *excmds[] = {
"print", /* lines to screen */
"quit", /* quit editor */
"read", /* add file to buffer */
"edit", /* replace buffer with file */
"write", /* write out file */
"wq", /* write file and quit */
"next", /* make new arglist or traverse this one */
"substitute", /* pattern */
"xit", /* write changes and quit */
"file", /* show/set file name */
"set", /* options */
"rm", /* a file */
"previous", /* back up in arglist */
"delete", /* lines from buffer */
"=", /* tell line number */
"yank", /* lines from buffer */
"put", /* back yanked lines */
"visual", /* go to visual mode */
"exec", /* go to exec mode */
"insert", /* text below current line */
"open", /* insert text above current line */
"change", /* lines */
"undo", /* last change */
"!", /* shell escape */
"map", /* keyboard macro */
"unmap", /* keyboard macro */
"source", /* read commands from file */
"version", /* print version # */
"args", /* print argument list */
"rewind", /* rewind argument list */
NULL
};
char wordset[] = "0123456789$_#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char spaces[] = { TAB,EOL,' ',0 };
int shiftwidth = 4,
#if USE_TERMCAP | OS_ATARI
dofscroll,
#else
dofscroll = LINES/2,
#endif
tabsize = 8;
int autoindent = YES,
autocopy = NO,
autowrite = YES,
wrapscan = YES,
overwrite = YES,
beautify = YES,
list = NO,
magic = YES,
bell = YES,
#if OS_ATARI
mapslash,
#endif
ignorecase = NO;
struct variable vars[]={
{"terminal", "", VSTR, V_CONST, (void*)&TERMNAME },
{"shiftwidth","sw", VINT, 0, (void*)&shiftwidth },
{"scroll", "", VINT, 0, (void*)&dofscroll },
{"tabsize", "ts", VINT, V_DISPLAY, (void*)&tabsize },
{"autoindent","ai", VBOOL, 0, (void*)&autoindent },
{"autocopy", "ac", VBOOL, 0, (void*)&autocopy },
{"autowrite", "aw", VBOOL, 0, (void*)&autowrite },
{"wrapscan", "ws", VBOOL, 0, (void*)&wrapscan },
{"overwrite", "ow", VBOOL, 0, (void*)&overwrite },
{"beautify", "be", VBOOL, 0, (void*)&beautify },
{"list", "", VBOOL, V_DISPLAY, (void*)&list },
{"magic", "", VBOOL, 0, (void*)&magic },
{"ignorecase","ic", VBOOL, 0, (void*)&ignorecase },
{"bell", "", VBOOL, 0, (void*)&bell },
#if OS_ATARI
{"mapslash", "ms", VBOOL, 0, (void*)&mapslash },
#endif
{NULL}
};
/* For movement routines */
int setstep[2] = {-1,1};
/* Where the last diddling left us */
struct coord curpos={0, 0};
/* initialize the buffer */
int bufmax = 0, /* End of file here */
lstart = 0, lend = 0, /* Start & end of current line */
ptop = 0, pend = 0, /* Top & bottom of CRT window */
curr = 0, /* Global cursor pos */
xp = 0, yp = 0, /* Cursor window position */
count = 0; /* Latest count */
bool modified= NO, /* File has been modified */
readonly= NO, /* is this file readonly? */
needchar= YES, /* Peekc flag */
deranged= NO, /* Up-arrow || down-arrow left xpos in Oz. */
indirect= NO, /* Reading from an indirect file?? */
redoing = NO, /* doing a redo? */
xerox = NO, /* making a redo buffer? */
newfile = YES, /* Editing a new file? */
newline = NO, /* Last insert/delete included a EOL */
lineonly= NO, /* Dumb terminal? */
zotscreen=NO, /* ask for [more] in execmode */
diddled = NO; /* force new window in editcore */
int macro = -1; /* Index into MCR */
char lsearch = 0; /* for N and n'ing... */
/* movement, command codes */
cmdtype movemap[256]={
/*^@*/ BAD_COMMAND,
/*^A*/ DEBUG_C,
/*^B*/ HARDMACRO,
/*^C*/ BAD_COMMAND,
/*^D*/ WINDOW_UP,
/*^E*/ HARDMACRO,
/*^F*/ HARDMACRO,
/*^G*/ FILE_C,
/*^H*/ GO_LEFT, /* also leftarrow */
/*^I*/ REDRAW_C,
/*^J*/ GO_DOWN, /* also downarrow */
/*^K*/ GO_UP, /* also uparrow */
/*^L*/ GO_RIGHT, /* also rightarrow */
/*^M*/ CR_FWD,
/*^N*/ BAD_COMMAND,
/*^O*/ BAD_COMMAND,
/*^P*/ BAD_COMMAND,
/*^Q*/ BAD_COMMAND,
/*^R*/ BAD_COMMAND,
/*^S*/ BAD_COMMAND,
/*^T*/ BAD_COMMAND,
/*^U*/ WINDOW_DOWN,
/*^V*/ BAD_COMMAND,
/*^W*/ BAD_COMMAND,
/*^X*/ BAD_COMMAND,
/*^Y*/ HARDMACRO,
/*^Z*/ BAD_COMMAND,
/*^[*/ BAD_COMMAND,
/*^\*/ BAD_COMMAND,
/*^]*/ BAD_COMMAND,
/*^^*/ BAD_COMMAND,
/*^_*/ BAD_COMMAND,
/* */ GO_RIGHT,
/*! */ EXEC_C,
/*" */ BAD_COMMAND,
/*# */ BAD_COMMAND,
/*$ */ TO_EOL,
/*% */ MATCHEXPR,
/*& */ RESUBST_C,
/*\ */ TO_MARK_LINE,
/*( */ SENT_BACK,
/*) */ SENT_FWD,
/** */ BAD_COMMAND,
/*+ */ CR_FWD,
/*, */ BAD_COMMAND,
/*- */ CR_BACK,
/*. */ REDO_C,
/*/ */ PATT_FWD,
/*0 */ TO_COL,
/*1 */ BAD_COMMAND,
/*2 */ BAD_COMMAND,
/*3 */ BAD_COMMAND,
/*4 */ BAD_COMMAND,
/*5 */ BAD_COMMAND,
/*6 */ BAD_COMMAND,
/*7 */ BAD_COMMAND,
/*8 */ BAD_COMMAND,
/*9 */ BAD_COMMAND,
/*: */ COLIN_C,
/*; */ BAD_COMMAND,
/*< */ ADJUST_C,
/*= */ BAD_COMMAND,
/*> */ ADJUST_C,
/*? */ PATT_BACK,
/*@ */ BAD_COMMAND,
/*A */ A_AT_END,
/*B */ BACK_WD,
/*C */ HARDMACRO,
/*D */ HARDMACRO,
/*E */ BAD_COMMAND,
/*F */ BACK_CHAR,
/*G */ GLOBAL_LINE,
/*H */ PAGE_BEGIN,
/*I */ I_AT_NONWHITE,
/*J */ JOIN_C,
/*K */ BAD_COMMAND,
/*L */ PAGE_END,
/*M */ PAGE_MIDDLE,
/*N */ BSEARCH,
/*O */ OPENUP_C,
/*P */ PUT_AFTER,
/*Q */ EDIT_C,
/*R */ BIG_REPL_C,
/*S */ BAD_COMMAND,
/*T */ BACKTO_CHAR,
/*U */ BAD_COMMAND,
/*V */ BAD_COMMAND,
/*W */ FORWD,
/*X */ HARDMACRO,
/*Y */ HARDMACRO,
/*Z */ ZZ_C,
/*[ */ BAD_COMMAND,
/*\ */ BAD_COMMAND,
/*] */ BAD_COMMAND,
/*^ */ NOTWHITE,
/*_ */ BAD_COMMAND,
/*` */ TO_MARK,
/*a */ APPEND_C,
/*b */ BACK_WD,
/*c */ CHANGE_C,
/*d */ DELETE_C,
/*e */ FORWD,
/*f */ TO_CHAR,
/*g */ BAD_COMMAND,
/*h */ GO_LEFT,
/*i */ INSERT_C,
/*j */ GO_DOWN,
/*k */ GO_UP,
/*l */ GO_RIGHT,
/*m */ MARKER_C,
/*n */ FSEARCH,
/*o */ OPEN_C,
/*p */ PUT_BEFORE,
/*q */ BAD_COMMAND,
/*r */ REPLACE_C,
/*s */ HARDMACRO,
/*t */ UPTO_CHAR,
/*u */ UNDO_C,
/*v */ BTO_WD,
/*w */ TO_WD,
/*x */ HARDMACRO,
/*y */ YANK_C,
/*z */ REWINDOW,
/*{ */ PARA_BACK,
/*| */ TO_COL,
/*} */ PARA_FWD,
/*~ */ TWIDDLE_C,
/*^?*/ BAD_COMMAND,
/*80*/ BAD_COMMAND,
/*81*/ BAD_COMMAND,
/*82*/ BAD_COMMAND,
/*83*/ BAD_COMMAND,
/*84*/ BAD_COMMAND,
/*85*/ BAD_COMMAND,
/*x6*/ BAD_COMMAND,
/*x7*/ BAD_COMMAND,
/*x8*/ BAD_COMMAND,
/*x9*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND,
/*xx*/ BAD_COMMAND
};

36
src/cmd/levee/grep.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#define LEND '$'
#define LSTART '^'
#define LITCHAR 'c'
#define ANY '.'
#define CCL '['
#define NCCL '!'
#define DASH '-'
#define CCLEND ']'
#define NEGATE '^'
#define CLOSURE '*'
#define ESCAPE '\\'
#define TOKENB '<'
#define TOKENE '>'
#define ARGSTART '('
#define ARGEND ')'
#define AMPERSAND '&'

156
src/cmd/levee/insert.c Normal file
View File

@@ -0,0 +1,156 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
int PROC
insertion(count, openflag, dp, yp, visual)
int count, openflag, *dp, *yp;
bool visual;
{
char cmd, c;
int rp; /* number of spaces to diddle */
int ts, ss; /* tabs && spaces to insert */
register int cp; /* current position */
int i; /* random index */
int endd; /* last open place */
register int rsize; /* size of upper buffer */
int currDLE = 0; /* what DLE is now */
int len; /* full insert size */
bool Dflag;
if (openflag != 0) { /* opening a line above || below */
if (openflag<0 && bufmax>0 && curr<bufmax) {
curr = 1+lend;
if (visual)
zwrite("\n", 1);
}
else { /* open above current line */
(*yp)--;
curr = lstart;
}
if (autoindent)
currDLE = findDLE(lstart, &i, skipws(lstart),0);
if (visual) {
#if TTY_VT52
if (OL) {
#else
if (OL && (*yp) < LINES-2) {
#endif
strput(OL);
(*yp)++;
curpos.y = *yp;
}
else {
mvcur(1+(*yp), 0);
strput(CE);
}
}
mvcur(-1, currDLE);
}
else {
if (autoindent)
currDLE = findDLE(lstart, &i, curr, 0);
if (curr == i) {
if (!delete_to_undo(&undo, lstart, i-lstart))
return(-1);
curr = lstart;
}
}
rsize = (bufmax-curr); /* amount of stuff above curr */
endd = SIZE - rsize; /* split the buffer */
if (rsize > 0)
moveright(&core[curr], &core[endd], rsize);
cp = curr;
do { /* Insert loop */
Dflag = (cp==0 || core[cp-1]==EOL);
do {
if (Dflag)
while ((cmd=peekc()) == '' || cmd == '') {
if (readchar() == '')
currDLE = min(COLS,currDLE+shiftwidth);
else
currDLE = max(0,currDLE-shiftwidth);
mvcur(-1, currDLE);
}
} while (!(c = line(core, cp, endd-1, &len)));
if (Dflag && (len > 0 || c == ESC)) {
/* makeDLE : optimize leading whitespace for insert */
currDLE = findDLE(cp, &rp, cp+len, currDLE);
if (rp > cp) {
len -= (rp-cp);
moveleft(&core[rp], &core[cp], len); /* squash whitespace */
}
if (currDLE > 0) { /* create DLE indent */
ts = currDLE / tabsize;
ss = currDLE % tabsize;
moveright(&core[cp], &core[cp+ts+ss], len);
len += (ts+ss);
fillchar(&core[cp ], ts, TAB);
fillchar(&core[cp+ts], ss, 32);
}
}
cp += len;
if (c == EOL) { /* Diddle-Diddle */
core[cp++] = EOL; /* add in a \n */
strput(CE); /* clear this line */
println();
if (visual) {
#if OS_RMX
/* at OL at bottom kludge... */
if (OL && (*yp) < LINES-2) {
#else
if (OL) {
#endif
strput(OL);
(*yp)++;
}
else
strput(CE);
}
if (!autoindent) /* reset currDLE? */
currDLE = 0;
mvcur(-1, currDLE);
}
} while (c != ESC && cp <= endd-INSSIZE);
*dp = cp; /* start display here */
if (count > 1) { /* repeated insertion */
len = cp-curr;
if ((count-1)*len < endd-cp)
for (i = 1;i <count;i++) {
moveright(&core[cp-len], &core[cp], len);
cp += len;
}
}
if (openflag != 0 /* open or insert at end of buffer */
|| (rsize < 1 && cp > curr && core[cp-1] != EOL))
core[cp++] = EOL;
len = cp-curr;
if (rsize > 0) /* if not at end of buffer, stitch things together */
moveleft(&core[endd], &core[cp], rsize);
insert_to_undo(&undo, curr, len);
core[bufmax] = EOL;
return(cp);
}

386
src/cmd/levee/levee.h Normal file
View File

@@ -0,0 +1,386 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1980-2008 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*
* Levee v3.C
* C version for Unix/Atari ST/MS-DOS/OS-2/FlexOs/iRMX/etc
* Pascal version for UCSD Pascal 4.X
*
* written fall 82' - now (approx) by David L. Parsons.
*
* many patches, suggestions,
* and impractical design goals by:
* Jim Bolland,
* John Plocher,
* John Tainter
*/
#ifndef LEVEE_D
#define LEVEE_D
#include "config.h"
#ifndef TRUE
#define TRUE (1) /* Nobody defines TRUE & FALSE, so I will do */
#define FALSE (0) /* it myself */
#endif
#define HANDLE int /* default file handle type */
#define PROC /* for magic function types (MSDOS) */
#define VOID void /* ancient creaking C compilers won't understand void */
/*
* Compilation defines for different systems.
*/
#if OS_ATARI
#include <stdio.h>
#define void int /* Alcyon C don't know void */
/* extractions from osbind.h */
#define OPEN_OLD(n) gemdos(0x3d,n,/*open mode*/0)
#define OPEN_NEW(n) gemdos(0x3c,n,/*permissions*/0)
#define CLOSE_FILE(f) gemdos(0x3e,f)
#define SEEK_POSITION(f,o,m) gemdos(0x42,(long)(o),f,m)
#define READ_TEXT(f,b,c) gemdos(0x3f,f,(long)(c),b)
#define WRITE_TEXT(f,b,c) gemdos(0x40,f,(long)(c),b)
extern char *malloc();
extern long gemdos();
#endif /*OS_ATARI*/
#if OS_RMX
#include <:inc:stdio.h>
#include <:inc:udi.h>
#define OPEN_OLD(n) open(n, /*open mode*/0)
#define OPEN_NEW(n) creat(n,/*permissions*/0)
#define CLOSE_FILE(f) close(f)
#define SEEK_POSITION(f,o,m) lseek((f),(long)(o),(m))
#define READ_TEXT(f,p,c) read((f),(p),(unsigned)(c))
#define WRITE_TEXT(f,p,c) write((f),(p),(unsigned)(c))
#define zwrite(p,s) write(1,(p), (unsigned)(s))
#endif /*OS_RMX*/
#if OS_DOS
#include <stdio.h>
#include <fcntl.h>
#define OPEN_OLD(n) open(n, O_RDONLY|O_BINARY)
#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666)
#define CLOSE_FILE(f) close(f)
#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
#define READ_TEXT(f,p,c) read(f, p, (int)(c))
#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s)
#undef PROC
#define PROC _fastcall
#include "proto.h"
#endif /*OS_DOS*/
#if OS_UNIX
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#define OPEN_OLD(n) open(n, O_RDONLY)
#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC, 0666)
#define CLOSE_FILE(f) close(f)
#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
#define READ_TEXT(f,p,c) read(f, p, (int)(c))
#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
#define zwrite(p,s) fwrite(p, 1, s, stdout)
#endif /*OS_UNIX*/
#if OS_FLEXOS
#include <stdio.h>
#define OPEN_OLD(n) s_open(m,0x08) /* note reversed parameters! */
#define OPEN_NEW(n) s_create(0,0,n,0,0/*mode*/,0)
#define CLOSE_FILE(f) s_close(0,f) /* Full close on handle */
#define SEEK_POSITION(f,o,m) s_seek((m&03)<<9, f, o)
#define READ_TEXT(f,p,c) s_read(0x0100,(long)(f),p,(long)(c),0L)
#define WRITE_TEXT(f,p,c) s_write(0x0101,(long)(f),p,(long)(c),0L)
#define zwrite(p,s) s_write(0x0101, 1L, p, (long)(s),0L)
#define unlink(n) s_delete(0, n)
#define rename(a,b) s_rename(0, a, b)
/* OPEN_OLD mode flags */
#undef HANDLE
#define HANDLE long
#endif /*OS_FLEXOS*/
#define bool int
/* ttydef stuff */
#if !(OS_ATARI | USE_TERMCAP)
#ifndef LINES
#define LINES 25
#endif /*LINES*/
#define COLS 79
#endif
#define YES 1
#define NO 0
#define UPARROW 11
#define DNARROW 10
#define LTARROW erase
#define RTARROW 12
#if !USE_TERMCAP
#define CA TRUE
#if !(OS_DOS||OS_FLEXOS)
#define canUPSCROLL 1
#endif
#endif
/* nospecific stuff */
#define MAGICNUMBER 42
#define hell_freezes_over FALSE
#define BUGS 7 /* sometime when you least expect it.. */
#define DW 23 /* Delete Word */
#define EOL 10 /* End Of Line */
#define DLE 16 /* Space compression lead-in */
#define ESC 27 /* Escape */
/* hardwired line kill and erase character for non-unix machines */
#define DEL 21 /* ^U */
#if RMX
#define ERASE 127
#else
#define ERASE 8 /* ^H */
#endif
#define TAB 9
/* variable types */
#define VBOOL 0
#define VINT 1
#define VSTR 2
#define ERR (-1)
/* Undostack commands */
#define U_ADDC 'A'
#define U_MOVEC 'M'
#define U_DELC 'D'
/* magic things for find */
#define MAXPAT ((int)300)
/* exec mode commands */
#define EX_CR (ERR-1)
#define EX_PR 0
#define EX_QUIT 1
#define EX_READ 2
#define EX_EDIT 3
#define EX_WRITE 4
#define EX_WQ 5
#define EX_NEXT 6
#define EX_SUBS 7
#define EX_XIT 8
#define EX_FILE 9
#define EX_SET 10
#define EX_RM 11
#define EX_PREV 12
#define EX_DELETE 13
#define EX_LINE 14
#define EX_YANK 15
#define EX_PUT 16
#define EX_VI 17
#define EX_EX 18
#define EX_INSERT 19
#define EX_OPEN 20
#define EX_CHANGE 21
#define EX_UNDO 22
#define EX_ESCAPE 23
#define EX_MAP 24
#define EX_UNMAP 25
#define EX_SOURCE 26
#define EX_VERSION 27
#define EX_ARGS 28
#define EX_REWIND 29
/* movement return states */
#define LEGALMOVE 0
#define BADMOVE 1
#define ESCAPED 2
#define findstates char
/* command codes */
#define BAD_COMMAND 0
/*visual movement*/
#define GO_RIGHT 1
#define GO_LEFT 2
#define GO_UP 3
#define GO_DOWN 4
#define FORWD 5
#define TO_WD 6
#define BACK_WD 7
#define BTO_WD 8
#define NOTWHITE 9
#define TO_COL 10
#define TO_EOL 11
#define MATCHEXPR 12
#define TO_CHAR 13
#define UPTO_CHAR 14
#define BACK_CHAR 15
#define BACKTO_CHAR 16
#define SENT_FWD 17
#define SENT_BACK 18
#define PAGE_BEGIN 19
#define PAGE_END 20
#define PAGE_MIDDLE 21
#define CR_FWD 22
#define CR_BACK 23
#define PATT_FWD 24
#define PATT_BACK 25
#define FSEARCH 26
#define BSEARCH 27
#define GLOBAL_LINE 28
#define TO_MARK 29
#define TO_MARK_LINE 30
#define PARA_FWD 31
#define PARA_BACK 32
/*modifications*/
#define DELETE_C 39
#define EXEC_C 40
#define ADJUST_C 41
#define CHANGE_C 42
#define YANK_C 43
#define INSERT_C 44
#define APPEND_C 45
#define I_AT_NONWHITE 46
#define A_AT_END 47
#define OPEN_C 48
#define OPENUP_C 49
#define REPLACE_C 50
#define TWIDDLE_C 51
#define RESUBST_C 52
#define JOIN_C 53
#define UNDO_C 54
#define BIG_REPL_C 55
#define PUT_BEFORE 56
#define PUT_AFTER 57
/*everything else*/
#define HARDMACRO 70
#define REWINDOW 71
#define ZZ_C 72
#define DEBUG_C 73
#define FILE_C 74
#define WINDOW_UP 75
#define WINDOW_DOWN 76
#define REDRAW_C 77
#define MARKER_C 78
#define REDO_C 79
#define EDIT_C 80
#define COLIN_C 81
/*macros*/
#define SOFTMACRO 100
#define INSMACRO 101
#define cmdtype char
/* exec mode states */
#define E_VISUAL 0
#define E_INIT 1
#define E_EDIT 2
#define exec_type char
/* various sizes */
#define INSSIZE ((int)80) /* Insert string size */
#define FSIZE ((int)39) /* File string size */
#ifndef SIZE
# define SIZE ((int)32760) /* Edit buffer size */
#endif
#define SBUFSIZE ((int)4096) /* Incore yank buffer size */
#define MAXMACROS 32 /* Maximum # of macros */
#define NMACROS 9 /* Nexting level for macros */
#define PAGESIZE ((int)1024) /* Bytes per block */
struct coord { /* Screen Coordinate */
int x,y;
};
struct ybuf { /* Yank Buffer */
int size; /* Bytes yanked */
bool lines, /* Yanked whole lines? */
has_eol; /* Yanked a EOL? */
char stuff[SBUFSIZE]; /* The stuff */
};
struct undostack { /* Undo Stack Descriptor */
int blockp, /* block address of core block */
ptr; /* offset within coreblock */
int coreblock[PAGESIZE]; /* core block */
};
union optionrec { /* Black Magic Option Structure */
int valu; /* if integer, the value */
char *strp; /* or if string, a pointer to it */
};
struct macrecord { /* Macro Descriptor */
char token; /* Character mapped */
cmdtype oldmap; /* Old value in movemap */
char *m_text; /* Replacement text */
};
struct tmacro { /* For running a macro */
char *mtext, /* Pointer to macro text */
*ip; /* Pointer into macro text */
int m_iter; /* Number of times to execute */
};
#define V_CONST 1 /* this option cannot be modified */
#define V_DISPLAY 2 /* this option affects the display */
struct variable { /* Settable Variable Record */
char *v_name; /* full name */
char *v_abbr; /* abbreviated name */
int v_tipe; /* what kind of variable */
int v_flags; /* special attributes... */
union optionrec *u; /* pointer to it */
};
#endif /*LEVEE_D*/

955
src/cmd/levee/lv.1 Normal file
View File

@@ -0,0 +1,955 @@
.TH LEVEE 1 "29 August 1998" "Mastodon Linux"
.SH NAME
.B levee
\-
A Screen Oriented Editor.
.SH SYNOPSIS
.B levee
[\fI+address\fR] [\fIfile \fB...\fR]
.SH DESCRIPTION
Levee is a screen oriented editor based on the Unix editor
"vi". It provides a terse, powerful way to enter and edit text
(however, if you want a word-processor, you're better off with
WordStar.)
Levee is a moded editor. It operates in 3 modes -- visual,
command, and insert. Most of the editing work is done is visual
mode, file reading and writing is done in command mode, and
insert mode does what you would expect.
.PP
When you enter Levee, you may specify an address to start
editing at. These addresses are in the same format as command
mode addresses, except that a naked + will put you at the very
end of the file.
.PP
Levee is copyright (c) 1982-2008 by David L. Parsons. (see
the notice at the end of this document for distribution terms)
.SH "COMMAND MODE COMMANDS"
These commands are used for editing new files, writing
modified files, changing options, doing substitutions, and
a subset of the visual commands. They take as input whole
lines, terminated by return (to execute), or escape (to
abort.)
Command mode is reached by typing ":" or "Q" from visual
mode. If you enter command mode by typing ":", Levee will
execute one command, then return to visual mode after
prompting you with "[more]". If you type anything except
a space or return, Levee will accept another command, and so
forth. If, however, you enter command mode via "Q", Levee
will remain in command mode until you enter the "visual"
command.
.SS "A NOTE ON COMMAND SYNTAX"
.PP
A command may be preceded by an optional line-range. If
you do not provide a line-range, Levee will use the default
line-range shown by the command. A line-range is one or two
address specifications in the following format:
.RS
(\fB.\fR|\fB$\fR|\fB'x\fR|\fB#\fR) [ (\fB+\fR|\fB-\fR) (\fB/\fIpatt\fB\fB/\fR|\fB?\fIpatt\fB?\fR|\fB#\fR) ]
.TP
.B \.
current line.
.TP
.B $
last line.
.TP
.B 'x
the line with mark x on it.
.TP
.B #
line #.
.RE
.PP
For example, ".-5,.+5p" will print every line within ten
lines of the current line. "$-5" is the fifth line from the
end of the file, and "/end/+2" is the second line past the
next occurrence of the pattern "end". Patterns may be
regular expressions (see below.)
Also, a naked line-range will set the current line to
the first line in the range and print all the lines in that
range. "1,10" sets the current line to 1, then prints lines
1 to 10.
If you specify a non-existent line in a range, the command
will abort and Levee will tell you "bad address".
.SS "Command mode commands"
.TP
.B args
show the current argument list, if one exists. The file that you
are currently editing will be framed by '[' and ']'.
.TP
.IB (.,.) change
delete lines, then enter insert mode.
.TP
.IB (.,.) delete
delete lines. Deleted lines are stored in a Yank Buffer for
later putback with "put".
.TP
.B "edit[!] [file]"
Discard the current file and start editing a new one. If
changes were made to the current file, you must enter "edit!"
to force Levee to discard the changes. If you do not specify
a filename, Levee will try to reedit the current filename.
When Levee reads in a new file, it will tell you how many
bytes it read in, or [overflow] if the file is larger than the
internal buffer (256000 bytes on most platforms; 20k on USCD
Pascal.)
.TP
.B execmode
Remain in command mode until you use the "visual" command.
.TP
.BI file [name]
Echo what the current filename is, its status, and the current
line. If you provide it with a name, it will change the filename
to that.
.TP
.IB (.) insert
Insert text above the current line. If you specify a line number,
Levee will make that the current line, then insert above it.
.RS
.SS "Insert mode commands"
.TP
.B ^W
back over the last word you entered.
.TP
.B ^H
back over one character.
.TP
.B ^U
back over all input on this line.
.TP
.B ^V
escape the next character typed. (For example,
.B ^V^H
will put a ^H into the file.)
.TP
.B ESC
exit insert mode.
.TP
.B ^D
If at start of line, reduce indentation 'shiftwidth' columns.
.TP
.B ^T
If at start of line, increase indentation 'shiftwidth' columns.
.RE
.PP
When in insert mode, Levee will not allow you to enter any control
characters except return and tab. Return ends input on this line and
opens a new line for input.
.TP
.BI map[!] [key [text]]
Define/list macros. There are 3 forms of map:
.TP
.I map.
This lists all the active macros.
.TP
.IR map (key).
This shows the macro associated with (key), if any.
.TP
.IR map "(key) (text)"
This maps (key) to (text). You may map any
key except ":" and escape. In the normal
form (map), the macro will be effective
in visual mode, but in the alternate form,
(map!), the macro will be effective in
insert and command modes.
.PP
For example, if you map!ped return to "hello world", every time
you entered a return in command or visual mode, the string "hello
world" would pop up.
.TP
.BI next [file ...]
Edit the next file in the arglist, or edit a new arglist. Levee
takes its initial arglist off the command line when you execute it.
If "autowrite" is set, Levee will write out the changes to the
current file before editing the next one.
.TP
.IB (.) open
Insert below the current line. Otherwise just like insert.
.TP
.B previous
Edit the previous file in the arglist. Otherwise, like next.
.TP
.IB (.,.) print
Display lines without changing the current line.
.TP
.IB (.) put
Put the contents of the yank buffer back on the line below
the current line. If you specify a line, it resets the current
line, then puts the yank buffer back. The yank buffer is filled
by the delete, change, or yank commands. Put does not destroy
the yank buffer, so you may put back text multiple times.
.TP
.B quit[!]
Exit Levee. If you want to discard changes, use "quit!"
.TP
.IB (.) read [file]
put the contents of 'file' after the current line.
.TP
.BI rm file
Delete 'file' from disk.
.TP
.BI set [option=value]
Set a tunable variable. Levee has a dozen or so user-definable
variables which you can twiddle via this command. There are boolean,
integer, and string variables that you can set. A string or integer
variable is set by 'set xxx=yyy', a boolean variable is set via
'set xxx' or 'set noxxx'.
Here are the settable variables (and abbreviations):
.TP
.BI tabsize (ts)
tab stop.
.TP
.BI shiftwidth (sw)
columns to shift on ^D, ^T, >>, or <<
.TP
.B scroll
number of lines to scroll on ^D, ^U
.TP
.BI autoindent (ai)
supply indentation during insert mode.
.TP
.BI autowrite (aw)
write out changes before :next, :prev
.TP
.BI autocopy (ac)
make backup copies before writing changes.
.TP
.B list
display tabs as ^I, end of line as $.
.TP
.B magic
use regular expressions in searches.
.TP
.B suffix
if the filename does not have a . in
it, supply the suffix. (this is the
only string variable.)
.TP
.BI overwrite (ow)
destroy old file first, then write.
.TP
.BI beautify (be)
When set, Levee will not allow insert
of any control character except tab
and return unless you escape it with
ctrl-V.
.TP
.B wrapscan
searches wrap around end of buffer.
.TP
.BI ignorecase (ic)
Ignore the case of alphabetic characters
during searches.
.TP
.B "mapslash"
(ST version only) Map '/' in filenames to
'\\'. If the environment contains `mapslash'
when levee is called, this variable will
default to true, otherwise it defaults to
false. (See the documentation for the
Teeny-shell on how the teeny-shell interprets
`mapslash')
.TP
.BI lines (li)
(ST version only) How many lines on the display.
This is primarily for running levee through
the serial port - put set li=xx into your
LVRC for a xx line terminal.
.TP
.BI cols (co)
(ST version only) How many columns on the
display. Like the lines variable, it's for
running levee through the serial port.
.PP
You may set multiple variables on one line, as in 'set ws noai'.
To see the current settings of these variables, :set -- without any
arguments -- will show the current settings.
At startup, Levee looks in the environment variable LVRC for
a list of variables to set (GEMDOS/MS-DOS). LVRC is one line
of the form 'option=value ...'. If you have a LVRC defined that
is 'ts=4 ow nows', Levee will set tabsize to 4, turn on overwrite,
and turn off wrapscan.
If you are using RMX, Levee looks in the file ":home:r?lvrc"
for initialization. If you are using Osy/SWOs, Levee looks in the
file "*.lvrc". The format of these files are different from the
LVRC variable -- see "source" for more information.
.TP
.BI source file
Take command mode commands from 'file'. These commands can be
any legal command, except "visual". If a error happens during
execution of 'file', Levee abandons that level of source'ing.
In Osy/SWOs, there are a few differences in insert mode from
within a sourced file. No character has special meaning except a
line containing nothing but a period, which terminates insert mode.
For example:
.RS
:commands
.br
.
.br
.
.br
:insert
.br
blah blah blah blah blah blah
.br
blah blah blah blah blah blah
.br
blah blah blah blah blah blah
.br
.
.br
:more commands
.RE
If you are running Levee under any other operating system,
you cannot do a insert from a :source file.
.TP
.B (.,.)substitute(delim)patt(delim)repl(delim)[qcpg]
.TP
.B (.,.)substitute&
Search for patt and replace it with repl. Levee will look for
patt once on each line and replace it with repl. The delimiter
may be any ascii character.
The pattern is a regular expression, just like a search pattern.
You may include parts of the pattern in the replacement string;
A '&' in the replacement pattern copies in the whole source pattern,
so if you do a 'sub/this/& and that/g', every instance of 'this'
will be replaced with 'this and that'. Also, you may pull parts of
the pattern out by using the \\( and \\) argument meta-characters.
Arguments gotten by \\( & \\) are put into the replacement string
everywhere you do a \\1..\\9 [ \\1 is the first argument you set up
with \\( & \\) ]. So, if you want to reverse the order of two substrings,
you can do 'sub/\\(string1\\)\\(string2\\)/\\2\\1/'.
substitute& redoes the last substitution.
Options:
.TP
.B q,c
before doing the substitute, display the affected
line and wait for you to type a character. If you
type 'y', it will do the substitution. 'q' aborts
the substitute, 'a' does the rest of the change
without prompting, and 'n' does not do it.
.TP
.B p
print the affected lines after the change.
.TP
.B g
do the change globally. That is, do it for every
occurence of patt on a line, rather than just
once.
.PP
.TP
.B undo
Undo the last modification to the file (except :edit, :next, :rm,
or :write.) You can only undo the last change to a file -- undo counts
as a change. :undo followed by :undo does nothing to the file.
.TP
.BI unmap (key)
Undefine a macro (see map).
.TP
.BI visual [list]
If you entered command mode by "Q" or "execmode", return to
visual mode. If you provide an argument list, it also does a
`:next' on that list.
.TP
.B version
Show which version of levee this is.
.TP
.IB (.,.) "write \fI[file]"
Write lines to a file. If you write the everything to 'file',
the filename is set to 'file', and if you do not specify a file,
Levee will write to the filename.
.TP
.IB (.,.) "wq \fI[file]"
Write to a file, then quit.
.TP
.IB (.,.) yank
Yank lines from the file into the yank buffer, for later
putback with "put".
.TP
.B xit[!]
Write changes to the current file, then exit. If there are
more files in the arglist, use "xit!"
.TP
.B ![command]
Execute command.
Example:
.RS
!ls => does a 'ls'.
.RE
This command is available only under GEMDOS, MSDOS, RMX, and
Unix.
.TP
.B ($)=
Give the line number of the addressed line. /end/= gives you
the line number of the next line with a 'end' on it.
.SH "VISUAL MODE COMMANDS"
Visual mode commands move you around and modify the file.
There are movement commands to move the cursor by a variety of
objects.
In the description, a (#) means a optional count. If a
command has a optional count, it will tell you what the count
does in parenthesis. A (*) means that the command can be used
in the delete, yank, and change commands.
Counts are made up by entering digits. If you type '45',
the count will be set to 45. To cancel a count, type ESC.
This section discusses 'whitespace' occasionally.
Whitespace is tabs, spaces, and end of line.
.SS "How the display works"
Characters are displayed on the screen as you would
expect, except that nonprinting characters are shown as ^x,
and tabs expand to spaces ( unless you set the option list,
then they show as ^I.) When sitting on a control character or
tab, the cursor is placed on the FIRST character displayed. If
you move the cursor to any other part of them ( via j or k --
see below), any changes will start at the next character.
Levee does not display a end of file marker, but lines
past the end of the file are denoted by ~ lines.
If list is set, tabs display as ^I, and the end of line
displays as $.
If a line is too long for the screen, it will just disappear off the end of the screen.
Levee will handle any screen resolution and any monospaced
font you hand it ( if you are running in low resolution, Levee
will give you a 25x40 window, for example.)
.SS "Visual mode commands"
.TP
.B ^A
Show a debugging message at the bottom of the screen. This is not at
all useful unless you are debugging the editor. Ignore it.
.TP
.B (#)^D
Scroll the screen down a half screen. If a count is specified, scroll
down the specified number of lines.
.TP
.B ^E
Scroll down 1 line (shorthand for 1^D )
.TP
.B ^G
Show file statistics. Exactly like ':file'.
.TP
.IB (*) (#)^H
Move the cursor left one (count) chars.
.TP
.B ^I
Redraw the screen.
.TP
.IB (*) (#)^J
Move down one (count) lines. When you use ^J and ^K (below) to move
up or down lines, the cursor will remain in the same column, even if
it is in the middle of a tabstop or past the end of a line.
.TP
.IB (*) (#)^K
Move up one (count) lines.
.TP
.IB (*) (#)^L
Move right one (count) characters.
.TP
.IB (*) (#)^M
Move to the first nonwhite space on the next line. If a count is specified,
move to the first nonwhite count lines down.
.TP
.B (#)^U
Scroll the screen up a half page. If a count is specified, scroll up
count lines.
.TP
.B ^Y
Scroll the screen up 1 line (shorthand for 1^U.)
.TP
.B (#)a
Insert text AFTER the cursor. If you give a count, the insertion will
be repeated count times ( 40i-ESC will give you a line of 40 dashes).
The commands in insert mode are the same for visual and command mode.
.TP
.IB (*) (#)b
Move to the beginning of the last word (the count'th word back).
A word is a collection of alphanumeric characters (a-z0-9$_#) or
any other nonwhite character (i.e. anything but space, tab, eoln).
.TP
.B c
Change a object. Change deletes an object, then enters insert mode without
redrawing the screen. When you tell it the object to be changed, Levee
puts a '$' on the last character of the object. You cannot change
backwards.
The object may be any visual mode command marked with a '(*) '. For
example, 'c4l' will change the next 4 characters on the line to something
else. (4cl does the same thing -- 4c4l changes the next 16 characters on
this line.)
'cc' will change whole lines.
When changing, deleting, or yanking a object, it will be placed into
a yank buffer, where it can be retrieved by the 'p' or 'P' commands.
.TP
.B (#)d
Delete an object. Like 'cc', 'dd' affects whole lines.
.TP
.IB (*) (#)e
Move to the end of the current word.
.TP
.IB (*) (#)f(x)
Find the next (count'th) occurance of a character on the current line.
For example, if the cursor is sitting on the first character of the
line 'abcdef', typing "ff" will put the cursor on the 'f'.
.TP
.IB (*) (#)h
Move left one (count) characters. Exactly like ^H.
.TP
.B (#)i
Start inserting characters at the cursor. If you specify a count,
the insertion will be duplicated count times.
.TP
.IB (*) (#)j
Move down one (count) lines. Exactly like ^J.
.TP
.IB (*) (#)k
Move up one (count) lines. Exactly like ^K.
.TP
,B (*) (#)l
Move right one (count) character. Exactly like ^L.
.TP
.B m(x)
Set the marker (x). There are 26 markers available (a-z). You may
move to a marker by use of the ' or ` commands.
.TP
.IB (*) n
Find the next occurance of a search pattern. When you do a search with
a / or ? command, Levee will remember the pattern and the direction you
searched in. 'n' will search in the same direction for the pattern, 'N'
searches in the opposite direction.
.TP
.B o
Open a line below the current line for insertion.
.TP
.B p
Put yanked/deleted text back after the cursor. Text is yanked
by the delete (d,x,X,D), change (c,C,s,S), and yank (y,Y) commands.
.TP
.B (#)r(x)
Replace characters (up to end of line) with (x). '4ra' will change the
next 4 characters after the cursor into 'aaaa'.
.TP
.B (#)s
change one (count) characters. Shorthand for (#)cl.
.TP
.IB (*) (#)t(x)
Move up to a character on the current line. If you are on the first
character of the line 'abcdef' and you type 'tf', you will end up sitting
on the 'e'.
.TP
.B u
Undo last modification. You can undo ANY modification command except
:edit, :next, :rm, or :write. (Just like :undo).
.TP
.IB (*) (#)v
Move back to the very end of the previous (count'th) word.
See 'b' for the definition of a word.
.TP
.IB (*) (#)w
Move up to the very beginning of the next (count'th) word.
.TP
.B (#)x
Delete one (count) characters forward. Shorthand for (#)dl.
.TP
.B y
Yank an object for later use by put. 'yy' yanks whole lines.
.TP
.B A
Append text at the end of the line. Shorthand for $a.
.TP
.IB (*) (#)B
Move to the beginning of the current word. Exactly like 'b'.
.B NOTE:
this is incorrect. the capitalized word movement commands should,
and will in the future, be used for movement by space-delimited words.
.TP
.B C
Change to the end of the line. Shorthand for c$.
.TP
.B D
Delete to the end of the line. Shorthand for d$.
.TP
.IB (*) (#)F(x)
Move to the first (count'th) previous occurance of a character on the
current line. If you are sitting at the end of the line 'abcdef', typing
"Fa" will move you back to the 'a' at the start of the line.
.TP
.IB (*) (#)G
Goto line. If you specify a count, Levee will move to that line, and if
there is no count, Levee moves to the absolute end of the file.
To get to the start of the file, type "1G". To the end, just "G".
.TP
.IB (*) H
Move to the first nonwhite character at the top of the screen.
.TP
.B I
Insert at the end of the current line. Shorthand for $i.
.TP
.B (#)J
Join two (count+1) lines together. Joining appends the second line at
the end of the first, putting a space between them. If the first line
ends in whitespace, Levee will not put in a space.
.TP
.IB (*) L
Move to the last nonwhite character on the last line of the screen.
.TP
.IB (*) M
Move to the first nonwhite character in the middle of the screen.
.TP
.B O
Open a line above the current line. Otherwise works just like 'o'.
.TP
.B P
Put back the yank buffer at the cursor. Otherwise works just like 'p'.
.TP
.B Q
Enter and remain in command mode. Just like the command :exec. To get
back to visual mode, you must enter the command ':visual'.
.TP
.B R
Replace mode. A limited subset of insert mode that overwrites characters
up to end of line. All of the normal insert mode commands apply.
If you overwrite a character, then back over it with ^H,^U, or ^W, it
will reappear after you exit Replace mode.
Escape exits replace mode.
.B NOTE:
due to a bug, entering a <return> in Replace mode will drop you
back into visual mode with an error. The replacements you have made
will remain.
.TP
.B S
Change characters backwards. Shorthand for (#)ch.
.TP
.IB (*) (#)T(x)
Move back to character on current line. If you are on the last character
of the line 'abcdef', typing "Ta" will move you back to the 'b'.
.TP
.IB (*) (#)W
Move to end of word. Exactly like 'e'.
.TP
.B (#)X
Delete characters backwards. Shorthand for (#)dh.
.TP
.B Y
Yank to end of line. Shorthand for y$.
.TP
.B ZZ
Write changes to current file and exit if last file in arglist.
Exactly like :xit.
.TP
.IB (*) (#)$
Move to end of line. If you give a count, move to the end of the (count-1)
line down (so 2$ moves you to the end of the next line.).
.TP
.B 0
Move to the beginning of the current line. Shorthand for 0|.
.TP
.B (#)!
Pipe an object through an external program. Like 'cc', '!!' affects whole lines.
.TP
.IB (*) %
Find matching bracket, parenthesis, or squiggly bracket. If you are not
sitting on a '[]{}()', Levee will search forward for one of them on the
current line, then match whatever it finds.
.TP
.B [space]
Move to the first nonwhite character on the current line.
.TP
.B &
Redo last substitution command.
.TP
.IB (*) (#){
Move to the beginning of the count'th paragraph back. A paragraph is
delimited by a blank line.
.TP
.IB (*) (#)}
Move to the end of the count'th paragraph forward.
.TP
.IB (*) (#)(
Move to the beginning of the count'th sentence back. A sentence is
delimited by a ., a !, or a ? followed by a space, a tab, or end of line.
.TP
.IB (*) (#))
Move to the end of the count'th sentence forward.
.TP
.IB (*) (#)-
Move to the (count'th) previous line, first nonwhite.
.TP
.IB (*) (#)+
Move to the (count'th) next line, first nonwhite.
.TP
.B (#)~
Change the case of the next count characters. Upper case becomes lowercase,
lowercase becomes uppercase.
.TP
.IB (*) `(x)
Move to the exact position of mark (x). There is a special mark for some
of the visual mode move ment commands -- '' will move you to where you
were before the last (,),',`,G,/,?,n,N command.
.TP
.B :
Execute one command mode command. When the command is done, it will return
to visual mode if it produces one line of output, but if it scrolls the
screen, Levee will prompt [more] before returning to visual mode. If you
type a : in response to the [more] prompt, Levee will remain in command
mode for one more command.
.TP
.B (#)<(#)
Shift one (count) objects left. If you specify a second count, Levee will
shift the object left that many columns -- if you do not, they will be sh
shifted shiftwidth columns.
This is a nondestructive shift. If the shift would carry past the left
margin, the objects will be moved up to the left margin but no farther.
Like the other object movement commands, '<<' will affect whole lines.
.TP
.B (#)>(#)
Shift one (count) objects right. Just like <, except it will not shift
objects past the right margin of the screen. If you do shift an object
past the right margin of the screen, all of its indent will be removed
and it will end up by the left margin.
.TP
.B \.
Repeat last modification command. (except undo)
.TP
.IB (*) ?
Search for pattern backwards. Escape aborts the search pattern, and a
empty pattern means search for the last pattern again.
.TP
.IB (*) /
Search for pattern forwards. Otherwise like ?.
.TP
.B (#)|
Move to specified column. If you don't have a count, move to column 0.
.SH "REGULAR EXPRESSIONS"
Levee gives special meanings to some characters during
a pattern match. The character "." will match any one char,
the character "*" will match zero or more occurances of the
previous char ( so, a* will match 'a','aa','aaa', etc, or it
will match nothing at all). If a pattern begins with "^", it
will only match at the beginning of a line, and patterns
ending with a "$" will only match at the end of a line.
Brackets ('[]') have special meaning as well. They mean
match any one of the characters inside the brackets. '[abc]'
will match 'a', 'b', or 'c'. You may specify a range of
characters inside brackets by using a dash (-). '[a-z]' will
match any lowercase alphabetic character. If ^ is the first
character in the bracket, it means match any character
except those in the brackets. '[^abc]' will match anything
except 'a','b', or 'c'.
Backslash takes away special meaning for these chars,
but '\\t' specifies a tab, and \\( & \\) delimit arguments
inside a pattern (used only by :substitute.) The patterns
\\< and \\> have special meaning, too; they match the start
and end of alpha-numeric tokens.
If you turn off the editor variable 'magic', none of
the above characters will have special meaning inside of
a pattern (see 'set').
Some example patterns:
.TP
.B ^end$
Find a line that is just 'end'.
.TP
.B [Ee][Nn][Dd]
Find a 'end', ignoring case.
.TP
.B [A-Za-z][A-Za-z0-9]*
Find the next identifier.
.TP
.B (\\*.*\\*)
Find the next one-line pascal comment.
.TP
.B \<the\>
Find the next occurance of `the'.
.SH LIMITATIONS
Levee can only edit files up to 256000 characters long. ^M is used
as its internal line separator, so inserting ^M will have interesting
consequences.
.SH BUGS
Probably infinite.
.SH AUTHOR
.B "David L. Parsons"
.I (orc@pell.chi.il.us)
.br
Testing, suggestions, and impractical design goals by:
Jim Bolland. John Tainter. John Plocher.
.SH COPYRIGHT
Copyright (c) 1982-2007 David L Parsons
.br
All rights reserved.
.br
Redistribution and use in source and binary forms, without or
without modification, are permitted provided that the above
copyright notice and this paragraph are duplicated in all such
forms and that any documentation, advertising materials, and
other materials related to such distribution and use acknowledge
that the software was developed by David L Parsons (orc@pell.chi.il.us).
My name may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
PURPOSE.

873
src/cmd/levee/lv.doc Normal file
View File

@@ -0,0 +1,873 @@
Levee. A Screen Oriented Editor.
USAGE
lv [+address] [file ...]
SYNOPSIS
Levee is a screen oriented editor based on the Unix editor
"vi". It provides a terse, powerful way to enter and edit text
(however, if you want a word-processor, you're better off with
WordStar.)
DESCRIPTION
Levee is a moded editor. It operates in 3 modes -- visual,
command, and insert. Most of the editing work is done is visual
mode, file reading and writing is done in command mode, and
insert mode does what you would expect.
When you enter Levee, you may specify an address to start
editing at. These addresses are in the same format as command
mode addresses, except that a naked + will put you at the very
end of the file.
Levee is copyright (c) 1982-1997 by David L. Parsons. (see
the notice at the end of this document for distribution terms)
Levee. A Screen Oriented Editor.
COMMANDS
Command mode commands:
These commands are used for editing new files, writing
modified files, changing options, doing substitutions, and
a subset of the visual commands. They take as input whole
lines, terminated by return (to execute), or escape (to
abort.)
Command mode is reached by typing ":" or "Q" from visual
mode. If you enter command mode by typing ":", Levee will
execute one command, then return to visual mode after
prompting you with "[more]". If you type anything except
a space or return, Levee will accept another command, and so
forth. If, however, you enter command mode via "Q", Levee
will remain in command mode until you enter the "visual"
command.
A NOTE ON COMMAND SYNTAX
A command may be preceded by an optional line-range. If
you do not provide a line-range, Levee will use the default
line-range shown by the command. A line-range is one or two
address specifications in the following format:
(.|$|'x|#) [ (+|-) (/patt/|?patt?|#) ]
. => current line.
$ => last line.
'x => the line with mark x on it.
# => line #.
For example, ".-5,.+5p" will print every line within ten
lines of the current line. "$-5" is the fifth line from the
end of the file, and "/end/+2" is the second line past the
next occurrence of the pattern "end". Patterns may be
regular expressions (see below.)
Also, a naked line-range will set the current line to
the first line in the range and print all the lines in that
range. "1,10" sets the current line to 1, then prints lines
1 to 10.
If you specify a non-existent line in a range, the comm-
and will abort and Levee will tell you "bad address".
Regular expressions:
Levee gives special meanings to some characters during
a pattern match. The character "." will match any one char,
the character "*" will match zero or more occurances of the
previous char ( so, a* will match 'a','aa','aaa', etc, or it
will match nothing at all). If a pattern begins with "^", it
will only match at the beginning of a line, and patterns
ending with a "$" will only match at the end of a line.
Levee. A Screen Oriented Editor.
Brackets ('[]') have special meaning as well. They mean
match any one of the characters inside the brackets. '[abc]'
will match 'a', 'b', or 'c'. You may specify a range of
characters inside brackets by using a dash (-). '[a-z]' will
match any lowercase alphabetic character. If ^ is the first
character in the bracket, it means match any character
except those in the brackets. '[^abc]' will match anything
except 'a','b', or 'c'.
Backslash takes away special meaning for these chars,
but '\t' specifies a tab, and \( & \) delimit arguments
inside a pattern (used only by :substitute.) The patterns
\< and \> have special meaning, too; they match the start
and end of alpha-numeric tokens.
If you turn off the editor variable 'magic', none of
the above characters will have special meaning inside of
a pattern (see 'set').
Some example patterns:
^end$ Find a line that is just 'end'.
[Ee][Nn][Dd] Find a 'end', ignoring case.
[A-Za-z][A-Za-z0-9]* Find the next identifier.
(\*.*\*) Find the next one-line pascal
comment.
\<the\> Find the next occurance of `the'.
Levee. A Screen Oriented Editor.
---------------
args
show the current argument list, if one exists. The file that you
are currently editing will be framed by '[' and ']'.
---------------
(.,.) change
delete lines, then enter insert mode.
---------------
(.,.) delete
delete lines. Deleted lines are stored in a Yank Buffer for
later putback with "put".
---------------
edit[!] [file]
Discard the current file and start editing a new one. If
changes were made to the current file, you must enter "edit!"
to force Levee to discard the changes. If you do not specify
a filename, Levee will try to reedit the current filename.
When Levee reads in a new file, it will tell you how many
bytes it read in, or [overflow] if the file is larger than the
internal buffer (currently 32760 bytes.)
---------------
execmode
Remain in command mode until you use the "visual" command.
---------------
file [name]
Echo what the current filename is, its status, and the current
line. If you provide it with a name, it will change the filename
to that.
---------------
(.) insert
Insert text above the current line. If you specify a line number,
Levee will make that the current line, then insert above it.
Commands within insert mode:
^W => back over the last word you entered.
^H => back over one character.
^U => back over all input on this line.
^V => escape the next character typed.
^V^H will put a ^H into the file.
ESC => exit insert mode.
^D => If at start of line, reduce indentation 'shiftwidth'
columns.
^T => If at start of line, increase indentation
'shiftwidth' columns.
When in insert mode, Levee will not allow you to enter any control
characters except return and tab. Return ends input on this line and
opens a new line for input.
Levee. A Screen Oriented Editor.
---------------
map[!] [key [text]]
Define/list macros. There are 3 forms of map:
1) map. This lists all the active macros.
2) map (key). This shows the macro associated with (key),
if any.
3) map (key) (text)
This maps (key) to (text). You may map any
key except ":" and escape. In the normal
form (map), the macro will be effective
in visual mode, but in the alternate form,
(map!), the macro will be effective in
insert and command modes.
For example, if you map!ped return to "hello world", every time
you entered a return in command or visual mode, the string "hello
world" would pop up.
---------------
next [file ...]
Edit the next file in the arglist, or edit a new arglist. Levee
takes its initial arglist off the command line when you execute it.
If "autowrite" is set, Levee will write out the changes to the
current file before editing the next one.
---------------
(.) open
Insert below the current line. Otherwise just like insert.
---------------
previous
Edit the previous file in the arglist. Otherwise, like next.
---------------
(.,.) print
Display lines without changing the current line.
---------------
(.) put
Put the contents of the yank buffer back on the line below
the current line. If you specify a line, it resets the current
line, then puts the yank buffer back. The yank buffer is filled
by the delete, change, or yank commands. Put does not destroy
the yank buffer, so you may put back text multiple times.
---------------
quit[!]
Exit Levee. If you want to discard changes, use "quit!"
---------------
(.) read [file]
put the contents of 'file' after the current line.
---------------
rm file
Delete 'file' from disk.
Levee. A Screen Oriented Editor.
---------------
set [option=value]
Set a tunable variable. Levee has a dozen or so user-definable
variables which you can twiddle via this command. There are boolean,
integer, and string variables that you can set. A string or integer
variable is set by 'set xxx=yyy', a boolean variable is set via
'set xxx' or 'set noxxx'.
Here are the settable variables (and abbreviations):
tabsize (ts) tab stop.
shiftwidth (sw) columns to shift on ^D, ^T, >>, or <<
scroll number of lines to scroll on ^D, ^U
autoindent (ai) supply indentation during insert mode.
autowrite (aw) write out changes before :next, :prev
autocopy (ac) make backup copies of before writing.
list display tabs as ^I, end of line as $.
magic use regular expressions in searches.
suffix if the filename does not have a . in
it, supply the suffix. (this is the
only string variable.)
overwrite (ow) destroy old file first, then write.
beautify (be) When set, Levee will not allow insert
of any control character except tab
and return unless you escape it with
ctrl-V.
wrapscan searches wrap around end of buffer.
ignorecase (ic) Ignore the case of alphabetic characters
during searches.
mapslash (ST version only) Map '/' in filenames to
'\'. If the environment contains `mapslash'
when levee is called, this variable will
default to true, otherwise it defaults to
false. (See the documentation for the
Teeny-shell on how the teeny-shell interprets
`mapslash')
lines (li) (ST version only) How many lines on the display.
This is primarily for running levee through
the serial port - put set li=xx into your
LVRC for a xx line terminal.
cols (co) (ST version only) How many columns on the
display. Like the lines variable, it's for
running levee through the serial port.
You may set multiple variables on one line, as in 'set ws noai'.
To see the current settings of these variables, :set -- without any
arguments -- will show the current settings.
At startup, Levee looks in the environment variable LVRC for
a list of variables to set (GEMDOS/MS-DOS). LVRC is one line
of the form 'option=value ...'. If you have a LVRC defined that
is 'ts=4 ow nows', Levee will set tabsize to 4, turn on overwrite,
and turn off wrapscan.
If you are using RMX, Levee looks in the file ":home:r?lvrc"
for initialization. If you are using Osy/SWOs, Levee looks in the
file "*.lvrc". The format of these files are different from the
LVRC variable -- see "source" for more information.
Levee. A Screen Oriented Editor.
---------------
source file
Take command mode commands from 'file'. These commands can be
any legal command, except "visual". If a error happens during
execution of 'file', Levee abandons that level of source'ing.
In Osy/SWOs, there are a few differences in insert mode from
within a sourced file. No character has special meaning except a
line containing nothing but a period, which terminates insert mode.
For example:
:commands
.
.
:insert
blah blah blah blah blah blah
blah blah blah blah blah blah
blah blah blah blah blah blah
.
:more commands
If you are running Levee under any other operating system,
you cannot do a insert from a :source file.
NOTE: If you are running Levee on RMX or Osy/SWOs, it will read
":home:r?lvrc" or "*.lvrc" at startup. These can consist of any
legal command mode instruction, just like any other source file.
---------------
(.,.)substitute(delim)patt(delim)repl(delim)[qcpg]
(.,.)substitute&
Search for patt and replace it with repl. Levee will look for
patt once on each line and replace it with repl. The delimiter
may be any ascii character.
The pattern is a regular expression, just like a search
pattern.
You may include parts of the pattern in the replacement string;
A '&' in the replacement pattern copies in the whole source pattern,
so if you do a 'sub/this/& and that/g', every instance of 'this'
will be replaced with 'this and that'. Also, you may pull parts of
the pattern out by using the \( and \) argument meta-characters.
Arguments gotten by \( & \) are put into the replacement string
everywhere you do a \1..\9 [ \1 is the first argument you set up
with \( & \) ]. So, if you want to reverse the order of two substrings,
you can do 'sub/\(string1\)\(string2\)/\2\1/'.
substitute& redoes the last substitution.
Options:
q,c => before doing the substitute, display the affected
line and wait for you to type a character. If you
type 'y', it will do the substitution. 'q' aborts
the substitute, 'a' does the rest of the change
without prompting, and 'n' does not do it.
p => print the affected lines after the change.
g => do the change globally. That is, do it for every
occurence of patt on a line, rather than just
once.
Levee. A Screen Oriented Editor.
---------------
undo
Undo the last modification to the file (except :edit, :next, :rm,
or :write.) You can only undo the last change to a file -- undo counts
as a change. :undo followed by :undo does nothing to the file.
---------------
unmap (key)
Undefine a macro (see map).
---------------
visual [list]
If you entered command mode by "Q" or "execmode", return to
visual mode. If you provide an argument list, it also does a
`:next' on that list.
---------------
version
Show which version of levee this is.
---------------
(.,.) write [file]
Write lines to a file. If you write the everything to 'file',
the filename is set to 'file', and if you do not specify a file,
Levee will write to the filename.
---------------
(.,.) wq [file]
Write to a file, then quit.
---------------
(.,.) yank
Yank lines from the file into the yank buffer, for later
putback with "put".
---------------
xit[!]
Write changes to the current file, then exit. If there are
more files in the arglist, use "xit!"
---------------
![command]
Execute command.
Example:
!ls => does a 'ls'.
This command is available only under GEMDOS, MSDOS, and RMX.
---------------
($)=
Give the line number of the addressed line. /end/= gives you
the line number of the next line with a 'end' on it.
---------------
Levee. A Screen Oriented Editor.
Visual mode commands.
Visual mode commands move you around and modify the file.
There are movement commands to move the cursor by a variety of
objects.
In the description, a (#) means a optional count. If a
command has a optional count, it will tell you what the count
does in parenthesis. A (*) means that the command can be used
in the delete, yank, and change commands.
Counts are made up by entering digits. If you type '45',
the count will be set to 45. To cancel a count, type ESC.
This section discusses 'whitespace' occasionally.
Whitespace is tabs, spaces, and end of line.
How the display works.
Characters are displayed on the screen as you would
expect, except that nonprinting characters are shown as ^x,
and tabs expand to spaces ( unless you set the option list,
then they show as ^I.) When sitting on a control character or
tab, the cursor is placed on the FIRST character displayed. If
you move the cursor to any other part of them ( via j or k --
see below), any changes will start at the next character.
Levee does not display a end of file marker, but lines
past the end of the file are denoted by ~ lines.
If list is set, tabs display as ^I, and the end of line
displays as $.
If a line is too long for the screen, it will just dis-
appear off the end of the screen.
Levee will handle any screen resolution and any monospaced
font you hand it ( if you are running in low resolution, Levee
will give you a 25x40 window, for example.)
Levee. A Screen Oriented Editor.
---------------
^A
Show a debugging message at the bottom of the screen. This is not at
all useful unless you are debugging the editor. Ignore it.
---------------
(#)^D
Scroll the screen down a half screen. If a count is specified, scroll
down the specified number of lines.
---------------
^E
Scroll down 1 line (shorthand for 1^D )
---------------
^G
Show file statistics. Exactly like ':file'.
(*)------------
(#)^H
Move the cursor left one (count) chars.
---------------
^I
Redraw the screen.
(*)------------
(#)^J
Move down one (count) lines. When you use ^J and ^K (below) to move
up or down lines, the cursor will remain in the same column, even if
it is in the middle of a tabstop or past the end of a line.
(*)------------
(#)^K
Move up one (count) lines.
(*)------------
(#)^L
Move right one (count) characters.
(*)------------
(#)^M
Move to the first nonwhite space on the next line. If a count is specified,
move to the first nonwhite count lines down.
Levee. A Screen Oriented Editor.
---------------
(#)^U
Scroll the screen up a half page. If a count is specified, scroll up
count lines.
---------------
^Y
Scroll the screen up 1 line (shorthand for 1^U.)
---------------
(#)a
Insert text AFTER the cursor. If you give a count, the insertion will
be repeated count times ( 40i-ESC will give you a line of 40 dashes).
The commands in insert mode are the same for visual and command mode.
(*)------------
(#)b
Move to the beginning of the last word (the count'th word back).
A word is a collection of alphanumeric characters (a-z0-9$_#) or
any other nonwhite character (i.e. anything but space, tab, eoln).
---------------
c
Change a object. Change deletes an object, then enters insert mode without
redrawing the screen. When you tell it the object to be changed, Levee
puts a '$' on the last character of the object. You cannot change
backwards.
The object may be any visual mode command marked with a '(*)'. For
example, 'c4l' will change the next 4 characters on the line to something
else. (4cl does the same thing -- 4c4l changes the next 16 characters on
this line.)
'cc' will change whole lines.
When changing, deleting, or yanking a object, it will be placed into
a yank buffer, where it can be retrieved by the 'p' or 'P' commands.
---------------
(#)d
Delete an object. Like 'cc', 'dd' effects whole lines.
(*)------------
(#)e
Move to the end of the current word.
(*)------------
(#)f(x)
Find the next (count'th) occurance of a character on the current line.
For example, if the cursor is sitting on the first character of the
line 'abcdef', typing "ff" will put the cursor on the 'f'.
(*)------------
(#)h
Move left one (count) characters. Exactly like ^H.
Levee. A Screen Oriented Editor.
---------------
(#)i
Start inserting characters at the cursor. If you specify a count,
the insertion will be duplicated count times.
(*)------------
(#)j
Move down one (count) lines. Exactly like ^J.
(*)------------
(#)k
Move up one (count) lines. Exactly like ^K.
(*)------------
(#)l
Move right one (count) character. Exactly like ^L.
---------------
m(x)
Set the marker (x). There are 26 markers available (a-z). You may
move to a marker by use of the ' or ` commands.
(*)------------
n
Find the next occurance of a search pattern. When you do a search with
a / or ? command, Levee will remember the pattern and the direction you
searched in. 'n' will search in the same direction for the pattern, 'N'
searches in the opposite direction.
---------------
o
Open a line below the current line for insertion.
---------------
p
Put yanked/deleted text back after the cursor. Text is yanked
by the delete (d,x,X,D), change (c,C,s,S), and yank (y,Y) commands.
---------------
(#)r(x)
Replace characters (up to end of line) with (x). '4ra' will change the
next 4 characters after the cursor into 'aaaa'.
---------------
(#)s
change one (count) characters. Shorthand for (#)cl.
(*)------------
(#)t(x)
Move up to a character on the current line. If you are on the first
character of the line 'abcdef' and you type 'tf', you will end up sitting
on the 'e'.
---------------
u
Undo last modification. You can undo ANY modification command except
:edit, :next, :rm, or :write. (Just like :undo).
Levee. A Screen Oriented Editor.
(*)------------
(#)v
Move back to the very end of the previous (count'th) word.
See 'b' for the definition of a word.
(*)------------
(#)w
Move up to the very beginning of the next (count'th) word.
---------------
(#)x
Delete one (count) characters forward. Shorthand for (#)dl.
---------------
y
Yank an object for later use by put. 'yy' yanks whole lines.
---------------
A
Append text at the end of the line. Shorthand for $a.
(*)------------
(#)B
Move to the beginning of the current word. Exactly like 'b'.
NOTE: this is incorrect. the capitalized word movement commands should,
and will in the future, be used for movement by space-delimited words.
---------------
C
Change to the end of the line. Shorthand for c$.
---------------
D
Delete to the end of the line. Shorthand for d$.
(*)------------
(#)F(x)
Move to the first (count'th) previous occurance of a character on the
current line. If you are sitting at the end of the line 'abcdef', typing
"Fa" will move you back to the 'a' at the start of the line.
(*)------------
(#)G
Goto line. If you specify a count, Levee will move to that line, and if
there is no count, Levee moves to the absolute end of the file.
To get to the start of the file, type "1G". To the end, just "G".
(*)------------
H
Move to the first nonwhite character at the top of the screen.
---------------
I
Insert at the end of the current line. Shorthand for $i.
Levee. A Screen Oriented Editor.
---------------
(#)J
Join two (count+1) lines together. Joining appends the second line at
the end of the first, putting a space between them. If the first line
ends in whitespace, Levee will not put in a space.
(*)------------
L
Move to the last nonwhite character on the last line of the screen.
(*)------------
M
Move to the first nonwhite character in the middle of the screen.
---------------
O
Open a line above the current line. Otherwise works just like 'o'.
---------------
P
Put back the yank buffer at the cursor. Otherwise works just like 'p'.
---------------
Q
Enter and remain in command mode. Just like the command :exec. To get
back to visual mode, you must enter the command ':visual'.
---------------
R
Replace mode. A limited subset of insert mode that overwrites characters
up to end of line. All of the normal insert mode commands apply.
If you overwrite a character, then back over it with ^H,^U, or ^W, it
will reappear after you exit Replace mode.
Escape exits replace mode.
NOTE: due to a bug, entering a <return> in Replace mode will drop you
back into visual mode with an error. The replacements you have made
will remain.
---------------
S
Change characters backwards. Shorthand for (#)ch.
(*)------------
(#)T(x)
Move back to character on current line. If you are on the last character
of the line 'abcdef', typing "Ta" will move you back to the 'b'.
(*)------------
(#)W
Move to end of word. Exactly like 'e'.
---------------
(#)X
Delete characters backwards. Shorthand for (#)dh.
Levee. A Screen Oriented Editor.
---------------
Y
Yank to end of line. Shorthand for y$.
---------------
ZZ
Write changes to current file and exit if last file in arglist.
Exactly like :xit.
(*)------------
(#)$
Move to end of line. If you give a count, move to the end of the (count-1)
line down (so 2$ moves you to the end of the next line.).
(*)------------
%
Find matching bracket, parenthesis, or squiggly bracket. If you are not
sitting on a '[]{}()', Levee will search forward for one of them on the
current line, then match whatever it finds.
(*)------------
^
Move to the first nonwhite character on the current line.
(*)------------
&
Redo last substitution command.
(*)------------
(#){
Move to the beginning of the count'th paragraph back. A paragraph is
delimited by a blank line.
(*)------------
(#)}
Move to the end of the count'th paragraph forward.
(*)------------
(#)(
Move to the beginning of the count'th sentence back. A sentence is
delimited by a ., a !, or a ? followed by a space, a tab, or end of line.
(*)------------
(#))
Move to the end of the count'th sentence forward.
(*)------------
(#)-
Move to the (count'th) previous line, first nonwhite.
(*)------------
(#)+
Move to the (count'th) next line, first nonwhite.
---------------
(#)~
Change the case of the next count characters. Upper case becomes lowercase,
lowercase becomes uppercase.
Levee. A Screen Oriented Editor.
(*)------------
`(x)
Move to the exact position of mark (x). There is a special mark for some
of the visual mode move ment commands -- '' will move you to where you
were before the last (,),',`,G,/,?,n,N command.
---------------
:
Execute one command mode command. When the command is done, it will return
to visual mode if it produces one line of output, but if it scrolls the
screen, Levee will prompt [more] before returning to visual mode. If you
type a : in response to the [more] prompt, Levee will remain in command
mode for one more command.
---------------
(#)<(#)
Shift one (count) objects left. If you specify a second count, Levee will
shift the object left that many columns -- if you do not, they will be sh
shifted shiftwidth columns.
This is a nondestructive shift. If the shift would carry past the left
margin, the objects will be moved up to the left margin but no farther.
Like the other object movement commands, '<<' will affect whole lines.
---------------
(#)>(#)
Shift one (count) objects right. Just like <, except it will not shift
objects past the right margin of the screen. If you do shift an object
past the right margin of the screen, all of its indent will be removed
and it will end up by the left margin.
---------------
.
Repeat last modification command. (except undo)
(*)------------
?
Search for pattern backwards. Escape aborts the search pattern, and a
empty pattern means search for the last pattern again.
(*)------------
/
Search for pattern forwards. Otherwise like ?.
(*)------------
(#)|
Move to specified column. If you don't have a count, move to column 0.
Levee. A Screen Oriented Editor.
LIMITATIONS
Levee can only edit files up to 256000 characters long. ^M is used
as its internal line separator, so inserting ^M will have interesting
consequences.
BUGS
Probably infinite.
AUTHOR
David L. Parsons (orc)
Testing, suggestions, and impractical design goals by:
Jim Bolland.
John Tainter.
John Plocher.
Levee. A Screen Oriented Editor.
COPYRIGHT
Copyright (c) 1982-2007 David L Parsons
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by David L Parsons (orc@pell.chi.il.us). My name may not be used
to endorse or promote products derived from this software without
specific prior written permission. THIS SOFTWARE IS PROVIDED
AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
FITNESS FOR A PARTICULAR PURPOSE.
Levee. A Screen Oriented Editor.
I N D E X
Are you kidding?

313
src/cmd/levee/main.c Normal file
View File

@@ -0,0 +1,313 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#include <stdlib.h>
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if OS_RMX
extern alien token rq$get$task$tokens(); /* for unique files */
#endif
VOID PROC
stamp(s, template)
/* make a unique temporary file */
char *s;
char *template;
{
#if OS_RMX
token dummy;
strcpy(s, ":work:");
strcat(s, template);
numtoa(&s[strlen(s)], rq$get$task$tokens(0,&dummy));
#else
#if OS_DOS || OS_ATARI
char *p;
#endif
#if OS_UNIX
strcpy(s, "/tmp/");
#endif
#if OS_FLEXOS
s[0] = 0;
#endif
#if OS_DOS
if (p=getenv("TMP")) {
strcpy(s, p);
if (s[strlen(s)-1] != '\\')
strcat(s, "\\");
}
else
s[0] = 0;
#endif
#if OS_ATARI
if (p=getenv("_TMP")) {
strcpy(s, p);
if (s[strlen(s)-1] != '\\')
strcat(s, "\\");
}
else
s[0] = 0;
#endif
strcat(s, template);
numtoa(&s[strlen(s)], getpid());
#endif
}
#if OS_RMX|OS_UNIX
PROC void
ctrlc()
/* ctrlc: RMX control-C handler */
{
count = 0; /* clear count, eh? */
}
#endif
#if OS_RMX
PROC
settty()
/* settty: set up the terminal for raw input */
{
unsigned dummy;
/* transparent mode? */
dq$special(1,&fileno(stdin),&dummy);
/* turn off control character assignments */
strput("\033]T:C15=0,C18=0,C20=0,C21=0,C23=0\033\\");
}
#endif
VOID PROC
initialize(count, args)
int count;
char **args;
/* initialize: set up everything I can in levee */
{
int i;
#if OS_RMX
int xmode = E_INIT, xquit;
#else
char *getenv();
#if OS_ATARI
extern int mapslash;
#endif
#endif
#if OS_UNIX
signal(SIGINT, ctrlc);
#else
signal(SIGINT, SIG_IGN);
#endif
initcon();
#if OS_RMX
exception(0);
dq$trap$cc(ctrlc,&i);
#endif
#if TTY_ZTERM
zconfig();
#endif /*TTY_ZTERM*/
#if OS_ATARI
screensz(&LINES, &COLS);
dofscroll = LINES/2;
#endif
#if OS_RMX
#if USE_TERMCAP
{ FILE *tcf;
extern char termcap[];
if (tcf=fopen(":termcap:","rb")) {
fgets(termcap,200,tcf); /* get a line... */
termcap[strlen(termcap)-1] = 0; /* erase \n at eof */
fclose(tcf); /* close the file */
}
}
#endif /*USE_TERMCAP*/
settty();
#endif /*OS_RMX*/
#if USE_TERMCAP
tc_init();
#endif
version(); strput(". Copyright (c) 1983-2007 by David Parsons");
if (!CA) {
lineonly = TRUE;
mvcur(0, 0);
strput(CE);
prints("(line mode)");
}
else
lineonly = FALSE;
/* initialize macro table */
for (i = 0;i < MAXMACROS;i++)
mbuffer[i].token = 0;
core[0] = EOL;
yank.size = ERR; /* no yanks yet */
undo.blockp = undo.ptr = 0;
fillchar(adjcurr, sizeof(adjcurr), 0);
fillchar(adjendp, sizeof(adjendp), 0);
adjcurr[BTO_WD] = /* more practical to just leave dynamic */
adjcurr[SENT_BACK] =
adjendp[BTO_WD] =
adjendp[FORWD] =
adjendp[MATCHEXPR] =
adjendp[PATT_BACK] =
adjendp[TO_CHAR] =
adjendp[UPTO_CHAR] =
adjendp[PAGE_BEGIN] =
adjendp[PAGE_MIDDLE]=
adjendp[PAGE_END] = TRUE;
fillchar(contexts, sizeof(contexts), -1);
stamp(undobuf, "$un");
stamp(yankbuf, "$ya");
stamp(undotmp, "$tm");
mvcur(LINES-1,0);
#if OS_ATARI
mapslash = getenv("mapslash") != 0L;
#endif
#if OS_RMX
do_file(":lvrc:", &xmode, &xquit);
#else /*!OS_RMX system has a environment.. */
{ char *p;
extern char *execstr; /* [exec.c] */
if ( (p=getenv("LVRC")) ) {
strcpy(instring,p);
execstr = instring;
setcmd();
}
}
#endif
++args, --count;
if (count > 0 && **args == '+') {
char *p = *args;
strcpy(startcmd, p[1] ? (1+p) : "$");
++args, --count;
}
argc = 0;
while (count-- > 0)
expandargs(*args++, &argc, &argv);
if (argc > 0) {
strcpy(filenm, argv[0]);
if (argc > 1)
toedit(argc);
inputf(filenm,TRUE);
}
else
filenm[0] = 0;
}
bool PROC
execmode(emode)
exec_type emode;
{
bool more, /* used [more] at end of line */
noquit; /* quit flag for :q, :xit, :wq */
exec_type mode;
zotscreen = diddled = FALSE;
noquit = TRUE;
if (lineonly)
println();
mode=emode;
do {
prompt(FALSE,":");
if (getlin(instring))
exec(instring, &mode, &noquit);
indirect = FALSE;
if (mode == E_VISUAL && zotscreen && noquit) { /*ask for more*/
prints(" [more]");
if ((ch=peekc()) == 13 || ch == ' ' || ch == ':')
readchar();
more = (ch != ' ' && ch != 13);
}
else
more = (mode == E_EDIT);
if (mode != E_VISUAL && curpos.x > 0)
println();
else
mvcur(-1,0);
} while (more && noquit);
if (zotscreen)
clrprompt();
return noquit;
}
#if OS_ATARI
long _STKSIZ = 4096;
long _BLKSIZ = 4096;
#endif
void /* should be union { void a; int b; float c; } to annoy the purists */
main(argc,argv)
int argc;
char **argv;
{
initialize(argc, argv);
diddled = TRUE; /* force screen redraw when we enter editcore() */
if (lineonly)
while (execmode(E_EDIT))
prints("(no visual mode)");
else
while (execmode(editcore()))
/* do nada */;
unlink(undobuf);
unlink(yankbuf);
#if TTY_ZTERM
zclose();
#endif
fixcon();
#if OS_RMX
strputs("\033]T:C15=3,C18=13,C20=5,C21=6,C23=4\033\\\n");
dq$special(2,&fileno(stdin),&curr);
#else
println();
#endif
exit(0);
}

479
src/cmd/levee/misc.c Normal file
View File

@@ -0,0 +1,479 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
bool PROC
getlin(str)
char *str;
{
int len;
char flag;
flag = line(str, 0, COLS-curpos.x, &len);
str[len] = 0;
strput(CE);
return (flag == EOL);
} /* getlin */
char PROC
readchar()
{
ch = peekc(); /* get the peeked character */
needchar = TRUE; /* force a read on next readchar/peekc */
if (xerox) { /* save this character for redo */
if (rcp >= &rcb[256-1]) /* oops, buffer overflow */
error();
else /* concat it at the end of rcb^ */
*rcp++ = ch;
}
return ch;
} /* readchar */
/* look at next input character without actually using it */
char PROC
peekc()
{
if (needchar) { /* if buffer is empty, */
if (macro >= 0) { /* if a macro */
lastchar = *mcr[macro].ip;
mcr[macro].ip++;
if (*mcr[macro].ip == 0) {
if (--mcr[macro].m_iter > 0)
mcr[macro].ip = mcr[macro].mtext;
else
--macro;
}
}
else /* else get one from the keyboard */
lastchar = getKey();
needchar = FALSE;
}
return lastchar;
} /* peekc */
/* find the amount of leading whitespace between start && limit.
endd is the last bit of whitespace found.
*/
int PROC
findDLE(start, endd, limit, dle)
int start, *endd, limit, dle;
{
while ((core[start] == '\t' || core[start] == ' ') && start < limit) {
if (core[start] == '\t')
dle = tabsize * (1+(dle/tabsize));
else
dle++;
start++;
}
*endd = start;
return dle;
} /* findDLE */
int PROC
skipws(loc)
int loc;
{
while ((core[loc] == '\t' || core[loc] == ' ') && loc <= bufmax)
loc++;
return(loc);
} /* skipws */
int PROC
setX(cp)
int cp;
{
int top, xp;
top = bseekeol(cp);
xp = 0;
while (top < cp) {
switch (cclass(core[top])) {
case 0 : xp++; break;
case 1 : xp += 2; break;
case 2 : xp = tabsize*(1+(xp/tabsize)); break;
case 3 : xp += 3; break;
}
top++;
}
return(xp);
} /* setX */
int PROC
setY(cp)
int cp;
{
int yp, ix;
ix = ptop;
yp = -1;
cp = min(cp,bufmax-1);
do {
yp++;
ix = 1+fseekeol(ix);
} while (ix <= cp);
return(yp);
} /* setY */
int PROC
to_line(cp)
int cp;
{
int tdx,line;
tdx = 0;
line = 0;
while (tdx <= cp) {
tdx = 1+fseekeol(tdx);
line++;
}
return(line);
} /* to_line */
int PROC
to_index(line)
int line;
{
int cp = 0;
while (cp < bufmax && line > 1) {
cp = 1+fseekeol(cp);
line--;
}
return(cp);
} /* to_index */
VOID PROC
swap(a,b)
int *a,*b;
{
int c;
c = *a;
*a = *b;
*b = c;
} /* swap */
int PROC
#if OS_ATARI
cclass(c)
register int c;
{
if (c >= ' ' && c < '')
return 0;
if (c == '\t' && !list)
return 2;
if (c >= 0)
return 1;
return 3;
} /* cclass */
#else
cclass(c)
register unsigned char c;
{
if (c == '\t' && !list)
return 2;
if (c == '' || c < ' ')
return 1;
#if !OS_DOS
if (c & 0x80)
return 3;
#endif
return 0;
} /* cclass */
#endif
#if OS_ATARI
/*
* wildly machine-dependent code to make a beep
*/
#include <atari\osbind.h>
static char sound[] = {
0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
0xF8,0x10,0x10,0x10,0x00,0x20,0x03
};
#define SADDR 0xFF8800L
typedef char srdef[4];
static srdef *SOUND = (srdef *)SADDR;
static
beeper()
{
register i;
for (i=0; i<sizeof(sound); i++) {
(*SOUND)[0] = i;
(*SOUND)[2] = sound[i];
}
} /* beeper */
#endif /*OS_ATARI*/
VOID PROC
error()
{
indirect = FALSE;
macro = -1;
if (xerox)
rcb[0] = 0;
xerox = FALSE;
#if OS_ATARI
Supexec(beeper);
#else
if (bell)
strput(BELL);
#endif /*OS_ATARI*/
} /* error */
/* the dirty work to start up a macro */
VOID PROC
insertmacro(cmdstr, count)
char *cmdstr;
int count;
{
if (macro >= NMACROS)
error();
else if (*cmdstr != 0) {
macro++;
mcr[macro].mtext = cmdstr; /* point at the text */
mcr[macro].ip = cmdstr; /* starting index */
mcr[macro].m_iter = count; /* # times to do the macro */
}
} /* insertmacro */
int PROC
lookup(c)
char c;
{
int ix = MAXMACROS;
while (--ix >= 0 && mbuffer[ix].token != c)
;
return ix;
} /* lookup */
VOID PROC
fixmarkers(base,offset)
int base,offset;
{
unsigned char c;
for (c = 0;c<'z'-'`';c++)
if (contexts[c] > base) {
if (contexts[c]+offset < base || contexts[c]+offset >= bufmax)
contexts[c] = -1;
else
contexts[c] += offset;
}
} /* fixmarkers */
VOID PROC
wr_stat()
{
clrprompt();
if (filenm[0] != 0) {
printch('"');
prints(filenm);
prints("\" ");
if (newfile)
prints("<New file> ");
}
else
prints("No file");
printch(' ');
if (readonly)
prints("<readonly> ");
else if (modified)
prints("<Modified> ");
if (bufmax > 0) {
prints(" line ");
printi(to_line(curr));
prints(" -");
printi((int)((long)(curr*100L)/(long)bufmax));
prints("%-");
}
else
prints("-empty-");
} /* wr_stat */
static int tabptr,
tabstack[20],
ixp;
VOID PROC
back_up(c)
char c;
{
switch (cclass(c)) {
case 0: ixp--; break;
case 1: ixp -= 2; break;
case 2: ixp = tabstack[--tabptr]; break;
case 3: ixp -= 3; break;
}
mvcur(-1,ixp);
} /* back_up */
/*
* put input into buf[] || instring[].
* return states are:
* 0 : backed over beginning
* ESC : ended with an ESC
* EOL : ended with an '\r'
*/
char PROC
line(s, start, endd, size)
char *s;
int start, endd, *size;
{
int col0,
ip;
unsigned char c;
col0 = ixp = curpos.x;
ip = start;
tabptr = 0;
while (1) {
c = readchar();
if (movemap[c] == INSMACRO) /* map!ped macro */
insertmacro(mbuffer[lookup(c)].m_text, 1);
else if (c == DW) {
while (!wc(s[ip-1]) && ip > start)
back_up(s[--ip]);
while (wc(s[ip-1]) && ip > start)
back_up(s[--ip]);
}
else if (c == eraseline) {
ip = start;
tabptr = 0;
mvcur(-1,ixp=col0);
}
else if (c==Erasechar) {
if (ip>start)
back_up(s[--ip]);
else {
*size = 0;
return(0);
}
}
else if (c=='\r' || c==ESC) {
*size = (ip-start);
return (c==ESC) ? ESC : EOL;
}
else if ((!beautify) || c == TAB || c == ''
|| (c >= ' ' && c <= '~')) {
if (ip < endd) {
if (c == '')
c = readchar();
switch (cclass(c)) {
case 0 : ixp++; break;
case 1 : ixp += 2; break;
case 2 :
tabstack[tabptr++] = ixp;
ixp = tabsize*(1+(ixp/tabsize));
break;
case 3 : ixp += 3; break;
}
s[ip++] = c;
printch(c);
}
else
error();
}
else
error();
}
} /* line */
/* move to core[loc] */
VOID PROC
setpos(loc)
int loc;
{
lstart = bseekeol(loc);
lend = fseekeol(loc);
xp = setX(loc);
curr = loc;
} /* setpos */
VOID PROC
resetX()
{
if (deranged) {
xp = setX(curr);
mvcur(-1, xp);
deranged = FALSE;
}
} /* resetX */
/* set end of window */
VOID PROC
setend()
{
int bottom, count;
bottom = ptop;
count = LINES-1;
while (bottom < bufmax && count > 0) {
bottom = 1+fseekeol(bottom);
count--;
}
pend = bottom-1; /* last char before eol || eof */
} /* setend */
/* set top of window
* return the number of lines actually between curr && ptop.
*/
int PROC
settop(lines)
int lines;
{
int top, yp;
top = curr;
yp = -1;
do {
yp++;
top = bseekeol(top) - 1;
lines--;
} while (top >= 0 && lines > 0);
ptop = top+1; /* tah-dah */
setend();
return(yp);
} /* settop */

197
src/cmd/levee/modify.c Normal file
View File

@@ -0,0 +1,197 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#include "grep.h"
/* modification commands that can be accessed by either editcore || execmode */
/* put stuff into the yank buffer */
bool PROC
doyank(low, high)
int low, high;
{
HANDLE f;
register int sz;
yank.size = high - low;
moveleft(&core[low], yank.stuff, min(yank.size, SBUFSIZE));
if (yank.size > SBUFSIZE) {
if ((f=OPEN_NEW(yankbuf)) >= 0) {
low += SBUFSIZE;
sz = WRITE_TEXT(f, core+low, high-low);
CLOSE_FILE(f);
if (sz == high-low)
return TRUE;
}
yank.size = -1;
return FALSE;
}
return TRUE;
}
bool PROC
deletion(low, high)
int low,high;
{
if (doyank(low, high)) /* fill yank buffer */
return delete_to_undo(&undo, low, high-low);
return FALSE;
}
/* move stuff from the yank buffer into core */
bool PROC
putback(start, newend)
int start, *newend;
{
int siz, st;
HANDLE f;
if (yank.size+bufmax < SIZE && yank.size > 0) {
*newend = start + yank.size;
if (start < bufmax)
moveright(&core[start], &core[start+yank.size], bufmax-start);
moveleft(yank.stuff, &core[start], min(SBUFSIZE, yank.size));
if (yank.size > SBUFSIZE) {
siz = yank.size - SBUFSIZE;
if ((f=OPEN_OLD(yankbuf)) >= 0) {
st = READ_TEXT(f, &core[start+SBUFSIZE], siz);
CLOSE_FILE(f);
if (st == siz)
goto succeed;
}
moveleft(&core[start+yank.size], &core[start], bufmax-start);
*newend = -1;
return FALSE;
}
succeed:
insert_to_undo(&undo, start, yank.size);
return TRUE;
}
return FALSE;
}
#define DSIZE 1024
int PROC
makedest(str,start,ssize,size)
/* makedest: make the replacement string for an regular expression */
char *str;
int start, ssize, size;
{
char *fr = dst;
char *to = str;
int as, asize, c;
while (*fr && size >= 0) {
if (*fr == AMPERSAND) { /* & copies in the pattern that we matched */
if ((size -= ssize) < 0)
return -1;
moveleft(&core[start],to,ssize);
to += ssize;
fr++;
}
else if (*fr == ESCAPE) { /* \1 .. \9 do arguments */
c = fr[1];
fr += 2;
if (c >= '1' && c <= '9') {
if ((as = RE_start[c-'1']) < 0)
continue;
asize = RE_size [c-'1'];
if ((size -= asize) < 0)
return -1;
moveleft(&core[as],to,asize);
to += asize;
}
else
*to++ = c;
}
else {
*to++ = *fr++;
--size;
}
}
return to-str;
}
int PROC
chop(start,endd,visual,query)
int start,*endd;
bool visual, *query;
{
int i,retval;
char c;
/*>>>>
bool ok;
<<<<*/
char dest[DSIZE];
register int len, dlen;
retval = -1;
/*dlen = strlen(dst);*/
restart:
count = 1;
i = findfwd(pattern, start, *endd);
if (i != ERR) {
if (*query) {
/*>>>> don't delete -- keep for future use
if (visual) {
mvcur(yp,setX(i));puts("?");
}
else {
<<<<*/
println();
writeline(-1,-1,bseekeol(i));
println();
mvcur(-1,setX(i));
prints("^?");
/*>>>>
}
<<<<*/
do
c = tolower(readchar());
while (c!='y'&&c!='n'&&c!='q'&&c!='a');
if (c == 'n') {
start = i+1;
goto restart;
}
else if (c == 'q')
return retval;
else if (c == 'a')
*query = FALSE;
}
len = lastp-i;
dlen = makedest(dest, i, len, DSIZE);
if (dlen >= 0 && bufmax-(int)(len+dlen) < SIZE
&& delete_to_undo(&undo, i, len)) {
modified = TRUE;
if (dlen > 0) {
moveright(&core[i], &core[i+dlen], bufmax-i);
insert_to_undo(&undo,i,dlen);
moveleft(dest,&core[i],dlen);
}
*endd += (dlen-len);
retval = i+dlen;
}
}
return retval;
}

444
src/cmd/levee/move.c Normal file
View File

@@ -0,0 +1,444 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
int PROC findcol();
int PROC moveword();
int PROC sentence();
int PROC match();
int PROC fchar(), bchar();
/* driver for movement commands */
findstates PROC
findCP(curp,newpos,cmd)
int curp, *newpos;
cmdtype cmd;
{
static char chars[2] = {'/','?'};
char tsearch;
*newpos = ERR;
switch (cmd) { /* move around */
case GO_LEFT:
*newpos = max(lstart, curp-max(count,1));
break;
case GO_RIGHT:
*newpos = min(lend, curp+max(count,1));
break;
case GO_UP:
case GO_DOWN:
*newpos = nextline(cmd==GO_DOWN, curp, count);
if (*newpos >= 0 && *newpos < bufmax)
*newpos = findcol(*newpos,xp);
break;
case FORWD:
case TO_WD:
case BACK_WD:
case BTO_WD:
*newpos = moveword(curp,(cmd <= TO_WD),(cmd==TO_WD || cmd==BTO_WD));
break;
case NOTWHITE:
*newpos = skipws(bseekeol(curp));
break;
case TO_COL:
*newpos = findcol(curp, count);
break;
case TO_EOL:
while ( (count-- > 1) && (curp < bufmax) )
curp = 1+fseekeol(curp);
*newpos = fseekeol(curp);
break;
case PARA_FWD:
do
curp = findfwd("^*[ \t$",curp+1,bufmax-1);
while (curp != ERR && --count > 0);
*newpos = (curp==ERR)?bufmax:curp;
break;
case PARA_BACK:
do
curp = findback("^*[ \t$",curp-1,0);
while (curp != ERR && --count > 0);
*newpos = (curp==ERR)?0:curp;
break;
case SENT_FWD:
case SENT_BACK:
*newpos = sentence(curp, cmd==SENT_FWD);
break;
case MATCHEXPR:
*newpos = match(curp);
break;
case TO_CHAR:
case UPTO_CHAR:
case BACK_CHAR:
case BACKTO_CHAR:
ch = readchar();
if (ch == ESC)
return ESCAPED;
if (cmd<=UPTO_CHAR) {
*newpos = fchar(curp,*newpos);
if (cmd==UPTO_CHAR && *newpos>=0)
*newpos = max(curp, *newpos-1);
}
else {
*newpos = bchar(curp,*newpos);
if (cmd==BACKTO_CHAR && *newpos>=0)
*newpos = min(curp, *newpos+1);
}
break;
case PAGE_BEGIN:
*newpos = ptop;
break;
case PAGE_END:
*newpos = pend;
break;
case PAGE_MIDDLE:
curp = ptop;
count = 12;
while (count-- > 0 && curp < bufmax)
curp = 1+fseekeol(curp);
*newpos = skipws(curp);
break;
case GLOBAL_LINE:
if (count <= 0)
*newpos = bufmax-1;
else
*newpos = to_index(count);
break;
case TO_MARK:
case TO_MARK_LINE:
*newpos = getcontext((char)tolower(readchar()), cmd==TO_MARK_LINE);
break;
case CR_FWD:
case CR_BACK:
curp = nextline(cmd==CR_FWD, curp, count);
if (cmd==CR_BACK && curp > 0)
curp = bseekeol(curp);
*newpos = skipws(curp);
break;
case PATT_FWD:
case PATT_BACK: /* search for pattern */
case FSEARCH:
case BSEARCH:
clrprompt();
if (cmd == PATT_FWD || cmd == PATT_BACK) {
printch(tsearch = instring[0] = chars[cmd-PATT_FWD]);
if (!getlin(&instring[1]))
return ESCAPED; /* needs to skip later tests */
}
else {
if (!lsearch)
return BADMOVE;
tsearch = lsearch;
printch(instring[0] = (cmd==FSEARCH)?lsearch:((lsearch=='?')?'/':'?') );
prints(lastpatt);
instring[1] = 0;
}
if (*findparse(instring, newpos, curp)) { /* croaked patt */
*newpos = ERR;
prompt(TRUE,"bad pattern");
}
else if (*newpos == ERR)
prompt(FALSE,"no match");
lsearch = tsearch; /* fixup for N, n */
break;
}
if ( ((*newpos) >= 0) && ((*newpos) <= bufmax) )
return LEGALMOVE;
return BADMOVE;
}
/* this procedure handles all movement in visual mode */
VOID PROC
movearound(cmd)
cmdtype cmd;
{
int cp;
switch (findCP(curr, &cp, cmd)) {
case LEGALMOVE:
if (cp < bufmax) {
if (cmd >= PATT_FWD) /* absolute move */
contexts[0] = curr; /* so save old position... */
curr = cp; /* goto new position */
if (cmd==GO_UP || cmd==GO_DOWN) /* reset Xpos */
deranged = TRUE;
else
xp = setX(cp); /* just reset XP */
if (cp < lstart || cp > lend) {
lstart = bseekeol(curr);
lend = fseekeol(curr);
if (curr < ptop) {
if (canUPSCROLL && ok_to_scroll(curr, ptop)) {
scrollback(curr);
yp = 0;
}
else {
yp = settop(LINES / 2);
redisplay(TRUE);
}
}
else if (curr > pend) {
if (ok_to_scroll(pend, curr)) {
scrollforward(curr);
yp = LINES-2;
}
else {
yp = settop(LINES / 2);
redisplay(TRUE);
}
}
else
yp = setY(curr);
}
}
else
error();
break;
case BADMOVE:
error();
break;
}
mvcur(yp, xp);
}
int PROC
findcol(ip, col)
int ip, col;
{
int tcol, endd;
ip = bseekeol(ip); /* start search here */
endd = fseekeol(ip); /* end search here */
tcol = 0;
while (tcol < col && ip < endd)
switch (cclass(core[ip++])) {
case 0: tcol++; break;
case 1: tcol += 2; break;
case 3: tcol += 3; break;
case 2: tcol = tabsize*(1+(tcol/tabsize)); break;
}
return(ip);
}
char dstpatt[]="[](){}", srcpatt[]="][)(}{";
/* find matching [], (), {} */
int PROC
match(p)
int p;
{
char srcchar, dstchar;
int lev, step;
while((lev = scan(6,'=',core[p],srcpatt)) >= 6 && core[p] != EOL)
p++;
if (lev < 6) {
srcchar = srcpatt[lev];
dstchar = dstpatt[lev];
step = setstep[lev&1];
lev = 0;
while (p >= 0 && p < bufmax) {
p += step;
if (core[p] == srcchar)
lev++;
else if (core[p] == dstchar)
if(--lev < 0)
return p;
}
}
return (-1);
}
char * PROC
class(c)
/* find the character class of a char -- for word movement */
char c;
{
if (strchr(wordset,c))
return wordset;
else if (strchr(spaces,c))
return spaces;
else
return (char*)NULL;
}
int PROC
skip(chars,cp,step)
/* skip past characters in a character class */
char *chars;
register int cp;
int step;
{
while (cp >= 0 && cp < bufmax && strchr(chars,core[cp]))
cp += step;
return cp;
}
int PROC
tow(cp,step)
/* skip to the start of the next word */
register int cp;
register int step;
{
while (cp >= 0 && cp < bufmax
&& !(strchr(wordset,core[cp]) || strchr(spaces,core[cp])))
cp += step;
return cp;
}
int PROC
moveword(cp,forwd,toword)
/* word movement */
int cp;
bool forwd, toword;
{
int step;
char *ccl;
step = setstep[forwd]; /* set direction to move.. */
if (!toword)
cp += step; /* advance one character */
count = max(1,count);
ccl = class(core[cp]);
if (toword && ccl == spaces) { /* skip to start of word */
count--;
cp = skip(spaces,cp,step);
ccl = class(core[cp]);
}
while (cp >= 0 && cp < bufmax && count-- > 0) {
if (ccl == spaces) {
cp = skip(spaces,cp,step);
ccl = class(core[cp]);
}
cp = (ccl)?skip(ccl,cp,step):tow(cp,step);
ccl = class(core[cp]);
}
if (toword) { /* past whitespace? */
if (ccl == spaces)
cp = skip(spaces,cp,step);
return cp;
}
return cp-step; /* sit on last character. */
}
/* find a character forward on current line */
int PROC
fchar(pos,npos)
int pos,npos;
{
do
pos += scan(lend-pos-1,'=',ch, &core[pos+1]) + 1;
while (--count>0 && pos<lend);
if (pos<lend)
return(pos);
return(npos);
}
/* find a character backward on the current line */
int PROC
bchar(pos,npos)
int pos,npos;
{
do
pos += scan(-pos+lstart+1,'=',ch, &core[pos-1]) - 1;
while (--count>0 && pos>=lstart);
if (pos>=lstart)
return(pos);
return(npos);
}
/* look for the end of a sentence forward */
int PROC
ahead(i)
int i;
{
char c;
do {
if ((c=core[i]) == '.' || c == '?' || c == '!')
if (i == bufmax-1 || (c=core[1+i]) == TAB || c == EOL || c == ' ')
return i;
} while (++i < bufmax);
return -1;
}
/* look for the end of a sentence backwards. */
int PROC
back(i)
int i;
{
char c;
do {
if ((c=core[i]) == '.' || c == '?' || c == '!')
if ((c=core[1+i]) == TAB || c == EOL || c == ' ')
return i;
} while (--i >= 0);
return -1;
}
/* find the end of the next/last sentence.
Sentences are delimited by ., !, or ? followed by a space.
*/
int PROC
sentence(start,forwd)
int start;
bool forwd;
{
do {
if (forwd)
start = ahead(start+1);
else
start = back(start-1);
} while (--count > 0 && start >= 0);
return start;
}

207
src/cmd/levee/os2call.c Normal file
View File

@@ -0,0 +1,207 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* os2 (and bound) interface for levee (Microsoft C)
*/
#include "levee.h"
#if OS2
#include <signal.h>
#include <glob.h>
#define INCL_DOS
#include <os2.h>
int PROC
min(a,b)
int a,b;
{
return (a>b) ? b : a;
}
int PROC
max(a,b)
int a,b;
{
return (a<b) ? b : a;
}
PROC
strput(s)
char *s;
{
write(1, s, strlen(s));
}
/* get a key, mapping certain control sequences
*/
PROC
getKey()
{
register c;
c = getch();
if (c == 0 || c == 0xe0)
switch (c=getch()) {
case 'K': return LTARROW;
case 'M': return RTARROW;
case 'H': return UPARROW;
case 'P': return DNARROW;
case 'I': return 'U'-'@'; /* page-up */
case 'Q': return 'D'-'@'; /* page-down */
default : return 0;
}
return c;
}
/* don't allow interruptions to happen
*/
PROC
nointr()
{
signal(SIGINT, SIG_IGN);
} /* nointr */
/* have ^C do what it usually does
*/
PROC
allowintr()
{
signal(SIGINT, SIG_DFL);
} /* allowintr */
/*
* basename() returns the filename part of a pathname
*/
char *
basename(s)
register char *s;
{
register char *p = s;
for (p = s+strlen(s); p > s; --p)
if (p[-1] == '/' || p[-1] == '\\' || p[-1] == ':')
return p;
return s;
} /* basename */
/*
* glob() expands a wildcard, via calls to DosFindFirst/Next()
* and pathname retention.
*/
char *
glob(path, dta)
char *path;
struct glob_t *dta;
{
static char path_bfr[256]; /* full pathname to return */
static char *file_part; /* points at file - for filling */
static char isdotpattern; /* looking for files starting with . */
static char isdotordotdot; /* special case . or .. */
static struct glob_t *dta_bfr; /* pointer to desired dta */
static FILEFINDBUF ffb; /* DOS & OS/2 dta */
static int dir; /* directory handle */
register st; /* status from DosFindxxx */
int count=1; /* how many files to find */
if (path) {
/* when we start searching, save the path part of the filename in
* a safe place.
*/
strcpy(path_bfr, path);
file_part = basename(path_bfr);
/* set up initial parameters for DosFindFirst()
*/
dta_bfr = dta;
dir = HDIR_SYSTEM;
if (isdotpattern = (*file_part == '.'))
/* DosFindFirst() magically expands . and .. into their
* directory names. Admittedly, there are cases where
* this can be useful, but this is not one of them. So,
* if we find that we're matching . and .., we just
* special-case ourselves into oblivion to get around
* this particular bit of DOS silliness.
*/
isdotordotdot = (file_part[1] == 0 || file_part[1] == '.');
else
isdotordotdot = 0;
st = DosFindFirst(path, &dir, 0x16, &ffb, sizeof ffb, &count, 0L);
}
else
st = DosFindNext(dir, &ffb, sizeof ffb, &count);
while (st == 0 && count > 0) {
/* Unless the pattern has a leading ., don't include any file
* that starts with .
*/
if (ffb.achName[0] == '.' && !isdotpattern) {
count = 1;
st = DosFindNext(dir, &ffb, sizeof ffb, &count);
}
else {
/* found a file - affix the path leading to it, then return
* a pointer to the (static) buffer holding the path+the name.
*/
strlwr(ffb.achName); /* DOS & OS/2 are case-insensitive */
if (dta_bfr) {
memcpy(&dta_bfr->wr_date, &ffb.fdateLastWrite, sizeof(short));
memcpy(&dta_bfr->wr_time, &ffb.ftimeLastWrite, sizeof(short));
if (isdotordotdot)
strcpy(dta_bfr->name, file_part);
else {
strncpy(dta_bfr->name,
ffb.achName, sizeof(dta_bfr->name)-1);
dta_bfr->name[sizeof(dta_bfr->name)-1] = 0;
}
dta_bfr->size = ffb.cbFile;
dta_bfr->attrib = ffb.attrFile;
}
if (!isdotordotdot)
strcpy(file_part, ffb.achName);
return path_bfr;
}
}
/* nothing matched
*/
if (path && isdotordotdot) {
/* must be at root, so statting dot will most likely fail. Fake a
* dta.
*/
if (dta_bfr) {
memset(dta_bfr, 0, sizeof *dta_bfr);
dta_bfr->attrib = 0x10;
dta_bfr->name[0] = '.';
}
return path_bfr;
}
return (char*)0;
} /* glob */
#endif

162
src/cmd/levee/proto.h Normal file
View File

@@ -0,0 +1,162 @@
/*
** levee function prototypes
** (generated by cl -Gms -Ox -nologo -I../tools -Zg)
*/
#ifndef _PROTO_D
#define _PROTO_D
char *PROC badccl(char *src);
char *PROC class(char c);
char *PROC dodash(char *src);
char *PROC findbounds(char *ip);
char *PROC findparse(char *src,int *idx,int start);
char *PROC getarg(void);
char *PROC getname(void);
char *PROC makepat(char *string,char delim);
char *PROC search(char *pat,int *start);
char *basename(char *s);
char *glob(char *path,struct glob_t *dta);
char PROC editcore(void);
char PROC esc(char * *s);
char PROC findCP(int curp,int *newpos,char cmd);
char PROC line(char *s,int start,int endd,int *size);
char PROC peekc(void);
char PROC readchar(void);
int PROC REmatch(char *pattern,int start,int end);
int PROC addarg(char *name);
int PROC addfile(struct _iobuf *f,int start,int endd,int *size);
int PROC adjuster(int sleft,int endd,int sw);
int PROC ahead(int i);
int PROC allowintr(void);
int PROC amatch(char *pattern,char *start,char *endp);
int PROC args(void);
int PROC back(int i);
int PROC back_up(char c);
int PROC backup(char *name);
int PROC bchar(int pos,int npos);
int PROC bigreplace(void);
int PROC bseekeol(int origin);
int PROC cclass(unsigned char c);
int PROC chop(int start,int *endd,int visual,int *query);
int PROC clrmsg(void);
int PROC clrprompt(void);
int PROC concatch(char c);
int PROC copyover(struct undostack *save_undo,int *curp);
int PROC cutandpaste(void);
int PROC delete_to_undo(struct undostack *u,int start,int lump);
int PROC deletion(int low,int high);
int PROC do_file(char *fname,char *mode,int *noquit);
int PROC doaddwork(char *token,int *argcp,char * * *argvp);
int PROC docommand(char cmd);
int PROC doinput(char *name);
int PROC doins(int flag);
int PROC doyank(int low,int high);
int PROC editfile(void);
int PROC errmsg(char *msg);
int PROC error(void);
int PROC exec(char *cmd,char *mode,int *noquit);
int PROC execmode(char emode);
int PROC exmacro(void);
int PROC expandargs(char *name,int *argcp,char * * *argvp);
int PROC fchar(int pos,int npos);
int PROC findDLE(int start,int *endd,int limit,int dle);
int PROC findarg(char *name);
int PROC findback(char *pattern,int start,int endp);
int PROC findcol(int ip,int col);
int PROC findfwd(char *pattern,int start,int endp);
int PROC fixcore(int *topp);
int PROC fixmarkers(int base,int offset);
int PROC fixupline(int dft);
int PROC format(char *out,unsigned short c);
int PROC fseekeol(int origin);
int PROC gcount(void);
int PROC getKey(void);
int PROC getcontext(char c,int begline);
int PROC getlin(char *str);
int PROC initialize(int count,char * *args);
int PROC inputf(char *fname,int newbuf);
int PROC insert_to_undo(struct undostack *u,int start,int size);
int PROC insertion(int count,int openflag,int *dp,int *yp,int visual);
int PROC insertmacro(char *cmdstr,int count);
int PROC join(int count);
int PROC killargs(int *argcp,char * * *argvp);
int PROC locate(char *pattern,char *linep);
int PROC lookup(char c);
int PROC macrocommand(void);
int PROC makedest(char *str,int start,int ssize,int size);
int PROC map(int insert);
int PROC match(int p);
int PROC max(int a,int b);
int PROC min(int a,int b);
int PROC move_to_undo(struct undostack *u,int start,int lump);
int PROC movearound(char cmd);
int PROC moveleft(char *src,char *dest,int length);
int PROC moveright(char *src,char *dest,int length);
int PROC moveword(int cp,int forwd,int toword);
int PROC mvcur(int y,int x);
int PROC nextfile(int prev);
int PROC nextline(int advance,int dest,int count);
int PROC nointr(void);
int PROC numtoa(char *str,int num);
int PROC ok_to_scroll(int top,int bottom);
int PROC oktoedit(int writeold);
int PROC omatch(char *pattern,char * *cp,char *endp);
int PROC outputf(char *fname);
int PROC parse(char *inp);
int PROC patsize(char * *pattern);
int PROC plural(int num,char *string);
int PROC popblock(struct undostack *u);
int PROC popmem(struct undostack *u,int start,int size);
int PROC popw(struct undostack *u,int *i);
int PROC print(void);
int PROC printall(void);
int PROC printch(char c);
int PROC printi(int num);
int PROC println(void);
int PROC printone(int i);
int PROC prints(char *s);
int PROC prompt(int toot,char *s);
int PROC pushblock(struct undostack *u);
int PROC pushmem(struct undostack *u,int start,int size);
int PROC pushw(struct undostack *u,int i);
int PROC put(int before);
int PROC putback(int start,int *newend);
int PROC putfile(struct _iobuf *f,int start,int endd);
int PROC putin(struct undostack *save_undo,int *curp);
int PROC readfile(void);
int PROC redisplay(int flag);
int PROC refresh(int y,int x,int start,int endd,int rest);
int PROC resetX(void);
int PROC scan(int length,char tst,char ch,char *src);
int PROC scroll(int down);
int PROC scrollback(int curr);
int PROC scrollforward(int curr);
int PROC sentence(int start,int forwd);
int PROC setX(int cp);
int PROC setY(int cp);
int PROC setcmd(void);
int PROC setend(void);
int PROC setpos(int loc);
int PROC settop(int lines);
int PROC skip(char *chars,int cp,int step);
int PROC skipws(int loc);
int PROC squiggle(int endp,char c,int dorepl);
int PROC stamp(char *s,char *template);
int PROC strput(char *s);
int PROC swap(int *a,int *b);
int PROC takeout(struct undostack *save_undo,int *curp);
int PROC to_index(int line);
int PROC to_line(int cp);
int PROC toedit(int count);
int PROC tow(int cp,int step);
int PROC undefine(int i);
int PROC unmap(void);
int PROC uputcmd(struct undostack *u,int size,int start,char cmd);
int PROC version(void);
int PROC whatline(void);
int PROC wr_stat(void);
int PROC writefile(void);
int PROC writeline(int y,int x,int start);
int PROC zdraw(char code);
int PROC zerostack(struct undostack *u);
int main(int argc,char * *argv);
#endif /*_PROTO_D*/

7
src/cmd/levee/readme.os2 Normal file
View File

@@ -0,0 +1,7 @@
If you wish to have your copy of Levee as a family mode application, all
you need to do is bind it. It's already set up as a family mode application-
there are some small differences for input (dos lv sees ^C and treats it
like an ordinary character; os2 lv never sees ^C, because it's eaten by trap
handlers) and redirectability (os2 lv uses getch() - a microsoft library
function; dos vi uses dos function 0x07 - "get raw character from stdin,
whatever that may be") but these shouldn't be a problem.

101
src/cmd/levee/rmxcall.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* iRMX interface for levee (Intel C)
*/
#include "levee.h"
#if OS_RMX
extern char FkL, CurRT, CurLT, CurUP, CurDN;
extern alien rq$s$write$move();
strput(s)
/* strput: write a string to stdout */
char *s;
{
int dummy;
if (s)
rq$s$write$move(fileno(stdout), s, strlen(s), &dummy);
}
char
getKey()
/* getKey: read a character from stdin */
{
char c,sw;
unsigned dummy;
read(0,&c,1);
if (c == FkL) { /* (single character) function key lead-in */
dq$special(3,&fileno(stdin),&dummy); /* grab a raw-mode character */
if (read(0,&sw,1) == 1)
if (sw == CurLT)
c = LTARROW;
else if (sw == CurRT)
c = RTARROW;
else if (sw == CurUP)
c = UPARROW;
else if (sw == CurDN)
c = DNARROW;
else
c = sw | 0x80;
dq$special(1,&fileno(stdin),&dummy); /* back into transparent mode */
}
#if 0
else if (c == 0x7f) /* good old dos kludge... */
return erase;
#endif
return c;
}
int max(a,b)
int a,b;
{
return (a>b)?a:b;
}
int min(a,b)
int a,b;
{
return (a>b)?b:a;
}
extern alien token rq$c$create$command$connection(),
rq$c$delete$command$connection(),
rq$c$send$command();
int system(s)
/* system: do a shell escape */
char *s;
{
char *string();
unsigned cp, error, status, dummy;
cp = rq$c$create$command$connection(fileno(stdin),fileno(stdout),0,&error);
if (!error) {
rq$c$send$command(cp,string(s),&status,&error);
rq$c$delete$command$connection(cp,&dummy);
}
return error?(error|0x8000):(status&0x7fff);
}
#endif

32
src/cmd/levee/tc Normal file
View File

@@ -0,0 +1,32 @@
if (!(ttytype = getenv("TERM"))) {
S1("TERM not set");
exit(6);
}
if (tgetent(tc, ttytype) != 1) {
sprintf(Msg, "Can't load %s", ttytype);
S;
exit(7);
}
ospeed = newmode.c_cflag & CBAUD;
LI = tgetnum("li") - 1;
CO = tgetnum("co");
if (!(s = Tgetstr("pc")))
PC = '\0';
else
PC = *s;
CD = Tgetstr("cd");
CE = Tgetstr("ce");
CL = Tgetstr("cl");
CM = Tgetstr("cm");
SE = Tgetstr("se");
SO = Tgetstr("so");
#ifdef linux
CF = Tgetstr("vi");
CN = Tgetstr("ve");
#else
CF = Tgetstr("CF");
CN = Tgetstr("CN");
#endif
if (CF && !CN)
CN = Tgetstr("CO");

291
src/cmd/levee/termcap.i Normal file
View File

@@ -0,0 +1,291 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#if TERMCAP_EMULATION
/*
* Termcap handlers
*
* Routines included:
* tc_init() -- set up all the terminal stuff levee will need.
* *xtract() -- get a field out of the termcap entry.
* *parseit() -- parse a termcap field.
* tgoto() -- put a gotoXY string into a buffer.
* * -> internal routine.
*/
#if OS_RMX | OS_DOS /* default to ANSI.SYS termcap */
char termcap[200] = "Ansi subset:CM=\033[%d;%dH,Y,1,1:\
CE=\033[K:CL=\033[H\033[J:LINES=24:COLS=79:HO=\033[H:FkL=\033:\
CurR=C:CurL=D:CurU=A:CurD=B";
#endif
char *
parseit(ptr,savearea)
/* parse a termcap field */
char *ptr;
char **savearea;
{
char *p = *savearea;
char *op = *savearea;
int tmp;
while (*ptr && *ptr != ':') {
if (*ptr == '\\' && ptr[1]) {
++ptr;
switch (*ptr) {
case 'E':
*p++ = '\033';
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
tmp = 0;
while (*ptr >= '0' && *ptr <= '9')
tmp = (tmp*8)+(*ptr++ - '0');
*p++ = tmp;
--ptr;
default:
*p++ = *ptr;
}
}
else *p++ = *ptr;
++ptr;
}
*p++ = 0;
*savearea = p;
return op;
} /* parseit */
char *
xtract(ptr,name,savearea)
/* get something from the termcap
*
* arguments: tcentry -- the termcap entry
* what -- the field we want to get (NULL means first field)
* savearea-- pointer to static buffer for parsed fields.
*/
char *ptr;
char name[];
char **savearea;
{
int size;
if (!ptr)
return NULL;
if (!name) /* return first field of entry -- terminal name? */
return parseit(ptr,savearea);
size = strlen(name);
/*
* always skip the first (terminal name) field
*/
while (*ptr) {
while (*ptr && *ptr != ':') {
if (*ptr == '\\')
ptr++;
ptr++;
}
if (*ptr)
ptr++;
if (*ptr && strncmp(name,ptr,size) == 0 && ptr[size] == '=')
return parseit(&ptr[1+size],savearea);
puts("\r");
}
return NULL;
} /* xtract */
char
charext(tc,what,savearea)
/* get a character field from the termcap */
char *tc, *what, **savearea;
{
char *p = xtract(tc,what,savearea);
if (p)
return *p;
return 0;
} /* charext */
/* internal variables just for termcap */
static int _Xfirst, _xpad, _ypad;
void
tc_init()
/* get the termcap stuff and go berserk parsing it */
/* if anything horrid goes wrong, levee will crash */
{
#if OS_RMX
char *p = termcap;
#else
char *getenv();
char *p = getenv("TERMCAP");
#endif
char *lp, *ptr;
#if OS_DOS
if (!p)
p = termcap;
#endif
#if !(OS_RMX|OS_DOS)
if (!p) {
puts("lv: no termcap\n");
exit(1);
}
#endif
lp = Malloc(strlen(p)+1);
if (!lp) {
puts("lv: out of memory\n");
exit(1);
}
TERMNAME = xtract(p,NULL,&lp);
CM = xtract(p,"CM",&lp);
HO = xtract(p,"HO",&lp);
UP = xtract(p,"UP",&lp);
CE = xtract(p,"CE",&lp);
CL = xtract(p,"CL",&lp);
BELL = xtract(p,"BELL",&lp);
if (!BELL)
BELL = "\007";
OL = xtract(p,"OL",&lp);
UpS = xtract(p,"UpS",&lp);
CURon= xtract(p,"CURon",&lp);
CURoff=xtract(p,"CURoff",&lp);
FkL = charext(p,"FkL",&lp);
CurRT= charext(p,"CurR",&lp);
CurLT= charext(p,"CurL",&lp);
CurUP= charext(p,"CurU",&lp);
CurDN= charext(p,"CurD",&lp);
canUPSCROLL = (UpS != NULL);
CA = (CM != NULL);
if ((LINES=atoi(ptr=xtract(p,"LINES",&lp))) <= 0) {
puts("lv: bad termcap");
exit(1);
}
dofscroll = LINES/2;
if ((COLS=atoi(ptr=xtract(p,"COLS",&lp))-1) <= 0 || COLS >= MAXCOLS) {
puts("lv: bad termcap");
exit(1);
}
_ypad = _xpad = 0;
_Xfirst = 1;
p = CM;
while (*p && *p != ',')
p++;
if (!*p)
return;
*p++ = 0;
if (*p != ',')
_Xfirst = (*p++ == 'X');
if (!*p)
return;
++p;
while (*p && *p != ',')
_xpad = (_xpad*10) + (*p++ - '0');
if (!*p)
return;
++p;
while (*p)
_ypad = (_ypad*10) + (*p++ - '0');
}
#define tgoto(s,y,x) (_Xfirst?sprintf(s,CM,x+_xpad,y+_ypad):\
sprintf(s,CM,y+_ypad,x+_xpad))
#else
#include <stdlib.h>
#ifdef HAVE_TERMCAP_H
# include <termcap.h>
#else
# include <term.h>
#endif
#include <string.h>
#include <sys/ioctl.h>
void
tc_init()
/* read in the termcap entry for this terminal.
*/
{
static char tcbuf[2048+1024];
char *bufp;
char *term = getenv("TERM");
if (( term ? tgetent(tcbuf, term) : 0) != 0) {
TERMNAME = term;
bufp = tcbuf + 2048;
CM = tgetstr("cm", &bufp);
UP = tgetstr("up", &bufp);
HO = tgetstr("ho", &bufp);
if (!HO) {
char *goto0 = tgoto(CM, 0, 0);
if (goto0)
HO = strdup(goto0);
}
CL = tgetstr("cl", &bufp);
CE = tgetstr("ce", &bufp);
BELL = tgetstr("vb", &bufp);
if (!BELL)
BELL = "\007";
OL = tgetstr("al", &bufp);
UpS = tgetstr("sr", &bufp);
CURon = tgetstr("ve", &bufp);
CURoff = tgetstr("vi", &bufp);
LINES = tgetnum("li");
COLS = tgetnum("co");
/* don't trust li & co, because we might actually
* be on a console or gui instead of the tinned
* tty that termcap expects
*/
#if defined(TIOCGSIZE)
{ struct ttysize tty;
if (ioctl(0, TIOCGSIZE, &tty) == 0) {
if (tty.ts_lines) LINES=tty.ts_lines;
if (tty.ts_cols) COLS=tty.ts_cols;
}
}
#elif defined(TIOCGWINSZ)
{ struct winsize tty;
if (ioctl(0, TIOCGWINSZ, &tty) == 0) {
if (tty.ws_row) LINES=tty.ws_row;
if (tty.ws_col) COLS=tty.ws_col;
}
}
#endif
dofscroll = LINES/2;
/* set cursor movement keys to zero for now */
FkL = CurRT = CurLT = CurUP = CurDN = EOF;
canUPSCROLL = (UpS != NULL);
CA = (CM != NULL);
}
}
#endif

86
src/cmd/levee/ucsd.c Normal file
View File

@@ -0,0 +1,86 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#ifndef moveleft
VOID PROC
moveleft(src,dest,length)
register char *src,*dest;
register int length;
{
while (--length >= 0)
*(dest++) = *(src++);
}
#endif /*moveleft*/
#ifndef moveright
VOID PROC
moveright(src,dest,length)
register char *src,*dest;
register int length;
{
src = &src[length];
dest = &dest[length];
while (--length >= 0)
*(--dest) = *(--src);
}
#endif /*moveright*/
#ifndef fillchar
VOID PROC
fillchar(src,length,ch)
register char *src,ch;
register int length;
{
while (--length >= 0)
*(src++) = ch;
}
#endif
int PROC
scan(length,tst,ch,src)
int length;
register char tst,ch,*src;
{
register int inc,l;
if (length < 0)
inc = -1;
else
inc = 1;
if (tst == '!') {
for(l = ((int)inc)*length; l > 0; l--,src += (long)inc)
if (*src != ch)
break;
}
else {
for(l = ((int)inc)*length; l > 0; l--,src += (long)inc)
if (*src == ch)
break;
}
return length-(inc*l);
}

272
src/cmd/levee/undo.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
#include "levee.h"
#include "extern.h"
#define BUFSZ sizeof(undo.coreblock)
#define AVAIL(x) ((x)<<1)
#define INDEX(x) ((1+x)>>1)
bool PROC
pushblock(u)
struct undostack *u;
{
if (u->blockp == 0)
if ((uwrite = OPEN_NEW(undobuf)) < 0)
return FALSE;
if (BUFSZ == WRITE_TEXT(uwrite, u->coreblock, BUFSZ)) {
u->blockp++;
u->ptr = 0;
return TRUE;
}
return FALSE;
}
bool PROC
pushw(u, i)
struct undostack *u;
int i;
{
if (u->ptr >= PAGESIZE && !pushblock(u))
return FALSE;
u->coreblock[u->ptr++] = i;
return TRUE;
}
bool PROC
pushmem(u, start, size)
struct undostack *u;
int start,size;
{
int chunk;
bool ok;
ok = TRUE;
while (ok && size > 0) {
chunk = min(size, AVAIL(PAGESIZE-u->ptr));
moveleft(&core[start], (char*)&u->coreblock[u->ptr], chunk);
size -= chunk;
start += chunk;
if (size > 0)
ok = pushblock(u);
else
u->ptr += INDEX(chunk);
}
return ok;
}
VOID PROC
zerostack(u)
struct undostack *u;
{
if (u->blockp > 0)
CLOSE_FILE(uwrite);
u->blockp = 0; /* initialize the stack */
u->ptr = 0;
}
bool PROC
uputcmd(u, size, start, cmd)
struct undostack *u;
int size,start;
char cmd;
{
return(pushw(u, size) && pushw(u, start) && pushw(u, cmd));
}
VOID PROC
insert_to_undo(u, start, size)
struct undostack *u;
int start,size;
{
if (uputcmd(u, size, start, U_DELC)) {
fixmarkers(start, size);
bufmax += size;
}
else
error();
}
/* delete stuff from the buffer && put it into the undo stack */
bool PROC
delete_to_undo(u, start, lump)
struct undostack *u;
int start, lump;
{
if (lump <= 0)
return TRUE;
else if (pushmem(u,start,lump) && uputcmd(u,lump,start,U_ADDC)) {
moveleft(&core[start+lump], &core[start], bufmax-(start+lump));
bufmax -= lump;
fixmarkers(start,-lump);
return TRUE;
}
else
return FALSE;
}
/* copy stuff into the undo buffer */
bool PROC
move_to_undo(u, start, lump)
struct undostack *u;
int start,lump;
{
return pushmem(u, start, lump) && uputcmd(u,lump,start,U_MOVEC);
}
bool PROC
popblock(u)
struct undostack *u;
{
if (u->blockp > 0) {
if (SEEK_POSITION(uread, (long)((--u->blockp)*BUFSZ), 0) < 0)
return FALSE;
if (BUFSZ == READ_TEXT(uread, u->coreblock, BUFSZ)) {
u->ptr = PAGESIZE;
return TRUE;
}
}
return FALSE;
}
bool PROC
popw(u, i)
struct undostack *u;
int *i;
{
if (u->ptr < 1 && !popblock(u))
return FALSE;
*i = u->coreblock[--u->ptr];
return TRUE;
}
bool PROC
popmem(u, start, size)
struct undostack *u;
int start, size;
{
int chunk, loc;
bool ok;
loc = start+size; /* running backwards */
ok = TRUE;
while (ok && size > 0) {
chunk = min(size, AVAIL(u->ptr));
size -= chunk;
loc -= chunk;
moveleft((char*)&u->coreblock[u->ptr-INDEX(chunk)], &core[loc], chunk);
if (size > 0)
ok = popblock(u);
else
u->ptr -= INDEX(chunk);
}
return(ok);
}
/* delete (I)nserted text */
bool PROC
takeout(save_undo,curp)
struct undostack *save_undo;
int *curp;
{
int lump;
return popw(&undo,curp) && popw(&undo,&lump)
&& delete_to_undo(save_undo,*curp,lump);
}
bool PROC
copyover(save_undo,curp)
struct undostack *save_undo;
int *curp;
{
int lump;
return popw(&undo, curp) && popw(&undo, &lump)
&& move_to_undo(save_undo, *curp, lump)
&& popmem(&undo, *curp, lump);
}
bool PROC
putin(save_undo,curp)
struct undostack *save_undo;
int *curp;
{
int lump;
if (popw(&undo,curp) && popw(&undo,&lump) && (bufmax+lump < SIZE)) {
insert_to_undo(save_undo, *curp, lump);
moveright(&core[*curp], &core[*curp+lump], bufmax-*curp);
if (popmem(&undo, *curp, lump))
return TRUE;
else
moveleft(&core[*curp+lump], &core[*curp], bufmax-*curp);
}
return FALSE;
}
/* driver for undo -- returns last address modified || -1 if error */
int PROC
fixcore(topp)
int *topp;
{
int curp;
static struct undostack save_undo;
bool closeio, ok;
int cch;
if (undo.blockp > 0 || undo.ptr > 0) {
closeio = (undo.blockp > 0);
if (closeio) { /* save diskfile */
CLOSE_FILE(uwrite); /* close current undo file */
rename(undobuf,undotmp);
uread = OPEN_OLD(undotmp); /* reopen it for reading */
if (uread < 0)
return -1;
}
*topp = SIZE+1;
curp = -MAGICNUMBER;
save_undo.blockp = save_undo.ptr = 0;
ok = TRUE;
while (ok && popw(&undo,&cch)) {
switch (cch) {
case U_ADDC : ok = putin(&save_undo, &curp); break;
case U_MOVEC: ok = copyover(&save_undo, &curp); break;
case U_DELC : ok = takeout(&save_undo, &curp); break;
}
if (curp < *topp)
*topp = curp;
}
if (curp >= 0)
undo = save_undo;
if (closeio) {
CLOSE_FILE(uread); /* Zap old buffer */
unlink(undotmp);
}
if (!ok)
error();
return(curp);
}
return ERR;
}

200
src/cmd/levee/unixcall.c Normal file
View File

@@ -0,0 +1,200 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* Unix interface for levee
*/
#include "levee.h"
#ifdef OS_UNIX
#include "extern.h"
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
int
min(a,b)
int a, b;
{
return (a>b) ? b : a;
}
int
max(a,b)
int a, b;
{
return (a<b) ? b : a;
}
void strput(s)
char *s;
{
if (s)
write(1, s, strlen(s));
}
#if !HAVE_BASENAME
char *
basename(s)
char *s;
{
char *rindex();
char *p;
if (p=strrchr(s,'/'))
return 1+p;
return s;
}
#endif
static int ioset = 0;
#ifdef HAVE_TERMIOS_H
#if !HAVE_TCGETATTR
#define tcgetattr(fd,t) ioctl(fd, TCGETS, t)
#define tcsetattr(fd,n,t) ioctl(fd, n, t)
#define TCSANOW TCSETAF
#endif
static struct termios old;
void
initcon()
{
struct termios new;
if (!ioset) {
tcgetattr(0, &old); /* get editing keys */
Erasechar = old.c_cc[VERASE];
eraseline = old.c_cc[VKILL];
new = old;
new.c_iflag &= ~(IXON|IXOFF|IXANY|ICRNL|INLCR);
new.c_lflag &= ~(ICANON|ISIG|ECHO);
new.c_oflag = 0;
tcsetattr(0, TCSANOW, &new);
ioset=1;
}
}
void
fixcon()
{
if (ioset) {
tcsetattr(0, TCSANOW, &old);
ioset = 0;
}
}
#else /* HAVE_TERMIOS_H */
static struct sgttyb old;
static struct tchars oldtchars;
static struct ltchars oldltchars;
void
initcon()
{
struct tchars new_tc;
struct ltchars new_ltc;
struct sgttyb new;
if (!ioset) {
ioctl(0, TIOCGETC, &oldtchars);
ioctl(0, TIOCGLTC, &oldltchars);
/* get editing keys */
Erasechar = 0177;
eraseline = 'U' & 037;
new_tc = oldtchars;
new_tc.t_eofc = -1; /* end-of-file */
new_tc.t_quitc = -1; /* quit */
new_tc.t_intrc = -1; /* interrupt */
new_ltc = oldltchars;
new_ltc.t_suspc = -1; /* stop process */
new_ltc.t_dsuspc = -1; /* delayed stop process */
new_ltc.t_rprntc = -1; /* reprint line */
new_ltc.t_flushc = -1; /* flush output */
new_ltc.t_werasc = -1; /* word erase */
new_ltc.t_lnextc = -1; /* literal next character */
ioctl(0, TIOCSETC, &new_tc);
ioctl(0, TIOCSLTC, &new_ltc);
ioctl(0, TIOCGETP, &old);
new = old;
new.sg_flags &= ~(ECHO | CRMOD | XTABS | RAW);
new.sg_flags |= CBREAK;
ioctl(0, TIOCSETP, &new);
ioset = 1;
}
}
void
fixcon()
{
if (ioset) {
ioctl(0, TIOCSETP, &old);
ioctl(0, TIOCSETC, &oldtchars);
ioctl(0, TIOCSLTC, &oldltchars);
ioset = 0;
}
}
#endif /* HAVE_TERMIOS_H */
int
getKey()
{
unsigned char c[1];
fd_set input;
fflush(stdout);
/* we're using Unix select() to wait for input, so lets hope that
* all the Unices out there support select(). If your Unix doesn't,
* you can make this work by replacing this select loop with:
*
* while (read(0,c,1) != 1)
* ;
* return c[1];
*
* ... and watch your load-average peg.
*/
while (1) {
FD_ZERO(&input);
FD_SET(0, &input);
select(1, &input, 0, 0, 0);
if( read(0,c,1) == 1)
return c[0];
};
}
#endif

1
src/cmd/levee/version.c Normal file
View File

@@ -0,0 +1 @@
char codeversion[] = VERSION;

109
src/cmd/levee/wildargs.c Normal file
View File

@@ -0,0 +1,109 @@
/*
* LEVEE, or Captain Video; A vi clone
*
* Copyright (c) 1982-2007 David L Parsons
* All rights reserved.
*
* Redistribution and use in source and binary forms, without or
* without modification, are permitted provided that the above
* copyright notice and this paragraph are duplicated in all such
* forms and that any documentation, advertising materials, and
* other materials related to such distribution and use acknowledge
* that the software was developed by David L Parsons (orc@pell.chi.il.us).
* My name may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/*
* wildcard filename expanders for levee.
*/
#include "levee.h"
#include "extern.h"
#if OS_UNIX
# include <stdlib.h>
#elif !OS_RMX
# include <glob.h>
#endif
int wilderr, wildcard;
int PROC
expandargs(name, argcp, argvp)
char *name;
int *argcp;
char ***argvp;
{
#if OS_RMX|OS_UNIX
wilderr = doaddwork(name, argcp, argvp) < 0;
#else
register char *p;
wilderr = 0;
if (p=glob(name, (char*)0)) {
do {
if (doaddwork(p, argcp, argvp) < 0) {
wilderr++;
break;
}
} while (p=glob((char*)0, (char*)0));
}
else if (doaddwork(name, argcp, argvp) < 0)
wilderr++;
#endif /*!OS_RMX*/
if (wilderr)
killargs(argcp, argvp);
return !wilderr;
}
#define QUANTUM 10
int PROC
doaddwork(token,argcp,argvp)
char *token;
int *argcp;
char ***argvp;
{
char **ap = *argvp;
int ac = *argcp;
int size;
if ( ac%QUANTUM == 0) { /* realloc more memory! */
size = (QUANTUM+ac)*sizeof(char**);
ap = (ac == 0)?malloc(size):realloc(ap, size);
if (!ap) {
*argcp = 0;
goto memfail;
}
}
if ( (ap[ac] = strdup(token)) ) {
#if OS_ATARI|OS_RMX|OS_FLEXOS
strlwr(ap[ac]); /* monocase filesystem */
#endif
*argvp = ap;
return (*argcp)++;
}
memfail:
errmsg("no memory");
return -1;
}
VOID PROC
killargs(argcp, argvp)
int *argcp;
char ***argvp;
{
int i;
for (i=(*argcp)-1; i >= 0; i--)
free((*argvp)[i]);
if (*argcp)
free(*argvp);
*argcp = 0;
*argvp = 0L;
}