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

📄 menu.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 Menu0 Menu0;	/* Menu is taken by mouse.h */struct Menu0{	Control;	CImage	*image;	CImage	*bordercolor;	CImage	*textcolor;	CImage	*selectcolor;	CImage	*selecttextcolor;	CFont	*font;	char		**line;	int		nline;	int		border;	int		align;	Image	*window;	int		visible;	/* state of menu */	int		selection;		/* currently selected line; -1 == none */	int		prevsel;	/* previous selection */	int		lastbut;	/* previous state of mouse button */};enum{	EAdd,	EAlign,	EBorder,	EBordercolor,	EFocus,	EFont,	EFormat,	EHide,	EImage,	ERect,	EReveal,	ESelectcolor,	ESelecttextcolor,	EShow,	ESize,	ETextcolor,	EWindow,};static char *cmds[] = {	[EAdd] = 			"add",	[EAlign] = 			"align",	[EBorder] = 		"border",	[EBordercolor] =	"bordercolor",	[EFocus] = 		"focus",	[EFont] =			"font",	[EFormat] = 		"format",	[EHide] =			"hide",	[EImage] =		"image",	[ERect] =			"rect",	[EReveal] =		"reveal",	[ESelectcolor] =	"selectcolor",	[ESelecttextcolor] =	"selecttextcolor",	[EShow] =			"show",	[ESize] =			"size",	[ETextcolor] =		"textcolor",	[EWindow] =		"window",	nil};static void	menushow(Menu0*);static void menuhide(Menu0*);static voidmenufree(Control *c){	Menu0 *m;	m = (Menu0*)c;	_putctlfont(m->font);	_putctlimage(m->image);	_putctlimage(m->textcolor);	_putctlimage(m->bordercolor);	_putctlimage(m->selectcolor);	_putctlimage(m->selecttextcolor);}static voidmenushow(Menu0 *m){	Rectangle r, clipr;	int i, dx, dy, w;	Font *f;	Point p, q;	Image *im, *c;	if(m->hidden || m->window == nil)		return;	m->visible = 1;	f = m->font->font;	draw(m->window, m->rect, m->image->image, nil, m->image->image->r.min);	if(m->border > 0)		border(m->window, m->rect, m->border, m->bordercolor->image, ZP);	/* text goes here */	dx = 0;	for(i=0; i<m->nline; i++){		w = stringwidth(f, m->line[i]);		if(dx < w)			dx = w;	}	dy = m->nline*f->height;	clipr = insetrect(m->rect, m->border);	p = _ctlalignpoint(clipr, dx, dy, m->align);	im = m->textcolor->image;//	if(m->pressed)//		im = m->pressedtextcolor->image;	for(i=0; i<m->nline; i++){		r.min = p;		r.max.x = p.x+dx;		r.max.y = p.y+f->height;		c = im;		if(i == m->selection){			draw(m->window, r, m->selectcolor->image, nil, ZP);			c = m->selecttextcolor->image;		}		q = _ctlalignpoint(r, stringwidth(f, m->line[i]), f->height, m->align%3);		_string(m->window, q, c,			ZP, f, m->line[i], nil, strlen(m->line[i]),			clipr, nil, ZP, SoverD);		p.y += f->height;	}//	if(m->pressed)//		draw(m->screen, m->rect, m->lighm->image, m->mask->image, m->mask->image->r.min);	flushimage(display, 1);}static Pointmenusize(Menu0 *m){	int x, y;	int i;	Point p;	Font *f;	x = 0;	y = 0;	f = m->font->font;	for(i=0; i<m->nline; i++){		p = stringsize(f, m->line[i]);		if(p.x > x)			x = p.x;		y += f->height;	}	return Pt(x+2*m->border, y+2*m->border);}static voidmenuhide(Menu0 *m){	freeimage(m->window);	m->window = nil;	m->rect.max.y = m->rect.min.y;	/* go to zero size */	m->lastbut = 0;	m->visible = 0;	if(m->selection >= 0)		m->prevsel = m->selection;	m->selection = -1;	_ctlfocus(m, 0);}static voidmenutrack(Control *c, Mouse *ms){	Rectangle r;	int s;	Menu0 *m;	m = (Menu0*)c;	if(m->window == nil)		return;	if(m->lastbut && ms->buttons==0){	/* menu was released */		chanprint(m->event, "%q: value %d", m->name, m->selection);		menuhide(m);		return;	}	m->lastbut = ms->buttons;	r = insetrect(m->rect, m->border);	if(!ptinrect(ms->xy, r))		s = -1;	else{		s = (ms->xy.y - r.min.y)/m->font->font->height;		if(s < 0 || s >= m->nline)			s = -1;	}	if(m->visible== 0 || s!=m->selection){		m->selection = s;		menushow(m);	}}static voidmenuctl(Control *c, CParse *cp){	int up, cmd, h;	Rectangle r;	Menu0 *m;	Point diag;	m = (Menu0*)c;	cmd = _ctllookup(cp->args[0], cmds, nelem(cmds));	switch(cmd){	default:		ctlerror("%q: unrecognized message '%s'", m->name, cp->str);		break;	case EAdd:		_ctlargcount(m, cp, 2);		m->line = ctlrealloc(m->line, (m->nline+1)*sizeof(char*));		m->line[m->nline++] = ctlstrdup(cp->args[1]);		menushow(m);		break;	case EAlign:		_ctlargcount(m, cp, 2);		m->align = _ctlalignment(cp->args[1]);		menushow(m);		break;	case EBorder:		_ctlargcount(m, cp, 2);		m->border = cp->iargs[1];		menushow(m);		break;	case EBordercolor:		_ctlargcount(m, cp, 2);		_setctlimage(m, &m->bordercolor, cp->args[1]);		menushow(m);		break;	case EFocus:		_ctlargcount(m, cp, 2);		if(atoi(cp->args[1]) == 0)			menuhide(m);		break;	case EFont:		_ctlargcount(m, cp, 2);		_setctlfont(m, &m->font, cp->args[1]);		break;	case EFormat:		_ctlargcount(m, cp, 2);		m->format = ctlstrdup(cp->args[1]);		break;	case EHide:		_ctlargcount(m, cp, 1);		m->hidden = 1;		break;	case EImage:		_ctlargcount(m, cp, 2);		_setctlimage(m, &m->image, cp->args[1]);		menushow(m);		break;	case ERect:		_ctlargcount(m, 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", m->name, cp->str);		m->rect = r;		menushow(m);		break;	case EReveal:		_ctlargcount(m, cp, 1);		m->hidden = 0;		menushow(m);		break;	case ESelectcolor:		_ctlargcount(m, cp, 2);		_setctlimage(m, &m->selectcolor, cp->args[1]);		menushow(m);		break;	case ESelecttextcolor:		_ctlargcount(m, cp, 2);		_setctlimage(m, &m->selecttextcolor, cp->args[1]);		menushow(m);		break;	case EShow:		_ctlargcount(m, cp, 1);		menushow(m);		break;	case ESize:		if (cp->nargs == 3)			r.max = Pt(0x7fffffff, 0x7fffffff);		else{			_ctlargcount(m, 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", m->name, cp->str);		m->size.min = r.min;		m->size.max = r.max;		break;	case ETextcolor:		_ctlargcount(m, cp, 2);		_setctlimage(m, &m->textcolor, cp->args[1]);		menushow(m);		break;	case EWindow:		/* no args == toggle; otherwise 0 or 1 for state of window */		if(cp->nargs >= 2)			up = cp->iargs[1];		else			up = (m->window == nil);		if(!up){	/* take window down */			if(m->window)				menuhide(m);			break;		}		if(m->window != nil)			break;		diag = menusize(m);		m->rect.max.x = m->rect.min.x + diag.x;		m->rect.max.y = m->rect.min.y + diag.y;		m->window = allocwindow(_screen, m->rect, Refbackup, DWhite);		if(m->window == nil)			m->window = m->screen;		up = m->prevsel;		if(up<0 || up>=m->nline)			up = 0;		m->selection = up;		menushow(m);		h = m->font->font->height;		moveto(m->controlset->mousectl,			Pt(m->rect.min.x+Dx(m->rect)/2, m->rect.min.y+up*h+h/2));//		_ctlfocus(m, 1);		break;	}}Control*createmenu(Controlset *cs, char *name){	Menu0 *m;	m = (Menu0*)_createctl(cs, "menu", sizeof(Menu0), name);	m->font = _getctlfont("font");	m->image = _getctlimage("white");	m->textcolor = _getctlimage("black");	m->selectcolor = _getctlimage("yellow");	m->selecttextcolor = _getctlimage("black");	m->bordercolor = _getctlimage("black");	m->format = ctlstrdup("%q: value %d");	m->border = 0;	m->align = Aupperleft;	m->visible = 0;	m->window = nil;	m->lastbut = 0;	m->selection = -1;	m->mouse = menutrack;	m->ctl = menuctl;	m->exit = menufree;	return (Control *)m;}

⌨️ 快捷键说明

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