forsyth20100821-1800749be1916 years agoHistory
1028 lines · 17.5 KB · C
RawDownload
#include "lib9.h"#include "draw.h"#include "tk.h"#include <kernel.h>#include <interp.h> enum{	Cmask,	Cctl,	Ckey,	Cbp,	Cbr,}; struct {	char*	event;	int	mask;	int	action;} etab[] ={	"Motion",		TkMotion,	Cmask,	"Double",		TkDouble,	Cmask,		"Map",			TkMap,		Cmask,	"Unmap",		TkUnmap,	Cmask,	"Destroy",		TkDestroy, Cmask,	"Enter",		TkEnter,	Cmask,	"Leave",		TkLeave,	Cmask,	"FocusIn",		TkFocusin,	Cmask,	"FocusOut",		TkFocusout,	Cmask,	"Configure",		TkConfigure,	Cmask,	"Control",		0,		Cctl,	"Key",			0,		Ckey,	"KeyPress",		0,		Ckey,	"Button",		0,		Cbp,	"ButtonPress",		0,		Cbp,	"ButtonRelease",	0,		Cbr,}; staticTkOption tkcurop[] ={	"x",		OPTdist,	O(TkCursor, p.x),	nil,	"y",		OPTdist,	O(TkCursor, p.y),	nil,	"bitmap",	OPTbmap,	O(TkCursor, bit),	nil,	"image",	OPTimag,	O(TkCursor, img),	nil,	"default",	OPTbool,	O(TkCursor, def),	nil,	nil}; staticTkOption focusopts[] = {	"global",			OPTbool,	0,	nil,	nil}; static char*tkseqitem(char *buf, char *arg){	while(*arg && (*arg == ' ' || *arg == '-'))		arg++;	while(*arg && *arg != ' ' && *arg != '-' && *arg != '>')		*buf++ = *arg++;	*buf = '\0';	return arg;} static char*tkseqkey(Rune *r, char *arg){	char *narg; 	while(*arg && (*arg == ' ' || *arg == '-'))		arg++;	if (*arg == '\\') {		if (*++arg == '\0') {			*r = 0;			return arg;		}	} else if (*arg == '\0' || *arg == '>' || *arg == '-') {		*r = 0;		return arg;	}	narg = arg + chartorune(r, arg);	return narg;} inttkseqparse(char *seq){	Rune r;	int i, event;	char *buf; 	buf = mallocz(Tkmaxitem, 0);	if(buf == nil)		return -1; 	event = 0; 	while(*seq && *seq != '>') {		seq = tkseqitem(buf, seq);			for(i = 0; i < nelem(etab); i++)				if(strcmp(buf, etab[i].event) == 0)				break;			if(i >= nelem(etab)) {			seq = tkextnparseseq(buf, seq, &event);			if (seq == nil) {				free(buf);				return -1;			}			continue;		}				switch(etab[i].action) {		case Cmask:			event |= etab[i].mask;			break;		case Cctl:			seq = tkseqkey(&r, seq);			if(r == 0) {				free(buf);				return -1;			}			if(r <= '~')				r &= 0x1f;			event |= TkKey|TKKEY(r);			break;			case Ckey:			seq = tkseqkey(&r, seq);			if(r != 0)				event |= TKKEY(r);			event |= TkKey;			break;		case Cbp:			seq = tkseqitem(buf, seq);			switch(buf[0]) {			default:				free(buf);				return -1;			case '\0':				event |= TkEpress;				break;			case '1':				event |= TkButton1P;				break;			case '2':				event |= TkButton2P;				break;			case '3':				event |= TkButton3P;				break;			case '4':				event |= TkButton4P;				break;			case '5':				event |= TkButton5P;				break;			case '6':				event |= TkButton6P;				break;			}			break;		case Cbr:			seq = tkseqitem(buf, seq);			switch(buf[0]) {			default:				free(buf);				return -1;			case '\0':				event |= TkErelease;				break;			case '1':				event |= TkButton1R;				break;			case '2':				event |= TkButton2R;				break;			case '3':				event |= TkButton3R;				break;			case '4':				event |= TkButton4R;				break;			case '5':				event |= TkButton5R;				break;			case '6':				event |= TkButton6R;				break;			}			break;		}	}	free(buf);	return event;} voidtkcmdbind(Tk *tk, int event, char *s, void *data){	Point p;	TkMouse *m;	TkGeom *g;	int v, len;	char *e, *c, *ec, *cmd;	TkTop *t; 	if(s == nil)		return;	cmd = malloc(2*Tkmaxitem);	if (cmd == nil) {		print("tk: bind command \"%s\": %s\n",			tk->name ? tk->name->name : "(noname)", TkNomem);		return;	} 	m = (TkMouse*)data;	c = cmd;	ec = cmd+2*Tkmaxitem-1;	while(*s && c < ec) {		if(*s != '%') {			*c++ = *s++;			continue;		}		s++;		len = ec-c;		switch(*s++) {		def:		default:			*c++ = s[-1];			break;		case '%':			*c++ = '%';			break;		case 'b':			v = 0;			if (!(event & TkKey)) {				if(event & (TkButton1P|TkButton1R))					v = 1;				else if(event & (TkButton2P|TkButton2R))					v = 2;				else if(event & (TkButton3P|TkButton3R))					v = 3;			}			c += snprint(c, len, "%d", v);			break;		case 'h':			if((event & TkConfigure) == 0)				goto def;			g = (TkGeom*)data;			c += snprint(c, len, "%d", g->height);			break;		case 's':			if((event & TkKey))				c += snprint(c, len, "%d", TKKEY(event));			else if((event & (TkEmouse|TkEnter)))				c += snprint(c, len, "%d", m->b);			else if((event & TkFocusin))				c += snprint(c, len, "%d", (int)data);			else				goto def;			break;		case 'w':			if((event & TkConfigure) == 0)				goto def;			g = (TkGeom*)data;			c += snprint(c, len, "%d", g->width);			break;		case 'x':		/* Relative mouse coords */		case 'y':			if((event & TkKey) || (event & (TkEmouse|TkEnter)) == 0)				goto def;			p = tkposn(tk);			if(s[-1] == 'x')				v = m->x - p.x;			else				v = m->y - p.y;			c += snprint(c, len, "%d", v - tk->borderwidth);			break;		case 'X':		/* Absolute mouse coords */		case 'Y':			if((event & TkKey) || (event & TkEmouse) == 0)				goto def;			c += snprint(c, len, "%d", s[-1] == 'X' ? m->x : m->y);			break;		case 'A':			if((event & TkKey) == 0)				goto def;			v = TKKEY(event);			if(v == '{' || v == '}' || v == '\\')				c += snprint(c, len, "\\%C", v);			else if(v != '\0')				c += snprint(c, len, "%C", v);			break;		case 'K':			if((event & TkKey) == 0)				goto def;			c += snprint(c, len, "%.4X", TKKEY(event));			break;		case 'W':		        if (tk->name != nil) 			  c += snprint(c, len, "%s", tk->name->name);			break;		}	}	*c = '\0';	e = nil;	t = tk->env->top;	t->execdepth = 0;	if(cmd[0] == '|')		tkexec(t, cmd+1, nil);	else if(cmd[0] != '\0')		e = tkexec(t, cmd, nil);	t->execdepth = -1; 	if(e == nil) {		free(cmd);		return;	} 	if(tk->name != nil){		char *s; 		if(t->errx[0] != '\0')			s = tkerrstr(t, e);		else			s = e;		print("tk: bind command \"%s\": %s: %s\n", tk->name->name, cmd, s);		if(s != e)			free(s);	}	free(cmd);} char*tkbind(TkTop *t, char *arg, char **ret){	Rune r;	Tk *tk;	TkAction **ap;	int i, mode, event;	char *cmd, *tag, *seq;	char *e; 	USED(ret); 	tag = mallocz(Tkmaxitem, 0);	if(tag == nil)		return TkNomem;	seq = mallocz(Tkmaxitem, 0);	if(seq == nil) {		free(tag);		return TkNomem;	} 	arg = tkword(t, arg, tag, tag+Tkmaxitem, nil);	if(tag[0] == '\0') {		e = TkBadtg;		goto err;	} 	arg = tkword(t, arg, seq, seq+Tkmaxitem, nil);	if(seq[0] == '<') {		event = tkseqparse(seq+1);		if(event == -1) {			e = TkBadsq;			goto err;		}	}	else {		chartorune(&r, seq);		event = TkKey | r;	}	if(event == 0) {		e = TkBadsq;		goto err;	} 	arg = tkskip(arg, " \t"); 	mode = TkArepl;	if(*arg == '+') {		mode = TkAadd;		arg++;	}	else if(*arg == '-'){		mode = TkAsub;		arg++;	} 	if(*arg == '{') {		cmd = tkskip(arg+1, " \t");		if(*cmd == '}') {			tk = tklook(t, tag, 0);			if(tk == nil) {				for(i = 0; ; i++) {					if(i >= TKwidgets) {						e = TkBadwp;						tkerr(t, tag);						goto err;					}					if(strcmp(tag, tkmethod[i]->name) == 0) {						ap = &(t->binds[i]);						break;					}				}			}			else				ap = &tk->binds;			tkcancel(ap, event);		}	} 	tkword(t, arg, seq, seq+Tkmaxitem, nil);	if(tag[0] == '.') {		tk = tklook(t, tag, 0);		if(tk == nil) {			e = TkBadwp;			tkerr(t, tag);			goto err;		} 		cmd = strdup(seq);		if(cmd == nil) {			e = TkNomem;			goto err;		}		e = tkaction(&tk->binds, event, TkDynamic, cmd, mode);		if(e != nil)			goto err;	/* tkaction does free(cmd) */		free(tag);		free(seq);		return nil;	}	/* documented but doesn't work */	if(strcmp(tag, "all") == 0) {		for(tk = t->root; tk; tk = tk->next) {			cmd = strdup(seq);			if(cmd == nil) {				e = TkNomem;				goto err;			}			e = tkaction(&tk->binds, event, TkDynamic, cmd, mode);			if(e != nil)				goto err;		}		free(tag);		free(seq);		return nil;	}	/* undocumented, probably unused, and doesn't work consistently */	for(i = 0; i < TKwidgets; i++) {		if(strcmp(tag, tkmethod[i]->name) == 0) {			cmd = strdup(seq);			if(cmd == nil) {				e = TkNomem;				goto err;			}			e = tkaction(t->binds + i,event, TkDynamic, cmd, mode);			if(e != nil)				goto err;			free(tag);			free(seq);			return nil;		}	} 	e = TkBadtg;err:	free(tag);	free(seq); 	return e;} char*tksend(TkTop *t, char *arg, char **ret){ 	TkVar *v;	char *var; 	USED(ret); 	var = mallocz(Tkmaxitem, 0);	if(var == nil)		return TkNomem; 	arg = tkword(t, arg, var, var+Tkmaxitem, nil);	v = tkmkvar(t, var, 0);	free(var);	if(v == nil)		return TkBadvr;	if(v->type != TkVchan)		return TkNotvt;

Lines 1–500 of 1028.