Category : OS/2 Files
Archive   : KSH48.ZIP
Filename : VI.C

 
Output of file : VI.C contained in archive : KSH48.ZIP
/*
* vi command editing
* written by John Rochester (initially for nsh)
* bludgeoned to fit PD ksh by Larry Bouzane and Eric Gisin
* Further hacked (bugfixes and tweaks) by Mike Jetzer
*/

#include "config.h"
#ifdef VI

#ifndef lint
static char *RCSid = "$Id: vi.c,v 1.3 1992/08/10 12:03:31 sjg Exp $";
#endif

#include "stdh.h"
#include
#include
#include
#include
#include
#include
#include "sh.h"
#include "expand.h"
#include "edit.h"

#define CMDLEN 256
#define Ctrl(c) (c&0x1f)
extern int histN();

static int nextstate ARGS((int ch));
static int vi_insert ARGS((int ch));
static int vi_cmd ARGS((int argcnt, char *cmd));
static int domove ARGS((int argcnt, char *cmd, int sub));
static int redo_insert ARGS((int count));
static yank_range ARGS((int a, int b));
static int bracktype ARGS((int ch));
static edit_reset ARGS((char *buf, int len));
static int putbuf ARGS((char *buf, int len, int repl));
static stripblanks ARGS((void));
static del_range ARGS((int a, int b));
static int findch ARGS((int ch, int cnt, int forw, int incl));
static int forwword ARGS((int argcnt));
static int backword ARGS((int argcnt));
static int endword ARGS((int argcnt));
static int Forwword ARGS((int argcnt));
static int Backword ARGS((int argcnt));
static int Endword ARGS((int argcnt));
static int grabhist ARGS((int save, int n));
static int grabsearch ARGS((int save, int start, int fwd, char *pat));
static redraw_line ARGS((void));
static refresh ARGS((int leftside));
static int outofwin ARGS((void));
static rewindow ARGS((void));
static int newcol ARGS((int ch, int col));
static display ARGS((char *wb1, char *wb2, int leftside));
static ed_mov_opt ARGS((int col, char *wb));

#define C_ 0x1
#define M_ 0x2
#define E_ 0x4
#define X_ 0x8
#define U_ 0x10
#define B_ 0x20
#define O_ 0x40
#define S_ 0x80

#define isbad(c) (classify[c]&B_)
#define iscmd(c) (classify[c]&(M_|E_|C_|U_))
#define ismove(c) (classify[c]&M_)
#define isextend(c) (classify[c]&E_)
#define islong(c) (classify[c]&X_)
#define ismeta(c) (classify[c]&O_)
#define isundoable(c) (!(classify[c]&U_))
#define issrch(c) (classify[c]&S_)

char classify[256] = {
B_, 0, 0, 0, 0, 0, O_, 0,
#if 1 /* Mike B. changes */
C_|M_, 0, O_, 0, O_, O_, O_, 0,
#else
C_, 0, O_, 0, O_, O_, O_, 0,
#endif
O_, 0, C_|U_, 0, 0, 0, 0, 0,
0, 0, O_, 0, 0, 0, 0, 0,
#if 1 /* Mike B. changes */
C_|M_, 0, 0, C_, M_, C_, 0, 0,
#else
C_, 0, 0, C_, M_, C_, 0, 0,
#endif
0, 0, C_, C_, M_, C_, 0, C_|S_,
M_, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, M_, 0, C_, 0, C_|S_,
0, C_, M_, C_, C_, M_, M_|X_, C_,
0, C_, 0, 0, 0, 0, C_, 0,
C_, 0, C_, C_, M_|X_, 0, 0, M_,
C_, C_, 0, 0, 0, 0, M_, C_,
0, C_, M_, E_, E_, M_, M_|X_, 0,
M_, C_, C_, C_, M_, 0, C_, 0,
C_, 0, C_, C_, M_|X_, C_|U_, 0, M_,
C_, E_, 0, 0, 0, 0, C_, 0
};

#define MAXVICMD 3
#define SRCHLEN 40

#define INSERT 1
#define REPLACE 2

#define VNORMAL 0
#define VARG1 1
#define VEXTCMD 2
#define VARG2 3
#define VXCH 4
#define VFAIL 5
#define VCMD 6
#define VREDO 7
#define VLIT 8
#define VSEARCH 9
#define VREPLACE1CHAR 10

struct edstate {
int winleft;
char *cbuf;
int cbufsize;
int linelen;
int cursor;
};

static char undocbuf[CMDLEN];

static struct edstate ebuf;
static struct edstate undobuf = { 0, undocbuf, CMDLEN, 0, 0 };

static struct edstate *es; /* current editor state */
static struct edstate *undo;

