Interdata_v6/usr/source/chicago/em2.c
#
/* This is the second and final segment of the QMC Unix Editor - em */
#define EOF -1
#define LBSIZE 512
#define SIGHUP 1
#define SIGINTR 2
#define SIGQUIT 3
#define UNIXBUFL 100
#define error errfunc() /*** was 'goto errlab' ***/
#define TABSET 7 /* this should be determined dynamically */
#define RAW 040
#define ECHO 010
#define OPEN '/'
#define BELL 07
#define ESCAPE 033
#define SPACE 040
#define BACKSL 0134
#define RUBOUT 0177
#define CTRLA 01
#define CTRLB 02
#define CTRLC 03
#define CTRLD 04
#define CTRLE 05
#define CTRLF 06
#define CTRLH 010
#define CTRLI 011
#define CTRLQ 021
#define CTRLR 022
#define CTRLS 023
#define CTRLV 026
#define CTRLW 027
#define CTRLX 030
#define CTRLZ 032
#define ITT 0100000
extern char *linebp, *loc2, linebuf[LBSIZE], genbuf[LBSIZE],
unixbuffer[UNIXBUFL];
extern int onquit,onhup, peekc;
extern int *zero, *addr1, *addr2;
extern int *errlab;
extern int lastc;
int margin LBSIZE - 40;
int oflag;
char *threshold, *savethresh;
char *lnp,*gnp,*brp;
int savetty, tty[3];
op(inglob)
{ register *a1;
register char *lp, *sp;
int seof, ch;
int t, nl;
extern getopen(), getnil();
threshold = genbuf + margin;
savethresh = 0;
switch (ch = peekc = getchar()) {
case BACKSL:
t = 1;
delete();
addr2 = addr1;
break;
case ';':
case '+':
t = 0;
break;
case '-':
t =1;
break;
default:
goto normal;
}
peekc = 0;
if(addr1 != addr2) error;
oflag = 0;
append(getnil, addr2 - t);
addr1 = addr2 =- (t-1);
setdot();
nonzero();
normal:
if(addr1 == zero) error;
if ((seof = getchar()) == '\n') { loc2 = linebuf-1;
seof = 0;}
else compile(seof);
setraw(); /* terminal into raw mode*/
for ( a1 = addr1; a1 <= addr2; a1++) {
if (seof) {if (execute(0,a1) == 0) continue;}
else getline(*a1);
puts("\\\r");
lp = linebuf;
sp = genbuf;
inglob =| 01;
while (lp < loc2){ putch(*lp); *sp++ = *lp++; }
lnp = lp;
gnp = sp;
oflag = gopen(); /* open the current line */
*a1 = putline(); /* write revised line */
nl = append( getopen,a1);
a1 =+ nl;
addr2 =+ nl;
}
setcook(); /* terminal in cook mode */
putchar('\n');
if (inglob == 0) { putchar('?'); error;}
}
getnil()
{
if(oflag == EOF) return EOF;
linebuf[0] = '\0';
oflag = EOF;
return 0;
}
setraw()
{
if(gtty(0,tty) == -1) error;
savetty = tty[2];
tty[2] =| RAW;
stty(0, tty);
}
setcook()
{
tty[2] = savetty;
stty(0, tty);
}
inword(c)
{
if (c < '0') return(0);
if (c <= '9') return(1);
c =& 0137;
if (c < 'A') return(0);
if (c <= 'Z') return(1);
return(0);
}
rescan()
{ register char *lp, *sp;
if(savethresh) { threshold = savethresh; savethresh = 0; }
lp = linebuf;
sp = genbuf;
while(*lp++ = *sp++) if(lp>linebuf+LBSIZE) {
*(--lp) = 0;
return 0;
}
}
gopen()
/*leaves revised line in linebuf,
returns 0 if more to follow, EOF if last line */
{ register char *lp, *sp, *rp;
register char *br, *pr;
int ch, tabs;
int retcode, savint, pid, rpid;
lp = lnp;
sp = gnp;
tabs = 0;
for (rp = genbuf; rp < sp; rp++) if (*rp == CTRLI) tabs =+ TABSET;
for(;;){
switch (ch = getchar()) {
case CTRLD:
case ESCAPE: /* close the line (see case '\n' also) */
close:
putb(lp);
while(*sp++ = *lp++);
rescan();
return(EOF);
case CTRLA: /* verify line */
verify: puts("\\\r");
putch('\r');
*sp = '\0';
putb(genbuf);
continue;
case CTRLB: /* back a word */
if(sp == genbuf) goto backquery;
while((*(--lp) = *(--sp)) == SPACE)
if(sp < genbuf) goto out;
if(inword(*sp)) {
while(inword((*(--lp) = *(--sp))))
if(sp < genbuf) goto out;
if(*sp == SPACE)
while((*(--lp) = *(--sp)) == SPACE)
if(sp < genbuf) goto out;
}
else while(sp >= genbuf && !inword(*sp))
if((*lp-- = *sp--) == CTRLI) tabs =- TABSET;
out: sp++;
lp++;
goto verify;
case CTRLC:
case CTRLQ: /* forward one char */
if(*lp == 0) goto backquery;
putch(*lp);
forward:
if(*lp == SPACE && sp + tabs > threshold) {
putch('\r');
ch = '\n'; putch(ch);
lp++;
*sp++ = ch;
br = sp;
break;
}
if(*lp == CTRLI) tabs =+ TABSET;
*sp++ = *lp++; /* one character */
if(sp + tabs == threshold) putch(BELL);
continue;
case CTRLF:
/* delete forward */
while(*lp++);
lp--;
goto verify;
case CTRLE:
putb(lp);
goto verify;
case CTRLH: help(); goto verify;
case CTRLR: /* margin release */
if(threshold-genbuf<LBSIZE-40) {
savethresh = threshold;
threshold = genbuf+LBSIZE-40;
}
else goto backquery;
continue;
case CTRLS: /* re-set to start of line */
while(*sp++ = *lp++);
rescan();
lp = linebuf; sp = genbuf;
tabs = 0;
goto verify;
case CTRLV: /* verify spelling */
/***
rp = sp;
pr = unixbuffer+UNIXBUFL-2;
*pr = 0;
while(*(--rp) == SPACE);
while(inword(*rp) && rp >= genbuf)
*(--pr) = *rp--;
if(*pr == 0) goto backquery;
puts("!!");
setcook();
if((pid = fork()) == 0)
{signal(SIGHUP, onhup);
signal(SIGQUIT, onquit);
execl("/bin/spell", "spell", pr, 0);
***/
puts("sorry, can't spell today");
/***
exit();
}
savint = signal(SIGINTR,1);
while((rpid = wait(&retcode)) != pid
&& rpid != -1);
signal(SIGINTR, savint);
setraw();
puts("!!");
***/
goto verify;
case CTRLW: /* forward one word */
if(*lp == '\0') goto backquery;
while(*lp == SPACE)
putch(*sp++ = *lp++);
if(inword(*lp)) {
while(inword(*lp)) {
putch(*sp++ = *lp++);
if(sp+tabs==threshold) putch(BELL);
}
if(*lp == SPACE) {
if(sp+tabs>threshold) {
ch = '\n';
lp++;
*sp++ = ch;
br = sp;
putch('\r');
putch('\n');
}
if(*lp == SPACE)
while(*(lp+1) == SPACE)
putch(*sp++ = *lp++);
}
}
else while(*lp && !inword(*lp)) {
if(*lp == CTRLI) tabs =+ TABSET;
putch(*sp++ = *lp++);
if(sp+tabs==threshold) putch(BELL);
}
break;
case CTRLZ: /* delete a word */
if(sp == genbuf) goto backquery;
while(*(--sp) == SPACE) if(sp < genbuf) goto zout;
if(inword(*sp)) {
while(inword(*(--sp)))
if(sp < genbuf) goto zout;
if(*sp == SPACE)
while(*(--sp) == SPACE)
if(sp < genbuf) goto zout;
}
else while(sp >= genbuf && !inword(*sp))
if(*sp-- == CTRLI) tabs =- TABSET;
zout: sp++;
goto verify;
case '@': /*delete displayed line */
/* delete backward */
sp = genbuf;
tabs = 0;
goto verify;
case RUBOUT:
lastc = ('\n');
puts("\\\r");
setcook();
error;
case CTRLX:
putch('#');
case '#':
if( sp == genbuf) goto backquery;
if(*(--sp) == CTRLI) tabs =- TABSET;
if( ch == CTRLX) goto verify;
continue;
case '\n':
case '\r': /* split line, actually handled at
end of switch block */
ch = '\n';
*sp++ = ch;
br = sp;
break;
case BACKSL: /* special symbols */
switch (ch = peekc = getchar()) {
case '(': ch = '{'; peekc = 0; break;
case ')': ch = '}'; peekc = 0; break;
case '!': ch = '|'; peekc = 0; break;
case '^': ch = '~'; peekc = 0; break;
case '\'': ch = '`'; peekc = 0; break;
case BACKSL:
case '#':
case '@': peekc = 0; break;
default: if(ch >= 'a' && ch <= 'z') {
peekc = 0; ch =- 040;}
else {
*(--lp) = BACKSL;
goto forward;
}
}
default: *(--lp) = ch;
goto forward;
}
if (ch == '\n') { /* split line */
if(*(br-1) != '\n') puts("!!"); /*debugging only */
lnp = sp;
while(*sp++ = *lp++); /*move the rest over */
brp = linebuf +(br - genbuf);
lnp = linebuf + (lnp - br);
rescan();
*(brp-1) ='\0';
return(0);
}
else continue;
backquery: putch(BELL); /***/
} /* end of forloop block */
} /* end of gopen */
getopen() /* calls gopen, deals with multiple lines etc. */
{ register char *lp, *sp;
if (oflag == EOF) return EOF;
/* otherwise, multiple lines */
lp = linebuf;
sp = brp;
while(*lp++ = *sp++); /*move it down */
sp = genbuf;
lp = linebuf;
while (lp < lnp) *sp++ = *lp++;
gnp = sp;
/* should check whether empty line returned */
oflag = gopen();
return 0;
}
struct { char byte[]; };
putch(ch)
{
write(1, &ch.byte[3], 1);
}
putb(ptr) char *ptr; /*display string */
{ register char *p;
p = ptr;
if(*p == '\0') return;
while(*(++p));
write(1,ptr,p-ptr);
}
help()
{ puts("\n");
puts(" ^A display Again ^Q next character");
puts(" ^B backup word ^R Release margin");
puts(" ESCAPE ^S re-scan from Start");
puts(" or ^D close line and exit ^V verify spelling");
puts(" ^E display to End ^W next Word");
puts(" ^F delete line Forward ^Z delete word");
puts(" ^H Help # or ^X delete character");
puts(" RUBOUT exit unchanged @ delete line backward\n");
puts(" Other characters (including RETURN) inserted as typed");
}