849 lines · 14.1 KB · C
RawDownload
#include "sam.h" Header	h;uchar	indata[DATASIZE];uchar	outdata[2*DATASIZE+3];	/* room for overflow message */uchar	*inp;uchar	*outp;uchar	*outmsg = outdata;Posn	cmdpt;Posn	cmdptadv;Buffer	snarfbuf;int	waitack;int	outbuffered;int	tversion; int	inshort(void);long	inlong(void);vlong	invlong(void);int	inmesg(Tmesg); void	outshort(int);void	outlong(long);void	outvlong(vlong);void	outcopy(int, void*);void	outsend(void);void	outstart(Hmesg); void	setgenstr(File*, Posn, Posn); #ifdef DEBUGchar *hname[] = {	[Hversion]	"Hversion",	[Hbindname]	"Hbindname",	[Hcurrent]	"Hcurrent",	[Hnewname]	"Hnewname",	[Hmovname]	"Hmovname",	[Hgrow]		"Hgrow",	[Hcheck0]	"Hcheck0",	[Hcheck]	"Hcheck",	[Hunlock]	"Hunlock",	[Hdata]		"Hdata",	[Horigin]	"Horigin",	[Hunlockfile]	"Hunlockfile",	[Hsetdot]	"Hsetdot",	[Hgrowdata]	"Hgrowdata",	[Hmoveto]	"Hmoveto",	[Hclean]	"Hclean",	[Hdirty]	"Hdirty",	[Hcut]		"Hcut",	[Hsetpat]	"Hsetpat",	[Hdelname]	"Hdelname",	[Hclose]	"Hclose",	[Hsetsnarf]	"Hsetsnarf",	[Hsnarflen]	"Hsnarflen",	[Hack]		"Hack",	[Hexit]		"Hexit",	[Hplumb]		"Hplumb",}; char *tname[] = {	[Tversion]	"Tversion",	[Tstartcmdfile]	"Tstartcmdfile",	[Tcheck]	"Tcheck",	[Trequest]	"Trequest",	[Torigin]	"Torigin",	[Tstartfile]	"Tstartfile",	[Tworkfile]	"Tworkfile",	[Ttype]		"Ttype",	[Tcut]		"Tcut",	[Tpaste]	"Tpaste",	[Tsnarf]	"Tsnarf",	[Tstartnewfile]	"Tstartnewfile",	[Twrite]	"Twrite",	[Tclose]	"Tclose",	[Tlook]		"Tlook",	[Tsearch]	"Tsearch",	[Tsend]		"Tsend",	[Tdclick]	"Tdclick",	[Tstartsnarf]	"Tstartsnarf",	[Tsetsnarf]	"Tsetsnarf",	[Tack]		"Tack",	[Texit]		"Texit",	[Tplumb]		"Tplumb",}; voidjournal(int out, char *s){	static int fd = -1; 	if(fd < 0)		fd = create("/tmp/sam.out", 1, 0666L);	fprint(fd, "%s%s\n", out? "out: " : "in:  ", s);} voidjournaln(int out, long n){	char buf[32]; 	snprint(buf, sizeof(buf), "%ld", n);	journal(out, buf);} voidjournalv(int out, vlong v){	char buf[32]; 	sprint(buf, sizeof(buf), "%lld", v);	journal(out, buf);}#else#define	journal(a, b)#define journaln(a, b)#define journalv(a, b)#endif intrcvchar(void){	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++];} intrcv(void){	int 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:				indata[i] = 0;				state = count = 0;				return inmesg(h.type);			}			break;		}	return 0;} File *whichfile(int tag){	int i; 	for(i = 0; i<file.nused; i++)		if(file.filepptr[i]->tag==tag)			return file.filepptr[i];	hiccough((char *)0);	return 0;} intinmesg(Tmesg type){	Rune buf[1025];	char cbuf[64];	int i, m;	short s;	long l, l1;	vlong v;	File *f;	Posn p0, p1, p;	Range r;	String *str;	char *c, *wdir;	Rune *rp;	Plumbmsg *pm; 	if(type > TMAX)		panic("inmesg"); 	journal(0, tname[type]); 	inp = indata;	switch(type){	case -1:		panic("rcv error"); 	default:		fprint(2, "unknown type %d\n", type);		panic("rcv unknown"); 	case Tversion:		tversion = inshort();		journaln(0, tversion);		break; 	case Tstartcmdfile:		v = invlong();		/* for 64-bit pointers */		journalv(0, v);		Strdupl(&genstr, samname);		cmd = newfile();		cmd->unread = 0;		outTsv(Hbindname, cmd->tag, v);		outTs(Hcurrent, cmd->tag);		logsetname(cmd, &genstr);		cmd->rasp = listalloc('P');		cmd->mod = 0;		if(cmdstr.n){			loginsert(cmd, 0L, cmdstr.s, cmdstr.n);			Strdelete(&cmdstr, 0L, (Posn)cmdstr.n);		}		fileupdate(cmd, FALSE, TRUE);		outT0(Hunlock);		break; 	case Tcheck:		/* go through whichfile to check the tag */		outTs(Hcheck, whichfile(inshort())->tag);		break; 	case Trequest:		f = whichfile(inshort());		p0 = inlong();		p1 = p0+inshort();		journaln(0, p0);		journaln(0, p1-p0);		if(f->unread)			panic("Trequest: unread");		if(p1>f->nc)			p1 = f->nc;		if(p0>f->nc) /* can happen e.g. scrolling during command */			p0 = f->nc;		if(p0 == p1){			i = 0;			r.p1 = r.p2 = p0;		}else{			r = rdata(f->rasp, p0, p1-p0);			i = r.p2-r.p1;			bufread(f, r.p1, buf, i);		}		buf[i]=0;		outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1));		break; 	case Torigin:		s = inshort();		l = inlong();		l1 = inlong();		journaln(0, l1);		lookorigin(whichfile(s), l, l1);		break; 	case Tstartfile:		termlocked++;		f = whichfile(inshort());		if(!f->rasp)	/* this might be a duplicate message */			f->rasp = listalloc('P');		current(f);		outTsv(Hbindname, f->tag, invlong());	/* for 64-bit pointers */		outTs(Hcurrent, f->tag);		journaln(0, f->tag);		if(f->unread)			load(f);		else{			if(f->nc>0){				rgrow(f->rasp, 0L, f->nc);				outTsll(Hgrow, f->tag, 0L, f->nc);			}			outTs(Hcheck0, f->tag);			moveto(f, f->dot.r);		}		break; 	case Tworkfile:		i = inshort();		f = whichfile(i);		current(f);		f->dot.r.p1 = inlong();		f->dot.r.p2 = inlong();		f->tdot = f->dot.r;		journaln(0, i);		journaln(0, f->dot.r.p1);		journaln(0, f->dot.r.p2);		break; 	case Ttype:		f = whichfile(inshort());		p0 = inlong();		journaln(0, p0);		journal(0, (char*)inp);		str = tmpcstr((char*)inp);		i = str->n;		loginsert(f, p0, str->s, str->n);		if(fileupdate(f, FALSE, FALSE))			seq++;		if(f==cmd && p0==f->nc-i && i>0 && str->s[i-1]=='\n'){			freetmpstr(str);			termlocked++;			termcommand();		}else			freetmpstr(str);		f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */		f->tdot = f->dot.r;		break; 	case Tcut:		f = whichfile(inshort());		p0 = inlong();		p1 = inlong();		journaln(0, p0);		journaln(0, p1);		logdelete(f, p0, p1);		if(fileupdate(f, FALSE, FALSE))			seq++;		f->dot.r.p1 = f->dot.r.p2 = p0;		f->tdot = f->dot.r;   /* terminal knows the value of dot already */		break; 	case Tpaste:		f = whichfile(inshort());		p0 = inlong();		journaln(0, p0);		for(l=0; l<snarfbuf.nc; l+=m){			m = snarfbuf.nc-l;			if(m>BLOCKSIZE)				m = BLOCKSIZE;			bufread(&snarfbuf, l, genbuf, m);			loginsert(f, p0, tmprstr(genbuf, m)->s, m);		}		if(fileupdate(f, FALSE, TRUE))			seq++;		f->dot.r.p1 = p0;		f->dot.r.p2 = p0+snarfbuf.nc;		f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */		telldot(f);		outTs(Hunlockfile, f->tag);		break; 	case Tsnarf:		i = inshort();		p0 = inlong();		p1 = inlong();		snarf(whichfile(i), p0, p1, &snarfbuf, 0);		break; 	case Tstartnewfile:		v = invlong();		Strdupl(&genstr, empty);		f = newfile();		f->rasp = listalloc('P');		outTsv(Hbindname, f->tag, v);		logsetname(f, &genstr);		outTs(Hcurrent, f->tag);		current(f);		load(f);		break; 	case Twrite:		termlocked++;		i = inshort();		journaln(0, i);		f = whichfile(i);		addr.r.p1 = 0;		addr.r.p2 = f->nc;		if(f->name.s[0] == 0)			error(Enoname);		Strduplstr(&genstr, &f->name);		writef(f);		break; 	case Tclose:		termlocked++;		i = inshort();		journaln(0, i);		f = whichfile(i);		current(f);		trytoclose(f);		/* if trytoclose fails, will error out */		delete(f);		break; 	case Tlook:		f = whichfile(inshort());		termlocked++;		p0 = inlong();		p1 = inlong();		journaln(0, p0);		journaln(0, p1);		setgenstr(f, p0, p1);		for(l = 0; l<genstr.n; l++){			i = genstr.s[l];			if(utfrune(".*+?(|)\\[]^$", i)){				str = tmpcstr("\\");				Strinsert(&genstr, str, l++);				freetmpstr(str);			}		}		Straddc(&genstr, '\0');		nextmatch(f, &genstr, p1, 1);		moveto(f, sel.p[0]);		break; 	case Tsearch:		termlocked++;		if(curfile == 0)			error(Enofile);		if(lastpat.s[0] == 0)			panic("Tsearch");		nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1);		moveto(curfile, sel.p[0]);		break; 	case Tsend:		termlocked++;		inshort();	/* ignored */		p0 = inlong();		p1 = inlong();		setgenstr(cmd, p0, p1);		bufreset(&snarfbuf);		bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n);		outTl(Hsnarflen, genstr.n);		if(genstr.s[genstr.n-1] != '\n')			Straddc(&genstr, '\n');		loginsert(cmd, cmd->nc, genstr.s, genstr.n);		fileupdate(cmd, FALSE, TRUE);		cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;		telldot(cmd);		termcommand();		break; 	case Tdclick:		f = whichfile(inshort());		p1 = inlong();		doubleclick(f, p1);		f->tdot.p1 = f->tdot.p2 = p1;		telldot(f);		outTs(Hunlockfile, f->tag);		break; 	case Tstartsnarf:		if (snarfbuf.nc <= 0) {	/* nothing to export */			outTs(Hsetsnarf, 0);			break;		}		c = 0;		i = 0;		m = snarfbuf.nc;		if(m > SNARFSIZE) {			m = SNARFSIZE;			dprint("?warning: snarf buffer truncated\n");		}		rp = malloc(m*sizeof(Rune));		if(rp){			bufread(&snarfbuf, 0, rp, m);			c = Strtoc(tmprstr(rp, m));			free(rp);			i = strlen(c);		}		outTs(Hsetsnarf, i);		if(c){			Write(1, c, i);			free(c);		} else			dprint("snarf buffer too long\n");		break; 	case Tsetsnarf:		m = inshort();		if(m > SNARFSIZE)			error(Etoolong);		c = malloc(m+1);		if(c){

Lines 1–500 of 849.