static char ibuf[CMDLEN]; /* input buffer */
static int inslen; /* length of input buffer */
static int srchlen; /* length of current search pattern */
static char ybuf[CMDLEN]; /* yank buffer */
static int yanklen; /* length of yank buffer */
static int fsavecmd = ' '; /* last find command */
static int fsavech; /* character to find */
static char lastcmd[MAXVICMD]; /* last non-move command */
static int lastac; /* argcnt for lastcmd */
static int lastsearch = ' '; /* last search command */
static char srchpat[SRCHLEN]; /* last search pattern */
static int insert; /* non-zero in insert mode */
static int hnum; /* position in history */
static int hlast; /* 1 past last position in history */
static int modified; /* buffer has been "modified" */
static int state;

#if 0
vi_init()
{
es = (struct edstate *) malloc((unsigned) sizeof(struct edstate));
fsavecmd = ' ';
lastsearch = ' ';
}

edit_init()
{
wbuf[0] = malloc((unsigned) (x_cols - 3));
wbuf[1] = malloc((unsigned) (x_cols - 3));
}
#endif

void
vi_reset(buf, len)
char *buf;
int len;
{
state = VNORMAL;
hnum = hlast = histnum(-1) + 1;
insert = INSERT;
yanklen = 0;
inslen = 0;
lastcmd[0] = 'a';
lastac = 1;
modified = 1;
edit_reset(buf, len);
}

int
vi_hook(ch)
int ch;
{
static char curcmd[MAXVICMD];
static char locpat[SRCHLEN];
static int cmdlen;
static int argc1, argc2;

if (state != VSEARCH && (ch == '\r' || ch == '\n')) {
x_putc('\r');
x_putc('\n');
x_flush();
return 1;
}

switch (state) {

case VREPLACE1CHAR:
curcmd[cmdlen++] = ch;
state = VCMD;
break;

case VNORMAL:
if (insert != 0) {
if (ch == Ctrl('v')) {
state = VLIT;
ch = '^';
}
if (vi_insert(ch) != 0) {
x_putc(Ctrl('g'));
state = VNORMAL;
} else {
if (state == VLIT) {
es->cursor--;
refresh(0);
} else
refresh(insert != 0);
}
} else {
cmdlen = 0;
argc1 = 0;
if (ch >= '1' && ch <= '9') {
argc1 = ch - '0';
state = VARG1;
} else {
curcmd[cmdlen++] = ch;
state = nextstate(ch);
if (state == VSEARCH) {
save_cbuf();
es->cursor = 0;
es->linelen = 0;
if (ch == '/') {
if (putbuf("/", 1, 0) != 0) {
return -1;
}
} else if (putbuf("?", 1, 0) != 0)
return -1;
refresh(0);
}
}
}
break;

case VLIT:
if (isbad(ch)) {
del_range(es->cursor, es->cursor + 1);
x_putc(Ctrl('g'));
} else
es->cbuf[es->cursor++] = ch;
refresh(1);
state = VNORMAL;
break;

case VARG1:
if (isdigit(ch))
argc1 = argc1 * 10 + ch - '0';
else {
curcmd[cmdlen++] = ch;
state = nextstate(ch);
}
break;

case VEXTCMD:
argc2 = 0;
if (ch >= '1' && ch <= '9') {
argc2 = ch - '0';
state = VARG2;
return 0;
} else {
curcmd[cmdlen++] = ch;
if (ch == curcmd[0])
state = VCMD;
else if (ismove(ch))
state = nextstate(ch);
else
state = VFAIL;
}
break;

case VARG2:
if (isdigit(ch))
argc2 = argc2 * 10 + ch - '0';
else {
if (argc1 == 0)
argc1 = argc2;
else
argc1 *= argc2;
curcmd[cmdlen++] = ch;
if (ch == curcmd[0])
state = VCMD;
else if (ismove(ch))
state = nextstate(ch);
else
state = VFAIL;

}
break;

case VXCH:
if (ch == Ctrl('['))
state = VNORMAL;
else {
curcmd[cmdlen++] = ch;
state = VCMD;
}
break;

case VSEARCH:
switch (ch) {

/* case Ctrl('['): */
case '\r':
case '\n':
locpat[srchlen] = '\0';
(void) strcpy(srchpat, locpat);
/* redraw_line(); */
state = VCMD;
break;

case 0x7f:
if (srchlen == 0) {
restore_cbuf();
state = VNORMAL;
} else {
srchlen--;
if (locpat[srchlen] < ' ' ||
locpat[srchlen] == 0x7f) {
es->linelen--;
}
es->linelen--;
es->cursor = es->linelen;
refresh(0);
return 0;
}
refresh(0);
break;

case Ctrl('u'):
srchlen = 0;
es->linelen = 1;
es->cursor = 1;
refresh(0);
return 0;

default:
if (srchlen == SRCHLEN - 1)
x_putc(Ctrl('g'));
else {
locpat[srchlen++] = ch;
if (ch < ' ' || ch == 0x7f) {
es->cbuf[es->linelen++] = '^';
es->cbuf[es->linelen++] = ch ^ '@';
} else
es->cbuf[es->linelen++] = ch;
es->cursor = es->linelen;
refresh(0);
}
return 0;
break;
}
break;
}
switch (state) {

case VCMD:
state = VNORMAL;
switch (vi_cmd(argc1, curcmd)) {
case -1:
x_putc(Ctrl('g'));
break;
case 0:
if (insert != 0)
inslen = 0;
refresh(insert != 0);
break;
case 1:
refresh(0);
x_putc('\r');
x_putc('\n');
x_flush();
return 1;
}
break;

case VREDO:
state = VNORMAL;
if (argc1 != 0)
lastac = argc1;
switch (vi_cmd(lastac, lastcmd) != 0) {
case -1:
x_putc(Ctrl('g'));
refresh(0);
break;
case 0:
if (insert != 0) {
if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
lastcmd[0] == 'C') {
if (redo_insert(1) != 0)
x_putc(Ctrl('g'));
} else {
if (redo_insert(lastac) != 0)
x_putc(Ctrl('g'));
}
}
refresh(0);
break;
case 1:
refresh(0);
x_putc('\r');
x_putc('\n');
x_flush();
return 1;
}

break;

case VFAIL:
state = VNORMAL;
x_putc(Ctrl('g'));
break;
}
return 0;
}

