glendafix fuckupd88043211 years agoHistory
806 lines · 15.1 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <mouse.h>#include <keyboard.h>#include <control.h> static int debug = 0; enum	/* alts */{	AKey,	AMouse,	ACtl,	AExit,	NALT}; static Controlset **controlset;int	ncontrolset;int	ctldeletequits; char *alignnames[Nalignments] = {	[Aupperleft] =		"upperleft",	[Auppercenter] =	"uppercenter",	[Aupperright] =		"upperright",	[Acenterleft] =		"centerleft",	[Acenter] =		"center",	[Acenterright] =	"centerright",	[Alowerleft] =		"lowerleft",	[Alowercenter] =	"lowercenter",	[Alowerright] =		"lowerright",}; char *ctltypenames[Ntypes] = {	[Ctlunknown] =		"unknown",	[Ctlbox] =			"box",	[Ctlbutton] =		"button",	[Ctlentry] =		"entry",	[Ctlkeyboard] =		"keyboard",	[Ctllabel] =		"label",	[Ctlmenu] =		"menu",	[Ctlradio] =		"radio",	[Ctlscribble] =		"scribble",	[Ctlslider] =		"slider",	[Ctltabs] =			"tabs",	[Ctltext] =			"text",	[Ctltextbutton] =	"textbutton",	[Ctltextbutton3] =	"textbutton3",	[Ctlgroup] =		"group",		// divider between controls and metacontrols	[Ctlboxbox] =		"boxbox",	[Ctlcolumn] =		"column",	[Ctlrow] =			"row",	[Ctlstack] =		"stack",	[Ctltab] =			"tab",}; static void	_ctlcmd(Controlset*, char*);static void	_ctlcontrol(Controlset*, char*); static char*_mkctlcmd(Control *c, char *fmt, va_list arg){	char *name, *p, *both; 	name = quotestrdup(c->name);	if(name == nil)		ctlerror("quotestrdup in ctlprint failed");	p = vsmprint(fmt, arg);	if(p == nil){		free(name);		ctlerror("vsmprint1 in ctlprint failed");	}	both = ctlmalloc(strlen(name)+strlen(p)+2);	strcpy(both, name);	strcat(both, " ");	strcat(both, p);	free(name);	free(p);	return both;} intctlprint(Control *c, char *fmt, ...){	int n;	char *p;	va_list arg; 	va_start(arg, fmt);	p = _mkctlcmd(c, fmt, arg);	va_end(arg);	n = sendp(c->controlset->ctl, p);	yield();	return n;} void_ctlprint(Control *c, char *fmt, ...){	char *p;	va_list arg; 	va_start(arg, fmt);	p = _mkctlcmd(c, fmt, arg);	va_end(arg);	_ctlcmd(c->controlset, p);	free(p);} int_ctllookup(char *s, char *tab[], int ntab){	int i; 	for(i=0; i<ntab; i++)		if(tab[i] != nil && strcmp(s, tab[i]) == 0)			return i;	return -1;} static Control*_newcontrol(Controlset *cs, uint n, char *name, char *type){	Control *c; 	for(c=cs->controls; c; c=c->next)		if(strcmp(c->name, name) == 0){			werrstr("control %q already defined", name);			return nil;		}	c = ctlmalloc(n);	c->screen = cs->screen;	c->name = ctlstrdup(name);	c->type = _ctllookup(type, ctltypenames, Ntypes);	if (c->type < 0)		ctlerror("unknown type: %s", type);	c->event = chancreate(sizeof(char*), 64);	c->data = chancreate(sizeof(char*), 0);	c->size = Rect(1, 1, _Ctlmaxsize, _Ctlmaxsize);	c->hidden = 0;	c->ctl = nil;	c->mouse = nil;	c->key = nil;	c->exit = nil;	c->setsize = nil; 	c->controlset = cs;	c->next = cs->controls;	cs->controls = c;	return c;} static voidcontrolsetthread(void *v){	Controlset *cs;	Mouse mouse;	Control *f;	int prevbut, n, i;	Alt alts[NALT+1];	char *str;	Rune buf[2][20], *rp; 	cs = v;	threadsetname("controlsetthread 0x%p", cs); 	alts[AKey].c = cs->kbdc;	alts[AKey].v = &rp;	alts[AKey].op = CHANRCV;	alts[AMouse].c = cs->mousec;	alts[AMouse].v = &mouse;	alts[AMouse].op = CHANRCV;	alts[ACtl].c = cs->ctl;	alts[ACtl].v = &str;	alts[ACtl].op = CHANRCV;	alts[AExit].c = cs->csexitc;	alts[AExit].v = nil;	alts[AExit].op = CHANRCV;	alts[NALT].op = CHANEND; 	cs->focus = nil;	prevbut=0;	n = 0;	for(;;){		/* toggle so we can receive in one buffer while client processes the other */		alts[AKey].v = buf[n];		rp = buf[n];		n = 1-n;		switch(alt(alts)){		case AKey:			if(ctldeletequits && rp[0]=='\177')				ctlerror("delete");			for(i=1; i<nelem(buf[0])-1; i++)				if(nbrecv(cs->kbdc, rp+i) <= 0)					break;			rp[i] = L'\0';			if(cs->focus && cs->focus->key)				cs->focus->key(cs->focus, rp);			break;		case AMouse:			/* is this a focus change? */			if(prevbut)	/* don't change focus if button was down */				goto Send;			if(cs->focus!=nil && cs->focus->hidden == 0 && ptinrect(mouse.xy, cs->focus->rect))				goto Send;			if(cs->clicktotype == 0)				goto Change;			/* click to type: only change if button is down */			if(mouse.buttons == 0)				goto Send;		Change:			/* change of focus */			if(cs->focus != nil)				_ctlprint(cs->focus, "focus 0");			cs->focus = nil;			for(f=cs->actives; f!=nil; f=f->nextactive)				if(f->hidden == 0 && f->mouse && ptinrect(mouse.xy, f->rect)){					cs->focus = f;					_ctlprint(f, "focus 1");					if (f->mouse) {						if (debug) fprint(2, "f->mouse %s\n", f->name);						f->mouse(f, &mouse);					}					break;				}		Send:			if(cs->focus && cs->focus->mouse) {				if (debug) fprint(2, "cs->focus->mouse %s\n", cs->focus->name);				cs->focus->mouse(cs->focus, &mouse);			}			prevbut=mouse.buttons;			break;		case ACtl:			_ctlcontrol(cs, str);			free(str);			break;		case AExit:			threadexits(nil);		}	}} Control*_createctl(Controlset *cs, char *type, uint size, char *name){	Control *c; 	c = _newcontrol(cs, size, name, type);	if(c == nil)		ctlerror("can't create %s control %q: %r", type, name);	return c;} voidclosecontrol(Control *c){	Control *prev, *p; 	if(c == nil)		return;	if (c == c->controlset->focus)		c->controlset->focus = nil;	if(c->exit)		c->exit(c); 	prev = nil;	for(p=c->controlset->controls; p; p=p->next){		if(p == c)			break;		prev = p;	}	if(p == nil)		ctlerror("closecontrol: no such control %q %p\n", c->name, c);	if(prev == nil)		c->controlset->controls = c->next;	else		prev->next = c->next; 	/* is it active? if so, delete from active list */	prev = nil;	for(p=c->controlset->actives; p; p=p->nextactive){		if(p == c)			break;		prev = p;	}	if(p != nil){		if(prev == nil)			c->controlset->actives = c->nextactive;		else			prev->nextactive = c->nextactive;	} 	if(!c->wevent)		chanfree(c->event);	if(!c->wdata)		chanfree(c->data);	free(c->name);	free(c->format);	free(c);} Control*controlcalled(char *name){	Control *c;	int i; 	for(i=0; i<ncontrolset; i++)		for(c=controlset[i]->controls; c; c=c->next)			if(strcmp(c->name, name) == 0)				return c;	return nil;} voidctlerror(char *fmt, ...){	va_list arg;	char buf[256]; 	va_start(arg, fmt);	vfprint(2, fmt, arg);	va_end(arg);	write(2, "\n", 1);	threadexitsall(buf);} Rune*_ctlrunestr(char *s){	Rune *r, *ret; 	ret = r = ctlmalloc((utflen(s)+1)*sizeof(Rune));	while(*s != '\0')		s += chartorune(r++, s);	*r = L'\0';	return ret;} char*_ctlstrrune(Rune *r){	char *s;	s = ctlmalloc(runestrlen(r)*UTFmax+1);	sprint(s, "%S", r);	return s;} void*ctlmalloc(uint n){	void *p; 	p = mallocz(n, 1);	if(p == nil)		ctlerror("control allocation failed: %r");	return p;} void*ctlrealloc(void *p, uint n){	p = realloc(p, n);	if(p == nil)		ctlerror("control reallocation failed: %r");	return p;} char*ctlstrdup(char *s){	char *t; 	t = strdup(s);	if(t == nil)		ctlerror("control strdup(%q) failed: %r", s);	return t;} static voidctokenize(char *s, CParse *cp){	snprint(cp->str, sizeof cp->str, "%s", s);	cp->args = cp->pargs;	cp->nargs = tokenize(s, cp->args, nelem(cp->pargs));} static intctlparse(CParse *cp, char *s, int hasreceiver){	int i;	char *t; 	/* keep original string for good error messages */	strncpy(cp->str, s, sizeof cp->str);	cp->str[sizeof cp->str - 1] = '\0';	ctokenize(s, cp);	if(cp->nargs == 0)		return -1;	/* strip leading sender name if present */	cp->sender = nil;	i = strlen(cp->args[0])-1;	if(cp->args[0][i] == ':'){		cp->sender = cp->args[0];		cp->sender[i] = '\0';		cp->args++;		cp->nargs--;	}	if(hasreceiver){		if(cp->nargs-- == 0)			return -1;		cp->receiver = *cp->args++;	}else		cp->receiver = nil;	for(i=0; i<cp->nargs; i++){		t = cp->args[i];		while(*t == '[')	/* %R gives [0 0] [1 1]; strtol will stop at closing ] */			t++;		cp->iargs[i] = strtol(t, 0, 0);	}	return cp->nargs;} void_ctlargcount(Control *c, CParse *cp, int n){	if(cp->nargs != n)		ctlerror("%q: wrong argument count in '%s'", c->name, cp->str);} static void_ctlcmd(Controlset *cs, char*s){	CParse cp;	char	*rcvrs[32];	int	ircvrs[32], n, i, hit;	Control *c; //	fprint(2, "_ctlcmd: %s\n", s);	cp.args = cp.pargs;	if (ctlparse(&cp, s, 1) < 0)		ctlerror("bad command string: %q", cp.str);	if (cp.nargs == 0 && strcmp(cp.receiver, "sync") == 0){		chanprint(cs->data, "sync");		return;	}	if (cp.nargs == 0)		ctlerror("no command in command string: %q", cp.str); 	n = tokenize(cp.receiver, rcvrs, nelem(rcvrs)); 	// lookup type names: a receiver can be a named type or a named control	for (i = 0; i < n; i++)		ircvrs[i] = _ctllookup(rcvrs[i], ctltypenames, Ntypes); 	for(c = cs->controls; c != nil; c = c->next){		/* if a control matches on more than one receiver element,		 * make sure it gets processed once; hence loop through controls		 * in the outer loop		 */		hit = 0;		for (i = 0; i < n; i++)			if(strcmp(c->name, rcvrs[i]) == 0 || c->type == ircvrs[i])				hit++;		if (hit && c->ctl)			c->ctl(c, &cp);	}} static void_ctlcontrol(Controlset *cs, char *s){	char *lines[16];	int i, n;	char *l; //	fprint(2, "_ctlcontrol: %s\n", s);	n = gettokens(s, lines, nelem(lines), "\n");	for(i=0; i<n; i++){		l = lines[i];		while(*l==' ' || *l=='\t')			l++;		if(*l != '\0')			_ctlcmd(cs, l);	}} Rune*_ctlgetsnarf(void){	int i, n;	char *sn, buf[512];	Rune *snarf; 	if(_ctlsnarffd < 0)		return nil;	sn = nil;	i = 0;

Lines 1–500 of 806.