V9/jtools/src/sam/mesg.c
#include "sam.h"
Header h;
uchar indata[DATASIZE];
uchar outdata[DATASIZE+3];
short outcount;
long inlong();
Posn cmdpt;
Posn cmdptadv;
Buffer *snarfbuf;
log(out, s)
char *s;
{
static fd=0;
if(fd<=0)
fd=creat("/usr/rob/sam.out", 0666);
fprint(fd, "%s%s\n", out? "out: " : "in: ", s);
}
logn(out, n)
int n;
{
char buf[32];
sprint(buf, "%d", n);
log(out, buf);
}
#ifdef DIST
#define log(a, b)
#define logn(a, b)
#endif
rcvchar(){
static uchar buf[64];
static i, nleft=0;
if(nleft<=0){
nleft=read(0, (char *)buf, sizeof buf);
if(nleft<=0)
return -1;
i=0;
}
--nleft;
return buf[i++];
}
rcv(){
register c;
static state=0;
static count=0;
static i=0;
while((c=rcvchar())!=-1)
switch(state){
case 0:
h.type=c;
state++;
break;
case 1:
h.count0=c;
state++;
break;
case 2:
h.count1=c;
count=h.count0|(h.count1<<8);
i=0;
if(count>DATASIZE)
panic("count>DATASIZE");
if(count==0)
goto zerocount;
state++;
break;
case 3:
indata[i++]=c;
if(i==count){
zerocount:
state=count=0;
return inmesg(h.type);
}
break;
}
return 0;
}
File *
whichfile(tag)
register tag;
{
register i;
for(i=0; i<file.nused; i++)
if(file.ptr[i]->tag==tag)
return file.ptr[i];
hiccough((char *)0);
/*NOTREACHED*/
return 0;
}
inmesg(type)
Tmesg type;
{
uchar buf[1025];
register i, m;
long l;
register File *f;
register Posn p0, p1;
Range r;
switch(type){
case -1:
panic("rcv error");
default:
panic("rcv unknown");
case Tcut:
log(0, "Tcut");
f=whichfile(inshort(0));
p0=inlong(2);
p1=inlong(6);
logn(0, (int)p0);
logn(0, (int)p1);
Fdelete(f, p0, p1);
if(Fupdate(f, FALSE, FALSE))
modnum++;
f->dot.r.p1=f->dot.r.p2=p0;
f->tdot=f->dot.r; /* terminal knows the value of dot already */
break;
case Tpaste:
log(0, "Tpaste");
f=whichfile(inshort(0));
p0=inlong(2);
logn(0, (int)p0);
for(l=0; l<snarfbuf->nbytes; l+=m){
m=snarfbuf->nbytes-l;
if(m>BLOCKSIZE)
m=BLOCKSIZE;
Bread(snarfbuf, genbuf, m, l);
Finsert(f, tempstr(genbuf, m), p0);
}
if(Fupdate(f, FALSE, TRUE))
modnum++;
f->dot.r.p1=p0;
f->dot.r.p2=p0+snarfbuf->nbytes;
f->tdot.p1= -1; /* force telldot to tell (arguably a BUG) */
telldot(f);
outTs(Hunlockfile, f->tag);
break;
case Tsnarf:
log(0, "Tsnarf");
snarf(whichfile(inshort(0)), inlong(2), inlong(6));
break;
case Ttype:
log(0, "Ttype");
f=whichfile(inshort(0));
p0=inlong(2);
logn(0, (int)p0);
log(0, (char *)indata+6);
i=strlen(indata+6);
Finsert(f, tempstr(indata+6, i), p0);
if(Fupdate(f, FALSE, FALSE))
modnum++;
if(f==cmd && p0==f->nbytes-i && i>0 && indata[i+6-1]=='\n')
termcommand();
f->dot.r.p1=f->dot.r.p2=p0+i; /* terminal knows this already */
f->tdot=f->dot.r;
break;
case Tstartfile:
log(0, "Tstartfile");
f=whichfile(inshort(0));
if(!f->rasp) /* this might be a duplicate message */
f->rasp=new(List, 1);
current(f);
outTsl(Hbindname, f->tag, inlong(2));
outTs(Hcurrent, f->tag);
logn(0, f->tag);
if(f->state==Unread)
load(f);
else{
if(f->nbytes>0){
rgrow(f->rasp, 0L, f->nbytes);
outTsll(Hgrow, f->tag, 0L, f->nbytes);
}
outTs(Hcheck0, f->tag);
moveto(f, f->dot.r);
}
break;
case Tstartcmdfile:
log(0, "Tstartcmdfile");
l=inlong(0);
strdup(&genstr, (uchar *)"~~sam~~");
cmd=newfile();
outTsl(Hbindname, cmd->tag, l);
outTs(Hcurrent, cmd->tag);
Fsetname(cmd);
cmd->rasp=new(List, 1);
cmd->state=Clean;
if(cmdstr.n){
Finsert(cmd, &cmdstr, 0L);
strdelete(&cmdstr, 0L, (Posn)cmdstr.n);
}
Fupdate(cmd, FALSE, TRUE);
outT0(Hunlock);
break;
case Tstartnewfile:
log(0, "Tstartnewfile");
l=inlong(0);
strdup(&genstr, (uchar *)"");
f=newfile();
f->rasp=new(List, 1);
outTsl(Hbindname, f->tag, l);
Fsetname(f);
outTs(Hcurrent, f->tag);
current(f);
load(f);
break;
case Trequest:
log(0, "Trequest");
f=whichfile(inshort(0));
p0=inlong(2);
logn(0, (int)p0);
logn(0, inshort(6));
if(f->state==Unread)
panic("Trequest: unread");
p1=p0+inshort(6);
if(p0>f->nbytes){ /* can happen e.g. scrolling during command */
buf[0]=0;
r.p1=r.p2=f->nbytes;
}else{
if(p1>f->nbytes)
p1=f->nbytes;
r=rdata(f->rasp, p0, p1-p0);
i=r.p2-r.p1;
if(Fchars(f, buf, r.p1, r.p2)!=i)
panic("Trequest 2");
buf[i]=0;
}
outTslS(Hdata, f->tag, r.p1, buf);
break;
case Twrite:
log(0, "Twrite");
f=whichfile(inshort(0));
addr.r.p1=0;
addr.r.p2=f->nbytes;
if(f->name.s[0]==0)
error(Enoname);
strdupstr(&genstr, &f->name);
writef(f);
break;
case Tworkfile:
log(0, "Tworkfile");
logn(0, (int)inlong(2));
logn(0, (int)inlong(6));
f=whichfile(inshort(0));
current(f);
f->dot.r.p1=inlong(2);
f->dot.r.p2=inlong(6);
f->tdot=f->dot.r;
break;
case Tcheck:
log(0, "Tcheck");
/* go through whichfile to check the tag */
outTs(Hcheck, whichfile(inshort(0))->tag);
break;
case Torigin:
log(0, "Torigin");
logn(0, (int)inlong(6));
lookorigin(whichfile(inshort(0)), inlong(2), inlong(6));
break;
case Tclose:
log(0, "Tclose");
f=whichfile(inshort(0));
current(f);
trytoclose(f);
break;
case Tlook:
log(0, "Tlook");
f=whichfile(inshort(0));
p0=inlong(2);
p1=inlong(6);
setgenstr(f, p0, p1);
for(l=0; l<genstr.n; l++){
i=genstr.s[l];
if(i && !('a'<=i && i<='z') && !('A'<=i && i<='Z'))
strinsert(&genstr, tempstr((uchar *)"\\", 1), l++);
}
straddc(&genstr, '\0');
{Regexp poot;
poot.text=genstr;
nextmatch(f, &poot, p1, 1); /* BUGGERED */
}
moveto(f, sel);
break;
case Tsearch:
log(0, "Tsearch");
if(curfile==0)
error(Enofile);
if(lastpat.n==0)
panic("Tsearch");
{Regexp poot;
poot.text=lastpat;
nextmatch(curfile, &poot, curfile->dot.r.p2, 1); /* BUGGERED */
}
moveto(curfile, sel);
break;
case Tsend:
log(0, "Tsend");
p0=inlong(2);
p1=inlong(6);
setgenstr(cmd, p0, p1);
Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
Binsert(snarfbuf, &genstr, (Posn)0);
outTl(Hsnarflen, (long)genstr.n);
if(genstr.s[genstr.n-1]!='\n')
straddc(&genstr, '\n');
Fdelete(cmd, cmdpt, cmd->nbytes);
Finsert(cmd, &genstr, cmd->nbytes);
Fupdate(cmd, FALSE, TRUE);
cmd->dot.r.p1=cmd->dot.r.p2=cmd->nbytes;
telldot(cmd);
termcommand();
break;
case Tunlockfile:
log(0, "Tunlockfile");
outTs(Hunlockfile, whichfile(inshort(0))->tag);
break;
case Tstartsnarf:
log(0, "Tstartsnarf");
if(snarfbuf->nbytes>BLOCKSIZE)
error(Etoolong);
outTs(Hsetsnarf, (int)snarfbuf->nbytes);
Bread(snarfbuf, genbuf, (int)snarfbuf->nbytes, (Posn)0);
Write(1, genbuf, (int)snarfbuf->nbytes);
break;
case Tsetsnarf:
log(0, "Tsetsnarf");
m=inshort(0);
if(m>BLOCKSIZE)
error(Etoolong);
for(i=0; i<m; i++)
genbuf[i]=rcvchar();
Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
Binsert(snarfbuf, tempstr(genbuf, m), (Posn)0);
outT0(Hunlock);
break;
case Tdclick:
log(0, "Tdclick");
f=whichfile(inshort(0));
p1=inlong(2);
doubleclick(f, p1);
f->tdot.p1=f->tdot.p2=p1;
telldot(f);
outTs(Hunlockfile, f->tag);
break;
case Texit:
log(0, "Texit");
return FALSE;
}
return TRUE;
}
snarf(f, p1, p2)
register File *f;
register Posn p1, p2;
{
register Posn l;
register i;
if(p1==p2)
return;
Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
/* Stage through genbuf to avoid compaction problems */
for(l=p1; l<p2; l+=i){
i=p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
Fchars(f, genbuf, l, l+i);
Binsert(snarfbuf, tempstr(genbuf, i), snarfbuf->nbytes);
}
}
inshort(n)
{
return indata[n]|(indata[n+1]<<8);
}
long
inlong(n)
{
return indata[n]|(indata[n+1]<<8)|
((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
}
setgenstr(f, p0, p1)
register File *f;
register Posn p0, p1;
{
if(p0!=p1){
if(p1-p0>=TBLOCKSIZE)
error(Etoolong);
strinsure(&genstr, p1-p0);
genstr.n=p1-p0;
Fchars(f, genstr.s, p0, p1);
}else{
if(snarfbuf->nbytes==0)
error(Eempty);
if(snarfbuf->nbytes>TBLOCKSIZE)
error(Etoolong);
Bread(snarfbuf, genbuf, (int)snarfbuf->nbytes, (Posn)0);
strinsure(&genstr, snarfbuf->nbytes);
bcopy(genbuf, genbuf+snarfbuf->nbytes, genstr.s, 1);
genstr.n=snarfbuf->nbytes;
}
}
outT0(type)
Hmesg type;
{
outstart(type);
outsend();
}
outTl(type, l)
Hmesg type;
long l;
{
outstart(type);
outlong(l);
outsend();
}
outTs(type, s)
Hmesg type;
{
outstart(type);
logn(1, s);
outshort(s);
outsend();
}
outTsS(type, s1, s)
Hmesg type;
uchar *s;
{
outstart(type);
outshort(s1);
outcopy(strlen(s)+1, s);
log(1, (char *)s);
outsend();
}
outTssl(type, s1, s2, l)
Hmesg type;
long l;
{
outstart(type);
outshort(s1);
outshort(s2);
outlong(l);
outsend();
}
outTslS(type, s1, l1, s)
Hmesg type;
Posn l1;
uchar *s;
{
char buf[100];
register i;
outstart(type);
outshort(s1);
outlong(l1);
logn(1, (int)l1);
outcopy(strlen(s)+1, s);
i=strlen(s);
if(i>99)
i=99;
buf[i]=0;
while(--i>=0)
buf[i]=s[i];
log(1, buf);
outsend();
}
outTS(type, s)
Hmesg type;
uchar *s;
{
char buf[100];
register i;
outstart(type);
outcopy(strlen(s)+1, s);
i=strlen(s);
if(i>99)
i=99;
buf[i]=0;
while(--i>=0)
buf[i]=s[i];
log(1, buf);
outsend();
}
outTsllS(type, s1, l1, l2, s)
Hmesg type;
Posn l1, l2;
uchar *s;
{
char buf[100];
register i;
outstart(type);
outshort(s1);
outlong(l1);
outlong(l2);
logn(1, (int)l1);
logn(1, (int)l2);
outcopy(strlen(s)+1, s);
i=strlen(s);
if(i>99)
i=99;
buf[i]=0;
while(--i>=0)
buf[i]=s[i];
log(1, buf);
outsend();
}
outTsll(type, s, l1, l2)
Hmesg type;
Posn l1, l2;
{
outstart(type);
outshort(s);
outlong(l1);
outlong(l2);
logn(1, (int)l1);
logn(1, (int)l2);
outsend();
}
outTsl(type, s, l)
Hmesg type;
Posn l;
{
outstart(type);
outshort(s);
outlong(l);
logn(1, (int)l);
outsend();
}
outstart(type)
Hmesg type;
{
switch(type){
case Hnewname:
log(1, "Hnewname");
break;
case Hdelname:
log(1, "Hdelname");
break;
case Hmovname:
log(1, "Hmovname");
break;
case Hbindname:
log(1, "Hbindname");
break;
case Hcurrent:
log(1, "Hcurrent");
break;
case Hgrow:
log(1, "Hgrow");
break;
case Hdata:
log(1, "Hdata");
break;
case Hgrowdata:
log(1, "Hgrowdata");
break;
case Hcut:
log(1, "Hcut");
break;
case Hclean:
log(1, "Hclean");
break;
case Hdirty:
log(1, "Hdirty");
break;
case Hcheck0:
log(1, "Hcheck0");
break;
case Hcheck:
log(1, "Hcheck");
break;
case Hmoveto:
log(1, "Hmoveto");
break;
case Hsetdot:
log(1, "Hsetdot");
break;
case Horigin:
log(1, "Horigin");
break;
case Hclose:
log(1, "Hclose");
break;
case Hunlock:
log(1, "Hunlock");
break;
case Hsetpat:
log(1, "Hsetpat");
break;
case Hsetsnarf:
log(1, "Hsetsnarf");
break;
case Hsnarflen:
log(1, "Hsnarflen");
break;
case Hexit:
log(1, "Hexit");
break;
}
outdata[0]=type;
outcount=0;
}
outcopy(count, data)
register uchar *data;
{
while(count--)
outdata[3+outcount++]= *data++;
}
outshort(s)
{
uchar buf[2];
buf[0]=s;
buf[1]=s>>8;
outcopy(2, buf);
}
outlong(l)
long l;
{
uchar buf[4];
buf[0]=l;
buf[1]=l>>8;
buf[2]=l>>16;
buf[3]=l>>24;
outcopy(4, buf);
}
outsend()
{
if(outcount>DATASIZE)
panic("outcount>DATASIZE");
outdata[1]=outcount;
outdata[2]=outcount>>8;
Write(1, outdata, outcount+3);
}