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

📄 keyboard.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <mouse.h>#include <keyboard.h>#include <control.h>typedef struct Keyboard Keyboard;enum{	SRegular	= 0,	SShift	= 1,	SCaps	= 2,	SMask	= 3,	Nstate	= 4,	SControl	= 4,};struct Keyboard{	Control;	CImage	*image;	CImage	*mask;	CImage	*light;	CImage	*textcolor;	CImage	*bordercolor;	CFont	*font;	CFont	*ctlfont;	Image	*im[Nstate];	int		border;	int		lastbut;	int		state;	char		*key;};enum{	EBorder,	EBordercolor,	EFocus,	EFont,	EFormat,	EHide,	EImage,	ELight,	EMask,	ERect,	EReveal,	EShow,	ESize,};static char *cmds[] = {	[EBorder] =	"border",	[EBordercolor] = "bordercolor",	[EFocus] = 	"focus",	[EFont] =		"font",	[EFormat] = 	"format",	[EHide] =		"hide",	[EImage] =	"image",	[ELight] =		"light",	[EMask] =		"mask",	[ERect] =		"rect",	[EReveal] =	"reveal",	[EShow] =		"show",	[ESize] =		"size",	nil};enum{	Nrow = 5};static uchar wid [Nrow][16] = {	{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 30, },	{24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 24, },	{32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },	{40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, },	{30, 30, 80, 40, 42, 24, },};static char *keyregular[Nrow] = {	"`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",	"->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0[\0]\0Del\0\0",	"Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0;\0'\0Enter\0\0",	"Shift\0z\0x\0c\0v\0b\0n\0m\0,\0.\0/\0Shift\0\0",	"Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"};static char *keyshift[Nrow] = {	"~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",	"->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0{\0}\0Del\0\0",	"Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0:\0\"\0Enter\0\0",	"Shift\0Z\0X\0C\0V\0B\0N\0M\0<\0>\0?\0Shift\0\0",	"Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"};static char *keycaps[Nrow] = {	"`\0001\0002\0003\0004\0005\0006\0007\0008\0009\0000\0-\0=\0\\\0<-\0\0",	"->\0Q\0W\0E\0R\0T\0Y\0U\0I\0O\0P\0[\0]\0Del\0\0",	"Caps\0A\0S\0D\0F\0G\0H\0J\0K\0L\0;\0'\0Enter\0\0",	"Shift\0Z\0X\0C\0V\0B\0N\0M\0,\0.\0/\0Shift\0\0",	"Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"};static char *keycapsshift[Nrow] = {	"~\0!\0@\0#\0$\0%\0^\0&\0*\0(\0)\0_\0+\0|\0<-\0\0",	"->\0q\0w\0e\0r\0t\0y\0u\0i\0o\0p\0{\0}\0Del\0\0",	"Caps\0a\0s\0d\0f\0g\0h\0j\0k\0l\0:\0\"\0Enter\0\0",	"Shift\0z\0x\0c\0v\0b\0n\0m\0<\0>\0?\0Shift\0\0",	"Ctrl\0Alt\0 \0Scrib\0Menu\0Esc\0\0"};struct{	char	*name;	int	val;}keytab[] = {	"Shift",	0,	"Ctrl",	0,	"Alt",		0,	"Caps",	0,	"Del",	'\177',	"Enter",	'\n',	"Esc",	'\033',	"<-",		'\b',	"->",		'\t',	"Scrib",	0x10000,	"Menu",	0x10001,	nil,		0,};static char **keyset[Nstate] = {	keyregular,	keyshift,	keycaps,	keycapsshift,};static void	keyboardshow(Keyboard*);static void	keyup(Keyboard*, Point);static void	keydown(Keyboard*, Point);static void	keyresize(Keyboard*);static voidkeyboardmouse(Control *c, Mouse *m){	Keyboard *k;	k = (Keyboard *)c;	if(m->buttons==1)		keydown(k, m->xy);	else if(k->lastbut==1 && m->buttons==0)		keyup(k, m->xy);	k->lastbut = m->buttons;}static voidkeyboardfree(Control *c){	int i;	Keyboard *k;	k = (Keyboard *)c;	_putctlimage(k->image);	_putctlimage(k->mask);	_putctlimage(k->light);	_putctlimage(k->textcolor);	_putctlimage(k->bordercolor);	_putctlfont(k->font);	_putctlfont(k->ctlfont);	for(i=0; i<nelem(k->im); i++)		freeimage(k->im[i]);	free(k->format);}static intkeyboardy(Keyboard *k, int row){	int dy;	if(row >= Nrow)		return k->rect.max.y-k->border;	dy = Dy(k->rect)-2*k->border;	return k->rect.min.y+k->border+(row*dy+Nrow-1)/Nrow;}static char*whichkey(Keyboard *k, Point p, int *rowp, int *colp, Rectangle *rp){	uchar *wp;	char *kp;	int row, col, dx, dy, x, n, maxx;	Rectangle r;	r = insetrect(k->rect, k->border);	if(!ptinrect(p, r))		return nil;	maxx = r.max.x;	dx = Dx(r);	dy = Dy(r);	row = (p.y - r.min.y)*Nrow/dy;	if(row >= Nrow)		row = Nrow-1;	r.min.y = keyboardy(k, row);	r.max.y = keyboardy(k, row+1);	x = r.min.x;	kp = keyset[k->state&SMask][row];	wp = wid[row];	for(col=0; *kp; col++,kp+=n+1){		n = strlen(kp);		r.min.x = x;		r.max.x = x + (wp[col]*dx+255)/256;		if(kp[n+1] == '\0')			r.max.x = maxx;		if(r.max.x > p.x)			break;		x = r.max.x;	}	*rp = insetrect(r, 1);	*rowp = row;	*colp = col;	return kp;}static Rectanglekeyrect(Keyboard *k, int row, int col){	uchar *wp;	char *kp;	int i, x, n, dx;	Rectangle r;	Point p;	r = insetrect(k->rect, k->border);	p = r.min;	dx = Dx(r);	r.min.y = keyboardy(k, row);	r.max.y = keyboardy(k, row+1);	x = r.min.x;	kp = keyset[0][row];	wp = wid[row];	for(i=0; *kp; i++,kp+=n+1){		n = strlen(kp);		r.min.x = x;		r.max.x = x + (wp[i]*dx+255)/256;		if(kp[n+1] == '\0')			r.max.x = p.x+dx;		if(i >= col)			break;		x = r.max.x;	}	return insetrect(r, 1);}static voidkeydraw(Keyboard *k, int state){	Point p, q;	int row, col, x, dx, dy, nexty, n;	uchar *wp;	char *kp;	Rectangle r;	Font *f, *f1, *f2;	Image *im;	freeimage(k->im[state]);	k->im[state] = nil;	if(Dx(k->rect)-2*k->border <= 0)		return;	im = allocimage(display, k->rect, screen->chan, 0, ~0);	if(im == nil)		return;	k->im[state] = im;	r = insetrect(k->rect, k->border);	border(im, k->rect, k->border, k->bordercolor->image, ZP);	draw(im, r, k->image->image, nil, ZP);	dx = Dx(r);	dy = Dy(r);	p = r.min;	f1 = k->font->font;	f2 = k->ctlfont->font;	nexty = p.y;	for(row=0; row<Nrow; row++){		x = p.x;		kp = keyset[state][row];		wp = wid[row];		r.min.y = nexty;		nexty = keyboardy(k, row+1);		r.max.y = nexty;		for(col=0; *kp; col++,kp+=n+1){			r.min.x = x;			r.max.x = x + (wp[col]*dx+255)/256;			n = strlen(kp);			if(kp[n+1] == '\0')				r.max.x = p.x+dx;			if(row == Nrow-1)				r.max.y = p.y+dy;			if(n > 1)				f = f2;			else				f = f1;			q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter);			_string(im, q, k->textcolor->image,				ZP, f, kp, nil, n, r,				nil, ZP, SoverD);			x = r.max.x;			if(kp[n+1])				draw(im, Rect(x, r.min.y, x+1, r.max.y),					k->textcolor->image, nil, ZP);		}		if(row != Nrow-1)			draw(im, Rect(p.x, r.max.y, p.x+dx, r.max.y+1),				k->textcolor->image, nil, ZP);	}}static voidkeyresize(Keyboard *k){	int i;	for(i=0; i<Nstate; i++)		keydraw(k, i);}static voidkeyboardshow(Keyboard *k){	Rectangle r;	if (k->hidden)		return;	if(k->im[0]==nil || !eqrect(k->im[0]->r, k->rect))		keyresize(k);	if(k->im[k->state&SMask] == nil)		return;	draw(k->screen, k->rect, k->im[k->state&SMask], nil, k->rect.min);	if(k->state & SShift){		r = keyrect(k, 3, 0);		draw(k->screen, r, k->light->image, k->mask->image, ZP);		r = keyrect(k, 3, 11);		draw(k->screen, r, k->light->image, k->mask->image, ZP);	}	if(k->state & SCaps){		r = keyrect(k, 2, 0);		draw(k->screen, r, k->light->image, k->mask->image, ZP);	}	if(k->state & SControl){		r = keyrect(k, 4, 0);		draw(k->screen, r, k->light->image, k->mask->image, ZP);	}	flushimage(display, 1);}static voidkeydown(Keyboard *k, Point p){	int row, col;	Rectangle r;	char *s;	s = whichkey(k, p, &row, &col, &r);	if(s == k->key)		return;	keyboardshow(k);	if(s != nil)		draw(k->screen, r, k->light->image, k->mask->image, ZP);	flushimage(display, 1);	k->key = s;}static intkeylookup(char *s){	int i;	for(i=0; keytab[i].name; i++)		if(strcmp(s, keytab[i].name) == 0)			return keytab[i].val;	return s[0];}static voidkeyup(Keyboard *k, Point p){	int row, col;	Rectangle r;	char *s;	int val;	s = whichkey(k, p, &row, &col, &r);	if(s == nil)		return;	val = keylookup(s);	if(k->state & SControl)		if(' '<val && val<0177)			val &= ~0x60;	if(strcmp(s, "Alt") == 0)		{;}	if(strcmp(s, "Ctrl") == 0){		k->state ^= SControl;	}else		k->state &= ~SControl;	if(strcmp(s, "Shift")==0 || strcmp(s, "Caps")==0){		if(strcmp(s, "Shift") == 0)			k->state ^= SShift;		if(strcmp(s, "Caps") == 0)			k->state ^= SCaps;	}else		k->state &= ~SShift;	keyboardshow(k);	if(val)		chanprint(k->event, k->format, k->name, val);	k->key = nil;}static voidkeyboardctl(Control *c, CParse *cp){	int cmd;	Rectangle r;	Keyboard *k;	k = (Keyboard*)c;	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));	switch(cmd){	default:		ctlerror("%q: unrecognized message '%s'", k->name, cp->str);		break;	case EBorder:		_ctlargcount(k, cp, 2);		if(cp->iargs[1] < 0)			ctlerror("%q: bad border: %c", k->name, cp->str);		k->border = cp->iargs[1];		break;	case EBordercolor:		_ctlargcount(k, cp, 2);		_setctlimage(k, &k->bordercolor, cp->args[1]);		break;	case EFocus:		/* ignore focus change */		break;	case EFont:		if(cp->nargs!=2 && cp->nargs!=3)			ctlerror("%q: bad font message '%s'", k->name, cp->str);		_setctlfont(k, &k->font, cp->args[1]);		if(cp->nargs == 3)			_setctlfont(k, &k->ctlfont, cp->args[2]);		else			_setctlfont(k, &k->ctlfont, cp->args[1]);		break;	case EFormat:		_ctlargcount(k, cp, 2);		k->format = ctlstrdup(cp->args[1]);		break;	case EHide:		_ctlargcount(k, cp, 1);		k->hidden = 1;		break;	case EImage:		_ctlargcount(k, cp, 2);		_setctlimage(k, &k->image, cp->args[1]);		break;	case ELight:		_ctlargcount(k, cp, 2);		_setctlimage(k, &k->light, cp->args[1]);		break;	case EMask:		_ctlargcount(k, cp, 2);		_setctlimage(k, &k->mask, cp->args[1]);		break;	case ERect:		_ctlargcount(k, cp, 5);		r.min.x = cp->iargs[1];		r.min.y = cp->iargs[2];		r.max.x = cp->iargs[3];		r.max.y = cp->iargs[4];		if(Dx(r)<0 || Dy(r)<0)			ctlerror("%q: bad rectangle: %s", k->name, cp->str);		k->rect = r;		keyboardshow(k);		break;	case EReveal:		_ctlargcount(k, cp, 1);		k->hidden = 0;		keyboardshow(k);		break;	case EShow:		_ctlargcount(k, cp, 1);		keyboardshow(k);		break;	case ESize:		if (cp->nargs == 3)			r.max = Pt(0x7fffffff, 0x7fffffff);		else{			_ctlargcount(k, cp, 5);			r.max.x = cp->iargs[3];			r.max.y = cp->iargs[4];		}		r.min.x = cp->iargs[1];		r.min.y = cp->iargs[2];		if(r.min.x<=0 || r.min.y<=0 || r.max.x<=0 || r.max.y<=0 || r.max.x < r.min.x || r.max.y < r.min.y)			ctlerror("%q: bad sizes: %s", k->name, cp->str);		k->size.min = r.min;		k->size.max = r.max;		break;	}}Control*createkeyboard(Controlset *cs, char *name){	Keyboard *k;	k = (Keyboard *)_createctl(cs, "keyboard", sizeof(Keyboard), name);	k->image = _getctlimage("white");	k->mask = _getctlimage("opaque");	k->light = _getctlimage("yellow");	k->bordercolor = _getctlimage("black");	k->textcolor = _getctlimage("black");	k->font = _getctlfont("font");	k->ctlfont = _getctlfont("font");	k->format = ctlstrdup("%q: value 0x%x");	k->border = 0;	k->lastbut = 0;	k->key = nil;	k->state = SRegular;	k->ctl = keyboardctl;	k->mouse = keyboardmouse;	k->exit = keyboardfree;	k->size = Rect(246, 2 + 5 * (k->font->font->height + 1), 512, 256);	return k;}

⌨️ 快捷键说明

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