static int
nextstate(ch)
int ch;
{
/*
* probably could have been done more elegantly than
* by creating a new state, but it works
*/
if (ch == 'r')
return VREPLACE1CHAR;
else if (isextend(ch))
return VEXTCMD;
else if (issrch(ch))
return VSEARCH;
else if (islong(ch))
return VXCH;
else if (ch == '.')
return VREDO;
else if (iscmd(ch))
return VCMD;
else
return VFAIL;
}

static int
vi_insert(ch)
int ch;
{
int tcursor;

switch (ch) {

case '\0':
return -1;

case Ctrl('['):
if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
lastcmd[0] == 'C')
return redo_insert(0);
else
return redo_insert(lastac - 1);

case 0x7f: /* delete */
/* tmp fix */
/* general fix is to get stty erase char and use that
*/
case Ctrl('H'): /* delete */
if (es->cursor != 0) {
if (inslen > 0)
inslen--;
es->cursor--;
if (insert != REPLACE) {
memmove(&es->cbuf[es->cursor],
&es->cbuf[es->cursor+1],
es->linelen - es->cursor);
es->linelen--;
}
}
break;

case Ctrl('U'):
if (es->cursor != 0) {
inslen = 0;
memmove(es->cbuf, &es->cbuf[es->cursor],
es->linelen - es->cursor);
es->linelen -= es->cursor;
es->cursor = 0;
}
break;

case Ctrl('W'):
if (es->cursor != 0) {
tcursor = backword(1);
memmove(&es->cbuf[tcursor], &es->cbuf[es->cursor],
es->linelen - es->cursor);
es->linelen -= es->cursor - tcursor;
if (inslen < es->cursor - tcursor)
inslen = 0;
else
inslen -= es->cursor - tcursor;
es->cursor = tcursor;
}
break;

default:
if (es->linelen == es->cbufsize - 1)
return -1;
ibuf[inslen++] = ch;
if (insert == INSERT) {
memmove(&es->cbuf[es->cursor+1], &es->cbuf[es->cursor],
es->linelen - es->cursor);
es->linelen++;
}
es->cbuf[es->cursor++] = ch;
if (insert == REPLACE && es->cursor > es->linelen)
es->linelen++;
}
return 0;
}

