#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
void
ungetkey(int c)
{
if (Peekkey != ATTN)
Peekkey = c;
}
int
getkey(void)
{
int c;
do {
c = getbr();
if (c==0)
(void) beep();
} while (c == 0);
return (c);
}
int
peekbr(void)
{
Peekkey = getbr();
return (Peekkey == 0);
}
short precbksl;
int
getbr(void)
{
unsigned char ch;
int c, d;
unsigned char *colp;
int cnt;
static unsigned char Peek2key;
extern short slevel, ttyindes;
getATTN:
if (Peekkey) {
c = Peekkey;
Peekkey = 0;
return (c);
}
if (Peek2key) {
c = Peek2key;
Peek2key = 0;
return (c);
}
if (vglobp) {
if (*vglobp)
return (lastvgk = *vglobp++);
lastvgk = 0;
return (ESCAPE);
}
if (vmacp) {
if (*vmacp)
return(*vmacp++);
vmacp = 0;
if (inopen == -1)
vundkind = VMANY;
inopen = 1;
vch_mac = VC_NOTINMAC;
}
flusho();
again:
if ((c=read(slevel == 0 ? 0 : ttyindes, &ch, 1)) != 1) {
if (errno == EINTR)
goto getATTN;
else if (errno == EIO)
kill(getpid(), SIGHUP);
error(gettext("Input read error"));
}
c = ch;
if (beehive_glitch && slevel==0 && c == ESCAPE) {
if (read(0, &Peek2key, 1) != 1)
goto getATTN;
switch (Peek2key) {
case 'C':
c = ' ';
Peek2key = 0;
break;
case 'q':
c = CTRL('c');
Peek2key = 0;
break;
case 'p':
Peek2key = 0;
break;
}
}
if (UPPERCASE) {
if (isupper(c))
c = tolower(c);
if (c == '\\') {
if (precbksl < 2)
precbksl++;
if (precbksl == 1)
goto again;
} else if (precbksl) {
d = 0;
if (islower(c))
d = toupper(c);
else {
colp = (unsigned char *)"({)}!|^~'~";
while (d = *colp++)
if (d == c) {
d = *colp++;
break;
} else
colp++;
}
if (precbksl == 2) {
if (!d) {
Peekkey = c;
precbksl = 0;
c = '\\';
}
} else if (d)
c = d;
else {
Peekkey = c;
precbksl = 0;
c = '\\';
}
}
if (c != '\\')
precbksl = 0;
}
#ifdef TRACE
if (trace) {
if (!techoin) {
tfixnl();
techoin = 1;
fprintf(trace, "*** Input: ");
}
tracec(c);
}
#endif
lastvgk = 0;
return (c);
}
int
getesc(void)
{
int c;
c = getkey();
switch (c) {
case CTRL('v'):
case CTRL('q'):
c = getkey();
return (c);
case ATTN:
case QUIT:
ungetkey(c);
return (0);
case ESCAPE:
return (0);
}
return (c);
}
int
peekkey(void)
{
Peekkey = getkey();
return (Peekkey);
}
int
readecho(c)
unsigned char c;
{
unsigned char *sc = cursor;
int (*OP)();
bool waste;
int OPeek;
if (WBOT == WECHO)
vclean();
else
vclrech(0);
splitw++;
vgoto(WECHO, 0);
putchar(c);
vclreol();
vgoto(WECHO, 1);
cursor = linebuf; linebuf[0] = 0; genbuf[0] = c;
ixlatctl(1);
if (peekbr()) {
if (!INS[0] || (unsigned char)INS[128] == 0200) {
INS[128] = 0;
goto blewit;
}
vglobp = INS;
}
OP = Pline; Pline = normline;
(void)vgetline(0, genbuf + 1, &waste, c);
doomed = 0;
ixlatctl(0);
if (Outchar == termchar)
putchar('\n');
vscrap();
Pline = OP;
if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL('h')) {
cursor = sc;
vclreol();
return (0);
}
blewit:
OPeek = Peekkey==CTRL('h') ? 0 : Peekkey; Peekkey = 0;
splitw = 0;
vclean();
vshow(dot, NOLINE);
vnline(sc);
Peekkey = OPeek;
return (1);
}
void
setLAST(void)
{
if (vglobp || vmacp)
return;
lastreg = vreg;
lasthad = Xhadcnt;
lastcnt = Xcnt;
*lastcp = 0;
CP(lastcmd, workcmd);
}
void
addtext(unsigned char *cp)
{
if (vglobp)
return;
addto(INS, cp);
if ((unsigned char)INS[128] == 0200)
lastcmd[0] = 0;
}
void
setDEL(void)
{
setBUF(DEL);
}
void
setBUF(unsigned char *BUF)
{
int c;
unsigned char *wp = wcursor;
c = *wp;
*wp = 0;
BUF[0] = 0;
BUF[128] = 0;
addto(BUF, cursor);
*wp = c;
}
void
addto(unsigned char *buf, unsigned char *str)
{
if ((unsigned char)buf[128] == 0200)
return;
if (strlen(buf) + strlen(str) + 1 >= VBSIZE) {
buf[128] = 0200;
return;
}
(void)strcat(buf, str);
buf[128] = 0;
}
char *
verbalize(cnt, cmdstr, sgn)
int cnt;
char *cmdstr, *sgn;
{
if (cmdstr[0] == '\0')
cmdstr = (char *)Command;
if (sgn[0] == '\0') {
switch (cmdstr[0]) {
case 'c':
if (cmdstr[1] == 'h') {
viprintf((cnt == 1) ?
gettext("1 line changed") :
gettext("%d lines changed"), cnt);
break;
} else if (cmdstr[1] != 'o') {
goto Default;
}
case 't':
if (cmdstr[1] != '\0')
goto Default;
viprintf((cnt == 1) ? gettext("1 line copied") :
gettext("%d lines copied"), cnt);
break;
case 'd':
viprintf((cnt == 1) ? gettext("1 line deleted") :
gettext("%d lines deleted"), cnt);
break;
case 'j':
viprintf((cnt == 1) ? gettext("1 line joined") :
gettext("%d lines joined"), cnt);
break;
case 'm':
viprintf((cnt == 1) ? gettext("1 line moved") :
gettext("%d lines moved"), cnt);
break;
case 'p':
viprintf((cnt == 1) ? gettext("1 line put") :
gettext("%d lines put"), cnt);
break;
case 'y':
viprintf((cnt == 1) ? gettext("1 line yanked") :
gettext("%d lines yanked"), cnt);
break;
case '>':
viprintf((cnt == 1) ? gettext("1 line >>ed") :
gettext("%d lines >>ed"), cnt);
break;
case '=':
viprintf((cnt == 1) ? gettext("1 line =ed") :
gettext("%d lines =ed"), cnt);
break;
case '<':
viprintf((cnt == 1) ? gettext("1 line <<ed") :
gettext("%d lines <<ed"), cnt);
break;
default:
Default:
viprintf((cnt == 1) ? gettext("1 line") :
gettext("%d lines"), cnt);
break;
}
} else if (sgn[0] == 'm') {
viprintf((cnt == 1) ? gettext("1 more line") :
gettext("%d more lines"), cnt);
} else {
viprintf((cnt == 1) ? gettext("1 fewer line") :
gettext("%d fewer lines"), cnt);
}
return (NULL);
}
int
noteit(must)
bool must;
{
int sdl = destline, sdc = destcol;
if (notecnt < 1 || !must && state == VISUAL)
return (0);
splitw++;
if (WBOT == WECHO)
vmoveitup(1, 1);
vigoto(WECHO, 0);
verbalize(notecnt, notenam, notesgn);
vclreol();
notecnt = 0;
if (state != VISUAL)
vcnt = vcline = 0;
splitw = 0;
if (state == ONEOPEN || state == CRTOPEN)
vup1();
destline = sdl; destcol = sdc;
return (1);
}
int
beep(void)
{
if (flash_screen && value(vi_FLASH))
vputp(flash_screen, 0);
else if (bell)
vputp(bell, 0);
return (0);
}
int
map(c, maps, commch)
int c;
struct maps *maps;
unsigned char commch;
{
int d;
unsigned char *p, *q;
unsigned char b[10];
unsigned char *st;
#ifdef MDEBUG
if (trace)
fprintf(trace,"map(%c): ",c);
#endif
if (c==0)
return(0);
b[0] = c;
b[1] = 0;
for (d=0; d < MAXNOMACS && maps[d].mapto; d++) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"\ntry '%s', ",maps[d].cap);
#endif
if (p = maps[d].cap) {
for (q=b; *p; p++, q++) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"q->b[%d], ",q-b);
#endif
if (*q==0) {
if ((c=='#' ? peekkey() : fastpeekkey()) == 0) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"fpk=0: will return '%c'",c);
#endif
#ifdef MDEBUG
if (trace)
fprintf(trace, "Call macpush, b %d %d %d\n", b[0], b[1], b[2]);
#endif
macpush(&b[1],maps == arrows);
#ifdef MDEBUG
if (trace)
fprintf(trace, "return %d\n", c);
#endif
return(c);
}
*q = getkey();
q[1] = 0;
}
if (*p != *q)
goto contin;
}
macpush(maps[d].mapto,maps == arrows);
if ((maps == immacs)
&& strcmp(maps[d].descr, maps[d].cap)) {
switch (commch) {
case 'R':
if (!strcmp(maps[d].descr, "home"))
st = (unsigned char *)"R";
else
if (outcol == 0)
st = (unsigned char *)"R";
else
st = (unsigned char *)"lR";
break;
case 'i':
if (!strcmp(maps[d].descr, "home"))
st = (unsigned char *)"i";
else
if (outcol == 0)
st = (unsigned char *)"i";
else
st = (unsigned char *)"li";
break;
case 'a':
if (!strcmp(maps[d].descr, "home"))
st = (unsigned char *)"i";
else
st = (unsigned char *)"a";
break;
default:
st = (unsigned char *)"i";
}
if(strlen(vmacbuf) + strlen(st) > BUFSIZE)
error(value(vi_TERSE) ?
gettext("Macro too long") : gettext("Macro too long - maybe recursive?"));
else
strcat(vmacbuf, st);
}
c = getkey();
#ifdef MDEBUG
if (trace)
fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c);
#endif
return(c);
contin:;
}
}
#ifdef MDEBUG
if (trace)
fprintf(trace,"Fail: push(%s), return %c", &b[1], c);
#endif
macpush(&b[1],0);
return(c);
}
void
macpush(unsigned char *st, int canundo)
{
unsigned char tmpbuf[BUFSIZE];
if (st==0 || *st==0)
return;
#ifdef MDEBUG
if (trace)
fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo);
#endif
if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZE)
error(value(vi_TERSE) ? gettext("Macro too long") :
gettext("Macro too long - maybe recursive?"));
if (vmacp) {
strcpy(tmpbuf, vmacp);
if (!FIXUNDO)
canundo = 0;
}
strcpy(vmacbuf, st);
if (vmacp)
strcat(vmacbuf, tmpbuf);
vmacp = vmacbuf;
if (canundo) {
#ifdef notdef
otchng = tchng;
vsave();
saveall();
inopen = -1;
vundkind = VMANY;
#endif
vch_mac = VC_NOCHANGE;
}
}
#ifdef UNDOTRACE
visdump(s)
unsigned char *s;
{
int i;
if (!trace) return;
fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO);
fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero);
for (i=0; i<TUBELINES; i++)
if (vtube[i] && *vtube[i])
fprintf(trace, "%d: '%s'\n", i, vtube[i]);
tvliny();
}
vudump(s)
unsigned char *s;
{
line *p;
unsigned char savelb[1024];
if (!trace) return;
fprintf(trace, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2));
fprintf(trace, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
lineno(undadot), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol));
fprintf(trace, " [\n");
CP(savelb, linebuf);
fprintf(trace, "linebuf = '%s'\n", linebuf);
for (p=zero+1; p<=truedol; p++) {
fprintf(trace, "%o ", *p);
getaline(*p);
fprintf(trace, "'%s'\n", linebuf);
}
fprintf(trace, "]\n");
CP(linebuf, savelb);
}
#endif
int
vgetcnt(void)
{
int c, cnt;
cnt = 0;
for (;;) {
c = getkey();
if (!isdigit(c))
break;
cnt *= 10, cnt += c - '0';
}
ungetkey(c);
Xhadcnt = 1;
Xcnt = cnt;
return(cnt);
}
int
fastpeekkey(void)
{
void trapalarm();
int c;
CATCH
if (value(vi_TIMEOUT) && inopen >= 0) {
signal(SIGALRM, trapalarm);
setalarm();
}
c = peekkey();
cancelalarm();
ONERR
c = 0;
ENDCATCH
return(c);
}
static int ftfd;
struct requestbuf {
short time;
short signo;
};
void
setalarm(void)
{
unsigned char ftname[20];
struct requestbuf rb;
#ifdef FTIOCSET
if (ftfd == 0) {
strcpy(ftname, "/dev/ft0");
while (ftfd <= 0 && ftname[7] <= '~') {
ftfd = open(ftname, 0);
if (ftfd <= 0)
ftname[7] ++;
}
}
if (ftfd <= 0) {
alarm(1);
} else {
rb.time = 6;
rb.signo = SIGALRM;
ioctl(ftfd, FTIOCSET, &rb);
}
#else
alarm(1);
#endif
}
void
cancelalarm(void)
{
struct requestbuf rb;
#ifdef FTIOCSET
if (ftfd > 0) {
rb.time = 0;
rb.signo = SIGALRM;
ioctl(ftfd, FTIOCCANCEL, &rb);
}
#endif
alarm(0);
}
void trapalarm() {
alarm(0);
longjmp(vreslab,1);
}