levee-3.5a/000077500000000000000000000000001101573714600126275ustar00rootroot00000000000000levee-3.5a/Makefile.in000066400000000000000000000031761101573714600147030ustar00rootroot00000000000000# 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 levee-3.5a/VERSION000066400000000000000000000000051101573714600136720ustar00rootroot000000000000003.5a levee-3.5a/beep.c000066400000000000000000000023761101573714600137160ustar00rootroot00000000000000/* * 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 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/dev/null >/dev/null; then __ac_dirname() { dirname "$1" } else __ac_dirname() { echo "$1" | sed -e 's:/[^/]*$::' } fi ac_progname=$0 ac_configure_command= Q=\' for x in "$@"; do ac_configure_command="$ac_configure_command $Q$x$Q" done # ac_configure_command="$*" __d=`__ac_dirname "$ac_progname"` if [ "$__d" = "$ac_progname" ]; then AC_SRCDIR=`pwd` else AC_SRCDIR=`cd $__d;pwd` fi __ac_dir() { if test -d "$1"; then (cd "$1";pwd) else echo "$1"; fi } while [ $# -gt 0 ]; do unset matched case X"$1" in X--src|X--srcdir) AC_SRCDIR=`__ac_dir "$2"` _set_srcdir=1 shift 2;; X--src=*|X--srcdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_SRCDIR=`__ac_dir "$__d"` _set_srcdir=1 shift 1 ;; X--prefix) AC_PREFIX=`__ac_dir "$2"` _set_prefix=1 shift 2;; X--prefix=*) __d=`echo "$1"| sed -e 's/^[^=]*=//'` AC_PREFIX=`__ac_dir "$__d"` _set_prefix=1 shift 1;; X--confdir) AC_CONFDIR=`__ac_dir "$2"` _set_confdir=1 shift 2;; X--confdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_CONFDIR=`__ac_dir "$__d"` _set_confdir=1 shift 1;; X--libexec|X--libexecdir) AC_LIBEXEC=`__ac_dir "$2"` _set_libexec=1 shift 2;; X--libexec=*|X--libexecdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_LIBEXEC=`__ac_dir "$__d"` _set_libexec=1 shift 1;; X--lib|X--libdir) AC_LIBDIR=`__ac_dir "$2"` _set_libdir=1 shift 2;; X--lib=*|X--libdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_LIBDIR=`__ac_dir "$__d"` _set_libdir=1 shift 1;; X--exec|X--execdir) AC_EXECDIR=`__ac_dir "$2"` _set_execdir=1 shift 2;; X--exec=*|X--execdir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_EXECDIR=`__ac_dir "$__d"` _set_execdir=1 shift 1;; X--sbin|X--sbindir) AC_SBINDIR=`__ac_dir "$2"` _set_sbindir=1 shift 2;; X--sbin=*|X--sbindir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_SBINDIR=`__ac_dir "$__d"` _set_sbindir=1 shift 1;; X--man|X--mandir) AC_MANDIR=`__ac_dir "$2"` _set_mandir=1 shift 2;; X--man=*|X--mandir=*) __d=`echo "$1" | sed -e 's/^[^=]*=//'` AC_MANDIR=`__ac_dir "$__d"` _set_mandir=1 shift 1;; X--use-*=*) _var=`echo "$1"| sed -n 's/^--use-\([A-Za-z][-A-Za-z0-9_]*\)=.*$/\1/p'` if [ "$_var" ]; then _val=`echo "$1" | sed -e 's/^--use-[^=]*=\(.*\)$/\1/'` _v=`echo $_var | tr '[a-z]' '[A-Z]' | tr '-' '_'` case X"$_val" in X[Yy][Ee][Ss]|X[Tt][Rr][Uu][Ee]) eval USE_${_v}=T ;; X[Nn][Oo]|X[Ff][Aa][Ll][Ss][Ee]) eval unset USE_${_v} ;; *) echo "Bad value for --use-$_var ; must be yes or no" exit 1 ;; esac else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--use-*) _var=`echo "$1"|sed -n 's/^--use-\([A-Za-z][-A-Za-z0-9_]*\)$/\1/p'` _v=`echo $_var | tr '[a-z]' '[A-Z]' | tr '-' '_'` eval USE_${_v}=T shift 1;; X--with-*=*) _var=`echo "$1"| sed -n 's/^--with-\([A-Za-z][-A-Za-z0-9_]*\)=.*$/\1/p'` if [ "$_var" ]; then _val=`echo "$1" | sed -e 's/^--with-[^=]*=\(.*\)$/\1/'` _v=`echo $_var | tr '[a-z]' '[A-Z]' | tr '-' '_'` eval WITH_${_v}=\"$_val\" else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--with-*) _var=`echo "$1" | sed -n 's/^--with-\([A-Za-z][A-Za-z0-9_-]*\)$/\1/p'` if [ "$_var" ]; then _v=`echo $_var | tr '[a-z]' '[A-Z]' | tr '-' '_'` eval WITH_${_v}=1 else echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi shift 1 ;; X--help) echo "$ac_standard" test "$ac_help" && echo "$ac_help" exit 0;; *) if [ "$LOCAL_AC_OPTIONS" ]; then eval "$LOCAL_AC_OPTIONS" else ac_error=T fi if [ "$ac_error" ]; then echo "Bad option $1. Use --help to show options" 1>&2 exit 1 fi ;; esac done # # echo w/o newline # echononl() { ${ac_echo:-echo} "${@}$ac_echo_nonl" } # # log something to the terminal and to a logfile. # LOG () { echo "$@" echo "$@" 1>&5 } # # log something to the terminal without a newline, and to a logfile with # a newline # LOGN () { echononl "$@" 1>&5 echo "$@" } # # log something to the terminal # TLOG () { echo "$@" 1>&5 } # # log something to the terminal, no newline # TLOGN () { echononl "$@" 1>&5 } # # AC_CONTINUE tells configure not to bomb if something fails, but to # continue blithely along # AC_CONTINUE () { __fail="return" } # # Emulate gnu autoconf's AC_CHECK_HEADERS() function # AC_CHECK_HEADERS () { AC_PROG_CC echo "/* AC_CHECK_HEADERS */" > /tmp/ngc$$.c for hdr in $*; do echo "#include <$hdr>" >> /tmp/ngc$$.c done echo "main() { }" >> /tmp/ngc$$.c LOGN "checking for header $hdr" if $AC_CC -o /tmp/ngc$$ /tmp/ngc$$.c; then AC_DEFINE 'HAVE_'`echo $hdr | tr 'a-z' 'A-Z' | tr './' '_'` 1 TLOG " (found)" rc=0 else TLOG " (not found)" rc=1 fi rm -f /tmp/ngc$$.c /tmp/ngc$$ return $rc } # # emulate GNU autoconf's AC_CHECK_FUNCS function # AC_CHECK_FUNCS () { AC_PROG_CC F=$1 shift rm -f /tmp/ngc$$.c while [ "$1" ]; do echo "#include <$1>" >> /tmp/ngc$$.c shift done cat >> /tmp/ngc$$.c << EOF main() { $F(); } EOF LOGN "checking for the $F function" if $AC_CC -o /tmp/ngc$$ /tmp/ngc$$.c $LIBS; then AC_DEFINE `echo ${2:-HAVE_$F} | tr 'a-z' 'A-Z'` 1 TLOG " (found)" rc=0 else echo "offending command was:" cat /tmp/ngc$$.c echo "$AC_CC -o /tmp/ngc$$ /tmp/ngc$$.c $LIBS" TLOG " (not found)" rc=1 fi rm -f /tmp/ngc$$.c /tmp/ngc$$ return $rc } # # check to see if some structure exists # # usage: AC_CHECK_STRUCT structure {include ...} # AC_CHECK_STRUCT () { AC_PROG_CC struct=$1 shift rm -f /tmp/ngc$$.c for include in $*; do echo "#include <$include>" >> /tmp/ngc$$.c done cat >> /tmp/ngc$$.c << EOF main() { struct $struct foo; } EOF LOGN "checking for struct $struct" if $AC_CC -o /tmp/ngc$$ /tmp/ngc$$.c $AC_LIBS 2>>config.log; then AC_DEFINE HAVE_STRUCT_`echo ${struct} | tr 'a-z' 'A-Z'` TLOG " (found)" rc=0 else TLOG " (not found)" rc=1 fi rm -f /tmp/ngc$$.c /tmp/ngc$$ return $rc } # # check to see if some structure contains a field # # usage: AC_CHECK_FIELD structure field {include ...} # AC_CHECK_FIELD () { AC_PROG_CC struct=$1 field=$2 shift 2 rm -f /tmp/ngc$$.c for include in $*;do echo "#include <$include>" >> /tmp/ngc$$.c done cat >> /tmp/ngc$$.c << EOF main() { struct $struct foo; foo.$field; } EOF LOGN "checking that struct $struct has a $field field" if $AC_CC -o /tmp/ngc$$ /tmp/ngc$$.c $AC_LIBS 2>>config.log; then AC_DEFINE HAVE_`echo ${struct}_$field | tr 'a-z' 'A-Z'` TLOG " (yes)" rc=0 else TLOG " (no)" rc=1 fi rm -f /tmp/ngc$$.c /tmp/ngc$$ return $rc } # # check that the C compiler works # AC_PROG_CC () { test "$AC_CC" && return 0 cat > /tmp/ngc$$.c << \EOF #include main() { puts("hello, sailor"); } EOF TLOGN "checking the C compiler" unset AC_CFLAGS AC_LDFLAGS if [ "$CC" ] ; then AC_CC="$CC" elif [ "$WITH_PATH" ]; then AC_CC=`acLookFor cc` elif [ "`acLookFor cc`" ]; then # don't specify the full path if the user is looking in their $PATH # for a C compiler. AC_CC=cc fi # finally check for POSIX c89 test "$AC_CC" || AC_CC=`acLookFor c89` if [ ! "$AC_CC" ]; then TLOG " (no C compiler found)" $__fail 1 fi echo "checking out the C compiler" $AC_CC -c -o /tmp/ngc$$.o /tmp/ngc$$.c $AC_CC -o /tmp/ngc$$ /tmp/ngc$$.o status=$? TLOGN " ($AC_CC)" if [ $status -eq 0 ]; then TLOG " ok" # check that the CFLAGS and LDFLAGS aren't bogus unset AC_CFLAGS AC_LDFLAGS if [ "$CFLAGS" ]; then test "$CFLAGS" && echo "validating CFLAGS=${CFLAGS}" if $AC_CC $CFLAGS -c -o /tmp/ngc$$.o /tmp/ngc$$.c ; then AC_CFLAGS=${CFLAGS:-"-g"} test "$CFLAGS" && echo "CFLAGS=\"${CFLAGS}\" are okay" elif [ "$CFLAGS" ]; then echo "ignoring bogus CFLAGS=\"${CFLAGS}\"" fi else AC_CFLAGS=-g fi if [ "$LDFLAGS" ]; then echo "validating LDFLAGS=${LDFLAGS}" if $AC_CC $LDFLAGS -o /tmp/ngc$$ /tmp/ngc$$.o; then AC_LDFLAGS="$LDFLAGS" TLOG "LDFLAGS=\"${AC_LDFLAGS}\" are okay" else TLOG "ignoring bogus LDFLAGS=\"${LDFLAGS}\"" fi else AC_LDFLAGS=${CFLAGS:-"-g"} fi else AC_FAIL " does not compile code properly" fi AC_SUB 'CC' "$AC_CC" rm -f /tmp/ngc$$ /tmp/ngc$$.c /tmp/ngc$$.o return $status } # # acLookFor actually looks for a program, without setting anything. # acLookFor () { path=${AC_PATH:-$ac_default_path} case "X$1" in X-[rx]) __mode=$1 shift ;; *) __mode=-x ;; esac oldifs="$IFS" for program in $*; do IFS=":" for x in $path; do if [ $__mode $x/$program -a -f $x/$program ]; then echo $x/$program break 2 fi done done IFS="$oldifs" unset __mode } # # check that a program exists and set its path # MF_PATH_INCLUDE () { SYM=$1; shift case X$1 in X-[rx]) __mode=$1 shift ;; *) unset __mode ;; esac TLOGN "looking for $1" DEST=`acLookFor $__mode $*` __sym=`echo "$SYM" | tr '[a-z]' '[A-Z]'` if [ "$DEST" ]; then TLOG " ($DEST)" echo "$1 is $DEST" AC_MAK $SYM AC_DEFINE PATH_$__sym \""$DEST"\" AC_SUB $__sym "$DEST" eval CF_$SYM=$DEST return 0 else #AC_SUB $__sym '' echo "$1 is not found" TLOG " (not found)" return 1 fi } # # AC_INIT starts the ball rolling # # After AC_INIT, fd's 1 and 2 point to config.log # and fd 5 points to what used to be fd 1 # AC_INIT () { __config_files="config.cmd config.sub config.h config.mak config.log" rm -f $__config_files __cwd=`pwd` exec 5>&1 1>$__cwd/config.log 2>&1 AC_CONFIGURE_FOR=__AC_`echo $1 | sed -e 's/\..$//' | tr 'a-z' 'A-Z' | tr ' ' '_'`_D # check to see whether to use echo -n or echo ...\c # echo -n hello > $$ echo world >> $$ if grep "helloworld" $$ >/dev/null; then ac_echo="echo -n" echo "[echo -n] works" else ac_echo="echo" echo 'hello\c' > $$ echo 'world' >> $$ if grep "helloworld" $$ >/dev/null; then ac_echo_nonl='\c' echo "[echo ...\\c] works" fi fi rm -f $$ LOG "Configuring for [$1]" cat > $__cwd/config.h << EOF /* * configuration for $1${2:+" ($2)"}, generated `date` * by ${LOGNAME:-`whoami`}@`hostname` */ #ifndef $AC_CONFIGURE_FOR #define $AC_CONFIGURE_FOR 1 EOF unset __share if [ -d $AC_PREFIX/share/man ]; then for t in 1 2 3 4 5 6 7 8 9; do if [ -d $AC_PREFIX/share/man/man$t ]; then __share=/share elif [ -d $AC_PREFIX/share/man/cat$t ]; then __share=/share fi done else __share= fi if [ -d $AC_PREFIX/libexec ]; then __libexec=libexec else __libexec=lib fi AC_PREFIX=${AC_PREFIX:-/usr/local} AC_EXECDIR=${AC_EXECDIR:-$AC_PREFIX/bin} AC_SBINDIR=${AC_SBINDIR:-$AC_PREFIX/sbin} AC_LIBDIR=${AC_LIBDIR:-$AC_PREFIX/lib} AC_MANDIR=${AC_MANDIR:-$AC_PREFIX$__share/man} AC_LIBEXEC=${AC_LIBEXEC:-$AC_PREFIX/$__libexec} AC_CONFDIR=${AC_CONFDIR:-/etc} AC_PATH=${WITH_PATH:-$PATH} AC_PROG_CPP AC_PROG_INSTALL if [ -z "$ac_os" ]; then ac_os=`uname -s` fi _os=`echo $ac_os | tr '[a-z]' '[A-Z]'` AC_DEFINE OS_$_os 1 eval OS_${_os}=1 unset _os } # # AC_LIBRARY checks to see if a given library exists and contains the # given function. # usage: AC_LIBRARY function library [alternate ...] # AC_LIBRARY() { SRC=$1 shift # first see if the function can be found in any of the # current libraries AC_QUIET AC_CHECK_FUNCS $SRC && return 0 # then search through the list of libraries __libs="$LIBS" for x in $*; do LIBS="$__libs $x" if AC_QUIET AC_CHECK_FUNCS $SRC; then AC_LIBS="$AC_LIBS $x" return 0 fi done return 1 } # # AC_PROG_LEX checks to see if LEX exists, and if it's lex or flex. # AC_PROG_LEX() { TLOGN "looking for lex " DEST=`acLookFor lex` if [ "$DEST" ]; then AC_MAK LEX AC_DEFINE PATH_LEX \"$DEST\" AC_SUB 'LEX' "$DEST" echo "lex is $DEST" else DEST=`acLookFor flex` if [ "$DEST" ]; then AC_MAK FLEX AC_DEFINE 'LEX' \"$DEST\" AC_SUB 'LEX', "$DEST" echo "lex is $DEST" else AC_SUB LEX '' echo "neither lex or flex found" TLOG " (not found)" return 1 fi fi if AC_LIBRARY yywrap -ll -lfl; then TLOG "($DEST)" return 0 fi TLOG "(no lex library found)" return 1 } # # AC_PROG_YACC checks to see if YACC exists, and if it's bison or # not. # AC_PROG_YACC () { TLOGN "looking for yacc " DEST=`acLookFor yacc` if [ "$DEST" ]; then AC_MAK YACC AC_DEFINE PATH_YACC \"$DEST\" AC_SUB 'YACC' "$DEST" TLOG "($DEST)" echo "yacc is $DEST" else DEST=`acLookFor bison` if [ "$DEST" ]; then AC_MAK BISON AC_DEFINE 'YACC' \"$DEST\" AC_SUB 'YACC' "$DEST -y" echo "yacc is $DEST -y" TLOG "($DEST -y)" else AC_SUB 'YACC' '' echo "neither yacc or bison found" TLOG " (not found)" return 1 fi fi return 0 } # # AC_PROG_LN_S checks to see if ln exists, and, if so, if ln -s works # AC_PROG_LN_S () { test "$AC_FIND_PROG" || AC_PROG_FIND test "$AC_FIND_PROG" || return 1 TLOGN "looking for \"ln -s\"" DEST=`acLookFor ln` if [ "$DEST" ]; then rm -f /tmp/b$$ $DEST -s /tmp/a$$ /tmp/b$$ if [ "`$AC_FIND_PROG /tmp/b$$ -type l -print`" ]; then TLOG " ($DEST)" echo "$DEST exists, and ln -s works" AC_SUB 'LN_S' "$DEST -s" rm -f /tmp/b$$ else AC_SUB 'LN_S' '' TLOG " ($DEST exists, but -s does not seem to work)" echo "$DEST exists, but ln -s doesn't seem to work" rm -f /tmp/b$$ return 1 fi else AC_SUB 'LN_S' '' echo "ln not found" TLOG " (not found)" return 1 fi } # # AC_PROG_FIND looks for the find program and sets the FIND environment # variable # AC_PROG_FIND () { if test -z "$AC_FIND_PROG"; then MF_PATH_INCLUDE FIND find rc=$? AC_FIND_PROG=$DEST return $rc fi return 0 } # # AC_PROG_AWK looks for the awk program and sets the AWK environment # variable # AC_PROG_AWK () { if test -z "$AC_AWK_PROG"; then MF_PATH_INCLUDE AWK awk rc=$? AC_AWK_PROG=$DEST return $rc fi return 0 } # # AC_PROG_SED looks for the sed program and sets the SED environment # variable # AC_PROG_SED () { if test -z "$AC_SED_PROG"; then MF_PATH_INCLUDE SED sed rc=$? AC_SED_PROG=$DEST return $rc fi return 0 } # # AC_HEADER_SYS_WAIT looks for sys/wait.h # AC_HEADER_SYS_WAIT () { AC_CHECK_HEADERS sys/wait.h || return 1 } # # AC_TYPE_PID_T checks to see if the pid_t type exists # AC_TYPE_PID_T () { cat > /tmp/pd$$.c << EOF #include main() { pid_t me; } EOF LOGN "checking for pid_t" if $AC_CC -c /tmp/pd$$.c -o /tmp/pd$$.o; then TLOG " (found)" rc=0 else echo "typedef int pid_t;" >> $__cwd/config.h TLOG " (not found)" rc=1 fi rm -f /tmp/pd$$.o /tmp/pd$$.c return $rc } # # AC_C_CONST checks to see if the compiler supports the const keyword # AC_C_CONST () { cat > /tmp/pd$$.c << EOF const char me=1; EOF LOGN "checking for \"const\" keyword" if $AC_CC -c /tmp/pd$$.c -o /tmp/pd$$.o; then TLOG " (yes)" rc=0 else AC_DEFINE 'const' '/**/' TLOG " (no)" rc=1 fi rm -f /tmp/pd$$.o /tmp/pd$$.c return $rc } # # AC_SCALAR_TYPES checks to see if the compiler can generate 2 and 4 byte ints. # AC_SCALAR_TYPES () { cat > /tmp/pd$$.c << EOF #include main() { unsigned long v_long; unsigned int v_int; unsigned short v_short; if (sizeof v_long == 4) puts("#define DWORD unsigned long"); else if (sizeof v_int == 4) puts("#define DWORD unsigned int"); else exit(1); if (sizeof v_int == 2) puts("#define WORD unsigned int"); else if (sizeof v_short == 2) puts("#define WORD unsigned short"); else exit(2); puts("#define BYTE unsigned char"); exit(0); } EOF rc=1 LOGN "defining WORD & DWORD scalar types" if $AC_CC /tmp/pd$$.c -o /tmp/pd$$; then if /tmp/pd$$ >> $__cwd/config.h; then rc=0 fi fi case "$rc" in 0) TLOG "" ;; *) TLOG " ** FAILED **" ;; esac rm -f /tmp/pd$$ /tmp/pd$$.c } # # AC_OUTPUT generates makefiles from makefile.in's # AC_OUTPUT () { cd $__cwd AC_SUB 'LIBS' "$AC_LIBS" AC_SUB 'CONFIGURE_FILES' "$__config_files" AC_SUB 'GENERATED_FILES' "$*" AC_SUB 'CFLAGS' "$AC_CFLAGS" AC_SUB 'LDFLAGS' "$AC_LDFLAGS" AC_SUB 'srcdir' "$AC_SRCDIR" AC_SUB 'prefix' "$AC_PREFIX" AC_SUB 'exedir' "$AC_EXECDIR" AC_SUB 'sbindir' "$AC_SBINDIR" AC_SUB 'libdir' "$AC_LIBDIR" AC_SUB 'libexec' "$AC_LIBEXEC" AC_SUB 'confdir' "$AC_CONFDIR" AC_SUB 'mandir' "$AC_MANDIR" if [ -r config.sub ]; then test "$AC_SED_PROG" || AC_PROG_SED test "$AC_SED_PROG" || return 1 echo >> config.h echo "#endif/* ${AC_CONFIGURE_FOR} */" >> config.h rm -f config.cmd Q=\' cat - > config.cmd << EOF #! /bin/sh ${CC:+CC=${Q}${CC}${Q}}${CFLAGS:+ CFLAGS=${Q}${CFLAGS}${Q}}${LDFLAGS:+ LDFLAGS=${Q}${LDFLAGS}${Q}} $ac_progname $ac_configure_command EOF chmod +x config.cmd __d=$AC_SRCDIR for makefile in $*;do if test -r $__d/${makefile}.in; then LOG "generating $makefile" ./config.md `__ac_dirname ./$makefile` 2>/dev/null $AC_SED_PROG -f config.sub < $__d/${makefile}.in > $makefile __config_files="$__config_files $makefile" else LOG "WARNING: ${makefile}.in does not exist!" fi done unset __d else echo fi } # # AC_CHECK_FLOCK checks to see if flock() exists and if the LOCK_NB argument # works properly. # AC_CHECK_FLOCK() { AC_CHECK_HEADERS sys/types.h sys/file.h fcntl.h cat << EOF > $$.c #include #include #include #include main() { int x = open("$$.c", O_RDWR, 0666); int y = open("$$.c", O_RDWR, 0666); if (flock(x, LOCK_EX) != 0) exit(1); if (flock(y, LOCK_EX|LOCK_NB) == 0) exit(1); exit(0); } EOF LOGN "checking for flock()" HAS_FLOCK=0 if $AC_CC -o flock $$.c ; then if ./flock ; then LOG " (found)" HAS_FLOCK=1 AC_DEFINE HAS_FLOCK else LOG " (bad)" fi else LOG " (no)" fi rm -f flock $$.c case "$HAS_FLOCK" in 0) return 1 ;; *) return 0 ;; esac } # # AC_PROG_INSTALL finds the install program and guesses whether it's a # Berkeley or GNU install program # AC_PROG_INSTALL () { DEST=`acLookFor install` LOGN "checking for install" unset IS_BSD if [ "$DEST" ]; then # BSD install or GNU install? Let's find out... touch /tmp/a$$ $DEST /tmp/a$$ /tmp/b$$ if test -r /tmp/a$$; then LOG " ($DEST)" else IS_BSD=1 LOG " ($DEST) bsd install" fi rm -f /tmp/a$$ /tmp/b$$ else DEST=`acLookFor ginstall` if [ "$DEST" ]; then LOG " ($DEST)" else DEST="false" LOG " (not found)" fi fi if [ "$IS_BSD" ]; then PROG_INSTALL="$DEST -c" else PROG_INSTALL="$DEST" fi AC_SUB 'INSTALL' "$PROG_INSTALL" AC_SUB 'INSTALL_PROGRAM' "$PROG_INSTALL -s -m 755" AC_SUB 'INSTALL_DATA' "$PROG_INSTALL -m 444" # finally build a little directory installer # if mkdir -p works, use that, otherwise use install -d, # otherwise build a script to do it by hand. # in every case, test to see if the directory exists before # making it. if mkdir -p $$a/b; then # I like this method best. __mkdir="mkdir -p" rmdir $$a/b rmdir $$a elif $PROG_INSTALL -d $$a/b; then __mkdir="$PROG_INSTALL -d" rmdir $$a/b rmdir $$a fi __config_files="$__config_files config.md" AC_SUB 'INSTALL_DIR' "$__cwd/config.md" echo "#! /bin/sh" > $__cwd/config.md echo "# script generated" `date` "by configure.sh" >> $__cwd/config.md echo >> $__cwd/config.md if [ "$__mkdir" ]; then echo "test -d \"\$1\" || $__mkdir \"\$1\"" >> $__cwd/config.md echo "exit $?" >> $__cwd/config.md else cat - >> $__cwd/config.md << \EOD pieces=`IFS=/; for x in $1; do echo $x; done` dir= for x in $pieces; do dir="$dir$x" mkdir $dir || exit 1 dir="$dir/" done exit 0 EOD fi chmod +x $__cwd/config.md } # # acCheckCPP is a local that runs a C preprocessor with a given set of # compiler options # acCheckCPP () { cat > /tmp/ngc$$.c << EOF #define FOO BAR FOO EOF if $1 $2 /tmp/ngc$$.c > /tmp/ngc$$.o; then if grep -v '#define' /tmp/ngc$$.o | grep -s BAR >/dev/null; then echo "CPP=[$1], CPPFLAGS=[$2]" AC_SUB 'CPP' "$1" AC_SUB 'CPPFLAGS' "$2" rm /tmp/ngc$$.c /tmp/ngc$$.o return 0 fi fi rm /tmp/ngc$$.c /tmp/ngc$$.o return 1 } # # AC_PROG_CPP checks for cpp, then checks to see which CPPFLAGS are needed # to run it as a filter. # AC_PROG_CPP () { if [ "$AC_CPP_PROG" ]; then DEST=$AC_CPP_PROG else __ac_path="$AC_PATH" AC_PATH="/lib:/usr/lib:${__ac_path:-$ac_default_path}" DEST=`acLookFor cpp` AC_PATH="$__ac_path" fi unset fail LOGN "Looking for cpp" if [ "$DEST" ]; then TLOGN " ($DEST)" acCheckCPP $DEST "$CPPFLAGS" || \ acCheckCPP $DEST -traditional-cpp -E || \ acCheckCPP $DEST -E || \ acCheckCPP $DEST -traditional-cpp -pipe || \ acCheckCPP $DEST -pipe || fail=1 if [ "$fail" ]; then AC_FAIL " (can't run cpp as a pipeline)" else TLOG " ok" return 0 fi fi AC_FAIL " (not found)" } # # AC_FAIL spits out an error message, then __fail's AC_FAIL() { LOG "$*" $__fail 1 } # # AC_SUB writes a substitution into config.sub AC_SUB() { ( _subst=`echo $2 | sed -e 's/;/\\;/g'` echo "s;@$1@;$_subst;g" ) >> $__cwd/config.sub } # # AC_MAK writes a define into config.mak AC_MAK() { echo "HAVE_$1 = 1" >> $__cwd/config.mak } # # AC_DEFINE adds a #define to config.h AC_DEFINE() { echo "#define $1 ${2:-1}" >> $__cwd/config.h } # # AC_CONFIG adds a configuration setting to all the config files AC_CONFIG() { AC_DEFINE "PATH_$1" \""$2"\" AC_MAK "$1" AC_SUB "$1" "$2" } # # AC_QUIET does something quietly AC_QUIET() { eval $* 5>/dev/null } levee-3.5a/configure.sh000077500000000000000000000054071101573714600151550ustar00rootroot00000000000000#! /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 " 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 levee-3.5a/display.c000066400000000000000000000137371101573714600144530ustar00rootroot00000000000000/* * 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 -- * ^ for control- * spaces for * 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 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); } levee-3.5a/dos.asm000066400000000000000000000014401101573714600141150ustar00rootroot00000000000000 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 levee-3.5a/doscall.c000066400000000000000000000112171101573714600144160ustar00rootroot00000000000000/* * 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 #include int PROC min(a,b) int a,b; { return (a>b) ? b : a; } int PROC max(a,b) int a,b; { return (a 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*/ levee-3.5a/editcor.c000066400000000000000000000325741101573714600144370ustar00rootroot00000000000000/* * 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 /* 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 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 ( !getline(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 */ } levee-3.5a/exec.c000066400000000000000000000451741101573714600137320ustar00rootroot00000000000000#include "levee.h" #include "extern.h" #include #include VOID PROC undefine(); VOID PROC fixupline(); VOID PROC doinput(); /* * do a newline and set flags. */ #define exprintln() (zotscreen=YES),println() VOID PROC plural(num,string) int num; char *string; { printi(num); prints(string); if (num != 1) printch('s'); } /* plural */ VOID PROC clrmsg() { mvcur(-1,0); strput(CE); } /* clrmsg */ VOID PROC errmsg(msg) char *msg; { mvcur(-1,0); prints(msg); strput(CE); } /* errmsg */ /* get a space-delimited token */ char *execstr; /* if someone calls getarg in the */ /* wrong place, death will come... */ char *PROC getarg() { char *rv; rv = execstr; while (*execstr && !isspace(*execstr)) ++execstr; if (*execstr) { *execstr++ = 0; while (isspace(*execstr)) ++execstr; } return (*rv) ? rv : NULL; } /* getarg */ VOID PROC version() /* version: print which version of levee we are... */ { errmsg("levee (c)");prints(codeversion); } /* version */ VOID PROC args() /* args: print the argument list */ { register int i; mvcur(-1,0); for (i=0; i < argc; i++) { if (curpos.x+strlen(argv[i]) >= COLS) exprintln(); else if (i > 0) printch(' '); if (pc == i) { /* highlight the current filename.. */ #if OS_ATARI|OS_FLEXOS strput("\033p"); #else printch('['); #endif prints(argv[i]); #if OS_ATARI|OS_FLEXOS strput("\033q"); #else printch(']'); #endif } else prints(argv[i]); } } /* args */ VOID PROC setcmd() { bool no = NO,b; #if 0 int len,i; #endif char *arg, *num; struct variable *vp; if ( (arg = getarg()) ) { do { if (*arg != 0) { if ( (num = strchr(arg, '=')) ) { b = NO; *num++ = 0; } else { /* set [no]opt */ b = YES; if (arg[0]=='n' && arg[1]=='o') { arg += 2; no = NO; } else no = YES; } for(vp=vars;vp->u && strcmp(arg,vp->v_name) && strcmp(arg,vp->v_abbr); vp++) ; if (!vp->u || vp->v_flags & V_CONST) { errmsg("Can't set "); prints(arg); } else { int j; if (b) if (vp->v_tipe == VBOOL) vp->u->valu = no; else goto badsettype; else if (vp->v_tipe == VSTR) { if (vp->u->strp) free(vp->u->strp); vp->u->strp = (*num) ? strdup(num) : NULL; } else if (*num && (j=atoi(num)) >= 0) vp->u->valu = j; else { badsettype: errmsg("bad set type"); continue; } diddled |= vp->v_flags & V_DISPLAY; } } } while ( (arg = getarg()) ); } else { version(); exprintln(); for(vp=vars;vp->u;vp++) { switch (vp->v_tipe) { case VBOOL: if (!vp->u->valu) prints("no"); prints(vp->v_name); break; case VSTR: if (!vp->u->strp) prints("no "); prints(vp->v_name); if (vp->u->strp) { mvcur(-1,10); prints("= "); prints(vp->u->strp); } break; default: prints(vp->v_name); mvcur(-1,10); prints("= "); printi(vp->u->valu); break; } exprintln(); } } } /* setcmd */ /* print a macro */ VOID PROC printone(i) int i; { if (i >= 0) { exprintln(); printch(mbuffer[i].token); mvcur(-1,3); if (movemap[(unsigned int)(mbuffer[i].token)] == INSMACRO) prints("!= "); else prints(" = "); prints(mbuffer[i].m_text); } } /* printone */ /* print all the macros */ VOID PROC printall() { int i; for (i = 0; i < MAXMACROS; i++) if (mbuffer[i].token != 0) printone(i); } /* printall */ /* :map ch text */ VOID PROC map(insert) bool insert; { char *macro, c; int i; /* get the macro */ if ((macro=getarg()) == NULL) { printall(); return; } if (strlen(macro) > 1) { errmsg("macros must be one character"); return; } c = macro[0]; if (*execstr == 0) printone(lookup(c)); else { if ((i = lookup(0)) < 0) errmsg("macro table full"); else if (c == ESC || c == ':') { errmsg("can't map "); printch(c); } else if (*execstr != 0) { undefine(lookup(c)); mbuffer[i].token = c; mbuffer[i].m_text = strdup(execstr); mbuffer[i].oldmap = movemap[(unsigned int)c]; if (insert) movemap[(unsigned int)c] = INSMACRO; else movemap[(unsigned int)c] = SOFTMACRO; } } } /* map */ VOID PROC undefine(i) int i; { char *p; if (i >= 0) { movemap[(unsigned int)(mbuffer[i].token)] = mbuffer[i].oldmap; mbuffer[i].token = 0; p = mbuffer[i].m_text; free(p); mbuffer[i].m_text = 0; } } /* undefine */ int PROC unmap() { int i; char *arg; if ( (arg=getarg()) ) { if (strlen(arg) == 1) { undefine(lookup(*arg)); return YES; } if (strcmp(arg,"all") == 0) { for (i = 0; i < MAXMACROS; i++) if (mbuffer[i].token != 0) undefine(i); return YES; } } return NO; } /* unmap */ /* return argument # of a filename */ int PROC findarg(name) register char *name; { int j; for (j = 0; j < argc; j++) if (strcmp(argv[j],name) == 0) return j; return -1; } /* findarg */ /* add a filename to the arglist */ int PROC addarg(name) register char *name; { int where; if ((where = findarg(name)) < 0) return doaddwork(name, &argc, &argv); return where; } /* addarg */ /* get a file name argument (substitute alt file for #) */ char * PROC getname() { extern int wilderr; #if OS_ATARI extern int mapslash; register char *p; #endif register char *name; if ( (name = getarg()) ) { if ( 0 == strcmp(name,"#") ) { if (*altnm) name = altnm; else { errmsg("no alt name"); wilderr++; return NULL; } } #if OS_ATARI if (mapslash) for (p=name; *p; p++) if (*p == '/') *p = '\\'; #endif } return name; } /* getname */ /* CAUTION: these make exec not quite recursive */ int high,low; /* low && high end of command range */ bool affirm; /* cmd! */ /* s/[src]/dst[/options] */ /* s& */ VOID PROC cutandpaste() { bool askme = NO, printme= NO, glob = NO; int newcurr = -1; int oldcurr = curr; int num; char delim; register char *ip; register char *dp; zerostack(&undo); ip = execstr; if (*ip != '&') { delim = *ip; ip = makepat(1+ip,delim); /* get search */ if (ip == NULL) goto splat; dp = dst; while (*ip && *ip != delim) { if (*ip == '\\' && ip[1] != 0) *dp++ = *ip++; *dp++ = *ip++; } *dp = 0; if (*ip == delim) { while (*++ip) switch (*ip) { case 'q': case 'c': askme = YES; break; case 'g': glob = YES; break; case 'p': printme= YES; break; } } } if (*lastpatt == 0) { splat: errmsg("bad substitute"); return; } fixupline(bseekeol(curr)); num = 0; do { low = chop(low, &high, NO, &askme); if (low > -1) { diddled = YES; num++; if (printme) { exprintln(); writeline(-1,-1,bseekeol(low)); } if (newcurr < 0) newcurr = low; if (!glob) low = 1+fseekeol(low); } } while (low >= 0); if (num > 0) { exprintln(); plural(num," substitution"); } fixupline((newcurr > -1) ? newcurr : oldcurr); } /* cutandpaste */ /* quietly read in a file (and mark it in the undo stack) */ int PROC insertfile(FILE *f, int insert, int at, int *fsize) { int high, onright, rc=0; onright = (bufmax-at); high = SIZE-onright; if ( insert && (onright > 0) ) moveright(&core[at], &core[high], onright); rc = addfile(f, at, high, fsize); if ( (rc == 0) && (*fsize < 0) ) { rc = -1; *fsize=0; } if ( insert ) { if ( *fsize ) insert_to_undo(&undo, at, *fsize); modified = YES; if (onright > 0) moveleft(&core[high], &core[at+(*fsize)], onright); } diddled = YES; return rc; } /* insertfile */ VOID PROC inputf(fname, newbuf) register char *fname; bool newbuf; { FILE *f; int fsize, /* bytes read in */ rc; if (newbuf) readonly = NO; zerostack(&undo); if ( newbuf ) { modified = NO; low = 0; } else { fixupline(bseekeol(curr)); } printch('"'); prints(fname); prints("\" "); if ((f=fopen(fname, "r")) == NULL) { prints("[No such file]"); fsize = 0; if (newbuf) newfile = YES; } else { rc = insertfile(f, !newbuf, low, &fsize); fclose(f); if ( rc > 0 ) plural(fsize, " byte"); else if ( rc < 0 ) prints("[read error]"); else { prints("[overflow]"); readonly=1; } if (newbuf) newfile = NO; } if (newbuf) { fillchar(contexts, sizeof(contexts), -1); bufmax = fsize; } if (*startcmd) { count = 1; if (*findparse(startcmd,&curr,low) != 0 || curr < 0) curr = low; *startcmd = 0; } else curr = low; } /* inputf */ /* Change a file's name (for autocopy). */ VOID PROC backup(name) char *name; { char back[80]; #if !OS_UNIX char *p; #endif strcpy(back, name); #if OS_UNIX strcat(back, "~"); #else p = strrchr(basename(back), '.'); if (p) strcpy(1+p, ",bkp"); else strcat(back, ".bkp"); #endif unlink(back); rename(name, back); } /* backup */ bool PROC outputf(fname) char *fname; { bool whole; FILE *f; int status; zerostack(&undo); /* undo doesn't survive past write */ if (high < 0) high = (low < 0) ? bufmax : (1+fseekeol(low)); if (low < 0) low = 0; printch('"'); prints(fname); prints("\" "); whole = (low == 0 && high >= bufmax-1); if (whole && autocopy) backup(fname); if ( (f=fopen(fname, "w")) ) { status = putfile(f, low, high); fclose(f); if (status) { plural(high-low," byte"); if (whole) modified = NO; return(YES); } else { prints("[write error]"); unlink(fname); } } else prints(fisro); return(NO); } /* outputf */ int PROC oktoedit(writeold) /* check and see if it is ok to edit a new file */ int writeold; /* automatically write out changes? */ { if (modified && !affirm) { if (readonly) { errmsg(fisro); return NO; } else if (writeold && *filenm) { if (!outputf(filenm)) return NO; printch(','); } else { errmsg(fismod); return NO; } } return YES; } /* oktoedit */ /* write out all || part of a file */ bool PROC writefile() { char *name; if ((name=getname()) == NULL) name = filenm; if (*name) { if (outputf(name)) { addarg(name); return YES; } else strcpy(altnm, name); } else errmsg("no file to write"); return NO; } VOID PROC editfile() { char *name = NULL; /* file to edit */ char **myargv; int myargc; int i, newpc; if ((name = getarg()) && *name == '+') { strcpy(startcmd, (name[1])?(1+name):"$"); name = getarg(); } myargc=0; if (name) do { if (!expandargs(name, &myargc, &myargv)) return; } while ( (name=getarg()) ); if (myargc == 0) { if (*filenm) name = filenm; else errmsg("no file to edit"); } else if ((newpc = addarg(myargv[0])) >= 0) { name = argv[pc = newpc]; for (i=1; i < myargc && doaddwork(myargv[i], &argc, &argv) >= 0; i++) ; } killargs(&myargc, &myargv); if (name && oktoedit(NO)) doinput(name); } VOID PROC doinput(name) char *name; { inputf(name, YES); strcpy(altnm, filenm); strcpy(filenm, name); } VOID PROC toedit(count) int count; { if (count > 1) { printi(count); prints(" files to edit; "); } } VOID PROC readfile() { char *name; if ( (name=getarg()) ) inputf(name,NO); else errmsg("no file to read"); } VOID PROC nextfile(prev) bool prev; { char *name = NULL; int newpc=pc, myargc=0; char **myargv; bool newlist = NO; if (prev == 0) while ( (name=getarg()) ) if (!expandargs(name, &myargc, &myargv)) return; if (oktoedit(autowrite)) { if (prev || (myargc == 1 && strcmp(myargv[0],"-") == 0)) { if (pc > 0) { newpc = pc-1; } else { prints("(no prev files)"); goto killem; } } else if (myargc == 0) { if (pc < argc-1) { newpc = 1+pc; } else { prints("(no more files)"); goto killem; } } else if (myargc > 1 || (newpc = findarg(myargv[0])) < 0) { toedit(myargc); newpc = 0; newlist++; } doinput(newlist ? myargv[0] : argv[newpc]); pc = newpc; if (newlist) { killargs(&argc, &argv); argc = myargc; argv = myargv; } else killem: if (!prev) killargs(&myargc, &myargv); } } /* * set up low, high; set dot to low */ VOID PROC fixupline(dft) int dft; { if (low < 0) low = dft; if (high < 0) high = fseekeol(low)+1; else if (high < low) { /* flip high & low */ int tmp; tmp = high; high = low; low = tmp; } if (low >= ptop && low < pend) { setpos(skipws(low)); yp = setY(curr); } else { curr = low; diddled = YES; } } VOID PROC whatline() { printi(to_line((low < 0) ? (bufmax-1) : low)); if (high >= 0) { printch(','); printi(to_line(high)); } } VOID PROC print() { do { exprintln(); writeline(-1, 0, low); low = fseekeol(low) + 1; } while (low < high); exprintln(); } /* move to different line */ /* execute lines from a :sourced || .lvrc file */ bool PROC do_file(fname,mode,noquit) char *fname; exec_type *mode; bool *noquit; { char line[120]; FILE *fp, *fopen(); if ((fp = fopen(fname,"r")) != NULL) { indirect = YES; while (fgets(line,120,fp) && indirect) { strtok(line, "\n"); if (*line != 0) exec(line,mode,noquit); } indirect = YES; fclose(fp); return YES; } return NO; } VOID PROC doins(flag) bool flag; { int i; curr = low; exprintln(); low = insertion(1,setstep[flag],&i,&i,NO)-1; if (low >= 0) curr = low; diddled = YES; } /* figure out a address range for a command */ char * PROC findbounds(ip) char *ip; { ip = findparse(ip, &low, curr); /* get the low address */ if (low >= 0) { low = bseekeol(low); /* at start of line */ if (*ip == ',') { /* high address? */ ip++; count = 0; ip = findparse(ip, &high, curr); if (high >= 0) { high = fseekeol(high); return(ip); } } else return(ip); } return(0); } /* parse the command line for lineranges && a command */ int PROC parse(inp) char *inp; { int j,k; char cmd[80]; low = high = ERR; affirm = 0; if (*inp == '%') { moveright(inp, 2+inp, 1+strlen(inp)); inp[0]='1'; inp[1]=','; inp[2]='$'; } while (isspace(*inp)) ++inp; if (strchr(".$-+0123456789?/`'", *inp)) if (!(inp=findbounds(inp))) { errmsg("bad address"); return ERR; } while (isspace(*inp)) ++inp; j = 0; while (isalpha(*inp)) cmd[j++] = *inp++; if (*inp == '!') { if (j == 0) cmd[j++] = '!'; else affirm++; inp++; } else if (*inp == '=' && j == 0) cmd[j++] = '='; while (isspace(*inp)) ++inp; execstr = inp; if (j==0) return EX_CR; for (k=0; excmds[k]; k++) if (strncmp(cmd, excmds[k], j) == 0) return k; return ERR; } /* inner loop of execmode */ VOID PROC exec(cmd, mode, noquit) char *cmd; exec_type *mode; bool *noquit; { int what; bool ok; what = parse(cmd); ok = YES; if (diddled) { lstart = bseekeol(curr); lend = fseekeol(curr); } switch (what) { case EX_QUIT: /* :quit */ if (affirm || what == lastexec || !modified) *noquit = NO; else errmsg(fismod); break; case EX_READ: /* :read */ clrmsg(); readfile(); break; case EX_EDIT: /* :read, :edit */ clrmsg(); editfile(); break; case EX_WRITE: case EX_WQ : /* :write, :wq */ clrmsg(); if (readonly && !affirm) prints(fisro); else if (writefile() && what==EX_WQ) *noquit = NO; break; case EX_PREV: case EX_NEXT: /* :next */ clrmsg(); nextfile(what==EX_PREV); break; case EX_SUBS: /* :substitute */ cutandpaste(); break; case EX_SOURCE: /* :source */ if ((cmd = getarg()) && !do_file(cmd, mode, noquit)) { errmsg("cannot open "); prints(cmd); } break; case EX_XIT: clrmsg(); if (modified) { if (readonly) { prints(fisro); break; } else if (!writefile()) break; } if (!affirm && (argc-pc > 1)) { /* any more files to edit? */ printch('('); plural(argc-pc-1," more file"); prints(" to edit)"); } else *noquit = NO; break; case EX_MAP: map(affirm); break; case EX_UNMAP: ok = unmap(); break; case EX_FILE: /* :file */ if ( (cmd=getarg()) ) { /* :file name */ strcpy(altnm, filenm); strcpy(filenm, cmd); pc = addarg(filenm); } wr_stat(); break; case EX_SET: /* :set */ setcmd(); break; case EX_CR: case EX_PR: /* :print */ fixupline(bseekeol(curr)); if (what == EX_PR) print(); break; case EX_LINE: /* := */ whatline(); break; case EX_DELETE: case EX_YANK: /* :delete, :yank */ yank.lines = YES; fixupline(lstart); zerostack(&undo); if (what == EX_DELETE) ok = deletion(low,high); else ok = doyank(low,high); diddled = YES; break; case EX_PUT: /* :put */ fixupline(lstart); zerostack(&undo); ok = putback(low, &high); diddled = YES; break; case EX_VI: /* :visual */ *mode = E_VISUAL; if (*execstr) { clrmsg(); nextfile(NO); } break; case EX_EX: *mode = E_EDIT; /* :execmode */ break; case EX_INSERT: case EX_OPEN: /* :insert, :open */ if (indirect) ok = NO; /* kludge, kludge, kludge!!!!!!!!!! */ else { zerostack(&undo); fixupline(lstart); doins(what == EX_OPEN); } break; case EX_CHANGE: /* :change */ if (indirect) ok = NO; /* kludge, kludge, kludge!!!!!!!!!! */ else { zerostack(&undo); yank.lines = YES; fixupline(lstart); if (deletion(low,high)) doins(YES); else ok = NO; } break; case EX_UNDO: /* :undo */ low = fixcore(&high); if (low >= 0) { diddled = YES; curr = low; } else ok = NO; break; case EX_ARGS: /* :args */ args(); break; case EX_VERSION: /* version */ version(); break; case EX_ESCAPE: /* shell escape hack */ zotscreen = YES; exprintln(); if (*execstr) { #if TTY_ZTERM zclose(); #endif #if OS_FLEXOS|OS_UNIX fixcon(); #else allowintr(); #endif system(execstr); #if OS_FLEXOS|OS_UNIX initcon(); #else nointr(); #endif } else prints("incomplete shell escape."); break; case EX_REWIND: clrmsg(); if (argc > 0 && oktoedit(autowrite)) { pc = 0; doinput(argv[0]); } break; default: prints(":not an editor command."); break; } lastexec = what; if (!ok) { errmsg(excmds[what]); prints(" error"); } } levee-3.5a/extern.h000066400000000000000000000142461101573714600143140ustar00rootroot00000000000000/* * 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 #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 getline(); 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*/ levee-3.5a/find.c000066400000000000000000000241601101573714600137160ustar00rootroot00000000000000/* * 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 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] 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 && dest0 && 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); } levee-3.5a/flexcall.c000066400000000000000000000041501101573714600145650ustar00rootroot00000000000000/* * 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 #include static int oldkmode; static int oldsmode; int min(a,b) { return (a>b) ? b : a; } int max(a,b) { return (a 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 (ab)?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*/ levee-3.5a/globals.c000066400000000000000000000335761101573714600144340ustar00rootroot00000000000000/* * 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 }; levee-3.5a/grep.h000066400000000000000000000022061101573714600137350ustar00rootroot00000000000000/* * 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 '&' levee-3.5a/insert.c000066400000000000000000000101301101573714600142720ustar00rootroot00000000000000/* * 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 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 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); } levee-3.5a/levee.h000066400000000000000000000217141101573714600141050ustar00rootroot00000000000000/* * 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 #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 #include #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 #include #include #include #include #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 #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*/ levee-3.5a/lv.1000066400000000000000000000626331101573714600133440ustar00rootroot00000000000000.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 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 \ 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. levee-3.5a/lv.doc000066400000000000000000000700261101573714600137440ustar00rootroot00000000000000 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. \ 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 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? levee-3.5a/main.c000066400000000000000000000137561101573714600137330ustar00rootroot00000000000000/* * 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 #if HAVE_SIGNAL_H #include #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 (getline(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); } levee-3.5a/misc.c000066400000000000000000000202161101573714600137270ustar00rootroot00000000000000/* * 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 getline(str) char *str; { int len; char flag; flag = line(str, 0, COLS-curpos.x, &len); str[len] = 0; strput(CE); return (flag == EOL); } /* getline */ 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 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= 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(" "); } else prints("No file"); printch(' '); if (readonly) prints(" "); else if (modified) prints(" "); 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 */ levee-3.5a/modify.c000066400000000000000000000105541101573714600142670ustar00rootroot00000000000000/* * 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; } levee-3.5a/move.c000066400000000000000000000215271101573714600137500ustar00rootroot00000000000000/* * 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 (!getline(&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 && pos0 && 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; } levee-3.5a/os2call.c000066400000000000000000000114611101573714600143350ustar00rootroot00000000000000/* * 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 #include #define INCL_DOS #include int PROC min(a,b) int a,b; { return (a>b) ? b : a; } int PROC max(a,b) int a,b; { return (a 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 levee-3.5a/proto.h000066400000000000000000000142251101573714600141470ustar00rootroot00000000000000/* ** 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 getline(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*/ levee-3.5a/readme.os2000066400000000000000000000007701101573714600145150ustar00rootroot00000000000000If 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. levee-3.5a/rmxcall.c000066400000000000000000000045221101573714600144400ustar00rootroot00000000000000/* * 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 levee-3.5a/tc000066400000000000000000000011701101573714600131570ustar00rootroot00000000000000 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"); levee-3.5a/termcap.i000066400000000000000000000143671101573714600144470ustar00rootroot00000000000000/* * 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 #include #include #include 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 levee-3.5a/ucsd.c000066400000000000000000000034761101573714600137430ustar00rootroot00000000000000/* * 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); } levee-3.5a/undo.c000066400000000000000000000131021101573714600137350ustar00rootroot00000000000000/* * 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; } levee-3.5a/unixcall.c000066400000000000000000000052501101573714600146140ustar00rootroot00000000000000/* * 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" #include #include #include #include #include #include #if USE_TERMCAP #include #endif int min(a,b) int a, b; { return (a>b) ? b : a; } int max(a,b) int a, b; { return (a #elif !OS_RMX # include #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; }