static int
vi_cmd(argcnt, cmd)
int argcnt;
char *cmd;
{
int ncursor;
int cur, c1, c2, c3 = 0;
struct edstate *t;


if (argcnt == 0) {
if (*cmd == 'G')
argcnt = hlast + 1;
else if (*cmd != '_')
argcnt = 1;
}

if (ismove(*cmd)) {
if ((cur = domove(argcnt, cmd, 0)) >= 0) {
if (cur == es->linelen && cur != 0)
cur--;
es->cursor = cur;
} else
return -1;
} else {
if (isundoable(*cmd)) {
undo->winleft = es->winleft;
memmove(undo->cbuf, es->cbuf, es->linelen);
undo->linelen = es->linelen;
undo->cursor = es->cursor;
lastac = argcnt;
memmove(lastcmd, cmd, MAXVICMD);
}
switch (*cmd) {

case Ctrl('r'):
redraw_line();
break;

case 'a':
modified = 1;
if (es->linelen != 0)
es->cursor++;
insert = INSERT;
break;

case 'A':
modified = 1;
del_range(0, 0);
es->cursor = es->linelen;
insert = INSERT;
break;

case 'c':
case 'd':
case 'y':
if (*cmd == cmd[1]) {
c1 = 0;
c2 = es->linelen;
} else if (!ismove(cmd[1]))
return -1;
else {
if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0)
return -1;
if (*cmd == 'c' &&
(cmd[1]=='w' || cmd[1]=='W') &&
!isspace(es->cbuf[es->cursor])) {
while (isspace(es->cbuf[--ncursor]))
;
ncursor++;
}
if (ncursor > es->cursor) {
c1 = es->cursor;
c2 = ncursor;
} else {
c1 = ncursor;
c2 = es->cursor;
}
}
if (*cmd != 'c' && c1 != c2)
yank_range(c1, c2);
if (*cmd != 'y') {
del_range(c1, c2);
es->cursor = c1;
}
if (*cmd == 'c') {
modified = 1;
insert = INSERT;
}
break;

case 'p':
modified = 1;
if (es->linelen != 0)
es->cursor++;
while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
;
if (es->cursor != 0)
es->cursor--;
if (argcnt != 0)
return -1;
break;

case 'P':
modified = 1;
while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
;
if (es->cursor != 0)
es->cursor--;
if (argcnt != 0)
return -1;
break;

case 'C':
modified = 1;
del_range(es->cursor, es->linelen);
insert = INSERT;
break;

case 'D':
yank_range(es->cursor, es->linelen);
del_range(es->cursor, es->linelen);
if (es->cursor != 0)
es->cursor--;
break;

case 'G':
if (grabhist(modified, argcnt - 1) < 0)
return -1;
else {
modified = 0;
hnum = argcnt - 1;
}
break;

case 'i':
modified = 1;
insert = INSERT;
break;

case 'I':
modified = 1;
es->cursor = 0;
insert = INSERT;
break;

case '+':
case 'j':
if (grabhist(modified, hnum + argcnt) < 0)
return -1;
else {
modified = 0;
hnum += argcnt;
}
break;

case '-':
case 'k':
if (grabhist(modified, hnum - argcnt) < 0)
return -1;
else {
modified = 0;
hnum -= argcnt;
}
break;

case 'r':
if (es->linelen == 0)
return -1;
modified = 1;
es->cbuf[es->cursor] = cmd[1];
break;

case 'R':
modified = 1;
insert = REPLACE;
break;

case 's':
if (es->linelen == 0)
return -1;
modified = 1;
if (es->cursor + argcnt > es->linelen)
argcnt = es->linelen - es->cursor;
del_range(es->cursor, es->cursor + argcnt);
insert = INSERT;
break;

case 'x':
if (es->linelen == 0)
return -1;
modified = 1;
if (es->cursor + argcnt > es->linelen)
argcnt = es->linelen - es->cursor;
yank_range(es->cursor, es->cursor + argcnt);
del_range(es->cursor, es->cursor + argcnt);
break;

case 'X':
if (es->cursor > 0) {
modified = 1;
if (es->cursor < argcnt)
argcnt = es->cursor;
yank_range(es->cursor - argcnt, es->cursor);
del_range(es->cursor - argcnt, es->cursor);
es->cursor -= argcnt;
} else
return -1;
break;

case 'u':
t = es;
es = undo;
undo = t;

break;

case '?':
hnum = -1;
/* ahhhhhh... */
case '/':
c3 = 1;
srchlen = 0;
lastsearch = *cmd;
/* fall through */
case 'n':
case 'N':
if (lastsearch == ' ')
return -1;
if (lastsearch == '?')
c1 = 1;
else
c1 = 0;
if (*cmd == 'N')
c1 = !c1;
if ((c2 = grabsearch(modified, hnum,
c1, srchpat)) < 0) {
if (c3) {
restore_cbuf();
refresh(0);
}
return -1;
} else {
modified = 0;
hnum = c2;
}
break;
case '_': {
int space;
char *p, *sp;

(void) histnum(-1);
p = *histpos();
#define issp(c) (isspace((c)) || (c) == '\n')
if (argcnt) {
while (*p && issp(*p))
p++;
while (*p && --argcnt) {
while (*p && !issp(*p))
p++;
while (*p && issp(*p))
p++;
}
if (!*p)
return -1;
sp = p;
} else {
sp = p;
space = 0;
while (*p) {
if (issp(*p))
space = 1;
else if (space) {
space = 0;
sp = p;
}
p++;
}
p = sp;
}
modified = 1;
if (es->linelen != 0)
es->cursor++;
while (*p && !issp(*p)) {
argcnt++;
p++;
}
if (putbuf(" ", 1, 0) != 0)
argcnt = -1;
else if (putbuf(sp, argcnt, 0) != 0)
argcnt = -1;
if (argcnt < 0) {
if (es->cursor != 0)
es->cursor--;
return -1;
}
insert = INSERT;
}
break;

case '~': {
char *p;

if (es->linelen == 0)
return -1;
p = &es->cbuf[es->cursor];
if (islower(*p)) {
modified = 1;
*p = toupper(*p);
} else if (isupper(*p)) {
modified = 1;
*p = tolower(*p);
}
if (es->cursor < es->linelen - 1)
es->cursor++;
}
break;

case '#':
es->cursor = 0;
if (putbuf("#", 1, 0) != 0)
return -1;
return 1;

case '*':
case '=': {
int rval = 0;
int start, end;
char *toglob = undo->cbuf;
char **ap;
char **ap2;
char **globstr();

if (isspace(es->cbuf[es->cursor]))
return -1;
start = es->cursor;
while (start > -1 && !isspace(es->cbuf[start]))
start--;
start++;
end = es->cursor;
while (end < es->linelen && !isspace(es->cbuf[end]))
end++;
/* use undo buffer to build word up in */
memmove(toglob, &es->cbuf[start], end-start);
if (toglob[end-start-1] != '*') {
toglob[end-start] = '*';
toglob[end-start+1] = '\0';
} else
toglob[end-start] = '\0';
ap = globstr(toglob);
ap2 = ap;
if (strcmp(ap[0], toglob) == 0 && ap[1] == (char *) 0)
rval = -1;
/* restore undo buffer that we used temporarily */
memmove(toglob, es->cbuf, es->linelen);
if (rval < 0)
return rval;
if (*cmd == '=') {
fputc('\n', shlout);
pr_menu(ap2, 0);
fflush(shlout);
if (es->linelen != 0)
es->cursor++;
redraw_line();
insert = INSERT;
state = VNORMAL;
return 0;
} else {
del_range(start, end);
es->cursor = start;
while (1) {
if (putbuf(*ap, strlen(*ap), 0) != 0) {
rval = -1;
break;
}
if (*++ap == (char *) 0)
break;
if (putbuf(" ", 1, 0) != 0) {
rval = -1;
break;
}

}
#if 0
/*
* this is definitely wrong
*/
for (ap = ap2; *ap; ap++)
free(*ap);

free(ap2);
#endif

modified = 1;
insert = INSERT;
refresh(0);
}
if (rval != 0)
return rval;
}
break;
}
if (insert == 0 && es->cursor != 0 && es->cursor >= es->linelen)
es->cursor--;
}
return 0;
}

