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

📄 devdraw.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
#include	"u.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"#define	Image	IMAGE#include	"draw.h"#include	"memdraw.h"#include	"memlayer.h"#include	"cursor.h"#include	"screen.h"#define blankscreen(x)#define ishwimage(x) (0)enum{	Qtopdir		= 0,	Qnew,	Qwinname,	Q3rd,	Q2nd,	Qcolormap,	Qctl,	Qdata,	Qrefresh,};/* * Qid path is: *	 4 bits of file type (qids above) *	24 bits of mux slot number +1; 0 means not attached to client */#define	QSHIFT	4	/* location in qid of client # */#define	QID(q)		((((ulong)(q).path)&0x0000000F)>>0)#define	CLIENTPATH(q)	((((ulong)q)&0x7FFFFFF0)>>QSHIFT)#define	CLIENT(q)	CLIENTPATH((q).path)#define	NHASH		(1<<5)#define	HASHMASK	(NHASH-1)#define	IOUNIT		(64*1024)typedef struct Client Client;typedef struct Draw Draw;typedef struct DImage DImage;typedef struct DScreen DScreen;typedef struct CScreen CScreen;typedef struct FChar FChar;typedef struct Refresh Refresh;typedef struct Refx Refx;typedef struct DName DName;ulong blanktime = 30;	/* in minutes; a half hour */struct Draw{	int		clientid;	int		nclient;	Client**	client;	int		nname;	DName*		name;	int		vers;	int		softscreen;	int		blanked;	/* screen turned off */	ulong		blanktime;	/* time of last operation */	ulong		savemap[3*256];};struct Client{	Ref		r;	DImage*		dimage[NHASH];	CScreen*	cscreen;	Refresh*	refresh;	Rendez		refrend;	uchar*		readdata;	int		nreaddata;	int		busy;	int		clientid;	int		slot;	int		refreshme;	int		infoid;	int		op;};struct Refresh{	DImage*		dimage;	Rectangle	r;	Refresh*	next;};struct Refx{	Client*		client;	DImage*		dimage;};struct DName{	char		*name;	Client		*client;	DImage*		dimage;	int		vers;};struct FChar{	int		minx;	/* left edge of bits */	int		maxx;	/* right edge of bits */	uchar		miny;	/* first non-zero scan-line */	uchar		maxy;	/* last non-zero scan-line + 1 */	schar		left;	/* offset of baseline */	uchar		width;	/* width of baseline */};/* * Reference counts in DImages: *	one per open by original client *	one per screen image or fill * 	one per image derived from this one by name */struct DImage{	int		id;	int		ref;	char		*name;	int		vers;	Memimage*	image;	int		ascent;	int		nfchar;	FChar*		fchar;	DScreen*	dscreen;	/* 0 if not a window */	DImage*		fromname;	/* image this one is derived from, by name */	DImage*		next;};struct CScreen{	DScreen*	dscreen;	CScreen*	next;};struct DScreen{	int		id;	int		public;	int		ref;	DImage		*dimage;	DImage		*dfill;	Memscreen*	screen;	Client*		owner;	DScreen*	next;};static	Draw		sdraw;	QLock	drawlock;static	Memimage	*screenimage;static	DImage*	screendimage;static	char	screenname[40];static	int	screennameid;static	Rectangle	flushrect;static	int		waste;static	DScreen*	dscreen;extern	void		flushmemscreen(Rectangle);	void		drawmesg(Client*, void*, int);	void		drawuninstall(Client*, int);	void		drawfreedimage(DImage*);	Client*		drawclientofpath(ulong);	DImage*	allocdimage(Memimage*);static	char Enodrawimage[] =	"unknown id for draw image";static	char Enodrawscreen[] =	"unknown id for draw screen";static	char Eshortdraw[] =	"short draw message";static	char Eshortread[] =	"draw read too short";static	char Eimageexists[] =	"image id in use";static	char Escreenexists[] =	"screen id in use";static	char Edrawmem[] =	"image memory allocation failed";static	char Ereadoutside[] =	"readimage outside image";static	char Ewriteoutside[] =	"writeimage outside image";static	char Enotfont[] =	"image not a font";static	char Eindex[] =		"character index out of range";static	char Enoclient[] =	"no such draw client";static	char Enameused[] =	"image name in use";static	char Enoname[] =	"no image with that name";static	char Eoldname[] =	"named image no longer valid";static	char Enamed[] = 	"image already has name";static	char Ewrongname[] = 	"wrong name for image";voiddrawqlock(void){	qlock(&drawlock);}intdrawcanqlock(void){	return canqlock(&drawlock);}voiddrawqunlock(void){	qunlock(&drawlock);}static intdrawgen(Chan *c, char *_, Dirtab *__, int ___, int s, Dir *dp){	int t;	Qid q;	ulong path;	Client *cl;	q.vers = 0;	if(s == DEVDOTDOT){		switch(QID(c->qid)){		case Qtopdir:		case Q2nd:			mkqid(&q, Qtopdir, 0, QTDIR);			devdir(c, q, "#i", 0, eve, 0500, dp);			break;		case Q3rd:			cl = drawclientofpath(c->qid.path);			if(cl == nil)				strcpy(up->genbuf, "??");			else				sprint(up->genbuf, "%d", cl->clientid);			mkqid(&q, Q2nd, 0, QTDIR);			devdir(c, q, up->genbuf, 0, eve, 0500, dp);			break;		default:			panic("drawwalk %llux", c->qid.path);		}		return 1;	}	/*	 * Top level directory contains the name of the device.	 */	t = QID(c->qid);	if(t == Qtopdir){		switch(s){		case 0:			mkqid(&q, Q2nd, 0, QTDIR);			devdir(c, q, "draw", 0, eve, 0555, dp);			break;		case 1:			mkqid(&q, Qwinname, 0, 0);			devdir(c, q, "winname", 0, eve, 0444, dp);			break;		default:			return -1;		}		return 1;	}	/*	 * Second level contains "new" plus all the clients.	 */	if(t == Q2nd || t == Qnew){		if(s == 0){			mkqid(&q, Qnew, 0, QTFILE);			devdir(c, q, "new", 0, eve, 0666, dp);		}		else if(s <= sdraw.nclient){			cl = sdraw.client[s-1];			if(cl == 0)				return 0;			sprint(up->genbuf, "%d", cl->clientid);			mkqid(&q, (s<<QSHIFT)|Q3rd, 0, QTDIR);			devdir(c, q, up->genbuf, 0, eve, 0555, dp);			return 1;		}		else			return -1;		return 1;	}	/*	 * Third level.	 */	path = c->qid.path&~((1<<QSHIFT)-1);	/* slot component */	q.vers = c->qid.vers;	q.type = QTFILE;	switch(s){	case 0:		q.path = path|Qcolormap;		devdir(c, q, "colormap", 0, eve, 0600, dp);		break;	case 1:		q.path = path|Qctl;		devdir(c, q, "ctl", 0, eve, 0600, dp);		break;	case 2:		q.path = path|Qdata;		devdir(c, q, "data", 0, eve, 0600, dp);		break;	case 3:		q.path = path|Qrefresh;		devdir(c, q, "refresh", 0, eve, 0400, dp);		break;	default:		return -1;	}	return 1;}staticintdrawrefactive(void *a){	Client *c;	c = a;	return c->refreshme || c->refresh!=0;}staticvoiddrawrefreshscreen(DImage *l, Client *client){	while(l != nil && l->dscreen == nil)		l = l->fromname;	if(l != nil && l->dscreen->owner != client)		l->dscreen->owner->refreshme = 1;}staticvoiddrawrefresh(Memimage *m, Rectangle r, void *v){	Refx *x;	DImage *d;	Client *c;	Refresh *ref;	if(v == 0)		return;	x = v;	c = x->client;	d = x->dimage;	for(ref=c->refresh; ref; ref=ref->next)		if(ref->dimage == d){			combinerect(&ref->r, r);			return;		}	ref = malloc(sizeof(Refresh));	if(ref){		ref->dimage = d;		ref->r = r;		ref->next = c->refresh;		c->refresh = ref;	}}static voidaddflush(Rectangle r){	int abb, ar, anbb;	Rectangle nbb;	if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))		return;	if(flushrect.min.x >= flushrect.max.x){		flushrect = r;		waste = 0;		return;	}	nbb = flushrect;	combinerect(&nbb, r);	ar = Dx(r)*Dy(r);	abb = Dx(flushrect)*Dy(flushrect);	anbb = Dx(nbb)*Dy(nbb);	/*	 * Area of new waste is area of new bb minus area of old bb,	 * less the area of the new segment, which we assume is not waste.	 * This could be negative, but that's OK.	 */	waste += anbb-abb - ar;	if(waste < 0)		waste = 0;	/*	 * absorb if:	 *	total area is small	 *	waste is less than half total area	 * 	rectangles touch	 */	if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){		flushrect = nbb;		return;	}	/* emit current state */	if(flushrect.min.x < flushrect.max.x)		flushmemscreen(flushrect);	flushrect = r;	waste = 0;}staticvoiddstflush(int dstid, Memimage *dst, Rectangle r){	Memlayer *l;	if(dstid == 0){		combinerect(&flushrect, r);		return;	}	/* how can this happen? -rsc, dec 12 2002 */	if(dst == 0){		print("nil dstflush\n");		return;	}	l = dst->layer;	if(l == nil)		return;	do{		if(l->screen->image->data != screenimage->data)			return;		r = rectaddpt(r, l->delta);		l = l->screen->image->layer;	}while(l);	addflush(r);}voiddrawflush(void){	if(flushrect.min.x < flushrect.max.x)		flushmemscreen(flushrect);	flushrect = Rect(10000, 10000, -10000, -10000);}staticintdrawcmp(char *a, char *b, int n){	if(strlen(a) != n)		return 1;	return memcmp(a, b, n);}DName*drawlookupname(int n, char *str){	DName *name, *ename;	name = sdraw.name;	ename = &name[sdraw.nname];	for(; name<ename; name++)		if(drawcmp(name->name, str, n) == 0)			return name;	return 0;}intdrawgoodname(DImage *d){	DName *n;	/* if window, validate the screen's own images */	if(d->dscreen)		if(drawgoodname(d->dscreen->dimage) == 0		|| drawgoodname(d->dscreen->dfill) == 0)			return 0;	if(d->name == nil)		return 1;	n = drawlookupname(strlen(d->name), d->name);	if(n==nil || n->vers!=d->vers)		return 0;	return 1;}DImage*drawlookup(Client *client, int id, int checkname){	DImage *d;	d = client->dimage[id&HASHMASK];	while(d){		if(d->id == id){			if(checkname && !drawgoodname(d))				error(Eoldname);			return d;		}		d = d->next;	}	return 0;}DScreen*drawlookupdscreen(int id){	DScreen *s;	s = dscreen;	while(s){		if(s->id == id)			return s;		s = s->next;	}	return 0;}DScreen*drawlookupscreen(Client *client, int id, CScreen **cs){	CScreen *s;	s = client->cscreen;	while(s){		if(s->dscreen->id == id){			*cs = s;			return s->dscreen;		}		s = s->next;	}	error(Enodrawscreen);	for(;;);}DImage*allocdimage(Memimage *i){	DImage *d;	d = malloc(sizeof(DImage));	if(d == 0)		return 0;	d->ref = 1;	d->name = 0;	d->vers = 0;	d->image = i;	d->nfchar = 0;	d->fchar = 0;	d->fromname = 0;	return d;}Memimage*drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen){	DImage *d;	d = allocdimage(i);	if(d == 0)		return 0;	d->id = id;	d->dscreen = dscreen;	d->next = client->dimage[id&HASHMASK];	client->dimage[id&HASHMASK] = d;	return i;}Memscreen*drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public){	Memscreen *s;	CScreen *c;	c = malloc(sizeof(CScreen));	if(dimage && dimage->image && dimage->image->chan == 0)		panic("bad image %p in drawinstallscreen", dimage->image);	if(c == 0)		return 0;	if(d == 0){		d = malloc(sizeof(DScreen));		if(d == 0){			free(c);			return 0;		}		s = malloc(sizeof(Memscreen));		if(s == 0){			free(c);			free(d);			return 0;		}		s->frontmost = 0;		s->rearmost = 0;		d->dimage = dimage;		if(dimage){			s->image = dimage->image;			dimage->ref++;		}		d->dfill = dfill;		if(dfill){			s->fill = dfill->image;			dfill->ref++;		}		d->ref = 0;		d->id = id;		d->screen = s;		d->public = public;		d->next = dscreen;		d->owner = client;		dscreen = d;	}	c->dscreen = d;	d->ref++;	c->next = client->cscreen;	client->cscreen = c;	return d->screen;}voiddrawdelname(DName *name){	int i;	i = name-sdraw.name;	memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));	sdraw.nname--;}voiddrawfreedscreen(DScreen *this){	DScreen *ds, *next;	this->ref--;	if(this->ref < 0)		print("negative ref in drawfreedscreen\n");	if(this->ref > 0)		return;	ds = dscreen;	if(ds == this){		dscreen = this->next;		goto Found;	}	while((next = ds->next)){	/* assign = */		if(next == this){			ds->next = this->next;			goto Found;		}		ds = next;	}	error(Enodrawimage);    Found:	if(this->dimage)		drawfreedimage(this->dimage);	if(this->dfill)		drawfreedimage(this->dfill);	free(this->screen);	free(this);}voiddrawfreedimage(DImage *dimage){	int i;	Memimage *l;	DScreen *ds;	dimage->ref--;	if(dimage->ref < 0)		print("negative ref in drawfreedimage\n");	if(dimage->ref > 0)		return;	/* any names? */	for(i=0; i<sdraw.nname; )		if(sdraw.name[i].dimage == dimage)			drawdelname(sdraw.name+i);		else			i++;	if(dimage->fromname){	/* acquired by name; owned by someone else*/		drawfreedimage(dimage->fromname);		goto Return;	}	ds = dimage->dscreen;	l = dimage->image;	dimage->dscreen = nil;	/* paranoia */	dimage->image = nil;	if(ds){		if(l->data == screenimage->data)			addflush(l->layer->screenr);		if(l->layer->refreshfn == drawrefresh)	/* else true owner will clean up */			free(l->layer->refreshptr);		l->layer->refreshptr = nil;		if(drawgoodname(dimage))			memldelete(l);		else			memlfree(l);		drawfreedscreen(ds);	}else		freememimage(l);    Return:	free(dimage->fchar);	free(dimage);}voiddrawuninstallscreen(Client *client, CScreen *this){	CScreen *cs, *next;	cs = client->cscreen;	if(cs == this){		client->cscreen = this->next;		drawfreedscreen(this->dscreen);		free(this);		return;	}	while((next = cs->next)){	/* assign = */		if(next == this){			cs->next = this->next;			drawfreedscreen(this->dscreen);			free(this);			return;		}		cs = next;	}}voiddrawuninstall(Client *client, int id){	DImage *d, *next;	d = client->dimage[id&HASHMASK];	if(d == 0)		error(Enodrawimage);	if(d->id == id){		client->dimage[id&HASHMASK] = d->next;		drawfreedimage(d);		return;	}	while((next = d->next)){	/* assign = */		if(next->id == id){			d->next = next->next;			drawfreedimage(next);			return;		}		d = next;	}	error(Enodrawimage);}voiddrawaddname(Client *client, DImage *di, int n, char *str){	DName *name, *ename, *new, *t;	name = sdraw.name;	ename = &name[sdraw.nname];	for(; name<ename; name++)

⌨️ 快捷键说明

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