--- /dev/null
+CSRCS = beep.c blockio.c display.c doscall.c editcor.c exec.c find.c
+CSRCS += flexcall.c gemcall.c globals.c insert.c main.c misc.c modify.c
+CSRCS += move.c rmxcall.c ucsd.c undo.c unixcall.c wildargs.c
+
+OBJS = $(SRCS,.c=.rel)
+
+levee: $(OBJS)
+ fcc -o levee $(OBJS)
+
+$(OBJS): $(SRCS)
+
+.c.rel:
+ fcc -Os -c $(@:.rel=.c)
+
+clean:
+ rm -rf $(OBJS) *.lst *.sym *.map *.noi *.lk *.ihx *.tmp *~ *.rel *.asm
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+
+#if ST
+#include <atari\osbind.h>
+
+char sound[] = {
+ 0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
+ 0xF8,0x10,0x10,0x10,0x00,0x20,0x03
+};
+
+#define SADDR 0xFF8800L
+
+typedef char srdef[4];
+
+srdef *SOUND = (srdef *)SADDR;
+
+main()
+{
+ register i;
+ long ssp;
+
+ ssp = Super(0L);
+ for (i=0; i<sizeof(sound); i++) {
+ (*SOUND)[0] = i;
+ (*SOUND)[2] = sound[i];
+ }
+ Super(ssp);
+}
+#endif /*ST*/
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include <stdio.h>
+#include <unistd.h>
+/* read in a file -- return TRUE -- read file
+ FALSE-- file too big
+*/
+
+int PROC addfile(FILE *f, int start, int endd, int *size)
+{
+ register int chunk;
+
+ chunk = read(fileno(f), core+start, (endd-start)-1);
+
+ *size = chunk;
+ return chunk < (endd-start)-1;
+}
+
+
+/* write out a file -- return TRUE if ok. */
+
+bool PROC putfile(FILE *f, int start, int endd)
+{
+ write(fileno(f), core+start, endd-start);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+
+#include <string.h>
+#include <unistd.h>
+/* do a gotoXY -- allowing -1 for same row/column */
+
+#if TERMCAP | ST
+
+#define MAXCOLS 160
+
+#if TERMCAP
+#include "termcap.i"
+#endif
+
+#else /*!(TERMCAP | ST)*/
+
+#define MAXCOLS COLS
+
+#endif
+
+PROC
+mvcur(int y, int x)
+{
+ static char gt[30];
+
+ 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 ZTERM
+ zgoto(x,y);
+#endif
+
+#if 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));
+ }
+#endif
+
+#if VT52
+ CM[2] = y+32;
+ CM[3] = x+32;
+ strput(CM);
+#endif
+
+#if TERMCAP
+ tgoto(gt,y,x);
+ strput(gt);
+#endif
+}
+
+PROC numtoa(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);
+}
+
+PROC
+printi(int num)
+{
+ char nb[10];
+ register int size;
+
+ numtoa(nb,num);
+ size = min(strlen(nb),COLS-curpos.x);
+ if (size > 0) {
+ zwrite(nb, size);
+ curpos.x += size;
+ }
+}
+
+PROC
+println(void)
+{
+ strput("\n\r");
+ curpos.x = 0;
+ curpos.y = min(curpos.y+1, LINES-1);
+}
+
+/* print a character out in a readable form --
+ * ^<x> for control-<x>
+ * spaces for <tab>
+ * normal for everything else
+ */
+
+static char hexdig[] = "0123456789ABCDEF";
+
+int PROC
+format(char *out, unsigned c)
+/* format: put a displayable version of c into out */
+{
+ if (c >= ' ' && c < '\7f') {
+ 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 MSDOS
+ out[0] = c;
+ return 1;
+#else
+ out[0] = '\\';
+ out[1] = hexdig[(c>>4)&017];
+ out[2] = hexdig[c&017];
+ return 3;
+#endif
+ }
+}
+
+PROC
+printch(char c)
+{
+ register int size;
+ char buf[MAXCOLS];
+
+ size = min(format(buf,c),COLS-curpos.x);
+ if (size > 0) {
+ zwrite(buf, size);
+ curpos.x += size;
+ }
+}
+
+PROC
+prints(char *s)
+{
+ int size,oxp = curpos.x;
+ char buf[MAXCOLS+1];
+ register 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)
+ zwrite(buf, size);
+}
+
+PROC
+writeline(int y,int x,int start)
+{
+ int endd,oxp;
+ register size;
+ char buf[MAXCOLS+1];
+ register 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) {
+ zwrite(buf, size);
+ }
+ if (curpos.x < COLS)
+ strput(CE);
+}
+
+/* redraw && refresh the screen */
+
+PROC
+refresh(int y,int x,int start,int endd, bool rest)
+{
+ int sp;
+
+#if ST
+ /* turn the cursor off */
+ asm(" clr.l -(sp) ");
+ asm(" move.w #21,-(sp) ");
+ asm(" trap #14 ");
+ asm(" addq.l #6,sp ");
+#endif
+ sp = start;
+ while (sp <= endd) {
+ writeline(y, x, sp);
+ sp = 1+fseekeol(sp);
+ y++;
+ x = 0;
+ }
+ if (rest && sp >= bufmax)
+ while (y<LINES-1) { /* fill screen with ~ */
+ mvcur(y, 0);
+ printch('~'); strput(CE);
+ y++;
+ }
+#if ST
+ /* turn the cursor back on */
+ asm(" clr.w -(sp) ");
+ asm(" move.w #1,-(sp) ");
+ asm(" move.w #21,-(sp) ");
+ asm(" trap #14 ");
+ asm(" addq.l #6,sp ");
+#endif
+}
+
+/* redraw everything */
+
+PROC
+redisplay(bool flag)
+{
+ if (flag)
+ clrprompt();
+ refresh(0, 0, ptop, pend, TRUE);
+}
+
+PROC
+scrollback(int curr)
+{
+ mvcur(0,0); /* move to the top line */
+ do {
+ ptop = bseekeol(ptop-1);
+ strput(UpS);
+ writeline(0, 0, ptop);
+ } while (ptop > curr);
+ setend();
+}
+
+PROC
+scrollforward(int curr)
+{
+ do {
+ writeline(LINES-1, 0, pend+1);
+ strput("\n");
+ 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(int top, int 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);
+}
+
+PROC
+clrprompt(void)
+{
+ mvcur(LINES-1,0);
+ strput(CE);
+}
+
+PROC
+prompt(bool toot, char *s)
+{
+ if (toot)
+ error();
+ clrprompt();
+ prints(s);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * dos interface for levee (Microsoft C)
+ */
+#include "levee.h"
+
+#if MSDOS
+#include <glob.h>
+#include <dos.h>
+
+int PROC
+min(a,b)
+int a,b;
+{
+ return (a>b) ? b : a;
+}
+
+int PROC
+max(a,b)
+int a,b;
+{
+ return (a<b) ? b : a;
+}
+
+PROC
+strput(s)
+char *s;
+{
+ write(1, s, strlen(s));
+}
+
+/* get a key, mapping certain control sequences
+ */
+PROC
+getKey()
+{
+ register c;
+ extern char _far crawcin();
+
+ c = crawcin();
+
+ if (c == 0 || c == 0xe0)
+ switch (c=crawcin()) {
+ case 'K': return LTARROW;
+ case 'M': return RTARROW;
+ case 'H': return UPARROW;
+ case 'P': return DNARROW;
+ case 'I': return 'U'-'@'; /* page-up */
+ case 'Q': return 'D'-'@'; /* page-down */
+ default : return 0;
+ }
+ return c;
+}
+
+
+/* don't allow interruptions to happen
+ */
+PROC
+nointr()
+{
+ extern void _cdecl _interrupt _far ignore_ctrlc();
+ _dos_setvect(0x23, ignore_ctrlc);
+} /* nointr */
+
+
+/* have ^C do what it usually does
+ */
+PROC
+allowintr()
+{
+ extern void _cdecl _interrupt _far intr_on_ctrlc();
+ _dos_setvect(0x23, intr_on_ctrlc);
+} /* allowintr */
+
+
+/*
+ * basename() returns the filename part of a pathname
+ */
+char *
+basename(s)
+register char *s;
+{
+ register char *p = s;
+
+ for (p = s+strlen(s); p > s; --p)
+ if (p[-1] == '/' || p[-1] == '\\' || p[-1] == ':')
+ return p;
+ return s;
+} /* basename */
+
+
+/*
+ * glob() expands a wildcard, via calls to _dos_findfirst/_next()
+ * and pathname retention.
+ */
+char *
+glob(path, dta)
+char *path;
+struct glob_t *dta;
+{
+ static char path_bfr[256]; /* full pathname to return */
+ static char *file_part; /* points at file - for filling */
+ static char isdotpattern; /* looking for files starting with . */
+ static char isdotordotdot; /* special case . or .. */
+ static struct glob_t *dta_bfr; /* pointer to desired dta */
+ static struct find_t dird; /* DOS dta */
+
+ register st; /* status from _dos_findxxx */
+
+ if (path) {
+ /* when we start searching, save the path part of the filename in
+ * a safe place.
+ */
+ strcpy(path_bfr, path);
+ file_part = basename(path_bfr);
+
+ /* set up initial parameters for DosFindFirst()
+ */
+ dta_bfr = dta;
+
+ if (isdotpattern = (*file_part == '.'))
+ /* _dos_findfirst() magically expands . and .. into their
+ * directory names. Admittedly, there are cases where
+ * this can be useful, but this is not one of them. So,
+ * if we find that we're matching . and .., we just
+ * special-case ourselves into oblivion to get around
+ * this particular bit of DOS silliness.
+ */
+ isdotordotdot = (file_part[1] == 0 || file_part[1] == '.');
+ else
+ isdotordotdot = 0;
+
+ st = _dos_findfirst(path, 0x16, &dird);
+ }
+ else
+ st = _dos_findnext(&dird);
+
+ while (st == 0) {
+ /* Unless the pattern has a leading ., don't include any file
+ * that starts with .
+ */
+ if (dird.name[0] == '.' && !isdotpattern)
+ st = _dos_findnext(&dird);
+ else {
+ /* found a file - affix the path leading to it, then return
+ * a pointer to the (static) buffer holding the path+the name.
+ */
+ strlwr(dird.name); /* DOS & OS/2 are case-insensitive */
+
+ if (dta_bfr) {
+ dta_bfr->wr_time = dird.wr_time;
+ dta_bfr->wr_date = dird.wr_date;
+ if (isdotordotdot)
+ strcpy(dta_bfr->name, file_part);
+ else {
+ strncpy(dta_bfr->name, dird.name, sizeof(dta_bfr->name)-1);
+ dta_bfr->name[sizeof(dta_bfr->name)-1] = 0;
+ }
+ dta_bfr->size = dird.size;
+ dta_bfr->attrib = dird.attrib;
+ }
+ if (!isdotordotdot)
+ strcpy(file_part, dird.name);
+ return path_bfr;
+ }
+ }
+ /* nothing matched
+ */
+ if (path && isdotordotdot) {
+ /* must be at root, so statting dot will most likely fail. Fake a
+ * dta.
+ */
+ if (dta_bfr) {
+ memset(dta_bfr, 0, sizeof *dta_bfr);
+ dta_bfr->attrib = 0x10;
+ dta_bfr->name[0] = '.';
+ }
+ return path_bfr;
+ }
+ return (char*)0;
+} /* glob */
+#endif /*MSDOS*/
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+
+#include <string.h>
+#include <ctype.h>
+/* do some undoable modification */
+
+/* These variables make docommand nonrecursive */
+
+bool ok;
+int newend, /* end position after change */
+ disp, /* start redisplay here */
+ newc, /* new cursor position for wierd cmds */
+ endY; /* final yp for endp */
+
+/* move a line of text right || left */
+
+PROC
+adjuster(bool sleft, int endd, int sw)
+{
+ bool noerror;
+ int np, ts,
+ ip,
+ ss, adjp,
+ DLEnum;
+
+ if (sw == -1)
+ sw = shiftwidth;
+ if (sleft)
+ sw = -sw;
+ curr = bseekeol(curr);
+ ip = curr;
+ noerror = TRUE;
+ do {
+ DLEnum = sw + findDLE(ip, &np, bufmax,0);
+ if (DLEnum >= 0 && DLEnum <= COLS && core[np] != EOL && np < bufmax) {
+ ts = DLEnum / tabsize;
+ ss = DLEnum % tabsize;
+ adjp = ts+ss+ip;
+ if (np-adjp < 0) { /* expand the buf */
+ moveright(&core[np], &core[adjp], bufmax-np);
+ insert_to_undo(&undo, adjp, adjp - np);
+ }
+ else
+ delete_to_undo(&undo, adjp, np - adjp);
+
+ endd += (adjp-np);
+ noerror = move_to_undo(&undo, ip, ts+ss);
+ fillchar(&core[ip], ts, TAB);
+ fillchar(&core[ip+ts], ss, 32);
+ }
+ else if (np > ip) { /* remove the indent code */
+ noerror = delete_to_undo(&undo, ip, np-ip);
+ endd += (ip - np);
+ }
+ ip = 1 + fseekeol(ip);
+ } while (noerror && ip < endd);
+ if (!noerror)
+ error();
+ newc = skipws(curr);
+ disp = curr;
+ newend = endd;
+ endY = setY(min(newend, pend));
+}
+
+/* join <count> lines together */
+
+PROC
+join(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();
+}
+
+PROC
+squiggle(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);
+ }
+ }
+}
+
+PROC
+bigreplace(void)
+{
+ 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(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));
+}
+
+PROC
+gcount(void)
+{
+ count = 0;
+ while (count>=0 && ch >= '0' && ch <='9') {
+ count = (count*10) + (ch-'0');
+ readchar(); /* get a char to replace the one we dumped */
+ }
+}
+
+PROC
+docommand(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 (ch >= '0' && ch <= '9') {
+ oldc = count;
+ 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[ch];
+
+ if (ok = (findCP(curr,&endp,movecmd) == LEGALMOVE)) {
+ if (curr > endp) {
+ swap(&curr,&endp);
+ ok = (cmd != CHANGE_C);
+ }
+ if (adjcurr[movecmd])
+ curr++;
+ if (adjendp[movecmd])
+ endp++;
+ }
+ if (!ok) {
+ if (ch != ESC)
+ error();
+ goto killredo;
+ }
+ }
+
+ endY = setY(endp);
+ newend = curr;
+ disp = curr;
+ switch (cmd) {
+ 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 0; /* 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 */
+
+PROC
+exmacro(void)
+{
+ 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 */
+
+PROC
+zdraw(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 */
+
+PROC
+macrocommand(void)
+{
+ 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 0x06: /* ^F */ /* scroll up one page */
+ strcpy(gcb,"22\x04"); break; /* 22^D */
+ case 0x02: /* ^B */ /* ... down one page */
+ strcpy(gcb,"22\x15"); break; /* 22^U */
+ case 0x05: /* ^E */ /* scroll up one line */
+ strcpy(gcb,"1\x04"); break; /* 1^D */
+ case 0x19: /* ^Y */ /* ... down one line */
+ strcpy(gcb,"1\x15"); break; /* 1^U */
+ default:
+ error();
+ return 0;
+ break;
+ }
+ if (macro<0)
+ zerostack(&undo);
+ insertmacro(gcb, 1);
+}
+
+/* scroll the window up || down */
+
+PROC
+scroll(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(void)
+{
+ 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 */
+ gcount(); /* ... a possible count */
+ switch (cmd = movemap[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 */
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * do a newline and set flags.
+ */
+#define exprintln() (zotscreen=YES),println()
+
+PROC
+plural(int num, char *string)
+{
+ printi(num);
+ prints(string);
+ if (num != 1)
+ printch('s');
+} /* plural */
+
+
+PROC
+clrmsg(void)
+{
+ mvcur(-1,0);
+ strput(CE);
+} /* clrmsg */
+
+
+PROC
+errmsg(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(void)
+{
+ char *rv;
+ rv = execstr;
+ while (*execstr && !isspace(*execstr))
+ ++execstr;
+ if (*execstr) {
+ *execstr++ = 0;
+ while (isspace(*execstr))
+ ++execstr;
+ }
+ return (*rv) ? rv : NULL;
+} /* getarg */
+
+
+PROC
+version()
+/* version: print which version of levee we are... */
+{
+ errmsg("levee ");prints(ED_NOTICE);printch(ED_REVISION);
+} /* version */
+
+
+PROC
+args(void)
+/* args: print the argument list */
+{
+ register 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 ST|FLEXOS
+ strput("\033p");
+#else
+ printch('[');
+#endif
+ prints(argv[i]);
+#if ST|FLEXOS
+ strput("\033q");
+#else
+ printch(']');
+#endif
+ }
+ else
+ prints(argv[i]);
+ }
+} /* args */
+
+PROC
+setcmd(void)
+{
+ bool no,b;
+ int len,i;
+ register char *arg;
+ char *num;
+ register 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 */
+PROC
+printone(int i)
+{
+ if (i >= 0) {
+ exprintln();
+ printch(mbuffer[i].token);
+ mvcur(-1,3);
+ if (movemap[mbuffer[i].token] == INSMACRO)
+ prints("!= ");
+ else
+ prints(" = ");
+ prints(mbuffer[i].m_text);
+ }
+} /* printone */
+
+
+/* print all the macros */
+PROC
+printall(void)
+{
+ int i;
+ for (i = 0; i < MAXMACROS; i++)
+ if (mbuffer[i].token != 0)
+ printone(i);
+} /* printall */
+
+
+/* :map ch text */
+PROC
+map(bool insert)
+{
+ register char *macro, c;
+ int i;
+ /* get the macro */
+ if ((macro=getarg()) == NULL) {
+ printall();
+ return 1;
+ }
+ if (strlen(macro) > 1) {
+ errmsg("macros must be one character");
+ return 0;
+ }
+ 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[c];
+ if (insert)
+ movemap[c] = INSMACRO;
+ else
+ movemap[c] = SOFTMACRO;
+ }
+ }
+} /* map */
+
+
+PROC
+undefine(int i)
+{
+ register char *p;
+ if (i >= 0) {
+ movemap[mbuffer[i].token] = mbuffer[i].oldmap;
+ mbuffer[i].token = 0;
+ p = mbuffer[i].m_text;
+ free(p);
+ mbuffer[i].m_text = 0;
+ }
+} /* undefine */
+
+
+PROC
+unmap(void)
+{
+ int i;
+ register 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(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(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(void)
+{
+ extern int wilderr;
+#if ST
+ extern int mapslash;
+ register char *p;
+#endif
+ register char *name;
+ if (name = getarg()) {
+ if (strcmp(name,"#") == 0)
+ if (*altnm)
+ name = altnm;
+ else {
+ errmsg("no alt name");
+ wilderr++;
+ return NULL;
+ }
+#if ST
+ 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& */
+PROC
+cutandpaste(void)
+{
+ 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 0;
+ }
+ 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 */
+
+
+PROC
+inputf(char *fname, bool newbuf)
+{
+ int onright, /* text moved right for :read */
+ fsize; /* bytes read in */
+ register FILE *f;
+
+
+ if (newbuf)
+ readonly = NO;
+
+ zerostack(&undo);
+ if (newbuf) {
+ modified = NO;
+ low = 0;
+ high = SIZE;
+ }
+ else { /* append stuff to the buffer */
+ fixupline(bseekeol(curr));
+ onright = bufmax-low;
+#if MSDOS
+ high = SIZE;
+ high -= onright;
+#else
+ high = (SIZE-onright);
+#endif
+ if (onright > 0)
+ moveright(&core[low], &core[high], onright);
+ }
+ printch('"');
+ prints(fname);
+ prints("\" ");
+ if ((f=fopen(fname, "r")) == NULL) {
+ prints("[No such file]");
+ fsize = 0;
+ if (newbuf)
+ newfile = YES;
+ }
+ else {
+ if (addfile(f, low, high, &fsize))
+ plural(fsize," byte");
+ else if (fsize < 0) {
+ prints("[read error]");
+ fsize = 0;
+ }
+ else {
+ prints("[overflow]");
+ readonly = YES;
+ }
+ fclose(f);
+ if (newbuf)
+ newfile = NO;
+ }
+ if (newbuf) {
+ fillchar(contexts, sizeof(contexts), -1);
+ bufmax = fsize;
+ }
+ else {
+ insert_to_undo(&undo, low, fsize);
+ modified = YES;
+ if (onright > 0)
+ moveleft(&core[high], &core[low+fsize], onright);
+ }
+ if (*startcmd) {
+ count = 1;
+ if (*findparse(startcmd,&curr,low) != 0 || curr < 0)
+ curr = low;
+ *startcmd = 0;
+ }
+ else
+ curr = low;
+ diddled = YES;
+} /* inputf */
+
+
+/* Change a file's name (for autocopy). */
+PROC
+backup(char *name)
+{
+ char back[80];
+ char *p;
+
+ strcpy(back, name);
+#if 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(char *fname)
+{
+ bool whole;
+ register 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 */
+
+
+PROC
+oktoedit(int writeold)
+/* check and see if it is ok to edit a new file */
+/* 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(void)
+{
+ register 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;
+}
+
+
+PROC
+editfile(void)
+{
+ register 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 0;
+ } 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);
+}
+
+
+PROC
+doinput(char *name)
+{
+ inputf(name, YES);
+ strcpy(altnm, filenm);
+ strcpy(filenm, name);
+}
+
+
+PROC
+toedit(int count)
+{
+ if (count > 1) {
+ printi(count);
+ prints(" files to edit; ");
+ }
+}
+
+
+PROC
+readfile(void)
+{
+ register char *name;
+
+ if (name=getarg())
+ inputf(name,NO);
+ else
+ errmsg("no file to read");
+}
+
+
+PROC
+nextfile(bool prev)
+{
+ register char *name = NULL;
+ int newpc=pc,
+ what,
+ myargc=0;
+ char **myargv;
+ bool newlist = NO;
+
+ if (prev == 0)
+ while (name=getarg())
+ if (!expandargs(name, &myargc, &myargv))
+ return 0;
+
+ 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
+ */
+PROC
+fixupline(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;
+ }
+}
+
+
+PROC
+whatline(void)
+{
+ printi(to_line((low < 0) ? (bufmax-1) : low));
+ if (high >= 0) {
+ printch(',');
+ printi(to_line(high));
+ }
+}
+
+
+PROC
+print(void)
+{
+ 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(char *fname, exec_type *mode, bool *noquit)
+{
+ char line[120];
+ register FILE *fp;
+
+ 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;
+}
+
+
+PROC doins(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(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 */
+PROC parse(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 */
+PROC
+exec(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 ZTERM
+ zclose();
+#endif
+#if FLEXOS|UNIX
+ fixcon();
+#else
+ allowintr();
+#endif
+//FIXME!! system(execstr);
+#if FLEXOS|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");
+ }
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#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 ST | TERMCAP
+extern int LINES, COLS;
+#endif
+#if TERMCAP
+extern bool CA, canUPSCROLL;
+extern char FkL,
+ CurRT,
+ CurLT,
+ CurDN,
+ CurUP;
+#endif /*TERMCAP*/
+extern char *TERMNAME,
+ *HO,
+ *UP,
+ *CE,
+ *CL,
+ *OL,
+ *BELL,
+ *CM,
+ *UpS,
+ *CURoff,
+ *CURon;
+
+extern
+char erasechar,
+ eraseline;
+
+extern
+char ED_NOTICE[], /* Editor version */
+ ED_REVISION, /* Small revisions & corrections */
+ 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 nlsearch;
+/* movement, command codes */
+extern
+cmdtype movemap[];
+#endif /*GLOBALS_D*/
+#ifndef EXTERN_D
+#define EXTERN_D
+#define wc(ch) (scan(65,'=',(ch),wordset)<65)
+
+#if SYS5
+#define fillchar(p,l,c) memset((p),(c),(l))
+#define index(s,c) strchr((s),(c))
+#else /*!SYS5*/
+#if ST
+#define fillchar(p,l,c) blkfill((p),(c),(l))
+#endif /*ST*/
+#endif /*SYS5*/
+ /* non int functions to be found elsewhere */
+
+#if 0
+extern findstates findCP();
+extern exec_type editcore();
+extern char line(), peekc(), readchar();
+extern bool getline();
+extern char *findparse(),*makepat();
+extern bool putfile();
+extern bool doyank(), deletion(), putback();
+extern bool pushb(),pushi(),pushmem(),uputcmd(),
+ delete_to_undo(),move_to_undo();
+#endif
+
+#endif /*EXTERN_D*/
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include "grep.h"
+#include <ctype.h>
+#include <string.h>
+
+static int arg; /* arguments inside of a RE */
+
+int PROC
+REmatch(char *pattern, int start, int end)
+{
+ register char *endp = &core[end];
+
+ if (!*pattern)
+ return -1;
+ arg = 0;
+ while (start <= end && !amatch(pattern, &core[start], endp))
+ start++;
+ return start;
+}
+
+int PROC
+omatch(char *pattern, char **cp, char *endp)
+{
+ register 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:
+#ifdef TOUPPER_FTN
+#undef toupper
+#endif
+ 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(char *pattern, char *start, char *endp)
+{
+ 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
+ */
+PROC
+patsize(char **pattern)
+{
+ register count;
+
+ switch (**pattern) {
+ case LITCHAR:
+ *pattern += 2;
+ break;
+ case CCL:
+ case NCCL:
+ count = *(++*pattern) & 0xff;
+ *pattern += 1+count;
+ break;
+ default:
+ (*pattern)++;
+ break;
+ }
+}
+
+PROC
+locate(char *pattern, char *linep)
+/* locate: find a character in a closure */
+{
+ 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;
+
+PROC
+concatch(char c)
+{
+ if (p < &pattern[MAXPAT-1])
+ *p++ = c;
+}
+
+char PROC
+esc(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(char *src)
+
+/* parse the innards of a [] */
+{
+ int k;
+ register char *start = src;
+ char cs[128];
+
+ fillchar(cs,sizeof(cs),FALSE);
+ while (*src && *src != CCLEND) {
+ if (*src == DASH && src>start && src[1] != CCLEND && src[-1]<src[1]) {
+ for ( k = src[-1]; k <= src[1]; k++)
+ cs[k] = TRUE;
+ src++;
+ }
+ else
+ cs[esc(&src)] = TRUE;
+ src++;
+ }
+ for (k=0; k < sizeof(cs); k++)
+ if (cs[k])
+ concatch((char)k);
+ return src;
+}
+
+char * PROC badccl(char *src)
+/* a [] was encountered. is it a CCL (match one of the included
+ * characters); or is it a NCCL (match all but the included characters)?
+ */
+{
+ register char *jstart;
+
+ if (*src == NEGATE) {
+ concatch(NCCL);
+ ++src;
+ }
+ else
+ concatch(CCL);
+ jstart = p;
+ concatch(0); /* this will be the length of the pattern */
+ src = dodash(src);
+ *jstart = (p-jstart)-1;
+ return src;
+}
+
+ /* patterns that cannot be closed */
+char badclose[] = { LSTART, LEND, CLOSURE, 0 };
+
+char * PROC makepat(char *string, char delim)
+/* make up the pattern string for find -- ripped from 'Software Tools' */
+{
+ register char *cp;
+ register char *oldcp;
+ char *start = string;
+ int inarg = FALSE;
+
+ for(arg=0;arg<9;++arg)
+ RE_start[arg] = RE_size[arg] = (-1);
+ arg = 0;
+ p = pattern;
+
+ while ((*string != delim) && (*string != 0)) {
+ oldcp = cp;
+ cp = p;
+
+ if (!magic) /* kludge for nonmagical patterns */
+ goto normal;
+ if (*string == ANY)
+ concatch(ANY);
+ else if ((*string == LSTART) && (string == start))
+ concatch(LSTART);
+ else if ((*string == LEND) && (string[1] == delim || string[1] == 0))
+ concatch(LEND);
+ else if (*string == CCL)
+ string = badccl(1+string);
+ else if ((*string == CLOSURE) && (p > pattern)) {
+ cp = oldcp;
+ if (strchr(badclose, *cp) || p >= &pattern[MAXPAT-1])
+ return NULL;
+ moveright(cp,1+cp,(int)(p-cp));
+ *cp = CLOSURE;
+ p++;
+ }
+ else if (*string == ESCAPE) {
+ if (string[1] == ARGSTART || string[1] == ARGEND) {
+ if (string[1] == ARGEND)
+ if (!inarg)
+ goto normal;
+ if (string[1] == ARGSTART) {
+ if (inarg)
+ goto normal;
+ if (++arg > 9)
+ return NULL;
+ }
+ inarg = !inarg;
+ }
+ else if (string[1] != TOKENB && string[1] != TOKENE)
+ goto normal;
+ ++string;
+ concatch(*string);
+ }
+ else {
+ normal:concatch(LITCHAR);
+ concatch(esc(&string));
+ }
+ if (*string)
+ string++;
+ }
+ if (inarg)
+ concatch(ARGEND);
+ if (p > pattern) { /* new pattern was created */
+ strncpy(lastpatt,start,(int)(string-start));
+ lastpatt[string-start] = 0;
+ concatch(0);
+ if (p-pattern >= MAXPAT)
+ return NULL;
+ }
+ return (*string == delim)?(string+1):(string);
+}
+
+PROC
+findfwd(char *pattern, int start, int endp)
+/* look for a regular expression forward */
+{
+ int ep;
+
+ while (start < endp) {
+ ep = fseekeol(start);
+ if ((start = REmatch(pattern, start, ep)) <= ep)
+ return start;
+ }
+ return ERR;
+ }
+
+PROC
+findback(char *pattern, int start, int endp)
+/* look for a regular expression backwards */
+{
+ int ep,i, j;
+
+ while (start > endp) {
+ ep = bseekeol(start);
+ if ((j = REmatch(pattern, ep, start)) <= start)
+ {
+ i = j;
+ while((j=REmatch(pattern, i+1, start)) <= start)
+ {
+ i = j;
+ }
+ return i;
+ }
+ start = ep-1;
+ }
+ return ERR;
+ }
+
+bool s_wrapped = 0;
+
+char * PROC
+search(char *pat, int *start)
+/* get a token for find & find it in the buffer
+ */
+{
+ bool forwd;
+ int pos;
+ char *p;
+
+ forwd = ((nlsearch = *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(char *src, int *idx, int start) /* driver for ?, /, && : lineranges */
+{
+ 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(bool advance, int dest, int count)
+{
+ if (advance)
+ do {
+ dest = fseekeol(dest) + 1;
+ count--;
+ } while (count>0 && dest<bufmax);
+ else
+ do {
+ dest = bseekeol(dest) - 1;
+ count--;
+ } while (count>0 && dest>=0);
+ return(dest);
+}
+
+int PROC
+fseekeol(int origin)
+{
+ return(origin + scan(bufmax-origin-1,'=',EOL,&core[origin]));
+}
+
+int PROC
+bseekeol(int origin)
+{
+ return(origin + scan(-origin,'=',EOL,&core[origin-1]));
+}
+
+/* get something from the context table */
+
+int PROC
+getcontext(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);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * flexos interface for levee (Metaware C)
+ */
+#include "levee.h"
+
+#if FLEXOS
+#include <flexos.h>
+#include <ctype.h>
+
+static int oldkmode;
+static int oldsmode;
+
+int
+min(a,b)
+{
+ return (a>b) ? b : a;
+}
+
+int
+max(a,b)
+{
+ return (a<b) ? b : a;
+}
+
+strput(s)
+char *s;
+{
+ s_write(0x01, 1L, s, (long)strlen(s), 0L);
+}
+
+char *
+basename(s)
+ char *s;
+{
+ char *strrchr();
+ register char *p;
+
+ if ((p=strrchr(s,'/')) || (p=strrchr(s,'\\')) || (p = strrchr(s,':')))
+ return 1+p;
+ return s;
+}
+
+getKey()
+{
+ char c;
+
+ s_read(0x0101, 0L, &c, 1L, 0L);
+ return c;
+}
+
+initcon()
+{
+ CONSOLE tty;
+
+ s_get(T_CON, 1L, &tty, SSIZE(tty));
+ oldkmode = tty.con_kmode;
+ oldsmode = tty.con_smode;
+ tty.con_kmode = 0x0667;
+ tty.con_smode = 0;
+ s_set(T_CON, 1L, &tty, SSIZE(tty));
+}
+
+fixcon()
+{
+ CONSOLE tty;
+
+ s_get(T_CON, 1L, &tty, SSIZE(tty));
+ tty.con_kmode = oldkmode;
+ tty.con_smode = oldsmode;
+ s_set(T_CON, 1L, &tty, SSIZE(tty));
+}
+
+char *
+strdup(s)
+char *s;
+{
+ char *malloc();
+ char *p;
+
+ if (p=malloc(strlen(s)+1))
+ strcpy(p, s);
+ return p;
+}
+
+getpid()
+{
+ PROCESS myself;
+
+ s_get(T_PDEF, 0L, &myself, SSIZE(myself));
+
+ return myself.ps_pid;
+}
+
+strlwr(s)
+char *s;
+{
+ while (*s) {
+ if (isupper(*s))
+ *s += 32;
+ s++;
+ }
+}
+#endif
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * Gemdos (Atari ST) bindings for levee (Alcyon/Sozobon C)
+ */
+#include "levee.h"
+
+#if ST
+#include <atari\osbind.h>
+
+strput(s)
+register char *s;
+{
+ write(1, s, strlen(s));
+}
+
+
+zwrite(s,len)
+char *s;
+{
+ write(1, s, len);
+}
+
+
+min(a,b)
+register int a, b;
+{
+ return (a<b)?a:b;
+}
+
+
+max(a,b)
+register int a, b;
+{
+ return (a>b)?a:b;
+}
+
+
+unsigned
+getKey()
+/* get input from the keyboard. All odd keys (function keys, et al) that
+ * do not produce a character have their scancode orred with $80 and returned.
+ */
+{
+ unsigned c;
+ long key;
+
+ c = (key = Crawcin()) & 0xff;
+ if (!c)
+ c = (((unsigned)(key>>16))|0x80) & 0xff;
+ return c;
+} /* getKey */
+#endif /*ST*/
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/* 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[80], /* 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 ST | TERMCAP
+int LINES, COLS;
+#endif
+
+#if 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 ANSI
+#if MSDOS
+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 MSDOS
+ *OL = NULL,
+ *UpS = NULL,
+#else
+ *OL = "\033[L",
+ *UpS = "\033[L",
+#endif
+ *BELL= "\007",
+ *CM = "\033[%d;%dH",
+ *CURoff,
+ *CURon;
+#endif /*ANSI*/
+
+#if VT52
+#if ST
+char *TERMNAME = "Atari ST",
+#else
+#if FLEXOS
+char *TERMNAME = "Flexos console",
+#else
+char *TERMNAME = "hardwired vt52",
+#endif /*FLEXOS*/
+#endif /*ST*/
+ *HO = "\033H",
+ *UP = "\033A",
+ *CE = "\033K",
+ *CL = "\033E",
+ *OL = "\033L",
+ *BELL= "\007",
+ *CM = "\033Y??",
+#if FLEXOS
+ *UpS = NULL, /* Reverse scrolling is painfully slow */
+#else
+ *UpS = "\033I",
+#endif
+ *CURoff= "\033f",
+ *CURon = "\033e";
+#endif /*VT52*/
+
+#if 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 /*TERMCAP*/
+
+char erasechar = ERASE, /* our erase character */
+ eraseline = DEL; /* and line-kill character */
+
+char ED_NOTICE[] = "(c)3.4", /* Editor version */
+ ED_REVISION = 'm', /* Small revisions & corrections */
+ 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 TERMCAP | ST
+ 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 ST
+ 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 ST
+ {"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 nlsearch = 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,
+ /*! */ BAD_COMMAND,
+ /*" */ 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 */ BAD_COMMAND,
+ /*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
+ };
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#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 '&'
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include <string.h>
+
+int PROC
+insertion(int count, int openflag, int *dp, int *yp, bool visual)
+{
+ char cmd, c;
+ int rp; /* number of spaces to diddle */
+ int ts, ss; /* tabs && spaces to insert */
+ register cp; /* current position */
+ int i; /* random index */
+ int endd; /* last open place */
+ register rsize; /* size of upper buffer */
+ int currDLE = 0; /* what DLE is now */
+ int len; /* full insert size */
+ bool Dflag;
+
+ if (openflag != 0) { /* opening a line above || below */
+ if (openflag<0 && bufmax>0 && curr<bufmax) {
+ curr = 1+lend;
+ if (visual)
+ strput("\n");
+ }
+ else { /* open above current line */
+ (*yp)--;
+ curr = lstart;
+ }
+ if (autoindent)
+ currDLE = findDLE(lstart, &i, skipws(lstart),0);
+ if (visual)
+#if VT52
+ if (OL) {
+#else
+ if (OL && (*yp) < LINES-2) {
+#endif
+ strput(OL);
+ (*yp)++;
+ curpos.y = *yp;
+ }
+ else {
+ mvcur(1+(*yp), 0);
+ strput(CE);
+ }
+ mvcur(-1, currDLE);
+ }
+ else {
+ if (autoindent)
+ currDLE = findDLE(lstart, &i, curr, 0);
+ if (curr == i) {
+ if (!delete_to_undo(&undo, lstart, i-lstart))
+ return(-1);
+ curr = lstart;
+ }
+ }
+
+ rsize = (bufmax-curr); /* amount of stuff above curr */
+ endd = SIZE - rsize; /* split the buffer */
+ if (rsize > 0)
+ moveright(&core[curr], &core[endd], rsize);
+
+ cp = curr;
+ do { /* Insert loop */
+ Dflag = (cp==0 || core[cp-1]==EOL);
+ do {
+ if (Dflag)
+ while ((cmd=peekc()) == 0x14 || cmd == 0x04) { /* handle ^T, ^D */
+ if (readchar() == 0x14)
+ 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 RMX
+ /* at OL at bottom kludge... */
+ if (OL && (*yp) < LINES-2) {
+#else
+ if (OL) {
+#endif
+ strput(OL);
+ (*yp)++;
+ }
+ else
+ strput(CE);
+ }
+ if (!autoindent) /* reset currDLE? */
+ currDLE = 0;
+ mvcur(-1, currDLE);
+ }
+ } while (c != ESC && cp <= endd-INSSIZE);
+ *dp = cp; /* start display here */
+
+ if (count > 1) { /* repeated insertion */
+ len = cp-curr;
+ if ((count-1)*len < endd-cp)
+ for (i = 1;i <count;i++) {
+ moveright(&core[cp-len], &core[cp], len);
+ cp += len;
+ }
+ }
+
+ if (openflag != 0 /* open or insert at end of buffer */
+ || (rsize < 1 && cp > curr && core[cp-1] != EOL))
+ core[cp++] = EOL;
+ len = cp-curr;
+
+ if (rsize > 0) /* if not at end of buffer, stitch things together */
+ moveleft(&core[endd], &core[cp], rsize);
+ insert_to_undo(&undo, curr, len);
+ core[bufmax] = EOL;
+ return(cp);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1980-1997 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 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
+#define TOUPPER_FTN /* defined if the libraries support toupper as */
+ /* a function call */
+
+#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) */
+
+/*
+ * Compilation defines for different systems.
+ * Choose only one from each group.
+ */
+/* system you are compiling Levee on */
+#define ST 0
+#define RMX 0
+#define UNIX 1
+#define MSDOS 0
+#define FLEXOS 0
+
+/* do your libraries follow system V standards? */
+#define SYS5 1
+
+/* what sort of terminal are you emulating? */
+#define VT52 1 /* this must be nonzero for the Atari ST */
+#define TERMCAP 0
+#define ZTERM 0
+#define ANSI 0
+
+#if ST
+
+#include <stdio.h>
+
+#define void int /* Alcyon C don't know void */
+
+/* extractions from osbind.h */
+#define OPEN_OLD(n) gemdos(0x3d,n,/*open mode*/0)
+#define OPEN_NEW(n) gemdos(0x3c,n,/*permissions*/0)
+#define CLOSE_FILE(f) gemdos(0x3e,f)
+#define SEEK_POSITION(f,o,m) gemdos(0x42,(long)(o),f,m)
+#define READ_TEXT(f,b,c) gemdos(0x3f,f,(long)(c),b)
+#define WRITE_TEXT(f,b,c) gemdos(0x40,f,(long)(c),b)
+
+extern char *malloc();
+extern long gemdos();
+
+#endif /*ST*/
+
+#if 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 /*RMX*/
+
+#if MSDOS
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#define OPEN_OLD(n) open(n, O_RDONLY|O_BINARY)
+#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666)
+#define CLOSE_FILE(f) close(f)
+#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
+#define READ_TEXT(f,p,c) read(f, p, (int)(c))
+#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
+
+#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s)
+
+#undef PROC
+#define PROC _fastcall
+
+#include "proto.h"
+
+#endif /*MSDOS*/
+
+#if UNIX
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#define OPEN_OLD(n) open(n, O_RDONLY)
+#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC, 0666)
+#define CLOSE_FILE(f) close(f)
+#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m))
+#define READ_TEXT(f,p,c) read(f, p, (int)(c))
+#define WRITE_TEXT(f,p,c) write(f, p, (int)(c))
+
+#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s)
+
+#endif /*MSDOS*/
+
+#if FLEXOS
+
+#undef TOUPPER_FTN /* Nope, gotta do macro */
+
+#include <stdio.h>
+
+#define OPEN_OLD(n) s_open(m,0x08) /* note reversed parameters! */
+#define OPEN_NEW(n) s_create(0,0,n,0,0/*mode*/,0)
+#define CLOSE_FILE(f) s_close(0,f) /* Full close on handle */
+#define SEEK_POSITION(f,o,m) s_seek((m&03)<<9, f, o)
+#define READ_TEXT(f,p,c) s_read(0x0100,(long)(f),p,(long)(c),0L)
+#define WRITE_TEXT(f,p,c) s_write(0x0101,(long)(f),p,(long)(c),0L)
+
+#define zwrite(p,s) s_write(0x0101, 1L, p, (long)(s),0L)
+
+#define unlink(n) s_delete(0, n)
+#define rename(a,b) s_rename(0, a, b)
+
+/* OPEN_OLD mode flags */
+
+#undef HANDLE
+#define HANDLE long
+
+#endif /*FLEXOS*/
+
+#define bool int
+
+/* ttydef stuff */
+#if !(ST | 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 !TERMCAP
+#define CA TRUE
+#define canUPSCROLL !(MSDOS|FLEXOS)
+#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 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)4096) /* Edit buffer size */
+#endif
+
+#define SBUFSIZE ((int)512) /* Incore yank buffer size */
+#define MAXMACROS 32 /* Maximum # of macros */
+#define NMACROS 9 /* Nexting level for macros */
+
+#define PAGESIZE ((int)512) /* 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 */
+};
+
+#include "proto.h"
+
+#endif /*LEVEE_D*/
--- /dev/null
+ 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)
+
+\f 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.
+
+\f Levee. A Screen Oriented Editor.
+ Brackets ('[]') have special meaning as well. They mean
+ match any one of the characters inside the brackets. '[abc]'
+ will match 'a', 'b', or 'c'. You may specify a range of
+ characters inside brackets by using a dash (-). '[a-z]' will
+ match any lowercase alphabetic character. If ^ is the first
+ character in the bracket, it means match any character
+ except those in the brackets. '[^abc]' will match anything
+ except 'a','b', or 'c'.
+
+ Backslash takes away special meaning for these chars,
+ but '\t' specifies a tab, and \( & \) delimit arguments
+ inside a pattern (used only by :substitute.) The patterns
+ \< and \> have special meaning, too; they match the start
+ and end of alpha-numeric tokens.
+
+ If you turn off the editor variable 'magic', none of
+ the above characters will have special meaning inside of
+ a pattern (see 'set').
+
+ Some example patterns:
+
+ ^end$ Find a line that is just 'end'.
+ [Ee][Nn][Dd] Find a 'end', ignoring case.
+ [A-Za-z][A-Za-z0-9]* Find the next identifier.
+ (\*.*\*) Find the next one-line pascal
+ comment.
+ \<the\> Find the next occurance of `the'.
+
+\f 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.
+
+\f 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.
+
+\f 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.
+
+\f 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.
+
+\f 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.
+
+---------------
+\f 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.)
+
+\f 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.
+
+\f 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.
+
+\f 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).
+
+\f 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.
+
+\f Levee. A Screen Oriented Editor.
+---------------
+ (#)J
+ Join two (count+1) lines together. Joining appends the second line at
+ the end of the first, putting a space between them. If the first line
+ ends in whitespace, Levee will not put in a space.
+
+(*)------------
+ L
+ Move to the last nonwhite character on the last line of the screen.
+
+(*)------------
+ M
+ Move to the first nonwhite character in the middle of the screen.
+
+---------------
+ O
+ Open a line above the current line. Otherwise works just like 'o'.
+
+---------------
+ P
+ Put back the yank buffer at the cursor. Otherwise works just like 'p'.
+
+---------------
+ Q
+ Enter and remain in command mode. Just like the command :exec. To get
+ back to visual mode, you must enter the command ':visual'.
+
+---------------
+ R
+ Replace mode. A limited subset of insert mode that overwrites characters
+ up to end of line. All of the normal insert mode commands apply.
+ If you overwrite a character, then back over it with ^H,^U, or ^W, it
+ will reappear after you exit Replace mode.
+
+ Escape exits replace mode.
+
+ NOTE: due to a bug, entering a <return> in Replace mode will drop you
+ back into visual mode with an error. The replacements you have made
+ will remain.
+
+---------------
+ S
+ Change characters backwards. Shorthand for (#)ch.
+
+(*)------------
+ (#)T(x)
+ Move back to character on current line. If you are on the last character
+ of the line 'abcdef', typing "Ta" will move you back to the 'b'.
+
+(*)------------
+ (#)W
+ Move to end of word. Exactly like 'e'.
+
+---------------
+ (#)X
+ Delete characters backwards. Shorthand for (#)dh.
+
+\f 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.
+
+\f 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.
+
+\f 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.
+
+\f Levee. A Screen Oriented Editor.
+
+ COPYRIGHT
+
+ Copyright (c) 1982-1997 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.
+
+\f Levee. A Screen Oriented Editor.
+ I N D E X
+ Are you kidding?
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+
+#include "levee.h"
+#include "extern.h"
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#if (SYS5 & !ST) /* if system 5 compatable, it has signals */
+#include <signal.h>
+#endif
+
+#if RMX
+ extern alien token rq$get$task$tokens(); /* for unique files */
+#endif
+
+PROC
+int stamp(char *s, char *template)
+/* make a unique temporary file */
+{
+#if RMX
+ token dummy;
+
+ strcpy(s, ":work:");
+ strcat(s, template);
+ numtoa(&s[strlen(s)], rq$get$task$tokens(0,&dummy));
+#else
+ char *p;
+
+#if UNIX
+ strcpy(s, "/tmp/");
+#endif
+
+#if FLEXOS
+ s[0] = 0;
+#endif
+
+#if MSDOS
+ if (p=getenv("TMP")) {
+ strcpy(s, p);
+ if (s[strlen(s)-1] != '\\')
+ strcat(s, "\\");
+ }
+ else
+ s[0] = 0;
+#endif
+#if ST
+ 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 RMX|UNIX
+PROC void
+ctrlc(void)
+/* ctrlc: RMX control-C handler */
+{
+ count = 0; /* clear count, eh? */
+}
+#endif
+
+#if RMX
+PROC
+void settty(void)
+/* 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
+
+PROC
+void initialize(int count, char **args)
+/* initialize: set up everything I can in levee */
+{
+ int i;
+#if RMX
+ int xmode = E_INIT, xquit;
+#else
+#if ST
+ extern int mapslash;
+#endif
+#endif
+
+#if 0
+ signal(SIGINT, ctrlc);
+#else
+/* signal(SIGINT, SIG_IGN); */
+#endif
+ initcon();
+
+#if RMX
+ exception(0);
+ dq$trap$cc(ctrlc,&i);
+#endif
+
+#if ZTERM
+ zconfig();
+#endif /*ZTERM*/
+
+#if ST
+ screensz(&LINES, &COLS);
+ dofscroll = LINES/2;
+#endif
+
+#if RMX
+#if 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 /*TERMCAP*/
+ settty();
+#endif /*RMX*/
+
+#if TERMCAP
+ tc_init();
+#endif
+
+ version(); strput(". Copyright (c) 1983-1989 by David Parsons");
+
+ if (!CA || HO[0] == 0) {
+ 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 ST
+ mapslash = getenv("mapslash") != 0L;
+#endif
+#if RMX
+ do_file(":lvrc:", &xmode, &xquit);
+#else /*!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(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 ST
+long _STKSIZ = 4096;
+long _BLKSIZ = 4096;
+#endif
+
+void main(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 ZTERM
+ zclose();
+#endif
+
+ fixcon();
+
+#if 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);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+
+bool PROC
+getline(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(void)
+{
+ 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(void)
+{
+ 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(int start, int *endd, int limit, int 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(int loc)
+{
+ while ((core[loc] == '\t' || core[loc] == ' ') && loc <= bufmax)
+ loc++;
+ return(loc);
+} /* skipws */
+
+
+int PROC
+setX(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(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(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(int line)
+{
+ int cp = 0;
+ while (cp < bufmax && line > 1) {
+ cp = 1+fseekeol(cp);
+ line--;
+ }
+ return(cp);
+} /* to_index */
+
+PROC
+void swap(int *a, int *b)
+{
+ int c;
+
+ c = *a;
+ *a = *b;
+ *b = c;
+} /* swap */
+
+
+int PROC
+#if ST
+cclass(int c)
+{
+ if (c >= ' ' && c < '\7f')
+ return 0;
+ if (c == '\t' && !list)
+ return 2;
+ if (c >= 0)
+ return 1;
+ return 3;
+} /* cclass */
+#else
+cclass(unsigned char c)
+{
+ if (c == '\t' && !list)
+ return 2;
+ if (c == '\7f' || c < ' ')
+ return 1;
+#if MSDOS==0
+ if (c & 0x80)
+ return 3;
+#endif
+ return 0;
+} /* cclass */
+#endif
+
+#if ST
+/*
+ * wildly machine-dependent code to make a beep
+ */
+#include <atari\osbind.h>
+
+static char sound[] = {
+ 0xA8,0x01,0xA9,0x01,0xAA,0x01,0x00,
+ 0xF8,0x10,0x10,0x10,0x00,0x20,0x03
+};
+
+#define SADDR 0xFF8800L
+
+typedef char srdef[4];
+
+static srdef *SOUND = (srdef *)SADDR;
+
+static
+beeper(void)
+{
+ register i;
+ for (i=0; i<sizeof(sound); i++) {
+ (*SOUND)[0] = i;
+ (*SOUND)[2] = sound[i];
+ }
+} /* beeper */
+#endif /*ST*/
+
+
+PROC
+error()
+{
+ indirect = FALSE;
+ macro = -1;
+ if (xerox)
+ rcb[0] = 0;
+ xerox = FALSE;
+#if ST
+ Supexec(beeper);
+#else
+ if (bell)
+ strput(BELL);
+#endif /*ST*/
+} /* error */
+
+
+/* the dirty work to start up a macro */
+PROC insertmacro(char *cmdstr, int count)
+{
+ if (macro >= NMACROS)
+ error();
+ else if (*cmdstr != 0) {
+ macro++;
+ mcr[macro].mtext = cmdstr; /* point at the text */
+ mcr[macro].ip = cmdstr; /* starting index */
+ mcr[macro].m_iter = count; /* # times to do the macro */
+ }
+} /* insertmacro */
+
+
+int PROC lookup(char c)
+{
+ int ix = MAXMACROS;
+
+ while (--ix >= 0 && mbuffer[ix].token != c)
+ ;
+ return ix;
+} /* lookup */
+
+
+PROC
+void fixmarkers(int base, int offset)
+{
+ 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 */
+
+
+PROC
+void wr_stat(void)
+{
+ clrprompt();
+ if (filenm[0] != 0) {
+ printch('"');
+ prints(filenm);
+ prints("\" ");
+ if (newfile)
+ prints("<New file> ");
+ }
+ else
+ prints("No file");
+ printch(' ');
+ if (readonly)
+ prints("<readonly> ");
+ else if (modified)
+ prints("<Modified> ");
+ if (bufmax > 0) {
+ prints(" line ");
+ printi(to_line(curr));
+ prints(" -");
+ printi((int)((long)(curr*100L)/(long)bufmax));
+ prints("%-");
+ }
+ else
+ prints("-empty-");
+} /* wr_stat */
+
+
+static int tabptr,
+ tabstack[20],
+ ixp;
+
+PROC
+void back_up(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(char *s, int start, int endd, int *size)
+{
+ int col0,
+ ip;
+ 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=='\n' || c=='\r' || c==ESC) {
+ *size = (ip-start);
+ return (c==ESC) ? ESC : EOL;
+ }
+ else if ((!beautify) || c == TAB || c == 0x16 /* ^V */
+ || (c >= ' ' && c <= '~')) {
+ if (ip < endd) {
+ if (c == 0x16)
+ 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] */
+PROC
+void setpos(int loc)
+{
+ lstart = bseekeol(loc);
+ lend = fseekeol(loc);
+ xp = setX(loc);
+ curr = loc;
+} /* setpos */
+
+
+PROC
+void resetX(void)
+{
+ if (deranged) {
+ xp = setX(curr);
+ mvcur(-1, xp);
+ deranged = FALSE;
+ }
+} /* resetX */
+
+
+/* set end of window */
+PROC
+void setend(void)
+{
+ 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(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 */
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include "grep.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+/* modification commands that can be accessed by either editcore || execmode */
+
+/* put stuff into the yank buffer */
+
+bool PROC
+doyank(int low, int high)
+{
+ HANDLE f;
+ register 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(int low, int 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(int start, int *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(char *str, int start, int ssize, int size)
+/* makedest: make the replacement string for an regular expression */
+{
+ register char *fr = dst;
+ register 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(int start, int *endd, bool visual, bool *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("?\b");
+ }
+ 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;
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include <ctype.h>
+#include <string.h>
+
+/* driver for movement commands */
+
+findstates PROC
+findCP(int curp, int *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("^*[\ 2 \t$",curp+1,bufmax-1);
+ while (curp != ERR && --count > 0);
+ *newpos = (curp==ERR)?bufmax:curp;
+ break;
+
+ case PARA_BACK:
+ do
+ curp = findback("^*[\ 2 \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 (!nlsearch)
+ return BADMOVE;
+ tsearch = nlsearch;
+ printch(instring[0] = (cmd==FSEARCH)?nlsearch:((nlsearch=='?')?'/':'?') );
+ 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");
+ nlsearch = tsearch; /* fixup for N, n */
+ break;
+ }
+ if ( ((*newpos) >= 0) && ((*newpos) <= bufmax) )
+ return LEGALMOVE;
+ return BADMOVE;
+}
+
+/* this procedure handles all movement in visual mode */
+
+PROC
+movearound(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(int ip, int 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(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(char c)
+/* find the character class of a char -- for word movement */
+{
+ if (strchr(wordset,c))
+ return wordset;
+ else if (strchr(spaces,c))
+ return spaces;
+ else
+ return (char*)NULL;
+}
+
+int PROC
+skip(char *chars, int cp, int step)
+/* skip past characters in a character class */
+{
+ while (cp >= 0 && cp < bufmax && strchr(chars,core[cp]))
+ cp += step;
+ return cp;
+}
+
+int PROC
+tow(int cp, int step)
+/* skip to the start of the next word */
+{
+ while (cp >= 0 && cp < bufmax
+ && !(strchr(wordset,core[cp]) || strchr(spaces,core[cp])))
+ cp += step;
+ return cp;
+}
+
+int PROC
+moveword(int cp, bool forwd, bool toword)
+/* word movement */
+{
+ int step;
+ register 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(int pos, int npos)
+{
+ do
+ pos += scan(lend-pos-1,'=',ch, &core[pos+1]) + 1;
+ while (--count>0 && pos<lend);
+ if (pos<lend)
+ return(pos);
+ return(npos);
+}
+
+/* find a character backward on the current line */
+
+int PROC
+bchar(int pos, int npos)
+{
+ do
+ pos += scan(-pos+lstart+1,'=',ch, &core[pos-1]) - 1;
+ while (--count>0 && pos>=lstart);
+ if (pos>=lstart)
+ return(pos);
+ return(npos);
+}
+
+/* look for the end of a sentence forward */
+
+int PROC
+ahead(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(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(int start, bool forwd)
+{
+ do {
+ if (forwd)
+ start = ahead(start+1);
+ else
+ start = back(start-1);
+ } while (--count > 0 && start >= 0);
+ return start;
+}
--- /dev/null
+/*
+** 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(FILE *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);
+void 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);
+void 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);
+void 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(FILE *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);
+void 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);
+void PROC setend(void);
+void 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);
+void 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);
+void 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);
+void main(int argc,char * *argv);
+void PROC initcon(void);
+void PROC fixcon(void);
+#endif /*_PROTO_D*/
--- /dev/null
+If you wish to have your copy of Levee as a family mode application, all
+you need to do is bind it. It's already set up as a family mode application-
+there are some small differences for input (dos lv sees ^C and treats it
+like an ordinary character; os2 lv never sees ^C, because it's eaten by trap
+handlers) and redirectability (os2 lv uses getch() - a microsoft library
+function; dos vi uses dos function 0x07 - "get raw character from stdin,
+whatever that may be") but these shouldn't be a problem.
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * iRMX interface for levee (Intel C)
+ */
+#include "levee.h"
+#if 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
--- /dev/null
+ 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");
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * 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 RMX | MSDOS /* 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(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(char *ptr, char name[], char **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.
+ */
+{
+ 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(char *tc, char *what, char **savearea)
+/* get a character field from the termcap */
+{
+ 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(void)
+/* get the termcap stuff and go berserk parsing it */
+/* if anything horrid goes wrong, levee will crash */
+{
+#if RMX
+ char *p = termcap;
+#else
+ char *getenv();
+ char *p = getenv("TERMCAP");
+#endif
+ char *lp, *ptr;
+
+#if MSDOS
+ if (!p)
+ p = termcap;
+#endif
+#if !(RMX|MSDOS)
+ 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))
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+
+#ifndef moveleft
+
+PROC
+moveleft(char *src, char *dest, int length)
+{
+ while (--length >= 0)
+ *(dest++) = *(src++);
+}
+
+#endif /*moveleft*/
+
+#ifndef moveright
+
+PROC
+moveright(char *src, char *dest, int length)
+{
+ src = &src[length];
+ dest = &dest[length];
+ while (--length >= 0)
+ *(--dest) = *(--src);
+}
+
+#endif /*moveright*/
+
+#ifndef fillchar
+
+PROC
+fillchar(char *src,int length, char ch)
+{
+ while (--length >= 0)
+ *(src++) = ch;
+}
+
+#endif
+
+int PROC
+scan(int length, char tst, char ch, char *src)
+{
+ register 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);
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+#include "levee.h"
+#include "extern.h"
+#include <unistd.h>
+#include <string.h>
+
+#define BUFSZ sizeof(undo.coreblock)
+#define AVAIL(x) ((x)<<1)
+#define INDEX(x) ((1+x)>>1)
+
+bool PROC
+pushblock(struct undostack *u)
+{
+ if (u->blockp == 0)
+ if ((uwrite = OPEN_NEW(undobuf)) < 0)
+ return FALSE;
+ if (BUFSZ == WRITE_TEXT(uwrite, (void *)u->coreblock, BUFSZ)) {
+ u->blockp++;
+ u->ptr = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool PROC
+pushw(struct undostack *u, int i)
+{
+ if (u->ptr >= PAGESIZE && !pushblock(u))
+ return FALSE;
+ u->coreblock[u->ptr++] = i;
+ return TRUE;
+}
+
+bool PROC
+pushmem(struct undostack *u, int start, int 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;
+}
+
+PROC
+zerostack(struct undostack *u)
+{
+ if (u->blockp > 0)
+ CLOSE_FILE(uwrite);
+ u->blockp = 0; /* initialize the stack */
+ u->ptr = 0;
+}
+
+bool PROC
+uputcmd(struct undostack *u, int size, int start, char cmd)
+{
+ return(pushw(u, size) && pushw(u, start) && pushw(u, cmd));
+}
+
+PROC
+insert_to_undo(struct undostack *u, int start, int 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(struct undostack *u, int start, int 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(struct undostack *u, int start, int lump)
+{
+ return pushmem(u, start, lump) && uputcmd(u,lump,start,U_MOVEC);
+}
+
+bool PROC
+popblock(struct undostack *u)
+{
+ if (u->blockp > 0) {
+ if (SEEK_POSITION(uread, (long)((--u->blockp)*BUFSZ), 0) < 0)
+ return FALSE;
+ if (BUFSZ == READ_TEXT(uread, (void *)u->coreblock, BUFSZ)) {
+ u->ptr = PAGESIZE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool PROC
+popw(struct undostack *u, int *i)
+{
+ if (u->ptr < 1 && !popblock(u))
+ return FALSE;
+ *i = u->coreblock[--u->ptr];
+ return TRUE;
+}
+
+bool PROC
+popmem(struct undostack *u, int start, int 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(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(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(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(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)
+ memcpy(&undo, &save_undo, sizeof(undo));
+ if (closeio) {
+ CLOSE_FILE(uread); /* Zap old buffer */
+ unlink(undotmp);
+ }
+ if (!ok)
+ error();
+ return(curp);
+ }
+ return ERR;
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * Unix interface for levee
+ */
+#include "levee.h"
+#include "extern.h"
+#include <termios.h>
+#ifdef GCC
+#include <ioctls.h>
+#endif
+#include <string.h>
+#include <unistd.h>
+
+int
+min(int a, int b)
+{
+ return (a>b) ? b : a;
+}
+
+int
+max(int a,int b)
+{
+ return (a<b) ? b : a;
+}
+
+strput(char *s)
+{
+ if (s)
+ write(1, s, strlen(s));
+}
+
+
+#ifndef GCC
+char *basename(char *s)
+{
+ register char *p;
+
+ if (p=strrchr(s,'/'))
+ return 1+p;
+ return s;
+}
+#endif
+
+
+static int ioset = 0;
+static struct termios old;
+
+void initcon(void)
+{
+ struct termios new;
+
+ if (!ioset) {
+ tcgetattr(0, &old);
+ /*ioctl(0, TCGETS, &old);*/ /* get editing keys */
+
+ erasechar = old.c_cc[VERASE];
+ eraseline = old.c_cc[VKILL];
+
+ memcpy(&new, &old, sizeof(new));
+
+ new.c_iflag &= ~(IXOFF|IXANY|ICRNL|INLCR);
+ new.c_lflag &= ~(ICANON|ISIG|ECHO);
+ new.c_oflag = 0;
+
+ tcsetattr(0, TCSANOW, &new);
+ /*ioctl(0, TCSETS, &new);*/
+ ioset=1;
+ }
+}
+
+void fixcon(void)
+{
+ if (ioset) {
+ tcsetattr(0, TCSANOW, &old);
+ /*ioctl(0, TCSETS, &old);*/
+/* More or less blind attempt to fix console corruption.
+ T. Huld 1998-05-19
+ ioctl(0, TCSETA, &old);
+*/
+ ioset = 0;
+ }
+}
+
+int getKey(void)
+{
+ unsigned char c;
+
+ read(0,&c,1);
+ return c;
+}
--- /dev/null
+/*
+ * LEVEE, or Captain Video; A vi clone
+ *
+ * Copyright (c) 1982-1997 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.
+ */
+/*
+ * wildcard filename expanders for levee.
+ */
+#include "levee.h"
+#if !(RMX|UNIX)
+# include <glob.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+int wilderr, wildcard;
+
+PROC
+expandargs(char *name, int *argcp, char ***argvp)
+{
+#if RMX|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 /*!RMX*/
+ if (wilderr)
+ killargs(argcp, argvp);
+ return !wilderr;
+}
+
+#define QUANTUM 10
+
+PROC
+doaddwork(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 ST|RMX|FLEXOS
+ strlwr(ap[ac]); /* monocase filesystem */
+#endif
+ *argvp = ap;
+ return (*argcp)++;
+ }
+memfail:
+ errmsg("no memory");
+ return -1;
+}
+
+PROC
+killargs(int *argcp, char ***argvp)
+{
+ int i;
+
+ for (i=(*argcp)-1; i >= 0; i--)
+ free((*argvp)[i]);
+ if (*argcp)
+ free(*argvp);
+ *argcp = 0;
+ *argvp = 0L;
+}