xref: /inferno-os/libinterp/draw.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include <lib9.h>
2*37da2899SCharles.Forsyth #include <kernel.h>
3*37da2899SCharles.Forsyth #include "interp.h"
4*37da2899SCharles.Forsyth #include "isa.h"
5*37da2899SCharles.Forsyth #include "runt.h"
6*37da2899SCharles.Forsyth #include "raise.h"
7*37da2899SCharles.Forsyth #include "drawmod.h"
8*37da2899SCharles.Forsyth #include "draw.h"
9*37da2899SCharles.Forsyth #include "drawif.h"
10*37da2899SCharles.Forsyth #include "memdraw.h"
11*37da2899SCharles.Forsyth #include "memlayer.h"
12*37da2899SCharles.Forsyth 
13*37da2899SCharles.Forsyth /*
14*37da2899SCharles.Forsyth  * When a Display is remote, it must be locked to synchronize the
15*37da2899SCharles.Forsyth  * outgoing message buffer with the refresh demon, which runs as a
16*37da2899SCharles.Forsyth  * different process.  When it is local, the refresh demon does nothing
17*37da2899SCharles.Forsyth  * and it is sufficient to use the interpreter's own acquire/release protection
18*37da2899SCharles.Forsyth  * to lock the buffer.
19*37da2899SCharles.Forsyth  *
20*37da2899SCharles.Forsyth  * Most action to the buffer is caused by calls from Limbo, so locking at
21*37da2899SCharles.Forsyth  * the top before going into the library is good enough.  However, the
22*37da2899SCharles.Forsyth  * garbage collector can call the free routines at other times, so they
23*37da2899SCharles.Forsyth  * need to protect themselves whether called through the Draw module
24*37da2899SCharles.Forsyth  * or not; hence the need for check against recursive locking in lockdisplay().
25*37da2899SCharles.Forsyth  * This also means that we needn't lock around calls to destroy if it's
26*37da2899SCharles.Forsyth  * extra work to do so.
27*37da2899SCharles.Forsyth  */
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth typedef struct Cache Cache;
30*37da2899SCharles.Forsyth typedef struct DRef DRef;
31*37da2899SCharles.Forsyth typedef struct DDisplay DDisplay;
32*37da2899SCharles.Forsyth typedef struct DImage DImage;
33*37da2899SCharles.Forsyth typedef struct DScreen DScreen;
34*37da2899SCharles.Forsyth typedef struct DFont DFont;
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth struct Cache
37*37da2899SCharles.Forsyth {
38*37da2899SCharles.Forsyth 	int	ref;
39*37da2899SCharles.Forsyth 	char*	name;
40*37da2899SCharles.Forsyth 	Display*display;
41*37da2899SCharles.Forsyth 	union{
42*37da2899SCharles.Forsyth 		Subfont*	sf;
43*37da2899SCharles.Forsyth 		Font*		f;
44*37da2899SCharles.Forsyth 		void*		ptr;
45*37da2899SCharles.Forsyth 	}u;
46*37da2899SCharles.Forsyth 	Cache*	next;
47*37da2899SCharles.Forsyth };
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth /* not visible to Limbo; used only for internal reference counting */
50*37da2899SCharles.Forsyth struct DRef
51*37da2899SCharles.Forsyth {
52*37da2899SCharles.Forsyth 	int		ref;
53*37da2899SCharles.Forsyth 	Display*	display;
54*37da2899SCharles.Forsyth };
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth struct DDisplay
57*37da2899SCharles.Forsyth {
58*37da2899SCharles.Forsyth 	Draw_Display	drawdisplay;
59*37da2899SCharles.Forsyth 	Display*	display;
60*37da2899SCharles.Forsyth 	DRef*		dref;
61*37da2899SCharles.Forsyth };
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth struct DImage
64*37da2899SCharles.Forsyth {
65*37da2899SCharles.Forsyth 	Draw_Image	drawimage;
66*37da2899SCharles.Forsyth 	Image*		image;
67*37da2899SCharles.Forsyth 	void*		refreshptr;
68*37da2899SCharles.Forsyth 	DRef*		dref;
69*37da2899SCharles.Forsyth 	int		flush;
70*37da2899SCharles.Forsyth };
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth struct DScreen
73*37da2899SCharles.Forsyth {
74*37da2899SCharles.Forsyth 	Draw_Screen	drawscreen;
75*37da2899SCharles.Forsyth 	Screen*		screen;
76*37da2899SCharles.Forsyth 	DRef*		dref;
77*37da2899SCharles.Forsyth };
78*37da2899SCharles.Forsyth 
79*37da2899SCharles.Forsyth struct DFont
80*37da2899SCharles.Forsyth {
81*37da2899SCharles.Forsyth 	Draw_Font	drawfont;
82*37da2899SCharles.Forsyth 	Font*		font;
83*37da2899SCharles.Forsyth 	DRef*		dref;
84*37da2899SCharles.Forsyth };
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth Cache*	sfcache[BIHASH];
87*37da2899SCharles.Forsyth Cache*	fcache[BIHASH];
88*37da2899SCharles.Forsyth void*	cacheqlock;
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth static	Cache	*cachelookup(Cache**, Display*, char*);
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth uchar fontmap[] = Draw_Font_map;
93*37da2899SCharles.Forsyth uchar imagemap[] = Draw_Image_map;
94*37da2899SCharles.Forsyth uchar screenmap[] = Draw_Screen_map;
95*37da2899SCharles.Forsyth uchar displaymap[] = Draw_Display_map;
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth Type*	TFont;
98*37da2899SCharles.Forsyth Type*	TImage;
99*37da2899SCharles.Forsyth Type*	TScreen;
100*37da2899SCharles.Forsyth Type*	TDisplay;
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth Draw_Image*	allocdrawimage(DDisplay*, Draw_Rect, ulong, Image*, int, int);
103*37da2899SCharles.Forsyth Draw_Image*	color(DDisplay*, ulong);
104*37da2899SCharles.Forsyth Draw_Screen	*mkdrawscreen(Screen*, Draw_Display*);
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth char		deffontname[] = "*default*";
107*37da2899SCharles.Forsyth void		refreshslave(Display*);
108*37da2899SCharles.Forsyth void		subfont_close(Subfont*);
109*37da2899SCharles.Forsyth void		freeallsubfonts(Display*);
110*37da2899SCharles.Forsyth 
111*37da2899SCharles.Forsyth void
drawmodinit(void)112*37da2899SCharles.Forsyth drawmodinit(void)
113*37da2899SCharles.Forsyth {
114*37da2899SCharles.Forsyth 	TFont = dtype(freedrawfont, sizeof(DFont), fontmap, sizeof(fontmap));
115*37da2899SCharles.Forsyth 	TImage = dtype(freedrawimage, sizeof(DImage), imagemap, sizeof(imagemap));
116*37da2899SCharles.Forsyth 	TScreen = dtype(freedrawscreen, sizeof(DScreen), screenmap, sizeof(screenmap));
117*37da2899SCharles.Forsyth 	TDisplay = dtype(freedrawdisplay, sizeof(DDisplay), displaymap, sizeof(displaymap));
118*37da2899SCharles.Forsyth 	builtinmod("$Draw", Drawmodtab, Drawmodlen);
119*37da2899SCharles.Forsyth }
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth static int
drawhash(char * s)122*37da2899SCharles.Forsyth drawhash(char *s)
123*37da2899SCharles.Forsyth {
124*37da2899SCharles.Forsyth 	int h;
125*37da2899SCharles.Forsyth 
126*37da2899SCharles.Forsyth 	h = 0;
127*37da2899SCharles.Forsyth 	while(*s){
128*37da2899SCharles.Forsyth 		h += *s++;
129*37da2899SCharles.Forsyth 		h <<= 1;
130*37da2899SCharles.Forsyth 		if(h & (1<<8))
131*37da2899SCharles.Forsyth 			h |= 1;
132*37da2899SCharles.Forsyth 	}
133*37da2899SCharles.Forsyth 	return (h&0xFFFF)%BIHASH;
134*37da2899SCharles.Forsyth }
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth static Cache*
cachelookup(Cache * cache[],Display * d,char * name)137*37da2899SCharles.Forsyth cachelookup(Cache *cache[], Display *d, char *name)
138*37da2899SCharles.Forsyth {
139*37da2899SCharles.Forsyth 	Cache *c;
140*37da2899SCharles.Forsyth 
141*37da2899SCharles.Forsyth 	libqlock(cacheqlock);
142*37da2899SCharles.Forsyth 	c = cache[drawhash(name)];
143*37da2899SCharles.Forsyth 	while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0))
144*37da2899SCharles.Forsyth 		c = c->next;
145*37da2899SCharles.Forsyth 	libqunlock(cacheqlock);
146*37da2899SCharles.Forsyth 	return c;
147*37da2899SCharles.Forsyth }
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth Cache*
cacheinstall(Cache ** cache,Display * d,char * name,void * ptr,char * type)150*37da2899SCharles.Forsyth cacheinstall(Cache **cache, Display *d, char *name, void *ptr, char *type)
151*37da2899SCharles.Forsyth {
152*37da2899SCharles.Forsyth 	Cache *c;
153*37da2899SCharles.Forsyth 	int hash;
154*37da2899SCharles.Forsyth 
155*37da2899SCharles.Forsyth 	USED(type);
156*37da2899SCharles.Forsyth 	c = cachelookup(cache, d, name);
157*37da2899SCharles.Forsyth 	if(c){
158*37da2899SCharles.Forsyth /*		print("%s %s already in cache\n", type, name); /**/
159*37da2899SCharles.Forsyth 		return nil;
160*37da2899SCharles.Forsyth 	}
161*37da2899SCharles.Forsyth 	c = malloc(sizeof(Cache));
162*37da2899SCharles.Forsyth 	if(c == nil)
163*37da2899SCharles.Forsyth 		return nil;
164*37da2899SCharles.Forsyth 	hash = drawhash(name);
165*37da2899SCharles.Forsyth 	c->ref = 0;	/* will be incremented by caller */
166*37da2899SCharles.Forsyth 	c->display = d;
167*37da2899SCharles.Forsyth 	c->name = strdup(name);
168*37da2899SCharles.Forsyth 	c->u.ptr = ptr;
169*37da2899SCharles.Forsyth 	libqlock(cacheqlock);
170*37da2899SCharles.Forsyth 	c->next = cache[hash];
171*37da2899SCharles.Forsyth 	cache[hash] = c;
172*37da2899SCharles.Forsyth 	libqunlock(cacheqlock);
173*37da2899SCharles.Forsyth 	return c;
174*37da2899SCharles.Forsyth }
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth void
cacheuninstall(Cache ** cache,Display * d,char * name,char * type)177*37da2899SCharles.Forsyth cacheuninstall(Cache **cache, Display *d, char *name, char *type)
178*37da2899SCharles.Forsyth {
179*37da2899SCharles.Forsyth 	Cache *c, *prev;
180*37da2899SCharles.Forsyth 	int hash;
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth 	hash = drawhash(name);
183*37da2899SCharles.Forsyth 	libqlock(cacheqlock);
184*37da2899SCharles.Forsyth 	c = cache[hash];
185*37da2899SCharles.Forsyth 	if(c == nil){
186*37da2899SCharles.Forsyth    Notfound:
187*37da2899SCharles.Forsyth 		libqunlock(cacheqlock);
188*37da2899SCharles.Forsyth 		print("%s not in %s cache\n", name, type);
189*37da2899SCharles.Forsyth 		return;
190*37da2899SCharles.Forsyth 	}
191*37da2899SCharles.Forsyth 	prev = nil;
192*37da2899SCharles.Forsyth 	while(c!=nil && (d!=c->display || strcmp(name, c->name)!=0)){
193*37da2899SCharles.Forsyth 		prev = c;
194*37da2899SCharles.Forsyth 		c = c->next;
195*37da2899SCharles.Forsyth 	}
196*37da2899SCharles.Forsyth 	if(c == nil)
197*37da2899SCharles.Forsyth 		goto Notfound;
198*37da2899SCharles.Forsyth 	if(prev == 0)
199*37da2899SCharles.Forsyth 		cache[hash] = c->next;
200*37da2899SCharles.Forsyth 	else
201*37da2899SCharles.Forsyth 		prev->next = c->next;
202*37da2899SCharles.Forsyth 	libqunlock(cacheqlock);
203*37da2899SCharles.Forsyth 	free(c->name);
204*37da2899SCharles.Forsyth 	free(c);
205*37da2899SCharles.Forsyth }
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth Image*
lookupimage(Draw_Image * di)208*37da2899SCharles.Forsyth lookupimage(Draw_Image *di)
209*37da2899SCharles.Forsyth {
210*37da2899SCharles.Forsyth 	Display *disp;
211*37da2899SCharles.Forsyth 	Image *i;
212*37da2899SCharles.Forsyth 	int locked;
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth 	if(di == H || D2H(di)->t != TImage)
215*37da2899SCharles.Forsyth 		return nil;
216*37da2899SCharles.Forsyth 	i = ((DImage*)di)->image;
217*37da2899SCharles.Forsyth 	if(i == nil)
218*37da2899SCharles.Forsyth 		return nil;
219*37da2899SCharles.Forsyth 	if(!eqrect(IRECT(di->clipr), i->clipr) || di->repl!=i->repl){
220*37da2899SCharles.Forsyth 		disp = i->display;
221*37da2899SCharles.Forsyth 		locked = lockdisplay(disp);
222*37da2899SCharles.Forsyth 		replclipr(i, di->repl, IRECT(di->clipr));
223*37da2899SCharles.Forsyth 		if(locked)
224*37da2899SCharles.Forsyth 			unlockdisplay(disp);
225*37da2899SCharles.Forsyth 	}
226*37da2899SCharles.Forsyth 	return i;
227*37da2899SCharles.Forsyth }
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth Screen*
lookupscreen(Draw_Screen * ds)230*37da2899SCharles.Forsyth lookupscreen(Draw_Screen *ds)
231*37da2899SCharles.Forsyth {
232*37da2899SCharles.Forsyth 	if(ds == H || D2H(ds)->t != TScreen)
233*37da2899SCharles.Forsyth 		return nil;
234*37da2899SCharles.Forsyth 	return ((DScreen*)ds)->screen;
235*37da2899SCharles.Forsyth }
236*37da2899SCharles.Forsyth 
237*37da2899SCharles.Forsyth Font*
lookupfont(Draw_Font * df)238*37da2899SCharles.Forsyth lookupfont(Draw_Font *df)
239*37da2899SCharles.Forsyth {
240*37da2899SCharles.Forsyth 	if(df == H || D2H(df)->t != TFont)
241*37da2899SCharles.Forsyth 		return nil;
242*37da2899SCharles.Forsyth 	return ((DFont*)df)->font;
243*37da2899SCharles.Forsyth }
244*37da2899SCharles.Forsyth 
245*37da2899SCharles.Forsyth Display*
lookupdisplay(Draw_Display * dd)246*37da2899SCharles.Forsyth lookupdisplay(Draw_Display *dd)
247*37da2899SCharles.Forsyth {
248*37da2899SCharles.Forsyth 	if(dd == H || D2H(dd)->t != TDisplay)
249*37da2899SCharles.Forsyth 		return nil;
250*37da2899SCharles.Forsyth 	return ((DDisplay*)dd)->display;
251*37da2899SCharles.Forsyth }
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth Image*
checkimage(Draw_Image * di)254*37da2899SCharles.Forsyth checkimage(Draw_Image *di)
255*37da2899SCharles.Forsyth {
256*37da2899SCharles.Forsyth 	Image *i;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 	if(di == H)
259*37da2899SCharles.Forsyth 		error("nil Image");
260*37da2899SCharles.Forsyth 	i = lookupimage(di);
261*37da2899SCharles.Forsyth 	if(i == nil)
262*37da2899SCharles.Forsyth 		error(exType);
263*37da2899SCharles.Forsyth 	return i;
264*37da2899SCharles.Forsyth }
265*37da2899SCharles.Forsyth 
266*37da2899SCharles.Forsyth Screen*
checkscreen(Draw_Screen * ds)267*37da2899SCharles.Forsyth checkscreen(Draw_Screen *ds)
268*37da2899SCharles.Forsyth {
269*37da2899SCharles.Forsyth 	Screen *s;
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth 	if(ds == H)
272*37da2899SCharles.Forsyth 		error("nil Screen");
273*37da2899SCharles.Forsyth 	s = lookupscreen(ds);
274*37da2899SCharles.Forsyth 	if(s == nil)
275*37da2899SCharles.Forsyth 		error(exType);
276*37da2899SCharles.Forsyth 	return s;
277*37da2899SCharles.Forsyth }
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth Font*
checkfont(Draw_Font * df)280*37da2899SCharles.Forsyth checkfont(Draw_Font *df)
281*37da2899SCharles.Forsyth {
282*37da2899SCharles.Forsyth 	Font *f;
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth 	if(df == H)
285*37da2899SCharles.Forsyth 		error("nil Font");
286*37da2899SCharles.Forsyth 	f = lookupfont(df);
287*37da2899SCharles.Forsyth 	if(f == nil)
288*37da2899SCharles.Forsyth 		error(exType);
289*37da2899SCharles.Forsyth 	return f;
290*37da2899SCharles.Forsyth }
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth Display*
checkdisplay(Draw_Display * dd)293*37da2899SCharles.Forsyth checkdisplay(Draw_Display *dd)
294*37da2899SCharles.Forsyth {
295*37da2899SCharles.Forsyth 	Display *d;
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth 	if(dd == H)
298*37da2899SCharles.Forsyth 		error("nil Display");
299*37da2899SCharles.Forsyth 	d = lookupdisplay(dd);
300*37da2899SCharles.Forsyth 	if(d == nil)
301*37da2899SCharles.Forsyth 		error(exType);
302*37da2899SCharles.Forsyth 	return d;
303*37da2899SCharles.Forsyth }
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth void
Display_allocate(void * fp)306*37da2899SCharles.Forsyth Display_allocate(void *fp)
307*37da2899SCharles.Forsyth {
308*37da2899SCharles.Forsyth 	F_Display_allocate *f;
309*37da2899SCharles.Forsyth 	char buf[128], *dev;
310*37da2899SCharles.Forsyth 	Subfont *df;
311*37da2899SCharles.Forsyth 	Display *display;
312*37da2899SCharles.Forsyth 	DDisplay *dd;
313*37da2899SCharles.Forsyth 	Heap *h;
314*37da2899SCharles.Forsyth 	Draw_Rect r;
315*37da2899SCharles.Forsyth 	DRef *dr;
316*37da2899SCharles.Forsyth 	Cache *c;
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 	f = fp;
319*37da2899SCharles.Forsyth 	destroy(*f->ret);
320*37da2899SCharles.Forsyth 	*f->ret = H;
321*37da2899SCharles.Forsyth 	if(cacheqlock == nil){
322*37da2899SCharles.Forsyth 		cacheqlock = libqlalloc();
323*37da2899SCharles.Forsyth 		if(cacheqlock == nil)
324*37da2899SCharles.Forsyth 			return;
325*37da2899SCharles.Forsyth 	}
326*37da2899SCharles.Forsyth 	dev = string2c(f->dev);
327*37da2899SCharles.Forsyth 	if(dev[0] == 0)
328*37da2899SCharles.Forsyth 		dev = 0;
329*37da2899SCharles.Forsyth 	display = initdisplay(dev, dev, nil);	/* TO DO: win, error */
330*37da2899SCharles.Forsyth 	if(display == 0)
331*37da2899SCharles.Forsyth 		return;
332*37da2899SCharles.Forsyth 
333*37da2899SCharles.Forsyth 	dr = malloc(sizeof(DRef));
334*37da2899SCharles.Forsyth 	if(dr == nil)
335*37da2899SCharles.Forsyth 		return;
336*37da2899SCharles.Forsyth 	h = heap(TDisplay);
337*37da2899SCharles.Forsyth 	if(h == H){
338*37da2899SCharles.Forsyth 		closedisplay(display);
339*37da2899SCharles.Forsyth 		return;
340*37da2899SCharles.Forsyth 	}
341*37da2899SCharles.Forsyth 	dd = H2D(DDisplay*, h);
342*37da2899SCharles.Forsyth 	dd->display = display;
343*37da2899SCharles.Forsyth 	*f->ret = &dd->drawdisplay;
344*37da2899SCharles.Forsyth 	dd->dref = dr;
345*37da2899SCharles.Forsyth 	display->limbo = dr;
346*37da2899SCharles.Forsyth 	dr->display = display;
347*37da2899SCharles.Forsyth 	dr->ref = 1;
348*37da2899SCharles.Forsyth 	df = getdefont(display);
349*37da2899SCharles.Forsyth 	if(df){
350*37da2899SCharles.Forsyth 		display->defaultsubfont = df;
351*37da2899SCharles.Forsyth 		sprint(buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
352*37da2899SCharles.Forsyth 			df->n-1, deffontname);
353*37da2899SCharles.Forsyth 		display->defaultfont = buildfont(display, buf, deffontname);
354*37da2899SCharles.Forsyth 		if(display->defaultfont){
355*37da2899SCharles.Forsyth 			c = cacheinstall(fcache, display, deffontname, display->defaultfont, "font");
356*37da2899SCharles.Forsyth 			if(c)
357*37da2899SCharles.Forsyth 				c->ref++;
358*37da2899SCharles.Forsyth 			/* else BUG? */
359*37da2899SCharles.Forsyth 		}
360*37da2899SCharles.Forsyth 	}
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth 	R2R(r, display->image->r);
363*37da2899SCharles.Forsyth 	dd->drawdisplay.image = allocdrawimage(dd, r, display->image->chan, display->image, 0, 0);
364*37da2899SCharles.Forsyth 	R2R(r, display->white->r);
365*37da2899SCharles.Forsyth 	dd->drawdisplay.black = allocdrawimage(dd, r, display->black->chan, display->black, 1, 0);
366*37da2899SCharles.Forsyth 	dd->drawdisplay.white = allocdrawimage(dd, r, display->white->chan, display->white, 1, 0);
367*37da2899SCharles.Forsyth 	dd->drawdisplay.opaque = allocdrawimage(dd, r, display->opaque->chan, display->opaque, 1, 0);
368*37da2899SCharles.Forsyth 	dd->drawdisplay.transparent = allocdrawimage(dd, r, display->transparent->chan, display->transparent, 1, 0);
369*37da2899SCharles.Forsyth 
370*37da2899SCharles.Forsyth 	/* don't call unlockdisplay because the qlock was left up by initdisplay */
371*37da2899SCharles.Forsyth 	libqunlock(display->qlock);
372*37da2899SCharles.Forsyth }
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth void
Display_getwindow(void * fp)375*37da2899SCharles.Forsyth Display_getwindow(void *fp)
376*37da2899SCharles.Forsyth {
377*37da2899SCharles.Forsyth 	F_Display_getwindow *f;
378*37da2899SCharles.Forsyth 	Display *disp;
379*37da2899SCharles.Forsyth 	int locked;
380*37da2899SCharles.Forsyth 	Image *image;
381*37da2899SCharles.Forsyth 	Screen *screen;
382*37da2899SCharles.Forsyth 	char *wn;
383*37da2899SCharles.Forsyth 	void *r;
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth 	f = fp;
386*37da2899SCharles.Forsyth 	r = f->ret->t0;
387*37da2899SCharles.Forsyth 	f->ret->t0 = H;
388*37da2899SCharles.Forsyth 	destroy(r);
389*37da2899SCharles.Forsyth 	r = f->ret->t1;
390*37da2899SCharles.Forsyth 	f->ret->t1 = H;
391*37da2899SCharles.Forsyth 	destroy(r);
392*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
393*37da2899SCharles.Forsyth 	if(f->winname == H)
394*37da2899SCharles.Forsyth 		wn = "/dev/winname";
395*37da2899SCharles.Forsyth 	else
396*37da2899SCharles.Forsyth 		wn = string2c(f->winname);
397*37da2899SCharles.Forsyth 	if(f->image == H)
398*37da2899SCharles.Forsyth 		image = nil;
399*37da2899SCharles.Forsyth 	else
400*37da2899SCharles.Forsyth 		image = checkimage(f->image);
401*37da2899SCharles.Forsyth 	if(f->screen == H)
402*37da2899SCharles.Forsyth 		screen = nil;
403*37da2899SCharles.Forsyth 	else
404*37da2899SCharles.Forsyth 		screen = checkscreen(f->screen);
405*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
406*37da2899SCharles.Forsyth 	if(gengetwindow(disp, wn, &image, &screen, f->backup) < 0){
407*37da2899SCharles.Forsyth 		/* TO DO: eliminate f->image and f->screen's references to Image and Screen */
408*37da2899SCharles.Forsyth 		goto Return;
409*37da2899SCharles.Forsyth 	}
410*37da2899SCharles.Forsyth 	if(screen != nil){
411*37da2899SCharles.Forsyth 		if(f->screen != H){
412*37da2899SCharles.Forsyth 			f->ret->t0 = f->screen;
413*37da2899SCharles.Forsyth 			D2H(f->screen)->ref++;
414*37da2899SCharles.Forsyth 		}else
415*37da2899SCharles.Forsyth 			f->ret->t0 = mkdrawscreen(screen, f->d);
416*37da2899SCharles.Forsyth 	}
417*37da2899SCharles.Forsyth 	if(image != nil){
418*37da2899SCharles.Forsyth 		if(f->image != H){
419*37da2899SCharles.Forsyth 			f->ret->t1 = f->image;
420*37da2899SCharles.Forsyth 			D2H(f->image)->ref++;
421*37da2899SCharles.Forsyth 		}else
422*37da2899SCharles.Forsyth 			f->ret->t1 = mkdrawimage(image, f->ret->t0, f->d, nil);
423*37da2899SCharles.Forsyth 	}
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth Return:
426*37da2899SCharles.Forsyth 	if(locked)
427*37da2899SCharles.Forsyth 		unlockdisplay(disp);
428*37da2899SCharles.Forsyth }
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth void
Display_startrefresh(void * fp)431*37da2899SCharles.Forsyth Display_startrefresh(void *fp)
432*37da2899SCharles.Forsyth {
433*37da2899SCharles.Forsyth 	F_Display_startrefresh *f;
434*37da2899SCharles.Forsyth 	Display *disp;
435*37da2899SCharles.Forsyth 
436*37da2899SCharles.Forsyth 	f = fp;
437*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
438*37da2899SCharles.Forsyth 	refreshslave(disp);
439*37da2899SCharles.Forsyth }
440*37da2899SCharles.Forsyth 
441*37da2899SCharles.Forsyth void
display_dec(void * v)442*37da2899SCharles.Forsyth display_dec(void *v)
443*37da2899SCharles.Forsyth {
444*37da2899SCharles.Forsyth 	DRef *dr;
445*37da2899SCharles.Forsyth 	Display *d;
446*37da2899SCharles.Forsyth 	int locked;
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth 	dr = v;
449*37da2899SCharles.Forsyth 	if(dr->ref-- != 1)
450*37da2899SCharles.Forsyth 		return;
451*37da2899SCharles.Forsyth 
452*37da2899SCharles.Forsyth 	d = dr->display;
453*37da2899SCharles.Forsyth 	locked = lockdisplay(d);
454*37da2899SCharles.Forsyth 	font_close(d->defaultfont);
455*37da2899SCharles.Forsyth 	subfont_close(d->defaultsubfont);
456*37da2899SCharles.Forsyth 	if(locked)
457*37da2899SCharles.Forsyth 		unlockdisplay(d);
458*37da2899SCharles.Forsyth 	freeallsubfonts(d);
459*37da2899SCharles.Forsyth 	closedisplay(d);
460*37da2899SCharles.Forsyth 	free(dr);
461*37da2899SCharles.Forsyth }
462*37da2899SCharles.Forsyth 
463*37da2899SCharles.Forsyth void
freedrawdisplay(Heap * h,int swept)464*37da2899SCharles.Forsyth freedrawdisplay(Heap *h, int swept)
465*37da2899SCharles.Forsyth {
466*37da2899SCharles.Forsyth 	DDisplay *dd;
467*37da2899SCharles.Forsyth 	Display *d;
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth 	dd = H2D(DDisplay*, h);
470*37da2899SCharles.Forsyth 
471*37da2899SCharles.Forsyth 	if(!swept) {
472*37da2899SCharles.Forsyth 		destroy(dd->drawdisplay.image);
473*37da2899SCharles.Forsyth 		destroy(dd->drawdisplay.black);
474*37da2899SCharles.Forsyth 		destroy(dd->drawdisplay.white);
475*37da2899SCharles.Forsyth 		destroy(dd->drawdisplay.opaque);
476*37da2899SCharles.Forsyth 		destroy(dd->drawdisplay.transparent);
477*37da2899SCharles.Forsyth 	}
478*37da2899SCharles.Forsyth 	/* we've now released dd->image etc.; make sure they're not freed again */
479*37da2899SCharles.Forsyth 	d = dd->display;
480*37da2899SCharles.Forsyth 	d->image = nil;
481*37da2899SCharles.Forsyth 	d->white = nil;
482*37da2899SCharles.Forsyth 	d->black = nil;
483*37da2899SCharles.Forsyth 	d->opaque = nil;
484*37da2899SCharles.Forsyth 	d->transparent = nil;
485*37da2899SCharles.Forsyth 	display_dec(dd->dref);
486*37da2899SCharles.Forsyth 	/* Draw_Display header will be freed by caller */
487*37da2899SCharles.Forsyth }
488*37da2899SCharles.Forsyth 
489*37da2899SCharles.Forsyth void
Display_color(void * fp)490*37da2899SCharles.Forsyth Display_color(void *fp)
491*37da2899SCharles.Forsyth {
492*37da2899SCharles.Forsyth 	F_Display_color *f;
493*37da2899SCharles.Forsyth 	Display *d;
494*37da2899SCharles.Forsyth 	int locked;
495*37da2899SCharles.Forsyth 
496*37da2899SCharles.Forsyth 	f = fp;
497*37da2899SCharles.Forsyth 	destroy(*f->ret);
498*37da2899SCharles.Forsyth 	*f->ret = H;
499*37da2899SCharles.Forsyth 	d = checkdisplay(f->d);
500*37da2899SCharles.Forsyth 	locked = lockdisplay(d);
501*37da2899SCharles.Forsyth 	*f->ret = color((DDisplay*)f->d, f->color);
502*37da2899SCharles.Forsyth 	if(locked)
503*37da2899SCharles.Forsyth 		unlockdisplay(d);
504*37da2899SCharles.Forsyth }
505*37da2899SCharles.Forsyth 
506*37da2899SCharles.Forsyth void
Image_flush(void * fp)507*37da2899SCharles.Forsyth Image_flush(void *fp)
508*37da2899SCharles.Forsyth {
509*37da2899SCharles.Forsyth 	F_Image_flush *f;
510*37da2899SCharles.Forsyth 	Image *d;
511*37da2899SCharles.Forsyth 	DImage *di;
512*37da2899SCharles.Forsyth 	int locked;
513*37da2899SCharles.Forsyth 
514*37da2899SCharles.Forsyth 	f = fp;
515*37da2899SCharles.Forsyth 	d = checkimage(f->win);
516*37da2899SCharles.Forsyth 	di = (DImage*)f->win;
517*37da2899SCharles.Forsyth 	switch(f->func){
518*37da2899SCharles.Forsyth 	case 0:	/* Draw->Flushoff */
519*37da2899SCharles.Forsyth 		di->flush = 0;
520*37da2899SCharles.Forsyth 		break;
521*37da2899SCharles.Forsyth 	case 1:	/* Draw->Flushon */
522*37da2899SCharles.Forsyth 		di->flush = 1;
523*37da2899SCharles.Forsyth 		/* fall through */
524*37da2899SCharles.Forsyth 	case 2:	/* Draw->Flushnow */
525*37da2899SCharles.Forsyth 		locked = lockdisplay(d->display);
526*37da2899SCharles.Forsyth 		if(d->id==0 || d->screen!=0)
527*37da2899SCharles.Forsyth 			flushimage(d->display, 1);
528*37da2899SCharles.Forsyth 		if(locked)
529*37da2899SCharles.Forsyth 			unlockdisplay(d->display);
530*37da2899SCharles.Forsyth 		break;
531*37da2899SCharles.Forsyth 	default:
532*37da2899SCharles.Forsyth 		error(exInval);
533*37da2899SCharles.Forsyth 	}
534*37da2899SCharles.Forsyth }
535*37da2899SCharles.Forsyth 
536*37da2899SCharles.Forsyth void
checkflush(Draw_Image * dst)537*37da2899SCharles.Forsyth checkflush(Draw_Image *dst)
538*37da2899SCharles.Forsyth {
539*37da2899SCharles.Forsyth 	DImage  *di;
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth 	di = (DImage*)dst;
542*37da2899SCharles.Forsyth 	if(di->flush && (di->image->id==0 || di->image->screen!=nil))
543*37da2899SCharles.Forsyth 		flushimage(di->image->display, 1);
544*37da2899SCharles.Forsyth }
545*37da2899SCharles.Forsyth 
546*37da2899SCharles.Forsyth static void
imagedraw(void * fp,int op)547*37da2899SCharles.Forsyth imagedraw(void *fp, int op)
548*37da2899SCharles.Forsyth {
549*37da2899SCharles.Forsyth 	F_Image_draw *f;
550*37da2899SCharles.Forsyth 	Image *d, *s, *m;
551*37da2899SCharles.Forsyth 	int locked;
552*37da2899SCharles.Forsyth 
553*37da2899SCharles.Forsyth 	f = fp;
554*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
555*37da2899SCharles.Forsyth 	if(f->src == H)
556*37da2899SCharles.Forsyth 		s = d->display->black;
557*37da2899SCharles.Forsyth 	else
558*37da2899SCharles.Forsyth 		s = checkimage(f->src);
559*37da2899SCharles.Forsyth 	if(f->matte == H)
560*37da2899SCharles.Forsyth 		m = d->display->white;	/* ones */
561*37da2899SCharles.Forsyth 	else
562*37da2899SCharles.Forsyth 		m = checkimage(f->matte);
563*37da2899SCharles.Forsyth 	if(d->display!=s->display || d->display!=m->display)
564*37da2899SCharles.Forsyth 		return;
565*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
566*37da2899SCharles.Forsyth 	drawop(d, IRECT(f->r), s, m, IPOINT(f->p), op);
567*37da2899SCharles.Forsyth 	checkflush(f->dst);
568*37da2899SCharles.Forsyth 	if(locked)
569*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
570*37da2899SCharles.Forsyth }
571*37da2899SCharles.Forsyth 
572*37da2899SCharles.Forsyth void
Image_draw(void * fp)573*37da2899SCharles.Forsyth Image_draw(void *fp)
574*37da2899SCharles.Forsyth {
575*37da2899SCharles.Forsyth 	imagedraw(fp, SoverD);
576*37da2899SCharles.Forsyth }
577*37da2899SCharles.Forsyth 
578*37da2899SCharles.Forsyth void
Image_drawop(void * fp)579*37da2899SCharles.Forsyth Image_drawop(void *fp)
580*37da2899SCharles.Forsyth {
581*37da2899SCharles.Forsyth 	F_Image_drawop *f;
582*37da2899SCharles.Forsyth 
583*37da2899SCharles.Forsyth 	f = fp;
584*37da2899SCharles.Forsyth 	imagedraw(fp, f->op);
585*37da2899SCharles.Forsyth }
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth static void
imagegendraw(void * fp,int op)588*37da2899SCharles.Forsyth imagegendraw(void *fp, int op)
589*37da2899SCharles.Forsyth {
590*37da2899SCharles.Forsyth 	F_Image_gendraw *f;
591*37da2899SCharles.Forsyth 	Image *d, *s, *m;
592*37da2899SCharles.Forsyth 	int locked;
593*37da2899SCharles.Forsyth 
594*37da2899SCharles.Forsyth 	f = fp;
595*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
596*37da2899SCharles.Forsyth 	if(f->src == H)
597*37da2899SCharles.Forsyth 		s = d->display->black;
598*37da2899SCharles.Forsyth 	else
599*37da2899SCharles.Forsyth 		s = checkimage(f->src);
600*37da2899SCharles.Forsyth 	if(f->matte == H)
601*37da2899SCharles.Forsyth 		m = d->display->white;	/* ones */
602*37da2899SCharles.Forsyth 	else
603*37da2899SCharles.Forsyth 		m = checkimage(f->matte);
604*37da2899SCharles.Forsyth 	if(d->display!=s->display || d->display!=m->display)
605*37da2899SCharles.Forsyth 		return;
606*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
607*37da2899SCharles.Forsyth 	gendrawop(d, IRECT(f->r), s, IPOINT(f->p0), m, IPOINT(f->p1), op);
608*37da2899SCharles.Forsyth 	checkflush(f->dst);
609*37da2899SCharles.Forsyth 	if(locked)
610*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
611*37da2899SCharles.Forsyth }
612*37da2899SCharles.Forsyth 
613*37da2899SCharles.Forsyth void
Image_gendraw(void * fp)614*37da2899SCharles.Forsyth Image_gendraw(void *fp)
615*37da2899SCharles.Forsyth {
616*37da2899SCharles.Forsyth 	imagegendraw(fp, SoverD);
617*37da2899SCharles.Forsyth }
618*37da2899SCharles.Forsyth 
619*37da2899SCharles.Forsyth void
Image_gendrawop(void * fp)620*37da2899SCharles.Forsyth Image_gendrawop(void *fp)
621*37da2899SCharles.Forsyth {
622*37da2899SCharles.Forsyth 	F_Image_gendrawop *f;
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth 	f = fp;
625*37da2899SCharles.Forsyth 	imagegendraw(fp, f->op);
626*37da2899SCharles.Forsyth }
627*37da2899SCharles.Forsyth 
628*37da2899SCharles.Forsyth static void
drawline(void * fp,int op)629*37da2899SCharles.Forsyth drawline(void *fp, int op)
630*37da2899SCharles.Forsyth {
631*37da2899SCharles.Forsyth 	F_Image_line *f;
632*37da2899SCharles.Forsyth 	Image *d, *s;
633*37da2899SCharles.Forsyth 	int locked;
634*37da2899SCharles.Forsyth 
635*37da2899SCharles.Forsyth 	f = fp;
636*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
637*37da2899SCharles.Forsyth 	s = checkimage(f->src);
638*37da2899SCharles.Forsyth 	if(d->display != s->display || f->radius < 0)
639*37da2899SCharles.Forsyth 		return;
640*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
641*37da2899SCharles.Forsyth 	lineop(d, IPOINT(f->p0), IPOINT(f->p1), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
642*37da2899SCharles.Forsyth 	checkflush(f->dst);
643*37da2899SCharles.Forsyth 	if(locked)
644*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
645*37da2899SCharles.Forsyth }
646*37da2899SCharles.Forsyth 
647*37da2899SCharles.Forsyth void
Image_line(void * fp)648*37da2899SCharles.Forsyth Image_line(void *fp)
649*37da2899SCharles.Forsyth {
650*37da2899SCharles.Forsyth 	drawline(fp, SoverD);
651*37da2899SCharles.Forsyth }
652*37da2899SCharles.Forsyth 
653*37da2899SCharles.Forsyth void
Image_lineop(void * fp)654*37da2899SCharles.Forsyth Image_lineop(void *fp)
655*37da2899SCharles.Forsyth {
656*37da2899SCharles.Forsyth 	F_Image_lineop *f;
657*37da2899SCharles.Forsyth 
658*37da2899SCharles.Forsyth 	f = fp;
659*37da2899SCharles.Forsyth 	drawline(fp, f->op);
660*37da2899SCharles.Forsyth }
661*37da2899SCharles.Forsyth 
662*37da2899SCharles.Forsyth static void
drawsplinepoly(void * fp,int smooth,int op)663*37da2899SCharles.Forsyth drawsplinepoly(void *fp, int smooth, int op)
664*37da2899SCharles.Forsyth {
665*37da2899SCharles.Forsyth 	F_Image_poly *f;
666*37da2899SCharles.Forsyth 	Image *d, *s;
667*37da2899SCharles.Forsyth 	int locked;
668*37da2899SCharles.Forsyth 
669*37da2899SCharles.Forsyth 	f = fp;
670*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
671*37da2899SCharles.Forsyth 	s = checkimage(f->src);
672*37da2899SCharles.Forsyth 	if(d->display != s->display|| f->radius < 0)
673*37da2899SCharles.Forsyth 		return;
674*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
675*37da2899SCharles.Forsyth 	/* sleazy: we know that Draw_Points have same shape as Points */
676*37da2899SCharles.Forsyth 	if(smooth)
677*37da2899SCharles.Forsyth 		bezsplineop(d, (Point*)f->p->data, f->p->len,
678*37da2899SCharles.Forsyth 			f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
679*37da2899SCharles.Forsyth 	else
680*37da2899SCharles.Forsyth 		polyop(d, (Point*)f->p->data, f->p->len, f->end0,
681*37da2899SCharles.Forsyth 			f->end1, f->radius, s, IPOINT(f->sp), op);
682*37da2899SCharles.Forsyth 	checkflush(f->dst);
683*37da2899SCharles.Forsyth 	if(locked)
684*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
685*37da2899SCharles.Forsyth }
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth void
Image_poly(void * fp)688*37da2899SCharles.Forsyth Image_poly(void *fp)
689*37da2899SCharles.Forsyth {
690*37da2899SCharles.Forsyth 	drawsplinepoly(fp, 0, SoverD);
691*37da2899SCharles.Forsyth }
692*37da2899SCharles.Forsyth 
693*37da2899SCharles.Forsyth void
Image_polyop(void * fp)694*37da2899SCharles.Forsyth Image_polyop(void *fp)
695*37da2899SCharles.Forsyth {
696*37da2899SCharles.Forsyth 	F_Image_polyop *f;
697*37da2899SCharles.Forsyth 
698*37da2899SCharles.Forsyth 	f = fp;
699*37da2899SCharles.Forsyth 	drawsplinepoly(fp, 0, f->op);
700*37da2899SCharles.Forsyth }
701*37da2899SCharles.Forsyth 
702*37da2899SCharles.Forsyth void
Image_bezspline(void * fp)703*37da2899SCharles.Forsyth Image_bezspline(void *fp)
704*37da2899SCharles.Forsyth {
705*37da2899SCharles.Forsyth 	drawsplinepoly(fp, 1, SoverD);
706*37da2899SCharles.Forsyth }
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth void
Image_bezsplineop(void * fp)709*37da2899SCharles.Forsyth Image_bezsplineop(void *fp)
710*37da2899SCharles.Forsyth {
711*37da2899SCharles.Forsyth 	F_Image_bezsplineop *f;
712*37da2899SCharles.Forsyth 
713*37da2899SCharles.Forsyth 	f = fp;
714*37da2899SCharles.Forsyth 	drawsplinepoly(fp, 1, f->op);
715*37da2899SCharles.Forsyth }
716*37da2899SCharles.Forsyth 
717*37da2899SCharles.Forsyth static void
drawbezier(void * fp,int op)718*37da2899SCharles.Forsyth drawbezier(void *fp, int op)
719*37da2899SCharles.Forsyth {
720*37da2899SCharles.Forsyth 	F_Image_bezier *f;
721*37da2899SCharles.Forsyth 	Image *d, *s;
722*37da2899SCharles.Forsyth 	int locked;
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth 	f = fp;
725*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
726*37da2899SCharles.Forsyth 	s = checkimage(f->src);
727*37da2899SCharles.Forsyth 	if(d->display != s->display || f->radius < 0)
728*37da2899SCharles.Forsyth 		return;
729*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
730*37da2899SCharles.Forsyth 	bezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
731*37da2899SCharles.Forsyth 		  IPOINT(f->d), f->end0, f->end1, f->radius, s, IPOINT(f->sp), op);
732*37da2899SCharles.Forsyth 	checkflush(f->dst);
733*37da2899SCharles.Forsyth 	if(locked)
734*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
735*37da2899SCharles.Forsyth }
736*37da2899SCharles.Forsyth 
737*37da2899SCharles.Forsyth void
Image_bezier(void * fp)738*37da2899SCharles.Forsyth Image_bezier(void *fp)
739*37da2899SCharles.Forsyth {
740*37da2899SCharles.Forsyth 	drawbezier(fp, SoverD);
741*37da2899SCharles.Forsyth }
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth void
Image_bezierop(void * fp)744*37da2899SCharles.Forsyth Image_bezierop(void *fp)
745*37da2899SCharles.Forsyth {
746*37da2899SCharles.Forsyth 	F_Image_bezierop *f;
747*37da2899SCharles.Forsyth 
748*37da2899SCharles.Forsyth 	f = fp;
749*37da2899SCharles.Forsyth 	drawbezier(fp, f->op);
750*37da2899SCharles.Forsyth }
751*37da2899SCharles.Forsyth 
752*37da2899SCharles.Forsyth static void
drawfillbezier(void * fp,int op)753*37da2899SCharles.Forsyth drawfillbezier(void *fp, int op)
754*37da2899SCharles.Forsyth {
755*37da2899SCharles.Forsyth 	F_Image_fillbezier *f;
756*37da2899SCharles.Forsyth 	Image *d, *s;
757*37da2899SCharles.Forsyth 	int locked;
758*37da2899SCharles.Forsyth 
759*37da2899SCharles.Forsyth 	f = fp;
760*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
761*37da2899SCharles.Forsyth 	s = checkimage(f->src);
762*37da2899SCharles.Forsyth 	if(d->display != s->display)
763*37da2899SCharles.Forsyth 		return;
764*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
765*37da2899SCharles.Forsyth 	fillbezierop(d, IPOINT(f->a), IPOINT(f->b), IPOINT(f->c),
766*37da2899SCharles.Forsyth 			IPOINT(f->d), f->wind, s, IPOINT(f->sp), op);
767*37da2899SCharles.Forsyth 	checkflush(f->dst);
768*37da2899SCharles.Forsyth 	if(locked)
769*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
770*37da2899SCharles.Forsyth }
771*37da2899SCharles.Forsyth 
772*37da2899SCharles.Forsyth void
Image_fillbezier(void * fp)773*37da2899SCharles.Forsyth Image_fillbezier(void *fp)
774*37da2899SCharles.Forsyth {
775*37da2899SCharles.Forsyth 	drawfillbezier(fp, SoverD);
776*37da2899SCharles.Forsyth }
777*37da2899SCharles.Forsyth 
778*37da2899SCharles.Forsyth void
Image_fillbezierop(void * fp)779*37da2899SCharles.Forsyth Image_fillbezierop(void *fp)
780*37da2899SCharles.Forsyth {
781*37da2899SCharles.Forsyth 	F_Image_fillbezierop *f;
782*37da2899SCharles.Forsyth 
783*37da2899SCharles.Forsyth 	f = fp;
784*37da2899SCharles.Forsyth 	drawfillbezier(fp, f->op);
785*37da2899SCharles.Forsyth }
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth static void
drawfillsplinepoly(void * fp,int smooth,int op)788*37da2899SCharles.Forsyth drawfillsplinepoly(void *fp, int smooth, int op)
789*37da2899SCharles.Forsyth {
790*37da2899SCharles.Forsyth 	F_Image_fillpoly *f;
791*37da2899SCharles.Forsyth 	Image *d, *s;
792*37da2899SCharles.Forsyth 	int locked;
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth 	f = fp;
795*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
796*37da2899SCharles.Forsyth 	s = checkimage(f->src);
797*37da2899SCharles.Forsyth 	if(d->display != s->display)
798*37da2899SCharles.Forsyth 		return;
799*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
800*37da2899SCharles.Forsyth 	/* sleazy: we know that Draw_Points have same shape as Points */
801*37da2899SCharles.Forsyth 	if(smooth)
802*37da2899SCharles.Forsyth 		fillbezsplineop(d, (Point*)f->p->data, f->p->len,
803*37da2899SCharles.Forsyth 			f->wind, s, IPOINT(f->sp), op);
804*37da2899SCharles.Forsyth 	else
805*37da2899SCharles.Forsyth 		fillpolyop(d, (Point*)f->p->data, f->p->len,
806*37da2899SCharles.Forsyth 			f->wind, s, IPOINT(f->sp), op);
807*37da2899SCharles.Forsyth 	checkflush(f->dst);
808*37da2899SCharles.Forsyth 	if(locked)
809*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
810*37da2899SCharles.Forsyth }
811*37da2899SCharles.Forsyth 
812*37da2899SCharles.Forsyth void
Image_fillpoly(void * fp)813*37da2899SCharles.Forsyth Image_fillpoly(void *fp)
814*37da2899SCharles.Forsyth {
815*37da2899SCharles.Forsyth 	drawfillsplinepoly(fp, 0, SoverD);
816*37da2899SCharles.Forsyth }
817*37da2899SCharles.Forsyth 
818*37da2899SCharles.Forsyth void
Image_fillpolyop(void * fp)819*37da2899SCharles.Forsyth Image_fillpolyop(void *fp)
820*37da2899SCharles.Forsyth {
821*37da2899SCharles.Forsyth 	F_Image_fillpolyop *f;
822*37da2899SCharles.Forsyth 
823*37da2899SCharles.Forsyth 	f = fp;
824*37da2899SCharles.Forsyth 	drawfillsplinepoly(fp, 0, f->op);
825*37da2899SCharles.Forsyth }
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth void
Image_fillbezspline(void * fp)828*37da2899SCharles.Forsyth Image_fillbezspline(void *fp)
829*37da2899SCharles.Forsyth {
830*37da2899SCharles.Forsyth 	drawfillsplinepoly(fp, 1, SoverD);
831*37da2899SCharles.Forsyth }
832*37da2899SCharles.Forsyth 
833*37da2899SCharles.Forsyth void
Image_fillbezsplineop(void * fp)834*37da2899SCharles.Forsyth Image_fillbezsplineop(void *fp)
835*37da2899SCharles.Forsyth {
836*37da2899SCharles.Forsyth 	F_Image_fillbezsplineop *f;
837*37da2899SCharles.Forsyth 
838*37da2899SCharles.Forsyth 	f = fp;
839*37da2899SCharles.Forsyth 	drawfillsplinepoly(fp, 1, f->op);
840*37da2899SCharles.Forsyth }
841*37da2899SCharles.Forsyth 
842*37da2899SCharles.Forsyth static void
drawarcellipse(void * fp,int isarc,int alpha,int phi,int op)843*37da2899SCharles.Forsyth drawarcellipse(void *fp, int isarc, int alpha, int phi, int op)
844*37da2899SCharles.Forsyth {
845*37da2899SCharles.Forsyth 	F_Image_arc *f;
846*37da2899SCharles.Forsyth 	Image *d, *s;
847*37da2899SCharles.Forsyth 	int locked;
848*37da2899SCharles.Forsyth 
849*37da2899SCharles.Forsyth 	f = fp;
850*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
851*37da2899SCharles.Forsyth 	s = checkimage(f->src);
852*37da2899SCharles.Forsyth 	if(d->display != s->display || f->thick < 0 || f->a<0 || f->b<0)
853*37da2899SCharles.Forsyth 		return;
854*37da2899SCharles.Forsyth 
855*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
856*37da2899SCharles.Forsyth 	if(isarc)
857*37da2899SCharles.Forsyth 		arcop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
858*37da2899SCharles.Forsyth 			IPOINT(f->sp), alpha, phi, op);
859*37da2899SCharles.Forsyth 	else
860*37da2899SCharles.Forsyth 		ellipseop(d, IPOINT(f->c), f->a, f->b, f->thick, s,
861*37da2899SCharles.Forsyth 			IPOINT(f->sp), op);
862*37da2899SCharles.Forsyth 	checkflush(f->dst);
863*37da2899SCharles.Forsyth 	if(locked)
864*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
865*37da2899SCharles.Forsyth }
866*37da2899SCharles.Forsyth 
867*37da2899SCharles.Forsyth void
Image_ellipse(void * fp)868*37da2899SCharles.Forsyth Image_ellipse(void *fp)
869*37da2899SCharles.Forsyth {
870*37da2899SCharles.Forsyth 	drawarcellipse(fp, 0, 0, 0, SoverD);
871*37da2899SCharles.Forsyth }
872*37da2899SCharles.Forsyth 
873*37da2899SCharles.Forsyth void
Image_ellipseop(void * fp)874*37da2899SCharles.Forsyth Image_ellipseop(void *fp)
875*37da2899SCharles.Forsyth {
876*37da2899SCharles.Forsyth 	F_Image_ellipseop *f;
877*37da2899SCharles.Forsyth 
878*37da2899SCharles.Forsyth 	f = fp;
879*37da2899SCharles.Forsyth 	drawarcellipse(fp, 0, 0, 0, f->op);
880*37da2899SCharles.Forsyth }
881*37da2899SCharles.Forsyth 
882*37da2899SCharles.Forsyth void
Image_arc(void * fp)883*37da2899SCharles.Forsyth Image_arc(void *fp)
884*37da2899SCharles.Forsyth {
885*37da2899SCharles.Forsyth 	F_Image_arc *f;
886*37da2899SCharles.Forsyth 
887*37da2899SCharles.Forsyth 	f = fp;
888*37da2899SCharles.Forsyth 	drawarcellipse(fp, 1, f->alpha, f->phi, SoverD);
889*37da2899SCharles.Forsyth }
890*37da2899SCharles.Forsyth 
891*37da2899SCharles.Forsyth void
Image_arcop(void * fp)892*37da2899SCharles.Forsyth Image_arcop(void *fp)
893*37da2899SCharles.Forsyth {
894*37da2899SCharles.Forsyth 	F_Image_arcop *f;
895*37da2899SCharles.Forsyth 
896*37da2899SCharles.Forsyth 	f = fp;
897*37da2899SCharles.Forsyth 	drawarcellipse(fp, 1, f->alpha, f->phi, f->op);
898*37da2899SCharles.Forsyth }
899*37da2899SCharles.Forsyth 
900*37da2899SCharles.Forsyth static void
drawfillarcellipse(void * fp,int isarc,int alpha,int phi,int op)901*37da2899SCharles.Forsyth drawfillarcellipse(void *fp, int isarc, int alpha, int phi, int op)
902*37da2899SCharles.Forsyth {
903*37da2899SCharles.Forsyth 	F_Image_fillarc *f;
904*37da2899SCharles.Forsyth 	Image *d, *s;
905*37da2899SCharles.Forsyth 	int locked;
906*37da2899SCharles.Forsyth 
907*37da2899SCharles.Forsyth 	f = fp;
908*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
909*37da2899SCharles.Forsyth 	s = checkimage(f->src);
910*37da2899SCharles.Forsyth 	if(d->display != s->display || f->a<0 || f->b<0)
911*37da2899SCharles.Forsyth 		return;
912*37da2899SCharles.Forsyth 
913*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
914*37da2899SCharles.Forsyth 	if(isarc)
915*37da2899SCharles.Forsyth 		fillarcop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), alpha, phi, op);
916*37da2899SCharles.Forsyth 	else
917*37da2899SCharles.Forsyth 		fillellipseop(d, IPOINT(f->c), f->a, f->b, s, IPOINT(f->sp), op);
918*37da2899SCharles.Forsyth 	checkflush(f->dst);
919*37da2899SCharles.Forsyth 	if(locked)
920*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
921*37da2899SCharles.Forsyth }
922*37da2899SCharles.Forsyth 
923*37da2899SCharles.Forsyth void
Image_fillellipse(void * fp)924*37da2899SCharles.Forsyth Image_fillellipse(void *fp)
925*37da2899SCharles.Forsyth {
926*37da2899SCharles.Forsyth 	drawfillarcellipse(fp, 0, 0, 0, SoverD);
927*37da2899SCharles.Forsyth }
928*37da2899SCharles.Forsyth 
929*37da2899SCharles.Forsyth void
Image_fillellipseop(void * fp)930*37da2899SCharles.Forsyth Image_fillellipseop(void *fp)
931*37da2899SCharles.Forsyth {
932*37da2899SCharles.Forsyth 	F_Image_fillellipseop *f;
933*37da2899SCharles.Forsyth 
934*37da2899SCharles.Forsyth 	f = fp;
935*37da2899SCharles.Forsyth 	drawfillarcellipse(fp, 0, 0, 0, f->op);
936*37da2899SCharles.Forsyth }
937*37da2899SCharles.Forsyth 
938*37da2899SCharles.Forsyth void
Image_fillarc(void * fp)939*37da2899SCharles.Forsyth Image_fillarc(void *fp)
940*37da2899SCharles.Forsyth {
941*37da2899SCharles.Forsyth 	F_Image_fillarc *f;
942*37da2899SCharles.Forsyth 
943*37da2899SCharles.Forsyth 	f = fp;
944*37da2899SCharles.Forsyth 	drawfillarcellipse(fp, 1, f->alpha, f->phi, SoverD);
945*37da2899SCharles.Forsyth }
946*37da2899SCharles.Forsyth 
947*37da2899SCharles.Forsyth void
Image_fillarcop(void * fp)948*37da2899SCharles.Forsyth Image_fillarcop(void *fp)
949*37da2899SCharles.Forsyth {
950*37da2899SCharles.Forsyth 	F_Image_fillarcop *f;
951*37da2899SCharles.Forsyth 
952*37da2899SCharles.Forsyth 	f = fp;
953*37da2899SCharles.Forsyth 	drawfillarcellipse(fp, 1, f->alpha, f->phi, f->op);
954*37da2899SCharles.Forsyth }
955*37da2899SCharles.Forsyth 
956*37da2899SCharles.Forsyth static void
drawtext(void * fp,int op)957*37da2899SCharles.Forsyth drawtext(void *fp, int op)
958*37da2899SCharles.Forsyth {
959*37da2899SCharles.Forsyth 	F_Image_text *f;
960*37da2899SCharles.Forsyth 	Font *font;
961*37da2899SCharles.Forsyth 	Point pt;
962*37da2899SCharles.Forsyth 	Image *s, *d;
963*37da2899SCharles.Forsyth 	String *str;
964*37da2899SCharles.Forsyth 	int locked;
965*37da2899SCharles.Forsyth 
966*37da2899SCharles.Forsyth 	f = fp;
967*37da2899SCharles.Forsyth 	if(f->dst == H || f->src == H)
968*37da2899SCharles.Forsyth 		goto Return;
969*37da2899SCharles.Forsyth 	if(f->font == H || f->str == H)
970*37da2899SCharles.Forsyth 		goto Return;
971*37da2899SCharles.Forsyth 	str = f->str;
972*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
973*37da2899SCharles.Forsyth 	s = checkimage(f->src);
974*37da2899SCharles.Forsyth 	font = checkfont(f->font);
975*37da2899SCharles.Forsyth 	if(d->display!=s->display || d->display!=font->display)
976*37da2899SCharles.Forsyth 		return;
977*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
978*37da2899SCharles.Forsyth 	if(str->len >= 0)
979*37da2899SCharles.Forsyth 		pt = stringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, op);
980*37da2899SCharles.Forsyth 	else
981*37da2899SCharles.Forsyth 		pt = runestringnop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, op);
982*37da2899SCharles.Forsyth 	checkflush(f->dst);
983*37da2899SCharles.Forsyth 	if(locked)
984*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
985*37da2899SCharles.Forsyth     Return:
986*37da2899SCharles.Forsyth 	P2P(*f->ret, pt);
987*37da2899SCharles.Forsyth }
988*37da2899SCharles.Forsyth 
989*37da2899SCharles.Forsyth void
Image_text(void * fp)990*37da2899SCharles.Forsyth Image_text(void *fp)
991*37da2899SCharles.Forsyth {
992*37da2899SCharles.Forsyth 	drawtext(fp, SoverD);
993*37da2899SCharles.Forsyth }
994*37da2899SCharles.Forsyth 
995*37da2899SCharles.Forsyth void
Image_textop(void * fp)996*37da2899SCharles.Forsyth Image_textop(void *fp)
997*37da2899SCharles.Forsyth {
998*37da2899SCharles.Forsyth 	F_Image_textop *f;
999*37da2899SCharles.Forsyth 
1000*37da2899SCharles.Forsyth 	f = fp;
1001*37da2899SCharles.Forsyth 	drawtext(fp, f->op);
1002*37da2899SCharles.Forsyth }
1003*37da2899SCharles.Forsyth 
1004*37da2899SCharles.Forsyth static void
drawtextbg(void * fp,int op)1005*37da2899SCharles.Forsyth drawtextbg(void *fp, int op)
1006*37da2899SCharles.Forsyth {
1007*37da2899SCharles.Forsyth 	F_Image_textbg *f;
1008*37da2899SCharles.Forsyth 	Font *font;
1009*37da2899SCharles.Forsyth 	Point pt;
1010*37da2899SCharles.Forsyth 	Image *s, *d, *bg;
1011*37da2899SCharles.Forsyth 	String *str;
1012*37da2899SCharles.Forsyth 	int locked;
1013*37da2899SCharles.Forsyth 
1014*37da2899SCharles.Forsyth 	f = fp;
1015*37da2899SCharles.Forsyth 	if(f->dst == H || f->src == H)
1016*37da2899SCharles.Forsyth 		goto Return;
1017*37da2899SCharles.Forsyth 	if(f->font == H || f->str == H)
1018*37da2899SCharles.Forsyth 		goto Return;
1019*37da2899SCharles.Forsyth 	str = f->str;
1020*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
1021*37da2899SCharles.Forsyth 	s = checkimage(f->src);
1022*37da2899SCharles.Forsyth 	bg = checkimage(f->bg);
1023*37da2899SCharles.Forsyth 	font = checkfont(f->font);
1024*37da2899SCharles.Forsyth 	if(d->display!=s->display || d->display!=font->display)
1025*37da2899SCharles.Forsyth 		return;
1026*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
1027*37da2899SCharles.Forsyth 	if(str->len >= 0)
1028*37da2899SCharles.Forsyth 		pt = stringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Sascii, str->len, bg, IPOINT(f->bgp), op);
1029*37da2899SCharles.Forsyth 	else
1030*37da2899SCharles.Forsyth 		pt = runestringnbgop(d, IPOINT(f->p), s, IPOINT(f->sp), font, str->Srune, -str->len, bg, IPOINT(f->bgp), op);
1031*37da2899SCharles.Forsyth 	checkflush(f->dst);
1032*37da2899SCharles.Forsyth 	if(locked)
1033*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
1034*37da2899SCharles.Forsyth     Return:
1035*37da2899SCharles.Forsyth 	P2P(*f->ret, pt);
1036*37da2899SCharles.Forsyth }
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth void
Image_textbg(void * fp)1039*37da2899SCharles.Forsyth Image_textbg(void *fp)
1040*37da2899SCharles.Forsyth {
1041*37da2899SCharles.Forsyth 	drawtextbg(fp, SoverD);
1042*37da2899SCharles.Forsyth }
1043*37da2899SCharles.Forsyth 
1044*37da2899SCharles.Forsyth void
Image_textbgop(void * fp)1045*37da2899SCharles.Forsyth Image_textbgop(void *fp)
1046*37da2899SCharles.Forsyth {
1047*37da2899SCharles.Forsyth 	F_Image_textbgop *f;
1048*37da2899SCharles.Forsyth 
1049*37da2899SCharles.Forsyth 	f = fp;
1050*37da2899SCharles.Forsyth 	drawtextbg(fp, f->op);
1051*37da2899SCharles.Forsyth }
1052*37da2899SCharles.Forsyth 
1053*37da2899SCharles.Forsyth static void
drawborder(void * fp,int op)1054*37da2899SCharles.Forsyth drawborder(void *fp, int op)
1055*37da2899SCharles.Forsyth {
1056*37da2899SCharles.Forsyth 	F_Image_border *f;
1057*37da2899SCharles.Forsyth 	Image *d, *s;
1058*37da2899SCharles.Forsyth 	int locked;
1059*37da2899SCharles.Forsyth 
1060*37da2899SCharles.Forsyth 	f = fp;
1061*37da2899SCharles.Forsyth 	d = checkimage(f->dst);
1062*37da2899SCharles.Forsyth 	s = checkimage(f->src);
1063*37da2899SCharles.Forsyth 	if(d->display != s->display)
1064*37da2899SCharles.Forsyth 		return;
1065*37da2899SCharles.Forsyth 	locked = lockdisplay(d->display);
1066*37da2899SCharles.Forsyth 	borderop(d, IRECT(f->r), f->i, s, IPOINT(f->sp), op);
1067*37da2899SCharles.Forsyth 	checkflush(f->dst);
1068*37da2899SCharles.Forsyth 	if(locked)
1069*37da2899SCharles.Forsyth 		unlockdisplay(d->display);
1070*37da2899SCharles.Forsyth }
1071*37da2899SCharles.Forsyth 
1072*37da2899SCharles.Forsyth void
Image_border(void * fp)1073*37da2899SCharles.Forsyth Image_border(void *fp)
1074*37da2899SCharles.Forsyth {
1075*37da2899SCharles.Forsyth 	drawborder(fp, SoverD);
1076*37da2899SCharles.Forsyth }
1077*37da2899SCharles.Forsyth 
1078*37da2899SCharles.Forsyth void
Display_newimage(void * fp)1079*37da2899SCharles.Forsyth Display_newimage(void *fp)
1080*37da2899SCharles.Forsyth {
1081*37da2899SCharles.Forsyth 	F_Display_newimage *f;
1082*37da2899SCharles.Forsyth 	Display *d;
1083*37da2899SCharles.Forsyth 	int locked;
1084*37da2899SCharles.Forsyth 
1085*37da2899SCharles.Forsyth 	f = fp;
1086*37da2899SCharles.Forsyth 	d = checkdisplay(f->d);
1087*37da2899SCharles.Forsyth 	destroy(*f->ret);
1088*37da2899SCharles.Forsyth 	*f->ret = H;
1089*37da2899SCharles.Forsyth 	locked = lockdisplay(d);
1090*37da2899SCharles.Forsyth 	*f->ret = allocdrawimage((DDisplay*)f->d, f->r, f->chans.desc,
1091*37da2899SCharles.Forsyth 				nil, f->repl, f->color);
1092*37da2899SCharles.Forsyth 	if(locked)
1093*37da2899SCharles.Forsyth 		unlockdisplay(d);
1094*37da2899SCharles.Forsyth }
1095*37da2899SCharles.Forsyth 
1096*37da2899SCharles.Forsyth void
Display_colormix(void * fp)1097*37da2899SCharles.Forsyth Display_colormix(void *fp)
1098*37da2899SCharles.Forsyth {
1099*37da2899SCharles.Forsyth 	F_Display_colormix *f;
1100*37da2899SCharles.Forsyth 	Display *disp;
1101*37da2899SCharles.Forsyth 	Image *i;
1102*37da2899SCharles.Forsyth 	int locked;
1103*37da2899SCharles.Forsyth 
1104*37da2899SCharles.Forsyth 	f = fp;
1105*37da2899SCharles.Forsyth 	destroy(*f->ret);
1106*37da2899SCharles.Forsyth 	*f->ret = H;
1107*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1108*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1109*37da2899SCharles.Forsyth 	i = allocimagemix(disp, f->c1, f->c2);
1110*37da2899SCharles.Forsyth 	if(locked)
1111*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1112*37da2899SCharles.Forsyth 	*f->ret = mkdrawimage(i, H, f->d, nil);
1113*37da2899SCharles.Forsyth }
1114*37da2899SCharles.Forsyth 
1115*37da2899SCharles.Forsyth void
Image_readpixels(void * fp)1116*37da2899SCharles.Forsyth Image_readpixels(void *fp)
1117*37da2899SCharles.Forsyth {
1118*37da2899SCharles.Forsyth 	F_Image_readpixels *f;
1119*37da2899SCharles.Forsyth 	Rectangle r;
1120*37da2899SCharles.Forsyth 	Image *i;
1121*37da2899SCharles.Forsyth 	int locked;
1122*37da2899SCharles.Forsyth 
1123*37da2899SCharles.Forsyth 	f = fp;
1124*37da2899SCharles.Forsyth 	R2R(r, f->r);
1125*37da2899SCharles.Forsyth 	i = checkimage(f->src);
1126*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
1127*37da2899SCharles.Forsyth 	*f->ret = unloadimage(i, r, f->data->data, f->data->len);
1128*37da2899SCharles.Forsyth 	if(locked)
1129*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
1130*37da2899SCharles.Forsyth }
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth void
Image_writepixels(void * fp)1133*37da2899SCharles.Forsyth Image_writepixels(void *fp)
1134*37da2899SCharles.Forsyth {
1135*37da2899SCharles.Forsyth 	Rectangle r;
1136*37da2899SCharles.Forsyth 	F_Image_writepixels *f;
1137*37da2899SCharles.Forsyth 	Image *i;
1138*37da2899SCharles.Forsyth 	int locked;
1139*37da2899SCharles.Forsyth 
1140*37da2899SCharles.Forsyth 	f = fp;
1141*37da2899SCharles.Forsyth 	R2R(r, f->r);
1142*37da2899SCharles.Forsyth 	i = checkimage(f->dst);
1143*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
1144*37da2899SCharles.Forsyth 	*f->ret = loadimage(i, r, f->data->data, f->data->len);
1145*37da2899SCharles.Forsyth 	checkflush(f->dst);
1146*37da2899SCharles.Forsyth 	if(locked)
1147*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
1148*37da2899SCharles.Forsyth }
1149*37da2899SCharles.Forsyth 
1150*37da2899SCharles.Forsyth void
Image_arrow(void * fp)1151*37da2899SCharles.Forsyth Image_arrow(void *fp)
1152*37da2899SCharles.Forsyth {
1153*37da2899SCharles.Forsyth 	F_Image_arrow *f;
1154*37da2899SCharles.Forsyth 
1155*37da2899SCharles.Forsyth 	f = fp;
1156*37da2899SCharles.Forsyth 	*f->ret = ARROW(f->a, f->b, f->c);
1157*37da2899SCharles.Forsyth }
1158*37da2899SCharles.Forsyth 
1159*37da2899SCharles.Forsyth void
Image_name(void * fp)1160*37da2899SCharles.Forsyth Image_name(void *fp)
1161*37da2899SCharles.Forsyth {
1162*37da2899SCharles.Forsyth 	F_Image_name *f;
1163*37da2899SCharles.Forsyth 	Image *i;
1164*37da2899SCharles.Forsyth 	int locked, ok;
1165*37da2899SCharles.Forsyth 	char *name;
1166*37da2899SCharles.Forsyth 
1167*37da2899SCharles.Forsyth 	f = fp;
1168*37da2899SCharles.Forsyth 	*f->ret = -1;
1169*37da2899SCharles.Forsyth 	i = checkimage(f->src);
1170*37da2899SCharles.Forsyth 	name = string2c(f->name);
1171*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
1172*37da2899SCharles.Forsyth 	*f->ret = ok = nameimage(i, name, f->in);
1173*37da2899SCharles.Forsyth 	if(locked)
1174*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
1175*37da2899SCharles.Forsyth 	if(ok){
1176*37da2899SCharles.Forsyth 		destroy(f->src->iname);
1177*37da2899SCharles.Forsyth 		if(f->in){
1178*37da2899SCharles.Forsyth 			f->src->iname = f->name;
1179*37da2899SCharles.Forsyth 			D2H(f->name)->ref++;
1180*37da2899SCharles.Forsyth 		}else
1181*37da2899SCharles.Forsyth 			f->src->iname = H;
1182*37da2899SCharles.Forsyth 	}
1183*37da2899SCharles.Forsyth }
1184*37da2899SCharles.Forsyth 
1185*37da2899SCharles.Forsyth Image*
display_open(Display * disp,char * name)1186*37da2899SCharles.Forsyth display_open(Display *disp, char *name)
1187*37da2899SCharles.Forsyth {
1188*37da2899SCharles.Forsyth 	Image *i;
1189*37da2899SCharles.Forsyth 	int fd;
1190*37da2899SCharles.Forsyth 
1191*37da2899SCharles.Forsyth 	fd = libopen(name, OREAD);
1192*37da2899SCharles.Forsyth 	if(fd < 0)
1193*37da2899SCharles.Forsyth 		return nil;
1194*37da2899SCharles.Forsyth 
1195*37da2899SCharles.Forsyth 	i = readimage(disp, fd, 1);
1196*37da2899SCharles.Forsyth 	libclose(fd);
1197*37da2899SCharles.Forsyth 	return i;
1198*37da2899SCharles.Forsyth }
1199*37da2899SCharles.Forsyth 
1200*37da2899SCharles.Forsyth void
Display_open(void * fp)1201*37da2899SCharles.Forsyth Display_open(void *fp)
1202*37da2899SCharles.Forsyth {
1203*37da2899SCharles.Forsyth 	Image *i;
1204*37da2899SCharles.Forsyth 	Display *disp;
1205*37da2899SCharles.Forsyth 	F_Display_open *f;
1206*37da2899SCharles.Forsyth 
1207*37da2899SCharles.Forsyth 	f = fp;
1208*37da2899SCharles.Forsyth 	destroy(*f->ret);
1209*37da2899SCharles.Forsyth 	*f->ret = H;
1210*37da2899SCharles.Forsyth 	disp = lookupdisplay(f->d);
1211*37da2899SCharles.Forsyth 	if(disp == nil)
1212*37da2899SCharles.Forsyth 		return;
1213*37da2899SCharles.Forsyth 	i = display_open(disp, string2c(f->name));
1214*37da2899SCharles.Forsyth 	if(i == nil)
1215*37da2899SCharles.Forsyth 		return;
1216*37da2899SCharles.Forsyth 	*f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
1217*37da2899SCharles.Forsyth }
1218*37da2899SCharles.Forsyth 
1219*37da2899SCharles.Forsyth void
Display_namedimage(void * fp)1220*37da2899SCharles.Forsyth Display_namedimage(void *fp)
1221*37da2899SCharles.Forsyth {
1222*37da2899SCharles.Forsyth 	F_Display_namedimage *f;
1223*37da2899SCharles.Forsyth 	Display *d;
1224*37da2899SCharles.Forsyth 	Image *i;
1225*37da2899SCharles.Forsyth 	Draw_Image *di;
1226*37da2899SCharles.Forsyth 	int locked;
1227*37da2899SCharles.Forsyth 
1228*37da2899SCharles.Forsyth 	f = fp;
1229*37da2899SCharles.Forsyth 	destroy(*f->ret);
1230*37da2899SCharles.Forsyth 	*f->ret = H;
1231*37da2899SCharles.Forsyth 	d = checkdisplay(f->d);
1232*37da2899SCharles.Forsyth 	locked = lockdisplay(d);
1233*37da2899SCharles.Forsyth 	i = namedimage(d, string2c(f->name));
1234*37da2899SCharles.Forsyth 	if(locked)
1235*37da2899SCharles.Forsyth 		unlockdisplay(d);
1236*37da2899SCharles.Forsyth 	if(i == nil)
1237*37da2899SCharles.Forsyth 		return;
1238*37da2899SCharles.Forsyth 	di =  allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, i->repl, 0);
1239*37da2899SCharles.Forsyth 	*f->ret = di;
1240*37da2899SCharles.Forsyth 	if(di == H){
1241*37da2899SCharles.Forsyth 		locked = lockdisplay(d);
1242*37da2899SCharles.Forsyth 		freeimage(i);
1243*37da2899SCharles.Forsyth 		if(locked)
1244*37da2899SCharles.Forsyth 			unlockdisplay(d);
1245*37da2899SCharles.Forsyth 	}else{
1246*37da2899SCharles.Forsyth 		di->iname = f->name;
1247*37da2899SCharles.Forsyth 		D2H(f->name)->ref++;
1248*37da2899SCharles.Forsyth 	}
1249*37da2899SCharles.Forsyth }
1250*37da2899SCharles.Forsyth 
1251*37da2899SCharles.Forsyth void
Display_readimage(void * fp)1252*37da2899SCharles.Forsyth Display_readimage(void *fp)
1253*37da2899SCharles.Forsyth {
1254*37da2899SCharles.Forsyth 	Image *i;
1255*37da2899SCharles.Forsyth 	Display *disp;
1256*37da2899SCharles.Forsyth 	F_Display_readimage *f;
1257*37da2899SCharles.Forsyth 	Sys_FD *fd;
1258*37da2899SCharles.Forsyth 	int locked;
1259*37da2899SCharles.Forsyth 
1260*37da2899SCharles.Forsyth 	f = fp;
1261*37da2899SCharles.Forsyth 	destroy(*f->ret);
1262*37da2899SCharles.Forsyth 	*f->ret = H;
1263*37da2899SCharles.Forsyth 	fd = f->fd;
1264*37da2899SCharles.Forsyth 	if(fd == H)
1265*37da2899SCharles.Forsyth 		return;
1266*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1267*37da2899SCharles.Forsyth 	i = readimage(disp, fd->fd, 1);
1268*37da2899SCharles.Forsyth 	if(i == nil)
1269*37da2899SCharles.Forsyth 		return;
1270*37da2899SCharles.Forsyth 	*f->ret = allocdrawimage((DDisplay*)f->d, DRECT(i->r), i->chan, i, 0, 0);
1271*37da2899SCharles.Forsyth 	if(*f->ret == H){
1272*37da2899SCharles.Forsyth 		locked = lockdisplay(disp);
1273*37da2899SCharles.Forsyth 		freeimage(i);
1274*37da2899SCharles.Forsyth 		if(locked)
1275*37da2899SCharles.Forsyth 			unlockdisplay(disp);
1276*37da2899SCharles.Forsyth 	}
1277*37da2899SCharles.Forsyth }
1278*37da2899SCharles.Forsyth 
1279*37da2899SCharles.Forsyth void
Display_writeimage(void * fp)1280*37da2899SCharles.Forsyth Display_writeimage(void *fp)
1281*37da2899SCharles.Forsyth {
1282*37da2899SCharles.Forsyth 	Image *i;
1283*37da2899SCharles.Forsyth 	F_Display_writeimage *f;
1284*37da2899SCharles.Forsyth 	Sys_FD *fd;
1285*37da2899SCharles.Forsyth 
1286*37da2899SCharles.Forsyth 	f = fp;
1287*37da2899SCharles.Forsyth 	*f->ret = -1;
1288*37da2899SCharles.Forsyth 	fd = f->fd;
1289*37da2899SCharles.Forsyth 	if(fd == H)
1290*37da2899SCharles.Forsyth 		return;
1291*37da2899SCharles.Forsyth 	i = checkimage(f->i);
1292*37da2899SCharles.Forsyth 	if(checkdisplay(f->d) != i->display)
1293*37da2899SCharles.Forsyth 		return;
1294*37da2899SCharles.Forsyth 	*f->ret = writeimage(fd->fd, i, 1);	/* TO DO: dolock? */
1295*37da2899SCharles.Forsyth }
1296*37da2899SCharles.Forsyth 
1297*37da2899SCharles.Forsyth Draw_Screen*
mkdrawscreen(Screen * s,Draw_Display * display)1298*37da2899SCharles.Forsyth mkdrawscreen(Screen *s, Draw_Display *display)
1299*37da2899SCharles.Forsyth {
1300*37da2899SCharles.Forsyth 	Heap *h;
1301*37da2899SCharles.Forsyth 	DScreen *ds;
1302*37da2899SCharles.Forsyth 	Draw_Image *dimage, *dfill;
1303*37da2899SCharles.Forsyth 
1304*37da2899SCharles.Forsyth 	dimage = mkdrawimage(s->image, H, display, nil);
1305*37da2899SCharles.Forsyth 	dfill = mkdrawimage(s->fill, H, display, nil);
1306*37da2899SCharles.Forsyth 	h = heap(TScreen);
1307*37da2899SCharles.Forsyth 	if(h == H)
1308*37da2899SCharles.Forsyth 		return nil;
1309*37da2899SCharles.Forsyth 	ds = H2D(DScreen*, h);
1310*37da2899SCharles.Forsyth 	ds->screen = s;
1311*37da2899SCharles.Forsyth 	ds->drawscreen.fill = dfill;
1312*37da2899SCharles.Forsyth 	D2H(dfill)->ref++;
1313*37da2899SCharles.Forsyth 	ds->drawscreen.image = dimage;
1314*37da2899SCharles.Forsyth 	D2H(dimage)->ref++;
1315*37da2899SCharles.Forsyth 	ds->drawscreen.display = dimage->display;
1316*37da2899SCharles.Forsyth 	D2H(dimage->display)->ref++;
1317*37da2899SCharles.Forsyth 	ds->drawscreen.id = s->id;
1318*37da2899SCharles.Forsyth 	ds->dref = s->display->limbo;
1319*37da2899SCharles.Forsyth 	ds->dref->ref++;
1320*37da2899SCharles.Forsyth 	return &ds->drawscreen;
1321*37da2899SCharles.Forsyth }
1322*37da2899SCharles.Forsyth 
1323*37da2899SCharles.Forsyth static DScreen*
allocdrawscreen(Draw_Image * dimage,Draw_Image * dfill,int public)1324*37da2899SCharles.Forsyth allocdrawscreen(Draw_Image *dimage, Draw_Image *dfill, int public)
1325*37da2899SCharles.Forsyth {
1326*37da2899SCharles.Forsyth 	Heap *h;
1327*37da2899SCharles.Forsyth 	Screen *s;
1328*37da2899SCharles.Forsyth 	DScreen *ds;
1329*37da2899SCharles.Forsyth 	Image *image, *fill;
1330*37da2899SCharles.Forsyth 
1331*37da2899SCharles.Forsyth 	image = ((DImage*)dimage)->image;
1332*37da2899SCharles.Forsyth 	fill = ((DImage*)dfill)->image;
1333*37da2899SCharles.Forsyth 	s = allocscreen(image, fill, public);
1334*37da2899SCharles.Forsyth 	if(s == 0)
1335*37da2899SCharles.Forsyth 		return nil;
1336*37da2899SCharles.Forsyth 	h = heap(TScreen);
1337*37da2899SCharles.Forsyth 	if(h == H)
1338*37da2899SCharles.Forsyth 		return nil;
1339*37da2899SCharles.Forsyth 	ds = H2D(DScreen*, h);
1340*37da2899SCharles.Forsyth 	ds->screen = s;
1341*37da2899SCharles.Forsyth 	ds->drawscreen.fill = dfill;
1342*37da2899SCharles.Forsyth 	D2H(dfill)->ref++;
1343*37da2899SCharles.Forsyth 	ds->drawscreen.image = dimage;
1344*37da2899SCharles.Forsyth 	D2H(dimage)->ref++;
1345*37da2899SCharles.Forsyth 	ds->drawscreen.display = dimage->display;
1346*37da2899SCharles.Forsyth 	D2H(dimage->display)->ref++;
1347*37da2899SCharles.Forsyth 	ds->drawscreen.id = s->id;
1348*37da2899SCharles.Forsyth 	ds->dref = image->display->limbo;
1349*37da2899SCharles.Forsyth 	ds->dref->ref++;
1350*37da2899SCharles.Forsyth 	return ds;
1351*37da2899SCharles.Forsyth }
1352*37da2899SCharles.Forsyth 
1353*37da2899SCharles.Forsyth void
Screen_allocate(void * fp)1354*37da2899SCharles.Forsyth Screen_allocate(void *fp)
1355*37da2899SCharles.Forsyth {
1356*37da2899SCharles.Forsyth 	F_Screen_allocate *f;
1357*37da2899SCharles.Forsyth 	DScreen *ds;
1358*37da2899SCharles.Forsyth 	Image *image;
1359*37da2899SCharles.Forsyth 	int locked;
1360*37da2899SCharles.Forsyth 
1361*37da2899SCharles.Forsyth 	f = fp;
1362*37da2899SCharles.Forsyth 	destroy(*f->ret);
1363*37da2899SCharles.Forsyth 	*f->ret = H;
1364*37da2899SCharles.Forsyth 	image = checkimage(f->image);
1365*37da2899SCharles.Forsyth 	checkimage(f->fill);
1366*37da2899SCharles.Forsyth 	locked = lockdisplay(image->display);
1367*37da2899SCharles.Forsyth 	ds = allocdrawscreen(f->image, f->fill, f->public);
1368*37da2899SCharles.Forsyth 	if(ds != nil)
1369*37da2899SCharles.Forsyth 		*f->ret = &ds->drawscreen;
1370*37da2899SCharles.Forsyth 	if(locked)
1371*37da2899SCharles.Forsyth 		unlockdisplay(image->display);
1372*37da2899SCharles.Forsyth }
1373*37da2899SCharles.Forsyth 
1374*37da2899SCharles.Forsyth void
Display_publicscreen(void * fp)1375*37da2899SCharles.Forsyth Display_publicscreen(void *fp)
1376*37da2899SCharles.Forsyth {
1377*37da2899SCharles.Forsyth 	F_Display_publicscreen *f;
1378*37da2899SCharles.Forsyth 	Heap *h;
1379*37da2899SCharles.Forsyth 	Screen *s;
1380*37da2899SCharles.Forsyth 	DScreen *ds;
1381*37da2899SCharles.Forsyth 	Display *disp;
1382*37da2899SCharles.Forsyth 	int locked;
1383*37da2899SCharles.Forsyth 
1384*37da2899SCharles.Forsyth 	f = fp;
1385*37da2899SCharles.Forsyth 	destroy(*f->ret);
1386*37da2899SCharles.Forsyth 	*f->ret = H;
1387*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1388*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1389*37da2899SCharles.Forsyth 	s = publicscreen(disp, f->id, disp->image->chan);
1390*37da2899SCharles.Forsyth 	if(locked)
1391*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1392*37da2899SCharles.Forsyth 	if(s == nil)
1393*37da2899SCharles.Forsyth 		return;
1394*37da2899SCharles.Forsyth 	h = heap(TScreen);
1395*37da2899SCharles.Forsyth 	if(h == H)
1396*37da2899SCharles.Forsyth 		return;
1397*37da2899SCharles.Forsyth 	ds = H2D(DScreen*, h);
1398*37da2899SCharles.Forsyth 	ds->screen = s;
1399*37da2899SCharles.Forsyth 	ds->drawscreen.fill = H;
1400*37da2899SCharles.Forsyth 	ds->drawscreen.image =H;
1401*37da2899SCharles.Forsyth 	ds->drawscreen.id = s->id;
1402*37da2899SCharles.Forsyth 	ds->drawscreen.display = f->d;
1403*37da2899SCharles.Forsyth 	D2H(f->d)->ref++;
1404*37da2899SCharles.Forsyth 	ds->dref = disp->limbo;
1405*37da2899SCharles.Forsyth 	ds->dref->ref++;
1406*37da2899SCharles.Forsyth 	*f->ret = &ds->drawscreen;
1407*37da2899SCharles.Forsyth }
1408*37da2899SCharles.Forsyth 
1409*37da2899SCharles.Forsyth void
freedrawscreen(Heap * h,int swept)1410*37da2899SCharles.Forsyth freedrawscreen(Heap *h, int swept)
1411*37da2899SCharles.Forsyth {
1412*37da2899SCharles.Forsyth 	DScreen *ds;
1413*37da2899SCharles.Forsyth 	Screen *s;
1414*37da2899SCharles.Forsyth 	Display *disp;
1415*37da2899SCharles.Forsyth 	int locked;
1416*37da2899SCharles.Forsyth 
1417*37da2899SCharles.Forsyth 	ds = H2D(DScreen*, h);
1418*37da2899SCharles.Forsyth 	if(!swept) {
1419*37da2899SCharles.Forsyth 		destroy(ds->drawscreen.image);
1420*37da2899SCharles.Forsyth 		destroy(ds->drawscreen.fill);
1421*37da2899SCharles.Forsyth 		destroy(ds->drawscreen.display);
1422*37da2899SCharles.Forsyth 	}
1423*37da2899SCharles.Forsyth 	s = lookupscreen(&ds->drawscreen);
1424*37da2899SCharles.Forsyth 	if(s == nil){
1425*37da2899SCharles.Forsyth 		if(!swept)
1426*37da2899SCharles.Forsyth 			freeptrs(ds, TScreen);
1427*37da2899SCharles.Forsyth 		return;
1428*37da2899SCharles.Forsyth 	}
1429*37da2899SCharles.Forsyth 	disp = s->display;
1430*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1431*37da2899SCharles.Forsyth 	freescreen(s);
1432*37da2899SCharles.Forsyth 	if(locked)
1433*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1434*37da2899SCharles.Forsyth 	display_dec(ds->dref);
1435*37da2899SCharles.Forsyth 	/* screen header will be freed by caller */
1436*37da2899SCharles.Forsyth }
1437*37da2899SCharles.Forsyth 
1438*37da2899SCharles.Forsyth void
Font_build(void * fp)1439*37da2899SCharles.Forsyth Font_build(void *fp)
1440*37da2899SCharles.Forsyth {
1441*37da2899SCharles.Forsyth 	F_Font_build *f;
1442*37da2899SCharles.Forsyth 	Font *font;
1443*37da2899SCharles.Forsyth 	DFont *dfont;
1444*37da2899SCharles.Forsyth 	Heap *h;
1445*37da2899SCharles.Forsyth 	char buf[128];
1446*37da2899SCharles.Forsyth 	char *name, *data;
1447*37da2899SCharles.Forsyth 	Subfont *df;
1448*37da2899SCharles.Forsyth 	Display *disp;
1449*37da2899SCharles.Forsyth 	int locked;
1450*37da2899SCharles.Forsyth 
1451*37da2899SCharles.Forsyth 	f = fp;
1452*37da2899SCharles.Forsyth 	destroy(*f->ret);
1453*37da2899SCharles.Forsyth 	*f->ret = H;
1454*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1455*37da2899SCharles.Forsyth 
1456*37da2899SCharles.Forsyth 	name = string2c(f->name);
1457*37da2899SCharles.Forsyth 	font = font_open(disp, name);
1458*37da2899SCharles.Forsyth 	if(font == nil) {
1459*37da2899SCharles.Forsyth 		if(strcmp(name, deffontname) == 0) {
1460*37da2899SCharles.Forsyth 			df = disp->defaultsubfont;
1461*37da2899SCharles.Forsyth 			sprint(buf, "%d %d\n0 %d\t%s\n",
1462*37da2899SCharles.Forsyth 				df->height, df->ascent, df->n-1, name);
1463*37da2899SCharles.Forsyth 			data = buf;
1464*37da2899SCharles.Forsyth 		}
1465*37da2899SCharles.Forsyth 		else
1466*37da2899SCharles.Forsyth 		if(f->desc == H)
1467*37da2899SCharles.Forsyth 			return;
1468*37da2899SCharles.Forsyth 		else
1469*37da2899SCharles.Forsyth 			data = string2c(f->desc);
1470*37da2899SCharles.Forsyth 
1471*37da2899SCharles.Forsyth 		locked = lockdisplay(disp);
1472*37da2899SCharles.Forsyth 		font = buildfont(disp, data, name);
1473*37da2899SCharles.Forsyth 		if(locked)
1474*37da2899SCharles.Forsyth 			unlockdisplay(disp);
1475*37da2899SCharles.Forsyth 		if(font == nil)
1476*37da2899SCharles.Forsyth 			return;
1477*37da2899SCharles.Forsyth 	}
1478*37da2899SCharles.Forsyth 
1479*37da2899SCharles.Forsyth 	h = heap(TFont);
1480*37da2899SCharles.Forsyth 	if(h == H)
1481*37da2899SCharles.Forsyth 		return;
1482*37da2899SCharles.Forsyth 
1483*37da2899SCharles.Forsyth 	dfont = H2D(DFont*, h);
1484*37da2899SCharles.Forsyth 	dfont->font = font;
1485*37da2899SCharles.Forsyth 	dfont->drawfont.name = f->name;
1486*37da2899SCharles.Forsyth 	D2H(f->name)->ref++;
1487*37da2899SCharles.Forsyth 	dfont->drawfont.height = font->height;
1488*37da2899SCharles.Forsyth 	dfont->drawfont.ascent = font->ascent;
1489*37da2899SCharles.Forsyth 	dfont->drawfont.display = f->d;
1490*37da2899SCharles.Forsyth 	D2H(f->d)->ref++;
1491*37da2899SCharles.Forsyth 	dfont->dref = disp->limbo;
1492*37da2899SCharles.Forsyth 	dfont->dref->ref++;
1493*37da2899SCharles.Forsyth 
1494*37da2899SCharles.Forsyth 	*f->ret = &dfont->drawfont;
1495*37da2899SCharles.Forsyth }
1496*37da2899SCharles.Forsyth 
1497*37da2899SCharles.Forsyth Font*
font_open(Display * display,char * name)1498*37da2899SCharles.Forsyth font_open(Display *display, char *name)
1499*37da2899SCharles.Forsyth {
1500*37da2899SCharles.Forsyth 	Cache *c;
1501*37da2899SCharles.Forsyth 	Font *font;
1502*37da2899SCharles.Forsyth 	int locked;
1503*37da2899SCharles.Forsyth 
1504*37da2899SCharles.Forsyth 	c = cachelookup(fcache, display, name);
1505*37da2899SCharles.Forsyth 	if(c)
1506*37da2899SCharles.Forsyth 		font = c->u.f;
1507*37da2899SCharles.Forsyth 	else {
1508*37da2899SCharles.Forsyth 		locked = lockdisplay(display);
1509*37da2899SCharles.Forsyth 		font = openfont(display, name);
1510*37da2899SCharles.Forsyth 		if(locked)
1511*37da2899SCharles.Forsyth 			unlockdisplay(display);
1512*37da2899SCharles.Forsyth 		if(font == nil)
1513*37da2899SCharles.Forsyth 			return nil;
1514*37da2899SCharles.Forsyth 		c = cacheinstall(fcache, display, name, font, "font");
1515*37da2899SCharles.Forsyth 	}
1516*37da2899SCharles.Forsyth 	if(c)
1517*37da2899SCharles.Forsyth 		c->ref++;
1518*37da2899SCharles.Forsyth 
1519*37da2899SCharles.Forsyth 	return font;
1520*37da2899SCharles.Forsyth }
1521*37da2899SCharles.Forsyth 
1522*37da2899SCharles.Forsyth void
font_close(Font * f)1523*37da2899SCharles.Forsyth font_close(Font *f)
1524*37da2899SCharles.Forsyth {
1525*37da2899SCharles.Forsyth 	Cache *c;
1526*37da2899SCharles.Forsyth 	Display *disp;
1527*37da2899SCharles.Forsyth 	int locked;
1528*37da2899SCharles.Forsyth 	disp = f->display;
1529*37da2899SCharles.Forsyth 	if(f->name == nil)
1530*37da2899SCharles.Forsyth 		return;
1531*37da2899SCharles.Forsyth 
1532*37da2899SCharles.Forsyth 	/* fonts from Font_build() aren't always in fcache, but we still need to free them */
1533*37da2899SCharles.Forsyth 	c = cachelookup(fcache, disp, f->name);
1534*37da2899SCharles.Forsyth 	if(c != nil && f == c->u.f) {
1535*37da2899SCharles.Forsyth 		if(c->ref <= 0)
1536*37da2899SCharles.Forsyth 			return;
1537*37da2899SCharles.Forsyth 		if(c->ref-- != 1)
1538*37da2899SCharles.Forsyth 			return;
1539*37da2899SCharles.Forsyth 		cacheuninstall(fcache, disp, f->name, "font");
1540*37da2899SCharles.Forsyth 	}
1541*37da2899SCharles.Forsyth 
1542*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1543*37da2899SCharles.Forsyth 	freefont(f);
1544*37da2899SCharles.Forsyth 	if(locked)
1545*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1546*37da2899SCharles.Forsyth }
1547*37da2899SCharles.Forsyth 
1548*37da2899SCharles.Forsyth void
freecachedsubfont(Subfont * sf)1549*37da2899SCharles.Forsyth freecachedsubfont(Subfont *sf)
1550*37da2899SCharles.Forsyth {
1551*37da2899SCharles.Forsyth 	Cache *c;
1552*37da2899SCharles.Forsyth 	Display *disp;
1553*37da2899SCharles.Forsyth 
1554*37da2899SCharles.Forsyth 	disp = sf->bits->display;
1555*37da2899SCharles.Forsyth 	c = cachelookup(sfcache, disp, sf->name);
1556*37da2899SCharles.Forsyth 	if(c == nil){
1557*37da2899SCharles.Forsyth 		fprint(2, "subfont %s not cached\n", sf->name);
1558*37da2899SCharles.Forsyth 		return;
1559*37da2899SCharles.Forsyth 	}
1560*37da2899SCharles.Forsyth 	if(c->ref > 0)
1561*37da2899SCharles.Forsyth 		c->ref--;
1562*37da2899SCharles.Forsyth 	/* if ref is zero, we leave it around for later harvesting by freeallsubfonts */
1563*37da2899SCharles.Forsyth }
1564*37da2899SCharles.Forsyth 
1565*37da2899SCharles.Forsyth void
freeallsubfonts(Display * d)1566*37da2899SCharles.Forsyth freeallsubfonts(Display *d)
1567*37da2899SCharles.Forsyth {
1568*37da2899SCharles.Forsyth 	int i;
1569*37da2899SCharles.Forsyth 	Cache *c, *prev, *o;
1570*37da2899SCharles.Forsyth 	Subfont *sf;
1571*37da2899SCharles.Forsyth 	int locked;
1572*37da2899SCharles.Forsyth 	if(cacheqlock == nil)	/* may not have allocated anything yet */
1573*37da2899SCharles.Forsyth 		return;
1574*37da2899SCharles.Forsyth 	libqlock(cacheqlock);
1575*37da2899SCharles.Forsyth 	for(i=0; i<BIHASH; i++){
1576*37da2899SCharles.Forsyth 		c = sfcache[i];
1577*37da2899SCharles.Forsyth 		prev = 0;
1578*37da2899SCharles.Forsyth 		while(c != nil){
1579*37da2899SCharles.Forsyth 			if(c->ref==0 && (d==nil || c->display==d)){
1580*37da2899SCharles.Forsyth 				if(prev == 0)
1581*37da2899SCharles.Forsyth 					sfcache[i] = c->next;
1582*37da2899SCharles.Forsyth 				else
1583*37da2899SCharles.Forsyth 					prev->next = c->next;
1584*37da2899SCharles.Forsyth 				free(c->name);
1585*37da2899SCharles.Forsyth 				sf = c->u.sf;
1586*37da2899SCharles.Forsyth 				if(--sf->ref==0){
1587*37da2899SCharles.Forsyth 					free(sf->info);
1588*37da2899SCharles.Forsyth 					locked = lockdisplay(c->display);
1589*37da2899SCharles.Forsyth 					freeimage(sf->bits);
1590*37da2899SCharles.Forsyth 					if(locked)
1591*37da2899SCharles.Forsyth 						unlockdisplay(c->display);
1592*37da2899SCharles.Forsyth 					free(sf);
1593*37da2899SCharles.Forsyth 				}
1594*37da2899SCharles.Forsyth 				o = c;
1595*37da2899SCharles.Forsyth 				c = c->next;
1596*37da2899SCharles.Forsyth 				free(o);
1597*37da2899SCharles.Forsyth 			}else{
1598*37da2899SCharles.Forsyth 				prev = c;
1599*37da2899SCharles.Forsyth 				c = c->next;
1600*37da2899SCharles.Forsyth 			}
1601*37da2899SCharles.Forsyth 		}
1602*37da2899SCharles.Forsyth 	}
1603*37da2899SCharles.Forsyth 	libqunlock(cacheqlock);
1604*37da2899SCharles.Forsyth }
1605*37da2899SCharles.Forsyth 
1606*37da2899SCharles.Forsyth void
subfont_close(Subfont * sf)1607*37da2899SCharles.Forsyth subfont_close(Subfont *sf)
1608*37da2899SCharles.Forsyth {
1609*37da2899SCharles.Forsyth 	freecachedsubfont(sf);
1610*37da2899SCharles.Forsyth }
1611*37da2899SCharles.Forsyth 
1612*37da2899SCharles.Forsyth void
freesubfont(Subfont * sf)1613*37da2899SCharles.Forsyth freesubfont(Subfont *sf)
1614*37da2899SCharles.Forsyth {
1615*37da2899SCharles.Forsyth 	freecachedsubfont(sf);
1616*37da2899SCharles.Forsyth }
1617*37da2899SCharles.Forsyth 
1618*37da2899SCharles.Forsyth void
Font_open(void * fp)1619*37da2899SCharles.Forsyth Font_open(void *fp)
1620*37da2899SCharles.Forsyth {
1621*37da2899SCharles.Forsyth 	Heap *h;
1622*37da2899SCharles.Forsyth 	Font *font;
1623*37da2899SCharles.Forsyth 	Display *disp;
1624*37da2899SCharles.Forsyth 	DFont *df;
1625*37da2899SCharles.Forsyth 	F_Font_open *f;
1626*37da2899SCharles.Forsyth 
1627*37da2899SCharles.Forsyth 	f = fp;
1628*37da2899SCharles.Forsyth 
1629*37da2899SCharles.Forsyth 	destroy(*f->ret);
1630*37da2899SCharles.Forsyth 	*f->ret = H;
1631*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth 	font = font_open(disp, string2c(f->name));
1634*37da2899SCharles.Forsyth 	if(font == 0)
1635*37da2899SCharles.Forsyth 		return;
1636*37da2899SCharles.Forsyth 
1637*37da2899SCharles.Forsyth 	h = heap(TFont);
1638*37da2899SCharles.Forsyth 	if(h == H)
1639*37da2899SCharles.Forsyth 		return;
1640*37da2899SCharles.Forsyth 
1641*37da2899SCharles.Forsyth 	df = H2D(DFont*, h);
1642*37da2899SCharles.Forsyth 	df->font = font;
1643*37da2899SCharles.Forsyth 	df->drawfont.name = f->name;
1644*37da2899SCharles.Forsyth 	D2H(f->name)->ref++;
1645*37da2899SCharles.Forsyth 	df->drawfont.height = font->height;
1646*37da2899SCharles.Forsyth 	df->drawfont.ascent = font->ascent;
1647*37da2899SCharles.Forsyth 	df->drawfont.display = f->d;
1648*37da2899SCharles.Forsyth 	D2H(f->d)->ref++;
1649*37da2899SCharles.Forsyth 	df->dref = disp->limbo;
1650*37da2899SCharles.Forsyth 	df->dref->ref++;
1651*37da2899SCharles.Forsyth 	*f->ret = &df->drawfont;
1652*37da2899SCharles.Forsyth }
1653*37da2899SCharles.Forsyth 
1654*37da2899SCharles.Forsyth void
Font_width(void * fp)1655*37da2899SCharles.Forsyth Font_width(void *fp)
1656*37da2899SCharles.Forsyth {
1657*37da2899SCharles.Forsyth 	F_Font_width *f;
1658*37da2899SCharles.Forsyth 	Font *font;
1659*37da2899SCharles.Forsyth 	char *s;
1660*37da2899SCharles.Forsyth 	int locked;
1661*37da2899SCharles.Forsyth 
1662*37da2899SCharles.Forsyth 	f = fp;
1663*37da2899SCharles.Forsyth 	s = string2c(f->str);
1664*37da2899SCharles.Forsyth 	if(f->f == H || s[0]=='\0')
1665*37da2899SCharles.Forsyth 		*f->ret = 0;
1666*37da2899SCharles.Forsyth 	else{
1667*37da2899SCharles.Forsyth 		font = checkfont(f->f);
1668*37da2899SCharles.Forsyth 		locked = lockdisplay(font->display);
1669*37da2899SCharles.Forsyth 		*f->ret = stringwidth(font, s);
1670*37da2899SCharles.Forsyth 		if(locked)
1671*37da2899SCharles.Forsyth 			unlockdisplay(font->display);
1672*37da2899SCharles.Forsyth 	}
1673*37da2899SCharles.Forsyth }
1674*37da2899SCharles.Forsyth 
1675*37da2899SCharles.Forsyth void
Font_bbox(void * fp)1676*37da2899SCharles.Forsyth Font_bbox(void *fp)
1677*37da2899SCharles.Forsyth {
1678*37da2899SCharles.Forsyth 	F_Font_bbox *f;
1679*37da2899SCharles.Forsyth 	Draw_Rect *ret;
1680*37da2899SCharles.Forsyth 
1681*37da2899SCharles.Forsyth 	/* place holder for the real thing */
1682*37da2899SCharles.Forsyth 	f = fp;
1683*37da2899SCharles.Forsyth 	ret = f->ret;
1684*37da2899SCharles.Forsyth 	ret->min.x = ret->min.y = 0;
1685*37da2899SCharles.Forsyth 	ret->max.x = ret->max.y = 0;
1686*37da2899SCharles.Forsyth }
1687*37da2899SCharles.Forsyth 
1688*37da2899SCharles.Forsyth /*
1689*37da2899SCharles.Forsyth  * BUG: would be nice if this cached the whole font.
1690*37da2899SCharles.Forsyth  * Instead only the subfonts are cached and the fonts are
1691*37da2899SCharles.Forsyth  * freed when released.
1692*37da2899SCharles.Forsyth  */
1693*37da2899SCharles.Forsyth void
freedrawfont(Heap * h,int swept)1694*37da2899SCharles.Forsyth freedrawfont(Heap*h, int swept)
1695*37da2899SCharles.Forsyth {
1696*37da2899SCharles.Forsyth 	Draw_Font *d;
1697*37da2899SCharles.Forsyth 	Font *f;
1698*37da2899SCharles.Forsyth 	d = H2D(Draw_Font*, h);
1699*37da2899SCharles.Forsyth 	f = lookupfont(d);
1700*37da2899SCharles.Forsyth 	if(!swept) {
1701*37da2899SCharles.Forsyth 		destroy(d->name);
1702*37da2899SCharles.Forsyth 		destroy(d->display);
1703*37da2899SCharles.Forsyth 	}
1704*37da2899SCharles.Forsyth 	font_close(f);
1705*37da2899SCharles.Forsyth 	display_dec(((DFont*)d)->dref);
1706*37da2899SCharles.Forsyth }
1707*37da2899SCharles.Forsyth 
1708*37da2899SCharles.Forsyth void
Chans_text(void * fp)1709*37da2899SCharles.Forsyth Chans_text(void *fp)
1710*37da2899SCharles.Forsyth {
1711*37da2899SCharles.Forsyth 	F_Chans_text *f;
1712*37da2899SCharles.Forsyth 	char buf[16];
1713*37da2899SCharles.Forsyth 
1714*37da2899SCharles.Forsyth 	f = fp;
1715*37da2899SCharles.Forsyth 	destroy(*f->ret);
1716*37da2899SCharles.Forsyth 	*f->ret = H;
1717*37da2899SCharles.Forsyth 	if(chantostr(buf, f->c.desc) != nil)
1718*37da2899SCharles.Forsyth 		retstr(buf, f->ret);
1719*37da2899SCharles.Forsyth }
1720*37da2899SCharles.Forsyth 
1721*37da2899SCharles.Forsyth void
Chans_depth(void * fp)1722*37da2899SCharles.Forsyth Chans_depth(void *fp)
1723*37da2899SCharles.Forsyth {
1724*37da2899SCharles.Forsyth 	F_Chans_depth *f;
1725*37da2899SCharles.Forsyth 
1726*37da2899SCharles.Forsyth 	f = fp;
1727*37da2899SCharles.Forsyth 	*f->ret = chantodepth(f->c.desc);
1728*37da2899SCharles.Forsyth }
1729*37da2899SCharles.Forsyth 
1730*37da2899SCharles.Forsyth void
Chans_eq(void * fp)1731*37da2899SCharles.Forsyth Chans_eq(void *fp)
1732*37da2899SCharles.Forsyth {
1733*37da2899SCharles.Forsyth 	F_Chans_eq *f;
1734*37da2899SCharles.Forsyth 
1735*37da2899SCharles.Forsyth 	f = fp;
1736*37da2899SCharles.Forsyth 	*f->ret = f->c.desc == f->d.desc;
1737*37da2899SCharles.Forsyth }
1738*37da2899SCharles.Forsyth 
1739*37da2899SCharles.Forsyth void
Chans_mk(void * fp)1740*37da2899SCharles.Forsyth Chans_mk(void *fp)
1741*37da2899SCharles.Forsyth {
1742*37da2899SCharles.Forsyth 	F_Chans_mk *f;
1743*37da2899SCharles.Forsyth 
1744*37da2899SCharles.Forsyth 	f = fp;
1745*37da2899SCharles.Forsyth 	f->ret->desc = strtochan(string2c(f->s));
1746*37da2899SCharles.Forsyth }
1747*37da2899SCharles.Forsyth 
1748*37da2899SCharles.Forsyth void
Display_rgb(void * fp)1749*37da2899SCharles.Forsyth Display_rgb(void *fp)
1750*37da2899SCharles.Forsyth {
1751*37da2899SCharles.Forsyth 	ulong c;
1752*37da2899SCharles.Forsyth 	Display *disp;
1753*37da2899SCharles.Forsyth 	F_Display_rgb *f;
1754*37da2899SCharles.Forsyth 	int locked;
1755*37da2899SCharles.Forsyth 	void *r;
1756*37da2899SCharles.Forsyth 
1757*37da2899SCharles.Forsyth 	f = fp;
1758*37da2899SCharles.Forsyth 	r = *f->ret;
1759*37da2899SCharles.Forsyth 	*f->ret = H;
1760*37da2899SCharles.Forsyth 	destroy(r);
1761*37da2899SCharles.Forsyth 	disp = checkdisplay(f->d);
1762*37da2899SCharles.Forsyth 
1763*37da2899SCharles.Forsyth 	c = ((f->r&255)<<24)|((f->g&255)<<16)|((f->b&255)<<8)|0xFF;
1764*37da2899SCharles.Forsyth 
1765*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1766*37da2899SCharles.Forsyth 	*f->ret = color((DDisplay*)f->d, c);
1767*37da2899SCharles.Forsyth 	if(locked)
1768*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1769*37da2899SCharles.Forsyth }
1770*37da2899SCharles.Forsyth 
1771*37da2899SCharles.Forsyth void
Display_rgb2cmap(void * fp)1772*37da2899SCharles.Forsyth Display_rgb2cmap(void *fp)
1773*37da2899SCharles.Forsyth {
1774*37da2899SCharles.Forsyth 	F_Display_rgb2cmap *f;
1775*37da2899SCharles.Forsyth 
1776*37da2899SCharles.Forsyth 	f = fp;
1777*37da2899SCharles.Forsyth 	/* f->display is unused, but someday may have color map */
1778*37da2899SCharles.Forsyth 	*f->ret = rgb2cmap(f->r, f->g, f->b);
1779*37da2899SCharles.Forsyth }
1780*37da2899SCharles.Forsyth 
1781*37da2899SCharles.Forsyth void
Display_cmap2rgb(void * fp)1782*37da2899SCharles.Forsyth Display_cmap2rgb(void *fp)
1783*37da2899SCharles.Forsyth {
1784*37da2899SCharles.Forsyth 	F_Display_cmap2rgb *f;
1785*37da2899SCharles.Forsyth 	ulong c;
1786*37da2899SCharles.Forsyth 
1787*37da2899SCharles.Forsyth 	f = fp;
1788*37da2899SCharles.Forsyth 	/* f->display is unused, but someday may have color map */
1789*37da2899SCharles.Forsyth 	c = cmap2rgb(f->c);
1790*37da2899SCharles.Forsyth 	f->ret->t0 = (c>>16)&0xFF;
1791*37da2899SCharles.Forsyth 	f->ret->t1 = (c>>8)&0xFF;
1792*37da2899SCharles.Forsyth 	f->ret->t2 = (c>>0)&0xFF;
1793*37da2899SCharles.Forsyth }
1794*37da2899SCharles.Forsyth 
1795*37da2899SCharles.Forsyth void
Display_cmap2rgba(void * fp)1796*37da2899SCharles.Forsyth Display_cmap2rgba(void *fp)
1797*37da2899SCharles.Forsyth {
1798*37da2899SCharles.Forsyth 	F_Display_cmap2rgba *f;
1799*37da2899SCharles.Forsyth 
1800*37da2899SCharles.Forsyth 	f = fp;
1801*37da2899SCharles.Forsyth 	/* f->display is unused, but someday may have color map */
1802*37da2899SCharles.Forsyth 	*f->ret = cmap2rgba(f->c);
1803*37da2899SCharles.Forsyth }
1804*37da2899SCharles.Forsyth 
1805*37da2899SCharles.Forsyth void
Draw_setalpha(void * fp)1806*37da2899SCharles.Forsyth Draw_setalpha(void *fp)
1807*37da2899SCharles.Forsyth {
1808*37da2899SCharles.Forsyth 	F_Draw_setalpha *f;
1809*37da2899SCharles.Forsyth 
1810*37da2899SCharles.Forsyth 	f = fp;
1811*37da2899SCharles.Forsyth 	*f->ret = setalpha(f->c, f->a);
1812*37da2899SCharles.Forsyth }
1813*37da2899SCharles.Forsyth 
1814*37da2899SCharles.Forsyth void
Draw_icossin(void * fp)1815*37da2899SCharles.Forsyth Draw_icossin(void *fp)
1816*37da2899SCharles.Forsyth {
1817*37da2899SCharles.Forsyth 	F_Draw_icossin *f;
1818*37da2899SCharles.Forsyth 	int s, c;
1819*37da2899SCharles.Forsyth 
1820*37da2899SCharles.Forsyth 	f = fp;
1821*37da2899SCharles.Forsyth 	icossin(f->deg, &s, &c);
1822*37da2899SCharles.Forsyth 	f->ret->t0 = s;
1823*37da2899SCharles.Forsyth 	f->ret->t1 = c;
1824*37da2899SCharles.Forsyth }
1825*37da2899SCharles.Forsyth 
1826*37da2899SCharles.Forsyth void
Draw_icossin2(void * fp)1827*37da2899SCharles.Forsyth Draw_icossin2(void *fp)
1828*37da2899SCharles.Forsyth {
1829*37da2899SCharles.Forsyth 	F_Draw_icossin2 *f;
1830*37da2899SCharles.Forsyth 	int s, c;
1831*37da2899SCharles.Forsyth 
1832*37da2899SCharles.Forsyth 	f = fp;
1833*37da2899SCharles.Forsyth 	icossin2(f->p.x, f->p.y, &s, &c);
1834*37da2899SCharles.Forsyth 	f->ret->t0 = s;
1835*37da2899SCharles.Forsyth 	f->ret->t1 = c;
1836*37da2899SCharles.Forsyth }
1837*37da2899SCharles.Forsyth 
1838*37da2899SCharles.Forsyth void
Draw_bytesperline(void * fp)1839*37da2899SCharles.Forsyth Draw_bytesperline(void *fp)
1840*37da2899SCharles.Forsyth {
1841*37da2899SCharles.Forsyth 	F_Draw_bytesperline *f;
1842*37da2899SCharles.Forsyth 
1843*37da2899SCharles.Forsyth 	f = fp;
1844*37da2899SCharles.Forsyth 	*f->ret = bytesperline(IRECT(f->r), f->d);
1845*37da2899SCharles.Forsyth }
1846*37da2899SCharles.Forsyth 
1847*37da2899SCharles.Forsyth Draw_Image*
color(DDisplay * dd,ulong color)1848*37da2899SCharles.Forsyth color(DDisplay *dd, ulong color)
1849*37da2899SCharles.Forsyth {
1850*37da2899SCharles.Forsyth 	int c;
1851*37da2899SCharles.Forsyth 	Draw_Rect r;
1852*37da2899SCharles.Forsyth 
1853*37da2899SCharles.Forsyth 	r.min.x = 0;
1854*37da2899SCharles.Forsyth 	r.min.y = 0;
1855*37da2899SCharles.Forsyth 	r.max.x = 1;
1856*37da2899SCharles.Forsyth 	r.max.y = 1;
1857*37da2899SCharles.Forsyth 	c = (color&0xff) == 0xff ? RGB24: RGBA32;
1858*37da2899SCharles.Forsyth 	return allocdrawimage(dd, r, c, nil, 1, color);
1859*37da2899SCharles.Forsyth }
1860*37da2899SCharles.Forsyth 
1861*37da2899SCharles.Forsyth Draw_Image*
mkdrawimage(Image * i,Draw_Screen * screen,Draw_Display * display,void * ref)1862*37da2899SCharles.Forsyth mkdrawimage(Image *i, Draw_Screen *screen, Draw_Display *display, void *ref)
1863*37da2899SCharles.Forsyth {
1864*37da2899SCharles.Forsyth 	Heap *h;
1865*37da2899SCharles.Forsyth 	DImage *di;
1866*37da2899SCharles.Forsyth 
1867*37da2899SCharles.Forsyth 	h = heap(TImage);
1868*37da2899SCharles.Forsyth 	if(h == H)
1869*37da2899SCharles.Forsyth 		return H;
1870*37da2899SCharles.Forsyth 
1871*37da2899SCharles.Forsyth 	di = H2D(DImage*, h);
1872*37da2899SCharles.Forsyth 	di->image = i;
1873*37da2899SCharles.Forsyth 	di->drawimage.screen = screen;
1874*37da2899SCharles.Forsyth 	if(screen != H)
1875*37da2899SCharles.Forsyth 		D2H(screen)->ref++;
1876*37da2899SCharles.Forsyth 	di->drawimage.display = display;
1877*37da2899SCharles.Forsyth 	if(display != H)
1878*37da2899SCharles.Forsyth 		D2H(display)->ref++;
1879*37da2899SCharles.Forsyth 	di->refreshptr = ref;
1880*37da2899SCharles.Forsyth 
1881*37da2899SCharles.Forsyth 	R2R(di->drawimage.r, i->r);
1882*37da2899SCharles.Forsyth 	R2R(di->drawimage.clipr, i->clipr);
1883*37da2899SCharles.Forsyth 	di->drawimage.chans.desc = i->chan;
1884*37da2899SCharles.Forsyth 	di->drawimage.depth = i->depth;
1885*37da2899SCharles.Forsyth 	di->drawimage.repl = i->repl;
1886*37da2899SCharles.Forsyth 	di->flush = 1;
1887*37da2899SCharles.Forsyth 	di->dref = i->display->limbo;
1888*37da2899SCharles.Forsyth 	di->dref->ref++;
1889*37da2899SCharles.Forsyth 	return &di->drawimage;
1890*37da2899SCharles.Forsyth }
1891*37da2899SCharles.Forsyth 
1892*37da2899SCharles.Forsyth void
Screen_newwindow(void * fp)1893*37da2899SCharles.Forsyth Screen_newwindow(void *fp)
1894*37da2899SCharles.Forsyth {
1895*37da2899SCharles.Forsyth 	F_Screen_newwindow *f;
1896*37da2899SCharles.Forsyth 	Image *i;
1897*37da2899SCharles.Forsyth 	Screen *s;
1898*37da2899SCharles.Forsyth 	Rectangle r;
1899*37da2899SCharles.Forsyth 	int locked;
1900*37da2899SCharles.Forsyth 	void *v;
1901*37da2899SCharles.Forsyth 
1902*37da2899SCharles.Forsyth 	f = fp;
1903*37da2899SCharles.Forsyth 	s = checkscreen(f->screen);
1904*37da2899SCharles.Forsyth 	R2R(r, f->r);
1905*37da2899SCharles.Forsyth 
1906*37da2899SCharles.Forsyth 	if(f->backing != Refnone && f->backing != Refbackup)
1907*37da2899SCharles.Forsyth 		f->backing = Refbackup;
1908*37da2899SCharles.Forsyth 
1909*37da2899SCharles.Forsyth 	v = *f->ret;
1910*37da2899SCharles.Forsyth 	*f->ret = H;
1911*37da2899SCharles.Forsyth 	destroy(v);
1912*37da2899SCharles.Forsyth 
1913*37da2899SCharles.Forsyth 	locked = lockdisplay(s->display);
1914*37da2899SCharles.Forsyth 	i = allocwindow(s, r, f->backing, f->color);
1915*37da2899SCharles.Forsyth 	if(locked)
1916*37da2899SCharles.Forsyth 		unlockdisplay(s->display);
1917*37da2899SCharles.Forsyth 	if(i == nil)
1918*37da2899SCharles.Forsyth 		return;
1919*37da2899SCharles.Forsyth 
1920*37da2899SCharles.Forsyth 	*f->ret = mkdrawimage(i, f->screen, f->screen->display, 0);
1921*37da2899SCharles.Forsyth }
1922*37da2899SCharles.Forsyth 
1923*37da2899SCharles.Forsyth static
1924*37da2899SCharles.Forsyth void
screentopbot(Draw_Screen * screen,Array * array,void (* topbot)(Image **,int))1925*37da2899SCharles.Forsyth screentopbot(Draw_Screen *screen, Array *array, void (*topbot)(Image **, int))
1926*37da2899SCharles.Forsyth {
1927*37da2899SCharles.Forsyth 	Screen *s;
1928*37da2899SCharles.Forsyth 	Draw_Image **di;
1929*37da2899SCharles.Forsyth 	Image **ip;
1930*37da2899SCharles.Forsyth 	int i, n, locked;
1931*37da2899SCharles.Forsyth 
1932*37da2899SCharles.Forsyth 	s = checkscreen(screen);
1933*37da2899SCharles.Forsyth 	di = (Draw_Image**)array->data;
1934*37da2899SCharles.Forsyth 	ip = malloc(array->len * sizeof(Image*));
1935*37da2899SCharles.Forsyth 	if(ip == nil)
1936*37da2899SCharles.Forsyth 		return;
1937*37da2899SCharles.Forsyth 	n = 0;
1938*37da2899SCharles.Forsyth 	for(i=0; i<array->len; i++)
1939*37da2899SCharles.Forsyth 		if(di[i] != H){
1940*37da2899SCharles.Forsyth 			ip[n] = lookupimage(di[i]);
1941*37da2899SCharles.Forsyth 			if(ip[n]==nil || ip[n]->screen != s){
1942*37da2899SCharles.Forsyth 				free(ip);
1943*37da2899SCharles.Forsyth 				return;
1944*37da2899SCharles.Forsyth 			}
1945*37da2899SCharles.Forsyth 			n++;
1946*37da2899SCharles.Forsyth 		}
1947*37da2899SCharles.Forsyth 	if(n == 0){
1948*37da2899SCharles.Forsyth 		free(ip);
1949*37da2899SCharles.Forsyth 		return;
1950*37da2899SCharles.Forsyth 	}
1951*37da2899SCharles.Forsyth 	locked = lockdisplay(s->display);
1952*37da2899SCharles.Forsyth 	(*topbot)(ip, n);
1953*37da2899SCharles.Forsyth 	free(ip);
1954*37da2899SCharles.Forsyth 	flushimage(s->display, 1);
1955*37da2899SCharles.Forsyth 	if(locked)
1956*37da2899SCharles.Forsyth 		unlockdisplay(s->display);
1957*37da2899SCharles.Forsyth }
1958*37da2899SCharles.Forsyth 
1959*37da2899SCharles.Forsyth void
Screen_top(void * fp)1960*37da2899SCharles.Forsyth Screen_top(void *fp)
1961*37da2899SCharles.Forsyth {
1962*37da2899SCharles.Forsyth 	F_Screen_top *f;
1963*37da2899SCharles.Forsyth 	f = fp;
1964*37da2899SCharles.Forsyth 	screentopbot(f->screen, f->wins, topnwindows);
1965*37da2899SCharles.Forsyth }
1966*37da2899SCharles.Forsyth 
1967*37da2899SCharles.Forsyth void
Screen_bottom(void * fp)1968*37da2899SCharles.Forsyth Screen_bottom(void *fp)
1969*37da2899SCharles.Forsyth {
1970*37da2899SCharles.Forsyth 	F_Screen_top *f;
1971*37da2899SCharles.Forsyth 	f = fp;
1972*37da2899SCharles.Forsyth 	screentopbot(f->screen, f->wins, bottomnwindows);
1973*37da2899SCharles.Forsyth }
1974*37da2899SCharles.Forsyth 
1975*37da2899SCharles.Forsyth void
freedrawimage(Heap * h,int swept)1976*37da2899SCharles.Forsyth freedrawimage(Heap *h, int swept)
1977*37da2899SCharles.Forsyth {
1978*37da2899SCharles.Forsyth 	Image *i;
1979*37da2899SCharles.Forsyth 	int locked;
1980*37da2899SCharles.Forsyth 	Display *disp;
1981*37da2899SCharles.Forsyth 	Draw_Image *d;
1982*37da2899SCharles.Forsyth 
1983*37da2899SCharles.Forsyth 	d = H2D(Draw_Image*, h);
1984*37da2899SCharles.Forsyth 	i = lookupimage(d);
1985*37da2899SCharles.Forsyth 	if(i == nil) {
1986*37da2899SCharles.Forsyth 		if(!swept)
1987*37da2899SCharles.Forsyth 			freeptrs(d, TImage);
1988*37da2899SCharles.Forsyth 		return;
1989*37da2899SCharles.Forsyth 	}
1990*37da2899SCharles.Forsyth 	disp = i->display;
1991*37da2899SCharles.Forsyth 	locked = lockdisplay(disp);
1992*37da2899SCharles.Forsyth 	freeimage(i);
1993*37da2899SCharles.Forsyth 	if(locked)
1994*37da2899SCharles.Forsyth 		unlockdisplay(disp);
1995*37da2899SCharles.Forsyth 	display_dec(((DImage*)d)->dref);
1996*37da2899SCharles.Forsyth 	/* image/layer header will be freed by caller */
1997*37da2899SCharles.Forsyth }
1998*37da2899SCharles.Forsyth 
1999*37da2899SCharles.Forsyth void
Image_top(void * fp)2000*37da2899SCharles.Forsyth Image_top(void *fp)
2001*37da2899SCharles.Forsyth {
2002*37da2899SCharles.Forsyth 	F_Image_top *f;
2003*37da2899SCharles.Forsyth 	Image *i;
2004*37da2899SCharles.Forsyth 	int locked;
2005*37da2899SCharles.Forsyth 
2006*37da2899SCharles.Forsyth 	f = fp;
2007*37da2899SCharles.Forsyth 	i = checkimage(f->win);
2008*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
2009*37da2899SCharles.Forsyth 	topwindow(i);
2010*37da2899SCharles.Forsyth 	flushimage(i->display, 1);
2011*37da2899SCharles.Forsyth 	if(locked)
2012*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
2013*37da2899SCharles.Forsyth }
2014*37da2899SCharles.Forsyth 
2015*37da2899SCharles.Forsyth void
Image_origin(void * fp)2016*37da2899SCharles.Forsyth Image_origin(void *fp)
2017*37da2899SCharles.Forsyth {
2018*37da2899SCharles.Forsyth 	F_Image_origin *f;
2019*37da2899SCharles.Forsyth 	Image *i;
2020*37da2899SCharles.Forsyth 	int locked;
2021*37da2899SCharles.Forsyth 
2022*37da2899SCharles.Forsyth 	f = fp;
2023*37da2899SCharles.Forsyth 	i = checkimage(f->win);
2024*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
2025*37da2899SCharles.Forsyth 	if(originwindow(i, IPOINT(f->log), IPOINT(f->scr)) < 0)
2026*37da2899SCharles.Forsyth 		*f->ret = -1;
2027*37da2899SCharles.Forsyth 	else{
2028*37da2899SCharles.Forsyth 		f->win->r = DRECT(i->r);
2029*37da2899SCharles.Forsyth 		f->win->clipr = DRECT(i->clipr);
2030*37da2899SCharles.Forsyth 		*f->ret = 1;
2031*37da2899SCharles.Forsyth 	}
2032*37da2899SCharles.Forsyth 	if(locked)
2033*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
2034*37da2899SCharles.Forsyth }
2035*37da2899SCharles.Forsyth 
2036*37da2899SCharles.Forsyth void
Image_bottom(void * fp)2037*37da2899SCharles.Forsyth Image_bottom(void *fp)
2038*37da2899SCharles.Forsyth {
2039*37da2899SCharles.Forsyth 	F_Image_top *f;
2040*37da2899SCharles.Forsyth 	Image *i;
2041*37da2899SCharles.Forsyth 	int locked;
2042*37da2899SCharles.Forsyth 
2043*37da2899SCharles.Forsyth 	f = fp;
2044*37da2899SCharles.Forsyth 	i = checkimage(f->win);
2045*37da2899SCharles.Forsyth 	locked = lockdisplay(i->display);
2046*37da2899SCharles.Forsyth 	bottomwindow(i);
2047*37da2899SCharles.Forsyth 	flushimage(i->display, 1);
2048*37da2899SCharles.Forsyth 	if(locked)
2049*37da2899SCharles.Forsyth 		unlockdisplay(i->display);
2050*37da2899SCharles.Forsyth }
2051*37da2899SCharles.Forsyth 
2052*37da2899SCharles.Forsyth Draw_Image*
allocdrawimage(DDisplay * ddisplay,Draw_Rect r,ulong chan,Image * iimage,int repl,int color)2053*37da2899SCharles.Forsyth allocdrawimage(DDisplay *ddisplay, Draw_Rect r, ulong chan, Image *iimage, int repl, int color)
2054*37da2899SCharles.Forsyth {
2055*37da2899SCharles.Forsyth 	Heap *h;
2056*37da2899SCharles.Forsyth 	DImage *di;
2057*37da2899SCharles.Forsyth 	Rectangle rr;
2058*37da2899SCharles.Forsyth 	Image *image;
2059*37da2899SCharles.Forsyth 
2060*37da2899SCharles.Forsyth 	image = iimage;
2061*37da2899SCharles.Forsyth 	if(iimage == nil){
2062*37da2899SCharles.Forsyth 		R2R(rr, r);
2063*37da2899SCharles.Forsyth 		image = allocimage(ddisplay->display, rr, chan, repl, color);
2064*37da2899SCharles.Forsyth 		if(image == nil)
2065*37da2899SCharles.Forsyth 			return H;
2066*37da2899SCharles.Forsyth 	}
2067*37da2899SCharles.Forsyth 
2068*37da2899SCharles.Forsyth 	h = heap(TImage);
2069*37da2899SCharles.Forsyth 	if(h == H){
2070*37da2899SCharles.Forsyth 		if(iimage == nil)
2071*37da2899SCharles.Forsyth 			freeimage(image);
2072*37da2899SCharles.Forsyth 		return H;
2073*37da2899SCharles.Forsyth 	}
2074*37da2899SCharles.Forsyth 
2075*37da2899SCharles.Forsyth 	di = H2D(DImage*, h);
2076*37da2899SCharles.Forsyth 	di->drawimage.r = r;
2077*37da2899SCharles.Forsyth 	R2R(di->drawimage.clipr, image->clipr);
2078*37da2899SCharles.Forsyth 	di->drawimage.chans.desc = chan;
2079*37da2899SCharles.Forsyth 	di->drawimage.depth = chantodepth(chan);
2080*37da2899SCharles.Forsyth 	di->drawimage.repl = repl;
2081*37da2899SCharles.Forsyth 	di->drawimage.display = (Draw_Display*)ddisplay;
2082*37da2899SCharles.Forsyth 	D2H(di->drawimage.display)->ref++;
2083*37da2899SCharles.Forsyth 	di->drawimage.screen = H;
2084*37da2899SCharles.Forsyth 	di->dref = ddisplay->display->limbo;
2085*37da2899SCharles.Forsyth 	di->dref->ref++;
2086*37da2899SCharles.Forsyth 	di->image = image;
2087*37da2899SCharles.Forsyth 	di->refreshptr = 0;
2088*37da2899SCharles.Forsyth 	di->flush = 1;
2089*37da2899SCharles.Forsyth 
2090*37da2899SCharles.Forsyth 	return &di->drawimage;
2091*37da2899SCharles.Forsyth }
2092*37da2899SCharles.Forsyth 
2093*37da2899SCharles.Forsyth /*
2094*37da2899SCharles.Forsyth  * Entry points called from the draw library
2095*37da2899SCharles.Forsyth  */
2096*37da2899SCharles.Forsyth Subfont*
lookupsubfont(Display * d,char * name)2097*37da2899SCharles.Forsyth lookupsubfont(Display *d, char *name)
2098*37da2899SCharles.Forsyth {
2099*37da2899SCharles.Forsyth 	Cache *c;
2100*37da2899SCharles.Forsyth 
2101*37da2899SCharles.Forsyth 	c = cachelookup(sfcache, d, name);
2102*37da2899SCharles.Forsyth 	if(c == nil)
2103*37da2899SCharles.Forsyth 		return nil;
2104*37da2899SCharles.Forsyth 	/*c->u.sf->ref++;*/	/* TO DO: need to revisit the reference counting */
2105*37da2899SCharles.Forsyth 	return c->u.sf;
2106*37da2899SCharles.Forsyth }
2107*37da2899SCharles.Forsyth 
2108*37da2899SCharles.Forsyth void
installsubfont(char * name,Subfont * subfont)2109*37da2899SCharles.Forsyth installsubfont(char *name, Subfont *subfont)
2110*37da2899SCharles.Forsyth {
2111*37da2899SCharles.Forsyth 	Cache *c;
2112*37da2899SCharles.Forsyth 
2113*37da2899SCharles.Forsyth 	c = cacheinstall(sfcache, subfont->bits->display, name, subfont, "subfont");
2114*37da2899SCharles.Forsyth 	if(c)
2115*37da2899SCharles.Forsyth 		c->ref++;
2116*37da2899SCharles.Forsyth }
2117*37da2899SCharles.Forsyth 
2118*37da2899SCharles.Forsyth /*
2119*37da2899SCharles.Forsyth  * BUG version
2120*37da2899SCharles.Forsyth  */
2121*37da2899SCharles.Forsyth char*
subfontname(char * cfname,char * fname,int maxdepth)2122*37da2899SCharles.Forsyth subfontname(char *cfname, char *fname, int maxdepth)
2123*37da2899SCharles.Forsyth {
2124*37da2899SCharles.Forsyth 	char *t, *u, tmp1[256], tmp2[256];
2125*37da2899SCharles.Forsyth 	int i, fd;
2126*37da2899SCharles.Forsyth 
2127*37da2899SCharles.Forsyth 	if(strcmp(cfname, deffontname) == 0)
2128*37da2899SCharles.Forsyth 		return strdup(cfname);
2129*37da2899SCharles.Forsyth 	t = cfname;
2130*37da2899SCharles.Forsyth 	if(t[0] != '/'){
2131*37da2899SCharles.Forsyth 		strcpy(tmp2, fname);
2132*37da2899SCharles.Forsyth 		u = utfrrune(tmp2, '/');
2133*37da2899SCharles.Forsyth 		if(u)
2134*37da2899SCharles.Forsyth 			u[0] = 0;
2135*37da2899SCharles.Forsyth 		else
2136*37da2899SCharles.Forsyth 			strcpy(tmp2, ".");
2137*37da2899SCharles.Forsyth 		snprint(tmp1, sizeof tmp1, "%s/%s", tmp2, t);
2138*37da2899SCharles.Forsyth 		t = tmp1;
2139*37da2899SCharles.Forsyth 	}
2140*37da2899SCharles.Forsyth 
2141*37da2899SCharles.Forsyth 	if(maxdepth > 8)
2142*37da2899SCharles.Forsyth 		maxdepth = 8;
2143*37da2899SCharles.Forsyth 
2144*37da2899SCharles.Forsyth 	for(i=3; i>=0; i--){
2145*37da2899SCharles.Forsyth 		if((1<<i) > maxdepth)
2146*37da2899SCharles.Forsyth 			continue;
2147*37da2899SCharles.Forsyth 		/* try i-bit grey */
2148*37da2899SCharles.Forsyth 		snprint(tmp2, sizeof tmp2, "%s.%d", t, i);
2149*37da2899SCharles.Forsyth 		fd = libopen(tmp2, OREAD);
2150*37da2899SCharles.Forsyth 		if(fd >= 0){
2151*37da2899SCharles.Forsyth 			libclose(fd);
2152*37da2899SCharles.Forsyth 			return strdup(tmp2);
2153*37da2899SCharles.Forsyth 		}
2154*37da2899SCharles.Forsyth 	}
2155*37da2899SCharles.Forsyth 
2156*37da2899SCharles.Forsyth 	return strdup(t);
2157*37da2899SCharles.Forsyth }
2158*37da2899SCharles.Forsyth 
2159*37da2899SCharles.Forsyth void
refreshslave(Display * d)2160*37da2899SCharles.Forsyth refreshslave(Display *d)
2161*37da2899SCharles.Forsyth {
2162*37da2899SCharles.Forsyth 	int i, n, id;
2163*37da2899SCharles.Forsyth 	uchar buf[5*(5*4)], *p;
2164*37da2899SCharles.Forsyth 	Rectangle r;
2165*37da2899SCharles.Forsyth 	Image *im;
2166*37da2899SCharles.Forsyth 	int locked;
2167*37da2899SCharles.Forsyth 
2168*37da2899SCharles.Forsyth 	for(;;){
2169*37da2899SCharles.Forsyth 		release();
2170*37da2899SCharles.Forsyth 		n = kchanio(d->refchan, buf, sizeof buf, OREAD);
2171*37da2899SCharles.Forsyth 		acquire();
2172*37da2899SCharles.Forsyth 		if(n < 0)	/* probably caused by closedisplay() closing refchan */
2173*37da2899SCharles.Forsyth 			return;	/* will fall off end of thread and close down */
2174*37da2899SCharles.Forsyth 		locked = lockdisplay(d);
2175*37da2899SCharles.Forsyth 		p = buf;
2176*37da2899SCharles.Forsyth 		for(i=0; i<n; i+=5*4,p+=5*4){
2177*37da2899SCharles.Forsyth 			id = BGLONG(p+0*4);
2178*37da2899SCharles.Forsyth 			r.min.x = BGLONG(p+1*4);
2179*37da2899SCharles.Forsyth 			r.min.y = BGLONG(p+2*4);
2180*37da2899SCharles.Forsyth 			r.max.x = BGLONG(p+3*4);
2181*37da2899SCharles.Forsyth 			r.max.y = BGLONG(p+4*4);
2182*37da2899SCharles.Forsyth 			for(im=d->windows; im; im=im->next)
2183*37da2899SCharles.Forsyth 				if(im->id == id)
2184*37da2899SCharles.Forsyth 					break;
2185*37da2899SCharles.Forsyth 			if(im && im->screen && im->reffn)
2186*37da2899SCharles.Forsyth 				(*im->reffn)(im, r, im->refptr);
2187*37da2899SCharles.Forsyth 		}
2188*37da2899SCharles.Forsyth 		flushimage(d, 1);
2189*37da2899SCharles.Forsyth 		if(locked)
2190*37da2899SCharles.Forsyth 			unlockdisplay(d);
2191*37da2899SCharles.Forsyth 	}
2192*37da2899SCharles.Forsyth }
2193*37da2899SCharles.Forsyth 
2194*37da2899SCharles.Forsyth void
startrefresh(Display * disp)2195*37da2899SCharles.Forsyth startrefresh(Display *disp)
2196*37da2899SCharles.Forsyth {
2197*37da2899SCharles.Forsyth 	USED(disp);
2198*37da2899SCharles.Forsyth }
2199*37da2899SCharles.Forsyth 
2200*37da2899SCharles.Forsyth static
2201*37da2899SCharles.Forsyth int
doflush(Display * d)2202*37da2899SCharles.Forsyth doflush(Display *d)
2203*37da2899SCharles.Forsyth {
2204*37da2899SCharles.Forsyth 	int m, n;
2205*37da2899SCharles.Forsyth 	char err[ERRMAX];
2206*37da2899SCharles.Forsyth 	uchar *tp;
2207*37da2899SCharles.Forsyth 
2208*37da2899SCharles.Forsyth 	n = d->bufp-d->buf;
2209*37da2899SCharles.Forsyth 	if(n <= 0)
2210*37da2899SCharles.Forsyth 		return 1;
2211*37da2899SCharles.Forsyth 
2212*37da2899SCharles.Forsyth 	if(d->local == 0)
2213*37da2899SCharles.Forsyth 		release();
2214*37da2899SCharles.Forsyth 	if((m = kchanio(d->datachan, d->buf, n, OWRITE)) != n){
2215*37da2899SCharles.Forsyth 		if(d->local == 0)
2216*37da2899SCharles.Forsyth 			acquire();
2217*37da2899SCharles.Forsyth 		kgerrstr(err, sizeof err);
2218*37da2899SCharles.Forsyth 		if(_drawdebug || strcmp(err, "screen id in use") != 0 && strcmp(err, exImage) != 0){
2219*37da2899SCharles.Forsyth 			print("flushimage fail: (%d not %d) d=%lux: %s\nbuffer: ", m, n, (ulong)d, err);
2220*37da2899SCharles.Forsyth 			for(tp = d->buf; tp < d->bufp; tp++)
2221*37da2899SCharles.Forsyth 				print("%.2x ", (int)*tp);
2222*37da2899SCharles.Forsyth 			print("\n");
2223*37da2899SCharles.Forsyth 		}
2224*37da2899SCharles.Forsyth 		d->bufp = d->buf;	/* might as well; chance of continuing */
2225*37da2899SCharles.Forsyth 		return -1;
2226*37da2899SCharles.Forsyth 	}
2227*37da2899SCharles.Forsyth 	d->bufp = d->buf;
2228*37da2899SCharles.Forsyth 	if(d->local == 0)
2229*37da2899SCharles.Forsyth 		acquire();
2230*37da2899SCharles.Forsyth 	return 1;
2231*37da2899SCharles.Forsyth }
2232*37da2899SCharles.Forsyth 
2233*37da2899SCharles.Forsyth int
flushimage(Display * d,int visible)2234*37da2899SCharles.Forsyth flushimage(Display *d, int visible)
2235*37da2899SCharles.Forsyth {
2236*37da2899SCharles.Forsyth 	int ret;
2237*37da2899SCharles.Forsyth 	Refreshq *r;
2238*37da2899SCharles.Forsyth 
2239*37da2899SCharles.Forsyth 	for(;;){
2240*37da2899SCharles.Forsyth 		if(visible)
2241*37da2899SCharles.Forsyth 			*d->bufp++ = 'v';	/* one byte always reserved for this */
2242*37da2899SCharles.Forsyth 		ret = doflush(d);
2243*37da2899SCharles.Forsyth 		if(d->refhead == nil)
2244*37da2899SCharles.Forsyth 			break;
2245*37da2899SCharles.Forsyth 		while(r = d->refhead){	/* assign = */
2246*37da2899SCharles.Forsyth 			d->refhead = r->next;
2247*37da2899SCharles.Forsyth 			if(d->refhead == nil)
2248*37da2899SCharles.Forsyth 				d->reftail = nil;
2249*37da2899SCharles.Forsyth 			r->reffn(nil, r->r, r->refptr);
2250*37da2899SCharles.Forsyth 			free(r);
2251*37da2899SCharles.Forsyth 		}
2252*37da2899SCharles.Forsyth 	}
2253*37da2899SCharles.Forsyth 	return ret;
2254*37da2899SCharles.Forsyth }
2255*37da2899SCharles.Forsyth 
2256*37da2899SCharles.Forsyth /*
2257*37da2899SCharles.Forsyth  * Turn off refresh for this window and remove any pending refresh events for it.
2258*37da2899SCharles.Forsyth  */
2259*37da2899SCharles.Forsyth void
delrefresh(Image * i)2260*37da2899SCharles.Forsyth delrefresh(Image *i)
2261*37da2899SCharles.Forsyth {
2262*37da2899SCharles.Forsyth 	Refreshq *r, *prev, *next;
2263*37da2899SCharles.Forsyth 	int locked;
2264*37da2899SCharles.Forsyth 	Display *d;
2265*37da2899SCharles.Forsyth 	void *refptr;
2266*37da2899SCharles.Forsyth 
2267*37da2899SCharles.Forsyth 	d = i->display;
2268*37da2899SCharles.Forsyth 	/*
2269*37da2899SCharles.Forsyth 	 * Any refresh function will do, because the data pointer is nil.
2270*37da2899SCharles.Forsyth 	 * Can't use nil, though, because that turns backing store back on.
2271*37da2899SCharles.Forsyth 	 */
2272*37da2899SCharles.Forsyth 	if(d->local)
2273*37da2899SCharles.Forsyth 		drawlsetrefresh(d->dataqid, i->id, memlnorefresh, nil);
2274*37da2899SCharles.Forsyth 	refptr = i->refptr;
2275*37da2899SCharles.Forsyth 	i->refptr = nil;
2276*37da2899SCharles.Forsyth 	if(d->refhead==nil || refptr==nil)
2277*37da2899SCharles.Forsyth 		return;
2278*37da2899SCharles.Forsyth 	locked = lockdisplay(d);
2279*37da2899SCharles.Forsyth 	prev = nil;
2280*37da2899SCharles.Forsyth 	for(r=d->refhead; r; r=next){
2281*37da2899SCharles.Forsyth 		next = r->next;
2282*37da2899SCharles.Forsyth 		if(r->refptr == refptr){
2283*37da2899SCharles.Forsyth 			if(prev)
2284*37da2899SCharles.Forsyth 				prev->next = next;
2285*37da2899SCharles.Forsyth 			else
2286*37da2899SCharles.Forsyth 				d->refhead = next;
2287*37da2899SCharles.Forsyth 			if(d->reftail == r)
2288*37da2899SCharles.Forsyth 				d->reftail = prev;
2289*37da2899SCharles.Forsyth 			free(r);
2290*37da2899SCharles.Forsyth 		}else
2291*37da2899SCharles.Forsyth 			prev = r;
2292*37da2899SCharles.Forsyth 	}
2293*37da2899SCharles.Forsyth 	if(locked)
2294*37da2899SCharles.Forsyth 		unlockdisplay(d);
2295*37da2899SCharles.Forsyth }
2296*37da2899SCharles.Forsyth 
2297*37da2899SCharles.Forsyth void
queuerefresh(Image * i,Rectangle r,Reffn reffn,void * refptr)2298*37da2899SCharles.Forsyth queuerefresh(Image *i, Rectangle r, Reffn reffn, void *refptr)
2299*37da2899SCharles.Forsyth {
2300*37da2899SCharles.Forsyth 	Display *d;
2301*37da2899SCharles.Forsyth 	Refreshq *rq;
2302*37da2899SCharles.Forsyth 
2303*37da2899SCharles.Forsyth 	d = i->display;
2304*37da2899SCharles.Forsyth 	rq = malloc(sizeof(Refreshq));
2305*37da2899SCharles.Forsyth 	if(rq == nil)
2306*37da2899SCharles.Forsyth 		return;
2307*37da2899SCharles.Forsyth 	if(d->reftail)
2308*37da2899SCharles.Forsyth 		d->reftail->next = rq;
2309*37da2899SCharles.Forsyth 	else
2310*37da2899SCharles.Forsyth 		d->refhead = rq;
2311*37da2899SCharles.Forsyth 	d->reftail = rq;
2312*37da2899SCharles.Forsyth 	rq->reffn = reffn;
2313*37da2899SCharles.Forsyth 	rq->refptr = refptr;
2314*37da2899SCharles.Forsyth 	rq->r = r;
2315*37da2899SCharles.Forsyth }
2316*37da2899SCharles.Forsyth 
2317*37da2899SCharles.Forsyth uchar*
bufimage(Display * d,int n)2318*37da2899SCharles.Forsyth bufimage(Display *d, int n)
2319*37da2899SCharles.Forsyth {
2320*37da2899SCharles.Forsyth 	uchar *p;
2321*37da2899SCharles.Forsyth 
2322*37da2899SCharles.Forsyth 	if(n<0 || n>Displaybufsize){
2323*37da2899SCharles.Forsyth 		kwerrstr("bad count in bufimage");
2324*37da2899SCharles.Forsyth 		return 0;
2325*37da2899SCharles.Forsyth 	}
2326*37da2899SCharles.Forsyth 	if(d->bufp+n > d->buf+Displaybufsize){
2327*37da2899SCharles.Forsyth 		if(d->local==0 && currun()!=libqlowner(d->qlock)) {
2328*37da2899SCharles.Forsyth 			print("bufimage: %lux %lux\n", (ulong)libqlowner(d->qlock), (ulong)currun());
2329*37da2899SCharles.Forsyth 			abort();
2330*37da2899SCharles.Forsyth 		}
2331*37da2899SCharles.Forsyth 		if(doflush(d) < 0)
2332*37da2899SCharles.Forsyth 			return 0;
2333*37da2899SCharles.Forsyth 	}
2334*37da2899SCharles.Forsyth 	p = d->bufp;
2335*37da2899SCharles.Forsyth 	d->bufp += n;
2336*37da2899SCharles.Forsyth 	/* return with buffer locked */
2337*37da2899SCharles.Forsyth 	return p;
2338*37da2899SCharles.Forsyth }
2339*37da2899SCharles.Forsyth 
2340*37da2899SCharles.Forsyth void
drawerror(Display * d,char * s)2341*37da2899SCharles.Forsyth drawerror(Display *d, char *s)
2342*37da2899SCharles.Forsyth {
2343*37da2899SCharles.Forsyth 	USED(d);
2344*37da2899SCharles.Forsyth 	fprint(2, "draw: %s: %r\n", s);
2345*37da2899SCharles.Forsyth }
2346