static int
domove(argcnt, cmd, sub)
int argcnt;
char *cmd;
int sub;
{
int bcount, i = 0, t; /* = 0 kludge for gcc -W */
int ncursor = 0; /* = 0 kludge for gcc -W */

switch (*cmd) {

case 'b':
if (!sub && es->cursor == 0)
return -1;
ncursor = backword(argcnt);
break;

case 'B':
if (!sub && es->cursor == 0)
return -1;
ncursor = Backword(argcnt);
break;

case 'e':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
ncursor = endword(argcnt);
if (sub)
ncursor++;
break;

case 'E':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
ncursor = Endword(argcnt);
if (sub)
ncursor++;
break;

case 'f':
case 'F':
case 't':
case 'T':
fsavecmd = *cmd;
fsavech = cmd[1];
/* drop through */

case ',':
case ';':
if (fsavecmd == ' ')
return -1;
i = fsavecmd == 'f' || fsavecmd == 'F';
t = fsavecmd > 'a';
if (*cmd == ',')
t = !t;
if ((ncursor = findch(fsavech, argcnt, t, i)) < 0)
return -1;
if (sub && t)
ncursor++;
break;

case 'h':
/* tmp fix */
case Ctrl('H'):
if (!sub && es->cursor == 0)
return -1;
ncursor = es->cursor - argcnt;
if (ncursor < 0)
ncursor = 0;
break;

case ' ':
case 'l':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
if (es->linelen != 0) {
ncursor = es->cursor + argcnt;
if (ncursor >= es->linelen)
ncursor = es->linelen - 1;
}
break;

case 'w':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
ncursor = forwword(argcnt);
break;

case 'W':
if (!sub && es->cursor + 1 >= es->linelen)
return -1;
ncursor = Forwword(argcnt);
break;

case '0':
ncursor = 0;
break;

case '^':
ncursor = 0;
while (ncursor < es->linelen - 1 && isspace(es->cbuf[ncursor]))
ncursor++;
break;

case '$':
if (es->linelen != 0)
ncursor = es->linelen;
else
ncursor = 0;
break;

case '%':
ncursor = es->cursor;
while (ncursor < es->linelen &&
(i = bracktype(es->cbuf[ncursor])) == 0)
ncursor++;
if (ncursor == es->linelen)
return -1;
bcount = 1;
do {
if (i > 0) {
if (++ncursor >= es->linelen)
return -1;
} else {
if (--ncursor < 0)
return -1;
}
t = bracktype(es->cbuf[ncursor]);
if (t == i)
bcount++;
else if (t == -i)
bcount--;
} while (bcount != 0);
if (sub)
ncursor++;
break;

default:
return -1;
}
return ncursor;
}

