File:  [Research Unix] / researchv9 / jerq / src / sam / term / main.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:59 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#include "samterm.h"

Text	cmd;
uchar	*scratch;
long	nscralloc;
long	typeaddr=-1;
Texture	*cursor;
Flayer	*which=0;
Flayer	*work=0;
long	snarflen;
char	lock=1;		/* goes to 2 soon */
main()
{
	register got, scr;
	register Text *t;
	Rectangle r;
	register Flayer *nwhich;
	GCALLOC(100, &scratch);
	nscralloc=100;
	request(KBD|MOUSE|RCV);
	for(; wait(MOUSE) && !getr(&r); sleep(60))
		;
	setlock();
	flstart(Drect);
	rinit(&cmd.rasp);
	flnew(&cmd.l[0], gettext, 1, (char *)&cmd);
	flinit(&cmd.l[0], r, &defont);
	cmd.nwin=1;
	which=&cmd.l[0];
	cmd.tag=Untagged;
	startnewfile(Tstartcmdfile, &cmd);
	P->state&=~RESHAPED;
	for(;;got=wait(KBD|MOUSE|RCV)){
		if(lock<2 && (P->state&RESHAPED))
			reshape();
		if(got&RCV)
			rcv();
		if(which && (got&KBD))
			type(which);
		if((got&MOUSE) && lock<2){
			if(!ptinrect(mouse.xy, Drect))
				continue;
			nwhich=flwhich(mouse.xy);
			scr=which && ptinrect(mouse.xy, which->scroll);
			if(button1()){
				typeaddr=-1;
				if(nwhich){
					if(nwhich!=which)
						current(nwhich);
					else if(scr)
						scroll(which, 1);
					else{
						t=(Text *)which->user1;
						if(flselect(which)){
							outTsl(Tdclick, t->tag, which->p0);
							t->lock++;
						}else if(t!=&cmd)
							outcmd();
					}
				}
			}else if(button2() && which){
				typeaddr=-1;
				if(scr)
					scroll(which, 2);
				else
					menu2hit();
			}else if(button3()){
				typeaddr=-1;
				if(scr)
					scroll(which, 3);
				else
					menu3hit();
			}
		}
	}
}
reshape(){
	register i;
	flreshape(Drect);
	for(i=0; i<nname; i++)
		if(text[i])
			hcheck(text[i]->tag);
	P->state&=~(MOVED|RESHAPED);
}
current(nw)
	register Flayer *nw;
{
	register Text *t;
	if(which)
		flborder(which, 0);
	if(nw){
		typeaddr=-1;
		cursswitch(&deadmouse);
		flupfront(nw);
		flborder(nw, 1);
		buttons(Up);
		cursswitch(cursor);
		t=(Text *)nw->user1;
		t->front=nw-&t->l[0];
		if(t!=&cmd)
			work=nw;
	}
	which=nw;
}
close(l)
	register Flayer *l;
{
	register Text *t=(Text *)l->user1;
	register m;
	m=whichmenu(t->tag);
	if(m<0)
		return;
	cursswitch(&deadmouse);
	flclose(l);
	cursswitch(cursor);
	if(l==which){
		which=0;
		current(flwhich(Pt(0, 0)));
	}
	if(l==work)
		work=0;
	if(--t->nwin==0){
		rclear(&t->rasp);
		free((char *)t);
		text[m]=0;
	}else if(l==&t->l[t->front]){
		for(m=0; m<NL; m++)	/* find one; any one will do */
			if(t->l[m].textfn){
				t->front=m;
				return;
			}
		panic("close");
	}
}
Flayer *
findl(t)
	register Text *t;
{
	register i;
	for(i=0; i<NL; i++)
		if(t->l[i].textfn==0)
			return &t->l[i];
	return 0;
}
duplicate(l, r, f, close)
	register Flayer *l;
	Rectangle r;
	Font *f;
{
	register Text *t=(Text *)l->user1;
	register Flayer *nl=findl(t);
	if(nl){
		cursswitch(&deadmouse);
		flnew(nl, gettext, l->user0, (char *)t);
		flinit(nl, r, f);
		nl->origin=l->origin;
		flinsert(nl, (*l->textfn)(l, l->f.nchars), l->origin);
		flsetselect(nl, l->p0, l->p1);
		if(close){
			flclose(l);
			if(l==which)
				which=0;
		}else
			t->nwin++;
		current(nl);
		hcheck(t->tag);
	}
	cursswitch(cursor);
}
buttons(updown)
{
	while((button123()!=0) != updown)
		wait(MOUSE);
}
getr(rp)
	Rectangle *rp;
{
	Point p;
	Rectangle r;
	*rp=getrect3();
	if(rp->corner.x && rp->corner.x-rp->origin.x<=5 && rp->corner.y-rp->origin.y<=5){
		p=rp->origin;
		r=cmd.l[cmd.front].entire;
		*rp=Drect;
		if(cmd.nwin==1){
			if (p.y <= r.origin.y)
				rp->corner.y = r.origin.y;
			else if (p.y >= r.corner.y)
				rp->origin.y = r.corner.y;
			else if (p.x <= r.origin.x)
				rp->corner.x = r.origin.x;
			else if (p.x >= r.corner.x)
				rp->origin.x = r.corner.x;
		}
	}
	return rectclip(rp, Drect) &&
	   rp->corner.x-rp->origin.x>100 && rp->corner.y-rp->origin.y>40;
}
snarf(t, w)
	register Text *t;
{
	register Flayer *l=&t->l[w];
	if(l->p1>l->p0){
		snarflen=l->p1-l->p0;
		outTsll(Tsnarf, t->tag, l->p0, l->p1);
	}
}
cut(t, w, save)
	Text *t;
{
	register long p0, p1;
	if((p0=t->l[w].p0)==(p1=t->l[w].p1))
		return;
	if(save)
		snarf(t, w);
	outTsll(Tcut, t->tag, p0, p1);
	t->lock++;
	flsetselect(&t->l[w], p0, p0);
	hcut(t->tag, p0, p1-p0);
	hcheck(t->tag);
}
paste(t, w)
	Text *t;
{
	long p0=t->l[w].p0;
	if(snarflen){
		cut(t, w, 0);
		t->lock++;
		outTsl(Tpaste, t->tag, p0);
	}
}
strlen(s)
	register uchar *s;
{
	register n=0;
	while(*s++)
		n++;
	return n;
}
alnum(c)
	register c;
{
	return ('0'<=c && c<='9') || (c=='_') ||
	       ('a'<=c && c<='z') || ('A'<=c && c<='Z');
}
raspc(r, p)
	register Rasp *r;
	register long p;
{
	rload(r, p, p+1);
	return scratch[0];	/* will be 0 if p is in a hole */
}
long
ctlw(r, o, p)
	register Rasp *r;
	register long o, p;
{
	register c;
	if(--p<o)
		return o;
	if(raspc(r, p)=='\n')
		return p;
	for(; p>=o && !alnum(c=raspc(r, p)); --p)
		if(c=='\n')
			return p+1;
	for(; p>o && alnum(raspc(r, p-1)); --p)
		;
	return p>=o? p : o;
}
#define	SCROLLKEY	0xB2
#define	ESC		0x1B
type(l)	/* what a bloody mess this is */
	register Flayer *l;
{
	Text *t=(Text *)l->user1;
	uchar buf[100];
	register uchar *p=buf;
	register c, backspacing=0;
	register long a;
	int scrollkey=qpeekc(&P->kbdqueue)==SCROLLKEY;	/* ICK */
	if(lock || t->lock)
		return;
	if((a=l->p0)!=l->p1 && !scrollkey){
		cut(t, t->front, 1);
		return;	/* it may now be locked */
	}
	while(!backspacing && (c=kbdchar())>0 && c!=SCROLLKEY && c!=ESC)
		switch(c&=0x7F){
		case '\027':
		case '\b':
			backspacing=1;
			break;
		case '\r':
			c='\n';
		default:
			*p++=c;
			break;
		}
	if(p>buf){
		if(typeaddr<0)
			typeaddr=a;
		*p=0;
		hgrow(t->tag, a, (long)(p-buf), 0);
		t->lock++;	/* pretend we Trequest'ed */
		hdata(t->tag, a, buf, (int)(p-buf));
		if(t==&cmd && a+(p-buf)==t->rasp.nbytes && p[-1]=='\n'){
			setlock();
			outcmd();
			outTslS(Ttype, t->tag, a, buf);
				typeaddr=-1;
		}else
			outTslS(Ttype, t->tag, a, buf);
		l->p0=l->p1=(a+=p-buf);
		center(l, a);
	}
	if(c==SCROLLKEY)
		center(l, l->origin+l->f.nchars+1);
		/* backspacing immediately after outcmd(): sorry */
	else if(!lock && backspacing && l->f.p0>0){
		l->p1=a;
		l->p0=c=='\b'? a-1 : ctlw(&t->rasp, l->origin, a);
		cut(t, t->front, 0);
		if(typeaddr>=l->p0)
			typeaddr=l->p0;
	}else{
		if(c==ESC && typeaddr>=0){
			l->p0=typeaddr, l->p1=a;
			typeaddr=-1;
		}
		for(l=t->l; l<&t->l[NL]; l++)
			if(l->textfn)
				flsetselect(l, l->p0, l->p1);
	}
}
center(l, a)
	register Flayer *l;
	register long a;
{
	register Text *t=(Text *)l->user1;
	if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){
		if(a>t->rasp.nbytes)
			a=t->rasp.nbytes;
		outTsll(Torigin, t->tag, a, 2L);
		outTs(Tunlockfile, t->tag);
		t->lock++;
		return 1;
	}
	return 0;
}
outcmd(){
	if(work)
		outTsll(Tworkfile, ((Text *)work->user1)->tag, work->p0, work->p1);
}
panic(s)
	char *s;
{
	rectf(D, Drect, F_XOR);
	string(&defont, s, D, add(Drect.origin, Pt(4, 4)), F_STORE);
	P->state|=1024;	/* ZOMBIE */
	request(0);
}
strgrow(s, n, want)	/* can always toss the old data when called */
	uchar **s;
	long *n;
{
	if(*n>=want)
		return;
	gcfree(*s);
	GCALLOC(want, s);
	*n=want;
}
uchar **
gettext(l, n)
	register Flayer *l;
	long n;
{
	register Text *t=(Text *)l->user1;
	rload(&t->rasp, l->origin, l->origin+n);
	return &scratch;
}
long
scrtotal(l)
	Flayer *l;
{
	return ((Text *)l->user1)->rasp.nbytes;
}
uchar *
ALLOC(n)
{
	register uchar *p=(uchar *)alloc(n);
	if(p==0)
		panic("ALLOC");
	return p;
}
GCALLOC(n, w)
	uchar **w;
{
	register i, j;
	register Text *t;
	register Flayer *l;
	if(gcalloc((unsigned long)n, (char **)w)==0){
		for(i=0; i<nname; i++)
			if(t=text[i]){
				/*raspcleanup(t); - uncache worthless stuff*/
				/*rclean(&t->rasp); (Can we do this if !t->lock?) */
				for(j=0,l=&t->l[0]; j<NL; j++,l++)
					if(l->textfn && l->visible==Some && l->f.b){
						bfree(l->f.b);
						l->f.b=0;
					}
			}
		if(gcalloc((unsigned long)n, w)==0)
			panic("GCALLOC");
	}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.