1992 lines · 38.6 KB · C
RawDownload
#include <lib9.h>#include <kern.h>#include <draw.h>#include <memdraw.h>#include <memlayer.h>#include <cursor.h>#include <ninep.h>#include <ninepserver.h>#include "dat.h"#include "fns.h"#include "fsys.h" typedef struct DImage DImage;typedef struct DName DName;typedef struct CScreen CScreen;typedef struct DScreen DScreen;typedef struct FChar FChar;typedef struct Refresh Refresh;typedef struct Refx Refx; #define	NHASH		(1<<5)#define	HASHMASK	(NHASH-1) struct DClient{	int		r;	// Ref	DImage*	dimage[NHASH];	CScreen*	cscreen;	Refresh*	refresh;//	Rendez	refrend;	Draw	*draw;	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{	DClient*		client;	DImage*		dimage;}; 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 */}; 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 DName{	char		*name;	DClient	*client;	DImage*	dimage;	int		vers;}; struct CScreen{	DScreen*	dscreen;	CScreen*	next;}; struct DScreen{	int		id;	int		public;	int		ref;	DImage	*dimage;	DImage	*dfill;	Memscreen*	screen;	DClient*	owner;	DScreen*	next;}; struct Draw{	Window*		window;	DImage*		screendimage;	Rectangle		flushrect;	int			waste;	DScreen*		dscreen;}; static void drawfreedimage(Draw*, DImage*);static int drawgoodname(DImage*);static void drawflush(Draw*);static DClient* drawlookupclient(int); int		nclient = 0;int		ndname = 0;DName*	dname = nil;int		vers = 0; /* used by libmemdraw */intiprint(char* fmt, ...){	int n;	va_list args; 	va_start(args, fmt);	n = vfprint(2, fmt, args);	va_end(args);	return n;} staticvoiddrawrefreshscreen(DImage *l, DClient *client){	while(l != nil && l->dscreen == nil)		l = l->fromname;	if(l != nil && l->dscreen->owner != client)		l->dscreen->owner->refreshme = 1;} staticvoiddrawrefresh(Memimage *l, Rectangle r, void *v){	Refx *x;	DImage *d;	DClient *c;	Refresh *ref; 	USED(l);	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 = mallocz(sizeof(Refresh), 1);	if(ref){		ref->dimage = d;		ref->r = r;		ref->next = c->refresh;		c->refresh = ref;	}} staticvoidaddflush(Draw *d, Rectangle r){	int abb, ar, anbb;	Rectangle nbb;	Memimage *screenimage; 	screenimage = d->window->screenimage;	if(!rectclip(&r, screenimage->r))		return; 	if(d->flushrect.min.x >= d->flushrect.max.x){		d->flushrect = r;		d->waste = 0;		return;	}	nbb = d->flushrect;	combinerect(&nbb, r);	ar = Dx(r)*Dy(r);	abb = Dx(d->flushrect)*Dy(d->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.	 */	d->waste += anbb-abb - ar;	if(d->waste < 0)		d->waste = 0;	/*	 * absorb if:	 *	total area is small	 *	waste is less than half total area	 * 	rectangles touch	 */	if(anbb<=1024 || d->waste*2<anbb || rectXrect(d->flushrect, r)){		d->flushrect = nbb;		return;	}	/* emit current state */	if(d->flushrect.min.x < d->flushrect.max.x)		xflushmemscreen(d->window, d->flushrect);	d->flushrect = r;	d->waste = 0;} staticvoiddstflush(Draw *d, Memimage *dst, Rectangle r){	Memimage *screenimage;	Memlayer *l; 	screenimage = d->window->screenimage;	if(dst == screenimage){		combinerect(&d->flushrect, r);		return;	}	/* how can this happen? -rsc, dec 12 2002 */	if(dst == 0){		fprint(2, "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(d, r);} staticvoiddrawflush(Draw *d){	if(d->flushrect.min.x < d->flushrect.max.x)		xflushmemscreen(d->window, d->flushrect);	d->flushrect = Rect(10000, 10000, -10000, -10000);} staticintdrawcmp(char *a, char *b, int n){	if(strlen(a) != n)		return 1;	return memcmp(a, b, n);} staticDName*drawlookupname(int n, char *str){	DName *name, *ename; 	name = dname;	ename = &name[ndname];	for(; name<ename; name++)		if(drawcmp(name->name, str, n) == 0)			return name;	return 0;} staticintdrawgoodname(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;} staticDImage*drawlookup(DClient *client, int id, int checkname){	DImage *d; 	d = client->dimage[id&HASHMASK];	while(d){		if(d->id == id){			if(checkname && !drawgoodname(d))				return 0; /* BUG: error(Eoldname); */			return d;		}		d = d->next;	}	return 0;} staticDScreen*drawlookupdscreen(Draw *draw, int id){	DScreen *s; 	s = draw->dscreen;	while(s){		if(s->id == id)			return s;		s = s->next;	}	return 0;} staticDScreen*drawlookupscreen(DClient *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;	}	/* caller must check! */	/* BUG: error(Enodrawscreen); */	return 0;} staticDImage*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;} staticMemimage*drawinstall(DClient *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;} staticMemscreen*drawinstallscreen(DClient *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)		fatal("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 = client->draw->dscreen;		d->owner = client;		client->draw->dscreen = d;	}	c->dscreen = d;	d->ref++;	c->next = client->cscreen;	client->cscreen = c;	return d->screen;} staticvoiddrawdelname(DName *name){	int i; 	i = name-dname;	memmove(name, name+1, (ndname-(i+1))*sizeof(DName));	ndname--;} staticvoiddrawfreedscreen(Draw *d, DScreen *this){	DScreen *ds, *next; 	this->ref--;	if(this->ref < 0)		fprint(2, "negative ref in drawfreedscreen\n");	if(this->ref > 0)		return;	ds = d->dscreen;	if(ds == this){		d->dscreen = this->next;		goto Found;	}	while(next = ds->next){	/* assign = */		if(next == this){			ds->next = this->next;			goto Found;		}		ds = next;	}	/* BUG: error(Enodrawimage); */	return; Found:	if(this->dimage)		drawfreedimage(d, this->dimage);	if(this->dfill)		drawfreedimage(d, this->dfill);	free(this->screen);	free(this);} staticvoiddrawfreedimage(Draw *d, DImage *dimage){	int i;	Memimage *l, *screenimage;	DScreen *ds; 	dimage->ref--;	if(dimage->ref < 0)		fprint(2, "negative ref in drawfreedimage\n");	if(dimage->ref > 0)

Lines 1–500 of 1992.