From: Alan Cox Date: Sat, 3 Jan 2015 00:18:41 +0000 (+0000) Subject: levee: A very small vi editor X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=013029235e3bbe25ba3a23aa459ff6a282dd8142;p=FUZIX.git levee: A very small vi editor Still a bit large but with some clean up and tweaking ought to be ok on bigger boxes, if a bit tight on a 48K bank. --- diff --git a/Applications/levee/Makefile b/Applications/levee/Makefile new file mode 100644 index 00000000..246658b4 --- /dev/null +++ b/Applications/levee/Makefile @@ -0,0 +1,16 @@ +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 diff --git a/Applications/levee/beep.c b/Applications/levee/beep.c new file mode 100644 index 00000000..9083f653 --- /dev/null +++ b/Applications/levee/beep.c @@ -0,0 +1,47 @@ +/* + * 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 + +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 +#include +/* 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); +} diff --git a/Applications/levee/display.c b/Applications/levee/display.c new file mode 100644 index 00000000..cdede2a9 --- /dev/null +++ b/Applications/levee/display.c @@ -0,0 +1,329 @@ +/* + * 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 +#include +/* 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 -- + * ^ for control- + * spaces for + * 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 < '') { + 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 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); +} diff --git a/Applications/levee/doscall.c b/Applications/levee/doscall.c new file mode 100644 index 00000000..e65e5e4f --- /dev/null +++ b/Applications/levee/doscall.c @@ -0,0 +1,199 @@ +/* + * 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 +#include + +int PROC +min(a,b) +int a,b; +{ + return (a>b) ? b : a; +} + +int PROC +max(a,b) +int a,b; +{ + return (a s; --p) + if (p[-1] == '/' || p[-1] == '\\' || p[-1] == ':') + return p; + return s; +} /* basename */ + + +/* + * glob() expands a wildcard, via calls to _dos_findfirst/_next() + * and pathname retention. + */ +char * +glob(path, dta) +char *path; +struct glob_t *dta; +{ + static char path_bfr[256]; /* full pathname to return */ + static char *file_part; /* points at file - for filling */ + static char isdotpattern; /* looking for files starting with . */ + static char isdotordotdot; /* special case . or .. */ + static struct glob_t *dta_bfr; /* pointer to desired dta */ + static struct find_t dird; /* DOS dta */ + + register st; /* status from _dos_findxxx */ + + if (path) { + /* when we start searching, save the path part of the filename in + * a safe place. + */ + strcpy(path_bfr, path); + file_part = basename(path_bfr); + + /* set up initial parameters for DosFindFirst() + */ + dta_bfr = dta; + + if (isdotpattern = (*file_part == '.')) + /* _dos_findfirst() magically expands . and .. into their + * directory names. Admittedly, there are cases where + * this can be useful, but this is not one of them. So, + * if we find that we're matching . and .., we just + * special-case ourselves into oblivion to get around + * this particular bit of DOS silliness. + */ + isdotordotdot = (file_part[1] == 0 || file_part[1] == '.'); + else + isdotordotdot = 0; + + st = _dos_findfirst(path, 0x16, &dird); + } + else + st = _dos_findnext(&dird); + + while (st == 0) { + /* Unless the pattern has a leading ., don't include any file + * that starts with . + */ + if (dird.name[0] == '.' && !isdotpattern) + st = _dos_findnext(&dird); + else { + /* found a file - affix the path leading to it, then return + * a pointer to the (static) buffer holding the path+the name. + */ + strlwr(dird.name); /* DOS & OS/2 are case-insensitive */ + + if (dta_bfr) { + dta_bfr->wr_time = dird.wr_time; + dta_bfr->wr_date = dird.wr_date; + if (isdotordotdot) + strcpy(dta_bfr->name, file_part); + else { + strncpy(dta_bfr->name, dird.name, sizeof(dta_bfr->name)-1); + dta_bfr->name[sizeof(dta_bfr->name)-1] = 0; + } + dta_bfr->size = dird.size; + dta_bfr->attrib = dird.attrib; + } + if (!isdotordotdot) + strcpy(file_part, dird.name); + return path_bfr; + } + } + /* nothing matched + */ + if (path && isdotordotdot) { + /* must be at root, so statting dot will most likely fail. Fake a + * dta. + */ + if (dta_bfr) { + memset(dta_bfr, 0, sizeof *dta_bfr); + dta_bfr->attrib = 0x10; + dta_bfr->name[0] = '.'; + } + return path_bfr; + } + return (char*)0; +} /* glob */ +#endif /*MSDOS*/ diff --git a/Applications/levee/editcor.c b/Applications/levee/editcor.c new file mode 100644 index 00000000..d692fb03 --- /dev/null +++ b/Applications/levee/editcor.c @@ -0,0 +1,588 @@ +/* + * 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 +#include +/* do some undoable modification */ + +/* These variables make docommand nonrecursive */ + +bool ok; +int newend, /* end position after change */ + disp, /* start redisplay here */ + newc, /* new cursor position for wierd cmds */ + endY; /* final yp for endp */ + +/* move a line of text right || left */ + +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 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 */ +} diff --git a/Applications/levee/exec.c b/Applications/levee/exec.c new file mode 100644 index 00000000..916e9f42 --- /dev/null +++ b/Applications/levee/exec.c @@ -0,0 +1,1078 @@ +/* + * 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 +#include +#include + +/* + * 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"); + } +} diff --git a/Applications/levee/extern.h b/Applications/levee/extern.h new file mode 100644 index 00000000..4d0d61a1 --- /dev/null +++ b/Applications/levee/extern.h @@ -0,0 +1,200 @@ +/* + * 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*/ diff --git a/Applications/levee/find.c b/Applications/levee/find.c new file mode 100644 index 00000000..1e9e263e --- /dev/null +++ b/Applications/levee/find.c @@ -0,0 +1,493 @@ +/* + * 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 +#include + +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] 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 && dest0 && 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); +} diff --git a/Applications/levee/flexcall.c b/Applications/levee/flexcall.c new file mode 100644 index 00000000..0f3f0137 --- /dev/null +++ b/Applications/levee/flexcall.c @@ -0,0 +1,121 @@ +/* + * 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 +#include + +static int oldkmode; +static int oldsmode; + +int +min(a,b) +{ + return (a>b) ? b : a; +} + +int +max(a,b) +{ + return (a + +strput(s) +register char *s; +{ + write(1, s, strlen(s)); +} + + +zwrite(s,len) +char *s; +{ + write(1, s, len); +} + + +min(a,b) +register int a, b; +{ + return (ab)?a:b; +} + + +unsigned +getKey() +/* get input from the keyboard. All odd keys (function keys, et al) that + * do not produce a character have their scancode orred with $80 and returned. + */ +{ + unsigned c; + long key; + + c = (key = Crawcin()) & 0xff; + if (!c) + c = (((unsigned)(key>>16))|0x80) & 0xff; + return c; +} /* getKey */ +#endif /*ST*/ diff --git a/Applications/levee/globals.c b/Applications/levee/globals.c new file mode 100644 index 00000000..c4f49dc4 --- /dev/null +++ b/Applications/levee/globals.c @@ -0,0 +1,548 @@ +/* + * 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 + }; diff --git a/Applications/levee/grep.h b/Applications/levee/grep.h new file mode 100644 index 00000000..fca8841f --- /dev/null +++ b/Applications/levee/grep.h @@ -0,0 +1,35 @@ +/* + * 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 '&' diff --git a/Applications/levee/insert.c b/Applications/levee/insert.c new file mode 100644 index 00000000..65b483a1 --- /dev/null +++ b/Applications/levee/insert.c @@ -0,0 +1,153 @@ +/* + * 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 + +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 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 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); +} diff --git a/Applications/levee/levee b/Applications/levee/levee new file mode 100644 index 00000000..ea0fc9d2 Binary files /dev/null and b/Applications/levee/levee differ diff --git a/Applications/levee/levee.bin b/Applications/levee/levee.bin new file mode 100644 index 00000000..d428380d Binary files /dev/null and b/Applications/levee/levee.bin differ diff --git a/Applications/levee/levee.h b/Applications/levee/levee.h new file mode 100644 index 00000000..292eaa20 --- /dev/null +++ b/Applications/levee/levee.h @@ -0,0 +1,399 @@ +/* + * 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 + +#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 +#include + +#define OPEN_OLD(n) open(n, O_RDONLY|O_BINARY) +#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666) +#define CLOSE_FILE(f) close(f) +#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m)) +#define READ_TEXT(f,p,c) read(f, p, (int)(c)) +#define WRITE_TEXT(f,p,c) write(f, p, (int)(c)) + +#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s) + +#undef PROC +#define PROC _fastcall + +#include "proto.h" + +#endif /*MSDOS*/ + +#if UNIX + +#include +#include + +#define OPEN_OLD(n) open(n, O_RDONLY) +#define OPEN_NEW(n) open(n, O_WRONLY|O_CREAT|O_TRUNC, 0666) +#define CLOSE_FILE(f) close(f) +#define SEEK_POSITION(f,o,m) lseek(f, (long)(o), (m)) +#define READ_TEXT(f,p,c) read(f, p, (int)(c)) +#define WRITE_TEXT(f,p,c) write(f, p, (int)(c)) + +#define zwrite(p,s) WRITE_TEXT(fileno(stdout), p, s) + +#endif /*MSDOS*/ + +#if FLEXOS + +#undef TOUPPER_FTN /* Nope, gotta do macro */ + +#include + +#define OPEN_OLD(n) s_open(m,0x08) /* note reversed parameters! */ +#define OPEN_NEW(n) s_create(0,0,n,0,0/*mode*/,0) +#define CLOSE_FILE(f) s_close(0,f) /* Full close on handle */ +#define SEEK_POSITION(f,o,m) s_seek((m&03)<<9, f, o) +#define READ_TEXT(f,p,c) s_read(0x0100,(long)(f),p,(long)(c),0L) +#define WRITE_TEXT(f,p,c) s_write(0x0101,(long)(f),p,(long)(c),0L) + +#define zwrite(p,s) s_write(0x0101, 1L, p, (long)(s),0L) + +#define unlink(n) s_delete(0, n) +#define rename(a,b) s_rename(0, a, b) + +/* OPEN_OLD mode flags */ + +#undef HANDLE +#define HANDLE long + +#endif /*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*/ diff --git a/Applications/levee/lv.doc b/Applications/levee/lv.doc new file mode 100644 index 00000000..0922341a --- /dev/null +++ b/Applications/levee/lv.doc @@ -0,0 +1,873 @@ + Levee. A Screen Oriented Editor. + + USAGE + lv [+address] [file ...] + + SYNOPSIS + Levee is a screen oriented editor based on the Unix editor + "vi". It provides a terse, powerful way to enter and edit text + (however, if you want a word-processor, you're better off with + WordStar.) + + DESCRIPTION + Levee is a moded editor. It operates in 3 modes -- visual, + command, and insert. Most of the editing work is done is visual + mode, file reading and writing is done in command mode, and + insert mode does what you would expect. + When you enter Levee, you may specify an address to start + editing at. These addresses are in the same format as command + mode addresses, except that a naked + will put you at the very + end of the file. + + Levee is copyright (c) 1982-1997 by David L. Parsons. (see + the notice at the end of this document for distribution terms) + + Levee. A Screen Oriented Editor. + COMMANDS + + Command mode commands: + + These commands are used for editing new files, writing + modified files, changing options, doing substitutions, and + a subset of the visual commands. They take as input whole + lines, terminated by return (to execute), or escape (to + abort.) + + Command mode is reached by typing ":" or "Q" from visual + mode. If you enter command mode by typing ":", Levee will + execute one command, then return to visual mode after + prompting you with "[more]". If you type anything except + a space or return, Levee will accept another command, and so + forth. If, however, you enter command mode via "Q", Levee + will remain in command mode until you enter the "visual" + command. + + A NOTE ON COMMAND SYNTAX + A command may be preceded by an optional line-range. If + you do not provide a line-range, Levee will use the default + line-range shown by the command. A line-range is one or two + address specifications in the following format: + + (.|$|'x|#) [ (+|-) (/patt/|?patt?|#) ] + + . => current line. + $ => last line. + 'x => the line with mark x on it. + # => line #. + + For example, ".-5,.+5p" will print every line within ten + lines of the current line. "$-5" is the fifth line from the + end of the file, and "/end/+2" is the second line past the + next occurrence of the pattern "end". Patterns may be + regular expressions (see below.) + + Also, a naked line-range will set the current line to + the first line in the range and print all the lines in that + range. "1,10" sets the current line to 1, then prints lines + 1 to 10. + + If you specify a non-existent line in a range, the comm- + and will abort and Levee will tell you "bad address". + + Regular expressions: + Levee gives special meanings to some characters during + a pattern match. The character "." will match any one char, + the character "*" will match zero or more occurances of the + previous char ( so, a* will match 'a','aa','aaa', etc, or it + will match nothing at all). If a pattern begins with "^", it + will only match at the beginning of a line, and patterns + ending with a "$" will only match at the end of a line. + + Levee. A Screen Oriented Editor. + Brackets ('[]') have special meaning as well. They mean + match any one of the characters inside the brackets. '[abc]' + will match 'a', 'b', or 'c'. You may specify a range of + characters inside brackets by using a dash (-). '[a-z]' will + match any lowercase alphabetic character. If ^ is the first + character in the bracket, it means match any character + except those in the brackets. '[^abc]' will match anything + except 'a','b', or 'c'. + + Backslash takes away special meaning for these chars, + but '\t' specifies a tab, and \( & \) delimit arguments + inside a pattern (used only by :substitute.) The patterns + \< and \> have special meaning, too; they match the start + and end of alpha-numeric tokens. + + If you turn off the editor variable 'magic', none of + the above characters will have special meaning inside of + a pattern (see 'set'). + + Some example patterns: + + ^end$ Find a line that is just 'end'. + [Ee][Nn][Dd] Find a 'end', ignoring case. + [A-Za-z][A-Za-z0-9]* Find the next identifier. + (\*.*\*) Find the next one-line pascal + comment. + \ Find the next occurance of `the'. + + Levee. A Screen Oriented Editor. + +--------------- + args + show the current argument list, if one exists. The file that you + are currently editing will be framed by '[' and ']'. + +--------------- + (.,.) change + delete lines, then enter insert mode. + +--------------- + (.,.) delete + delete lines. Deleted lines are stored in a Yank Buffer for + later putback with "put". + +--------------- + edit[!] [file] + Discard the current file and start editing a new one. If + changes were made to the current file, you must enter "edit!" + to force Levee to discard the changes. If you do not specify + a filename, Levee will try to reedit the current filename. + + When Levee reads in a new file, it will tell you how many + bytes it read in, or [overflow] if the file is larger than the + internal buffer (currently 32760 bytes.) + +--------------- + execmode + Remain in command mode until you use the "visual" command. + +--------------- + file [name] + Echo what the current filename is, its status, and the current + line. If you provide it with a name, it will change the filename + to that. + +--------------- + (.) insert + Insert text above the current line. If you specify a line number, + Levee will make that the current line, then insert above it. + + Commands within insert mode: + ^W => back over the last word you entered. + ^H => back over one character. + ^U => back over all input on this line. + ^V => escape the next character typed. + ^V^H will put a ^H into the file. + ESC => exit insert mode. + ^D => If at start of line, reduce indentation 'shiftwidth' + columns. + ^T => If at start of line, increase indentation + 'shiftwidth' columns. + + When in insert mode, Levee will not allow you to enter any control + characters except return and tab. Return ends input on this line and + opens a new line for input. + + Levee. A Screen Oriented Editor. +--------------- + map[!] [key [text]] + Define/list macros. There are 3 forms of map: + + 1) map. This lists all the active macros. + 2) map (key). This shows the macro associated with (key), + if any. + 3) map (key) (text) + This maps (key) to (text). You may map any + key except ":" and escape. In the normal + form (map), the macro will be effective + in visual mode, but in the alternate form, + (map!), the macro will be effective in + insert and command modes. + + For example, if you map!ped return to "hello world", every time + you entered a return in command or visual mode, the string "hello + world" would pop up. + +--------------- + next [file ...] + Edit the next file in the arglist, or edit a new arglist. Levee + takes its initial arglist off the command line when you execute it. + If "autowrite" is set, Levee will write out the changes to the + current file before editing the next one. + +--------------- + (.) open + Insert below the current line. Otherwise just like insert. + +--------------- + previous + Edit the previous file in the arglist. Otherwise, like next. + +--------------- + (.,.) print + Display lines without changing the current line. + +--------------- + (.) put + Put the contents of the yank buffer back on the line below + the current line. If you specify a line, it resets the current + line, then puts the yank buffer back. The yank buffer is filled + by the delete, change, or yank commands. Put does not destroy + the yank buffer, so you may put back text multiple times. + +--------------- + quit[!] + Exit Levee. If you want to discard changes, use "quit!" + +--------------- + (.) read [file] + put the contents of 'file' after the current line. + +--------------- + rm file + Delete 'file' from disk. + + Levee. A Screen Oriented Editor. +--------------- + set [option=value] + Set a tunable variable. Levee has a dozen or so user-definable + variables which you can twiddle via this command. There are boolean, + integer, and string variables that you can set. A string or integer + variable is set by 'set xxx=yyy', a boolean variable is set via + 'set xxx' or 'set noxxx'. + + Here are the settable variables (and abbreviations): + tabsize (ts) tab stop. + shiftwidth (sw) columns to shift on ^D, ^T, >>, or << + scroll number of lines to scroll on ^D, ^U + autoindent (ai) supply indentation during insert mode. + autowrite (aw) write out changes before :next, :prev + autocopy (ac) make backup copies of before writing. + list display tabs as ^I, end of line as $. + magic use regular expressions in searches. + suffix if the filename does not have a . in + it, supply the suffix. (this is the + only string variable.) + overwrite (ow) destroy old file first, then write. + beautify (be) When set, Levee will not allow insert + of any control character except tab + and return unless you escape it with + ctrl-V. + wrapscan searches wrap around end of buffer. + ignorecase (ic) Ignore the case of alphabetic characters + during searches. + mapslash (ST version only) Map '/' in filenames to + '\'. If the environment contains `mapslash' + when levee is called, this variable will + default to true, otherwise it defaults to + false. (See the documentation for the + Teeny-shell on how the teeny-shell interprets + `mapslash') + lines (li) (ST version only) How many lines on the display. + This is primarily for running levee through + the serial port - put set li=xx into your + LVRC for a xx line terminal. + cols (co) (ST version only) How many columns on the + display. Like the lines variable, it's for + running levee through the serial port. + + You may set multiple variables on one line, as in 'set ws noai'. + To see the current settings of these variables, :set -- without any + arguments -- will show the current settings. + + At startup, Levee looks in the environment variable LVRC for + a list of variables to set (GEMDOS/MS-DOS). LVRC is one line + of the form 'option=value ...'. If you have a LVRC defined that + is 'ts=4 ow nows', Levee will set tabsize to 4, turn on overwrite, + and turn off wrapscan. + + If you are using RMX, Levee looks in the file ":home:r?lvrc" + for initialization. If you are using Osy/SWOs, Levee looks in the + file "*.lvrc". The format of these files are different from the + LVRC variable -- see "source" for more information. + + Levee. A Screen Oriented Editor. +--------------- + source file + Take command mode commands from 'file'. These commands can be + any legal command, except "visual". If a error happens during + execution of 'file', Levee abandons that level of source'ing. + + In Osy/SWOs, there are a few differences in insert mode from + within a sourced file. No character has special meaning except a + line containing nothing but a period, which terminates insert mode. + For example: + + :commands + . + . + :insert + blah blah blah blah blah blah + blah blah blah blah blah blah + blah blah blah blah blah blah + . + :more commands + + If you are running Levee under any other operating system, + you cannot do a insert from a :source file. + +NOTE: If you are running Levee on RMX or Osy/SWOs, it will read + ":home:r?lvrc" or "*.lvrc" at startup. These can consist of any + legal command mode instruction, just like any other source file. + +--------------- + (.,.)substitute(delim)patt(delim)repl(delim)[qcpg] + (.,.)substitute& + Search for patt and replace it with repl. Levee will look for + patt once on each line and replace it with repl. The delimiter + may be any ascii character. + + The pattern is a regular expression, just like a search + pattern. + + You may include parts of the pattern in the replacement string; + A '&' in the replacement pattern copies in the whole source pattern, + so if you do a 'sub/this/& and that/g', every instance of 'this' + will be replaced with 'this and that'. Also, you may pull parts of + the pattern out by using the \( and \) argument meta-characters. + Arguments gotten by \( & \) are put into the replacement string + everywhere you do a \1..\9 [ \1 is the first argument you set up + with \( & \) ]. So, if you want to reverse the order of two substrings, + you can do 'sub/\(string1\)\(string2\)/\2\1/'. + + substitute& redoes the last substitution. + + Options: + q,c => before doing the substitute, display the affected + line and wait for you to type a character. If you + type 'y', it will do the substitution. 'q' aborts + the substitute, 'a' does the rest of the change + without prompting, and 'n' does not do it. + p => print the affected lines after the change. + g => do the change globally. That is, do it for every + occurence of patt on a line, rather than just + once. + + Levee. A Screen Oriented Editor. +--------------- + undo + Undo the last modification to the file (except :edit, :next, :rm, + or :write.) You can only undo the last change to a file -- undo counts + as a change. :undo followed by :undo does nothing to the file. + +--------------- + unmap (key) + Undefine a macro (see map). + +--------------- + visual [list] + If you entered command mode by "Q" or "execmode", return to + visual mode. If you provide an argument list, it also does a + `:next' on that list. + +--------------- + version + Show which version of levee this is. + +--------------- + (.,.) write [file] + Write lines to a file. If you write the everything to 'file', + the filename is set to 'file', and if you do not specify a file, + Levee will write to the filename. + +--------------- + (.,.) wq [file] + Write to a file, then quit. + +--------------- + (.,.) yank + Yank lines from the file into the yank buffer, for later + putback with "put". + +--------------- + xit[!] + Write changes to the current file, then exit. If there are + more files in the arglist, use "xit!" + +--------------- + ![command] + Execute command. + + Example: + !ls => does a 'ls'. + + This command is available only under GEMDOS, MSDOS, and RMX. + +--------------- + ($)= + Give the line number of the addressed line. /end/= gives you + the line number of the next line with a 'end' on it. + +--------------- + Levee. A Screen Oriented Editor. + Visual mode commands. + Visual mode commands move you around and modify the file. + There are movement commands to move the cursor by a variety of + objects. + + In the description, a (#) means a optional count. If a + command has a optional count, it will tell you what the count + does in parenthesis. A (*) means that the command can be used + in the delete, yank, and change commands. + + Counts are made up by entering digits. If you type '45', + the count will be set to 45. To cancel a count, type ESC. + + This section discusses 'whitespace' occasionally. + Whitespace is tabs, spaces, and end of line. + + How the display works. + + Characters are displayed on the screen as you would + expect, except that nonprinting characters are shown as ^x, + and tabs expand to spaces ( unless you set the option list, + then they show as ^I.) When sitting on a control character or + tab, the cursor is placed on the FIRST character displayed. If + you move the cursor to any other part of them ( via j or k -- + see below), any changes will start at the next character. + + Levee does not display a end of file marker, but lines + past the end of the file are denoted by ~ lines. + + If list is set, tabs display as ^I, and the end of line + displays as $. + + If a line is too long for the screen, it will just dis- + appear off the end of the screen. + + Levee will handle any screen resolution and any monospaced + font you hand it ( if you are running in low resolution, Levee + will give you a 25x40 window, for example.) + + Levee. A Screen Oriented Editor. +--------------- + ^A + Show a debugging message at the bottom of the screen. This is not at + all useful unless you are debugging the editor. Ignore it. + +--------------- + (#)^D + Scroll the screen down a half screen. If a count is specified, scroll + down the specified number of lines. + +--------------- + ^E + Scroll down 1 line (shorthand for 1^D ) + +--------------- + ^G + Show file statistics. Exactly like ':file'. + +(*)------------ + (#)^H + Move the cursor left one (count) chars. + +--------------- + ^I + Redraw the screen. + +(*)------------ + (#)^J + Move down one (count) lines. When you use ^J and ^K (below) to move + up or down lines, the cursor will remain in the same column, even if + it is in the middle of a tabstop or past the end of a line. + +(*)------------ + (#)^K + Move up one (count) lines. + +(*)------------ + (#)^L + Move right one (count) characters. + +(*)------------ + (#)^M + Move to the first nonwhite space on the next line. If a count is specified, + move to the first nonwhite count lines down. + + Levee. A Screen Oriented Editor. +--------------- + (#)^U + Scroll the screen up a half page. If a count is specified, scroll up + count lines. + +--------------- + ^Y + Scroll the screen up 1 line (shorthand for 1^U.) + +--------------- + (#)a + Insert text AFTER the cursor. If you give a count, the insertion will + be repeated count times ( 40i-ESC will give you a line of 40 dashes). + + The commands in insert mode are the same for visual and command mode. + +(*)------------ + (#)b + Move to the beginning of the last word (the count'th word back). + A word is a collection of alphanumeric characters (a-z0-9$_#) or + any other nonwhite character (i.e. anything but space, tab, eoln). + +--------------- + c + Change a object. Change deletes an object, then enters insert mode without + redrawing the screen. When you tell it the object to be changed, Levee + puts a '$' on the last character of the object. You cannot change + backwards. + + The object may be any visual mode command marked with a '(*)'. For + example, 'c4l' will change the next 4 characters on the line to something + else. (4cl does the same thing -- 4c4l changes the next 16 characters on + this line.) + + 'cc' will change whole lines. + + When changing, deleting, or yanking a object, it will be placed into + a yank buffer, where it can be retrieved by the 'p' or 'P' commands. + +--------------- + (#)d + Delete an object. Like 'cc', 'dd' effects whole lines. + +(*)------------ + (#)e + Move to the end of the current word. + +(*)------------ + (#)f(x) + Find the next (count'th) occurance of a character on the current line. + For example, if the cursor is sitting on the first character of the + line 'abcdef', typing "ff" will put the cursor on the 'f'. + +(*)------------ + (#)h + Move left one (count) characters. Exactly like ^H. + + Levee. A Screen Oriented Editor. +--------------- + (#)i + Start inserting characters at the cursor. If you specify a count, + the insertion will be duplicated count times. + +(*)------------ + (#)j + Move down one (count) lines. Exactly like ^J. + +(*)------------ + (#)k + Move up one (count) lines. Exactly like ^K. + +(*)------------ + (#)l + Move right one (count) character. Exactly like ^L. + +--------------- + m(x) + Set the marker (x). There are 26 markers available (a-z). You may + move to a marker by use of the ' or ` commands. + +(*)------------ + n + Find the next occurance of a search pattern. When you do a search with + a / or ? command, Levee will remember the pattern and the direction you + searched in. 'n' will search in the same direction for the pattern, 'N' + searches in the opposite direction. + +--------------- + o + Open a line below the current line for insertion. + +--------------- + p + Put yanked/deleted text back after the cursor. Text is yanked + by the delete (d,x,X,D), change (c,C,s,S), and yank (y,Y) commands. + +--------------- + (#)r(x) + Replace characters (up to end of line) with (x). '4ra' will change the + next 4 characters after the cursor into 'aaaa'. + +--------------- + (#)s + change one (count) characters. Shorthand for (#)cl. + +(*)------------ + (#)t(x) + Move up to a character on the current line. If you are on the first + character of the line 'abcdef' and you type 'tf', you will end up sitting + on the 'e'. + +--------------- + u + Undo last modification. You can undo ANY modification command except + :edit, :next, :rm, or :write. (Just like :undo). + + Levee. A Screen Oriented Editor. +(*)------------ + (#)v + Move back to the very end of the previous (count'th) word. + See 'b' for the definition of a word. + +(*)------------ + (#)w + Move up to the very beginning of the next (count'th) word. + +--------------- + (#)x + Delete one (count) characters forward. Shorthand for (#)dl. + +--------------- + y + Yank an object for later use by put. 'yy' yanks whole lines. + +--------------- + A + Append text at the end of the line. Shorthand for $a. + +(*)------------ + (#)B + Move to the beginning of the current word. Exactly like 'b'. + + NOTE: this is incorrect. the capitalized word movement commands should, + and will in the future, be used for movement by space-delimited words. + +--------------- + C + Change to the end of the line. Shorthand for c$. + +--------------- + D + Delete to the end of the line. Shorthand for d$. + +(*)------------ + (#)F(x) + Move to the first (count'th) previous occurance of a character on the + current line. If you are sitting at the end of the line 'abcdef', typing + "Fa" will move you back to the 'a' at the start of the line. + +(*)------------ + (#)G + Goto line. If you specify a count, Levee will move to that line, and if + there is no count, Levee moves to the absolute end of the file. + + To get to the start of the file, type "1G". To the end, just "G". + +(*)------------ + H + Move to the first nonwhite character at the top of the screen. + +--------------- + I + Insert at the end of the current line. Shorthand for $i. + + Levee. A Screen Oriented Editor. +--------------- + (#)J + Join two (count+1) lines together. Joining appends the second line at + the end of the first, putting a space between them. If the first line + ends in whitespace, Levee will not put in a space. + +(*)------------ + L + Move to the last nonwhite character on the last line of the screen. + +(*)------------ + M + Move to the first nonwhite character in the middle of the screen. + +--------------- + O + Open a line above the current line. Otherwise works just like 'o'. + +--------------- + P + Put back the yank buffer at the cursor. Otherwise works just like 'p'. + +--------------- + Q + Enter and remain in command mode. Just like the command :exec. To get + back to visual mode, you must enter the command ':visual'. + +--------------- + R + Replace mode. A limited subset of insert mode that overwrites characters + up to end of line. All of the normal insert mode commands apply. + If you overwrite a character, then back over it with ^H,^U, or ^W, it + will reappear after you exit Replace mode. + + Escape exits replace mode. + + NOTE: due to a bug, entering a in Replace mode will drop you + back into visual mode with an error. The replacements you have made + will remain. + +--------------- + S + Change characters backwards. Shorthand for (#)ch. + +(*)------------ + (#)T(x) + Move back to character on current line. If you are on the last character + of the line 'abcdef', typing "Ta" will move you back to the 'b'. + +(*)------------ + (#)W + Move to end of word. Exactly like 'e'. + +--------------- + (#)X + Delete characters backwards. Shorthand for (#)dh. + + Levee. A Screen Oriented Editor. +--------------- + Y + Yank to end of line. Shorthand for y$. + +--------------- + ZZ + Write changes to current file and exit if last file in arglist. + Exactly like :xit. + +(*)------------ + (#)$ + Move to end of line. If you give a count, move to the end of the (count-1) + line down (so 2$ moves you to the end of the next line.). + +(*)------------ + % + Find matching bracket, parenthesis, or squiggly bracket. If you are not + sitting on a '[]{}()', Levee will search forward for one of them on the + current line, then match whatever it finds. + +(*)------------ + ^ + Move to the first nonwhite character on the current line. + +(*)------------ + & + Redo last substitution command. + +(*)------------ + (#){ + Move to the beginning of the count'th paragraph back. A paragraph is + delimited by a blank line. + +(*)------------ + (#)} + Move to the end of the count'th paragraph forward. + +(*)------------ + (#)( + Move to the beginning of the count'th sentence back. A sentence is + delimited by a ., a !, or a ? followed by a space, a tab, or end of line. + +(*)------------ + (#)) + Move to the end of the count'th sentence forward. + +(*)------------ + (#)- + Move to the (count'th) previous line, first nonwhite. + +(*)------------ + (#)+ + Move to the (count'th) next line, first nonwhite. + +--------------- + (#)~ + Change the case of the next count characters. Upper case becomes lowercase, + lowercase becomes uppercase. + + Levee. A Screen Oriented Editor. +(*)------------ + `(x) + Move to the exact position of mark (x). There is a special mark for some + of the visual mode move ment commands -- '' will move you to where you + were before the last (,),',`,G,/,?,n,N command. + +--------------- + : + Execute one command mode command. When the command is done, it will return + to visual mode if it produces one line of output, but if it scrolls the + screen, Levee will prompt [more] before returning to visual mode. If you + type a : in response to the [more] prompt, Levee will remain in command + mode for one more command. + +--------------- + (#)<(#) + Shift one (count) objects left. If you specify a second count, Levee will + shift the object left that many columns -- if you do not, they will be sh + shifted shiftwidth columns. + + This is a nondestructive shift. If the shift would carry past the left + margin, the objects will be moved up to the left margin but no farther. + + Like the other object movement commands, '<<' will affect whole lines. + +--------------- + (#)>(#) + Shift one (count) objects right. Just like <, except it will not shift + objects past the right margin of the screen. If you do shift an object + past the right margin of the screen, all of its indent will be removed + and it will end up by the left margin. + +--------------- + . + Repeat last modification command. (except undo) + +(*)------------ + ? + Search for pattern backwards. Escape aborts the search pattern, and a + empty pattern means search for the last pattern again. + +(*)------------ + / + Search for pattern forwards. Otherwise like ?. + +(*)------------ + (#)| + Move to specified column. If you don't have a count, move to column 0. + + Levee. A Screen Oriented Editor. + + + LIMITATIONS + Levee can only edit files up to 256000 characters long. ^M is used + as its internal line separator, so inserting ^M will have interesting + consequences. + + BUGS + Probably infinite. + + AUTHOR + David L. Parsons (orc) + + Testing, suggestions, and impractical design goals by: + Jim Bolland. + John Tainter. + John Plocher. + + Levee. A Screen Oriented Editor. + + COPYRIGHT + + Copyright (c) 1982-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. A Screen Oriented Editor. + I N D E X + Are you kidding? diff --git a/Applications/levee/main.c b/Applications/levee/main.c new file mode 100644 index 00000000..9e2fd73b --- /dev/null +++ b/Applications/levee/main.c @@ -0,0 +1,302 @@ +/* + * 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 +#include +#include + +#if (SYS5 & !ST) /* if system 5 compatable, it has signals */ +#include +#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); +} diff --git a/Applications/levee/misc.c b/Applications/levee/misc.c new file mode 100644 index 00000000..fb7e532f --- /dev/null +++ b/Applications/levee/misc.c @@ -0,0 +1,456 @@ +/* + * 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 < '') + 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 == '' || 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 + +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= 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(" "); + } + else + prints("No file"); + printch(' '); + if (readonly) + prints(" "); + else if (modified) + prints(" "); + if (bufmax > 0) { + prints(" line "); + printi(to_line(curr)); + prints(" -"); + printi((int)((long)(curr*100L)/(long)bufmax)); + prints("%-"); + } + else + prints("-empty-"); +} /* wr_stat */ + + +static int tabptr, + tabstack[20], + ixp; + +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 */ diff --git a/Applications/levee/modify.c b/Applications/levee/modify.c new file mode 100644 index 00000000..71ad4b07 --- /dev/null +++ b/Applications/levee/modify.c @@ -0,0 +1,192 @@ +/* + * 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 +#include +#include + +/* 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("?"); + } + 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; +} diff --git a/Applications/levee/move.c b/Applications/levee/move.c new file mode 100644 index 00000000..cc0bfd06 --- /dev/null +++ b/Applications/levee/move.c @@ -0,0 +1,420 @@ +/* + * 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 +#include + +/* 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("^*[ \t$",curp+1,bufmax-1); + while (curp != ERR && --count > 0); + *newpos = (curp==ERR)?bufmax:curp; + break; + + case PARA_BACK: + do + curp = findback("^*[ \t$",curp-1,0); + while (curp != ERR && --count > 0); + *newpos = (curp==ERR)?0:curp; + break; + + case SENT_FWD: + case SENT_BACK: + *newpos = sentence(curp, cmd==SENT_FWD); + break; + + case MATCHEXPR: + *newpos = match(curp); + break; + + case TO_CHAR: + case UPTO_CHAR: + case BACK_CHAR: + case BACKTO_CHAR: + ch = readchar(); + if (ch == ESC) + return ESCAPED; + if (cmd<=UPTO_CHAR) { + *newpos = fchar(curp,*newpos); + if (cmd==UPTO_CHAR && *newpos>=0) + *newpos = max(curp, *newpos-1); + } + else { + *newpos = bchar(curp,*newpos); + if (cmd==BACKTO_CHAR && *newpos>=0) + *newpos = min(curp, *newpos+1); + } + break; + + case PAGE_BEGIN: + *newpos = ptop; + break; + + case PAGE_END: + *newpos = pend; + break; + + case PAGE_MIDDLE: + curp = ptop; + count = 12; + while (count-- > 0 && curp < bufmax) + curp = 1+fseekeol(curp); + *newpos = skipws(curp); + break; + + case GLOBAL_LINE: + if (count <= 0) + *newpos = bufmax-1; + else + *newpos = to_index(count); + break; + + case TO_MARK: + case TO_MARK_LINE: + *newpos = getcontext((char)tolower(readchar()), cmd==TO_MARK_LINE); + break; + + case CR_FWD: + case CR_BACK: + curp = nextline(cmd==CR_FWD, curp, count); + if (cmd==CR_BACK && curp > 0) + curp = bseekeol(curp); + *newpos = skipws(curp); + break; + + case PATT_FWD: + case PATT_BACK: /* search for pattern */ + case FSEARCH: + case BSEARCH: + clrprompt(); + if (cmd == PATT_FWD || cmd == PATT_BACK) { + printch(tsearch = instring[0] = chars[cmd-PATT_FWD]); + if (!getline(&instring[1])) + return ESCAPED; /* needs to skip later tests */ + } + else { + if (!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 && pos0 && 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; +} diff --git a/Applications/levee/proto.h b/Applications/levee/proto.h new file mode 100644 index 00000000..72707afb --- /dev/null +++ b/Applications/levee/proto.h @@ -0,0 +1,164 @@ +/* +** 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*/ diff --git a/Applications/levee/readme.os2 b/Applications/levee/readme.os2 new file mode 100644 index 00000000..c1ec0057 --- /dev/null +++ b/Applications/levee/readme.os2 @@ -0,0 +1,7 @@ +If you wish to have your copy of Levee as a family mode application, all +you need to do is bind it. It's already set up as a family mode application- +there are some small differences for input (dos lv sees ^C and treats it +like an ordinary character; os2 lv never sees ^C, because it's eaten by trap +handlers) and redirectability (os2 lv uses getch() - a microsoft library +function; dos vi uses dos function 0x07 - "get raw character from stdin, +whatever that may be") but these shouldn't be a problem. diff --git a/Applications/levee/rmxcall.c b/Applications/levee/rmxcall.c new file mode 100644 index 00000000..b9f2371f --- /dev/null +++ b/Applications/levee/rmxcall.c @@ -0,0 +1,100 @@ +/* + * 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 diff --git a/Applications/levee/tc b/Applications/levee/tc new file mode 100644 index 00000000..770fbb95 --- /dev/null +++ b/Applications/levee/tc @@ -0,0 +1,32 @@ + if (!(ttytype = getenv("TERM"))) { + S1("TERM not set"); + exit(6); + } + if (tgetent(tc, ttytype) != 1) { + sprintf(Msg, "Can't load %s", ttytype); + S; + exit(7); + } + ospeed = newmode.c_cflag & CBAUD; + LI = tgetnum("li") - 1; + CO = tgetnum("co"); + if (!(s = Tgetstr("pc"))) + PC = '\0'; + else + PC = *s; + + CD = Tgetstr("cd"); + CE = Tgetstr("ce"); + CL = Tgetstr("cl"); + CM = Tgetstr("cm"); + SE = Tgetstr("se"); + SO = Tgetstr("so"); +#ifdef linux + CF = Tgetstr("vi"); + CN = Tgetstr("ve"); +#else + CF = Tgetstr("CF"); + CN = Tgetstr("CN"); +#endif + if (CF && !CN) + CN = Tgetstr("CO"); diff --git a/Applications/levee/termcap.i b/Applications/levee/termcap.i new file mode 100644 index 00000000..312f534d --- /dev/null +++ b/Applications/levee/termcap.i @@ -0,0 +1,204 @@ +/* + * 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)) diff --git a/Applications/levee/ucsd.c b/Applications/levee/ucsd.c new file mode 100644 index 00000000..805e262d --- /dev/null +++ b/Applications/levee/ucsd.c @@ -0,0 +1,77 @@ +/* + * 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); +} diff --git a/Applications/levee/undo.c b/Applications/levee/undo.c new file mode 100644 index 00000000..23c96650 --- /dev/null +++ b/Applications/levee/undo.c @@ -0,0 +1,246 @@ +/* + * 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 +#include + +#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; +} diff --git a/Applications/levee/unixcall.c b/Applications/levee/unixcall.c new file mode 100644 index 00000000..01715d2c --- /dev/null +++ b/Applications/levee/unixcall.c @@ -0,0 +1,107 @@ +/* + * 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 +#ifdef GCC +#include +#endif +#include +#include + +int +min(int a, int b) +{ + return (a>b) ? b : a; +} + +int +max(int a,int b) +{ + return (a +#endif +#include +#include + +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; +}