⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 tmp[64], *str;	Rune buf[2][20], *rp;	cs = v;	snprint(tmp, sizeof tmp, "controlsetthread 0x%p", cs);	threadsetname(tmp);	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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -