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);
}