static int
redo_insert(count)
int count;
{
while (count-- > 0)
if (putbuf(ibuf, inslen, insert==REPLACE) != 0)
return -1;
if (es->cursor > 0)
es->cursor--;
insert = 0;
return 0;
}

static
yank_range(a, b)
int a, b;
{
yanklen = b - a;
if (yanklen != 0)
memmove(ybuf, &es->cbuf[a], yanklen);
}

static int
bracktype(ch)
int ch;
{
switch (ch) {

case '(':
return 1;

case '[':
return 2;

case '{':
return 3;

case ')':
return -1;

case ']':
return -2;

case '}':
return -3;

default:
return 0;
}
}

/*
* Non user interface editor routines below here
*/

static int cur_col; /* current column on line */
static int pwidth; /* width of prompt */
static int winwidth; /* width of window */
/*static char *wbuf[2]; /* window buffers */
static char wbuf[2][128-3]; /* window buffers */ /* TODO */
static int win; /* window buffer in use */
static char morec; /* more character at right of window */
static int lastref; /* argument to last refresh() */
static char holdbuf[CMDLEN]; /* place to hold last edit buffer */
static int holdlen; /* length of holdbuf */

save_cbuf()
{
memmove(holdbuf, es->cbuf, es->linelen);
holdlen = es->linelen;
holdbuf[holdlen] = '\0';
}

restore_cbuf()
{
es->cursor = 0;
es->linelen = holdlen;
memmove(es->cbuf, holdbuf, holdlen);
}

static
edit_reset(buf, len)
char *buf;
int len;
{
es = &ebuf;
es->cbuf = buf;
es->cbufsize = len;
undo = &undobuf;
undo->cbufsize = len;

es->linelen = undo->linelen = 0;
es->cursor = undo->cursor = 0;
es->winleft = undo->winleft = 0;

cur_col = pwidth = promptlen(prompt);
winwidth = x_cols - pwidth - 3;
x_putc('\r');
x_flush();
pprompt(prompt);
/* docap(CLR_EOL, 0); */
win = 0;
morec = ' ';
lastref = 1;
}

static int
putbuf(buf, len, repl)
char *buf;
int len;
int repl;
{
if (len == 0)
return 0;
if (repl) {
if (es->cursor + len >= es->cbufsize - 1)
return -1;
if (es->cursor + len > es->linelen)
es->linelen = es->cursor + len;
} else {
if (es->linelen + len >= es->cbufsize - 1)
return -1;
memmove(&es->cbuf[es->cursor + len], &es->cbuf[es->cursor],
es->linelen - es->cursor);
es->linelen += len;
}
memmove(&es->cbuf[es->cursor], buf, len);
es->cursor += len;
return 0;
}

static
stripblanks()
{
int ncursor;

ncursor = 0;
while (ncursor < es->linelen && isspace(es->cbuf[ncursor]))
ncursor++;
del_range(0, ncursor);
}

static
del_range(a, b)
int a, b;
{
if (es->linelen != b)
memmove(&es->cbuf[a], &es->cbuf[b], es->linelen - b);
es->linelen -= b - a;
}

static int
findch(ch, cnt, forw, incl)
int ch;
int forw;
int incl;
{
int ncursor;

if (es->linelen == 0)
return -1;
ncursor = es->cursor;
while (cnt--) {
do {
if (forw) {
if (++ncursor == es->linelen)
return -1;
} else {
if (--ncursor < 0)
return -1;
}
} while (es->cbuf[ncursor] != ch);
}
if (!incl) {
if (forw)
ncursor--;
else
ncursor++;
}
return ncursor;
}

#define Isalnum(x) (isalnum(x) || (x == '_'))
static int
forwword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
if (Isalnum(es->cbuf[ncursor]))
while (Isalnum(es->cbuf[ncursor]) &&
++ncursor < es->linelen)
;
else if (!isspace(es->cbuf[ncursor]))
while (!Isalnum(es->cbuf[ncursor]) &&
!isspace(es->cbuf[ncursor]) &&
++ncursor < es->linelen)
;
while (isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
;
}
return ncursor;
}

