675 lines · 11.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include "flayer.h"#include "samterm.h" int	mainstacksize = 16*1024; Text	cmd;Rune	*scratch;long	nscralloc;Cursor	*cursor;Flayer	*which = 0;Flayer	*work = 0;long	snarflen;long	typestart = -1;long	typeend = -1;long	typeesc = -1;long	modified = 0;		/* strange lookahead for menus */char	hostlock = 1;char	hasunlocked = 0;int	maxtab = 8;int	autoindent; voidthreadmain(int argc, char *argv[]){	int i, got, scr;	Text *t;	Rectangle r;	Flayer *nwhich; 	getscreen(argc, argv);	iconinit();	initio();	scratch = alloc(100*RUNESIZE);	nscralloc = 100;	r = screen->r;	r.max.y = r.min.y+Dy(r)/5;	flstart(screen->clipr);	rinit(&cmd.rasp);	flnew(&cmd.l[0], gettext, 1, &cmd);	flinit(&cmd.l[0], r, font, cmdcols);	cmd.nwin = 1;	which = &cmd.l[0];	cmd.tag = Untagged;	outTs(Tversion, VERSION);	startnewfile(Tstartcmdfile, &cmd); 	got = 0;	for(;;got = waitforio()){		if(hasunlocked && RESIZED())			resize();		if(got&(1<<RHost))			rcv();		if(got&(1<<RPlumb)){			for(i=0; cmd.l[i].textfn==0; i++)				;			current(&cmd.l[i]);			flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes);			type(which, RPlumb);		}		if(got&(1<<RKeyboard))			if(which)				type(which, RKeyboard);			else				kbdblock();		if(got&(1<<RMouse)){			if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){				mouseunblock();				continue;			}			nwhich = flwhich(mousep->xy);			scr = which && ptinrect(mousep->xy, which->scroll);			if(mousep->buttons)				flushtyping(1);			if(mousep->buttons&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((mousep->buttons&2) && which){				if(scr)					scroll(which, 2);				else					menu2hit();			}else if((mousep->buttons&4)){				if(scr)					scroll(which, 3);				else					menu3hit();			}			mouseunblock();		}	}}  voidresize(void){	int i; 	flresize(screen->clipr);	for(i = 0; i<nname; i++)		if(text[i])			hcheck(text[i]->tag);} voidcurrent(Flayer *nw){	Text *t; 	if(which)		flborder(which, 0);	if(nw){		flushtyping(1);		flupfront(nw);		flborder(nw, 1);		buttons(Up);		t = (Text *)nw->user1;		t->front = nw-&t->l[0];		if(t != &cmd)			work = nw;	}	which = nw;} voidcloseup(Flayer *l){	Text *t=(Text *)l->user1;	int m; 	m = whichmenu(t->tag);	if(m < 0)		return;	flclose(l);	if(l == which){		which = 0;		current(flwhich(Pt(0, 0)));	}	if(l == work)		work = 0;	if(--t->nwin == 0){		rclear(&t->rasp);		free((uchar *)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(Text *t){	int i;	for(i = 0; i<NL; i++)		if(t->l[i].textfn==0)			return &t->l[i];	return 0;} voidduplicate(Flayer *l, Rectangle r, Font *f, int close){	Text *t=(Text *)l->user1;	Flayer *nl = findl(t);	Rune *rp;	ulong n; 	if(nl){		flnew(nl, gettext, l->user0, (char *)t);		flinit(nl, r, f, l->f.cols);		nl->origin = l->origin;		rp = (*l->textfn)(l, l->f.nchars, &n);		flinsert(nl, rp, rp+n, 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);	}	setcursor(mousectl, cursor);} voidbuttons(int updown){	while(((mousep->buttons&7)!=0) != updown)		getmouse();} intgetr(Rectangle *rp){	Point p;	Rectangle r; 	*rp = getrect(3, mousectl);	if(rp->max.x && rp->max.x-rp->min.x<=5 && rp->max.y-rp->min.y<=5){		p = rp->min;		r = cmd.l[cmd.front].entire;		*rp = screen->r;		if(cmd.nwin==1){			if (p.y <= r.min.y)				rp->max.y = r.min.y;			else if (p.y >= r.max.y)				rp->min.y = r.max.y;			if (p.x <= r.min.x)				rp->max.x = r.min.x;			else if (p.x >= r.max.x)				rp->min.x = r.max.x;		}	}	return rectclip(rp, screen->r) &&	   rp->max.x-rp->min.x>100 && rp->max.y-rp->min.y>40;} voidsnarf(Text *t, int w){	Flayer *l = &t->l[w]; 	if(l->p1>l->p0){		snarflen = l->p1-l->p0;		outTsll(Tsnarf, t->tag, l->p0, l->p1);	}} voidcut(Text *t, int w, int save, int check){	long p0, p1;	Flayer *l; 	l = &t->l[w];	p0 = l->p0;	p1 = l->p1;	if(p0 == p1)		return;	if(p0 < 0)		panic("cut");	if(save)		snarf(t, w);	outTsll(Tcut, t->tag, p0, p1);	flsetselect(l, p0, p0);	t->lock++;	hcut(t->tag, p0, p1-p0);	if(check)		hcheck(t->tag);} voidpaste(Text *t, int w){	if(snarflen){		cut(t, w, 0, 0);		t->lock++;		outTsl(Tpaste, t->tag, t->l[w].p0);	}} voidscrorigin(Flayer *l, int but, long p0){	Text *t=(Text *)l->user1; 	switch(but){	case 1:		outTsll(Torigin, t->tag, l->origin, p0);		break;	case 2:		outTsll(Torigin, t->tag, p0, 1L);		break;	case 3:		horigin(t->tag,p0);	}} intalnum(int c){	/*	 * Hard to get absolutely right.  Use what we know about ASCII	 * and assume anything above the Latin control characters is	 * potentially an alphanumeric.	 */	if(c<=' ')		return 0;	if(0x7F<=c && c<=0xA0)		return 0;	if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))		return 0;	return 1;} intraspc(Rasp *r, long p){	ulong n;	rload(r, p, p+1, &n);	if(n)		return scratch[0];	return 0;} longctlw(Rasp *r, long o, long p){	int 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;} longctlu(Rasp *r, long o, long p){	if(--p < o)		return o;	if(raspc(r, p)=='\n')		return p;	for(; p-1>=o && raspc(r, p-1)!='\n'; --p)		;	return p>=o? p : o;} intcenter(Flayer *l, long a){	Text *t; 	t = l->user1;	if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){		if(a > t->rasp.nrunes)			a = t->rasp.nrunes;		outTsll(Torigin, t->tag, a, 2L);		return 1;	}	return 0;} intonethird(Flayer *l, long a){	Text *t;	Rectangle s;	long lines; 	t = l->user1;	if(!t->lock && (a<l->origin || l->origin+l->f.nchars<a)){		if(a > t->rasp.nrunes)			a = t->rasp.nrunes;		s = insetrect(l->scroll, 1);		lines = ((s.max.y-s.min.y)/l->f.font->height+1)/3;		if (lines < 2)			lines = 2;		outTsll(Torigin, t->tag, a, lines);		return 1;	}	return 0;} voidflushtyping(int clearesc){	Text *t;	ulong n; 	if(clearesc)		typeesc = -1;		if(typestart == typeend) {		modified = 0;		return;	}	t = which->user1;	if(t != &cmd)		modified = 1;	rload(&t->rasp, typestart, typeend, &n);	scratch[n] = 0;	if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){		setlock();		outcmd();	}	outTslS(Ttype, t->tag, typestart, scratch);	typestart = -1;	typeend = -1;} #define	BACKSCROLLKEY	Kup#define	ENDKEY	Kend#define	ESC		0x1B#define	HOMEKEY	Khome#define	LEFTARROW	Kleft#define	LINEEND	0x05#define	LINESTART	0x01#define	PAGEDOWN	Kpgdown#define	PAGEUP	Kpgup#define	RIGHTARROW	Kright#define	SCROLLKEY	Kdown intnontypingkey(int c){	switch(c){	case BACKSCROLLKEY:	case ENDKEY:	case HOMEKEY:	case LEFTARROW:	case LINEEND:	case LINESTART:	case PAGEDOWN:	case PAGEUP:	case RIGHTARROW:	case SCROLLKEY:		return 1;	}	return 0;}  voidtype(Flayer *l, int res)	/* what a bloody mess this is */{	Text *t = (Text *)l->user1;	Rune buf[100];	Rune *p = buf;	int c, backspacing;	long a, a0;	int scrollkey; 	scrollkey = 0;	if(res == RKeyboard)		scrollkey = nontypingkey(qpeekc());	/* ICK */ 	if(hostlock || t->lock){		kbdblock();		return;	}	a = l->p0;	if(a!=l->p1 && !scrollkey){		flushtyping(1);		cut(t, t->front, 1, 1);		return;	/* it may now be locked */	}	backspacing = 0;	while((c = kbdchar())>0){		if(res == RKeyboard){			if(nontypingkey(c) || c==ESC)				break;			/* backspace, ctrl-u, ctrl-w, del */			if(c=='\b' || c==0x15 || c==0x17 || c==0x7F){				backspacing = 1;				break;			}		}		*p++ = c;

Lines 1–500 of 675.