static int
backword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor > 0 && argcnt--) {
while (--ncursor > 0 && isspace(es->cbuf[ncursor]))
;
if (ncursor > 0) {
if (Isalnum(es->cbuf[ncursor]))
while (--ncursor >= 0 &&
Isalnum(es->cbuf[ncursor]))
;
else
while (--ncursor >= 0 &&
!Isalnum(es->cbuf[ncursor]) &&
!isspace(es->cbuf[ncursor]))
;
ncursor++;
}
}
return ncursor;
}

static int
endword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
while (++ncursor < es->linelen - 1 &&
isspace(es->cbuf[ncursor]))
;
if (ncursor < es->linelen - 1) {
if (Isalnum(es->cbuf[ncursor]))
while (++ncursor < es->linelen &&
Isalnum(es->cbuf[ncursor]))
;
else
while (++ncursor < es->linelen &&
!Isalnum(es->cbuf[ncursor]) &&
!isspace(es->cbuf[ncursor]))
;
ncursor--;
}
}
return ncursor;
}

static int
Forwword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor < es->linelen && argcnt--) {
while (!isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
;
while (isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
;
}
return ncursor;
}

static int
Backword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor > 0 && argcnt--) {
while (--ncursor >= 0 && isspace(es->cbuf[ncursor]))
;
while (ncursor >= 0 && !isspace(es->cbuf[ncursor]))
ncursor--;
ncursor++;
}
return ncursor;
}

static int
Endword(argcnt)
int argcnt;
{
int ncursor;

ncursor = es->cursor;
while (ncursor < es->linelen - 1 && argcnt--) {
while (++ncursor < es->linelen - 1 &&
isspace(es->cbuf[ncursor]))
;
if (ncursor < es->linelen - 1) {
while (++ncursor < es->linelen &&
!isspace(es->cbuf[ncursor]))
;
ncursor--;
}
}
return ncursor;
}

static int
grabhist(save, n)
int save;
int n;
{
char *hptr;

if (n < 0 || n > hlast)
return -1;
if (n == hlast) {
restore_cbuf();
return 0;
}
(void) histnum(n);
if ((hptr = *histpos()) == NULL) {
shellf("grabhist: bad history array\n");
return -1;
}
if (save)
save_cbuf();
es->linelen = strlen(hptr);
memmove(es->cbuf, hptr, es->linelen);
es->cursor = 0;
return 0;
}

static int
grabsearch(save, start, fwd, pat)
int save, start, fwd;
char *pat;
{
char *hptr;

if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
return -1;
if ((hptr = findhist(start, fwd, pat)) == NULL) {
/* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */
if (start != 0 && fwd && strcmp(holdbuf, pat) >= 0) {
restore_cbuf();
return 0;
} else
return -1;
} else if (hptr == (char *)-1) {
return -1;
}
if (save)
save_cbuf();
es->linelen = strlen(hptr);
memmove(es->cbuf, hptr, es->linelen);
es->cursor = 0;
return histN();
}

static
redraw_line()
{
x_putc('\r');
x_putc('\n');
x_flush();
pprompt(prompt);
cur_col = pwidth;
morec = ' ';
}

static
refresh(leftside)
int leftside;
{
if (leftside < 0)
leftside = lastref;
else
lastref = leftside;
if (outofwin())
rewindow();
display(wbuf[1 - win], wbuf[win], leftside);
win = 1 - win;
}

static int
outofwin()
{
int cur, col;

if (es->cursor < es->winleft)
return 1;
col = 0;
cur = es->winleft;
while (cur < es->cursor)
col = newcol(es->cbuf[cur++], col);
if (col > winwidth)
return 1;
return 0;
}

static
rewindow()
{
register int tcur, tcol;
int holdcur1, holdcol1;
int holdcur2, holdcol2;

holdcur1 = holdcur2 = tcur = 0;
holdcol1 = holdcol2 = tcol = 0;
while (tcur < es->cursor) {
if (tcol - holdcol2 > winwidth / 2) {
holdcur1 = holdcur2;
holdcol1 = holdcol2;
holdcur2 = tcur;
holdcol2 = tcol;
}
tcol = newcol(es->cbuf[tcur++], tcol);
}
while (tcol - holdcol1 > winwidth / 2)
holdcol1 = newcol(es->cbuf[holdcur1++], holdcol1);
es->winleft = holdcur1;
}

static int
newcol(ch, col)
int ch, col;
{
if (ch < ' ' || ch == 0x7f) {
if (ch == '\t')
return (col | 7) + 1;
else
return col + 2;
} else
return col + 1;
}

static
display(wb1, wb2, leftside)
char *wb1, *wb2;
int leftside;
{
char *twb1, *twb2, mc;
int cur, col, cnt;
int ncol = 0; /* set to 0 kludge for gcc -W */
int moreright;

col = 0;
cur = es->winleft;
moreright = 0;
twb1 = wb1;
while (col < winwidth && cur < es->linelen) {
if (cur == es->cursor && leftside)
ncol = col + pwidth;
if (es->cbuf[cur] < ' ' || es->cbuf[cur] == 0x7f) {
if (es->cbuf[cur] == '\t') {
do {
*twb1++ = ' ';
} while (++col < winwidth && (col & 7) != 0);
} else {
*twb1++ = '^';
if (++col < winwidth) {
*twb1++ = es->cbuf[cur] ^ '@';
col++;
}
}
} else {
*twb1++ = es->cbuf[cur];
col++;
}
if (cur == es->cursor && !leftside)
ncol = col + pwidth - 1;
cur++;
}
if (cur == es->cursor)
ncol = col + pwidth;
if (col < winwidth) {
while (col < winwidth) {
*twb1++ = ' ';
col++;
}
} else
moreright++;
*twb1 = ' ';

col = pwidth;
cnt = winwidth;
twb1 = wb1;
twb2 = wb2;
while (cnt--) {
if (*twb1 != *twb2) {
if (cur_col != col)
ed_mov_opt(col, wb1);
x_putc(*twb1);
cur_col++;
}
twb1++;
twb2++;
col++;
}
if (es->winleft > 0 && moreright)
mc = '+';
else if (es->winleft > 0)
mc = '<';
else if (moreright)
mc = '>';
else
mc = ' ';
if (mc != morec) {
ed_mov_opt(x_cols - 2, wb1);
x_putc(mc);
cur_col++;
morec = mc;
}
#if 0
/*
* Hack to fix the ^r redraw problem, but it redraws way too much.
* Probably unacceptable at low baudrates. Someone please fix this
*/
else
{
ed_mov_opt(x_cols - 2, wb1);
}
#endif
if (cur_col != ncol)
ed_mov_opt(ncol, wb1);
}

static
ed_mov_opt(col, wb)
int col;
char *wb;
{
if (col < cur_col) {
if (col + 1 < cur_col - col) {
x_putc('\r');
x_flush();
pprompt(prompt);
cur_col = pwidth;
while (cur_col++ < col)
x_putc(*wb++);
} else {
while (cur_col-- > col)
x_putc('\b');
}
} else {
wb = &wb[cur_col - pwidth];
while (cur_col++ < col)
x_putc(*wb++);
}
cur_col = col;
}

int
x_vi(buf, len)
char *buf;
size_t len;
{
int c;

vi_reset(buf, len > CMDLEN ? CMDLEN : len);
x_flush();
while ((c = getch()) != -1) {
if (vi_hook(c))
break;
x_flush();
}

if (c == -1)
return -1;

if (es->cbuf != buf) {
memmove(buf, es->cbuf, es->linelen);
buf[es->linelen] = '\n';
} else
es->cbuf[es->linelen] = '\n';

es->linelen++;
return es->linelen;
}

getch()
{
unsigned char buf;

#ifdef OS2
do
{
buf = _read_kbd(0, 1, 0);
if ( buf == 0 || buf == 0xE0 )
_read_kbd(0, 1, 0);
}
while ( buf == 0 || buf == 0xE0 );
if (buf == Ctrl('c')) {
#else
if (read(ttyfd, &buf, 1) != 1)
return -1;
if ((buf & 0x7f) == Ctrl('c')) {
#endif
/*
* If you hit ctrl-c, the buffer was left in a
* strange state; the next command typed was
* mucked up. Doing all of this is probably
* overkill, but it works most of the time.
*/
memset(es->cbuf, 0, CMDLEN);
es->winleft = 0;
es->cbufsize = 0;
es->linelen = 0;
es->cursor = 0;

memset(undo->cbuf, 0, CMDLEN);
undo->winleft = 0;
undo->cbufsize = 0;
undo->linelen = 0;
undo->cursor = 0;
x_mode(FALSE);
trapsig(SIGINT);
#ifdef OS2
} else if (buf == Ctrl('d'))
return -1;
return buf;
#else
} else if ((buf & 0x7f) == Ctrl('d'))
return -1;
return buf & 0x7f;
#endif
}


char **globstr(stuff)
char *stuff;
{
char *vecp[2];

vecp[0] = stuff;
vecp[1] = NULL;
return(eval(vecp, DOBLANK|DOGLOB|DOTILDE));
}
#endif /* VI */


  3 Responses to “Category : OS/2 Files
Archive   : KSH48.ZIP
Filename : VI.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/